{"_id":"@aihu/editor","name":"@aihu/editor","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.2":{"name":"@aihu/editor","version":"0.1.2","license":"MIT","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./safe-href":{"types":"./dist/safe-href.d.ts","import":"./dist/safe-href.js"},"./components/aihu-editor.aihu":"./components/aihu-editor.aihu","./components/aihu-editor-toolbar.aihu":"./components/aihu-editor-toolbar.aihu"},"sideEffects":false,"scripts":{"build":"rolldown -c","typecheck":"tsc --noEmit","test:e2e":"playwright test --config e2e/playwright.config.ts","prepublishOnly":"bun run build"},"dependencies":{"@aihu/signals":"0.5.0"},"description":"Hand-rolled, dependency-free, GX-governed rich-text editor — JSON doc model, invertible transactions, markdown (web-v1 dialect) round-trip, contenteditable view with IME-safe read-back, agent read/suggest/write surface.","repository":{"type":"git","url":"git+https://github.com/fellwork/aihu.git","directory":"packages/editor"},"homepage":"https://github.com/fellwork/aihu/tree/main/packages/editor#readme","bugs":{"url":"https://github.com/fellwork/aihu/issues"},"publishConfig":{"access":"public"},"_id":"@aihu/editor@0.1.2","_integrity":"sha512-rhEMeL59r+AXXKJ5Mg9sdIxj7ciU8i4IzDeDV03nAxzFMSzpoEF8YMCBQWeWeDQdZekQPDP85la2Y70eHGvRQg==","_resolved":"/tmp/tmp.Saqfrj5Dsp/aihu-editor-0.1.2.tgz","_from":"file:/tmp/tmp.Saqfrj5Dsp/aihu-editor-0.1.2.tgz","_nodeVersion":"22.12.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-rhEMeL59r+AXXKJ5Mg9sdIxj7ciU8i4IzDeDV03nAxzFMSzpoEF8YMCBQWeWeDQdZekQPDP85la2Y70eHGvRQg==","shasum":"2d310d97ad77f0eaf3141ff0a992d03a046de637","tarball":"https://registry.npmjs.org/@aihu/editor/-/editor-0.1.2.tgz","fileCount":13,"unpackedSize":289547,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aihu%2feditor@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFITwiZiHnFcOwPlTOPFMloh+O0ejfDTRwrNmb7hhn6OAiEA2fMqV8aPxsIfRiUODT6CudaLNhfSUEs2dtcMSic4eGI="}]},"_npmUser":{"name":"srmcguirt","email":"srmcguirt@gmail.com"},"directories":{},"maintainers":[{"name":"srmcguirt","email":"srmcguirt@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/editor_0.1.2_1785028558894_0.9174467405160809"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-26T01:15:58.693Z","0.1.2":"2026-07-26T01:15:59.037Z","modified":"2026-07-26T01:15:59.541Z"},"maintainers":[{"name":"srmcguirt","email":"srmcguirt@gmail.com"}],"description":"Hand-rolled, dependency-free, GX-governed rich-text editor — JSON doc model, invertible transactions, markdown (web-v1 dialect) round-trip, contenteditable view with IME-safe read-back, agent read/suggest/write surface.","homepage":"https://github.com/fellwork/aihu/tree/main/packages/editor#readme","repository":{"type":"git","url":"git+https://github.com/fellwork/aihu.git","directory":"packages/editor"},"bugs":{"url":"https://github.com/fellwork/aihu/issues"},"license":"MIT","readme":"# @aihu/editor\n\n> **Aihu** — agentic discovery and interaction, for human purpose.\n\nHand-rolled, dependency-free, GX-governed rich-text editor — JSON doc model, invertible transactions, markdown (web-v1 dialect) round-trip, contenteditable view with IME-safe read-back, agent read/suggest/write surface.\n\nHeld-private workspace package. Not yet published to npm.\n\n> **Status:** Held private — not yet published to npm. See [v1.1 roadmap](../../docs/roadmap/SUMMARY.md) for ratification gating (e.g. RFC #56 live-binding for `@aihu/plugin` enforcement).\n\n<!-- BEGIN_HANDWRITTEN: prose -->\n## What this is\n\nThe editor from `docs/plans/editor/architecture.md` (Phase-0 amended): no ProseMirror, no Lexical, no third-party runtime dependencies — the whole pipeline is aihu's own. Three layers:\n\n- **`EditorCore`** — DOM-free: the document model (paragraphs, headings 1–3, flat bullet/ordered lists, inline-only blockquote, hr; strong/em/code/link marks, at most one per run), serializable **invertible steps**, one `apply()` door (validate → mutate a clone → normalize → commit; never partial), and undo/redo with ~1 s typing coalescing. This is what a server or an agent test harness drives.\n- **`EditorView`** — binds a core to one `contenteditable` root. `beforeinput`-primary (unknown inputTypes fail closed), composition is browser-owned with a synchronous `takeRecords()` drain on `compositionend` (Phase-0 amendment A1), uncontrolled DOM mutations recover through a **structure-aware read-back** that preserves marks (A2), all offsets are UTF-16 code units (A3), and commands resolve the live selection from the DOM at dispatch (A4).\n- **`<aihu-editor>`** (`components/aihu-editor.aihu`) — the SFC: props/events, the `agentAccess` knob, the suggest-mode accept/reject bar, and a `mode: 'source'` markdown-textarea fallback sharing the same props/events. `<aihu-editor-toolbar>` is separate and talks only through `exec`/`can`.\n\n```ts\nimport { EditorCore, EditorView, fromMarkdown, toMarkdown } from '@aihu/editor'\n\nconst core = new EditorCore(fromMarkdown('# Hello\\n\\nworld'))\nconst view = new EditorView(document.querySelector('#surface')!, core)\ncore.onTransaction((tr, doc) => console.log(tr.origin, toMarkdown(doc)))\n```\n\n## Markdown — the web-v1 dialect\n\n`toMarkdown`/`fromMarkdown` are dialect-locked to fellwork/web's `journal/markdown.ts` **plus** the landed escape semantics of web#46: all-ASCII-punctuation backslash escapes, honored line-start escapes (`\\#`, `\\-`, `\\>`, `1\\.`, `\\---`), verbatim code spans (backtick content gets a longer delimiter, never `\\` inside a span), and no hard line breaks. The round-trip contract — `fromMarkdown(toMarkdown(d)) ≡ d` (mod ids) — is enforced by a vendored golden corpus (`tests/fixtures/golden.json`) and 1 000 fuzzed docs per run. Fenced code blocks and pipe tables are v2: they import as degraded paragraphs, and the editor never emits them.\n\n## Security posture\n\nNo HTML sink anywhere — rendering is `createElement`/`createTextNode` only, enforced by a runnable grep gate (`tests/no-html-sink.test.ts`). Paste goes through an inert `DOMParser` allowlist walk that drops every attribute except `a[href]`, and hrefs pass `safeHref` (same contract as web; exported standalone as `@aihu/editor/safe-href`) **at model write time** — a `javascript:` href cannot exist in the doc, whether it arrives by paste, typing, or an agent's `applyMark`.\n\n## The GX surface\n\nThe thesis-critical part: the keyboard and the agent share ONE transaction pipeline.\n\n- **Read** (`expose: read`): `doc`, `docMarkdown`, `docOutline`, `selectionContext`.\n- **Write** (`expose: read write`): `insertBlock`, `replaceRange`, `applyMark`, `applyTransaction` — all validated by the same `EditorCore.apply()` as keystrokes, all landing in the shared undo history with `origin: 'agent:<tool>'`. A human Ctrl-Z reverts an agent edit and vice versa.\n- **`agentAccess` prop**: `'none' | 'read' | 'suggest' | 'write'`, default `'read'`, failing closed on unknown values. In `'suggest'` mode writes are validated but **staged** as accept/reject proposals — the human governs, the agent proposes through the same typed channel.\n\n## Testing\n\n- Unit (vitest/jsdom): core, steps/inversion, history, serializers + round-trip fuzz, input rules, commands, paste sanitization, position map, read-back, view, agent gateway, compile gate for the SFCs.\n- Real browsers (Playwright, chromium+webkit+firefox): `bun run test:e2e` — typing/IME (real Chromium IME via CDP), paste, agent tiers, structure-aware read-back, selection survival. Playwright is a root devDependency.\n<!-- END_HANDWRITTEN: prose -->\n\n## Install\n\n<!-- BEGIN_AUTOGEN: install -->\n<!-- regenerate: bun scripts/sync-readme.ts (also runs in pre-commit + CI) -->\n\n```bash\nnpm install @aihu/editor\n# or\nbun add @aihu/editor\n```\n\n<sub><i>Auto-generated against `@aihu/editor@0.1.2`.</i></sub>\n\n<!-- END_AUTOGEN: install -->\n\n## Package facts\n\n<!-- BEGIN_AUTOGEN: stats -->\n<!-- regenerate: bun scripts/sync-readme.ts (also runs in pre-commit + CI) -->\n\n| | |\n|---|---|\n| **Version** | `0.1.2` |\n| **Tier** | G — Content — GX-governed rich-text editor (JSON doc model + transactions) |\n| **Bundle size** | 13.56 kB (gz) — limit 14 KB |\n| **Published files** | 4 entries |\n| **License** | MIT |\n\n<sub><i>Auto-generated against `@aihu/editor@0.1.2`.</i></sub>\n\n<!-- END_AUTOGEN: stats -->\n\n## Exports\n\n<!-- BEGIN_AUTOGEN: exports -->\n<!-- regenerate: bun scripts/sync-readme.ts (also runs in pre-commit + CI) -->\n\n| Subpath | ESM | CJS |\n|---|---|---|\n| `.` | `./dist/index.js` | `—` |\n| `./safe-href` | `./dist/safe-href.js` | `—` |\n| `./components/aihu-editor.aihu` | `./components/aihu-editor.aihu` | — |\n| `./components/aihu-editor-toolbar.aihu` | `./components/aihu-editor-toolbar.aihu` | — |\n\n<sub><i>Auto-generated against `@aihu/editor@0.1.2`.</i></sub>\n\n<!-- END_AUTOGEN: exports -->\n\n## Dependencies\n\n<!-- BEGIN_AUTOGEN: deps -->\n<!-- regenerate: bun scripts/sync-readme.ts (also runs in pre-commit + CI) -->\n\n**Dependencies:**\n\n- `@aihu/signals` — `workspace:*`\n\n<sub><i>Auto-generated against `@aihu/editor@0.1.2`.</i></sub>\n\n<!-- END_AUTOGEN: deps -->\n\n## See also\n\n<!-- BEGIN_AUTOGEN: see-also -->\n<!-- regenerate: bun scripts/sync-readme.ts (also runs in pre-commit + CI) -->\n\n- [@aihu/agent](../agent)\n- [@aihu/store](../store)\n- [Aihu framework root](../../README.md)\n\n<sub><i>Auto-generated against `@aihu/editor@0.1.2`.</i></sub>\n\n<!-- END_AUTOGEN: see-also -->\n\n## License\n\n<!-- BEGIN_AUTOGEN: license -->\n<!-- regenerate: bun scripts/sync-readme.ts (also runs in pre-commit + CI) -->\n\nMIT — see [LICENSE](../../LICENSE).\n\n<sub><i>Auto-generated against `@aihu/editor@0.1.2`.</i></sub>\n\n<!-- END_AUTOGEN: license -->\n","readmeFilename":"README.md","_rev":"1-11c9f76cd17ddff6fa7d52e6329bab14"}