Skip to content

Commit

Permalink
Resolves #88, opens up permalinks usage for files with any extension.
Browse files Browse the repository at this point in the history
This commit also remaps the `match` option to accept glob patterns and formalizes the default linkset match to '**/*.html'
  • Loading branch information
webketje committed Nov 23, 2023
1 parent 67f2432 commit 77979b5
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 28 deletions.
12 changes: 9 additions & 3 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,15 @@ export type Linkset = {
*/
isDefault?: boolean;
/**
* An object whose key:value pairs will be used to match files and transform their permalinks according to the rules in this linkset
*/
match: {
* A glob pattern or array of glob patterns passed to {@linkcode Metalsmith.match}, or an object whose `key:value` pairs
* will be used to match files when at least one `key:value` pair matches, and transform their permalinks according to the rules in this linkset.
* @default `**\/*.html`
* @example
* '**\/*.json' // only target JSON files
* ['**\/*.md', '**\/*.html'] // pass multiple glob patterns
* { product: true, service: true } // target files with either key:value match
*/
match: string | string[] | {
[x: string]: any;
};
/**
Expand Down
46 changes: 21 additions & 25 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ const dupeHandlers = {
* Linkset definition
*
* @typedef {Object} Linkset
* @property {Object.<string,*>} match An object whose key:value pairs will be used to match files and transform their permalinks according to the rules in this linkset
* @property {string|string[]|Object.<string,*>} [match="**\/*.html"]
* * A glob pattern or array of glob patterns passed to {@linkcode Metalsmith.match}, or an object whose `key:value` pairs
* will be used to match files when at least one `key:value` pair matches, and transform their permalinks according to the rules in this linkset.
* @property {string} pattern A permalink pattern to transform file paths into, e.g. `blog/:date/:title`
* @property {SlugifyOptions|slugFunction} [slug] [Slugify options](https://github.com/simov/slugify) or a custom slug function of the form `(pathpart) => string`
* @property {string} [date='YYYY/MM/DD'] [Moment.js format string](https://momentjs.com/docs/#/displaying/format/) to transform Date link parts into, defaults to `YYYY/MM/DD`.
Expand All @@ -79,6 +81,7 @@ const emptyStr = ''
const dash = '-'

const defaultLinkset = {
match: '**/*.html',
pattern: ':dirname/:basename',
date: {
format: 'YYYY/MM/DD',
Expand Down Expand Up @@ -126,14 +129,6 @@ function slugFn(options = defaultOptions.slug) {
}
}

/**
* Check whether a file is an HTML file.
*
* @param {string} str The path
* @return {boolean}
*/
const html = (str) => path.extname(str) === '.html'

const normalizeLinkset = (linkset, defaultLs = defaultLinkset) => {
linkset = { ...defaultLs, ...linkset }
if (typeof linkset.slug !== 'function') {
Expand Down Expand Up @@ -244,19 +239,18 @@ function permalinks(options) {
const normalizedOptions = normalizeOptions(options)
const defaultLinkset = normalizedOptions.linksets[normalizedOptions.linksets.length - 1]

const findLinkset = (file) => {
const set = normalizedOptions.linksets.find(
(ls) =>
ls.match &&
Object.keys(ls.match).some((key) => {
if (file[key] === ls.match[key]) {
return true
}
if (Array.isArray(file[key]) && file[key].includes(ls.match[key])) {
return true
}
})
)
const findLinkset = (file, path, metalsmith) => {
const set = normalizedOptions.linksets.find((ls) => {
if (typeof ls.match === 'string' || Array.isArray(ls.match)) return !!metalsmith.match(ls.match, [path]).length
return Object.keys(ls.match).some((key) => {
if (file[key] === ls.match[key]) {
return true
}
if (Array.isArray(file[key]) && file[key].includes(ls.match[key])) {
return true
}
})
})

if (!set) return defaultLinkset
return set
Expand All @@ -271,14 +265,16 @@ function permalinks(options) {
}

const makeUnique = normalizedOptions.duplicates
const patternMatch = normalizedOptions.linksets[normalizedOptions.linksets.length - 1].match

Object.keys(files)
.filter((file) => html(file) && files[file].permalink !== false)
metalsmith
.match(patternMatch, Object.keys(files))
.filter((file) => files[file].permalink !== false)
.forEach((file) => {
const data = files[file]
debug('checking file: %s', file)

const linkset = findLinkset(data)
const linkset = findLinkset(data, file, metalsmith)

debug('applying pattern: %s to file: %s', linkset.pattern, file)

Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"items": [
{
"name": "Ancestry",
"icon": "link",
"repository": "https://github.com/tests-always-included/metalsmith-ancestry",
"description": "Builds a file tree in metadata so you can determine parents, list children, jump to previous and next siblings."
},
{
"name": "Angular $templateCache",
"icon": "addfile",
"repository": "https://github.com/tests-always-included/metalsmith-angular-templatecache",
"description": "Convert AngularJS templates from HTML into JavaScript and preload $templateCache.",
"status": "unmaintained"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"status": 200,
"message": "OK"
}
Empty file.
Empty file.
17 changes: 17 additions & 0 deletions test/fixtures/match-pattern-complex/src/plugins.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"items": [
{
"name": "Ancestry",
"icon": "link",
"repository": "https://github.com/tests-always-included/metalsmith-ancestry",
"description": "Builds a file tree in metadata so you can determine parents, list children, jump to previous and next siblings."
},
{
"name": "Angular $templateCache",
"icon": "addfile",
"repository": "https://github.com/tests-always-included/metalsmith-angular-templatecache",
"description": "Convert AngularJS templates from HTML into JavaScript and preload $templateCache.",
"status": "unmaintained"
}
]
}
3 changes: 3 additions & 0 deletions test/fixtures/match-pattern-complex/src/services.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
title: Services
---
4 changes: 4 additions & 0 deletions test/fixtures/match-pattern-complex/src/status.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"status": 200,
"message": "OK"
}
34 changes: 34 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -422,5 +422,39 @@ describe('@metalsmith/permalinks', () => {
done()
})
})

it('should process files other than .html if pattern match is given', (done) => {
const basePath = path.join(fixturesBase, 'match-pattern-complex')
Metalsmith(basePath)
.env('DEBUG', process.env.DEBUG)
.use(
permalinks({
match: '**/*.json',
pattern: 'api/:basename',
directoryIndex: 'index.json'
})
)
.use(
permalinks({
match: ['**/*.md'],
pattern: ':title',
linksets: [
{
match: 'index.md',
pattern: 'api'
}
]
})
)
.build((err) => {
if (err) return done(err)
try {
equal(path.join(basePath, 'build'), path.join(basePath, 'expected'))
done()
} catch (err) {
done(err)
}
})
})
})
})

0 comments on commit 77979b5

Please sign in to comment.