@mulmoclaude/markdown-utils 1.2.0 → 1.3.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.
|
@@ -19,6 +19,18 @@ export interface ParsedMarkdown {
|
|
|
19
19
|
* a well-formed envelope falls back to `{ meta: {}, hasHeader: false }`
|
|
20
20
|
* so a typo in the header doesn't break rendering. */
|
|
21
21
|
export declare function parseFrontmatter(raw: string): ParsedMarkdown;
|
|
22
|
+
/** Split a document into its frontmatter `prefix` (the `---\n…\n---\n`
|
|
23
|
+
* envelope, empty string when there is none) and the `body` that
|
|
24
|
+
* follows. `prefix + body` reproduces the input exactly: `body` is
|
|
25
|
+
* always a suffix of `raw` (see `parseFrontmatter`), so `prefix` is
|
|
26
|
+
* the leading slice of the exact remaining length. Reach for this
|
|
27
|
+
* instead of re-deriving the split when you need to rewrite the body
|
|
28
|
+
* and re-attach the original header verbatim — e.g. toggling a task
|
|
29
|
+
* checkbox without disturbing the YAML. */
|
|
30
|
+
export declare function splitFrontmatter(raw: string): {
|
|
31
|
+
prefix: string;
|
|
32
|
+
body: string;
|
|
33
|
+
};
|
|
22
34
|
/** Serialize a meta object + body back into the canonical
|
|
23
35
|
* `---\n...\n---\n\nbody` shape. An empty `meta` returns the body
|
|
24
36
|
* alone (no envelope) — the lazy-on-write contract: don't add
|
|
@@ -38,6 +38,19 @@ export function parseFrontmatter(raw) {
|
|
|
38
38
|
}
|
|
39
39
|
return { meta, body, hasHeader: true };
|
|
40
40
|
}
|
|
41
|
+
/** Split a document into its frontmatter `prefix` (the `---\n…\n---\n`
|
|
42
|
+
* envelope, empty string when there is none) and the `body` that
|
|
43
|
+
* follows. `prefix + body` reproduces the input exactly: `body` is
|
|
44
|
+
* always a suffix of `raw` (see `parseFrontmatter`), so `prefix` is
|
|
45
|
+
* the leading slice of the exact remaining length. Reach for this
|
|
46
|
+
* instead of re-deriving the split when you need to rewrite the body
|
|
47
|
+
* and re-attach the original header verbatim — e.g. toggling a task
|
|
48
|
+
* checkbox without disturbing the YAML. */
|
|
49
|
+
export function splitFrontmatter(raw) {
|
|
50
|
+
const { body } = parseFrontmatter(raw);
|
|
51
|
+
const prefix = raw.slice(0, raw.length - body.length);
|
|
52
|
+
return { prefix, body };
|
|
53
|
+
}
|
|
41
54
|
/** Serialize a meta object + body back into the canonical
|
|
42
55
|
* `---\n...\n---\n\nbody` shape. An empty `meta` returns the body
|
|
43
56
|
* alone (no envelope) — the lazy-on-write contract: don't add
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// diagram render itself is deferred to `mermaidRender.ts`, which
|
|
5
5
|
// scans the placeholders in the DOM after Vue's v-html injects the
|
|
6
6
|
// html. Two-step split keeps this file pure (no runtime deps beyond
|
|
7
|
-
// `marked`
|
|
8
|
-
// browser.
|
|
7
|
+
// `marked` and the zero-dep `@mulmoclaude/common` leaf) so tests can
|
|
8
|
+
// assert the html shape without booting a browser.
|
|
9
9
|
//
|
|
10
10
|
// Why a renderer override and not a block tokenizer:
|
|
11
11
|
// - marked already handles every fence variation CommonMark / GFM
|
|
@@ -22,9 +22,7 @@
|
|
|
22
22
|
// non-mermaid fence returns `false` from here and falls through to
|
|
23
23
|
// highlight's code renderer unchanged, while a `mermaid` fence
|
|
24
24
|
// short-circuits into the placeholder and never reaches highlight.
|
|
25
|
-
|
|
26
|
-
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
27
|
-
}
|
|
25
|
+
import { escapeHtml } from "@mulmoclaude/common";
|
|
28
26
|
export const mermaidExtension = {
|
|
29
27
|
renderer: {
|
|
30
28
|
code(token) {
|
|
@@ -163,8 +163,11 @@ export function makeTasksInteractive(html) {
|
|
|
163
163
|
// marked v18 default output:
|
|
164
164
|
// <input disabled="" type="checkbox"> (unchecked)
|
|
165
165
|
// <input checked="" disabled="" type="checkbox"> (checked)
|
|
166
|
-
//
|
|
167
|
-
//
|
|
168
|
-
//
|
|
169
|
-
|
|
166
|
+
// Match those two shapes exactly and re-emit with `class="md-task"` in
|
|
167
|
+
// disabled's slot. The middle was `[^>]*` once, which is what made this
|
|
168
|
+
// quadratic: on input full of `<input =` the engine re-scans the run for
|
|
169
|
+
// every start position looking for a `disabled=""` that never arrives.
|
|
170
|
+
// An optional literal group can't backtrack, and marked emits nothing else
|
|
171
|
+
// here — the checked/unchecked pair above is the whole surface.
|
|
172
|
+
return html.replace(/<input (checked="" )?disabled="" type="checkbox">/g, '<input $1class="md-task" type="checkbox">');
|
|
170
173
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mulmoclaude/markdown-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Browser-safe markdown / image rendering utilities shared by the MulmoClaude host and the markdown plugin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -33,8 +33,9 @@
|
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"author": "Receptron Team",
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"
|
|
37
|
-
"js-yaml": "^5.2.
|
|
36
|
+
"@mulmoclaude/common": "^1.1.0",
|
|
37
|
+
"js-yaml": "^5.2.2",
|
|
38
|
+
"marked": "^18.0.7"
|
|
38
39
|
},
|
|
39
40
|
"peerDependencies": {
|
|
40
41
|
"mermaid": "^11.16.0",
|