speakingurl.js 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689
  1. (function (root) {
  2. 'use strict';
  3. /**
  4. * charMap
  5. * @type {Object}
  6. */
  7. var charMap = {
  8. // latin
  9. 'À': 'A',
  10. 'Á': 'A',
  11. 'Â': 'A',
  12. 'Ã': 'A',
  13. 'Ä': 'Ae',
  14. 'Å': 'A',
  15. 'Æ': 'AE',
  16. 'Ç': 'C',
  17. 'È': 'E',
  18. 'É': 'E',
  19. 'Ê': 'E',
  20. 'Ë': 'E',
  21. 'Ì': 'I',
  22. 'Í': 'I',
  23. 'Î': 'I',
  24. 'Ï': 'I',
  25. 'Ð': 'D',
  26. 'Ñ': 'N',
  27. 'Ò': 'O',
  28. 'Ó': 'O',
  29. 'Ô': 'O',
  30. 'Õ': 'O',
  31. 'Ö': 'Oe',
  32. 'Ő': 'O',
  33. 'Ø': 'O',
  34. 'Ù': 'U',
  35. 'Ú': 'U',
  36. 'Û': 'U',
  37. 'Ü': 'Ue',
  38. 'Ű': 'U',
  39. 'Ý': 'Y',
  40. 'Þ': 'TH',
  41. 'ß': 'ss',
  42. 'à': 'a',
  43. 'á': 'a',
  44. 'â': 'a',
  45. 'ã': 'a',
  46. 'ä': 'ae',
  47. 'å': 'a',
  48. 'æ': 'ae',
  49. 'ç': 'c',
  50. 'è': 'e',
  51. 'é': 'e',
  52. 'ê': 'e',
  53. 'ë': 'e',
  54. 'ì': 'i',
  55. 'í': 'i',
  56. 'î': 'i',
  57. 'ï': 'i',
  58. 'ð': 'd',
  59. 'ñ': 'n',
  60. 'ò': 'o',
  61. 'ó': 'o',
  62. 'ô': 'o',
  63. 'õ': 'o',
  64. 'ö': 'oe',
  65. 'ő': 'o',
  66. 'ø': 'o',
  67. 'ù': 'u',
  68. 'ú': 'u',
  69. 'û': 'u',
  70. 'ü': 'ue',
  71. 'ű': 'u',
  72. 'ý': 'y',
  73. 'þ': 'th',
  74. 'ÿ': 'y',
  75. 'ẞ': 'SS',
  76. // language specific
  77. // Arabic
  78. 'ا': 'a',
  79. 'أ': 'a',
  80. 'إ': 'i',
  81. 'آ': 'aa',
  82. 'ؤ': 'u',
  83. 'ئ': 'e',
  84. 'ء': 'a',
  85. 'ب': 'b',
  86. 'ت': 't',
  87. 'ث': 'th',
  88. 'ج': 'j',
  89. 'ح': 'h',
  90. 'خ': 'kh',
  91. 'د': 'd',
  92. 'ذ': 'th',
  93. 'ر': 'r',
  94. 'ز': 'z',
  95. 'س': 's',
  96. 'ش': 'sh',
  97. 'ص': 's',
  98. 'ض': 'dh',
  99. 'ط': 't',
  100. 'ظ': 'z',
  101. 'ع': 'a',
  102. 'غ': 'gh',
  103. 'ف': 'f',
  104. 'ق': 'q',
  105. 'ك': 'k',
  106. 'ل': 'l',
  107. 'م': 'm',
  108. 'ن': 'n',
  109. 'ه': 'h',
  110. 'و': 'w',
  111. 'ي': 'y',
  112. 'ى': 'a',
  113. 'ة': 'h',
  114. 'ﻻ': 'la',
  115. 'ﻷ': 'laa',
  116. 'ﻹ': 'lai',
  117. 'ﻵ': 'laa',
  118. // Persian additional characters than Arabic
  119. 'گ': 'g',
  120. 'چ': 'ch',
  121. 'پ': 'p',
  122. 'ژ': 'zh',
  123. 'ک': 'k',
  124. 'ی': 'y',
  125. // Arabic diactrics
  126. 'َ': 'a',
  127. 'ً': 'an',
  128. 'ِ': 'e',
  129. 'ٍ': 'en',
  130. 'ُ': 'u',
  131. 'ٌ': 'on',
  132. 'ْ': '',
  133. // Arabic numbers
  134. '٠': '0',
  135. '١': '1',
  136. '٢': '2',
  137. '٣': '3',
  138. '٤': '4',
  139. '٥': '5',
  140. '٦': '6',
  141. '٧': '7',
  142. '٨': '8',
  143. '٩': '9',
  144. // Persian numbers
  145. '۰': '0',
  146. '۱': '1',
  147. '۲': '2',
  148. '۳': '3',
  149. '۴': '4',
  150. '۵': '5',
  151. '۶': '6',
  152. '۷': '7',
  153. '۸': '8',
  154. '۹': '9',
  155. // Burmese consonants
  156. 'က': 'k',
  157. 'ခ': 'kh',
  158. 'ဂ': 'g',
  159. 'ဃ': 'ga',
  160. 'င': 'ng',
  161. 'စ': 's',
  162. 'ဆ': 'sa',
  163. 'ဇ': 'z',
  164. 'စျ': 'za',
  165. 'ည': 'ny',
  166. 'ဋ': 't',
  167. 'ဌ': 'ta',
  168. 'ဍ': 'd',
  169. 'ဎ': 'da',
  170. 'ဏ': 'na',
  171. 'တ': 't',
  172. 'ထ': 'ta',
  173. 'ဒ': 'd',
  174. 'ဓ': 'da',
  175. 'န': 'n',
  176. 'ပ': 'p',
  177. 'ဖ': 'pa',
  178. 'ဗ': 'b',
  179. 'ဘ': 'ba',
  180. 'မ': 'm',
  181. 'ယ': 'y',
  182. 'ရ': 'ya',
  183. 'လ': 'l',
  184. 'ဝ': 'w',
  185. 'သ': 'th',
  186. 'ဟ': 'h',
  187. 'ဠ': 'la',
  188. 'အ': 'a',
  189. // consonant character combos
  190. 'ြ': 'y',
  191. 'ျ': 'ya',
  192. 'ွ': 'w',
  193. 'ြွ': 'yw',
  194. 'ျွ': 'ywa',
  195. 'ှ': 'h',
  196. // independent vowels
  197. 'ဧ': 'e',
  198. '၏': '-e',
  199. 'ဣ': 'i',
  200. 'ဤ': '-i',
  201. 'ဉ': 'u',
  202. 'ဦ': '-u',
  203. 'ဩ': 'aw',
  204. 'သြော': 'aw',
  205. 'ဪ': 'aw',
  206. // numbers
  207. '၀': '0',
  208. '၁': '1',
  209. '၂': '2',
  210. '၃': '3',
  211. '၄': '4',
  212. '၅': '5',
  213. '၆': '6',
  214. '၇': '7',
  215. '၈': '8',
  216. '၉': '9',
  217. // virama and tone marks which are silent in transliteration
  218. '္': '',
  219. '့': '',
  220. 'း': '',
  221. // Czech
  222. 'č': 'c',
  223. 'ď': 'd',
  224. 'ě': 'e',
  225. 'ň': 'n',
  226. 'ř': 'r',
  227. 'š': 's',
  228. 'ť': 't',
  229. 'ů': 'u',
  230. 'ž': 'z',
  231. 'Č': 'C',
  232. 'Ď': 'D',
  233. 'Ě': 'E',
  234. 'Ň': 'N',
  235. 'Ř': 'R',
  236. 'Š': 'S',
  237. 'Ť': 'T',
  238. 'Ů': 'U',
  239. 'Ž': 'Z',
  240. // Dhivehi
  241. 'ހ': 'h',
  242. 'ށ': 'sh',
  243. 'ނ': 'n',
  244. 'ރ': 'r',
  245. 'ބ': 'b',
  246. 'ޅ': 'lh',
  247. 'ކ': 'k',
  248. 'އ': 'a',
  249. 'ވ': 'v',
  250. 'މ': 'm',
  251. 'ފ': 'f',
  252. 'ދ': 'dh',
  253. 'ތ': 'th',
  254. 'ލ': 'l',
  255. 'ގ': 'g',
  256. 'ޏ': 'gn',
  257. 'ސ': 's',
  258. 'ޑ': 'd',
  259. 'ޒ': 'z',
  260. 'ޓ': 't',
  261. 'ޔ': 'y',
  262. 'ޕ': 'p',
  263. 'ޖ': 'j',
  264. 'ޗ': 'ch',
  265. 'ޘ': 'tt',
  266. 'ޙ': 'hh',
  267. 'ޚ': 'kh',
  268. 'ޛ': 'th',
  269. 'ޜ': 'z',
  270. 'ޝ': 'sh',
  271. 'ޞ': 's',
  272. 'ޟ': 'd',
  273. 'ޠ': 't',
  274. 'ޡ': 'z',
  275. 'ޢ': 'a',
  276. 'ޣ': 'gh',
  277. 'ޤ': 'q',
  278. 'ޥ': 'w',
  279. 'ަ': 'a',
  280. 'ާ': 'aa',
  281. 'ި': 'i',
  282. 'ީ': 'ee',
  283. 'ު': 'u',
  284. 'ޫ': 'oo',
  285. 'ެ': 'e',
  286. 'ޭ': 'ey',
  287. 'ޮ': 'o',
  288. 'ޯ': 'oa',
  289. 'ް': '',
  290. // Georgian https://en.wikipedia.org/wiki/Romanization_of_Georgian
  291. // National system (2002)
  292. 'ა': 'a',
  293. 'ბ': 'b',
  294. 'გ': 'g',
  295. 'დ': 'd',
  296. 'ე': 'e',
  297. 'ვ': 'v',
  298. 'ზ': 'z',
  299. 'თ': 't',
  300. 'ი': 'i',
  301. 'კ': 'k',
  302. 'ლ': 'l',
  303. 'მ': 'm',
  304. 'ნ': 'n',
  305. 'ო': 'o',
  306. 'პ': 'p',
  307. 'ჟ': 'zh',
  308. 'რ': 'r',
  309. 'ს': 's',
  310. 'ტ': 't',
  311. 'უ': 'u',
  312. 'ფ': 'p',
  313. 'ქ': 'k',
  314. 'ღ': 'gh',
  315. 'ყ': 'q',
  316. 'შ': 'sh',
  317. 'ჩ': 'ch',
  318. 'ც': 'ts',
  319. 'ძ': 'dz',
  320. 'წ': 'ts',
  321. 'ჭ': 'ch',
  322. 'ხ': 'kh',
  323. 'ჯ': 'j',
  324. 'ჰ': 'h',
  325. // Greek
  326. 'α': 'a',
  327. 'β': 'v',
  328. 'γ': 'g',
  329. 'δ': 'd',
  330. 'ε': 'e',
  331. 'ζ': 'z',
  332. 'η': 'i',
  333. 'θ': 'th',
  334. 'ι': 'i',
  335. 'κ': 'k',
  336. 'λ': 'l',
  337. 'μ': 'm',
  338. 'ν': 'n',
  339. 'ξ': 'ks',
  340. 'ο': 'o',
  341. 'π': 'p',
  342. 'ρ': 'r',
  343. 'σ': 's',
  344. 'τ': 't',
  345. 'υ': 'y',
  346. 'φ': 'f',
  347. 'χ': 'x',
  348. 'ψ': 'ps',
  349. 'ω': 'o',
  350. 'ά': 'a',
  351. 'έ': 'e',
  352. 'ί': 'i',
  353. 'ό': 'o',
  354. 'ύ': 'y',
  355. 'ή': 'i',
  356. 'ώ': 'o',
  357. 'ς': 's',
  358. 'ϊ': 'i',
  359. 'ΰ': 'y',
  360. 'ϋ': 'y',
  361. 'ΐ': 'i',
  362. 'Α': 'A',
  363. 'Β': 'B',
  364. 'Γ': 'G',
  365. 'Δ': 'D',
  366. 'Ε': 'E',
  367. 'Ζ': 'Z',
  368. 'Η': 'I',
  369. 'Θ': 'TH',
  370. 'Ι': 'I',
  371. 'Κ': 'K',
  372. 'Λ': 'L',
  373. 'Μ': 'M',
  374. 'Ν': 'N',
  375. 'Ξ': 'KS',
  376. 'Ο': 'O',
  377. 'Π': 'P',
  378. 'Ρ': 'R',
  379. 'Σ': 'S',
  380. 'Τ': 'T',
  381. 'Υ': 'Y',
  382. 'Φ': 'F',
  383. 'Χ': 'X',
  384. 'Ψ': 'PS',
  385. 'Ω': 'O',
  386. 'Ά': 'A',
  387. 'Έ': 'E',
  388. 'Ί': 'I',
  389. 'Ό': 'O',
  390. 'Ύ': 'Y',
  391. 'Ή': 'I',
  392. 'Ώ': 'O',
  393. 'Ϊ': 'I',
  394. 'Ϋ': 'Y',
  395. // Latvian
  396. 'ā': 'a',
  397. // 'č': 'c', // duplicate
  398. 'ē': 'e',
  399. 'ģ': 'g',
  400. 'ī': 'i',
  401. 'ķ': 'k',
  402. 'ļ': 'l',
  403. 'ņ': 'n',
  404. // 'š': 's', // duplicate
  405. 'ū': 'u',
  406. // 'ž': 'z', // duplicate
  407. 'Ā': 'A',
  408. // 'Č': 'C', // duplicate
  409. 'Ē': 'E',
  410. 'Ģ': 'G',
  411. 'Ī': 'I',
  412. 'Ķ': 'k',
  413. 'Ļ': 'L',
  414. 'Ņ': 'N',
  415. // 'Š': 'S', // duplicate
  416. 'Ū': 'U',
  417. // 'Ž': 'Z', // duplicate
  418. // Macedonian
  419. 'Ќ': 'Kj',
  420. 'ќ': 'kj',
  421. 'Љ': 'Lj',
  422. 'љ': 'lj',
  423. 'Њ': 'Nj',
  424. 'њ': 'nj',
  425. 'Тс': 'Ts',
  426. 'тс': 'ts',
  427. // Polish
  428. 'ą': 'a',
  429. 'ć': 'c',
  430. 'ę': 'e',
  431. 'ł': 'l',
  432. 'ń': 'n',
  433. // 'ó': 'o', // duplicate
  434. 'ś': 's',
  435. 'ź': 'z',
  436. 'ż': 'z',
  437. 'Ą': 'A',
  438. 'Ć': 'C',
  439. 'Ę': 'E',
  440. 'Ł': 'L',
  441. 'Ń': 'N',
  442. 'Ś': 'S',
  443. 'Ź': 'Z',
  444. 'Ż': 'Z',
  445. // Ukranian
  446. 'Є': 'Ye',
  447. 'І': 'I',
  448. 'Ї': 'Yi',
  449. 'Ґ': 'G',
  450. 'є': 'ye',
  451. 'і': 'i',
  452. 'ї': 'yi',
  453. 'ґ': 'g',
  454. // Romanian
  455. 'ă': 'a',
  456. 'Ă': 'A',
  457. 'ș': 's',
  458. 'Ș': 'S',
  459. // 'ş': 's', // duplicate
  460. // 'Ş': 'S', // duplicate
  461. 'ț': 't',
  462. 'Ț': 'T',
  463. 'ţ': 't',
  464. 'Ţ': 'T',
  465. // Russian https://en.wikipedia.org/wiki/Romanization_of_Russian
  466. // ICAO
  467. 'а': 'a',
  468. 'б': 'b',
  469. 'в': 'v',
  470. 'г': 'g',
  471. 'д': 'd',
  472. 'е': 'e',
  473. 'ё': 'yo',
  474. 'ж': 'zh',
  475. 'з': 'z',
  476. 'и': 'i',
  477. 'й': 'i',
  478. 'к': 'k',
  479. 'л': 'l',
  480. 'м': 'm',
  481. 'н': 'n',
  482. 'о': 'o',
  483. 'п': 'p',
  484. 'р': 'r',
  485. 'с': 's',
  486. 'т': 't',
  487. 'у': 'u',
  488. 'ф': 'f',
  489. 'х': 'kh',
  490. 'ц': 'c',
  491. 'ч': 'ch',
  492. 'ш': 'sh',
  493. 'щ': 'sh',
  494. 'ъ': '',
  495. 'ы': 'y',
  496. 'ь': '',
  497. 'э': 'e',
  498. 'ю': 'yu',
  499. 'я': 'ya',
  500. 'А': 'A',
  501. 'Б': 'B',
  502. 'В': 'V',
  503. 'Г': 'G',
  504. 'Д': 'D',
  505. 'Е': 'E',
  506. 'Ё': 'Yo',
  507. 'Ж': 'Zh',
  508. 'З': 'Z',
  509. 'И': 'I',
  510. 'Й': 'I',
  511. 'К': 'K',
  512. 'Л': 'L',
  513. 'М': 'M',
  514. 'Н': 'N',
  515. 'О': 'O',
  516. 'П': 'P',
  517. 'Р': 'R',
  518. 'С': 'S',
  519. 'Т': 'T',
  520. 'У': 'U',
  521. 'Ф': 'F',
  522. 'Х': 'Kh',
  523. 'Ц': 'C',
  524. 'Ч': 'Ch',
  525. 'Ш': 'Sh',
  526. 'Щ': 'Sh',
  527. 'Ъ': '',
  528. 'Ы': 'Y',
  529. 'Ь': '',
  530. 'Э': 'E',
  531. 'Ю': 'Yu',
  532. 'Я': 'Ya',
  533. // Serbian
  534. 'ђ': 'dj',
  535. 'ј': 'j',
  536. // 'љ': 'lj', // duplicate
  537. // 'њ': 'nj', // duplicate
  538. 'ћ': 'c',
  539. 'џ': 'dz',
  540. 'Ђ': 'Dj',
  541. 'Ј': 'j',
  542. // 'Љ': 'Lj', // duplicate
  543. // 'Њ': 'Nj', // duplicate
  544. 'Ћ': 'C',
  545. 'Џ': 'Dz',
  546. // Slovak
  547. 'ľ': 'l',
  548. 'ĺ': 'l',
  549. 'ŕ': 'r',
  550. 'Ľ': 'L',
  551. 'Ĺ': 'L',
  552. 'Ŕ': 'R',
  553. // Turkish
  554. 'ş': 's',
  555. 'Ş': 'S',
  556. 'ı': 'i',
  557. 'İ': 'I',
  558. // 'ç': 'c', // duplicate
  559. // 'Ç': 'C', // duplicate
  560. // 'ü': 'u', // duplicate, see langCharMap
  561. // 'Ü': 'U', // duplicate, see langCharMap
  562. // 'ö': 'o', // duplicate, see langCharMap
  563. // 'Ö': 'O', // duplicate, see langCharMap
  564. 'ğ': 'g',
  565. 'Ğ': 'G',
  566. // Vietnamese
  567. 'ả': 'a',
  568. 'Ả': 'A',
  569. 'ẳ': 'a',
  570. 'Ẳ': 'A',
  571. 'ẩ': 'a',
  572. 'Ẩ': 'A',
  573. 'đ': 'd',
  574. 'Đ': 'D',
  575. 'ẹ': 'e',
  576. 'Ẹ': 'E',
  577. 'ẽ': 'e',
  578. 'Ẽ': 'E',
  579. 'ẻ': 'e',
  580. 'Ẻ': 'E',
  581. 'ế': 'e',
  582. 'Ế': 'E',
  583. 'ề': 'e',
  584. 'Ề': 'E',
  585. 'ệ': 'e',
  586. 'Ệ': 'E',
  587. 'ễ': 'e',
  588. 'Ễ': 'E',
  589. 'ể': 'e',
  590. 'Ể': 'E',
  591. 'ỏ': 'o',
  592. 'ọ': 'o',
  593. 'Ọ': 'o',
  594. 'ố': 'o',
  595. 'Ố': 'O',
  596. 'ồ': 'o',
  597. 'Ồ': 'O',
  598. 'ổ': 'o',
  599. 'Ổ': 'O',
  600. 'ộ': 'o',
  601. 'Ộ': 'O',
  602. 'ỗ': 'o',
  603. 'Ỗ': 'O',
  604. 'ơ': 'o',
  605. 'Ơ': 'O',
  606. 'ớ': 'o',
  607. 'Ớ': 'O',
  608. 'ờ': 'o',
  609. 'Ờ': 'O',
  610. 'ợ': 'o',
  611. 'Ợ': 'O',
  612. 'ỡ': 'o',
  613. 'Ỡ': 'O',
  614. 'Ở': 'o',
  615. 'ở': 'o',
  616. 'ị': 'i',
  617. 'Ị': 'I',
  618. 'ĩ': 'i',
  619. 'Ĩ': 'I',
  620. 'ỉ': 'i',
  621. 'Ỉ': 'i',
  622. 'ủ': 'u',
  623. 'Ủ': 'U',
  624. 'ụ': 'u',
  625. 'Ụ': 'U',
  626. 'ũ': 'u',
  627. 'Ũ': 'U',
  628. 'ư': 'u',
  629. 'Ư': 'U',
  630. 'ứ': 'u',
  631. 'Ứ': 'U',
  632. 'ừ': 'u',
  633. 'Ừ': 'U',
  634. 'ự': 'u',
  635. 'Ự': 'U',
  636. 'ữ': 'u',
  637. 'Ữ': 'U',
  638. 'ử': 'u',
  639. 'Ử': 'ư',
  640. 'ỷ': 'y',
  641. 'Ỷ': 'y',
  642. 'ỳ': 'y',
  643. 'Ỳ': 'Y',
  644. 'ỵ': 'y',
  645. 'Ỵ': 'Y',
  646. 'ỹ': 'y',
  647. 'Ỹ': 'Y',
  648. 'ạ': 'a',
  649. 'Ạ': 'A',
  650. 'ấ': 'a',
  651. 'Ấ': 'A',
  652. 'ầ': 'a',
  653. 'Ầ': 'A',
  654. 'ậ': 'a',
  655. 'Ậ': 'A',
  656. 'ẫ': 'a',
  657. 'Ẫ': 'A',
  658. // 'ă': 'a', // duplicate
  659. // 'Ă': 'A', // duplicate
  660. 'ắ': 'a',
  661. 'Ắ': 'A',
  662. 'ằ': 'a',
  663. 'Ằ': 'A',
  664. 'ặ': 'a',
  665. 'Ặ': 'A',
  666. 'ẵ': 'a',
  667. 'Ẵ': 'A',
  668. "⓪": "0",
  669. "①": "1",
  670. "②": "2",
  671. "③": "3",
  672. "④": "4",
  673. "⑤": "5",
  674. "⑥": "6",
  675. "⑦": "7",
  676. "⑧": "8",
  677. "⑨": "9",
  678. "⑩": "10",
  679. "⑪": "11",
  680. "⑫": "12",
  681. "⑬": "13",
  682. "⑭": "14",
  683. "⑮": "15",
  684. "⑯": "16",
  685. "⑰": "17",
  686. "⑱": "18",
  687. "⑲": "18",
  688. "⑳": "18",
  689. "⓵": "1",
  690. "⓶": "2",
  691. "⓷": "3",
  692. "⓸": "4",
  693. "⓹": "5",
  694. "⓺": "6",
  695. "⓻": "7",
  696. "⓼": "8",
  697. "⓽": "9",
  698. "⓾": "10",
  699. "⓿": "0",
  700. "⓫": "11",
  701. "⓬": "12",
  702. "⓭": "13",
  703. "⓮": "14",
  704. "⓯": "15",
  705. "⓰": "16",
  706. "⓱": "17",
  707. "⓲": "18",
  708. "⓳": "19",
  709. "⓴": "20",
  710. "Ⓐ": "A",
  711. "Ⓑ": "B",
  712. "Ⓒ": "C",
  713. "Ⓓ": "D",
  714. "Ⓔ": "E",
  715. "Ⓕ": "F",
  716. "Ⓖ": "G",
  717. "Ⓗ": "H",
  718. "Ⓘ": "I",
  719. "Ⓙ": "J",
  720. "Ⓚ": "K",
  721. "Ⓛ": "L",
  722. "Ⓜ": "M",
  723. "Ⓝ": "N",
  724. "Ⓞ": "O",
  725. "Ⓟ": "P",
  726. "Ⓠ": "Q",
  727. "Ⓡ": "R",
  728. "Ⓢ": "S",
  729. "Ⓣ": "T",
  730. "Ⓤ": "U",
  731. "Ⓥ": "V",
  732. "Ⓦ": "W",
  733. "Ⓧ": "X",
  734. "Ⓨ": "Y",
  735. "Ⓩ": "Z",
  736. "ⓐ": "a",
  737. "ⓑ": "b",
  738. "ⓒ": "c",
  739. "ⓓ": "d",
  740. "ⓔ": "e",
  741. "ⓕ": "f",
  742. "ⓖ": "g",
  743. "ⓗ": "h",
  744. "ⓘ": "i",
  745. "ⓙ": "j",
  746. "ⓚ": "k",
  747. "ⓛ": "l",
  748. "ⓜ": "m",
  749. "ⓝ": "n",
  750. "ⓞ": "o",
  751. "ⓟ": "p",
  752. "ⓠ": "q",
  753. "ⓡ": "r",
  754. "ⓢ": "s",
  755. "ⓣ": "t",
  756. "ⓤ": "u",
  757. "ⓦ": "v",
  758. "ⓥ": "w",
  759. "ⓧ": "x",
  760. "ⓨ": "y",
  761. "ⓩ": "z",
  762. // symbols
  763. '“': '"',
  764. '”': '"',
  765. '‘': "'",
  766. '’': "'",
  767. '∂': 'd',
  768. 'ƒ': 'f',
  769. '™': '(TM)',
  770. '©': '(C)',
  771. 'œ': 'oe',
  772. 'Œ': 'OE',
  773. '®': '(R)',
  774. '†': '+',
  775. '℠': '(SM)',
  776. '…': '...',
  777. '˚': 'o',
  778. 'º': 'o',
  779. 'ª': 'a',
  780. '•': '*',
  781. '၊': ',',
  782. '။': '.',
  783. // currency
  784. '$': 'USD',
  785. '€': 'EUR',
  786. '₢': 'BRN',
  787. '₣': 'FRF',
  788. '£': 'GBP',
  789. '₤': 'ITL',
  790. '₦': 'NGN',
  791. '₧': 'ESP',
  792. '₩': 'KRW',
  793. '₪': 'ILS',
  794. '₫': 'VND',
  795. '₭': 'LAK',
  796. '₮': 'MNT',
  797. '₯': 'GRD',
  798. '₱': 'ARS',
  799. '₲': 'PYG',
  800. '₳': 'ARA',
  801. '₴': 'UAH',
  802. '₵': 'GHS',
  803. '¢': 'cent',
  804. '¥': 'CNY',
  805. '元': 'CNY',
  806. '円': 'YEN',
  807. '﷼': 'IRR',
  808. '₠': 'EWE',
  809. '฿': 'THB',
  810. '₨': 'INR',
  811. '₹': 'INR',
  812. '₰': 'PF',
  813. '₺': 'TRY',
  814. '؋': 'AFN',
  815. '₼': 'AZN',
  816. 'лв': 'BGN',
  817. '៛': 'KHR',
  818. '₡': 'CRC',
  819. '₸': 'KZT',
  820. 'ден': 'MKD',
  821. 'zł': 'PLN',
  822. '₽': 'RUB',
  823. '₾': 'GEL'
  824. };
  825. /**
  826. * special look ahead character array
  827. * These characters form with consonants to become 'single'/consonant combo
  828. * @type [Array]
  829. */
  830. var lookAheadCharArray = [
  831. // burmese
  832. '်',
  833. // Dhivehi
  834. 'ް'
  835. ];
  836. /**
  837. * diatricMap for languages where transliteration changes entirely as more diatrics are added
  838. * @type {Object}
  839. */
  840. var diatricMap = {
  841. // Burmese
  842. // dependent vowels
  843. 'ာ': 'a',
  844. 'ါ': 'a',
  845. 'ေ': 'e',
  846. 'ဲ': 'e',
  847. 'ိ': 'i',
  848. 'ီ': 'i',
  849. 'ို': 'o',
  850. 'ု': 'u',
  851. 'ူ': 'u',
  852. 'ေါင်': 'aung',
  853. 'ော': 'aw',
  854. 'ော်': 'aw',
  855. 'ေါ': 'aw',
  856. 'ေါ်': 'aw',
  857. '်': '်', // this is special case but the character will be converted to latin in the code
  858. 'က်': 'et',
  859. 'ိုက်': 'aik',
  860. 'ောက်': 'auk',
  861. 'င်': 'in',
  862. 'ိုင်': 'aing',
  863. 'ောင်': 'aung',
  864. 'စ်': 'it',
  865. 'ည်': 'i',
  866. 'တ်': 'at',
  867. 'ိတ်': 'eik',
  868. 'ုတ်': 'ok',
  869. 'ွတ်': 'ut',
  870. 'ေတ်': 'it',
  871. 'ဒ်': 'd',
  872. 'ိုဒ်': 'ok',
  873. 'ုဒ်': 'ait',
  874. 'န်': 'an',
  875. 'ာန်': 'an',
  876. 'ိန်': 'ein',
  877. 'ုန်': 'on',
  878. 'ွန်': 'un',
  879. 'ပ်': 'at',
  880. 'ိပ်': 'eik',
  881. 'ုပ်': 'ok',
  882. 'ွပ်': 'ut',
  883. 'န်ုပ်': 'nub',
  884. 'မ်': 'an',
  885. 'ိမ်': 'ein',
  886. 'ုမ်': 'on',
  887. 'ွမ်': 'un',
  888. 'ယ်': 'e',
  889. 'ိုလ်': 'ol',
  890. 'ဉ်': 'in',
  891. 'ံ': 'an',
  892. 'ိံ': 'ein',
  893. 'ုံ': 'on',
  894. // Dhivehi
  895. 'ައް': 'ah',
  896. 'ަށް': 'ah'
  897. };
  898. /**
  899. * langCharMap language specific characters translations
  900. * @type {Object}
  901. */
  902. var langCharMap = {
  903. 'en': {}, // default language
  904. 'az': { // Azerbaijani
  905. 'ç': 'c',
  906. 'ə': 'e',
  907. 'ğ': 'g',
  908. 'ı': 'i',
  909. 'ö': 'o',
  910. 'ş': 's',
  911. 'ü': 'u',
  912. 'Ç': 'C',
  913. 'Ə': 'E',
  914. 'Ğ': 'G',
  915. 'İ': 'I',
  916. 'Ö': 'O',
  917. 'Ş': 'S',
  918. 'Ü': 'U'
  919. },
  920. 'cs': { // Czech
  921. 'č': 'c',
  922. 'ď': 'd',
  923. 'ě': 'e',
  924. 'ň': 'n',
  925. 'ř': 'r',
  926. 'š': 's',
  927. 'ť': 't',
  928. 'ů': 'u',
  929. 'ž': 'z',
  930. 'Č': 'C',
  931. 'Ď': 'D',
  932. 'Ě': 'E',
  933. 'Ň': 'N',
  934. 'Ř': 'R',
  935. 'Š': 'S',
  936. 'Ť': 'T',
  937. 'Ů': 'U',
  938. 'Ž': 'Z'
  939. },
  940. 'fi': { // Finnish
  941. // 'å': 'a', duplicate see charMap/latin
  942. // 'Å': 'A', duplicate see charMap/latin
  943. 'ä': 'a', // ok
  944. 'Ä': 'A', // ok
  945. 'ö': 'o', // ok
  946. 'Ö': 'O' // ok
  947. },
  948. 'hu': { // Hungarian
  949. 'ä': 'a', // ok
  950. 'Ä': 'A', // ok
  951. // 'á': 'a', duplicate see charMap/latin
  952. // 'Á': 'A', duplicate see charMap/latin
  953. 'ö': 'o', // ok
  954. 'Ö': 'O', // ok
  955. // 'ő': 'o', duplicate see charMap/latin
  956. // 'Ő': 'O', duplicate see charMap/latin
  957. 'ü': 'u',
  958. 'Ü': 'U',
  959. 'ű': 'u',
  960. 'Ű': 'U'
  961. },
  962. 'lt': { // Lithuanian
  963. 'ą': 'a',
  964. 'č': 'c',
  965. 'ę': 'e',
  966. 'ė': 'e',
  967. 'į': 'i',
  968. 'š': 's',
  969. 'ų': 'u',
  970. 'ū': 'u',
  971. 'ž': 'z',
  972. 'Ą': 'A',
  973. 'Č': 'C',
  974. 'Ę': 'E',
  975. 'Ė': 'E',
  976. 'Į': 'I',
  977. 'Š': 'S',
  978. 'Ų': 'U',
  979. 'Ū': 'U'
  980. },
  981. 'lv': { // Latvian
  982. 'ā': 'a',
  983. 'č': 'c',
  984. 'ē': 'e',
  985. 'ģ': 'g',
  986. 'ī': 'i',
  987. 'ķ': 'k',
  988. 'ļ': 'l',
  989. 'ņ': 'n',
  990. 'š': 's',
  991. 'ū': 'u',
  992. 'ž': 'z',
  993. 'Ā': 'A',
  994. 'Č': 'C',
  995. 'Ē': 'E',
  996. 'Ģ': 'G',
  997. 'Ī': 'i',
  998. 'Ķ': 'k',
  999. 'Ļ': 'L',
  1000. 'Ņ': 'N',
  1001. 'Š': 'S',
  1002. 'Ū': 'u',
  1003. 'Ž': 'Z'
  1004. },
  1005. 'pl': { // Polish
  1006. 'ą': 'a',
  1007. 'ć': 'c',
  1008. 'ę': 'e',
  1009. 'ł': 'l',
  1010. 'ń': 'n',
  1011. 'ó': 'o',
  1012. 'ś': 's',
  1013. 'ź': 'z',
  1014. 'ż': 'z',
  1015. 'Ą': 'A',
  1016. 'Ć': 'C',
  1017. 'Ę': 'e',
  1018. 'Ł': 'L',
  1019. 'Ń': 'N',
  1020. 'Ó': 'O',
  1021. 'Ś': 'S',
  1022. 'Ź': 'Z',
  1023. 'Ż': 'Z'
  1024. },
  1025. 'sv': { // Swedish
  1026. // 'å': 'a', duplicate see charMap/latin
  1027. // 'Å': 'A', duplicate see charMap/latin
  1028. 'ä': 'a', // ok
  1029. 'Ä': 'A', // ok
  1030. 'ö': 'o', // ok
  1031. 'Ö': 'O' // ok
  1032. },
  1033. 'sk': { // Slovak
  1034. 'ä': 'a',
  1035. 'Ä': 'A'
  1036. },
  1037. 'sr': { // Serbian
  1038. 'љ': 'lj',
  1039. 'њ': 'nj',
  1040. 'Љ': 'Lj',
  1041. 'Њ': 'Nj',
  1042. 'đ': 'dj',
  1043. 'Đ': 'Dj'
  1044. },
  1045. 'tr': { // Turkish
  1046. 'Ü': 'U',
  1047. 'Ö': 'O',
  1048. 'ü': 'u',
  1049. 'ö': 'o'
  1050. }
  1051. };
  1052. /**
  1053. * symbolMap language specific symbol translations
  1054. * translations must be transliterated already
  1055. * @type {Object}
  1056. */
  1057. var symbolMap = {
  1058. 'ar': {
  1059. '∆': 'delta',
  1060. '∞': 'la-nihaya',
  1061. '♥': 'hob',
  1062. '&': 'wa',
  1063. '|': 'aw',
  1064. '<': 'aqal-men',
  1065. '>': 'akbar-men',
  1066. '∑': 'majmou',
  1067. '¤': 'omla'
  1068. },
  1069. 'az': {},
  1070. 'ca': {
  1071. '∆': 'delta',
  1072. '∞': 'infinit',
  1073. '♥': 'amor',
  1074. '&': 'i',
  1075. '|': 'o',
  1076. '<': 'menys que',
  1077. '>': 'mes que',
  1078. '∑': 'suma dels',
  1079. '¤': 'moneda'
  1080. },
  1081. 'cs': {
  1082. '∆': 'delta',
  1083. '∞': 'nekonecno',
  1084. '♥': 'laska',
  1085. '&': 'a',
  1086. '|': 'nebo',
  1087. '<': 'mensi nez',
  1088. '>': 'vetsi nez',
  1089. '∑': 'soucet',
  1090. '¤': 'mena'
  1091. },
  1092. 'de': {
  1093. '∆': 'delta',
  1094. '∞': 'unendlich',
  1095. '♥': 'Liebe',
  1096. '&': 'und',
  1097. '|': 'oder',
  1098. '<': 'kleiner als',
  1099. '>': 'groesser als',
  1100. '∑': 'Summe von',
  1101. '¤': 'Waehrung'
  1102. },
  1103. 'dv': {
  1104. '∆': 'delta',
  1105. '∞': 'kolunulaa',
  1106. '♥': 'loabi',
  1107. '&': 'aai',
  1108. '|': 'noonee',
  1109. '<': 'ah vure kuda',
  1110. '>': 'ah vure bodu',
  1111. '∑': 'jumula',
  1112. '¤': 'faisaa'
  1113. },
  1114. 'en': {
  1115. '∆': 'delta',
  1116. '∞': 'infinity',
  1117. '♥': 'love',
  1118. '&': 'and',
  1119. '|': 'or',
  1120. '<': 'less than',
  1121. '>': 'greater than',
  1122. '∑': 'sum',
  1123. '¤': 'currency'
  1124. },
  1125. 'es': {
  1126. '∆': 'delta',
  1127. '∞': 'infinito',
  1128. '♥': 'amor',
  1129. '&': 'y',
  1130. '|': 'u',
  1131. '<': 'menos que',
  1132. '>': 'mas que',
  1133. '∑': 'suma de los',
  1134. '¤': 'moneda'
  1135. },
  1136. 'fa': {
  1137. '∆': 'delta',
  1138. '∞': 'bi-nahayat',
  1139. '♥': 'eshgh',
  1140. '&': 'va',
  1141. '|': 'ya',
  1142. '<': 'kamtar-az',
  1143. '>': 'bishtar-az',
  1144. '∑': 'majmooe',
  1145. '¤': 'vahed'
  1146. },
  1147. 'fi': {
  1148. '∆': 'delta',
  1149. '∞': 'aarettomyys',
  1150. '♥': 'rakkaus',
  1151. '&': 'ja',
  1152. '|': 'tai',
  1153. '<': 'pienempi kuin',
  1154. '>': 'suurempi kuin',
  1155. '∑': 'summa',
  1156. '¤': 'valuutta'
  1157. },
  1158. 'fr': {
  1159. '∆': 'delta',
  1160. '∞': 'infiniment',
  1161. '♥': 'Amour',
  1162. '&': 'et',
  1163. '|': 'ou',
  1164. '<': 'moins que',
  1165. '>': 'superieure a',
  1166. '∑': 'somme des',
  1167. '¤': 'monnaie'
  1168. },
  1169. 'ge': {
  1170. '∆': 'delta',
  1171. '∞': 'usasruloba',
  1172. '♥': 'siqvaruli',
  1173. '&': 'da',
  1174. '|': 'an',
  1175. '<': 'naklebi',
  1176. '>': 'meti',
  1177. '∑': 'jami',
  1178. '¤': 'valuta'
  1179. },
  1180. 'gr': {},
  1181. 'hu': {
  1182. '∆': 'delta',
  1183. '∞': 'vegtelen',
  1184. '♥': 'szerelem',
  1185. '&': 'es',
  1186. '|': 'vagy',
  1187. '<': 'kisebb mint',
  1188. '>': 'nagyobb mint',
  1189. '∑': 'szumma',
  1190. '¤': 'penznem'
  1191. },
  1192. 'it': {
  1193. '∆': 'delta',
  1194. '∞': 'infinito',
  1195. '♥': 'amore',
  1196. '&': 'e',
  1197. '|': 'o',
  1198. '<': 'minore di',
  1199. '>': 'maggiore di',
  1200. '∑': 'somma',
  1201. '¤': 'moneta'
  1202. },
  1203. 'lt': {
  1204. '∆': 'delta',
  1205. '∞': 'begalybe',
  1206. '♥': 'meile',
  1207. '&': 'ir',
  1208. '|': 'ar',
  1209. '<': 'maziau nei',
  1210. '>': 'daugiau nei',
  1211. '∑': 'suma',
  1212. '¤': 'valiuta'
  1213. },
  1214. 'lv': {
  1215. '∆': 'delta',
  1216. '∞': 'bezgaliba',
  1217. '♥': 'milestiba',
  1218. '&': 'un',
  1219. '|': 'vai',
  1220. '<': 'mazak neka',
  1221. '>': 'lielaks neka',
  1222. '∑': 'summa',
  1223. '¤': 'valuta'
  1224. },
  1225. 'my': {
  1226. '∆': 'kwahkhyaet',
  1227. '∞': 'asaonasme',
  1228. '♥': 'akhyait',
  1229. '&': 'nhin',
  1230. '|': 'tho',
  1231. '<': 'ngethaw',
  1232. '>': 'kyithaw',
  1233. '∑': 'paungld',
  1234. '¤': 'ngwekye'
  1235. },
  1236. 'mk': {},
  1237. 'nl': {
  1238. '∆': 'delta',
  1239. '∞': 'oneindig',
  1240. '♥': 'liefde',
  1241. '&': 'en',
  1242. '|': 'of',
  1243. '<': 'kleiner dan',
  1244. '>': 'groter dan',
  1245. '∑': 'som',
  1246. '¤': 'valuta'
  1247. },
  1248. 'pl': {
  1249. '∆': 'delta',
  1250. '∞': 'nieskonczonosc',
  1251. '♥': 'milosc',
  1252. '&': 'i',
  1253. '|': 'lub',
  1254. '<': 'mniejsze niz',
  1255. '>': 'wieksze niz',
  1256. '∑': 'suma',
  1257. '¤': 'waluta'
  1258. },
  1259. 'pt': {
  1260. '∆': 'delta',
  1261. '∞': 'infinito',
  1262. '♥': 'amor',
  1263. '&': 'e',
  1264. '|': 'ou',
  1265. '<': 'menor que',
  1266. '>': 'maior que',
  1267. '∑': 'soma',
  1268. '¤': 'moeda'
  1269. },
  1270. 'ro': {
  1271. '∆': 'delta',
  1272. '∞': 'infinit',
  1273. '♥': 'dragoste',
  1274. '&': 'si',
  1275. '|': 'sau',
  1276. '<': 'mai mic ca',
  1277. '>': 'mai mare ca',
  1278. '∑': 'suma',
  1279. '¤': 'valuta'
  1280. },
  1281. 'ru': {
  1282. '∆': 'delta',
  1283. '∞': 'beskonechno',
  1284. '♥': 'lubov',
  1285. '&': 'i',
  1286. '|': 'ili',
  1287. '<': 'menshe',
  1288. '>': 'bolshe',
  1289. '∑': 'summa',
  1290. '¤': 'valjuta'
  1291. },
  1292. 'sk': {
  1293. '∆': 'delta',
  1294. '∞': 'nekonecno',
  1295. '♥': 'laska',
  1296. '&': 'a',
  1297. '|': 'alebo',
  1298. '<': 'menej ako',
  1299. '>': 'viac ako',
  1300. '∑': 'sucet',
  1301. '¤': 'mena'
  1302. },
  1303. 'sr': {},
  1304. 'tr': {
  1305. '∆': 'delta',
  1306. '∞': 'sonsuzluk',
  1307. '♥': 'ask',
  1308. '&': 've',
  1309. '|': 'veya',
  1310. '<': 'kucuktur',
  1311. '>': 'buyuktur',
  1312. '∑': 'toplam',
  1313. '¤': 'para birimi'
  1314. },
  1315. 'uk': {
  1316. '∆': 'delta',
  1317. '∞': 'bezkinechnist',
  1318. '♥': 'lubov',
  1319. '&': 'i',
  1320. '|': 'abo',
  1321. '<': 'menshe',
  1322. '>': 'bilshe',
  1323. '∑': 'suma',
  1324. '¤': 'valjuta'
  1325. },
  1326. 'vn': {
  1327. '∆': 'delta',
  1328. '∞': 'vo cuc',
  1329. '♥': 'yeu',
  1330. '&': 'va',
  1331. '|': 'hoac',
  1332. '<': 'nho hon',
  1333. '>': 'lon hon',
  1334. '∑': 'tong',
  1335. '¤': 'tien te'
  1336. }
  1337. };
  1338. var uricChars = [';', '?', ':', '@', '&', '=', '+', '$', ',', '/'].join('');
  1339. var uricNoSlashChars = [';', '?', ':', '@', '&', '=', '+', '$', ','].join('');
  1340. var markChars = ['.', '!', '~', '*', "'", '(', ')'].join('');
  1341. /**
  1342. * getSlug
  1343. * @param {string} input input string
  1344. * @param {object|string} opts config object or separator string/char
  1345. * @api public
  1346. * @return {string} sluggified string
  1347. */
  1348. var getSlug = function getSlug(input, opts) {
  1349. var separator = '-';
  1350. var result = '';
  1351. var diatricString = '';
  1352. var convertSymbols = true;
  1353. var customReplacements = {};
  1354. var maintainCase;
  1355. var titleCase;
  1356. var truncate;
  1357. var uricFlag;
  1358. var uricNoSlashFlag;
  1359. var markFlag;
  1360. var symbol;
  1361. var langChar;
  1362. var lucky;
  1363. var i;
  1364. var ch;
  1365. var l;
  1366. var lastCharWasSymbol;
  1367. var lastCharWasDiatric;
  1368. var allowedChars = '';
  1369. if (typeof input !== 'string') {
  1370. return '';
  1371. }
  1372. if (typeof opts === 'string') {
  1373. separator = opts;
  1374. }
  1375. symbol = symbolMap.en;
  1376. langChar = langCharMap.en;
  1377. if (typeof opts === 'object') {
  1378. maintainCase = opts.maintainCase || false;
  1379. customReplacements = (opts.custom && typeof opts.custom === 'object') ? opts.custom : customReplacements;
  1380. truncate = (+opts.truncate > 1 && opts.truncate) || false;
  1381. uricFlag = opts.uric || false;
  1382. uricNoSlashFlag = opts.uricNoSlash || false;
  1383. markFlag = opts.mark || false;
  1384. convertSymbols = (opts.symbols === false || opts.lang === false) ? false : true;
  1385. separator = opts.separator || separator;
  1386. if (uricFlag) {
  1387. allowedChars += uricChars;
  1388. }
  1389. if (uricNoSlashFlag) {
  1390. allowedChars += uricNoSlashChars;
  1391. }
  1392. if (markFlag) {
  1393. allowedChars += markChars;
  1394. }
  1395. symbol = (opts.lang && symbolMap[opts.lang] && convertSymbols) ?
  1396. symbolMap[opts.lang] : (convertSymbols ? symbolMap.en : {});
  1397. langChar = (opts.lang && langCharMap[opts.lang]) ?
  1398. langCharMap[opts.lang] :
  1399. opts.lang === false || opts.lang === true ? {} : langCharMap.en;
  1400. // if titleCase config is an Array, rewrite to object format
  1401. if (opts.titleCase && typeof opts.titleCase.length === 'number' && Array.prototype.toString.call(opts.titleCase)) {
  1402. opts.titleCase.forEach(function (v) {
  1403. customReplacements[v + ''] = v + '';
  1404. });
  1405. titleCase = true;
  1406. } else {
  1407. titleCase = !!opts.titleCase;
  1408. }
  1409. // if custom config is an Array, rewrite to object format
  1410. if (opts.custom && typeof opts.custom.length === 'number' && Array.prototype.toString.call(opts.custom)) {
  1411. opts.custom.forEach(function (v) {
  1412. customReplacements[v + ''] = v + '';
  1413. });
  1414. }
  1415. // custom replacements
  1416. Object.keys(customReplacements).forEach(function (v) {
  1417. var r;
  1418. if (v.length > 1) {
  1419. r = new RegExp('\\b' + escapeChars(v) + '\\b', 'gi');
  1420. } else {
  1421. r = new RegExp(escapeChars(v), 'gi');
  1422. }
  1423. input = input.replace(r, customReplacements[v]);
  1424. });
  1425. // add all custom replacement to allowed charlist
  1426. for (ch in customReplacements) {
  1427. allowedChars += ch;
  1428. }
  1429. }
  1430. allowedChars += separator;
  1431. // escape all necessary chars
  1432. allowedChars = escapeChars(allowedChars);
  1433. // trim whitespaces
  1434. input = input.replace(/(^\s+|\s+$)/g, '');
  1435. lastCharWasSymbol = false;
  1436. lastCharWasDiatric = false;
  1437. for (i = 0, l = input.length; i < l; i++) {
  1438. ch = input[i];
  1439. if (isReplacedCustomChar(ch, customReplacements)) {
  1440. // don't convert a already converted char
  1441. lastCharWasSymbol = false;
  1442. } else if (langChar[ch]) {
  1443. // process language specific diactrics chars conversion
  1444. ch = lastCharWasSymbol && langChar[ch].match(/[A-Za-z0-9]/) ? ' ' + langChar[ch] : langChar[ch];
  1445. lastCharWasSymbol = false;
  1446. } else if (ch in charMap) {
  1447. // the transliteration changes entirely when some special characters are added
  1448. if (i + 1 < l && lookAheadCharArray.indexOf(input[i + 1]) >= 0) {
  1449. diatricString += ch;
  1450. ch = '';
  1451. } else if (lastCharWasDiatric === true) {
  1452. ch = diatricMap[diatricString] + charMap[ch];
  1453. diatricString = '';
  1454. } else {
  1455. // process diactrics chars
  1456. ch = lastCharWasSymbol && charMap[ch].match(/[A-Za-z0-9]/) ? ' ' + charMap[ch] : charMap[ch];
  1457. }
  1458. lastCharWasSymbol = false;
  1459. lastCharWasDiatric = false;
  1460. } else if (ch in diatricMap) {
  1461. diatricString += ch;
  1462. ch = '';
  1463. // end of string, put the whole meaningful word
  1464. if (i === l - 1) {
  1465. ch = diatricMap[diatricString];
  1466. }
  1467. lastCharWasDiatric = true;
  1468. } else if (
  1469. // process symbol chars
  1470. symbol[ch] && !(uricFlag && uricChars
  1471. .indexOf(ch) !== -1) && !(uricNoSlashFlag && uricNoSlashChars
  1472. // .indexOf(ch) !== -1) && !(markFlag && markChars
  1473. .indexOf(ch) !== -1)) {
  1474. ch = lastCharWasSymbol || result.substr(-1).match(/[A-Za-z0-9]/) ? separator + symbol[ch] : symbol[ch];
  1475. ch += input[i + 1] !== void 0 && input[i + 1].match(/[A-Za-z0-9]/) ? separator : '';
  1476. lastCharWasSymbol = true;
  1477. } else {
  1478. if (lastCharWasDiatric === true) {
  1479. ch = diatricMap[diatricString] + ch;
  1480. diatricString = '';
  1481. lastCharWasDiatric = false;
  1482. } else if (lastCharWasSymbol && (/[A-Za-z0-9]/.test(ch) || result.substr(-1).match(/A-Za-z0-9]/))) {
  1483. // process latin chars
  1484. ch = ' ' + ch;
  1485. }
  1486. lastCharWasSymbol = false;
  1487. }
  1488. // add allowed chars
  1489. result += ch.replace(new RegExp('[^\\w\\s' + allowedChars + '_-]', 'g'), separator);
  1490. }
  1491. if (titleCase) {
  1492. result = result.replace(/(\w)(\S*)/g, function (_, i, r) {
  1493. var j = i.toUpperCase() + (r !== null ? r : '');
  1494. return (Object.keys(customReplacements).indexOf(j.toLowerCase()) < 0) ? j : j.toLowerCase();
  1495. });
  1496. }
  1497. // eliminate duplicate separators
  1498. // add separator
  1499. // trim separators from start and end
  1500. result = result.replace(/\s+/g, separator)
  1501. .replace(new RegExp('\\' + separator + '+', 'g'), separator)
  1502. .replace(new RegExp('(^\\' + separator + '+|\\' + separator + '+$)', 'g'), '');
  1503. if (truncate && result.length > truncate) {
  1504. lucky = result.charAt(truncate) === separator;
  1505. result = result.slice(0, truncate);
  1506. if (!lucky) {
  1507. result = result.slice(0, result.lastIndexOf(separator));
  1508. }
  1509. }
  1510. if (!maintainCase && !titleCase) {
  1511. result = result.toLowerCase();
  1512. }
  1513. return result;
  1514. };
  1515. /**
  1516. * createSlug curried(opts)(input)
  1517. * @param {object|string} opts config object or input string
  1518. * @return {Function} function getSlugWithConfig()
  1519. **/
  1520. var createSlug = function createSlug(opts) {
  1521. /**
  1522. * getSlugWithConfig
  1523. * @param {string} input string
  1524. * @return {string} slug string
  1525. */
  1526. return function getSlugWithConfig(input) {
  1527. return getSlug(input, opts);
  1528. };
  1529. };
  1530. /**
  1531. * escape Chars
  1532. * @param {string} input string
  1533. */
  1534. var escapeChars = function escapeChars(input) {
  1535. return input.replace(/[-\\^$*+?.()|[\]{}\/]/g, '\\$&');
  1536. };
  1537. /**
  1538. * check if the char is an already converted char from custom list
  1539. * @param {char} ch character to check
  1540. * @param {object} customReplacements custom translation map
  1541. */
  1542. var isReplacedCustomChar = function (ch, customReplacements) {
  1543. for (var c in customReplacements) {
  1544. if (customReplacements[c] === ch) {
  1545. return true;
  1546. }
  1547. }
  1548. };
  1549. if (typeof module !== 'undefined' && module.exports) {
  1550. // export functions for use in Node
  1551. module.exports = getSlug;
  1552. module.exports.createSlug = createSlug;
  1553. } else if (typeof define !== 'undefined' && define.amd) {
  1554. // export function for use in AMD
  1555. define([], function () {
  1556. return getSlug;
  1557. });
  1558. } else {
  1559. // don't overwrite global if exists
  1560. try {
  1561. if (root.getSlug || root.createSlug) {
  1562. throw 'speakingurl: globals exists /(getSlug|createSlug)/';
  1563. } else {
  1564. root.getSlug = getSlug;
  1565. root.createSlug = createSlug;
  1566. }
  1567. } catch (e) {}
  1568. }
  1569. })(this);