@stackone/malachite 2.56.0 → 2.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,24 +1,25 @@
1
1
  import { jsx as i, jsxs as c } from "react/jsx-runtime";
2
- import I from "marked-react";
2
+ import b from "marked-react";
3
3
  import d from "react";
4
- import { FOCUS_RING as g } from "../focusRing.js";
4
+ import { FOCUS_RING as E } from "../focusRing.js";
5
5
  import u from "./CodeText.js";
6
- import b from "./PageTitle.js";
7
- import E from "./SectionTitle.js";
8
- import { getInlineMarked as k } from "./inlineMarkdown.js";
9
- import { getFontSize as x, getTextColor as y } from "./textStyles.js";
10
- const L = "• ", R = {
6
+ import x from "./PageTitle.js";
7
+ import k from "./SectionTitle.js";
8
+ import { getInlineMarked as y } from "./inlineMarkdown.js";
9
+ import { getFontSize as L, getTextColor as R } from "./textStyles.js";
10
+ const _ = "• ", S = {
11
11
  color: "inherit",
12
12
  textDecoration: "underline",
13
13
  fontWeight: 600
14
- }, _ = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]), p = (e) => {
14
+ }, T = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]), p = (e) => {
15
15
  if (typeof e != "string")
16
16
  return !1;
17
17
  const r = /^([a-z][a-z0-9+.-]*):/i.exec(e.replace(/[\u0000-\u0020]/g, ""));
18
- return !r || _.has(`${r[1].toLowerCase()}:`);
19
- }, T = ({
18
+ return !r || T.has(`${r[1].toLowerCase()}:`);
19
+ }, w = (e) => /^\/(?![/\\])[^\t\n\r]*$/.test(e), f = `md-link rounded-xs ${E}`, N = ({
20
20
  omitMargin: e,
21
- links: r
21
+ links: r,
22
+ renderLink: s
22
23
  }) => ({
23
24
  blockquote(t) {
24
25
  return /* @__PURE__ */ i(
@@ -57,7 +58,7 @@ const L = "• ", R = {
57
58
  ) }, this.elementId);
58
59
  },
59
60
  heading(t, n) {
60
- return n === 1 ? /* @__PURE__ */ i(b, { children: t }, this.elementId) : /* @__PURE__ */ i(E, { children: t }, this.elementId);
61
+ return n === 1 ? /* @__PURE__ */ i(x, { children: t }, this.elementId) : /* @__PURE__ */ i(k, { children: t }, this.elementId);
61
62
  },
62
63
  br() {
63
64
  return /* @__PURE__ */ i("br", {}, this.elementId);
@@ -65,13 +66,13 @@ const L = "• ", R = {
65
66
  // `text`/`strong` are deliberately NOT overridden: a wrapping Text emits a font-weight, and
66
67
  // the nested 400 beat strong's 600 — which is why bold never rendered.
67
68
  link(t, n) {
68
- return p(t) ? r === "inert" ? /* @__PURE__ */ i("span", { style: R, children: n }, this.elementId) : (
69
+ return p(t) ? r === "inert" ? /* @__PURE__ */ i("span", { style: S, children: n }, this.elementId) : s && w(t) ? /* @__PURE__ */ i(d.Fragment, { children: s({ href: t, children: n, className: f }) }, this.elementId) : (
69
70
  // Hover is in tailwind.css: CLAUDE.md forbids JS for styling, and JS misses keyboard.
70
71
  // FOCUS_RING because a colour change alone is not a focus indicator.
71
72
  /* @__PURE__ */ i(
72
73
  "a",
73
74
  {
74
- className: `md-link rounded-xs ${g}`,
75
+ className: f,
75
76
  href: t,
76
77
  target: "_blank",
77
78
  rel: "noopener noreferrer",
@@ -82,24 +83,24 @@ const L = "• ", R = {
82
83
  ) : /* @__PURE__ */ i(d.Fragment, { children: n }, this.elementId);
83
84
  },
84
85
  // Overridden only to vet `src`. Alt text stands in for a rejected image.
85
- image(t, n, s) {
86
+ image(t, n, l) {
86
87
  return p(t) ? /* @__PURE__ */ i(
87
88
  "img",
88
89
  {
89
90
  src: t,
90
91
  alt: n ?? "",
91
- title: s ?? void 0,
92
+ title: l ?? void 0,
92
93
  style: { maxWidth: "100%" }
93
94
  },
94
95
  this.elementId
95
96
  ) : /* @__PURE__ */ i("span", { children: n ?? "" }, this.elementId);
96
97
  },
97
98
  // Preflight resets list-style/margin/padding; padding-left on the LIST is the hanging indent.
98
- list(t, n, s) {
99
+ list(t, n, l) {
99
100
  return /* @__PURE__ */ i(
100
101
  n ? "ol" : "ul",
101
102
  {
102
- start: n && s !== 1 ? s : void 0,
103
+ start: n && l !== 1 ? l : void 0,
103
104
  style: {
104
105
  listStyle: n ? "decimal" : "disc",
105
106
  paddingLeft: "1.25em",
@@ -116,7 +117,7 @@ const L = "• ", R = {
116
117
  /* @__PURE__ */ i("li", { style: { padding: e ? "0px" : "2px 0px" }, children: t }, this.elementId)
117
118
  );
118
119
  }
119
- }), w = () => ({
120
+ }), F = () => ({
120
121
  paragraph(e) {
121
122
  return /* @__PURE__ */ c("span", { children: [
122
123
  e,
@@ -142,15 +143,15 @@ const L = "• ", R = {
142
143
  // The list owns markers and breaks — ordered numbering needs `start` plus the item index.
143
144
  // A <br> opens a line box (what -webkit-line-clamp counts); `display: block` would not.
144
145
  // Items OPEN with it, so tailwind.css suppresses the leading one on a first-child list.
145
- list(e, r, t) {
146
- const n = d.Children.toArray(e);
146
+ list(e, r, s) {
147
+ const t = d.Children.toArray(e);
147
148
  return /* @__PURE__ */ c("span", { role: "list", style: { display: "inline" }, children: [
148
- n.map((s, l) => (
149
+ t.map((n, l) => (
149
150
  // Index as key: one list node's rendered children never reorder.
150
151
  /* @__PURE__ */ c("span", { role: "listitem", style: { display: "inline" }, children: [
151
152
  /* @__PURE__ */ i("br", {}),
152
- /* @__PURE__ */ i("span", { "aria-hidden": "true", children: r ? `${(t ?? 1) + l}. ` : L }),
153
- s
153
+ /* @__PURE__ */ i("span", { "aria-hidden": "true", children: r ? `${(s ?? 1) + l}. ` : _ }),
154
+ n
154
155
  ] }, l)
155
156
  )),
156
157
  /* @__PURE__ */ i("br", {})
@@ -208,124 +209,125 @@ const L = "• ", R = {
208
209
  image(e, r) {
209
210
  return /* @__PURE__ */ i("span", { children: r ? `${r} ` : "" }, this.elementId);
210
211
  }
211
- }), F = () => ({
212
+ }), C = () => ({
212
213
  image(e, r) {
213
214
  return /* @__PURE__ */ i(d.Fragment, { children: r ?? "" }, this.elementId);
214
215
  },
215
216
  br() {
216
217
  return /* @__PURE__ */ i(d.Fragment, { children: " " }, this.elementId);
217
218
  }
218
- }), f = (e) => {
219
+ }), I = (e) => {
219
220
  const r = e.split(`
220
- `), t = r.reduce((s, l) => {
221
+ `), s = r.reduce((n, l) => {
221
222
  var o;
222
- return l.trim() !== "" && s.push(((o = l.match(/^[ \t]*(?=\S)/gm)) == null ? void 0 : o[0].length) ?? 0), s;
223
+ return l.trim() !== "" && n.push(((o = l.match(/^[ \t]*(?=\S)/gm)) == null ? void 0 : o[0].length) ?? 0), n;
223
224
  }, []);
224
- if (t.length === 0)
225
+ if (s.length === 0)
225
226
  return e;
226
- const n = Math.min(...t);
227
- return r.map((s) => s.replace(new RegExp(`^[ \\t]{${n}}`, "gm"), "")).join(`
227
+ const t = Math.min(...s);
228
+ return r.map((n) => n.replace(new RegExp(`^[ \\t]{${t}}`, "gm"), "")).join(`
228
229
  `);
229
- }, N = /^ {0,3}(?:```|~~~)/, S = /^ {2,}\S/, B = /^ {0,3}(?:=+|-+)\s*$/, C = /^ {0,3}(?:(?:-\s*){3,}|(?:\*\s*){3,}|(?:_\s*){3,})$/, A = /^[-*+]\s/, $ = /^(\d{1,9})[.)]\s/, D = /^\*\*[^*]+:\*\*$|^\*\*[^*]+\*\*:$/, h = /\*\*[^*\n]+?:\*\*|\*\*[^*\n]+?\*\*:/g, M = /^\s*(?:[-*+]|\d{1,9}[.)])\s+/, O = (e) => {
230
+ }, A = /^ {0,3}(?:```|~~~)/, B = /^ {2,}\S/, $ = /^ {0,3}(?:=+|-+)\s*$/, D = /^ {0,3}(?:(?:-\s*){3,}|(?:\*\s*){3,}|(?:_\s*){3,})$/, M = /^[-*+]\s/, v = /^(\d{1,9})[.)]\s/, O = /^\*\*[^*]+:\*\*$|^\*\*[^*]+\*\*:$/, h = /\*\*[^*\n]+?:\*\*|\*\*[^*\n]+?\*\*:/g, K = /^\s*(?:[-*+]|\d{1,9}[.)])\s+/, W = (e) => {
230
231
  var l;
231
- const r = ((l = M.exec(e)) == null ? void 0 : l[0]) ?? "";
232
- let t = e.slice(r.length);
233
- const n = [];
234
- let s = !0;
232
+ const r = ((l = K.exec(e)) == null ? void 0 : l[0]) ?? "";
233
+ let s = e.slice(r.length);
234
+ const t = [];
235
+ let n = !0;
235
236
  for (; ; ) {
236
237
  h.lastIndex = 0;
237
- let o = null, a = h.exec(t);
238
+ let o = null, a = h.exec(s);
238
239
  for (; a; ) {
239
240
  if (a.index > 0) {
240
241
  o = a;
241
242
  break;
242
243
  }
243
- a = h.exec(t);
244
+ a = h.exec(s);
244
245
  }
245
246
  if (!o)
246
247
  break;
247
- const m = t.slice(0, o.index).trimEnd();
248
- m && (n.push((s ? r : "") + m), s = !1), t = t.slice(o.index);
248
+ const m = s.slice(0, o.index).trimEnd();
249
+ m && (t.push((n ? r : "") + m), n = !1), s = s.slice(o.index);
249
250
  }
250
- return n.push((s ? r : "") + t), n;
251
- }, v = (e, r) => {
252
- const t = e.trim();
253
- if (!t)
251
+ return t.push((n ? r : "") + s), t;
252
+ }, j = (e, r) => {
253
+ const s = e.trim();
254
+ if (!s)
254
255
  return "blank";
255
- if (C.test(e) || B.test(e))
256
+ if (D.test(e) || $.test(e))
256
257
  return r === "blank" ? "prose" : r;
257
- if (A.test(t))
258
+ if (M.test(s))
258
259
  return "item";
259
- const n = $.exec(t);
260
- return n && (r !== "prose" || n[1] === "1") ? "item" : D.test(t) ? "label" : "prose";
261
- }, K = (e) => {
260
+ const t = v.exec(s);
261
+ return t && (r !== "prose" || t[1] === "1") ? "item" : O.test(s) ? "label" : "prose";
262
+ }, H = (e) => {
262
263
  const r = e.split(`
263
- `), t = [];
264
- let n = "blank", s = !1;
264
+ `), s = [];
265
+ let t = "blank", n = !1;
265
266
  for (const l of r) {
266
- if (N.test(l)) {
267
- s = !s, t.push(l), n = "blank";
267
+ if (A.test(l)) {
268
+ n = !n, s.push(l), t = "blank";
268
269
  continue;
269
270
  }
270
- if (s) {
271
- t.push(l);
271
+ if (n) {
272
+ s.push(l);
272
273
  continue;
273
274
  }
274
- if (S.test(l)) {
275
- t.push(l);
275
+ if (B.test(l)) {
276
+ s.push(l);
276
277
  continue;
277
278
  }
278
- for (const o of O(l))
279
- n = W(o, n, t);
279
+ for (const o of W(l))
280
+ t = U(o, t, s);
280
281
  }
281
- return t.join(`
282
+ return s.join(`
282
283
  `);
283
- }, W = (e, r, t) => {
284
- const n = v(e, r);
285
- return n !== "blank" && r !== "blank" && n !== r && t.push(""), t.push(e), n;
286
- }, j = ({
284
+ }, U = (e, r, s) => {
285
+ const t = j(e, r);
286
+ return t !== "blank" && r !== "blank" && t !== r && s.push(""), s.push(e), t;
287
+ }, q = ({
287
288
  text: e,
288
289
  color: r,
289
- size: t,
290
- omitMargin: n,
291
- variant: s = "block",
290
+ size: s,
291
+ omitMargin: t,
292
+ variant: n = "block",
292
293
  normalizeSource: l = !1,
293
- links: o = "interactive"
294
+ links: o = "interactive",
295
+ renderLink: a
294
296
  }) => {
295
- const a = d.useMemo(
296
- () => l ? K(f(e ?? "")) : f(e ?? ""),
297
+ const m = d.useMemo(
298
+ () => l ? H(I(e ?? "")) : I(e ?? ""),
297
299
  [e, l]
298
- ), m = d.useMemo(
300
+ ), g = d.useMemo(
299
301
  () => ({
300
- ...T({ omitMargin: n, links: o }),
301
- ...s === "flow" ? w() : {},
302
- ...s === "inline" ? F() : {}
302
+ ...N({ omitMargin: t, links: o, renderLink: a }),
303
+ ...n === "flow" ? F() : {},
304
+ ...n === "inline" ? C() : {}
303
305
  }),
304
- [n, s, o]
306
+ [t, n, o, a]
305
307
  );
306
308
  return e ? /* @__PURE__ */ i(
307
- s === "block" ? "div" : "span",
309
+ n === "block" ? "div" : "span",
308
310
  {
309
- className: s === "flow" ? "md-root md-flow" : "md-root",
311
+ className: n === "flow" ? "md-root md-flow" : "md-root",
310
312
  style: {
311
313
  display: "contents",
312
- color: y(r ?? "primary"),
313
- fontSize: t === "inherit" ? "inherit" : x(t ?? "small")
314
+ color: R(r ?? "primary"),
315
+ fontSize: s === "inherit" ? "inherit" : L(s ?? "small")
314
316
  },
315
317
  children: /* @__PURE__ */ i(
316
- I,
318
+ b,
317
319
  {
318
- value: a,
319
- renderer: m,
320
- isInline: s === "inline",
321
- gfm: s !== "inline",
322
- instance: s === "inline" ? k() : void 0
320
+ value: m,
321
+ renderer: g,
322
+ isInline: n === "inline",
323
+ gfm: n !== "inline",
324
+ instance: n === "inline" ? y() : void 0
323
325
  }
324
326
  )
325
327
  }
326
328
  ) : null;
327
- }, V = d.memo(j);
329
+ }, te = d.memo(q);
328
330
  export {
329
- V as default
331
+ te as default
330
332
  };
331
333
  //# sourceMappingURL=MarkdownBlock.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownBlock.js","sources":["../../../src/components/Typography/MarkdownBlock.tsx"],"sourcesContent":["import Markdown, { ReactRenderer } from 'marked-react';\nimport React from 'react';\nimport { FOCUS_RING } from '../focusRing';\nimport CodeText from './CodeText';\nimport PageTitle from './PageTitle';\nimport SectionTitle from './SectionTitle';\nimport type { FontSize, TextColor } from './Text';\nimport { getInlineMarked } from './inlineMarkdown';\nimport { getFontSize, getTextColor } from './textStyles';\n\n/** `inline`: one line of inline syntax, with no autolinked emails or URLs. */\nexport type MarkdownVariant = 'block' | 'flow' | 'inline';\n\n/** `inert` draws links without an anchor, for markdown inside a <button>. */\nexport type MarkdownLinks = 'interactive' | 'inert';\n\nexport interface MarkdownProps {\n text: string;\n color?: TextColor;\n size?: FontSize | 'inherit';\n omitMargin?: boolean;\n variant?: MarkdownVariant;\n normalizeSource?: boolean;\n links?: MarkdownLinks;\n}\n\nconst FLOW_BULLET = '• ';\n\n// Inline, not `md-link`, for portals outside the shadow root; the link token is unreadable on tooltips.\nconst INERT_LINK_STYLE: React.CSSProperties = {\n color: 'inherit',\n textDecoration: 'underline',\n fontWeight: 600,\n};\n\n// Third-party content, and React does not sanitize href — `javascript:` would execute.\nconst ALLOWED_SCHEMES = new Set(['http:', 'https:', 'mailto:', 'tel:']);\n\nconst isSafeHref = (href: unknown): href is string => {\n if (typeof href !== 'string') {\n return false;\n }\n const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(href.replace(/[\\u0000-\\u0020]/g, ''));\n // No scheme means relative or fragment, which has nothing to vet.\n return !scheme || ALLOWED_SCHEMES.has(`${scheme[1].toLowerCase()}:`);\n};\n\n// Renderer args are always arrays: never unwrap with `x[0]`, it drops all tokens after the first.\nconst getRendererFunction = ({\n omitMargin,\n links,\n}: Pick<MarkdownProps, 'omitMargin' | 'links'>): Partial<ReactRenderer> => ({\n blockquote(this: ReactRenderer, quote) {\n return (\n <div\n key={this.elementId}\n style={{\n backgroundColor: 'var(--malachite-card-dimmed-background)',\n padding: '20px',\n borderRadius: '20px',\n border: '1px solid var(--malachite-card-border)',\n margin: '16px 0',\n }}\n >\n {quote}\n </div>\n );\n },\n\n paragraph(this: ReactRenderer, text) {\n return (\n <div key={this.elementId} style={{ marginBottom: omitMargin ? '0px' : '16px' }}>\n {text}\n </div>\n );\n },\n\n codespan(this: ReactRenderer, code) {\n return (\n <CodeText key={this.elementId} variant=\"inline\">\n {code}\n </CodeText>\n );\n },\n\n code(this: ReactRenderer, code) {\n return (\n <pre key={this.elementId} style={{ margin: omitMargin ? 0 : '16px 0' }}>\n <CodeText\n style={{\n display: 'block',\n whiteSpace: 'pre',\n overflowX: 'auto',\n padding: '12px',\n }}\n >\n {code}\n </CodeText>\n </pre>\n );\n },\n\n heading(this: ReactRenderer, text, level) {\n return level === 1 ? (\n <PageTitle key={this.elementId}>{text}</PageTitle>\n ) : (\n <SectionTitle key={this.elementId}>{text}</SectionTitle>\n );\n },\n\n br(this: ReactRenderer) {\n return <br key={this.elementId} />;\n },\n\n // `text`/`strong` are deliberately NOT overridden: a wrapping Text emits a font-weight, and\n // the nested 400 beat strong's 600 — which is why bold never rendered.\n\n link(this: ReactRenderer, href, children) {\n // Keep the label for a rejected scheme rather than deleting content.\n if (!isSafeHref(href)) {\n return <React.Fragment key={this.elementId}>{children}</React.Fragment>;\n }\n if (links === 'inert') {\n return (\n <span key={this.elementId} style={INERT_LINK_STYLE}>\n {children}\n </span>\n );\n }\n return (\n // Hover is in tailwind.css: CLAUDE.md forbids JS for styling, and JS misses keyboard.\n // FOCUS_RING because a colour change alone is not a focus indicator.\n <a\n key={this.elementId}\n className={`md-link rounded-xs ${FOCUS_RING}`}\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {children}\n </a>\n );\n },\n\n // Overridden only to vet `src`. Alt text stands in for a rejected image.\n image(this: ReactRenderer, src, alt, title) {\n if (!isSafeHref(src)) {\n return <span key={this.elementId}>{alt ?? ''}</span>;\n }\n return (\n <img\n key={this.elementId}\n src={src}\n alt={alt ?? ''}\n title={title ?? undefined}\n style={{ maxWidth: '100%' }}\n />\n );\n },\n\n // Preflight resets list-style/margin/padding; padding-left on the LIST is the hanging indent.\n list(this: ReactRenderer, children, ordered, start) {\n const Tag = ordered ? 'ol' : 'ul';\n return (\n <Tag\n key={this.elementId}\n // Forward `start` or `3. three` silently renumbers from 1.\n start={ordered && start !== 1 ? start : undefined}\n style={{\n listStyle: ordered ? 'decimal' : 'disc',\n paddingLeft: '1.25em',\n margin: 0,\n }}\n >\n {children}\n </Tag>\n );\n },\n\n listItem(this: ReactRenderer, children) {\n return (\n // Padding too: it pushes line boxes off ClampText's line grid, slicing the last line.\n <li key={this.elementId} style={{ padding: omitMargin ? '0px' : '2px 0px' }}>\n {children}\n </li>\n );\n },\n});\n\n/** Turns every block-level node inline for `flow`. Every block renderer must appear here, or the\n * one invariant — no block children — breaks silently. */\nconst getFlowOverrides = (): Partial<ReactRenderer> => ({\n paragraph(this: ReactRenderer, text) {\n return <span key={this.elementId}>{text} </span>;\n },\n\n // Roles are pinned: without the real <h*> the heading leaves the a11y tree entirely.\n heading(this: ReactRenderer, text, level) {\n return (\n <span\n key={this.elementId}\n role=\"heading\"\n aria-level={level}\n style={{ fontWeight: 600 }}\n >\n {text}{' '}\n </span>\n );\n },\n\n // The list owns markers and breaks — ordered numbering needs `start` plus the item index.\n // A <br> opens a line box (what -webkit-line-clamp counts); `display: block` would not.\n // Items OPEN with it, so tailwind.css suppresses the leading one on a first-child list.\n list(this: ReactRenderer, children, ordered, start) {\n const items = React.Children.toArray(children);\n return (\n <span key={this.elementId} role=\"list\" style={{ display: 'inline' }}>\n {items.map((item, index) => (\n // Index as key: one list node's rendered children never reorder.\n <span key={index} role=\"listitem\" style={{ display: 'inline' }}>\n <br />\n {/* Decoration — the role already conveys position. */}\n <span aria-hidden=\"true\">\n {ordered ? `${(start ?? 1) + index}. ` : FLOW_BULLET}\n </span>\n {item}\n </span>\n ))}\n {/* Closes the list so following prose starts on its own line. */}\n <br />\n </span>\n );\n },\n\n listItem(this: ReactRenderer, children) {\n return <React.Fragment key={this.elementId}>{children}</React.Fragment>;\n },\n\n blockquote(this: ReactRenderer, quote) {\n return <span key={this.elementId}>{quote} </span>;\n },\n\n // A hard break here is incidental wrapping; honouring it spends a clamped line on nothing.\n br(this: ReactRenderer) {\n return <span key={this.elementId}> </span>;\n },\n\n // Whitespace collapses, so a multi-line snippet becomes one run instead of the whole budget.\n code(this: ReactRenderer, code) {\n return (\n <React.Fragment key={this.elementId}>\n <CodeText variant=\"inline\">{code}</CodeText>{' '}\n </React.Fragment>\n );\n },\n\n hr(this: ReactRenderer) {\n return <span key={this.elementId}> </span>;\n },\n\n // Flattened to cell text: rows would each cost a line while carrying little at preview width.\n table(this: ReactRenderer, children) {\n return <span key={this.elementId}>{children} </span>;\n },\n tableHeader(this: ReactRenderer, children) {\n return <span key={this.elementId}>{children}</span>;\n },\n tableBody(this: ReactRenderer, children) {\n return <span key={this.elementId}>{children}</span>;\n },\n tableRow(this: ReactRenderer, children) {\n return <span key={this.elementId}>{children}</span>;\n },\n tableCell(this: ReactRenderer, children) {\n return <span key={this.elementId}>{children} </span>;\n },\n\n // Replaced content grows the line box and breaks the grid the clamp measures against.\n checkbox(this: ReactRenderer, checked) {\n return <span key={this.elementId}>{checked ? '[x] ' : '[ ] '}</span>;\n },\n\n image(this: ReactRenderer, _src, alt) {\n return <span key={this.elementId}>{alt ? `${alt} ` : ''}</span>;\n },\n});\n\n// An image would fetch a third-party URL and a break would wrap the line.\nconst getInlineOverrides = (): Partial<ReactRenderer> => ({\n image(this: ReactRenderer, _src, alt) {\n return <React.Fragment key={this.elementId}>{alt ?? ''}</React.Fragment>;\n },\n\n br(this: ReactRenderer) {\n return <React.Fragment key={this.elementId}> </React.Fragment>;\n },\n});\n\nconst dedent = (str: string) => {\n const lines = str.split('\\n');\n const indents = lines.reduce<number[]>((acc, line) => {\n if (line.trim() !== '') {\n acc.push(line.match(/^[ \\t]*(?=\\S)/gm)?.[0].length ?? 0);\n }\n return acc;\n }, []);\n // Blank-only input has no indents to measure, and Math.min() would return Infinity — which\n // reads as a literal `{Infinity}` quantifier today, but throws the moment the `u` flag is added.\n if (indents.length === 0) {\n return str;\n }\n const indent = Math.min(...indents);\n return lines.map((line) => line.replace(new RegExp(`^[ \\\\t]{${indent}}`, 'gm'), '')).join('\\n');\n};\n\ntype BlockKind = 'blank' | 'item' | 'label' | 'prose';\n\nconst FENCE = /^ {0,3}(?:```|~~~)/;\n/** Lazy continuation or indented code — either way not a new block of a different kind. */\nconst INDENTED = /^ {2,}\\S/;\n/** Belongs to the line ABOVE; a break between them demotes the heading to a thematic rule. */\nconst SETEXT_UNDERLINE = /^ {0,3}(?:=+|-+)\\s*$/;\n/** Tested before the bullet rule so `---` is not read as a list item. */\nconst THEMATIC_BREAK = /^ {0,3}(?:(?:-\\s*){3,}|(?:\\*\\s*){3,}|(?:_\\s*){3,})$/;\nconst BULLET_MARKER = /^[-*+]\\s/;\nconst ORDERED_MARKER = /^(\\d{1,9})[.)]\\s/;\n/** The colon is REQUIRED: emphasis mid-sentence looks identical, and splitting it would turn\n * one paragraph into three. */\nconst BOLD_LABEL = /^\\*\\*[^*]+:\\*\\*$|^\\*\\*[^*]+\\*\\*:$/;\n\nconst INLINE_LABEL = /\\*\\*[^*\\n]+?:\\*\\*|\\*\\*[^*\\n]+?\\*\\*:/g;\nconst LEADING_MARKER = /^\\s*(?:[-*+]|\\d{1,9}[.)])\\s+/;\n\n/** Splits a bold label that TRAILS other text onto its own line — `...support. **Pagination\n * Mode:**`. Line classification alone cannot fix it: the whole line is prose. A label that\n * OPENS its line, or a list item, is a lead-in and left alone. */\nconst splitTrailingLabels = (line: string): string[] => {\n const marker = LEADING_MARKER.exec(line)?.[0] ?? '';\n let rest = line.slice(marker.length);\n const out: string[] = [];\n let isFirst = true;\n\n while (true) {\n INLINE_LABEL.lastIndex = 0;\n let found: RegExpExecArray | null = null;\n let match = INLINE_LABEL.exec(rest);\n while (match) {\n // index 0 means the label opens the chunk — a lead-in, not a new block.\n if (match.index > 0) {\n found = match;\n break;\n }\n match = INLINE_LABEL.exec(rest);\n }\n if (!found) {\n break;\n }\n const before = rest.slice(0, found.index).trimEnd();\n if (before) {\n out.push((isFirst ? marker : '') + before);\n isFirst = false;\n }\n rest = rest.slice(found.index);\n }\n\n out.push((isFirst ? marker : '') + rest);\n return out;\n};\n\nconst classifyLine = (line: string, previous: BlockKind): BlockKind => {\n const trimmed = line.trim();\n if (!trimmed) {\n return 'blank';\n }\n if (THEMATIC_BREAK.test(line) || SETEXT_UNDERLINE.test(line)) {\n // Continues what came before, so nothing is inserted above it.\n return previous === 'blank' ? 'prose' : previous;\n }\n if (BULLET_MARKER.test(trimmed)) {\n return 'item';\n }\n const ordered = ORDERED_MARKER.exec(trimmed);\n if (ordered) {\n // Only a list starting at 1 may interrupt a paragraph, else \"Released in\\n2024.\" would\n // become `<ol start=\"2024\">`.\n if (previous !== 'prose' || ordered[1] === '1') {\n return 'item';\n }\n }\n if (BOLD_LABEL.test(trimmed)) {\n return 'label';\n }\n return 'prose';\n};\n\n/** Inserts the blank line CommonMark needs between blocks of different kinds — generated\n * descriptions separate them with a single `\\n`, which reads as lazy continuation. Only a\n * CHANGE of kind breaks, so tight lists and wrapped paragraphs survive. Skips fences, indented\n * lines and setext underlines, where a blank line changes meaning. */\nconst explicitBlocks = (text: string): string => {\n const lines = text.split('\\n');\n const out: string[] = [];\n let previous: BlockKind = 'blank';\n let inFence = false;\n\n for (const line of lines) {\n if (FENCE.test(line)) {\n inFence = !inFence;\n out.push(line);\n // A fence is its own block on both sides.\n previous = 'blank';\n continue;\n }\n if (inFence) {\n out.push(line);\n continue;\n }\n if (INDENTED.test(line)) {\n out.push(line);\n continue;\n }\n // One line can hold a block AND a trailing label, so split before classifying.\n for (const piece of splitTrailingLabels(line)) {\n previous = pushClassified(piece, previous, out);\n }\n }\n return out.join('\\n');\n};\n\nconst pushClassified = (line: string, previous: BlockKind, out: string[]): BlockKind => {\n const kind = classifyLine(line, previous);\n if (kind !== 'blank' && previous !== 'blank' && kind !== previous) {\n out.push('');\n }\n out.push(line);\n return kind;\n};\n\nconst MarkdownBlock: React.FC<MarkdownProps> = ({\n text,\n color,\n size,\n omitMargin,\n variant = 'block',\n normalizeSource = false,\n links = 'interactive',\n}) => {\n // Hooks before the early return so hook order stays stable. marked-react re-lexes on every\n // render, and this can land in a virtualized Table cell.\n const source = React.useMemo(\n () => (normalizeSource ? explicitBlocks(dedent(text ?? '')) : dedent(text ?? '')),\n [text, normalizeSource],\n );\n const renderer = React.useMemo(\n () => ({\n ...getRendererFunction({ omitMargin, links }),\n ...(variant === 'flow' ? getFlowOverrides() : {}),\n ...(variant === 'inline' ? getInlineOverrides() : {}),\n }),\n [omitMargin, variant, links],\n );\n\n if (!text) {\n return null;\n }\n\n // `display: contents` generates no box, so this only propagates colour and size — a real box\n // would be a block child for -webkit-line-clamp to count, and a stray div inside Alert. The\n // tag still switches: `display` does not change content-model validity.\n const Root = variant === 'block' ? 'div' : 'span';\n return (\n <Root\n className={variant === 'flow' ? 'md-root md-flow' : 'md-root'}\n style={{\n display: 'contents',\n color: getTextColor(color ?? 'primary'),\n fontSize: size === 'inherit' ? 'inherit' : getFontSize(size ?? 'small'),\n }}\n >\n <Markdown\n value={source}\n renderer={renderer}\n isInline={variant === 'inline'}\n gfm={variant !== 'inline'}\n instance={variant === 'inline' ? getInlineMarked() : undefined}\n />\n </Root>\n );\n};\n\n// marked-react re-parses on every render; every prop is a primitive, so shallow equality is exact.\nexport default React.memo(MarkdownBlock);\n"],"names":["FLOW_BULLET","INERT_LINK_STYLE","ALLOWED_SCHEMES","isSafeHref","href","scheme","getRendererFunction","omitMargin","links","quote","jsx","text","code","CodeText","level","PageTitle","SectionTitle","children","FOCUS_RING","React","src","alt","title","ordered","start","getFlowOverrides","jsxs","items","item","index","checked","_src","getInlineOverrides","dedent","str","lines","indents","acc","line","_a","indent","FENCE","INDENTED","SETEXT_UNDERLINE","THEMATIC_BREAK","BULLET_MARKER","ORDERED_MARKER","BOLD_LABEL","INLINE_LABEL","LEADING_MARKER","splitTrailingLabels","marker","rest","out","isFirst","found","match","before","classifyLine","previous","trimmed","explicitBlocks","inFence","piece","pushClassified","kind","MarkdownBlock","color","size","variant","normalizeSource","source","renderer","getTextColor","getFontSize","Markdown","getInlineMarked","MarkdownBlock$1"],"mappings":"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"}
1
+ {"version":3,"file":"MarkdownBlock.js","sources":["../../../src/components/Typography/MarkdownBlock.tsx"],"sourcesContent":["import Markdown, { ReactRenderer } from 'marked-react';\nimport React from 'react';\nimport type { RenderLink } from '../PageLayout/types';\nimport { FOCUS_RING } from '../focusRing';\nimport CodeText from './CodeText';\nimport PageTitle from './PageTitle';\nimport SectionTitle from './SectionTitle';\nimport type { FontSize, TextColor } from './Text';\nimport { getInlineMarked } from './inlineMarkdown';\nimport { getFontSize, getTextColor } from './textStyles';\n\n/** `inline`: one line of inline syntax, with no autolinked emails or URLs. */\nexport type MarkdownVariant = 'block' | 'flow' | 'inline';\n\n/** `inert` draws links without an anchor, for markdown inside a <button>. */\nexport type MarkdownLinks = 'interactive' | 'inert';\n\nexport interface MarkdownProps {\n text: string;\n color?: TextColor;\n size?: FontSize | 'inherit';\n omitMargin?: boolean;\n variant?: MarkdownVariant;\n normalizeSource?: boolean;\n links?: MarkdownLinks;\n /** Renders root-relative links (`/path`) through the app's router, in the same tab. Other\n * links still open in a new tab. Pass a stable function: a new one re-parses the markdown. */\n renderLink?: RenderLink;\n}\n\nconst FLOW_BULLET = '• ';\n\n// Inline, not `md-link`, for portals outside the shadow root; the link token is unreadable on tooltips.\nconst INERT_LINK_STYLE: React.CSSProperties = {\n color: 'inherit',\n textDecoration: 'underline',\n fontWeight: 600,\n};\n\n// Third-party content, and React does not sanitize href — `javascript:` would execute.\nconst ALLOWED_SCHEMES = new Set(['http:', 'https:', 'mailto:', 'tel:']);\n\nconst isSafeHref = (href: unknown): href is string => {\n if (typeof href !== 'string') {\n return false;\n }\n const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(href.replace(/[\\u0000-\\u0020]/g, ''));\n // No scheme means relative or fragment, which has nothing to vet.\n return !scheme || ALLOWED_SCHEMES.has(`${scheme[1].toLowerCase()}:`);\n};\n\n// `//host` and `/\\host` are protocol-relative to a browser, so they leave the app.\n// URL parsing drops tab, CR and LF, so `/\\t/evil.com` would resolve off-site.\nconst isRootRelative = (href: string): boolean => /^\\/(?![/\\\\])[^\\t\\n\\r]*$/.test(href);\n\nconst LINK_CLASSES = `md-link rounded-xs ${FOCUS_RING}`;\n\n// Renderer args are always arrays: never unwrap with `x[0]`, it drops all tokens after the first.\nconst getRendererFunction = ({\n omitMargin,\n links,\n renderLink,\n}: Pick<MarkdownProps, 'omitMargin' | 'links' | 'renderLink'>): Partial<ReactRenderer> => ({\n blockquote(this: ReactRenderer, quote) {\n return (\n <div\n key={this.elementId}\n style={{\n backgroundColor: 'var(--malachite-card-dimmed-background)',\n padding: '20px',\n borderRadius: '20px',\n border: '1px solid var(--malachite-card-border)',\n margin: '16px 0',\n }}\n >\n {quote}\n </div>\n );\n },\n\n paragraph(this: ReactRenderer, text) {\n return (\n <div key={this.elementId} style={{ marginBottom: omitMargin ? '0px' : '16px' }}>\n {text}\n </div>\n );\n },\n\n codespan(this: ReactRenderer, code) {\n return (\n <CodeText key={this.elementId} variant=\"inline\">\n {code}\n </CodeText>\n );\n },\n\n code(this: ReactRenderer, code) {\n return (\n <pre key={this.elementId} style={{ margin: omitMargin ? 0 : '16px 0' }}>\n <CodeText\n style={{\n display: 'block',\n whiteSpace: 'pre',\n overflowX: 'auto',\n padding: '12px',\n }}\n >\n {code}\n </CodeText>\n </pre>\n );\n },\n\n heading(this: ReactRenderer, text, level) {\n return level === 1 ? (\n <PageTitle key={this.elementId}>{text}</PageTitle>\n ) : (\n <SectionTitle key={this.elementId}>{text}</SectionTitle>\n );\n },\n\n br(this: ReactRenderer) {\n return <br key={this.elementId} />;\n },\n\n // `text`/`strong` are deliberately NOT overridden: a wrapping Text emits a font-weight, and\n // the nested 400 beat strong's 600 — which is why bold never rendered.\n\n link(this: ReactRenderer, href, children) {\n // Keep the label for a rejected scheme rather than deleting content.\n if (!isSafeHref(href)) {\n return <React.Fragment key={this.elementId}>{children}</React.Fragment>;\n }\n if (links === 'inert') {\n return (\n <span key={this.elementId} style={INERT_LINK_STYLE}>\n {children}\n </span>\n );\n }\n if (renderLink && isRootRelative(href)) {\n return (\n <React.Fragment key={this.elementId}>\n {renderLink({ href, children, className: LINK_CLASSES })}\n </React.Fragment>\n );\n }\n return (\n // Hover is in tailwind.css: CLAUDE.md forbids JS for styling, and JS misses keyboard.\n // FOCUS_RING because a colour change alone is not a focus indicator.\n <a\n key={this.elementId}\n className={LINK_CLASSES}\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {children}\n </a>\n );\n },\n\n // Overridden only to vet `src`. Alt text stands in for a rejected image.\n image(this: ReactRenderer, src, alt, title) {\n if (!isSafeHref(src)) {\n return <span key={this.elementId}>{alt ?? ''}</span>;\n }\n return (\n <img\n key={this.elementId}\n src={src}\n alt={alt ?? ''}\n title={title ?? undefined}\n style={{ maxWidth: '100%' }}\n />\n );\n },\n\n // Preflight resets list-style/margin/padding; padding-left on the LIST is the hanging indent.\n list(this: ReactRenderer, children, ordered, start) {\n const Tag = ordered ? 'ol' : 'ul';\n return (\n <Tag\n key={this.elementId}\n // Forward `start` or `3. three` silently renumbers from 1.\n start={ordered && start !== 1 ? start : undefined}\n style={{\n listStyle: ordered ? 'decimal' : 'disc',\n paddingLeft: '1.25em',\n margin: 0,\n }}\n >\n {children}\n </Tag>\n );\n },\n\n listItem(this: ReactRenderer, children) {\n return (\n // Padding too: it pushes line boxes off ClampText's line grid, slicing the last line.\n <li key={this.elementId} style={{ padding: omitMargin ? '0px' : '2px 0px' }}>\n {children}\n </li>\n );\n },\n});\n\n/** Turns every block-level node inline for `flow`. Every block renderer must appear here, or the\n * one invariant — no block children — breaks silently. */\nconst getFlowOverrides = (): Partial<ReactRenderer> => ({\n paragraph(this: ReactRenderer, text) {\n return <span key={this.elementId}>{text} </span>;\n },\n\n // Roles are pinned: without the real <h*> the heading leaves the a11y tree entirely.\n heading(this: ReactRenderer, text, level) {\n return (\n <span\n key={this.elementId}\n role=\"heading\"\n aria-level={level}\n style={{ fontWeight: 600 }}\n >\n {text}{' '}\n </span>\n );\n },\n\n // The list owns markers and breaks — ordered numbering needs `start` plus the item index.\n // A <br> opens a line box (what -webkit-line-clamp counts); `display: block` would not.\n // Items OPEN with it, so tailwind.css suppresses the leading one on a first-child list.\n list(this: ReactRenderer, children, ordered, start) {\n const items = React.Children.toArray(children);\n return (\n <span key={this.elementId} role=\"list\" style={{ display: 'inline' }}>\n {items.map((item, index) => (\n // Index as key: one list node's rendered children never reorder.\n <span key={index} role=\"listitem\" style={{ display: 'inline' }}>\n <br />\n {/* Decoration — the role already conveys position. */}\n <span aria-hidden=\"true\">\n {ordered ? `${(start ?? 1) + index}. ` : FLOW_BULLET}\n </span>\n {item}\n </span>\n ))}\n {/* Closes the list so following prose starts on its own line. */}\n <br />\n </span>\n );\n },\n\n listItem(this: ReactRenderer, children) {\n return <React.Fragment key={this.elementId}>{children}</React.Fragment>;\n },\n\n blockquote(this: ReactRenderer, quote) {\n return <span key={this.elementId}>{quote} </span>;\n },\n\n // A hard break here is incidental wrapping; honouring it spends a clamped line on nothing.\n br(this: ReactRenderer) {\n return <span key={this.elementId}> </span>;\n },\n\n // Whitespace collapses, so a multi-line snippet becomes one run instead of the whole budget.\n code(this: ReactRenderer, code) {\n return (\n <React.Fragment key={this.elementId}>\n <CodeText variant=\"inline\">{code}</CodeText>{' '}\n </React.Fragment>\n );\n },\n\n hr(this: ReactRenderer) {\n return <span key={this.elementId}> </span>;\n },\n\n // Flattened to cell text: rows would each cost a line while carrying little at preview width.\n table(this: ReactRenderer, children) {\n return <span key={this.elementId}>{children} </span>;\n },\n tableHeader(this: ReactRenderer, children) {\n return <span key={this.elementId}>{children}</span>;\n },\n tableBody(this: ReactRenderer, children) {\n return <span key={this.elementId}>{children}</span>;\n },\n tableRow(this: ReactRenderer, children) {\n return <span key={this.elementId}>{children}</span>;\n },\n tableCell(this: ReactRenderer, children) {\n return <span key={this.elementId}>{children} </span>;\n },\n\n // Replaced content grows the line box and breaks the grid the clamp measures against.\n checkbox(this: ReactRenderer, checked) {\n return <span key={this.elementId}>{checked ? '[x] ' : '[ ] '}</span>;\n },\n\n image(this: ReactRenderer, _src, alt) {\n return <span key={this.elementId}>{alt ? `${alt} ` : ''}</span>;\n },\n});\n\n// An image would fetch a third-party URL and a break would wrap the line.\nconst getInlineOverrides = (): Partial<ReactRenderer> => ({\n image(this: ReactRenderer, _src, alt) {\n return <React.Fragment key={this.elementId}>{alt ?? ''}</React.Fragment>;\n },\n\n br(this: ReactRenderer) {\n return <React.Fragment key={this.elementId}> </React.Fragment>;\n },\n});\n\nconst dedent = (str: string) => {\n const lines = str.split('\\n');\n const indents = lines.reduce<number[]>((acc, line) => {\n if (line.trim() !== '') {\n acc.push(line.match(/^[ \\t]*(?=\\S)/gm)?.[0].length ?? 0);\n }\n return acc;\n }, []);\n // Blank-only input has no indents to measure, and Math.min() would return Infinity — which\n // reads as a literal `{Infinity}` quantifier today, but throws the moment the `u` flag is added.\n if (indents.length === 0) {\n return str;\n }\n const indent = Math.min(...indents);\n return lines.map((line) => line.replace(new RegExp(`^[ \\\\t]{${indent}}`, 'gm'), '')).join('\\n');\n};\n\ntype BlockKind = 'blank' | 'item' | 'label' | 'prose';\n\nconst FENCE = /^ {0,3}(?:```|~~~)/;\n/** Lazy continuation or indented code — either way not a new block of a different kind. */\nconst INDENTED = /^ {2,}\\S/;\n/** Belongs to the line ABOVE; a break between them demotes the heading to a thematic rule. */\nconst SETEXT_UNDERLINE = /^ {0,3}(?:=+|-+)\\s*$/;\n/** Tested before the bullet rule so `---` is not read as a list item. */\nconst THEMATIC_BREAK = /^ {0,3}(?:(?:-\\s*){3,}|(?:\\*\\s*){3,}|(?:_\\s*){3,})$/;\nconst BULLET_MARKER = /^[-*+]\\s/;\nconst ORDERED_MARKER = /^(\\d{1,9})[.)]\\s/;\n/** The colon is REQUIRED: emphasis mid-sentence looks identical, and splitting it would turn\n * one paragraph into three. */\nconst BOLD_LABEL = /^\\*\\*[^*]+:\\*\\*$|^\\*\\*[^*]+\\*\\*:$/;\n\nconst INLINE_LABEL = /\\*\\*[^*\\n]+?:\\*\\*|\\*\\*[^*\\n]+?\\*\\*:/g;\nconst LEADING_MARKER = /^\\s*(?:[-*+]|\\d{1,9}[.)])\\s+/;\n\n/** Splits a bold label that TRAILS other text onto its own line — `...support. **Pagination\n * Mode:**`. Line classification alone cannot fix it: the whole line is prose. A label that\n * OPENS its line, or a list item, is a lead-in and left alone. */\nconst splitTrailingLabels = (line: string): string[] => {\n const marker = LEADING_MARKER.exec(line)?.[0] ?? '';\n let rest = line.slice(marker.length);\n const out: string[] = [];\n let isFirst = true;\n\n while (true) {\n INLINE_LABEL.lastIndex = 0;\n let found: RegExpExecArray | null = null;\n let match = INLINE_LABEL.exec(rest);\n while (match) {\n // index 0 means the label opens the chunk — a lead-in, not a new block.\n if (match.index > 0) {\n found = match;\n break;\n }\n match = INLINE_LABEL.exec(rest);\n }\n if (!found) {\n break;\n }\n const before = rest.slice(0, found.index).trimEnd();\n if (before) {\n out.push((isFirst ? marker : '') + before);\n isFirst = false;\n }\n rest = rest.slice(found.index);\n }\n\n out.push((isFirst ? marker : '') + rest);\n return out;\n};\n\nconst classifyLine = (line: string, previous: BlockKind): BlockKind => {\n const trimmed = line.trim();\n if (!trimmed) {\n return 'blank';\n }\n if (THEMATIC_BREAK.test(line) || SETEXT_UNDERLINE.test(line)) {\n // Continues what came before, so nothing is inserted above it.\n return previous === 'blank' ? 'prose' : previous;\n }\n if (BULLET_MARKER.test(trimmed)) {\n return 'item';\n }\n const ordered = ORDERED_MARKER.exec(trimmed);\n if (ordered) {\n // Only a list starting at 1 may interrupt a paragraph, else \"Released in\\n2024.\" would\n // become `<ol start=\"2024\">`.\n if (previous !== 'prose' || ordered[1] === '1') {\n return 'item';\n }\n }\n if (BOLD_LABEL.test(trimmed)) {\n return 'label';\n }\n return 'prose';\n};\n\n/** Inserts the blank line CommonMark needs between blocks of different kinds — generated\n * descriptions separate them with a single `\\n`, which reads as lazy continuation. Only a\n * CHANGE of kind breaks, so tight lists and wrapped paragraphs survive. Skips fences, indented\n * lines and setext underlines, where a blank line changes meaning. */\nconst explicitBlocks = (text: string): string => {\n const lines = text.split('\\n');\n const out: string[] = [];\n let previous: BlockKind = 'blank';\n let inFence = false;\n\n for (const line of lines) {\n if (FENCE.test(line)) {\n inFence = !inFence;\n out.push(line);\n // A fence is its own block on both sides.\n previous = 'blank';\n continue;\n }\n if (inFence) {\n out.push(line);\n continue;\n }\n if (INDENTED.test(line)) {\n out.push(line);\n continue;\n }\n // One line can hold a block AND a trailing label, so split before classifying.\n for (const piece of splitTrailingLabels(line)) {\n previous = pushClassified(piece, previous, out);\n }\n }\n return out.join('\\n');\n};\n\nconst pushClassified = (line: string, previous: BlockKind, out: string[]): BlockKind => {\n const kind = classifyLine(line, previous);\n if (kind !== 'blank' && previous !== 'blank' && kind !== previous) {\n out.push('');\n }\n out.push(line);\n return kind;\n};\n\nconst MarkdownBlock: React.FC<MarkdownProps> = ({\n text,\n color,\n size,\n omitMargin,\n variant = 'block',\n normalizeSource = false,\n links = 'interactive',\n renderLink,\n}) => {\n // Hooks before the early return so hook order stays stable. marked-react re-lexes on every\n // render, and this can land in a virtualized Table cell.\n const source = React.useMemo(\n () => (normalizeSource ? explicitBlocks(dedent(text ?? '')) : dedent(text ?? '')),\n [text, normalizeSource],\n );\n const renderer = React.useMemo(\n () => ({\n ...getRendererFunction({ omitMargin, links, renderLink }),\n ...(variant === 'flow' ? getFlowOverrides() : {}),\n ...(variant === 'inline' ? getInlineOverrides() : {}),\n }),\n [omitMargin, variant, links, renderLink],\n );\n\n if (!text) {\n return null;\n }\n\n // `display: contents` generates no box, so this only propagates colour and size — a real box\n // would be a block child for -webkit-line-clamp to count, and a stray div inside Alert. The\n // tag still switches: `display` does not change content-model validity.\n const Root = variant === 'block' ? 'div' : 'span';\n return (\n <Root\n className={variant === 'flow' ? 'md-root md-flow' : 'md-root'}\n style={{\n display: 'contents',\n color: getTextColor(color ?? 'primary'),\n fontSize: size === 'inherit' ? 'inherit' : getFontSize(size ?? 'small'),\n }}\n >\n <Markdown\n value={source}\n renderer={renderer}\n isInline={variant === 'inline'}\n gfm={variant !== 'inline'}\n instance={variant === 'inline' ? getInlineMarked() : undefined}\n />\n </Root>\n );\n};\n\n// marked-react re-parses on every render. Every prop but `renderLink` is a primitive.\nexport default React.memo(MarkdownBlock);\n"],"names":["FLOW_BULLET","INERT_LINK_STYLE","ALLOWED_SCHEMES","isSafeHref","href","scheme","isRootRelative","LINK_CLASSES","FOCUS_RING","getRendererFunction","omitMargin","links","renderLink","quote","jsx","text","code","CodeText","level","PageTitle","SectionTitle","children","React","src","alt","title","ordered","start","getFlowOverrides","jsxs","items","item","index","checked","_src","getInlineOverrides","dedent","str","lines","indents","acc","line","_a","indent","FENCE","INDENTED","SETEXT_UNDERLINE","THEMATIC_BREAK","BULLET_MARKER","ORDERED_MARKER","BOLD_LABEL","INLINE_LABEL","LEADING_MARKER","splitTrailingLabels","marker","rest","out","isFirst","found","match","before","classifyLine","previous","trimmed","explicitBlocks","inFence","piece","pushClassified","kind","MarkdownBlock","color","size","variant","normalizeSource","source","renderer","getTextColor","getFontSize","Markdown","getInlineMarked","MarkdownBlock$1"],"mappings":"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"}
@@ -1,30 +1,26 @@
1
- const a = {
1
+ const r = {
2
2
  default: {
3
- badge: "var(--malachite-text-secondary)",
4
3
  tray: "neutral",
5
4
  confirmVariant: "filled",
6
5
  calloutType: "info"
7
6
  },
8
7
  warning: {
9
- badge: "var(--malachite-tag-warning-foreground)",
10
8
  tray: "warning",
11
9
  confirmVariant: "filled",
12
10
  calloutType: "warning"
13
11
  },
14
12
  destructive: {
15
- badge: "var(--malachite-tag-error-foreground)",
16
13
  tray: "error",
17
14
  confirmVariant: "destructive",
18
15
  calloutType: "error"
19
16
  },
20
17
  success: {
21
- badge: "var(--malachite-tag-success-foreground)",
22
18
  tray: "success",
23
19
  confirmVariant: "filled",
24
20
  calloutType: "success"
25
21
  }
26
22
  };
27
23
  export {
28
- a as CONFIRMATION_DIALOG_VARIANTS
24
+ r as CONFIRMATION_DIALOG_VARIANTS
29
25
  };
30
26
  //# sourceMappingURL=confirmationDialogVariants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"confirmationDialogVariants.js","sources":["../../src/components/confirmationDialogVariants.ts"],"sourcesContent":["import type { AlertType } from './Alert';\nimport type { ButtonVariant } from './Button';\nimport type { ModalTrayTone } from './modalTray';\n\nexport type ConfirmationDialogVariant = 'default' | 'warning' | 'destructive' | 'success';\n\nexport interface ConfirmationDialogVariantStyle {\n badge: string;\n tray: ModalTrayTone;\n confirmVariant: ButtonVariant;\n calloutType: AlertType;\n}\n\nexport const CONFIRMATION_DIALOG_VARIANTS: Record<\n ConfirmationDialogVariant,\n ConfirmationDialogVariantStyle\n> = {\n default: {\n badge: 'var(--malachite-text-secondary)',\n tray: 'neutral',\n confirmVariant: 'filled',\n calloutType: 'info',\n },\n warning: {\n badge: 'var(--malachite-tag-warning-foreground)',\n tray: 'warning',\n confirmVariant: 'filled',\n calloutType: 'warning',\n },\n destructive: {\n badge: 'var(--malachite-tag-error-foreground)',\n tray: 'error',\n confirmVariant: 'destructive',\n calloutType: 'error',\n },\n success: {\n badge: 'var(--malachite-tag-success-foreground)',\n tray: 'success',\n confirmVariant: 'filled',\n calloutType: 'success',\n },\n};\n"],"names":["CONFIRMATION_DIALOG_VARIANTS"],"mappings":"AAaO,MAAMA,IAGT;AAAA,EACA,SAAS;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa;AAAA,EAAA;AAAA,EAEjB,SAAS;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa;AAAA,EAAA;AAAA,EAEjB,aAAa;AAAA,IACT,OAAO;AAAA,IACP,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa;AAAA,EAAA;AAAA,EAEjB,SAAS;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa;AAAA,EAAA;AAErB;"}
1
+ {"version":3,"file":"confirmationDialogVariants.js","sources":["../../src/components/confirmationDialogVariants.ts"],"sourcesContent":["import type { AlertType } from './Alert';\nimport type { ButtonVariant } from './Button';\nimport type { ModalTrayTone } from './modalTray';\n\nexport type ConfirmationDialogVariant = 'default' | 'warning' | 'destructive' | 'success';\n\nexport interface ConfirmationDialogVariantStyle {\n tray: ModalTrayTone;\n confirmVariant: ButtonVariant;\n calloutType: AlertType;\n}\n\nexport const CONFIRMATION_DIALOG_VARIANTS: Record<\n ConfirmationDialogVariant,\n ConfirmationDialogVariantStyle\n> = {\n default: {\n tray: 'neutral',\n confirmVariant: 'filled',\n calloutType: 'info',\n },\n warning: {\n tray: 'warning',\n confirmVariant: 'filled',\n calloutType: 'warning',\n },\n destructive: {\n tray: 'error',\n confirmVariant: 'destructive',\n calloutType: 'error',\n },\n success: {\n tray: 'success',\n confirmVariant: 'filled',\n calloutType: 'success',\n },\n};\n"],"names":["CONFIRMATION_DIALOG_VARIANTS"],"mappings":"AAYO,MAAMA,IAGT;AAAA,EACA,SAAS;AAAA,IACL,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa;AAAA,EAAA;AAAA,EAEjB,SAAS;AAAA,IACL,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa;AAAA,EAAA;AAAA,EAEjB,aAAa;AAAA,IACT,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa;AAAA,EAAA;AAAA,EAEjB,SAAS;AAAA,IACL,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,aAAa;AAAA,EAAA;AAErB;"}
@@ -0,0 +1,11 @@
1
+ const a = {
2
+ default: "var(--malachite-text-secondary)",
3
+ accent: "var(--malachite-accent-foreground)",
4
+ warning: "var(--malachite-tag-warning-foreground)",
5
+ destructive: "var(--malachite-tag-error-foreground)",
6
+ success: "var(--malachite-tag-success-foreground)"
7
+ };
8
+ export {
9
+ a as ICON_BADGE_FILL
10
+ };
11
+ //# sourceMappingURL=iconBadgeVariants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iconBadgeVariants.js","sources":["../../src/components/iconBadgeVariants.ts"],"sourcesContent":["export type IconBadgeVariant = 'default' | 'accent' | 'warning' | 'destructive' | 'success';\n\n/** Foreground tokens, not backgrounds: the glyph is drawn in the card background, so the fill\n * needs the vivid end of each pair to keep it legible. */\nexport const ICON_BADGE_FILL: Record<IconBadgeVariant, string> = {\n default: 'var(--malachite-text-secondary)',\n accent: 'var(--malachite-accent-foreground)',\n warning: 'var(--malachite-tag-warning-foreground)',\n destructive: 'var(--malachite-tag-error-foreground)',\n success: 'var(--malachite-tag-success-foreground)',\n};\n"],"names":["ICON_BADGE_FILL"],"mappings":"AAIO,MAAMA,IAAoD;AAAA,EAC7D,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,aAAa;AAAA,EACb,SAAS;AACb;"}
package/dist/index.d.ts CHANGED
@@ -174,6 +174,8 @@ declare interface AlertProps {
174
174
  * Screen readers reliably announce an `alert` as it mounts; a `status` is read when its
175
175
  * `message` changes, so keep a live info or success alert mounted. Off by default. */
176
176
  live?: boolean;
177
+ /** Routes root-relative links in `message` through the app's router; see `MarkdownBlock`. */
178
+ renderLink?: RenderLink;
177
179
  }
178
180
 
179
181
  export declare type AlertType = 'info' | 'success' | 'error' | 'warning' | 'assistant';
@@ -317,7 +319,7 @@ export declare const Breadcrumbs: default_2.FC<BreadcrumbsProps>;
317
319
  export declare interface BreadcrumbsProps {
318
320
  links: BreadcrumbLink[];
319
321
  actions?: PageAction[];
320
- renderLink?: RenderBreadcrumbLink;
322
+ renderLink?: RenderLink;
321
323
  className?: string;
322
324
  style?: default_2.CSSProperties;
323
325
  }
@@ -1803,6 +1805,18 @@ export declare function getCurrentThemeMode(): 'light' | 'dark';
1803
1805
 
1804
1806
  export declare const GlobeIcon: React.FC<IconProps_56>;
1805
1807
 
1808
+ export declare const IconBadge: default_2.FC<IconBadgeProps>;
1809
+
1810
+ export declare interface IconBadgeProps {
1811
+ /** Drawn at 12px in the card background colour; an svg painting with `currentColor`. */
1812
+ icon: default_2.ReactNode;
1813
+ /** `accent` is the brand's interaction colour, so a rebrand repaints it. */
1814
+ variant?: IconBadgeVariant;
1815
+ className?: string;
1816
+ }
1817
+
1818
+ export declare type IconBadgeVariant = 'default' | 'accent' | 'warning' | 'destructive' | 'success';
1819
+
1806
1820
  /** A non-interactive icon carrying a meaning, for where an icon button would offer nothing to do. */
1807
1821
  export declare const IconIndicator: default_2.FC<IconIndicatorProps>;
1808
1822
 
@@ -3293,6 +3307,9 @@ export declare interface MarkdownProps {
3293
3307
  variant?: MarkdownVariant;
3294
3308
  normalizeSource?: boolean;
3295
3309
  links?: MarkdownLinks;
3310
+ /** Renders root-relative links (`/path`) through the app's router, in the same tab. Other
3311
+ * links still open in a new tab. Pass a stable function: a new one re-parses the markdown. */
3312
+ renderLink?: RenderLink;
3296
3313
  }
3297
3314
 
3298
3315
  /** `inline`: one line of inline syntax, with no autolinked emails or URLs. */
@@ -3908,7 +3925,7 @@ export declare const RefreshIcon: React.FC<IconProps_86>;
3908
3925
  export declare interface RegularLayoutProps {
3909
3926
  breadcrumbLinks?: BreadcrumbLink[];
3910
3927
  breadcrumbActions?: PageAction[];
3911
- renderLink?: RenderBreadcrumbLink;
3928
+ renderLink?: RenderLink;
3912
3929
  title?: default_2.ReactNode;
3913
3930
  titleSuffix?: default_2.ReactNode;
3914
3931
  subtitle?: string;
@@ -3940,10 +3957,11 @@ export declare const RejectIcon: React.FC<IconProps_87>;
3940
3957
  export declare const ReloadIcon: React.FC<IconProps_88>;
3941
3958
 
3942
3959
  /**
3943
- * Renders a crumb or the back button through the app's own link component, spreading every
3944
- * field onto it. A client-side-routed consumer MUST pass this, or navigation breaks.
3960
+ * Renders an in-app link through the app's own link component, spreading every field onto it:
3961
+ * breadcrumbs, the back button, and root-relative markdown links. A client-side-routed consumer
3962
+ * MUST pass this, or navigation breaks.
3945
3963
  */
3946
- declare type RenderBreadcrumbLink = (props: {
3964
+ export declare type RenderLink = (props: {
3947
3965
  href: string;
3948
3966
  children: default_2.ReactNode;
3949
3967
  className?: string;
@@ -4354,6 +4372,14 @@ export declare interface SidePanelProps {
4354
4372
  bodyPadding?: boolean;
4355
4373
  /** `above-app-overlays` lifts the overlay stack clear of chrome pinned near max-int. */
4356
4374
  stacking?: 'default' | 'above-app-overlays';
4375
+ /** Full-width Alert bands at the top of the body, above `children`, in order. Unaffected by
4376
+ * `bodyPadding`. The message is markdown. */
4377
+ callouts?: {
4378
+ type?: AlertType;
4379
+ message: string;
4380
+ }[];
4381
+ /** Routes root-relative links in `callouts` through the app's router; see `MarkdownBlock`. */
4382
+ renderLink?: RenderLink;
4357
4383
  children: default_2.ReactNode;
4358
4384
  }
4359
4385