@incremark/svelte 0.2.3 → 0.2.4

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.
@@ -5,11 +5,12 @@
5
5
 
6
6
  <script lang="ts">
7
7
  import { onMount, onDestroy } from 'svelte'
8
+ import type { HTMLAttributes } from 'svelte/elements';
8
9
 
9
10
  /**
10
11
  * 组件 Props
11
12
  */
12
- interface Props {
13
+ interface Props extends HTMLAttributes<HTMLDivElement>{
13
14
  /** 是否启用自动滚动 */
14
15
  enabled?: boolean
15
16
  /** 触发自动滚动的底部阈值(像素) */
@@ -1,7 +1,8 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
1
2
  /**
2
3
  * 组件 Props
3
4
  */
4
- interface Props {
5
+ interface Props extends HTMLAttributes<HTMLDivElement> {
5
6
  /** 是否启用自动滚动 */
6
7
  enabled?: boolean;
7
8
  /** 触发自动滚动的底部阈值(像素) */
@@ -1 +1 @@
1
- {"version":3,"file":"AutoScrollContainer.svelte.d.ts","sourceRoot":"","sources":["../../src/components/AutoScrollContainer.svelte.ts"],"names":[],"mappings":"AAME;;GAEG;AACH,UAAU,KAAK;IACb,eAAe;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW;IACX,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,UAAU;IACV,QAAQ,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAA;CACpC;AAmJH,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"AutoScrollContainer.svelte.d.ts","sourceRoot":"","sources":["../../src/components/AutoScrollContainer.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD;;GAEG;AACH,UAAU,KAAM,SAAQ,cAAc,CAAC,cAAc,CAAC;IACpD,eAAe;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW;IACX,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,UAAU;IACV,QAAQ,CAAC,EAAE,OAAO,QAAQ,EAAE,OAAO,CAAA;CACpC;AAoJH,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
@@ -4,8 +4,9 @@
4
4
  -->
5
5
 
6
6
  <script lang="ts">
7
+ import type { Component } from 'svelte'
7
8
  import type { Readable } from 'svelte/store'
8
- import type { ParsedBlock, RootContent } from '@incremark/core'
9
+ import type { RootContent } from '@incremark/core'
9
10
  import type { HTML } from 'mdast'
10
11
 
11
12
  import { getDefinitionsContext } from '../context/definitionsContext'
@@ -24,6 +25,7 @@
24
25
  import IncremarkHtmlElement from './IncremarkHtmlElement.svelte'
25
26
  import IncremarkDefault from './IncremarkDefault.svelte'
26
27
  import IncremarkFootnotes from './IncremarkFootnotes.svelte'
28
+ import IncremarkRenderer from './IncremarkRenderer.svelte'
27
29
 
28
30
  /**
29
31
  * 检查是否是 html 节点
@@ -40,6 +42,10 @@
40
42
  blocks?: BlockWithStableId[] | Readable<BlockWithStableId[]>
41
43
  /** 自定义组件映射,key 为节点类型 */
42
44
  components?: ComponentMap
45
+ /** 自定义容器组件映射,key 为容器名称(如 'warning', 'info') */
46
+ customContainers?: Record<string, Component<any>>
47
+ /** 自定义代码块组件映射,key 为代码语言名称(如 'echart', 'mermaid') */
48
+ customCodeBlocks?: Record<string, Component<any>>
43
49
  /** 待处理块的样式类名 */
44
50
  pendingClass?: string
45
51
  /** 已完成块的样式类名 */
@@ -53,6 +59,8 @@
53
59
  let {
54
60
  blocks = [],
55
61
  components = {},
62
+ customContainers = {},
63
+ customCodeBlocks = {},
56
64
  pendingClass = 'incremark-pending',
57
65
  completedClass = 'incremark-completed',
58
66
  showBlockStatus = false,
@@ -102,13 +110,6 @@
102
110
  ...components
103
111
  })
104
112
 
105
- /**
106
- * 获取组件
107
- */
108
- function getComponent(type: string): any {
109
- return mergedComponents[type] || components?.default || IncremarkDefault
110
- }
111
-
112
113
  // 处理 blocks(可能是 store 或数组)
113
114
  const blocksArray = $derived.by(() => {
114
115
  if (incremark) {
@@ -132,16 +133,13 @@
132
133
  <div
133
134
  class="incremark-block {block.status === 'completed' ? completedClass : pendingClass} {showBlockStatus ? 'incremark-show-status' : ''} {(block as BlockWithStableId).isLastPending ? 'incremark-last-pending' : ''}"
134
135
  >
135
- <!-- HTML 节点:渲染为代码块显示源代码 -->
136
- {#if isHtmlNode(block.node)}
137
- <pre class="incremark-html-code"><code>{block.node.value}</code></pre>
138
- {:else}
139
- <!-- 其他节点:使用对应组件 -->
140
- {@const Component = getComponent(block.node.type)}
141
- {#if Component}
142
- <Component node={block.node} />
143
- {/if}
144
- {/if}
136
+ <!-- 使用 IncremarkRenderer,传递 customContainers 和 customCodeBlocks -->
137
+ <IncremarkRenderer
138
+ node={block.node}
139
+ customContainers={customContainers}
140
+ customCodeBlocks={customCodeBlocks}
141
+ blockStatus={block.status}
142
+ />
145
143
  </div>
146
144
  {/if}
147
145
  {/each}
@@ -152,16 +150,13 @@
152
150
  <div
153
151
  class="incremark-block {block.status === 'completed' ? completedClass : pendingClass} {showBlockStatus ? 'incremark-show-status' : ''} {block.isLastPending ? 'incremark-last-pending' : ''}"
154
152
  >
155
- <!-- HTML 节点:渲染为代码块显示源代码 -->
156
- {#if isHtmlNode(block.node)}
157
- <pre class="incremark-html-code"><code>{block.node.value}</code></pre>
158
- {:else}
159
- <!-- 其他节点:使用对应组件 -->
160
- {@const Component = getComponent(block.node.type)}
161
- {#if Component}
162
- <Component node={block.node} />
163
- {/if}
164
- {/if}
153
+ <!-- 使用 IncremarkRenderer,传递 customContainers 和 customCodeBlocks -->
154
+ <IncremarkRenderer
155
+ node={block.node}
156
+ customContainers={customContainers}
157
+ customCodeBlocks={customCodeBlocks}
158
+ blockStatus={block.status}
159
+ />
165
160
  </div>
166
161
  {/if}
167
162
  {/each}
@@ -1,3 +1,4 @@
1
+ import type { Component } from 'svelte';
1
2
  import type { Readable } from 'svelte/store';
2
3
  import type { UseIncremarkReturn } from '../stores/useIncremark';
3
4
  import type { ComponentMap, BlockWithStableId } from './types';
@@ -9,6 +10,10 @@ interface Props {
9
10
  blocks?: BlockWithStableId[] | Readable<BlockWithStableId[]>;
10
11
  /** 自定义组件映射,key 为节点类型 */
11
12
  components?: ComponentMap;
13
+ /** 自定义容器组件映射,key 为容器名称(如 'warning', 'info') */
14
+ customContainers?: Record<string, Component<any>>;
15
+ /** 自定义代码块组件映射,key 为代码语言名称(如 'echart', 'mermaid') */
16
+ customCodeBlocks?: Record<string, Component<any>>;
12
17
  /** 待处理块的样式类名 */
13
18
  pendingClass?: string;
14
19
  /** 已完成块的样式类名 */
@@ -18,7 +23,7 @@ interface Props {
18
23
  /** 可选:useIncremark 返回的对象(用于自动注入数据) */
19
24
  incremark?: UseIncremarkReturn;
20
25
  }
21
- declare const Incremark: import("svelte").Component<Props, {}, "">;
26
+ declare const Incremark: Component<Props, {}, "">;
22
27
  type Incremark = ReturnType<typeof Incremark>;
23
28
  export default Incremark;
24
29
  //# sourceMappingURL=Incremark.svelte.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Incremark.svelte.d.ts","sourceRoot":"","sources":["../../src/components/Incremark.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAK5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAe5D;;GAEG;AACH,UAAU,KAAK;IACb,wCAAwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,EAAE,GAAG,QAAQ,CAAC,iBAAiB,EAAE,CAAC,CAAA;IAC5D,wBAAwB;IACxB,UAAU,CAAC,EAAE,YAAY,CAAA;IACzB,gBAAgB;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,gBAAgB;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,sCAAsC;IACtC,SAAS,CAAC,EAAE,kBAAkB,CAAA;CAC/B;AAmKH,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"Incremark.svelte.d.ts","sourceRoot":"","sources":["../../src/components/Incremark.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAK5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAgB5D;;GAEG;AACH,UAAU,KAAK;IACb,wCAAwC;IACxC,MAAM,CAAC,EAAE,iBAAiB,EAAE,GAAG,QAAQ,CAAC,iBAAiB,EAAE,CAAC,CAAA;IAC5D,wBAAwB;IACxB,UAAU,CAAC,EAAE,YAAY,CAAA;IACzB,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;IACjD,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;IACjD,gBAAgB;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,gBAAgB;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,sCAAsC;IACtC,SAAS,CAAC,EAAE,kBAAkB,CAAA;CAC/B;AAgJH,QAAA,MAAM,SAAS,0BAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -19,13 +19,19 @@
19
19
  disableHighlight?: boolean
20
20
  /** Mermaid 渲染延迟(毫秒),用于流式输入时防抖 */
21
21
  mermaidDelay?: number
22
+ /** 自定义代码块组件映射,key 为代码语言名称 */
23
+ customCodeBlocks?: Record<string, any>
24
+ /** 块状态,用于判断是否使用自定义组件 */
25
+ blockStatus?: 'pending' | 'stable' | 'completed'
22
26
  }
23
27
 
24
28
  let {
25
29
  node,
26
30
  theme = 'github-dark',
27
31
  disableHighlight = false,
28
- mermaidDelay = 500
32
+ mermaidDelay = 500,
33
+ customCodeBlocks,
34
+ blockStatus = 'completed'
29
35
  }: Props = $props()
30
36
 
31
37
  // 状态
@@ -55,6 +61,18 @@
55
61
  const code = $derived(node.value)
56
62
  const isMermaid = $derived(language === 'mermaid')
57
63
 
64
+ // 检查是否有自定义代码块组件
65
+ const CustomCodeBlock = $derived.by(() => {
66
+ // 如果代码块还在 pending 状态,不使用自定义组件
67
+ if (blockStatus === 'pending') {
68
+ return null
69
+ }
70
+ return customCodeBlocks?.[language] || null
71
+ })
72
+
73
+ // 是否使用自定义组件
74
+ const useCustomComponent = $derived(!!CustomCodeBlock)
75
+
58
76
  /**
59
77
  * 切换 Mermaid 视图模式
60
78
  */
@@ -210,8 +228,15 @@
210
228
  })
211
229
  </script>
212
230
 
231
+ <!-- 自定义代码块组件 -->
232
+ {#if useCustomComponent && CustomCodeBlock}
233
+ <svelte:component
234
+ this={CustomCodeBlock}
235
+ codeStr={code}
236
+ lang={language}
237
+ />
213
238
  <!-- Mermaid 图表 -->
214
- {#if isMermaid}
239
+ {:else if isMermaid}
215
240
  <div class="incremark-mermaid">
216
241
  <div class="mermaid-header">
217
242
  <span class="language">MERMAID</span>
@@ -11,6 +11,10 @@ interface Props {
11
11
  disableHighlight?: boolean;
12
12
  /** Mermaid 渲染延迟(毫秒),用于流式输入时防抖 */
13
13
  mermaidDelay?: number;
14
+ /** 自定义代码块组件映射,key 为代码语言名称 */
15
+ customCodeBlocks?: Record<string, any>;
16
+ /** 块状态,用于判断是否使用自定义组件 */
17
+ blockStatus?: 'pending' | 'stable' | 'completed';
14
18
  }
15
19
  declare const IncremarkCode: import("svelte").Component<Props, {}, "">;
16
20
  type IncremarkCode = ReturnType<typeof IncremarkCode>;
@@ -1 +1 @@
1
- {"version":3,"file":"IncremarkCode.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkCode.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAI/B;;GAEG;AACH,UAAU,KAAK;IACb,WAAW;IACX,IAAI,EAAE,IAAI,CAAA;IACV,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,eAAe;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAkQH,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"IncremarkCode.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkCode.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAI/B;;GAEG;AACH,UAAU,KAAK;IACb,WAAW;IACX,IAAI,EAAE,IAAI,CAAA;IACV,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,eAAe;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6BAA6B;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACtC,wBAAwB;IACxB,WAAW,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAA;CACjD;AAmRH,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
@@ -0,0 +1,83 @@
1
+ <!--
2
+ @file IncremarkContainer.svelte - 容器组件
3
+ @description 用于渲染自定义容器节点
4
+ -->
5
+
6
+ <script lang="ts">
7
+ import type { RootContent } from 'mdast'
8
+ import IncremarkRenderer from './IncremarkRenderer.svelte'
9
+
10
+ /**
11
+ * 容器节点类型定义
12
+ * 根据 directive 解析后的结构
13
+ */
14
+ export interface ContainerNode {
15
+ type: 'containerDirective' | 'leafDirective' | 'textDirective'
16
+ name: string
17
+ attributes?: Record<string, string>
18
+ children?: RootContent[]
19
+ }
20
+
21
+ /**
22
+ * 组件 Props
23
+ */
24
+ interface Props {
25
+ node: ContainerNode
26
+ customContainers?: Record<string, any>
27
+ }
28
+
29
+ let { node, customContainers = {} }: Props = $props()
30
+
31
+ /**
32
+ * 解析 attributes 字符串为对象
33
+ * directive 的 attributes 可能是字符串格式,需要解析
34
+ */
35
+ function parseOptions(attributes?: Record<string, string>): Record<string, any> {
36
+ if (!attributes) return {}
37
+
38
+ const options: Record<string, any> = {}
39
+ for (const [key, value] of Object.entries(attributes)) {
40
+ // 尝试解析 JSON 值
41
+ try {
42
+ options[key] = JSON.parse(value)
43
+ } catch {
44
+ // 如果不是 JSON,直接使用字符串值
45
+ options[key] = value
46
+ }
47
+ }
48
+ return options
49
+ }
50
+
51
+ const containerName = $derived(node.name)
52
+ const options = $derived(parseOptions(node.attributes))
53
+ const CustomContainer = $derived(customContainers?.[containerName])
54
+
55
+ // 如果没有自定义容器组件,使用默认渲染
56
+ const hasCustomContainer = $derived(!!CustomContainer)
57
+ </script>
58
+
59
+ {#if hasCustomContainer && CustomContainer}
60
+ <!-- 如果有自定义容器组件,使用自定义组件 -->
61
+ <CustomContainer
62
+ name={containerName}
63
+ options={options}
64
+ >
65
+ {#if node.children && node.children.length > 0}
66
+ {#each node.children as child, index (index)}
67
+ <IncremarkRenderer node={child} />
68
+ {/each}
69
+ {/if}
70
+ </CustomContainer>
71
+ {:else}
72
+ <!-- 如果没有自定义容器组件,使用默认渲染 -->
73
+ <div class="incremark-container incremark-container-{containerName}">
74
+ {#if node.children && node.children.length > 0}
75
+ <div class="incremark-container-content">
76
+ {#each node.children as child, index (index)}
77
+ <IncremarkRenderer node={child} />
78
+ {/each}
79
+ </div>
80
+ {/if}
81
+ </div>
82
+ {/if}
83
+
@@ -0,0 +1,22 @@
1
+ import type { RootContent } from 'mdast';
2
+ /**
3
+ * 容器节点类型定义
4
+ * 根据 directive 解析后的结构
5
+ */
6
+ export interface ContainerNode {
7
+ type: 'containerDirective' | 'leafDirective' | 'textDirective';
8
+ name: string;
9
+ attributes?: Record<string, string>;
10
+ children?: RootContent[];
11
+ }
12
+ /**
13
+ * 组件 Props
14
+ */
15
+ interface Props {
16
+ node: ContainerNode;
17
+ customContainers?: Record<string, any>;
18
+ }
19
+ declare const IncremarkContainer: import("svelte").Component<Props, {}, "">;
20
+ type IncremarkContainer = ReturnType<typeof IncremarkContainer>;
21
+ export default IncremarkContainer;
22
+ //# sourceMappingURL=IncremarkContainer.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IncremarkContainer.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkContainer.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAItC;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,oBAAoB,GAAG,eAAe,GAAG,eAAe,CAAA;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAA;CACzB;AAED;;GAEG;AACH,UAAU,KAAK;IACb,IAAI,EAAE,aAAa,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CACvC;AAgEH,QAAA,MAAM,kBAAkB,2CAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
@@ -9,19 +9,10 @@
9
9
  import { getDefinitionsContext } from '../context/definitionsContext'
10
10
  import IncremarkRenderer from './IncremarkRenderer.svelte'
11
11
 
12
- // 从 context 获取数据
13
- let definations: Readable<Record<string, any>> | null = null
14
- let footnoteDefinitions: Readable<Record<string, FootnoteDefinition>> | null = null
15
- let footnoteReferenceOrder: Readable<string[]> | null = null
16
12
 
17
- try {
18
- const context = getDefinitionsContext()
19
- definations = context.definations
20
- footnoteDefinitions = context.footnoteDefinitions
21
- footnoteReferenceOrder = context.footnoteReferenceOrder
22
- } catch {
23
- // Context 不存在
24
- }
13
+ const context = getDefinitionsContext()
14
+ const footnoteDefinitions = $derived(context?.footnoteDefinitions ?? {});
15
+ const footnoteReferenceOrder = $derived(context?.footnoteReferenceOrder ?? []);
25
16
 
26
17
  /**
27
18
  * 按引用顺序排列的脚注列表
@@ -1 +1 @@
1
- {"version":3,"file":"IncremarkFootnotes.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkFootnotes.svelte.ts"],"names":[],"mappings":"AAqFA,QAAA,MAAM,kBAAkB,2DAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"IncremarkFootnotes.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkFootnotes.svelte.ts"],"names":[],"mappings":"AA4EA,QAAA,MAAM,kBAAkB,2DAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
@@ -4,7 +4,6 @@
4
4
  -->
5
5
 
6
6
  <script lang="ts">
7
- import type { Readable } from 'svelte/store'
8
7
  import type { PhrasingContent, ImageReference, LinkReference } from 'mdast'
9
8
  import type { TextChunk } from '@incremark/core'
10
9
  import {
@@ -72,25 +71,9 @@
72
71
 
73
72
  // 获取 definitions context(可能不存在)
74
73
  // 使用 $derived 来确保响应式
75
- const definations = $derived.by(() => {
76
- try {
77
- const context = getDefinitionsContext()
78
- return context.definations
79
- } catch {
80
- // Context 不存在,返回 null
81
- return null
82
- }
83
- })
84
-
85
- const footnoteDefinitions = $derived.by(() => {
86
- try {
87
- const context = getDefinitionsContext()
88
- return context.footnoteDefinitions
89
- } catch {
90
- // Context 不存在,返回 null
91
- return null
92
- }
93
- })
74
+ const context = getDefinitionsContext()
75
+ const definations = $derived(context?.definations ?? {});
76
+
94
77
 
95
78
  /**
96
79
  * 获取节点的 chunks(类型安全)
@@ -173,7 +156,7 @@
173
156
 
174
157
  <!-- 引用式图片(imageReference) -->
175
158
  {#if isImageReference(node)}
176
- {#if definations && $definations[node.identifier]}
159
+ {#if $definations && $definations[node.identifier]}
177
160
  <img
178
161
  class="incremark-image incremark-reference-image"
179
162
  src={$definations[node.identifier].url}
@@ -191,7 +174,7 @@
191
174
 
192
175
  <!-- 引用式链接(linkReference) -->
193
176
  {#if isLinkReference(node)}
194
- {#if definations && $definations[node.identifier]}
177
+ {#if $definations && $definations[node.identifier]}
195
178
  <a
196
179
  class="incremark-link incremark-reference-link"
197
180
  href={$definations[node.identifier].url}
@@ -1 +1 @@
1
- {"version":3,"file":"IncremarkInline.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkInline.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAiC,MAAM,OAAO,CAAA;AAW3E,OAAO,eAAe,MAAM,0BAA0B,CAAC;AAGrD;;GAEG;AACH,UAAU,KAAK;IACb,aAAa;IACb,KAAK,EAAE,eAAe,EAAE,CAAA;CACzB;AAyMH,QAAA,MAAM,eAAe,2CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"IncremarkInline.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkInline.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAiC,MAAM,OAAO,CAAA;AAW3E,OAAO,eAAe,MAAM,0BAA0B,CAAC;AAGrD;;GAEG;AACH,UAAU,KAAK;IACb,aAAa;IACb,KAAK,EAAE,eAAe,EAAE,CAAA;CACzB;AAwLH,QAAA,MAAM,eAAe,2CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
@@ -1,11 +1,12 @@
1
1
  <!--
2
2
  @file IncremarkList.svelte - 列表组件
3
- @description 渲染 Markdown 列表(有序列表和无序列表),支持任务列表
3
+ @description 渲染 Markdown 列表(有序列表和无序列表),支持任务列表和嵌套列表
4
4
  -->
5
5
 
6
6
  <script lang="ts">
7
- import type { List, ListItem, PhrasingContent } from 'mdast'
7
+ import type { List, ListItem, PhrasingContent, BlockContent } from 'mdast'
8
8
  import IncremarkInline from './IncremarkInline.svelte'
9
+ import IncremarkList from './IncremarkList.svelte';
9
10
 
10
11
  /**
11
12
  * 组件 Props
@@ -30,12 +31,12 @@
30
31
  )
31
32
 
32
33
  /**
33
- * 获取列表项内容
34
- *
34
+ * 获取列表项的内联内容(来自第一个 paragraph)
35
+ *
35
36
  * @param item - 列表项节点
36
37
  * @returns 行内内容数组
37
38
  */
38
- function getItemContent(item: ListItem): PhrasingContent[] {
39
+ function getItemInlineContent(item: ListItem): PhrasingContent[] {
39
40
  const firstChild = item.children[0]
40
41
  if (firstChild?.type === 'paragraph') {
41
42
  return firstChild.children as PhrasingContent[]
@@ -43,9 +44,26 @@
43
44
  return []
44
45
  }
45
46
 
47
+ /**
48
+ * 获取列表项的块级子节点(嵌套列表、代码块等)
49
+ * 排除第一个 paragraph,因为它已经被 getItemInlineContent 处理
50
+ *
51
+ * @param item - 列表项节点
52
+ * @returns 块级子节点数组
53
+ */
54
+ function getItemBlockChildren(item: ListItem): BlockContent[] {
55
+ return item.children.filter((child, index) => {
56
+ // 第一个 paragraph 已经被处理为内联内容
57
+ if (index === 0 && child.type === 'paragraph') {
58
+ return false
59
+ }
60
+ return true
61
+ }) as BlockContent[]
62
+ }
63
+
46
64
  /**
47
65
  * 判断列表项是否是任务项
48
- *
66
+ *
49
67
  * @param item - 列表项节点
50
68
  * @returns 是否是任务项
51
69
  */
@@ -54,30 +72,37 @@
54
72
  }
55
73
  </script>
56
74
 
57
- <svelte:element
58
- this={tag}
75
+ <svelte:element
76
+ this={tag}
59
77
  class="incremark-list"
60
78
  class:task-list={isTaskList}
61
79
  >
62
80
  {#each node.children as item, index (index)}
63
- <li
81
+ <li
64
82
  class="incremark-list-item"
65
83
  class:task-item={isTaskItem(item)}
66
84
  >
67
85
  {#if isTaskItem(item)}
68
86
  <label class="task-label">
69
- <input
70
- type="checkbox"
71
- checked={item.checked}
72
- disabled
87
+ <input
88
+ type="checkbox"
89
+ checked={item.checked}
90
+ disabled
73
91
  class="checkbox"
74
92
  />
75
93
  <span class="task-content">
76
- <IncremarkInline nodes={getItemContent(item)} />
94
+ <IncremarkInline nodes={getItemInlineContent(item)} />
77
95
  </span>
78
96
  </label>
79
97
  {:else}
80
- <IncremarkInline nodes={getItemContent(item)} />
98
+ <IncremarkInline nodes={getItemInlineContent(item)} />
99
+ <!-- 递归渲染嵌套列表和其他块级内容 -->
100
+ {#each getItemBlockChildren(item) as child, childIndex (childIndex)}
101
+ {#if child.type === 'list'}
102
+ <IncremarkList node={child} />
103
+ {/if}
104
+ <!-- 其他块级内容可以在这里扩展 -->
105
+ {/each}
81
106
  {/if}
82
107
  </li>
83
108
  {/each}
@@ -1,4 +1,5 @@
1
1
  import type { List } from 'mdast';
2
+ import IncremarkList from './IncremarkList.svelte';
2
3
  /**
3
4
  * 组件 Props
4
5
  */
@@ -1 +1 @@
1
- {"version":3,"file":"IncremarkList.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkList.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAA6B,MAAM,OAAO,CAAA;AAI1D;;GAEG;AACH,UAAU,KAAK;IACb,WAAW;IACX,IAAI,EAAE,IAAI,CAAA;CACX;AAmEH,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"IncremarkList.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkList.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAA2C,MAAM,OAAO,CAAA;AAE1E,OAAO,aAAa,MAAM,wBAAwB,CAAC;AAGjD;;GAEG;AACH,UAAU,KAAK;IACb,WAAW;IACX,IAAI,EAAE,IAAI,CAAA;CACX;AA4FH,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
@@ -15,16 +15,25 @@
15
15
  import IncremarkMath from './IncremarkMath.svelte'
16
16
  import IncremarkHtmlElement from './IncremarkHtmlElement.svelte'
17
17
  import IncremarkDefault from './IncremarkDefault.svelte'
18
+ import IncremarkContainer, { type ContainerNode } from './IncremarkContainer.svelte'
18
19
 
19
20
  /**
20
21
  * 组件 Props
21
22
  */
22
23
  interface Props {
23
24
  /** 要渲染的节点 */
24
- node: RootContent
25
+ node: RootContent | ContainerNode
26
+ customContainers?: Record<string, any>
27
+ customCodeBlocks?: Record<string, any>
28
+ blockStatus?: 'pending' | 'stable' | 'completed'
25
29
  }
26
30
 
27
- let { node }: Props = $props()
31
+ let {
32
+ node,
33
+ customContainers,
34
+ customCodeBlocks,
35
+ blockStatus
36
+ }: Props = $props()
28
37
 
29
38
  /**
30
39
  * 组件映射
@@ -52,14 +61,39 @@
52
61
  /**
53
62
  * 检查是否是 html 节点
54
63
  */
55
- function isHtmlNode(node: RootContent): node is HTML {
64
+ function isHtmlNode(node: RootContent | ContainerNode): node is HTML {
56
65
  return node.type === 'html'
57
66
  }
67
+
68
+ /**
69
+ * 检查是否是容器节点
70
+ */
71
+ function isContainerNode(node: RootContent | ContainerNode): node is ContainerNode {
72
+ return (node as any).type === 'containerDirective' ||
73
+ (node as any).type === 'leafDirective' ||
74
+ (node as any).type === 'textDirective'
75
+ }
58
76
  </script>
59
77
 
60
78
  <!-- HTML 节点:渲染为代码块显示源代码 -->
61
79
  {#if isHtmlNode(node)}
62
80
  <pre class="incremark-html-code"><code>{node.value}</code></pre>
81
+ <!-- 容器节点:使用容器组件,传递 customContainers -->
82
+ {:else if isContainerNode(node)}
83
+ <IncremarkContainer
84
+ node={node}
85
+ customContainers={customContainers}
86
+ />
87
+ <!-- 代码节点:特殊处理,传递 customCodeBlocks 和 blockStatus -->
88
+ {:else if node.type === 'code'}
89
+ {@const Component = getComponent('code')}
90
+ {#if Component}
91
+ <Component
92
+ node={node}
93
+ customCodeBlocks={customCodeBlocks}
94
+ blockStatus={blockStatus}
95
+ />
96
+ {/if}
63
97
  {:else}
64
98
  <!-- 其他节点:使用对应组件 -->
65
99
  {@const Component = getComponent(node.type)}
@@ -1,10 +1,14 @@
1
1
  import type { RootContent } from 'mdast';
2
+ import { type ContainerNode } from './IncremarkContainer.svelte';
2
3
  /**
3
4
  * 组件 Props
4
5
  */
5
6
  interface Props {
6
7
  /** 要渲染的节点 */
7
- node: RootContent;
8
+ node: RootContent | ContainerNode;
9
+ customContainers?: Record<string, any>;
10
+ customCodeBlocks?: Record<string, any>;
11
+ blockStatus?: 'pending' | 'stable' | 'completed';
8
12
  }
9
13
  declare const IncremarkRenderer: import("svelte").Component<Props, {}, "">;
10
14
  type IncremarkRenderer = ReturnType<typeof IncremarkRenderer>;
@@ -1 +1 @@
1
- {"version":3,"file":"IncremarkRenderer.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkRenderer.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAQ,MAAM,OAAO,CAAA;AAa5C;;GAEG;AACH,UAAU,KAAK;IACb,aAAa;IACb,IAAI,EAAE,WAAW,CAAA;CAClB;AAgEH,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"IncremarkRenderer.svelte.d.ts","sourceRoot":"","sources":["../../src/components/IncremarkRenderer.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAQ,MAAM,OAAO,CAAA;AAW9C,OAA2B,EAAE,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAGnF;;GAEG;AACH,UAAU,KAAK;IACb,aAAa;IACb,IAAI,EAAE,WAAW,GAAG,aAAa,CAAA;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACtC,WAAW,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAA;CACjD;AAwFH,QAAA,MAAM,iBAAiB,2CAAwC,CAAC;AAChE,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9D,eAAe,iBAAiB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@incremark/svelte",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "Incremark Svelte 5 集成",
5
5
  "type": "module",
6
6
  "svelte": "./dist/index.js",
@@ -24,10 +24,10 @@
24
24
  ],
25
25
  "dependencies": {
26
26
  "shiki": "^3.20.0",
27
- "@incremark/core": "0.2.3",
28
- "@incremark/theme": "0.2.3",
29
- "@incremark/shared": "0.2.3",
30
- "@incremark/devtools": "0.2.3"
27
+ "@incremark/core": "0.2.4",
28
+ "@incremark/devtools": "0.2.4",
29
+ "@incremark/shared": "0.2.4",
30
+ "@incremark/theme": "0.2.4"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "svelte": "^5.0.0",