@mulmoclaude/markdown-utils 1.2.0 → 1.3.1

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 CHANGED
@@ -1,3 +1,11 @@
1
1
  # @mulmoclaude/markdown-utils
2
2
 
3
3
  Browser-safe markdown / image rendering utilities shared by the MulmoClaude host and the markdown plugin.
4
+
5
+ ## Related projects
6
+
7
+ Published from the MulmoClaude monorepo by [Receptron](https://github.com/receptron).
8
+
9
+ - **[MulmoClaude](https://github.com/receptron/mulmoclaude)** — an open-source AI assistant platform that runs on your own computer. Claude Code as the engine, a personal wiki for long-term memory, schema-driven collections for your data, and chat that summons the right GUI (markdown, charts, forms, spreadsheets, wikis) for each task.
10
+ - **[MulmoTerminal](https://github.com/receptron/mulmoterminal)** — a terminal-first cockpit for running many AI coding agents in parallel. One roster showing every session's summary and PR status, tmux-backed session persistence, git-worktree isolation, one-click PRs, and mobile push with remote reply.
11
+ - **[MulmoTerminal manual](https://receptron.github.io/mulmoterminal/)** — setup, workflows, feature reference, configuration, mobile notifications, and alternative / local model providers. Available in English and Japanese.
@@ -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`) so tests can assert the html shape without booting a
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
- function escapeHtml(text) {
26
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
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
- // Both end with ` type="checkbox">`. Capture everything between
167
- // `<input ` and `disabled=""` (typically empty or `checked="" `)
168
- // and re-emit with `class="md-task"` in disabled's slot.
169
- return html.replace(/<input ([^>]*)disabled="" type="checkbox">/g, '<input $1class="md-task" type="checkbox">');
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.2.0",
3
+ "version": "1.3.1",
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
- "marked": "^18.0.6",
37
- "js-yaml": "^5.2.1"
36
+ "@mulmoclaude/common": "^1.1.1",
37
+ "js-yaml": "^5.2.2",
38
+ "marked": "^18.0.7"
38
39
  },
39
40
  "peerDependencies": {
40
41
  "mermaid": "^11.16.0",
@@ -44,5 +45,20 @@
44
45
  "mermaid": "^11.16.0",
45
46
  "typescript": "^6.0.3",
46
47
  "vue": "^3.5.40"
48
+ },
49
+ "homepage": "https://github.com/receptron/mulmoclaude/tree/main/packages/markdown-utils#readme",
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/receptron/mulmoclaude.git",
53
+ "directory": "packages/markdown-utils"
54
+ },
55
+ "keywords": [
56
+ "mulmoclaude",
57
+ "markdown",
58
+ "rendering",
59
+ "browser-safe"
60
+ ],
61
+ "bugs": {
62
+ "url": "https://github.com/receptron/mulmoclaude/issues"
47
63
  }
48
64
  }