@damiro/stylo 0.15.2 → 0.17.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.
Files changed (79) hide show
  1. package/README.md +1 -1
  2. package/dist/{InPlaceView-DVX9qV68.js → InPlaceView-CRb5AkfX.js} +781 -743
  3. package/dist/InPlaceView-CRb5AkfX.js.map +1 -0
  4. package/dist/Preview-5lm2uUVj.js +319 -0
  5. package/dist/Preview-5lm2uUVj.js.map +1 -0
  6. package/dist/SplitView.d.ts +4 -1
  7. package/dist/SplitView.d.ts.map +1 -1
  8. package/dist/Stylo.d.ts.map +1 -1
  9. package/dist/editor/SourceView.d.ts +4 -1
  10. package/dist/editor/SourceView.d.ts.map +1 -1
  11. package/dist/editor/theme.d.ts.map +1 -1
  12. package/dist/editor/useCodeMirror.d.ts +7 -1
  13. package/dist/editor/useCodeMirror.d.ts.map +1 -1
  14. package/dist/embed-DKKeCE1Y.js +109 -0
  15. package/dist/embed-DKKeCE1Y.js.map +1 -0
  16. package/dist/{highlight-BLdNzTxQ.js → embed-cache-CcBfVrc9.js} +47 -4
  17. package/dist/embed-cache-CcBfVrc9.js.map +1 -0
  18. package/dist/inplace/InPlaceView.d.ts +4 -1
  19. package/dist/inplace/InPlaceView.d.ts.map +1 -1
  20. package/dist/inplace/context-menu-helpers.d.ts +3 -4
  21. package/dist/inplace/context-menu-helpers.d.ts.map +1 -1
  22. package/dist/inplace/decorate.d.ts.map +1 -1
  23. package/dist/inplace/edit-line-prefix.d.ts.map +1 -1
  24. package/dist/inplace/embed.d.ts.map +1 -1
  25. package/dist/inplace/extension.d.ts.map +1 -1
  26. package/dist/inplace/inline-md.d.ts.map +1 -1
  27. package/dist/inplace/link-row.d.ts +14 -13
  28. package/dist/inplace/link-row.d.ts.map +1 -1
  29. package/dist/inplace/list-guides.d.ts.map +1 -1
  30. package/dist/inplace/math.d.ts +18 -3
  31. package/dist/inplace/math.d.ts.map +1 -1
  32. package/dist/inplace/table-widget-keys.d.ts +46 -0
  33. package/dist/inplace/table-widget-keys.d.ts.map +1 -0
  34. package/dist/inplace/table-widget.d.ts +1 -2
  35. package/dist/inplace/table-widget.d.ts.map +1 -1
  36. package/dist/inplace/tables.d.ts.map +1 -1
  37. package/dist/inplace/wikilinks.d.ts +1 -1
  38. package/dist/inplace/wikilinks.d.ts.map +1 -1
  39. package/dist/render/Embed.d.ts.map +1 -1
  40. package/dist/render/Preview.d.ts.map +1 -1
  41. package/dist/render/embed-cache.d.ts +13 -0
  42. package/dist/render/embed-cache.d.ts.map +1 -1
  43. package/dist/render/preview-components.d.ts +22 -0
  44. package/dist/render/preview-components.d.ts.map +1 -0
  45. package/dist/render/remark-wikilink.d.ts.map +1 -1
  46. package/dist/render/taskCheckbox.d.ts +30 -0
  47. package/dist/render/taskCheckbox.d.ts.map +1 -1
  48. package/dist/stylo.js +213 -196
  49. package/dist/stylo.js.map +1 -1
  50. package/dist/toolbar/Toolbar.d.ts.map +1 -1
  51. package/dist/toolbar/command-helpers.d.ts +27 -0
  52. package/dist/toolbar/command-helpers.d.ts.map +1 -1
  53. package/dist/toolbar/heading.d.ts +3 -0
  54. package/dist/toolbar/heading.d.ts.map +1 -1
  55. package/dist/toolbar/inline-ops.d.ts +6 -0
  56. package/dist/toolbar/inline-ops.d.ts.map +1 -1
  57. package/dist/toolbar/table.d.ts.map +1 -1
  58. package/dist/types/core.d.ts +209 -0
  59. package/dist/types/core.d.ts.map +1 -0
  60. package/dist/types/inplace.d.ts +91 -0
  61. package/dist/types/inplace.d.ts.map +1 -0
  62. package/dist/types/sources.d.ts +66 -0
  63. package/dist/types/sources.d.ts.map +1 -0
  64. package/dist/types/toolbar.d.ts +72 -0
  65. package/dist/types/toolbar.d.ts.map +1 -0
  66. package/dist/types.d.ts +11 -406
  67. package/dist/types.d.ts.map +1 -1
  68. package/dist/{useCodeMirror-CXtuBlLf.js → useCodeMirror-B07wRexo.js} +317 -268
  69. package/dist/useCodeMirror-B07wRexo.js.map +1 -0
  70. package/package.json +4 -4
  71. package/dist/InPlaceView-DVX9qV68.js.map +0 -1
  72. package/dist/Preview-BcdSr09-.js +0 -304
  73. package/dist/Preview-BcdSr09-.js.map +0 -1
  74. package/dist/embed-Dsu6b-MV.js +0 -131
  75. package/dist/embed-Dsu6b-MV.js.map +0 -1
  76. package/dist/highlight-BLdNzTxQ.js.map +0 -1
  77. package/dist/inplace/table-widget-caret.d.ts +0 -11
  78. package/dist/inplace/table-widget-caret.d.ts.map +0 -1
  79. package/dist/useCodeMirror-CXtuBlLf.js.map +0 -1
@@ -0,0 +1,319 @@
1
+ import { a as e, c as t, i as n, n as r, o as i, r as a, s as o, t as s } from "./markdown-DcS6jMel.js";
2
+ import { a as c, c as l, l as u, u as d } from "./embed-cache-CcBfVrc9.js";
3
+ import { a as f, i as p, n as m, o as h, t as g } from "./embed-DKKeCE1Y.js";
4
+ import { Children as _, cloneElement as v, isValidElement as y, useEffect as b, useMemo as x, useRef as S, useState as C } from "react";
5
+ import { LanguageDescription as w } from "@codemirror/language";
6
+ import { highlightTree as T, tagHighlighter as E } from "@lezer/highlight";
7
+ import { jsx as D, jsxs as O } from "react/jsx-runtime";
8
+ //#region src/render/highlightCode.ts
9
+ var k = E(c.map(({ tags: e, token: t }) => ({
10
+ tag: e,
11
+ class: `stylo-tok-${t}`
12
+ }))), A = {
13
+ "&": "&",
14
+ "<": "&lt;",
15
+ ">": "&gt;"
16
+ }, j = (e) => e.replace(/[&<>]/g, (e) => A[e] ?? e);
17
+ function M(e, t) {
18
+ return typeof t == "function" ? t(e) : w.matchLanguageName(t, e, !0);
19
+ }
20
+ async function N(e, t, n) {
21
+ let r = /\S*/.exec(t)?.[0] ?? "";
22
+ if (!r) return null;
23
+ let i = M(r, n);
24
+ if (!i) return null;
25
+ let a;
26
+ if (i instanceof w) try {
27
+ a = (await i.load()).language;
28
+ } catch {
29
+ return null;
30
+ }
31
+ else a = i;
32
+ let o = a.parser.parse(e), s = "", c = 0;
33
+ return T(o, k, (t, n, r) => {
34
+ t > c && (s += j(e.slice(c, t))), s += `<span class="${r}">${j(e.slice(t, n))}</span>`, c = n;
35
+ }), c < e.length && (s += j(e.slice(c))), s;
36
+ }
37
+ //#endregion
38
+ //#region src/render/CodeBlock.tsx
39
+ function P({ code: e, language: t, codeLanguages: n, className: r }) {
40
+ let [i, a] = C(null);
41
+ return b(() => {
42
+ let r = !0;
43
+ return a(null), N(e, t, n).then((e) => {
44
+ r && a(e);
45
+ }), () => {
46
+ r = !1;
47
+ };
48
+ }, [
49
+ e,
50
+ t,
51
+ n
52
+ ]), i == null ? /* @__PURE__ */ D("code", {
53
+ className: r,
54
+ children: e
55
+ }) : /* @__PURE__ */ D("code", {
56
+ className: r,
57
+ dangerouslySetInnerHTML: { __html: i }
58
+ });
59
+ }
60
+ //#endregion
61
+ //#region src/render/taskCheckbox.ts
62
+ var F = /^[ \t]*(?:[-*+]|\d+[.)])[ \t]+\[([ xX])\]/;
63
+ function I(e, t) {
64
+ let n = e.indexOf("\n", t), r = e.slice(t, n === -1 ? e.length : n), i = F.exec(r);
65
+ if (!i) return null;
66
+ let a = t + i[0].length - 3;
67
+ return {
68
+ start: a,
69
+ end: a + 3
70
+ };
71
+ }
72
+ function L(e, t, n, r) {
73
+ if (!r || typeof t != "string" || !t.includes("task-list-item")) return null;
74
+ let i = e?.position?.start.offset;
75
+ if (i === void 0) return null;
76
+ let a = I(n, i);
77
+ return a ? (e) => r({
78
+ ...a,
79
+ checked: e.target.checked
80
+ }) : null;
81
+ }
82
+ function R(e, t) {
83
+ if (!y(e)) return { done: !1 };
84
+ if (e.type === "input") return {
85
+ done: !0,
86
+ node: v(e, {
87
+ disabled: !1,
88
+ onChange: t
89
+ })
90
+ };
91
+ let n = _.toArray(e.props.children);
92
+ if (n.length === 0) return { done: !1 };
93
+ let r = R(n[0], t);
94
+ return r.done ? {
95
+ done: !0,
96
+ node: v(e, {}, [r.node, ...n.slice(1)])
97
+ } : { done: !1 };
98
+ }
99
+ //#endregion
100
+ //#region src/render/preview-components.tsx
101
+ function z(e, t) {
102
+ let n = e[t];
103
+ return typeof n == "string" ? n : void 0;
104
+ }
105
+ function B(e, t, n, r, i) {
106
+ return e === void 0 || !t ? i : /* @__PURE__ */ D(h, {
107
+ reference: e,
108
+ source: t,
109
+ onError: n,
110
+ inline: r
111
+ });
112
+ }
113
+ function V({ valueRef: e, onWikiLinkClick: t, embedSource: n, onResolveError: r, codeLanguages: i, onTaskToggle: a }) {
114
+ return {
115
+ a({ node: e, children: n, ...r }) {
116
+ let i = z(r, "data-wikilink");
117
+ return i === void 0 ? /* @__PURE__ */ D("a", {
118
+ ...r,
119
+ rel: "noreferrer",
120
+ children: n
121
+ }) : /* @__PURE__ */ D("a", {
122
+ ...r,
123
+ href: "#",
124
+ onClick: (e) => {
125
+ e.preventDefault(), t?.(i);
126
+ },
127
+ children: n
128
+ });
129
+ },
130
+ div({ node: e, children: t, ...i }) {
131
+ return /* @__PURE__ */ D("div", {
132
+ ...i,
133
+ children: B(z(i, "data-stylo-embed"), n, r, !1, t)
134
+ });
135
+ },
136
+ span({ node: e, children: t, ...i }) {
137
+ return /* @__PURE__ */ D("span", {
138
+ ...i,
139
+ children: B(z(i, "data-stylo-embed-inline"), n, r, !0, t)
140
+ });
141
+ },
142
+ li({ node: t, children: n, ...r }) {
143
+ let i = L(t, r.className, e.current, a);
144
+ if (i) {
145
+ let e = _.toArray(n), t = e.findIndex((e) => y(e)), a = t === -1 ? null : R(e[t], i);
146
+ if (a?.done) {
147
+ let n = e.map((e, n) => n === t ? a.node : e);
148
+ return /* @__PURE__ */ D("li", {
149
+ ...r,
150
+ children: n
151
+ });
152
+ }
153
+ }
154
+ return /* @__PURE__ */ D("li", {
155
+ ...r,
156
+ children: n
157
+ });
158
+ },
159
+ table({ node: e, children: t, ...n }) {
160
+ return /* @__PURE__ */ D("div", {
161
+ className: "stylo-table-wrap",
162
+ children: /* @__PURE__ */ D("table", {
163
+ ...n,
164
+ children: t
165
+ })
166
+ });
167
+ },
168
+ code({ node: e, className: t, children: n, ...r }) {
169
+ let a = /language-(\w+)/.exec(t || "")?.[1];
170
+ return a && i ? /* @__PURE__ */ D(P, {
171
+ className: t,
172
+ language: a,
173
+ code: String(n).replace(/\n$/, ""),
174
+ codeLanguages: i
175
+ }) : /* @__PURE__ */ D("code", {
176
+ ...r,
177
+ className: t,
178
+ children: n
179
+ });
180
+ }
181
+ };
182
+ }
183
+ //#endregion
184
+ //#region src/render/remark-callout.ts
185
+ function H() {
186
+ return (e) => {
187
+ o(e, "blockquote", (e) => {
188
+ let t = e.children[0];
189
+ if (t?.type !== "paragraph") return;
190
+ let n = t.children[0];
191
+ if (n?.type !== "text") return;
192
+ let r = p.exec(n.value);
193
+ if (!r) return;
194
+ n.value = n.value.slice(r[0].length);
195
+ let i = r[1].toLowerCase();
196
+ e.data ??= {};
197
+ let a = e.data.hProperties ??= {};
198
+ a.className = ["stylo-callout", `stylo-callout-${f(i)}`], a["data-callout"] = i;
199
+ });
200
+ };
201
+ }
202
+ //#endregion
203
+ //#region src/render/remark-embed.ts
204
+ function U() {
205
+ return (e) => {
206
+ o(e, "paragraph", (e) => {
207
+ let t = e.children.length === 1 ? e.children[0] : void 0;
208
+ if (t?.type !== "text" || !m(t.value)) return;
209
+ g.lastIndex = 0;
210
+ let n = (g.exec(t.value.trim())?.[1] ?? "").trim();
211
+ n && (e.children = [], e.data ??= {}, e.data.hName = "div", e.data.hProperties = {
212
+ className: ["stylo-embed"],
213
+ "data-stylo-embed": n
214
+ });
215
+ }), o(e, "text", (e, n, r) => {
216
+ if (n == null || r == null || !e.value.includes("![[")) return;
217
+ let i = [], a = 0;
218
+ g.lastIndex = 0;
219
+ for (let t of e.value.matchAll(g)) {
220
+ let n = (t[1] ?? "").trim();
221
+ if (!n) continue;
222
+ let r = t.index ?? 0;
223
+ r > a && i.push({
224
+ type: "text",
225
+ value: e.value.slice(a, r)
226
+ }), i.push({
227
+ type: "text",
228
+ value: "",
229
+ data: {
230
+ hName: "span",
231
+ hProperties: {
232
+ className: ["stylo-embed"],
233
+ "data-stylo-embed-inline": n
234
+ },
235
+ hChildren: []
236
+ }
237
+ }), a = r + t[0].length;
238
+ }
239
+ if (i.length) return a < e.value.length && i.push({
240
+ type: "text",
241
+ value: e.value.slice(a)
242
+ }), r.children.splice(n, 1, ...i), [t, n + i.length];
243
+ });
244
+ };
245
+ }
246
+ //#endregion
247
+ //#region src/render/remark-wikilink.ts
248
+ function W() {
249
+ return (e) => {
250
+ o(e, "text", (e, t, n) => {
251
+ if (n == null || t == null || !e.value.includes("[[")) return;
252
+ let r = [], i = 0;
253
+ for (let t of e.value.matchAll(u)) {
254
+ let [n = "", a = "", o] = t, s = t.index ?? 0;
255
+ s > 0 && e.value[s - 1] === "!" || (s > i && r.push({
256
+ type: "text",
257
+ value: e.value.slice(i, s)
258
+ }), r.push({
259
+ type: "link",
260
+ url: "#",
261
+ data: { hProperties: { "data-wikilink": a.trim() } },
262
+ children: [{
263
+ type: "text",
264
+ value: (o ?? a).trim()
265
+ }]
266
+ }), i = s + n.length);
267
+ }
268
+ if (i !== 0) return i < e.value.length && r.push({
269
+ type: "text",
270
+ value: e.value.slice(i)
271
+ }), n.children.splice(t, 1, ...r), t + r.length;
272
+ });
273
+ };
274
+ }
275
+ //#endregion
276
+ //#region src/render/Preview.tsx
277
+ var G = [e];
278
+ function K({ value: e, onWikiLinkClick: t, embedSource: o, onResolveError: c, frontmatter: u = "hidden", codeLanguages: f, softBreaks: p, onTaskToggle: m }) {
279
+ let h = u === "code" ? l(e) : null, g = x(() => [
280
+ a,
281
+ r,
282
+ s,
283
+ ...p ? [n] : [],
284
+ ...o ? [U] : [],
285
+ W,
286
+ H
287
+ ], [o, p]), _ = S(e);
288
+ _.current = e;
289
+ let v = x(() => V({
290
+ valueRef: _,
291
+ onWikiLinkClick: t,
292
+ embedSource: o,
293
+ onResolveError: c,
294
+ codeLanguages: f,
295
+ onTaskToggle: m
296
+ }), [
297
+ t,
298
+ o,
299
+ c,
300
+ f,
301
+ m
302
+ ]);
303
+ return /* @__PURE__ */ O("div", {
304
+ className: d.preview,
305
+ children: [h && /* @__PURE__ */ D("div", {
306
+ className: "stylo-frontmatter",
307
+ children: h.frontmatter
308
+ }), /* @__PURE__ */ D(i, {
309
+ remarkPlugins: g,
310
+ rehypePlugins: G,
311
+ components: v,
312
+ children: e
313
+ })]
314
+ });
315
+ }
316
+ //#endregion
317
+ export { K as Preview };
318
+
319
+ //# sourceMappingURL=Preview-5lm2uUVj.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Preview-5lm2uUVj.js","names":[],"sources":["../src/render/highlightCode.ts","../src/render/CodeBlock.tsx","../src/render/taskCheckbox.ts","../src/render/preview-components.tsx","../src/render/remark-callout.ts","../src/render/remark-embed.ts","../src/render/remark-wikilink.ts","../src/render/Preview.tsx"],"sourcesContent":["import { LanguageDescription, type Language } from \"@codemirror/language\"\nimport { highlightTree, tagHighlighter } from \"@lezer/highlight\"\nimport { SYNTAX_TAG_GROUPS } from \"../editor/highlight\"\nimport type { CodeLanguages } from \"../types\"\n\n/**\n * `preview`'s counterpart to `src/editor/highlight.ts`'s `styloHighlightStyle`\n * — same `SYNTAX_TAG_GROUPS`, same tags, but emitting plain `stylo-tok-<token>`\n * classes (styled in `stylo.module.css`) instead of a CodeMirror `StyleModule`,\n * since `highlightTree` here runs outside of any `EditorView`.\n */\nconst previewHighlighter = tagHighlighter(\n SYNTAX_TAG_GROUPS.map(({ tags, token }) => ({ tag: tags, class: `stylo-tok-${token}` })),\n)\n\nconst ESCAPES: Record<string, string> = { \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\" }\nconst escapeHtml = (text: string) => text.replace(/[&<>]/g, (c) => ESCAPES[c] ?? c)\n\n/**\n * Resolves a fence's language the same way `@codemirror/lang-markdown`\n * resolves `codeLanguages` for the CodeMirror surfaces, so a name that matches\n * on one matches on the other: the function form is called with the name\n * directly, an array is matched fuzzily by `LanguageDescription.matchLanguageName`.\n */\nfunction resolveLanguage(\n name: string,\n codeLanguages: CodeLanguages,\n): Language | LanguageDescription | null {\n if (typeof codeLanguages === \"function\") return codeLanguages(name)\n return LanguageDescription.matchLanguageName(codeLanguages, name, true)\n}\n\n/**\n * Tokenizes one fenced code block for `preview`, reusing the exact grammars\n * and colour mapping the in-place canvas's CodeMirror highlighter uses, so a\n * block looks identical whether the note is being read or edited. Returns\n * `null` — the block stays plain, un-highlighted text — when `codeLanguages`\n * has no match for `info`, or the match fails to load.\n */\nexport async function highlightToHtml(\n code: string,\n info: string,\n codeLanguages: CodeLanguages,\n): Promise<string | null> {\n const name = /\\S*/.exec(info)?.[0] ?? \"\"\n if (!name) return null\n\n const match = resolveLanguage(name, codeLanguages)\n if (!match) return null\n\n let language: Language\n if (match instanceof LanguageDescription) {\n try {\n language = (await match.load()).language\n } catch {\n return null\n }\n } else {\n language = match\n }\n\n const tree = language.parser.parse(code)\n let html = \"\"\n let pos = 0\n highlightTree(tree, previewHighlighter, (from, to, classes) => {\n if (from > pos) html += escapeHtml(code.slice(pos, from))\n html += `<span class=\"${classes}\">${escapeHtml(code.slice(from, to))}</span>`\n pos = to\n })\n if (pos < code.length) html += escapeHtml(code.slice(pos))\n return html\n}\n","import { useEffect, useState } from \"react\"\nimport type { CodeLanguages } from \"../types\"\nimport { highlightToHtml } from \"./highlightCode\"\n\ninterface CodeBlockProps {\n code: string\n language: string\n codeLanguages: CodeLanguages\n className?: string\n}\n\n/**\n * One fenced code block in `preview`. Renders plain text immediately — so\n * there is never a loading flash for something this small — then swaps in\n * `--stylo-syntax-*`-coloured spans once `codeLanguages` resolves and the\n * block's grammar parses. Per-language grammars stay exactly as lazy as they\n * already are for the CodeMirror surfaces (`codeLanguages` is host-supplied),\n * so a `preview`-only consumer never pays for one it never shows.\n */\nexport function CodeBlock({ code, language, codeLanguages, className }: CodeBlockProps) {\n const [html, setHtml] = useState<string | null>(null)\n\n useEffect(() => {\n let live = true\n setHtml(null)\n highlightToHtml(code, language, codeLanguages).then((result) => {\n if (live) setHtml(result)\n })\n return () => {\n live = false\n }\n }, [code, language, codeLanguages])\n\n if (html == null) return <code className={className}>{code}</code>\n // `html` is built in highlightCode.ts from the parsed source text (HTML-escaped)\n // and fixed `stylo-tok-*` class names only — no host or document input reaches it.\n return <code className={className} dangerouslySetInnerHTML={{ __html: html }} />\n}\n","import {\n Children,\n cloneElement,\n isValidElement,\n type ChangeEvent,\n type ReactElement,\n type ReactNode,\n} from \"react\"\nimport type { TaskToggleInfo } from \"../types\"\n\n/**\n * A task-list item's own `[ ]` / `[x]` marker sits right after its bullet or\n * ordinal and indentation — nothing else can appear before it on the line.\n * Anchoring the match to the very start of the item's raw text (from mdast's\n * `position.start.offset`) makes this safe even when the item's own text\n * could otherwise read as another marker further into the line.\n */\nconst CHECKBOX_PREFIX = /^[ \\t]*(?:[-*+]|\\d+[.)])[ \\t]+\\[([ xX])\\]/\n\n/**\n * Locates the exact `[ ]` / `[x]` substring of a task-list item within\n * `value`, given the raw offset where the item itself starts (a GFM\n * `listItem`'s `position.start.offset`, as parsed by `remark-gfm`).\n * Returns `null` if the prefix doesn't match a checkbox — it always should\n * for a node `remark-gfm` marked `checked`, but a raw markdown edit racing\n * the render is not impossible.\n */\nexport function findCheckboxOffsets(\n value: string,\n itemStart: number,\n): { start: number; end: number } | null {\n const lineEnd = value.indexOf(\"\\n\", itemStart)\n const prefix = value.slice(itemStart, lineEnd === -1 ? value.length : lineEnd)\n const match = CHECKBOX_PREFIX.exec(prefix)\n if (!match) return null\n const start = itemStart + match[0].length - 3\n return { start, end: start + 3 }\n}\n\n/**\n * Builds the checkbox's `onChange` handler for a rendered `<li>`, or `null`\n * when it isn't an eligible task item — not a task list item at all,\n * `onTaskToggle` unset, no position data, or (a raw-edit race, effectively\n * never) a marker `findCheckboxOffsets` can't locate.\n */\nexport function makeToggleHandler(\n node: { position?: { start: { offset?: number } } } | undefined,\n className: string | undefined,\n value: string,\n onTaskToggle: ((info: TaskToggleInfo) => void) | undefined,\n): ((event: ChangeEvent<HTMLInputElement>) => void) | null {\n if (!onTaskToggle || typeof className !== \"string\" || !className.includes(\"task-list-item\")) {\n return null\n }\n const itemStart = node?.position?.start.offset\n if (itemStart === undefined) return null\n const offsets = findCheckboxOffsets(value, itemStart)\n if (!offsets) return null\n return (event) => onTaskToggle({ ...offsets, checked: event.target.checked })\n}\n\n/**\n * A task item's checkbox `<input>` is always the leftmost leaf of its `<li>`\n * — `mdast-util-to-hast` unshifts it onto the first paragraph, itself the\n * first result, whether or not GFM kept that paragraph wrapped (a \"loose\"\n * list, blank lines between items) or unwrapped it (a \"tight\" one). Walking\n * only the first-child spine finds it either way without ever wandering into\n * a nested sub-list's own checkbox, which lives as a later sibling, not a\n * descendant of the first child.\n */\nexport function enableLeadingCheckbox(\n node: ReactNode,\n onChange: (event: ChangeEvent<HTMLInputElement>) => void,\n): { done: true; node: ReactNode } | { done: false } {\n if (!isValidElement(node)) return { done: false }\n if (node.type === \"input\") {\n return {\n done: true,\n node: cloneElement(node as ReactElement<Record<string, unknown>>, {\n disabled: false,\n onChange,\n }),\n }\n }\n const kids = Children.toArray((node.props as { children?: ReactNode }).children)\n if (kids.length === 0) return { done: false }\n const result = enableLeadingCheckbox(kids[0], onChange)\n if (!result.done) return { done: false }\n return {\n done: true,\n node: cloneElement(node as ReactElement<{ children?: ReactNode }>, {}, [\n result.node,\n ...kids.slice(1),\n ]),\n }\n}\n","import { Children, isValidElement, type ReactNode } from \"react\"\nimport type { Components } from \"react-markdown\"\nimport type { CodeLanguages, EmbedSource, ResolveErrorInfo, TaskToggleInfo } from \"../types\"\nimport { CodeBlock } from \"./CodeBlock\"\nimport { Embed } from \"./Embed\"\nimport { enableLeadingCheckbox, makeToggleHandler } from \"./taskCheckbox\"\n\nexport interface PreviewComponentsOptions {\n /** Read at click time, not baked into the closure — kept fresh across\n * re-renders without forcing `buildPreviewComponents` itself to depend on\n * `value` (which changes every keystroke and would defeat memoizing it). */\n valueRef: { current: string }\n onWikiLinkClick?: (target: string) => void\n embedSource?: EmbedSource\n onResolveError?: (error: unknown, info: ResolveErrorInfo) => void\n codeLanguages?: CodeLanguages\n onTaskToggle?: (info: TaskToggleInfo) => void\n}\n\n/** One `data-*` attribute off a component's spread props, as a string. */\nfunction dataAttr(rest: object, key: string): string | undefined {\n const v = (rest as Record<string, unknown>)[key]\n return typeof v === \"string\" ? v : undefined\n}\n\n/** The `![[ref]]` embed for a `data-stylo-embed(-inline)` node, or `children` unchanged. */\nfunction embedOrChildren(\n reference: string | undefined,\n embedSource: EmbedSource | undefined,\n onResolveError: PreviewComponentsOptions[\"onResolveError\"],\n inline: boolean,\n children: ReactNode,\n): ReactNode {\n if (reference === undefined || !embedSource) return children\n return (\n <Embed reference={reference} source={embedSource} onError={onResolveError} inline={inline} />\n )\n}\n\n/**\n * Builds `react-markdown`'s `components` map for `Preview`: the wikilink\n * click handler on `a`, the embed slots on `div` / `span`, the task-checkbox\n * wiring on `li`, the table wrapper, and fenced-code highlighting.\n */\nexport function buildPreviewComponents({\n valueRef,\n onWikiLinkClick,\n embedSource,\n onResolveError,\n codeLanguages,\n onTaskToggle,\n}: PreviewComponentsOptions): Components {\n return {\n a({ node: _node, children, ...rest }) {\n const target = dataAttr(rest, \"data-wikilink\")\n if (target !== undefined) {\n return (\n <a\n {...rest}\n href=\"#\"\n onClick={(event) => {\n event.preventDefault()\n onWikiLinkClick?.(target)\n }}\n >\n {children}\n </a>\n )\n }\n return (\n <a {...rest} rel=\"noreferrer\">\n {children}\n </a>\n )\n },\n div({ node: _node, children, ...rest }) {\n return (\n <div {...rest}>\n {embedOrChildren(\n dataAttr(rest, \"data-stylo-embed\"),\n embedSource,\n onResolveError,\n false,\n children,\n )}\n </div>\n )\n },\n span({ node: _node, children, ...rest }) {\n return (\n <span {...rest}>\n {embedOrChildren(\n dataAttr(rest, \"data-stylo-embed-inline\"),\n embedSource,\n onResolveError,\n true,\n children,\n )}\n </span>\n )\n },\n li({ node, children, ...rest }) {\n const handleToggle = makeToggleHandler(node, rest.className, valueRef.current, onTaskToggle)\n if (handleToggle) {\n // A loose list (blank line between items) keeps the `<li>`'s content\n // wrapped in a `<p>`, itself preceded by a formatting `\"\\n\"` text\n // node — skip past that to the first real element.\n const kids = Children.toArray(children)\n const firstElementIndex = kids.findIndex((kid) => isValidElement(kid))\n const enabled =\n firstElementIndex === -1\n ? null\n : enableLeadingCheckbox(kids[firstElementIndex], handleToggle)\n if (enabled?.done) {\n const nextKids: ReactNode[] = kids.map((kid, i) =>\n i === firstElementIndex ? enabled.node : kid,\n )\n return <li {...rest}>{nextKids}</li>\n }\n }\n return <li {...rest}>{children}</li>\n },\n table({ node: _node, children, ...rest }) {\n return (\n <div className=\"stylo-table-wrap\">\n <table {...rest}>{children}</table>\n </div>\n )\n },\n code({ node: _node, className, children, ...rest }) {\n const language = /language-(\\w+)/.exec(className || \"\")?.[1]\n if (language && codeLanguages) {\n return (\n <CodeBlock\n className={className}\n language={language}\n code={String(children).replace(/\\n$/, \"\")}\n codeLanguages={codeLanguages}\n />\n )\n }\n return (\n <code {...rest} className={className}>\n {children}\n </code>\n )\n },\n }\n}\n","import type { Blockquote, Root } from \"mdast\"\nimport { visit } from \"unist-util-visit\"\nimport { CALLOUT_TOKEN, calloutBucket } from \"../callout\"\n\n/**\n * Turns an Obsidian callout blockquote (`> [!note] Title`) into a\n * `<blockquote class=\"stylo-callout stylo-callout-<bucket>\" data-callout=\"note\">`.\n * The `[!type]` token is stripped from the first line; a `::before` label keyed\n * off `data-callout` stands in for it (matching the in-place canvas). The\n * `-` / `+` fold marker is accepted and ignored — the box always renders open.\n */\nexport function remarkCallout() {\n return (tree: Root) => {\n visit(tree, \"blockquote\", (node: Blockquote) => {\n const para = node.children[0]\n if (para?.type !== \"paragraph\") return\n const first = para.children[0]\n if (first?.type !== \"text\") return\n\n const m = CALLOUT_TOKEN.exec(first.value)\n if (!m) return\n\n first.value = first.value.slice(m[0].length)\n const type = m[1]!.toLowerCase()\n node.data ??= {}\n const props = (node.data.hProperties ??= {}) as Record<string, unknown>\n props.className = [\"stylo-callout\", `stylo-callout-${calloutBucket(type)}`]\n props[\"data-callout\"] = type\n })\n }\n}\n","import type { Paragraph, PhrasingContent, Root, Text } from \"mdast\"\nimport { SKIP, visit } from \"unist-util-visit\"\nimport { EMBED_PATTERN, isLoneEmbed } from \"../embed\"\n\n/**\n * Turns `![[ref]]` transclusion syntax into empty carrier elements the `Embed`\n * component (wired in `Preview`) fills from the host's `embedSource`.\n *\n * - A **lone** `![[ref]]` — the whole paragraph, trimmed — becomes a block\n * `<div class=\"stylo-embed\" data-stylo-embed=\"ref\">`.\n * - A `![[ref]]` **inside other text** becomes an inline\n * `<span class=\"stylo-embed\" data-stylo-embed-inline=\"ref\">`, and the\n * surrounding text is preserved around it. The host node should be phrasing\n * content in this case.\n *\n * `![[…]]` inside inline or fenced code is left literal (it is not a `text`\n * node). Must run before `remarkWikilink`, or the inner `[[ref]]` is rewritten\n * to a link first. Off unless the consumer passes `embedSource` — `Preview` only\n * adds this plugin then.\n */\nexport function remarkEmbed() {\n return (tree: Root) => {\n visit(tree, \"paragraph\", (node: Paragraph) => {\n const only = node.children.length === 1 ? node.children[0] : undefined\n if (only?.type !== \"text\" || !isLoneEmbed(only.value)) return\n\n EMBED_PATTERN.lastIndex = 0\n const ref = (EMBED_PATTERN.exec(only.value.trim())?.[1] ?? \"\").trim()\n if (!ref) return\n\n node.children = []\n node.data ??= {}\n node.data.hName = \"div\"\n node.data.hProperties = { className: [\"stylo-embed\"], \"data-stylo-embed\": ref }\n })\n\n visit(tree, \"text\", (node: Text, index, parent) => {\n if (index == null || parent == null || !node.value.includes(\"![[\")) return\n\n const parts: PhrasingContent[] = []\n let cursor = 0\n // `matchAll` seeds its internal copy from the shared regex's `lastIndex`;\n // reset it so the scan starts at 0 (the lone-paragraph pass above left it\n // mid-string).\n EMBED_PATTERN.lastIndex = 0\n for (const match of node.value.matchAll(EMBED_PATTERN)) {\n const ref = (match[1] ?? \"\").trim()\n if (!ref) continue\n const start = match.index ?? 0\n if (start > cursor) parts.push({ type: \"text\", value: node.value.slice(cursor, start) })\n parts.push({\n type: \"text\",\n value: \"\",\n data: {\n hName: \"span\",\n hProperties: { className: [\"stylo-embed\"], \"data-stylo-embed-inline\": ref },\n hChildren: [],\n },\n })\n cursor = start + match[0].length\n }\n\n if (!parts.length) return\n if (cursor < node.value.length) parts.push({ type: \"text\", value: node.value.slice(cursor) })\n parent.children.splice(index, 1, ...parts)\n return [SKIP, index + parts.length]\n })\n }\n}\n","import type { Link, Root, Text } from \"mdast\"\nimport { visit } from \"unist-util-visit\"\nimport { WIKILINK_PATTERN } from \"../wikilink\"\n\n/**\n * Rewrites `[[target]]` and `[[target|label]]` inside text into link nodes that\n * carry a `data-wikilink` attribute holding the target. The rendered href is\n * inert (`#`); navigation is the host's job via `onWikiLinkClick`.\n */\nexport function remarkWikilink() {\n return (tree: Root) => {\n visit(tree, \"text\", (node: Text, index, parent) => {\n if (parent == null || index == null || !node.value.includes(\"[[\")) return\n\n const out: Array<Text | Link> = []\n let cursor = 0\n\n for (const match of node.value.matchAll(WIKILINK_PATTERN)) {\n const [raw = \"\", rawTarget = \"\", rawLabel] = match\n const start = match.index ?? 0\n // A `![[ref]]` embed either was already consumed by `remarkEmbed`\n // earlier in the pipeline (when `embedSource` is set), or wasn't —\n // either way its inner `[[ref]]` must stay untouched here rather than\n // becoming a dead link, per `EmbedSource`'s documented fallback (a\n // bare `![[ref]]` renders unchanged with no `embedSource`).\n if (start > 0 && node.value[start - 1] === \"!\") continue\n if (start > cursor) {\n out.push({ type: \"text\", value: node.value.slice(cursor, start) })\n }\n out.push({\n type: \"link\",\n url: \"#\",\n data: { hProperties: { \"data-wikilink\": rawTarget.trim() } },\n children: [{ type: \"text\", value: (rawLabel ?? rawTarget).trim() }],\n })\n cursor = start + raw.length\n }\n\n if (cursor === 0) return\n if (cursor < node.value.length) {\n out.push({ type: \"text\", value: node.value.slice(cursor) })\n }\n\n parent.children.splice(index, 1, ...out)\n return index + out.length\n })\n }\n}\n","import { useMemo, useRef } from \"react\"\nimport Markdown from \"react-markdown\"\nimport rehypeKatex from \"rehype-katex\"\nimport remarkBreaks from \"remark-breaks\"\nimport remarkFrontmatter from \"remark-frontmatter\"\nimport remarkGfm from \"remark-gfm\"\nimport remarkMath from \"remark-math\"\nimport { splitFrontmatter } from \"../frontmatter\"\nimport styles from \"../styles/stylo.module.css\"\nimport type {\n CodeLanguages,\n EmbedSource,\n FrontmatterDisplay,\n ResolveErrorInfo,\n TaskToggleInfo,\n} from \"../types\"\nimport { buildPreviewComponents } from \"./preview-components\"\nimport { remarkCallout } from \"./remark-callout\"\nimport { remarkEmbed } from \"./remark-embed\"\nimport { remarkWikilink } from \"./remark-wikilink\"\n\nconst REHYPE_PLUGINS = [rehypeKatex]\n\nexport interface PreviewProps {\n value: string\n onWikiLinkClick?: (target: string) => void\n /** Resolves `![[ref]]` embeds. Omit and `![[…]]` stays literal. */\n embedSource?: EmbedSource\n /** Notified when `embedSource` rejects; the literal fallback still renders. */\n onResolveError?: (error: unknown, info: ResolveErrorInfo) => void\n /** `\"code\"` renders the `---` block as a styled `<pre>`; `\"hidden\"` (default) drops it. */\n frontmatter?: FrontmatterDisplay\n /**\n * Grammars for fenced-code syntax highlighting, matching the CodeMirror\n * surfaces' `codeLanguages` prop exactly (same resolution rules, same\n * `--stylo-syntax-*` colours). Omit and fenced code renders as plain,\n * un-highlighted text — today's behaviour.\n */\n codeLanguages?: CodeLanguages\n /**\n * Turn a single line ending into a real line break (`<br>`) instead of\n * CommonMark's default — a blank line required to start a new paragraph,\n * otherwise consecutive lines join into one run. Obsidian's Live Preview\n * reads this way. Off by default: every existing `preview` render keeps\n * today's paragraph-joining behaviour unless a host opts in. Has no effect\n * on `in-place` / `source` — CodeMirror already decorates each source line\n * independently there.\n */\n softBreaks?: boolean\n /**\n * Makes task-list checkboxes clickable instead of `disabled`. Fired with\n * raw `value` offsets bracketing the clicked marker and its new state; the\n * host owns splicing `value` and calling its own `onChange`. Off by\n * default — every checkbox stays `disabled`, today's behaviour, until a\n * host opts in.\n */\n onTaskToggle?: (info: TaskToggleInfo) => void\n}\n\n/** Rendered Markdown + KaTeX view. A pure function of the string. */\nexport function Preview({\n value,\n onWikiLinkClick,\n embedSource,\n onResolveError,\n frontmatter = \"hidden\",\n codeLanguages,\n softBreaks,\n onTaskToggle,\n}: PreviewProps) {\n const fm = frontmatter === \"code\" ? splitFrontmatter(value) : null\n\n // `remarkEmbed` must precede `remarkWikilink` (it consumes the `![[…]]` before\n // the inner `[[…]]` is rewritten) and is only in the pipeline when the host\n // opts in, so a bare `![[x]]` renders unchanged otherwise.\n const remarkPlugins = useMemo(\n () => [\n remarkFrontmatter,\n remarkGfm,\n remarkMath,\n ...(softBreaks ? [remarkBreaks] : []),\n ...(embedSource ? [remarkEmbed] : []),\n remarkWikilink,\n remarkCallout,\n ],\n [embedSource, softBreaks],\n )\n\n // `value` changes on every keystroke, so it's read through a ref rather than\n // closed over directly — otherwise memoizing `components` on it would be\n // pointless, defeating the point of memoizing at all (a changed component\n // identity at the same tree position makes react-markdown remount it, which\n // is exactly what stable identities here are meant to avoid for `CodeBlock`\n // and `Embed`).\n const valueRef = useRef(value)\n valueRef.current = value\n\n const components = useMemo(\n () =>\n buildPreviewComponents({\n valueRef,\n onWikiLinkClick,\n embedSource,\n onResolveError,\n codeLanguages,\n onTaskToggle,\n }),\n [onWikiLinkClick, embedSource, onResolveError, codeLanguages, onTaskToggle],\n )\n\n return (\n <div className={styles.preview}>\n {fm && <div className=\"stylo-frontmatter\">{fm.frontmatter}</div>}\n <Markdown\n remarkPlugins={remarkPlugins}\n rehypePlugins={REHYPE_PLUGINS}\n components={components}\n >\n {value}\n </Markdown>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { ReactNode } from "react";
2
+ import type { Extension } from "@codemirror/state";
2
3
  import type { EditorView } from "@codemirror/view";
3
4
  import type { CodeLanguages, EmbedSource, FrontmatterDisplay, ResolveErrorInfo, TagSource, TaskToggleInfo, WikiLinkSource } from "./types";
4
5
  export interface SplitViewProps {
@@ -19,6 +20,8 @@ export interface SplitViewProps {
19
20
  onSave?: (value: string) => void;
20
21
  /** Forwarded the source pane's `EditorView` for the shared toolbar. */
21
22
  onViewChange?: (view: EditorView | null) => void;
23
+ /** Host CodeMirror extensions for the source pane. */
24
+ hostExtensions?: readonly Extension[];
22
25
  /** Host content docked in the source pane, after its search panel. Read once. */
23
26
  canvasHeader?: (ctx: {
24
27
  view: EditorView | null;
@@ -30,5 +33,5 @@ export interface SplitViewProps {
30
33
  * Stylo root to have a bounded height — otherwise both panes grow and the page
31
34
  * scrolls instead.
32
35
  */
33
- export declare function SplitView({ value, onChange, onWikiLinkClick, readOnly, placeholder, codeLanguages, wikiLinkSource, tagSource, embedSource, onResolveError, frontmatter, softBreaks, onTaskToggle, onSave, onViewChange, canvasHeader, }: SplitViewProps): import("react").JSX.Element;
36
+ export declare function SplitView({ value, onChange, onWikiLinkClick, readOnly, placeholder, codeLanguages, wikiLinkSource, tagSource, embedSource, onResolveError, frontmatter, softBreaks, onTaskToggle, onSave, onViewChange, canvasHeader, hostExtensions, }: SplitViewProps): import("react").JSX.Element;
34
37
  //# sourceMappingURL=SplitView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SplitView.d.ts","sourceRoot":"","sources":["../src/SplitView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAIlD,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,SAAS,EACT,cAAc,EACd,cAAc,EACf,MAAM,SAAS,CAAA;AAEhB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACjE,WAAW,CAAC,EAAE,kBAAkB,CAAA;IAChC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IAC7C,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,uEAAuE;IACvE,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAChD,iFAAiF;IACjF,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,KAAK,SAAS,CAAA;CAC/D;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,EACd,SAAS,EACT,WAAW,EACX,cAAc,EACd,WAAW,EACX,UAAU,EACV,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,YAAY,GACb,EAAE,cAAc,+BAqEhB"}
1
+ {"version":3,"file":"SplitView.d.ts","sourceRoot":"","sources":["../src/SplitView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAIlD,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,SAAS,EACT,cAAc,EACd,cAAc,EACf,MAAM,SAAS,CAAA;AAEhB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACjE,WAAW,CAAC,EAAE,kBAAkB,CAAA;IAChC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IAC7C,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,uEAAuE;IACvE,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAChD,sDAAsD;IACtD,cAAc,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;IACrC,iFAAiF;IACjF,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,KAAK,SAAS,CAAA;CAC/D;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,EACd,SAAS,EACT,WAAW,EACX,cAAc,EACd,WAAW,EACX,UAAU,EACV,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,cAAc,GACf,EAAE,cAAc,+BAsEhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"Stylo.d.ts","sourceRoot":"","sources":["../src/Stylo.tsx"],"names":[],"mappings":"AAUA,OAAO,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAoB,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAExE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,oGAgMhB,CAAA"}
1
+ {"version":3,"file":"Stylo.d.ts","sourceRoot":"","sources":["../src/Stylo.tsx"],"names":[],"mappings":"AAWA,OAAO,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAoB,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAExE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,oGA4MhB,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import type { ReactNode } from "react";
2
+ import type { Extension } from "@codemirror/state";
2
3
  import type { EditorView } from "@codemirror/view";
3
4
  import type { CodeLanguages, ResolveErrorInfo, TagSource, WikiLinkSource } from "../types";
4
5
  export interface SourceViewProps {
@@ -18,11 +19,13 @@ export interface SourceViewProps {
18
19
  onSave?: (value: string) => void;
19
20
  /** Called with the `EditorView` once created, and with `null` on teardown. */
20
21
  onViewChange?: (view: EditorView | null) => void;
22
+ /** Host CodeMirror extensions, reconfigured in place when the array changes. */
23
+ hostExtensions?: readonly Extension[];
21
24
  /** Host content docked after the search panel, before the document. Read once. */
22
25
  canvasHeader?: (ctx: {
23
26
  view: EditorView | null;
24
27
  }) => ReactNode;
25
28
  }
26
29
  /** Raw CodeMirror 6 Markdown surface bound to the canonical string. */
27
- export declare function SourceView({ value, onChange, readOnly, placeholder, codeLanguages, wikiLinkSource, tagSource, onResolveError, onSave, onViewChange, canvasHeader, }: SourceViewProps): import("react").JSX.Element;
30
+ export declare function SourceView({ value, onChange, readOnly, placeholder, codeLanguages, wikiLinkSource, tagSource, onResolveError, onSave, onViewChange, canvasHeader, hostExtensions, }: SourceViewProps): import("react").JSX.Element;
28
31
  //# sourceMappingURL=SourceView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SourceView.d.ts","sourceRoot":"","sources":["../../src/editor/SourceView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAO1F,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,qDAAqD;IACrD,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,6CAA6C;IAC7C,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACjE,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAChD,kFAAkF;IAClF,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,KAAK,SAAS,CAAA;CAC/D;AAED,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,EACd,SAAS,EACT,cAAc,EACd,MAAM,EACN,YAAY,EACZ,YAAY,GACb,EAAE,eAAe,+BAyCjB"}
1
+ {"version":3,"file":"SourceView.d.ts","sourceRoot":"","sources":["../../src/editor/SourceView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAO1F,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,qDAAqD;IACrD,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,6CAA6C;IAC7C,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACjE,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,8EAA8E;IAC9E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAChD,gFAAgF;IAChF,cAAc,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;IACrC,kFAAkF;IAClF,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE;QAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,KAAK,SAAS,CAAA;CAC/D;AAED,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,EACd,SAAS,EACT,cAAc,EACd,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,cAAc,GACf,EAAE,eAAe,+BA0CjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/editor/theme.ts"],"names":[],"mappings":"AAEA,yFAAyF;AACzF,eAAO,MAAM,UAAU,uCAoIrB,CAAA"}
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/editor/theme.ts"],"names":[],"mappings":"AAEA,yFAAyF;AACzF,eAAO,MAAM,UAAU,uCAwIrB,CAAA"}
@@ -15,6 +15,12 @@ export interface UseCodeMirrorOptions {
15
15
  * layer). Captured once — pass a stable, module-level array.
16
16
  */
17
17
  extensions?: Extension[];
18
+ /**
19
+ * Host-supplied extensions, appended after everything else. Unlike
20
+ * `extensions`, reactive: a changed array (compared shallowly) reconfigures
21
+ * the live view without a remount.
22
+ */
23
+ hostExtensions?: readonly Extension[];
18
24
  /** Fenced-code grammars, forwarded to the Markdown language. Read once. */
19
25
  codeLanguages?: CodeLanguages;
20
26
  /** `[[wikilink]]` autocomplete source. Read once. */
@@ -31,5 +37,5 @@ export interface UseCodeMirrorOptions {
31
37
  * Owns a CodeMirror `EditorView` for the lifetime of the host element and keeps
32
38
  * it in sync with a controlled Markdown string. Returns a ref for the container.
33
39
  */
34
- export declare function useCodeMirror({ value, onChange, readOnly, placeholder, onSave, onViewChange, extensions, codeLanguages, wikiLinkSource, tagSource, onResolveError, }: UseCodeMirrorOptions): import("react").RefObject<HTMLDivElement | null>;
40
+ export declare function useCodeMirror({ value, onChange, readOnly, placeholder, onSave, onViewChange, extensions, hostExtensions, codeLanguages, wikiLinkSource, tagSource, onResolveError, }: UseCodeMirrorOptions): import("react").RefObject<HTMLDivElement | null>;
35
41
  //# sourceMappingURL=useCodeMirror.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useCodeMirror.d.ts","sourceRoot":"","sources":["../../src/editor/useCodeMirror.ts"],"names":[],"mappings":"AACA,OAAO,EAAwC,KAAK,SAAS,EAAQ,MAAM,mBAAmB,CAAA;AAC9F,OAAO,EAAE,UAAU,EAAU,MAAM,kBAAkB,CAAA;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAO1F,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qFAAqF;IACrF,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,oFAAoF;IACpF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAChD;;;OAGG;IACH,UAAU,CAAC,EAAE,SAAS,EAAE,CAAA;IACxB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,qDAAqD;IACrD,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,6CAA6C;IAC7C,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;CAClE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,QAAQ,EACR,QAAgB,EAChB,WAAW,EACX,MAAM,EACN,YAAY,EACZ,UAAU,EACV,aAAa,EACb,cAAc,EACd,SAAS,EACT,cAAc,GACf,EAAE,oBAAoB,oDA8EtB"}
1
+ {"version":3,"file":"useCodeMirror.d.ts","sourceRoot":"","sources":["../../src/editor/useCodeMirror.ts"],"names":[],"mappings":"AACA,OAAO,EAAwC,KAAK,SAAS,EAAQ,MAAM,mBAAmB,CAAA;AAC9F,OAAO,EAAE,UAAU,EAAU,MAAM,kBAAkB,CAAA;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAO1F,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qFAAqF;IACrF,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,oFAAoF;IACpF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAA;IAChD;;;OAGG;IACH,UAAU,CAAC,EAAE,SAAS,EAAE,CAAA;IACxB;;;;OAIG;IACH,cAAc,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;IACrC,2EAA2E;IAC3E,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,qDAAqD;IACrD,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,6CAA6C;IAC7C,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAA;CAClE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,QAAQ,EACR,QAAgB,EAChB,WAAW,EACX,MAAM,EACN,YAAY,EACZ,UAAU,EACV,cAAc,EACd,aAAa,EACb,cAAc,EACd,SAAS,EACT,cAAc,GACf,EAAE,oBAAoB,oDAsHtB"}
@@ -0,0 +1,109 @@
1
+ import { i as e, n as t, r as n } from "./embed-cache-CcBfVrc9.js";
2
+ import { useEffect as r, useState as i } from "react";
3
+ import { jsx as a } from "react/jsx-runtime";
4
+ //#region src/render/Embed.tsx
5
+ function o({ reference: o, source: s, onError: c, inline: l }) {
6
+ let [u, d] = i(() => {
7
+ let e = n(s, o);
8
+ return e ? {
9
+ status: "ready",
10
+ node: e.node
11
+ } : { status: "loading" };
12
+ });
13
+ r(() => {
14
+ let r = !0;
15
+ function i() {
16
+ let t = n(s, o);
17
+ if (t) {
18
+ d({
19
+ status: "ready",
20
+ node: t.node
21
+ });
22
+ return;
23
+ }
24
+ d({ status: "loading" }), e(s, o).then((e) => r && d({
25
+ status: "ready",
26
+ node: e
27
+ }), (e) => {
28
+ r && (c?.(e, {
29
+ source: "embedSource",
30
+ input: o
31
+ }), d({ status: "error" }));
32
+ });
33
+ }
34
+ i();
35
+ let a = t(s, o, i);
36
+ return () => {
37
+ r = !1, a();
38
+ };
39
+ }, [
40
+ o,
41
+ s,
42
+ c
43
+ ]);
44
+ let f = `![[${o}]]`;
45
+ if (u.status === "loading") return /* @__PURE__ */ a("span", {
46
+ "aria-busy": "true",
47
+ children: f
48
+ });
49
+ if (u.status === "ready" && u.node != null) {
50
+ let e = (e) => e.stopPropagation();
51
+ return l ? /* @__PURE__ */ a("span", {
52
+ className: "stylo-embed-content stylo-embed-inline",
53
+ onMouseDown: e,
54
+ children: u.node
55
+ }) : /* @__PURE__ */ a("div", {
56
+ className: "stylo-embed-content",
57
+ onMouseDown: e,
58
+ children: u.node
59
+ });
60
+ }
61
+ return /* @__PURE__ */ a("span", { children: f });
62
+ }
63
+ //#endregion
64
+ //#region src/callout.ts
65
+ var s = /^\[!(\w+)\][+-]?[ \t]*/, c = /^([\s>]*)(\[!(\w+)\][+-]?[ \t]*)/, l = {
66
+ note: "note",
67
+ info: "note",
68
+ abstract: "note",
69
+ summary: "note",
70
+ tldr: "note",
71
+ tip: "tip",
72
+ hint: "tip",
73
+ important: "tip",
74
+ success: "tip",
75
+ check: "tip",
76
+ done: "tip",
77
+ question: "warn",
78
+ help: "warn",
79
+ faq: "warn",
80
+ warning: "warn",
81
+ caution: "warn",
82
+ attention: "warn",
83
+ todo: "warn",
84
+ failure: "danger",
85
+ fail: "danger",
86
+ missing: "danger",
87
+ danger: "danger",
88
+ error: "danger",
89
+ bug: "danger",
90
+ example: "example",
91
+ quote: "example",
92
+ cite: "example"
93
+ };
94
+ function u(e) {
95
+ return l[e.toLowerCase()] ?? "note";
96
+ }
97
+ //#endregion
98
+ //#region src/embed.ts
99
+ var d = /!\[\[([^\]\n]+?)\]\]/g;
100
+ function f(e) {
101
+ let t = e.trim();
102
+ d.lastIndex = 0;
103
+ let n = d.exec(t);
104
+ return n != null && n[0].length === t.length;
105
+ }
106
+ //#endregion
107
+ export { u as a, s as i, f as n, o, c as r, d as t };
108
+
109
+ //# sourceMappingURL=embed-DKKeCE1Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed-DKKeCE1Y.js","names":[],"sources":["../src/render/Embed.tsx","../src/callout.ts","../src/embed.ts"],"sourcesContent":["import { type ReactNode, useEffect, useState } from \"react\"\nimport type { EmbedSource, ResolveErrorInfo } from \"../types\"\nimport { onEmbedInvalidated, peekEmbed, resolveEmbed } from \"./embed-cache\"\n\ninterface EmbedProps {\n /** The raw `![[ref]]` reference, trimmed. */\n reference: string\n source: EmbedSource\n /** Notified if `source` rejects; the literal fallback still renders. */\n onError?: (error: unknown, info: ResolveErrorInfo) => void\n /**\n * Render as phrasing content in a `<span>` (a `![[…]]` mid-sentence) rather\n * than the default block `<div>`. The host node should be inline in this mode.\n */\n inline?: boolean\n}\n\ntype State = { status: \"loading\" | \"error\" } | { status: \"ready\"; node: ReactNode }\n\n/**\n * Renders one `![[ref]]` embed. Resolves the reference through `embedSource` —\n * via a shared cache (`embed-cache.ts`), so an embed re-mounted by a scroll or a\n * `preview` re-render is not re-fetched — and drops the result into\n * `<div class=\"stylo-embed-content\">`, or a `<span>` when `inline`. While it\n * resolves — and if it rejects, or resolves to `null` — the literal `![[ref]]`\n * text stands in, so a reference is never silently lost.\n */\nexport function Embed({ reference, source, onError, inline }: EmbedProps) {\n const [state, setState] = useState<State>(() => {\n const hit = peekEmbed(source, reference)\n return hit ? { status: \"ready\", node: hit.node } : { status: \"loading\" }\n })\n\n useEffect(() => {\n let live = true\n function load() {\n const hit = peekEmbed(source, reference)\n if (hit) {\n setState({ status: \"ready\", node: hit.node })\n return\n }\n setState({ status: \"loading\" })\n resolveEmbed(source, reference).then(\n (node) => live && setState({ status: \"ready\", node }),\n (error) => {\n if (!live) return\n onError?.(error, { source: \"embedSource\", input: reference })\n setState({ status: \"error\" })\n },\n )\n }\n load()\n // Reruns this same load when a host calls `StyloHandle.invalidateEmbed`\n // for this ref, so a mounted embed updates immediately rather than only\n // on its next mount.\n const unsubscribe = onEmbedInvalidated(source, reference, load)\n return () => {\n live = false\n unsubscribe()\n }\n }, [reference, source, onError])\n\n const literal = `![[${reference}]]`\n if (state.status === \"loading\") return <span aria-busy=\"true\">{literal}</span>\n if (state.status === \"ready\" && state.node != null) {\n // Keep the mousedown away from the in-place canvas's own delegated\n // handler — same reason and technique as the editable table widget\n // (`table-widget.ts`): CodeMirror's built-in click-to-place-caret runs\n // for *any* mousedown that reaches `contentDOM`'s listener regardless of\n // what a custom `domEventHandlers` hook decided, so returning `false`\n // from one is not enough to keep an atomic widget's interactive content\n // clickable — the event has to be stopped before it gets there. Not\n // `preventDefault` — the button (or whatever the host renders) still\n // gets the click natively. Inert outside the canvas (`preview` / `split`\n // have no such listener to stop).\n const stop = (e: { stopPropagation: () => void }) => e.stopPropagation()\n return inline ? (\n <span className=\"stylo-embed-content stylo-embed-inline\" onMouseDown={stop}>\n {state.node}\n </span>\n ) : (\n <div className=\"stylo-embed-content\" onMouseDown={stop}>\n {state.node}\n </div>\n )\n }\n return <span>{literal}</span>\n}\n","/**\n * Obsidian-style callouts: a blockquote whose first line is `> [!type]`,\n * optionally `> [!type] Title` or `> [!type]- Title` (the `-` / `+` fold marker\n * is parsed but Stylo always renders expanded).\n *\n * Single source of truth for the in-place decoration scanner (`nodes.ts`) and\n * the preview remark plugin (`remark-callout.ts`), so the two never drift. The\n * many Obsidian type names collapse to five colour buckets; the raw type is kept\n * on a `data-callout` attribute for a `::before` label and consumer styling.\n */\n\n/** `[!type]` with an optional fold marker, anchored after any `>` prefix. */\nexport const CALLOUT_TOKEN = /^\\[!(\\w+)\\][+-]?[ \\t]*/\n\n/** A blockquote head line in the in-place canvas: `> ` prefix, then the token. */\nexport const CALLOUT_HEAD_LINE = /^([\\s>]*)(\\[!(\\w+)\\][+-]?[ \\t]*)/\n\nexport type CalloutBucket = \"note\" | \"tip\" | \"warn\" | \"danger\" | \"example\"\n\nconst BUCKET: Record<string, CalloutBucket> = {\n note: \"note\",\n info: \"note\",\n abstract: \"note\",\n summary: \"note\",\n tldr: \"note\",\n tip: \"tip\",\n hint: \"tip\",\n important: \"tip\",\n success: \"tip\",\n check: \"tip\",\n done: \"tip\",\n question: \"warn\",\n help: \"warn\",\n faq: \"warn\",\n warning: \"warn\",\n caution: \"warn\",\n attention: \"warn\",\n todo: \"warn\",\n failure: \"danger\",\n fail: \"danger\",\n missing: \"danger\",\n danger: \"danger\",\n error: \"danger\",\n bug: \"danger\",\n example: \"example\",\n quote: \"example\",\n cite: \"example\",\n}\n\n/** The colour bucket for a callout type; unknown types read as `note`. */\nexport function calloutBucket(type: string): CalloutBucket {\n return BUCKET[type.toLowerCase()] ?? \"note\"\n}\n","/**\n * `![[ref]]` transclusion. Capture group 1 is the raw reference — everything\n * between `![[` and `]]`, passed to the host verbatim (any `#heading`,\n * `#^blockid`, or `|size` suffix included). The `g` flag is set for\n * `matchAll` / `exec` loops.\n *\n * Deliberately not built on `WIKILINK_PATTERN`: in an embed the `|` is a size\n * hint (`![[image.png|300]]`), not a display label, so Stylo does not split on\n * it — the whole reference goes to `embedSource`.\n */\nexport const EMBED_PATTERN = /!\\[\\[([^\\]\\n]+?)\\]\\]/g\n\n/** True when `text` (trimmed) is exactly one `![[ref]]` and nothing else. */\nexport function isLoneEmbed(text: string): boolean {\n const trimmed = text.trim()\n EMBED_PATTERN.lastIndex = 0\n const m = EMBED_PATTERN.exec(trimmed)\n return m != null && m[0].length === trimmed.length\n}\n"],"mappings":";;;;AA2BA,SAAgB,EAAM,EAAE,cAAW,WAAQ,YAAS,aAAsB;CACxE,IAAM,CAAC,GAAO,KAAY,QAAsB;EAC9C,IAAM,IAAM,EAAU,GAAQ,CAAS;EACvC,OAAO,IAAM;GAAE,QAAQ;GAAS,MAAM,EAAI;EAAK,IAAI,EAAE,QAAQ,UAAU;CACzE,CAAC;CAED,QAAgB;EACd,IAAI,IAAO;EACX,SAAS,IAAO;GACd,IAAM,IAAM,EAAU,GAAQ,CAAS;GACvC,IAAI,GAAK;IACP,EAAS;KAAE,QAAQ;KAAS,MAAM,EAAI;IAAK,CAAC;IAC5C;GACF;GAEA,AADA,EAAS,EAAE,QAAQ,UAAU,CAAC,GAC9B,EAAa,GAAQ,CAAS,CAAC,CAAC,MAC7B,MAAS,KAAQ,EAAS;IAAE,QAAQ;IAAS;GAAK,CAAC,IACnD,MAAU;IACJ,MACL,IAAU,GAAO;KAAE,QAAQ;KAAe,OAAO;IAAU,CAAC,GAC5D,EAAS,EAAE,QAAQ,QAAQ,CAAC;GAC9B,CACF;EACF;EACA,EAAK;EAIL,IAAM,IAAc,EAAmB,GAAQ,GAAW,CAAI;EAC9D,aAAa;GAEX,AADA,IAAO,IACP,EAAY;EACd;CACF,GAAG;EAAC;EAAW;EAAQ;CAAO,CAAC;CAE/B,IAAM,IAAU,MAAM,EAAU;CAChC,IAAI,EAAM,WAAW,WAAW,OAAO,kBAAC,QAAD;EAAM,aAAU;EAAQ,UAAA;CAAc,CAAA;CAC7E,IAAI,EAAM,WAAW,WAAW,EAAM,QAAQ,MAAM;EAWlD,IAAM,KAAQ,MAAuC,EAAE,gBAAgB;EACvE,OAAO,IACL,kBAAC,QAAD;GAAM,WAAU;GAAyC,aAAa;GACnE,UAAA,EAAM;EACH,CAAA,IAEN,kBAAC,OAAD;GAAK,WAAU;GAAsB,aAAa;GAC/C,UAAA,EAAM;EACJ,CAAA;CAET;CACA,OAAO,kBAAC,QAAD,EAAA,UAAO,EAAc,CAAA;AAC9B;;;AC3EA,IAAa,IAAgB,0BAGhB,IAAoB,oCAI3B,IAAwC;CAC5C,MAAM;CACN,MAAM;CACN,UAAU;CACV,SAAS;CACT,MAAM;CACN,KAAK;CACL,MAAM;CACN,WAAW;CACX,SAAS;CACT,OAAO;CACP,MAAM;CACN,UAAU;CACV,MAAM;CACN,KAAK;CACL,SAAS;CACT,SAAS;CACT,WAAW;CACX,MAAM;CACN,SAAS;CACT,MAAM;CACN,SAAS;CACT,QAAQ;CACR,OAAO;CACP,KAAK;CACL,SAAS;CACT,OAAO;CACP,MAAM;AACR;AAGA,SAAgB,EAAc,GAA6B;CACzD,OAAO,EAAO,EAAK,YAAY,MAAM;AACvC;;;AC1CA,IAAa,IAAgB;AAG7B,SAAgB,EAAY,GAAuB;CACjD,IAAM,IAAU,EAAK,KAAK;CAC1B,EAAc,YAAY;CAC1B,IAAM,IAAI,EAAc,KAAK,CAAO;CACpC,OAAO,KAAK,QAAQ,EAAE,EAAE,CAAC,WAAW,EAAQ;AAC9C"}