diff --git a/src/backends/backend.js b/src/backends/backend.js index 19d02097..96746a0d 100644 --- a/src/backends/backend.js +++ b/src/backends/backend.js @@ -5,8 +5,7 @@ import GitGatewayBackend from "./git-gateway/implementation"; import { resolveFormat } from "../formats/formats"; import { selectListMethod, selectEntrySlug, selectEntryPath, selectAllowNewEntries, selectFolderEntryExtension } from "../reducers/collections"; import { createEntry } from "../valueObjects/Entry"; -import { sanitizeIRI } from "../lib/urlHelper"; -import sanitizeFilename from 'sanitize-filename'; +import { sanitizeSlug } from "../lib/urlHelper"; class LocalStorageAuthStore { storageKey = "netlify-cms-user"; @@ -43,7 +42,7 @@ const slugFormatter = (template = "{{slug}}", entryData) => { return identifier; }; - let slug = template.replace(/\{\{([^\}]+)\}\}/g, (_, field) => { + const slug = template.replace(/\{\{([^\}]+)\}\}/g, (_, field) => { switch (field) { case "year": return date.getFullYear(); @@ -56,21 +55,14 @@ const slugFormatter = (template = "{{slug}}", entryData) => { default: return entryData.get(field, "").trim(); } - }); - - // Convert slug to lower-case; - slug = slug.toLocaleLowerCase(); + }) + // Convert slug to lower-case + .toLocaleLowerCase() // Replace periods and spaces with dashes. - slug = slug.replace(/[.\s]/g, '-'); - // Sanitize as IRI (i18n URI) and as filename. - slug = sanitizeIRI(slug, {replacement: "-"}); - slug = sanitizeFilename(slug, {replacement: "-"}); + .replace(/[.\s]/g, '-'); - // Remove any doubled or trailing replacement characters (that were added in the sanitizers). - slug = slug.replace(/-+/g, '-').replace(/-$/, ''); - - return slug; + return sanitizeSlug(slug); }; class Backend { diff --git a/src/lib/urlHelper.js b/src/lib/urlHelper.js index 63dff30c..da81ec7e 100644 --- a/src/lib/urlHelper.js +++ b/src/lib/urlHelper.js @@ -1,4 +1,6 @@ import url from 'url'; +import sanitizeFilename from 'sanitize-filename'; +import { isString, escapeRegExp } from 'lodash'; function getUrl(url, direct) { return `${ direct ? '/#' : '' }${ url }`; @@ -28,6 +30,23 @@ export function sanitizeIRI(str, { replacement }) { return result; } +export function sanitizeSlug(str, { replacement = '-' }) { + if (!isString(str)) throw "`sanitizeSlug` only accepts strings as input."; + if (!isString(replacement)) throw "the `sanitizeSlug` replacement character must be a string."; + let slug = str; + + // Sanitize as IRI (i18n URI) and as filename. + slug = sanitizeIRI(slug, {replacement}); + slug = sanitizeFilename(slug, {replacement}); + + // Remove any doubled or trailing replacement characters (that were added in the sanitizers). + const doubleReplacement = new RegExp('(?:' + escapeRegExp(replacement) + ')+', 'g'); + const trailingReplacment = new RegExp(escapeRegExp(replacement) + '$') + slug = slug.replace(doubleReplacement, '-').replace(trailingReplacment, ''); + + return slug; +} + export function urlize(string) { const sanitized = makePathSanitized(string); const parsedURL = url.parse(sanitized);