Skip to content

fix(compiler): use posix separators for nested stylesheet imports#6762

Open
anxkhn wants to merge 2 commits into
reflex-dev:mainfrom
anxkhn:patch-9
Open

fix(compiler): use posix separators for nested stylesheet imports#6762
anxkhn wants to merge 2 commits into
reflex-dev:mainfrom
anxkhn:patch-9

Conversation

@anxkhn

@anxkhn anxkhn commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

All Submissions

  • Have you followed the guidelines stated in CONTRIBUTING.md?
  • Have you checked to ensure there aren't any other open Pull Requests for the desired change?

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Changes To Core Features

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully run tests with your changes locally?

What and why

Nested/subfolder stylesheets silently fail to load on Windows.

_compile_root_stylesheet (reflex/compiler/compiler.py) builds the relative
target as a pathlib.Path and then emits it into a CSS @import:

target_path = stylesheet.relative_to(assets_app_path).with_suffix(".css")
...
str_target_path = "./" + str(target_path)   # OS-dependent separator

For a nested stylesheet, str(Path("subdir/theme.css")) is
"subdir\\theme.css" on Windows, so the compiler writes:

@import url('./subdir\theme.css');

Per the CSS spec, a backslash inside url() is an escape-sequence introducer,
not a path separator (\t becomes a hex escape), so the browser requests a
mangled URL and the stylesheet never loads. This only happens on Windows;
POSIX already renders /, which is why it went unnoticed. Nested stylesheets
are explicitly supported: rx.App(stylesheets=["subdir/theme.css"]), and a
directory stylesheet is expanded via rglob into arbitrarily deep files, both
of which yield multi-segment relative paths.

The fix normalizes the import URL to forward slashes on every platform:

str_target_path = "./" + target_path.as_posix()

On POSIX the output is byte-for-byte identical to before, so only Windows
behavior changes. This mirrors the separator-normalization idiom already used
elsewhere in the compiler (e.g. reflex/compiler/utils.py).

Tests

  • Added test_compile_stylesheets_nested_import_uses_posix_separators in
    tests/units/compiler/test_compiler.py. It simulates Windows by forcing the
    relative path to a PureWindowsPath and asserts the emitted import is
    @import url('./subdir/theme.css'); with no backslash. It fails before the
    fix (emitting @import url('./subdir\theme.css');) and passes after.
  • Made two existing scss/sass assertions in the same file separator-independent
    so they express the intended forward-slash output directly.
  • uv run pytest tests/units/compiler -q -> 180 passed.
  • uv run ruff check . / uv run ruff format --check -> clean.
  • uv run pyright reflex tests -> 0 errors.

---

## Commits on the branch (2)

f7ec2402 fix(compiler): use posix separators for nested stylesheet imports
4f3b39fd fix(compiler): add changelog fragment for nested stylesheet posix fix


Both are GitHub-verified (ED25519, signature `G`) and carry a `Signed-off-by`
trailer. Diff: 3 files, +60/-6.

- `reflex/compiler/compiler.py` - one-line fix (`str(...)` -> `.as_posix()`) plus a
  three-line inline comment explaining the CSS-escape hazard.
- `tests/units/compiler/test_compiler.py` - new regression test + two assertions
  made separator-independent.
- `news/6725.bugfix.md` - towncrier changelog fragment (one user-facing sentence).

anxkhn added 2 commits July 14, 2026 13:53
The root stylesheet is compiled by interpolating each stylesheet's relative
path into a CSS `@import url('...')`. The path was rendered with
`str(target_path)`, which uses the OS separator, so on Windows a nested
stylesheet (e.g. `rx.App(stylesheets=["subdir/theme.css"])`, or a stylesheet
directory expanded via rglob) emitted `@import url('./subdir\theme.css');`.
In CSS a backslash inside url() is an escape introducer, not a path
separator, so the browser requested a mangled URL and the nested stylesheet
silently failed to load on Windows only. Top-level stylesheets have no
separator, which is why this went unnoticed.

Build the URL with `target_path.as_posix()` so the import always uses forward
slashes. On POSIX this is identical to the previous output; it only fixes
Windows. Add a regression test that forces a Windows-style relative path and
asserts the emitted import is POSIX-normalized, and make the existing
scss/sass assertions separator-independent.

Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
@anxkhn anxkhn requested a review from a team as a code owner July 14, 2026 08:24
@greptile-apps

greptile-apps Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes nested stylesheet imports on Windows. The main changes are:

  • Emits CSS import paths with POSIX separators.
  • Adds a Windows-path test for nested stylesheets.
  • Updates Sass and SCSS expectations to use forward slashes.
  • Adds a bug-fix changelog entry.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
reflex/compiler/compiler.py Uses Path.as_posix() when rendering local stylesheet paths into CSS import URLs.
tests/units/compiler/test_compiler.py Adds coverage for Windows-style nested paths and makes related expected URLs platform-independent.
news/6725.bugfix.md Documents the Windows nested-stylesheet import fix.

Reviews (1): Last reviewed commit: "fix(compiler): add changelog fragment fo..." | Re-trigger Greptile

@codspeed-hq

codspeed-hq Bot commented Jul 14, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 26 untouched benchmarks
⏩ 8 skipped benchmarks1


Comparing anxkhn:patch-9 (366ade7) with main (32cc257)

Open in CodSpeed

Footnotes

  1. 8 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant