diff --git a/packages/kg-utils/lib/slugify.js b/packages/kg-utils/lib/slugify.js index 0e36e5cc0e..795293aaf5 100644 --- a/packages/kg-utils/lib/slugify.js +++ b/packages/kg-utils/lib/slugify.js @@ -1,6 +1,22 @@ const semver = require('semver'); -module.exports = function (inputString = '', {ghostVersion = '4.0', type = 'mobiledoc'} = {}) { +/** + * Helper function to create a slug from a string + * @param {string} inputString - The string to slugify + * @param {RegExp} symbolRegex - Regex for symbols to remove + * @returns {string} + */ +function createSlug(inputString, symbolRegex) { + return encodeURIComponent( + inputString.trim() + .toLowerCase() + .replace(symbolRegex, '') + .replace(/\s+/g, '-') + .replace(/^-|-{2,}|-$/g, '') + ); +} + +module.exports = function (inputString = '', {ghostVersion = '6.0', type = 'mobiledoc'} = {}) { const version = semver.coerce(ghostVersion); if (typeof inputString !== 'string' || (inputString || '').trim() === '') { @@ -19,15 +35,15 @@ module.exports = function (inputString = '', {ghostVersion = '4.0', type = 'mobi .replace(/-{2,}/g, '-') .toLowerCase(); } + } + + // new slugs introduced in 4.0 + // allows all chars except symbols but will urlEncode everything + // produces %-encoded chars in src but browsers show real chars in status bar and url bar + if (semver.satisfies(version, '<6.x')) { + return createSlug(inputString, /[\][!"#$%&'()*+,./:;<=>?@\\^_{|}~]/g); } else { - // new slugs introduced in 4.0 - // allows all chars except symbols but will urlEncode everything - // produces %-encoded chars in src but browsers show real chars in status bar and url bar - return encodeURIComponent(inputString.trim() - .toLowerCase() - .replace(/[\][!"#$%&'()*+,./:;<=>?@\\^_{|}~]/g, '') - .replace(/\s+/g, '-') - .replace(/^-|-{2,}|-$/g, '') - ); + // For ghost versions 6.x and above, remove additional symbols + return createSlug(inputString, /[\][!"#$%&'()*+,./:;<=>?@\\^_{|}~‘’“”`¡¿–—•]/g); } }; diff --git a/packages/kg-utils/test/slugify.test.js b/packages/kg-utils/test/slugify.test.js index c5214d13a0..2096c81905 100644 --- a/packages/kg-utils/test/slugify.test.js +++ b/packages/kg-utils/test/slugify.test.js @@ -50,27 +50,34 @@ describe('slugify()', function () { }); }); - describe('4.x', function () { + describe('>=4.x <6.x', function () { it('replaces all white space with "-"', function () { - slugify('test one\t two') + slugify('test one\t two', {ghostVersion: '4.0'}) .should.equal('test-one-two'); }); it('strips symbols', function () { - slugify('test! one? {two}') + slugify('test! one? {two}', {ghostVersion: '4.0'}) .should.equal('test-one-two'); }); it('%-encodes chars', function () { - const slug = slugify('ñéïñ'); + const slug = slugify('ñéïñ', {ghostVersion: '4.0'}); slug.should.equal('%C3%B1%C3%A9%C3%AF%C3%B1'); decodeURIComponent(slug).should.equal('ñéïñ'); }); it('removes leading/trailing "-" and collapses "-" groups', function () { - slugify(' \ttest one two! \t') + slugify(' \ttest one two! \t', {ghostVersion: '4.0'}) .should.equal('test-one-two'); }); }); + + describe('>=6.x', function () { + it('removes additional symbols', function () { + slugify('test “fancy” ‘quotes’ – — dashes ¡and! other¿ • stuff`') + .should.equal('test-fancy-quotes-dashes-and-other-stuff'); + }); + }); });