Skip to content

Commit

Permalink
BREAKING: Solves #94, removes invalid file path characters & sets mor…
Browse files Browse the repository at this point in the history
…e sensible slugify defaults

This change sets more sensible slugify option defaults. As such it may result in different destination paths for existing builds.
To maintain compatibility, users should set slugify options to { lower: true, extend: {}, remove: /[^\w\s$*_+~.()'"!\-:@]+/g }.
  • Loading branch information
webketje committed Oct 15, 2023
1 parent 176515e commit b30d875
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 9 deletions.
32 changes: 26 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,29 @@ const dupeHandlers = {
* @property {SlugifyOptions|slugFunction} [slug] {@link SlugifyOptions} or a custom slug function of the form `(pathpart) => string`
*/

// These are the invalid path chars on Windows, on *nix systems all are valid except forward slash.
// However, it is highly unlikely that anyone would want these to appear in a file path and they can still be overridden if necessary
const invalidPathChars = '[<>:"\'/\\|?*]'
const defaultSlugifyRemoveChars = '[^\\w\\s$_+~.()!\\-@]+'
const emptyStr = ''
const dash = '-'

/** @type {Options} */
const defaultOptions = {
date: 'YYYY/MM/DD',
slug: { lower: true },
slug: {
lower: true,
remove: new RegExp(`${defaultSlugifyRemoveChars}|${invalidPathChars}`, 'g'),
extend: {
// by default slugify strips these, resulting in word concatenation. Map these chars to dash to force a word break
':': dash,
'|': dash,
'/': dash,
// by default slugify translates these to "smaller" & "greater", unwanted when a <html> tag is in the permalink
'<': emptyStr,
'>': emptyStr
}
},
trailingSlash: false,
linksets: [],
duplicates: 'error',
Expand All @@ -91,12 +110,13 @@ const defaultOptions = {
* @return {String}
*/
function slugFn(options = defaultOptions.slug) {
return function defaultSlugFn(text) {
if (typeof options.extend === 'object' && options.extend !== null) {
slugify.extend(options.extend)
}
options = Object.assign({}, defaultOptions.slug, options)
if (typeof options.extend === 'object' && options.extend !== null) {
slugify.extend(options.extend)
}

return slugify(text, Object.assign({}, defaultOptions.slug, options))
return function defaultSlugFn(text) {
return slugify(text, options)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
special
5 changes: 5 additions & 0 deletions test/fixtures/permalink-invalid-chars/src/special.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: >
"special chars" in 'HTML'? F|ward/slash*"
---
special
4 changes: 4 additions & 0 deletions test/fixtures/permalink-invalid-chars/src/test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: 'HTML <head>: essential tags - meta/ti\\tle'
---
test
Empty file.
3 changes: 3 additions & 0 deletions test/fixtures/slug-custom-function/src/hello.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
title: 你好, world!
---
11 changes: 8 additions & 3 deletions test/index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,17 @@ const fixtures = [
options: ':title'
},
{
message: 'should override path in any files with permalink option',
message: 'should override destination path in any files with permalink option',
folder: 'permalink-override',
options: ':title'
},
{
message: 'should accepts a shorthand string',
message: 'should remove/replace invalid path characters by default',
folder: 'permalink-invalid-chars',
options: ':title'
},
{
message: 'should accept a shorthand string',
folder: 'shorthand',
options: ':title'
},
Expand Down Expand Up @@ -233,7 +238,7 @@ describe('@metalsmith/permalinks', () => {
.build((err) => {
if (err) return done(err)
try {
equal(path.join(basePath, 'expected'), path.join(basePath, 'build'))
equal(path.join(basePath, 'build'), path.join(basePath, 'expected'))
done()
} catch (err) {
done(err)
Expand Down

0 comments on commit b30d875

Please sign in to comment.