vantage-md 0.1.7 → 0.5.4
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.
- package/README.md +24 -9
- package/dist/index.cjs +862 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +440 -14
- package/dist/index.d.ts +440 -14
- package/dist/index.js +840 -47
- package/dist/index.js.map +1 -1
- package/dist/prose.css +2 -1
- package/dist/react.cjs +1063 -117
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +260 -14
- package/dist/react.d.ts +260 -14
- package/dist/react.js +1056 -118
- package/dist/react.js.map +1 -1
- package/dist/styles.css +240 -0
- package/package.json +18 -8
package/dist/react.cjs
CHANGED
|
@@ -53,25 +53,503 @@ var BLOCK_TAGS = /* @__PURE__ */ new Set([
|
|
|
53
53
|
"hr",
|
|
54
54
|
"div"
|
|
55
55
|
]);
|
|
56
|
-
function visit(node) {
|
|
56
|
+
function visit(node, offset) {
|
|
57
57
|
if ("children" in node) {
|
|
58
58
|
for (const child of node.children) {
|
|
59
59
|
if (child.type === "element") {
|
|
60
60
|
if (BLOCK_TAGS.has(child.tagName) && child.position?.start?.line) {
|
|
61
61
|
child.properties = child.properties || {};
|
|
62
|
-
child.properties["dataSourceLine"] = child.position.start.line;
|
|
62
|
+
child.properties["dataSourceLine"] = child.position.start.line + offset;
|
|
63
63
|
}
|
|
64
|
-
visit(child);
|
|
64
|
+
visit(child, offset);
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
var rehypeSourceLines = () => {
|
|
69
|
+
var rehypeSourceLines = (options) => {
|
|
70
|
+
const offset = options?.offset ?? 0;
|
|
70
71
|
return (tree) => {
|
|
71
|
-
visit(tree);
|
|
72
|
+
visit(tree, offset);
|
|
72
73
|
};
|
|
73
74
|
};
|
|
74
75
|
var rehypeSourceLines_default = rehypeSourceLines;
|
|
76
|
+
|
|
77
|
+
// src/vantageDirectives.ts
|
|
78
|
+
var VANTAGE_TONES = [
|
|
79
|
+
"note",
|
|
80
|
+
"tip",
|
|
81
|
+
"important",
|
|
82
|
+
"warning",
|
|
83
|
+
"caution",
|
|
84
|
+
"muted"
|
|
85
|
+
];
|
|
86
|
+
var VANTAGE_EMPHASIS = ["strong", "normal", "quiet"];
|
|
87
|
+
var VANTAGE_BADGES = [
|
|
88
|
+
"draft",
|
|
89
|
+
"stale",
|
|
90
|
+
"blocked",
|
|
91
|
+
"done",
|
|
92
|
+
"wip"
|
|
93
|
+
];
|
|
94
|
+
var VANTAGE_COLLAPSED = ["true", "false"];
|
|
95
|
+
var VANTAGE_RUNS = ["start", "middle", "end", "only"];
|
|
96
|
+
var VANTAGE_STYLE_TARGETS = [
|
|
97
|
+
"p",
|
|
98
|
+
"h1",
|
|
99
|
+
"h2",
|
|
100
|
+
"h3",
|
|
101
|
+
"h4",
|
|
102
|
+
"h5",
|
|
103
|
+
"h6",
|
|
104
|
+
"li",
|
|
105
|
+
"blockquote",
|
|
106
|
+
"pre",
|
|
107
|
+
"table",
|
|
108
|
+
"tr",
|
|
109
|
+
"ul",
|
|
110
|
+
"ol",
|
|
111
|
+
"hr",
|
|
112
|
+
"div"
|
|
113
|
+
];
|
|
114
|
+
var VANTAGE_ANCHOR_TARGETS = [
|
|
115
|
+
"p",
|
|
116
|
+
"h1",
|
|
117
|
+
"h2",
|
|
118
|
+
"h3",
|
|
119
|
+
"h4",
|
|
120
|
+
"h5",
|
|
121
|
+
"h6",
|
|
122
|
+
"li",
|
|
123
|
+
"blockquote",
|
|
124
|
+
"pre",
|
|
125
|
+
"table"
|
|
126
|
+
];
|
|
127
|
+
var STYLE_KEYS = {
|
|
128
|
+
tone: VANTAGE_TONES,
|
|
129
|
+
emphasis: VANTAGE_EMPHASIS,
|
|
130
|
+
badge: VANTAGE_BADGES,
|
|
131
|
+
collapsed: VANTAGE_COLLAPSED
|
|
132
|
+
};
|
|
133
|
+
var DIRECTIVE_VOCABULARY = {
|
|
134
|
+
section: STYLE_KEYS,
|
|
135
|
+
block: STYLE_KEYS,
|
|
136
|
+
oq: { id: null, leaning: null }
|
|
137
|
+
};
|
|
138
|
+
var WS = /[ \t\r\n]*/y;
|
|
139
|
+
var SENTINEL_PREFIX = /^[ \t\r\n]*vantage:/;
|
|
140
|
+
var NAME = /[a-z][a-z0-9-]*/y;
|
|
141
|
+
var UNQUOTED = /[A-Za-z0-9_.:#-]+/y;
|
|
142
|
+
var QUOTED = /"[^"]*"/y;
|
|
143
|
+
function token(comment, offset) {
|
|
144
|
+
const rest = comment.slice(offset);
|
|
145
|
+
const end = rest.search(/[ \t\r\n]/);
|
|
146
|
+
const word = end === -1 ? rest : rest.slice(0, end);
|
|
147
|
+
return word.length > 24 ? `${word.slice(0, 24)}\u2026` : word;
|
|
148
|
+
}
|
|
149
|
+
function matchAt(pattern, comment, offset) {
|
|
150
|
+
pattern.lastIndex = offset;
|
|
151
|
+
const match = pattern.exec(comment);
|
|
152
|
+
return match === null ? null : match[0];
|
|
153
|
+
}
|
|
154
|
+
function skipWhitespace(comment, offset) {
|
|
155
|
+
return matchAt(WS, comment, offset)?.length ?? 0;
|
|
156
|
+
}
|
|
157
|
+
function malformed(reason, offset) {
|
|
158
|
+
return { kind: "malformed", reason, offset };
|
|
159
|
+
}
|
|
160
|
+
function parseVantageDirective(comment) {
|
|
161
|
+
const sentinel = SENTINEL_PREFIX.exec(comment);
|
|
162
|
+
if (sentinel === null) return null;
|
|
163
|
+
let at = sentinel[0].length;
|
|
164
|
+
at += skipWhitespace(comment, at);
|
|
165
|
+
const nameOffset = at;
|
|
166
|
+
const name = matchAt(NAME, comment, at);
|
|
167
|
+
if (name === null) {
|
|
168
|
+
return malformed("no directive name after `vantage:`", at);
|
|
169
|
+
}
|
|
170
|
+
at += name.length;
|
|
171
|
+
const pairs = [];
|
|
172
|
+
while (at < comment.length) {
|
|
173
|
+
const gap = skipWhitespace(comment, at);
|
|
174
|
+
at += gap;
|
|
175
|
+
if (at >= comment.length) break;
|
|
176
|
+
if (gap === 0) {
|
|
177
|
+
return malformed(`\`${token(comment, at)}\` needs a space before it`, at);
|
|
178
|
+
}
|
|
179
|
+
const keyOffset = at;
|
|
180
|
+
const key = matchAt(NAME, comment, at);
|
|
181
|
+
if (key === null) {
|
|
182
|
+
return malformed(
|
|
183
|
+
`\`${token(comment, at)}\` is not a \`key=value\` pair`,
|
|
184
|
+
at
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
at += key.length;
|
|
188
|
+
if (comment[at] !== "=") {
|
|
189
|
+
return malformed(`\`${key}\` is not followed by \`=value\``, at);
|
|
190
|
+
}
|
|
191
|
+
at += 1;
|
|
192
|
+
const valueOffset = at;
|
|
193
|
+
const quoted = matchAt(QUOTED, comment, at);
|
|
194
|
+
if (quoted !== null) {
|
|
195
|
+
at += quoted.length;
|
|
196
|
+
pairs.push({
|
|
197
|
+
key,
|
|
198
|
+
value: quoted.slice(1, -1),
|
|
199
|
+
keyOffset,
|
|
200
|
+
valueOffset,
|
|
201
|
+
quoted: true
|
|
202
|
+
});
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const unquoted = matchAt(UNQUOTED, comment, at);
|
|
206
|
+
if (unquoted === null) {
|
|
207
|
+
const found = token(comment, at);
|
|
208
|
+
return malformed(
|
|
209
|
+
found === "" ? `\`${key}=\` has no value` : `\`${found}\` is not a valid value for \`${key}\``,
|
|
210
|
+
at
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
at += unquoted.length;
|
|
214
|
+
pairs.push({ key, value: unquoted, keyOffset, valueOffset, quoted: false });
|
|
215
|
+
}
|
|
216
|
+
return { kind: "directive", name, nameOffset, pairs };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// src/rehypeVantageDirectives.ts
|
|
220
|
+
var STYLE_TARGET_TAGS = new Set(VANTAGE_STYLE_TARGETS);
|
|
221
|
+
var ANCHOR_TARGET_TAGS = new Set(VANTAGE_ANCHOR_TARGETS);
|
|
222
|
+
var HEADING_DEPTHS = /* @__PURE__ */ new Map([
|
|
223
|
+
["h1", 1],
|
|
224
|
+
["h2", 2],
|
|
225
|
+
["h3", 3],
|
|
226
|
+
["h4", 4],
|
|
227
|
+
["h5", 5],
|
|
228
|
+
["h6", 6]
|
|
229
|
+
]);
|
|
230
|
+
var RANGE_PROPERTIES = /* @__PURE__ */ new Map([
|
|
231
|
+
["tone", "dataVantageTone"],
|
|
232
|
+
["emphasis", "dataVantageEmphasis"]
|
|
233
|
+
]);
|
|
234
|
+
var POINT_PROPERTIES = /* @__PURE__ */ new Map([["badge", "dataVantageBadge"]]);
|
|
235
|
+
var RUN_PROPERTY = "dataVantageRun";
|
|
236
|
+
var OQ_PROPERTY = "dataVantageOq";
|
|
237
|
+
var LEANING_PROPERTY = "dataVantageLeaning";
|
|
238
|
+
var COLLAPSED_PROPERTY = "dataVantageCollapsed";
|
|
239
|
+
var COLLAPSE_GROUP_PROPERTY = "dataVantageCollapseGroup";
|
|
240
|
+
var COLLAPSE_TOGGLE_PROPERTY = "dataVantageCollapseToggle";
|
|
241
|
+
var MAX_LEANING = 500;
|
|
242
|
+
function isSkippable(node) {
|
|
243
|
+
if (node.type === "comment" || node.type === "doctype") return true;
|
|
244
|
+
if (node.type === "text") return node.value.trim() === "";
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
function headingDepth(node) {
|
|
248
|
+
if (node.type !== "element") return void 0;
|
|
249
|
+
return HEADING_DEPTHS.get(node.tagName);
|
|
250
|
+
}
|
|
251
|
+
function setProperty(element, property, value) {
|
|
252
|
+
element.properties = element.properties ?? {};
|
|
253
|
+
element.properties[property] = value;
|
|
254
|
+
}
|
|
255
|
+
function runValue(index, length) {
|
|
256
|
+
if (length === 1) return "only";
|
|
257
|
+
if (index === 0) return "start";
|
|
258
|
+
return index === length - 1 ? "end" : "middle";
|
|
259
|
+
}
|
|
260
|
+
function vocabularyOf(name, key) {
|
|
261
|
+
return DIRECTIVE_VOCABULARY[name]?.[key];
|
|
262
|
+
}
|
|
263
|
+
function accepts(name, key, value) {
|
|
264
|
+
const values = vocabularyOf(name, key);
|
|
265
|
+
if (values === void 0) return false;
|
|
266
|
+
return values === null || values.includes(value);
|
|
267
|
+
}
|
|
268
|
+
function styleRange(children, targetIndex, name) {
|
|
269
|
+
const range = [targetIndex];
|
|
270
|
+
const depth = name === "section" ? headingDepth(children[targetIndex]) : void 0;
|
|
271
|
+
if (depth === void 0) return range;
|
|
272
|
+
for (let i = targetIndex + 1; i < children.length; i++) {
|
|
273
|
+
const node = children[i];
|
|
274
|
+
const nodeDepth = headingDepth(node);
|
|
275
|
+
if (nodeDepth !== void 0 && nodeDepth <= depth) break;
|
|
276
|
+
if (node.type === "element" && STYLE_TARGET_TAGS.has(node.tagName)) {
|
|
277
|
+
range.push(i);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return range;
|
|
281
|
+
}
|
|
282
|
+
function collapsesSection(name, pairs, target) {
|
|
283
|
+
if (name !== "section") return false;
|
|
284
|
+
if (pairs.get("collapsed") !== "true") return false;
|
|
285
|
+
return headingDepth(target) !== void 0;
|
|
286
|
+
}
|
|
287
|
+
function stampStyle(children, targetIndex, name, pairs, state) {
|
|
288
|
+
const target = children[targetIndex];
|
|
289
|
+
if (!STYLE_TARGET_TAGS.has(target.tagName)) return;
|
|
290
|
+
const rangeStamps = [];
|
|
291
|
+
const targetStamps = [];
|
|
292
|
+
for (const [key, value] of pairs) {
|
|
293
|
+
if (!accepts(name, key, value)) continue;
|
|
294
|
+
const rangeProperty = RANGE_PROPERTIES.get(key);
|
|
295
|
+
if (rangeProperty !== void 0) {
|
|
296
|
+
rangeStamps.push([rangeProperty, value]);
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
const pointProperty = POINT_PROPERTIES.get(key);
|
|
300
|
+
if (pointProperty !== void 0) targetStamps.push([pointProperty, value]);
|
|
301
|
+
}
|
|
302
|
+
const collapses = collapsesSection(name, pairs, target);
|
|
303
|
+
if (rangeStamps.length === 0 && targetStamps.length === 0 && !collapses) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const range = styleRange(children, targetIndex, name);
|
|
307
|
+
const group = collapses && range.length > 1 ? String(state.nextGroup++) : void 0;
|
|
308
|
+
for (let i = 0; i < range.length; i++) {
|
|
309
|
+
const element = children[range[i]];
|
|
310
|
+
for (const [property, value] of rangeStamps) {
|
|
311
|
+
setProperty(element, property, value);
|
|
312
|
+
}
|
|
313
|
+
if (i === 0) {
|
|
314
|
+
for (const [property, value] of targetStamps) {
|
|
315
|
+
setProperty(element, property, value);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (rangeStamps.length > 0) {
|
|
319
|
+
setProperty(element, RUN_PROPERTY, runValue(i, range.length));
|
|
320
|
+
}
|
|
321
|
+
if (group === void 0) continue;
|
|
322
|
+
if (i === 0) {
|
|
323
|
+
setProperty(element, COLLAPSE_TOGGLE_PROPERTY, group);
|
|
324
|
+
} else {
|
|
325
|
+
setProperty(element, COLLAPSED_PROPERTY, "true");
|
|
326
|
+
setProperty(element, COLLAPSE_GROUP_PROPERTY, group);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
function stampOq(target, pairs) {
|
|
331
|
+
setProperty(target, OQ_PROPERTY, "true");
|
|
332
|
+
const leaning = pairs.get("leaning");
|
|
333
|
+
if (leaning === void 0) return;
|
|
334
|
+
const text = leaning.replace(/\s+/g, " ").trim().slice(0, MAX_LEANING);
|
|
335
|
+
if (text !== "") setProperty(target, LEANING_PROPERTY, text);
|
|
336
|
+
}
|
|
337
|
+
function stampRun(children, targetIndex, run, state) {
|
|
338
|
+
const target = children[targetIndex];
|
|
339
|
+
const style = /* @__PURE__ */ new Map();
|
|
340
|
+
const oq = /* @__PURE__ */ new Map();
|
|
341
|
+
let styleName;
|
|
342
|
+
let hasOq = false;
|
|
343
|
+
for (const directive of run) {
|
|
344
|
+
if (directive.name === "section" || directive.name === "block") {
|
|
345
|
+
styleName = directive.name;
|
|
346
|
+
for (const pair of directive.pairs) style.set(pair.key, pair.value);
|
|
347
|
+
} else if (directive.name === "oq") {
|
|
348
|
+
hasOq = true;
|
|
349
|
+
for (const pair of directive.pairs) oq.set(pair.key, pair.value);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (styleName !== void 0) {
|
|
353
|
+
stampStyle(children, targetIndex, styleName, style, state);
|
|
354
|
+
}
|
|
355
|
+
if (hasOq && ANCHOR_TARGET_TAGS.has(target.tagName)) {
|
|
356
|
+
stampOq(target, oq);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
function directiveOf(node) {
|
|
360
|
+
if (node.type !== "comment") return void 0;
|
|
361
|
+
const parsed = parseVantageDirective(node.value);
|
|
362
|
+
return parsed !== null && parsed.kind === "directive" ? parsed : void 0;
|
|
363
|
+
}
|
|
364
|
+
function processChildren(parent, state) {
|
|
365
|
+
const children = parent.children;
|
|
366
|
+
let i = 0;
|
|
367
|
+
while (i < children.length) {
|
|
368
|
+
const node = children[i];
|
|
369
|
+
if (node.type === "element") {
|
|
370
|
+
processChildren(node, state);
|
|
371
|
+
i++;
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
const first = directiveOf(node);
|
|
375
|
+
if (first === void 0) {
|
|
376
|
+
i++;
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
const run = [first];
|
|
380
|
+
let j = i + 1;
|
|
381
|
+
let targetIndex = -1;
|
|
382
|
+
for (; j < children.length; j++) {
|
|
383
|
+
const next = children[j];
|
|
384
|
+
if (next.type === "element") {
|
|
385
|
+
targetIndex = j;
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
if (!isSkippable(next)) break;
|
|
389
|
+
const directive = directiveOf(next);
|
|
390
|
+
if (directive !== void 0) run.push(directive);
|
|
391
|
+
}
|
|
392
|
+
if (targetIndex >= 0) stampRun(children, targetIndex, run, state);
|
|
393
|
+
i = j;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
var rehypeVantageDirectives = () => {
|
|
397
|
+
return (tree) => {
|
|
398
|
+
processChildren(tree, { nextGroup: 1 });
|
|
399
|
+
};
|
|
400
|
+
};
|
|
401
|
+
var rehypeVantageDirectives_default = rehypeVantageDirectives;
|
|
402
|
+
|
|
403
|
+
// src/rehypeVantageMathStamps.ts
|
|
404
|
+
var CARRIED_KEY = "vantageDisplayMathStamps";
|
|
405
|
+
function classNames(node) {
|
|
406
|
+
const value = node.properties?.className;
|
|
407
|
+
return Array.isArray(value) ? value.map(String) : [];
|
|
408
|
+
}
|
|
409
|
+
function isDisplayMath(node) {
|
|
410
|
+
if (node.type !== "element" || node.tagName !== "pre") return false;
|
|
411
|
+
return node.children.some(
|
|
412
|
+
(child) => child.type === "element" && child.tagName === "code" && classNames(child).includes("language-math")
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
function carriedProperties(properties) {
|
|
416
|
+
const carried = {};
|
|
417
|
+
for (const [key, value] of Object.entries(properties ?? {})) {
|
|
418
|
+
if (key === "dataSourceLine" || key.startsWith("dataVantage")) {
|
|
419
|
+
carried[key] = value;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return carried;
|
|
423
|
+
}
|
|
424
|
+
function collect(parent, out) {
|
|
425
|
+
const children = parent.children;
|
|
426
|
+
for (let i = 0; i < children.length; i++) {
|
|
427
|
+
const node = children[i];
|
|
428
|
+
if (node.type !== "element") continue;
|
|
429
|
+
if (isDisplayMath(node)) {
|
|
430
|
+
const properties = carriedProperties(node.properties);
|
|
431
|
+
if (Object.keys(properties).length > 0) {
|
|
432
|
+
out.push({
|
|
433
|
+
parent,
|
|
434
|
+
anchor: i === 0 ? void 0 : children[i - 1],
|
|
435
|
+
properties
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
collect(node, out);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
function reapply(carried) {
|
|
444
|
+
for (const { parent, anchor, properties } of carried) {
|
|
445
|
+
const siblings = parent.children;
|
|
446
|
+
let index = 0;
|
|
447
|
+
if (anchor !== void 0) {
|
|
448
|
+
const at = siblings.indexOf(anchor);
|
|
449
|
+
if (at === -1) continue;
|
|
450
|
+
index = at + 1;
|
|
451
|
+
}
|
|
452
|
+
const replacement = siblings[index];
|
|
453
|
+
if (replacement === void 0 || replacement.type !== "element") continue;
|
|
454
|
+
if (!classNames(replacement).some((name) => name.startsWith("katex"))) {
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
replacement.properties ??= {};
|
|
458
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
459
|
+
replacement.properties[key] ??= value;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
var rehypeCaptureMathStamps = () => {
|
|
464
|
+
return (tree, file) => {
|
|
465
|
+
const carried = [];
|
|
466
|
+
collect(tree, carried);
|
|
467
|
+
file.data[CARRIED_KEY] = carried;
|
|
468
|
+
};
|
|
469
|
+
};
|
|
470
|
+
var rehypeRestoreMathStamps = () => {
|
|
471
|
+
return (_tree, file) => {
|
|
472
|
+
const carried = file.data[CARRIED_KEY];
|
|
473
|
+
delete file.data[CARRIED_KEY];
|
|
474
|
+
if (Array.isArray(carried)) reapply(carried);
|
|
475
|
+
};
|
|
476
|
+
};
|
|
477
|
+
var SAFE_STYLE_PROPERTIES = [
|
|
478
|
+
// Box metrics. `top`/`right`/`bottom`/`left` are inert now that `position` is
|
|
479
|
+
// banned, and they stay only because dropping them would fail the whole
|
|
480
|
+
// attribute for a document that writes one — the all-or-nothing rule below
|
|
481
|
+
// makes every removal a behaviour change. They buy an attacker nothing that
|
|
482
|
+
// negative `margin` does not already buy.
|
|
483
|
+
"height",
|
|
484
|
+
"min-height",
|
|
485
|
+
"max-height",
|
|
486
|
+
"width",
|
|
487
|
+
"min-width",
|
|
488
|
+
"max-width",
|
|
489
|
+
"top",
|
|
490
|
+
"bottom",
|
|
491
|
+
"left",
|
|
492
|
+
"right",
|
|
493
|
+
"margin",
|
|
494
|
+
"margin-top",
|
|
495
|
+
"margin-right",
|
|
496
|
+
"margin-bottom",
|
|
497
|
+
"margin-left",
|
|
498
|
+
"padding",
|
|
499
|
+
"padding-top",
|
|
500
|
+
"padding-right",
|
|
501
|
+
"padding-bottom",
|
|
502
|
+
"padding-left",
|
|
503
|
+
// Rules and boxes.
|
|
504
|
+
"border",
|
|
505
|
+
"border-style",
|
|
506
|
+
"border-color",
|
|
507
|
+
"border-width",
|
|
508
|
+
"border-top-width",
|
|
509
|
+
"border-right-width",
|
|
510
|
+
"border-bottom-width",
|
|
511
|
+
"border-left-width",
|
|
512
|
+
"border-top-style",
|
|
513
|
+
"border-right-style",
|
|
514
|
+
"border-bottom-style",
|
|
515
|
+
"border-left-style",
|
|
516
|
+
"border-top-color",
|
|
517
|
+
"border-right-color",
|
|
518
|
+
"border-bottom-color",
|
|
519
|
+
"border-left-color",
|
|
520
|
+
"border-radius",
|
|
521
|
+
// Typography.
|
|
522
|
+
"color",
|
|
523
|
+
"background-color",
|
|
524
|
+
"font",
|
|
525
|
+
"font-size",
|
|
526
|
+
"font-style",
|
|
527
|
+
"font-weight",
|
|
528
|
+
"font-family",
|
|
529
|
+
"font-variant",
|
|
530
|
+
"line-height",
|
|
531
|
+
"letter-spacing",
|
|
532
|
+
"word-spacing",
|
|
533
|
+
"text-align",
|
|
534
|
+
"text-decoration",
|
|
535
|
+
"text-indent",
|
|
536
|
+
"white-space",
|
|
537
|
+
"vertical-align",
|
|
538
|
+
"list-style-type",
|
|
539
|
+
// Flow.
|
|
540
|
+
"display",
|
|
541
|
+
"float",
|
|
542
|
+
"clear",
|
|
543
|
+
"opacity",
|
|
544
|
+
"overflow"
|
|
545
|
+
];
|
|
546
|
+
var VALUE = `[^;:()"'\\\\]*`;
|
|
547
|
+
var DECLARATION = `(?:(?:${SAFE_STYLE_PROPERTIES.join("|")})\\s*:${VALUE})`;
|
|
548
|
+
var SAFE_STYLE = new RegExp(
|
|
549
|
+
`^\\s*(?:${DECLARATION};\\s*)*${DECLARATION}?$`,
|
|
550
|
+
"i"
|
|
551
|
+
);
|
|
552
|
+
var COLLAPSE_GROUP_ID = /^[0-9]+$/;
|
|
75
553
|
var sanitizeSchema = {
|
|
76
554
|
...rehypeSanitize.defaultSchema,
|
|
77
555
|
tagNames: [
|
|
@@ -107,20 +585,94 @@ var sanitizeSchema = {
|
|
|
107
585
|
"*": [
|
|
108
586
|
...rehypeSanitize.defaultSchema.attributes?.["*"] || [],
|
|
109
587
|
"className",
|
|
110
|
-
"style",
|
|
111
|
-
"dataSourceLine"
|
|
588
|
+
["style", SAFE_STYLE],
|
|
589
|
+
"dataSourceLine",
|
|
590
|
+
// What `rehypeVantageDirectives` compiles a `<!-- vantage: … -->` comment
|
|
591
|
+
// into, named individually — never by a `data-vantage-*` wildcard, which
|
|
592
|
+
// would readmit whatever a future bug emits and whatever a document
|
|
593
|
+
// hand-writes as raw HTML.
|
|
594
|
+
//
|
|
595
|
+
// The value lists are the belt to the plugin's braces: the vocabulary is
|
|
596
|
+
// closed in the plugin *and* here, imported from the one module that
|
|
597
|
+
// defines it, so even if a refactor let an unvalidated value reach the
|
|
598
|
+
// tree the sanitiser still refuses it.
|
|
599
|
+
["dataVantageTone", ...VANTAGE_TONES],
|
|
600
|
+
["dataVantageEmphasis", ...VANTAGE_EMPHASIS],
|
|
601
|
+
["dataVantageBadge", ...VANTAGE_BADGES],
|
|
602
|
+
["dataVantageCollapsed", ...VANTAGE_COLLAPSED],
|
|
603
|
+
// The other half of `collapsed`: which group a hidden block belongs to,
|
|
604
|
+
// and which group a heading toggles. Both are plugin-minted counters with
|
|
605
|
+
// no vocabulary to allowlist, so they take a pattern instead —
|
|
606
|
+
// `hast-util-sanitize` accepts a `RegExp` in place of a literal value.
|
|
607
|
+
// A pattern rather than a bare name because the JS interpolates the value
|
|
608
|
+
// into a selector: anything but digits has no business reaching it.
|
|
609
|
+
["dataVantageCollapseGroup", COLLAPSE_GROUP_ID],
|
|
610
|
+
["dataVantageCollapseToggle", COLLAPSE_GROUP_ID],
|
|
611
|
+
["dataVantageRun", ...VANTAGE_RUNS],
|
|
612
|
+
["dataVantageOq", "true"],
|
|
613
|
+
// The design's one genuinely free-text value: the body of a review
|
|
614
|
+
// comment, so it cannot be value-allowlisted and this entry is name-only.
|
|
615
|
+
// Two defences remain rather than three — `hast` escapes the value on
|
|
616
|
+
// serialisation and React sets it through the DOM property path, so it
|
|
617
|
+
// cannot break out of the attribute — and the honest record of that is in
|
|
618
|
+
// the design doc rather than a third layer implied here.
|
|
619
|
+
"dataVantageLeaning"
|
|
112
620
|
],
|
|
113
621
|
code: [...rehypeSanitize.defaultSchema.attributes?.code || [], "className"],
|
|
114
|
-
span: [
|
|
115
|
-
|
|
622
|
+
span: [
|
|
623
|
+
...rehypeSanitize.defaultSchema.attributes?.span || [],
|
|
624
|
+
"className",
|
|
625
|
+
["style", SAFE_STYLE]
|
|
626
|
+
],
|
|
627
|
+
div: [
|
|
628
|
+
...rehypeSanitize.defaultSchema.attributes?.div || [],
|
|
629
|
+
"className",
|
|
630
|
+
["style", SAFE_STYLE]
|
|
631
|
+
],
|
|
116
632
|
a: [...rehypeSanitize.defaultSchema.attributes?.a || [], "id", "className"],
|
|
117
633
|
math: ["xmlns"],
|
|
118
634
|
annotation: ["encoding"],
|
|
119
635
|
img: [...rehypeSanitize.defaultSchema.attributes?.img || [], "loading"],
|
|
120
|
-
td: [...rehypeSanitize.defaultSchema.attributes?.td || [], "style"],
|
|
121
|
-
th: [...rehypeSanitize.defaultSchema.attributes?.th || [], "style"]
|
|
636
|
+
td: [...rehypeSanitize.defaultSchema.attributes?.td || [], ["style", SAFE_STYLE]],
|
|
637
|
+
th: [...rehypeSanitize.defaultSchema.attributes?.th || [], ["style", SAFE_STYLE]]
|
|
122
638
|
}
|
|
123
639
|
};
|
|
640
|
+
|
|
641
|
+
// src/pipeline.ts
|
|
642
|
+
function buildRemarkPlugins(options = {}) {
|
|
643
|
+
const { gfm = true, math = true } = options;
|
|
644
|
+
const plugins = [];
|
|
645
|
+
if (gfm) plugins.push([remarkGfm__default.default, { singleTilde: false }]);
|
|
646
|
+
if (math) plugins.push([remarkMath__default.default, { singleDollarTextMath: false }]);
|
|
647
|
+
return plugins;
|
|
648
|
+
}
|
|
649
|
+
function buildRehypePlugins(options = {}) {
|
|
650
|
+
const {
|
|
651
|
+
math = true,
|
|
652
|
+
highlight = true,
|
|
653
|
+
sourceLines = true,
|
|
654
|
+
sanitize = true,
|
|
655
|
+
bodyLineOffset = 0
|
|
656
|
+
} = options;
|
|
657
|
+
const plugins = [rehypeRaw__default.default];
|
|
658
|
+
if (sourceLines) {
|
|
659
|
+
plugins.push([rehypeSourceLines_default, { offset: bodyLineOffset }]);
|
|
660
|
+
}
|
|
661
|
+
plugins.push(rehypeVantageDirectives_default);
|
|
662
|
+
if (sanitize) plugins.push([rehypeSanitize__default.default, sanitizeSchema]);
|
|
663
|
+
plugins.push(rehypeSlug__default.default);
|
|
664
|
+
if (highlight) plugins.push(rehypeHighlight__default.default);
|
|
665
|
+
if (math) {
|
|
666
|
+
plugins.push(rehypeCaptureMathStamps, rehypeKatex__default.default, rehypeRestoreMathStamps);
|
|
667
|
+
}
|
|
668
|
+
return plugins;
|
|
669
|
+
}
|
|
670
|
+
function buildPipeline(options = {}) {
|
|
671
|
+
return {
|
|
672
|
+
remarkPlugins: buildRemarkPlugins(options),
|
|
673
|
+
rehypePlugins: buildRehypePlugins(options)
|
|
674
|
+
};
|
|
675
|
+
}
|
|
124
676
|
function parseFrontmatter(content) {
|
|
125
677
|
if (content.startsWith("+++")) {
|
|
126
678
|
return parseFrontmatterWithDelimiter(content, "+++", "toml");
|
|
@@ -128,24 +680,74 @@ function parseFrontmatter(content) {
|
|
|
128
680
|
if (content.startsWith("---")) {
|
|
129
681
|
return parseFrontmatterWithDelimiter(content, "---", "yaml");
|
|
130
682
|
}
|
|
131
|
-
return
|
|
683
|
+
return withOffset(content, {
|
|
684
|
+
frontmatter: {},
|
|
685
|
+
body: content,
|
|
686
|
+
format: "none"
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
function withOffset(content, parsed) {
|
|
690
|
+
const stripped = content.slice(0, content.length - parsed.body.length);
|
|
691
|
+
let bodyLineOffset = 0;
|
|
692
|
+
for (const ch of stripped) {
|
|
693
|
+
if (ch === "\n") bodyLineOffset++;
|
|
694
|
+
}
|
|
695
|
+
return { ...parsed, bodyLineOffset };
|
|
132
696
|
}
|
|
133
697
|
function parseFrontmatterWithDelimiter(content, delimiter, format) {
|
|
134
698
|
const searchStart = delimiter.length;
|
|
135
699
|
const endIndex = content.indexOf(`
|
|
136
700
|
${delimiter}`, searchStart);
|
|
137
701
|
if (endIndex === -1) {
|
|
138
|
-
return
|
|
702
|
+
return withOffset(content, {
|
|
703
|
+
frontmatter: {},
|
|
704
|
+
body: content,
|
|
705
|
+
format: "none",
|
|
706
|
+
problem: { kind: "unterminated", delimiter }
|
|
707
|
+
});
|
|
139
708
|
}
|
|
140
709
|
const raw = content.slice(searchStart + 1, endIndex).trim();
|
|
141
710
|
const bodyStart = endIndex + 1 + delimiter.length;
|
|
142
711
|
const body = content.slice(bodyStart).replace(/^\n/, "");
|
|
143
712
|
try {
|
|
144
|
-
const
|
|
145
|
-
return
|
|
146
|
-
|
|
147
|
-
|
|
713
|
+
const parsed = format === "toml" ? smolToml.parse(raw) : YAML__default.default.parse(raw);
|
|
714
|
+
return withOffset(content, {
|
|
715
|
+
frontmatter: parsed || {},
|
|
716
|
+
body,
|
|
717
|
+
format,
|
|
718
|
+
...isMapping(parsed) ? {} : { problem: { kind: "not-a-mapping", delimiter } }
|
|
719
|
+
});
|
|
720
|
+
} catch (error) {
|
|
721
|
+
return withOffset(content, {
|
|
722
|
+
frontmatter: {},
|
|
723
|
+
body: content,
|
|
724
|
+
format: "none",
|
|
725
|
+
problem: { kind: "invalid", delimiter, ...errorPosition(error) }
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
function isMapping(value) {
|
|
730
|
+
return value === null || value === void 0 || typeof value === "object" && !Array.isArray(value);
|
|
731
|
+
}
|
|
732
|
+
function errorPosition(error) {
|
|
733
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
734
|
+
const source = error;
|
|
735
|
+
const yamlPosition = source?.linePos?.[0];
|
|
736
|
+
if (typeof yamlPosition?.line === "number") {
|
|
737
|
+
return {
|
|
738
|
+
message,
|
|
739
|
+
line: yamlPosition.line,
|
|
740
|
+
...typeof yamlPosition.col === "number" ? { column: yamlPosition.col } : {}
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
if (typeof source?.line === "number") {
|
|
744
|
+
return {
|
|
745
|
+
message,
|
|
746
|
+
line: source.line,
|
|
747
|
+
...typeof source.column === "number" ? { column: source.column } : {}
|
|
748
|
+
};
|
|
148
749
|
}
|
|
750
|
+
return { message };
|
|
149
751
|
}
|
|
150
752
|
|
|
151
753
|
// src/mermaidCache.ts
|
|
@@ -172,23 +774,286 @@ async function getMermaid() {
|
|
|
172
774
|
}
|
|
173
775
|
return mermaidLoading;
|
|
174
776
|
}
|
|
175
|
-
var AlertTriangleIcon = () => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
]
|
|
777
|
+
var AlertTriangleIcon = () => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
778
|
+
"svg",
|
|
779
|
+
{
|
|
780
|
+
width: "16",
|
|
781
|
+
height: "16",
|
|
782
|
+
viewBox: "0 0 24 24",
|
|
783
|
+
fill: "none",
|
|
784
|
+
stroke: "currentColor",
|
|
785
|
+
strokeWidth: "2",
|
|
786
|
+
strokeLinecap: "round",
|
|
787
|
+
strokeLinejoin: "round",
|
|
788
|
+
className: "w-4 h-4 shrink-0",
|
|
789
|
+
children: [
|
|
790
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }),
|
|
791
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 9v4" }),
|
|
792
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 17h.01" })
|
|
793
|
+
]
|
|
794
|
+
}
|
|
795
|
+
);
|
|
796
|
+
var ChevronDownIcon = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
797
|
+
"svg",
|
|
798
|
+
{
|
|
799
|
+
width: "12",
|
|
800
|
+
height: "12",
|
|
801
|
+
viewBox: "0 0 24 24",
|
|
802
|
+
fill: "none",
|
|
803
|
+
stroke: "currentColor",
|
|
804
|
+
strokeWidth: "2",
|
|
805
|
+
strokeLinecap: "round",
|
|
806
|
+
strokeLinejoin: "round",
|
|
807
|
+
className: "w-3 h-3",
|
|
808
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" })
|
|
809
|
+
}
|
|
810
|
+
);
|
|
811
|
+
var ChevronUpIcon = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
812
|
+
"svg",
|
|
813
|
+
{
|
|
814
|
+
width: "12",
|
|
815
|
+
height: "12",
|
|
816
|
+
viewBox: "0 0 24 24",
|
|
817
|
+
fill: "none",
|
|
818
|
+
stroke: "currentColor",
|
|
819
|
+
strokeWidth: "2",
|
|
820
|
+
strokeLinecap: "round",
|
|
821
|
+
strokeLinejoin: "round",
|
|
822
|
+
className: "w-3 h-3",
|
|
823
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m18 15-6-6-6 6" })
|
|
824
|
+
}
|
|
825
|
+
);
|
|
826
|
+
var MaximizeIcon = () => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
827
|
+
"svg",
|
|
828
|
+
{
|
|
829
|
+
width: "16",
|
|
830
|
+
height: "16",
|
|
831
|
+
viewBox: "0 0 24 24",
|
|
832
|
+
fill: "none",
|
|
833
|
+
stroke: "currentColor",
|
|
834
|
+
strokeWidth: "2",
|
|
835
|
+
strokeLinecap: "round",
|
|
836
|
+
strokeLinejoin: "round",
|
|
837
|
+
className: "w-4 h-4 text-gray-600",
|
|
838
|
+
children: [
|
|
839
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }),
|
|
840
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 21 3 21 3 15" }),
|
|
841
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", x2: "14", y1: "3", y2: "10" }),
|
|
842
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", x2: "10", y1: "21", y2: "14" })
|
|
843
|
+
]
|
|
844
|
+
}
|
|
845
|
+
);
|
|
846
|
+
var CloseIcon = () => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
847
|
+
"svg",
|
|
848
|
+
{
|
|
849
|
+
width: "20",
|
|
850
|
+
height: "20",
|
|
851
|
+
viewBox: "0 0 24 24",
|
|
852
|
+
fill: "none",
|
|
853
|
+
stroke: "currentColor",
|
|
854
|
+
strokeWidth: "2",
|
|
855
|
+
strokeLinecap: "round",
|
|
856
|
+
strokeLinejoin: "round",
|
|
857
|
+
className: "w-5 h-5",
|
|
858
|
+
children: [
|
|
859
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18" }),
|
|
860
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 6 12 12" })
|
|
861
|
+
]
|
|
862
|
+
}
|
|
863
|
+
);
|
|
864
|
+
var PlusIcon = () => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
865
|
+
"svg",
|
|
866
|
+
{
|
|
867
|
+
width: "16",
|
|
868
|
+
height: "16",
|
|
869
|
+
viewBox: "0 0 24 24",
|
|
870
|
+
fill: "none",
|
|
871
|
+
stroke: "currentColor",
|
|
872
|
+
strokeWidth: "2",
|
|
873
|
+
strokeLinecap: "round",
|
|
874
|
+
strokeLinejoin: "round",
|
|
875
|
+
className: "w-4 h-4",
|
|
876
|
+
children: [
|
|
877
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 12h14" }),
|
|
878
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 5v14" })
|
|
879
|
+
]
|
|
880
|
+
}
|
|
881
|
+
);
|
|
882
|
+
var MinusIcon = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
883
|
+
"svg",
|
|
884
|
+
{
|
|
885
|
+
width: "16",
|
|
886
|
+
height: "16",
|
|
887
|
+
viewBox: "0 0 24 24",
|
|
888
|
+
fill: "none",
|
|
889
|
+
stroke: "currentColor",
|
|
890
|
+
strokeWidth: "2",
|
|
891
|
+
strokeLinecap: "round",
|
|
892
|
+
strokeLinejoin: "round",
|
|
893
|
+
className: "w-4 h-4",
|
|
894
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 12h14" })
|
|
895
|
+
}
|
|
896
|
+
);
|
|
897
|
+
var ResetIcon = () => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
898
|
+
"svg",
|
|
899
|
+
{
|
|
900
|
+
width: "16",
|
|
901
|
+
height: "16",
|
|
902
|
+
viewBox: "0 0 24 24",
|
|
903
|
+
fill: "none",
|
|
904
|
+
stroke: "currentColor",
|
|
905
|
+
strokeWidth: "2",
|
|
906
|
+
strokeLinecap: "round",
|
|
907
|
+
strokeLinejoin: "round",
|
|
908
|
+
className: "w-4 h-4",
|
|
909
|
+
children: [
|
|
910
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
|
|
911
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 3v5h5" })
|
|
912
|
+
]
|
|
913
|
+
}
|
|
914
|
+
);
|
|
915
|
+
var MIN_SCALE = 0.2;
|
|
916
|
+
var MAX_SCALE = 8;
|
|
917
|
+
function ZoomableSvg({ svg }) {
|
|
918
|
+
const [scale, setScale] = react.useState(1);
|
|
919
|
+
const [offset, setOffset] = react.useState({ x: 0, y: 0 });
|
|
920
|
+
const dragRef = react.useRef(null);
|
|
921
|
+
const [isDragging, setIsDragging] = react.useState(false);
|
|
922
|
+
const viewportRef = react.useRef(null);
|
|
923
|
+
const reset = react.useCallback(() => {
|
|
924
|
+
setScale(1);
|
|
925
|
+
setOffset({ x: 0, y: 0 });
|
|
926
|
+
}, []);
|
|
927
|
+
const zoomBy = react.useCallback(
|
|
928
|
+
(factor, anchor) => {
|
|
929
|
+
setScale((prev) => {
|
|
930
|
+
const next = Math.min(MAX_SCALE, Math.max(MIN_SCALE, prev * factor));
|
|
931
|
+
if (next === prev) return prev;
|
|
932
|
+
const rect = viewportRef.current?.getBoundingClientRect();
|
|
933
|
+
if (rect) {
|
|
934
|
+
const ax = (anchor?.x ?? rect.width / 2) - rect.width / 2;
|
|
935
|
+
const ay = (anchor?.y ?? rect.height / 2) - rect.height / 2;
|
|
936
|
+
setOffset((o) => ({
|
|
937
|
+
x: ax - (ax - o.x) * next / prev,
|
|
938
|
+
y: ay - (ay - o.y) * next / prev
|
|
939
|
+
}));
|
|
940
|
+
}
|
|
941
|
+
return next;
|
|
942
|
+
});
|
|
943
|
+
},
|
|
944
|
+
[]
|
|
945
|
+
);
|
|
946
|
+
const handleWheel = react.useCallback(
|
|
947
|
+
(e) => {
|
|
948
|
+
e.preventDefault();
|
|
949
|
+
const rect = viewportRef.current?.getBoundingClientRect();
|
|
950
|
+
const anchor = rect ? { x: e.clientX - rect.left, y: e.clientY - rect.top } : void 0;
|
|
951
|
+
zoomBy(e.deltaY < 0 ? 1.15 : 1 / 1.15, anchor);
|
|
952
|
+
},
|
|
953
|
+
[zoomBy]
|
|
954
|
+
);
|
|
955
|
+
const handlePointerDown = (e) => {
|
|
956
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
957
|
+
dragRef.current = {
|
|
958
|
+
startX: e.clientX,
|
|
959
|
+
startY: e.clientY,
|
|
960
|
+
originX: offset.x,
|
|
961
|
+
originY: offset.y
|
|
962
|
+
};
|
|
963
|
+
setIsDragging(true);
|
|
964
|
+
};
|
|
965
|
+
const handlePointerMove = (e) => {
|
|
966
|
+
const d = dragRef.current;
|
|
967
|
+
if (!d) return;
|
|
968
|
+
setOffset({
|
|
969
|
+
x: d.originX + (e.clientX - d.startX),
|
|
970
|
+
y: d.originY + (e.clientY - d.startY)
|
|
971
|
+
});
|
|
972
|
+
};
|
|
973
|
+
const endDrag = (e) => {
|
|
974
|
+
if (dragRef.current) {
|
|
975
|
+
try {
|
|
976
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
977
|
+
} catch {
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
dragRef.current = null;
|
|
981
|
+
setIsDragging(false);
|
|
982
|
+
};
|
|
983
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full h-full", children: [
|
|
984
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
985
|
+
"div",
|
|
986
|
+
{
|
|
987
|
+
ref: viewportRef,
|
|
988
|
+
onWheel: handleWheel,
|
|
989
|
+
onPointerDown: handlePointerDown,
|
|
990
|
+
onPointerMove: handlePointerMove,
|
|
991
|
+
onPointerUp: endDrag,
|
|
992
|
+
onPointerLeave: endDrag,
|
|
993
|
+
onDoubleClick: reset,
|
|
994
|
+
className: "w-full h-full overflow-hidden touch-none select-none",
|
|
995
|
+
style: { cursor: isDragging ? "grabbing" : "grab" },
|
|
996
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
997
|
+
"div",
|
|
998
|
+
{
|
|
999
|
+
className: "mermaid-zoom flex items-center justify-center w-full h-full",
|
|
1000
|
+
style: {
|
|
1001
|
+
transform: `translate(${offset.x}px, ${offset.y}px) scale(${scale})`,
|
|
1002
|
+
transformOrigin: "center center",
|
|
1003
|
+
transition: isDragging ? "none" : "transform 0.08s ease-out"
|
|
1004
|
+
},
|
|
1005
|
+
dangerouslySetInnerHTML: { __html: svg }
|
|
1006
|
+
}
|
|
1007
|
+
)
|
|
1008
|
+
}
|
|
1009
|
+
),
|
|
1010
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-4 right-4 flex items-center gap-1 rounded-lg bg-white/95 shadow-md border border-gray-200 px-1.5 py-1", children: [
|
|
1011
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1012
|
+
"button",
|
|
1013
|
+
{
|
|
1014
|
+
onClick: () => zoomBy(1 / 1.3),
|
|
1015
|
+
className: "p-1.5 rounded hover:bg-gray-100 text-gray-600",
|
|
1016
|
+
"aria-label": "Zoom out",
|
|
1017
|
+
title: "Zoom out",
|
|
1018
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(MinusIcon, {})
|
|
1019
|
+
}
|
|
1020
|
+
),
|
|
1021
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1022
|
+
"button",
|
|
1023
|
+
{
|
|
1024
|
+
onClick: reset,
|
|
1025
|
+
className: "px-2 py-1 text-xs font-medium rounded hover:bg-gray-100 text-gray-600 min-w-[3rem]",
|
|
1026
|
+
title: "Reset zoom (or double-click)",
|
|
1027
|
+
children: [
|
|
1028
|
+
Math.round(scale * 100),
|
|
1029
|
+
"%"
|
|
1030
|
+
]
|
|
1031
|
+
}
|
|
1032
|
+
),
|
|
1033
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1034
|
+
"button",
|
|
1035
|
+
{
|
|
1036
|
+
onClick: () => zoomBy(1.3),
|
|
1037
|
+
className: "p-1.5 rounded hover:bg-gray-100 text-gray-600",
|
|
1038
|
+
"aria-label": "Zoom in",
|
|
1039
|
+
title: "Zoom in",
|
|
1040
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {})
|
|
1041
|
+
}
|
|
1042
|
+
),
|
|
1043
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-5 bg-gray-200 mx-0.5" }),
|
|
1044
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1045
|
+
"button",
|
|
1046
|
+
{
|
|
1047
|
+
onClick: reset,
|
|
1048
|
+
className: "p-1.5 rounded hover:bg-gray-100 text-gray-600",
|
|
1049
|
+
"aria-label": "Reset view",
|
|
1050
|
+
title: "Reset view",
|
|
1051
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ResetIcon, {})
|
|
1052
|
+
}
|
|
1053
|
+
)
|
|
1054
|
+
] })
|
|
1055
|
+
] });
|
|
1056
|
+
}
|
|
192
1057
|
function extractErrorMessage(err) {
|
|
193
1058
|
if (err instanceof Error) {
|
|
194
1059
|
const msg = err.message;
|
|
@@ -227,12 +1092,12 @@ function DiagramModal({
|
|
|
227
1092
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
228
1093
|
"div",
|
|
229
1094
|
{
|
|
230
|
-
className: "bg-white rounded-lg shadow-xl w-
|
|
1095
|
+
className: "bg-white rounded-lg shadow-xl w-[96vw] h-[94vh] flex flex-col overflow-hidden",
|
|
231
1096
|
role: "dialog",
|
|
232
1097
|
"aria-modal": "true",
|
|
233
1098
|
onClick: (e) => e.stopPropagation(),
|
|
234
1099
|
children: [
|
|
235
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 border-b", children: [
|
|
1100
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between p-4 border-b shrink-0", children: [
|
|
236
1101
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold", children: "Mermaid Diagram" }),
|
|
237
1102
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
238
1103
|
"button",
|
|
@@ -244,7 +1109,7 @@ function DiagramModal({
|
|
|
244
1109
|
}
|
|
245
1110
|
)
|
|
246
1111
|
] }),
|
|
247
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
1112
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden bg-gray-50", children })
|
|
248
1113
|
]
|
|
249
1114
|
}
|
|
250
1115
|
)
|
|
@@ -363,33 +1228,114 @@ var MermaidDiagramInner = ({ code }) => {
|
|
|
363
1228
|
]
|
|
364
1229
|
}
|
|
365
1230
|
),
|
|
366
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
367
|
-
DiagramModal,
|
|
368
|
-
{
|
|
369
|
-
isOpen: isModalOpen,
|
|
370
|
-
onClose: () => setIsModalOpen(false),
|
|
371
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
372
|
-
"div",
|
|
373
|
-
{
|
|
374
|
-
className: "flex justify-center items-center min-h-[50vh]",
|
|
375
|
-
dangerouslySetInnerHTML: { __html: svg }
|
|
376
|
-
}
|
|
377
|
-
)
|
|
378
|
-
}
|
|
379
|
-
)
|
|
1231
|
+
/* @__PURE__ */ jsxRuntime.jsx(DiagramModal, { isOpen: isModalOpen, onClose: () => setIsModalOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(ZoomableSvg, { svg }) })
|
|
380
1232
|
] });
|
|
381
1233
|
};
|
|
382
1234
|
var MermaidDiagram = react.memo(
|
|
383
1235
|
MermaidDiagramInner,
|
|
384
1236
|
(prevProps, nextProps) => prevProps.code === nextProps.code
|
|
385
1237
|
);
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
1238
|
+
|
|
1239
|
+
// src/vantageFrontmatter.ts
|
|
1240
|
+
var DOC_STATUSES = [
|
|
1241
|
+
"draft",
|
|
1242
|
+
"in-review",
|
|
1243
|
+
"accepted",
|
|
1244
|
+
"deprecated"
|
|
1245
|
+
];
|
|
1246
|
+
var VANTAGE_FRONTMATTER_KEYS = ["status-chip"];
|
|
1247
|
+
var DOC_STATUS_TONES = {
|
|
1248
|
+
draft: "muted",
|
|
1249
|
+
"in-review": "warning",
|
|
1250
|
+
accepted: "tip",
|
|
1251
|
+
deprecated: "caution"
|
|
1252
|
+
};
|
|
1253
|
+
var STATUS_CHIP_VALUES = [
|
|
1254
|
+
...DOC_STATUSES,
|
|
1255
|
+
"true",
|
|
1256
|
+
"false"
|
|
1257
|
+
];
|
|
1258
|
+
function isDocStatus(value) {
|
|
1259
|
+
return typeof value === "string" && DOC_STATUSES.includes(value);
|
|
1260
|
+
}
|
|
1261
|
+
function isTable(value) {
|
|
1262
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date);
|
|
1263
|
+
}
|
|
1264
|
+
function readVantageFrontmatter(frontmatter) {
|
|
1265
|
+
const issues = [];
|
|
1266
|
+
if (!Object.hasOwn(frontmatter, "vantage")) return { issues };
|
|
1267
|
+
const value = frontmatter["vantage"];
|
|
1268
|
+
if (!isTable(value)) {
|
|
1269
|
+
issues.push({ kind: "not-a-table", value });
|
|
1270
|
+
return { issues };
|
|
1271
|
+
}
|
|
1272
|
+
let statusChip;
|
|
1273
|
+
for (const key of Object.keys(value)) {
|
|
1274
|
+
if (!VANTAGE_FRONTMATTER_KEYS.includes(key)) {
|
|
1275
|
+
issues.push({ kind: "unknown-key", key });
|
|
1276
|
+
continue;
|
|
1277
|
+
}
|
|
1278
|
+
if (key === "status-chip") {
|
|
1279
|
+
statusChip = readStatusChip(frontmatter, value[key], issues);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
return { ...statusChip === void 0 ? {} : { statusChip }, issues };
|
|
1283
|
+
}
|
|
1284
|
+
function readStatusChip(frontmatter, raw, issues) {
|
|
1285
|
+
const status = frontmatter["status"];
|
|
1286
|
+
if (raw === false) return void 0;
|
|
1287
|
+
if (raw === true) {
|
|
1288
|
+
if (isDocStatus(status)) return status;
|
|
1289
|
+
issues.push({ kind: "status-chip-orphan", status });
|
|
1290
|
+
return void 0;
|
|
1291
|
+
}
|
|
1292
|
+
if (isDocStatus(raw)) {
|
|
1293
|
+
if (isDocStatus(status) && status !== raw) {
|
|
1294
|
+
issues.push({ kind: "status-chip-disagrees", chip: raw, status });
|
|
1295
|
+
}
|
|
1296
|
+
return raw;
|
|
1297
|
+
}
|
|
1298
|
+
issues.push({
|
|
1299
|
+
kind: "bad-value",
|
|
1300
|
+
key: "status-chip",
|
|
1301
|
+
value: raw,
|
|
1302
|
+
legal: STATUS_CHIP_VALUES
|
|
1303
|
+
});
|
|
1304
|
+
return void 0;
|
|
1305
|
+
}
|
|
1306
|
+
var DocumentStatusChipInner = ({
|
|
1307
|
+
status
|
|
1308
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1309
|
+
"span",
|
|
1310
|
+
{
|
|
1311
|
+
className: `vantage-chip vantage-chip--${DOC_STATUS_TONES[status]}`,
|
|
1312
|
+
"data-vantage-status": status,
|
|
1313
|
+
title: `Document status: ${status}`,
|
|
1314
|
+
children: status
|
|
1315
|
+
}
|
|
1316
|
+
);
|
|
1317
|
+
var DocumentStatusChip = react.memo(DocumentStatusChipInner);
|
|
1318
|
+
var FileTextIcon = () => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1319
|
+
"svg",
|
|
1320
|
+
{
|
|
1321
|
+
width: "14",
|
|
1322
|
+
height: "14",
|
|
1323
|
+
viewBox: "0 0 24 24",
|
|
1324
|
+
fill: "none",
|
|
1325
|
+
stroke: "currentColor",
|
|
1326
|
+
strokeWidth: "2",
|
|
1327
|
+
strokeLinecap: "round",
|
|
1328
|
+
strokeLinejoin: "round",
|
|
1329
|
+
className: "text-slate-400",
|
|
1330
|
+
children: [
|
|
1331
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
|
|
1332
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" }),
|
|
1333
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 9H8" }),
|
|
1334
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 13H8" }),
|
|
1335
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 17H8" })
|
|
1336
|
+
]
|
|
1337
|
+
}
|
|
1338
|
+
);
|
|
393
1339
|
function isStringArray(value) {
|
|
394
1340
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
395
1341
|
}
|
|
@@ -433,6 +1379,7 @@ function ValueCell({ value }) {
|
|
|
433
1379
|
function flattenEntries(entries) {
|
|
434
1380
|
const result = [];
|
|
435
1381
|
for (const [key, value] of entries) {
|
|
1382
|
+
if (key === "vantage") continue;
|
|
436
1383
|
if (key === "taxonomies" && isPlainObject(value)) {
|
|
437
1384
|
for (const [taxKey, taxVal] of Object.entries(value)) {
|
|
438
1385
|
result.push([taxKey, taxVal]);
|
|
@@ -450,31 +1397,33 @@ function flattenEntries(entries) {
|
|
|
450
1397
|
var FrontmatterDisplayInner = ({
|
|
451
1398
|
frontmatter
|
|
452
1399
|
}) => {
|
|
453
|
-
const
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
457
|
-
/* @__PURE__ */ jsxRuntime.
|
|
458
|
-
|
|
459
|
-
/* @__PURE__ */ jsxRuntime.
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
{
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
1400
|
+
const entries = flattenEntries(Object.entries(frontmatter));
|
|
1401
|
+
const { statusChip } = readVantageFrontmatter(frontmatter);
|
|
1402
|
+
if (entries.length === 0 && statusChip === void 0) return null;
|
|
1403
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1404
|
+
statusChip !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "vantage-chrome", children: /* @__PURE__ */ jsxRuntime.jsx(DocumentStatusChip, { status: statusChip }) }),
|
|
1405
|
+
entries.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-8 rounded-lg overflow-hidden bg-gradient-to-br from-slate-50 to-slate-100 dark:from-slate-800 dark:to-slate-800/80 border border-slate-200 dark:border-slate-700 shadow-sm", children: [
|
|
1406
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-2.5 bg-white/60 dark:bg-slate-900/40 border-b border-slate-200 dark:border-slate-700 flex items-center gap-2", children: [
|
|
1407
|
+
/* @__PURE__ */ jsxRuntime.jsx(FileTextIcon, {}),
|
|
1408
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wider", children: "Metadata" })
|
|
1409
|
+
] }),
|
|
1410
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx("table", { className: "w-full text-sm", children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: entries.map(([key, value]) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1411
|
+
"tr",
|
|
1412
|
+
{
|
|
1413
|
+
className: "border-b border-slate-200/60 dark:border-slate-700/60 last:border-0",
|
|
1414
|
+
children: [
|
|
1415
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 pr-4 font-medium text-slate-500 dark:text-slate-400 whitespace-nowrap align-top w-1/4 min-w-[100px]", children: key }),
|
|
1416
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-2 text-slate-800 dark:text-slate-200 align-top", children: /* @__PURE__ */ jsxRuntime.jsx(ValueCell, { value }) })
|
|
1417
|
+
]
|
|
1418
|
+
},
|
|
1419
|
+
key
|
|
1420
|
+
)) }) }) })
|
|
1421
|
+
] })
|
|
472
1422
|
] });
|
|
473
1423
|
};
|
|
474
1424
|
var FrontmatterDisplay = react.memo(FrontmatterDisplayInner);
|
|
475
1425
|
|
|
476
|
-
// src/
|
|
477
|
-
var HIGHLIGHT_CLASS = "line-anchor-highlight";
|
|
1426
|
+
// src/lineAnchor.ts
|
|
478
1427
|
function parseLineAnchor(hash) {
|
|
479
1428
|
if (!hash) return null;
|
|
480
1429
|
const frag = hash.startsWith("#") ? hash.slice(1) : hash;
|
|
@@ -484,6 +1433,9 @@ function parseLineAnchor(hash) {
|
|
|
484
1433
|
const end = match[2] ? parseInt(match[2], 10) : start;
|
|
485
1434
|
return { start: Math.min(start, end), end: Math.max(start, end) };
|
|
486
1435
|
}
|
|
1436
|
+
|
|
1437
|
+
// src/scrollToLineAnchor.ts
|
|
1438
|
+
var HIGHLIGHT_CLASS = "line-anchor-highlight";
|
|
487
1439
|
function clearLineAnchorHighlights(container) {
|
|
488
1440
|
container.querySelectorAll(`.${HIGHLIGHT_CLASS}`).forEach((node) => {
|
|
489
1441
|
node.classList.remove(HIGHLIGHT_CLASS);
|
|
@@ -496,10 +1448,7 @@ function scrollToLineAnchor(container, hash) {
|
|
|
496
1448
|
const blocks = container.querySelectorAll("[data-source-line]");
|
|
497
1449
|
let firstMatch = null;
|
|
498
1450
|
for (const block of blocks) {
|
|
499
|
-
const line = parseInt(
|
|
500
|
-
block.dataset.sourceLine || "0",
|
|
501
|
-
10
|
|
502
|
-
);
|
|
1451
|
+
const line = parseInt(block.dataset.sourceLine || "0", 10);
|
|
503
1452
|
if (line >= range.start && line <= range.end) {
|
|
504
1453
|
block.classList.add(HIGHLIGHT_CLASS);
|
|
505
1454
|
if (!firstMatch) firstMatch = block;
|
|
@@ -646,9 +1595,13 @@ var MarkdownViewerInner = ({
|
|
|
646
1595
|
}) => {
|
|
647
1596
|
const containerRef = react.useRef(null);
|
|
648
1597
|
useLineAnchor(containerRef, hash);
|
|
649
|
-
const { frontmatter, body } = react.useMemo(() => {
|
|
1598
|
+
const { frontmatter, body, bodyLineOffset } = react.useMemo(() => {
|
|
650
1599
|
return parseFrontmatter(content);
|
|
651
1600
|
}, [content]);
|
|
1601
|
+
const { remarkPlugins, rehypePlugins } = react.useMemo(
|
|
1602
|
+
() => buildPipeline({ bodyLineOffset }),
|
|
1603
|
+
[bodyLineOffset]
|
|
1604
|
+
);
|
|
652
1605
|
const handleLinkClick = react.useCallback(
|
|
653
1606
|
(e, href) => {
|
|
654
1607
|
if (href.startsWith("#")) {
|
|
@@ -771,18 +1724,8 @@ var MarkdownViewerInner = ({
|
|
|
771
1724
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
772
1725
|
ReactMarkdown__default.default,
|
|
773
1726
|
{
|
|
774
|
-
remarkPlugins
|
|
775
|
-
|
|
776
|
-
[remarkMath__default.default, { singleDollarTextMath: false }]
|
|
777
|
-
],
|
|
778
|
-
rehypePlugins: [
|
|
779
|
-
rehypeRaw__default.default,
|
|
780
|
-
rehypeSourceLines_default,
|
|
781
|
-
[rehypeSanitize__default.default, sanitizeSchema],
|
|
782
|
-
rehypeSlug__default.default,
|
|
783
|
-
rehypeHighlight__default.default,
|
|
784
|
-
rehypeKatex__default.default
|
|
785
|
-
],
|
|
1727
|
+
remarkPlugins,
|
|
1728
|
+
rehypePlugins,
|
|
786
1729
|
urlTransform: transformImageUri,
|
|
787
1730
|
components: markdownComponents,
|
|
788
1731
|
children: body
|
|
@@ -809,27 +1752,22 @@ async function renderMarkdown(content, options = {}) {
|
|
|
809
1752
|
if (parseFm) {
|
|
810
1753
|
parsed = parseFrontmatter(content);
|
|
811
1754
|
} else {
|
|
812
|
-
parsed = {
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
}
|
|
828
|
-
processor = processor.use(remarkRehype__default.default, { allowDangerousHtml: true });
|
|
829
|
-
for (const [plugin, ...args] of rehypePlugins) {
|
|
830
|
-
processor = processor.use(plugin, ...args);
|
|
831
|
-
}
|
|
832
|
-
processor = processor.use(rehypeStringify__default.default);
|
|
1755
|
+
parsed = {
|
|
1756
|
+
frontmatter: {},
|
|
1757
|
+
body: content,
|
|
1758
|
+
format: "none",
|
|
1759
|
+
bodyLineOffset: 0
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1762
|
+
const { remarkPlugins, rehypePlugins } = buildPipeline({
|
|
1763
|
+
gfm,
|
|
1764
|
+
math,
|
|
1765
|
+
highlight,
|
|
1766
|
+
sourceLines,
|
|
1767
|
+
sanitize,
|
|
1768
|
+
bodyLineOffset: parsed.bodyLineOffset
|
|
1769
|
+
});
|
|
1770
|
+
const processor = unified.unified().use(remarkParse__default.default).use(remarkPlugins).use(remarkRehype__default.default, { allowDangerousHtml: true }).use(rehypePlugins).use(rehypeStringify__default.default);
|
|
833
1771
|
const result = await processor.process(parsed.body);
|
|
834
1772
|
return {
|
|
835
1773
|
html: String(result),
|
|
@@ -910,12 +1848,20 @@ function resolveLinks(html, options = {}) {
|
|
|
910
1848
|
);
|
|
911
1849
|
}
|
|
912
1850
|
|
|
1851
|
+
exports.DOC_STATUSES = DOC_STATUSES;
|
|
1852
|
+
exports.DOC_STATUS_TONES = DOC_STATUS_TONES;
|
|
1853
|
+
exports.DocumentStatusChip = DocumentStatusChip;
|
|
913
1854
|
exports.FrontmatterDisplay = FrontmatterDisplay;
|
|
914
1855
|
exports.MarkdownViewer = MarkdownViewer;
|
|
915
1856
|
exports.MermaidDiagram = MermaidDiagram;
|
|
1857
|
+
exports.VANTAGE_FRONTMATTER_KEYS = VANTAGE_FRONTMATTER_KEYS;
|
|
1858
|
+
exports.buildPipeline = buildPipeline;
|
|
1859
|
+
exports.buildRemarkPlugins = buildRemarkPlugins;
|
|
916
1860
|
exports.clearLineAnchorHighlights = clearLineAnchorHighlights;
|
|
1861
|
+
exports.isDocStatus = isDocStatus;
|
|
917
1862
|
exports.parseFrontmatter = parseFrontmatter;
|
|
918
1863
|
exports.parseLineAnchor = parseLineAnchor;
|
|
1864
|
+
exports.readVantageFrontmatter = readVantageFrontmatter;
|
|
919
1865
|
exports.rehypeSourceLines = rehypeSourceLines_default;
|
|
920
1866
|
exports.renderMarkdown = renderMarkdown;
|
|
921
1867
|
exports.renderMermaidBlocks = renderMermaidBlocks;
|