Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pluralize.js 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /* global define */
  2. (function (root, pluralize) {
  3. /* istanbul ignore else */
  4. if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
  5. // Node.
  6. module.exports = pluralize();
  7. } else if (typeof define === 'function' && define.amd) {
  8. // AMD, registers as an anonymous module.
  9. define(function () {
  10. return pluralize();
  11. });
  12. } else {
  13. // Browser global.
  14. root.pluralize = pluralize();
  15. }
  16. })(this, function () {
  17. // Rule storage - pluralize and singularize need to be run sequentially,
  18. // while other rules can be optimized using an object for instant lookups.
  19. var pluralRules = [];
  20. var singularRules = [];
  21. var uncountables = {};
  22. var irregularPlurals = {};
  23. var irregularSingles = {};
  24. /**
  25. * Sanitize a pluralization rule to a usable regular expression.
  26. *
  27. * @param {(RegExp|string)} rule
  28. * @return {RegExp}
  29. */
  30. function sanitizeRule (rule) {
  31. if (typeof rule === 'string') {
  32. return new RegExp('^' + rule + '$', 'i');
  33. }
  34. return rule;
  35. }
  36. /**
  37. * Pass in a word token to produce a function that can replicate the case on
  38. * another word.
  39. *
  40. * @param {string} word
  41. * @param {string} token
  42. * @return {Function}
  43. */
  44. function restoreCase (word, token) {
  45. // Tokens are an exact match.
  46. if (word === token) return token;
  47. // Upper cased words. E.g. "HELLO".
  48. if (word === word.toUpperCase()) return token.toUpperCase();
  49. // Title cased words. E.g. "Title".
  50. if (word[0] === word[0].toUpperCase()) {
  51. return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase();
  52. }
  53. // Lower cased words. E.g. "test".
  54. return token.toLowerCase();
  55. }
  56. /**
  57. * Interpolate a regexp string.
  58. *
  59. * @param {string} str
  60. * @param {Array} args
  61. * @return {string}
  62. */
  63. function interpolate (str, args) {
  64. return str.replace(/\$(\d{1,2})/g, function (match, index) {
  65. return args[index] || '';
  66. });
  67. }
  68. /**
  69. * Replace a word using a rule.
  70. *
  71. * @param {string} word
  72. * @param {Array} rule
  73. * @return {string}
  74. */
  75. function replace (word, rule) {
  76. return word.replace(rule[0], function (match, index) {
  77. var result = interpolate(rule[1], arguments);
  78. if (match === '') {
  79. return restoreCase(word[index - 1], result);
  80. }
  81. return restoreCase(match, result);
  82. });
  83. }
  84. /**
  85. * Sanitize a word by passing in the word and sanitization rules.
  86. *
  87. * @param {string} token
  88. * @param {string} word
  89. * @param {Array} rules
  90. * @return {string}
  91. */
  92. function sanitizeWord (token, word, rules) {
  93. // Empty string or doesn't need fixing.
  94. if (!token.length || uncountables.hasOwnProperty(token)) {
  95. return word;
  96. }
  97. var len = rules.length;
  98. // Iterate over the sanitization rules and use the first one to match.
  99. while (len--) {
  100. var rule = rules[len];
  101. if (rule[0].test(word)) return replace(word, rule);
  102. }
  103. return word;
  104. }
  105. /**
  106. * Replace a word with the updated word.
  107. *
  108. * @param {Object} replaceMap
  109. * @param {Object} keepMap
  110. * @param {Array} rules
  111. * @return {Function}
  112. */
  113. function replaceWord (replaceMap, keepMap, rules) {
  114. return function (word) {
  115. // Get the correct token and case restoration functions.
  116. var token = word.toLowerCase();
  117. // Check against the keep object map.
  118. if (keepMap.hasOwnProperty(token)) {
  119. return restoreCase(word, token);
  120. }
  121. // Check against the replacement map for a direct word replacement.
  122. if (replaceMap.hasOwnProperty(token)) {
  123. return restoreCase(word, replaceMap[token]);
  124. }
  125. // Run all the rules against the word.
  126. return sanitizeWord(token, word, rules);
  127. };
  128. }
  129. /**
  130. * Check if a word is part of the map.
  131. */
  132. function checkWord (replaceMap, keepMap, rules, bool) {
  133. return function (word) {
  134. var token = word.toLowerCase();
  135. if (keepMap.hasOwnProperty(token)) return true;
  136. if (replaceMap.hasOwnProperty(token)) return false;
  137. return sanitizeWord(token, token, rules) === token;
  138. };
  139. }
  140. /**
  141. * Pluralize or singularize a word based on the passed in count.
  142. *
  143. * @param {string} word
  144. * @param {number} count
  145. * @param {boolean} inclusive
  146. * @return {string}
  147. */
  148. function pluralize (word, count, inclusive) {
  149. var pluralized = count === 1
  150. ? pluralize.singular(word) : pluralize.plural(word);
  151. return (inclusive ? count + ' ' : '') + pluralized;
  152. }
  153. /**
  154. * Pluralize a word.
  155. *
  156. * @type {Function}
  157. */
  158. pluralize.plural = replaceWord(
  159. irregularSingles, irregularPlurals, pluralRules
  160. );
  161. /**
  162. * Check if a word is plural.
  163. *
  164. * @type {Function}
  165. */
  166. pluralize.isPlural = checkWord(
  167. irregularSingles, irregularPlurals, pluralRules
  168. );
  169. /**
  170. * Singularize a word.
  171. *
  172. * @type {Function}
  173. */
  174. pluralize.singular = replaceWord(
  175. irregularPlurals, irregularSingles, singularRules
  176. );
  177. /**
  178. * Check if a word is singular.
  179. *
  180. * @type {Function}
  181. */
  182. pluralize.isSingular = checkWord(
  183. irregularPlurals, irregularSingles, singularRules
  184. );
  185. /**
  186. * Add a pluralization rule to the collection.
  187. *
  188. * @param {(string|RegExp)} rule
  189. * @param {string} replacement
  190. */
  191. pluralize.addPluralRule = function (rule, replacement) {
  192. pluralRules.push([sanitizeRule(rule), replacement]);
  193. };
  194. /**
  195. * Add a singularization rule to the collection.
  196. *
  197. * @param {(string|RegExp)} rule
  198. * @param {string} replacement
  199. */
  200. pluralize.addSingularRule = function (rule, replacement) {
  201. singularRules.push([sanitizeRule(rule), replacement]);
  202. };
  203. /**
  204. * Add an uncountable word rule.
  205. *
  206. * @param {(string|RegExp)} word
  207. */
  208. pluralize.addUncountableRule = function (word) {
  209. if (typeof word === 'string') {
  210. uncountables[word.toLowerCase()] = true;
  211. return;
  212. }
  213. // Set singular and plural references for the word.
  214. pluralize.addPluralRule(word, '$0');
  215. pluralize.addSingularRule(word, '$0');
  216. };
  217. /**
  218. * Add an irregular word definition.
  219. *
  220. * @param {string} single
  221. * @param {string} plural
  222. */
  223. pluralize.addIrregularRule = function (single, plural) {
  224. plural = plural.toLowerCase();
  225. single = single.toLowerCase();
  226. irregularSingles[single] = plural;
  227. irregularPlurals[plural] = single;
  228. };
  229. /**
  230. * Irregular rules.
  231. */
  232. [
  233. // Pronouns.
  234. ['I', 'we'],
  235. ['me', 'us'],
  236. ['he', 'they'],
  237. ['she', 'they'],
  238. ['them', 'them'],
  239. ['myself', 'ourselves'],
  240. ['yourself', 'yourselves'],
  241. ['itself', 'themselves'],
  242. ['herself', 'themselves'],
  243. ['himself', 'themselves'],
  244. ['themself', 'themselves'],
  245. ['is', 'are'],
  246. ['was', 'were'],
  247. ['has', 'have'],
  248. ['this', 'these'],
  249. ['that', 'those'],
  250. // Words ending in with a consonant and `o`.
  251. ['echo', 'echoes'],
  252. ['dingo', 'dingoes'],
  253. ['volcano', 'volcanoes'],
  254. ['tornado', 'tornadoes'],
  255. ['torpedo', 'torpedoes'],
  256. // Ends with `us`.
  257. ['genus', 'genera'],
  258. ['viscus', 'viscera'],
  259. // Ends with `ma`.
  260. ['stigma', 'stigmata'],
  261. ['stoma', 'stomata'],
  262. ['dogma', 'dogmata'],
  263. ['lemma', 'lemmata'],
  264. ['schema', 'schemata'],
  265. ['anathema', 'anathemata'],
  266. // Other irregular rules.
  267. ['ox', 'oxen'],
  268. ['axe', 'axes'],
  269. ['die', 'dice'],
  270. ['yes', 'yeses'],
  271. ['foot', 'feet'],
  272. ['eave', 'eaves'],
  273. ['goose', 'geese'],
  274. ['tooth', 'teeth'],
  275. ['quiz', 'quizzes'],
  276. ['human', 'humans'],
  277. ['proof', 'proofs'],
  278. ['carve', 'carves'],
  279. ['valve', 'valves'],
  280. ['looey', 'looies'],
  281. ['thief', 'thieves'],
  282. ['groove', 'grooves'],
  283. ['pickaxe', 'pickaxes'],
  284. ['whiskey', 'whiskies']
  285. ].forEach(function (rule) {
  286. return pluralize.addIrregularRule(rule[0], rule[1]);
  287. });
  288. /**
  289. * Pluralization rules.
  290. */
  291. [
  292. [/s?$/i, 's'],
  293. [/[^\u0000-\u007F]$/i, '$0'],
  294. [/([^aeiou]ese)$/i, '$1'],
  295. [/(ax|test)is$/i, '$1es'],
  296. [/(alias|[^aou]us|tlas|gas|ris)$/i, '$1es'],
  297. [/(e[mn]u)s?$/i, '$1s'],
  298. [/([^l]ias|[aeiou]las|[emjzr]as|[iu]am)$/i, '$1'],
  299. [/(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1i'],
  300. [/(alumn|alg|vertebr)(?:a|ae)$/i, '$1ae'],
  301. [/(seraph|cherub)(?:im)?$/i, '$1im'],
  302. [/(her|at|gr)o$/i, '$1oes'],
  303. [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, '$1a'],
  304. [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, '$1a'],
  305. [/sis$/i, 'ses'],
  306. [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, '$1$2ves'],
  307. [/([^aeiouy]|qu)y$/i, '$1ies'],
  308. [/([^ch][ieo][ln])ey$/i, '$1ies'],
  309. [/(x|ch|ss|sh|zz)$/i, '$1es'],
  310. [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, '$1ices'],
  311. [/(m|l)(?:ice|ouse)$/i, '$1ice'],
  312. [/(pe)(?:rson|ople)$/i, '$1ople'],
  313. [/(child)(?:ren)?$/i, '$1ren'],
  314. [/eaux$/i, '$0'],
  315. [/m[ae]n$/i, 'men'],
  316. ['thou', 'you']
  317. ].forEach(function (rule) {
  318. return pluralize.addPluralRule(rule[0], rule[1]);
  319. });
  320. /**
  321. * Singularization rules.
  322. */
  323. [
  324. [/s$/i, ''],
  325. [/(ss)$/i, '$1'],
  326. [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, '$1fe'],
  327. [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'],
  328. [/ies$/i, 'y'],
  329. [/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i, '$1ie'],
  330. [/\b(mon|smil)ies$/i, '$1ey'],
  331. [/(m|l)ice$/i, '$1ouse'],
  332. [/(seraph|cherub)im$/i, '$1'],
  333. [/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|tlas|gas|(?:her|at|gr)o|ris)(?:es)?$/i, '$1'],
  334. [/(analy|ba|diagno|parenthe|progno|synop|the|empha|cri)(?:sis|ses)$/i, '$1sis'],
  335. [/(movie|twelve|abuse|e[mn]u)s$/i, '$1'],
  336. [/(test)(?:is|es)$/i, '$1is'],
  337. [/(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1us'],
  338. [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, '$1um'],
  339. [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, '$1on'],
  340. [/(alumn|alg|vertebr)ae$/i, '$1a'],
  341. [/(cod|mur|sil|vert|ind)ices$/i, '$1ex'],
  342. [/(matr|append)ices$/i, '$1ix'],
  343. [/(pe)(rson|ople)$/i, '$1rson'],
  344. [/(child)ren$/i, '$1'],
  345. [/(eau)x?$/i, '$1'],
  346. [/men$/i, 'man']
  347. ].forEach(function (rule) {
  348. return pluralize.addSingularRule(rule[0], rule[1]);
  349. });
  350. /**
  351. * Uncountable rules.
  352. */
  353. [
  354. // Singular words with no plurals.
  355. 'adulthood',
  356. 'advice',
  357. 'agenda',
  358. 'aid',
  359. 'alcohol',
  360. 'ammo',
  361. 'anime',
  362. 'athletics',
  363. 'audio',
  364. 'bison',
  365. 'blood',
  366. 'bream',
  367. 'buffalo',
  368. 'butter',
  369. 'carp',
  370. 'cash',
  371. 'chassis',
  372. 'chess',
  373. 'clothing',
  374. 'cod',
  375. 'commerce',
  376. 'cooperation',
  377. 'corps',
  378. 'debris',
  379. 'diabetes',
  380. 'digestion',
  381. 'elk',
  382. 'energy',
  383. 'equipment',
  384. 'excretion',
  385. 'expertise',
  386. 'flounder',
  387. 'fun',
  388. 'gallows',
  389. 'garbage',
  390. 'graffiti',
  391. 'headquarters',
  392. 'health',
  393. 'herpes',
  394. 'highjinks',
  395. 'homework',
  396. 'housework',
  397. 'information',
  398. 'jeans',
  399. 'justice',
  400. 'kudos',
  401. 'labour',
  402. 'literature',
  403. 'machinery',
  404. 'mackerel',
  405. 'mail',
  406. 'media',
  407. 'mews',
  408. 'moose',
  409. 'music',
  410. 'manga',
  411. 'news',
  412. 'pike',
  413. 'plankton',
  414. 'pliers',
  415. 'pollution',
  416. 'premises',
  417. 'rain',
  418. 'research',
  419. 'rice',
  420. 'salmon',
  421. 'scissors',
  422. 'series',
  423. 'sewage',
  424. 'shambles',
  425. 'shrimp',
  426. 'species',
  427. 'staff',
  428. 'swine',
  429. 'tennis',
  430. 'traffic',
  431. 'transporation',
  432. 'trout',
  433. 'tuna',
  434. 'wealth',
  435. 'welfare',
  436. 'whiting',
  437. 'wildebeest',
  438. 'wildlife',
  439. 'you',
  440. // Regexes.
  441. /[^aeiou]ese$/i, // "chinese", "japanese"
  442. /deer$/i, // "deer", "reindeer"
  443. /fish$/i, // "fish", "blowfish", "angelfish"
  444. /measles$/i,
  445. /o[iu]s$/i, // "carnivorous"
  446. /pox$/i, // "chickpox", "smallpox"
  447. /sheep$/i
  448. ].forEach(pluralize.addUncountableRule);
  449. return pluralize;
  450. });