Skip to content
This repository has been archived by the owner on Nov 26, 2021. It is now read-only.

Commit

Permalink
feat: Allow for a custom filename builder fn in config
Browse files Browse the repository at this point in the history
  • Loading branch information
bnchdrff authored and Khaledgarbaya committed Oct 27, 2016
1 parent 04f6734 commit 3b0ab12
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 3 deletions.
22 changes: 22 additions & 0 deletions docs/source-file-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,28 @@ E.g.

**Default value:** `${sys.contentType.sys.id}-${sys.id}`

### `entry_filename_builder` *(optional)*

**Use a custom function to generate the filename**

`source/posts-that-need-fancy-filenames.html`

```markdown
---
title: test__posts__filenameBuilder
contentful:
content_type: 2wKn6yEnZewu2SCCkus4as
entry_filename_builder: aldente
entry_template: post.html
layout: posts.html
---
POSTS-CONTENT-FILENAME-BUILDER
```

In your global configuration, define an object `filenameBuilders` with a property named to match `entity_filename_builder` with a function as its value. This function will be called with the arguments `entry` (the entry being processed) and `fileOptions`. Return the desired filename.

Note that a function cannot be specified in the site configuration if it is stored as JSON; rather you will need to invoke Metalsmith programmatically to use this feature.

### `entry_id` *(optional)*

**Render a file based on a single entry**
Expand Down
6 changes: 6 additions & 0 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ function getFileName (entry, fileOptions, globalOptions) {
fileOptions = fileOptions || {}
globalOptions = globalOptions || {}

// Hand off control if a specified custom filename builder exists.
if (fileOptions.entry_filename_builder &&
typeof globalOptions.filenameBuilders[fileOptions.entry_filename_builder] === 'function') {
return globalOptions.filenameBuilders[fileOptions.entry_filename_builder](entry, fileOptions)
}

const extension = fileOptions.use_template_extension
? fileOptions.entry_template.split('.').slice(1).pop()
: 'html'
Expand Down
29 changes: 29 additions & 0 deletions lib/util.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,32 @@ test('util.getFileName - should set notFound key', t => {
t.is(fileName, 'foo/__not-available__.html')
t.pass()
})

test('util.getFileName - should use a custom filename builder if available', t => {
const fileName = util.getFileName(
{
sys: {
contentType: {
sys: {
id: 'foo'
}
},
id: 'bar'
}
},
{
entry_filename_builder: 'bazquxer'
},
{
filenameBuilders: {
bazquxer () {
return 'baz-qux.html'
}
}
}
)

t.is(fileName, 'baz-qux.html')
t.pass()
})

4 changes: 2 additions & 2 deletions lib/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ function validateFileNameForEntry (fileName, entry, regex, options) {
if (regex.test(fileName)) {
if (options.throw_errors) {
throw new Error(
`contentful-metalsmith: \'entry_file_pattern\' for entry with id '${entry.sys.id}' could not be resolved`
`contentful-metalsmith: 'entry_file_pattern' for entry with id '${entry.sys.id}' could not be resolved`
)
} else {
console.warn(
`contentful-metalsmith: \'entry_file_pattern\' for entry with id '${entry.sys.id}' could not be resolved -> falling back to ${fileName}`
`contentful-metalsmith: 'entry_file_pattern' for entry with id '${entry.sys.id}' could not be resolved -> falling back to ${fileName}`
)
}
}
Expand Down
19 changes: 18 additions & 1 deletion test/index.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import test from 'ava'
import fs from 'fs'
import Metalsmith from 'metalsmith'
import slug from 'slug-component'

const expectedResults = {
postsCustomFileName: `Down the Rabbit HoleSeven Tips From Ernest Hemingway on How to Write Fiction
Expand Down Expand Up @@ -60,7 +61,12 @@ test.serial.cb('e2e - it propagate errors properly', t => {
test.serial.cb('e2e - it should render all templates properly', t => {
const metalsmith = createMetalsmith({
space_id: 'w7sdyslol3fu',
access_token: 'baa905fc9cbfab17b1bc0b556a7e17a3e783a2068c9fd6ccf74ba09331357182'
access_token: 'baa905fc9cbfab17b1bc0b556a7e17a3e783a2068c9fd6ccf74ba09331357182',
filenameBuilders: {
aldente (entry) {
return `aldente-${slug(entry.fields.title)}.html`
}
}
})

metalsmith.build(error => {
Expand Down Expand Up @@ -121,11 +127,22 @@ test.serial.cb('e2e - it should render all templates properly', t => {
fs.readFileSync(`${__dirname}/build/post-down-the-rabbit-hole.html`, { encoding: 'utf8' }),
expectedResults.posts.downTheRabbitHole
)

t.is(
fs.readFileSync(`${__dirname}/build/post-seven-tips-from-ernest-hemingway-on-how-to-write-fiction.html`, { encoding: 'utf8' }),
expectedResults.posts.sevenTips
)

t.is(
fs.readFileSync(`${__dirname}/build/aldente-seven-tips-from-ernest-hemingway-on-how-to-write-fiction.html`, { encoding: 'utf8' }),
expectedResults.posts.sevenTips
)

t.is(
fs.readFileSync(`${__dirname}/build/aldente-seven-tips-from-ernest-hemingway-on-how-to-write-fiction.html`, { encoding: 'utf8' }),
expectedResults.posts.sevenTips
)

//
// render a post defined with id
//
Expand Down
9 changes: 9 additions & 0 deletions test/src/posts-filename-builder.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: test__posts__filenameBuilder
contentful:
content_type: 2wKn6yEnZewu2SCCkus4as
entry_filename_builder: aldente
entry_template: post.html
layout: posts.html
---
POSTS-CONTENT-FILENAME-BUILDER

0 comments on commit 3b0ab12

Please sign in to comment.