@incremark/react 0.2.6 → 0.3.0

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
@@ -193,17 +193,7 @@ function useTypewriter(options) {
193
193
  }, [sourceBlocks, transformer]);
194
194
  const blocks = useMemo(() => {
195
195
  if (!typewriterEnabled || !transformer) {
196
- const result = [];
197
- for (const block of completedBlocks) {
198
- result.push({ ...block, stableId: block.id });
199
- }
200
- for (let i = 0; i < pendingBlocks.length; i++) {
201
- result.push({
202
- ...pendingBlocks[i],
203
- stableId: `pending-${i}`
204
- });
205
- }
206
- return result;
196
+ return [...completedBlocks, ...pendingBlocks];
207
197
  }
208
198
  return displayBlocks.map((db, index) => {
209
199
  const isPending = !db.isDisplayComplete;
@@ -220,7 +210,6 @@ function useTypewriter(options) {
220
210
  }
221
211
  const block = {
222
212
  id: db.id,
223
- stableId: db.id,
224
213
  status: db.isDisplayComplete ? "completed" : "pending",
225
214
  isLastPending,
226
215
  node,
@@ -452,8 +441,8 @@ function useDevTools(incremark, options = {}) {
452
441
  devtoolsRef.current = devtools;
453
442
  incremark.parser.setOnChange((state) => {
454
443
  const blocks = [
455
- ...state.completedBlocks.map((b) => ({ ...b, stableId: b.id })),
456
- ...state.pendingBlocks.map((b, i) => ({ ...b, stableId: `pending-${i}` }))
444
+ ...state.completedBlocks,
445
+ ...state.pendingBlocks
457
446
  ];
458
447
  devtools.update({
459
448
  blocks,
@@ -547,6 +536,44 @@ function useBlockTransformer(sourceBlocks, options = {}) {
547
536
  };
548
537
  }
549
538
 
539
+ // src/hooks/useLocale.ts
540
+ import { useContext as useContext2 } from "react";
541
+
542
+ // src/components/ConfigProvider.tsx
543
+ import { createContext as createContext2, useMemo as useMemo3 } from "react";
544
+ import { jsx as jsx2 } from "react/jsx-runtime";
545
+ var LocaleContext = createContext2(null);
546
+ function ConfigProvider({ children, locale = enShared }) {
547
+ const contextValue = useMemo3(() => ({ locale }), [locale]);
548
+ return /* @__PURE__ */ jsx2(LocaleContext.Provider, { value: contextValue, children });
549
+ }
550
+
551
+ // src/hooks/useLocale.ts
552
+ function useLocale() {
553
+ const context = useContext2(LocaleContext);
554
+ if (!context) {
555
+ const t2 = (key) => {
556
+ const keys = key.split(".");
557
+ let value = enShared;
558
+ for (const k of keys) {
559
+ value = value?.[k];
560
+ }
561
+ 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
+ };
574
+ return { t };
575
+ }
576
+
550
577
  // src/components/IncremarkInline.tsx
551
578
  import React3 from "react";
552
579
  import {
@@ -557,7 +584,7 @@ import {
557
584
 
558
585
  // src/components/IncremarkHtmlElement.tsx
559
586
  import React2 from "react";
560
- import { jsx as jsx2 } from "react/jsx-runtime";
587
+ import { jsx as jsx3 } from "react/jsx-runtime";
561
588
  var INLINE_ELEMENTS = [
562
589
  "a",
563
590
  "abbr",
@@ -679,22 +706,22 @@ function toReactProps(attrs) {
679
706
  function renderChildren(children) {
680
707
  if (!children || children.length === 0) return null;
681
708
  if (hasOnlyInlineChildren(children)) {
682
- return /* @__PURE__ */ jsx2(IncremarkInline, { nodes: children });
709
+ return /* @__PURE__ */ jsx3(IncremarkInline, { nodes: children });
683
710
  }
684
711
  return children.map((child, idx) => {
685
712
  if (child.type === "htmlElement") {
686
- return /* @__PURE__ */ jsx2(IncremarkHtmlElement, { node: child }, idx);
713
+ return /* @__PURE__ */ jsx3(IncremarkHtmlElement, { node: child }, idx);
687
714
  }
688
715
  if (child.type === "text") {
689
- return /* @__PURE__ */ jsx2(React2.Fragment, { children: child.value }, idx);
716
+ return /* @__PURE__ */ jsx3(React2.Fragment, { children: child.value }, idx);
690
717
  }
691
718
  if (["strong", "emphasis", "inlineCode", "link", "image", "break"].includes(child.type)) {
692
- return /* @__PURE__ */ jsx2(IncremarkInline, { nodes: [child] }, idx);
719
+ return /* @__PURE__ */ jsx3(IncremarkInline, { nodes: [child] }, idx);
693
720
  }
694
721
  if (child.type === "paragraph") {
695
- return /* @__PURE__ */ jsx2("p", { children: /* @__PURE__ */ jsx2(IncremarkInline, { nodes: child.children }) }, idx);
722
+ return /* @__PURE__ */ jsx3("p", { children: /* @__PURE__ */ jsx3(IncremarkInline, { nodes: child.children }) }, idx);
696
723
  }
697
- return /* @__PURE__ */ jsx2("div", { className: "incremark-unknown-child", children: child.type }, idx);
724
+ return /* @__PURE__ */ jsx3("div", { className: "incremark-unknown-child", children: child.type }, idx);
698
725
  });
699
726
  }
700
727
  var IncremarkHtmlElement = ({ node }) => {
@@ -702,13 +729,13 @@ var IncremarkHtmlElement = ({ node }) => {
702
729
  const Tag = tagName;
703
730
  const reactProps = toReactProps(attrs);
704
731
  if (isVoidElement(tagName)) {
705
- return /* @__PURE__ */ jsx2(Tag, { ...reactProps, className: `incremark-html-element incremark-${tagName} ${reactProps.className || ""}` });
732
+ return /* @__PURE__ */ jsx3(Tag, { ...reactProps, className: `incremark-html-element incremark-${tagName} ${reactProps.className || ""}` });
706
733
  }
707
- return /* @__PURE__ */ jsx2(Tag, { ...reactProps, className: `incremark-html-element incremark-${tagName} ${reactProps.className || ""}`, children: renderChildren(children) });
734
+ return /* @__PURE__ */ jsx3(Tag, { ...reactProps, className: `incremark-html-element incremark-${tagName} ${reactProps.className || ""}`, children: renderChildren(children) });
708
735
  };
709
736
 
710
737
  // src/components/IncremarkInline.tsx
711
- import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
738
+ import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
712
739
  function isHtmlElementNode(node) {
713
740
  return node.type === "htmlElement";
714
741
  }
@@ -721,45 +748,45 @@ function isLinkReference(node) {
721
748
  var IncremarkInline = ({ nodes }) => {
722
749
  if (!nodes || nodes.length === 0) return null;
723
750
  const { definitions, footnoteDefinitions } = useDefinitions();
724
- return /* @__PURE__ */ jsx3(Fragment, { children: nodes.map((node, i) => {
751
+ return /* @__PURE__ */ jsx4(Fragment, { children: nodes.map((node, i) => {
725
752
  if (node.type === "text") {
726
753
  const textNode = node;
727
754
  if (hasChunks(node) && textNode.chunks && textNode.chunks.length > 0) {
728
755
  return /* @__PURE__ */ jsxs(React3.Fragment, { children: [
729
756
  getStableText(textNode),
730
- textNode.chunks.map((chunk) => /* @__PURE__ */ jsx3("span", { "data-chunk-key": chunk.createdAt, className: "incremark-fade-in", children: chunk.text }, chunk.createdAt))
757
+ textNode.chunks.map((chunk) => /* @__PURE__ */ jsx4("span", { "data-chunk-key": chunk.createdAt, className: "incremark-fade-in", children: chunk.text }, chunk.createdAt))
731
758
  ] }, i);
732
759
  }
733
- return /* @__PURE__ */ jsx3(React3.Fragment, { children: node.value }, i);
760
+ return /* @__PURE__ */ jsx4(React3.Fragment, { children: node.value }, i);
734
761
  }
735
762
  if (isHtmlElementNode(node)) {
736
- return /* @__PURE__ */ jsx3(IncremarkHtmlElement, { node }, i);
763
+ return /* @__PURE__ */ jsx4(IncremarkHtmlElement, { node }, i);
737
764
  }
738
765
  if (isHtmlNode(node)) {
739
- return /* @__PURE__ */ jsx3(
766
+ return /* @__PURE__ */ jsx4(
740
767
  "span",
741
768
  {
742
- style: { display: "contents" },
769
+ className: "incremark-inline-html",
743
770
  dangerouslySetInnerHTML: { __html: node.value }
744
771
  },
745
772
  i
746
773
  );
747
774
  }
748
775
  if (node.type === "strong") {
749
- return /* @__PURE__ */ jsx3("strong", { children: /* @__PURE__ */ jsx3(IncremarkInline, { nodes: node.children }) }, i);
776
+ return /* @__PURE__ */ jsx4("strong", { children: /* @__PURE__ */ jsx4(IncremarkInline, { nodes: node.children }) }, i);
750
777
  }
751
778
  if (node.type === "emphasis") {
752
- return /* @__PURE__ */ jsx3("em", { children: /* @__PURE__ */ jsx3(IncremarkInline, { nodes: node.children }) }, i);
779
+ return /* @__PURE__ */ jsx4("em", { children: /* @__PURE__ */ jsx4(IncremarkInline, { nodes: node.children }) }, i);
753
780
  }
754
781
  if (node.type === "inlineCode") {
755
- return /* @__PURE__ */ jsx3("code", { className: "incremark-inline-code", children: node.value }, i);
782
+ return /* @__PURE__ */ jsx4("code", { className: "incremark-inline-code", children: node.value }, i);
756
783
  }
757
784
  if (node.type === "link") {
758
- return /* @__PURE__ */ jsx3("a", { href: node.url, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsx3(IncremarkInline, { nodes: node.children }) }, i);
785
+ return /* @__PURE__ */ jsx4("a", { href: node.url, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsx4(IncremarkInline, { nodes: node.children }) }, i);
759
786
  }
760
787
  if (node.type === "image") {
761
788
  const imageNode = node;
762
- return /* @__PURE__ */ jsx3(
789
+ return /* @__PURE__ */ jsx4(
763
790
  "img",
764
791
  {
765
792
  src: imageNode.url,
@@ -773,7 +800,7 @@ var IncremarkInline = ({ nodes }) => {
773
800
  if (isImageReference(node)) {
774
801
  const definition = definitions[node.identifier];
775
802
  if (definition) {
776
- return /* @__PURE__ */ jsx3(
803
+ return /* @__PURE__ */ jsx4(
777
804
  "img",
778
805
  {
779
806
  src: definition.url,
@@ -795,14 +822,14 @@ var IncremarkInline = ({ nodes }) => {
795
822
  if (isLinkReference(node)) {
796
823
  const definition = definitions[node.identifier];
797
824
  if (definition) {
798
- return /* @__PURE__ */ jsx3(
825
+ return /* @__PURE__ */ jsx4(
799
826
  "a",
800
827
  {
801
828
  href: definition.url,
802
829
  title: definition.title || void 0,
803
830
  target: "_blank",
804
831
  rel: "noopener noreferrer",
805
- children: /* @__PURE__ */ jsx3(IncremarkInline, { nodes: node.children })
832
+ children: /* @__PURE__ */ jsx4(IncremarkInline, { nodes: node.children })
806
833
  },
807
834
  i
808
835
  );
@@ -818,78 +845,83 @@ var IncremarkInline = ({ nodes }) => {
818
845
  if (node.type === "footnoteReference") {
819
846
  const footnoteRef = node;
820
847
  const hasDefinition = footnoteDefinitions[footnoteRef.identifier];
821
- return /* @__PURE__ */ jsx3("sup", { className: "incremark-footnote-ref", children: /* @__PURE__ */ jsx3("a", { href: `#fn-${footnoteRef.identifier}`, id: `fnref-${footnoteRef.identifier}`, children: hasDefinition ? `[${footnoteRef.identifier}]` : `[^${footnoteRef.identifier}]` }) }, i);
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);
822
849
  }
823
850
  if (node.type === "break") {
824
- return /* @__PURE__ */ jsx3("br", {}, i);
851
+ return /* @__PURE__ */ jsx4("br", {}, i);
825
852
  }
826
853
  if (node.type === "delete") {
827
- return /* @__PURE__ */ jsx3("del", { children: /* @__PURE__ */ jsx3(IncremarkInline, { nodes: node.children }) }, i);
854
+ return /* @__PURE__ */ jsx4("del", { children: /* @__PURE__ */ jsx4(IncremarkInline, { nodes: node.children }) }, i);
828
855
  }
829
- return /* @__PURE__ */ jsx3("span", { children: node.value || "" }, i);
856
+ return /* @__PURE__ */ jsx4("span", { children: node.value || "" }, i);
830
857
  }) });
831
858
  };
832
859
 
833
860
  // src/components/IncremarkHeading.tsx
834
- import { jsx as jsx4 } from "react/jsx-runtime";
861
+ import { jsx as jsx5 } from "react/jsx-runtime";
835
862
  var IncremarkHeading = ({ node }) => {
836
863
  const Tag = `h${node.depth}`;
837
- return /* @__PURE__ */ jsx4(Tag, { className: `incremark-heading h${node.depth}`, children: /* @__PURE__ */ jsx4(IncremarkInline, { nodes: node.children }) });
864
+ return /* @__PURE__ */ jsx5(Tag, { className: `incremark-heading h${node.depth}`, children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children }) });
838
865
  };
839
866
 
840
867
  // src/components/IncremarkParagraph.tsx
841
- import { jsx as jsx5 } from "react/jsx-runtime";
868
+ import { jsx as jsx6 } from "react/jsx-runtime";
842
869
  var IncremarkParagraph = ({ node }) => {
843
- return /* @__PURE__ */ jsx5("p", { className: "incremark-paragraph", children: /* @__PURE__ */ jsx5(IncremarkInline, { nodes: node.children }) });
870
+ return /* @__PURE__ */ jsx6("p", { className: "incremark-paragraph", children: /* @__PURE__ */ jsx6(IncremarkInline, { nodes: node.children }) });
844
871
  };
845
872
 
846
873
  // src/components/IncremarkCode.tsx
847
- import React4, { useState as useState5, useEffect as useEffect4, useRef as useRef5, useCallback as useCallback5 } from "react";
848
- import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
849
- var IncremarkCode = ({
874
+ import React7 from "react";
875
+
876
+ // src/components/IncremarkCodeMermaid.tsx
877
+ import { useState as useState5, useEffect as useEffect4, useRef as useRef5, useCallback as useCallback5 } from "react";
878
+ import { GravityMermaid, LucideCode, LucideEye, LucideCopy, LucideCopyCheck } from "@incremark/icons";
879
+ import { isClipboardAvailable } from "@incremark/shared";
880
+
881
+ // src/components/SvgIcon.tsx
882
+ import { jsx as jsx7 } from "react/jsx-runtime";
883
+ var SvgIcon = ({
884
+ svg,
885
+ sizeClass,
886
+ className
887
+ }) => {
888
+ return /* @__PURE__ */ jsx7(
889
+ "span",
890
+ {
891
+ className: `incremark-icon ${sizeClass || ""} ${className || ""}`.trim(),
892
+ dangerouslySetInnerHTML: { __html: svg },
893
+ "aria-hidden": "true"
894
+ }
895
+ );
896
+ };
897
+
898
+ // src/components/IncremarkCodeMermaid.tsx
899
+ import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
900
+ var IncremarkCodeMermaid = ({
850
901
  node,
851
- theme = "github-dark",
852
- fallbackTheme = "github-dark",
853
- disableHighlight = false,
854
- mermaidDelay = 500,
855
- customCodeBlocks,
856
- blockStatus = "completed",
857
- codeBlockConfigs
902
+ mermaidDelay = 500
858
903
  }) => {
859
904
  const [copied, setCopied] = useState5(false);
860
- const [highlightedHtml, setHighlightedHtml] = useState5("");
861
- const [isHighlighting, setIsHighlighting] = useState5(false);
905
+ const { t } = useLocale();
862
906
  const [mermaidSvg, setMermaidSvg] = useState5("");
863
907
  const [mermaidLoading, setMermaidLoading] = useState5(false);
864
908
  const [mermaidViewMode, setMermaidViewMode] = useState5("preview");
865
909
  const mermaidRef = useRef5(null);
866
- const highlighterRef = useRef5(null);
867
910
  const mermaidTimerRef = useRef5(null);
868
- const loadedLanguagesRef = useRef5(/* @__PURE__ */ new Set());
869
- const loadedThemesRef = useRef5(/* @__PURE__ */ new Set());
870
- const language = node.lang || "text";
911
+ const copyTimeoutRef = useRef5(null);
871
912
  const code = node.value;
872
- const isMermaid = language === "mermaid";
873
- const CustomCodeBlock = React4.useMemo(() => {
874
- const component = customCodeBlocks?.[language];
875
- if (!component) return null;
876
- const config = codeBlockConfigs?.[language];
877
- if (config?.takeOver) {
878
- return component;
879
- }
880
- if (blockStatus !== "completed") {
881
- return null;
882
- }
883
- return component;
884
- }, [customCodeBlocks, language, blockStatus, codeBlockConfigs]);
885
913
  const toggleMermaidView = useCallback5(() => {
886
914
  setMermaidViewMode((prev) => prev === "preview" ? "source" : "preview");
887
915
  }, []);
888
916
  const copyCode = useCallback5(async () => {
917
+ if (!isClipboardAvailable()) return;
889
918
  try {
890
919
  await navigator.clipboard.writeText(code);
891
920
  setCopied(true);
892
- setTimeout(() => setCopied(false), 2e3);
921
+ if (copyTimeoutRef.current) {
922
+ clearTimeout(copyTimeoutRef.current);
923
+ }
924
+ copyTimeoutRef.current = setTimeout(() => setCopied(false), 2e3);
893
925
  } catch {
894
926
  }
895
927
  }, [code]);
@@ -902,7 +934,8 @@ var IncremarkCode = ({
902
934
  mermaidRef.current.initialize({
903
935
  startOnLoad: false,
904
936
  theme: "dark",
905
- securityLevel: "loose"
937
+ securityLevel: "loose",
938
+ suppressErrorRendering: true
906
939
  });
907
940
  }
908
941
  const mermaid = mermaidRef.current;
@@ -916,7 +949,7 @@ var IncremarkCode = ({
916
949
  }
917
950
  }, [code]);
918
951
  const scheduleRenderMermaid = useCallback5(() => {
919
- if (!isMermaid || !code) return;
952
+ if (!code) return;
920
953
  if (mermaidTimerRef.current) {
921
954
  clearTimeout(mermaidTimerRef.current);
922
955
  }
@@ -924,66 +957,293 @@ var IncremarkCode = ({
924
957
  mermaidTimerRef.current = setTimeout(() => {
925
958
  doRenderMermaid();
926
959
  }, mermaidDelay);
927
- }, [isMermaid, code, mermaidDelay, doRenderMermaid]);
928
- const highlight = useCallback5(async () => {
929
- if (isMermaid) {
930
- scheduleRenderMermaid();
931
- return;
960
+ }, [code, mermaidDelay, doRenderMermaid]);
961
+ useEffect4(() => {
962
+ scheduleRenderMermaid();
963
+ }, [scheduleRenderMermaid]);
964
+ useEffect4(() => {
965
+ return () => {
966
+ if (mermaidTimerRef.current) {
967
+ clearTimeout(mermaidTimerRef.current);
968
+ }
969
+ if (copyTimeoutRef.current) {
970
+ clearTimeout(copyTimeoutRef.current);
971
+ }
972
+ };
973
+ }, []);
974
+ return /* @__PURE__ */ jsxs2("div", { className: "incremark-mermaid", children: [
975
+ /* @__PURE__ */ jsxs2("div", { className: "mermaid-header", children: [
976
+ /* @__PURE__ */ jsxs2("span", { className: "language", children: [
977
+ /* @__PURE__ */ jsx8(SvgIcon, { svg: GravityMermaid, className: "language-icon" }),
978
+ "MERMAID"
979
+ ] }),
980
+ /* @__PURE__ */ jsxs2("div", { className: "mermaid-actions", children: [
981
+ /* @__PURE__ */ jsx8(
982
+ "button",
983
+ {
984
+ className: "code-btn",
985
+ onClick: toggleMermaidView,
986
+ type: "button",
987
+ disabled: !mermaidSvg,
988
+ "aria-label": mermaidViewMode === "preview" ? t("mermaid.viewSource") : t("mermaid.preview"),
989
+ title: mermaidViewMode === "preview" ? "View Source" : "Preview",
990
+ children: /* @__PURE__ */ jsx8(SvgIcon, { svg: mermaidViewMode === "preview" ? LucideCode : LucideEye })
991
+ }
992
+ ),
993
+ /* @__PURE__ */ jsx8(
994
+ "button",
995
+ {
996
+ className: "code-btn",
997
+ onClick: copyCode,
998
+ type: "button",
999
+ "aria-label": copied ? t("mermaid.copied") : t("mermaid.copy"),
1000
+ title: copied ? "Copied!" : "Copy",
1001
+ children: /* @__PURE__ */ jsx8(SvgIcon, { svg: copied ? LucideCopyCheck : LucideCopy })
1002
+ }
1003
+ )
1004
+ ] })
1005
+ ] }),
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 }) })
1007
+ ] });
1008
+ };
1009
+
1010
+ // src/components/IncremarkCodeDefault.tsx
1011
+ import { useState as useState6, useEffect as useEffect5, useCallback as useCallback6, useRef as useRef6 } from "react";
1012
+ import { LucideCopy as LucideCopy2, LucideCopyCheck as LucideCopyCheck2 } from "@incremark/icons";
1013
+ import { isClipboardAvailable as isClipboardAvailable2 } from "@incremark/shared";
1014
+
1015
+ // src/hooks/useShiki.ts
1016
+ import React5 from "react";
1017
+ var ShikiManager = class _ShikiManager {
1018
+ static instance = null;
1019
+ /** 存储 highlighter 实例,key 为主题名称 */
1020
+ highlighters = /* @__PURE__ */ new Map();
1021
+ constructor() {
1022
+ }
1023
+ static getInstance() {
1024
+ if (!_ShikiManager.instance) {
1025
+ _ShikiManager.instance = new _ShikiManager();
932
1026
  }
933
- if (!code || disableHighlight) {
934
- setHighlightedHtml("");
935
- return;
1027
+ return _ShikiManager.instance;
1028
+ }
1029
+ /**
1030
+ * 获取或创建 highlighter
1031
+ * @param theme 主题名称
1032
+ * @returns highlighter 实例
1033
+ */
1034
+ async getHighlighter(theme) {
1035
+ if (this.highlighters.has(theme)) {
1036
+ return this.highlighters.get(theme);
936
1037
  }
937
- setIsHighlighting(true);
1038
+ const { createHighlighter } = await import("shiki");
1039
+ const highlighter = await createHighlighter({
1040
+ themes: [theme],
1041
+ langs: []
1042
+ });
1043
+ const info = {
1044
+ highlighter,
1045
+ loadedLanguages: /* @__PURE__ */ new Set(),
1046
+ loadedThemes: /* @__PURE__ */ new Set([theme])
1047
+ };
1048
+ this.highlighters.set(theme, info);
1049
+ return info;
1050
+ }
1051
+ /**
1052
+ * 加载语言(按需)
1053
+ * @param theme 主题名称
1054
+ * @param lang 语言名称
1055
+ */
1056
+ async loadLanguage(theme, lang) {
1057
+ const info = this.highlighters.get(theme);
1058
+ if (!info || info.loadedLanguages.has(lang)) return;
938
1059
  try {
939
- if (!highlighterRef.current) {
940
- const { createHighlighter } = await import("shiki");
941
- highlighterRef.current = await createHighlighter({
942
- themes: [theme],
943
- langs: []
944
- });
945
- loadedThemesRef.current.add(theme);
1060
+ await info.highlighter.loadLanguage(lang);
1061
+ info.loadedLanguages.add(lang);
1062
+ } catch {
1063
+ }
1064
+ }
1065
+ /**
1066
+ * 加载主题(按需)
1067
+ * @param theme 主题名称
1068
+ */
1069
+ async loadTheme(theme) {
1070
+ const info = this.highlighters.get(theme);
1071
+ if (!info || info.loadedThemes.has(theme)) return;
1072
+ try {
1073
+ await info.highlighter.loadTheme(theme);
1074
+ info.loadedThemes.add(theme);
1075
+ } catch {
1076
+ }
1077
+ }
1078
+ /**
1079
+ * 高亮代码
1080
+ * @param theme 主题名称
1081
+ * @param code 代码内容
1082
+ * @param lang 语言名称
1083
+ * @param fallbackTheme 回退主题
1084
+ * @returns 高亮后的 HTML
1085
+ */
1086
+ async codeToHtml(theme, code, lang, fallbackTheme) {
1087
+ const info = this.highlighters.get(theme);
1088
+ if (!info) throw new Error("Highlighter not found");
1089
+ const actualLang = info.loadedLanguages.has(lang) ? lang : "text";
1090
+ const actualTheme = info.loadedThemes.has(theme) ? theme : fallbackTheme;
1091
+ return info.highlighter.codeToHtml(code, {
1092
+ lang: actualLang,
1093
+ theme: actualTheme
1094
+ });
1095
+ }
1096
+ /**
1097
+ * 清理所有 highlighter(应用退出或需要重置时调用)
1098
+ */
1099
+ disposeAll() {
1100
+ for (const [, info] of this.highlighters) {
1101
+ if (info.highlighter?.dispose) {
1102
+ info.highlighter.dispose();
946
1103
  }
947
- const highlighter = highlighterRef.current;
948
- const lang = language;
949
- if (!loadedLanguagesRef.current.has(lang) && lang !== "text") {
950
- try {
951
- await highlighter.loadLanguage(lang);
952
- loadedLanguagesRef.current.add(lang);
953
- } catch {
954
- }
1104
+ }
1105
+ this.highlighters.clear();
1106
+ }
1107
+ };
1108
+ var shikiManagerInstance = null;
1109
+ function getShikiManager() {
1110
+ if (!shikiManagerInstance) {
1111
+ shikiManagerInstance = ShikiManager.getInstance();
1112
+ }
1113
+ return shikiManagerInstance;
1114
+ }
1115
+ 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);
1121
+ }
1122
+ return highlighterInfoRef.current;
1123
+ }, [theme]);
1124
+ const highlight = React5.useCallback(async (code, lang, fallbackTheme) => {
1125
+ setIsHighlighting(true);
1126
+ try {
1127
+ const info = await getHighlighter();
1128
+ const manager = getShikiManager();
1129
+ if (!info.loadedLanguages.has(lang) && lang !== "text") {
1130
+ await manager.loadLanguage(theme, lang);
955
1131
  }
956
- if (!loadedThemesRef.current.has(theme)) {
957
- try {
958
- await highlighter.loadTheme(theme);
959
- loadedThemesRef.current.add(theme);
960
- } catch {
961
- }
1132
+ if (!info.loadedThemes.has(theme)) {
1133
+ await manager.loadTheme(theme);
962
1134
  }
963
- const html = highlighter.codeToHtml(code, {
964
- lang: loadedLanguagesRef.current.has(lang) ? lang : "text",
965
- theme: loadedThemesRef.current.has(theme) ? theme : fallbackTheme
966
- });
967
- setHighlightedHtml(html);
968
- } catch {
969
- setHighlightedHtml("");
1135
+ return await manager.codeToHtml(theme, code, lang, fallbackTheme);
1136
+ } catch (e) {
1137
+ throw e;
970
1138
  } finally {
971
1139
  setIsHighlighting(false);
972
1140
  }
973
- }, [code, language, theme, fallbackTheme, disableHighlight, isMermaid, scheduleRenderMermaid]);
974
- useEffect4(() => {
975
- highlight();
976
- }, [highlight]);
977
- useEffect4(() => {
1141
+ }, [getHighlighter, theme]);
1142
+ return {
1143
+ isHighlighting,
1144
+ highlight
1145
+ };
1146
+ }
1147
+
1148
+ // src/components/IncremarkCodeDefault.tsx
1149
+ import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
1150
+ var IncremarkCodeDefault = ({
1151
+ node,
1152
+ theme = "github-dark",
1153
+ fallbackTheme = "github-dark",
1154
+ disableHighlight = false
1155
+ }) => {
1156
+ const [copied, setCopied] = useState6(false);
1157
+ const [highlightedHtml, setHighlightedHtml] = useState6("");
1158
+ const language = node.lang || "text";
1159
+ const code = node.value;
1160
+ const { t } = useLocale();
1161
+ const { isHighlighting, highlight } = useShiki(theme);
1162
+ const copyTimeoutRef = useRef6(null);
1163
+ const copyCode = useCallback6(async () => {
1164
+ if (!isClipboardAvailable2()) return;
1165
+ try {
1166
+ await navigator.clipboard.writeText(code);
1167
+ setCopied(true);
1168
+ if (copyTimeoutRef.current) {
1169
+ clearTimeout(copyTimeoutRef.current);
1170
+ }
1171
+ copyTimeoutRef.current = setTimeout(() => setCopied(false), 2e3);
1172
+ } catch {
1173
+ }
1174
+ }, [code]);
1175
+ useEffect5(() => {
978
1176
  return () => {
979
- if (mermaidTimerRef.current) {
980
- clearTimeout(mermaidTimerRef.current);
1177
+ if (copyTimeoutRef.current) {
1178
+ clearTimeout(copyTimeoutRef.current);
981
1179
  }
982
1180
  };
983
1181
  }, []);
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
+ return /* @__PURE__ */ jsxs3("div", { className: "incremark-code", children: [
1198
+ /* @__PURE__ */ jsxs3("div", { className: "code-header", children: [
1199
+ /* @__PURE__ */ jsx9("span", { className: "language", children: language }),
1200
+ /* @__PURE__ */ jsx9(
1201
+ "button",
1202
+ {
1203
+ className: "code-btn",
1204
+ onClick: copyCode,
1205
+ type: "button",
1206
+ "aria-label": copied ? t("code.copied") : t("code.copy"),
1207
+ title: copied ? "Copied!" : "Copy",
1208
+ children: /* @__PURE__ */ jsx9(SvgIcon, { svg: copied ? LucideCopyCheck2 : LucideCopy2 })
1209
+ }
1210
+ )
1211
+ ] }),
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 }) }) })
1213
+ ] });
1214
+ };
1215
+
1216
+ // src/components/IncremarkCode.tsx
1217
+ import { jsx as jsx10 } from "react/jsx-runtime";
1218
+ var IncremarkCode = ({
1219
+ node,
1220
+ theme = "github-dark",
1221
+ fallbackTheme = "github-dark",
1222
+ disableHighlight = false,
1223
+ mermaidDelay = 500,
1224
+ customCodeBlocks,
1225
+ blockStatus = "completed",
1226
+ codeBlockConfigs,
1227
+ defaultCodeComponent: DefaultCodeComponent = IncremarkCodeDefault
1228
+ }) => {
1229
+ const language = node.lang || "text";
1230
+ const code = node.value;
1231
+ const isMermaid = language === "mermaid";
1232
+ const CustomCodeBlock = React7.useMemo(() => {
1233
+ const component = customCodeBlocks?.[language];
1234
+ if (!component) return null;
1235
+ const config = codeBlockConfigs?.[language];
1236
+ if (config?.takeOver) {
1237
+ return component;
1238
+ }
1239
+ if (blockStatus !== "completed") {
1240
+ return null;
1241
+ }
1242
+ return component;
1243
+ }, [customCodeBlocks, language, blockStatus, codeBlockConfigs]);
984
1244
  if (CustomCodeBlock) {
985
1245
  const config = codeBlockConfigs?.[language];
986
- return /* @__PURE__ */ jsx6(
1246
+ return /* @__PURE__ */ jsx10(
987
1247
  CustomCodeBlock,
988
1248
  {
989
1249
  codeStr: code,
@@ -994,38 +1254,28 @@ var IncremarkCode = ({
994
1254
  );
995
1255
  }
996
1256
  if (isMermaid) {
997
- return /* @__PURE__ */ jsxs2("div", { className: "incremark-mermaid", children: [
998
- /* @__PURE__ */ jsxs2("div", { className: "mermaid-header", children: [
999
- /* @__PURE__ */ jsx6("span", { className: "language", children: "MERMAID" }),
1000
- /* @__PURE__ */ jsxs2("div", { className: "mermaid-actions", children: [
1001
- /* @__PURE__ */ jsx6(
1002
- "button",
1003
- {
1004
- className: "code-btn",
1005
- onClick: toggleMermaidView,
1006
- type: "button",
1007
- disabled: !mermaidSvg,
1008
- children: mermaidViewMode === "preview" ? "\u6E90\u7801" : "\u9884\u89C8"
1009
- }
1010
- ),
1011
- /* @__PURE__ */ jsx6("button", { className: "code-btn", onClick: copyCode, type: "button", children: copied ? "\u2713 \u5DF2\u590D\u5236" : "\u590D\u5236" })
1012
- ] })
1013
- ] }),
1014
- /* @__PURE__ */ jsx6("div", { className: "mermaid-content", children: mermaidLoading && !mermaidSvg ? /* @__PURE__ */ jsx6("div", { className: "mermaid-loading", children: /* @__PURE__ */ jsx6("pre", { className: "mermaid-source-code", children: code }) }) : mermaidViewMode === "source" ? /* @__PURE__ */ jsx6("pre", { className: "mermaid-source-code", children: code }) : mermaidSvg ? /* @__PURE__ */ jsx6("div", { className: "mermaid-svg", dangerouslySetInnerHTML: { __html: mermaidSvg } }) : /* @__PURE__ */ jsx6("pre", { className: "mermaid-source-code", children: code }) })
1015
- ] });
1257
+ return /* @__PURE__ */ jsx10(
1258
+ IncremarkCodeMermaid,
1259
+ {
1260
+ node,
1261
+ mermaidDelay
1262
+ }
1263
+ );
1016
1264
  }
1017
- return /* @__PURE__ */ jsxs2("div", { className: "incremark-code", children: [
1018
- /* @__PURE__ */ jsxs2("div", { className: "code-header", children: [
1019
- /* @__PURE__ */ jsx6("span", { className: "language", children: language }),
1020
- /* @__PURE__ */ jsx6("button", { className: "code-btn", onClick: copyCode, type: "button", children: copied ? "\u2713 \u5DF2\u590D\u5236" : "\u590D\u5236" })
1021
- ] }),
1022
- /* @__PURE__ */ jsx6("div", { className: "code-content", children: isHighlighting && !highlightedHtml ? /* @__PURE__ */ jsx6("div", { className: "code-loading", children: /* @__PURE__ */ jsx6("pre", { children: /* @__PURE__ */ jsx6("code", { children: code }) }) }) : highlightedHtml ? /* @__PURE__ */ jsx6("div", { className: "shiki-wrapper", dangerouslySetInnerHTML: { __html: highlightedHtml } }) : /* @__PURE__ */ jsx6("pre", { className: "code-fallback", children: /* @__PURE__ */ jsx6("code", { children: code }) }) })
1023
- ] });
1265
+ return /* @__PURE__ */ jsx10(
1266
+ DefaultCodeComponent,
1267
+ {
1268
+ node,
1269
+ theme,
1270
+ fallbackTheme,
1271
+ disableHighlight
1272
+ }
1273
+ );
1024
1274
  };
1025
1275
 
1026
1276
  // src/components/IncremarkList.tsx
1027
- import React5 from "react";
1028
- import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
1277
+ import React8 from "react";
1278
+ import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
1029
1279
  function getItemInlineContent(item) {
1030
1280
  const firstChild = item.children[0];
1031
1281
  if (firstChild?.type === "paragraph") {
@@ -1044,13 +1294,13 @@ function getItemBlockChildren(item) {
1044
1294
  var IncremarkList = ({ node }) => {
1045
1295
  const Tag = node.ordered ? "ol" : "ul";
1046
1296
  const isTaskList = node.children?.some((item) => item.checked !== null && item.checked !== void 0);
1047
- return /* @__PURE__ */ jsx7(Tag, { className: `incremark-list ${isTaskList ? "task-list" : ""}`, children: node.children?.map((item, index) => {
1297
+ return /* @__PURE__ */ jsx11(Tag, { className: `incremark-list ${isTaskList ? "task-list" : ""}`, start: node.start || void 0, children: node.children?.map((item, index) => {
1048
1298
  const isTaskItem = item.checked !== null && item.checked !== void 0;
1049
1299
  const inlineContent = getItemInlineContent(item);
1050
1300
  const blockChildren = getItemBlockChildren(item);
1051
1301
  if (isTaskItem) {
1052
- return /* @__PURE__ */ jsx7("li", { className: "incremark-list-item task-item", children: /* @__PURE__ */ jsxs3("label", { className: "task-label", children: [
1053
- /* @__PURE__ */ jsx7(
1302
+ return /* @__PURE__ */ jsx11("li", { className: "incremark-list-item task-item", children: /* @__PURE__ */ jsxs4("label", { className: "task-label", children: [
1303
+ /* @__PURE__ */ jsx11(
1054
1304
  "input",
1055
1305
  {
1056
1306
  type: "checkbox",
@@ -1059,43 +1309,43 @@ var IncremarkList = ({ node }) => {
1059
1309
  className: "checkbox"
1060
1310
  }
1061
1311
  ),
1062
- /* @__PURE__ */ jsx7("span", { className: "task-content", children: /* @__PURE__ */ jsx7(IncremarkInline, { nodes: inlineContent }) })
1312
+ /* @__PURE__ */ jsx11("span", { className: "task-content", children: /* @__PURE__ */ jsx11(IncremarkInline, { nodes: inlineContent }) })
1063
1313
  ] }) }, index);
1064
1314
  }
1065
- return /* @__PURE__ */ jsxs3("li", { className: "incremark-list-item", children: [
1066
- /* @__PURE__ */ jsx7(IncremarkInline, { nodes: inlineContent }),
1067
- blockChildren.map((child, childIndex) => /* @__PURE__ */ jsx7(React5.Fragment, { children: /* @__PURE__ */ jsx7(IncremarkRenderer, { node: child }) }, childIndex))
1315
+ 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))
1068
1318
  ] }, index);
1069
1319
  }) });
1070
1320
  };
1071
1321
 
1072
1322
  // src/components/IncremarkBlockquote.tsx
1073
- import React6 from "react";
1074
- import { jsx as jsx8 } from "react/jsx-runtime";
1323
+ import React9 from "react";
1324
+ import { jsx as jsx12 } from "react/jsx-runtime";
1075
1325
  var IncremarkBlockquote = ({ node }) => {
1076
- return /* @__PURE__ */ jsx8("blockquote", { className: "incremark-blockquote", children: node.children.map((child, index) => /* @__PURE__ */ jsx8(React6.Fragment, { children: /* @__PURE__ */ jsx8(IncremarkRenderer, { node: child }) }, index)) });
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)) });
1077
1327
  };
1078
1328
 
1079
1329
  // src/components/IncremarkTable.tsx
1080
- import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
1330
+ import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
1081
1331
  function getCellContent(cell) {
1082
1332
  return cell.children;
1083
1333
  }
1084
1334
  var IncremarkTable = ({ node }) => {
1085
- return /* @__PURE__ */ jsx9("div", { className: "incremark-table-wrapper", children: /* @__PURE__ */ jsxs4("table", { className: "incremark-table", children: [
1086
- /* @__PURE__ */ jsx9("thead", { children: node.children?.[0] && /* @__PURE__ */ jsx9("tr", { children: node.children[0].children.map((cell, cellIndex) => /* @__PURE__ */ jsx9(
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(
1087
1337
  "th",
1088
1338
  {
1089
- style: { textAlign: node.align?.[cellIndex] || "left" },
1090
- children: /* @__PURE__ */ jsx9(IncremarkInline, { nodes: getCellContent(cell) })
1339
+ className: `incremark-table-align-${node.align?.[cellIndex] || "left"}`,
1340
+ children: /* @__PURE__ */ jsx13(IncremarkInline, { nodes: getCellContent(cell) })
1091
1341
  },
1092
1342
  cellIndex
1093
1343
  )) }) }),
1094
- /* @__PURE__ */ jsx9("tbody", { children: node.children?.slice(1).map((row, rowIndex) => /* @__PURE__ */ jsx9("tr", { children: row.children.map((cell, cellIndex) => /* @__PURE__ */ jsx9(
1344
+ /* @__PURE__ */ jsx13("tbody", { children: node.children?.slice(1).map((row, rowIndex) => /* @__PURE__ */ jsx13("tr", { children: row.children.map((cell, cellIndex) => /* @__PURE__ */ jsx13(
1095
1345
  "td",
1096
1346
  {
1097
- style: { textAlign: node.align?.[cellIndex] || "left" },
1098
- children: /* @__PURE__ */ jsx9(IncremarkInline, { nodes: getCellContent(cell) })
1347
+ className: `incremark-table-align-${node.align?.[cellIndex] || "left"}`,
1348
+ children: /* @__PURE__ */ jsx13(IncremarkInline, { nodes: getCellContent(cell) })
1099
1349
  },
1100
1350
  cellIndex
1101
1351
  )) }, rowIndex)) })
@@ -1103,25 +1353,25 @@ var IncremarkTable = ({ node }) => {
1103
1353
  };
1104
1354
 
1105
1355
  // src/components/IncremarkThematicBreak.tsx
1106
- import { jsx as jsx10 } from "react/jsx-runtime";
1356
+ import { jsx as jsx14 } from "react/jsx-runtime";
1107
1357
  var IncremarkThematicBreak = () => {
1108
- return /* @__PURE__ */ jsx10("hr", { className: "incremark-hr" });
1358
+ return /* @__PURE__ */ jsx14("hr", { className: "incremark-hr" });
1109
1359
  };
1110
1360
 
1111
1361
  // src/components/IncremarkMath.tsx
1112
- import { useState as useState6, useEffect as useEffect5, useRef as useRef6, useCallback as useCallback6 } from "react";
1113
- import { jsx as jsx11 } from "react/jsx-runtime";
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";
1114
1364
  var IncremarkMath = ({
1115
1365
  node,
1116
1366
  renderDelay = 300
1117
1367
  }) => {
1118
- const [renderedHtml, setRenderedHtml] = useState6("");
1119
- const [isLoading, setIsLoading] = useState6(false);
1120
- const katexRef = useRef6(null);
1121
- const renderTimerRef = useRef6(null);
1368
+ const [renderedHtml, setRenderedHtml] = useState7("");
1369
+ const [isLoading, setIsLoading] = useState7(false);
1370
+ const katexRef = useRef7(null);
1371
+ const renderTimerRef = useRef7(null);
1122
1372
  const isInline = node.type === "inlineMath";
1123
1373
  const formula = node.value;
1124
- const doRender = useCallback6(async () => {
1374
+ const doRender = useCallback7(async () => {
1125
1375
  if (!formula) return;
1126
1376
  try {
1127
1377
  if (!katexRef.current) {
@@ -1141,7 +1391,7 @@ var IncremarkMath = ({
1141
1391
  setIsLoading(false);
1142
1392
  }
1143
1393
  }, [formula, isInline]);
1144
- const scheduleRender = useCallback6(() => {
1394
+ const scheduleRender = useCallback7(() => {
1145
1395
  if (!formula) {
1146
1396
  setRenderedHtml("");
1147
1397
  return;
@@ -1154,10 +1404,10 @@ var IncremarkMath = ({
1154
1404
  doRender();
1155
1405
  }, renderDelay);
1156
1406
  }, [formula, renderDelay, doRender]);
1157
- useEffect5(() => {
1407
+ useEffect6(() => {
1158
1408
  scheduleRender();
1159
1409
  }, [scheduleRender]);
1160
- useEffect5(() => {
1410
+ useEffect6(() => {
1161
1411
  return () => {
1162
1412
  if (renderTimerRef.current) {
1163
1413
  clearTimeout(renderTimerRef.current);
@@ -1165,13 +1415,13 @@ var IncremarkMath = ({
1165
1415
  };
1166
1416
  }, []);
1167
1417
  if (isInline) {
1168
- return /* @__PURE__ */ jsx11("span", { className: "incremark-math-inline", children: renderedHtml && !isLoading ? /* @__PURE__ */ jsx11("span", { dangerouslySetInnerHTML: { __html: renderedHtml } }) : /* @__PURE__ */ jsx11("code", { className: "math-source", children: formula }) });
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 }) });
1169
1419
  }
1170
- return /* @__PURE__ */ jsx11("div", { className: "incremark-math-block", children: renderedHtml && !isLoading ? /* @__PURE__ */ jsx11("div", { className: "math-rendered", dangerouslySetInnerHTML: { __html: renderedHtml } }) : /* @__PURE__ */ jsx11("pre", { className: "math-source-block", children: /* @__PURE__ */ jsx11("code", { children: formula }) }) });
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 }) }) });
1171
1421
  };
1172
1422
 
1173
1423
  // src/components/IncremarkContainer.tsx
1174
- import { jsx as jsx12 } from "react/jsx-runtime";
1424
+ import { jsx as jsx16 } from "react/jsx-runtime";
1175
1425
  function parseOptions(attributes) {
1176
1426
  if (!attributes) return {};
1177
1427
  const options = {};
@@ -1189,22 +1439,22 @@ var IncremarkContainer = ({ node, customContainers }) => {
1189
1439
  const options = parseOptions(node.attributes);
1190
1440
  const CustomContainer = customContainers?.[containerName];
1191
1441
  if (CustomContainer) {
1192
- return /* @__PURE__ */ jsx12(CustomContainer, { name: containerName, options, children: node.children?.map((child, index) => /* @__PURE__ */ jsx12(IncremarkRenderer, { node: child }, index)) });
1442
+ return /* @__PURE__ */ jsx16(CustomContainer, { name: containerName, options, children: node.children?.map((child, index) => /* @__PURE__ */ jsx16(IncremarkRenderer, { node: child }, index)) });
1193
1443
  }
1194
- return /* @__PURE__ */ jsx12("div", { className: `incremark-container incremark-container-${containerName}`, children: node.children && node.children.length > 0 && /* @__PURE__ */ jsx12("div", { className: "incremark-container-content", children: node.children.map((child, index) => /* @__PURE__ */ jsx12(IncremarkRenderer, { node: child }, index)) }) });
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)) }) });
1195
1445
  };
1196
1446
 
1197
1447
  // src/components/IncremarkDefault.tsx
1198
- import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
1448
+ import { jsx as jsx17, jsxs as jsxs6 } from "react/jsx-runtime";
1199
1449
  var IncremarkDefault = ({ node }) => {
1200
- return /* @__PURE__ */ jsxs5("div", { className: "incremark-default", children: [
1201
- /* @__PURE__ */ jsx13("span", { className: "type-badge", children: node.type }),
1202
- /* @__PURE__ */ jsx13("pre", { children: JSON.stringify(node, null, 2) })
1450
+ 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) })
1203
1453
  ] });
1204
1454
  };
1205
1455
 
1206
1456
  // src/components/IncremarkRenderer.tsx
1207
- import { jsx as jsx14 } from "react/jsx-runtime";
1457
+ import { jsx as jsx18 } from "react/jsx-runtime";
1208
1458
  var defaultComponents = {
1209
1459
  heading: IncremarkHeading,
1210
1460
  paragraph: IncremarkParagraph,
@@ -1240,10 +1490,10 @@ var IncremarkRenderer = ({
1240
1490
  return null;
1241
1491
  }
1242
1492
  if (isHtmlNode2(node)) {
1243
- return /* @__PURE__ */ jsx14("pre", { className: "incremark-html-code", children: /* @__PURE__ */ jsx14("code", { children: node.value }) });
1493
+ return /* @__PURE__ */ jsx18("pre", { className: "incremark-html-code", children: /* @__PURE__ */ jsx18("code", { children: node.value }) });
1244
1494
  }
1245
1495
  if (isContainerNode(node)) {
1246
- return /* @__PURE__ */ jsx14(
1496
+ return /* @__PURE__ */ jsx18(
1247
1497
  IncremarkContainer,
1248
1498
  {
1249
1499
  node,
@@ -1252,26 +1502,27 @@ var IncremarkRenderer = ({
1252
1502
  );
1253
1503
  }
1254
1504
  if (node.type === "code") {
1255
- return /* @__PURE__ */ jsx14(
1505
+ return /* @__PURE__ */ jsx18(
1256
1506
  IncremarkCode,
1257
1507
  {
1258
1508
  node,
1259
1509
  customCodeBlocks,
1260
1510
  codeBlockConfigs,
1261
- blockStatus
1511
+ blockStatus,
1512
+ defaultCodeComponent: components?.["code"]
1262
1513
  }
1263
1514
  );
1264
1515
  }
1265
1516
  const Component = getComponent(node.type, components);
1266
- return /* @__PURE__ */ jsx14(Component, { node });
1517
+ return /* @__PURE__ */ jsx18(Component, { node });
1267
1518
  };
1268
1519
 
1269
1520
  // src/components/IncremarkFootnotes.tsx
1270
- import React8 from "react";
1271
- import { jsx as jsx15, jsxs as jsxs6 } from "react/jsx-runtime";
1521
+ import React11 from "react";
1522
+ import { jsx as jsx19, jsxs as jsxs7 } from "react/jsx-runtime";
1272
1523
  var IncremarkFootnotes = () => {
1273
1524
  const { footnoteDefinitions, footnoteReferenceOrder } = useDefinitions();
1274
- const orderedFootnotes = React8.useMemo(() => {
1525
+ const orderedFootnotes = React11.useMemo(() => {
1275
1526
  return footnoteReferenceOrder.map((identifier) => ({
1276
1527
  identifier,
1277
1528
  definition: footnoteDefinitions[identifier]
@@ -1280,22 +1531,22 @@ var IncremarkFootnotes = () => {
1280
1531
  if (orderedFootnotes.length === 0) {
1281
1532
  return null;
1282
1533
  }
1283
- return /* @__PURE__ */ jsxs6("section", { className: "incremark-footnotes", children: [
1284
- /* @__PURE__ */ jsx15("hr", { className: "incremark-footnotes-divider" }),
1285
- /* @__PURE__ */ jsx15("ol", { className: "incremark-footnotes-list", children: orderedFootnotes.map((item, index) => /* @__PURE__ */ jsxs6(
1534
+ 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(
1286
1537
  "li",
1287
1538
  {
1288
1539
  id: `fn-${item.identifier}`,
1289
1540
  className: "incremark-footnote-item",
1290
1541
  children: [
1291
- /* @__PURE__ */ jsxs6("div", { className: "incremark-footnote-content", children: [
1292
- /* @__PURE__ */ jsxs6("span", { className: "incremark-footnote-number", children: [
1542
+ /* @__PURE__ */ jsxs7("div", { className: "incremark-footnote-content", children: [
1543
+ /* @__PURE__ */ jsxs7("span", { className: "incremark-footnote-number", children: [
1293
1544
  index + 1,
1294
1545
  "."
1295
1546
  ] }),
1296
- /* @__PURE__ */ jsx15("div", { className: "incremark-footnote-body", children: item.definition.children.map((child, childIndex) => /* @__PURE__ */ jsx15(IncremarkRenderer, { node: child }, childIndex)) })
1547
+ /* @__PURE__ */ jsx19("div", { className: "incremark-footnote-body", children: item.definition.children.map((child, childIndex) => /* @__PURE__ */ jsx19(IncremarkRenderer, { node: child }, childIndex)) })
1297
1548
  ] }),
1298
- /* @__PURE__ */ jsx15(
1549
+ /* @__PURE__ */ jsx19(
1299
1550
  "a",
1300
1551
  {
1301
1552
  href: `#fnref-${item.identifier}`,
@@ -1312,13 +1563,13 @@ var IncremarkFootnotes = () => {
1312
1563
  };
1313
1564
 
1314
1565
  // src/components/IncremarkContainerProvider.tsx
1315
- import { jsx as jsx16 } from "react/jsx-runtime";
1566
+ import { jsx as jsx20 } from "react/jsx-runtime";
1316
1567
  var IncremarkContainerProvider = ({ children, definitions }) => {
1317
- return /* @__PURE__ */ jsx16(DefinitionsContext.Provider, { value: definitions, children });
1568
+ return /* @__PURE__ */ jsx20(DefinitionsContext.Provider, { value: definitions, children });
1318
1569
  };
1319
1570
 
1320
1571
  // src/components/Incremark.tsx
1321
- import { jsx as jsx17, jsxs as jsxs7 } from "react/jsx-runtime";
1572
+ import { jsx as jsx21, jsxs as jsxs8 } from "react/jsx-runtime";
1322
1573
  var Incremark = (props) => {
1323
1574
  const {
1324
1575
  blocks: propsBlocks,
@@ -1328,11 +1579,13 @@ var Incremark = (props) => {
1328
1579
  customCodeBlocks,
1329
1580
  showBlockStatus = true,
1330
1581
  className = "",
1582
+ pendingClass = "incremark-pending",
1583
+ completedClass = "incremark-completed",
1331
1584
  incremark
1332
1585
  } = props;
1333
1586
  if (incremark) {
1334
1587
  const { blocks: blocks2, isDisplayComplete: isDisplayComplete2, _definitionsContextValue } = incremark;
1335
- return /* @__PURE__ */ jsx17(IncremarkContainerProvider, { definitions: _definitionsContextValue, children: /* @__PURE__ */ jsx17(
1588
+ return /* @__PURE__ */ jsx21(IncremarkContainerProvider, { definitions: _definitionsContextValue, children: /* @__PURE__ */ jsx21(
1336
1589
  IncremarkInternal,
1337
1590
  {
1338
1591
  blocks: blocks2,
@@ -1341,13 +1594,15 @@ var Incremark = (props) => {
1341
1594
  customCodeBlocks,
1342
1595
  showBlockStatus,
1343
1596
  className,
1597
+ pendingClass,
1598
+ completedClass,
1344
1599
  isDisplayComplete: isDisplayComplete2
1345
1600
  }
1346
1601
  ) });
1347
1602
  }
1348
1603
  const blocks = propsBlocks || [];
1349
1604
  const isDisplayComplete = propsIsDisplayComplete;
1350
- return /* @__PURE__ */ jsx17(
1605
+ return /* @__PURE__ */ jsx21(
1351
1606
  IncremarkInternal,
1352
1607
  {
1353
1608
  blocks,
@@ -1356,6 +1611,8 @@ var Incremark = (props) => {
1356
1611
  customCodeBlocks,
1357
1612
  showBlockStatus,
1358
1613
  className,
1614
+ pendingClass,
1615
+ completedClass,
1359
1616
  isDisplayComplete
1360
1617
  }
1361
1618
  );
@@ -1368,9 +1625,11 @@ var IncremarkInternal = ({
1368
1625
  codeBlockConfigs,
1369
1626
  showBlockStatus,
1370
1627
  className,
1628
+ pendingClass,
1629
+ completedClass,
1371
1630
  isDisplayComplete
1372
1631
  }) => {
1373
- return /* @__PURE__ */ jsxs7("div", { className: `incremark ${className}`, children: [
1632
+ return /* @__PURE__ */ jsxs8("div", { className: `incremark ${className}`, children: [
1374
1633
  blocks.map((block) => {
1375
1634
  if (block.node.type === "definition" || block.node.type === "footnoteDefinition") {
1376
1635
  return null;
@@ -1378,11 +1637,11 @@ var IncremarkInternal = ({
1378
1637
  const isPending = block.status === "pending";
1379
1638
  const classes = [
1380
1639
  "incremark-block",
1381
- isPending ? "incremark-pending" : "incremark-completed",
1640
+ isPending ? pendingClass : completedClass,
1382
1641
  showBlockStatus && "incremark-show-status",
1383
1642
  block.isLastPending && "incremark-last-pending"
1384
1643
  ].filter(Boolean).join(" ");
1385
- return /* @__PURE__ */ jsx17("div", { className: classes, children: /* @__PURE__ */ jsx17(
1644
+ return /* @__PURE__ */ jsx21("div", { className: classes, children: /* @__PURE__ */ jsx21(
1386
1645
  IncremarkRenderer,
1387
1646
  {
1388
1647
  node: block.node,
@@ -1392,22 +1651,112 @@ var IncremarkInternal = ({
1392
1651
  codeBlockConfigs,
1393
1652
  blockStatus: block.status
1394
1653
  }
1395
- ) }, block.stableId);
1654
+ ) }, block.id);
1396
1655
  }),
1397
- isDisplayComplete && /* @__PURE__ */ jsx17(IncremarkFootnotes, {})
1656
+ isDisplayComplete && /* @__PURE__ */ jsx21(IncremarkFootnotes, {})
1398
1657
  ] });
1399
1658
  };
1400
1659
 
1660
+ // 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";
1663
+ var IncremarkContent = (props) => {
1664
+ const {
1665
+ stream,
1666
+ content,
1667
+ components,
1668
+ customContainers,
1669
+ customCodeBlocks,
1670
+ codeBlockConfigs,
1671
+ isFinished = false,
1672
+ incremarkOptions,
1673
+ showBlockStatus,
1674
+ pendingClass
1675
+ } = props;
1676
+ const initialOptionsRef = useRef8({
1677
+ gfm: true,
1678
+ htmlTree: true,
1679
+ containers: true,
1680
+ math: true,
1681
+ ...incremarkOptions
1682
+ });
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);
1692
+ const handleStreamInput = useCallback8(async () => {
1693
+ if (!stream || isStreamingRef.current) return;
1694
+ isStreamingRef.current = true;
1695
+ try {
1696
+ const streamGen = stream();
1697
+ for await (const chunk of streamGen) {
1698
+ append(chunk);
1699
+ }
1700
+ finalize();
1701
+ } catch (error) {
1702
+ console.error("Stream error: ", error);
1703
+ finalize();
1704
+ } finally {
1705
+ isStreamingRef.current = false;
1706
+ }
1707
+ }, [stream, append, finalize]);
1708
+ const handleContentInput = useCallback8((newContent, oldContent) => {
1709
+ if (!newContent) {
1710
+ if (oldContent) {
1711
+ reset();
1712
+ }
1713
+ return;
1714
+ }
1715
+ if (newContent?.startsWith(oldContent ?? "")) {
1716
+ const delta = newContent.slice((oldContent || "").length);
1717
+ append(delta);
1718
+ } else {
1719
+ render(newContent);
1720
+ }
1721
+ }, [append, render, reset]);
1722
+ useEffect7(() => {
1723
+ if (isStreamMode) {
1724
+ handleStreamInput();
1725
+ } else {
1726
+ handleContentInput(content, prevContentRef.current);
1727
+ }
1728
+ prevContentRef.current = content;
1729
+ }, [content, isStreamMode, handleStreamInput, handleContentInput]);
1730
+ useEffect7(() => {
1731
+ if (isFinished && content === markdown) {
1732
+ finalize();
1733
+ }
1734
+ }, [isFinished, content, markdown, finalize]);
1735
+ return /* @__PURE__ */ jsx22(IncremarkContainerProvider, { definitions: _definitionsContextValue, children: /* @__PURE__ */ jsx22(
1736
+ Incremark,
1737
+ {
1738
+ blocks,
1739
+ isDisplayComplete,
1740
+ showBlockStatus,
1741
+ pendingClass,
1742
+ components,
1743
+ customContainers,
1744
+ customCodeBlocks,
1745
+ codeBlockConfigs
1746
+ }
1747
+ ) });
1748
+ };
1749
+
1401
1750
  // src/components/AutoScrollContainer.tsx
1402
1751
  import {
1403
- useRef as useRef7,
1404
- useEffect as useEffect6,
1405
- useCallback as useCallback7,
1406
- useState as useState7,
1752
+ useRef as useRef9,
1753
+ useEffect as useEffect8,
1754
+ useCallback as useCallback9,
1755
+ useState as useState8,
1407
1756
  forwardRef,
1408
1757
  useImperativeHandle
1409
1758
  } from "react";
1410
- import { jsx as jsx18 } from "react/jsx-runtime";
1759
+ import { jsx as jsx23 } from "react/jsx-runtime";
1411
1760
  var AutoScrollContainer = forwardRef(
1412
1761
  ({
1413
1762
  children,
@@ -1417,17 +1766,17 @@ var AutoScrollContainer = forwardRef(
1417
1766
  style,
1418
1767
  className
1419
1768
  }, ref) => {
1420
- const containerRef = useRef7(null);
1421
- const [isUserScrolledUp, setIsUserScrolledUp] = useState7(false);
1422
- const lastScrollTopRef = useRef7(0);
1423
- const lastScrollHeightRef = useRef7(0);
1424
- const isNearBottom = useCallback7(() => {
1769
+ const containerRef = useRef9(null);
1770
+ const [isUserScrolledUp, setIsUserScrolledUp] = useState8(false);
1771
+ const lastScrollTopRef = useRef9(0);
1772
+ const lastScrollHeightRef = useRef9(0);
1773
+ const isNearBottom = useCallback9(() => {
1425
1774
  const container = containerRef.current;
1426
1775
  if (!container) return true;
1427
1776
  const { scrollTop, scrollHeight, clientHeight } = container;
1428
1777
  return scrollHeight - scrollTop - clientHeight <= threshold;
1429
1778
  }, [threshold]);
1430
- const scrollToBottom = useCallback7(
1779
+ const scrollToBottom = useCallback9(
1431
1780
  (force = false) => {
1432
1781
  const container = containerRef.current;
1433
1782
  if (!container) return;
@@ -1439,12 +1788,12 @@ var AutoScrollContainer = forwardRef(
1439
1788
  },
1440
1789
  [isUserScrolledUp, behavior]
1441
1790
  );
1442
- const hasScrollbar = useCallback7(() => {
1791
+ const hasScrollbar = useCallback9(() => {
1443
1792
  const container = containerRef.current;
1444
1793
  if (!container) return false;
1445
1794
  return container.scrollHeight > container.clientHeight;
1446
1795
  }, []);
1447
- const handleScroll = useCallback7(() => {
1796
+ const handleScroll = useCallback9(() => {
1448
1797
  const container = containerRef.current;
1449
1798
  if (!container) return;
1450
1799
  const { scrollTop, scrollHeight, clientHeight } = container;
@@ -1466,14 +1815,14 @@ var AutoScrollContainer = forwardRef(
1466
1815
  lastScrollTopRef.current = scrollTop;
1467
1816
  lastScrollHeightRef.current = scrollHeight;
1468
1817
  }, [isNearBottom]);
1469
- useEffect6(() => {
1818
+ useEffect8(() => {
1470
1819
  const container = containerRef.current;
1471
1820
  if (container) {
1472
1821
  lastScrollTopRef.current = container.scrollTop;
1473
1822
  lastScrollHeightRef.current = container.scrollHeight;
1474
1823
  }
1475
1824
  }, []);
1476
- useEffect6(() => {
1825
+ useEffect8(() => {
1477
1826
  const container = containerRef.current;
1478
1827
  if (!container || !enabled) return;
1479
1828
  const observer = new MutationObserver(() => {
@@ -1505,16 +1854,12 @@ var AutoScrollContainer = forwardRef(
1505
1854
  }),
1506
1855
  [scrollToBottom, isUserScrolledUp]
1507
1856
  );
1508
- return /* @__PURE__ */ jsx18(
1857
+ return /* @__PURE__ */ jsx23(
1509
1858
  "div",
1510
1859
  {
1511
1860
  ref: containerRef,
1512
1861
  className: `auto-scroll-container ${className || ""}`.trim(),
1513
- style: {
1514
- overflowY: "auto",
1515
- height: "100%",
1516
- ...style
1517
- },
1862
+ style,
1518
1863
  onScroll: handleScroll,
1519
1864
  children
1520
1865
  }
@@ -1524,21 +1869,21 @@ var AutoScrollContainer = forwardRef(
1524
1869
  AutoScrollContainer.displayName = "AutoScrollContainer";
1525
1870
 
1526
1871
  // src/ThemeProvider.tsx
1527
- import { useEffect as useEffect7, useRef as useRef8 } from "react";
1872
+ import { useEffect as useEffect9, useRef as useRef10 } from "react";
1528
1873
  import { applyTheme } from "@incremark/theme";
1529
- import { jsx as jsx19 } from "react/jsx-runtime";
1874
+ import { jsx as jsx24 } from "react/jsx-runtime";
1530
1875
  var ThemeProvider = ({
1531
1876
  theme,
1532
1877
  children,
1533
1878
  className = ""
1534
1879
  }) => {
1535
- const containerRef = useRef8(null);
1536
- useEffect7(() => {
1880
+ const containerRef = useRef10(null);
1881
+ useEffect9(() => {
1537
1882
  if (containerRef.current) {
1538
1883
  applyTheme(containerRef.current, theme);
1539
1884
  }
1540
1885
  }, [theme]);
1541
- return /* @__PURE__ */ jsx19("div", { ref: containerRef, className: `incremark-theme-provider ${className}`.trim(), children });
1886
+ return /* @__PURE__ */ jsx24("div", { ref: containerRef, className: `incremark-theme-provider ${className}`.trim(), children });
1542
1887
  };
1543
1888
 
1544
1889
  // src/index.ts
@@ -1564,12 +1909,15 @@ import {
1564
1909
  mergeTheme,
1565
1910
  applyTheme as applyTheme2
1566
1911
  } from "@incremark/theme";
1912
+ import { en as enShared, zhCN as zhCNShared } from "@incremark/shared";
1567
1913
  export {
1568
1914
  AutoScrollContainer,
1569
1915
  BlockTransformer2 as BlockTransformer,
1916
+ ConfigProvider,
1570
1917
  DefinitionsProvider,
1571
1918
  Incremark,
1572
1919
  IncremarkContainerProvider,
1920
+ IncremarkContent,
1573
1921
  IncremarkFootnotes,
1574
1922
  IncremarkHtmlElement,
1575
1923
  IncremarkInline,
@@ -1585,6 +1933,7 @@ export {
1585
1933
  darkTheme,
1586
1934
  defaultPlugins2 as defaultPlugins,
1587
1935
  defaultTheme,
1936
+ enShared as en,
1588
1937
  generateCSSVars,
1589
1938
  imagePlugin,
1590
1939
  mathPlugin,
@@ -1595,7 +1944,9 @@ export {
1595
1944
  useBlockTransformer,
1596
1945
  useDefinitions,
1597
1946
  useDevTools,
1598
- useIncremark
1947
+ useIncremark,
1948
+ useLocale,
1949
+ zhCNShared as zhCN
1599
1950
  };
1600
1951
  /**
1601
1952
  * @file Definitions Context - 管理 Markdown 引用定义