1
0
Fork
You've already forked cms
0

Richtext format #52

Merged
ernstla merged 7 commits from rewrite/richtext-format into main 2026年07月06日 13:38:21 +02:00
No description provided.
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
All checks were successful
ci / ci (push) Successful in 2m27s
e163ae2832
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.
Drop the legacy HTML render path for richtext
All checks were successful
ci / ci (push) Successful in 2m37s
2977bd58b5
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 deleted branch rewrite/richtext-format 2026年07月06日 13:38:21 +02:00
Sign in to join this conversation.
No reviewers
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
Reference in a new issue
cosray/cms
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?