Skip to content

Commit 2a75032

Browse files
namedgraphclaude
andcommitted
Thread doc-uri / fragment / mode separately across navigation
The client-side navigation pipeline overloaded a single $uri to mean both "doc to fetch/cache" and "resource to display." Different consumers silently stripped or kept different parts, surfacing as: blank panes on fragment-bearing link clicks, mode toggles ignored when the doc was cached, URL bar gaining a re-encoded fragment after forth-and-back navigation across the local tab. Split into explicit components, threaded through every entry point: - $doc-uri (no fragment, no query) — cache key (LinkedDataHub.contents), tab <li> data-uri, pane @about, every lookup predicate. Always via ac:absolute-path. - $fragment — the sub-anchor; lives on the outer URL per RFC 3986, extracted via ac:fragment-id($href). Round-tripped through tab @href via the 3-arity ldh:href. - $query-params — mode/forClass/etc.; callers strip the URL fragment via ac:document-uri before passing to ldh:parse-query-params, so no caller can corrupt the last value by gluing the fragment onto it. Touched: ldh:DocumentNavigate, ldh:RDFDocumentLoad, ldh:rdf-document-response, ldh:RenderTab, ldh:ActivateTab, ldh:TabSwitch, ldh:AddTabNavBarListItem; the four event handlers (main, link click, tab click, popstate), close-tab fallback, navbar-form, onDelete, onRDFFileUpload; modal/form callers in bootstrap/2.3.2/client. bs2:TabBody and bs2:DocumentBody now take @about as a mandatory param; the no-op ixsl:set-attribute workaround (operating on a detached node after ixsl:replace-element) is removed; layout.xsl passes @about server-side. TabSwitch gate requires cache hit AND non-uri query params unchanged (deep-equal vs ldh:query-params()); mode changes correctly fall through to DocumentNavigate, so the rendered DOM gets refreshed. ldh:query-params is now defined once (imports/default.xsl); the client-side override that wrapped ixsl:query-params() shadowed fragment-safe parsing and is removed. The remaining direct ixsl:query-params() callers (ac:query stylesheet param, navigation.xsl mode tunnel) go through ldh:query-params() too. Anchor-emitting server templates (xhtml:Anchor, svg:Anchor, @Rdf:resource|srx:uri) drop the encoded-full-URI fragment convention: $fragment = ac:fragment-id(.), $href via ac:document-uri. External resource links become ?uri=<doc-uri>#<frag> instead of ?uri=<doc-uri%23frag>#<encoded-full-uri>. Scroll-to-fragment in RenderTab and TabSwitch uses [@about = $resource-uri] in the active pane, replacing id($fragment, ixsl:page()). Sidesteps the DOM-id uniqueness constraint when two panes both render a resource at #this — the RDFa-emitted @about is resource-URI-scoped, naturally unique. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 5525722 commit 2a75032

8 files changed

Lines changed: 208 additions & 133 deletions

File tree

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -762,9 +762,10 @@ WHERE
762762
<xsl:variable name="href" select="?headers?location" as="xs:anyURI"/>
763763

764764
<xsl:call-template name="ldh:DocumentNavigate">
765-
<xsl:with-param name="uri" select="$href"/>
765+
<xsl:with-param name="doc-uri" select="ac:absolute-path($href)"/>
766+
<xsl:with-param name="fragment" select="ac:fragment-id($href)"/>
766767
</xsl:call-template>
767-
</xsl:for-each>
768+
</xsl:for-each>
768769
</xsl:function>
769770

770771
<xsl:function name="ldh:row-form-submit-violation" ixsl:updating="yes">

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/functions.xsl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ exclude-result-prefixes="#all"
4141
<xsl:sequence select="xs:anyURI(ixsl:location())"/>
4242
</xsl:function>
4343

44-
<xsl:function name="ldh:query-params" as="map(xs:string, xs:string*)">
45-
<xsl:sequence select="ixsl:query-params()"/>
46-
</xsl:function>
44+
<!-- ldh:query-params is defined once in imports/default.xsl and works in both contexts via ldh:request-uri -->
4745

4846
<xsl:function name="ldh:base-uri" as="xs:anyURI">
4947
<xsl:param name="arg" as="node()"/> <!-- ignored -->

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,7 +1272,8 @@ LIMIT 10
12721272
<xsl:variable name="form" select="$context('form')" as="element()?"/>
12731273
<xsl:sequence select="ixsl:call($form/ancestor::div[contains-token(@class, 'modal')], 'remove', [])[current-date() lt xs:date('2000-01-01')]"/>
12741274
<xsl:call-template name="ldh:DocumentNavigate">
1275-
<xsl:with-param name="uri" select="$doc-uri"/>
1275+
<xsl:with-param name="doc-uri" select="$doc-uri"/>
1276+
<xsl:with-param name="fragment" select="()"/>
12761277
</xsl:call-template>
12771278
</xsl:when>
12781279
<xsl:when test="$status = 201 and map:contains($response?headers, 'location')">
@@ -1571,7 +1572,8 @@ LIMIT 10
15711572
<xsl:sequence select="ixsl:call($form/ancestor::div[contains-token(@class, 'modal')], 'remove', [])[current-date() lt xs:date('2000-01-01')]"/>
15721573

15731574
<xsl:call-template name="ldh:DocumentNavigate">
1574-
<xsl:with-param name="uri" select="ac:absolute-path($uri)"/>
1575+
<xsl:with-param name="doc-uri" select="ac:absolute-path($uri)"/>
1576+
<xsl:with-param name="fragment" select="ac:fragment-id($uri)"/>
15751577
</xsl:call-template>
15761578
</xsl:when>
15771579
<!-- Error -->
@@ -1598,7 +1600,8 @@ LIMIT 10
15981600
<xsl:sequence select="ixsl:call($form/ancestor::div[contains-token(@class, 'modal')], 'remove', [])[current-date() lt xs:date('2000-01-01')]"/>
15991601

16001602
<xsl:call-template name="ldh:DocumentNavigate">
1601-
<xsl:with-param name="uri" select="ac:absolute-path($uri)"/>
1603+
<xsl:with-param name="doc-uri" select="ac:absolute-path($uri)"/>
1604+
<xsl:with-param name="fragment" select="ac:fragment-id($uri)"/>
16021605
</xsl:call-template>
16031606
</xsl:when>
16041607
<!-- Error: render error message inline in the form's fieldset -->

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/navigation.xsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ ORDER BY DESC(?created)
667667
<ul class="well well-small nav nav-list">
668668
<xsl:apply-templates select="$results/rdf:RDF/rdf:Description[not(@rdf:about = $doc-uri)]" mode="xhtml:ListItem">
669669
<xsl:sort select="ac:label(.)" order="ascending" lang="{$ldt:lang}"/>
670-
<xsl:with-param name="mode" select="ixsl:query-params()?mode[1]" tunnel="yes"/> <!-- TO-DO: support multiple modes -->
670+
<xsl:with-param name="mode" select="ldh:query-params()?mode[1]" tunnel="yes"/> <!-- TO-DO: support multiple modes -->
671671
<xsl:with-param name="render-id" select="false()" tunnel="yes"/>
672672
</xsl:apply-templates>
673673
</ul>

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/document.xsl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ extension-element-prefixes="ixsl"
419419
<xsl:param name="base" as="xs:anyURI?"/>
420420
<xsl:param name="endpoint" as="xs:anyURI?"/>
421421
<xsl:param name="application" as="xs:anyURI?"/>
422+
<xsl:param name="about" as="xs:anyURI"/>
422423
<xsl:param name="object-metadata" as="document-node()?" tunnel="yes"/>
423424

424425
<div>
@@ -444,6 +445,7 @@ extension-element-prefixes="ixsl"
444445

445446
<xsl:apply-templates select="." mode="bs2:DocumentBody">
446447
<xsl:with-param name="mode" select="$mode"/>
448+
<xsl:with-param name="about" select="$about"/>
447449
</xsl:apply-templates>
448450
</div>
449451
</xsl:template>
@@ -454,7 +456,7 @@ extension-element-prefixes="ixsl"
454456
<xsl:param name="id" as="xs:string?"/>
455457
<xsl:param name="class" select="'document-body'" as="xs:string?"/>
456458
<xsl:param name="mode" as="xs:anyURI"/>
457-
<xsl:param name="about" select="ac:absolute-path(ldh:base-uri(.))" as="xs:anyURI"/>
459+
<xsl:param name="about" as="xs:anyURI"/>
458460
<xsl:param name="object-metadata" as="document-node()?" tunnel="yes"/>
459461

460462
<div>
@@ -464,9 +466,7 @@ extension-element-prefixes="ixsl"
464466
<xsl:if test="$class">
465467
<xsl:attribute name="class" select="$class"/>
466468
</xsl:if>
467-
<xsl:if test="$about">
468-
<xsl:attribute name="about" select="$about"/>
469-
</xsl:if>
469+
<xsl:attribute name="about" select="$about"/>
470470

471471
<xsl:apply-templates select="." mode="bs2:ActionBar">
472472
<xsl:with-param name="active-mode" select="$mode"/>

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/imports/default.xsl

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ exclude-result-prefixes="#all"
161161
</xsl:function>
162162

163163
<xsl:function name="ldh:query-params" as="map(xs:string, xs:string*)">
164-
<xsl:sequence select="ldh:parse-query-params(substring-after(ldh:request-uri(), '?'))"/>
164+
<!-- ac:document-uri strips the URL's #fragment so it doesn't get glued onto the last query value -->
165+
<xsl:sequence select="ldh:parse-query-params(substring-after(ac:document-uri(ldh:request-uri()), '?'))"/>
165166
</xsl:function>
166167

167168
<xsl:function name="ldh:base-uri" as="xs:anyURI" use-when="system-property('xsl:product-name') = 'SAXON'">
@@ -329,7 +330,7 @@ exclude-result-prefixes="#all"
329330

330331
<xsl:function name="ldh:parse-query-params" as="map(xs:string, xs:string*)">
331332
<xsl:param name="query-string" as="xs:string"/>
332-
333+
333334
<xsl:sequence select="map:merge(
334335
tokenize($query-string, '&amp;')[normalize-space()]
335336
!
@@ -534,8 +535,8 @@ exclude-result-prefixes="#all"
534535
<!-- subject resource -->
535536
<xsl:template match="@rdf:about" mode="xhtml:Anchor">
536537
<!-- <xsl:param name="graph" as="xs:anyURI?" tunnel="yes"/>-->
537-
<xsl:param name="fragment" select="if (starts-with(., ldt:base())) then (if (contains(., '#')) then substring-after(., '#') else ()) else encode-for-uri(.)" as="xs:string?"/>
538-
<xsl:param name="href" select="ldh:href(xs:anyURI(.), map{}, $fragment)" as="xs:anyURI"/>
538+
<xsl:param name="fragment" select="ac:fragment-id(.)" as="xs:string?"/>
539+
<xsl:param name="href" select="ldh:href(ac:document-uri(xs:anyURI(.)), map{}, $fragment)" as="xs:anyURI"/>
539540
<xsl:param name="id" as="xs:string?"/>
540541
<xsl:param name="title" select="." as="xs:string?"/>
541542
<xsl:param name="class" as="xs:string?"/>
@@ -551,8 +552,8 @@ exclude-result-prefixes="#all"
551552
</xsl:template>
552553

553554
<xsl:template match="@rdf:about | @rdf:resource" mode="svg:Anchor">
554-
<xsl:param name="fragment" select="if (starts-with(., ldt:base())) then (if (contains(., '#')) then substring-after(., '#') else ()) else encode-for-uri(.)" as="xs:string?"/>
555-
<xsl:param name="href" select="ldh:href(xs:anyURI(.), map{}, $fragment)" as="xs:anyURI"/>
555+
<xsl:param name="fragment" select="ac:fragment-id(.)" as="xs:string?"/>
556+
<xsl:param name="href" select="ldh:href(ac:document-uri(xs:anyURI(.)), map{}, $fragment)" as="xs:anyURI"/>
556557
<xsl:param name="id" select="$fragment" as="xs:string?"/>
557558
<xsl:param name="label" select="if (parent::rdf:Description) then ac:svg-label(..) else ac:svg-object-label(.)" as="xs:string"/>
558559
<xsl:param name="title" select="$label" as="xs:string"/>
@@ -573,8 +574,8 @@ exclude-result-prefixes="#all"
573574

574575
<!-- proxy link URIs if they are external -->
575576
<xsl:template match="@rdf:resource | srx:uri" priority="2">
576-
<xsl:param name="fragment" select="if (starts-with(., ldt:base())) then (if (contains(., '#')) then substring-after(., '#') else ()) else encode-for-uri(.)" as="xs:string?"/>
577-
<xsl:param name="href" select="ldh:href(xs:anyURI(.), map{}, $fragment)" as="xs:anyURI"/>
577+
<xsl:param name="fragment" select="ac:fragment-id(.)" as="xs:string?"/>
578+
<xsl:param name="href" select="ldh:href(ac:document-uri(xs:anyURI(.)), map{}, $fragment)" as="xs:anyURI"/>
578579
<xsl:param name="id" as="xs:string?"/>
579580
<xsl:param name="title" select="." as="xs:string?"/>
580581
<xsl:param name="class" as="xs:string?"/>

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,7 @@ exclude-result-prefixes="#all">
758758
<xsl:with-param name="mode" select="ac:mode(root())"/>
759759
<xsl:with-param name="base" select="ldt:base()"/>
760760
<xsl:with-param name="endpoint" select="sd:endpoint()"/>
761+
<xsl:with-param name="about" select="ac:absolute-path(ldh:base-uri(.))"/>
761762
<xsl:with-param name="object-metadata" select="$object-metadata" tunnel="yes"/>
762763
</xsl:apply-templates>
763764
</div>

0 commit comments

Comments
 (0)