Skip to content

Commit

Permalink
feat: support frontmatter defaults in headmatter
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed May 9, 2021
1 parent 417fb25 commit 78688a4
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 59 deletions.
1 change: 1 addition & 0 deletions packages/parser/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ export function parse(
slides,
config,
features: detectFeatures(markdown),
headmatter,
}
}

Expand Down
107 changes: 56 additions & 51 deletions packages/slidev/node/plugins/loaders.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { basename } from 'path'
import { ModuleNode, Update, ViteDevServer, Plugin } from 'vite'
import { isString, isTruthy, notNullish, objectMap, slash } from '@antfu/utils'
import { isString, notNullish, objectMap, range, slash } from '@antfu/utils'
import type { Connect } from 'vite'
import fg from 'fast-glob'
import Markdown from 'markdown-it'
// @ts-expect-error
import mila from 'markdown-it-link-attributes'
import { SlideInfo, SlideInfoExtended } from '@slidev/types'
import { SlideInfo, SlideInfoExtended, SlidevMarkdown } from '@slidev/types'
import * as parser from '@slidev/parser/fs'
import equal from 'fast-deep-equal'
import { ResolvedSlidevOptions, SlidevPluginOptions } from '../options'
Expand Down Expand Up @@ -121,13 +121,18 @@ export function createSlidesLoader(

const newData = await parser.load(entry)

const moduleIds: string[] = []
const moduleIds = new Set<string>()

if (data.slides.length !== newData.slides.length)
moduleIds.push('/@slidev/routes')
moduleIds.add('/@slidev/routes')

if (!equal(data.headmatter.defaults, newData.headmatter.defaults)) {
moduleIds.add('/@slidev/routes')
range(data.slides.length).map(i => hmrPages.add(i))
}

if (!equal(data.config, newData.config))
moduleIds.push('/@slidev/configs')
moduleIds.add('/@slidev/configs')

if (!equal(data.features, newData.features)) {
setTimeout(() => {
Expand All @@ -151,27 +156,26 @@ export function createSlidesLoader(
pluginOptions.onDataReload?.(newData, data)
Object.assign(data, newData)

const modules = (
await Promise.all(
Array.from(hmrPages)
.map(async(i) => {
const file = `${slidePrefix}${i + 1}.md`
return await VuePlugin.handleHotUpdate!({
...ctx,
modules: Array.from(ctx.server.moduleGraph.getModulesByFile(file) || []),
file,
read: () => (<any>MarkdownPlugin.transform)(newData.slides[i]?.raw, file),
})
}),
const vueModules = (
await Promise.all(Array.from(hmrPages).map(async(i) => {
const file = `${slidePrefix}${i + 1}.md`
return await VuePlugin.handleHotUpdate!({
...ctx,
modules: Array.from(ctx.server.moduleGraph.getModulesByFile(file) || []),
file,
async read() {
return await transformMarkdown((<any>MarkdownPlugin.transform)(newData.slides[i]?.content, file), i, newData)
},
})
}),
)
).flatMap(i => i || [])
hmrPages.clear()

const moduleEntries = moduleIds
.filter(isTruthy)
const moduleEntries = Array.from(moduleIds)
.map(id => ctx.server.moduleGraph.getModuleById(id))
.filter(notNullish)
.concat(modules)
.concat(vueModules)
.filter(i => !i.id?.startsWith('/@id/@vite-icons'))

return moduleEntries
Expand Down Expand Up @@ -204,7 +208,7 @@ export function createSlidesLoader(
const [, no, type] = match
const pageNo = parseInt(no) - 1
if (type === 'md')
return data.slides[pageNo]?.raw
return data.slides[pageNo]?.content
}
return ''
}
Expand All @@ -214,41 +218,42 @@ export function createSlidesLoader(
name: 'slidev:layout-transform:pre',
enforce: 'pre',
async transform(code, id) {
if (id.startsWith(slidePrefix)) {
const remaning = id.slice(slidePrefix.length)
const match = remaning.match(regexIdQuery)
if (!match)
return
if (!id.startsWith(slidePrefix))
return
const remaning = id.slice(slidePrefix.length)
const match = remaning.match(regexIdQuery)
if (!match)
return
const [, no, type] = match
if (type !== 'md')
return

const [, no, type] = match
if (type !== 'md')
return

const pageNo = parseInt(no) - 1
const layouts = await getLayouts()
const layoutName = data.slides[pageNo]?.frontmatter?.layout || (pageNo === 0 ? 'cover' : 'default')
if (!layouts[layoutName])
throw new Error(`Unknown layout "${layoutName}"`)

const imports = [
`import InjectedLayout from "${toAtFS(layouts[layoutName])}"`,
]

code = code.replace(/(<script setup.*>)/g, `$1${imports.join('\n')}\n`)
code = code.replace(/<template>([\s\S]*?)<\/template>/mg, '<template><InjectedLayout v-bind="frontmatter">$1</InjectedLayout></template>')
return code
}
},
},
{
name: 'xxx',
handleHotUpdate(i) {
if (i.file.endsWith('.vue'))
console.dir(i.modules)
const pageNo = parseInt(no) - 1
return transformMarkdown(code, pageNo, data)
},
},
]

async function transformMarkdown(code: string, pageNo: number, data: SlidevMarkdown) {
const layouts = await getLayouts()
const frontmatter = {
...(data.headmatter?.defaults as object || {}),
...(data.slides[pageNo]?.frontmatter || {}),
}
const layoutName = frontmatter?.layout || (pageNo === 0 ? 'cover' : 'default')
if (!layouts[layoutName])
throw new Error(`Unknown layout "${layoutName}"`)

const imports = [
`import InjectedLayout from "${toAtFS(layouts[layoutName])}"`,
`const frontmatter = ${JSON.stringify(frontmatter)}`,
]

code = code.replace(/(<script setup.*>)/g, `$1${imports.join('\n')}\n`)
code = code.replace(/<template>([\s\S]*?)<\/template>/mg, '<template><InjectedLayout v-bind="frontmatter">$1</InjectedLayout></template>')
return code
}

async function getLayouts() {
const layouts: Record<string, string> = {}

Expand Down
1 change: 1 addition & 0 deletions packages/slidev/node/plugins/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export async function createMarkdownPlugin(
return Markdown({
wrapperClasses: '',
headEnabled: false,
frontmatter: false,
markdownItOptions: {
quotes: '""\'\'',
html: true,
Expand Down
4 changes: 2 additions & 2 deletions packages/slidev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@
"vite": "^2.2.4",
"vite-plugin-components": "^0.8.4",
"vite-plugin-icons": "^0.5.0",
"vite-plugin-md": "^0.6.5",
"vite-plugin-md": "^0.6.6",
"vite-plugin-remote-assets": "^0.2.2",
"vite-plugin-windicss": "^0.16.0-beta.14",
"vue": "^3.0.11",
"windicss": "^3.0.0-beta.6",
"windicss": "^3.0.0-beta.7",
"yargs": "^17.0.1"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions packages/types/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ export interface SlidevMarkdown {
raw: string
config: SlidevConfig
features: SlidevFeatureFlags
headmatter: Record<string, unknown>
}
18 changes: 12 additions & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 78688a4

Please sign in to comment.