pass lang and custom_attrs from app to html root (#2697)

* pass lang and custom_attrs from app to html root

* fix some pre-commit errors and try adding lang

* fix tests

* really fix test

* cleanup with @benedikt-bartscher

* fix props and tests

* use str instead of var

* change typing of html_custom_attrs to not allow Vars
This commit is contained in:
macmoritz 2024-03-03 22:51:20 +01:00 committed by GitHub
parent 5cb1f2007c
commit 9e0452beb0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 49 additions and 7 deletions

View File

@ -133,6 +133,12 @@ class App(Base):
# Components to add to the head of every page.
head_components: List[Component] = []
# The language to add to the html root tag of every page.
html_lang: Optional[str] = None
# Attributes to add to the html root tag of every page.
html_custom_attrs: Optional[Dict[str, str]] = None
# A component that is present on every page.
overlay_component: Optional[
Union[Component, ComponentCallable]
@ -782,7 +788,12 @@ class App(Base):
submit_work(compiler.compile_root_stylesheet, self.stylesheets)
# Compile the root document.
submit_work(compiler.compile_document_root, self.head_components)
submit_work(
compiler.compile_document_root,
self.head_components,
html_lang=self.html_lang,
html_custom_attrs=self.html_custom_attrs,
)
# Compile the theme.
submit_work(compiler.compile_theme, style=self.style)

View File

@ -4,7 +4,7 @@ from __future__ import annotations
import os
from pathlib import Path
from typing import Iterable, Optional, Type
from typing import Dict, Iterable, Optional, Type, Union
from reflex import constants
from reflex.compiler import templates, utils
@ -19,6 +19,7 @@ from reflex.config import get_config
from reflex.state import BaseState
from reflex.style import LIGHT_COLOR_MODE
from reflex.utils.imports import ImportVar
from reflex.vars import Var
def _compile_document_root(root: Component) -> str:
@ -299,11 +300,17 @@ def _compile_tailwind(
)
def compile_document_root(head_components: list[Component]) -> tuple[str, str]:
def compile_document_root(
head_components: list[Component],
html_lang: Optional[str] = None,
html_custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
) -> tuple[str, str]:
"""Compile the document root.
Args:
head_components: The components to include in the head.
html_lang: The language of the document, will be added to the html root element.
html_custom_attrs: custom attributes added to the html root element.
Returns:
The path and code of the compiled document root.
@ -312,7 +319,9 @@ def compile_document_root(head_components: list[Component]) -> tuple[str, str]:
output_path = utils.get_page_path(constants.PageNames.DOCUMENT_ROOT)
# Create the document root.
document_root = utils.create_document_root(head_components)
document_root = utils.create_document_root(
head_components, html_lang=html_lang, html_custom_attrs=html_custom_attrs
)
# Compile the document root.
code = _compile_document_root(document_root)

View File

@ -2,7 +2,7 @@
from __future__ import annotations
import os
from typing import Any, Callable, Type
from typing import Any, Callable, Dict, Optional, Type, Union
from urllib.parse import urlparse
from pydantic.fields import ModelField
@ -24,6 +24,7 @@ from reflex.components.component import Component, ComponentStyle, CustomCompone
from reflex.state import BaseState, Cookie, LocalStorage
from reflex.style import Style
from reflex.utils import console, format, imports, path_ops
from reflex.vars import Var
# To re-export this function.
merge_imports = imports.merge_imports
@ -261,11 +262,17 @@ def compile_custom_component(
)
def create_document_root(head_components: list[Component] | None = None) -> Component:
def create_document_root(
head_components: list[Component] | None = None,
html_lang: Optional[str] = None,
html_custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
) -> Component:
"""Create the document root.
Args:
head_components: The components to add to the head.
html_lang: The language of the document, will be added to the html root element.
html_custom_attrs: custom attributes added to the html root element.
Returns:
The document root.
@ -277,6 +284,8 @@ def create_document_root(head_components: list[Component] | None = None) -> Comp
Main.create(),
NextScript.create(),
),
lang=html_lang or "en",
custom_attrs=html_custom_attrs or {},
)

View File

@ -1,5 +1,7 @@
"""Document components."""
from typing import Optional
from reflex.components.component import Component
@ -14,6 +16,8 @@ class Html(NextDocumentLib):
tag = "Html"
lang: Optional[str]
class DocumentHead(NextDocumentLib):
"""The document head."""

View File

@ -7,6 +7,7 @@ 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
from typing import Optional
from reflex.components.component import Component
class NextDocumentLib(Component):
@ -94,6 +95,7 @@ class Html(NextDocumentLib):
def create( # type: ignore
cls,
*children,
lang: Optional[str] = None,
style: Optional[Style] = None,
key: Optional[Any] = None,
id: Optional[Any] = None,

View File

@ -195,8 +195,11 @@ def test_create_document_root():
"""Test that the document root is created correctly."""
# Test with no components.
root = utils.create_document_root()
root.render()
assert isinstance(root, utils.Html)
assert isinstance(root.children[0], utils.DocumentHead)
# Default language.
assert root.lang == "en" # type: ignore
# No children in head.
assert len(root.children[0].children) == 0
@ -205,6 +208,10 @@ def test_create_document_root():
utils.NextScript.create(src="foo.js"),
utils.NextScript.create(src="bar.js"),
]
root = utils.create_document_root(head_components=comps) # type: ignore
root = utils.create_document_root(head_components=comps, html_lang="rx", html_custom_attrs={"project": "reflex"}) # type: ignore
# Two children in head.
assert isinstance(root, utils.Html)
assert len(root.children[0].children) == 2
assert root.lang == "rx" # type: ignore
assert isinstance(root.custom_attrs, dict)
assert root.custom_attrs == {"project": "reflex"}