@draftably/markdown 0.1.0 → 0.2.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 (50) hide show
  1. package/README.md +16 -64
  2. package/dist/chunks/{core-DPjuIyPG.js → core-D4HpamVq.js} +19 -13
  3. package/dist/chunks/mermaid-facade-BoLWBerE.js +289 -0
  4. package/dist/chunks/mermaid-importer-IVovOQE9.js +3753 -0
  5. package/dist/markdown-it.js +86 -85
  6. package/dist/mermaid.js +93 -0
  7. package/dist/remark.js +46 -46
  8. package/dist/types/{core.d.ts → packages/markdown/src/core.d.ts} +11 -0
  9. package/dist/types/packages/markdown/src/mermaid.d.ts +8 -0
  10. package/dist/types/{remark.d.ts → packages/markdown/src/remark.d.ts} +1 -1
  11. package/dist/types/src/dsl/cells.d.ts +91 -0
  12. package/dist/types/src/dsl/channels.d.ts +53 -0
  13. package/dist/types/src/dsl/compile.d.ts +162 -0
  14. package/dist/types/src/dsl/frame.d.ts +38 -0
  15. package/dist/types/src/dsl/lanes.d.ts +23 -0
  16. package/dist/types/src/dsl/legend-notes.d.ts +3 -0
  17. package/dist/types/src/dsl/project.d.ts +39 -0
  18. package/dist/types/src/dsl/syntax.d.ts +317 -0
  19. package/dist/types/src/import/import-core.d.ts +105 -0
  20. package/dist/types/src/import/mermaid-facade.d.ts +120 -0
  21. package/dist/types/src/import/mermaid-importer.d.ts +4 -0
  22. package/dist/types/src/import/mermaid-sequence.d.ts +8 -0
  23. package/dist/types/src/model/appearance.d.ts +209 -0
  24. package/dist/types/src/model/bounds.d.ts +19 -0
  25. package/dist/types/src/model/document.d.ts +24 -0
  26. package/dist/types/src/model/font-faces.d.ts +24 -0
  27. package/dist/types/src/model/fonts.d.ts +47 -0
  28. package/dist/types/src/model/footnote.d.ts +34 -0
  29. package/dist/types/src/model/geometry.d.ts +29 -0
  30. package/dist/types/src/model/graph.d.ts +53 -0
  31. package/dist/types/src/model/heading.d.ts +38 -0
  32. package/dist/types/src/model/icons.d.ts +2 -0
  33. package/dist/types/src/model/labels.d.ts +88 -0
  34. package/dist/types/src/model/link.d.ts +63 -0
  35. package/dist/types/src/model/markers.d.ts +47 -0
  36. package/dist/types/src/model/note.d.ts +75 -0
  37. package/dist/types/src/model/rich-text.d.ts +24 -0
  38. package/dist/types/src/model/routes.d.ts +170 -0
  39. package/dist/types/src/model/status.d.ts +84 -0
  40. package/dist/types/src/model/styles.d.ts +13 -0
  41. package/dist/types/src/model/types.d.ts +277 -0
  42. package/package.json +9 -7
  43. /package/dist/types/{client-validation.d.ts → packages/markdown/src/client-validation.d.ts} +0 -0
  44. /package/dist/types/{client.d.ts → packages/markdown/src/client.d.ts} +0 -0
  45. /package/dist/types/{files.d.ts → packages/markdown/src/files.d.ts} +0 -0
  46. /package/dist/types/{index.d.ts → packages/markdown/src/index.d.ts} +0 -0
  47. /package/dist/types/{markdown-it-helpers.d.ts → packages/markdown/src/markdown-it-helpers.d.ts} +0 -0
  48. /package/dist/types/{markdown-it.d.ts → packages/markdown/src/markdown-it.d.ts} +0 -0
  49. /package/dist/types/{metadata.d.ts → packages/markdown/src/metadata.d.ts} +0 -0
  50. /package/dist/types/{source.d.ts → packages/markdown/src/source.d.ts} +0 -0
@@ -1,155 +1,156 @@
1
- import { m as T, p as S, i as P, a as I, h as F } from "./chunks/core-DPjuIyPG.js";
2
- import { p as j } from "./chunks/metadata-Dx6T_2Zy.js";
3
- function x(t) {
1
+ import { m as I, a as T, p as F, i as j, b as x, h as H } from "./chunks/core-D4HpamVq.js";
2
+ import { p as O } from "./chunks/metadata-Dx6T_2Zy.js";
3
+ function R(t) {
4
4
  return /^draft(?:\s|$)/.test(t.trim());
5
5
  }
6
- function E(t) {
6
+ function M(t) {
7
7
  return t.replace(
8
8
  /[&<>"']/g,
9
- (r) => ({
9
+ (e) => ({
10
10
  "&": "&amp;",
11
11
  "<": "&lt;",
12
12
  ">": "&gt;",
13
13
  '"': "&quot;",
14
14
  "'": "&#39;"
15
- })[r]
15
+ })[e]
16
16
  );
17
17
  }
18
- function H(t) {
19
- const r = `${t.width === void 0 ? "" : ` width="${t.width}"`}${t.height === void 0 ? "" : ` height="${t.height}"`}`;
20
- return `<img src="${E(t.url)}" alt="${E(t.alt)}"${r}>`;
18
+ function _(t) {
19
+ const e = `${t.width === void 0 ? "" : ` width="${t.width}"`}${t.height === void 0 ? "" : ` height="${t.height}"`}`;
20
+ return `<img src="${M(t.url)}" alt="${M(t.alt)}"${e}>`;
21
21
  }
22
- function A(t, r) {
23
- const d = t.type;
24
- if (d === "paragraph") {
25
- const e = t.data?.hProperties ?? {}, l = typeof e.id == "string" ? ` id="${r(e.id)}"` : "", a = t.children.map((o) => A(o, r)).join("");
26
- return `<p${l}>${a}</p>
22
+ function A(t, e) {
23
+ const c = t.type;
24
+ if (c === "paragraph") {
25
+ const r = t.data?.hProperties ?? {}, f = typeof r.id == "string" ? ` id="${e(r.id)}"` : "", o = t.children.map((s) => A(s, e)).join("");
26
+ return `<p${f}>${o}</p>
27
27
  `;
28
28
  }
29
- if (d === "figure") {
30
- const l = t.data?.hProperties?.id, h = typeof l == "string" ? ` id="${r(l)}"` : "", a = t.children;
31
- return `<figure${h}>${a.map((o) => A(o, r)).join("")}</figure>
29
+ if (c === "figure") {
30
+ const f = t.data?.hProperties?.id, h = typeof f == "string" ? ` id="${e(f)}"` : "", o = t.children;
31
+ return `<figure${h}>${o.map((s) => A(s, e)).join("")}</figure>
32
32
  `;
33
33
  }
34
- if (d === "image") {
35
- const e = t.data?.hProperties ?? {};
36
- return H({
34
+ if (c === "image") {
35
+ const r = t.data?.hProperties ?? {};
36
+ return _({
37
37
  url: String(t.url ?? ""),
38
38
  alt: String(t.alt ?? ""),
39
- ...typeof e.width == "number" ? { width: e.width } : {},
40
- ...typeof e.height == "number" ? { height: e.height } : {}
39
+ ...typeof r.width == "number" ? { width: r.width } : {},
40
+ ...typeof r.height == "number" ? { height: r.height } : {}
41
41
  });
42
42
  }
43
- if (d === "figcaption")
44
- return `<figcaption>${t.children.map((l) => A(l, r)).join("")}</figcaption>`;
45
- if (d === "div") {
46
- const e = t.data?.hProperties ?? {};
47
- if (!(e["data-draftably-region"] === "") || typeof e["data-draftably-init"] != "string" || typeof e["data-draftably-policy"] != "string" || typeof e["data-draftably-key"] != "string")
43
+ if (c === "figcaption")
44
+ return `<figcaption>${t.children.map((f) => A(f, e)).join("")}</figcaption>`;
45
+ if (c === "div") {
46
+ const r = t.data?.hProperties ?? {};
47
+ if (!(r["data-draftably-region"] === "") || typeof r["data-draftably-init"] != "string" || typeof r["data-draftably-policy"] != "string" || typeof r["data-draftably-key"] != "string")
48
48
  throw new Error("Invalid generated viewer region.");
49
- const h = typeof e["aria-label"] == "string" ? e["aria-label"] : "Diagram viewer";
50
- return `<div class="draftably-viewer-region" data-draftably-region="" data-draftably-init="${r(String(e["data-draftably-init"]))}" data-draftably-policy="${r(String(e["data-draftably-policy"]))}" data-draftably-key="${r(String(e["data-draftably-key"]))}" role="region" aria-label="${r(h)}"></div>`;
49
+ const h = typeof r["aria-label"] == "string" ? r["aria-label"] : "Diagram viewer";
50
+ return `<div class="draftably-viewer-region" data-draftably-region="" data-draftably-init="${e(String(r["data-draftably-init"]))}" data-draftably-policy="${e(String(r["data-draftably-policy"]))}" data-draftably-key="${e(String(r["data-draftably-key"]))}" role="region" aria-label="${e(h)}"></div>`;
51
51
  }
52
- if (d === "text") return r(String(t.value ?? ""));
53
- throw new Error(`Unsupported generated AST node: ${String(d)}.`);
52
+ if (c === "text") return e(String(t.value ?? ""));
53
+ throw new Error(`Unsupported generated AST node: ${String(c)}.`);
54
54
  }
55
- function _(t) {
55
+ function B(t) {
56
56
  if (!t || typeof t.emitAsset != "function")
57
57
  throw new TypeError("createMarkdownItDraft requires an emitAsset function.");
58
- const r = /* @__PURE__ */ new WeakMap(), d = (a) => a.type === "fence" && x(a.info ?? "");
59
- function e(a) {
60
- const o = a, p = o.renderer.rules.fence;
61
- o.renderer.rules.fence = function(c, u, g, y, b) {
62
- const $ = c[u];
63
- if (!d($))
64
- return p ? p(c, u, g, y, b) : b.renderToken(c, u, g);
65
- const D = r.get($);
66
- if (!D)
58
+ const e = /* @__PURE__ */ new WeakMap(), c = (o) => o.type === "fence" && R(o.info ?? "");
59
+ function r(o) {
60
+ const s = o, l = s.renderer.rules.fence;
61
+ s.renderer.rules.fence = function(d, p, y, g, b) {
62
+ const $ = d[p];
63
+ if (!c($) && !e.has($))
64
+ return l ? l(d, p, y, g, b) : b.renderToken(d, p, y);
65
+ const v = e.get($);
66
+ if (!v)
67
67
  throw new Error(
68
68
  "Draft fence rendered before prepare(). Prepare and render the same token tree."
69
69
  );
70
- return A(D.node, (k) => o.utils.escapeHtml(k));
70
+ return A(v.node, (k) => s.utils.escapeHtml(k));
71
71
  };
72
72
  }
73
- async function l(a, o, p = {}) {
74
- const c = a.parse(o, p), u = await h(c, p);
75
- return { html: a.renderer.render(c, a.options, p), manifest: u };
73
+ async function f(o, s, l = {}) {
74
+ const d = o.parse(s, l), p = await h(d, l);
75
+ return { html: o.renderer.render(d, o.options, l), manifest: p };
76
76
  }
77
- async function h(a, o = {}) {
78
- const p = { path: o.draftably?.documentPath }, c = [], u = /* @__PURE__ */ new Set(), g = /* @__PURE__ */ new Set(), y = [], b = /* @__PURE__ */ new Set(), $ = t.sources && {
77
+ async function h(o, s = {}) {
78
+ const l = { path: s.draftably?.documentPath }, d = [], p = /* @__PURE__ */ new Set(), y = /* @__PURE__ */ new Set(), g = [], b = /* @__PURE__ */ new Set(), $ = t.sources && {
79
79
  ...t.sources,
80
- onDependency: (w) => {
81
- u.add(w.dependencyPath);
80
+ onDependency: (m) => {
81
+ p.add(m.dependencyPath);
82
82
  try {
83
- t.sources?.onDependency?.(w);
84
- } catch (s) {
85
- throw F(s, "Markdown dependency callback failed.");
83
+ t.sources?.onDependency?.(m);
84
+ } catch (a) {
85
+ throw H(a, "Markdown dependency callback failed.");
86
86
  }
87
87
  }
88
88
  };
89
- let D = 0;
90
- const k = async (w) => {
91
- for (const s of w) {
92
- if (d(s)) {
93
- const M = D++, v = { sourceId: p.path, line: (s.map?.[0] ?? 0) + 1 };
94
- r.delete(s);
89
+ let v = 0;
90
+ const k = async (m) => {
91
+ for (const a of m) {
92
+ const D = { sourceId: l.path, line: (a.map?.[0] ?? 0) + 1 }, w = a.type === "fence" && /^mermaid(?:\s|$)/.test((a.info ?? "").trim()) ? await I(a.content ?? "", D, t) : void 0;
93
+ if (g.push(...w?.diagnostics ?? []), w && e.delete(a), c(a) || w?.source) {
94
+ const P = v++;
95
+ e.delete(a);
95
96
  try {
96
97
  let n;
97
98
  try {
98
- n = j(s.info ?? "");
99
- } catch (f) {
100
- const m = f instanceof Error ? f.message : "Invalid draft fence metadata.";
101
- throw Object.assign(new Error(m), {
102
- diagnostic: T("DRAFT_METADATA", m, v)
99
+ n = w ? { alt: w.alt } : O(a.info ?? "");
100
+ } catch (u) {
101
+ const E = u instanceof Error ? u.message : "Invalid draft fence metadata.";
102
+ throw Object.assign(new Error(E), {
103
+ diagnostic: T("DRAFT_METADATA", E, D)
103
104
  });
104
105
  }
105
106
  if (n.id && b.has(n.id)) {
106
- const f = `Duplicate draft id "${n.id}" in this document.`;
107
- throw Object.assign(new Error(f), {
108
- diagnostic: T("DRAFT_METADATA", f, v)
107
+ const u = `Duplicate draft id "${n.id}" in this document.`;
108
+ throw Object.assign(new Error(u), {
109
+ diagnostic: T("DRAFT_METADATA", u, D)
109
110
  });
110
111
  }
111
112
  n.id && b.add(n.id);
112
- const i = await S(s.content ?? "", n, v, p, M, {
113
+ const S = w?.source ?? a.content ?? "", i = await F(S, n, D, l, P, {
113
114
  ...t,
114
115
  sources: $
115
116
  });
116
- r.set(s, { node: i.node, diagnostics: i.diagnostics }), i.asset && c.push(i.asset), c.push(...i.extraAssets ?? []), i.dependency && u.add(i.dependency), i.clientModule && g.add(i.clientModule), y.push(...i.diagnostics);
117
+ e.set(a, { node: i.node, diagnostics: i.diagnostics }), i.asset && d.push(i.asset), d.push(...i.extraAssets ?? []), i.dependency && p.add(i.dependency), i.clientModule && y.add(i.clientModule), g.push(...i.diagnostics);
117
118
  } catch (n) {
118
- if (P(n)) throw n.cause ?? n;
119
- if (I(n)) throw n;
120
- const i = n.diagnostic, f = n.diagnostics, m = i ?? f?.[0] ?? T(
119
+ if (j(n)) throw n.cause ?? n;
120
+ if (x(n)) throw n;
121
+ const S = n.diagnostic, i = n.diagnostics, u = S ?? i?.[0] ?? T(
121
122
  "DRAFT_BUILD",
122
123
  n instanceof Error ? n.message : "Could not prepare diagram.",
123
- v
124
+ D
124
125
  );
125
- if (y.push(...f ?? [m]), (t.errors ?? "fail") === "fail")
126
+ if (g.push(...i ?? [u]), (t.errors ?? "fail") === "fail")
126
127
  throw Object.assign(new Error("Draftably Markdown preparation failed."), {
127
- diagnostics: f ?? [m]
128
+ diagnostics: i ?? [u]
128
129
  });
129
- r.set(s, {
130
+ e.set(a, {
130
131
  node: {
131
132
  type: "paragraph",
132
133
  children: [{ type: "text", value: "Diagram unavailable." }]
133
134
  },
134
- diagnostics: f ?? [m]
135
+ diagnostics: i ?? [u]
135
136
  });
136
137
  }
137
138
  }
138
- s.children?.length && await k(s.children);
139
+ a.children?.length && await k(a.children);
139
140
  }
140
141
  };
141
- await k(a);
142
- for (const w of y) t.onDiagnostic?.(w);
142
+ await k(o);
143
+ for (const m of g) t.onDiagnostic?.(m);
143
144
  return {
144
145
  version: 1,
145
- assets: c,
146
- clientModules: [...g],
147
- dependencies: [...u],
148
- diagnostics: y
146
+ assets: d,
147
+ clientModules: [...y],
148
+ dependencies: [...p],
149
+ diagnostics: g
149
150
  };
150
151
  }
151
- return { plugin: e, prepare: h, render: l };
152
+ return { plugin: r, prepare: h, render: f };
152
153
  }
153
154
  export {
154
- _ as createMarkdownItDraft
155
+ B as createMarkdownItDraft
155
156
  };
@@ -0,0 +1,93 @@
1
+ import { isMainThread as y, workerData as b, parentPort as g, Worker as v } from "node:worker_threads";
2
+ const k = /^(?:flowchart|graph|sequenceDiagram)\b/;
3
+ function D(i) {
4
+ const s = i.replace(/^\uFEFF/, "").split(`
5
+ `);
6
+ let e = 0;
7
+ if (s[0]?.trim() === "---" && (e = s.findIndex((t, r) => r > 0 && t.trim() === "---") + 1, e === 0))
8
+ return !1;
9
+ for (; e < s.length; e++) {
10
+ const t = s[e].trim();
11
+ if (!(!t || t.startsWith("%%")))
12
+ return k.test(t);
13
+ }
14
+ return !1;
15
+ }
16
+ let f, F = 0;
17
+ const n = /* @__PURE__ */ new Map();
18
+ function T() {
19
+ const i = new v(new URL(import.meta.url), {
20
+ workerData: { kind: "draftably-mermaid" },
21
+ resourceLimits: { maxOldGenerationSizeMb: 512, stackSizeMb: 4 }
22
+ });
23
+ i.unref();
24
+ const s = (e) => {
25
+ f = void 0;
26
+ for (const [t, r] of n) r({ id: t, messages: [e] });
27
+ n.clear();
28
+ };
29
+ return i.on("message", (e) => {
30
+ n.get(e.id)?.(e), n.delete(e.id);
31
+ }), i.on("error", (e) => s(`Mermaid parser failed: ${e.message}`)), i.on("exit", (e) => s(`Mermaid parser stopped with status ${e}.`)), i;
32
+ }
33
+ async function I(i, s) {
34
+ if (!D(i)) return { source: null, diagnostics: [] };
35
+ f ??= T();
36
+ const e = F++, t = f, r = await new Promise((o) => {
37
+ const d = setTimeout(() => {
38
+ n.delete(e), t.terminate(), o({ id: e, messages: ["Mermaid parsing timed out."] });
39
+ }, 3e4);
40
+ n.set(e, (c) => {
41
+ clearTimeout(d), o(c);
42
+ }), t.ref(), t.postMessage({ id: e, text: i });
43
+ }).finally(() => {
44
+ n.size || t.unref();
45
+ });
46
+ return {
47
+ source: r.source ?? null,
48
+ alt: r.alt,
49
+ diagnostics: r.source ? [] : [
50
+ {
51
+ code: "DRAFT_MERMAID",
52
+ severity: "warning",
53
+ message: `Left this Mermaid fence to Mermaid: ${r.messages.join(" ") || "it could not be converted."}`,
54
+ location: s,
55
+ itemIds: []
56
+ }
57
+ ]
58
+ };
59
+ }
60
+ async function S() {
61
+ globalThis.fetch = async () => {
62
+ throw Error("Mermaid resource loading is disabled.");
63
+ };
64
+ const { JSDOM: i } = await import("jsdom"), { createMermaidFlowParser: s, makePlainLabel: e } = await import("./chunks/mermaid-facade-BoLWBerE.js"), { importMermaidFlow: t } = await import("./chunks/mermaid-importer-IVovOQE9.js"), r = new i("<!doctype html><html><body></body></html>", {
65
+ url: "https://import.invalid/"
66
+ });
67
+ Object.assign(globalThis, {
68
+ window: r.window,
69
+ document: r.window.document,
70
+ Option: r.window.Option
71
+ });
72
+ const o = s(async () => (await import("mermaid")).default), d = e(r.window.document);
73
+ g.on("message", async ({ id: c, text: h }) => {
74
+ let m;
75
+ try {
76
+ const a = await o(h), l = a.ok ? a.snapshot : void 0, p = l?.family === "sequence" ? l.title ?? "" : "", M = p || (l?.family === "sequence" ? "Sequence diagram" : "Flowchart"), w = t(a, d, p);
77
+ m = {
78
+ id: c,
79
+ source: w.nativeSource,
80
+ alt: M,
81
+ messages: w.diagnostics.filter((u) => u.severity === "error").map((u) => u.message)
82
+ };
83
+ } catch (a) {
84
+ m = { id: c, messages: [a instanceof Error ? a.message : String(a)] };
85
+ }
86
+ g.postMessage(m);
87
+ });
88
+ }
89
+ !y && b?.kind === "draftably-mermaid" && S();
90
+ export {
91
+ I as convertMermaid,
92
+ D as isMermaidCandidate
93
+ };
package/dist/remark.js CHANGED
@@ -1,86 +1,86 @@
1
- import { m as h, p as b, i as k, a as v, h as F } from "./chunks/core-DPjuIyPG.js";
2
- import { p as x } from "./chunks/metadata-Dx6T_2Zy.js";
3
- function j(s) {
1
+ import { m as T, a as g, p as k, i as F, b as x, h as O } from "./chunks/core-D4HpamVq.js";
2
+ import { p as I } from "./chunks/metadata-Dx6T_2Zy.js";
3
+ function R(s) {
4
4
  if (!s || typeof s.emitAsset != "function")
5
5
  throw new TypeError("remarkDraft requires an emitAsset function.");
6
- return async (D, d) => {
7
- const A = { path: d.path }, u = [], m = /* @__PURE__ */ new Set(), p = /* @__PURE__ */ new Set(), E = s.sources && {
6
+ return async (A, f) => {
7
+ const b = { path: f.path }, m = [], w = /* @__PURE__ */ new Set(), p = /* @__PURE__ */ new Set(), v = s.sources && {
8
8
  ...s.sources,
9
9
  onDependency: (i) => {
10
10
  p.add(i.dependencyPath);
11
11
  try {
12
12
  s.sources?.onDependency?.(i);
13
13
  } catch (r) {
14
- throw F(r, "Markdown dependency callback failed.");
14
+ throw O(r, "Markdown dependency callback failed.");
15
15
  }
16
16
  }
17
- }, l = [], g = /* @__PURE__ */ new Set();
18
- let M = 0;
19
- async function w(i) {
17
+ }, o = [], y = /* @__PURE__ */ new Set();
18
+ let E = 0;
19
+ async function D(i) {
20
20
  const r = i.children;
21
21
  if (r)
22
- for (let o = 0; o < r.length; o++) {
23
- const n = r[o];
24
- if (n.type === "code" && n.lang === "draft") {
25
- const T = M++, f = {
26
- sourceId: d.path,
27
- line: n.position?.start?.line ?? 1,
28
- column: n.position?.start?.column
29
- };
22
+ for (let c = 0; c < r.length; c++) {
23
+ const t = r[c], d = {
24
+ sourceId: f.path,
25
+ line: t.position?.start?.line ?? 1,
26
+ column: t.position?.start?.column
27
+ }, l = t.type === "code" && t.lang === "mermaid" ? await T(t.value ?? "", d, s) : void 0;
28
+ if (o.push(...l?.diagnostics ?? []), t.type === "code" && t.lang === "draft" || l?.source) {
29
+ const M = E++;
30
30
  try {
31
31
  let e;
32
32
  try {
33
- e = x(n.meta ? `draft ${n.meta}` : "draft");
34
- } catch (a) {
35
- const c = a instanceof Error ? a.message : "Invalid draft fence metadata.";
36
- throw Object.assign(new Error(c), {
37
- diagnostic: h("DRAFT_METADATA", c, f)
33
+ e = l ? { alt: l.alt } : I(t.meta ? `draft ${t.meta}` : "draft");
34
+ } catch (n) {
35
+ const u = n instanceof Error ? n.message : "Invalid draft fence metadata.";
36
+ throw Object.assign(new Error(u), {
37
+ diagnostic: g("DRAFT_METADATA", u, d)
38
38
  });
39
39
  }
40
- if (e.id && g.has(e.id)) {
41
- const a = `Duplicate draft id "${e.id}" in this document.`;
42
- throw Object.assign(new Error(a), {
43
- diagnostic: h("DRAFT_METADATA", a, f)
40
+ if (e.id && y.has(e.id)) {
41
+ const n = `Duplicate draft id "${e.id}" in this document.`;
42
+ throw Object.assign(new Error(n), {
43
+ diagnostic: g("DRAFT_METADATA", n, d)
44
44
  });
45
45
  }
46
- e.id && g.add(e.id);
47
- const t = await b(n.value ?? "", e, f, A, T, {
46
+ e.id && y.add(e.id);
47
+ const h = l?.source ?? t.value ?? "", a = await k(h, e, d, b, M, {
48
48
  ...s,
49
- sources: E
49
+ sources: v
50
50
  });
51
- r.splice(o, 1, t.node), t.asset && u.push(t.asset), u.push(...t.extraAssets ?? []), t.clientModule && m.add(t.clientModule), t.dependency && p.add(t.dependency), l.push(...t.diagnostics);
51
+ r.splice(c, 1, a.node), a.asset && m.push(a.asset), m.push(...a.extraAssets ?? []), a.clientModule && w.add(a.clientModule), a.dependency && p.add(a.dependency), o.push(...a.diagnostics);
52
52
  } catch (e) {
53
- if (k(e)) throw e.cause ?? e;
54
- if (v(e)) throw e;
55
- const t = e.diagnostic, a = e.diagnostics, c = t ?? a?.[0] ?? h(
53
+ if (F(e)) throw e.cause ?? e;
54
+ if (x(e)) throw e;
55
+ const h = e.diagnostic, a = e.diagnostics, n = h ?? a?.[0] ?? g(
56
56
  "DRAFT_BUILD",
57
57
  e instanceof Error ? e.message : "Could not prepare diagram.",
58
- f
58
+ d
59
59
  );
60
- if (l.push(...a ?? [c]), (s.errors ?? "fail") === "fail") {
61
- const y = new Error("Draftably Markdown transform failed.");
62
- throw Object.assign(y, { diagnostics: a ?? [c] }), y;
60
+ if (o.push(...a ?? [n]), (s.errors ?? "fail") === "fail") {
61
+ const u = new Error("Draftably Markdown transform failed.");
62
+ throw Object.assign(u, { diagnostics: a ?? [n] }), u;
63
63
  }
64
- r.splice(o, 1, {
64
+ r.splice(c, 1, {
65
65
  type: "paragraph",
66
66
  children: [{ type: "text", value: "Diagram unavailable." }]
67
67
  });
68
68
  }
69
69
  } else
70
- await w(n);
70
+ await D(t);
71
71
  }
72
72
  }
73
- await w(D);
74
- for (const i of l) s.onDiagnostic?.(i);
75
- d.data ??= {}, d.data.draftably = {
73
+ await D(A);
74
+ for (const i of o) s.onDiagnostic?.(i);
75
+ f.data ??= {}, f.data.draftably = {
76
76
  version: 1,
77
- assets: u,
78
- clientModules: [...m],
77
+ assets: m,
78
+ clientModules: [...w],
79
79
  dependencies: [...p],
80
- diagnostics: l
80
+ diagnostics: o
81
81
  };
82
82
  };
83
83
  }
84
84
  export {
85
- j as default
85
+ R as default
86
86
  };
@@ -37,6 +37,11 @@ export type EmitAsset = (asset: DraftAsset, context: {
37
37
  export interface DraftMarkdownOptions {
38
38
  emitAsset: EmitAsset;
39
39
  errors?: 'fail' | 'placeholder';
40
+ /**
41
+ * `convert` draws ```mermaid fences that hold a flowchart or sequence as Draftably images and
42
+ * leaves every other Mermaid family as a code block. `off` (default) leaves all of them.
43
+ */
44
+ mermaid?: 'convert' | 'off';
40
45
  interactive?: MarkdownInteractiveBridge;
41
46
  render?: {
42
47
  includeSource?: boolean;
@@ -84,6 +89,12 @@ export interface MarkdownInteractiveBridge {
84
89
  url: string;
85
90
  }>;
86
91
  }
92
+ /** Native source for a Mermaid fence, or null when the fence stays as code. */
93
+ export declare function mermaidSource(text: string, location: Diagnostic['location'], options: DraftMarkdownOptions): Promise<{
94
+ source: string | null;
95
+ alt?: string;
96
+ diagnostics: Diagnostic[];
97
+ }>;
87
98
  export declare function makeDiagnostic(code: string, message: string, location?: Diagnostic['location'], related?: Diagnostic['related']): Diagnostic;
88
99
  export declare function contentHash(value: string | Uint8Array): string;
89
100
  export declare function hostFailure(error: unknown, message?: string): Error;
@@ -0,0 +1,8 @@
1
+ import type { Diagnostic } from '@draftably/runtime';
2
+ export declare function isMermaidCandidate(text: string): boolean;
3
+ /** Native source for a Mermaid flowchart or sequence, or null to leave the fence to Mermaid. */
4
+ export declare function convertMermaid(text: string, location: Diagnostic['location']): Promise<{
5
+ source: string | null;
6
+ alt?: string;
7
+ diagnostics: Diagnostic[];
8
+ }>;
@@ -16,6 +16,6 @@ interface FileLike {
16
16
  path?: string;
17
17
  data?: Record<string, unknown>;
18
18
  }
19
- /** Convert only parser-recognized `draft` code nodes into static image nodes. */
19
+ /** Convert parser-recognized `draft` code nodes, and opted-in Mermaid ones, into static image nodes. */
20
20
  export default function remarkDraft(options: DraftMarkdownOptions): (tree: Node, file: FileLike) => Promise<void>;
21
21
  export {};
@@ -0,0 +1,91 @@
1
+ import type { ResolvedAppearance } from '../model/appearance';
2
+ /** Width of a marker's bar, centred on the seam it marks. */
3
+ export declare const MARKER_WIDTH = 8;
4
+ /** How far a marker's bar runs past the cells, so a line meets it clear of their corners. */
5
+ export declare const MARKER_TAIL = 16;
6
+ /** Height of a cells group's title band for a title type of this line height. */
7
+ export declare const cellsBandFor: (lineHeight: number) => number;
8
+ export interface CellInput {
9
+ id: string;
10
+ label: string;
11
+ marker: boolean;
12
+ /** Columns the cell covers in a grid. */
13
+ span?: number;
14
+ /** From a `size` line. */
15
+ size?: {
16
+ width: number;
17
+ height?: number;
18
+ };
19
+ }
20
+ export interface CellBox {
21
+ x: number;
22
+ y: number;
23
+ w: number;
24
+ h: number;
25
+ }
26
+ /** A cell's own size: one line of title when it fits in `MAX_CELL`, wrapped when it does not. */
27
+ export declare function cellSize(c: CellInput, look: ResolvedAppearance): {
28
+ w: number;
29
+ h: number;
30
+ };
31
+ /**
32
+ * Cells edge to edge, in rows of `columns` columns filled in order; a cell's `span` covers that
33
+ * many columns, and a cell that does not fit the rest of a row starts the next one. Without
34
+ * `columns`, the cells form one row (`right`) or one column (`down`). Each column is as wide as
35
+ * its widest single cell, widened at its last column for a wider spanning cell, and each row is
36
+ * as tall as its tallest cell. Cells narrower than `minWidth` in all, the title band's width,
37
+ * widen the last column.
38
+ *
39
+ * A marker takes no room: in one row or column, its bar sits on the seam before the next cell
40
+ * and spans the band above as well, so it cuts the whole object, and runs a short tail past the
41
+ * cells where lines meet it.
42
+ */
43
+ export declare function layoutCells(cells: CellInput[], shape: {
44
+ direction: 'right' | 'down';
45
+ columns?: number;
46
+ }, look: ResolvedAppearance, minWidth?: number): {
47
+ boxes: Map<string, CellBox>;
48
+ w: number;
49
+ h: number;
50
+ };
51
+ /** Width of one unit of a byte or bit layout, and the units in each row, unless the file says. */
52
+ export declare const UNIT_WIDTH: {
53
+ readonly bit: 24;
54
+ readonly byte: 48;
55
+ };
56
+ export declare const UNIT_COLUMNS: {
57
+ readonly bit: 32;
58
+ readonly byte: 16;
59
+ };
60
+ export interface UnitCells {
61
+ /** Each field's main box: the longest piece, which holds its title. */
62
+ boxes: Map<string, CellBox>;
63
+ /** The other pieces of a field that runs on past a row's end. */
64
+ pieces: Map<string, CellBox[]>;
65
+ /** Fields of variable length, drawn with broken ends. */
66
+ open: string[];
67
+ /** Unit numbers above the first row: their centres, and the room they take above the cells. */
68
+ ruler?: {
69
+ h: number;
70
+ ticks: Array<{
71
+ x: number;
72
+ label: string;
73
+ }>;
74
+ };
75
+ w: number;
76
+ h: number;
77
+ }
78
+ /**
79
+ * A byte or bit layout: every unit has one width, so a field's width is its size. Rows hold
80
+ * `columns` units. A field longer than the rest of its row runs on into the next rows; a field of
81
+ * variable length (`span: 'var'`) fills the rest of its row, or a whole row, with broken ends.
82
+ * Every row has the height of the tallest title.
83
+ */
84
+ export declare function layoutUnits(cells: Array<CellInput & {
85
+ open?: boolean;
86
+ }>, shape: {
87
+ unit: 'bit' | 'byte';
88
+ columns?: number;
89
+ unitWidth?: number;
90
+ ruler: boolean;
91
+ }, look: ResolvedAppearance): UnitCells;