Skip to content

Commit

Permalink
feat(remark-fff): ✨ support nested target
Browse files Browse the repository at this point in the history
  • Loading branch information
kwaa committed Dec 26, 2023
1 parent 47139a3 commit f6e8100
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 52 deletions.
9 changes: 9 additions & 0 deletions .changeset/poor-glasses-deliver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"remark-fff": patch
"fff-flavored-frontmatter": patch
"fff-transform-presets": patch
"indiekit-preset-fff": patch
"markdown-it-fff": patch
---

Version 1.2.0-alpha.1
64 changes: 38 additions & 26 deletions packages/remark-fff/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Plugin, Transformer } from 'unified'

import { strict, transform } from 'fff-flavored-frontmatter'

import type { _Post, RemarkFFFOptions } from './types'
import type { RemarkFFFOptions } from './types'

/**
* Remark plugin for auto-conversion other frontmatter variable formats to {@link https://fff.js.org | FFF Flavored Frontmatter}.
Expand All @@ -19,40 +19,52 @@ export const remarkFFF: Plugin<[RemarkFFFOptions]>
},
): Transformer =>
(_tree, file) => {
// make TS happy
const post: _Post = file as unknown as _Post
const fm = transform(
{
...(options.target === 'mdsvex'
? post.data.fm
: (options.target === 'astro'
? post.data.astro.frontmatter
// eslint-disable-next-line unicorn/no-nested-ternary
: (options.target === 'nuxt'
? post.data
: post.data))),
},
[
...options.presets,
...(options.strict ? [strict(options.strict)] : []),
],
)
let targets: string[] | undefined

// Compatible with old target parameters before 1.2.
// TODO: remove in 1.3
switch (options.target) {
case 'mdsvex': {
file.data.fm = fm
targets = ['fm']
break
}
case 'astro': {
file.data.astro = {
...file.data.astro as object,
frontmatter: fm,
}
targets = ['astro', 'frontmatter']
break
}
case 'nuxt': {
file.data = fm
targets = undefined
break
}
default: { file.data = fm }
default: {
targets = options.target
}
}

let input = file.data as Record<string, unknown>
if (targets) {
for (const target of targets) {
try {
input = input[target] as Record<string, unknown>
}
catch {
input = {}
}
}
}

const output = transform(
input,
[
...options.presets,
...(options.strict ? [strict(options.strict)] : []),
],
)

file.data = targets
? {
...file.data,
...targets.reduceRight((output, key) => ({ [key]: output }), output),
}
: output
}
39 changes: 13 additions & 26 deletions packages/remark-fff/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type {
FFFFlavoredFrontmatter,
FFFTransformPreset,
StrictPresetOptions,
} from 'fff-flavored-frontmatter'
Expand All @@ -11,30 +10,18 @@ import type {
export interface RemarkFFFOptions {
presets: FFFTransformPreset[]
strict?: StrictPresetOptions
/**
* Replacement target for Remark FFF.
* @example
* ```ts
* // astro: file.data.astro.frontmatter
* const target = ['astro', 'frontmatter'] // file.data['astro']['frontmatter']
* // mdsvex: file.data.fm
* const target = ['fm'] // file.data['fm']
* // nuxt: file.data
* const target = undefined // file.data
* ```
*/
// eslint-disable-next-line @typescript-eslint/ban-types
target: 'astro' | 'mdsvex' | 'nuxt' | (string & {})
target?: 'astro' | 'mdsvex' | 'nuxt' | string[]
}

/**
* Internal Post Data Type.
* @internal
*/
export type _Post =
| /** MDsveX */ {
data: {
astro: {
frontmatter: FFFFlavoredFrontmatter & Record<string, unknown>
}
fm: never
}
filename: never
path: string
}
| /** Astro */ {
data: {
astro: never
fm: FFFFlavoredFrontmatter & Record<string, unknown>
}
filename: string
path: never
}
23 changes: 23 additions & 0 deletions packages/remark-fff/test/frontmatter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,27 @@ describe('remark-fff strict mode', () => {
.processSync(file).data as { fm: FFFFlavoredFrontmatter }
expect(fm.image).toEqual('https://fff.js.org/glowing_star.svg')
})
it('custom nested target', () => {
const file = new VFile({
data: {
a: {
b: {
c: {
d: {
date: '2023-12-25',
},
},
},
},
},
})
const data = remark()
.use(remarkFrontmatter)
.use(remarkFFF, {
presets: [{ created: 'date' }],
target: ['a', 'b', 'c', 'd'],
})
.processSync(file).data as { a: { b: { c: { d: FFFFlavoredFrontmatter } } } }
expect(data.a.b.c.d.created).toEqual('2023-12-25')
})
})

0 comments on commit f6e8100

Please sign in to comment.