From 1f3fee598b8492bc251ab55494993b83959bbd35 Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Wed, 5 Jun 2024 10:02:05 -0700 Subject: [PATCH] [REF-3004] Use relative path to stylesheet for postcss-import compat (#3435) * test_tailwind: include custom stylesheet * [REF-3004] Use relative path to stylesheet for postcss-import compat postcss-import balls all of the CSS up into a single file, which happens at compile time. So, replace the `@/` with `../public` so the import paths can be resolved relative to the `styles` directory. * test_compiler: fix compile_stylesheets expectations * Use constants.Dirs.PUBLIC instead of "public" --- integration/test_tailwind.py | 15 ++++- reflex/compiler/compiler.py | 2 +- reflex/constants/base.py | 4 +- reflex/constants/base.pyi | 99 --------------------------------- tests/compiler/test_compiler.py | 4 +- 5 files changed, 20 insertions(+), 104 deletions(-) delete mode 100644 reflex/constants/base.pyi diff --git a/integration/test_tailwind.py b/integration/test_tailwind.py index 6155729c9..c7320cb21 100644 --- a/integration/test_tailwind.py +++ b/integration/test_tailwind.py @@ -25,6 +25,8 @@ def TailwindApp( paragraph_text: Text for the paragraph. paragraph_class_name: Tailwind class_name for the paragraph. """ + from pathlib import Path + import reflex as rx class UnusedState(rx.State): @@ -35,10 +37,15 @@ def TailwindApp( rx.chakra.text(paragraph_text, class_name=paragraph_class_name), rx.el.p(paragraph_text, class_name=paragraph_class_name), rx.text(paragraph_text, as_="p", class_name=paragraph_class_name), + rx.el.div("Test external stylesheet", class_name="external"), id="p-content", ) - app = rx.App(style={"font_family": "monospace"}) + assets = Path(__file__).resolve().parent.parent / "assets" + assets.mkdir(exist_ok=True) + stylesheet = assets / "test_styles.css" + stylesheet.write_text(".external { color: rgba(0, 0, 255, 0.5) }") + app = rx.App(style={"font_family": "monospace"}, stylesheets=[stylesheet.name]) app.add_page(index) if tailwind_disabled: config = rx.config.get_config() @@ -107,3 +114,9 @@ def test_tailwind_app(tailwind_app: AppHarness, tailwind_disabled: bool): else: # expect "text-red-500" from tailwind utility class assert p.value_of_css_property("color") in TEXT_RED_500_COLOR + + # Assert external stylesheet is applying rules + external = driver.find_elements(By.CLASS_NAME, "external") + assert len(external) == 1 + for ext_div in external: + assert ext_div.value_of_css_property("color") == "rgba(0, 0, 255, 0.5)" diff --git a/reflex/compiler/compiler.py b/reflex/compiler/compiler.py index 3f4f9a4be..128b2906a 100644 --- a/reflex/compiler/compiler.py +++ b/reflex/compiler/compiler.py @@ -169,7 +169,7 @@ def _compile_root_stylesheet(stylesheets: list[str]) -> str: raise FileNotFoundError( f"The stylesheet file {stylesheet_full_path} does not exist." ) - stylesheet = f"@/{stylesheet.strip('/')}" + stylesheet = f"../{constants.Dirs.PUBLIC}/{stylesheet.strip('/')}" sheets.append(stylesheet) if stylesheet not in sheets else None return templates.STYLE.render(stylesheets=sheets) diff --git a/reflex/constants/base.py b/reflex/constants/base.py index 94559c346..fbbe51707 100644 --- a/reflex/constants/base.py +++ b/reflex/constants/base.py @@ -27,6 +27,8 @@ class Dirs(SimpleNamespace): UTILS = "utils" # The name of the output static directory. STATIC = "_static" + # The name of the public html directory served at "/" + PUBLIC = "public" # The name of the state file. STATE_PATH = "/".join([UTILS, "state"]) # The name of the components file. @@ -40,7 +42,7 @@ class Dirs(SimpleNamespace): # The directory where the utils file is located. WEB_UTILS = os.path.join(WEB, UTILS) # The directory where the assets are located. - WEB_ASSETS = os.path.join(WEB, "public") + WEB_ASSETS = os.path.join(WEB, PUBLIC) # The env json file. ENV_JSON = os.path.join(WEB, "env.json") # The reflex json file. diff --git a/reflex/constants/base.pyi b/reflex/constants/base.pyi deleted file mode 100644 index 2fbeafd79..000000000 --- a/reflex/constants/base.pyi +++ /dev/null @@ -1,99 +0,0 @@ -"""Stub file for reflex/constants/base.py""" -# ------------------- DO NOT EDIT ---------------------- -# This file was generated by `reflex/utils/pyi_generator.py`! -# ------------------------------------------------------ - -from typing import Any, Dict, Literal, Optional, Union, overload -from reflex.vars import Var, BaseVar, ComputedVar -from reflex.event import EventChain, EventHandler, EventSpec -from reflex.style import Style -import os -import platform -from enum import Enum -from importlib import metadata -from types import SimpleNamespace -from platformdirs import PlatformDirs - -IS_WINDOWS = platform.system() == "Windows" -IS_WINDOWS_BUN_SUPPORTED_MACHINE = IS_WINDOWS and platform.machine() in [ - "AMD64", - "x86_64", -] - -class Dirs(SimpleNamespace): - WEB = ".web" - APP_ASSETS = "assets" - EXTERNAL_APP_ASSETS = "external" - UTILS = "utils" - STATIC = "_static" - STATE_PATH = "/".join([UTILS, "state"]) - COMPONENTS_PATH = "/".join([UTILS, "components"]) - CONTEXTS_PATH = "/".join([UTILS, "context"]) - WEB_PAGES = os.path.join(WEB, "pages") - WEB_STATIC = os.path.join(WEB, STATIC) - WEB_UTILS = os.path.join(WEB, UTILS) - WEB_ASSETS = os.path.join(WEB, "public") - ENV_JSON = os.path.join(WEB, "env.json") - REFLEX_JSON = os.path.join(WEB, "reflex.json") - POSTCSS_JS = os.path.join(WEB, "postcss.config.js") - -class Reflex(SimpleNamespace): - MODULE_NAME = "reflex" - VERSION = metadata.version(MODULE_NAME) - JSON = os.path.join(Dirs.WEB, "reflex.json") - _dir = os.environ.get("REFLEX_DIR", "") - DIR = _dir or PlatformDirs(MODULE_NAME, False).user_data_dir - ROOT_DIR = os.path.dirname( - os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - ) - -class ReflexHostingCLI(SimpleNamespace): - MODULE_NAME = "reflex-hosting-cli" - -class Templates(SimpleNamespace): - APP_TEMPLATES_ROUTE = "/app-templates" - DEFAULT = "blank" - - class Dirs(SimpleNamespace): - BASE = os.path.join(Reflex.ROOT_DIR, Reflex.MODULE_NAME, ".templates") - WEB_TEMPLATE = os.path.join(BASE, "web") - JINJA_TEMPLATE = os.path.join(BASE, "jinja") - CODE = "code" - -class Next(SimpleNamespace): - CONFIG_FILE = "next.config.js" - SITEMAP_CONFIG_FILE = os.path.join(Dirs.WEB, "next-sitemap.config.js") - NODE_MODULES = "node_modules" - PACKAGE_LOCK = "package-lock.json" - FRONTEND_LISTENING_REGEX = "Local:[\\s]+(.*)" - -class ColorMode(SimpleNamespace): - NAME = "colorMode" - USE = "useColorMode" - TOGGLE = "toggleColorMode" - -class Env(str, Enum): - DEV = "dev" - PROD = "prod" - -class LogLevel(str, Enum): - DEBUG = "debug" - INFO = "info" - WARNING = "warning" - ERROR = "error" - CRITICAL = "critical" - -POLLING_MAX_HTTP_BUFFER_SIZE = 1000 * 1000 - -class Ping(SimpleNamespace): - INTERVAL = 25 - TIMEOUT = 120 - -COOKIES = "cookies" -LOCAL_STORAGE = "local_storage" -SKIP_COMPILE_ENV_VAR = "__REFLEX_SKIP_COMPILE" -ENV_MODE_ENV_VAR = "REFLEX_ENV_MODE" -PYTEST_CURRENT_TEST = "PYTEST_CURRENT_TEST" -RELOAD_CONFIG = "__REFLEX_RELOAD_CONFIG" -REFLEX_VAR_OPENING_TAG = "" -REFLEX_VAR_CLOSING_TAG = "" diff --git a/tests/compiler/test_compiler.py b/tests/compiler/test_compiler.py index b6191974a..20dc7dd31 100644 --- a/tests/compiler/test_compiler.py +++ b/tests/compiler/test_compiler.py @@ -135,7 +135,7 @@ def test_compile_stylesheets(tmp_path, mocker): f"@import url('./tailwind.css'); \n" f"@import url('https://fonts.googleapis.com/css?family=Sofia&effect=neon|outline|emboss|shadow-multiple'); \n" f"@import url('https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css'); \n" - f"@import url('@/styles.css'); \n" + f"@import url('../public/styles.css'); \n" f"@import url('https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css'); \n", ) @@ -166,7 +166,7 @@ def test_compile_stylesheets_exclude_tailwind(tmp_path, mocker): assert compiler.compile_root_stylesheet(stylesheets) == ( os.path.join(".web", "styles", "styles.css"), - "@import url('@/styles.css'); \n", + "@import url('../public/styles.css'); \n", )