Add head components to app (#1868)

This commit is contained in:
Nikhil Rao 2023-09-25 16:53:15 -07:00 committed by GitHub
parent 8231993e5a
commit 89404e0b4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 29 deletions

View File

@ -114,6 +114,9 @@ class App(Base):
# The async server name space # The async server name space
event_namespace: Optional[EventNamespace] = None 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. # A component that is present on every page.
overlay_component: Optional[ overlay_component: Optional[
Union[Component, ComponentCallable] Union[Component, ComponentCallable]
@ -401,6 +404,12 @@ class App(Base):
# Add script tags if given # Add script tags if given
if script_tags: 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) component.children.extend(script_tags)
# Add the page. # Add the page.
@ -629,7 +638,7 @@ class App(Base):
compile_results.append(compiler.compile_root_stylesheet(self.stylesheets)) compile_results.append(compiler.compile_root_stylesheet(self.stylesheets))
# Compile the root document. # 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 the theme.
compile_results.append(compiler.compile_theme(self.style)) compile_results.append(compiler.compile_theme(self.style))

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import os import os
from pathlib import Path from pathlib import Path
from typing import List, Set, Tuple, Type from typing import Type
from reflex import constants from reflex import constants
from reflex.compiler import templates, utils 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. """Compile the root stylesheet.
Args: Args:
@ -137,7 +137,7 @@ def compile_root_stylesheet(stylesheets: List[str]) -> Tuple[str, str]:
return output_path, code return output_path, code
def _compile_root_stylesheet(stylesheets: List[str]) -> str: def _compile_root_stylesheet(stylesheets: list[str]) -> str:
"""Compile the root stylesheet. """Compile the root stylesheet.
Args: Args:
@ -182,7 +182,7 @@ def _compile_component(component: Component) -> str:
return templates.COMPONENT.render(component=component) return templates.COMPONENT.render(component=component)
def _compile_components(components: Set[CustomComponent]) -> str: def _compile_components(components: set[CustomComponent]) -> str:
"""Compile the components. """Compile the components.
Args: 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. """Compile the document root.
Args:
head_components: The components to include in the head.
Returns: Returns:
The path and code of the compiled document root. 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) output_path = utils.get_page_path(constants.DOCUMENT_ROOT)
# Create the document root. # Create the document root.
document_root = utils.create_document_root() document_root = utils.create_document_root(head_components)
# Compile the document root. # Compile the document root.
code = _compile_document_root(document_root) code = _compile_document_root(document_root)
return output_path, code return output_path, code
def compile_theme(style: ComponentStyle) -> Tuple[str, str]: def compile_theme(style: ComponentStyle) -> tuple[str, str]:
"""Compile the theme. """Compile the theme.
Args: Args:
@ -261,9 +265,7 @@ def compile_theme(style: ComponentStyle) -> Tuple[str, str]:
return output_path, code return output_path, code
def compile_contexts( def compile_contexts(state: Type[State]) -> tuple[str, str]:
state: Type[State],
) -> Tuple[str, str]:
"""Compile the initial state / context. """Compile the initial state / context.
Args: Args:
@ -279,10 +281,8 @@ def compile_contexts(
def compile_page( def compile_page(
path: str, path: str, component: Component, state: Type[State]
component: Component, ) -> tuple[str, str]:
state: Type[State],
) -> Tuple[str, str]:
"""Compile a single page. """Compile a single page.
Args: Args:
@ -301,7 +301,7 @@ def compile_page(
return output_path, code return output_path, code
def compile_components(components: Set[CustomComponent]): def compile_components(components: set[CustomComponent]):
"""Compile the custom components. """Compile the custom components.
Args: Args:

View File

@ -2,7 +2,7 @@
from __future__ import annotations from __future__ import annotations
import os import os
from typing import Any, Dict, List, Optional, Set, Tuple, Type from typing import Any, Type
from urllib.parse import urlparse from urllib.parse import urlparse
from pydantic.fields import ModelField from pydantic.fields import ModelField
@ -31,7 +31,7 @@ from reflex.vars import ImportVar
merge_imports = imports.merge_imports 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. """Compile an import statement.
Args: Args:
@ -79,7 +79,7 @@ def validate_imports(imports: imports.ImportDict):
used_tags[import_name] = lib 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. """Compile an import dict.
Args: Args:
@ -112,7 +112,7 @@ def compile_imports(imports: imports.ImportDict) -> List[dict]:
return import_dicts 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. """Get dictionary for import template.
Args: 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. """Compile the state of the app.
Args: Args:
@ -225,7 +225,7 @@ def compile_client_storage(state: Type[State]) -> dict[str, dict]:
def compile_custom_component( def compile_custom_component(
component: CustomComponent, component: CustomComponent,
) -> Tuple[dict, imports.ImportDict]: ) -> tuple[dict, imports.ImportDict]:
"""Compile a custom component. """Compile a custom component.
Args: 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. """Create the document root.
Args:
head_components: The components to add to the head.
Returns: Returns:
The document root. The document root.
""" """
head_components = head_components or []
return Html.create( return Html.create(
DocumentHead.create(), DocumentHead.create(*head_components),
Body.create( Body.create(
ColorModeScript.create(), ColorModeScript.create(),
Main.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. """Create the base style for the app.
Args: Args:
@ -350,11 +354,11 @@ def get_components_path() -> str:
return os.path.join(constants.WEB_UTILS_DIR, "components" + constants.JS_EXT) 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. """Get the path for an asset.
Args: 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: Returns:
The path of the asset. The path of the asset.
@ -366,7 +370,7 @@ def get_asset_path(filename: Optional[str] = None) -> str:
def add_meta( 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: ) -> Component:
"""Add metadata to a page. """Add metadata to a page.
@ -406,7 +410,7 @@ def write_page(path: str, code: str):
f.write(code) 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. """Remove all files and folders in a directory except for the keep_files.
Args: Args:

View File

@ -189,3 +189,22 @@ def test_compile_nonexistent_stylesheet(tmp_path, mocker):
with pytest.raises(FileNotFoundError): with pytest.raises(FileNotFoundError):
compiler.compile_root_stylesheet(stylesheets) 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