diff --git a/CLAUDE.md b/CLAUDE.md
index 4351540..05937cc 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -8,7 +8,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- **Undo is region-keyed**: one global stack, each stash entry carries `data-root` (region index) and restores only its region; caret data is region-relative. Stash ids: `rdfa-editor-undo-storage/-stack/-redo-stack`.
- Blocks never move between regions (drop-target resolution is scoped to the dragged block's region). ToC and view-source follow the active region (`tocRoot` remembered at render); lint and find work across all regions.
- **Editor state lives on one window container** `window.rdfaEditor` — a single object created with `Object()` in the `main` template (mirrors LinkedDataHub's `window.LinkedDataHub`), holding all mutable state under bare names (`range`, `activeBlock`, `editingSpan`, …). Every read/write goes through the `rdfae:editor-state()` accessor (`index.xsl`): reads `ixsl:get(rdfae:editor-state(), 'range')`, writes `object="rdfae:editor-state()"`. Browser globals (`scrollX`, `Date`, `location.href`, …) are read straight off `ixsl:window()` and are not editor state. Editor UI containers carry the `rdfa-editor-ui` class and all generic CSS selectors (`.btn-*`, `.modal-*`, `.crumb`, …) are scoped under it — LDH/Bootstrap pages stay unaffected.
-- The extractor entry is a **named template only** (`-it:extract-rdfa`; no unnamed-mode `match="/"`) so it composes with host stylesheets' root templates. Integration with LinkedDataHub's client.xsl is compile-proven (see docs/ldh/MIGRATION.md §10).
+- The extractor entry is a **named template only** (`rdfax:extract-rdfa`, invoked headless as `-it:"Q{https://w3id.org/atomgraph/rdfa-editor/rdfa#}extract-rdfa"`; no unnamed-mode `match="/"`) so it composes with host stylesheets' root templates. Integration with LinkedDataHub's client.xsl is compile-proven (see docs/ldh/MIGRATION.md §10).
- Links in content: plain click places the caret (links render with a text I-beam, not a pointer, so the affordance matches — they are editable text); Ctrl/Cmd+Click opens the href. The annotation overlay paints the stored selection as `.rdfa-editor-selection-hint` boxes (no content mutation), cleared on hide.
## Overview
@@ -61,7 +61,7 @@ Run `make sef` after any XSLT change; run the tests after any extractor change.
- **No deviation from W3C specs.** The extractor follows the RDFa 1.1 processing rules exactly. Markup that relies on non-conformant readings (e.g. `about="#part" property="schema:hasPart"` expected to yield an edge) is a markup bug — the conformant containment idiom is `property="…hasPart" resource="#part" typeof="…"`.
- **Content model: XHTML 1.0 Strict + HTML5 figure**, transcribed in `content-model.xsl` — nesting the DTD allows must round-trip intact; nesting it disallows is normalized at boundaries (canonical serialization, paste, load-init) and reported by lint. This changed the **storage contract for blockquote**: it is block-only, so stored bare-text quotes are rewritten to `blockquote > p` once at load/save (LDH content audit advised).
- All `innerHTML` writes of serialized XDM use `serialize(…, map{ 'method': 'html' })` — XML's self-closing `
&accept=application/rdf+xml` endpoint (constructor.xsl:203-209 pattern) via `ixsl:promise`; typeahead control (LDH typeahead.xsl precedent) replaces the selects.
7. **i18n** — strings into `translations.rdf` (`key('resources', id, document(...))` + `ac:label`).
8. **Feature flag** — decision DEFERRED (user); document options: `lapp:Application` property / XSL param via web.xml / hard cutover.
-9. **Build** — modules pulled into the LDH webapp tree at build time and `xsl:import`ed from `client.xsl`; existing pom `xslt3-he … -relocate:on` step compiles everything (pom.xml:39, 383-391). Conflict audit checklist: our unnamed-mode `match="/"` (extract-rdfa) vs LDH root templates, `body` keydown fallback, host-level event templates, `xsl:output`, `id('content')` assumptions.
+9. **Build** — modules pulled into the LDH webapp tree at build time and `xsl:import`ed from `client.xsl`; existing pom `xslt3-he … -relocate:on` step compiles everything (pom.xml:39, 383-391). Conflict audit checklist: the extractor entry (named-only `rdfax:extract-rdfa` since the unnamed-mode `match="/"` was dropped) vs LDH root templates, `body` keydown fallback, host-level event templates, `xsl:output`, `id('content')` assumptions.
10. **v6 note** — view mode renders XMLLiteral via identity transform (`imports/default.xsl:1489-1503`); the eventual v6 in-place model (edit the view markup, PUT canonical doc) is the successor to this form-control integration.
## C. Milestones
@@ -74,7 +74,7 @@ Mapped integration surface (all in `LinkedDataHub/src/main/webapp/static/com/ato
### D2. HTML paste (`src/edit.xsl` onpaste)
- `text/html` non-empty → HTML path; else existing plain-text path.
- Parse: detached `$carrier := createElement('div')` + `innerHTML :=` clipboard HTML (scripts inert when detached; XPath over detached nodes already proven).
-- Sanitize: `$clean :=` apply-templates `$carrier/node()` in `mode="canonical"` (now incl. D1 rules).
+- Sanitize: `$clean :=` apply-templates `$carrier/node()` in `mode="cm:canonical"` (now incl. D1 rules).
- Wrap stray top-level inline runs: `for-each-group group-adjacent="boolean(self::p|self::h1|…block…)"` → non-block groups wrapped in ``.
- Re-materialize XDM → live DOM: `serialize()` the fragment → `$stage := createElement('div')` + `innerHTML` (safe post-sanitization).
- Insert:
diff --git a/docs/ldh/MIGRATION.md b/docs/ldh/MIGRATION.md
index 88c5062..d484c76 100644
--- a/docs/ldh/MIGRATION.md
+++ b/docs/ldh/MIGRATION.md
@@ -56,7 +56,7 @@ kept the textarea in sync continuously; the replacement syncs once, declarativel
```xml
-
+
@@ -65,7 +65,7 @@ kept the textarea in sync continuously; the replacement syncs once, declarativel
```
Key points: serialize the container's **children only** (no wrapper element —
-parse-rdf-post adds the div); `mode="canonical"` guarantees the stored literal is
+parse-rdf-post adds the div); `mode="cm:canonical"` guarantees the stored literal is
sanitized and free of editing ephemera (chrome, contenteditable, classes, on*
handlers, unsafe URLs). SaxonJS 3 applies `ixsl:set-property` immediately
(verified in-browser), so the value is readable by `ldh:parse-rdf-post` within
@@ -132,8 +132,8 @@ The full integration was proven by compiling LDH's `client.xsl` (from the built
single SEF via `xslt3-he -nogo -ns:##html5 -relocate:on` — no errors, no conflicts.
Audit results:
-- Extractor entry is a **named template only** (`extract-rdfa`; the unnamed-mode
- `match="/"` was removed; headless tests invoke with `-it:extract-rdfa`). All other
+- Extractor entry is a **named template only** (`rdfax:extract-rdfa`; the unnamed-mode
+ `match="/"` was removed; headless tests invoke with `-it:"Q{https://w3id.org/atomgraph/rdfa-editor/rdfa#}extract-rdfa"`). All other
editor matching lives in named modes (`rdfax:extract`, `canonical`) or `ixsl:*` event
modes.
- Event templates: LDH has no `contenteditable` usage and no `body` keydown template
diff --git a/index.html b/index.html
index 6dac44f..c45d8bb 100644
--- a/index.html
+++ b/index.html
@@ -21,7 +21,7 @@
return SaxonJS.transform({
documentPool: pool,
stylesheetLocation: "dist/index.xsl.sef.json",
- initialTemplate: "main",
+ initialTemplate: "Q{https://w3id.org/atomgraph/rdfa-editor#}main",
logLevel: 10
}, "async");
})
diff --git a/src/RDFa2RDFXML-v3.xsl b/src/RDFa2RDFXML-v3.xsl
index 7ff325d..cac9ec2 100644
--- a/src/RDFa2RDFXML-v3.xsl
+++ b/src/RDFa2RDFXML-v3.xsl
@@ -49,7 +49,8 @@
'dct': 'http://purl.org/dc/terms/'
}"/>
-
+
+
rdf:Description per subject (via rdfae:group-triples) for readability -->
-
+
diff --git a/src/canonical-xhtml.xsl b/src/canonical-xhtml.xsl
index 0aaac74..46453ed 100644
--- a/src/canonical-xhtml.xsl
+++ b/src/canonical-xhtml.xsl
@@ -15,11 +15,11 @@ version="3.0">
(index.xsl does; the test driver is tests/canonical-driver.xsl).
Two passes in a fixed order:
- 1. mode="canonical" strips editing ephemera per the LDH v6 convention
+ 1. mode="cm:canonical" strips editing ephemera per the LDH v6 convention
(everything carrying @data-role is removable by
construction), sanitizes, and normalizes browser mess.
Nesting analysis must never see chrome, so this runs first.
- 2. mode="cm-normalize" coerces the result to the XHTML Strict content model
+ 2. mode="cm:normalize" coerces the result to the XHTML Strict content model
(blockquote is block-only, p is inline-only, ul holds
only li, ...), always RDFa-preserving. The load-init
path (edit.xsl) runs this pass ALONE on host content.
@@ -32,13 +32,13 @@ version="3.0">
-
-
+
+
-
+
-
+
@@ -50,15 +50,15 @@ version="3.0">
-
-
+
+
-
+
+
-
+
+ | form | input | button | select | textarea | link | meta | base" mode="cm:canonical" priority="3"/>
-
+
-
+
+ mode="cm:canonical"/>
+ | @*[starts-with(name(), 'aria-')] | @*[starts-with(name(), 'data-')]" mode="cm:canonical"/>
-
+
-
+
-
+
+ or @datatype or @lang or @xml:lang)]" mode="cm:canonical">
+ [empty(*[cm:block(local-name(.))])]" mode="cm:canonical">
@@ -179,7 +179,7 @@ version="3.0">
wrapper (p may not contain blocks) - unwrap to its children; stray inline
residue is re-coerced by pass 2 in the parent's context -->
+ [exists(*[cm:block(local-name(.))])]" mode="cm:canonical">
@@ -189,7 +189,7 @@ version="3.0">
has become real content and stays a p -->
+ mode="cm:canonical" priority="1">
@@ -197,29 +197,29 @@ version="3.0">
clipboard/host wrappers, keep RDFa-bearing ones (dropping them would lose
triples; lint reports them as unknown-element) -->
+ [not(@property or @about or @typeof or @resource)]" mode="cm:canonical">
+ [not(@property or @about or @typeof or @resource or @content)]" mode="cm:canonical" priority="1"/>
-
+
+ mode="cm:canonical"/>
-
+
-
+
@@ -227,13 +227,13 @@ version="3.0">
Matches EVERY inline-only element and decides on the PROCESSED children, so
blocks surfaced by inner splits are handled in the same bottom-up pass (one
invocation reaches the fixed point). An RDFa-bearing parent stays whole -
- its block children demote to inline via mode="cm-demote" (recursive, all
+ its block children demote to inline via mode="cm:demote" (recursive, all
attributes kept), so the extracted literal and triples are unchanged. A
plain parent splits around its block children; inline runs keep a shell
copying ALL attributes (safe: this branch is non-RDFa by construction, so
nothing duplicates a triple - an split by a block keeps its target
on both halves); whitespace-only residue between blocks drops -->
-
+
@@ -248,7 +248,7 @@ version="3.0">
-
+
@@ -277,9 +277,9 @@ version="3.0">
kept), recursively - a demoted list becomes nested spans, never a bare li
inside a span. Text, inline and unknown elements pass through with their
children demoted likewise -->
-
+
-
+
@@ -288,7 +288,7 @@ version="3.0">
-
+
@@ -299,7 +299,7 @@ version="3.0">
-
+
@@ -310,7 +310,7 @@ version="3.0">
-
+
@@ -321,7 +321,7 @@ version="3.0">
-
+
@@ -333,7 +333,7 @@ version="3.0">
-
+
@@ -370,7 +370,7 @@ version="3.0">
-
+
@@ -387,24 +387,24 @@ version="3.0">
-
+
-
+
-
+
-
+
diff --git a/src/edit.xsl b/src/edit.xsl
index c845890..ae9879a 100644
--- a/src/edit.xsl
+++ b/src/edit.xsl
@@ -1601,7 +1601,7 @@ version="3.0">
-
+
diff --git a/src/navigate.xsl b/src/navigate.xsl
index d2de4d2..90e6ddf 100644
--- a/src/navigate.xsl
+++ b/src/navigate.xsl
@@ -319,7 +319,7 @@ version="3.0">
-
+
diff --git a/src/select.xsl b/src/select.xsl
index 291f79f..0b5e102 100644
--- a/src/select.xsl
+++ b/src/select.xsl
@@ -445,7 +445,7 @@ version="3.0">
@@ -485,7 +485,7 @@ version="3.0">
-
+
diff --git a/tests/fixture-blocks.html b/tests/fixture-blocks.html
index 99f9d49..f3959ec 100644
--- a/tests/fixture-blocks.html
+++ b/tests/fixture-blocks.html
@@ -23,7 +23,7 @@
return SaxonJS.transform({
documentPool: pool,
stylesheetLocation: "../dist/ldh-editor.xsl.sef.json",
- initialTemplate: "main",
+ initialTemplate: "Q{https://w3id.org/atomgraph/rdfa-editor#}main",
logLevel: 10
}, "async");
})
diff --git a/tests/fixture-dragnest.html b/tests/fixture-dragnest.html
index 47fe5f7..339d2d9 100644
--- a/tests/fixture-dragnest.html
+++ b/tests/fixture-dragnest.html
@@ -18,7 +18,7 @@
return SaxonJS.transform({
documentPool: pool,
stylesheetLocation: "../dist/index.xsl.sef.json",
- initialTemplate: "main",
+ initialTemplate: "Q{https://w3id.org/atomgraph/rdfa-editor#}main",
logLevel: 10
}, "async");
})
diff --git a/tests/fixture-nesting.html b/tests/fixture-nesting.html
index 08e6de3..b9e1af8 100644
--- a/tests/fixture-nesting.html
+++ b/tests/fixture-nesting.html
@@ -18,7 +18,7 @@
return SaxonJS.transform({
documentPool: pool,
stylesheetLocation: "../dist/ldh-editor.xsl.sef.json",
- initialTemplate: "main",
+ initialTemplate: "Q{https://w3id.org/atomgraph/rdfa-editor#}main",
logLevel: 10
}, "async");
})
diff --git a/tests/fixture.html b/tests/fixture.html
index 1fcf2d4..bd12578 100644
--- a/tests/fixture.html
+++ b/tests/fixture.html
@@ -24,7 +24,7 @@
return SaxonJS.transform({
documentPool: pool,
stylesheetLocation: "../dist/index.xsl.sef.json",
- initialTemplate: "main",
+ initialTemplate: "Q{https://w3id.org/atomgraph/rdfa-editor#}main",
logLevel: 10
}, "async");
})
diff --git a/tests/run-tests.sh b/tests/run-tests.sh
index f6ee632..960ed7d 100755
--- a/tests/run-tests.sh
+++ b/tests/run-tests.sh
@@ -12,7 +12,7 @@ fail=0
for fixture in tests/fixtures/*.xhtml; do
name=$(basename "$fixture" .xhtml)
- if ! npx xslt3-he -xsl:src/RDFa2RDFXML-v3.xsl -s:"$fixture" -it:extract-rdfa -o:"$tmp/$name.rdf" base-uri="$BASE" 2>"$tmp/$name.err"; then
+ if ! npx xslt3-he -xsl:src/RDFa2RDFXML-v3.xsl -s:"$fixture" -it:"Q{https://w3id.org/atomgraph/rdfa-editor/rdfa#}extract-rdfa" -o:"$tmp/$name.rdf" base-uri="$BASE" 2>"$tmp/$name.err"; then
echo "FAIL $name (extraction error)"
cat "$tmp/$name.err"
fail=1
@@ -48,7 +48,7 @@ done
for fixture in tests/fixtures/canonical/*.xhtml; do
name=$(basename "$fixture" .xhtml)
- if ! npx xslt3-he -xsl:tests/canonical-driver.xsl -s:"$fixture" -it:canonical-xhtml -o:"$tmp/c-$name.xhtml" 2>"$tmp/c-$name.err"; then
+ if ! npx xslt3-he -xsl:tests/canonical-driver.xsl -s:"$fixture" -it:"Q{https://w3id.org/atomgraph/rdfa-editor/content-model#}canonical-xhtml" -o:"$tmp/c-$name.xhtml" 2>"$tmp/c-$name.err"; then
echo "FAIL canonical/$name (transform error)"
cat "$tmp/c-$name.err"
fail=1