Add head components to app (#1868)
This commit is contained in:
parent
8231993e5a
commit
89404e0b4a
@ -114,6 +114,9 @@ class App(Base):
|
||||
# The async server name space
|
||||
event_namespace: Optional[EventNamespace] = None
|
||||
|
||||
# Components to add to the head of every page.
|
||||
head_components: List[Component] = []
|
||||
|
||||
# A component that is present on every page.
|
||||
overlay_component: Optional[
|
||||
Union[Component, ComponentCallable]
|
||||
@ -401,6 +404,12 @@ class App(Base):
|
||||
|
||||
# Add script tags if given
|
||||
if script_tags:
|
||||
console.deprecate(
|
||||
feature_name="Passing script tags to add_page",
|
||||
reason="Add script components as children to the page component instead",
|
||||
deprecation_version="v0.2.9",
|
||||
removal_version="v0.2.11",
|
||||
)
|
||||
component.children.extend(script_tags)
|
||||
|
||||
# Add the page.
|
||||
@ -629,7 +638,7 @@ class App(Base):
|
||||
compile_results.append(compiler.compile_root_stylesheet(self.stylesheets))
|
||||
|
||||
# Compile the root document.
|
||||
compile_results.append(compiler.compile_document_root())
|
||||
compile_results.append(compiler.compile_document_root(self.head_components))
|
||||
|
||||
# Compile the theme.
|
||||
compile_results.append(compiler.compile_theme(self.style))
|
||||
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import List, Set, Tuple, Type
|
||||
from typing import Type
|
||||
|
||||
from reflex import constants
|
||||
from reflex.compiler import templates, utils
|
||||
@ -121,7 +121,7 @@ def _compile_page(
|
||||
)
|
||||
|
||||
|
||||
def compile_root_stylesheet(stylesheets: List[str]) -> Tuple[str, str]:
|
||||
def compile_root_stylesheet(stylesheets: list[str]) -> tuple[str, str]:
|
||||
"""Compile the root stylesheet.
|
||||
|
||||
Args:
|
||||
@ -137,7 +137,7 @@ def compile_root_stylesheet(stylesheets: List[str]) -> Tuple[str, str]:
|
||||
return output_path, code
|
||||
|
||||
|
||||
def _compile_root_stylesheet(stylesheets: List[str]) -> str:
|
||||
def _compile_root_stylesheet(stylesheets: list[str]) -> str:
|
||||
"""Compile the root stylesheet.
|
||||
|
||||
Args:
|
||||
@ -182,7 +182,7 @@ def _compile_component(component: Component) -> str:
|
||||
return templates.COMPONENT.render(component=component)
|
||||
|
||||
|
||||
def _compile_components(components: Set[CustomComponent]) -> str:
|
||||
def _compile_components(components: set[CustomComponent]) -> str:
|
||||
"""Compile the components.
|
||||
|
||||
Args:
|
||||
@ -226,9 +226,12 @@ def _compile_tailwind(
|
||||
)
|
||||
|
||||
|
||||
def compile_document_root() -> Tuple[str, str]:
|
||||
def compile_document_root(head_components: list[Component]) -> tuple[str, str]:
|
||||
"""Compile the document root.
|
||||
|
||||
Args:
|
||||
head_components: The components to include in the head.
|
||||
|
||||
Returns:
|
||||
The path and code of the compiled document root.
|
||||
"""
|
||||
@ -236,13 +239,14 @@ def compile_document_root() -> Tuple[str, str]:
|
||||
output_path = utils.get_page_path(constants.DOCUMENT_ROOT)
|
||||
|
||||
# Create the document root.
|
||||
document_root = utils.create_document_root()
|
||||
document_root = utils.create_document_root(head_components)
|
||||
|
||||
# Compile the document root.
|
||||
code = _compile_document_root(document_root)
|
||||
return output_path, code
|
||||
|
||||
|
||||
def compile_theme(style: ComponentStyle) -> Tuple[str, str]:
|
||||
def compile_theme(style: ComponentStyle) -> tuple[str, str]:
|
||||
"""Compile the theme.
|
||||
|
||||
Args:
|
||||
@ -261,9 +265,7 @@ def compile_theme(style: ComponentStyle) -> Tuple[str, str]:
|
||||
return output_path, code
|
||||
|
||||
|
||||
def compile_contexts(
|
||||
state: Type[State],
|
||||
) -> Tuple[str, str]:
|
||||
def compile_contexts(state: Type[State]) -> tuple[str, str]:
|
||||
"""Compile the initial state / context.
|
||||
|
||||
Args:
|
||||
@ -279,10 +281,8 @@ def compile_contexts(
|
||||
|
||||
|
||||
def compile_page(
|
||||
path: str,
|
||||
component: Component,
|
||||
state: Type[State],
|
||||
) -> Tuple[str, str]:
|
||||
path: str, component: Component, state: Type[State]
|
||||
) -> tuple[str, str]:
|
||||
"""Compile a single page.
|
||||
|
||||
Args:
|
||||
@ -301,7 +301,7 @@ def compile_page(
|
||||
return output_path, code
|
||||
|
||||
|
||||
def compile_components(components: Set[CustomComponent]):
|
||||
def compile_components(components: set[CustomComponent]):
|
||||
"""Compile the custom components.
|
||||
|
||||
Args:
|
||||
|
@ -2,7 +2,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import Any, Dict, List, Optional, Set, Tuple, Type
|
||||
from typing import Any, Type
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from pydantic.fields import ModelField
|
||||
@ -31,7 +31,7 @@ from reflex.vars import ImportVar
|
||||
merge_imports = imports.merge_imports
|
||||
|
||||
|
||||
def compile_import_statement(fields: Set[ImportVar]) -> Tuple[str, Set[str]]:
|
||||
def compile_import_statement(fields: set[ImportVar]) -> tuple[str, set[str]]:
|
||||
"""Compile an import statement.
|
||||
|
||||
Args:
|
||||
@ -79,7 +79,7 @@ def validate_imports(imports: imports.ImportDict):
|
||||
used_tags[import_name] = lib
|
||||
|
||||
|
||||
def compile_imports(imports: imports.ImportDict) -> List[dict]:
|
||||
def compile_imports(imports: imports.ImportDict) -> list[dict]:
|
||||
"""Compile an import dict.
|
||||
|
||||
Args:
|
||||
@ -112,7 +112,7 @@ def compile_imports(imports: imports.ImportDict) -> List[dict]:
|
||||
return import_dicts
|
||||
|
||||
|
||||
def get_import_dict(lib: str, default: str = "", rest: Optional[Set] = None) -> Dict:
|
||||
def get_import_dict(lib: str, default: str = "", rest: set[str] | None = None) -> dict:
|
||||
"""Get dictionary for import template.
|
||||
|
||||
Args:
|
||||
@ -130,7 +130,7 @@ def get_import_dict(lib: str, default: str = "", rest: Optional[Set] = None) ->
|
||||
}
|
||||
|
||||
|
||||
def compile_state(state: Type[State]) -> Dict:
|
||||
def compile_state(state: Type[State]) -> dict:
|
||||
"""Compile the state of the app.
|
||||
|
||||
Args:
|
||||
@ -225,7 +225,7 @@ def compile_client_storage(state: Type[State]) -> dict[str, dict]:
|
||||
|
||||
def compile_custom_component(
|
||||
component: CustomComponent,
|
||||
) -> Tuple[dict, imports.ImportDict]:
|
||||
) -> tuple[dict, imports.ImportDict]:
|
||||
"""Compile a custom component.
|
||||
|
||||
Args:
|
||||
@ -258,14 +258,18 @@ def compile_custom_component(
|
||||
)
|
||||
|
||||
|
||||
def create_document_root() -> Component:
|
||||
def create_document_root(head_components: list[Component] | None = None) -> Component:
|
||||
"""Create the document root.
|
||||
|
||||
Args:
|
||||
head_components: The components to add to the head.
|
||||
|
||||
Returns:
|
||||
The document root.
|
||||
"""
|
||||
head_components = head_components or []
|
||||
return Html.create(
|
||||
DocumentHead.create(),
|
||||
DocumentHead.create(*head_components),
|
||||
Body.create(
|
||||
ColorModeScript.create(),
|
||||
Main.create(),
|
||||
@ -274,7 +278,7 @@ def create_document_root() -> Component:
|
||||
)
|
||||
|
||||
|
||||
def create_theme(style: ComponentStyle) -> Dict:
|
||||
def create_theme(style: ComponentStyle) -> dict:
|
||||
"""Create the base style for the app.
|
||||
|
||||
Args:
|
||||
@ -350,11 +354,11 @@ def get_components_path() -> str:
|
||||
return os.path.join(constants.WEB_UTILS_DIR, "components" + constants.JS_EXT)
|
||||
|
||||
|
||||
def get_asset_path(filename: Optional[str] = None) -> str:
|
||||
def get_asset_path(filename: str | None = None) -> str:
|
||||
"""Get the path for an asset.
|
||||
|
||||
Args:
|
||||
filename: Optional, if given, is added to the root path of assets dir.
|
||||
filename: If given, is added to the root path of assets dir.
|
||||
|
||||
Returns:
|
||||
The path of the asset.
|
||||
@ -366,7 +370,7 @@ def get_asset_path(filename: Optional[str] = None) -> str:
|
||||
|
||||
|
||||
def add_meta(
|
||||
page: Component, title: str, image: str, description: str, meta: List[Dict]
|
||||
page: Component, title: str, image: str, description: str, meta: list[dict]
|
||||
) -> Component:
|
||||
"""Add metadata to a page.
|
||||
|
||||
@ -406,7 +410,7 @@ def write_page(path: str, code: str):
|
||||
f.write(code)
|
||||
|
||||
|
||||
def empty_dir(path: str, keep_files: Optional[List[str]] = None):
|
||||
def empty_dir(path: str, keep_files: list[str] | None = None):
|
||||
"""Remove all files and folders in a directory except for the keep_files.
|
||||
|
||||
Args:
|
||||
|
@ -189,3 +189,22 @@ def test_compile_nonexistent_stylesheet(tmp_path, mocker):
|
||||
|
||||
with pytest.raises(FileNotFoundError):
|
||||
compiler.compile_root_stylesheet(stylesheets)
|
||||
|
||||
|
||||
def test_create_document_root():
|
||||
"""Test that the document root is created correctly."""
|
||||
# Test with no components.
|
||||
root = utils.create_document_root()
|
||||
assert isinstance(root, utils.Html)
|
||||
assert isinstance(root.children[0], utils.DocumentHead)
|
||||
# No children in head.
|
||||
assert len(root.children[0].children) == 0
|
||||
|
||||
# Test with components.
|
||||
comps = [
|
||||
utils.NextScript.create(src="foo.js"),
|
||||
utils.NextScript.create(src="bar.js"),
|
||||
]
|
||||
root = utils.create_document_root(head_components=comps) # type: ignore
|
||||
# Two children in head.
|
||||
assert len(root.children[0].children) == 2
|
||||
|
Loading…
Reference in New Issue
Block a user