@incremark/react 0.3.0 → 0.3.2

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.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/hooks/useIncremark.ts
2
- import { useState as useState3, useCallback as useCallback3, useMemo as useMemo2, useRef as useRef2 } from "react";
2
+ import { useState as useState3, useCallback as useCallback3, useMemo as useMemo2, useRef as useRef2, useEffect as useEffect2 } from "react";
3
3
  import {
4
4
  createIncremarkParser
5
5
  } from "@incremark/core";
@@ -102,13 +102,21 @@ function useProvideDefinitions() {
102
102
  import { useState as useState2, useCallback as useCallback2, useMemo, useRef, useEffect } from "react";
103
103
  import {
104
104
  createBlockTransformer,
105
- defaultPlugins
105
+ defaultPlugins,
106
+ mathPlugin,
107
+ collectFootnoteReferences
106
108
  } from "@incremark/core";
107
109
 
108
110
  // src/utils/cursor.ts
109
111
  function addCursorToNode(node, cursor) {
112
+ if (node.type === "code") {
113
+ return node;
114
+ }
110
115
  const cloned = JSON.parse(JSON.stringify(node));
111
116
  function addToLast(n) {
117
+ if (n.type === "code") {
118
+ return false;
119
+ }
112
120
  if (n.children && n.children.length > 0) {
113
121
  for (let i = n.children.length - 1; i >= 0; i--) {
114
122
  if (addToLast(n.children[i])) {
@@ -154,14 +162,12 @@ function useTypewriter(options) {
154
162
  tickInterval: twOptions.tickInterval ?? 30,
155
163
  effect: twOptions.effect ?? "none",
156
164
  pauseOnHidden: twOptions.pauseOnHidden ?? true,
157
- plugins: twOptions.plugins ?? defaultPlugins,
165
+ // 默认插件 + 数学公式插件(数学公式应该整体显示,不参与打字机逐字符效果)
166
+ plugins: twOptions.plugins ?? [...defaultPlugins, mathPlugin],
158
167
  onChange: (blocks2) => {
159
168
  setDisplayBlocks(blocks2);
160
169
  setIsTypewriterProcessing(transformerRef.current?.isProcessing() ?? false);
161
170
  setIsTypewriterPaused(transformerRef.current?.isPausedState() ?? false);
162
- if (transformerRef.current?.isProcessing()) {
163
- setIsAnimationComplete(false);
164
- }
165
171
  },
166
172
  onAllComplete: () => {
167
173
  setIsAnimationComplete(true);
@@ -170,24 +176,23 @@ function useTypewriter(options) {
170
176
  }
171
177
  const transformer = transformerRef.current;
172
178
  const sourceBlocks = useMemo(
173
- () => completedBlocks.map((block) => ({
174
- id: block.id,
175
- node: block.node,
176
- status: block.status
177
- })),
178
- [completedBlocks]
179
+ () => [
180
+ ...completedBlocks.map((block) => ({
181
+ id: block.id,
182
+ node: block.node,
183
+ status: block.status
184
+ })),
185
+ ...pendingBlocks.map((block) => ({
186
+ id: block.id,
187
+ node: block.node,
188
+ status: block.status
189
+ }))
190
+ ],
191
+ [completedBlocks, pendingBlocks]
179
192
  );
180
193
  useEffect(() => {
181
194
  if (!transformer) return;
182
195
  transformer.push(sourceBlocks);
183
- const displayBlocks2 = transformer.getDisplayBlocks();
184
- const currentDisplaying = displayBlocks2.find((b) => !b.isDisplayComplete);
185
- if (currentDisplaying) {
186
- const updated = sourceBlocks.find((b) => b.id === currentDisplaying.id);
187
- if (updated) {
188
- transformer.update(updated);
189
- }
190
- }
191
196
  setIsTypewriterProcessing(transformer.isProcessing());
192
197
  setIsTypewriterPaused(transformer.isPausedState());
193
198
  }, [sourceBlocks, transformer]);
@@ -223,6 +228,37 @@ function useTypewriter(options) {
223
228
  return block;
224
229
  });
225
230
  }, [completedBlocks, pendingBlocks, typewriterEnabled, typewriterEffect, displayBlocks]);
231
+ const displayedFootnoteReferenceOrder = useMemo(() => {
232
+ if (!typewriterEnabled || !transformer) {
233
+ const references2 = [];
234
+ const seen2 = /* @__PURE__ */ new Set();
235
+ for (const block of [...completedBlocks, ...pendingBlocks]) {
236
+ const blockRefs = collectFootnoteReferences(block.node);
237
+ for (const ref of blockRefs) {
238
+ if (!seen2.has(ref)) {
239
+ seen2.add(ref);
240
+ references2.push(ref);
241
+ }
242
+ }
243
+ }
244
+ return references2;
245
+ }
246
+ if (!isAnimationComplete) {
247
+ return [];
248
+ }
249
+ const references = [];
250
+ const seen = /* @__PURE__ */ new Set();
251
+ for (const db of displayBlocks) {
252
+ const blockRefs = collectFootnoteReferences(db.displayNode);
253
+ for (const ref of blockRefs) {
254
+ if (!seen.has(ref)) {
255
+ seen.add(ref);
256
+ references.push(ref);
257
+ }
258
+ }
259
+ }
260
+ return references;
261
+ }, [typewriterEnabled, transformer, isAnimationComplete, completedBlocks, pendingBlocks, displayBlocks]);
226
262
  const skip = useCallback2(() => {
227
263
  transformer?.skip();
228
264
  setIsTypewriterProcessing(false);
@@ -280,7 +316,8 @@ function useTypewriter(options) {
280
316
  blocks,
281
317
  typewriter: typewriterControls,
282
318
  transformer,
283
- isAnimationComplete
319
+ isAnimationComplete,
320
+ displayedFootnoteReferenceOrder
284
321
  };
285
322
  }
286
323
 
@@ -315,14 +352,26 @@ function useIncremark(options = {}) {
315
352
  const [pendingBlocks, setPendingBlocks] = useState3([]);
316
353
  const [isLoading, setIsLoading] = useState3(false);
317
354
  const [isFinalized, setIsFinalized] = useState3(false);
355
+ const [ast, setAst] = useState3({
356
+ type: "root",
357
+ children: []
358
+ });
318
359
  const handleUpdate = useCallback3(
319
360
  (update, isFinalize) => {
320
361
  setMarkdown(parser.getBuffer());
362
+ if (update.updated.length > 0) {
363
+ const idsToRemove = new Set(update.updated.map((b) => b.id));
364
+ setCompletedBlocks((prev) => prev.filter((b) => !idsToRemove.has(b.id)));
365
+ }
321
366
  if (update.completed.length > 0) {
322
367
  setCompletedBlocks((prev) => [...prev, ...update.completed]);
323
368
  }
324
369
  setPendingBlocks(update.pending);
325
370
  if (isFinalize) {
371
+ if (update.pending.length > 0) {
372
+ setCompletedBlocks((prev) => [...prev, ...update.pending]);
373
+ setPendingBlocks([]);
374
+ }
326
375
  setIsLoading(false);
327
376
  setIsFinalized(true);
328
377
  } else {
@@ -332,7 +381,7 @@ function useIncremark(options = {}) {
332
381
  },
333
382
  [parser, setFootnoteReferenceOrder]
334
383
  );
335
- const { blocks, typewriter, transformer, isAnimationComplete } = useTypewriter({
384
+ const { blocks, typewriter, transformer, isAnimationComplete, displayedFootnoteReferenceOrder } = useTypewriter({
336
385
  typewriter: options.typewriter,
337
386
  completedBlocks,
338
387
  pendingBlocks
@@ -343,16 +392,10 @@ function useIncremark(options = {}) {
343
392
  }
344
393
  return isFinalized && isAnimationComplete;
345
394
  }, [options.typewriter, typewriter.enabled, isFinalized, isAnimationComplete]);
346
- const ast = useMemo2(
347
- () => ({
348
- type: "root",
349
- children: [...completedBlocks.map((b) => b.node), ...pendingBlocks.map((b) => b.node)]
350
- }),
351
- [completedBlocks, pendingBlocks]
352
- );
353
395
  const append = useCallback3(
354
396
  (chunk) => {
355
397
  const update = parser.append(chunk);
398
+ setAst(update.ast);
356
399
  handleUpdate(update, false);
357
400
  return update;
358
401
  },
@@ -374,6 +417,7 @@ function useIncremark(options = {}) {
374
417
  setIsLoading(false);
375
418
  setIsFinalized(false);
376
419
  setFootnoteReferenceOrder([]);
420
+ setAst({ type: "root", children: [] });
377
421
  transformer?.reset();
378
422
  }, [parser, transformer, setFootnoteReferenceOrder]);
379
423
  const render = useCallback3(
@@ -389,6 +433,26 @@ function useIncremark(options = {}) {
389
433
  },
390
434
  [parser, setFootnoteReferenceOrder]
391
435
  );
436
+ const updateOptions = useCallback3(
437
+ (newOptions) => {
438
+ parser.updateOptions(newOptions);
439
+ setCompletedBlocks([]);
440
+ setPendingBlocks([]);
441
+ setMarkdown("");
442
+ setIsLoading(false);
443
+ setIsFinalized(false);
444
+ setFootnoteReferenceOrder([]);
445
+ setAst({ type: "root", children: [] });
446
+ transformer?.reset();
447
+ },
448
+ [parser, transformer, setFootnoteReferenceOrder]
449
+ );
450
+ useEffect2(
451
+ () => {
452
+ setFootnoteReferenceOrder(displayedFootnoteReferenceOrder);
453
+ },
454
+ [displayedFootnoteReferenceOrder, setFootnoteReferenceOrder]
455
+ );
392
456
  return {
393
457
  /** 已收集的完整 Markdown 字符串 */
394
458
  markdown,
@@ -421,6 +485,8 @@ function useIncremark(options = {}) {
421
485
  reset,
422
486
  /** 一次性渲染(reset + append + finalize) */
423
487
  render,
488
+ /** 更新解析器配置(动态更新,不需要重建实例) */
489
+ updateOptions,
424
490
  /** 解析器实例 */
425
491
  parser,
426
492
  /** 打字机控制 */
@@ -431,12 +497,12 @@ function useIncremark(options = {}) {
431
497
  }
432
498
 
433
499
  // src/hooks/useDevTools.ts
434
- import { useEffect as useEffect2, useRef as useRef3 } from "react";
500
+ import { useEffect as useEffect3, useRef as useRef3 } from "react";
435
501
  import { createDevTools } from "@incremark/devtools";
436
502
  function useDevTools(incremark, options = {}) {
437
503
  const devtoolsRef = useRef3(null);
438
504
  const optionsRef = useRef3(options);
439
- useEffect2(() => {
505
+ useEffect3(() => {
440
506
  const devtools = createDevTools(optionsRef.current);
441
507
  devtoolsRef.current = devtools;
442
508
  incremark.parser.setOnChange((state) => {
@@ -463,7 +529,7 @@ function useDevTools(incremark, options = {}) {
463
529
  }
464
530
 
465
531
  // src/hooks/useBlockTransformer.ts
466
- import { useState as useState4, useCallback as useCallback4, useRef as useRef4, useEffect as useEffect3 } from "react";
532
+ import { useState as useState4, useCallback as useCallback4, useRef as useRef4, useEffect as useEffect4 } from "react";
467
533
  import {
468
534
  createBlockTransformer as createBlockTransformer2
469
535
  } from "@incremark/core";
@@ -484,7 +550,7 @@ function useBlockTransformer(sourceBlocks, options = {}) {
484
550
  });
485
551
  }
486
552
  const transformer = transformerRef.current;
487
- useEffect3(() => {
553
+ useEffect4(() => {
488
554
  transformer.push(sourceBlocks);
489
555
  const currentDisplaying = displayBlocks.find((b) => !b.isDisplayComplete);
490
556
  if (currentDisplaying) {
@@ -494,7 +560,7 @@ function useBlockTransformer(sourceBlocks, options = {}) {
494
560
  }
495
561
  }
496
562
  }, [sourceBlocks, transformer]);
497
- useEffect3(() => {
563
+ useEffect4(() => {
498
564
  return () => {
499
565
  transformer.destroy();
500
566
  };
@@ -537,45 +603,39 @@ function useBlockTransformer(sourceBlocks, options = {}) {
537
603
  }
538
604
 
539
605
  // src/hooks/useLocale.ts
540
- import { useContext as useContext2 } from "react";
606
+ import { useContext as useContext2, useMemo as useMemo4 } from "react";
607
+ import { zhCN as zhCN2 } from "@incremark/shared";
541
608
 
542
609
  // src/components/ConfigProvider.tsx
543
610
  import { createContext as createContext2, useMemo as useMemo3 } from "react";
611
+ import { zhCN } from "@incremark/shared";
544
612
  import { jsx as jsx2 } from "react/jsx-runtime";
545
613
  var LocaleContext = createContext2(null);
546
- function ConfigProvider({ children, locale = enShared }) {
547
- const contextValue = useMemo3(() => ({ locale }), [locale]);
614
+ function ConfigProvider({ children, locale }) {
615
+ const contextValue = useMemo3(() => ({ locale: locale || zhCN }), [locale]);
548
616
  return /* @__PURE__ */ jsx2(LocaleContext.Provider, { value: contextValue, children });
549
617
  }
550
618
 
551
619
  // src/hooks/useLocale.ts
552
620
  function useLocale() {
553
621
  const context = useContext2(LocaleContext);
554
- if (!context) {
555
- const t2 = (key) => {
622
+ const { locale } = context || { locale: zhCN2 };
623
+ const t = useMemo4(
624
+ () => (key) => {
556
625
  const keys = key.split(".");
557
- let value = enShared;
626
+ let value = locale;
558
627
  for (const k of keys) {
559
628
  value = value?.[k];
560
629
  }
561
630
  return value || key;
562
- };
563
- return { t: t2 };
564
- }
565
- const { locale } = context;
566
- const t = (key) => {
567
- const keys = key.split(".");
568
- let value = locale;
569
- for (const k of keys) {
570
- value = value?.[k];
571
- }
572
- return value || key;
573
- };
631
+ },
632
+ [locale]
633
+ );
574
634
  return { t };
575
635
  }
576
636
 
577
637
  // src/components/IncremarkInline.tsx
578
- import React3 from "react";
638
+ import React4 from "react";
579
639
  import {
580
640
  hasChunks,
581
641
  getStableText,
@@ -734,8 +794,73 @@ var IncremarkHtmlElement = ({ node }) => {
734
794
  return /* @__PURE__ */ jsx3(Tag, { ...reactProps, className: `incremark-html-element incremark-${tagName} ${reactProps.className || ""}`, children: renderChildren(children) });
735
795
  };
736
796
 
797
+ // src/components/IncremarkMath.tsx
798
+ import { useState as useState5, useEffect as useEffect5, useRef as useRef5, useCallback as useCallback5 } from "react";
799
+ import { jsx as jsx4 } from "react/jsx-runtime";
800
+ var IncremarkMath = ({
801
+ node,
802
+ renderDelay = 300
803
+ }) => {
804
+ const [renderedHtml, setRenderedHtml] = useState5("");
805
+ const [isLoading, setIsLoading] = useState5(false);
806
+ const katexRef = useRef5(null);
807
+ const renderTimerRef = useRef5(null);
808
+ const isInline = node.type === "inlineMath";
809
+ const formula = node.value;
810
+ const doRender = useCallback5(async () => {
811
+ if (!formula) return;
812
+ try {
813
+ if (!katexRef.current) {
814
+ const katexModule = await import("katex");
815
+ katexRef.current = katexModule.default;
816
+ }
817
+ const katex = katexRef.current;
818
+ const html = katex.renderToString(formula, {
819
+ displayMode: !isInline,
820
+ throwOnError: false,
821
+ strict: false
822
+ });
823
+ setRenderedHtml(html);
824
+ } catch {
825
+ setRenderedHtml("");
826
+ } finally {
827
+ setIsLoading(false);
828
+ }
829
+ }, [formula, isInline]);
830
+ const scheduleRender = useCallback5(() => {
831
+ if (!formula) {
832
+ setRenderedHtml("");
833
+ return;
834
+ }
835
+ if (renderTimerRef.current) {
836
+ clearTimeout(renderTimerRef.current);
837
+ }
838
+ setIsLoading(true);
839
+ renderTimerRef.current = setTimeout(() => {
840
+ doRender();
841
+ }, renderDelay);
842
+ }, [formula, renderDelay, doRender]);
843
+ useEffect5(() => {
844
+ scheduleRender();
845
+ }, [scheduleRender]);
846
+ useEffect5(() => {
847
+ return () => {
848
+ if (renderTimerRef.current) {
849
+ clearTimeout(renderTimerRef.current);
850
+ }
851
+ };
852
+ }, []);
853
+ if (isInline) {
854
+ return /* @__PURE__ */ jsx4("span", { className: "incremark-math-inline", children: renderedHtml && !isLoading ? /* @__PURE__ */ jsx4("span", { dangerouslySetInnerHTML: { __html: renderedHtml } }) : /* @__PURE__ */ jsx4("code", { className: "math-source", children: formula }) });
855
+ }
856
+ return /* @__PURE__ */ jsx4("div", { className: "incremark-math-block", children: renderedHtml && !isLoading ? /* @__PURE__ */ jsx4("div", { className: "math-rendered", dangerouslySetInnerHTML: { __html: renderedHtml } }) : /* @__PURE__ */ jsx4("pre", { className: "math-source-block", children: /* @__PURE__ */ jsx4("code", { children: formula }) }) });
857
+ };
858
+
737
859
  // src/components/IncremarkInline.tsx
738
- import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
860
+ import { Fragment, jsx as jsx5, jsxs } from "react/jsx-runtime";
861
+ function isInlineMath(node) {
862
+ return node.type === "inlineMath";
863
+ }
739
864
  function isHtmlElementNode(node) {
740
865
  return node.type === "htmlElement";
741
866
  }
@@ -748,22 +873,25 @@ function isLinkReference(node) {
748
873
  var IncremarkInline = ({ nodes }) => {
749
874
  if (!nodes || nodes.length === 0) return null;
750
875
  const { definitions, footnoteDefinitions } = useDefinitions();
751
- return /* @__PURE__ */ jsx4(Fragment, { children: nodes.map((node, i) => {
876
+ return /* @__PURE__ */ jsx5(Fragment, { children: nodes.map((node, i) => {
752
877
  if (node.type === "text") {
753
878
  const textNode = node;
754
879
  if (hasChunks(node) && textNode.chunks && textNode.chunks.length > 0) {
755
- return /* @__PURE__ */ jsxs(React3.Fragment, { children: [
880
+ return /* @__PURE__ */ jsxs(React4.Fragment, { children: [
756
881
  getStableText(textNode),
757
- textNode.chunks.map((chunk) => /* @__PURE__ */ jsx4("span", { "data-chunk-key": chunk.createdAt, className: "incremark-fade-in", children: chunk.text }, chunk.createdAt))
882
+ textNode.chunks.map((chunk) => /* @__PURE__ */ jsx5("span", { "data-chunk-key": chunk.createdAt, className: "incremark-fade-in", children: chunk.text }, chunk.createdAt))
758
883
  ] }, i);
759
884
  }
760
- return /* @__PURE__ */ jsx4(React3.Fragment, { children: node.value }, i);
885
+ return /* @__PURE__ */ jsx5(React4.Fragment, { children: node.value }, i);
886
+ }
887
+ if (isInlineMath(node)) {
888
+ return /* @__PURE__ */ jsx5(IncremarkMath, { node }, i);
761
889
  }
762
890
  if (isHtmlElementNode(node)) {
763
- return /* @__PURE__ */ jsx4(IncremarkHtmlElement, { node }, i);
891
+ return /* @__PURE__ */ jsx5(IncremarkHtmlElement, { node }, i);
764
892
  }
765
893
  if (isHtmlNode(node)) {
766
- return /* @__PURE__ */ jsx4(
894
+ return /* @__PURE__ */ jsx5(
767
895
  "span",
768
896
  {
769
897
  className: "incremark-inline-html",
@@ -773,20 +901,20 @@ var IncremarkInline = ({ nodes }) => {
773
901
  );
774
902
  }
775
903
  if (node.type === "strong") {
776
- return /* @__PURE__ */ jsx4("strong", { children: /* @__PURE__ */ jsx4(IncremarkInline, { nodes: node.children }) }, i);
904
+ return /* @__PURE__ */ jsx5("strong", { children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children }) }, i);
777
905
  }
778
906
  if (node.type === "emphasis") {
779
- return /* @__PURE__ */ jsx4("em", { children: /* @__PURE__ */ jsx4(IncremarkInline, { nodes: node.children }) }, i);
907
+ return /* @__PURE__ */ jsx5("em", { children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children }) }, i);
780
908
  }
781
909
  if (node.type === "inlineCode") {
782
- return /* @__PURE__ */ jsx4("code", { className: "incremark-inline-code", children: node.value }, i);
910
+ return /* @__PURE__ */ jsx5("code", { className: "incremark-inline-code", children: node.value }, i);
783
911
  }
784
912
  if (node.type === "link") {
785
- return /* @__PURE__ */ jsx4("a", { href: node.url, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsx4(IncremarkInline, { nodes: node.children }) }, i);
913
+ return /* @__PURE__ */ jsx5("a", { href: node.url, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children }) }, i);
786
914
  }
787
915
  if (node.type === "image") {
788
916
  const imageNode = node;
789
- return /* @__PURE__ */ jsx4(
917
+ return /* @__PURE__ */ jsx5(
790
918
  "img",
791
919
  {
792
920
  src: imageNode.url,
@@ -800,7 +928,7 @@ var IncremarkInline = ({ nodes }) => {
800
928
  if (isImageReference(node)) {
801
929
  const definition = definitions[node.identifier];
802
930
  if (definition) {
803
- return /* @__PURE__ */ jsx4(
931
+ return /* @__PURE__ */ jsx5(
804
932
  "img",
805
933
  {
806
934
  src: definition.url,
@@ -822,14 +950,14 @@ var IncremarkInline = ({ nodes }) => {
822
950
  if (isLinkReference(node)) {
823
951
  const definition = definitions[node.identifier];
824
952
  if (definition) {
825
- return /* @__PURE__ */ jsx4(
953
+ return /* @__PURE__ */ jsx5(
826
954
  "a",
827
955
  {
828
956
  href: definition.url,
829
957
  title: definition.title || void 0,
830
958
  target: "_blank",
831
959
  rel: "noopener noreferrer",
832
- children: /* @__PURE__ */ jsx4(IncremarkInline, { nodes: node.children })
960
+ children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children })
833
961
  },
834
962
  i
835
963
  );
@@ -845,47 +973,47 @@ var IncremarkInline = ({ nodes }) => {
845
973
  if (node.type === "footnoteReference") {
846
974
  const footnoteRef = node;
847
975
  const hasDefinition = footnoteDefinitions[footnoteRef.identifier];
848
- return /* @__PURE__ */ jsx4("sup", { className: "incremark-footnote-ref", children: /* @__PURE__ */ jsx4("a", { href: `#fn-${footnoteRef.identifier}`, id: `fnref-${footnoteRef.identifier}`, children: hasDefinition ? `[${footnoteRef.identifier}]` : `[^${footnoteRef.identifier}]` }) }, i);
976
+ return /* @__PURE__ */ jsx5("sup", { className: "incremark-footnote-ref", children: /* @__PURE__ */ jsx5("a", { href: `#fn-${footnoteRef.identifier}`, id: `fnref-${footnoteRef.identifier}`, children: hasDefinition ? `[${footnoteRef.identifier}]` : `[^${footnoteRef.identifier}]` }) }, i);
849
977
  }
850
978
  if (node.type === "break") {
851
- return /* @__PURE__ */ jsx4("br", {}, i);
979
+ return /* @__PURE__ */ jsx5("br", {}, i);
852
980
  }
853
981
  if (node.type === "delete") {
854
- return /* @__PURE__ */ jsx4("del", { children: /* @__PURE__ */ jsx4(IncremarkInline, { nodes: node.children }) }, i);
982
+ return /* @__PURE__ */ jsx5("del", { children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children }) }, i);
855
983
  }
856
- return /* @__PURE__ */ jsx4("span", { children: node.value || "" }, i);
984
+ return /* @__PURE__ */ jsx5("span", { children: node.value || "" }, i);
857
985
  }) });
858
986
  };
859
987
 
860
988
  // src/components/IncremarkHeading.tsx
861
- import { jsx as jsx5 } from "react/jsx-runtime";
989
+ import { jsx as jsx6 } from "react/jsx-runtime";
862
990
  var IncremarkHeading = ({ node }) => {
863
991
  const Tag = `h${node.depth}`;
864
- return /* @__PURE__ */ jsx5(Tag, { className: `incremark-heading h${node.depth}`, children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children }) });
992
+ return /* @__PURE__ */ jsx6(Tag, { className: `incremark-heading h${node.depth}`, children: /* @__PURE__ */ jsx6(IncremarkInline, { nodes: node.children }) });
865
993
  };
866
994
 
867
995
  // src/components/IncremarkParagraph.tsx
868
- import { jsx as jsx6 } from "react/jsx-runtime";
996
+ import { jsx as jsx7 } from "react/jsx-runtime";
869
997
  var IncremarkParagraph = ({ node }) => {
870
- return /* @__PURE__ */ jsx6("p", { className: "incremark-paragraph", children: /* @__PURE__ */ jsx6(IncremarkInline, { nodes: node.children }) });
998
+ return /* @__PURE__ */ jsx7("p", { className: "incremark-paragraph", children: /* @__PURE__ */ jsx7(IncremarkInline, { nodes: node.children }) });
871
999
  };
872
1000
 
873
1001
  // src/components/IncremarkCode.tsx
874
- import React7 from "react";
1002
+ import React9 from "react";
875
1003
 
876
1004
  // src/components/IncremarkCodeMermaid.tsx
877
- import { useState as useState5, useEffect as useEffect4, useRef as useRef5, useCallback as useCallback5 } from "react";
1005
+ import { useState as useState6, useEffect as useEffect6, useRef as useRef6, useCallback as useCallback6 } from "react";
878
1006
  import { GravityMermaid, LucideCode, LucideEye, LucideCopy, LucideCopyCheck } from "@incremark/icons";
879
1007
  import { isClipboardAvailable } from "@incremark/shared";
880
1008
 
881
1009
  // src/components/SvgIcon.tsx
882
- import { jsx as jsx7 } from "react/jsx-runtime";
1010
+ import { jsx as jsx8 } from "react/jsx-runtime";
883
1011
  var SvgIcon = ({
884
1012
  svg,
885
1013
  sizeClass,
886
1014
  className
887
1015
  }) => {
888
- return /* @__PURE__ */ jsx7(
1016
+ return /* @__PURE__ */ jsx8(
889
1017
  "span",
890
1018
  {
891
1019
  className: `incremark-icon ${sizeClass || ""} ${className || ""}`.trim(),
@@ -896,24 +1024,24 @@ var SvgIcon = ({
896
1024
  };
897
1025
 
898
1026
  // src/components/IncremarkCodeMermaid.tsx
899
- import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
1027
+ import { jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
900
1028
  var IncremarkCodeMermaid = ({
901
1029
  node,
902
1030
  mermaidDelay = 500
903
1031
  }) => {
904
- const [copied, setCopied] = useState5(false);
1032
+ const [copied, setCopied] = useState6(false);
905
1033
  const { t } = useLocale();
906
- const [mermaidSvg, setMermaidSvg] = useState5("");
907
- const [mermaidLoading, setMermaidLoading] = useState5(false);
908
- const [mermaidViewMode, setMermaidViewMode] = useState5("preview");
909
- const mermaidRef = useRef5(null);
910
- const mermaidTimerRef = useRef5(null);
911
- const copyTimeoutRef = useRef5(null);
1034
+ const [mermaidSvg, setMermaidSvg] = useState6("");
1035
+ const [mermaidLoading, setMermaidLoading] = useState6(false);
1036
+ const [mermaidViewMode, setMermaidViewMode] = useState6("preview");
1037
+ const mermaidRef = useRef6(null);
1038
+ const mermaidTimerRef = useRef6(null);
1039
+ const copyTimeoutRef = useRef6(null);
912
1040
  const code = node.value;
913
- const toggleMermaidView = useCallback5(() => {
1041
+ const toggleMermaidView = useCallback6(() => {
914
1042
  setMermaidViewMode((prev) => prev === "preview" ? "source" : "preview");
915
1043
  }, []);
916
- const copyCode = useCallback5(async () => {
1044
+ const copyCode = useCallback6(async () => {
917
1045
  if (!isClipboardAvailable()) return;
918
1046
  try {
919
1047
  await navigator.clipboard.writeText(code);
@@ -925,7 +1053,7 @@ var IncremarkCodeMermaid = ({
925
1053
  } catch {
926
1054
  }
927
1055
  }, [code]);
928
- const doRenderMermaid = useCallback5(async () => {
1056
+ const doRenderMermaid = useCallback6(async () => {
929
1057
  if (!code) return;
930
1058
  try {
931
1059
  if (!mermaidRef.current) {
@@ -948,7 +1076,7 @@ var IncremarkCodeMermaid = ({
948
1076
  setMermaidLoading(false);
949
1077
  }
950
1078
  }, [code]);
951
- const scheduleRenderMermaid = useCallback5(() => {
1079
+ const scheduleRenderMermaid = useCallback6(() => {
952
1080
  if (!code) return;
953
1081
  if (mermaidTimerRef.current) {
954
1082
  clearTimeout(mermaidTimerRef.current);
@@ -958,10 +1086,10 @@ var IncremarkCodeMermaid = ({
958
1086
  doRenderMermaid();
959
1087
  }, mermaidDelay);
960
1088
  }, [code, mermaidDelay, doRenderMermaid]);
961
- useEffect4(() => {
1089
+ useEffect6(() => {
962
1090
  scheduleRenderMermaid();
963
1091
  }, [scheduleRenderMermaid]);
964
- useEffect4(() => {
1092
+ useEffect6(() => {
965
1093
  return () => {
966
1094
  if (mermaidTimerRef.current) {
967
1095
  clearTimeout(mermaidTimerRef.current);
@@ -974,11 +1102,11 @@ var IncremarkCodeMermaid = ({
974
1102
  return /* @__PURE__ */ jsxs2("div", { className: "incremark-mermaid", children: [
975
1103
  /* @__PURE__ */ jsxs2("div", { className: "mermaid-header", children: [
976
1104
  /* @__PURE__ */ jsxs2("span", { className: "language", children: [
977
- /* @__PURE__ */ jsx8(SvgIcon, { svg: GravityMermaid, className: "language-icon" }),
1105
+ /* @__PURE__ */ jsx9(SvgIcon, { svg: GravityMermaid, className: "language-icon" }),
978
1106
  "MERMAID"
979
1107
  ] }),
980
1108
  /* @__PURE__ */ jsxs2("div", { className: "mermaid-actions", children: [
981
- /* @__PURE__ */ jsx8(
1109
+ /* @__PURE__ */ jsx9(
982
1110
  "button",
983
1111
  {
984
1112
  className: "code-btn",
@@ -987,10 +1115,10 @@ var IncremarkCodeMermaid = ({
987
1115
  disabled: !mermaidSvg,
988
1116
  "aria-label": mermaidViewMode === "preview" ? t("mermaid.viewSource") : t("mermaid.preview"),
989
1117
  title: mermaidViewMode === "preview" ? "View Source" : "Preview",
990
- children: /* @__PURE__ */ jsx8(SvgIcon, { svg: mermaidViewMode === "preview" ? LucideCode : LucideEye })
1118
+ children: /* @__PURE__ */ jsx9(SvgIcon, { svg: mermaidViewMode === "preview" ? LucideCode : LucideEye })
991
1119
  }
992
1120
  ),
993
- /* @__PURE__ */ jsx8(
1121
+ /* @__PURE__ */ jsx9(
994
1122
  "button",
995
1123
  {
996
1124
  className: "code-btn",
@@ -998,22 +1126,22 @@ var IncremarkCodeMermaid = ({
998
1126
  type: "button",
999
1127
  "aria-label": copied ? t("mermaid.copied") : t("mermaid.copy"),
1000
1128
  title: copied ? "Copied!" : "Copy",
1001
- children: /* @__PURE__ */ jsx8(SvgIcon, { svg: copied ? LucideCopyCheck : LucideCopy })
1129
+ children: /* @__PURE__ */ jsx9(SvgIcon, { svg: copied ? LucideCopyCheck : LucideCopy })
1002
1130
  }
1003
1131
  )
1004
1132
  ] })
1005
1133
  ] }),
1006
- /* @__PURE__ */ jsx8("div", { className: "mermaid-content", children: mermaidLoading && !mermaidSvg ? /* @__PURE__ */ jsx8("div", { className: "mermaid-loading", children: /* @__PURE__ */ jsx8("pre", { className: "mermaid-source-code", children: code }) }) : mermaidViewMode === "source" ? /* @__PURE__ */ jsx8("pre", { className: "mermaid-source-code", children: code }) : mermaidSvg ? /* @__PURE__ */ jsx8("div", { className: "mermaid-svg", dangerouslySetInnerHTML: { __html: mermaidSvg } }) : /* @__PURE__ */ jsx8("pre", { className: "mermaid-source-code", children: code }) })
1134
+ /* @__PURE__ */ jsx9("div", { className: "mermaid-content", children: mermaidLoading && !mermaidSvg ? /* @__PURE__ */ jsx9("div", { className: "mermaid-loading", children: /* @__PURE__ */ jsx9("pre", { className: "mermaid-source-code", children: code }) }) : mermaidViewMode === "source" ? /* @__PURE__ */ jsx9("pre", { className: "mermaid-source-code", children: code }) : mermaidSvg ? /* @__PURE__ */ jsx9("div", { className: "mermaid-svg", dangerouslySetInnerHTML: { __html: mermaidSvg } }) : /* @__PURE__ */ jsx9("pre", { className: "mermaid-source-code", children: code }) })
1007
1135
  ] });
1008
1136
  };
1009
1137
 
1010
1138
  // src/components/IncremarkCodeDefault.tsx
1011
- import { useState as useState6, useEffect as useEffect5, useCallback as useCallback6, useRef as useRef6 } from "react";
1139
+ import { useState as useState8, useEffect as useEffect8, useCallback as useCallback7, useRef as useRef8, useMemo as useMemo5 } from "react";
1012
1140
  import { LucideCopy as LucideCopy2, LucideCopyCheck as LucideCopyCheck2 } from "@incremark/icons";
1013
1141
  import { isClipboardAvailable as isClipboardAvailable2 } from "@incremark/shared";
1014
1142
 
1015
1143
  // src/hooks/useShiki.ts
1016
- import React5 from "react";
1144
+ import React6 from "react";
1017
1145
  var ShikiManager = class _ShikiManager {
1018
1146
  static instance = null;
1019
1147
  /** 存储 highlighter 实例,key 为主题名称 */
@@ -1113,15 +1241,30 @@ function getShikiManager() {
1113
1241
  return shikiManagerInstance;
1114
1242
  }
1115
1243
  function useShiki(theme) {
1116
- const [isHighlighting, setIsHighlighting] = React5.useState(false);
1117
- const highlighterInfoRef = React5.useRef(null);
1118
- const getHighlighter = React5.useCallback(async () => {
1119
- if (!highlighterInfoRef.current) {
1120
- highlighterInfoRef.current = await getShikiManager().getHighlighter(theme);
1244
+ const [isHighlighting, setIsHighlighting] = React6.useState(false);
1245
+ const [isReady, setIsReady] = React6.useState(false);
1246
+ const [highlighterInfo, setHighlighterInfo] = React6.useState(null);
1247
+ const initHighlighter = React6.useCallback(async () => {
1248
+ if (isReady) return;
1249
+ try {
1250
+ const info = await getShikiManager().getHighlighter(theme);
1251
+ setHighlighterInfo(info);
1252
+ setIsReady(true);
1253
+ } catch (e) {
1254
+ console.warn("Failed to initialize Shiki highlighter:", e);
1255
+ throw e;
1121
1256
  }
1122
- return highlighterInfoRef.current;
1123
- }, [theme]);
1124
- const highlight = React5.useCallback(async (code, lang, fallbackTheme) => {
1257
+ }, [theme, isReady]);
1258
+ const getHighlighter = React6.useCallback(async () => {
1259
+ if (!highlighterInfo) {
1260
+ const info = await getShikiManager().getHighlighter(theme);
1261
+ setHighlighterInfo(info);
1262
+ setIsReady(true);
1263
+ return info;
1264
+ }
1265
+ return highlighterInfo;
1266
+ }, [theme, highlighterInfo]);
1267
+ const highlight = React6.useCallback(async (code, lang, fallbackTheme) => {
1125
1268
  setIsHighlighting(true);
1126
1269
  try {
1127
1270
  const info = await getHighlighter();
@@ -1140,27 +1283,788 @@ function useShiki(theme) {
1140
1283
  }
1141
1284
  }, [getHighlighter, theme]);
1142
1285
  return {
1286
+ highlighterInfo,
1143
1287
  isHighlighting,
1288
+ isReady,
1289
+ initHighlighter,
1144
1290
  highlight
1145
1291
  };
1146
1292
  }
1147
1293
 
1294
+ // src/components/CachedCodeRenderer.tsx
1295
+ import { objectId } from "@antfu/utils";
1296
+
1297
+ // ../../node_modules/.pnpm/@shikijs+vscode-textmate@10.0.2/node_modules/@shikijs/vscode-textmate/dist/index.js
1298
+ function escapeRegExpCharacters(value) {
1299
+ return value.replace(/[\-\\\{\}\*\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, "\\$&");
1300
+ }
1301
+ var CachedFn = class {
1302
+ constructor(fn) {
1303
+ this.fn = fn;
1304
+ }
1305
+ cache = /* @__PURE__ */ new Map();
1306
+ get(key) {
1307
+ if (this.cache.has(key)) {
1308
+ return this.cache.get(key);
1309
+ }
1310
+ const value = this.fn(key);
1311
+ this.cache.set(key, value);
1312
+ return value;
1313
+ }
1314
+ };
1315
+ var ScopeStack = class _ScopeStack {
1316
+ constructor(parent, scopeName) {
1317
+ this.parent = parent;
1318
+ this.scopeName = scopeName;
1319
+ }
1320
+ static push(path, scopeNames) {
1321
+ for (const name of scopeNames) {
1322
+ path = new _ScopeStack(path, name);
1323
+ }
1324
+ return path;
1325
+ }
1326
+ static from(...segments) {
1327
+ let result = null;
1328
+ for (let i = 0; i < segments.length; i++) {
1329
+ result = new _ScopeStack(result, segments[i]);
1330
+ }
1331
+ return result;
1332
+ }
1333
+ push(scopeName) {
1334
+ return new _ScopeStack(this, scopeName);
1335
+ }
1336
+ getSegments() {
1337
+ let item = this;
1338
+ const result = [];
1339
+ while (item) {
1340
+ result.push(item.scopeName);
1341
+ item = item.parent;
1342
+ }
1343
+ result.reverse();
1344
+ return result;
1345
+ }
1346
+ toString() {
1347
+ return this.getSegments().join(" ");
1348
+ }
1349
+ extends(other) {
1350
+ if (this === other) {
1351
+ return true;
1352
+ }
1353
+ if (this.parent === null) {
1354
+ return false;
1355
+ }
1356
+ return this.parent.extends(other);
1357
+ }
1358
+ getExtensionIfDefined(base) {
1359
+ const result = [];
1360
+ let item = this;
1361
+ while (item && item !== base) {
1362
+ result.push(item.scopeName);
1363
+ item = item.parent;
1364
+ }
1365
+ return item === base ? result.reverse() : void 0;
1366
+ }
1367
+ };
1368
+ var FontStyle = /* @__PURE__ */ ((FontStyle2) => {
1369
+ FontStyle2[FontStyle2["NotSet"] = -1] = "NotSet";
1370
+ FontStyle2[FontStyle2["None"] = 0] = "None";
1371
+ FontStyle2[FontStyle2["Italic"] = 1] = "Italic";
1372
+ FontStyle2[FontStyle2["Bold"] = 2] = "Bold";
1373
+ FontStyle2[FontStyle2["Underline"] = 4] = "Underline";
1374
+ FontStyle2[FontStyle2["Strikethrough"] = 8] = "Strikethrough";
1375
+ return FontStyle2;
1376
+ })(FontStyle || {});
1377
+ var emptyParentScopes = Object.freeze([]);
1378
+ var EncodedTokenMetadata = class _EncodedTokenMetadata {
1379
+ static toBinaryStr(encodedTokenAttributes) {
1380
+ return encodedTokenAttributes.toString(2).padStart(32, "0");
1381
+ }
1382
+ static print(encodedTokenAttributes) {
1383
+ const languageId = _EncodedTokenMetadata.getLanguageId(encodedTokenAttributes);
1384
+ const tokenType = _EncodedTokenMetadata.getTokenType(encodedTokenAttributes);
1385
+ const fontStyle = _EncodedTokenMetadata.getFontStyle(encodedTokenAttributes);
1386
+ const foreground = _EncodedTokenMetadata.getForeground(encodedTokenAttributes);
1387
+ const background = _EncodedTokenMetadata.getBackground(encodedTokenAttributes);
1388
+ console.log({
1389
+ languageId,
1390
+ tokenType,
1391
+ fontStyle,
1392
+ foreground,
1393
+ background
1394
+ });
1395
+ }
1396
+ static getLanguageId(encodedTokenAttributes) {
1397
+ return (encodedTokenAttributes & 255) >>> 0;
1398
+ }
1399
+ static getTokenType(encodedTokenAttributes) {
1400
+ return (encodedTokenAttributes & 768) >>> 8;
1401
+ }
1402
+ static containsBalancedBrackets(encodedTokenAttributes) {
1403
+ return (encodedTokenAttributes & 1024) !== 0;
1404
+ }
1405
+ static getFontStyle(encodedTokenAttributes) {
1406
+ return (encodedTokenAttributes & 30720) >>> 11;
1407
+ }
1408
+ static getForeground(encodedTokenAttributes) {
1409
+ return (encodedTokenAttributes & 16744448) >>> 15;
1410
+ }
1411
+ static getBackground(encodedTokenAttributes) {
1412
+ return (encodedTokenAttributes & 4278190080) >>> 24;
1413
+ }
1414
+ /**
1415
+ * Updates the fields in `metadata`.
1416
+ * A value of `0`, `NotSet` or `null` indicates that the corresponding field should be left as is.
1417
+ */
1418
+ static set(encodedTokenAttributes, languageId, tokenType, containsBalancedBrackets, fontStyle, foreground, background) {
1419
+ let _languageId = _EncodedTokenMetadata.getLanguageId(encodedTokenAttributes);
1420
+ let _tokenType = _EncodedTokenMetadata.getTokenType(encodedTokenAttributes);
1421
+ let _containsBalancedBracketsBit = _EncodedTokenMetadata.containsBalancedBrackets(encodedTokenAttributes) ? 1 : 0;
1422
+ let _fontStyle = _EncodedTokenMetadata.getFontStyle(encodedTokenAttributes);
1423
+ let _foreground = _EncodedTokenMetadata.getForeground(encodedTokenAttributes);
1424
+ let _background = _EncodedTokenMetadata.getBackground(encodedTokenAttributes);
1425
+ if (languageId !== 0) {
1426
+ _languageId = languageId;
1427
+ }
1428
+ if (tokenType !== 8) {
1429
+ _tokenType = fromOptionalTokenType(tokenType);
1430
+ }
1431
+ if (containsBalancedBrackets !== null) {
1432
+ _containsBalancedBracketsBit = containsBalancedBrackets ? 1 : 0;
1433
+ }
1434
+ if (fontStyle !== -1) {
1435
+ _fontStyle = fontStyle;
1436
+ }
1437
+ if (foreground !== 0) {
1438
+ _foreground = foreground;
1439
+ }
1440
+ if (background !== 0) {
1441
+ _background = background;
1442
+ }
1443
+ return (_languageId << 0 | _tokenType << 8 | _containsBalancedBracketsBit << 10 | _fontStyle << 11 | _foreground << 15 | _background << 24) >>> 0;
1444
+ }
1445
+ };
1446
+ function fromOptionalTokenType(standardType) {
1447
+ return standardType;
1448
+ }
1449
+ function ruleIdFromNumber(id) {
1450
+ return id;
1451
+ }
1452
+ function ruleIdToNumber(id) {
1453
+ return id;
1454
+ }
1455
+ var BasicScopeAttributes = class {
1456
+ constructor(languageId, tokenType) {
1457
+ this.languageId = languageId;
1458
+ this.tokenType = tokenType;
1459
+ }
1460
+ };
1461
+ var BasicScopeAttributesProvider = class _BasicScopeAttributesProvider {
1462
+ _defaultAttributes;
1463
+ _embeddedLanguagesMatcher;
1464
+ constructor(initialLanguageId, embeddedLanguages) {
1465
+ this._defaultAttributes = new BasicScopeAttributes(
1466
+ initialLanguageId,
1467
+ 8
1468
+ /* NotSet */
1469
+ );
1470
+ this._embeddedLanguagesMatcher = new ScopeMatcher(Object.entries(embeddedLanguages || {}));
1471
+ }
1472
+ getDefaultAttributes() {
1473
+ return this._defaultAttributes;
1474
+ }
1475
+ getBasicScopeAttributes(scopeName) {
1476
+ if (scopeName === null) {
1477
+ return _BasicScopeAttributesProvider._NULL_SCOPE_METADATA;
1478
+ }
1479
+ return this._getBasicScopeAttributes.get(scopeName);
1480
+ }
1481
+ static _NULL_SCOPE_METADATA = new BasicScopeAttributes(0, 0);
1482
+ _getBasicScopeAttributes = new CachedFn((scopeName) => {
1483
+ const languageId = this._scopeToLanguage(scopeName);
1484
+ const standardTokenType = this._toStandardTokenType(scopeName);
1485
+ return new BasicScopeAttributes(languageId, standardTokenType);
1486
+ });
1487
+ /**
1488
+ * Given a produced TM scope, return the language that token describes or null if unknown.
1489
+ * e.g. source.html => html, source.css.embedded.html => css, punctuation.definition.tag.html => null
1490
+ */
1491
+ _scopeToLanguage(scope) {
1492
+ return this._embeddedLanguagesMatcher.match(scope) || 0;
1493
+ }
1494
+ _toStandardTokenType(scopeName) {
1495
+ const m = scopeName.match(_BasicScopeAttributesProvider.STANDARD_TOKEN_TYPE_REGEXP);
1496
+ if (!m) {
1497
+ return 8;
1498
+ }
1499
+ switch (m[1]) {
1500
+ case "comment":
1501
+ return 1;
1502
+ case "string":
1503
+ return 2;
1504
+ case "regex":
1505
+ return 3;
1506
+ case "meta.embedded":
1507
+ return 0;
1508
+ }
1509
+ throw new Error("Unexpected match for standard token type!");
1510
+ }
1511
+ static STANDARD_TOKEN_TYPE_REGEXP = /\b(comment|string|regex|meta\.embedded)\b/;
1512
+ };
1513
+ var ScopeMatcher = class {
1514
+ values;
1515
+ scopesRegExp;
1516
+ constructor(values) {
1517
+ if (values.length === 0) {
1518
+ this.values = null;
1519
+ this.scopesRegExp = null;
1520
+ } else {
1521
+ this.values = new Map(values);
1522
+ const escapedScopes = values.map(
1523
+ ([scopeName, value]) => escapeRegExpCharacters(scopeName)
1524
+ );
1525
+ escapedScopes.sort();
1526
+ escapedScopes.reverse();
1527
+ this.scopesRegExp = new RegExp(
1528
+ `^((${escapedScopes.join(")|(")}))($|\\.)`,
1529
+ ""
1530
+ );
1531
+ }
1532
+ }
1533
+ match(scope) {
1534
+ if (!this.scopesRegExp) {
1535
+ return void 0;
1536
+ }
1537
+ const m = scope.match(this.scopesRegExp);
1538
+ if (!m) {
1539
+ return void 0;
1540
+ }
1541
+ return this.values.get(m[1]);
1542
+ }
1543
+ };
1544
+ var DebugFlags = {
1545
+ InDebugMode: typeof process !== "undefined" && !!process.env["VSCODE_TEXTMATE_DEBUG"]
1546
+ };
1547
+ var AttributedScopeStack = class _AttributedScopeStack {
1548
+ /**
1549
+ * Invariant:
1550
+ * ```
1551
+ * if (parent && !scopePath.extends(parent.scopePath)) {
1552
+ * throw new Error();
1553
+ * }
1554
+ * ```
1555
+ */
1556
+ constructor(parent, scopePath, tokenAttributes) {
1557
+ this.parent = parent;
1558
+ this.scopePath = scopePath;
1559
+ this.tokenAttributes = tokenAttributes;
1560
+ }
1561
+ static fromExtension(namesScopeList, contentNameScopesList) {
1562
+ let current = namesScopeList;
1563
+ let scopeNames = namesScopeList?.scopePath ?? null;
1564
+ for (const frame of contentNameScopesList) {
1565
+ scopeNames = ScopeStack.push(scopeNames, frame.scopeNames);
1566
+ current = new _AttributedScopeStack(current, scopeNames, frame.encodedTokenAttributes);
1567
+ }
1568
+ return current;
1569
+ }
1570
+ static createRoot(scopeName, tokenAttributes) {
1571
+ return new _AttributedScopeStack(null, new ScopeStack(null, scopeName), tokenAttributes);
1572
+ }
1573
+ static createRootAndLookUpScopeName(scopeName, tokenAttributes, grammar) {
1574
+ const rawRootMetadata = grammar.getMetadataForScope(scopeName);
1575
+ const scopePath = new ScopeStack(null, scopeName);
1576
+ const rootStyle = grammar.themeProvider.themeMatch(scopePath);
1577
+ const resolvedTokenAttributes = _AttributedScopeStack.mergeAttributes(
1578
+ tokenAttributes,
1579
+ rawRootMetadata,
1580
+ rootStyle
1581
+ );
1582
+ return new _AttributedScopeStack(null, scopePath, resolvedTokenAttributes);
1583
+ }
1584
+ get scopeName() {
1585
+ return this.scopePath.scopeName;
1586
+ }
1587
+ toString() {
1588
+ return this.getScopeNames().join(" ");
1589
+ }
1590
+ equals(other) {
1591
+ return _AttributedScopeStack.equals(this, other);
1592
+ }
1593
+ static equals(a, b) {
1594
+ do {
1595
+ if (a === b) {
1596
+ return true;
1597
+ }
1598
+ if (!a && !b) {
1599
+ return true;
1600
+ }
1601
+ if (!a || !b) {
1602
+ return false;
1603
+ }
1604
+ if (a.scopeName !== b.scopeName || a.tokenAttributes !== b.tokenAttributes) {
1605
+ return false;
1606
+ }
1607
+ a = a.parent;
1608
+ b = b.parent;
1609
+ } while (true);
1610
+ }
1611
+ static mergeAttributes(existingTokenAttributes, basicScopeAttributes, styleAttributes) {
1612
+ let fontStyle = -1;
1613
+ let foreground = 0;
1614
+ let background = 0;
1615
+ if (styleAttributes !== null) {
1616
+ fontStyle = styleAttributes.fontStyle;
1617
+ foreground = styleAttributes.foregroundId;
1618
+ background = styleAttributes.backgroundId;
1619
+ }
1620
+ return EncodedTokenMetadata.set(
1621
+ existingTokenAttributes,
1622
+ basicScopeAttributes.languageId,
1623
+ basicScopeAttributes.tokenType,
1624
+ null,
1625
+ fontStyle,
1626
+ foreground,
1627
+ background
1628
+ );
1629
+ }
1630
+ pushAttributed(scopePath, grammar) {
1631
+ if (scopePath === null) {
1632
+ return this;
1633
+ }
1634
+ if (scopePath.indexOf(" ") === -1) {
1635
+ return _AttributedScopeStack._pushAttributed(this, scopePath, grammar);
1636
+ }
1637
+ const scopes = scopePath.split(/ /g);
1638
+ let result = this;
1639
+ for (const scope of scopes) {
1640
+ result = _AttributedScopeStack._pushAttributed(result, scope, grammar);
1641
+ }
1642
+ return result;
1643
+ }
1644
+ static _pushAttributed(target, scopeName, grammar) {
1645
+ const rawMetadata = grammar.getMetadataForScope(scopeName);
1646
+ const newPath = target.scopePath.push(scopeName);
1647
+ const scopeThemeMatchResult = grammar.themeProvider.themeMatch(newPath);
1648
+ const metadata = _AttributedScopeStack.mergeAttributes(
1649
+ target.tokenAttributes,
1650
+ rawMetadata,
1651
+ scopeThemeMatchResult
1652
+ );
1653
+ return new _AttributedScopeStack(target, newPath, metadata);
1654
+ }
1655
+ getScopeNames() {
1656
+ return this.scopePath.getSegments();
1657
+ }
1658
+ getExtensionIfDefined(base) {
1659
+ const result = [];
1660
+ let self = this;
1661
+ while (self && self !== base) {
1662
+ result.push({
1663
+ encodedTokenAttributes: self.tokenAttributes,
1664
+ scopeNames: self.scopePath.getExtensionIfDefined(self.parent?.scopePath ?? null)
1665
+ });
1666
+ self = self.parent;
1667
+ }
1668
+ return self === base ? result.reverse() : void 0;
1669
+ }
1670
+ };
1671
+ var StateStackImpl = class _StateStackImpl {
1672
+ /**
1673
+ * Invariant:
1674
+ * ```
1675
+ * if (contentNameScopesList !== nameScopesList && contentNameScopesList?.parent !== nameScopesList) {
1676
+ * throw new Error();
1677
+ * }
1678
+ * if (this.parent && !nameScopesList.extends(this.parent.contentNameScopesList)) {
1679
+ * throw new Error();
1680
+ * }
1681
+ * ```
1682
+ */
1683
+ constructor(parent, ruleId, enterPos, anchorPos, beginRuleCapturedEOL, endRule, nameScopesList, contentNameScopesList) {
1684
+ this.parent = parent;
1685
+ this.ruleId = ruleId;
1686
+ this.beginRuleCapturedEOL = beginRuleCapturedEOL;
1687
+ this.endRule = endRule;
1688
+ this.nameScopesList = nameScopesList;
1689
+ this.contentNameScopesList = contentNameScopesList;
1690
+ this.depth = this.parent ? this.parent.depth + 1 : 1;
1691
+ this._enterPos = enterPos;
1692
+ this._anchorPos = anchorPos;
1693
+ }
1694
+ _stackElementBrand = void 0;
1695
+ // TODO remove me
1696
+ static NULL = new _StateStackImpl(
1697
+ null,
1698
+ 0,
1699
+ 0,
1700
+ 0,
1701
+ false,
1702
+ null,
1703
+ null,
1704
+ null
1705
+ );
1706
+ /**
1707
+ * The position on the current line where this state was pushed.
1708
+ * This is relevant only while tokenizing a line, to detect endless loops.
1709
+ * Its value is meaningless across lines.
1710
+ */
1711
+ _enterPos;
1712
+ /**
1713
+ * The captured anchor position when this stack element was pushed.
1714
+ * This is relevant only while tokenizing a line, to restore the anchor position when popping.
1715
+ * Its value is meaningless across lines.
1716
+ */
1717
+ _anchorPos;
1718
+ /**
1719
+ * The depth of the stack.
1720
+ */
1721
+ depth;
1722
+ equals(other) {
1723
+ if (other === null) {
1724
+ return false;
1725
+ }
1726
+ return _StateStackImpl._equals(this, other);
1727
+ }
1728
+ static _equals(a, b) {
1729
+ if (a === b) {
1730
+ return true;
1731
+ }
1732
+ if (!this._structuralEquals(a, b)) {
1733
+ return false;
1734
+ }
1735
+ return AttributedScopeStack.equals(a.contentNameScopesList, b.contentNameScopesList);
1736
+ }
1737
+ /**
1738
+ * A structural equals check. Does not take into account `scopes`.
1739
+ */
1740
+ static _structuralEquals(a, b) {
1741
+ do {
1742
+ if (a === b) {
1743
+ return true;
1744
+ }
1745
+ if (!a && !b) {
1746
+ return true;
1747
+ }
1748
+ if (!a || !b) {
1749
+ return false;
1750
+ }
1751
+ if (a.depth !== b.depth || a.ruleId !== b.ruleId || a.endRule !== b.endRule) {
1752
+ return false;
1753
+ }
1754
+ a = a.parent;
1755
+ b = b.parent;
1756
+ } while (true);
1757
+ }
1758
+ clone() {
1759
+ return this;
1760
+ }
1761
+ static _reset(el) {
1762
+ while (el) {
1763
+ el._enterPos = -1;
1764
+ el._anchorPos = -1;
1765
+ el = el.parent;
1766
+ }
1767
+ }
1768
+ reset() {
1769
+ _StateStackImpl._reset(this);
1770
+ }
1771
+ pop() {
1772
+ return this.parent;
1773
+ }
1774
+ safePop() {
1775
+ if (this.parent) {
1776
+ return this.parent;
1777
+ }
1778
+ return this;
1779
+ }
1780
+ push(ruleId, enterPos, anchorPos, beginRuleCapturedEOL, endRule, nameScopesList, contentNameScopesList) {
1781
+ return new _StateStackImpl(
1782
+ this,
1783
+ ruleId,
1784
+ enterPos,
1785
+ anchorPos,
1786
+ beginRuleCapturedEOL,
1787
+ endRule,
1788
+ nameScopesList,
1789
+ contentNameScopesList
1790
+ );
1791
+ }
1792
+ getEnterPos() {
1793
+ return this._enterPos;
1794
+ }
1795
+ getAnchorPos() {
1796
+ return this._anchorPos;
1797
+ }
1798
+ getRule(grammar) {
1799
+ return grammar.getRule(this.ruleId);
1800
+ }
1801
+ toString() {
1802
+ const r = [];
1803
+ this._writeString(r, 0);
1804
+ return "[" + r.join(",") + "]";
1805
+ }
1806
+ _writeString(res, outIndex) {
1807
+ if (this.parent) {
1808
+ outIndex = this.parent._writeString(res, outIndex);
1809
+ }
1810
+ res[outIndex++] = `(${this.ruleId}, ${this.nameScopesList?.toString()}, ${this.contentNameScopesList?.toString()})`;
1811
+ return outIndex;
1812
+ }
1813
+ withContentNameScopesList(contentNameScopeStack) {
1814
+ if (this.contentNameScopesList === contentNameScopeStack) {
1815
+ return this;
1816
+ }
1817
+ return this.parent.push(
1818
+ this.ruleId,
1819
+ this._enterPos,
1820
+ this._anchorPos,
1821
+ this.beginRuleCapturedEOL,
1822
+ this.endRule,
1823
+ this.nameScopesList,
1824
+ contentNameScopeStack
1825
+ );
1826
+ }
1827
+ withEndRule(endRule) {
1828
+ if (this.endRule === endRule) {
1829
+ return this;
1830
+ }
1831
+ return new _StateStackImpl(
1832
+ this.parent,
1833
+ this.ruleId,
1834
+ this._enterPos,
1835
+ this._anchorPos,
1836
+ this.beginRuleCapturedEOL,
1837
+ endRule,
1838
+ this.nameScopesList,
1839
+ this.contentNameScopesList
1840
+ );
1841
+ }
1842
+ // Used to warn of endless loops
1843
+ hasSameRuleAs(other) {
1844
+ let el = this;
1845
+ while (el && el._enterPos === other._enterPos) {
1846
+ if (el.ruleId === other.ruleId) {
1847
+ return true;
1848
+ }
1849
+ el = el.parent;
1850
+ }
1851
+ return false;
1852
+ }
1853
+ toStateStackFrame() {
1854
+ return {
1855
+ ruleId: ruleIdToNumber(this.ruleId),
1856
+ beginRuleCapturedEOL: this.beginRuleCapturedEOL,
1857
+ endRule: this.endRule,
1858
+ nameScopesList: this.nameScopesList?.getExtensionIfDefined(this.parent?.nameScopesList ?? null) ?? [],
1859
+ contentNameScopesList: this.contentNameScopesList?.getExtensionIfDefined(this.nameScopesList) ?? []
1860
+ };
1861
+ }
1862
+ static pushFrame(self, frame) {
1863
+ const namesScopeList = AttributedScopeStack.fromExtension(self?.nameScopesList ?? null, frame.nameScopesList);
1864
+ return new _StateStackImpl(
1865
+ self,
1866
+ ruleIdFromNumber(frame.ruleId),
1867
+ frame.enterPos ?? -1,
1868
+ frame.anchorPos ?? -1,
1869
+ frame.beginRuleCapturedEOL,
1870
+ frame.endRule,
1871
+ namesScopeList,
1872
+ AttributedScopeStack.fromExtension(namesScopeList, frame.contentNameScopesList)
1873
+ );
1874
+ }
1875
+ };
1876
+ var INITIAL = StateStackImpl.NULL;
1877
+
1878
+ // ../../node_modules/.pnpm/@shikijs+core@3.21.0/node_modules/@shikijs/core/dist/index.mjs
1879
+ function getTokenStyleObject(token) {
1880
+ const styles = {};
1881
+ if (token.color)
1882
+ styles.color = token.color;
1883
+ if (token.bgColor)
1884
+ styles["background-color"] = token.bgColor;
1885
+ if (token.fontStyle) {
1886
+ if (token.fontStyle & FontStyle.Italic)
1887
+ styles["font-style"] = "italic";
1888
+ if (token.fontStyle & FontStyle.Bold)
1889
+ styles["font-weight"] = "bold";
1890
+ const decorations = [];
1891
+ if (token.fontStyle & FontStyle.Underline)
1892
+ decorations.push("underline");
1893
+ if (token.fontStyle & FontStyle.Strikethrough)
1894
+ decorations.push("line-through");
1895
+ if (decorations.length)
1896
+ styles["text-decoration"] = decorations.join(" ");
1897
+ }
1898
+ return styles;
1899
+ }
1900
+
1901
+ // src/components/CachedCodeRenderer.tsx
1902
+ import { useEffect as useEffect7, useRef as useRef7, useState as useState7, forwardRef, useImperativeHandle } from "react";
1903
+ import { CodeToTokenTransformStream } from "shiki-stream";
1904
+ import { jsx as jsx10 } from "react/jsx-runtime";
1905
+ var CachedCodeRenderer = forwardRef(
1906
+ function CachedCodeRenderer2({ code, lang, theme, highlighter, onStreamStart, onStreamEnd, onStreamError }, ref) {
1907
+ const [hasStreamError, setHasStreamError] = useState7(false);
1908
+ const [tokens, setTokens] = useState7([]);
1909
+ const streamRef = useRef7({
1910
+ controller: null,
1911
+ index: 0,
1912
+ initialized: false,
1913
+ streamConsumed: false
1914
+ });
1915
+ useImperativeHandle(ref, () => ({
1916
+ reset: () => {
1917
+ setHasStreamError(false);
1918
+ setTokens([]);
1919
+ streamRef.current.index = 0;
1920
+ }
1921
+ }));
1922
+ useEffect7(() => {
1923
+ if (streamRef.current.initialized) return;
1924
+ streamRef.current.initialized = true;
1925
+ const textStream = new ReadableStream({
1926
+ start(controller) {
1927
+ streamRef.current.controller = controller;
1928
+ }
1929
+ });
1930
+ let tokenStream = null;
1931
+ try {
1932
+ tokenStream = textStream.pipeThrough(
1933
+ new CodeToTokenTransformStream({
1934
+ highlighter,
1935
+ lang,
1936
+ theme,
1937
+ allowRecalls: true
1938
+ })
1939
+ );
1940
+ } catch (error) {
1941
+ console.error("Failed to create token stream:", error);
1942
+ setHasStreamError(true);
1943
+ onStreamError?.();
1944
+ return;
1945
+ }
1946
+ let started = false;
1947
+ let tokenCount = 0;
1948
+ tokenStream.pipeTo(new WritableStream({
1949
+ write(token) {
1950
+ if (!started) {
1951
+ started = true;
1952
+ onStreamStart?.();
1953
+ }
1954
+ if ("recall" in token) {
1955
+ setTokens((prev) => {
1956
+ const newTokens = [...prev];
1957
+ newTokens.splice(newTokens.length - token.recall, token.recall);
1958
+ return newTokens;
1959
+ });
1960
+ } else {
1961
+ setTokens((prev) => [...prev, token]);
1962
+ }
1963
+ tokenCount++;
1964
+ },
1965
+ close: () => {
1966
+ console.log(`[React CodeRenderer] Stream completed, total tokens: ${tokenCount}`);
1967
+ onStreamEnd?.();
1968
+ }
1969
+ })).catch((error) => {
1970
+ console.error("Stream error:", error);
1971
+ setHasStreamError(true);
1972
+ onStreamError?.();
1973
+ });
1974
+ streamRef.current.streamConsumed = true;
1975
+ }, []);
1976
+ useEffect7(() => {
1977
+ const { controller, index } = streamRef.current;
1978
+ if (!controller || hasStreamError) return;
1979
+ if (code.length > index) {
1980
+ const incremental = code.slice(index);
1981
+ try {
1982
+ controller.enqueue(incremental);
1983
+ streamRef.current.index = code.length;
1984
+ } catch {
1985
+ }
1986
+ }
1987
+ }, [code, hasStreamError]);
1988
+ if (hasStreamError) {
1989
+ return /* @__PURE__ */ jsx10("pre", { className: "shiki incremark-code-stream", children: /* @__PURE__ */ jsx10("code", { children: code }) });
1990
+ }
1991
+ return /* @__PURE__ */ jsx10("pre", { className: "shiki incremark-code-stream", children: /* @__PURE__ */ jsx10("code", { children: tokens.map((token) => {
1992
+ const styleObj = token.htmlStyle || getTokenStyleObject(token);
1993
+ const reactStyle = {};
1994
+ if (typeof styleObj === "string") {
1995
+ styleObj.split(";").forEach((rule) => {
1996
+ const colonIndex = rule.indexOf(":");
1997
+ if (colonIndex > 0) {
1998
+ const key = rule.slice(0, colonIndex).trim();
1999
+ const value = rule.slice(colonIndex + 1).trim();
2000
+ if (key && value) {
2001
+ const camelKey = key.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
2002
+ reactStyle[camelKey] = value;
2003
+ }
2004
+ }
2005
+ });
2006
+ } else if (styleObj && typeof styleObj === "object") {
2007
+ for (const [key, value] of Object.entries(styleObj)) {
2008
+ const camelKey = key.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
2009
+ reactStyle[camelKey] = value;
2010
+ }
2011
+ }
2012
+ return /* @__PURE__ */ jsx10("span", { style: reactStyle, children: token.content }, objectId(token));
2013
+ }) }) });
2014
+ }
2015
+ );
2016
+
1148
2017
  // src/components/IncremarkCodeDefault.tsx
1149
- import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
2018
+ import { jsx as jsx11, jsxs as jsxs3 } from "react/jsx-runtime";
1150
2019
  var IncremarkCodeDefault = ({
1151
2020
  node,
1152
2021
  theme = "github-dark",
1153
2022
  fallbackTheme = "github-dark",
1154
- disableHighlight = false
2023
+ disableHighlight = false,
2024
+ blockStatus = "pending"
1155
2025
  }) => {
1156
- const [copied, setCopied] = useState6(false);
1157
- const [highlightedHtml, setHighlightedHtml] = useState6("");
1158
- const language = node.lang || "text";
1159
- const code = node.value;
2026
+ const [copied, setCopied] = useState8(false);
2027
+ const [isLanguageLoaded, setIsLanguageLoaded] = useState8(false);
2028
+ const language = useMemo5(() => node.lang || "text", [node.lang]);
2029
+ const code = useMemo5(() => node.value, [node.value]);
1160
2030
  const { t } = useLocale();
1161
- const { isHighlighting, highlight } = useShiki(theme);
1162
- const copyTimeoutRef = useRef6(null);
1163
- const copyCode = useCallback6(async () => {
2031
+ const { highlighterInfo, initHighlighter } = useShiki(theme);
2032
+ const shouldEnableHighlight = useMemo5(() => {
2033
+ return !disableHighlight && code && code.length > 0;
2034
+ }, [disableHighlight, code]);
2035
+ useEffect8(() => {
2036
+ const loadLanguageIfNeeded = async () => {
2037
+ if (!shouldEnableHighlight) {
2038
+ return;
2039
+ }
2040
+ if (!highlighterInfo) {
2041
+ await initHighlighter();
2042
+ } else if (language && language !== "text") {
2043
+ if (!highlighterInfo.loadedLanguages.has(language)) {
2044
+ try {
2045
+ setIsLanguageLoaded(false);
2046
+ const supportedLangs = highlighterInfo.highlighter.getLoadedLanguages();
2047
+ const bundledLangs = await import("shiki").then((m) => Object.keys(m.bundledLanguages || {}));
2048
+ const isSupported = supportedLangs.includes(language) || bundledLangs.includes(language);
2049
+ if (isSupported) {
2050
+ await highlighterInfo.highlighter.loadLanguage(language);
2051
+ highlighterInfo.loadedLanguages.add(language);
2052
+ }
2053
+ setIsLanguageLoaded(true);
2054
+ } catch {
2055
+ setIsLanguageLoaded(true);
2056
+ }
2057
+ } else {
2058
+ setIsLanguageLoaded(true);
2059
+ }
2060
+ } else {
2061
+ setIsLanguageLoaded(true);
2062
+ }
2063
+ };
2064
+ loadLanguageIfNeeded();
2065
+ }, [highlighterInfo, language, shouldEnableHighlight, initHighlighter]);
2066
+ const copyTimeoutRef = useRef8(null);
2067
+ const copyCode = useCallback7(async () => {
1164
2068
  if (!isClipboardAvailable2()) return;
1165
2069
  try {
1166
2070
  await navigator.clipboard.writeText(code);
@@ -1172,32 +2076,17 @@ var IncremarkCodeDefault = ({
1172
2076
  } catch {
1173
2077
  }
1174
2078
  }, [code]);
1175
- useEffect5(() => {
2079
+ useEffect8(() => {
1176
2080
  return () => {
1177
2081
  if (copyTimeoutRef.current) {
1178
2082
  clearTimeout(copyTimeoutRef.current);
1179
2083
  }
1180
2084
  };
1181
2085
  }, []);
1182
- const doHighlight = useCallback6(async () => {
1183
- if (!code || disableHighlight) {
1184
- setHighlightedHtml("");
1185
- return;
1186
- }
1187
- try {
1188
- const html = await highlight(code, language, fallbackTheme);
1189
- setHighlightedHtml(html);
1190
- } catch {
1191
- setHighlightedHtml("");
1192
- }
1193
- }, [code, language, fallbackTheme, disableHighlight, highlight]);
1194
- useEffect5(() => {
1195
- doHighlight();
1196
- }, [doHighlight]);
1197
2086
  return /* @__PURE__ */ jsxs3("div", { className: "incremark-code", children: [
1198
2087
  /* @__PURE__ */ jsxs3("div", { className: "code-header", children: [
1199
- /* @__PURE__ */ jsx9("span", { className: "language", children: language }),
1200
- /* @__PURE__ */ jsx9(
2088
+ /* @__PURE__ */ jsx11("span", { className: "language", children: language }),
2089
+ /* @__PURE__ */ jsx11(
1201
2090
  "button",
1202
2091
  {
1203
2092
  className: "code-btn",
@@ -1205,16 +2094,27 @@ var IncremarkCodeDefault = ({
1205
2094
  type: "button",
1206
2095
  "aria-label": copied ? t("code.copied") : t("code.copy"),
1207
2096
  title: copied ? "Copied!" : "Copy",
1208
- children: /* @__PURE__ */ jsx9(SvgIcon, { svg: copied ? LucideCopyCheck2 : LucideCopy2 })
2097
+ children: /* @__PURE__ */ jsx11(SvgIcon, { svg: copied ? LucideCopyCheck2 : LucideCopy2 })
1209
2098
  }
1210
2099
  )
1211
2100
  ] }),
1212
- /* @__PURE__ */ jsx9("div", { className: "code-content", children: isHighlighting && !highlightedHtml ? /* @__PURE__ */ jsx9("div", { className: "code-loading", children: /* @__PURE__ */ jsx9("pre", { children: /* @__PURE__ */ jsx9("code", { children: code }) }) }) : highlightedHtml ? /* @__PURE__ */ jsx9("div", { className: "shiki-wrapper", dangerouslySetInnerHTML: { __html: highlightedHtml } }) : /* @__PURE__ */ jsx9("pre", { className: "code-fallback", children: /* @__PURE__ */ jsx9("code", { children: code }) }) })
2101
+ /* @__PURE__ */ jsx11("div", { className: "code-content", children: /* @__PURE__ */ jsx11("div", { className: "shiki-wrapper", children: shouldEnableHighlight && highlighterInfo && isLanguageLoaded ? /* @__PURE__ */ jsx11(
2102
+ CachedCodeRenderer,
2103
+ {
2104
+ code,
2105
+ lang: language,
2106
+ theme,
2107
+ highlighter: highlighterInfo.highlighter
2108
+ }
2109
+ ) : (
2110
+ // 无高亮模式(禁用高亮、无代码内容、或语言未加载完成时显示)
2111
+ /* @__PURE__ */ jsx11("pre", { className: "code-fallback", children: /* @__PURE__ */ jsx11("code", { children: code }) })
2112
+ ) }) })
1213
2113
  ] });
1214
2114
  };
1215
2115
 
1216
2116
  // src/components/IncremarkCode.tsx
1217
- import { jsx as jsx10 } from "react/jsx-runtime";
2117
+ import { jsx as jsx12 } from "react/jsx-runtime";
1218
2118
  var IncremarkCode = ({
1219
2119
  node,
1220
2120
  theme = "github-dark",
@@ -1222,14 +2122,14 @@ var IncremarkCode = ({
1222
2122
  disableHighlight = false,
1223
2123
  mermaidDelay = 500,
1224
2124
  customCodeBlocks,
1225
- blockStatus = "completed",
2125
+ blockStatus = "pending",
1226
2126
  codeBlockConfigs,
1227
2127
  defaultCodeComponent: DefaultCodeComponent = IncremarkCodeDefault
1228
2128
  }) => {
1229
2129
  const language = node.lang || "text";
1230
2130
  const code = node.value;
1231
2131
  const isMermaid = language === "mermaid";
1232
- const CustomCodeBlock = React7.useMemo(() => {
2132
+ const CustomCodeBlock = React9.useMemo(() => {
1233
2133
  const component = customCodeBlocks?.[language];
1234
2134
  if (!component) return null;
1235
2135
  const config = codeBlockConfigs?.[language];
@@ -1243,7 +2143,7 @@ var IncremarkCode = ({
1243
2143
  }, [customCodeBlocks, language, blockStatus, codeBlockConfigs]);
1244
2144
  if (CustomCodeBlock) {
1245
2145
  const config = codeBlockConfigs?.[language];
1246
- return /* @__PURE__ */ jsx10(
2146
+ return /* @__PURE__ */ jsx12(
1247
2147
  CustomCodeBlock,
1248
2148
  {
1249
2149
  codeStr: code,
@@ -1254,7 +2154,7 @@ var IncremarkCode = ({
1254
2154
  );
1255
2155
  }
1256
2156
  if (isMermaid) {
1257
- return /* @__PURE__ */ jsx10(
2157
+ return /* @__PURE__ */ jsx12(
1258
2158
  IncremarkCodeMermaid,
1259
2159
  {
1260
2160
  node,
@@ -1262,20 +2162,21 @@ var IncremarkCode = ({
1262
2162
  }
1263
2163
  );
1264
2164
  }
1265
- return /* @__PURE__ */ jsx10(
2165
+ return /* @__PURE__ */ jsx12(
1266
2166
  DefaultCodeComponent,
1267
2167
  {
1268
2168
  node,
1269
2169
  theme,
1270
2170
  fallbackTheme,
1271
- disableHighlight
2171
+ disableHighlight,
2172
+ blockStatus
1272
2173
  }
1273
2174
  );
1274
2175
  };
1275
2176
 
1276
2177
  // src/components/IncremarkList.tsx
1277
- import React8 from "react";
1278
- import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
2178
+ import React10 from "react";
2179
+ import { jsx as jsx13, jsxs as jsxs4 } from "react/jsx-runtime";
1279
2180
  function getItemInlineContent(item) {
1280
2181
  const firstChild = item.children[0];
1281
2182
  if (firstChild?.type === "paragraph") {
@@ -1294,13 +2195,13 @@ function getItemBlockChildren(item) {
1294
2195
  var IncremarkList = ({ node }) => {
1295
2196
  const Tag = node.ordered ? "ol" : "ul";
1296
2197
  const isTaskList = node.children?.some((item) => item.checked !== null && item.checked !== void 0);
1297
- return /* @__PURE__ */ jsx11(Tag, { className: `incremark-list ${isTaskList ? "task-list" : ""}`, start: node.start || void 0, children: node.children?.map((item, index) => {
2198
+ return /* @__PURE__ */ jsx13(Tag, { className: `incremark-list ${isTaskList ? "task-list" : ""}`, start: node.start || void 0, children: node.children?.map((item, index) => {
1298
2199
  const isTaskItem = item.checked !== null && item.checked !== void 0;
1299
2200
  const inlineContent = getItemInlineContent(item);
1300
2201
  const blockChildren = getItemBlockChildren(item);
1301
2202
  if (isTaskItem) {
1302
- return /* @__PURE__ */ jsx11("li", { className: "incremark-list-item task-item", children: /* @__PURE__ */ jsxs4("label", { className: "task-label", children: [
1303
- /* @__PURE__ */ jsx11(
2203
+ return /* @__PURE__ */ jsx13("li", { className: "incremark-list-item task-item", children: /* @__PURE__ */ jsxs4("label", { className: "task-label", children: [
2204
+ /* @__PURE__ */ jsx13(
1304
2205
  "input",
1305
2206
  {
1306
2207
  type: "checkbox",
@@ -1309,43 +2210,43 @@ var IncremarkList = ({ node }) => {
1309
2210
  className: "checkbox"
1310
2211
  }
1311
2212
  ),
1312
- /* @__PURE__ */ jsx11("span", { className: "task-content", children: /* @__PURE__ */ jsx11(IncremarkInline, { nodes: inlineContent }) })
2213
+ /* @__PURE__ */ jsx13("span", { className: "task-content", children: /* @__PURE__ */ jsx13(IncremarkInline, { nodes: inlineContent }) })
1313
2214
  ] }) }, index);
1314
2215
  }
1315
2216
  return /* @__PURE__ */ jsxs4("li", { className: "incremark-list-item", children: [
1316
- /* @__PURE__ */ jsx11(IncremarkInline, { nodes: inlineContent }),
1317
- blockChildren.map((child, childIndex) => /* @__PURE__ */ jsx11(React8.Fragment, { children: /* @__PURE__ */ jsx11(IncremarkRenderer, { node: child }) }, childIndex))
2217
+ /* @__PURE__ */ jsx13(IncremarkInline, { nodes: inlineContent }),
2218
+ blockChildren.map((child, childIndex) => /* @__PURE__ */ jsx13(React10.Fragment, { children: /* @__PURE__ */ jsx13(IncremarkRenderer, { node: child }) }, childIndex))
1318
2219
  ] }, index);
1319
2220
  }) });
1320
2221
  };
1321
2222
 
1322
2223
  // src/components/IncremarkBlockquote.tsx
1323
- import React9 from "react";
1324
- import { jsx as jsx12 } from "react/jsx-runtime";
2224
+ import React11 from "react";
2225
+ import { jsx as jsx14 } from "react/jsx-runtime";
1325
2226
  var IncremarkBlockquote = ({ node }) => {
1326
- return /* @__PURE__ */ jsx12("blockquote", { className: "incremark-blockquote", children: node.children.map((child, index) => /* @__PURE__ */ jsx12(React9.Fragment, { children: /* @__PURE__ */ jsx12(IncremarkRenderer, { node: child }) }, index)) });
2227
+ return /* @__PURE__ */ jsx14("blockquote", { className: "incremark-blockquote", children: node.children.map((child, index) => /* @__PURE__ */ jsx14(React11.Fragment, { children: /* @__PURE__ */ jsx14(IncremarkRenderer, { node: child }) }, index)) });
1327
2228
  };
1328
2229
 
1329
2230
  // src/components/IncremarkTable.tsx
1330
- import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
2231
+ import { jsx as jsx15, jsxs as jsxs5 } from "react/jsx-runtime";
1331
2232
  function getCellContent(cell) {
1332
2233
  return cell.children;
1333
2234
  }
1334
2235
  var IncremarkTable = ({ node }) => {
1335
- return /* @__PURE__ */ jsx13("div", { className: "incremark-table-wrapper", children: /* @__PURE__ */ jsxs5("table", { className: "incremark-table", children: [
1336
- /* @__PURE__ */ jsx13("thead", { children: node.children?.[0] && /* @__PURE__ */ jsx13("tr", { children: node.children[0].children.map((cell, cellIndex) => /* @__PURE__ */ jsx13(
2236
+ return /* @__PURE__ */ jsx15("div", { className: "incremark-table-wrapper", children: /* @__PURE__ */ jsxs5("table", { className: "incremark-table", children: [
2237
+ /* @__PURE__ */ jsx15("thead", { children: node.children?.[0] && /* @__PURE__ */ jsx15("tr", { children: node.children[0].children.map((cell, cellIndex) => /* @__PURE__ */ jsx15(
1337
2238
  "th",
1338
2239
  {
1339
2240
  className: `incremark-table-align-${node.align?.[cellIndex] || "left"}`,
1340
- children: /* @__PURE__ */ jsx13(IncremarkInline, { nodes: getCellContent(cell) })
2241
+ children: /* @__PURE__ */ jsx15(IncremarkInline, { nodes: getCellContent(cell) })
1341
2242
  },
1342
2243
  cellIndex
1343
2244
  )) }) }),
1344
- /* @__PURE__ */ jsx13("tbody", { children: node.children?.slice(1).map((row, rowIndex) => /* @__PURE__ */ jsx13("tr", { children: row.children.map((cell, cellIndex) => /* @__PURE__ */ jsx13(
2245
+ /* @__PURE__ */ jsx15("tbody", { children: node.children?.slice(1).map((row, rowIndex) => /* @__PURE__ */ jsx15("tr", { children: row.children.map((cell, cellIndex) => /* @__PURE__ */ jsx15(
1345
2246
  "td",
1346
2247
  {
1347
2248
  className: `incremark-table-align-${node.align?.[cellIndex] || "left"}`,
1348
- children: /* @__PURE__ */ jsx13(IncremarkInline, { nodes: getCellContent(cell) })
2249
+ children: /* @__PURE__ */ jsx15(IncremarkInline, { nodes: getCellContent(cell) })
1349
2250
  },
1350
2251
  cellIndex
1351
2252
  )) }, rowIndex)) })
@@ -1353,75 +2254,13 @@ var IncremarkTable = ({ node }) => {
1353
2254
  };
1354
2255
 
1355
2256
  // src/components/IncremarkThematicBreak.tsx
1356
- import { jsx as jsx14 } from "react/jsx-runtime";
2257
+ import { jsx as jsx16 } from "react/jsx-runtime";
1357
2258
  var IncremarkThematicBreak = () => {
1358
- return /* @__PURE__ */ jsx14("hr", { className: "incremark-hr" });
1359
- };
1360
-
1361
- // src/components/IncremarkMath.tsx
1362
- import { useState as useState7, useEffect as useEffect6, useRef as useRef7, useCallback as useCallback7 } from "react";
1363
- import { jsx as jsx15 } from "react/jsx-runtime";
1364
- var IncremarkMath = ({
1365
- node,
1366
- renderDelay = 300
1367
- }) => {
1368
- const [renderedHtml, setRenderedHtml] = useState7("");
1369
- const [isLoading, setIsLoading] = useState7(false);
1370
- const katexRef = useRef7(null);
1371
- const renderTimerRef = useRef7(null);
1372
- const isInline = node.type === "inlineMath";
1373
- const formula = node.value;
1374
- const doRender = useCallback7(async () => {
1375
- if (!formula) return;
1376
- try {
1377
- if (!katexRef.current) {
1378
- const katexModule = await import("katex");
1379
- katexRef.current = katexModule.default;
1380
- }
1381
- const katex = katexRef.current;
1382
- const html = katex.renderToString(formula, {
1383
- displayMode: !isInline,
1384
- throwOnError: false,
1385
- strict: false
1386
- });
1387
- setRenderedHtml(html);
1388
- } catch {
1389
- setRenderedHtml("");
1390
- } finally {
1391
- setIsLoading(false);
1392
- }
1393
- }, [formula, isInline]);
1394
- const scheduleRender = useCallback7(() => {
1395
- if (!formula) {
1396
- setRenderedHtml("");
1397
- return;
1398
- }
1399
- if (renderTimerRef.current) {
1400
- clearTimeout(renderTimerRef.current);
1401
- }
1402
- setIsLoading(true);
1403
- renderTimerRef.current = setTimeout(() => {
1404
- doRender();
1405
- }, renderDelay);
1406
- }, [formula, renderDelay, doRender]);
1407
- useEffect6(() => {
1408
- scheduleRender();
1409
- }, [scheduleRender]);
1410
- useEffect6(() => {
1411
- return () => {
1412
- if (renderTimerRef.current) {
1413
- clearTimeout(renderTimerRef.current);
1414
- }
1415
- };
1416
- }, []);
1417
- if (isInline) {
1418
- return /* @__PURE__ */ jsx15("span", { className: "incremark-math-inline", children: renderedHtml && !isLoading ? /* @__PURE__ */ jsx15("span", { dangerouslySetInnerHTML: { __html: renderedHtml } }) : /* @__PURE__ */ jsx15("code", { className: "math-source", children: formula }) });
1419
- }
1420
- return /* @__PURE__ */ jsx15("div", { className: "incremark-math-block", children: renderedHtml && !isLoading ? /* @__PURE__ */ jsx15("div", { className: "math-rendered", dangerouslySetInnerHTML: { __html: renderedHtml } }) : /* @__PURE__ */ jsx15("pre", { className: "math-source-block", children: /* @__PURE__ */ jsx15("code", { children: formula }) }) });
2259
+ return /* @__PURE__ */ jsx16("hr", { className: "incremark-hr" });
1421
2260
  };
1422
2261
 
1423
2262
  // src/components/IncremarkContainer.tsx
1424
- import { jsx as jsx16 } from "react/jsx-runtime";
2263
+ import { jsx as jsx17 } from "react/jsx-runtime";
1425
2264
  function parseOptions(attributes) {
1426
2265
  if (!attributes) return {};
1427
2266
  const options = {};
@@ -1439,22 +2278,22 @@ var IncremarkContainer = ({ node, customContainers }) => {
1439
2278
  const options = parseOptions(node.attributes);
1440
2279
  const CustomContainer = customContainers?.[containerName];
1441
2280
  if (CustomContainer) {
1442
- return /* @__PURE__ */ jsx16(CustomContainer, { name: containerName, options, children: node.children?.map((child, index) => /* @__PURE__ */ jsx16(IncremarkRenderer, { node: child }, index)) });
2281
+ return /* @__PURE__ */ jsx17(CustomContainer, { name: containerName, options, children: node.children?.map((child, index) => /* @__PURE__ */ jsx17(IncremarkRenderer, { node: child }, index)) });
1443
2282
  }
1444
- return /* @__PURE__ */ jsx16("div", { className: `incremark-container incremark-container-${containerName}`, children: node.children && node.children.length > 0 && /* @__PURE__ */ jsx16("div", { className: "incremark-container-content", children: node.children.map((child, index) => /* @__PURE__ */ jsx16(IncremarkRenderer, { node: child }, index)) }) });
2283
+ return /* @__PURE__ */ jsx17("div", { className: `incremark-container incremark-container-${containerName}`, children: node.children && node.children.length > 0 && /* @__PURE__ */ jsx17("div", { className: "incremark-container-content", children: node.children.map((child, index) => /* @__PURE__ */ jsx17(IncremarkRenderer, { node: child }, index)) }) });
1445
2284
  };
1446
2285
 
1447
2286
  // src/components/IncremarkDefault.tsx
1448
- import { jsx as jsx17, jsxs as jsxs6 } from "react/jsx-runtime";
2287
+ import { jsx as jsx18, jsxs as jsxs6 } from "react/jsx-runtime";
1449
2288
  var IncremarkDefault = ({ node }) => {
1450
2289
  return /* @__PURE__ */ jsxs6("div", { className: "incremark-default", children: [
1451
- /* @__PURE__ */ jsx17("span", { className: "type-badge", children: node.type }),
1452
- /* @__PURE__ */ jsx17("pre", { children: JSON.stringify(node, null, 2) })
2290
+ /* @__PURE__ */ jsx18("span", { className: "type-badge", children: node.type }),
2291
+ /* @__PURE__ */ jsx18("pre", { children: JSON.stringify(node, null, 2) })
1453
2292
  ] });
1454
2293
  };
1455
2294
 
1456
2295
  // src/components/IncremarkRenderer.tsx
1457
- import { jsx as jsx18 } from "react/jsx-runtime";
2296
+ import { jsx as jsx19 } from "react/jsx-runtime";
1458
2297
  var defaultComponents = {
1459
2298
  heading: IncremarkHeading,
1460
2299
  paragraph: IncremarkParagraph,
@@ -1490,10 +2329,10 @@ var IncremarkRenderer = ({
1490
2329
  return null;
1491
2330
  }
1492
2331
  if (isHtmlNode2(node)) {
1493
- return /* @__PURE__ */ jsx18("pre", { className: "incremark-html-code", children: /* @__PURE__ */ jsx18("code", { children: node.value }) });
2332
+ return /* @__PURE__ */ jsx19("pre", { className: "incremark-html-code", children: /* @__PURE__ */ jsx19("code", { children: node.value }) });
1494
2333
  }
1495
2334
  if (isContainerNode(node)) {
1496
- return /* @__PURE__ */ jsx18(
2335
+ return /* @__PURE__ */ jsx19(
1497
2336
  IncremarkContainer,
1498
2337
  {
1499
2338
  node,
@@ -1502,7 +2341,7 @@ var IncremarkRenderer = ({
1502
2341
  );
1503
2342
  }
1504
2343
  if (node.type === "code") {
1505
- return /* @__PURE__ */ jsx18(
2344
+ return /* @__PURE__ */ jsx19(
1506
2345
  IncremarkCode,
1507
2346
  {
1508
2347
  node,
@@ -1514,15 +2353,15 @@ var IncremarkRenderer = ({
1514
2353
  );
1515
2354
  }
1516
2355
  const Component = getComponent(node.type, components);
1517
- return /* @__PURE__ */ jsx18(Component, { node });
2356
+ return /* @__PURE__ */ jsx19(Component, { node });
1518
2357
  };
1519
2358
 
1520
2359
  // src/components/IncremarkFootnotes.tsx
1521
- import React11 from "react";
1522
- import { jsx as jsx19, jsxs as jsxs7 } from "react/jsx-runtime";
2360
+ import React12 from "react";
2361
+ import { jsx as jsx20, jsxs as jsxs7 } from "react/jsx-runtime";
1523
2362
  var IncremarkFootnotes = () => {
1524
2363
  const { footnoteDefinitions, footnoteReferenceOrder } = useDefinitions();
1525
- const orderedFootnotes = React11.useMemo(() => {
2364
+ const orderedFootnotes = React12.useMemo(() => {
1526
2365
  return footnoteReferenceOrder.map((identifier) => ({
1527
2366
  identifier,
1528
2367
  definition: footnoteDefinitions[identifier]
@@ -1532,8 +2371,8 @@ var IncremarkFootnotes = () => {
1532
2371
  return null;
1533
2372
  }
1534
2373
  return /* @__PURE__ */ jsxs7("section", { className: "incremark-footnotes", children: [
1535
- /* @__PURE__ */ jsx19("hr", { className: "incremark-footnotes-divider" }),
1536
- /* @__PURE__ */ jsx19("ol", { className: "incremark-footnotes-list", children: orderedFootnotes.map((item, index) => /* @__PURE__ */ jsxs7(
2374
+ /* @__PURE__ */ jsx20("hr", { className: "incremark-footnotes-divider" }),
2375
+ /* @__PURE__ */ jsx20("ol", { className: "incremark-footnotes-list", children: orderedFootnotes.map((item, index) => /* @__PURE__ */ jsxs7(
1537
2376
  "li",
1538
2377
  {
1539
2378
  id: `fn-${item.identifier}`,
@@ -1544,9 +2383,9 @@ var IncremarkFootnotes = () => {
1544
2383
  index + 1,
1545
2384
  "."
1546
2385
  ] }),
1547
- /* @__PURE__ */ jsx19("div", { className: "incremark-footnote-body", children: item.definition.children.map((child, childIndex) => /* @__PURE__ */ jsx19(IncremarkRenderer, { node: child }, childIndex)) })
2386
+ /* @__PURE__ */ jsx20("div", { className: "incremark-footnote-body", children: item.definition.children.map((child, childIndex) => /* @__PURE__ */ jsx20(IncremarkRenderer, { node: child }, childIndex)) })
1548
2387
  ] }),
1549
- /* @__PURE__ */ jsx19(
2388
+ /* @__PURE__ */ jsx20(
1550
2389
  "a",
1551
2390
  {
1552
2391
  href: `#fnref-${item.identifier}`,
@@ -1563,13 +2402,13 @@ var IncremarkFootnotes = () => {
1563
2402
  };
1564
2403
 
1565
2404
  // src/components/IncremarkContainerProvider.tsx
1566
- import { jsx as jsx20 } from "react/jsx-runtime";
2405
+ import { jsx as jsx21 } from "react/jsx-runtime";
1567
2406
  var IncremarkContainerProvider = ({ children, definitions }) => {
1568
- return /* @__PURE__ */ jsx20(DefinitionsContext.Provider, { value: definitions, children });
2407
+ return /* @__PURE__ */ jsx21(DefinitionsContext.Provider, { value: definitions, children });
1569
2408
  };
1570
2409
 
1571
2410
  // src/components/Incremark.tsx
1572
- import { jsx as jsx21, jsxs as jsxs8 } from "react/jsx-runtime";
2411
+ import { jsx as jsx22, jsxs as jsxs8 } from "react/jsx-runtime";
1573
2412
  var Incremark = (props) => {
1574
2413
  const {
1575
2414
  blocks: propsBlocks,
@@ -1585,7 +2424,7 @@ var Incremark = (props) => {
1585
2424
  } = props;
1586
2425
  if (incremark) {
1587
2426
  const { blocks: blocks2, isDisplayComplete: isDisplayComplete2, _definitionsContextValue } = incremark;
1588
- return /* @__PURE__ */ jsx21(IncremarkContainerProvider, { definitions: _definitionsContextValue, children: /* @__PURE__ */ jsx21(
2427
+ return /* @__PURE__ */ jsx22(IncremarkContainerProvider, { definitions: _definitionsContextValue, children: /* @__PURE__ */ jsx22(
1589
2428
  IncremarkInternal,
1590
2429
  {
1591
2430
  blocks: blocks2,
@@ -1602,7 +2441,7 @@ var Incremark = (props) => {
1602
2441
  }
1603
2442
  const blocks = propsBlocks || [];
1604
2443
  const isDisplayComplete = propsIsDisplayComplete;
1605
- return /* @__PURE__ */ jsx21(
2444
+ return /* @__PURE__ */ jsx22(
1606
2445
  IncremarkInternal,
1607
2446
  {
1608
2447
  blocks,
@@ -1641,7 +2480,7 @@ var IncremarkInternal = ({
1641
2480
  showBlockStatus && "incremark-show-status",
1642
2481
  block.isLastPending && "incremark-last-pending"
1643
2482
  ].filter(Boolean).join(" ");
1644
- return /* @__PURE__ */ jsx21("div", { className: classes, children: /* @__PURE__ */ jsx21(
2483
+ return /* @__PURE__ */ jsx22("div", { className: classes, children: /* @__PURE__ */ jsx22(
1645
2484
  IncremarkRenderer,
1646
2485
  {
1647
2486
  node: block.node,
@@ -1653,13 +2492,13 @@ var IncremarkInternal = ({
1653
2492
  }
1654
2493
  ) }, block.id);
1655
2494
  }),
1656
- isDisplayComplete && /* @__PURE__ */ jsx21(IncremarkFootnotes, {})
2495
+ isDisplayComplete && /* @__PURE__ */ jsx22(IncremarkFootnotes, {})
1657
2496
  ] });
1658
2497
  };
1659
2498
 
1660
2499
  // src/components/IncremarkContent.tsx
1661
- import { useEffect as useEffect7, useRef as useRef8, useMemo as useMemo4, useCallback as useCallback8 } from "react";
1662
- import { jsx as jsx22 } from "react/jsx-runtime";
2500
+ import { useEffect as useEffect9, useRef as useRef9, useMemo as useMemo6, useCallback as useCallback8 } from "react";
2501
+ import { jsx as jsx23 } from "react/jsx-runtime";
1663
2502
  var IncremarkContent = (props) => {
1664
2503
  const {
1665
2504
  stream,
@@ -1673,22 +2512,40 @@ var IncremarkContent = (props) => {
1673
2512
  showBlockStatus,
1674
2513
  pendingClass
1675
2514
  } = props;
1676
- const initialOptionsRef = useRef8({
2515
+ const initialOptionsRef = useRef9({
1677
2516
  gfm: true,
1678
2517
  htmlTree: true,
1679
2518
  containers: true,
1680
2519
  math: true,
1681
2520
  ...incremarkOptions
1682
2521
  });
1683
- const { blocks, append, finalize, render, reset, isDisplayComplete, markdown, typewriter, _definitionsContextValue } = useIncremark(initialOptionsRef.current);
1684
- useEffect7(() => {
1685
- if (incremarkOptions?.typewriter) {
1686
- typewriter.setOptions(incremarkOptions.typewriter);
1687
- }
1688
- }, [incremarkOptions?.typewriter, typewriter]);
1689
- const isStreamMode = useMemo4(() => typeof stream === "function", [stream]);
1690
- const prevContentRef = useRef8(void 0);
1691
- const isStreamingRef = useRef8(false);
2522
+ const { blocks, append, finalize, render, reset, updateOptions, isDisplayComplete, markdown, typewriter, _definitionsContextValue } = useIncremark(initialOptionsRef.current);
2523
+ const prevOptionsRef = useRef9(incremarkOptions);
2524
+ useEffect9(() => {
2525
+ const prev = prevOptionsRef.current;
2526
+ const current = incremarkOptions;
2527
+ if (prev === current) return;
2528
+ prevOptionsRef.current = current;
2529
+ const prevMath = typeof prev?.math === "object" ? JSON.stringify(prev.math) : String(prev?.math ?? true);
2530
+ const currentMath = typeof current?.math === "object" ? JSON.stringify(current.math) : String(current?.math ?? true);
2531
+ const prevAstBuilder = prev?.astBuilder?.name ?? "default";
2532
+ const currentAstBuilder = current?.astBuilder?.name ?? "default";
2533
+ if (prevMath !== currentMath || prev?.gfm !== current?.gfm || prev?.htmlTree !== current?.htmlTree || prev?.containers !== current?.containers || prevAstBuilder !== currentAstBuilder) {
2534
+ updateOptions({
2535
+ gfm: current?.gfm ?? true,
2536
+ math: current?.math ?? true,
2537
+ htmlTree: current?.htmlTree ?? true,
2538
+ containers: current?.containers ?? true,
2539
+ astBuilder: current?.astBuilder
2540
+ });
2541
+ }
2542
+ if (current?.typewriter) {
2543
+ typewriter.setOptions(current.typewriter);
2544
+ }
2545
+ }, [incremarkOptions, updateOptions, typewriter]);
2546
+ const isStreamMode = useMemo6(() => typeof stream === "function", [stream]);
2547
+ const prevContentRef = useRef9(void 0);
2548
+ const isStreamingRef = useRef9(false);
1692
2549
  const handleStreamInput = useCallback8(async () => {
1693
2550
  if (!stream || isStreamingRef.current) return;
1694
2551
  isStreamingRef.current = true;
@@ -1719,7 +2576,7 @@ var IncremarkContent = (props) => {
1719
2576
  render(newContent);
1720
2577
  }
1721
2578
  }, [append, render, reset]);
1722
- useEffect7(() => {
2579
+ useEffect9(() => {
1723
2580
  if (isStreamMode) {
1724
2581
  handleStreamInput();
1725
2582
  } else {
@@ -1727,12 +2584,12 @@ var IncremarkContent = (props) => {
1727
2584
  }
1728
2585
  prevContentRef.current = content;
1729
2586
  }, [content, isStreamMode, handleStreamInput, handleContentInput]);
1730
- useEffect7(() => {
2587
+ useEffect9(() => {
1731
2588
  if (isFinished && content === markdown) {
1732
2589
  finalize();
1733
2590
  }
1734
2591
  }, [isFinished, content, markdown, finalize]);
1735
- return /* @__PURE__ */ jsx22(IncremarkContainerProvider, { definitions: _definitionsContextValue, children: /* @__PURE__ */ jsx22(
2592
+ return /* @__PURE__ */ jsx23(IncremarkContainerProvider, { definitions: _definitionsContextValue, children: /* @__PURE__ */ jsx23(
1736
2593
  Incremark,
1737
2594
  {
1738
2595
  blocks,
@@ -1749,15 +2606,15 @@ var IncremarkContent = (props) => {
1749
2606
 
1750
2607
  // src/components/AutoScrollContainer.tsx
1751
2608
  import {
1752
- useRef as useRef9,
1753
- useEffect as useEffect8,
2609
+ useRef as useRef10,
2610
+ useEffect as useEffect10,
1754
2611
  useCallback as useCallback9,
1755
- useState as useState8,
1756
- forwardRef,
1757
- useImperativeHandle
2612
+ useState as useState9,
2613
+ forwardRef as forwardRef2,
2614
+ useImperativeHandle as useImperativeHandle2
1758
2615
  } from "react";
1759
- import { jsx as jsx23 } from "react/jsx-runtime";
1760
- var AutoScrollContainer = forwardRef(
2616
+ import { jsx as jsx24 } from "react/jsx-runtime";
2617
+ var AutoScrollContainer = forwardRef2(
1761
2618
  ({
1762
2619
  children,
1763
2620
  enabled = true,
@@ -1766,10 +2623,10 @@ var AutoScrollContainer = forwardRef(
1766
2623
  style,
1767
2624
  className
1768
2625
  }, ref) => {
1769
- const containerRef = useRef9(null);
1770
- const [isUserScrolledUp, setIsUserScrolledUp] = useState8(false);
1771
- const lastScrollTopRef = useRef9(0);
1772
- const lastScrollHeightRef = useRef9(0);
2626
+ const containerRef = useRef10(null);
2627
+ const [isUserScrolledUp, setIsUserScrolledUp] = useState9(false);
2628
+ const lastScrollTopRef = useRef10(0);
2629
+ const lastScrollHeightRef = useRef10(0);
1773
2630
  const isNearBottom = useCallback9(() => {
1774
2631
  const container = containerRef.current;
1775
2632
  if (!container) return true;
@@ -1815,14 +2672,14 @@ var AutoScrollContainer = forwardRef(
1815
2672
  lastScrollTopRef.current = scrollTop;
1816
2673
  lastScrollHeightRef.current = scrollHeight;
1817
2674
  }, [isNearBottom]);
1818
- useEffect8(() => {
2675
+ useEffect10(() => {
1819
2676
  const container = containerRef.current;
1820
2677
  if (container) {
1821
2678
  lastScrollTopRef.current = container.scrollTop;
1822
2679
  lastScrollHeightRef.current = container.scrollHeight;
1823
2680
  }
1824
2681
  }, []);
1825
- useEffect8(() => {
2682
+ useEffect10(() => {
1826
2683
  const container = containerRef.current;
1827
2684
  if (!container || !enabled) return;
1828
2685
  const observer = new MutationObserver(() => {
@@ -1845,7 +2702,7 @@ var AutoScrollContainer = forwardRef(
1845
2702
  });
1846
2703
  return () => observer.disconnect();
1847
2704
  }, [enabled, isUserScrolledUp, scrollToBottom]);
1848
- useImperativeHandle(
2705
+ useImperativeHandle2(
1849
2706
  ref,
1850
2707
  () => ({
1851
2708
  scrollToBottom: () => scrollToBottom(true),
@@ -1854,7 +2711,7 @@ var AutoScrollContainer = forwardRef(
1854
2711
  }),
1855
2712
  [scrollToBottom, isUserScrolledUp]
1856
2713
  );
1857
- return /* @__PURE__ */ jsx23(
2714
+ return /* @__PURE__ */ jsx24(
1858
2715
  "div",
1859
2716
  {
1860
2717
  ref: containerRef,
@@ -1869,21 +2726,21 @@ var AutoScrollContainer = forwardRef(
1869
2726
  AutoScrollContainer.displayName = "AutoScrollContainer";
1870
2727
 
1871
2728
  // src/ThemeProvider.tsx
1872
- import { useEffect as useEffect9, useRef as useRef10 } from "react";
2729
+ import { useEffect as useEffect11, useRef as useRef11 } from "react";
1873
2730
  import { applyTheme } from "@incremark/theme";
1874
- import { jsx as jsx24 } from "react/jsx-runtime";
2731
+ import { jsx as jsx25 } from "react/jsx-runtime";
1875
2732
  var ThemeProvider = ({
1876
2733
  theme,
1877
2734
  children,
1878
2735
  className = ""
1879
2736
  }) => {
1880
- const containerRef = useRef10(null);
1881
- useEffect9(() => {
2737
+ const containerRef = useRef11(null);
2738
+ useEffect11(() => {
1882
2739
  if (containerRef.current) {
1883
2740
  applyTheme(containerRef.current, theme);
1884
2741
  }
1885
2742
  }, [theme]);
1886
- return /* @__PURE__ */ jsx24("div", { ref: containerRef, className: `incremark-theme-provider ${className}`.trim(), children });
2743
+ return /* @__PURE__ */ jsx25("div", { ref: containerRef, className: `incremark-theme-provider ${className}`.trim(), children });
1887
2744
  };
1888
2745
 
1889
2746
  // src/index.ts
@@ -1896,7 +2753,7 @@ import {
1896
2753
  codeBlockPlugin,
1897
2754
  mermaidPlugin,
1898
2755
  imagePlugin,
1899
- mathPlugin,
2756
+ mathPlugin as mathPlugin2,
1900
2757
  thematicBreakPlugin,
1901
2758
  defaultPlugins as defaultPlugins2,
1902
2759
  allPlugins,
@@ -1936,7 +2793,7 @@ export {
1936
2793
  enShared as en,
1937
2794
  generateCSSVars,
1938
2795
  imagePlugin,
1939
- mathPlugin,
2796
+ mathPlugin2 as mathPlugin,
1940
2797
  mergeTheme,
1941
2798
  mermaidPlugin,
1942
2799
  sliceAst,