@dsh-plus/llm-pi 0.1.18 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/lib/client.js +709 -91
  2. package/lib/style.css +90 -78
  3. package/package.json +27 -27
package/lib/client.js CHANGED
@@ -18000,16 +18000,16 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
18000
18000
  init_shellscript();
18001
18001
  init_json();
18002
18002
  var DiffBlock_module_default = {
18003
- "add": "IDEaOG_add",
18004
- "block": "IDEaOG_block",
18005
- "body": "IDEaOG_body",
18006
- "copyButton": "IDEaOG_copyButton",
18007
- "del": "IDEaOG_del",
18008
- "expand": "IDEaOG_expand",
18009
- "footer": "IDEaOG_footer",
18010
- "gap": "IDEaOG_gap",
18011
- "line": "IDEaOG_line",
18012
- "path": "IDEaOG_path"
18003
+ "add": "obLtqa_add",
18004
+ "block": "obLtqa_block",
18005
+ "body": "obLtqa_body",
18006
+ "copyButton": "obLtqa_copyButton",
18007
+ "del": "obLtqa_del",
18008
+ "expand": "obLtqa_expand",
18009
+ "footer": "obLtqa_footer",
18010
+ "gap": "obLtqa_gap",
18011
+ "line": "obLtqa_line",
18012
+ "path": "obLtqa_path"
18013
18013
  };
18014
18014
  //#endregion
18015
18015
  //#region ../../node_modules/.pnpm/mdast-util-to-string@4.0.0/node_modules/mdast-util-to-string/lib/index.js
@@ -59244,26 +59244,27 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
59244
59244
  chunkString: "chunkString"
59245
59245
  };
59246
59246
  //#endregion
59247
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-client-ui-primitives@0.1.2-alpha.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-client-ui-primitives/lib/markdown/CodeBlock.module.css
59247
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-client-ui-primitives@0.1.3-alpha.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-client-ui-primitives/lib/markdown/CodeBlock.module.css
59248
59248
  var CodeBlock_module_default = {
59249
- "action": "xeLGkW_action",
59250
- "banner": "xeLGkW_banner",
59251
- "bannerWrap": "xeLGkW_bannerWrap",
59252
- "block": "xeLGkW_block",
59253
- "copyButton": "xeLGkW_copyButton",
59254
- "infostring": "xeLGkW_infostring",
59255
- "plain": "xeLGkW_plain",
59256
- "shiki": "xeLGkW_shiki"
59249
+ "action": "folzqq_action",
59250
+ "banner": "folzqq_banner",
59251
+ "bannerWrap": "folzqq_bannerWrap",
59252
+ "block": "folzqq_block",
59253
+ "copyButton": "folzqq_copyButton",
59254
+ "infostring": "folzqq_infostring",
59255
+ "plain": "folzqq_plain",
59256
+ "shiki": "folzqq_shiki"
59257
59257
  };
59258
59258
  //#endregion
59259
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-client-ui-primitives@0.1.2-alpha.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-client-ui-primitives/lib/markdown/MarkdownText.module.css
59259
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-client-ui-primitives@0.1.3-alpha.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-client-ui-primitives/lib/markdown/MarkdownText.module.css
59260
59260
  var MarkdownText_module_default = {
59261
- "fileMention": "Ns7beW_fileMention",
59262
- "image": "Ns7beW_image",
59263
- "imageAlt": "Ns7beW_imageAlt",
59264
- "markdown": "Ns7beW_markdown",
59265
- "tableFill": "Ns7beW_tableFill",
59266
- "tableScroll": "Ns7beW_tableScroll"
59261
+ "fileMention": "vrxa6G_fileMention",
59262
+ "image": "vrxa6G_image",
59263
+ "imageAlt": "vrxa6G_imageAlt",
59264
+ "linkIcon": "vrxa6G_linkIcon",
59265
+ "markdown": "vrxa6G_markdown",
59266
+ "tableFill": "vrxa6G_tableFill",
59267
+ "tableScroll": "vrxa6G_tableScroll"
59267
59268
  };
59268
59269
  //#endregion
59269
59270
  //#region ../../node_modules/.pnpm/@shikijs+langs@4.4.3/node_modules/@shikijs/langs/dist/python.mjs
@@ -59583,7 +59584,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
59583
59584
  less_default = [lang];
59584
59585
  }));
59585
59586
  //#endregion
59586
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-client-ui-primitives@0.1.2-alpha.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-client-ui-primitives/lib/index.js
59587
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-client-ui-primitives@0.1.3-alpha.2_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-client-ui-primitives/lib/index.js
59587
59588
  init_typescript();
59588
59589
  init_shellscript();
59589
59590
  init_json();
@@ -59631,6 +59632,267 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
59631
59632
  el.remove();
59632
59633
  }
59633
59634
  }
59635
+ /** Code, web, and data extensions: all three categories share the code glyph. */
59636
+ const CODE_EXTENSIONS = /* @__PURE__ */ new Set([
59637
+ "ts",
59638
+ "tsx",
59639
+ "js",
59640
+ "jsx",
59641
+ "mjs",
59642
+ "cjs",
59643
+ "cts",
59644
+ "mts",
59645
+ "css",
59646
+ "scss",
59647
+ "sass",
59648
+ "less",
59649
+ "html",
59650
+ "htm",
59651
+ "vue",
59652
+ "svelte",
59653
+ "astro",
59654
+ "json",
59655
+ "jsonc",
59656
+ "json5",
59657
+ "yaml",
59658
+ "yml",
59659
+ "toml",
59660
+ "xml",
59661
+ "ini",
59662
+ "env",
59663
+ "sh",
59664
+ "bash",
59665
+ "zsh",
59666
+ "fish",
59667
+ "ps1",
59668
+ "bat",
59669
+ "cmd",
59670
+ "py",
59671
+ "pyi",
59672
+ "rb",
59673
+ "rs",
59674
+ "go",
59675
+ "java",
59676
+ "kt",
59677
+ "kts",
59678
+ "c",
59679
+ "cc",
59680
+ "cpp",
59681
+ "cxx",
59682
+ "h",
59683
+ "hh",
59684
+ "hpp",
59685
+ "cs",
59686
+ "php",
59687
+ "swift",
59688
+ "sql",
59689
+ "csv",
59690
+ "tsv",
59691
+ "proto",
59692
+ "graphql",
59693
+ "gql",
59694
+ "lua",
59695
+ "r",
59696
+ "pl",
59697
+ "scala",
59698
+ "clj",
59699
+ "cljs",
59700
+ "ex",
59701
+ "exs",
59702
+ "erl",
59703
+ "hs",
59704
+ "dart"
59705
+ ]);
59706
+ const IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
59707
+ "png",
59708
+ "jpg",
59709
+ "jpeg",
59710
+ "gif",
59711
+ "svg",
59712
+ "webp",
59713
+ "avif",
59714
+ "bmp",
59715
+ "ico",
59716
+ "tif",
59717
+ "tiff",
59718
+ "heic",
59719
+ "heif"
59720
+ ]);
59721
+ const DOCUMENT_EXTENSIONS = /* @__PURE__ */ new Set([
59722
+ "pdf",
59723
+ "doc",
59724
+ "docx",
59725
+ "xls",
59726
+ "xlsx",
59727
+ "ppt",
59728
+ "pptx"
59729
+ ]);
59730
+ /**
59731
+ * Derive a file path's link-icon category from its extension. Unknown and
59732
+ * missing extensions fall to `other` (the plain-paper glyph).
59733
+ * @param path - File path as the producing tool spelled it (either separator).
59734
+ * @returns The file's glyph category; never `url` or `folder`.
59735
+ */
59736
+ function classifyLinkPath(path) {
59737
+ const name = path.slice(Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1);
59738
+ const dot = name.lastIndexOf(".");
59739
+ if (dot < 0) return "other";
59740
+ const extension = name.slice(dot + 1).toLowerCase();
59741
+ if (CODE_EXTENSIONS.has(extension)) return "code";
59742
+ if (IMAGE_EXTENSIONS.has(extension)) return "image";
59743
+ return DOCUMENT_EXTENSIONS.has(extension) ? "document" : "other";
59744
+ }
59745
+ const GlobeGlyph = ({ size, className }) => (0, react_jsx_runtime.jsx)("svg", {
59746
+ width: size,
59747
+ height: size,
59748
+ className,
59749
+ viewBox: "0 0 20 20",
59750
+ fill: "none",
59751
+ xmlns: "http://www.w3.org/2000/svg",
59752
+ "aria-hidden": true,
59753
+ children: (0, react_jsx_runtime.jsx)("path", {
59754
+ fillRule: "evenodd",
59755
+ clipRule: "evenodd",
59756
+ d: "M9.99951 1.68994C14.5889 1.68994 18.3098 5.41022 18.3101 9.99951C18.3101 14.589 14.589 18.3101 9.99951 18.3101C5.41022 18.3098 1.68994 14.5889 1.68994 9.99951C1.69017 5.41037 5.41037 1.69017 9.99951 1.68994ZM3.23193 10.7495C3.52924 13.463 5.41981 15.6965 7.94873 16.4946C7.74323 16.1395 7.56487 15.736 7.41162 15.3022C6.97892 14.0773 6.70459 12.4906 6.63232 10.7495H3.23193ZM13.3667 10.7495C13.2944 12.4906 13.0211 14.0773 12.5884 15.3022C12.4352 15.7359 12.2557 16.1386 12.0503 16.4937C14.5794 15.6956 16.4707 13.4631 16.7681 10.7495H13.3667ZM8.13428 10.7495C8.20587 12.3512 8.45916 13.7619 8.82666 14.8022C9.046 15.4231 9.29031 15.8714 9.52686 16.1499C9.76321 16.428 9.92505 16.4651 9.99951 16.4653C10.0737 16.4653 10.2362 16.4288 10.4731 16.1499C10.7097 15.8714 10.954 15.4231 11.1733 14.8022C11.5408 13.7619 11.7941 12.3512 11.8657 10.7495H8.13428ZM9.99951 3.18994C9.92505 3.19013 9.76321 3.22823 9.52686 3.50635C9.29035 3.78486 9.04595 4.23325 8.82666 4.854C8.43314 5.96808 8.16996 7.50638 8.12158 9.24951H11.8784C11.83 7.50638 11.5669 5.96808 11.1733 4.854C10.954 4.23324 10.7097 3.78486 10.4731 3.50635C10.2362 3.22748 10.0737 3.18994 9.99951 3.18994ZM12.27 3.57861C12.3862 3.82232 12.4924 4.0822 12.5884 4.354C13.0494 5.65902 13.33 7.37415 13.3784 9.24951H16.7681C16.4792 6.61525 14.6885 4.43369 12.27 3.57861ZM7.729 3.57861C5.3109 4.4338 3.52072 6.61541 3.23193 9.24951H6.62158C6.67001 7.37415 6.95063 5.65902 7.41162 4.354C7.50759 4.08233 7.61287 3.82221 7.729 3.57861Z",
59757
+ fill: "currentColor"
59758
+ })
59759
+ });
59760
+ const CodeGlyph = ({ size, className }) => (0, react_jsx_runtime.jsxs)("svg", {
59761
+ width: size,
59762
+ height: size,
59763
+ className,
59764
+ viewBox: "0 0 20 20",
59765
+ fill: "none",
59766
+ xmlns: "http://www.w3.org/2000/svg",
59767
+ "aria-hidden": true,
59768
+ children: [
59769
+ (0, react_jsx_runtime.jsx)("path", {
59770
+ d: "M5 15.2021L1.67188 11.874C1.42017 11.6223 1.1823 11.3858 1.00781 11.1689C0.823288 10.9396 0.645016 10.6559 0.586914 10.2891C0.556619 10.0975 0.556619 9.90245 0.586914 9.71094C0.645016 9.3441 0.823288 9.06042 1.00781 8.83105C1.1823 8.61419 1.42017 8.37768 1.67188 8.12598L5 4.79785L6.20215 6L2.87402 9.32813C2.59555 9.6066 2.43539 9.76802 2.33203 9.89648C2.29246 9.94567 2.27406 9.97638 2.26563 9.99121C2.26528 9.99711 2.26528 10.0029 2.26563 10.0088C2.27406 10.0236 2.29246 10.0543 2.33203 10.1035C2.43539 10.232 2.59555 10.3934 2.87402 10.6719L6.20215 14L5 15.2021Z",
59771
+ fill: "currentColor"
59772
+ }),
59773
+ (0, react_jsx_runtime.jsx)("path", {
59774
+ d: "M15 15.2021L18.3281 11.874C18.5798 11.6223 18.8177 11.3858 18.9922 11.1689C19.1767 10.9396 19.355 10.6559 19.4131 10.2891C19.4434 10.0975 19.4434 9.90245 19.4131 9.71094C19.355 9.3441 19.1767 9.06042 18.9922 8.83105C18.8177 8.61419 18.5798 8.37768 18.3281 8.12598L15 4.79785L13.7979 6L17.126 9.32813C17.4045 9.6066 17.5646 9.76802 17.668 9.89648C17.7075 9.94567 17.7259 9.97638 17.7344 9.99121C17.7347 9.99711 17.7347 10.0029 17.7344 10.0088C17.7259 10.0236 17.7075 10.0543 17.668 10.1035C17.5646 10.232 17.4045 10.3934 17.126 10.6719L13.7979 14L15 15.2021Z",
59775
+ fill: "currentColor"
59776
+ }),
59777
+ (0, react_jsx_runtime.jsx)("path", {
59778
+ d: "M9.41181 15.0993L7.76955 14.6593L10.3577 5.00002L12 5.44006L9.41181 15.0993Z",
59779
+ fill: "currentColor"
59780
+ })
59781
+ ]
59782
+ });
59783
+ const FolderGlyph = ({ size, className }) => (0, react_jsx_runtime.jsxs)("svg", {
59784
+ width: size,
59785
+ height: size,
59786
+ className,
59787
+ viewBox: "0 0 20 20",
59788
+ fill: "none",
59789
+ xmlns: "http://www.w3.org/2000/svg",
59790
+ "aria-hidden": true,
59791
+ children: [(0, react_jsx_runtime.jsx)("path", {
59792
+ d: "M1.2002 11.4178V6.7244C1.2002 6.47036 1.19957 6.2962 1.21387 6.12773C1.29746 5.14425 1.76052 4.23195 2.50489 3.58378C2.63247 3.47269 2.77337 3.37059 2.97852 3.2205C3.11259 3.12241 3.20444 3.05471 3.29981 2.99296C3.85318 2.6347 4.49029 2.42604 5.14844 2.38847C5.26177 2.38201 5.37601 2.38261 5.542 2.38261H7.91211C8.63453 2.38261 9.13199 2.37701 9.61329 2.49882C9.7656 2.53739 9.91613 2.58526 10.0625 2.64237C10.525 2.8229 10.9267 3.11712 11.5147 3.5369L12.0859 3.94413C12.1927 4.02032 12.2509 4.06163 12.2959 4.09062C12.3336 4.11488 12.3394 4.11605 12.332 4.11308C12.3403 4.11633 12.3488 4.11875 12.3574 4.12089C12.3627 4.12161 12.3757 4.12265 12.4004 4.12382C12.4538 4.12635 12.5252 4.12675 12.6563 4.12675C13.7369 4.12675 14.6105 4.12608 15.3086 4.19999C16.0209 4.27545 16.643 4.43585 17.1885 4.82011C17.5449 5.07115 17.8554 5.38173 18.1064 5.73808C18.4908 6.28368 18.6521 6.90645 18.7275 7.61894C18.8014 8.31701 18.7998 9.19066 18.7998 10.2713V11.4178C18.7998 12.5248 18.801 13.4195 18.7236 14.1336C18.6446 14.8626 18.4763 15.4982 18.0742 16.0516C17.8399 16.374 17.5559 16.6571 17.2334 16.8914C16.68 17.2935 16.0445 17.4628 15.3154 17.5418C14.6014 17.6191 13.7065 17.618 12.5996 17.618H7.40039C6.29352 17.618 5.39863 17.6191 4.68457 17.5418C3.95547 17.4628 3.32001 17.2935 2.76661 16.8914C2.44414 16.6571 2.16011 16.374 1.92579 16.0516C1.52375 15.4982 1.35537 14.8626 1.27637 14.1336C1.199 13.4195 1.2002 12.5248 1.2002 11.4178ZM2.79981 11.4178C2.79981 12.5602 2.80136 13.3529 2.86719 13.9607C2.93144 14.5537 3.04885 14.8759 3.21973 15.1111C3.35542 15.2979 3.52029 15.4618 3.70704 15.5975C3.94221 15.7683 4.26361 15.8867 4.85645 15.951C5.46439 16.0168 6.25766 16.0174 7.40039 16.0174H12.5996C13.7424 16.0174 14.5356 16.0168 15.1436 15.951C15.7364 15.8867 16.0578 15.7683 16.293 15.5975C16.4797 15.4618 16.6446 15.2979 16.7803 15.1111C16.9512 14.8759 17.0686 14.5537 17.1328 13.9607C17.1986 13.3529 17.2002 12.5602 17.2002 11.4178V10.2713C17.2002 9.15571 17.1987 8.38124 17.1357 7.7869C17.0743 7.20716 16.9618 6.8914 16.7988 6.65995C16.6534 6.45353 16.473 6.2741 16.2666 6.1287C16.0351 5.96565 15.7196 5.85222 15.1397 5.79081C14.5454 5.7279 13.7716 5.72733 12.6563 5.72733C12.4465 5.72733 12.2081 5.73253 11.9736 5.6746C11.8947 5.65509 11.8168 5.63037 11.7412 5.60038C11.517 5.51135 11.3268 5.36863 11.1563 5.24687L10.585 4.83866C9.93302 4.37321 9.71454 4.22394 9.48047 4.13261C9.39579 4.09958 9.30882 4.07191 9.22071 4.0496C8.97721 3.98798 8.71286 3.98222 7.91211 3.98222H5.542C5.35809 3.98222 5.29665 3.98285 5.23926 3.98612C4.85821 4.00788 4.48933 4.12829 4.16895 4.33573C4.12071 4.36697 4.07125 4.40295 3.92286 4.51151C3.69569 4.67771 3.61995 4.73389 3.55567 4.78983C3.1248 5.16501 2.8561 5.69324 2.80762 6.26249C2.80039 6.34752 2.79981 6.44244 2.79981 6.7244V11.4178Z",
59793
+ fill: "currentColor"
59794
+ }), (0, react_jsx_runtime.jsx)("path", {
59795
+ d: "M15.4913 8.11793V9.71754H4.50892V8.11793H15.4913Z",
59796
+ fill: "currentColor"
59797
+ })]
59798
+ });
59799
+ const PhotoGlyph = ({ size, className }) => (0, react_jsx_runtime.jsxs)("svg", {
59800
+ width: size,
59801
+ height: size,
59802
+ className,
59803
+ viewBox: "0 0 20 20",
59804
+ fill: "none",
59805
+ xmlns: "http://www.w3.org/2000/svg",
59806
+ "aria-hidden": true,
59807
+ children: [(0, react_jsx_runtime.jsx)("path", {
59808
+ fillRule: "evenodd",
59809
+ clipRule: "evenodd",
59810
+ d: "M13 5.15039C14.574 5.15039 15.8496 6.42599 15.8496 8C15.8496 9.57401 14.574 10.8496 13 10.8496C11.426 10.8496 10.1504 9.57401 10.1504 8C10.1504 6.42599 11.426 5.1504 13 5.15039ZM13 6.84961C12.3649 6.84961 11.8496 7.36488 11.8496 8C11.8496 8.63513 12.3649 9.15039 13 9.15039C13.6351 9.15039 14.1504 8.63513 14.1504 8C14.1504 7.36488 13.6351 6.84961 13 6.84961Z",
59811
+ fill: "currentColor"
59812
+ }), (0, react_jsx_runtime.jsx)("path", {
59813
+ fillRule: "evenodd",
59814
+ clipRule: "evenodd",
59815
+ d: "M12.5996 2.15039C13.7056 2.15039 14.6038 2.14883 15.3213 2.22656C16.0546 2.30602 16.6994 2.47647 17.2627 2.88574C17.5895 3.1232 17.8768 3.41049 18.1143 3.73731C18.5235 4.30063 18.694 4.9454 18.7734 5.67871C18.8512 6.39616 18.8496 7.29441 18.8496 8.40039V11.5996C18.8496 12.7056 18.8512 13.6038 18.7734 14.3213C18.694 15.0546 18.5235 15.6994 18.1143 16.2627C17.8768 16.5895 17.5895 16.8768 17.2627 17.1143C16.6994 17.5235 16.0546 17.694 15.3213 17.7734C14.6038 17.8512 13.7056 17.8496 12.5996 17.8496H7.40039C6.29441 17.8496 5.39616 17.8512 4.67871 17.7734C3.9454 17.694 3.30063 17.5235 2.73731 17.1143C2.41049 16.8768 2.1232 16.5895 1.88574 16.2627C1.47647 15.6994 1.30602 15.0546 1.22656 14.3213C1.14883 13.6038 1.15039 12.7056 1.15039 11.5996V8.40039C1.15039 7.29441 1.14883 6.39616 1.22656 5.67871C1.30602 4.9454 1.47647 4.30063 1.88574 3.73731C2.1232 3.41049 2.41049 3.1232 2.73731 2.88574C3.30063 2.47647 3.9454 2.30602 4.67871 2.22656C5.39616 2.14883 6.29441 2.15039 7.40039 2.15039H12.5996ZM5.56348 10.8164C5.30962 10.8348 5.02517 10.9291 4.58008 11.1973C4.13813 11.4635 3.60989 11.8565 2.85449 12.4229C2.85831 13.1414 2.86855 13.6903 2.91699 14.1377C2.98078 14.7264 3.09709 15.0384 3.26074 15.2637C3.39335 15.4462 3.55382 15.6067 3.73633 15.7393C3.96158 15.9029 4.2736 16.0192 4.86231 16.083C5.46688 16.1485 6.25677 16.1504 7.40039 16.1504H11.9492L8.71094 12.9131C8.00039 12.2025 7.51129 11.7149 7.09571 11.376C6.69274 11.0474 6.42364 10.9144 6.17481 10.8604C5.97432 10.8168 5.7681 10.8017 5.56348 10.8164ZM7.40039 3.84961C6.25677 3.84961 5.46688 3.85153 4.86231 3.91699C4.2736 3.98078 3.96158 4.09709 3.73633 4.26074C3.55382 4.39335 3.39335 4.55382 3.26074 4.73633C3.09709 4.96158 2.98078 5.2736 2.91699 5.86231C2.85153 6.46688 2.84961 7.25677 2.84961 8.40039V10.3105C3.15698 10.0902 3.43896 9.8988 3.70215 9.74024C4.26649 9.40025 4.81639 9.16621 5.44141 9.1211C5.80775 9.0947 6.17623 9.1213 6.53516 9.19922C7.14769 9.33224 7.65922 9.64212 8.16992 10.0586C8.66793 10.4648 9.22718 11.025 9.91309 11.7109L14.333 16.1318C14.6363 16.122 14.9012 16.1086 15.1377 16.083C15.7264 16.0192 16.0384 15.9029 16.2637 15.7393C16.4462 15.6067 16.6067 15.4462 16.7393 15.2637C16.9029 15.0384 17.0192 14.7264 17.083 14.1377C17.1485 13.5331 17.1504 12.7432 17.1504 11.5996V8.40039C17.1504 7.25677 17.1485 6.46688 17.083 5.86231C17.0192 5.2736 16.9029 4.96158 16.7393 4.73633C16.6067 4.55382 16.4462 4.39335 16.2637 4.26074C16.0384 4.09709 15.7264 3.98078 15.1377 3.91699C14.5331 3.85153 13.7432 3.84961 12.5996 3.84961H7.40039Z",
59816
+ fill: "currentColor"
59817
+ })]
59818
+ });
59819
+ const PaperGlyph = ({ size, className }) => (0, react_jsx_runtime.jsx)("svg", {
59820
+ width: size,
59821
+ height: size,
59822
+ className,
59823
+ viewBox: "0 0 20 20",
59824
+ fill: "none",
59825
+ xmlns: "http://www.w3.org/2000/svg",
59826
+ "aria-hidden": true,
59827
+ children: (0, react_jsx_runtime.jsx)("path", {
59828
+ d: "M11.3467 4.59607C11.3469 5.40284 11.3499 5.9609 11.3965 6.39099C11.444 6.82964 11.5288 7.03981 11.6328 7.18298C11.7253 7.3102 11.8376 7.42158 11.9648 7.51404C12.108 7.61807 12.3181 7.70283 12.7568 7.75037C13.1851 7.79675 13.7399 7.79992 14.541 7.80017L11.3467 4.59607ZM17.2695 12.7455C17.2695 13.5901 17.2706 14.2881 17.21 14.848C17.1477 15.4228 17.0119 15.9463 16.6768 16.4076C16.4856 16.6707 16.2543 16.902 15.9912 17.0931C15.5298 17.4284 15.0065 17.5641 14.4316 17.6263C13.8718 17.687 13.1737 17.6859 12.3291 17.6859H8.23926C7.39498 17.6859 6.69745 17.687 6.1377 17.6263C5.56284 17.5641 5.03855 17.4284 4.57715 17.0931C4.31413 16.902 4.08272 16.6706 3.8916 16.4076C3.55647 15.9463 3.42167 15.4227 3.35938 14.848C3.29872 14.2881 3.29981 13.5901 3.29981 12.7455V6.80017C3.29981 5.95586 3.29876 5.25837 3.35938 4.69861C3.42166 4.12375 3.55638 3.59946 3.8916 3.13806C4.08274 2.87503 4.31412 2.64365 4.57715 2.45252C5.03855 2.11729 5.56284 1.98257 6.1377 1.92029C6.69746 1.85967 7.39495 1.86072 8.23926 1.86072H9.38468C10.039 1.86072 10.3661 1.86072 10.6679 1.95896C10.7677 1.99146 10.8648 2.03176 10.9583 2.0795C11.241 2.22382 11.472 2.45549 11.934 2.91883L16.2188 7.21612C16.679 7.67761 16.909 7.90836 17.0523 8.1902C17.0997 8.28342 17.1397 8.38022 17.172 8.4797C17.2695 8.78045 17.2695 9.10631 17.2695 9.75801V12.7455ZM4.89942 12.7455C4.89942 13.6256 4.90106 14.2215 4.9502 14.6752C4.99773 15.1139 5.08249 15.324 5.18652 15.4672C5.27898 15.5944 5.39037 15.7067 5.51758 15.7992C5.66076 15.9032 5.87093 15.988 6.30957 16.0355C6.76321 16.0847 7.35919 16.0853 8.23926 16.0853H12.3291C13.2091 16.0853 13.8051 16.0846 14.2588 16.0355C14.6973 15.988 14.9076 15.9032 15.0508 15.7992C15.1781 15.7067 15.2903 15.5945 15.3828 15.4672C15.4868 15.324 15.5716 15.1139 15.6191 14.6752C15.6683 14.2215 15.6689 13.6256 15.6689 12.7455V9.40076H14.6865C13.8419 9.40076 13.1439 9.40185 12.584 9.34119C12.0093 9.27889 11.4857 9.14411 11.0244 8.80896C10.7614 8.61784 10.53 8.38645 10.3389 8.12341C10.0036 7.66202 9.86795 7.13773 9.80567 6.56287C9.74505 6.00312 9.74609 5.30558 9.7461 4.4613V3.46033H8.23926C7.35919 3.46033 6.76321 3.46196 6.30957 3.51111C5.87097 3.55865 5.66075 3.64342 5.51758 3.74744C5.39057 3.83979 5.27888 3.95148 5.18652 4.07849C5.0825 4.22166 4.99773 4.43188 4.9502 4.87048C4.90105 5.32412 4.89942 5.92011 4.89942 6.80017V12.7455Z",
59829
+ fill: "currentColor"
59830
+ })
59831
+ });
59832
+ const PaperDocGlyph = ({ size, className }) => (0, react_jsx_runtime.jsxs)("svg", {
59833
+ width: size,
59834
+ height: size,
59835
+ className,
59836
+ viewBox: "0 0 20 20",
59837
+ fill: "none",
59838
+ xmlns: "http://www.w3.org/2000/svg",
59839
+ "aria-hidden": true,
59840
+ children: [
59841
+ (0, react_jsx_runtime.jsx)("path", {
59842
+ d: "M11.3457 4.5957C11.3459 5.40247 11.3489 5.96054 11.3955 6.39063C11.443 6.82927 11.5278 7.03944 11.6318 7.18262C11.7243 7.30983 11.8367 7.42122 11.9639 7.51367C12.1071 7.61771 12.3171 7.70247 12.7559 7.75C13.1841 7.79639 13.739 7.79955 14.54 7.79981L11.3457 4.5957ZM17.2686 12.7451C17.2686 13.5897 17.2696 14.2878 17.209 14.8477C17.1467 15.4224 17.011 15.9459 16.6758 16.4072C16.4846 16.6703 16.2533 16.9016 15.9902 17.0928C15.5289 17.428 15.0055 17.5637 14.4307 17.626C13.8708 17.6866 13.1727 17.6855 12.3281 17.6855H8.23828C7.394 17.6855 6.69647 17.6866 6.13672 17.626C5.56186 17.5637 5.03757 17.428 4.57617 17.0928C4.31315 16.9016 4.08175 16.6703 3.89063 16.4072C3.55549 15.9459 3.42069 15.4224 3.3584 14.8477C3.29774 14.2878 3.29883 13.5897 3.29883 12.7451V6.79981C3.29883 5.95549 3.29778 5.258 3.3584 4.69824C3.42068 4.12338 3.5554 3.5991 3.89063 3.1377C4.08176 2.87466 4.31314 2.64328 4.57617 2.45215C5.03757 2.11692 5.56186 1.98221 6.13672 1.91992C6.69648 1.8593 7.39397 1.86035 8.23828 1.86035H9.3837C10.038 1.86035 10.3652 1.86035 10.6669 1.9586C10.7668 1.99109 10.8639 2.03139 10.9573 2.07913C11.24 2.22346 11.471 2.45512 11.933 2.91846L16.2178 7.21575C16.678 7.67725 16.9081 7.90799 17.0514 8.18983C17.0988 8.28305 17.1388 8.37985 17.171 8.47933C17.2686 8.78009 17.2686 9.10594 17.2686 9.75765V12.7451ZM4.89844 12.7451C4.89844 13.6253 4.90008 14.2211 4.94922 14.6748C4.99675 15.1135 5.08151 15.3236 5.18555 15.4668C5.278 15.594 5.38939 15.7064 5.5166 15.7988C5.65978 15.9029 5.86995 15.9876 6.30859 16.0352C6.76223 16.0843 7.35822 16.085 8.23828 16.085H12.3281C13.2081 16.085 13.8042 16.0843 14.2578 16.0352C14.6963 15.9876 14.9066 15.9028 15.0498 15.7988C15.1771 15.7063 15.2893 15.5941 15.3818 15.4668C15.4859 15.3236 15.5706 15.1135 15.6182 14.6748C15.6673 14.2211 15.668 13.6252 15.668 12.7451V9.40039H14.6855C13.841 9.40039 13.1429 9.40148 12.583 9.34082C12.0083 9.27852 11.4847 9.14374 11.0234 8.8086C10.7604 8.61747 10.5291 8.38608 10.3379 8.12305C10.0027 7.66165 9.86697 7.13736 9.80469 6.5625C9.74408 6.00275 9.74512 5.30522 9.74512 4.46094V3.45996H8.23828C7.35822 3.45996 6.76223 3.46159 6.30859 3.51074C5.86999 3.55828 5.65977 3.64305 5.5166 3.74707C5.38959 3.83942 5.2779 3.95111 5.18555 4.07813C5.08153 4.2213 4.99676 4.43152 4.94922 4.87012C4.90007 5.32376 4.89844 5.91974 4.89844 6.79981V12.7451Z",
59843
+ fill: "currentColor"
59844
+ }),
59845
+ (0, react_jsx_runtime.jsx)("path", {
59846
+ d: "M11.1523 13.0995V14.4999H6.30273V13.0995H11.1523Z",
59847
+ fill: "currentColor"
59848
+ }),
59849
+ (0, react_jsx_runtime.jsx)("path", {
59850
+ d: "M10.2148 10V11.4004H6.30273V10H10.2148Z",
59851
+ fill: "currentColor"
59852
+ })
59853
+ ]
59854
+ });
59855
+ /** Local exhaustiveness helper — this package does not depend on `dsh-llm`. */
59856
+ /* v8 ignore next 3 -- closed-union backstop; only reached if a kind is forged */
59857
+ function assertNever$1(value) {
59858
+ throw new Error(`unreachable link icon kind: ${String(value)}`);
59859
+ }
59860
+ /**
59861
+ * Render the leading glyph for one clickable artifact link.
59862
+ * @param props - The link category, optional size (default 14px — the inline
59863
+ * link text size these glyphs sit beside), and optional CSS class.
59864
+ * @returns The category's SVG glyph, riding currentColor.
59865
+ */
59866
+ function LinkIcon({ kind, size = 14, className }) {
59867
+ switch (kind) {
59868
+ case "url": return (0, react_jsx_runtime.jsx)(GlobeGlyph, {
59869
+ size,
59870
+ className
59871
+ });
59872
+ case "folder": return (0, react_jsx_runtime.jsx)(FolderGlyph, {
59873
+ size,
59874
+ className
59875
+ });
59876
+ case "code": return (0, react_jsx_runtime.jsx)(CodeGlyph, {
59877
+ size,
59878
+ className
59879
+ });
59880
+ case "image": return (0, react_jsx_runtime.jsx)(PhotoGlyph, {
59881
+ size,
59882
+ className
59883
+ });
59884
+ case "document": return (0, react_jsx_runtime.jsx)(PaperDocGlyph, {
59885
+ size,
59886
+ className
59887
+ });
59888
+ case "other": return (0, react_jsx_runtime.jsx)(PaperGlyph, {
59889
+ size,
59890
+ className
59891
+ });
59892
+ /* v8 ignore next -- closed-union backstop; only reached if a kind is forged */
59893
+ default: return assertNever$1(kind);
59894
+ }
59895
+ }
59634
59896
  /**
59635
59897
  * The client's ONE syntax highlighter: a synchronous fine-grained shiki core
59636
59898
  * (JavaScript regex engine — no oniguruma WASM, bundle-friendly) with an
@@ -59753,6 +60015,14 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
59753
60015
  ["xml", "xml"],
59754
60016
  ["lua", "lua"]
59755
60017
  ]);
60018
+ /**
60019
+ * Whether a language hint can use the shared syntax highlighter.
60020
+ * @param lang - Language hint from a code surface.
60021
+ * @returns Whether the hint resolves to a supported grammar.
60022
+ */
60023
+ function supportsHighlighting(lang) {
60024
+ return lang !== void 0 && LANG_ALIASES.has(lang.toLowerCase());
60025
+ }
59756
60026
  /** All token colors resolve through `--shiki-*` custom properties (theme package sheets). */
59757
60027
  const cssVariablesTheme = createCssVariablesTheme({
59758
60028
  name: "css-variables",
@@ -59935,10 +60205,11 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
59935
60205
  * tokenization is line-based and forward-only — a line's tokens depend only on
59936
60206
  * its own text and the grammar state entering it — so appended text never
59937
60207
  * changes a completed line's tokens. The session caches the spans of every
59938
- * completed line together with the grammar state after them; each
59939
- * {@link update} tokenizes newly completed text from that state, plus the
59940
- * still-growing last line. Per-call cost therefore excludes the completed
59941
- * prefix, and the result equals a from-scratch tokenization of the same code.
60208
+ * completed line together with the grammar state after them;
60209
+ * {@link updateFrame} reports only newly completed lines plus the still-growing
60210
+ * last line, while {@link update} materializes the complete compatibility
60211
+ * result. Per-call tokenization cost therefore excludes the completed prefix,
60212
+ * and the result equals a from-scratch tokenization of the same code.
59942
60213
  * Non-append input and a change of resolved grammar reset the cache and
59943
60214
  * re-tokenize fully, so any input stays correct.
59944
60215
  */
@@ -59954,11 +60225,15 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
59954
60225
  lastCode;
59955
60226
  lastLang;
59956
60227
  lastResult;
60228
+ generation = 0;
60229
+ lastFrame;
59957
60230
  reset(resolved) {
59958
60231
  this.resolved = resolved;
59959
60232
  this.prefix = "";
59960
60233
  this.spans = [];
59961
60234
  this.state = void 0;
60235
+ this.generation += 1;
60236
+ this.lastFrame = void 0;
59962
60237
  }
59963
60238
  /** Tokenize `text` with `resolved`, resuming from the cached grammar state when one exists. */
59964
60239
  tokenize(resolved, text) {
@@ -59969,28 +60244,23 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
59969
60244
  });
59970
60245
  }
59971
60246
  /**
59972
- * Tokenize the fence's current text into per-line highlighted runs;
59973
- * `undefined` means the caller renders its plain fallback. Idempotent per
59974
- * (`code`, `lang`) input — repeated calls return the identical result array —
59975
- * and a retained line keeps its span-array identity across growing calls, so
59976
- * a React caller can reuse cached line elements. A lazy grammar not yet
59977
- * loaded returns `undefined` and loads in the background exactly as
59978
- * {@link highlightToHtml} does; the next call after it registers highlights.
59979
- * @param code - the fence text accumulated so far (display-trimmed, no synthetic trailing newline).
59980
- * @param lang - the language hint (a markdown fence info string).
59981
- * @returns one entry per line of `code` (each an array of runs), or `undefined` for unknown or not-yet-loaded languages.
60247
+ * Tokenize one update as a delta for a retained renderer.
60248
+ * @param code - the fence text accumulated so far.
60249
+ * @param lang - the language hint.
60250
+ * @returns Newly completed lines plus the current tail, or `undefined` for the plain arm.
59982
60251
  */
59983
- update(code, lang) {
59984
- if (code === this.lastCode && lang === this.lastLang && this.lastResult !== void 0) return this.lastResult;
60252
+ updateFrame(code, lang) {
60253
+ if (code === this.lastCode && lang === this.lastLang && this.lastFrame !== void 0) return this.lastFrame;
59985
60254
  this.lastCode = code;
59986
60255
  this.lastLang = lang;
60256
+ this.lastResult = void 0;
59987
60257
  const resolved = lang === void 0 ? void 0 : LANG_ALIASES.get(lang.toLowerCase());
59988
60258
  if (resolved === void 0 || !ensureGrammar(resolved)) {
59989
60259
  this.reset(void 0);
59990
- this.lastResult = void 0;
59991
60260
  return;
59992
60261
  }
59993
60262
  if (resolved !== this.resolved || !code.startsWith(this.prefix)) this.reset(resolved);
60263
+ const firstNewLine = this.spans.length;
59994
60264
  const rest = code.slice(this.prefix.length);
59995
60265
  const lastNewline = rest.lastIndexOf("\n");
59996
60266
  if (lastNewline >= 0) {
@@ -60000,10 +60270,98 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
60000
60270
  this.state = highlighter().getLastGrammarState(tokens);
60001
60271
  this.prefix = code.slice(0, this.prefix.length + lastNewline + 1);
60002
60272
  }
60003
- this.lastResult = [...this.spans, ...this.tokenize(resolved, rest.slice(lastNewline + 1)).map(lineSpans)];
60273
+ this.lastFrame = {
60274
+ generation: this.generation,
60275
+ appended: this.spans.slice(firstNewLine),
60276
+ tail: this.tokenize(resolved, rest.slice(lastNewline + 1)).map(lineSpans)
60277
+ };
60278
+ return this.lastFrame;
60279
+ }
60280
+ /**
60281
+ * Tokenize the fence's current text into per-line highlighted runs;
60282
+ * `undefined` means the caller renders its plain fallback. Idempotent per
60283
+ * (`code`, `lang`) input — repeated calls return the identical result array —
60284
+ * and a retained line keeps its span-array identity across growing calls, so
60285
+ * a React caller can reuse cached line elements. A lazy grammar not yet
60286
+ * loaded returns `undefined` and loads in the background exactly as
60287
+ * {@link highlightToHtml} does; the next call after it registers highlights.
60288
+ * @param code - the fence text accumulated so far (display-trimmed, no synthetic trailing newline).
60289
+ * @param lang - the language hint (a markdown fence info string).
60290
+ * @returns one entry per line of `code` (each an array of runs), or `undefined` for unknown or not-yet-loaded languages.
60291
+ */
60292
+ update(code, lang) {
60293
+ if (code === this.lastCode && lang === this.lastLang && this.lastResult !== void 0) return this.lastResult;
60294
+ const frame = this.updateFrame(code, lang);
60295
+ if (frame === void 0) return void 0;
60296
+ this.lastResult = [...this.spans, ...frame.tail];
60004
60297
  return this.lastResult;
60005
60298
  }
60006
60299
  };
60300
+ const noop = () => {};
60301
+ /** One document-wide observer; activated elements leave it permanently. */
60302
+ var HighlightViewport = class {
60303
+ observer;
60304
+ activators = /* @__PURE__ */ new Map();
60305
+ observe(element, activate) {
60306
+ if (typeof IntersectionObserver === "undefined") {
60307
+ activate();
60308
+ return noop;
60309
+ }
60310
+ this.observer ??= new IntersectionObserver((entries) => {
60311
+ for (const entry of entries) {
60312
+ if (!entry.isIntersecting) continue;
60313
+ const current = this.activators.get(entry.target);
60314
+ /* v8 ignore next -- the observer reports only elements still registered with it. */
60315
+ if (current === void 0) continue;
60316
+ this.activators.delete(entry.target);
60317
+ this.observer?.unobserve(entry.target);
60318
+ current();
60319
+ }
60320
+ this.releaseEmptyObserver();
60321
+ });
60322
+ this.activators.set(element, activate);
60323
+ this.observer.observe(element);
60324
+ return () => {
60325
+ this.activators.delete(element);
60326
+ this.observer?.unobserve(element);
60327
+ this.releaseEmptyObserver();
60328
+ };
60329
+ }
60330
+ releaseEmptyObserver() {
60331
+ if (this.activators.size > 0) return;
60332
+ this.observer?.disconnect();
60333
+ this.observer = void 0;
60334
+ }
60335
+ };
60336
+ const highlightViewport = new HighlightViewport();
60337
+ /**
60338
+ * Activate one supported code surface when it first intersects the viewport.
60339
+ * Activation lasts for the component lifetime; browsers without
60340
+ * IntersectionObserver activate immediately.
60341
+ * @param target - Code surface whose plain rendering reserves its geometry.
60342
+ * @param lang - Optional language hint.
60343
+ * @returns Whether this component may build highlighted output.
60344
+ */
60345
+ function useViewportHighlighting(target, lang) {
60346
+ const supported = supportsHighlighting(lang);
60347
+ const [activated, setActivated] = (0, react.useState)(false);
60348
+ const activate = (0, react.useCallback)(() => {
60349
+ setActivated(true);
60350
+ }, []);
60351
+ (0, react.useEffect)(() => {
60352
+ if (activated || !supported) return;
60353
+ const element = target.current;
60354
+ /* v8 ignore next -- React attaches the host ref before running effects. */
60355
+ if (element === null) return;
60356
+ return highlightViewport.observe(element, activate);
60357
+ }, [
60358
+ activate,
60359
+ activated,
60360
+ supported,
60361
+ target
60362
+ ]);
60363
+ return activated && supported;
60364
+ }
60007
60365
  DiffBlock_module_default.path, DiffBlock_module_default.del, DiffBlock_module_default.add, DiffBlock_module_default.gap;
60008
60366
  /**
60009
60367
  * Incremental block-level markdown parsing for an append-only text stream.
@@ -60011,19 +60369,23 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
60011
60369
  * Re-parsing the whole accumulated document on every streaming chunk is
60012
60370
  * quadratic in the final reply length. CommonMark block parsing is line-based
60013
60371
  * and appended text can only reshape the parse frontier — the last top-level
60014
- * block (a paragraph becoming a setext heading or a table, a list continuing
60015
- * after a blank line, an unclosed fence swallowing lines) — so earlier blocks
60016
- * are final. This parser therefore freezes all but the trailing
60017
- * {@link UNSTABLE_TAIL_BLOCKS} blocks and re-parses only the source tail
60018
- * behind them: each source region is parsed O(1) times over the stream
60019
- * instead of once per chunk.
60020
- *
60021
- * The freeze boundary comes from the parser's own `position` offsets, never
60022
- * from custom source scanning. The cut sits at the *end offset* of the last
60023
- * frozen block (not the next block's start): a following block's start offset
60024
- * excludes up to three spaces of insignificant leading indentation, which is
60025
- * harmless to drop, but cutting at the previous end also keeps the
60026
- * inter-block blank lines in the tail so the sliced source stays verbatim.
60372
+ * block (a paragraph becoming a setext heading or a table, or a list
60373
+ * continuing after a blank line) — so earlier blocks are final. This parser
60374
+ * therefore freezes all but the trailing {@link UNSTABLE_TAIL_BLOCKS} blocks
60375
+ * and re-parses only the source tail behind them. A final unclosed top-level
60376
+ * fence cannot freeze as a block, so its completed content lines use a second
60377
+ * frontier: only the last completed line and current partial line return
60378
+ * through the caller's grammar. Each source region is therefore parsed a
60379
+ * bounded number of times over the stream instead of once per chunk.
60380
+ *
60381
+ * The block freeze boundary comes from the parser's own `position` offsets.
60382
+ * The cut sits at the *end offset* of the last frozen block (not the next
60383
+ * block's start): a following block's start offset excludes up to three spaces
60384
+ * of insignificant leading indentation, which is harmless to drop, but
60385
+ * cutting at the previous end also keeps the inter-block blank lines in the
60386
+ * tail so the sliced source stays verbatim. Fence scanning only recognizes a
60387
+ * parser-confirmed code node and closing delimiter; ambiguous input returns to
60388
+ * the normal tail parse.
60027
60389
  *
60028
60390
  * Known deviation, shared with any prefix-freeze scheme: micromark resolves
60029
60391
  * reference-style links and footnotes document-wide at parse time, so a
@@ -60048,6 +60410,84 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
60048
60410
  const offset = node.position?.start.offset;
60049
60411
  return offset === void 0 ? -(index + 1) : base + offset;
60050
60412
  }
60413
+ /** Return the first line terminator at or after `start`, including a CRLF pair. */
60414
+ function lineTerminatorEnd(text, start) {
60415
+ for (let index = start; index < text.length; index += 1) {
60416
+ const char = text[index];
60417
+ if (char === "\n") return index + 1;
60418
+ if (char === "\r") return text[index + 1] === "\n" ? index + 2 : index + 1;
60419
+ }
60420
+ }
60421
+ /**
60422
+ * Source prefix before the last completed line. Keeping that line beside the
60423
+ * current partial line lets the grammar retain its trailing-newline semantics.
60424
+ */
60425
+ function committableLinePrefixLength(text) {
60426
+ let previousEnd = 0;
60427
+ let end = 0;
60428
+ for (let index = 0; index < text.length; index += 1) {
60429
+ const char = text[index];
60430
+ if (char === "\n") {
60431
+ previousEnd = end;
60432
+ end = index + 1;
60433
+ continue;
60434
+ }
60435
+ if (char !== "\r" || index + 1 >= text.length) continue;
60436
+ if (text[index + 1] === "\n") index += 1;
60437
+ previousEnd = end;
60438
+ end = index + 1;
60439
+ }
60440
+ return previousEnd;
60441
+ }
60442
+ /** Exact source terminator ending a non-empty committable prefix. */
60443
+ function trailingLineTerminator(text) {
60444
+ return text.endsWith("\r\n") ? "\r\n" : text.endsWith("\r") ? "\r" : "\n";
60445
+ }
60446
+ /** Whether `text` contains a CommonMark closing fence on one of its logical lines. */
60447
+ function containsClosingFence(text, marker, markerLength) {
60448
+ let start = 0;
60449
+ while (start <= text.length) {
60450
+ let end = start;
60451
+ while (end < text.length && text[end] !== "\n" && text[end] !== "\r") end += 1;
60452
+ const line = text.slice(start, end);
60453
+ let indent = 0;
60454
+ while (indent < 3 && line[indent] === " ") indent += 1;
60455
+ let run = indent;
60456
+ while (line[run] === marker) run += 1;
60457
+ if (run - indent >= markerLength && /^[ \t]*$/.test(line.slice(run))) return true;
60458
+ if (end === text.length) return false;
60459
+ start = text[end] === "\r" && text[end + 1] === "\n" ? end + 2 : end + 1;
60460
+ }
60461
+ /* v8 ignore next -- each loop iteration returns at EOF or advances past a line terminator. */
60462
+ return false;
60463
+ }
60464
+ /** Advance an mdast point across one append while treating a split CRLF as one line ending. */
60465
+ function advancePoint(point, appended, precededByCarriageReturn) {
60466
+ let line = point.line;
60467
+ let column = point.column;
60468
+ let afterCarriageReturn = precededByCarriageReturn;
60469
+ for (const char of appended) {
60470
+ if (char === "\n") {
60471
+ if (!afterCarriageReturn) line += 1;
60472
+ column = 1;
60473
+ afterCarriageReturn = false;
60474
+ continue;
60475
+ }
60476
+ if (char === "\r") {
60477
+ line += 1;
60478
+ column = 1;
60479
+ afterCarriageReturn = true;
60480
+ continue;
60481
+ }
60482
+ column += 1;
60483
+ afterCarriageReturn = false;
60484
+ }
60485
+ return {
60486
+ line,
60487
+ column,
60488
+ offset: point.offset + appended.length
60489
+ };
60490
+ }
60051
60491
  /**
60052
60492
  * Append-only incremental parser over a caller-supplied grammar. One instance
60053
60493
  * accumulates one streaming document; non-append input resets it.
@@ -60059,10 +60499,112 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
60059
60499
  frozen = [];
60060
60500
  generation = 0;
60061
60501
  cached = null;
60502
+ openFence = null;
60062
60503
  /** @param parse - Grammar shared with whatever renders the blocks, so boundaries agree. */
60063
60504
  constructor(parse) {
60064
60505
  this.parse = parse;
60065
60506
  }
60507
+ /** Parse one unclosed-fence content slice through the caller's grammar. */
60508
+ fenceValue(state, text) {
60509
+ const root = this.parse(`${state.syntheticPrefix}${text}`);
60510
+ if (root.children.length !== 1) return void 0;
60511
+ const node = root.children[0];
60512
+ return node.type === "code" ? node.value : void 0;
60513
+ }
60514
+ /** Recognize the parsed tail's final unclosed fence and prepare its incremental content frontier. */
60515
+ openFenceState(text, base, tail, frozen) {
60516
+ const codeIndex = tail.length - 1;
60517
+ const block = tail[codeIndex];
60518
+ if (block?.node.type !== "code") return null;
60519
+ const node = block.node;
60520
+ const startOffset = node.position?.start.offset;
60521
+ const end = node.position?.end;
60522
+ if (startOffset === void 0 || end?.offset === void 0) return null;
60523
+ /* v8 ignore next -- the caller's parse slice ends at text.length, so its final node ends there. */
60524
+ if (base + end.offset !== text.length) return null;
60525
+ const source = text.slice(base);
60526
+ const previousLf = source.lastIndexOf("\n", startOffset - 1);
60527
+ const previousCr = source.lastIndexOf("\r", startOffset - 1);
60528
+ const lineStart = Math.max(previousLf, previousCr) + 1;
60529
+ const terminatorEnd = lineTerminatorEnd(source, startOffset);
60530
+ /* v8 ignore next -- a parser-confirmed fenced code node requires its opening line terminator. */
60531
+ if (terminatorEnd === void 0) return null;
60532
+ if (terminatorEnd === source.length && source.endsWith("\r")) return null;
60533
+ const openingLine = source.slice(lineStart, terminatorEnd).replace(/[\r\n]+$/, "");
60534
+ const opening = /^( {0,3})(`{3,}|~{3,})/.exec(openingLine);
60535
+ if (opening === null) return null;
60536
+ const indent = opening[1];
60537
+ const run = opening[2];
60538
+ /* v8 ignore next -- mdast positions a fenced code node at the matched delimiter after indentation. */
60539
+ if (lineStart + indent.length !== startOffset) return null;
60540
+ const marker = run[0];
60541
+ const contentStart = base + terminatorEnd;
60542
+ const content = text.slice(contentStart);
60543
+ if (containsClosingFence(content, marker, run.length)) return null;
60544
+ const syntheticPrefix = `${indent}${run}\n`;
60545
+ const stableLength = committableLinePrefixLength(content);
60546
+ const stableValue = stableLength === 0 ? "" : this.fenceValue({ syntheticPrefix }, content.slice(0, stableLength));
60547
+ if (stableValue === void 0) return null;
60548
+ const pendingStart = contentStart + stableLength;
60549
+ const stableSource = content.slice(0, stableLength);
60550
+ const valuePrefix = stableLength === 0 ? "" : `${stableValue}${trailingLineTerminator(stableSource)}`;
60551
+ const pendingValue = this.fenceValue({ syntheticPrefix }, text.slice(pendingStart));
60552
+ if (pendingValue === void 0 || `${valuePrefix}${pendingValue}` !== node.value) return null;
60553
+ return {
60554
+ marker,
60555
+ markerLength: run.length,
60556
+ syntheticPrefix,
60557
+ codeIndex,
60558
+ frozen,
60559
+ tail,
60560
+ pendingStart,
60561
+ valuePrefix,
60562
+ end: {
60563
+ line: end.line,
60564
+ column: end.column,
60565
+ offset: end.offset
60566
+ },
60567
+ endedWithCarriageReturn: text.endsWith("\r")
60568
+ };
60569
+ }
60570
+ /** Extend a recognized unclosed fence without parsing its completed content prefix again. */
60571
+ updateOpenFence(state, text, previousText) {
60572
+ const pending = text.slice(state.pendingStart);
60573
+ if (containsClosingFence(pending, state.marker, state.markerLength)) return void 0;
60574
+ const pendingValue = this.fenceValue(state, pending);
60575
+ if (pendingValue === void 0) return void 0;
60576
+ const stableLength = committableLinePrefixLength(pending);
60577
+ const stableValue = stableLength === 0 ? "" : this.fenceValue(state, pending.slice(0, stableLength));
60578
+ if (stableValue === void 0) return void 0;
60579
+ const previousNode = state.tail[state.codeIndex].node;
60580
+ const end = advancePoint(state.end, text.slice(previousText.length), state.endedWithCarriageReturn);
60581
+ const node = {
60582
+ ...previousNode,
60583
+ value: `${state.valuePrefix}${pendingValue}`,
60584
+ position: {
60585
+ start: previousNode.position.start,
60586
+ end
60587
+ }
60588
+ };
60589
+ const tail = state.tail.map((entry, index) => index === state.codeIndex ? {
60590
+ ...entry,
60591
+ node
60592
+ } : entry);
60593
+ const cached = {
60594
+ frozen: state.frozen,
60595
+ tail,
60596
+ generation: this.generation
60597
+ };
60598
+ this.openFence = {
60599
+ ...state,
60600
+ tail,
60601
+ pendingStart: state.pendingStart + stableLength,
60602
+ valuePrefix: stableLength === 0 ? state.valuePrefix : `${state.valuePrefix}${stableValue}${trailingLineTerminator(pending.slice(0, stableLength))}`,
60603
+ end,
60604
+ endedWithCarriageReturn: text.endsWith("\r")
60605
+ };
60606
+ return cached;
60607
+ }
60066
60608
  /**
60067
60609
  * Fold the current accumulated text and return the frozen/tail split.
60068
60610
  * Idempotent for identical input (the previous result is returned as-is),
@@ -60076,8 +60618,19 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
60076
60618
  this.prevText = "";
60077
60619
  this.tailStart = 0;
60078
60620
  this.frozen = [];
60621
+ this.openFence = null;
60079
60622
  this.generation += 1;
60080
60623
  }
60624
+ const previousText = this.prevText;
60625
+ if (previousText !== "" && this.openFence !== null) {
60626
+ const incremental = this.updateOpenFence(this.openFence, text, previousText);
60627
+ if (incremental !== void 0) {
60628
+ this.prevText = text;
60629
+ this.cached = incremental;
60630
+ return incremental;
60631
+ }
60632
+ this.openFence = null;
60633
+ }
60081
60634
  this.prevText = text;
60082
60635
  const base = this.tailStart;
60083
60636
  const blocks = this.parse(text.slice(base)).children;
@@ -60102,6 +60655,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
60102
60655
  tail,
60103
60656
  generation: this.generation
60104
60657
  };
60658
+ this.openFence = this.openFenceState(text, base, tail, this.cached.frozen);
60105
60659
  return this.cached;
60106
60660
  }
60107
60661
  };
@@ -60482,52 +61036,100 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
60482
61036
  },
60483
61037
  tabIndex: 0
60484
61038
  };
61039
+ /** Completed-line group size; React reconciles groups while the DOM remains line-for-line identical. */
61040
+ const STREAMING_LINE_GROUP_SIZE = 32;
61041
+ function renderLine(line, index) {
61042
+ return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [index > 0 && "\n", (0, react_jsx_runtime.jsx)("span", {
61043
+ className: "line",
61044
+ children: line.map((span, spanIndex) => (0, react_jsx_runtime.jsx)("span", {
61045
+ style: span.style,
61046
+ children: span.text
61047
+ }, spanIndex))
61048
+ })] }, index);
61049
+ }
60485
61050
  function CodeBlock({ code, lang, streaming, className, copyLabel, copiedLabel }) {
60486
61051
  const trimmed = code.endsWith("\n") ? code.slice(0, -1) : code;
61052
+ const rootRef = (0, react.useRef)(null);
61053
+ const highlighting = useViewportHighlighting(rootRef, lang);
60487
61054
  const loaded = (0, react.useSyncExternalStore)(subscribeGrammarLoaded, grammarLoadCount, grammarLoadCount);
60488
- const html = (0, react.useMemo)(() => streaming === true ? void 0 : highlightToHtml(trimmed, lang), [
60489
- streaming,
60490
- trimmed,
60491
- lang,
60492
- loaded
60493
- ]);
60494
61055
  const sessionRef = (0, react.useRef)(null);
60495
61056
  const lineCacheRef = (0, react.useRef)(null);
61057
+ const settledRef = (0, react.useRef)(false);
60496
61058
  const streamedBody = (0, react.useMemo)(() => {
61059
+ if (!highlighting) {
61060
+ sessionRef.current = null;
61061
+ lineCacheRef.current = null;
61062
+ settledRef.current = false;
61063
+ return;
61064
+ }
60497
61065
  if (streaming !== true) {
61066
+ const previous = lineCacheRef.current;
61067
+ if (previous !== null && previous.code === trimmed && previous.lang === lang) {
61068
+ settledRef.current = true;
61069
+ return previous.body;
61070
+ }
60498
61071
  sessionRef.current = null;
60499
61072
  lineCacheRef.current = null;
61073
+ settledRef.current = true;
60500
61074
  return;
60501
61075
  }
61076
+ if (settledRef.current) {
61077
+ sessionRef.current = null;
61078
+ lineCacheRef.current = null;
61079
+ settledRef.current = false;
61080
+ }
60502
61081
  sessionRef.current ??= new StreamingHighlightSession();
60503
- const lines = sessionRef.current.update(trimmed, lang);
60504
- if (lines === void 0) {
61082
+ const frame = sessionRef.current.updateFrame(trimmed, lang);
61083
+ if (frame === void 0) {
60505
61084
  lineCacheRef.current = null;
60506
61085
  return;
60507
61086
  }
60508
61087
  const previous = lineCacheRef.current;
60509
- const elements = lines.map((line, index) => previous !== null && previous.lines[index] === line ? previous.elements[index] : (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [index > 0 && "\n", (0, react_jsx_runtime.jsx)("span", {
60510
- className: "line",
60511
- children: line.map((span, spanIndex) => (0, react_jsx_runtime.jsx)("span", {
60512
- style: span.style,
60513
- children: span.text
60514
- }, spanIndex))
60515
- })] }, index));
60516
- lineCacheRef.current = {
60517
- lines,
60518
- elements
60519
- };
60520
- return (0, react_jsx_runtime.jsx)("pre", {
61088
+ if (previous?.frame === frame && previous.code === trimmed && previous.lang === lang) return previous.body;
61089
+ const sameGeneration = previous?.generation === frame.generation;
61090
+ const groups = sameGeneration ? [...previous.groups] : [];
61091
+ let pending = sameGeneration ? [...previous.pending] : [];
61092
+ let nextLine = sameGeneration ? previous.nextLine : 0;
61093
+ for (const line of frame.appended) {
61094
+ pending.push(renderLine(line, nextLine));
61095
+ nextLine += 1;
61096
+ if (pending.length !== STREAMING_LINE_GROUP_SIZE) continue;
61097
+ const start = nextLine - pending.length;
61098
+ groups.push((0, react_jsx_runtime.jsx)(react.Fragment, { children: pending }, start));
61099
+ pending = [];
61100
+ }
61101
+ const tail = frame.tail.map((line, index) => renderLine(line, nextLine + index));
61102
+ const tailGroup = (0, react_jsx_runtime.jsx)(react.Fragment, { children: [...pending, ...tail] }, nextLine - pending.length);
61103
+ const body = (0, react_jsx_runtime.jsx)("pre", {
60521
61104
  ...SHIKI_PRE_PROPS,
60522
- children: (0, react_jsx_runtime.jsx)("code", { children: elements })
61105
+ children: (0, react_jsx_runtime.jsxs)("code", { children: [groups, tailGroup] })
60523
61106
  });
61107
+ lineCacheRef.current = {
61108
+ code: trimmed,
61109
+ lang,
61110
+ generation: frame.generation,
61111
+ frame,
61112
+ groups,
61113
+ pending,
61114
+ nextLine,
61115
+ body
61116
+ };
61117
+ return body;
60524
61118
  }, [
60525
61119
  streaming,
61120
+ highlighting,
61121
+ trimmed,
61122
+ lang,
61123
+ loaded
61124
+ ]);
61125
+ const html = (0, react.useMemo)(() => highlighting && streaming !== true && streamedBody === void 0 ? highlightToHtml(trimmed, lang) : void 0, [
61126
+ streaming,
61127
+ highlighting,
61128
+ streamedBody,
60526
61129
  trimmed,
60527
61130
  lang,
60528
61131
  loaded
60529
61132
  ]);
60530
- const rootRef = (0, react.useRef)(null);
60531
61133
  const [copied, setCopied] = (0, react.useState)(false);
60532
61134
  const onCopy = (0, react.useCallback)(() => {
60533
61135
  if (copied) return;
@@ -60771,13 +61373,16 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
60771
61373
  const href = inlineCodeHttpUrl(value);
60772
61374
  if (href !== void 0) return (0, react_jsx_runtime.jsx)("code", { children: renderSafeLink(href, [value], "link") }, key);
60773
61375
  const mention = context.inLink === true ? void 0 : context.fileMentions?.resolve(value);
60774
- if (mention !== void 0) return (0, react_jsx_runtime.jsx)("code", { children: (0, react_jsx_runtime.jsx)("button", {
61376
+ if (mention !== void 0) return (0, react_jsx_runtime.jsx)("code", { children: (0, react_jsx_runtime.jsxs)("button", {
60775
61377
  type: "button",
60776
61378
  className: MarkdownText_module_default.fileMention,
60777
61379
  title: mention.title,
60778
61380
  "aria-label": mention.label,
60779
61381
  onClick: mention.open,
60780
- children: value
61382
+ children: [(0, react_jsx_runtime.jsx)(LinkIcon, {
61383
+ kind: classifyLinkPath(value),
61384
+ className: MarkdownText_module_default.linkIcon
61385
+ }), value]
60781
61386
  }) }, key);
60782
61387
  return (0, react_jsx_runtime.jsx)("code", { children: value }, key);
60783
61388
  }
@@ -60791,7 +61396,7 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
60791
61396
  case "link": return renderAnchor(node.url, renderChildren(node.children, {
60792
61397
  ...context,
60793
61398
  inLink: true
60794
- }), key);
61399
+ }), key, !anchorWrapsOnlyImages(node.children));
60795
61400
  case "linkReference": return renderLinkReference(node, key, context);
60796
61401
  case "image": return renderImage(node.url, node.alt ?? "", key);
60797
61402
  case "imageReference": return renderImageReference(node, key, context);
@@ -60886,22 +61491,33 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
60886
61491
  }
60887
61492
  return (0, react_jsx_runtime.jsx)("tr", { children: cells }, key);
60888
61493
  }
61494
+ /**
61495
+ * True when an anchor's markdown children are all images, so the anchor is a
61496
+ * clickable picture (badge, thumbnail): the leading URL glyph would dangle
61497
+ * beside the image instead of leading link text, so those anchors skip it.
61498
+ */
61499
+ function anchorWrapsOnlyImages(children) {
61500
+ return children.length > 0 && children.every((child) => child.type === "image" || child.type === "imageReference");
61501
+ }
60889
61502
  /** Anchor over an already-authored href: allowlisted or unwrapped, external links get the safe attributes. */
60890
- function renderSafeLink(href, children, key) {
61503
+ function renderSafeLink(href, children, key, glyph = true) {
60891
61504
  const safeHref = sanitizeUrl(href);
60892
61505
  if (safeHref === "") return (0, react_jsx_runtime.jsx)(react.Fragment, { children }, key);
60893
- return (0, react_jsx_runtime.jsx)("a", {
61506
+ return (0, react_jsx_runtime.jsxs)("a", {
60894
61507
  href: safeHref,
60895
61508
  ...["http:", "https:"].includes(new URL(safeHref).protocol) ? {
60896
61509
  target: "_blank",
60897
61510
  rel: "noopener noreferrer"
60898
61511
  } : {},
60899
- children
61512
+ children: [glyph && (0, react_jsx_runtime.jsx)(LinkIcon, {
61513
+ kind: "url",
61514
+ className: MarkdownText_module_default.linkIcon
61515
+ }), children]
60900
61516
  }, key);
60901
61517
  }
60902
61518
  /** Anchor over a parsed markdown destination, which hast normalized before the allowlist saw it. */
60903
- function renderAnchor(url, children, key) {
60904
- return renderSafeLink(normalizeUri(url), children, key);
61519
+ function renderAnchor(url, children, key, glyph = true) {
61520
+ return renderSafeLink(normalizeUri(url), children, key, glyph);
60905
61521
  }
60906
61522
  /**
60907
61523
  * The complete inline-code value when it is exactly an absolute HTTP(S) URL
@@ -60944,10 +61560,11 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
60944
61560
  renderChildren(node.children, context),
60945
61561
  referenceSuffix(node)
60946
61562
  ] }, key);
60947
- return renderAnchor(definition.url, renderChildren(node.children, {
61563
+ const rendered = renderChildren(node.children, {
60948
61564
  ...context,
60949
61565
  inLink: true
60950
- }), key);
61566
+ });
61567
+ return renderAnchor(definition.url, rendered, key, !anchorWrapsOnlyImages(node.children));
60951
61568
  }
60952
61569
  function renderImageReference(node, key, context) {
60953
61570
  const definition = context.targets.definitions.get(node.identifier.toUpperCase());
@@ -61027,7 +61644,8 @@ XID_Start XIDS`.split(/\s/).map((p) => [w(p), p]));
61027
61644
  };
61028
61645
  const blocks = wrapBlockChildren(renderBlocks(root.children.map((node, index) => ({
61029
61646
  node,
61030
- key: index
61647
+ /* v8 ignore next -- parseFull uses parseGfm, which stamps every top-level node. */
61648
+ key: node.position?.start.offset ?? -(index + 1)
61031
61649
  })), context), false);
61032
61650
  const section = renderFootnoteSection(context);
61033
61651
  return section === null ? blocks : [