diff --git a/src/index.js b/src/index.js index 4e532f0..3f15d62 100644 --- a/src/index.js +++ b/src/index.js @@ -256,6 +256,14 @@ function permalinks(options) { } let ppath = replace(linkset.pattern, data, opts) || resolve(file, normalizedOptions.directoryIndex) + // invalid on Windows, but best practice not to use them anyway + const invalidFilepathChars = /\||:|<|>|\*|\?|"/ + if (invalidFilepathChars.test(ppath)) { + const msg = `Filepath "${file}" contains invalid filepath characters (one of :|<>"*?) after resolving as linkset pattern "${linkset.pattern}"` + debug.error(msg) + done(new Error(msg)) + } + // Override the path with `permalink` option if (Object.prototype.hasOwnProperty.call(data, 'permalink') && data.permalink !== false) { ppath = data.permalink diff --git a/test/fixtures/invalid-filename-chars/expected/post/index.html b/test/fixtures/invalid-filename-chars/expected/post/index.html new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/invalid-filename-chars/src/post.html b/test/fixtures/invalid-filename-chars/src/post.html new file mode 100644 index 0000000..ee9c514 --- /dev/null +++ b/test/fixtures/invalid-filename-chars/src/post.html @@ -0,0 +1,3 @@ +--- +title: ":::|||" +--- \ No newline at end of file diff --git a/test/index.cjs b/test/index.cjs index e386392..e572e10 100644 --- a/test/index.cjs +++ b/test/index.cjs @@ -258,6 +258,7 @@ describe('@metalsmith/permalinks', () => { }) }) + // this test was probably added to address an oddity in regexparam library path handling related to having a leading slash it('should use the resolve path for false values (not root)', (done) => { Metalsmith(path.join(fixturesBase, 'falsy')) .use(permalinks(':falsy/:title')) @@ -272,6 +273,21 @@ describe('@metalsmith/permalinks', () => { }) }) + // better to error the build and make users aware of an anti-pattern, + // than silently strip/replace the invalid chars and let them follow bad practice + it('should error when encountering invalid filepath characters after permalink pattern resolution', done => { + Metalsmith(path.join(fixturesBase, 'invalid-filename-chars')) + .use(permalinks(':title')) + .build((err) => { + try { + assert.strictEqual(err.message, 'Filepath "post.html" contains invalid filepath characters (one of :|<>"*?) after resolving as linkset pattern ":title"') + done() + } catch (err) { + done(err) + } + }) + }) + it('should allow an alternative directoryIndex', (done) => { const basepath = path.join(fixturesBase, 'custom-indexfile') Metalsmith(basepath)