@ai-react-markdown/mantine 2.12.0 → 2.13.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/README.md +8 -7
- package/dist/index.cjs +145 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +141 -56
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -24,8 +24,14 @@ var MantineAIMDefaultExtraStyles = ({ children }) => {
|
|
|
24
24
|
var DefaultExtraStyles_default = MantineAIMDefaultExtraStyles;
|
|
25
25
|
|
|
26
26
|
// src/components/customized/PreCode.tsx
|
|
27
|
-
import { memo as memo3, useEffect as
|
|
28
|
-
import {
|
|
27
|
+
import { createContext, memo as memo3, useContext, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState3 } from "react";
|
|
28
|
+
import {
|
|
29
|
+
CodeHighlight,
|
|
30
|
+
CodeHighlightTabs as CodeHighlightTabs2,
|
|
31
|
+
CodeHighlightControl as CodeHighlightControl2,
|
|
32
|
+
CodeHighlightAdapterProvider,
|
|
33
|
+
useHighlight
|
|
34
|
+
} from "@mantine/code-highlight";
|
|
29
35
|
import { useAIMarkdownState as useAIMarkdownState2, useAIMarkdownTheme as useAIMarkdownTheme2 } from "@ai-react-markdown/core";
|
|
30
36
|
|
|
31
37
|
// src/hooks/useMantineCodeBlockOptions.ts
|
|
@@ -37,7 +43,8 @@ var defaultMantineCodeBlockOptions = Object.freeze({
|
|
|
37
43
|
defaultExpanded: true,
|
|
38
44
|
autoDetectUnknownLanguage: false,
|
|
39
45
|
formatJson: true,
|
|
40
|
-
expandNestedJson: true
|
|
46
|
+
expandNestedJson: true,
|
|
47
|
+
highlightIntervalMs: 50
|
|
41
48
|
});
|
|
42
49
|
|
|
43
50
|
// src/hooks/useMantineCodeBlockOptions.ts
|
|
@@ -50,6 +57,9 @@ function useMantineCodeBlockOptions() {
|
|
|
50
57
|
const value = group?.[key];
|
|
51
58
|
if (value !== void 0) resolved[key] = value;
|
|
52
59
|
}
|
|
60
|
+
if (!Number.isFinite(resolved.highlightIntervalMs) || resolved.highlightIntervalMs < 0) {
|
|
61
|
+
resolved.highlightIntervalMs = defaultMantineCodeBlockOptions.highlightIntervalMs;
|
|
62
|
+
}
|
|
53
63
|
return resolved;
|
|
54
64
|
}, [group]);
|
|
55
65
|
}
|
|
@@ -483,6 +493,51 @@ function createJsonCompletenessScanner() {
|
|
|
483
493
|
};
|
|
484
494
|
}
|
|
485
495
|
|
|
496
|
+
// src/components/customized/useCodeFrame.ts
|
|
497
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
498
|
+
|
|
499
|
+
// src/components/customized/codeFrame.ts
|
|
500
|
+
function createCodeFrame(initial, publish) {
|
|
501
|
+
let shown = initial;
|
|
502
|
+
let latest = initial;
|
|
503
|
+
let delay = 0;
|
|
504
|
+
let timer;
|
|
505
|
+
const cancel = () => {
|
|
506
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
507
|
+
timer = void 0;
|
|
508
|
+
};
|
|
509
|
+
const flush = () => {
|
|
510
|
+
cancel();
|
|
511
|
+
if (shown.code === latest.code && shown.language === latest.language) return;
|
|
512
|
+
shown = latest;
|
|
513
|
+
publish(shown);
|
|
514
|
+
};
|
|
515
|
+
return {
|
|
516
|
+
update(next, streaming, interval) {
|
|
517
|
+
const replaced = next.language !== latest.language || !next.code.startsWith(latest.code);
|
|
518
|
+
latest = next;
|
|
519
|
+
if (delay !== interval) cancel();
|
|
520
|
+
delay = interval;
|
|
521
|
+
if (!streaming || interval === 0 || replaced) return flush();
|
|
522
|
+
if (shown.code === next.code && shown.language === next.language) return cancel();
|
|
523
|
+
timer ??= setTimeout(flush, interval);
|
|
524
|
+
},
|
|
525
|
+
// Cancellation is reversible: Strict Mode replays the update effect.
|
|
526
|
+
dispose: cancel
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// src/components/customized/useCodeFrame.ts
|
|
531
|
+
function useCodeFrame(code, language, streaming, interval) {
|
|
532
|
+
const [frame, setFrame] = useState2(() => ({ code, language }));
|
|
533
|
+
const [controller] = useState2(() => createCodeFrame({ code, language }, setFrame));
|
|
534
|
+
useEffect2(() => {
|
|
535
|
+
controller.update({ code, language }, streaming, interval);
|
|
536
|
+
}, [controller, code, language, streaming, interval]);
|
|
537
|
+
useEffect2(() => () => controller.dispose(), [controller]);
|
|
538
|
+
return !streaming || interval === 0 || language !== frame.language || !code.startsWith(frame.code) ? code : frame.code;
|
|
539
|
+
}
|
|
540
|
+
|
|
486
541
|
// src/components/customized/PreCode.tsx
|
|
487
542
|
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
488
543
|
var hljsAutoPromise = null;
|
|
@@ -500,13 +555,13 @@ var AUTODETECT_MIN_CHARS = 32;
|
|
|
500
555
|
var HLJS_LOAD_RETRIES = 3;
|
|
501
556
|
var HLJS_LOAD_RETRY_MS = 1500;
|
|
502
557
|
function useAutoDetectedLanguage(codeText, enabled, streaming) {
|
|
503
|
-
const [detected, setDetected] =
|
|
558
|
+
const [detected, setDetected] = useState3(
|
|
504
559
|
null
|
|
505
560
|
);
|
|
506
|
-
const [loadAttempt, setLoadAttempt] =
|
|
561
|
+
const [loadAttempt, setLoadAttempt] = useState3(0);
|
|
507
562
|
const loadFailuresRef = useRef2(0);
|
|
508
563
|
const previousTextRef = useRef2(codeText);
|
|
509
|
-
|
|
564
|
+
useEffect3(() => {
|
|
510
565
|
const appended = codeText.startsWith(previousTextRef.current);
|
|
511
566
|
previousTextRef.current = codeText;
|
|
512
567
|
if (!enabled) {
|
|
@@ -552,7 +607,9 @@ function preloadMantineCodeAssets() {
|
|
|
552
607
|
() => void 0
|
|
553
608
|
);
|
|
554
609
|
}
|
|
555
|
-
|
|
610
|
+
var RawCodeContext = createContext("");
|
|
611
|
+
function RawCodeCopy() {
|
|
612
|
+
const code = useContext(RawCodeContext);
|
|
556
613
|
return /* @__PURE__ */ jsx4(CopyButton2, { value: code, children: ({ copied, copy }) => /* @__PURE__ */ jsx4(
|
|
557
614
|
CodeHighlightControl2,
|
|
558
615
|
{
|
|
@@ -578,6 +635,64 @@ function RawCodeCopy({ code }) {
|
|
|
578
635
|
}
|
|
579
636
|
) });
|
|
580
637
|
}
|
|
638
|
+
function createCachedHighlightAdapter(highlight) {
|
|
639
|
+
let previous;
|
|
640
|
+
let result;
|
|
641
|
+
return {
|
|
642
|
+
getHighlighter: () => (input) => {
|
|
643
|
+
if (!previous || input.code !== previous.code || input.language !== previous.language || input.colorScheme !== previous.colorScheme) {
|
|
644
|
+
result = highlight(input);
|
|
645
|
+
previous = input;
|
|
646
|
+
}
|
|
647
|
+
return result;
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
var OrdinaryCodeHighlight = memo3(function OrdinaryCodeHighlight2({
|
|
652
|
+
code,
|
|
653
|
+
language,
|
|
654
|
+
fileName,
|
|
655
|
+
fontSize,
|
|
656
|
+
defaultExpanded
|
|
657
|
+
}) {
|
|
658
|
+
const highlight = useHighlight();
|
|
659
|
+
const adapter = useMemo2(() => createCachedHighlightAdapter(highlight), [highlight]);
|
|
660
|
+
return /* @__PURE__ */ jsx4(CodeHighlightAdapterProvider, { adapter, children: fileName === "unknown" ? /* @__PURE__ */ jsx4(
|
|
661
|
+
CodeHighlight,
|
|
662
|
+
{
|
|
663
|
+
mb: 15,
|
|
664
|
+
fz: fontSize,
|
|
665
|
+
w: "100%",
|
|
666
|
+
code,
|
|
667
|
+
withBorder: true,
|
|
668
|
+
withExpandButton: true,
|
|
669
|
+
defaultExpanded,
|
|
670
|
+
maxCollapsedHeight: "320px",
|
|
671
|
+
withCopyButton: false,
|
|
672
|
+
controls: [/* @__PURE__ */ jsx4(RawCodeCopy, {}, "copy")]
|
|
673
|
+
}
|
|
674
|
+
) : /* @__PURE__ */ jsx4(
|
|
675
|
+
CodeHighlightTabs2,
|
|
676
|
+
{
|
|
677
|
+
mb: 15,
|
|
678
|
+
fz: fontSize,
|
|
679
|
+
w: "100%",
|
|
680
|
+
code: [
|
|
681
|
+
{
|
|
682
|
+
fileName,
|
|
683
|
+
code,
|
|
684
|
+
language
|
|
685
|
+
}
|
|
686
|
+
],
|
|
687
|
+
withBorder: true,
|
|
688
|
+
withExpandButton: true,
|
|
689
|
+
defaultExpanded,
|
|
690
|
+
maxCollapsedHeight: "320px",
|
|
691
|
+
withCopyButton: false,
|
|
692
|
+
controls: [/* @__PURE__ */ jsx4(RawCodeCopy, {}, "copy")]
|
|
693
|
+
}
|
|
694
|
+
) });
|
|
695
|
+
});
|
|
581
696
|
var SpecialCodeLanguage = /* @__PURE__ */ ((SpecialCodeLanguage2) => {
|
|
582
697
|
SpecialCodeLanguage2["Mermaid"] = "mermaid";
|
|
583
698
|
return SpecialCodeLanguage2;
|
|
@@ -587,7 +702,7 @@ var MantineAIMPreCode = memo3(
|
|
|
587
702
|
(props) => {
|
|
588
703
|
const { fontSize } = useAIMarkdownTheme2();
|
|
589
704
|
const { streaming } = useAIMarkdownState2();
|
|
590
|
-
const { autoDetectUnknownLanguage, defaultExpanded, formatJson, expandNestedJson } = useMantineCodeBlockOptions();
|
|
705
|
+
const { autoDetectUnknownLanguage, defaultExpanded, formatJson, expandNestedJson, highlightIntervalMs } = useMantineCodeBlockOptions();
|
|
591
706
|
const detectedLanguage = useAutoDetectedLanguage(
|
|
592
707
|
props.codeText,
|
|
593
708
|
autoDetectUnknownLanguage && !props.existLanguage,
|
|
@@ -599,7 +714,7 @@ var MantineAIMPreCode = memo3(
|
|
|
599
714
|
[codeLanguage]
|
|
600
715
|
);
|
|
601
716
|
const isSpecialCodeBlock = SPECIAL_LANGUAGES.has(codeLanguage);
|
|
602
|
-
const [scanJson] =
|
|
717
|
+
const [scanJson] = useState3(createJsonCompletenessScanner);
|
|
603
718
|
const jsonComplete = useMemo2(
|
|
604
719
|
() => usedCodeLanguage === "json" && formatJson && streaming ? scanJson(props.codeText) : false,
|
|
605
720
|
[usedCodeLanguage, formatJson, streaming, scanJson, props.codeText]
|
|
@@ -610,53 +725,14 @@ var MantineAIMPreCode = memo3(
|
|
|
610
725
|
if (formatJson && usedCodeStr && usedCodeLanguage === "json" && (!streaming || jsonComplete)) {
|
|
611
726
|
usedCodeStr = prettyPrintJson(usedCodeStr, expandNestedJson);
|
|
612
727
|
}
|
|
613
|
-
return
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
fz: fontSize,
|
|
618
|
-
w: "100%",
|
|
619
|
-
code: usedCodeStr,
|
|
620
|
-
withBorder: true,
|
|
621
|
-
withExpandButton: true,
|
|
622
|
-
defaultExpanded,
|
|
623
|
-
maxCollapsedHeight: "320px",
|
|
624
|
-
withCopyButton: false,
|
|
625
|
-
controls: [/* @__PURE__ */ jsx4(RawCodeCopy, { code: props.codeText }, "copy")]
|
|
626
|
-
}
|
|
627
|
-
) : /* @__PURE__ */ jsx4(
|
|
628
|
-
CodeHighlightTabs2,
|
|
629
|
-
{
|
|
630
|
-
mb: 15,
|
|
631
|
-
fz: fontSize,
|
|
632
|
-
w: "100%",
|
|
633
|
-
code: [
|
|
634
|
-
{
|
|
635
|
-
fileName: usedFileName,
|
|
636
|
-
code: usedCodeStr,
|
|
637
|
-
language: usedCodeLanguage
|
|
638
|
-
}
|
|
639
|
-
],
|
|
640
|
-
withBorder: true,
|
|
641
|
-
withExpandButton: true,
|
|
642
|
-
defaultExpanded,
|
|
643
|
-
maxCollapsedHeight: "320px",
|
|
644
|
-
withCopyButton: false,
|
|
645
|
-
controls: [/* @__PURE__ */ jsx4(RawCodeCopy, { code: props.codeText }, "copy")]
|
|
646
|
-
}
|
|
647
|
-
);
|
|
648
|
-
}, [
|
|
649
|
-
isSpecialCodeBlock,
|
|
650
|
-
props.codeText,
|
|
728
|
+
return usedCodeStr;
|
|
729
|
+
}, [isSpecialCodeBlock, props.codeText, usedCodeLanguage, streaming, formatJson, expandNestedJson, jsonComplete]);
|
|
730
|
+
const displayedCode = useCodeFrame(
|
|
731
|
+
normalCodeBlockContent ?? "",
|
|
651
732
|
usedCodeLanguage,
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
streaming,
|
|
656
|
-
formatJson,
|
|
657
|
-
expandNestedJson,
|
|
658
|
-
jsonComplete
|
|
659
|
-
]);
|
|
733
|
+
streaming && !isSpecialCodeBlock,
|
|
734
|
+
highlightIntervalMs
|
|
735
|
+
);
|
|
660
736
|
const specialCodeBlockContent = useMemo2(() => {
|
|
661
737
|
switch (codeLanguage) {
|
|
662
738
|
case "mermaid" /* Mermaid */:
|
|
@@ -665,7 +741,16 @@ var MantineAIMPreCode = memo3(
|
|
|
665
741
|
return null;
|
|
666
742
|
}
|
|
667
743
|
}, [codeLanguage, props.codeText]);
|
|
668
|
-
return isSpecialCodeBlock ? specialCodeBlockContent :
|
|
744
|
+
return isSpecialCodeBlock ? specialCodeBlockContent : /* @__PURE__ */ jsx4(RawCodeContext.Provider, { value: props.codeText, children: /* @__PURE__ */ jsx4(
|
|
745
|
+
OrdinaryCodeHighlight,
|
|
746
|
+
{
|
|
747
|
+
code: displayedCode,
|
|
748
|
+
language: usedCodeLanguage,
|
|
749
|
+
fileName: usedFileName,
|
|
750
|
+
fontSize,
|
|
751
|
+
defaultExpanded
|
|
752
|
+
}
|
|
753
|
+
) });
|
|
669
754
|
}
|
|
670
755
|
);
|
|
671
756
|
MantineAIMPreCode.displayName = "MantineAIMPreCode";
|