Added definition list block and code block
This commit is contained in:
11
src/lib/constants/terms.ts
Normal file
11
src/lib/constants/terms.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export const TERM_KINDS = [
|
||||
{ label: 'Entry', value: 'entry' },
|
||||
{ label: 'Prime', value: 'prime' },
|
||||
{ label: 'Essence', value: 'essence' },
|
||||
{ label: 'Element', value: 'element' },
|
||||
{ label: 'Stage', value: 'stage' },
|
||||
{ label: 'Tier', value: 'tier' },
|
||||
{ label: 'Premise', value: 'premise' },
|
||||
] as const
|
||||
|
||||
export type TermKind = (typeof TERM_KINDS)[number]['value']
|
||||
38
src/lib/markdoc/highlight.ts
Normal file
38
src/lib/markdoc/highlight.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { createHighlighter, type Highlighter } from 'shiki'
|
||||
|
||||
const THEMES = { light: 'github-light', dark: 'github-dark' } as const
|
||||
|
||||
const LANGS = [
|
||||
'astro',
|
||||
'bash',
|
||||
'css',
|
||||
'diff',
|
||||
'html',
|
||||
'ini',
|
||||
'js',
|
||||
'json',
|
||||
'jsonc',
|
||||
'jsx',
|
||||
'md',
|
||||
'python',
|
||||
'sql',
|
||||
'ts',
|
||||
'tsx',
|
||||
'xml',
|
||||
'yaml',
|
||||
]
|
||||
|
||||
export type Highlight = (code: string, lang: string) => string | null
|
||||
|
||||
let ready: Promise<Highlighter> | null = null
|
||||
|
||||
export async function createHighlight(): Promise<Highlight> {
|
||||
ready ??= createHighlighter({ themes: Object.values(THEMES), langs: LANGS })
|
||||
const highlighter = await ready
|
||||
const loaded = new Set(highlighter.getLoadedLanguages())
|
||||
|
||||
return (code, lang) =>
|
||||
loaded.has(lang)
|
||||
? highlighter.codeToHtml(code, { lang, themes: THEMES, defaultColor: false })
|
||||
: null
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import Markdoc from '@markdoc/markdoc'
|
||||
|
||||
import { createDiagnostics } from '../diagnostics'
|
||||
import { createHighlight } from './highlight'
|
||||
import { createNodes } from './nodes'
|
||||
import { createTags } from './tags'
|
||||
import type { NodeState, Renderable, Rendered, ResolveLink } from './types'
|
||||
@@ -21,11 +22,13 @@ export async function render(
|
||||
ids: new Set(),
|
||||
footnotes: [],
|
||||
sidenoteCount: 0,
|
||||
spoilerCount: 0,
|
||||
markers: new Set(),
|
||||
problems: [],
|
||||
}
|
||||
const highlight = await createHighlight()
|
||||
const config = {
|
||||
nodes: createNodes(state),
|
||||
nodes: createNodes(state, highlight),
|
||||
tags: createTags(state, resolveLink),
|
||||
}
|
||||
const problems = createDiagnostics()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Markdoc, { type Node, type Schema } from '@markdoc/markdoc'
|
||||
|
||||
import { slugify } from '../content/slug'
|
||||
import type { Highlight } from './highlight'
|
||||
import type { NodeState } from './types'
|
||||
|
||||
const { Tag } = Markdoc
|
||||
@@ -18,8 +19,27 @@ function uniqueId(text: string, ids: Set<string>): string {
|
||||
return id
|
||||
}
|
||||
|
||||
export function createNodes(state: NodeState): Record<string, Schema> {
|
||||
export function createNodes(state: NodeState, highlight: Highlight): Record<string, Schema> {
|
||||
return {
|
||||
fence: {
|
||||
...Markdoc.nodes.fence,
|
||||
transform(node) {
|
||||
/* transformAttributes renames `language` to `data-language`, so the
|
||||
raw attribute is the honest source. The content carries a trailing
|
||||
newline that would render as a blank last line. */
|
||||
const lang = String(node.attributes.language ?? '').trim()
|
||||
const code = String(node.attributes.content ?? '').replace(/\n$/, '')
|
||||
const html = lang ? highlight(code, lang) : null
|
||||
|
||||
if (lang && !html)
|
||||
state.problems.push({
|
||||
level: 'warning',
|
||||
message: `No highlighting for language "${lang}" — add it to LANGS in highlight.ts.`,
|
||||
})
|
||||
|
||||
return new Tag('Code', { code, lang: lang || undefined, html: html ?? undefined }, [])
|
||||
},
|
||||
},
|
||||
document: {
|
||||
...Markdoc.nodes.document,
|
||||
transform: (node, config) => node.transformChildren(config),
|
||||
|
||||
@@ -60,6 +60,8 @@ const generated =
|
||||
components: generalBlocks(ARTICLES),
|
||||
render: {
|
||||
tags: {
|
||||
definitions: 'DefinitionList',
|
||||
definition: 'Definition',
|
||||
callout: 'Callout',
|
||||
figure: 'Figure',
|
||||
tableWrapper: 'TableWrapper',
|
||||
@@ -84,6 +86,16 @@ export function createTags(state: NodeState, resolveLink: ResolveLink): Record<s
|
||||
])
|
||||
},
|
||||
},
|
||||
spoiler: {
|
||||
...generated.spoiler,
|
||||
transform(node, config) {
|
||||
const id = `spoiler-${(state.spoilerCount += 1)}`
|
||||
return new Tag('span', { class: 'spoiler' }, [
|
||||
new Tag('input', { id, class: 'spoiler__toggle', type: 'checkbox' }, []),
|
||||
new Tag('label', { class: 'spoiler__text', for: id }, node.transformChildren(config)),
|
||||
])
|
||||
},
|
||||
},
|
||||
sidenote: {
|
||||
...generated.sidenote,
|
||||
transform(node, config) {
|
||||
|
||||
@@ -23,6 +23,7 @@ export type NodeState = {
|
||||
ids: Set<string>
|
||||
footnotes: Footnote[]
|
||||
sidenoteCount: number
|
||||
spoilerCount: number
|
||||
markers: Set<string>
|
||||
problems: Problem[]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user