initial commit
[emels.git] / emels / static / admin / js / urlify.js
1 /*global XRegExp*/
2 (function() {
3     'use strict';
4
5     var LATIN_MAP = {
6         'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE',
7         'Ç': 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I',
8         'Î': 'I', 'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O',
9         'Õ': 'O', 'Ö': 'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U',
10         'Ü': 'U', 'Ű': 'U', 'Ý': 'Y', 'Þ': 'TH', 'Ÿ': 'Y', 'ß': 'ss', 'à': 'a',
11         'á': 'a', 'â': 'a', 'ã': 'a', 'ä': 'a', 'å': 'a', 'æ': 'ae', 'ç': 'c',
12         'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e', 'ì': 'i', 'í': 'i', 'î': 'i',
13         'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ': 'o',
14         'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u',
15         'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
16     };
17     var LATIN_SYMBOLS_MAP = {
18         '©': '(c)'
19     };
20     var GREEK_MAP = {
21         'α': 'a', 'β': 'b', 'γ': 'g', 'δ': 'd', 'ε': 'e', 'ζ': 'z', 'η': 'h',
22         'θ': '8', 'ι': 'i', 'κ': 'k', 'λ': 'l', 'μ': 'm', 'ν': 'n', 'ξ': '3',
23         'ο': 'o', 'π': 'p', 'ρ': 'r', 'σ': 's', 'τ': 't', 'υ': 'y', 'φ': 'f',
24         'χ': 'x', 'ψ': 'ps', 'ω': 'w', 'ά': 'a', 'έ': 'e', 'ί': 'i', 'ό': 'o',
25         'ύ': 'y', 'ή': 'h', 'ώ': 'w', 'ς': 's', 'ϊ': 'i', 'ΰ': 'y', 'ϋ': 'y',
26         'ΐ': 'i', 'Α': 'A', 'Β': 'B', 'Γ': 'G', 'Δ': 'D', 'Ε': 'E', 'Ζ': 'Z',
27         'Η': 'H', 'Θ': '8', 'Ι': 'I', 'Κ': 'K', 'Λ': 'L', 'Μ': 'M', 'Ν': 'N',
28         'Ξ': '3', 'Ο': 'O', 'Π': 'P', 'Ρ': 'R', 'Σ': 'S', 'Τ': 'T', 'Υ': 'Y',
29         'Φ': 'F', 'Χ': 'X', 'Ψ': 'PS', 'Ω': 'W', 'Ά': 'A', 'Έ': 'E', 'Ί': 'I',
30         'Ό': 'O', 'Ύ': 'Y', 'Ή': 'H', 'Ώ': 'W', 'Ϊ': 'I', 'Ϋ': 'Y'
31     };
32     var TURKISH_MAP = {
33         'ş': 's', 'Ş': 'S', 'ı': 'i', 'İ': 'I', 'ç': 'c', 'Ç': 'C', 'ü': 'u',
34         'Ü': 'U', 'ö': 'o', 'Ö': 'O', 'ğ': 'g', 'Ğ': 'G'
35     };
36     var ROMANIAN_MAP = {
37         'ă': 'a', 'î': 'i', 'ș': 's', 'ț': 't', 'â': 'a',
38         'Ă': 'A', 'Î': 'I', 'Ș': 'S', 'Ț': 'T', 'Â': 'A'
39     };
40     var RUSSIAN_MAP = {
41         'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo',
42         'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'j', 'к': 'k', 'л': 'l', 'м': 'm',
43         'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u',
44         'ф': 'f', 'х': 'h', 'ц': 'c', 'ч': 'ch', 'ш': 'sh', 'щ': 'sh', 'ъ': '',
45         'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu', 'я': 'ya',
46         'А': 'A', 'Б': 'B', 'В': 'V', 'Г': 'G', 'Д': 'D', 'Е': 'E', 'Ё': 'Yo',
47         'Ж': 'Zh', 'З': 'Z', 'И': 'I', 'Й': 'J', 'К': 'K', 'Л': 'L', 'М': 'M',
48         'Н': 'N', 'О': 'O', 'П': 'P', 'Р': 'R', 'С': 'S', 'Т': 'T', 'У': 'U',
49         'Ф': 'F', 'Х': 'H', 'Ц': 'C', 'Ч': 'Ch', 'Ш': 'Sh', 'Щ': 'Sh', 'Ъ': '',
50         'Ы': 'Y', 'Ь': '', 'Э': 'E', 'Ю': 'Yu', 'Я': 'Ya'
51     };
52     var UKRAINIAN_MAP = {
53         'Є': 'Ye', 'І': 'I', 'Ї': 'Yi', 'Ґ': 'G', 'є': 'ye', 'і': 'i',
54         'ї': 'yi', 'ґ': 'g'
55     };
56     var CZECH_MAP = {
57         'č': 'c', 'ď': 'd', 'ě': 'e', 'ň': 'n', 'ř': 'r', 'š': 's', 'ť': 't',
58         'ů': 'u', 'ž': 'z', 'Č': 'C', 'Ď': 'D', 'Ě': 'E', 'Ň': 'N', 'Ř': 'R',
59         'Š': 'S', 'Ť': 'T', 'Ů': 'U', 'Ž': 'Z'
60     };
61     var POLISH_MAP = {
62         'ą': 'a', 'ć': 'c', 'ę': 'e', 'ł': 'l', 'ń': 'n', 'ó': 'o', 'ś': 's',
63         'ź': 'z', 'ż': 'z',
64         'Ą': 'A', 'Ć': 'C', 'Ę': 'E', 'Ł': 'L', 'Ń': 'N', 'Ó': 'O', 'Ś': 'S',
65         'Ź': 'Z', 'Ż': 'Z'
66     };
67     var LATVIAN_MAP = {
68         'ā': 'a', 'č': 'c', 'ē': 'e', 'ģ': 'g', 'ī': 'i', 'ķ': 'k', 'ļ': 'l',
69         'ņ': 'n', 'š': 's', 'ū': 'u', 'ž': 'z',
70         'Ā': 'A', 'Č': 'C', 'Ē': 'E', 'Ģ': 'G', 'Ī': 'I', 'Ķ': 'K', 'Ļ': 'L',
71         'Ņ': 'N', 'Š': 'S', 'Ū': 'U', 'Ž': 'Z'
72     };
73     var ARABIC_MAP = {
74         'أ': 'a', 'ب': 'b', 'ت': 't', 'ث': 'th', 'ج': 'g', 'ح': 'h', 'خ': 'kh', 'د': 'd',
75         'ذ': 'th', 'ر': 'r', 'ز': 'z', 'س': 's', 'ش': 'sh', 'ص': 's', 'ض': 'd', 'ط': 't',
76         'ظ': 'th', 'ع': 'aa', 'غ': 'gh', 'ف': 'f', 'ق': 'k', 'ك': 'k', 'ل': 'l', 'م': 'm',
77         'ن': 'n', 'ه': 'h', 'و': 'o', 'ي': 'y'
78     };
79     var LITHUANIAN_MAP = {
80         'ą': 'a', 'č': 'c', 'ę': 'e', 'ė': 'e', 'į': 'i', 'š': 's', 'ų': 'u',
81         'ū': 'u', 'ž': 'z',
82         'Ą': 'A', 'Č': 'C', 'Ę': 'E', 'Ė': 'E', 'Į': 'I', 'Š': 'S', 'Ų': 'U',
83         'Ū': 'U', 'Ž': 'Z'
84     };
85     var SERBIAN_MAP = {
86         'ђ': 'dj', 'ј': 'j', 'љ': 'lj', 'њ': 'nj', 'ћ': 'c', 'џ': 'dz',
87         'đ': 'dj', 'Ђ': 'Dj', 'Ј': 'j', 'Љ': 'Lj', 'Њ': 'Nj', 'Ћ': 'C',
88         'Џ': 'Dz', 'Đ': 'Dj'
89     };
90     var AZERBAIJANI_MAP = {
91         'ç': 'c', 'ə': 'e', 'ğ': 'g', 'ı': 'i', 'ö': 'o', 'ş': 's', 'ü': 'u',
92         'Ç': 'C', 'Ə': 'E', 'Ğ': 'G', 'İ': 'I', 'Ö': 'O', 'Ş': 'S', 'Ü': 'U'
93     };
94     var GEORGIAN_MAP = {
95         'ა': 'a', 'ბ': 'b', 'გ': 'g', 'დ': 'd', 'ე': 'e', 'ვ': 'v', 'ზ': 'z',
96         'თ': 't', 'ი': 'i', 'კ': 'k', 'ლ': 'l', 'მ': 'm', 'ნ': 'n', 'ო': 'o',
97         'პ': 'p', 'ჟ': 'j', 'რ': 'r', 'ს': 's', 'ტ': 't', 'უ': 'u', 'ფ': 'f',
98         'ქ': 'q', 'ღ': 'g', 'ყ': 'y', 'შ': 'sh', 'ჩ': 'ch', 'ც': 'c', 'ძ': 'dz',
99         'წ': 'w', 'ჭ': 'ch', 'ხ': 'x', 'ჯ': 'j', 'ჰ': 'h'
100     };
101
102     var ALL_DOWNCODE_MAPS = [
103         LATIN_MAP,
104         LATIN_SYMBOLS_MAP,
105         GREEK_MAP,
106         TURKISH_MAP,
107         ROMANIAN_MAP,
108         RUSSIAN_MAP,
109         UKRAINIAN_MAP,
110         CZECH_MAP,
111         POLISH_MAP,
112         LATVIAN_MAP,
113         ARABIC_MAP,
114         LITHUANIAN_MAP,
115         SERBIAN_MAP,
116         AZERBAIJANI_MAP,
117         GEORGIAN_MAP
118     ];
119
120     var Downcoder = {
121         'Initialize': function() {
122             if (Downcoder.map) {  // already made
123                 return;
124             }
125             Downcoder.map = {};
126             Downcoder.chars = [];
127             for (var i = 0; i < ALL_DOWNCODE_MAPS.length; i++) {
128                 var lookup = ALL_DOWNCODE_MAPS[i];
129                 for (var c in lookup) {
130                     if (lookup.hasOwnProperty(c)) {
131                         Downcoder.map[c] = lookup[c];
132                     }
133                 }
134             }
135             for (var k in Downcoder.map) {
136                 if (Downcoder.map.hasOwnProperty(k)) {
137                     Downcoder.chars.push(k);
138                 }
139             }
140             Downcoder.regex = new RegExp(Downcoder.chars.join('|'), 'g');
141         }
142     };
143
144     function downcode(slug) {
145         Downcoder.Initialize();
146         return slug.replace(Downcoder.regex, function(m) {
147             return Downcoder.map[m];
148         });
149     }
150
151
152     function URLify(s, num_chars, allowUnicode) {
153         // changes, e.g., "Petty theft" to "petty-theft"
154         // remove all these words from the string before urlifying
155         if (!allowUnicode) {
156             s = downcode(s);
157         }
158         var removelist = [
159             "a", "an", "as", "at", "before", "but", "by", "for", "from", "is",
160             "in", "into", "like", "of", "off", "on", "onto", "per", "since",
161             "than", "the", "this", "that", "to", "up", "via", "with"
162         ];
163         var r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
164         s = s.replace(r, '');
165         // if downcode doesn't hit, the char will be stripped here
166         if (allowUnicode) {
167             // Keep Unicode letters including both lowercase and uppercase
168             // characters, whitespace, and dash; remove other characters.
169             s = XRegExp.replace(s, XRegExp('[^-_\\p{L}\\p{N}\\s]', 'g'), '');
170         } else {
171             s = s.replace(/[^-\w\s]/g, '');  // remove unneeded chars
172         }
173         s = s.replace(/^\s+|\s+$/g, '');   // trim leading/trailing spaces
174         s = s.replace(/[-\s]+/g, '-');     // convert spaces to hyphens
175         s = s.toLowerCase();               // convert to lowercase
176         return s.substring(0, num_chars);  // trim to first num_chars chars
177     }
178     window.URLify = URLify;
179 })();