You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The export's page URLs are document-relative: Hooks\Main::onGetLocalURL writes ./Page.html, and maintenance/rename.php reparents each subpage's references by its depth (RelativeUrl::reparent) so a page one directory down says ../Page.html. That covers href, src, srcset and CSS url() inside the page's own HTML — everything a skin renders.
It does not cover a local URL that leaves the HTML. An extension that asks Title::getLocalURL() for a value it ships in a ResourceLoader module gets the same ./Page.html string, and that string lands in one bundle serving every page at every depth. Nothing reparents it, and nothing could: there is one copy for the whole site, so there is no depth to correct it by.
Title::getLocalURL() promises a URL that means the same thing wherever it is used, and wikven returns one that does not. Reparenting keeps that promise inside a page, so nothing noticed until a value escaped the page.
The live instance, now closed
SifterSearch's ClientConfig::forModules() baked the results page's URL into its modules' config.json:
docs/.wikven.yml names Search, so the bundle carried ./Search.html. From Deploying/ko.html — a translated page, exported into a real Deploying/ directory — that resolved to /wikven/Deploying/Search.html, while the page that exists is /wikven/Search.html. It reached the search form's action, the fallback link ext.sifter.retarget repoints, and the submit navigation and typeahead footer URL ext.sifter.pagefind builds. #421 had just made the toggle's own href depth-correct in the HTML, and ext.sifter.retarget then overwrote it with the bundle's copy, so on a subpage the script replaced a working href with a broken one.
Fixed on the consumer's side: SifterSearch #64 anchors the results-page URL at the parent of the bundle path before baking it into the module, released as v0.7.1; #427 picks it up and covers it with browser tests read from a page at depth.
The decision
Three ways to answer the class, not the instance:
Leave it to the consumer. Each extension that ships a local URL in a bundle resolves it itself (SifterSearch resolves against bundlePath, which is site-root-anchored by construction). Nothing changes here, and every such extension pays separately.
Anchor the export's URLs at the site root. A site would declare the path it is served under, and every consumer would get a URL that means one thing. The largest change, and the one that ends the class rather than this instance.
So what is left is a choice between 1 and 3, and it comes down to one property: whether a wikven export must be droppable at an arbitrary path with no configuration. Relative URLs buy exactly that — the output works from a subdirectory, another host, or a local filesystem without being told where it is — and the price is that a URL cannot survive leaving the page. Root-anchored URLs pay with that portability and buy a URL that is correct everywhere, bundles included.
Cost of option 3, as the tree stands
There is no site-wide base-path setting today.includes/WikvenSettings.php has no base path, article path or canonical-URL concept; option 3 introduces one, and every URL-producing path (onGetLocalURL, RelativeUrl::reparent, maintenance/rename.php) is rewritten around it.
The concept is not foreign, though.SifterSearchBundlePath already asks a subdirectory deploy for its path, so a site deployed under one is already writing that value down once.
One instance found so far, and it is closed upstream under option 1.
Resolution: staying with option 1
Labelled wontfix on those grounds — not because the hole is not real, but because ending the class costs the export's configuration-free portability, and the evidence for spending that is one instance that already has a fix. Each consumer anchoring its own is the working arrangement.
Worth reopening the choice when either of these lands:
A second instance appears — another extension carrying a local URL into a bundle, a JS config var it ships rather than the page carries, or a generated asset. Two instances make it a class in practice, not just in principle.
A compatibility break is on the table anyway (a major release), since option 3 changes every URL in the output and is cheapest to take alongside other breaking changes.
RelativeUrl's docblock states the boundary, so the next person carrying a local URL into a bundle reads why nothing will fix it for them:
What this cannot reach is a local URL baked into a ResourceLoader module's bundle: one file serves every page at every depth, so there is no depth to correct it by, and an extension shipping one has to anchor it itself.
The export's page URLs are document-relative:
Hooks\Main::onGetLocalURLwrites./Page.html, andmaintenance/rename.phpreparents each subpage's references by its depth (RelativeUrl::reparent) so a page one directory down says../Page.html. That covershref,src,srcsetand CSSurl()inside the page's own HTML — everything a skin renders.It does not cover a local URL that leaves the HTML. An extension that asks
Title::getLocalURL()for a value it ships in a ResourceLoader module gets the same./Page.htmlstring, and that string lands in one bundle serving every page at every depth. Nothing reparents it, and nothing could: there is one copy for the whole site, so there is no depth to correct it by.Title::getLocalURL()promises a URL that means the same thing wherever it is used, and wikven returns one that does not. Reparenting keeps that promise inside a page, so nothing noticed until a value escaped the page.The live instance, now closed
SifterSearch's
ClientConfig::forModules()baked the results page's URL into its modules'config.json:docs/.wikven.ymlnamesSearch, so the bundle carried./Search.html. FromDeploying/ko.html— a translated page, exported into a realDeploying/directory — that resolved to/wikven/Deploying/Search.html, while the page that exists is/wikven/Search.html. It reached the search form'saction, the fallback linkext.sifter.retargetrepoints, and the submit navigation and typeahead footer URLext.sifter.pagefindbuilds. #421 had just made the toggle's own href depth-correct in the HTML, andext.sifter.retargetthen overwrote it with the bundle's copy, so on a subpage the script replaced a working href with a broken one.Fixed on the consumer's side: SifterSearch #64 anchors the results-page URL at the parent of the bundle path before baking it into the module, released as v0.7.1; #427 picks it up and covers it with browser tests read from a page at depth.
The decision
Three ways to answer the class, not the instance:
bundlePath, which is site-root-anchored by construction). Nothing changes here, and every such extension pays separately.RLCONF), so a per-page value is corrected the way anhrefis. Done — split out as A local URL a page carries in its JavaScript config is never reparented #444 and shipped in fix: reparent the local URLs a page carries in its JavaScript config #445:RelativeUrl::reparent()now rewrites the root-relative strings in a page'sRLCONFobject. It fixes values that ride in the page, and by construction cannot reach values baked into a shared bundle, which is what this issue keeps.So what is left is a choice between 1 and 3, and it comes down to one property: whether a wikven export must be droppable at an arbitrary path with no configuration. Relative URLs buy exactly that — the output works from a subdirectory, another host, or a local filesystem without being told where it is — and the price is that a URL cannot survive leaving the page. Root-anchored URLs pay with that portability and buy a URL that is correct everywhere, bundles included.
Cost of option 3, as the tree stands
includes/WikvenSettings.phphas no base path, article path or canonical-URL concept; option 3 introduces one, and every URL-producing path (onGetLocalURL,RelativeUrl::reparent,maintenance/rename.php) is rewritten around it.SifterSearchBundlePathalready asks a subdirectory deploy for its path, so a site deployed under one is already writing that value down once.Resolution: staying with option 1
Labelled
wontfixon those grounds — not because the hole is not real, but because ending the class costs the export's configuration-free portability, and the evidence for spending that is one instance that already has a fix. Each consumer anchoring its own is the working arrangement.Worth reopening the choice when either of these lands:
RelativeUrl's docblock states the boundary, so the next person carrying a local URL into a bundle reads why nothing will fix it for them:Reported upstream as chaotic-ground/SifterSearch#63, where one of the candidate fixes lives.