返回 slidev
slot-sugar.ts
根目录 / packages / slidev / node / syntax / slot-sugar.ts
1 import type { MarkdownExit } from 'markdown-exit'
2
3 const RE_SLOT_MARKER = /^::\s*([\w.\-:]+)\s*::\s*$/
4
5 export default function MarkdownItSlotSugar(md: MarkdownExit) {
6 md.block.ruler.before('fence', 'slot_marker', (state, startLine, _endLine, silent) => {
7 if (state.sCount[startLine] - state.blkIndent > 0)
8 return false
9
10 const pos = state.bMarks[startLine] + state.tShift[startLine]
11 const max = state.eMarks[startLine]
12 const lineText = state.src.slice(pos, max)
13
14 const match = lineText.match(RE_SLOT_MARKER)
15 if (!match)
16 return false
17
18 if (silent)
19 return true
20
21 const token = state.push('slot_marker', '', 0)
22 token.meta = { slotName: match[1] }
23 token.map = [startLine, startLine + 1]
24
25 state.line = startLine + 1
26 state.env.hasSlotMarker = true
27
28 return true
29 }, { alt: ['paragraph', 'reference', 'blockquote', 'list'] })
30
31 md.core.ruler.push('slot_sugar_compiler', (state) => {
32 if (!state.env.hasSlotMarker)
33 return
34
35 const tokens = state.tokens
36 const newTokens = []
37 let hasOpenSlot = false
38
39 for (let i = 0; i < tokens.length; i++) {
40 const token = tokens[i]
41
42 if (token.type === 'slot_marker') {
43 if (hasOpenSlot) {
44 const closeHtml = new state.Token('html_block', '', 0)
45 closeHtml.content = '\n</template>\n'
46 newTokens.push(closeHtml)
47 }
48
49 const openHtml = new state.Token('html_block', '', 0)
50 openHtml.content = `\n<template v-slot:${token.meta.slotName}="slotProps">\n`
51 newTokens.push(openHtml)
52
53 hasOpenSlot = true
54 }
55 else {
56 newTokens.push(token)
57 }
58 }
59
60 if (hasOpenSlot) {
61 const closeHtml = new state.Token('html_block', '', 0)
62 closeHtml.content = '\n</template>\n'
63 newTokens.push(closeHtml)
64 }
65
66 state.tokens = newTokens
67 })
68 }
69
69 lines TYPESCRIPT