From c0b5de6e81f40b4a5b4c10affe2d15c8b55e8688 Mon Sep 17 00:00:00 2001 From: cobbspur Date: Wed, 23 Sep 2015 11:54:56 +0100 Subject: [PATCH] Fix handling of slugs on import closes Issue #5812 - pass importing property through to utils - fix safeString method for imports --- core/server/models/base/index.js | 2 +- core/server/models/post.js | 2 +- core/server/utils/index.js | 23 ++++++++++------- core/test/unit/server_utils_spec.js | 39 ++++++++++++++++++++--------- 4 files changed, 43 insertions(+), 23 deletions(-) diff --git a/core/server/models/base/index.js b/core/server/models/base/index.js index 03ca55c517..2a3a38f3ff 100644 --- a/core/server/models/base/index.js +++ b/core/server/models/base/index.js @@ -423,7 +423,7 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({ }); }; - slug = utils.safeString(base); + slug = utils.safeString(base, options); // If it's a user, let's try to cut it down (unless this is a human request) if (baseName === 'user' && options && options.shortSlug && slugTryCount === 1 && slug !== 'ghost-owner') { diff --git a/core/server/models/post.js b/core/server/models/post.js index 7b5042ac51..c9718d4612 100644 --- a/core/server/models/post.js +++ b/core/server/models/post.js @@ -154,7 +154,7 @@ Post = ghostBookshelf.Model.extend({ if (this.hasChanged('slug') || !this.get('slug')) { // Pass the new slug through the generator to strip illegal characters, detect duplicates return ghostBookshelf.Model.generateSlug(Post, this.get('slug') || this.get('title'), - {status: 'all', transacting: options.transacting}) + {status: 'all', transacting: options.transacting, importing: options.importing}) .then(function then(slug) { self.set({slug: slug}); }); diff --git a/core/server/utils/index.js b/core/server/utils/index.js index a222d28395..8bb0d3ac29 100644 --- a/core/server/utils/index.js +++ b/core/server/utils/index.js @@ -1,4 +1,5 @@ var unidecode = require('unidecode'), + _ = require('lodash'), utils, getRandomInt; @@ -50,9 +51,10 @@ utils = { return buf.join(''); }, - safeString: function (string) { - // Handle the £ symbol seperately, since it needs to be removed before - // the unicode conversion. + safeString: function (string, options) { + options = options || {}; + + // Handle the £ symbol separately, since it needs to be removed before the unicode conversion. string = string.replace(/£/g, '-'); // Remove non ascii characters @@ -62,15 +64,18 @@ utils = { string = string.replace(/(\s|\.|@|:|\/|\?|#|\[|\]|!|\$|&|\(|\)|\*|\+|,|;|=|\\|%|<|>|\||\^|~|"|–|—)/g, '-') // Remove apostrophes .replace(/'/g, '') - // Convert 2 or more dashes into a single dash - .replace(/-+/g, '-') - // Remove any dashes at the beginning - .replace(/^-/, '') // Make the whole thing lowercase .toLowerCase(); - // Remove trailing dash if needed - string = string.charAt(string.length - 1) === '-' ? string.substr(0, string.length - 1) : string; + // We do not need to make the following changes when importing data + if (!_.has(options, 'importing') || !options.importing) { + // Convert 2 or more dashes into a single dash + string = string.replace(/-+/g, '-') + // Remove trailing dash + .replace(/-$/, '') + // Remove any dashes at the beginning + .replace(/^-/, ''); + } // Handle whitespace at the beginning or end. string = string.trim(); diff --git a/core/test/unit/server_utils_spec.js b/core/test/unit/server_utils_spec.js index c2e8ed9199..8c0c3a44dc 100644 --- a/core/test/unit/server_utils_spec.js +++ b/core/test/unit/server_utils_spec.js @@ -7,60 +7,75 @@ var should = require('should'), should.equal(true, true); describe('Safe String', function () { - var safeString = utils.safeString; + var safeString = utils.safeString, + options = {}; it('should remove beginning and ending whitespace', function () { - var result = safeString(' stringwithspace '); + var result = safeString(' stringwithspace ', options); result.should.equal('stringwithspace'); }); it('should remove non ascii characters', function () { - var result = safeString('howtowin✓'); + var result = safeString('howtowin✓', options); result.should.equal('howtowin'); }); it('should replace spaces with dashes', function () { - var result = safeString('how to win'); + var result = safeString('how to win', options); result.should.equal('how-to-win'); }); it('should replace most special characters with dashes', function () { - var result = safeString('a:b/c?d#e[f]g!h$i&j(k)l*m+n,o;p=q\\r%su|v^w~x£y"z@1.2'); + var result = safeString('a:b/c?d#e[f]g!h$i&j(k)l*m+n,o;p=q\\r%su|v^w~x£y"z@1.2', options); result.should.equal('a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z-1-2'); }); it('should remove special characters at the beginning of a string', function () { - var result = safeString('.Not special'); + var result = safeString('.Not special', options); result.should.equal('not-special'); }); it('should remove apostrophes ', function () { - var result = safeString('how we shouldn\'t be'); + var result = safeString('how we shouldn\'t be', options); result.should.equal('how-we-shouldnt-be'); }); it('should convert to lowercase', function () { - var result = safeString('This has Upper Case'); + var result = safeString('This has Upper Case', options); result.should.equal('this-has-upper-case'); }); it('should convert multiple dashes into a single dash', function () { - var result = safeString('This :) means everything'); + var result = safeString('This :) means everything', options); result.should.equal('this-means-everything'); }); it('should remove trailing dashes from the result', function () { - var result = safeString('This.'); + var result = safeString('This.', options); result.should.equal('this'); }); it('should handle pound signs', function () { - var result = safeString('WHOOPS! I spent all my £ again!'); + var result = safeString('WHOOPS! I spent all my £ again!', options); result.should.equal('whoops-i-spent-all-my-again'); }); it('should properly handle unicode punctuation conversion', function () { - var result = safeString('に間違いがないか、再度確認してください。再読み込みしてください。'); + var result = safeString('に間違いがないか、再度確認してください。再読み込みしてください。', options); result.should.equal('nijian-wei-iganaika-zai-du-que-ren-sitekudasai-zai-du-miip-misitekudasai'); }); + + it('should not lose or convert dashes if options are passed with truthy importing flag', function () { + var result, + options = {importing: true}; + result = safeString('-slug-with-starting-ending-and---multiple-dashes-', options); + result.should.equal('-slug-with-starting-ending-and---multiple-dashes-'); + }); + + it('should still remove/convert invalid characters when passed options with truthy importing flag', function () { + var result, + options = {importing: true}; + result = safeString('-slug-&with-✓-invalid-characters-に\'', options); + result.should.equal('-slug--with--invalid-characters-ni'); + }); });