Skip to content

Commit

Permalink
feat: allow optional pattern placeholder
Browse files Browse the repository at this point in the history
  • Loading branch information
webketje committed Jan 30, 2022
1 parent 796a7f0 commit a7f89ea
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 18 deletions.
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ yarn add @metalsmith/permalinks
const Metalsmith = require('metalsmith')
const permalinks = require('@metalsmith/permalinks')

const metalsmith = new Metalsmith(__dirname).use(
Metalsmith(__dirname).use(
permalinks({
pattern: ':title'
})
Expand Down Expand Up @@ -67,6 +67,36 @@ Metalsmith(__dirname).use(
)
```

### Optional permalink pattern parts

The pattern option can also contain optional placeholders with the syntax `:PROPERTY?`. If the property is not defined in a file's metadata, it will be replaced with an empty string `''`. For example the pattern `:category?/:title` applied to a source directory with 2 files:

<table>
<tr>
<td>
<pre><code>---
title: With category
category: category1
---</pre></code>
</td>
</tr>
<tr>
<td>
<pre><code>---
title: No category
---</pre></code>
</td>
</tr>
</table>

would generate the file tree:

```
build
├── category1/with-category.html
└── no-category.html
```

### Dates

By default any date will be converted to a `YYYY/MM/DD` format when using in a permalink pattern, but you can change the conversion by passing a `date` option:
Expand Down
33 changes: 16 additions & 17 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ const defaultOptions = {
*
* @return {String}
*/
function slugFn(options = defaultOptions) {
function slugFn(options = defaultOptions.slug) {
return (text) => {
if (typeof options.extend === 'object' && options.extend !== null) {
slugify.extend(options.extend)
}

return slugify(text, Object.assign({}, { lower: true }, options))
return slugify(text, Object.assign({}, defaultOptions.slug, options))
}
}

Expand Down Expand Up @@ -210,13 +210,19 @@ const resolve = (str) => {
*/
const replace = (pattern, data, options) => {
if (!pattern) return null
const parsed = route.parse(pattern)
const keys = parsed.keys
const { keys } = route.parse(pattern)
const ret = {}

for (let i = 0, key; (key = keys[i++]); ) {
const val = data[key]
if (!val || (Array.isArray(val) && val.length === 0)) return null
const isOptional = pattern.match(`${key}\\?`)
if (!val || (Array.isArray(val) && val.length === 0)) {
if (isOptional) {
ret[key] = ''
continue
}
return null
}
if (val instanceof Date) {
ret[key] = options.date(val)
} else {
Expand All @@ -225,6 +231,7 @@ const replace = (pattern, data, options) => {
}

const transformed = route.inject(pattern, ret)

// handle absolute paths
if (transformed.startsWith('/')) return transformed.slice(1)
return transformed
Expand Down Expand Up @@ -261,23 +268,15 @@ function inititalizePermalinks(options) {

const findLinkset = (file) => {
const set = linksets.find((ls) =>
Object.keys(ls.match).reduce((sofar, key) => {
if (!sofar) {
return sofar
}

Object.keys(ls.match).some((key) => {
if (file[key] === ls.match[key]) {
return true
}

if (file[key] && file[key].indexOf) {
return file[key].includes(ls.match[key])
if (Array.isArray(file[key]) && file[key].includes(ls.match[key])) {
return true
}

return false
}, true)
})
)

return set || defaultLinkset
}

Expand Down
Empty file.
Empty file.
4 changes: 4 additions & 0 deletions test/fixtures/optional-path-parts/src/docs.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
title: documentation
date: 2022-01-15
---
3 changes: 3 additions & 0 deletions test/fixtures/optional-path-parts/src/post.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
title: First post
---
7 changes: 7 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,13 @@ const fixtures = [
}
]
}
},
{
message: 'should handle optional path params properly',
folder: 'optional-path-parts',
options: {
pattern: ':date?/:title'
}
}
]

Expand Down

0 comments on commit a7f89ea

Please sign in to comment.