No description provided.
Richtext format #52
Merged
ernstla
merged 7 commits from 2026年07月06日 13:38:21 +02:00
rewrite/richtext-format into main
ernstla
commented 2026年07月05日 23:25:07 +02:00
ernstla
added 6 commits 2026年07月05日 23:25:08 +02:00
Cosray-owned richtext storage format v1 (spec: hq/cosray/richtext-format.md): Validator (writer-strict, config-declared classes/styles), Normalizer (canonical form: key order, default omission, run merging, empty -> null), Renderer (doc -> HTML, uid resolution via Resolver, render-time link rel policy, reader-tolerant), Scanner (image.uid/link.node/link.asset), the Envelope marker, and richtext.classes/richtext.styles config.
Field/RichText saves are writer-strict: the shape requires the envelope (format/version) and validates every locale document against the spec vocabulary and the declared richtext.classes/richtext.styles; richtext blocks get the same treatment in BlockValidator. Store canonicalizes envelope-marked values on save (byte-stable storage, empty docs -> null). Value/RichText and the richtext block type render structured documents through the Renderer (legacy format-less HTML keeps the sanitizer path); uid references resolve through Owner::paths() (new UrlPaths service + paths/activeByNodeUid.sql) and the asset catalog. The serializer's asset map now includes link.asset references via Scanner::scanContent, and NodeContentNormalizer passes the envelope through byte-identically.
The editor keeps ProseMirror behind the internal driver seam (editor.ts + format.ts + schema.ts): components bind cosray richtext documents, format.ts adapts them to and from the live PM doc, legacy HTML parses through the editor schema once at mount and every save submits the envelope (host.ts/FormPatch carry format/version through the [json] channel; element.php exposes them in the SSR payload). Schema: fontSize becomes the config-declared style mark, link learns node/asset target kinds (rel dropped - render-time policy), and a new inline image node references catalog assets by uid with a thumbnail node view. Toolbar: paragraph classes and text styles come from richtext.classes/richtext.styles (empty config = no control), image insertion via a library/upload modal reusing LibraryBrowser and the pool-first upload endpoint. Richtext blocks convert and stamp the envelope the same way; their init is structured from the start.
The headless converter (panel/src/tools/richtext-convert.ts, bundled to panel/build/tools/richtext-convert.mjs) parses legacy HTML through the panel's own editor schema under jsdom, so migrated content is byte-identical to what the editor itself would produce. Migration 000000-000020 streams every legacy richtext value (fields, blocks, entries subfields; nodes + drafts) through the converter as NDJSON, resolves reference carriers (internal hrefs -> link.node via url_paths, uid-form asset URLs -> link.asset, legacy <img src> tagged with data-uid so the parse keeps them as image nodes), drops no-op cms-text-base style marks, canonicalizes through the Normalizer (empty -> null) and stamps the envelope. Idempotent: entries carrying a format key are skipped. A report at richtext-migration-report.json lists undeclared classes/styles, unresolved links, and dropped images; the seed migration records 020 for fresh installs.
Migration 020 matches internal links with trailing slashes (legacy content links pages that way) and resolves pre-catalog owner-scoped asset URLs through asset-legacy-map.json where present. The serializer's read payload gains a 'paths' map (node uid -> locale path map) for every link.node reference, mirroring the assets map so headless consumers can resolve internal richtext links.
Rename the serializer link-path map to nodePaths
e163ae2832
All checks were successful
ci / ci (push) Successful in 2m27s
read() merges the node's own 'paths' (locale to URL path of the serialized node) over the base array, which silently clobbered the new reference map.
ernstla
added 1 commit 2026年07月06日 13:34:56 +02:00
Drop the legacy HTML render path for richtext
2977bd58b5
All checks were successful
ci / ci (push) Successful in 2m37s
All databases convert through migration 020 in the same deploy, so format-less values (unmigrated legacy HTML) now render empty instead of falling back to sanitized passthrough. Value/RichText loses clean() and the sanitizer dependency (excerpt() works on the rendered output); the richtext block type renders structured documents only. The html format marker remains solely as the migration's input state.
ernstla
merged commit 2977bd58b5 into main 2026年07月06日 13:38:21 +02:00
ernstla
deleted branch rewrite/richtext-format 2026年07月06日 13:38:21 +02:00
Sign in to join this conversation.
No reviewers
Labels
Clear labels
bug
Something isn't working
dependencies
Pull requests that update a dependency file
documentation
Improvements or additions to documentation
duplicate
This issue or pull request already exists
enhancement
New feature or request
good first issue
Good for newcomers
help wanted
Extra attention is needed
invalid
This doesn't seem right
javascript
Pull requests that update javascript code
question
Further information is requested
wontfix
This will not be worked on
No labels
bug
dependencies
documentation
duplicate
enhancement
good first issue
help wanted
invalid
javascript
question
wontfix
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
cosray/cms!52
Loading...
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "rewrite/richtext-format"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?