Embed LDH's RDF-defined blocks as atomic RDFa islands#16
Open
namedgraph wants to merge 2 commits into
Open
Conversation
Blocks defined purely in RDF (ldh:View, ldh:ResultSetChart, ldh:Object) can now live wherever the content model admits a div, per the LDH v6 document format: a div[@about][@typeof] block element with its definition triples as span[@Property] children (objects via @resource, literals as span text) - no wrappers, no rdf:_N sequences, no document-to-block containment edges. The editor treats such a div as an atomic island: never a text host, focusable/navigable/deletable like a block image (shared local:select-island doctrine, undo/redo chords included), a hard boundary for merges (merge-host-in gains a tail-island guard - islands hold no hosts, the lookup would leapfrog them) and for the delete machine (clamped-range moves boundaries out of islands, so they join selections whole and are only ever removed whole), and byte-identical on round-trip: the visual rendering is injected into an ephemeral div[data-role=rendering] child by the overridable mode="local:render-island" hook and stripped at canonicalization. The core (new src/blocks.xsl: $object-block-types param, the local:island predicate, the render hook + neutral card, extension stubs) knows no LDH vocabulary. The LDH extension (src/ldh-blocks.xsl, layered by the src/ldh-editor.xsl entry via xsl:import) supplies the class list, async renderers - ixsl:promise/ixsl:http-request chains fetching the referenced documents by content negotiation on clean trailing-slash URIs (no file extensions anywhere; serve.mjs replaces python http.server and negotiates rdf+xml / sparql-results+xml representations) - and the Block... insert dialog wired into the slash menu and toolbar through the new hook points. In production LinkedDataHub, client.xsl plays the extension's role, bridging the hook into its block rendering (MIGRATION.md par. 12). Two build flavors: the core SEF (dist/index.xsl.sef.json) is what GitHub Pages deploys - Pages cannot content-negotiate, so the LDH-extended SEF (dist/ldh-editor.xsl.sef.json) and the demo/ showcase page stay local-only. New coverage: extractor/canonical/lint fixtures for the storage form, tests/browser/blocks.mjs against tests/fixture-blocks.html (hydration, round-trip, navigation, boundaries, dialog insertion top-level and nested, stage-2/sweep atomicity, canonical copy, undo); fixture-nesting.html runs the extended SEF so every core suite doubles as proof the extension layers non-invasively. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The plan shipped in 0496acf (src/blocks.xsl, src/ldh-blocks.xsl, src/ldh-editor.xsl, demo/, tests, CLAUDE.md docs); the file is no longer needed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Blocks defined purely in RDF —
ldh:View,ldh:ResultSetChart,ldh:Object— can now be embedded wherever the content model admits a block, per the LDH v6 document format: adiv[@about][@typeof]element with its definition triples asspan[@property]children (objects via@resource, literals as span text). No wrappers, nordf:_Nsequences, no document→block containment edges — extraction yields the block descriptions, containment is implicit in the content.The editor treats such a block as an atomic island:
tabindex="-1"makes it a focusable navigation island (shared doctrine with block images: arrow-key selection, Backspace/Delete removes it whole, undo/redo chords work while it's focused);local:merge-host-ingains a tail-island guard) and for the cross-host delete machine (local:clamped-rangemoves boundaries out of islands, so a selection takes them whole or not at all);div[data-role=rendering]child by the overridablemode="local:render-island"hook and stripped at canonicalization; the extractor skips it.Core / extension split
src/blocks.xsl(core, zero LDH knowledge):$object-block-typesparam (default empty), thelocal:island()predicate, the render hook + neutral card, and extension stubs for dialogs / toolbar buttons / slash-menu items.src/ldh-blocks.xsl+ entrysrc/ldh-editor.xsl(xsl:importlayering, higher import precedence): the LDH class list, async renderers —ixsl:promise/ixsl:http-requestchains fetching the referenced documents by content negotiation on clean trailing-slash URIs (no file extensions anywhere) — and the "Block…" insert dialog wired into the slash menu and toolbar. In production LinkedDataHub, client.xsl plays this module's role, bridging the hook into its block rendering (v6ldh:Block/ v5ldh:RenderRow— MIGRATION.md §12).Build & deployment
Two SEFs: the core
dist/index.xsl.sef.jsonis what GitHub Pages deploys (Pages can't content-negotiate); the LDH-extendeddist/ldh-editor.xsl.sef.jsonpowers the local/demo/showcase and the browser fixtures.make upnow serves vianode serve.mjs, which negotiatesapplication/rdf+xml/application/sparql-results+xmlrepresentations of document URIs.Test plan
make test— 50 headless PASS, incl. new extractor/canonical/lint fixtures for the storage formmake test-browser— all 14 suites green, incl. newblocks.mjs(43 assertions: hydration, view-source round-trip, island navigation/deletion/boundaries, dialog insertion top-level and nested in a list item, stage-2/sweep delete atomicity, canonical copy, undo + invariants after every mutation)fixture-nesting.htmlruns the extended SEF, so every existing suite doubles as proof the extension layers without disturbing core behaviormake up→/demo/hydrates a chart and a nested object block over conneg; Source shows the clean v6 placeholder; Extract RDF shows the block descriptions🤖 Generated with Claude Code