-
-
Notifications
You must be signed in to change notification settings - Fork 378
/
schema.ts
67 lines (52 loc) 路 2.22 KB
/
schema.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/* Copyright 2021, Milkdown by Mirone. */
import type { MilkdownPlugin, TimerType } from '@milkdown/ctx'
import { createSlice, createTimer } from '@milkdown/ctx'
import { Schema } from '@milkdown/prose/model'
import type {
MarkSchema, NodeSchema, RemarkParser,
} from '@milkdown/transformer'
import { InitReady, remarkCtx, remarkPluginsCtx } from '.'
/// The timer which will be resolved when the schema plugin is ready.
export const SchemaReady = createTimer('schemaReady')
/// A slice which stores timers that need to be waited for before starting to run the plugin.
/// By default, it's `[InitReady]`.
export const schemaTimerCtx = createSlice([] as TimerType[], 'schemaTimer')
/// A slice which contains the schema.
export const schemaCtx = createSlice({} as Schema, 'schema')
/// A slice which stores the nodes spec.
export const nodesCtx = createSlice([] as Array<[string, NodeSchema]>, 'nodes')
/// A slice which stores the marks spec.
export const marksCtx = createSlice([] as Array<[string, MarkSchema]>, 'marks')
const extendPriority = <T extends NodeSchema | MarkSchema>(x: T): T => {
return {
...x,
parseDOM: x.parseDOM?.map(rule => ({ priority: x.priority, ...rule })),
}
}
/// The schema plugin.
/// This plugin will load all nodes spec and marks spec and create a schema.
///
/// This plugin will wait for the init plugin.
export const schema: MilkdownPlugin = (ctx) => {
ctx.inject(schemaCtx).inject(nodesCtx).inject(marksCtx).inject(schemaTimerCtx, [InitReady]).record(SchemaReady)
return async () => {
await ctx.waitTimers(schemaTimerCtx)
const remark = ctx.get(remarkCtx)
const remarkPlugins = ctx.get(remarkPluginsCtx)
const processor = remarkPlugins.reduce((acc: RemarkParser, plug) => acc.use(plug), remark)
ctx.set(remarkCtx, processor)
const nodes = Object.fromEntries(ctx.get(nodesCtx).map(([key, x]) => [key, extendPriority(x)]))
const marks = Object.fromEntries(ctx.get(marksCtx).map(([key, x]) => [key, extendPriority(x)]))
ctx.set(
schemaCtx,
new Schema({
nodes,
marks,
}),
)
ctx.done(SchemaReady)
return () => {
ctx.remove(schemaCtx).remove(nodesCtx).remove(marksCtx).remove(schemaTimerCtx).clearTimer(SchemaReady)
}
}
}