├── LICENSE ├── README.md ├── package.json └── parameterize.js /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | node-parameterize 2 | ================= 3 | This repository adds node.js and npm support for [parameterize](http://apidock.com/rails/String/parameterize) which is originally used in Ruby on Rails. It replaces special characters in a string so that it may be used as part of a 'pretty' URL. 4 | 5 | parameterize.js is a port of django admin [urlify.js](https://github.com/django/django/blob/master/django/contrib/admin/static/admin/js/urlify.js) 6 | 7 | Installing 8 | -------------------------------- 9 | npm install parameterize 10 | 11 | 12 | Supports 13 | -------------------------------- 14 | Turkish 15 | Azerbaijani 16 | Serbian 17 | Greek 18 | Georgian 19 | Russian 20 | Ukranian 21 | Czech 22 | Polish 23 | Romanian 24 | Latvanian 25 | Lithuanian 26 | Arabic 27 | Latin special chars 28 | 29 | 30 | Require 31 | -------------------------------- 32 | ```javascript 33 | var parameterize = require('parameterize'); 34 | ``` 35 | 36 | 37 | Using 38 | -------------------------------- 39 | ```javascript 40 | parameterize('parameterized url with special characters, öçıŞÇ'); 41 | // outputs 42 | // parameterized-url-with-special-characters-ocisc 43 | ``` 44 | 45 | ```javascript 46 | // using optional length limit 47 | parameterize('this is a long text', 10); 48 | // outputs 49 | // this-is-a-l 50 | ``` 51 | 52 | ```javascript 53 | // you can change delimiter character 54 | parameterize('this is a long text', 10, '_'); 55 | // outputs 56 | // this_is_a_l 57 | ``` 58 | 59 | Using in express.js 3 view files as view helper 60 | -------------------------------- 61 | 62 | You can implement it as in the example just below in your app.js file so that you can use it in all views. Note that it should be before the line 'app.use(app.router)'. 63 | 64 | app.configure 65 | -------------------------------- 66 | 67 | ```javascript 68 | app.use(function(req, res, next) { 69 | res.locals.parameterize = parameterize 70 | next(); 71 | }); 72 | 73 | app.use(app.router); 74 | ``` 75 | 76 | 77 | using with jade template engine 78 | ---- 79 | index.jade 80 | 81 | ```html 82 | #{parameterize('parameterized url with special characters, öçıŞÇ')} 83 | // output: 84 | // parameterized-url-with-special-characters-ocisc 85 | ``` 86 | 87 | 88 | using with ejs template engine 89 | --- 90 | index.ejs 91 | 92 | ```ejs 93 | <% parameterize('parameterized url with special characters, öçıŞÇ') %> 94 | // parameterized-url-with-special-characters-ocisc 95 | ``` 96 | 97 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "name": "Fırat Yalavuz", 4 | "email": "yalavuz@gmail.com", 5 | "url": "http://firat.me" 6 | }, 7 | "name": "parameterize", 8 | "license": "MIT", 9 | "description": "This repository adds node.js and npm support for parameterize which is originally used in Ruby on Rails. It replaces special characters in a string so that it may be used as part of a 'pretty' URL.", 10 | "tags": [ 11 | "urlify", 12 | "Parameterize", 13 | "url", 14 | "parameter", 15 | "permalink", 16 | "seo" 17 | ], 18 | "version": "1.0.0", 19 | "repository": { 20 | "type": "git", 21 | "url": "git@github.com:fyalavuz/node-parameterize.git" 22 | }, 23 | "main": "parameterize.js", 24 | "engines": { 25 | "node": "*" 26 | }, 27 | "dependencies": {}, 28 | "devDependencies": {}, 29 | "optionalDependencies": {}, 30 | "readmeFilename": "README.md" 31 | } 32 | -------------------------------------------------------------------------------- /parameterize.js: -------------------------------------------------------------------------------- 1 | var LATIN_MAP = { 2 | 'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 3 | 'Ç': 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 4 | 'Î': 'I', 'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 5 | 'Õ': 'O', 'Ö': 'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 6 | 'Ü': 'U', 'Ű': 'U', 'Ý': 'Y', 'Þ': 'TH', 'Ÿ': 'Y', 'ß': 'ss', 'à': 'a', 7 | 'á': 'a', 'â': 'a', 'ã': 'a', 'ä': 'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 8 | 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e', 'ì': 'i', 'í': 'i', 'î': 'i', 9 | 'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ': 'o', 10 | 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u', 11 | 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y' 12 | }; 13 | 14 | var LATIN_SYMBOLS_MAP = { 15 | '©': '(c)' 16 | }; 17 | 18 | var GREEK_MAP = { 19 | 'α': 'a', 'β': 'b', 'γ': 'g', 'δ': 'd', 'ε': 'e', 'ζ': 'z', 'η': 'h', 20 | 'θ': '8', 'ι': 'i', 'κ': 'k', 'λ': 'l', 'μ': 'm', 'ν': 'n', 'ξ': '3', 21 | 'ο': 'o', 'π': 'p', 'ρ': 'r', 'σ': 's', 'τ': 't', 'υ': 'y', 'φ': 'f', 22 | 'χ': 'x', 'ψ': 'ps', 'ω': 'w', 'ά': 'a', 'έ': 'e', 'ί': 'i', 'ό': 'o', 23 | 'ύ': 'y', 'ή': 'h', 'ώ': 'w', 'ς': 's', 'ϊ': 'i', 'ΰ': 'y', 'ϋ': 'y', 24 | 'ΐ': 'i', 'Α': 'A', 'Β': 'B', 'Γ': 'G', 'Δ': 'D', 'Ε': 'E', 'Ζ': 'Z', 25 | 'Η': 'H', 'Θ': '8', 'Ι': 'I', 'Κ': 'K', 'Λ': 'L', 'Μ': 'M', 'Ν': 'N', 26 | 'Ξ': '3', 'Ο': 'O', 'Π': 'P', 'Ρ': 'R', 'Σ': 'S', 'Τ': 'T', 'Υ': 'Y', 27 | 'Φ': 'F', 'Χ': 'X', 'Ψ': 'PS', 'Ω': 'W', 'Ά': 'A', 'Έ': 'E', 'Ί': 'I', 28 | 'Ό': 'O', 'Ύ': 'Y', 'Ή': 'H', 'Ώ': 'W', 'Ϊ': 'I', 'Ϋ': 'Y' 29 | }; 30 | 31 | var TURKISH_MAP = { 32 | 'ş': 's', 'Ş': 'S', 'ı': 'i', 'İ': 'I', 'ç': 'c', 'Ç': 'C', 'ü': 'u', 33 | 'Ü': 'U', 'ö': 'o', 'Ö': 'O', 'ğ': 'g', 'Ğ': 'G' 34 | }; 35 | 36 | var ROMANIAN_MAP = { 37 | 'ă': 'a', 'î': 'i', 'ș': 's', 'ț': 't', 'â': 'a', 38 | 'Ă': 'A', 'Î': 'I', 'Ș': 'S', 'Ț': 'T', 'Â': 'A' 39 | }; 40 | 41 | var RUSSIAN_MAP = { 42 | 'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo', 43 | 'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'j', 'к': 'k', 'л': 'l', 'м': 'm', 44 | 'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u', 45 | 'ф': 'f', 'х': 'h', 'ц': 'c', 'ч': 'ch', 'ш': 'sh', 'щ': 'sh', 'ъ': '', 46 | 'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu', 'я': 'ya', 47 | 'А': 'A', 'Б': 'B', 'В': 'V', 'Г': 'G', 'Д': 'D', 'Е': 'E', 'Ё': 'Yo', 48 | 'Ж': 'Zh', 'З': 'Z', 'И': 'I', 'Й': 'J', 'К': 'K', 'Л': 'L', 'М': 'M', 49 | 'Н': 'N', 'О': 'O', 'П': 'P', 'Р': 'R', 'С': 'S', 'Т': 'T', 'У': 'U', 50 | 'Ф': 'F', 'Х': 'H', 'Ц': 'C', 'Ч': 'Ch', 'Ш': 'Sh', 'Щ': 'Sh', 'Ъ': '', 51 | 'Ы': 'Y', 'Ь': '', 'Э': 'E', 'Ю': 'Yu', 'Я': 'Ya' 52 | }; 53 | 54 | var UKRAINIAN_MAP = { 55 | 'Є': 'Ye', 'І': 'I', 'Ї': 'Yi', 'Ґ': 'G', 'є': 'ye', 'і': 'i', 56 | 'ї': 'yi', 'ґ': 'g' 57 | }; 58 | 59 | var CZECH_MAP = { 60 | 'č': 'c', 'ď': 'd', 'ě': 'e', 'ň': 'n', 'ř': 'r', 'š': 's', 'ť': 't', 61 | 'ů': 'u', 'ž': 'z', 'Č': 'C', 'Ď': 'D', 'Ě': 'E', 'Ň': 'N', 'Ř': 'R', 62 | 'Š': 'S', 'Ť': 'T', 'Ů': 'U', 'Ž': 'Z' 63 | }; 64 | 65 | var POLISH_MAP = { 66 | 'ą': 'a', 'ć': 'c', 'ę': 'e', 'ł': 'l', 'ń': 'n', 'ó': 'o', 'ś': 's', 67 | 'ź': 'z', 'ż': 'z', 68 | 'Ą': 'A', 'Ć': 'C', 'Ę': 'E', 'Ł': 'L', 'Ń': 'N', 'Ó': 'O', 'Ś': 'S', 69 | 'Ź': 'Z', 'Ż': 'Z' 70 | }; 71 | 72 | var LATVIAN_MAP = { 73 | 'ā': 'a', 'č': 'c', 'ē': 'e', 'ģ': 'g', 'ī': 'i', 'ķ': 'k', 'ļ': 'l', 74 | 'ņ': 'n', 'š': 's', 'ū': 'u', 'ž': 'z', 75 | 'Ā': 'A', 'Č': 'C', 'Ē': 'E', 'Ģ': 'G', 'Ī': 'I', 'Ķ': 'K', 'Ļ': 'L', 76 | 'Ņ': 'N', 'Š': 'S', 'Ū': 'U', 'Ž': 'Z' 77 | }; 78 | 79 | var ARABIC_MAP = { 80 | 'أ': 'a', 'ب': 'b', 'ت': 't', 'ث': 'th', 'ج': 'g', 'ح': 'h', 'خ': 'kh', 'د': 'd', 81 | 'ذ': 'th', 'ر': 'r', 'ز': 'z', 'س': 's', 'ش': 'sh', 'ص': 's', 'ض': 'd', 'ط': 't', 82 | 'ظ': 'th', 'ع': 'aa', 'غ': 'gh', 'ف': 'f', 'ق': 'k', 'ك': 'k', 'ل': 'l', 'م': 'm', 83 | 'ن': 'n', 'ه': 'h', 'و': 'o', 'ي': 'y' 84 | }; 85 | var LITHUANIAN_MAP = { 86 | 'ą': 'a', 'č': 'c', 'ę': 'e', 'ė': 'e', 'į': 'i', 'š': 's', 'ų': 'u', 87 | 'ū': 'u', 'ž': 'z', 88 | 'Ą': 'A', 'Č': 'C', 'Ę': 'E', 'Ė': 'E', 'Į': 'I', 'Š': 'S', 'Ų': 'U', 89 | 'Ū': 'U', 'Ž': 'Z' 90 | }; 91 | var SERBIAN_MAP = { 92 | 'ђ': 'dj', 'ј': 'j', 'љ': 'lj', 'њ': 'nj', 'ћ': 'c', 'џ': 'dz', 93 | 'đ': 'dj', 'Ђ': 'Dj', 'Ј': 'j', 'Љ': 'Lj', 'Њ': 'Nj', 'Ћ': 'C', 94 | 'Џ': 'Dz', 'Đ': 'Dj' 95 | }; 96 | var AZERBAIJANI_MAP = { 97 | 'ç': 'c', 'ə': 'e', 'ğ': 'g', 'ı': 'i', 'ö': 'o', 'ş': 's', 'ü': 'u', 98 | 'Ç': 'C', 'Ə': 'E', 'Ğ': 'G', 'İ': 'I', 'Ö': 'O', 'Ş': 'S', 'Ü': 'U' 99 | }; 100 | var GEORGIAN_MAP = { 101 | 'ა': 'a', 'ბ': 'b', 'გ': 'g', 'დ': 'd', 'ე': 'e', 'ვ': 'v', 'ზ': 'z', 102 | 'თ': 't', 'ი': 'i', 'კ': 'k', 'ლ': 'l', 'მ': 'm', 'ნ': 'n', 'ო': 'o', 103 | 'პ': 'p', 'ჟ': 'j', 'რ': 'r', 'ს': 's', 'ტ': 't', 'უ': 'u', 'ფ': 'f', 104 | 'ქ': 'q', 'ღ': 'g', 'ყ': 'y', 'შ': 'sh', 'ჩ': 'ch', 'ც': 'c', 'ძ': 'dz', 105 | 'წ': 'w', 'ჭ': 'ch', 'ხ': 'x', 'ჯ': 'j', 'ჰ': 'h' 106 | }; 107 | 108 | var SLOVAK_MAP = { 109 | 'á': 'a', 'ä': 'a', 'č': 'c', 'ď': 'd', 'é': 'e', 'í': 'i', 'ľ': 'l', 110 | 'ĺ': 'l', 'ň': 'n', 'ó': 'o', 'ô': 'o', 'ŕ': 'r', 'š': 's', 'ť': 't', 111 | 'ú': 'u', 'ý': 'y', 'ž': 'z', 112 | 'Á': 'a', 'Ä': 'A', 'Č': 'C', 'Ď': 'D', 'É': 'E', 'Í': 'I', 'Ľ': 'L', 113 | 'Ĺ': 'L', 'Ň': 'N', 'Ó': 'O', 'Ô': 'O', 'Ŕ': 'R', 'Š': 'S', 'Ť': 'T', 114 | 'Ú': 'U', 'Ý': 'Y', 'Ž': 'Z' 115 | }; 116 | 117 | var ALL_DOWNCODE_MAPS = [ 118 | LATIN_MAP, 119 | LATIN_SYMBOLS_MAP, 120 | GREEK_MAP, 121 | TURKISH_MAP, 122 | ROMANIAN_MAP, 123 | RUSSIAN_MAP, 124 | UKRAINIAN_MAP, 125 | CZECH_MAP, 126 | POLISH_MAP, 127 | LATVIAN_MAP, 128 | ARABIC_MAP, 129 | LITHUANIAN_MAP, 130 | SERBIAN_MAP, 131 | AZERBAIJANI_MAP, 132 | GEORGIAN_MAP, 133 | SLOVAK_MAP 134 | ]; 135 | 136 | 137 | var Downcoder = new Object(); 138 | Downcoder.Initialize = function() 139 | { 140 | if (Downcoder.map) // already made 141 | return ; 142 | Downcoder.map ={} 143 | Downcoder.chars = '' ; 144 | for(var i in ALL_DOWNCODE_MAPS) 145 | { 146 | var lookup = ALL_DOWNCODE_MAPS[i] 147 | for (var c in lookup) 148 | { 149 | Downcoder.map[c] = lookup[c] ; 150 | Downcoder.chars += c ; 151 | } 152 | } 153 | Downcoder.regex = new RegExp('[' + Downcoder.chars + ']|[^' + Downcoder.chars + ']+','g') ; 154 | } 155 | 156 | var downcode = function(slug){ 157 | Downcoder.Initialize() ; 158 | var downcoded ="" 159 | var pieces = slug.match(Downcoder.regex); 160 | if(pieces) 161 | { 162 | for (var i = 0 ; i < pieces.length ; i++) 163 | { 164 | if (pieces[i].length == 1) 165 | { 166 | var mapped = Downcoder.map[pieces[i]] ; 167 | if (mapped != null) 168 | { 169 | downcoded+=mapped; 170 | continue ; 171 | } 172 | } 173 | downcoded+=pieces[i]; 174 | } 175 | } 176 | else 177 | { 178 | downcoded = slug; 179 | } 180 | return downcoded; 181 | } 182 | 183 | parameterize = function(s, num_chars, delimiter) { 184 | delimiter = delimiter || '-' 185 | 186 | // changes, e.g., "Petty theft" to "petty_theft" 187 | // remove all these words from the string before urlifying 188 | s = downcode(s); 189 | // 190 | // if downcode doesn't hit, the char will be stripped here 191 | s = s.replace(/[^-\w\s\u4E00-\u9FA5]/g, ''); // remove unneeded chars 192 | s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces 193 | s = s.replace(/[-\s]+/g, delimiter); // convert spaces to hyphens 194 | s = s.toLowerCase(); // convert to lowercase 195 | return s.substring(0, num_chars);// trim to first num_chars chars 196 | } 197 | 198 | 199 | if (typeof module !== 'undefined' && module.exports) { 200 | module.exports = parameterize; 201 | } else if (typeof define === 'function' && define.amd) { 202 | define('parameterize', [], function(require, exports, module) { 203 | return parameterize; 204 | }); 205 | } 206 | --------------------------------------------------------------------------------