@stackone/malachite 2.49.0 → 2.49.1

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.
@@ -1,61 +1,63 @@
1
- import { jsxs as S, jsx as e } from "react/jsx-runtime";
2
- import T from "@uiw/react-json-view";
3
- import g from "react";
4
- import _ from "./CustomIcons/CopyIcon.js";
5
- import { diffHunks as D } from "./codeBlockDiff.js";
6
- import { CodeLine as I } from "./codeBlockLine.js";
7
- import { FOCUS_RING as O } from "./focusRing.js";
8
- const A = g.lazy(() => import("./CodeBlockHighlighter.js")), z = {
1
+ import { jsxs as _, jsx as e } from "react/jsx-runtime";
2
+ import D from "@uiw/react-json-view";
3
+ import j from "react";
4
+ import O from "./CustomIcons/CopyIcon.js";
5
+ import { diffHunks as $ } from "./codeBlockDiff.js";
6
+ import { CodeLine as z } from "./codeBlockLine.js";
7
+ import { FOCUS_RING_INSET as K, FOCUS_RING as B } from "./focusRing.js";
8
+ const F = j.lazy(() => import("./CodeBlockHighlighter.js")), E = {
9
9
  added: "var(--malachite-codeblock-diff-added-background)",
10
10
  removed: "var(--malachite-codeblock-diff-removed-background)",
11
11
  context: void 0
12
- }, B = {
12
+ }, G = {
13
13
  added: "+",
14
14
  removed: "-",
15
15
  context: void 0
16
- }, K = {
16
+ }, M = {
17
17
  added: "var(--malachite-codeblock-diff-assistant-background)",
18
18
  removed: "var(--malachite-codeblock-diff-assistant-removed-background)",
19
19
  context: void 0
20
- }, $ = {
20
+ }, U = {
21
21
  added: "✦",
22
22
  // U+2212 minus sign, not a hyphen: the mock is explicit about which glyph.
23
23
  removed: "−",
24
24
  context: "·"
25
- }, M = {
25
+ }, H = {
26
26
  added: "var(--malachite-codeblock-diff-assistant-foreground)",
27
27
  removed: "var(--malachite-codeblock-diff-removed-foreground)",
28
28
  context: "var(--malachite-codeblock-diff-context-foreground)"
29
- }, E = (o) => `⋯ ${o} unchanged ${o === 1 ? "line" : "lines"}`, G = (o, d, n) => {
29
+ }, P = (o) => `⋯ ${o} unchanged ${o === 1 ? "line" : "lines"}`, q = (o, d, n) => {
30
30
  const t = n === "assistant";
31
31
  return {
32
- background: t ? K[o.type] : z[o.type],
33
- marker: t ? $[o.type] : B[o.type],
34
- markerColor: t ? M[o.type] : void 0,
32
+ background: t ? M[o.type] : E[o.type],
33
+ marker: t ? U[o.type] : G[o.type],
34
+ markerColor: t ? H[o.type] : void 0,
35
35
  // Reserved on unchanged rows too, so the code column does not step in and out.
36
36
  reserveMarker: !0,
37
37
  // Context rows read as de-emphasised, not just unmarked, in the assistant palette.
38
38
  textColor: t && o.type === "context" ? "var(--malachite-codeblock-diff-context-text)" : void 0,
39
39
  strikethrough: t && o.type === "removed",
40
- separatorAbove: o.skippedAbove === void 0 ? void 0 : E(o.skippedAbove),
40
+ separatorAbove: o.skippedAbove === void 0 ? void 0 : P(o.skippedAbove),
41
41
  // A removed line has no number in the after-text, so it keeps the one it had before.
42
42
  lineNumber: d ? o.afterNumber ?? o.beforeNumber : void 0
43
43
  };
44
- }, Y = ({
44
+ }, eo = ({
45
45
  code: o,
46
46
  json: d,
47
47
  showLineNumbers: n = !0,
48
48
  className: t = "",
49
- style: j = {},
50
- height: x,
51
- enableCopy: s = !0,
52
- wrapLines: u = !1,
53
- language: v,
54
- collapsed: N = !1,
55
- diff: l
49
+ style: x = {},
50
+ height: C,
51
+ enableCopy: u = !0,
52
+ wrapLines: k = !1,
53
+ language: b,
54
+ collapsed: I = !1,
55
+ diff: l,
56
+ "aria-label": w,
57
+ "aria-labelledby": S
56
58
  }) => {
57
- const a = l ? D(l.before, l.after, l.context) : null, m = (a == null ? void 0 : a.map((c) => c.text).join(`
58
- `)) ?? "", k = (() => {
59
+ const a = l ? $(l.before, l.after, l.context) : null, m = (a == null ? void 0 : a.map((c) => c.text).join(`
60
+ `)) ?? "", h = (() => {
59
61
  if (a)
60
62
  return m;
61
63
  if (o)
@@ -66,36 +68,42 @@ const A = g.lazy(() => import("./CodeBlockHighlighter.js")), z = {
66
68
  } catch {
67
69
  return;
68
70
  }
69
- })(), C = s && k !== void 0 && /* @__PURE__ */ e(
71
+ })(), N = u && h !== void 0 && /* @__PURE__ */ e(
70
72
  "button",
71
73
  {
72
74
  type: "button",
73
75
  "aria-label": "Copy",
74
76
  onClick: () => {
75
77
  var c, r;
76
- k !== void 0 && ((r = (c = navigator.clipboard) == null ? void 0 : c.writeText(k)) == null || r.catch(() => {
78
+ h !== void 0 && ((r = (c = navigator.clipboard) == null ? void 0 : c.writeText(h)) == null || r.catch(() => {
77
79
  }));
78
80
  },
79
- className: `absolute top-2 right-2 z-10 flex items-center justify-center rounded-md border border-solid border-[var(--malachite-codeblock-border)] bg-[var(--malachite-codeblock-background)] p-1.5 transition-colors hover:bg-[var(--malachite-codeblock-border)] ${O}`,
81
+ className: `absolute top-2 right-2 z-10 flex items-center justify-center rounded-md border border-solid border-[var(--malachite-codeblock-border)] bg-[var(--malachite-codeblock-background)] p-1.5 transition-colors hover:bg-[var(--malachite-codeblock-border)] ${B}`,
80
82
  style: { color: "var(--malachite-codeblock-line-number)" },
81
- children: /* @__PURE__ */ e(_, { size: 14 })
83
+ children: /* @__PURE__ */ e(O, { size: 14 })
82
84
  }
83
- );
85
+ ), i = {
86
+ role: "region",
87
+ "aria-label": S ? w : w ?? "Code",
88
+ "aria-labelledby": S,
89
+ tabIndex: 0,
90
+ className: `box-border h-full overflow-auto ${K}`
91
+ };
84
92
  if (d && !a)
85
- return /* @__PURE__ */ S(
93
+ return /* @__PURE__ */ _(
86
94
  "div",
87
95
  {
88
- className: `relative border rounded-lg overflow-hidden ${t}`,
96
+ className: `relative border border-solid rounded-lg overflow-hidden ${t}`,
89
97
  style: {
90
98
  backgroundColor: "var(--malachite-codeblock-background)",
91
99
  borderColor: "var(--malachite-codeblock-border)",
92
- height: x,
93
- ...j
100
+ height: C,
101
+ ...x
94
102
  },
95
103
  children: [
96
- C,
97
- /* @__PURE__ */ e(
98
- T,
104
+ N,
105
+ /* @__PURE__ */ e("div", { ...i, children: /* @__PURE__ */ e(
106
+ D,
99
107
  {
100
108
  value: d,
101
109
  style: {
@@ -133,39 +141,40 @@ const A = g.lazy(() => import("./CodeBlockHighlighter.js")), z = {
133
141
  "--w-rjv-type-undefined-color": "var(--malachite-codeblock-comment)"
134
142
  },
135
143
  displayDataTypes: !1,
136
- enableClipboard: s,
137
- collapsed: N,
144
+ enableClipboard: u,
145
+ collapsed: I,
138
146
  displayObjectSize: !1
139
147
  }
140
- )
148
+ ) })
141
149
  ]
142
150
  }
143
151
  );
144
- const h = s && (!!o || !!a), p = (c, r) => {
145
- const f = c.split(`
152
+ const p = u && (!!o || !!a), f = (c, r) => {
153
+ const y = c.split(`
146
154
  `);
147
155
  return /* @__PURE__ */ e(
148
156
  "div",
149
157
  {
150
- className: "p-4 overflow-auto text-left",
151
- style: { paddingRight: h ? 44 : void 0 },
152
- children: /* @__PURE__ */ e("div", { style: { width: "max-content", minWidth: "100%" }, children: f.map((i, y) => {
153
- const b = r == null ? void 0 : r(y);
158
+ ...i,
159
+ className: `${i.className} p-4 text-left`,
160
+ style: { paddingRight: p ? 44 : void 0 },
161
+ children: /* @__PURE__ */ e("div", { style: { width: "max-content", minWidth: "100%" }, children: y.map((v, g) => {
162
+ const s = r == null ? void 0 : r(g);
154
163
  return /* @__PURE__ */ e(
155
- I,
164
+ z,
156
165
  {
157
- line: i,
158
- lineNumber: (b == null ? void 0 : b.lineNumber) ?? (n ? y + 1 : void 0),
159
- wrap: u,
160
- decoration: b,
161
- children: i
166
+ line: v,
167
+ lineNumber: (s == null ? void 0 : s.lineNumber) ?? (n ? g + 1 : void 0),
168
+ wrap: k,
169
+ decoration: s,
170
+ children: v
162
171
  },
163
- y
172
+ g
164
173
  );
165
174
  }) })
166
175
  }
167
176
  );
168
- }, w = () => o ? p(o) : null, F = (c) => {
177
+ }, A = () => o ? f(o) : null, R = (c) => {
169
178
  if (c.length === 0)
170
179
  return /* @__PURE__ */ e(
171
180
  "div",
@@ -175,49 +184,51 @@ const A = g.lazy(() => import("./CodeBlockHighlighter.js")), z = {
175
184
  children: "No changes"
176
185
  }
177
186
  );
178
- const r = (f) => {
179
- const i = c[f];
180
- return i ? G(i, n, l == null ? void 0 : l.origin) : void 0;
187
+ const r = (y) => {
188
+ const v = c[y];
189
+ return v ? q(v, n, l == null ? void 0 : l.origin) : void 0;
181
190
  };
182
- return v ? /* @__PURE__ */ e(g.Suspense, { fallback: p(m, r), children: /* @__PURE__ */ e(
183
- A,
191
+ return b ? /* @__PURE__ */ e(j.Suspense, { fallback: f(m, r), children: /* @__PURE__ */ e(
192
+ F,
184
193
  {
185
194
  code: m,
186
- language: v,
195
+ language: b,
187
196
  showLineNumbers: n,
188
- wrapLines: u,
189
- copyClearance: h,
190
- decorate: r
197
+ wrapLines: k,
198
+ copyClearance: p,
199
+ decorate: r,
200
+ viewportProps: i
191
201
  }
192
- ) }) : p(m, r);
193
- }, R = () => o ? v ? /* @__PURE__ */ e(g.Suspense, { fallback: w(), children: /* @__PURE__ */ e(
194
- A,
202
+ ) }) : f(m, r);
203
+ }, T = () => o ? b ? /* @__PURE__ */ e(j.Suspense, { fallback: A(), children: /* @__PURE__ */ e(
204
+ F,
195
205
  {
196
206
  code: o,
197
- language: v,
207
+ language: b,
198
208
  showLineNumbers: n,
199
- wrapLines: u,
200
- copyClearance: h
209
+ wrapLines: k,
210
+ copyClearance: p,
211
+ viewportProps: i
201
212
  }
202
- ) }) : w() : null;
203
- return /* @__PURE__ */ S(
213
+ ) }) : A() : null;
214
+ return /* @__PURE__ */ _(
204
215
  "div",
205
216
  {
206
- className: `relative border rounded-lg overflow-hidden ${t}`,
217
+ className: `relative border border-solid rounded-lg overflow-hidden ${t}`,
207
218
  style: {
208
219
  backgroundColor: "var(--malachite-codeblock-background)",
209
220
  borderColor: "var(--malachite-codeblock-border)",
210
- height: x,
211
- ...j
221
+ height: C,
222
+ ...x
212
223
  },
213
224
  children: [
214
- C,
215
- a ? F(a) : R()
225
+ N,
226
+ a ? R(a) : T()
216
227
  ]
217
228
  }
218
229
  );
219
230
  };
220
231
  export {
221
- Y as default
232
+ eo as default
222
233
  };
223
234
  //# sourceMappingURL=CodeBlock.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CodeBlock.js","sources":["../../src/components/CodeBlock.tsx"],"sourcesContent":["import JsonView from '@uiw/react-json-view';\nimport React from 'react';\nimport CopyIcon from './CustomIcons/CopyIcon';\nimport { type DiffDisplayRow, type DiffRowType, diffHunks } from './codeBlockDiff';\nimport { CodeLine, type CodeLineDecoration } from './codeBlockLine';\nimport { FOCUS_RING } from './focusRing';\n\nconst CodeBlockHighlighter = React.lazy(() => import('./CodeBlockHighlighter'));\n\nexport interface CodeBlockProps {\n /** The code content to display */\n code?: string;\n /** JSON object to display as formatted JSON */\n json?: object;\n /** Show line numbers */\n showLineNumbers?: boolean;\n /** Custom class name */\n className?: string;\n /** Custom styles */\n style?: React.CSSProperties;\n /** Height of the code block */\n height?: string | number;\n /** Enable copy functionality */\n enableCopy?: boolean;\n /** Wrap long lines instead of scrolling horizontally */\n wrapLines?: boolean;\n /**\n * Highlight the code with this language's grammar. `cedar` is a grammar this library\n * ships itself (`prismCedar.ts`), since Prism and refractor carry none; widen the union\n * as further grammars are registered in CodeBlockHighlighter.\n */\n language?: 'yaml' | 'cedar';\n /** How much of a `json` tree starts collapsed: `true` all of it, a number below that depth. */\n collapsed?: boolean | number;\n /**\n * Renders the change between two texts rather than one text, and takes precedence over\n * `code` and `json`. Only the changed lines are shown, with `context` unchanged ones either\n * side, so a small edit to a long document reads as a few hunks instead of the whole thing.\n */\n diff?: {\n before: string;\n after: string;\n /** Unchanged lines kept either side of each change. Three by convention. */\n context?: number;\n /**\n * Swaps the `+`/`-` gutter and tinted rows for the palette a mock specified for\n * AI-authored changes: star, minus-sign and middle-dot markers, and a struck-through\n * removal. Omit to keep the neutral markers; there is no default consumer for the\n * assistant look yet.\n */\n origin?: 'assistant';\n };\n}\n\nconst DIFF_BACKGROUNDS: Record<DiffRowType, string | undefined> = {\n added: 'var(--malachite-codeblock-diff-added-background)',\n removed: 'var(--malachite-codeblock-diff-removed-background)',\n context: undefined,\n};\n\nconst DIFF_MARKERS: Record<DiffRowType, string | undefined> = {\n added: '+',\n removed: '-',\n context: undefined,\n};\n\n// The assistant palette also marks context rows, which the neutral one leaves bare.\nconst ASSISTANT_DIFF_BACKGROUNDS: Record<DiffRowType, string | undefined> = {\n added: 'var(--malachite-codeblock-diff-assistant-background)',\n removed: 'var(--malachite-codeblock-diff-assistant-removed-background)',\n context: undefined,\n};\n\nconst ASSISTANT_DIFF_MARKERS: Record<DiffRowType, string> = {\n added: '\\u2726',\n // U+2212 minus sign, not a hyphen: the mock is explicit about which glyph.\n removed: '\\u2212',\n context: '\\u00b7',\n};\n\nconst ASSISTANT_DIFF_MARKER_COLORS: Record<DiffRowType, string> = {\n added: 'var(--malachite-codeblock-diff-assistant-foreground)',\n removed: 'var(--malachite-codeblock-diff-removed-foreground)',\n context: 'var(--malachite-codeblock-diff-context-foreground)',\n};\n\nconst unchangedRun = (count: number): string =>\n `\\u22ef ${count} unchanged ${count === 1 ? 'line' : 'lines'}`;\n\nconst diffDecoration = (\n row: DiffDisplayRow,\n showLineNumbers: boolean,\n origin?: 'assistant',\n): CodeLineDecoration => {\n const assistant = origin === 'assistant';\n\n return {\n background: assistant ? ASSISTANT_DIFF_BACKGROUNDS[row.type] : DIFF_BACKGROUNDS[row.type],\n marker: assistant ? ASSISTANT_DIFF_MARKERS[row.type] : DIFF_MARKERS[row.type],\n markerColor: assistant ? ASSISTANT_DIFF_MARKER_COLORS[row.type] : undefined,\n // Reserved on unchanged rows too, so the code column does not step in and out.\n reserveMarker: true,\n // Context rows read as de-emphasised, not just unmarked, in the assistant palette.\n textColor:\n assistant && row.type === 'context'\n ? 'var(--malachite-codeblock-diff-context-text)'\n : undefined,\n strikethrough: assistant && row.type === 'removed',\n separatorAbove: row.skippedAbove === undefined ? undefined : unchangedRun(row.skippedAbove),\n // A removed line has no number in the after-text, so it keeps the one it had before.\n lineNumber: showLineNumbers ? (row.afterNumber ?? row.beforeNumber) : undefined,\n };\n};\n\nconst CodeBlock: React.FC<CodeBlockProps> = ({\n code,\n json,\n showLineNumbers = true,\n className = '',\n style = {},\n height,\n enableCopy = true,\n wrapLines = false,\n language,\n collapsed = false,\n diff,\n}) => {\n const diffRows = diff ? diffHunks(diff.before, diff.after, diff.context) : null;\n const diffText = diffRows?.map((row) => row.text).join('\\n') ?? '';\n\n /**\n * What the button puts on the clipboard, in the same form the block is showing. A JSON\n * block is pretty-printed rather than handed over minified: the reader is copying what\n * they can see. `undefined` means there is nothing to copy and no button to offer.\n */\n const copyText = (): string | undefined => {\n if (diffRows) {\n return diffText;\n }\n\n // An empty block has nothing to copy, so it offers no button — `!== undefined` would\n // hand back the empty string and put a dead control on it.\n if (code) {\n return code;\n }\n\n if (json !== undefined) {\n try {\n return JSON.stringify(json, null, 2);\n } catch {\n // A cycle or a BigInt: no honest text to copy, so offer no button.\n return undefined;\n }\n }\n\n return undefined;\n };\n\n const textToCopy = copyText();\n\n // `?.` no-ops when the clipboard API is absent (insecure context); `.catch` swallows a rejection.\n const handleCopy = () => {\n if (textToCopy === undefined) {\n return;\n }\n\n navigator.clipboard?.writeText(textToCopy)?.catch(() => undefined);\n };\n\n // Declared once and rendered by both the JSON branch and the code branch below, so the\n // two tabs of one document do not disagree about whether it can be copied.\n const copyButton = enableCopy && textToCopy !== undefined && (\n <button\n type=\"button\"\n aria-label=\"Copy\"\n onClick={handleCopy}\n className={`absolute top-2 right-2 z-10 flex items-center justify-center rounded-md border border-solid border-[var(--malachite-codeblock-border)] bg-[var(--malachite-codeblock-background)] p-1.5 transition-colors hover:bg-[var(--malachite-codeblock-border)] ${FOCUS_RING}`}\n style={{ color: 'var(--malachite-codeblock-line-number)' }}\n >\n <CopyIcon size={14} />\n </button>\n );\n\n // If JSON is provided, use JsonView component\n if (json && !diffRows) {\n return (\n <div\n className={`relative border rounded-lg overflow-hidden ${className}`}\n style={{\n backgroundColor: 'var(--malachite-codeblock-background)',\n borderColor: 'var(--malachite-codeblock-border)',\n height,\n ...style,\n }}\n >\n {copyButton}\n <JsonView\n value={json}\n style={\n {\n backgroundColor: 'var(--malachite-codeblock-background)',\n color: 'var(--malachite-codeblock-foreground)',\n fontSize: '14px',\n fontFamily: 'var(--malachite-font-mono, monospace)',\n padding: '16px',\n lineHeight: '1.5',\n textAlign: 'left',\n '--w-rjv-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-key-string': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-background-color': 'var(--malachite-codeblock-background)',\n '--w-rjv-line-color': 'var(--malachite-codeblock-border)',\n '--w-rjv-arrow-color': 'var(--malachite-codeblock-line-number)',\n '--w-rjv-edit-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-info-color': 'var(--malachite-codeblock-line-number)',\n '--w-rjv-update-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-copied-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-copied-success-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-curlybraces-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-colon-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-brackets-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-quotes-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-quotes-string-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-type-string-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-type-int-color': 'var(--malachite-codeblock-number)',\n '--w-rjv-type-float-color': 'var(--malachite-codeblock-number)',\n '--w-rjv-type-bigint-color': 'var(--malachite-codeblock-number)',\n '--w-rjv-type-boolean-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-type-date-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-type-url-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-type-null-color': 'var(--malachite-codeblock-comment)',\n '--w-rjv-type-nan-color': 'var(--malachite-codeblock-comment)',\n '--w-rjv-type-undefined-color': 'var(--malachite-codeblock-comment)',\n } as React.CSSProperties\n }\n displayDataTypes={false}\n enableClipboard={enableCopy}\n collapsed={collapsed}\n displayObjectSize={false}\n />\n </div>\n );\n }\n\n // Reserve clearance so a wide first line never sits under the floating copy button.\n const copyClearance = enableCopy && (!!code || !!diffRows);\n\n const renderPlainLines = (\n text: string,\n decorate?: (index: number) => CodeLineDecoration | undefined,\n ) => {\n const lines = text.split('\\n');\n\n return (\n <div\n className=\"p-4 overflow-auto text-left\"\n style={{ paddingRight: copyClearance ? 44 : undefined }}\n >\n {/* As wide as the widest line, floored at the view, so rows filling it end level. */}\n <div style={{ width: 'max-content', minWidth: '100%' }}>\n {lines.map((line, index) => {\n const decoration = decorate?.(index);\n\n return (\n <CodeLine\n key={index}\n line={line}\n lineNumber={\n decoration?.lineNumber ??\n (showLineNumbers ? index + 1 : undefined)\n }\n wrap={wrapLines}\n decoration={decoration}\n >\n {line}\n </CodeLine>\n );\n })}\n </div>\n </div>\n );\n };\n\n const renderPlainCode = () => (code ? renderPlainLines(code) : null);\n\n const renderDiff = (rows: DiffDisplayRow[]) => {\n if (rows.length === 0) {\n return (\n <div\n className=\"p-4 text-left\"\n style={{ color: 'var(--malachite-codeblock-comment)' }}\n >\n No changes\n </div>\n );\n }\n\n const decorate = (index: number) => {\n const row = rows[index];\n\n return row ? diffDecoration(row, showLineNumbers, diff?.origin) : undefined;\n };\n\n if (language) {\n return (\n <React.Suspense fallback={renderPlainLines(diffText, decorate)}>\n {/*\n * The whole merged text goes to the highlighter in one piece, so a hunk\n * is tokenised in the company of its neighbours rather than on its own.\n * Prism still cannot see the lines the hunks left out, so a construct\n * spanning an omitted run can highlight oddly — the reason `context`\n * defaults to a few lines rather than none.\n */}\n <CodeBlockHighlighter\n code={diffText}\n language={language}\n showLineNumbers={showLineNumbers}\n wrapLines={wrapLines}\n copyClearance={copyClearance}\n decorate={decorate}\n />\n </React.Suspense>\n );\n }\n\n return renderPlainLines(diffText, decorate);\n };\n\n // For code strings, create a simple syntax-highlighted view\n const renderCodeContent = () => {\n if (!code) {\n return null;\n }\n\n if (language) {\n return (\n <React.Suspense fallback={renderPlainCode()}>\n <CodeBlockHighlighter\n code={code}\n language={language}\n showLineNumbers={showLineNumbers}\n wrapLines={wrapLines}\n copyClearance={copyClearance}\n />\n </React.Suspense>\n );\n }\n\n return renderPlainCode();\n };\n\n return (\n <div\n className={`relative border rounded-lg overflow-hidden ${className}`}\n style={{\n backgroundColor: 'var(--malachite-codeblock-background)',\n borderColor: 'var(--malachite-codeblock-border)',\n height,\n ...style,\n }}\n >\n {copyButton}\n {diffRows ? renderDiff(diffRows) : renderCodeContent()}\n </div>\n );\n};\n\nexport default CodeBlock;\n"],"names":["CodeBlockHighlighter","React","DIFF_BACKGROUNDS","DIFF_MARKERS","ASSISTANT_DIFF_BACKGROUNDS","ASSISTANT_DIFF_MARKERS","ASSISTANT_DIFF_MARKER_COLORS","unchangedRun","count","diffDecoration","row","showLineNumbers","origin","assistant","CodeBlock","code","json","className","style","height","enableCopy","wrapLines","language","collapsed","diff","diffRows","diffHunks","diffText","textToCopy","copyButton","jsx","_b","_a","FOCUS_RING","CopyIcon","jsxs","JsonView","copyClearance","renderPlainLines","text","decorate","lines","line","index","decoration","CodeLine","renderPlainCode","renderDiff","rows","renderCodeContent"],"mappings":"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"}
1
+ {"version":3,"file":"CodeBlock.js","sources":["../../src/components/CodeBlock.tsx"],"sourcesContent":["import JsonView from '@uiw/react-json-view';\nimport React from 'react';\nimport CopyIcon from './CustomIcons/CopyIcon';\nimport { type DiffDisplayRow, type DiffRowType, diffHunks } from './codeBlockDiff';\nimport { CodeLine, type CodeLineDecoration } from './codeBlockLine';\nimport { FOCUS_RING, FOCUS_RING_INSET } from './focusRing';\n\nconst CodeBlockHighlighter = React.lazy(() => import('./CodeBlockHighlighter'));\n\nexport interface CodeBlockProps {\n /** The code content to display */\n code?: string;\n /** JSON object to display as formatted JSON */\n json?: object;\n /** Show line numbers */\n showLineNumbers?: boolean;\n /** Custom class name */\n className?: string;\n /** Custom styles */\n style?: React.CSSProperties;\n /** Height of the code block */\n height?: string | number;\n /** Enable copy functionality */\n enableCopy?: boolean;\n /** Wrap long lines instead of scrolling horizontally */\n wrapLines?: boolean;\n /**\n * Highlight the code with this language's grammar. `cedar` is a grammar this library\n * ships itself (`prismCedar.ts`), since Prism and refractor carry none; widen the union\n * as further grammars are registered in CodeBlockHighlighter.\n */\n language?: 'yaml' | 'cedar';\n /** How much of a `json` tree starts collapsed: `true` all of it, a number below that depth. */\n collapsed?: boolean | number;\n /**\n * Renders the change between two texts rather than one text, and takes precedence over\n * `code` and `json`. Only the changed lines are shown, with `context` unchanged ones either\n * side, so a small edit to a long document reads as a few hunks instead of the whole thing.\n */\n diff?: {\n before: string;\n after: string;\n /** Unchanged lines kept either side of each change. Three by convention. */\n context?: number;\n /**\n * Swaps the `+`/`-` gutter and tinted rows for the palette a mock specified for\n * AI-authored changes: star, minus-sign and middle-dot markers, and a struck-through\n * removal. Omit to keep the neutral markers; there is no default consumer for the\n * assistant look yet.\n */\n origin?: 'assistant';\n };\n /** Names the scrollable region. Defaults to \"Code\". */\n 'aria-label'?: string;\n /** Names the scrollable region by a visible label instead of `aria-label`. */\n 'aria-labelledby'?: string;\n}\n\nconst DIFF_BACKGROUNDS: Record<DiffRowType, string | undefined> = {\n added: 'var(--malachite-codeblock-diff-added-background)',\n removed: 'var(--malachite-codeblock-diff-removed-background)',\n context: undefined,\n};\n\nconst DIFF_MARKERS: Record<DiffRowType, string | undefined> = {\n added: '+',\n removed: '-',\n context: undefined,\n};\n\n// The assistant palette also marks context rows, which the neutral one leaves bare.\nconst ASSISTANT_DIFF_BACKGROUNDS: Record<DiffRowType, string | undefined> = {\n added: 'var(--malachite-codeblock-diff-assistant-background)',\n removed: 'var(--malachite-codeblock-diff-assistant-removed-background)',\n context: undefined,\n};\n\nconst ASSISTANT_DIFF_MARKERS: Record<DiffRowType, string> = {\n added: '\\u2726',\n // U+2212 minus sign, not a hyphen: the mock is explicit about which glyph.\n removed: '\\u2212',\n context: '\\u00b7',\n};\n\nconst ASSISTANT_DIFF_MARKER_COLORS: Record<DiffRowType, string> = {\n added: 'var(--malachite-codeblock-diff-assistant-foreground)',\n removed: 'var(--malachite-codeblock-diff-removed-foreground)',\n context: 'var(--malachite-codeblock-diff-context-foreground)',\n};\n\nconst unchangedRun = (count: number): string =>\n `\\u22ef ${count} unchanged ${count === 1 ? 'line' : 'lines'}`;\n\nconst diffDecoration = (\n row: DiffDisplayRow,\n showLineNumbers: boolean,\n origin?: 'assistant',\n): CodeLineDecoration => {\n const assistant = origin === 'assistant';\n\n return {\n background: assistant ? ASSISTANT_DIFF_BACKGROUNDS[row.type] : DIFF_BACKGROUNDS[row.type],\n marker: assistant ? ASSISTANT_DIFF_MARKERS[row.type] : DIFF_MARKERS[row.type],\n markerColor: assistant ? ASSISTANT_DIFF_MARKER_COLORS[row.type] : undefined,\n // Reserved on unchanged rows too, so the code column does not step in and out.\n reserveMarker: true,\n // Context rows read as de-emphasised, not just unmarked, in the assistant palette.\n textColor:\n assistant && row.type === 'context'\n ? 'var(--malachite-codeblock-diff-context-text)'\n : undefined,\n strikethrough: assistant && row.type === 'removed',\n separatorAbove: row.skippedAbove === undefined ? undefined : unchangedRun(row.skippedAbove),\n // A removed line has no number in the after-text, so it keeps the one it had before.\n lineNumber: showLineNumbers ? (row.afterNumber ?? row.beforeNumber) : undefined,\n };\n};\n\nconst CodeBlock: React.FC<CodeBlockProps> = ({\n code,\n json,\n showLineNumbers = true,\n className = '',\n style = {},\n height,\n enableCopy = true,\n wrapLines = false,\n language,\n collapsed = false,\n diff,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n}) => {\n const diffRows = diff ? diffHunks(diff.before, diff.after, diff.context) : null;\n const diffText = diffRows?.map((row) => row.text).join('\\n') ?? '';\n\n /**\n * What the button puts on the clipboard, in the same form the block is showing. A JSON\n * block is pretty-printed rather than handed over minified: the reader is copying what\n * they can see. `undefined` means there is nothing to copy and no button to offer.\n */\n const copyText = (): string | undefined => {\n if (diffRows) {\n return diffText;\n }\n\n // An empty block has nothing to copy, so it offers no button — `!== undefined` would\n // hand back the empty string and put a dead control on it.\n if (code) {\n return code;\n }\n\n if (json !== undefined) {\n try {\n return JSON.stringify(json, null, 2);\n } catch {\n // A cycle or a BigInt: no honest text to copy, so offer no button.\n return undefined;\n }\n }\n\n return undefined;\n };\n\n const textToCopy = copyText();\n\n // `?.` no-ops when the clipboard API is absent (insecure context); `.catch` swallows a rejection.\n const handleCopy = () => {\n if (textToCopy === undefined) {\n return;\n }\n\n navigator.clipboard?.writeText(textToCopy)?.catch(() => undefined);\n };\n\n // Declared once and rendered by both the JSON branch and the code branch below, so the\n // two tabs of one document do not disagree about whether it can be copied.\n const copyButton = enableCopy && textToCopy !== undefined && (\n <button\n type=\"button\"\n aria-label=\"Copy\"\n onClick={handleCopy}\n className={`absolute top-2 right-2 z-10 flex items-center justify-center rounded-md border border-solid border-[var(--malachite-codeblock-border)] bg-[var(--malachite-codeblock-background)] p-1.5 transition-colors hover:bg-[var(--malachite-codeblock-border)] ${FOCUS_RING}`}\n style={{ color: 'var(--malachite-codeblock-line-number)' }}\n >\n <CopyIcon size={14} />\n </button>\n );\n\n // Tabbable so a keyboard can scroll it: Safari never focuses a scroll container on its own.\n const viewportProps = {\n role: 'region',\n 'aria-label': ariaLabelledBy ? ariaLabel : (ariaLabel ?? 'Code'),\n 'aria-labelledby': ariaLabelledBy,\n tabIndex: 0,\n className: `box-border h-full overflow-auto ${FOCUS_RING_INSET}`,\n } satisfies React.HTMLAttributes<HTMLElement>;\n\n // If JSON is provided, use JsonView component\n if (json && !diffRows) {\n return (\n <div\n className={`relative border border-solid rounded-lg overflow-hidden ${className}`}\n style={{\n backgroundColor: 'var(--malachite-codeblock-background)',\n borderColor: 'var(--malachite-codeblock-border)',\n height,\n ...style,\n }}\n >\n {copyButton}\n {/* The frame clips at `height`; this scrolls inside it, so the copy button stays put. */}\n <div {...viewportProps}>\n <JsonView\n value={json}\n style={\n {\n backgroundColor: 'var(--malachite-codeblock-background)',\n color: 'var(--malachite-codeblock-foreground)',\n fontSize: '14px',\n fontFamily: 'var(--malachite-font-mono, monospace)',\n padding: '16px',\n lineHeight: '1.5',\n textAlign: 'left',\n '--w-rjv-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-key-string': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-background-color': 'var(--malachite-codeblock-background)',\n '--w-rjv-line-color': 'var(--malachite-codeblock-border)',\n '--w-rjv-arrow-color': 'var(--malachite-codeblock-line-number)',\n '--w-rjv-edit-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-info-color': 'var(--malachite-codeblock-line-number)',\n '--w-rjv-update-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-copied-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-copied-success-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-curlybraces-color':\n 'var(--malachite-codeblock-foreground)',\n '--w-rjv-colon-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-brackets-color': 'var(--malachite-codeblock-foreground)',\n '--w-rjv-quotes-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-quotes-string-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-type-string-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-type-int-color': 'var(--malachite-codeblock-number)',\n '--w-rjv-type-float-color': 'var(--malachite-codeblock-number)',\n '--w-rjv-type-bigint-color': 'var(--malachite-codeblock-number)',\n '--w-rjv-type-boolean-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-type-date-color': 'var(--malachite-codeblock-string)',\n '--w-rjv-type-url-color': 'var(--malachite-codeblock-keyword)',\n '--w-rjv-type-null-color': 'var(--malachite-codeblock-comment)',\n '--w-rjv-type-nan-color': 'var(--malachite-codeblock-comment)',\n '--w-rjv-type-undefined-color':\n 'var(--malachite-codeblock-comment)',\n } as React.CSSProperties\n }\n displayDataTypes={false}\n enableClipboard={enableCopy}\n collapsed={collapsed}\n displayObjectSize={false}\n />\n </div>\n </div>\n );\n }\n\n // Reserve clearance so a wide first line never sits under the floating copy button.\n const copyClearance = enableCopy && (!!code || !!diffRows);\n\n const renderPlainLines = (\n text: string,\n decorate?: (index: number) => CodeLineDecoration | undefined,\n ) => {\n const lines = text.split('\\n');\n\n return (\n <div\n {...viewportProps}\n className={`${viewportProps.className} p-4 text-left`}\n style={{ paddingRight: copyClearance ? 44 : undefined }}\n >\n {/* As wide as the widest line, floored at the view, so rows filling it end level. */}\n <div style={{ width: 'max-content', minWidth: '100%' }}>\n {lines.map((line, index) => {\n const decoration = decorate?.(index);\n\n return (\n <CodeLine\n key={index}\n line={line}\n lineNumber={\n decoration?.lineNumber ??\n (showLineNumbers ? index + 1 : undefined)\n }\n wrap={wrapLines}\n decoration={decoration}\n >\n {line}\n </CodeLine>\n );\n })}\n </div>\n </div>\n );\n };\n\n const renderPlainCode = () => (code ? renderPlainLines(code) : null);\n\n const renderDiff = (rows: DiffDisplayRow[]) => {\n if (rows.length === 0) {\n return (\n <div\n className=\"p-4 text-left\"\n style={{ color: 'var(--malachite-codeblock-comment)' }}\n >\n No changes\n </div>\n );\n }\n\n const decorate = (index: number) => {\n const row = rows[index];\n\n return row ? diffDecoration(row, showLineNumbers, diff?.origin) : undefined;\n };\n\n if (language) {\n return (\n <React.Suspense fallback={renderPlainLines(diffText, decorate)}>\n {/*\n * The whole merged text goes to the highlighter in one piece, so a hunk\n * is tokenised in the company of its neighbours rather than on its own.\n * Prism still cannot see the lines the hunks left out, so a construct\n * spanning an omitted run can highlight oddly — the reason `context`\n * defaults to a few lines rather than none.\n */}\n <CodeBlockHighlighter\n code={diffText}\n language={language}\n showLineNumbers={showLineNumbers}\n wrapLines={wrapLines}\n copyClearance={copyClearance}\n decorate={decorate}\n viewportProps={viewportProps}\n />\n </React.Suspense>\n );\n }\n\n return renderPlainLines(diffText, decorate);\n };\n\n // For code strings, create a simple syntax-highlighted view\n const renderCodeContent = () => {\n if (!code) {\n return null;\n }\n\n if (language) {\n return (\n <React.Suspense fallback={renderPlainCode()}>\n <CodeBlockHighlighter\n code={code}\n language={language}\n showLineNumbers={showLineNumbers}\n wrapLines={wrapLines}\n copyClearance={copyClearance}\n viewportProps={viewportProps}\n />\n </React.Suspense>\n );\n }\n\n return renderPlainCode();\n };\n\n return (\n <div\n className={`relative border border-solid rounded-lg overflow-hidden ${className}`}\n style={{\n backgroundColor: 'var(--malachite-codeblock-background)',\n borderColor: 'var(--malachite-codeblock-border)',\n height,\n ...style,\n }}\n >\n {copyButton}\n {diffRows ? renderDiff(diffRows) : renderCodeContent()}\n </div>\n );\n};\n\nexport default CodeBlock;\n"],"names":["CodeBlockHighlighter","React","DIFF_BACKGROUNDS","DIFF_MARKERS","ASSISTANT_DIFF_BACKGROUNDS","ASSISTANT_DIFF_MARKERS","ASSISTANT_DIFF_MARKER_COLORS","unchangedRun","count","diffDecoration","row","showLineNumbers","origin","assistant","CodeBlock","code","json","className","style","height","enableCopy","wrapLines","language","collapsed","diff","ariaLabel","ariaLabelledBy","diffRows","diffHunks","diffText","textToCopy","copyButton","jsx","_b","_a","FOCUS_RING","CopyIcon","viewportProps","FOCUS_RING_INSET","jsxs","JsonView","copyClearance","renderPlainLines","text","decorate","lines","line","index","decoration","CodeLine","renderPlainCode","renderDiff","rows","renderCodeContent"],"mappings":"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"}
@@ -1,13 +1,13 @@
1
1
  import { jsx as n } from "react/jsx-runtime";
2
- import y from "react-syntax-highlighter/dist/esm/create-element.js";
2
+ import w from "react-syntax-highlighter/dist/esm/create-element.js";
3
3
  import m from "react-syntax-highlighter/dist/esm/prism-light.js";
4
- import w from "refractor/yaml";
5
- import f from "./prismCedar.js";
6
- import { CodeLine as L } from "./codeBlockLine.js";
4
+ import f from "refractor/yaml";
5
+ import L from "./prismCedar.js";
6
+ import { CodeLine as R } from "./codeBlockLine.js";
7
7
  import { CODE_FONT as t } from "./codeBlockStyles.js";
8
8
  let s = !1;
9
- const R = () => {
10
- s || (s = !0, m.registerLanguage("yaml", w), m.registerLanguage("cedar", f));
9
+ const x = () => {
10
+ s || (s = !0, m.registerLanguage("yaml", f), m.registerLanguage("cedar", L));
11
11
  }, E = {
12
12
  'code[class*="language-"]': t,
13
13
  'pre[class*="language-"]': t,
@@ -53,11 +53,12 @@ const R = () => {
53
53
  language: e,
54
54
  showLineNumbers: c = !0,
55
55
  wrapLines: a = !1,
56
- copyClearance: k = !1,
57
- decorate: i
56
+ copyClearance: h = !1,
57
+ decorate: i,
58
+ viewportProps: k
58
59
  }) => {
59
- R();
60
- const h = o.split(`
60
+ x();
61
+ const b = o.split(`
61
62
  `);
62
63
  return /* @__PURE__ */ n(
63
64
  m,
@@ -65,30 +66,33 @@ const R = () => {
65
66
  language: e,
66
67
  style: E,
67
68
  wrapLines: !0,
68
- renderer: ({ rows: u, stylesheet: g, useInlineStyles: b }) => u.map((v, r) => {
69
- const l = i == null ? void 0 : i(r), p = (l == null ? void 0 : l.lineNumber) ?? (c ? r + 1 : void 0);
69
+ renderer: ({ rows: g, stylesheet: u, useInlineStyles: v }) => g.map((p, r) => {
70
+ const l = i == null ? void 0 : i(r), y = (l == null ? void 0 : l.lineNumber) ?? (c ? r + 1 : void 0);
70
71
  return /* @__PURE__ */ n(
71
- L,
72
+ R,
72
73
  {
73
- line: h[r] ?? "",
74
- lineNumber: p,
74
+ line: b[r] ?? "",
75
+ lineNumber: y,
75
76
  wrap: a,
76
77
  decoration: l,
77
- children: y({
78
- node: d(v),
79
- stylesheet: g,
80
- useInlineStyles: b,
78
+ children: w({
79
+ node: d(p),
80
+ stylesheet: u,
81
+ useInlineStyles: v,
81
82
  key: `code-line-${r}`
82
83
  })
83
84
  },
84
85
  r
85
86
  );
86
87
  }),
88
+ ...k,
87
89
  customStyle: {
88
90
  ...t,
91
+ boxSizing: "border-box",
92
+ height: "100%",
89
93
  margin: 0,
90
94
  padding: "16px",
91
- paddingRight: k ? "44px" : "16px",
95
+ paddingRight: h ? "44px" : "16px",
92
96
  overflow: "auto"
93
97
  },
94
98
  codeTagProps: {
@@ -1 +1 @@
1
- {"version":3,"file":"CodeBlockHighlighter.js","sources":["../../src/components/CodeBlockHighlighter.tsx"],"sourcesContent":["import type React from 'react';\nimport createElement from 'react-syntax-highlighter/dist/esm/create-element.js';\nimport PrismLight from 'react-syntax-highlighter/dist/esm/prism-light.js';\nimport yaml from 'refractor/yaml';\nimport cedar from './prismCedar';\nimport { CodeLine, type CodeLineDecoration } from './codeBlockLine';\nimport { CODE_FONT } from './codeBlockStyles';\n\n// Registered on first render rather than at import. A bare top-level call is an import-time\n// side effect, which `sideEffects: false` in package.json tells a bundler it may drop; the\n// same reason the font faces go in through ensureInterFontFace and not a top-level call.\nlet languagesRegistered = false;\n\nconst ensureLanguagesRegistered = (): void => {\n if (languagesRegistered) {\n return;\n }\n languagesRegistered = true;\n PrismLight.registerLanguage('yaml', yaml);\n PrismLight.registerLanguage('cedar', cedar);\n};\n\n// Prism token colors bound to the codeblock theme tokens so highlighting follows the theme.\nconst PRISM_MALACHITE_THEME: { [key: string]: React.CSSProperties } = {\n 'code[class*=\"language-\"]': CODE_FONT,\n 'pre[class*=\"language-\"]': CODE_FONT,\n comment: { color: 'var(--malachite-codeblock-comment)' },\n prolog: { color: 'var(--malachite-codeblock-comment)' },\n cdata: { color: 'var(--malachite-codeblock-comment)' },\n punctuation: { color: 'var(--malachite-codeblock-foreground)' },\n key: { color: 'var(--malachite-codeblock-keyword)' },\n atrule: { color: 'var(--malachite-codeblock-keyword)' },\n 'attr-name': { color: 'var(--malachite-codeblock-keyword)' },\n directive: { color: 'var(--malachite-codeblock-keyword)' },\n keyword: { color: 'var(--malachite-codeblock-keyword)' },\n property: { color: 'var(--malachite-codeblock-keyword)' },\n boolean: { color: 'var(--malachite-codeblock-keyword)' },\n important: { color: 'var(--malachite-codeblock-keyword)' },\n null: { color: 'var(--malachite-codeblock-keyword)' },\n tag: { color: 'var(--malachite-codeblock-keyword)' },\n anchor: { color: 'var(--malachite-codeblock-keyword)' },\n alias: { color: 'var(--malachite-codeblock-keyword)' },\n // Cedar's entity paths (`StackOne::Action`) are types, which is what this token is for.\n 'class-name': { color: 'var(--malachite-codeblock-type)' },\n // The scope variables. Given the one remaining distinct hue so they read as language\n // rather than as another blue keyword.\n builtin: { color: 'var(--malachite-codeblock-number)' },\n operator: { color: 'var(--malachite-codeblock-line-number)' },\n string: { color: 'var(--malachite-codeblock-string)' },\n scalar: { color: 'var(--malachite-codeblock-string)' },\n char: { color: 'var(--malachite-codeblock-string)' },\n url: { color: 'var(--malachite-codeblock-string)' },\n number: { color: 'var(--malachite-codeblock-number)' },\n datetime: { color: 'var(--malachite-codeblock-number)' },\n};\n\ntype SyntaxNode = {\n type: 'text' | 'element';\n value?: string | number;\n children?: SyntaxNode[];\n};\n\n/** Local, not the ambient `rendererProps`: that global leaks out of DefinitelyTyped by accident. */\ntype RowRendererProps = {\n rows: SyntaxNode[];\n stylesheet: { [key: string]: React.CSSProperties };\n useInlineStyles: boolean;\n};\n\n/** Prism keeps the source newline on each row's last token; `CodeLine` supplies the break now. */\nconst withoutTrailingNewline = <T extends SyntaxNode>(node: T): T => {\n if (node.type === 'text') {\n return typeof node.value === 'string' && node.value.endsWith('\\n')\n ? { ...node, value: node.value.slice(0, -1) }\n : node;\n }\n const children = node.children;\n if (!children?.length) {\n return node;\n }\n const last = children[children.length - 1];\n const trimmed = withoutTrailingNewline(last);\n return trimmed === last ? node : { ...node, children: [...children.slice(0, -1), trimmed] };\n};\n\nexport interface CodeBlockHighlighterProps {\n code: string;\n language: 'yaml' | 'cedar';\n showLineNumbers?: boolean;\n wrapLines?: boolean;\n /** Right padding reserving space for the floating copy button. */\n copyClearance?: boolean;\n /**\n * Per-line markup, by index into `code`. How a diff tints its rows and numbers them from\n * the text each line actually came from.\n */\n decorate?: (index: number) => CodeLineDecoration | undefined;\n}\n\nconst CodeBlockHighlighter: React.FC<CodeBlockHighlighterProps> = ({\n code,\n language,\n showLineNumbers = true,\n wrapLines = false,\n copyClearance = false,\n decorate,\n}) => {\n ensureLanguagesRegistered();\n\n const lines = code.split('\\n');\n\n // We lay rows out ourselves rather than passing `showLineNumbers`/`wrapLongLines` down:\n // that mode makes every line a flex container, so the Prism token spans become flex items\n // and the line shreds into out-of-order fragments.\n const renderRows = ({ rows, stylesheet, useInlineStyles }: RowRendererProps) =>\n rows.map((row, index) => {\n const decoration = decorate?.(index);\n // A decoration's own number wins: in a diff the row's position in the merged\n // text is not its line number in either of the texts it came from.\n const lineNumber = decoration?.lineNumber ?? (showLineNumbers ? index + 1 : undefined);\n\n return (\n <CodeLine\n key={index}\n line={lines[index] ?? ''}\n lineNumber={lineNumber}\n wrap={wrapLines}\n decoration={decoration}\n >\n {createElement({\n node: withoutTrailingNewline(row),\n stylesheet,\n useInlineStyles,\n key: `code-line-${index}`,\n })}\n </CodeLine>\n );\n });\n\n return (\n <PrismLight\n language={language}\n style={PRISM_MALACHITE_THEME}\n wrapLines\n renderer={renderRows}\n customStyle={{\n ...CODE_FONT,\n margin: 0,\n padding: '16px',\n paddingRight: copyClearance ? '44px' : '16px',\n overflow: 'auto',\n }}\n // The `code` element is the rows' wrapper here, so it takes the sizing the plain\n // path puts on a div of its own.\n codeTagProps={{\n style: { ...CODE_FONT, display: 'block', width: 'max-content', minWidth: '100%' },\n }}\n >\n {code}\n </PrismLight>\n );\n};\n\nexport default CodeBlockHighlighter;\n"],"names":["languagesRegistered","ensureLanguagesRegistered","PrismLight","yaml","cedar","PRISM_MALACHITE_THEME","CODE_FONT","withoutTrailingNewline","node","children","last","trimmed","CodeBlockHighlighter","code","language","showLineNumbers","wrapLines","copyClearance","decorate","lines","jsx","rows","stylesheet","useInlineStyles","row","index","decoration","lineNumber","CodeLine","createElement"],"mappings":"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"}
1
+ {"version":3,"file":"CodeBlockHighlighter.js","sources":["../../src/components/CodeBlockHighlighter.tsx"],"sourcesContent":["import type React from 'react';\nimport createElement from 'react-syntax-highlighter/dist/esm/create-element.js';\nimport PrismLight from 'react-syntax-highlighter/dist/esm/prism-light.js';\nimport yaml from 'refractor/yaml';\nimport cedar from './prismCedar';\nimport { CodeLine, type CodeLineDecoration } from './codeBlockLine';\nimport { CODE_FONT } from './codeBlockStyles';\n\n// Registered on first render rather than at import. A bare top-level call is an import-time\n// side effect, which `sideEffects: false` in package.json tells a bundler it may drop; the\n// same reason the font faces go in through ensureInterFontFace and not a top-level call.\nlet languagesRegistered = false;\n\nconst ensureLanguagesRegistered = (): void => {\n if (languagesRegistered) {\n return;\n }\n languagesRegistered = true;\n PrismLight.registerLanguage('yaml', yaml);\n PrismLight.registerLanguage('cedar', cedar);\n};\n\n// Prism token colors bound to the codeblock theme tokens so highlighting follows the theme.\nconst PRISM_MALACHITE_THEME: { [key: string]: React.CSSProperties } = {\n 'code[class*=\"language-\"]': CODE_FONT,\n 'pre[class*=\"language-\"]': CODE_FONT,\n comment: { color: 'var(--malachite-codeblock-comment)' },\n prolog: { color: 'var(--malachite-codeblock-comment)' },\n cdata: { color: 'var(--malachite-codeblock-comment)' },\n punctuation: { color: 'var(--malachite-codeblock-foreground)' },\n key: { color: 'var(--malachite-codeblock-keyword)' },\n atrule: { color: 'var(--malachite-codeblock-keyword)' },\n 'attr-name': { color: 'var(--malachite-codeblock-keyword)' },\n directive: { color: 'var(--malachite-codeblock-keyword)' },\n keyword: { color: 'var(--malachite-codeblock-keyword)' },\n property: { color: 'var(--malachite-codeblock-keyword)' },\n boolean: { color: 'var(--malachite-codeblock-keyword)' },\n important: { color: 'var(--malachite-codeblock-keyword)' },\n null: { color: 'var(--malachite-codeblock-keyword)' },\n tag: { color: 'var(--malachite-codeblock-keyword)' },\n anchor: { color: 'var(--malachite-codeblock-keyword)' },\n alias: { color: 'var(--malachite-codeblock-keyword)' },\n // Cedar's entity paths (`StackOne::Action`) are types, which is what this token is for.\n 'class-name': { color: 'var(--malachite-codeblock-type)' },\n // The scope variables. Given the one remaining distinct hue so they read as language\n // rather than as another blue keyword.\n builtin: { color: 'var(--malachite-codeblock-number)' },\n operator: { color: 'var(--malachite-codeblock-line-number)' },\n string: { color: 'var(--malachite-codeblock-string)' },\n scalar: { color: 'var(--malachite-codeblock-string)' },\n char: { color: 'var(--malachite-codeblock-string)' },\n url: { color: 'var(--malachite-codeblock-string)' },\n number: { color: 'var(--malachite-codeblock-number)' },\n datetime: { color: 'var(--malachite-codeblock-number)' },\n};\n\ntype SyntaxNode = {\n type: 'text' | 'element';\n value?: string | number;\n children?: SyntaxNode[];\n};\n\n/** Local, not the ambient `rendererProps`: that global leaks out of DefinitelyTyped by accident. */\ntype RowRendererProps = {\n rows: SyntaxNode[];\n stylesheet: { [key: string]: React.CSSProperties };\n useInlineStyles: boolean;\n};\n\n/** Prism keeps the source newline on each row's last token; `CodeLine` supplies the break now. */\nconst withoutTrailingNewline = <T extends SyntaxNode>(node: T): T => {\n if (node.type === 'text') {\n return typeof node.value === 'string' && node.value.endsWith('\\n')\n ? { ...node, value: node.value.slice(0, -1) }\n : node;\n }\n const children = node.children;\n if (!children?.length) {\n return node;\n }\n const last = children[children.length - 1];\n const trimmed = withoutTrailingNewline(last);\n return trimmed === last ? node : { ...node, children: [...children.slice(0, -1), trimmed] };\n};\n\nexport interface CodeBlockHighlighterProps {\n code: string;\n language: 'yaml' | 'cedar';\n showLineNumbers?: boolean;\n wrapLines?: boolean;\n /** Right padding reserving space for the floating copy button. */\n copyClearance?: boolean;\n /**\n * Per-line markup, by index into `code`. How a diff tints its rows and numbers them from\n * the text each line actually came from.\n */\n decorate?: (index: number) => CodeLineDecoration | undefined;\n /** Spread onto the `pre`, which is the block's scroll viewport. */\n viewportProps?: Pick<\n React.HTMLAttributes<HTMLElement>,\n 'role' | 'aria-label' | 'aria-labelledby' | 'tabIndex' | 'className'\n >;\n}\n\nconst CodeBlockHighlighter: React.FC<CodeBlockHighlighterProps> = ({\n code,\n language,\n showLineNumbers = true,\n wrapLines = false,\n copyClearance = false,\n decorate,\n viewportProps,\n}) => {\n ensureLanguagesRegistered();\n\n const lines = code.split('\\n');\n\n // We lay rows out ourselves rather than passing `showLineNumbers`/`wrapLongLines` down:\n // that mode makes every line a flex container, so the Prism token spans become flex items\n // and the line shreds into out-of-order fragments.\n const renderRows = ({ rows, stylesheet, useInlineStyles }: RowRendererProps) =>\n rows.map((row, index) => {\n const decoration = decorate?.(index);\n // A decoration's own number wins: in a diff the row's position in the merged\n // text is not its line number in either of the texts it came from.\n const lineNumber = decoration?.lineNumber ?? (showLineNumbers ? index + 1 : undefined);\n\n return (\n <CodeLine\n key={index}\n line={lines[index] ?? ''}\n lineNumber={lineNumber}\n wrap={wrapLines}\n decoration={decoration}\n >\n {createElement({\n node: withoutTrailingNewline(row),\n stylesheet,\n useInlineStyles,\n key: `code-line-${index}`,\n })}\n </CodeLine>\n );\n });\n\n return (\n <PrismLight\n language={language}\n style={PRISM_MALACHITE_THEME}\n wrapLines\n renderer={renderRows}\n {...viewportProps}\n customStyle={{\n ...CODE_FONT,\n boxSizing: 'border-box',\n height: '100%',\n margin: 0,\n padding: '16px',\n paddingRight: copyClearance ? '44px' : '16px',\n overflow: 'auto',\n }}\n // The `code` element is the rows' wrapper here, so it takes the sizing the plain\n // path puts on a div of its own.\n codeTagProps={{\n style: { ...CODE_FONT, display: 'block', width: 'max-content', minWidth: '100%' },\n }}\n >\n {code}\n </PrismLight>\n );\n};\n\nexport default CodeBlockHighlighter;\n"],"names":["languagesRegistered","ensureLanguagesRegistered","PrismLight","yaml","cedar","PRISM_MALACHITE_THEME","CODE_FONT","withoutTrailingNewline","node","children","last","trimmed","CodeBlockHighlighter","code","language","showLineNumbers","wrapLines","copyClearance","decorate","viewportProps","lines","jsx","rows","stylesheet","useInlineStyles","row","index","decoration","lineNumber","CodeLine","createElement"],"mappings":";;;;;;;AAWA,IAAIA,IAAsB;AAE1B,MAAMC,IAA4B,MAAY;AAC1C,EAAID,MAGJA,IAAsB,IACtBE,EAAW,iBAAiB,QAAQC,CAAI,GACxCD,EAAW,iBAAiB,SAASE,CAAK;AAC9C,GAGMC,IAAgE;AAAA,EAClE,4BAA4BC;AAAA,EAC5B,2BAA2BA;AAAA,EAC3B,SAAS,EAAE,OAAO,qCAAA;AAAA,EAClB,QAAQ,EAAE,OAAO,qCAAA;AAAA,EACjB,OAAO,EAAE,OAAO,qCAAA;AAAA,EAChB,aAAa,EAAE,OAAO,wCAAA;AAAA,EACtB,KAAK,EAAE,OAAO,qCAAA;AAAA,EACd,QAAQ,EAAE,OAAO,qCAAA;AAAA,EACjB,aAAa,EAAE,OAAO,qCAAA;AAAA,EACtB,WAAW,EAAE,OAAO,qCAAA;AAAA,EACpB,SAAS,EAAE,OAAO,qCAAA;AAAA,EAClB,UAAU,EAAE,OAAO,qCAAA;AAAA,EACnB,SAAS,EAAE,OAAO,qCAAA;AAAA,EAClB,WAAW,EAAE,OAAO,qCAAA;AAAA,EACpB,MAAM,EAAE,OAAO,qCAAA;AAAA,EACf,KAAK,EAAE,OAAO,qCAAA;AAAA,EACd,QAAQ,EAAE,OAAO,qCAAA;AAAA,EACjB,OAAO,EAAE,OAAO,qCAAA;AAAA;AAAA,EAEhB,cAAc,EAAE,OAAO,kCAAA;AAAA;AAAA;AAAA,EAGvB,SAAS,EAAE,OAAO,oCAAA;AAAA,EAClB,UAAU,EAAE,OAAO,yCAAA;AAAA,EACnB,QAAQ,EAAE,OAAO,oCAAA;AAAA,EACjB,QAAQ,EAAE,OAAO,oCAAA;AAAA,EACjB,MAAM,EAAE,OAAO,oCAAA;AAAA,EACf,KAAK,EAAE,OAAO,oCAAA;AAAA,EACd,QAAQ,EAAE,OAAO,oCAAA;AAAA,EACjB,UAAU,EAAE,OAAO,oCAAA;AACvB,GAgBMC,IAAyB,CAAuBC,MAAe;AACjE,MAAIA,EAAK,SAAS;AACd,WAAO,OAAOA,EAAK,SAAU,YAAYA,EAAK,MAAM,SAAS;AAAA,CAAI,IAC3D,EAAE,GAAGA,GAAM,OAAOA,EAAK,MAAM,MAAM,GAAG,EAAE,MACxCA;AAEV,QAAMC,IAAWD,EAAK;AACtB,MAAI,EAACC,KAAA,QAAAA,EAAU;AACX,WAAOD;AAEX,QAAME,IAAOD,EAASA,EAAS,SAAS,CAAC,GACnCE,IAAUJ,EAAuBG,CAAI;AAC3C,SAAOC,MAAYD,IAAOF,IAAO,EAAE,GAAGA,GAAM,UAAU,CAAC,GAAGC,EAAS,MAAM,GAAG,EAAE,GAAGE,CAAO,EAAA;AAC5F,GAqBMC,IAA4D,CAAC;AAAA,EAC/D,MAAAC;AAAA,EACA,UAAAC;AAAA,EACA,iBAAAC,IAAkB;AAAA,EAClB,WAAAC,IAAY;AAAA,EACZ,eAAAC,IAAgB;AAAA,EAChB,UAAAC;AAAA,EACA,eAAAC;AACJ,MAAM;AACF,EAAAlB,EAAA;AAEA,QAAMmB,IAAQP,EAAK,MAAM;AAAA,CAAI;AA8B7B,SACI,gBAAAQ;AAAA,IAACnB;AAAA,IAAA;AAAA,MACG,UAAAY;AAAA,MACA,OAAOT;AAAA,MACP,WAAS;AAAA,MACT,UA9BW,CAAC,EAAE,MAAAiB,GAAM,YAAAC,GAAY,iBAAAC,QACpCF,EAAK,IAAI,CAACG,GAAKC,MAAU;AACrB,cAAMC,IAAaT,KAAA,gBAAAA,EAAWQ,IAGxBE,KAAaD,KAAA,gBAAAA,EAAY,gBAAeZ,IAAkBW,IAAQ,IAAI;AAE5E,eACA,gBAAAL;AAAA,UAACQ;AAAA,UAAA;AAAA,YAEG,MAAMT,EAAMM,CAAK,KAAK;AAAA,YACtB,YAAAE;AAAA,YACA,MAAMZ;AAAA,YACN,YAAAW;AAAA,YAEC,UAAAG,EAAc;AAAA,cACX,MAAMvB,EAAuBkB,CAAG;AAAA,cAChC,YAAAF;AAAA,cACA,iBAAAC;AAAA,cACA,KAAK,aAAaE,CAAK;AAAA,YAAA,CAC1B;AAAA,UAAA;AAAA,UAXIA;AAAA,QAAA;AAAA,MAcb,CAAC;AAAA,MAQI,GAAGP;AAAA,MACJ,aAAa;AAAA,QACT,GAAGb;AAAA,QACH,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,cAAcW,IAAgB,SAAS;AAAA,QACvC,UAAU;AAAA,MAAA;AAAA,MAId,cAAc;AAAA,QACV,OAAO,EAAE,GAAGX,GAAW,SAAS,SAAS,OAAO,eAAe,UAAU,OAAA;AAAA,MAAO;AAAA,MAGnF,UAAAO;AAAA,IAAA;AAAA,EAAA;AAGb;"}