@incremark/vue 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/ThemeProvider.vue.d.ts +25 -0
  2. package/dist/components/AutoScrollContainer.vue.d.ts +31 -0
  3. package/dist/components/Incremark.vue.d.ts +30 -0
  4. package/dist/components/IncremarkBlockquote.vue.d.ts +6 -0
  5. package/dist/components/IncremarkCode.vue.d.ts +16 -0
  6. package/dist/components/IncremarkDefault.vue.d.ts +6 -0
  7. package/dist/components/IncremarkFootnotes.vue.d.ts +2 -0
  8. package/dist/components/IncremarkHeading.vue.d.ts +6 -0
  9. package/dist/components/IncremarkHtmlElement.vue.d.ts +20 -0
  10. package/dist/components/IncremarkInline.vue.d.ts +6 -0
  11. package/dist/components/IncremarkList.vue.d.ts +6 -0
  12. package/dist/components/IncremarkMath.vue.d.ts +17 -0
  13. package/dist/components/IncremarkParagraph.vue.d.ts +6 -0
  14. package/dist/components/IncremarkRenderer.vue.d.ts +6 -0
  15. package/dist/components/IncremarkTable.vue.d.ts +6 -0
  16. package/dist/components/IncremarkThematicBreak.vue.d.ts +2 -0
  17. package/{src/components/index.ts → dist/components/index.d.ts} +16 -23
  18. package/dist/composables/index.d.ts +8 -0
  19. package/dist/composables/useBlockTransformer.d.ts +68 -0
  20. package/dist/composables/useDefinationsContext.d.ts +9 -0
  21. package/dist/composables/useDevTools.d.ts +18 -0
  22. package/dist/composables/useIncremark.d.ts +112 -0
  23. package/dist/composables/useProvideDefinations.d.ts +16 -0
  24. package/dist/composables/useStreamRenderer.d.ts +26 -0
  25. package/dist/composables/useTypewriter.d.ts +37 -0
  26. package/dist/index.d.ts +10 -0
  27. package/dist/index.js +1 -2
  28. package/dist/index.js.map +1 -1
  29. package/dist/utils/cursor.d.ts +18 -0
  30. package/package.json +11 -13
  31. package/dist/index.css +0 -6
  32. package/dist/index.css.map +0 -1
  33. package/src/ThemeProvider.vue +0 -41
  34. package/src/components/AutoScrollContainer.vue +0 -164
  35. package/src/components/Incremark.vue +0 -131
  36. package/src/components/IncremarkBlockquote.vue +0 -18
  37. package/src/components/IncremarkCode.vue +0 -236
  38. package/src/components/IncremarkDefault.vue +0 -15
  39. package/src/components/IncremarkFootnotes.vue +0 -78
  40. package/src/components/IncremarkHeading.vue +0 -17
  41. package/src/components/IncremarkHtmlElement.vue +0 -127
  42. package/src/components/IncremarkInline.vue +0 -187
  43. package/src/components/IncremarkList.vue +0 -46
  44. package/src/components/IncremarkMath.vue +0 -105
  45. package/src/components/IncremarkParagraph.vue +0 -14
  46. package/src/components/IncremarkRenderer.vue +0 -50
  47. package/src/components/IncremarkTable.vue +0 -42
  48. package/src/components/IncremarkThematicBreak.vue +0 -8
  49. package/src/composables/index.ts +0 -11
  50. package/src/composables/useBlockTransformer.ts +0 -141
  51. package/src/composables/useDefinationsContext.ts +0 -16
  52. package/src/composables/useDevTools.ts +0 -54
  53. package/src/composables/useIncremark.ts +0 -238
  54. package/src/composables/useProvideDefinations.ts +0 -61
  55. package/src/composables/useStreamRenderer.ts +0 -55
  56. package/src/composables/useTypewriter.ts +0 -205
  57. package/src/index.ts +0 -78
  58. package/src/utils/cursor.ts +0 -46
@@ -1,78 +0,0 @@
1
- <!--
2
- /**
3
- * 脚注列表组件
4
- *
5
- * 在文档底部渲染所有脚注定义,按引用出现的顺序排列
6
- *
7
- * @component IncremarkFootnotes
8
- *
9
- * @remarks
10
- * 样式定义在 @incremark/theme 中的 footnotes.less
11
- * footnoteReferenceOrder 自动从 context 获取,无需手动传递
12
- */
13
- -->
14
- <script setup lang="ts">
15
- import { computed } from 'vue'
16
- import type { FootnoteDefinition, RootContent } from 'mdast'
17
- import { useDefinationsContext } from '../composables/useDefinationsContext'
18
- import IncremarkRenderer from './IncremarkRenderer.vue'
19
-
20
- const { definations, footnoteDefinitions, footnoteReferenceOrder } = useDefinationsContext()
21
-
22
- /**
23
- * 按引用顺序排列的脚注列表
24
- * 只显示已有定义的脚注
25
- */
26
- const orderedFootnotes = computed<Array<{ identifier: string; definition: FootnoteDefinition }>>(() => {
27
- return footnoteReferenceOrder.value
28
- .map(identifier => ({
29
- identifier,
30
- definition: footnoteDefinitions.value[identifier]
31
- }))
32
- .filter(item => item.definition !== undefined)
33
- })
34
-
35
- /**
36
- * 是否有脚注需要显示
37
- */
38
- const hasFootnotes = computed(() => orderedFootnotes.value.length > 0)
39
- </script>
40
-
41
- <template>
42
- <section v-if="hasFootnotes" class="incremark-footnotes">
43
- <hr class="incremark-footnotes-divider" />
44
- <ol class="incremark-footnotes-list">
45
- <li
46
- v-for="(item, index) in orderedFootnotes"
47
- :key="item.identifier"
48
- :id="`fn-${item.identifier}`"
49
- class="incremark-footnote-item"
50
- >
51
- <div class="incremark-footnote-content">
52
- <!-- 脚注序号 -->
53
- <span class="incremark-footnote-number">{{ index + 1 }}.</span>
54
-
55
- <!-- 脚注内容 -->
56
- <div class="incremark-footnote-body">
57
- <IncremarkRenderer
58
- v-for="(child, childIndex) in item.definition.children"
59
- :key="childIndex"
60
- :node="(child as RootContent)"
61
- />
62
- </div>
63
- </div>
64
-
65
- <!-- 返回链接 -->
66
- <a
67
- :href="`#fnref-${item.identifier}`"
68
- class="incremark-footnote-backref"
69
- aria-label="返回引用位置"
70
- >
71
-
72
- </a>
73
- </li>
74
- </ol>
75
- </section>
76
- </template>
77
-
78
-
@@ -1,17 +0,0 @@
1
- <script setup lang="ts">
2
- import type { Heading } from 'mdast'
3
- import { computed } from 'vue'
4
- import IncremarkInline from './IncremarkInline.vue'
5
-
6
- const props = defineProps<{
7
- node: Heading
8
- }>()
9
-
10
- const tag = computed(() => `h${props.node.depth}`)
11
- </script>
12
-
13
- <template>
14
- <component :is="tag" :class="`incremark-heading h${node.depth}`">
15
- <IncremarkInline :nodes="node.children" />
16
- </component>
17
- </template>
@@ -1,127 +0,0 @@
1
- <script setup lang="ts">
2
- import type { RootContent, PhrasingContent } from 'mdast'
3
- import IncremarkInline from './IncremarkInline.vue'
4
-
5
- /**
6
- * HtmlElementNode 类型定义(与 @incremark/core 中的定义一致)
7
- */
8
- interface HtmlElementNode {
9
- type: 'htmlElement'
10
- tagName: string
11
- attrs: Record<string, string>
12
- children: RootContent[]
13
- data?: {
14
- rawHtml?: string
15
- parsed?: boolean
16
- originalType?: string
17
- }
18
- }
19
-
20
- defineProps<{
21
- node: HtmlElementNode
22
- }>()
23
-
24
- /**
25
- * 判断是否是行内元素
26
- */
27
- function isInlineElement(tagName: string): boolean {
28
- const inlineElements = [
29
- 'a', 'abbr', 'acronym', 'b', 'bdo', 'big', 'br', 'button', 'cite',
30
- 'code', 'dfn', 'em', 'i', 'img', 'input', 'kbd', 'label', 'map',
31
- 'object', 'output', 'q', 'samp', 'script', 'select', 'small',
32
- 'span', 'strong', 'sub', 'sup', 'textarea', 'time', 'tt', 'var'
33
- ]
34
- return inlineElements.includes(tagName.toLowerCase())
35
- }
36
-
37
- /**
38
- * 判断是否是自闭合元素
39
- */
40
- function isVoidElement(tagName: string): boolean {
41
- const voidElements = [
42
- 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
43
- 'link', 'meta', 'param', 'source', 'track', 'wbr'
44
- ]
45
- return voidElements.includes(tagName.toLowerCase())
46
- }
47
-
48
- /**
49
- * 判断子节点是否都是行内内容
50
- */
51
- function hasOnlyInlineChildren(children: RootContent[]): boolean {
52
- if (!children || children.length === 0) return true
53
-
54
- return children.every(child => {
55
- const type = child.type
56
- // 常见的行内类型
57
- const inlineTypes = ['text', 'strong', 'emphasis', 'inlineCode', 'link', 'image', 'break', 'html', 'htmlElement']
58
- if (inlineTypes.includes(type)) {
59
- // 如果是 htmlElement,检查是否是行内元素
60
- if (type === 'htmlElement') {
61
- return isInlineElement((child as unknown as HtmlElementNode).tagName)
62
- }
63
- return true
64
- }
65
- return false
66
- })
67
- }
68
-
69
- /**
70
- * 将属性对象转换为 HTML 属性字符串(用于 v-bind)
71
- */
72
- function getAttrs(attrs: Record<string, string>): Record<string, string> {
73
- // 过滤掉可能有问题的属性
74
- const result: Record<string, string> = {}
75
- for (const [key, value] of Object.entries(attrs)) {
76
- // 跳过事件属性(已在解析时过滤,这里双重保险)
77
- if (key.startsWith('on')) continue
78
- result[key] = value
79
- }
80
- return result
81
- }
82
- </script>
83
-
84
- <template>
85
- <component
86
- :is="node.tagName"
87
- v-bind="getAttrs(node.attrs)"
88
- :class="['incremark-html-element', `incremark-${node.tagName}`]"
89
- >
90
- <!-- 自闭合元素没有子节点 -->
91
- <template v-if="!isVoidElement(node.tagName)">
92
- <!-- 如果子节点都是行内内容,使用 IncremarkInline -->
93
- <template v-if="hasOnlyInlineChildren(node.children)">
94
- <IncremarkInline :nodes="(node.children as PhrasingContent[])" />
95
- </template>
96
-
97
- <!-- 否则递归渲染每个子节点 -->
98
- <template v-else>
99
- <template v-for="(child, idx) in node.children" :key="idx">
100
- <!-- 如果子节点是 htmlElement,递归 -->
101
- <IncremarkHtmlElement
102
- v-if="child.type === 'htmlElement'"
103
- :node="(child as unknown as HtmlElementNode)"
104
- />
105
- <!-- 如果是文本节点 -->
106
- <template v-else-if="child.type === 'text'">
107
- {{ (child as any).value }}
108
- </template>
109
- <!-- 其他类型尝试用 IncremarkInline -->
110
- <IncremarkInline
111
- v-else-if="['strong', 'emphasis', 'inlineCode', 'link', 'image', 'break'].includes(child.type)"
112
- :nodes="[child as PhrasingContent]"
113
- />
114
- <!-- 段落等块级元素 -->
115
- <template v-else-if="child.type === 'paragraph'">
116
- <p><IncremarkInline :nodes="((child as any).children as PhrasingContent[])" /></p>
117
- </template>
118
- <!-- 其他未知类型,显示原始 -->
119
- <template v-else>
120
- <div class="incremark-unknown-child">{{ child.type }}</div>
121
- </template>
122
- </template>
123
- </template>
124
- </template>
125
- </component>
126
- </template>
127
-
@@ -1,187 +0,0 @@
1
- <script setup lang="ts">
2
- import type { PhrasingContent, RootContent, ImageReference, LinkReference } from 'mdast'
3
- import type { TextChunk } from '@incremark/core'
4
- import {
5
- type TextNodeWithChunks,
6
- hasChunks,
7
- getStableText,
8
- isHtmlNode
9
- } from '@incremark/shared'
10
- import IncremarkMath from './IncremarkMath.vue'
11
- import IncremarkHtmlElement from './IncremarkHtmlElement.vue'
12
- import { useDefinationsContext } from '../composables/useDefinationsContext'
13
-
14
- // Math 节点类型
15
- interface MathNode {
16
- type: 'math' | 'inlineMath'
17
- value: string
18
- }
19
-
20
- // HtmlElement 节点类型
21
- interface HtmlElementNode {
22
- type: 'htmlElement'
23
- tagName: string
24
- attrs: Record<string, string>
25
- children: RootContent[]
26
- }
27
-
28
- /**
29
- * 类型守卫:检查是否是 htmlElement 节点
30
- */
31
- function isHtmlElementNode(node: PhrasingContent): node is PhrasingContent & HtmlElementNode {
32
- return (node as unknown as HtmlElementNode).type === 'htmlElement'
33
- }
34
-
35
- /**
36
- * 类型守卫:检查是否是 imageReference 节点
37
- */
38
- function isImageReference(node: PhrasingContent): node is ImageReference {
39
- return node.type === 'imageReference'
40
- }
41
-
42
- /**
43
- * 类型守卫:检查是否是 linkReference 节点
44
- */
45
- function isLinkReference(node: PhrasingContent): node is LinkReference {
46
- return node.type === 'linkReference'
47
- }
48
-
49
- const props = defineProps<{
50
- nodes: PhrasingContent[]
51
- }>()
52
-
53
- const {
54
- definations,
55
- footnoteDefinitions
56
- } = useDefinationsContext()
57
-
58
- /**
59
- * 获取节点的 chunks(类型安全)
60
- */
61
- function getChunks(node: PhrasingContent): TextChunk[] | undefined {
62
- if (hasChunks(node)) {
63
- return (node as TextNodeWithChunks).chunks
64
- }
65
- return undefined
66
- }
67
-
68
- /**
69
- * 类型守卫:检查是否是 inlineMath 节点
70
- * inlineMath 是 mdast-util-math 扩展的类型,不在标准 PhrasingContent 中
71
- */
72
- function isInlineMath(node: PhrasingContent): node is PhrasingContent & MathNode {
73
- return (node as unknown as MathNode).type === 'inlineMath'
74
- }
75
-
76
- </script>
77
-
78
- <template>
79
- <template v-for="(node, idx) in nodes" :key="idx">
80
- <!-- 文本(支持 chunks 渐入动画) -->
81
- <template v-if="node.type === 'text'">
82
- <!-- 稳定文本(已经显示过的部分,无动画) -->
83
- {{ getStableText(node as TextNodeWithChunks) }}
84
- <!-- 新增的 chunk 部分(带渐入动画) -->
85
- <span
86
- v-for="chunk in getChunks(node)"
87
- :key="chunk.createdAt"
88
- class="incremark-fade-in"
89
- >{{ chunk.text }}</span>
90
- </template>
91
-
92
- <!-- 行内公式 -->
93
- <IncremarkMath v-else-if="isInlineMath(node)" :node="(node as unknown as MathNode)" />
94
-
95
- <!-- htmlElement 节点(结构化的 HTML 元素) -->
96
- <IncremarkHtmlElement
97
- v-else-if="isHtmlElementNode(node)"
98
- :node="(node as unknown as HtmlElementNode)"
99
- />
100
-
101
- <!-- HTML 节点(原始 HTML,如未启用 htmlTree 选项) -->
102
- <span v-else-if="isHtmlNode(node)" style="display: contents;" v-html="(node as any).value"></span>
103
-
104
- <!-- 加粗 -->
105
- <strong v-else-if="node.type === 'strong'">
106
- <IncremarkInline :nodes="(node.children as PhrasingContent[])" />
107
- </strong>
108
-
109
- <!-- 斜体 -->
110
- <em v-else-if="node.type === 'emphasis'">
111
- <IncremarkInline :nodes="(node.children as PhrasingContent[])" />
112
- </em>
113
-
114
- <!-- 行内代码 -->
115
- <code v-else-if="node.type === 'inlineCode'" class="incremark-inline-code">{{ (node as any).value }}</code>
116
-
117
- <!-- 链接 -->
118
- <a
119
- v-else-if="node.type === 'link'"
120
- class="incremark-link"
121
- :href="node.url"
122
- target="_blank"
123
- rel="noopener noreferrer"
124
- >
125
- <IncremarkInline :nodes="(node.children as PhrasingContent[])" />
126
- </a>
127
-
128
- <!-- 图片 -->
129
- <img
130
- v-else-if="node.type === 'image'"
131
- class="incremark-image"
132
- :src="node.url"
133
- :alt="node.alt || ''"
134
- :title="(node as any).title || undefined"
135
- loading="lazy"
136
- />
137
-
138
- <!-- 引用式图片(imageReference) -->
139
- <template v-else-if="isImageReference(node)">
140
- <img
141
- v-if="definations[node.identifier]"
142
- class="incremark-image incremark-reference-image"
143
- :src="definations[node.identifier].url"
144
- :alt="(node as ImageReference).alt || ''"
145
- :title="definations[node.identifier].title || undefined"
146
- loading="lazy"
147
- />
148
- <!-- 如果没有找到定义,渲染为原始文本(降级处理) -->
149
- <span v-else class="incremark-image-ref-missing">
150
- ![{{ (node as ImageReference).alt }}][{{ (node as ImageReference).identifier || (node as ImageReference).label }}]
151
- </span>
152
- </template>
153
-
154
- <!-- 引用式链接(linkReference) -->
155
- <template v-else-if="isLinkReference(node)">
156
- <a
157
- v-if="definations[node.identifier]"
158
- class="incremark-link incremark-reference-link"
159
- :href="definations[node.identifier].url"
160
- :title="definations[node.identifier].title || undefined"
161
- target="_blank"
162
- rel="noopener noreferrer"
163
- >
164
- <IncremarkInline :nodes="((node as LinkReference).children as PhrasingContent[])" />
165
- </a>
166
- <!-- 如果没有找到定义,渲染为原始文本(降级处理) -->
167
- <span v-else class="incremark-link-ref-missing">
168
- [{{ ((node as LinkReference).children as any[]).map((c: any) => c.value).join('') }}][{{ (node as LinkReference).identifier || (node as LinkReference).label }}]
169
- </span>
170
- </template>
171
-
172
- <!-- 脚注引用(footnoteReference) -->
173
- <sup v-else-if="node.type === 'footnoteReference'" class="incremark-footnote-ref">
174
- <a :href="`#fn-${(node as any).identifier}`" :id="`fnref-${(node as any).identifier}`">
175
- [{{ (node as any).identifier }}]
176
- </a>
177
- </sup>
178
-
179
- <!-- 换行 -->
180
- <br v-else-if="node.type === 'break'" />
181
-
182
- <!-- 删除线 -->
183
- <del v-else-if="node.type === 'delete'">
184
- <IncremarkInline :nodes="(node.children as PhrasingContent[])" />
185
- </del>
186
- </template>
187
- </template>
@@ -1,46 +0,0 @@
1
- <script setup lang="ts">
2
- import type { List, ListItem, PhrasingContent } from 'mdast'
3
- import { computed } from 'vue'
4
- import IncremarkInline from './IncremarkInline.vue'
5
-
6
- const props = defineProps<{
7
- node: List
8
- }>()
9
-
10
- const tag = computed(() => props.node.ordered ? 'ol' : 'ul')
11
-
12
- function getItemContent(item: ListItem): PhrasingContent[] {
13
- const firstChild = item.children[0]
14
- if (firstChild?.type === 'paragraph') {
15
- return firstChild.children as PhrasingContent[]
16
- }
17
- return []
18
- }
19
- </script>
20
-
21
- <template>
22
- <component :is="tag" class="incremark-list" :class="{ 'task-list': node.children.some(item => item.checked !== null && item.checked !== undefined) }">
23
- <li
24
- v-for="(item, index) in node.children"
25
- :key="index"
26
- class="incremark-list-item"
27
- :class="{ 'task-item': item.checked !== null && item.checked !== undefined }"
28
- >
29
- <label v-if="item.checked !== null && item.checked !== undefined" class="task-label">
30
- <input
31
- type="checkbox"
32
- :checked="item.checked"
33
- disabled
34
- class="checkbox"
35
- />
36
- <span class="task-content">
37
- <IncremarkInline :nodes="getItemContent(item)" />
38
- </span>
39
- </label>
40
- <template v-else>
41
- <IncremarkInline :nodes="getItemContent(item)" />
42
- </template>
43
- </li>
44
- </component>
45
- </template>
46
-
@@ -1,105 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed, ref, watch, shallowRef, onUnmounted } from 'vue'
3
-
4
- // Math 节点类型(来自 mdast-util-math)
5
- interface MathNode {
6
- type: 'math' | 'inlineMath'
7
- value: string
8
- data?: {
9
- hName?: string
10
- hProperties?: Record<string, any>
11
- }
12
- }
13
-
14
- const props = withDefaults(
15
- defineProps<{
16
- node: MathNode
17
- /** 渲染延迟(毫秒),用于流式输入时防抖 */
18
- renderDelay?: number
19
- }>(),
20
- {
21
- renderDelay: 300
22
- }
23
- )
24
-
25
- const renderedHtml = ref('')
26
- const renderError = ref('')
27
- const isLoading = ref(false)
28
- const katexRef = shallowRef<any>(null)
29
- let renderTimer: ReturnType<typeof setTimeout> | null = null
30
-
31
- const isInline = computed(() => props.node.type === 'inlineMath')
32
- const formula = computed(() => props.node.value)
33
-
34
- // 带防抖动的渲染
35
- function scheduleRender() {
36
- if (!formula.value) {
37
- renderedHtml.value = ''
38
- return
39
- }
40
-
41
- // 清除之前的定时器
42
- if (renderTimer) {
43
- clearTimeout(renderTimer)
44
- }
45
-
46
- isLoading.value = true
47
-
48
- // 防抖动延迟渲染
49
- renderTimer = setTimeout(() => {
50
- doRender()
51
- }, props.renderDelay)
52
- }
53
-
54
- async function doRender() {
55
- if (!formula.value) return
56
-
57
- try {
58
- // 动态导入 KaTeX
59
- if (!katexRef.value) {
60
- // @ts-ignore - katex 是可选依赖
61
- const katexModule = await import('katex')
62
- katexRef.value = katexModule.default
63
- }
64
-
65
- const katex = katexRef.value
66
- renderedHtml.value = katex.renderToString(formula.value, {
67
- displayMode: !isInline.value,
68
- throwOnError: false,
69
- strict: false
70
- })
71
- renderError.value = ''
72
- } catch (e: any) {
73
- // 静默失败,可能是公式不完整
74
- renderError.value = ''
75
- renderedHtml.value = ''
76
- } finally {
77
- isLoading.value = false
78
- }
79
- }
80
-
81
- onUnmounted(() => {
82
- if (renderTimer) {
83
- clearTimeout(renderTimer)
84
- }
85
- })
86
-
87
- watch(formula, scheduleRender, { immediate: true })
88
- </script>
89
-
90
- <template>
91
- <!-- 行内公式 -->
92
- <span v-if="isInline" class="incremark-math-inline">
93
- <!-- 渲染成功 -->
94
- <span v-if="renderedHtml && !isLoading" v-html="renderedHtml" />
95
- <!-- 加载中或未渲染:显示源码 -->
96
- <code v-else class="math-source">{{ formula }}</code>
97
- </span>
98
- <!-- 块级公式 -->
99
- <div v-else class="incremark-math-block">
100
- <!-- 渲染成功 -->
101
- <div v-if="renderedHtml && !isLoading" v-html="renderedHtml" class="math-rendered" />
102
- <!-- 加载中或未渲染:显示源码 -->
103
- <pre v-else class="math-source-block"><code>{{ formula }}</code></pre>
104
- </div>
105
- </template>
@@ -1,14 +0,0 @@
1
- <script setup lang="ts">
2
- import type { Paragraph } from 'mdast'
3
- import IncremarkInline from './IncremarkInline.vue'
4
-
5
- defineProps<{
6
- node: Paragraph
7
- }>()
8
- </script>
9
-
10
- <template>
11
- <p class="incremark-paragraph">
12
- <IncremarkInline :nodes="node.children" />
13
- </p>
14
- </template>
@@ -1,50 +0,0 @@
1
- <script setup lang="ts">
2
- import type { RootContent, HTML } from 'mdast'
3
- import type { Component } from 'vue'
4
- import IncremarkHeading from './IncremarkHeading.vue'
5
- import IncremarkParagraph from './IncremarkParagraph.vue'
6
- import IncremarkCode from './IncremarkCode.vue'
7
- import IncremarkList from './IncremarkList.vue'
8
- import IncremarkTable from './IncremarkTable.vue'
9
- import IncremarkBlockquote from './IncremarkBlockquote.vue'
10
- import IncremarkThematicBreak from './IncremarkThematicBreak.vue'
11
- import IncremarkMath from './IncremarkMath.vue'
12
- import IncremarkHtmlElement from './IncremarkHtmlElement.vue'
13
- import IncremarkDefault from './IncremarkDefault.vue'
14
-
15
- const props = defineProps<{
16
- node: RootContent
17
- }>()
18
-
19
- const componentMap: Record<string, Component> = {
20
- heading: IncremarkHeading,
21
- paragraph: IncremarkParagraph,
22
- code: IncremarkCode,
23
- list: IncremarkList,
24
- table: IncremarkTable,
25
- blockquote: IncremarkBlockquote,
26
- thematicBreak: IncremarkThematicBreak,
27
- math: IncremarkMath,
28
- inlineMath: IncremarkMath,
29
- htmlElement: IncremarkHtmlElement,
30
- }
31
-
32
- function getComponent(type: string): Component {
33
- return componentMap[type] || IncremarkDefault
34
- }
35
-
36
- /**
37
- * 检查是否是 html 节点
38
- */
39
- function isHtmlNode(node: RootContent): node is HTML {
40
- return node.type === 'html'
41
- }
42
- </script>
43
-
44
- <template>
45
- <!-- HTML 节点:渲染为代码块显示源代码 -->
46
- <pre v-if="isHtmlNode(node)" class="incremark-html-code"><code>{{ (node as HTML).value }}</code></pre>
47
- <!-- 其他节点:使用对应组件 -->
48
- <component v-else :is="getComponent(node.type)" :node="node" />
49
- </template>
50
-
@@ -1,42 +0,0 @@
1
- <script setup lang="ts">
2
- import type { Table, TableCell, PhrasingContent } from 'mdast'
3
- import IncremarkInline from './IncremarkInline.vue'
4
-
5
- defineProps<{
6
- node: Table
7
- }>()
8
-
9
- function getCellContent(cell: TableCell): PhrasingContent[] {
10
- return cell.children as PhrasingContent[]
11
- }
12
- </script>
13
-
14
- <template>
15
- <div class="incremark-table-wrapper">
16
- <table class="incremark-table">
17
- <thead>
18
- <tr v-if="node.children[0]">
19
- <th
20
- v-for="(cell, cellIndex) in node.children[0].children"
21
- :key="cellIndex"
22
- :style="{ textAlign: node.align?.[cellIndex] || 'left' }"
23
- >
24
- <IncremarkInline :nodes="getCellContent(cell)" />
25
- </th>
26
- </tr>
27
- </thead>
28
- <tbody>
29
- <tr v-for="(row, rowIndex) in node.children.slice(1)" :key="rowIndex">
30
- <td
31
- v-for="(cell, cellIndex) in row.children"
32
- :key="cellIndex"
33
- :style="{ textAlign: node.align?.[cellIndex] || 'left' }"
34
- >
35
- <IncremarkInline :nodes="getCellContent(cell)" />
36
- </td>
37
- </tr>
38
- </tbody>
39
- </table>
40
- </div>
41
- </template>
42
-
@@ -1,8 +0,0 @@
1
- <script setup lang="ts">
2
- // ThematicBreak 不需要 props
3
- </script>
4
-
5
- <template>
6
- <hr class="incremark-hr" />
7
- </template>
8
-
@@ -1,11 +0,0 @@
1
- export { useIncremark } from './useIncremark'
2
- export type { UseIncremarkOptions, TypewriterOptions, TypewriterControls } from './useIncremark'
3
-
4
- export { useStreamRenderer } from './useStreamRenderer'
5
- export type { UseStreamRendererOptions } from './useStreamRenderer'
6
-
7
- export { useDevTools } from './useDevTools'
8
- export type { UseDevToolsOptions } from './useDevTools'
9
-
10
- export { useBlockTransformer } from './useBlockTransformer'
11
- export type { UseBlockTransformerOptions, UseBlockTransformerReturn } from './useBlockTransformer'