Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
218f802
docs(hangul): record isolated workstream
seonghobae Aug 13, 2026
7c02a72
test(hangul): define HWP and HWPX authoring contract
seonghobae Aug 13, 2026
35dabb5
feat(hangul): add bridge module boundary
seonghobae Aug 13, 2026
88d77be
feat(hangul): implement editable document bridge
seonghobae Aug 13, 2026
4a1160a
docs(hangul): add HWP/HWPX authoring ADR
seonghobae Aug 13, 2026
026bfa8
test(hangul): cover HWP and conversion failure boundaries
seonghobae Aug 13, 2026
4288002
docs(hangul): document import edit and export contract
seonghobae Aug 13, 2026
1ab306d
build(hangul): add isolated package bundle
seonghobae Aug 13, 2026
a75f53e
build(hangul): publish framework-neutral package subpath
seonghobae Aug 13, 2026
acb9b33
test(hangul): verify packed package consumers
seonghobae Aug 13, 2026
56ed351
test(hangul): define optional RHWP adapter contract
seonghobae Aug 13, 2026
d5613c7
feat(hangul): add parser module adapter
seonghobae Aug 13, 2026
cb5b21b
test(hangul): exercise generic parser module adapter
seonghobae Aug 13, 2026
c8979f9
build(hangul): add package entrypoint file
seonghobae Aug 13, 2026
5b0e402
feat(hangul): expose bridge and module adapter
seonghobae Aug 13, 2026
7b50641
fix(hangul): preserve ES2018 HTML escaping
seonghobae Aug 13, 2026
1fabafb
docs(adr): align Hangul rollback heading
seonghobae Aug 13, 2026
1f3ada6
docs(package): discover Hangul subpath
seonghobae Aug 13, 2026
4ed9a87
docs(readme): list Hangul package surface
seonghobae Aug 13, 2026
f4374d6
test(hangul): close public bridge coverage gaps
seonghobae Aug 13, 2026
28e5aa7
fix(hangul): remove unreachable mark fallback branches
seonghobae Aug 13, 2026
512df0a
fix(hangul): remove TipTap declaration dependency
seonghobae Aug 13, 2026
7c78edf
test(hangul): require payload-redacted export diagnostics
seonghobae Aug 14, 2026
fe54337
fix(hangul): redact unsupported type diagnostics
seonghobae Aug 14, 2026
40223e5
test(hangul): preserve common document structures
seonghobae Aug 14, 2026
ec3343f
feat(hangul): preserve common document structures
seonghobae Aug 14, 2026
628fc51
test(hangul): reject unsupported imported blocks
seonghobae Aug 14, 2026
7959d2f
fix(hangul): reject unsupported imported blocks
seonghobae Aug 15, 2026
ea8b1c9
test(hangul): expose lossy unsupported inline import
seonghobae Aug 15, 2026
f804a0c
fix(hangul): reject unsupported imported inline marks
seonghobae Aug 15, 2026
a4b7130
fix(hangul): preserve transparent inline wrappers
seonghobae Aug 15, 2026
bcfb5b4
test(hangul): contain hostile engine throw values
seonghobae Aug 15, 2026
63f6573
fix(hangul): brand module-owned engine errors
seonghobae Aug 15, 2026
561b08a
test(hangul): reject invalid byte limits before engine work
seonghobae Aug 16, 2026
aad9956
fix(hangul): validate runtime byte limits
seonghobae Aug 16, 2026
6bf3fd8
test(hangul): cover hostile source byteLength override
seonghobae Aug 16, 2026
8b0c770
test(hangul): cover forged and shared source views
seonghobae Aug 16, 2026
9b8566a
fix(hangul): snapshot untrusted source bytes
seonghobae Aug 16, 2026
fee63ea
test(hangul): cover hostile engine output views
seonghobae Aug 16, 2026
a1a452e
test(hangul): keep output boundary regression type-safe
seonghobae Aug 16, 2026
1f2639b
fix(hangul): snapshot untrusted engine output bytes
seonghobae Aug 16, 2026
83c5a2f
test(hangul): cover hostile import engine operation failures
seonghobae Aug 16, 2026
38407d1
fix(hangul): contain hostile import operation failures
seonghobae Aug 16, 2026
d87e726
test(hangul): reject invalid runtime export formats
seonghobae Aug 16, 2026
43bbb37
fix(hangul): validate runtime export format
seonghobae Aug 16, 2026
136bead
test(docs): require ADR discovery consistency
seonghobae Aug 16, 2026
d772aa2
fix(docs): assign unique Hangul ADR 0030
seonghobae Aug 16, 2026
31e51df
test(hangul): expose cleanup failure escape
seonghobae Aug 17, 2026
5b690bf
fix(hangul): contain engine cleanup failures
seonghobae Aug 17, 2026
5065766
test(hangul): bind documented compatibility to implementation
seonghobae Aug 17, 2026
3998f0f
docs(hangul): reconcile implemented compatibility
seonghobae Aug 17, 2026
f9048de
test(hangul): expose hostile option access failure
seonghobae Aug 17, 2026
c697bf1
test(hangul): reach hostile option behavior boundary
seonghobae Aug 17, 2026
bbce45d
fix(hangul): contain hostile option access
seonghobae Aug 17, 2026
2b072d6
test(hangul): use repository-relative documentation path
seonghobae Aug 17, 2026
f90d32a
test(hangul): require public capability metadata
seonghobae Aug 17, 2026
62a26e7
fix(hangul): return deterministic capability metadata
seonghobae Aug 17, 2026
3cbbc8c
docs(hangul): document public capability metadata
seonghobae Aug 17, 2026
b0aa788
test(hangul): bind guide to capability contract
seonghobae Aug 17, 2026
5dd74fe
test(hangul): reject malformed engine structural metadata
seonghobae Aug 17, 2026
f39ed00
test(hangul): require stable single-read section metadata
seonghobae Aug 17, 2026
a5ce70a
test(hangul): reject malformed export structural metadata
seonghobae Aug 17, 2026
f318699
fix(hangul): validate engine structural metadata
seonghobae Aug 17, 2026
cf5060b
test(hangul): contain hostile document JSON access
seonghobae Aug 17, 2026
d90333a
fix(hangul): contain document JSON inspection failures
seonghobae Aug 17, 2026
2b39a64
test(hangul): preserve direct list item content
seonghobae Aug 17, 2026
9f78831
fix(hangul): preserve direct list item content
seonghobae Aug 17, 2026
666025c
test(hangul): cover mixed inline element list content
seonghobae Aug 17, 2026
a602c22
fix(hangul): make text-node list invariant explicit
seonghobae Aug 17, 2026
a82d638
test(hangul): reject non-string engine text before member access
seonghobae Aug 17, 2026
38e0ff0
fix(hangul): validate host engine text before use
seonghobae Aug 17, 2026
e098292
test(hangul): project known HWP/HWPX fixtures
cursoragent Aug 17, 2026
f51cdd7
docs(hangul): bind fixture fail-closed contract
cursoragent Aug 17, 2026
030512a
test(hangul): bound hostile engine metadata
seonghobae Aug 20, 2026
88936bd
fix(hangul): bound engine traversal metadata
seonghobae Aug 20, 2026
dcefbe6
test(hangul): contract traversal safety limits
seonghobae Aug 20, 2026
487e6cb
docs(hangul): specify traversal safety ceilings
seonghobae Aug 20, 2026
5ee6e4d
docs(hangul): record bounded host metadata decision
seonghobae Aug 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ runtime.
| React editor | `@contextualwisdomlab/cwl-editor` | Markdown/HTML WYSIWYG component and serializers |
| Collaboration | `@contextualwisdomlab/cwl-editor/collaboration` | Provider-neutral Yjs collaborative editing |
| Converter | `@contextualwisdomlab/cwl-editor/converter` | Framework-independent base64/data-URI utilities |
| Hangul documents | `@contextualwisdomlab/cwl-editor/hangul` | Framework-independent HWP/HWPX import/export bridge with a host-injected engine |
| Envelope identity | `@contextualwisdomlab/cwl-editor/envelope-identity` | Framework-independent bounded schema identity for host-owned migration routing |
| Revision evidence | `@contextualwisdomlab/cwl-editor/revision-evidence` | Framework-independent canonical envelope, strong revision, and transition evidence |
| Text-position selector | `@contextualwisdomlab/cwl-editor/text-position-selector` | React-free deterministic W3C `TextPositionSelector` projection core |
Expand Down
139 changes: 139 additions & 0 deletions docs/HANGUL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# HWP and HWPX authoring

Inkspan's Hangul bridge opens HWP/HWPX bytes through a host-provided parser/serializer and projects supported content into the same TipTap/ProseMirror JSON edited by `CwlEditor`. HWPX is the recommended save target because it is the open XML/OWPML path standardized by KS X 6101; legacy HWP remains an explicit compatibility target when the selected engine supports it.

## Authority boundary

Inkspan owns:

- the editable TipTap JSON projection;
- deterministic conversion rules;
- stable error semantics;
- byte/resource limits;
- explicit loss reporting;
- deterministic public capability metadata for the bounded bridge.

The host owns:

- file pickers and drag/drop;
- filesystem and object-storage access;
- WASM or native-engine initialization;
- passwords and protected-document UX;
- publication/download behavior;
- telemetry and persistence.

The Hangul package never fetches external resources and never executes active content from a document.

## Import flow

```mermaid
sequenceDiagram
participant Host
participant Bridge as Inkspan Hangul bridge
participant Engine as Host-provided HWP engine
participant Editor as CwlEditor

Host->>Bridge: openHangulDocument(bytes, { engine })
Bridge->>Engine: open(bytes)
Engine-->>Bridge: bounded document API
Bridge->>Engine: source format / sections / HTML projection
Bridge-->>Host: { documentJson, sourceFormat, warnings, lossy, capabilities }
Host->>Editor: setDocumentJson(documentJson)
```

The original bytes remain host-owned. Importing a file does not mutate it. The returned `capabilities` object is frozen, deterministic Inkspan metadata: it declares `importFormats`, `exportFormats`, `recommendedExportFormat`, and the currently round-trippable `supportedContent`. Hosts can use that metadata for UI and routing without probing the host engine or inferring support from failures.

## Export flow

```mermaid
sequenceDiagram
participant Host
participant Editor as CwlEditor
participant Bridge as Inkspan Hangul bridge
participant Engine as Host-provided HWP engine

Host->>Editor: getDocumentJson()
Editor-->>Host: edited JSON
Host->>Bridge: exportHangulDocument(JSON, format)
Bridge->>Engine: create blank document
Bridge->>Engine: paste bounded deterministic HTML
Bridge->>Engine: exportHwpx() or exportHwp()
Engine-->>Bridge: bytes
Bridge-->>Host: { bytes, format, warnings }
```

## Minimal integration

```ts
import {
exportHangulDocument,
openHangulDocument,
type HangulDocumentEngine,
} from '@contextualwisdomlab/cwl-editor/hangul';

async function openIntoEditor(
source: Uint8Array,
engine: HangulDocumentEngine,
editor: { setDocumentJson(value: unknown): void },
) {
const imported = await openHangulDocument(source, { engine });
editor.setDocumentJson(imported.documentJson);
return imported;
}

async function saveAsHwpx(
documentJson: Parameters<typeof exportHangulDocument>[0],
engine: HangulDocumentEngine,
) {
return exportHangulDocument(documentJson, {
engine,
format: 'hwpx',
});
}
```

## Compatibility contract

The initial bridge deliberately supports a bounded semantic subset and rejects unsupported export nodes instead of silently deleting them. The compatibility matrix expands only when real HWP/HWPX fixtures demonstrate stable round-trip behavior. `capabilities.supportedContent` is the machine-consumable projection of the same currently implemented subset; this table remains the human-readable contract and limitation guide.

Committed synthetic OWPML fixtures under `src/hangul/fixtures/` are the current known-document suite. `briefing-minutes.section.xml` must project to the expected heading, paragraph, and table cells when wrapped as HWPX or legacy HWP. `unsupported-shape.section.xml` must fail closed; Inkspan does not keep surrounding paragraphs while dropping a shape. After export, the same fixture engine reopens the bytes and compares semantic JSON. These fixtures are synthetic and contain no customer documents. To inspect a mismatch, open the exact source fixture and compare it against the committed expected paragraphs and tables.

| Content | Import | Export | Notes |
|---|---|---|---|
| Paragraph text | Yes | Yes | Unicode preserved by JavaScript strings and the selected engine |
| Headings 1-6 | Yes | Yes | Semantic heading level |
| Bold | Yes | Yes | Common HTML projection |
| Italic | Yes | Yes | Common HTML projection |
| Strike | Yes | Yes | Common HTML projection |
| Lists | Yes | Yes | Structural bullet and ordered lists; explicit start-number metadata is not modeled |
| Block quotes | Yes | Yes | Nested supported block content is preserved |
| Code blocks | Yes | Yes | Text content is preserved; language metadata is not modeled |
| Basic tables | Yes | Yes | Header/cell topology is preserved; spans and layout styling are not modeled |
| Links | Planned | Planned | Must use Inkspan safe-link policy |
| Images | Planned | Planned | Must remain inline/host-approved; no external fetch |
| Shapes/charts/equations | Rejected | Rejected | Fail closed; no silent drop |
| Macros/OLE/active content | Not executed | Not generated | Outside the editor authority boundary |

## Failure containment

The host engine is untrusted at every call boundary, including cleanup. Open/create/operation failures are normalized to stable payload-redacted `HangulDocumentError` values. If engine cleanup fails after an otherwise successful public operation, Inkspan reports `ENGINE_CLEANUP_FAILED` without reading or stringifying the host-thrown value. If cleanup fails while Inkspan is already propagating a normalized primary import/export error, the primary error remains authoritative and the secondary cleanup failure is contained.

## Security requirements

Treat both formats as untrusted document containers. Production implementations must enforce bounded source and output bytes. The bridge also rejects host structural metadata above 4,096 sections, 1,000,000 paragraphs per section, or 16,777,216 UTF-16 code units per paragraph before traversing or passing those values back to the host engine. These are Inkspan safety ceilings, not HWP/HWPX format maxima.

A native HWPX implementation must additionally bound ZIP entry count, expanded bytes, expansion ratio, XML depth, XML node count, text size, relationships, and embedded payloads. DTD and external entity resolution must be disabled. External relationships are metadata only unless the host separately authorizes a resource.

Passwords, cookies, credentials, filesystem paths, and secret values must never enter warnings, error strings, result objects, or deterministic snapshots.

## Standards and format sources

HWPX follows OWPML document structure standardized as KS X 6101. The Korean standards catalogue records the standard as confirmed on 2024-10-30. Hancom publishes HWP 5.x and OWPML format material and recommends HWPX as the open machine-readable Hangul document format.

### References (APA 7th)

Korean Agency for Technology and Standards. (2024). *KS X 6101: Open Word-Processor Markup Language (OWPML) document structure*. e-Nara Standard Certification. https://www.standard.go.kr/KSCI/standardIntro/getStandardSearchView.do?ksNo=KSX6101

Hancom Inc. (n.d.). *HWP/OWPML formats*. https://license.hancom.com/support/downloadCenter/hwpOwpml

Hancom Inc. (n.d.). *HWPX format structure*. Hancom Tech. https://tech.hancom.com/hwpxformat/
76 changes: 76 additions & 0 deletions docs/adr/0030-hangul-document-authoring-boundary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# ADR 0030: Hangul document authoring boundary

- Status: Proposed
- Date: 2026-08-14
- Decision owners: Inkspan maintainers

## Context

Inkspan needs to open, edit, and save Korean Hangul Word Processor documents without turning the editor package into a filesystem-, network-, or vendor-runtime-owning application. HWP 5.x is a published binary format. HWPX is the XML-based Hangul standard-document format built on OWPML, whose document structure is standardized as KS X 6101. The Korean standards catalogue records KS X 6101 as current after confirmation on 2024-10-30. Hancom also publishes HWP/OWPML format material and describes HWPX as an OWPML-based, machine-readable format.

The editor already treats TipTap/ProseMirror JSON as the editable document authority. Introducing a second editable authority for HWP/HWPX would make autosave, collaboration, revision evidence, and host integration inconsistent.

## Alternatives considered

1. Parse HWP/HWPX directly inside the React editor. Rejected because binary/XML parsing, optional WASM initialization, document resources, and UI lifecycle become coupled.
2. Convert every document through HTML and keep HTML as the editing authority. Rejected because HTML cannot represent every Hangul layout primitive and would make conversion loss implicit.
3. Introduce a framework-neutral Hangul bridge with a host-injected parser/serializer engine and TipTap JSON as the editing authority. Selected.

## Decision

Inkspan exposes a framework-neutral Hangul bridge under a dedicated package boundary. The bridge accepts HWP/HWPX bytes through a host-injected engine, projects the supported semantic subset to TipTap JSON, and serializes edited JSON back through the engine. HWPX is the recommended export format because it is the open XML/OWPML path; HWP remains an explicit compatibility export.

The host owns file selection, filesystem access, network access, WASM/module initialization, password UX, persistence, and download/publication. The bridge receives bytes and returns bytes. It never fetches external document resources.

Unsupported structures are never silently asserted to be lossless. Import results carry warnings and a lossy flag. Export rejects editor structures that cannot be represented by the current bridge rather than dropping them silently.

Host-returned structural metadata is untrusted work/index input. Before traversing or passing such metadata back into the host engine, Inkspan rejects values above 4,096 sections, 1,000,000 paragraphs per section, or 16,777,216 UTF-16 code units per paragraph. These are Inkspan safety ceilings, not HWP/HWPX format maxima; changing them is a resource-safety decision that requires corresponding regression evidence.

## Consequences

- Existing `CwlEditorHandle.setDocumentJson()` remains the single editing ingress.
- HWP and HWPX share one product API while their parsing implementations remain replaceable.
- Parser/serializer upgrades do not require React changes.
- Full visual round-trip fidelity is not claimed until covered by real-document compatibility fixtures.
- HWPX can later gain a first-party native OWPML implementation without changing the public bridge contract.
- A forged engine cannot turn a small input into effectively unbounded section traversal or oversized paragraph indexes/offsets merely by returning safe-integer metadata.

## Failure and recovery semantics

Malformed input, unsupported source identity, resource-limit breaches, engine failures, and unsupported export structures fail closed with stable error codes. The original input is never mutated. Hosts may keep the original bytes and offer a fallback download or alternate viewer.

## Security and privacy impact

HWP/HWPX bytes are untrusted input. The bridge has no remote-resource fetch path and no active-content execution path. Source and output byte bounds are enforced before publication. Host structural counts and paragraph lengths are bounded before traversal, indexing, deletion, or HTML projection. Credentials, cookies, filesystem paths, and document passwords are not part of result objects or telemetry contracts.

A future native HWPX parser must additionally bound ZIP entries, expansion ratio, XML depth, XML node count, text length, relationship targets, embedded objects, and external references. DTD and external-entity resolution must remain disabled.

## Compatibility and migration

The public contract identifies source and output as `hwp` or `hwpx`. HWPX is preferred for newly saved documents. Existing HWP users can explicitly request HWP export when their selected engine supports it. If a later native HWPX implementation replaces the initial engine adapter, compatibility is governed by the same JSON projection tests and real-document fixture suite.

## Verification and acceptance evidence

Acceptance requires all of the following on one exact PR head:

- HWP and HWPX import tests;
- edited JSON to HWPX and HWP export tests;
- committed synthetic `briefing-minutes` and `unsupported-shape` fixtures that project known paragraphs/tables and fail closed on unsupported structures;
- real documents reopened after export and compared against expected semantic content;
- hostile/malformed input and resource-limit tests, including over-limit host section/paragraph metadata that fails before child traversal or host mutation;
- package-consumer verification for ESM, CommonJS, and declarations;
- production statement and branch coverage at repository policy thresholds;
- public API docstring coverage at repository policy thresholds;
- required CI, SAST, security, and independent review gates.

Until that evidence is merged to protected `main`, this ADR remains Proposed.

## Rollback or supersession

The feature can be rolled back by removing the Hangul package subpath while retaining this ADR as historical evidence. A future design that makes native OWPML the canonical editable authority or grants the package filesystem/network authority requires a superseding ADR.

## Standards and source traceability

- Korean Agency for Technology and Standards. (2024). *KS X 6101: Open Word-Processor Markup Language (OWPML) document structure*. e-Nara Standard Certification. https://www.standard.go.kr/KSCI/standardIntro/getStandardSearchView.do?ksNo=KSX6101
- Hancom Inc. (n.d.). *HWP/OWPML formats*. https://license.hancom.com/support/downloadCenter/hwpOwpml
- Hancom Inc. (n.d.). *HWPX format structure*. Hancom Tech. https://tech.hancom.com/hwpxformat/
1 change: 1 addition & 0 deletions docs/adr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ This index records durable architectural decisions. Protected-main implementatio
| [0024](0024-bounded-docx-paragraph-alignment.md) | Accepted | Bounded paragraph alignment in deterministic DOCX output |
| [0025](0025-bounded-docx-heading-alignment.md) | Accepted | Bounded heading alignment in deterministic DOCX output |
| [0026](0026-bounded-docx-external-hyperlinks.md) | Accepted | Bounded external hyperlinks in deterministic DOCX rich text |
| [0030](0030-hangul-document-authoring-boundary.md) | Proposed | Hangul document authoring boundary |

## Decision discipline

Expand Down
3 changes: 3 additions & 0 deletions docs/hangul-workstream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# HWP and HWPX workstream

This branch tracks the isolated, non-release implementation for issue #319.
24 changes: 15 additions & 9 deletions docs/package-distribution.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Package distribution and consumer contract

Inkspan publishes the React editor, provider-neutral collaboration adapter,
framework-independent autosave/evidence/converter utilities, CSS, and offline
font assets from one npm package. This document defines the supported package
boundary for standalone applications, CWL organization services, and naruon
integrations.
framework-independent autosave/evidence/converter/Hangul utilities, CSS, and
offline font assets from one npm package. This document defines the supported
package boundary for standalone applications, CWL organization services, and
naruon integrations.

## Public entrypoints

Expand All @@ -14,6 +14,7 @@ integrations.
| `@contextualwisdomlab/cwl-editor/autosave` | Framework-independent autosave queue/session APIs for bounded local save ordering and host-owned durable concurrency |
| `@contextualwisdomlab/cwl-editor/collaboration` | Optional Yjs collaboration surface with host-owned transport and lifecycle |
| `@contextualwisdomlab/cwl-editor/converter` | Framework-independent base64 and data-URI utilities |
| `@contextualwisdomlab/cwl-editor/hangul` | `implemented_on_active_pr` — framework-independent HWP/HWPX byte-to-document bridge with a host-injected parser/serializer engine; filesystem, network, persistence, credentials, and publication remain host-owned |
| `@contextualwisdomlab/cwl-editor/envelope-identity` | Framework-independent identity-only envelope routing for bounded schema identity inspection; migration remains host-owned |
| `@contextualwisdomlab/cwl-editor/revision-evidence` | Framework-independent revision evidence and document-transition evidence for local content equality/lineage claims |
| `@contextualwisdomlab/cwl-editor/text-position-selector` | `implemented_on_protected_main` — React-free text-position projection core implementing W3C `TextPositionSelector`; interactive capture, revision binding, authorization, persistence, and re-anchoring remain outside this subpath |
Expand Down Expand Up @@ -57,12 +58,17 @@ embedded in the npm tarball.
and collaboration entrypoints. It is declared in Inkspan's package
dependencies so the consumer's package manager installs and resolves it; it
is not merely a type-only dependency.
- The framework-independent autosave, converter, envelope-identity,
- The framework-independent autosave, converter, Hangul, envelope-identity,
revision-evidence, text-position-selector, and Markdown entrypoints do not
require React UI, a mounted editor, naruon, contextual-orchestrator, a
database, provider credentials, or host transport. Their individual
package-consumer gates additionally prevent framework dependencies from
leaking into subpaths whose public contracts exclude them.
- The Hangul subpath accepts and returns bytes through a host-injected document
engine. Inkspan owns the deterministic supported JSON projection, local
source/output resource ceilings, and stable failure contract; the host owns
file selection, filesystem and network access, engine/WASM initialization,
password UX, durable persistence, credentials, and artifact publication.
- The Markdown subpath exposes `markdownToHtml`, `htmlToMarkdown`,
`normalizeMarkdown`, `markdownToEmailHtml`, `markdownToPlainText`, and
`htmlToPlainText` plus their option types. It bundles deterministic conversion
Expand Down Expand Up @@ -108,10 +114,10 @@ production library build. The verification chain:
3. confirms required licenses, declarations, styles, and font assets ship;
4. rejects internal source, tests, demos, Office files, coverage output, and
workflow files from the npm tarball;
5. imports the root, collaboration, converter, autosave, envelope-identity,
revision-evidence, text-position-selector, and Markdown surfaces through their
dedicated packed-consumer checks, including framework-free isolation where
that is part of the public contract;
5. imports the root, collaboration, converter, Hangul, autosave,
envelope-identity, revision-evidence, text-position-selector, and Markdown
surfaces through their dedicated packed-consumer checks, including
framework-free isolation where that is part of the public contract;
6. exercises supported ESM/CommonJS entrypoints and compiles strict TypeScript
consumers against the published declaration surfaces;
7. resolves public CSS and font subpaths; and
Expand Down
Loading
Loading