Found while verifying the published v2.3.1 artifact. #139 fixed the _assets/ stylesheets — all 5 of them are clean — but Remix also emits stylesheets outside _assets/, and those were never in the rewriter's scope. Four of them still ship absolute /myst_assets_folder/… URLs, which is exactly the #138 defect.
What ships in v2.3.1
Unzipping quantecon-theme.zip from the release:
| Location |
Files |
Absolute refs remaining |
public/build/_assets/ |
5 |
0 — #139 working as intended |
public/build/ |
1 (root-*.css) |
1 |
public/build/_shared/ |
1 (plotly-renderer-*.css) |
1 |
public/build/routes/ |
2 (_index-*.css, $-*.css) |
1 each |
All four point at the same asset:
:root{--jp-icon-plotly: url(/myst_assets_folder/_assets/plotly-6TYK7N2P.svg)}
The file itself is present in the bundle at public/build/_assets/plotly-6TYK7N2P.svg — it is only the reference that is wrong. So under myst start it resolves (the theme's server mounts public/build at that path) and in myst build --html output it 404s, along with the same baseurl breakage #139 fixed in passing.
Cause
scripts/relative-css-asset-urls.mjs enumerates one directory:
const assetsDir = path.resolve(assetsBuildDirectory, '_assets');
for (const name of fs.readdirSync(assetsDir).filter((f) => f.endsWith('.css'))) {
Route and shared chunk CSS lands in public/build/, public/build/_shared/ and public/build/routes/, so readdirSync never sees it. #139's scoping note ("only the KaTeX stylesheet is affected today; app.css and thebe-core.css emit no url() references") was measured against the _assets/ set and did not cover these.
Why the fix is not just a wider glob
The script's substitution hardcodes a stylesheet-relative ./:
const after = before.replace(URL_RE, 'url($1./');
That is correct only for stylesheets sitting inside _assets/. For the newly-included files the depth differs:
| Stylesheet |
Correct reference |
public/build/_assets/*.css |
./plotly-*.svg |
public/build/root-*.css |
./_assets/plotly-*.svg |
public/build/_shared/*.css |
../_assets/plotly-*.svg |
public/build/routes/*.css |
../_assets/plotly-*.svg |
So the rewriter needs to walk the build directory recursively and compute the prefix per stylesheet from its own location, rather than assuming one. The existence check should resolve against each stylesheet's directory too — that guard is what would have caught this had the files been in scope.
Impact
Low but real. --jp-icon-plotly is a JupyterLab-style icon variable, so the visible symptom is a missing plotly icon on statically built sites that render plotly outputs — not the maths-wide degradation #138 caused. It does not warrant re-tagging v2.3.1; it can ride the next release.
Verification for the fix
grep -ro "url([^)]*myst_assets_folder[^)]*)" --include='*.css' public/build | wc -l should be 0 after a npm run prod:build, and each rewritten target must exist at the path the stylesheet now names — worth asserting from the stylesheet's own directory, since that is the assumption that silently failed here.
Found while verifying the published v2.3.1 artifact. #139 fixed the
_assets/stylesheets — all 5 of them are clean — but Remix also emits stylesheets outside_assets/, and those were never in the rewriter's scope. Four of them still ship absolute/myst_assets_folder/…URLs, which is exactly the #138 defect.What ships in v2.3.1
Unzipping
quantecon-theme.zipfrom the release:public/build/_assets/public/build/root-*.css)public/build/_shared/plotly-renderer-*.css)public/build/routes/_index-*.css,$-*.css)All four point at the same asset:
The file itself is present in the bundle at
public/build/_assets/plotly-6TYK7N2P.svg— it is only the reference that is wrong. So undermyst startit resolves (the theme's server mountspublic/buildat that path) and inmyst build --htmloutput it 404s, along with the samebaseurlbreakage #139 fixed in passing.Cause
scripts/relative-css-asset-urls.mjsenumerates one directory:Route and shared chunk CSS lands in
public/build/,public/build/_shared/andpublic/build/routes/, soreaddirSyncnever sees it. #139's scoping note ("only the KaTeX stylesheet is affected today;app.cssandthebe-core.cssemit nourl()references") was measured against the_assets/set and did not cover these.Why the fix is not just a wider glob
The script's substitution hardcodes a stylesheet-relative
./:That is correct only for stylesheets sitting inside
_assets/. For the newly-included files the depth differs:public/build/_assets/*.css./plotly-*.svgpublic/build/root-*.css./_assets/plotly-*.svgpublic/build/_shared/*.css../_assets/plotly-*.svgpublic/build/routes/*.css../_assets/plotly-*.svgSo the rewriter needs to walk the build directory recursively and compute the prefix per stylesheet from its own location, rather than assuming one. The existence check should resolve against each stylesheet's directory too — that guard is what would have caught this had the files been in scope.
Impact
Low but real.
--jp-icon-plotlyis a JupyterLab-style icon variable, so the visible symptom is a missing plotly icon on statically built sites that render plotly outputs — not the maths-wide degradation #138 caused. It does not warrant re-tagging v2.3.1; it can ride the next release.Verification for the fix
grep -ro "url([^)]*myst_assets_folder[^)]*)" --include='*.css' public/build | wc -lshould be 0 after anpm run prod:build, and each rewritten target must exist at the path the stylesheet now names — worth asserting from the stylesheet's own directory, since that is the assumption that silently failed here.