| 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 |