From 3a4f02f3fd779263ce43c295fc3bf2b3f6bc20c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= Date: Wed, 15 Jul 2026 01:22:22 +0300 Subject: [PATCH] Serialize the Source view as Exclusive XML Canonicalization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit serialize(indent:true()) was no canonical form at all: SaxonJS indents between the element children of mixed content (injecting whitespace that renders, e.g. around a figcaption's
s), empty elements stayed self-closed and attribute order was arbitrary. Port LinkedDataHub's ldh:canonicalize-xml instead: vendor its xml-c14n-sync.js bundle (W3C xml-exc-c14n#WithComments, the rdf:XMLLiteral value space) and run the canonical tree through it — serialize() → parse-xml() bridges the XDM temporary tree to the browser DOM the lib walks. Host pages now include the lib alongside SaxonJS3.js. Co-Authored-By: Claude Fable 5 --- CLAUDE.md | 4 ++-- README.md | 10 +++++++--- index.html | 1 + lib/xml-c14n-sync.js | 1 + src/canonical-xhtml.xsl | 5 +++-- src/edit.xsl | 12 +++++++++++- tests/fixture-dragnest.html | 1 + tests/fixture-nesting.html | 1 + tests/fixture.html | 1 + 9 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 lib/xml-c14n-sync.js diff --git a/CLAUDE.md b/CLAUDE.md index 6546a31..c9c35b6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,11 +13,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Overview -RDFa-Editor is a prototype XHTML+RDFa authoring tool using client-side XSLT. Content lives in a `#content` container of structured blocks (p, h1–h3, ul/ol, blockquote, pre, figure, table), always editable Notion-style: typing within blocks, Enter splits, Backspace-at-start merges, toolbar for block types / inline formatting / lists / figures / tables / links, drag-handle reordering (nested blocks included — every `%block` drags, drops land wherever the content model admits it), a `/` slash menu (in an empty block) and markdown shortcuts (`# `, `- `, `1. `, `> `, ` ``` `) that insert/convert blocks per the content model. Nesting follows the **XHTML Strict content model** (see content-model.xsl below): `blockquote` is a block *container* (`blockquote > p+` — bare text inside it is invalid and gets normalized; the toolbar quote toggle wraps/unwraps), `li`/`td`/`th`/`dd`/`figcaption` are `%Flow;` (mixed text AND nested blocks — Tab/Shift+Tab indent/outdent nested lists), `p`/`h1–h6`/`caption`/`dt` are inline-only. Tables are composite blocks (structure locked; `td`/`th`/`caption` editable) inserted via a rows×cols dialog with an optional header row and caption; row/column toolbar controls, Tab/Shift+Tab cell traversal and Enter (step down a column) all grow the grid at its bottom edge. Right-click a text selection to annotate it with RDFa; right-click an existing annotation to edit or remove it. "Extract RDF" shows the page's triples; "Source" shows the canonical XHTML+RDFa serialization (all editing ephemera stripped). +RDFa-Editor is a prototype XHTML+RDFa authoring tool using client-side XSLT. Content lives in a `#content` container of structured blocks (p, h1–h3, ul/ol, blockquote, pre, figure, table), always editable Notion-style: typing within blocks, Enter splits, Backspace-at-start merges, toolbar for block types / inline formatting / lists / figures / tables / links, drag-handle reordering (nested blocks included — every `%block` drags, drops land wherever the content model admits it), a `/` slash menu (in an empty block) and markdown shortcuts (`# `, `- `, `1. `, `> `, ` ``` `) that insert/convert blocks per the content model. Nesting follows the **XHTML Strict content model** (see content-model.xsl below): `blockquote` is a block *container* (`blockquote > p+` — bare text inside it is invalid and gets normalized; the toolbar quote toggle wraps/unwraps), `li`/`td`/`th`/`dd`/`figcaption` are `%Flow;` (mixed text AND nested blocks — Tab/Shift+Tab indent/outdent nested lists), `p`/`h1–h6`/`caption`/`dt` are inline-only. Tables are composite blocks (structure locked; `td`/`th`/`caption` editable) inserted via a rows×cols dialog with an optional header row and caption; row/column toolbar controls, Tab/Shift+Tab cell traversal and Enter (step down a column) all grow the grid at its bottom edge. Right-click a text selection to annotate it with RDFa; right-click an existing annotation to edit or remove it. "Extract RDF" shows the page's triples; "Source" shows the canonical XHTML+RDFa serialization (all editing ephemera stripped) in [Exclusive XML Canonicalization](https://www.w3.org/TR/xml-exc-c14n/) form (`

`, sorted attributes/namespace declarations, no indentation — the `rdf:XMLLiteral` value space). ## Architecture -XSLT 3.0 running on **SaxonJS 3** with its interactive extensions (`ixsl:` namespace). `index.html` loads `lib/SaxonJS3.js` and executes `dist/index.xsl.sef.json` (initial template `main`). The editor UI is fully generated by the stylesheet — the overlay is rendered once at startup (hidden) and only populated/shown/hidden afterwards, so the stylesheet is self-contained and embeddable on any host page. +XSLT 3.0 running on **SaxonJS 3** with its interactive extensions (`ixsl:` namespace). `index.html` loads `lib/SaxonJS3.js` plus `lib/xml-c14n-sync.js` (the exclusive-c14n serializer LinkedDataHub also ships — the "Source" view calls it through `local:canonicalize-xml` in edit.xsl, a port of LDH's `ldh:canonicalize-xml`: `serialize()` → `parse-xml()` bridges XDM to browser DOM, which the lib walks) and executes `dist/index.xsl.sef.json` (initial template `main`). The editor UI is fully generated by the stylesheet — the overlay is rendered once at startup (hidden) and only populated/shown/hidden afterwards, so the stylesheet is self-contained and embeddable on any host page (host pages must include both libs). Modules under `src/`: diff --git a/README.md b/README.md index c52c93d..0133983 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,9 @@ RDFa extraction and the document canonicalization are all XSLT. vocabulary dropdowns fed by plain ontology RDF/XML files); right-click an annotation to edit or remove it. - **Strictly W3C-conformant RDFa 1.1 extraction** to RDF/XML ("Extract RDF"), a - **canonical serialization** stripping all editing ephemera ("Source"), and + **canonical serialization** stripping all editing ephemera and emitting + [Exclusive XML Canonicalization](https://www.w3.org/TR/xml-exc-c14n/) — the + `rdf:XMLLiteral` value space ("Source"), and **RDFa lint** (unresolvable terms, unsafe markup, step-11 conflicts) surfaced as wavy underlines + a breadcrumb badge. - **Navigation**: ToC drawer (outline with section drag-reorder), breadcrumb bar with @@ -47,8 +49,10 @@ See `CLAUDE.md` for the module map and conventions. The load-bearing pieces: `src/canonical-xhtml.xsl` (canonical + sanitized serialization form, pure XSLT), `src/lint-rdfa.xsl` (pure), and the IXSL modules `edit.xsl` / `annotate.xsl` / `overlay.xsl` / `navigate.xsl` / `undo.xsl` / `vocab.xsl`. The editor's stylesheet is -self-contained: a host page provides one or more `.rdfa-editor-content` regions, `rdfa-editor.css`, and -preloads the vocabulary documents into the SaxonJS document pool (see `index.html`). +self-contained: a host page provides one or more `.rdfa-editor-content` regions, `rdfa-editor.css`, +loads `lib/xml-c14n-sync.js` (the exclusive-c14n serializer the "Source" view uses — the same lib +LinkedDataHub canonicalizes `rdf:XMLLiteral`s with), and preloads the vocabulary documents into the +SaxonJS document pool (see `index.html`). ## Embedding in LinkedDataHub diff --git a/index.html b/index.html index 1de806e..aa8d6f7 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,7 @@ RDFa Editor + + + +