Added
dj-navigatekeepsaria-current="page"in sync across SPA navigation (#1756). A persistent nav usually lives outside[dj-root]; sincedj-navigateswaps only the[dj-root]subtree, a server-rendered active-link highlight previously stayed on the page you navigated from. The client now setsaria-current="page"on the[dj-navigate]link whose path matches the current URL (and removes it from the others) after each navigation — on click, on the WS mount, and on back/forward (popstate). Cross-origindj-navigatetargets are never marked current, and an app-authoredaria-currentof a different value is left untouched. Style the active link witha[dj-navigate][aria-current="page"]. (Syncingdocument.titleand the[dj-root]dj-viewattribute across SPA nav remain tracked in #1756.)
Fixed
render_full_templateejected page content outside[dj-root]for multi-line<div>tags, leaking it acrossdj-navigate(#1749). Thedj-rootregion's closing</div>was located by counting<div>depth, but the opening-tag check only matched the exact forms"<div "and"<div>"— a multi-line opening tag (<div\n class=...>/<div\t...>) was not counted. Each missed open under-counted depth, so a later</div>closed thedj-rootregion early; the full rendered view was then spliced in place of the truncated region, leaving the tail of the page outside<div dj-root>(and duplicated). Becausedj-navigateswaps only the[dj-root]subtree, that ejected content was never cleared on navigation (it leaked onto the next page — observed on a page authored with multi-line<div>sections, reached via a fresh GET). Fix: match<divfollowed by any tag-boundary char (whitespace,>,/). Same family as #1746.dj-rootboundary close tag missed whitespace (</div >/</div\n>), and two divergent scanners (#1751). Completes the #1749 fix class._find_closing_div_pos(the shared scanner, 6 call sites) hardcoded the close as</div>— the close-side twin of #1749's open-side under-count, which would over-count depth and fail to find the close. Now matches</div\s*>. Also consolidatedrender_full_template's separate hand-rolled depth loop (whose open side was fixed in #1749/#1750) into the shared_find_closing_div_pos, removing the parallel-path-drift that let the open-side bug exist in one copy and not the other.render_full_templatedouble-rendered the whole page when a child template merely mentioneddj-root/dj-viewas text (#1746).get_template()picked the VDOM source with a naive substring check ("dj-root" in template_source or "dj-view" in template_source). When the real<div dj-root>lived in the BASE template and the child only displayed the tokens in text (e.g. a<code>example) — or as a substring of another word (adj-view) — the check wrongly selected the child as the VDOM source, sorender_full_templatenested the entire page (two<!DOCTYPE>/two<footer>, truncated inline<script>, brokendj-navigatemorphs). Replaced the substring check with the anchored-attribute regexes_DJ_ROOT_RE/_DJ_VIEW_REalready used elsewhere in the module, which require a real<div ... dj-root/dj-view ...>tag.