Skip to content

Commit ee9e4ee

Browse files
committed
feat: add HtmlBlockNode component and parser for HTML block support
1 parent 6b5b2db commit ee9e4ee

File tree

8 files changed

+47
-2
lines changed

8 files changed

+47
-2
lines changed

components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ declare module 'vue' {
2323
HardBreakNode: typeof import('./src/components/HardBreakNode/HardBreakNode.vue')['default']
2424
HeadingNode: typeof import('./src/components/HeadingNode/HeadingNode.vue')['default']
2525
HighlightNode: typeof import('./src/components/HighlightNode/HighlightNode.vue')['default']
26+
HtmlBlockNode: typeof import('./src/components/HtmlBlockNode/HtmlBlockNode.vue')['default']
2627
ImageNode: typeof import('./src/components/ImageNode/ImageNode.vue')['default']
2728
InlineCodeNode: typeof import('./src/components/InlineCodeNode/InlineCodeNode.vue')['default']
2829
InsertNode: typeof import('./src/components/InsertNode/InsertNode.vue')['default']

packages/markdown-parser/src/parser/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { parseDefinitionList } from './node-parsers/definition-list-parser'
1010
import { parseFootnote } from './node-parsers/footnote-parser'
1111
import { parseHardBreak } from './node-parsers/hardbreak-parser'
1212
import { parseHeading } from './node-parsers/heading-parser'
13+
import { parseHtmlBlock } from './node-parsers/html-block-parser'
1314
import { parseList } from './node-parsers/list-parser'
1415
import { parseMathBlock } from './node-parsers/math-block-parser'
1516
import { parseParagraph } from './node-parsers/paragraph-parser'
@@ -35,6 +36,7 @@ export function parseMarkdownToStructure(
3536
// 此时 markdown 解析会出错要跳过
3637
safeMarkdown = safeMarkdown.replace(/(\n\[|\n\()+\n*$/g, '\n')
3738
}
39+
3840
// Get tokens from markdown-it
3941
const tokens = md.parse(safeMarkdown, {}) as MarkdownToken[]
4042
// Defensive: ensure tokens is an array
@@ -113,6 +115,7 @@ export function processTokens(tokens: MarkdownToken[]): ParsedNode[] {
113115
break
114116

115117
case 'html_block':
118+
result.push(parseHtmlBlock(token))
116119
i += 1
117120
break
118121
case 'code_block':
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { HtmlBlockNode, MarkdownToken } from '../../types'
2+
3+
export function parseHtmlBlock(token: MarkdownToken): HtmlBlockNode {
4+
return {
5+
type: 'html_block',
6+
content: String(token.content ?? ''),
7+
raw: String(token.content ?? ''),
8+
loading: false,
9+
}
10+
}

packages/markdown-parser/src/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ export interface CodeBlockNode extends BaseNode {
5555
raw: string
5656
}
5757

58+
export interface HtmlBlockNode extends BaseNode {
59+
type: 'html_block'
60+
content: string
61+
}
62+
5863
export interface InlineCodeNode extends BaseNode {
5964
type: 'inline_code'
6065
code: string
@@ -267,6 +272,7 @@ export type ParsedNode
267272
| MathInlineNode
268273
| MathBlockNode
269274
| ReferenceNode
275+
| HtmlBlockNode
270276
| Record<string, unknown>
271277
export interface CustomComponents {
272278
text: unknown
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script setup lang="ts">
2+
defineProps<{
3+
node: {
4+
content: string
5+
loading?: boolean
6+
}
7+
}>()
8+
</script>
9+
10+
<template>
11+
<div class="html-block-node" v-html="node.content" />
12+
</template>
13+
14+
<style scoped>
15+
</style>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import type { App } from 'vue'
2+
import HtmlBlockNode from './HtmlBlockNode.vue'
3+
4+
HtmlBlockNode.install = (app: App) => {
5+
app.component(HtmlBlockNode.__name as string, HtmlBlockNode)
6+
}
7+
8+
export default HtmlBlockNode

src/components/NodeRenderer/NodeRenderer.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup lang="ts">
22
import type { BaseNode, ParsedNode, ParseOptions } from 'stream-markdown-parser'
3-
import { getMarkdown, parseMarkdownToStructure } from 'stream-markdown-parser'
43
import { computed, defineAsyncComponent, ref } from 'vue'
4+
import { getMarkdown, parseMarkdownToStructure } from '../../../packages/markdown-parser'
55
import AdmonitionNode from '../../components/AdmonitionNode'
66
import BlockquoteNode from '../../components/BlockquoteNode'
77
import CheckboxNode from '../../components/CheckboxNode'
@@ -32,6 +32,7 @@ import TextNode from '../../components/TextNode'
3232
import ThematicBreakNode from '../../components/ThematicBreakNode'
3333
import { provideViewportPriority } from '../../composables/viewportPriority'
3434
import { getCustomNodeComponents } from '../../utils/nodeComponents'
35+
import HtmlBlockNode from '../HtmlBlockNode/HtmlBlockNode.vue'
3536
import { MathBlockNodeAsync, MathInlineNodeAsync } from './asyncComponent'
3637
import FallbackComponent from './FallbackComponent.vue'
3738
@@ -161,6 +162,7 @@ const nodeComponents = {
161162
checkbox_input: CheckboxNode,
162163
inline_code: InlineCodeNode,
163164
reference: ReferenceNode,
165+
html_block: HtmlBlockNode,
164166
// 可以添加更多节点类型
165167
// 例如:custom_node: CustomNode,
166168
...getCustomNodeComponents(props.customId),

test/link-parsing.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ describe('link parsing', () => {
7676

7777
it('test the intermediate state of the link tag', () => {
7878
const nodes = parseMarkdownToStructure(`<a href="https://example.com">`, md) as any
79-
expect(nodes.length).toBe(0)
79+
expect(nodes.length).toBe(1)
8080
})
8181

8282
it('parses link with parentheses and CJK brackets as a single link', () => {

0 commit comments

Comments
 (0)