diff --git a/README.md b/README.md index 6b7030c2..93641294 100644 --- a/README.md +++ b/README.md @@ -345,10 +345,10 @@ gatsby-config.js autoGenHomeLabel: `Root`, // exlude: optional, include to overwrite these default excluded pages exclude: [ - `/dev-404-page`, - `/404`, + `/dev-404-page/`, + `/404/`, `/404.html`, - `/offline-plugin-app-shell-fallback`, + `/offline-plugin-app-shell-fallback/`, ], // crumbLabelUpdates: optional, update specific crumbLabels in the path crumbLabelUpdates: [ @@ -356,7 +356,10 @@ gatsby-config.js pathname: '/book', crumbLabel: 'Books' } - ] + ], + // trailingSlashes: optional, will add trailing slashes to the end + // of crumb pathnames. default is false + trailingSlashes: true, // usePathPrefix: optional, if you are using pathPrefix above usePathPrefix: '/blog', }, diff --git a/src/gatsby-node.js b/src/gatsby-node.js index b9a8b248..e493d1fb 100644 --- a/src/gatsby-node.js +++ b/src/gatsby-node.js @@ -3,16 +3,17 @@ exports.onCreatePage = ({ page, pathPrefix, actions }, pluginOptions) => { const { createPage, deletePage } = actions const defaultOptions = { + trailingSlashes: false, exclude: [ - `/dev-404-page`, - `/404`, + `/dev-404-page/`, + `/404/`, `/404.html`, - `/offline-plugin-app-shell-fallback`, + `/offline-plugin-app-shell-fallback/`, ], } const optionsActual = { ...defaultOptions, ...pluginOptions } - const { crumbLabelUpdates = [] } = optionsActual + const { crumbLabelUpdates = [], trailingSlashes } = optionsActual // for pages not excludecd, create crumbs out of each section of the page path if (!optionsActual.exclude.includes(page.path)) { @@ -34,12 +35,13 @@ exports.onCreatePage = ({ page, pathPrefix, actions }, pluginOptions) => { ] } else if (index !== 0 && split !== '') { // remaining sections of path + acc += `/${split}` const n = acc.lastIndexOf('/') // update crumbLabel for any crumbLabelUpdates otherwise use path let crumbLabel = acc.slice(n + 1).replace(/%20/g, ' ') - crumbLabelUpdates.forEach(labelUpdate => { + crumbLabelUpdates.forEach((labelUpdate) => { if (labelUpdate.pathname === acc) { crumbLabel = labelUpdate.crumbLabel } @@ -57,6 +59,17 @@ exports.onCreatePage = ({ page, pathPrefix, actions }, pluginOptions) => { crumbs = [...crumbs] } }) + + // if trailingSlashes add a trailing slash to the end of + // each crumb. Excluding root (/) and crumbs including a "." (ex: 404.html) + if (trailingSlashes) { + crumbs.forEach((crumb, index) => { + if (index !== 0 && crumb.pathname.indexOf('.') === -1) { + crumbs[index].pathname = `${crumbs[index].pathname}/` + } + }) + } + const breadcrumb = { location: page.path, crumbs, diff --git a/src/gatsby-node.test.js b/src/gatsby-node.test.js index 193c544c..64ceab3c 100644 --- a/src/gatsby-node.test.js +++ b/src/gatsby-node.test.js @@ -106,6 +106,52 @@ const calledWithLongLabelUpdates = { }, } +const calledWithTrailingSlashes = { + path: '/long/test', + context: { + breadcrumb: { + crumbs: [ + { + crumbLabel: 'Home', + pathname: '/', + }, + { + crumbLabel: 'long', + pathname: '/long/', + }, + { + crumbLabel: 'test', + pathname: '/long/test/', + }, + ], + location: '/long/test', + }, + }, +} + +const calledWithTrailingSlashesLabelUpdates = { + path: '/long/test', + context: { + breadcrumb: { + crumbs: [ + { + crumbLabel: 'Home', + pathname: '/', + }, + { + crumbLabel: 'LONG', + pathname: '/long/', + }, + { + crumbLabel: 'test', + pathname: '/long/test/', + }, + ], + location: '/long/test', + }, + }, +} + afterEach(() => { actions.createPage.mockClear() actions.deletePage.mockClear() @@ -202,4 +248,33 @@ describe('AutoGen crumbs: ', () => { expect(actions.deletePage).not.toHaveBeenCalled() expect(actions.createPage).not.toHaveBeenCalled() }) + it('should generate crumbs with trailingSlashes', () => { + onCreatePage( + { page: mockPageLongPath, actions }, + { + useAutoGen: true, + trailingSlashes: true, + }, + ) + expect(actions.deletePage).toHaveBeenCalledTimes(1) + expect(actions.deletePage).toHaveBeenCalledWith(mockPageLongPath) + expect(actions.createPage).toHaveBeenCalledTimes(1) + expect(actions.createPage).toHaveBeenCalledWith(calledWithTrailingSlashes) + }) + it('should generate crumbs with trailingSlashes and label updates', () => { + onCreatePage( + { page: mockPageLongPath, actions }, + { + useAutoGen: true, + trailingSlashes: true, + crumbLabelUpdates: [{ pathname: '/long', crumbLabel: 'LONG' }], + }, + ) + expect(actions.deletePage).toHaveBeenCalledTimes(1) + expect(actions.deletePage).toHaveBeenCalledWith(mockPageLongPath) + expect(actions.createPage).toHaveBeenCalledTimes(1) + expect(actions.createPage).toHaveBeenCalledWith( + calledWithTrailingSlashesLabelUpdates, + ) + }) })