diff --git a/public/src/modules/slugify.js b/public/src/modules/slugify.js new file mode 100644 index 0000000000..09ac707152 --- /dev/null +++ b/public/src/modules/slugify.js @@ -0,0 +1,37 @@ +'use strict'; + +(function (factory) { + if (typeof module === 'object' && module.exports) { + module.exports = factory(require('xregexp')); + } else { + define('slugify', ['xregexp'], factory); + } +}(function (XRegExp) { + var invalidUnicodeChars = XRegExp('[^\\p{L}\\s\\d\\-_]', 'g'); + var invalidLatinChars = /[^\w\s\d\-_]/g; + var trimRegex = /^\s+|\s+$/g; + var collapseWhitespace = /\s+/g; + var collapseDash = /-+/g; + var trimTrailingDash = /-$/g; + var trimLeadingDash = /^-/g; + var isLatin = /^[\w\d\s.,\-@]+$/; + + // http://dense13.com/blog/2009/05/03/converting-string-to-slug-javascript/ + return function slugify(str, preserveCase) { + if (!str) { + return ''; + } + str = String(str).replace(trimRegex, ''); + if (isLatin.test(str)) { + str = str.replace(invalidLatinChars, '-'); + } else { + str = XRegExp.replace(str, invalidUnicodeChars, '-'); + } + str = !preserveCase ? str.toLocaleLowerCase() : str; + str = str.replace(collapseWhitespace, '-'); + str = str.replace(collapseDash, '-'); + str = str.replace(trimTrailingDash, ''); + str = str.replace(trimLeadingDash, ''); + return str; + }; +})); diff --git a/public/src/utils.js b/public/src/utils.js index 103eefe7fe..2b80762dab 100644 --- a/public/src/utils.js +++ b/public/src/utils.js @@ -330,6 +330,8 @@ return String(str).replace(new RegExp('<(\\/)?(' + (pattern || '[^\\s>]+') + ')(\\s+[^<>]*?)?\\s*(\\/)?>', 'gi'), ''); }, + + // TODO: remove XRegExp & all these in 1.16.0, they are moved to slugify module invalidUnicodeChars: XRegExp('[^\\p{L}\\s\\d\\-_]', 'g'), invalidLatinChars: /[^\w\s\d\-_]/g, trimRegex: /^\s+|\s+$/g, @@ -338,10 +340,15 @@ trimTrailingDash: /-$/g, trimLeadingDash: /^-/g, isLatin: /^[\w\d\s.,\-@]+$/, - languageKeyRegex: /\[\[[\w]+:.+\]\]/, // http://dense13.com/blog/2009/05/03/converting-string-to-slug-javascript/ slugify: function (str, preserveCase) { + if (typeof module === 'object' && module.exports) { + console.warn('[deprecated] utils.slugify deprecated. Use `require("slugify")` instead'); + } else { + console.warn('[deprecated] utils.slugify deprecated. Use `require(["slugify"], function (slugify) { ... })` instead'); + } + if (!str) { return ''; } @@ -397,6 +404,7 @@ return !isNaN(parseFloat(n)) && isFinite(n); }, + languageKeyRegex: /\[\[[\w]+:.+\]\]/, hasLanguageKey: function (input) { return utils.languageKeyRegex.test(input); }, diff --git a/src/meta/js.js b/src/meta/js.js index e972ababf8..915a8250e0 100644 --- a/src/meta/js.js +++ b/src/meta/js.js @@ -103,6 +103,7 @@ JS.scripts = { 'compare-versions.js': 'node_modules/compare-versions/index.js', 'timeago/locales': 'node_modules/timeago/locales', 'jquery-form.js': 'node_modules/jquery-form/dist/jquery.form.min.js', + 'xregexp.js': 'node_modules/xregexp/xregexp-all.js', }, }; diff --git a/src/slugify.js b/src/slugify.js new file mode 100644 index 0000000000..6ef70c1b87 --- /dev/null +++ b/src/slugify.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('../public/src/modules/slugify');