Added layouts + routes
This commit is contained in:
@@ -21,3 +21,6 @@ export function assertNoErrors(list: Diagnostic[]): void {
|
||||
const errors = list.filter((d) => d.level === 'error').length
|
||||
if (errors) throw new Error(`Content has ${errors} error(s):\n${formatDiagnostics(list)}`)
|
||||
}
|
||||
|
||||
export const forEntry = (list: Diagnostic[], collection: string, id: string) =>
|
||||
list.filter((d) => d.collection === collection && d.id === id)
|
||||
|
||||
33
src/lib/markdoc/index.ts
Normal file
33
src/lib/markdoc/index.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import Markdoc from '@markdoc/markdoc'
|
||||
|
||||
import { createDiagnostics } from '../diagnostics'
|
||||
import { createNodes } from './nodes'
|
||||
import type { NodeState, Renderable, Rendered } from './types'
|
||||
|
||||
const LEVEL = {
|
||||
critical: 'error',
|
||||
error: 'error',
|
||||
warning: 'warning',
|
||||
} as const
|
||||
|
||||
export async function render({ collection, id, content }: Renderable): Promise<Rendered> {
|
||||
const { node } = await content()
|
||||
const state: NodeState = {
|
||||
headings: [],
|
||||
ids: new Set(),
|
||||
}
|
||||
const config = {
|
||||
nodes: createNodes(state),
|
||||
}
|
||||
const problems = createDiagnostics()
|
||||
|
||||
for (const { lines, error } of Markdoc.validate(node, config)) {
|
||||
const level = LEVEL[error.level as keyof typeof LEVEL]
|
||||
if (level) problems[level](collection, id, `Line ${lines[0] + 1} : ${error.message}`)
|
||||
}
|
||||
return {
|
||||
tree: Markdoc.transform(node, config),
|
||||
headings: state.headings,
|
||||
diagnostics: problems.list,
|
||||
}
|
||||
}
|
||||
49
src/lib/markdoc/nodes.ts
Normal file
49
src/lib/markdoc/nodes.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import Markdoc, { type Node, type Schema } from '@markdoc/markdoc'
|
||||
|
||||
import { slugify } from '../content/slug'
|
||||
import type { NodeState } from './types'
|
||||
|
||||
const { Tag } = Markdoc
|
||||
|
||||
const textOf = (node: Node): string =>
|
||||
node.type === 'text' || node.type === 'code'
|
||||
? String(node.attributes.content ?? '')
|
||||
: node.children.map(textOf).join('')
|
||||
|
||||
function uniqueId(text: string, ids: Set<string>): string {
|
||||
const base = slugify(text) || 'section'
|
||||
let id = base
|
||||
for (let n = 2; ids.has(id); n++) id = `${base}-${n}`
|
||||
ids.add(id)
|
||||
return id
|
||||
}
|
||||
|
||||
export function createNodes(state: NodeState): Record<string, Schema> {
|
||||
return {
|
||||
document: {
|
||||
...Markdoc.nodes.document,
|
||||
transform: (node, config) => node.transformChildren(config),
|
||||
},
|
||||
heading: {
|
||||
...Markdoc.nodes.heading,
|
||||
transform(node, config) {
|
||||
const level = Number(node.attributes.level)
|
||||
const text = textOf(node)
|
||||
const id = uniqueId(text, state.ids)
|
||||
state.headings.push({ id, level, text })
|
||||
return new Tag(`h${level}`, { id }, node.transformChildren(config))
|
||||
},
|
||||
},
|
||||
table: {
|
||||
...Markdoc.nodes.table,
|
||||
transform(node, config) {
|
||||
const table = new Tag(
|
||||
'table',
|
||||
node.transformAttributes(config),
|
||||
node.transformChildren(config),
|
||||
)
|
||||
return new Tag('div', { class: 'table-scroll', tabindex: 0 }, [table])
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
26
src/lib/markdoc/types.ts
Normal file
26
src/lib/markdoc/types.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import type { Node, RenderableTreeNode } from '@markdoc/markdoc'
|
||||
|
||||
import type { Diagnostic } from '../diagnostics/types'
|
||||
|
||||
export type Heading = {
|
||||
id: string
|
||||
level: number
|
||||
text: string
|
||||
}
|
||||
|
||||
export type NodeState = {
|
||||
headings: Heading[]
|
||||
ids: Set<string>
|
||||
}
|
||||
|
||||
export type Rendered = {
|
||||
tree: RenderableTreeNode
|
||||
headings: Heading[]
|
||||
diagnostics: Diagnostic[]
|
||||
}
|
||||
|
||||
export type Renderable = {
|
||||
collection: string
|
||||
id: string
|
||||
content: () => Promise<{ node: Node }>
|
||||
}
|
||||
Reference in New Issue
Block a user