-
-
Notifications
You must be signed in to change notification settings - Fork 17
Version 3 refactoring #78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from 19 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
f2c04d1
chore: code restructuring
volfpeter d9c9307
chore: updating example apps + small doc fix
volfpeter 93656f4
docs: update the Jinja intro in the readme
volfpeter af1a108
docs: update the htmy example in the documentation
volfpeter 7f55448
docs: update the jinja example in the documentation
volfpeter 8dc22f5
chore: fix type hint in custom-templating docs
volfpeter 9e94407
docs: updated API documentation
volfpeter b7f7f18
chore: update dependencies
volfpeter 27707c2
chore: bump patch version
volfpeter 3ce19bd
chore: rename *HTMLRenderer types to *RenderFunction, refs #44
volfpeter c24184d
docs: add v3 upgrade guide, plus a minor doc fix
volfpeter 626be7e
docs: add the v3 upgrade guide to the docs
volfpeter 28a1a2e
coderabbit evaluation
volfpeter 16af2fd
chore: fixed typos, removed comments that are no longer needed
volfpeter 3790558
docs: replace remaining HTMLRenderer usage with RenderFunction
volfpeter 764baac
docs: add Opinions section
volfpeter 12745c0
docs: processing comments from coderabbit review
volfpeter 5d8144d
docs: more nitpicking
volfpeter f00b676
chore: replace the stupid HTMY.htmy property with HTMY.renderer, refs
volfpeter f4d5a83
docs: fixing some small documentation issues
volfpeter 3fbf95d
feat: upgrade htmy, and the htmy extra also brings lxml by default
volfpeter 11c2432
feat: upgrade htmy to 0.8.1 and allow any RendererType implementations
volfpeter 10f94f4
fix: v3 upgrade docs and htmy dev dependency version
volfpeter 7bb3df0
chore: more intuitive (and shorter) poe task names
volfpeter 24aee69
feat: simplify the RenderFunction type (require str return type) and
volfpeter fa8ff79
docs: nitpicking in the v3 upgrade docs
volfpeter 6771ec4
chore: cleanup the page() core decorator
volfpeter 1e5e6b5
chore: process typos based on coderabbit feedback
volfpeter 6d821a4
feat: make the component_selector argument optional for the htmy
volfpeter 9e14226
chore: add some type ignores where mypy can't infer the generic, not the
volfpeter File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,4 @@ | ||
| # Core Decorators | ||
|
|
||
| ## ::: fasthx.hx | ||
|
|
||
| options: | ||
| show_root_heading: true | ||
|
|
||
| ## ::: fasthx.page | ||
| # ::: fasthx.core_decorators | ||
|
|
||
| options: | ||
| show_root_heading: true | ||
volfpeter marked this conversation as resolved.
Show resolved
Hide resolved
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,4 @@ | ||
| # FastAPI Dependencies | ||
|
|
||
| ## ::: fasthx.DependsHXRequest | ||
|
|
||
| options: | ||
| show_root_heading: true | ||
|
|
||
| ## ::: fasthx.get_hx_request | ||
| # ::: fasthx.dependencies | ||
|
|
||
| options: | ||
| show_root_heading: true | ||
volfpeter marked this conversation as resolved.
Show resolved
Hide resolved
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,4 @@ | ||
| # `Jinja` | ||
| # ::: fasthx.jinja | ||
|
|
||
| ## ::: fasthx.Jinja | ||
| options: | ||
| show_root_heading: true | ||
|
|
||
| ## ::: fasthx.JinjaContext | ||
| options: | ||
| show_root_heading: true | ||
|
|
||
| ## ::: fasthx.TemplateHeader | ||
| options: | ||
| show_root_heading: true | ||
|
|
||
| ## ::: fasthx.JinjaPath | ||
| options: | ||
| show_root_heading: true | ||
|
|
||
| ## ::: fasthx.JinjaContextFactory | ||
| members: | ||
| - __call__ | ||
| options: | ||
| show_root_heading: true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,25 +1,4 @@ | ||
| # Typing | ||
| # ::: fasthx.typing | ||
|
|
||
| ## ::: fasthx.HTMLRenderer | ||
| options: | ||
| show_root_heading: true | ||
|
|
||
| ## ::: fasthx.typing.SyncHTMLRenderer | ||
| members: | ||
| - __call__ | ||
| options: | ||
| show_root_heading: true | ||
|
|
||
| ## ::: fasthx.typing.AsyncHTMLRenderer | ||
| members: | ||
| - __call__ | ||
| options: | ||
| show_root_heading: true | ||
|
|
||
| ## ::: fasthx.typing.RequestComponentSelector | ||
| options: | ||
| show_root_heading: true | ||
|
|
||
| ## ::: fasthx.typing.ComponentSelector | ||
| options: | ||
| show_root_heading: true | ||
volfpeter marked this conversation as resolved.
Show resolved
Hide resolved
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,13 +8,13 @@ First, let's create an `htmy_app.py` file, import everything that is required fo | |
| import random | ||
| from dataclasses import dataclass | ||
| from datetime import date | ||
| from typing import Any | ||
|
|
||
| from fastapi import FastAPI | ||
| from fasthx.htmy import HTMY, ComponentHeader, CurrentRequest, RouteParams | ||
| from htmy import Component, Context, html | ||
| from pydantic import BaseModel | ||
|
|
||
| from fasthx.htmy import HTMY, ComponentHeader, CurrentRequest, RouteParams | ||
|
|
||
|
|
||
| class User(BaseModel): | ||
| """User model.""" | ||
|
|
@@ -23,24 +23,19 @@ class User(BaseModel): | |
| birthday: date | ||
| ``` | ||
|
|
||
| The main content on the user interface will be a user list, so let's start by creating a simple `UserListItem` component: | ||
| The main content on the user interface will be a user list, so let's start by creating a simple `user_list_item` component factory (see the [htmy components guide](https://volfpeter.github.io/htmy/components-guide/) for more information): | ||
|
|
||
| ```python | ||
| @dataclass | ||
| class UserListItem: | ||
| """User list item component.""" | ||
|
|
||
| user: User | ||
|
|
||
| def htmy(self, context: Context) -> Component: | ||
| return html.li( | ||
| html.span(self.user.name, class_="font-semibold"), | ||
| html.em(f" (born {self.user.birthday.isoformat()})"), | ||
| class_="text-lg", | ||
| ) | ||
| def user_list_item(user: User) -> html.li: | ||
| """User list item component factory.""" | ||
| return html.li( | ||
| html.span(user.name, class_="font-semibold"), | ||
| html.em(f" (born {user.birthday.isoformat()})"), | ||
| class_="text-lg", | ||
| ) | ||
| ``` | ||
|
|
||
| As you can see, the component has a single `user` property and it renders an `<li>` HTML element with the user's name and birthday in it. | ||
| As you can see, the component factory expects a `user` and it creates an `<li>` HTML element with the user's name and birthday in it. | ||
|
|
||
| The next component we need is the user list itself. This is going to be the most complex part of the example: | ||
|
|
||
|
|
@@ -70,7 +65,7 @@ class UserOverview: | |
| rerenders: int = route_params["rerenders"] | ||
|
|
||
| # Create the user list item generator. | ||
| user_list_items = (UserListItem(u) for u in self.users) | ||
| user_list_items = (user_list_item(u) for u in self.users) | ||
|
|
||
| # Create the ordered or unordered user list. | ||
| user_list = ( | ||
|
|
@@ -92,7 +87,7 @@ class UserOverview: | |
| user_list, | ||
| # -- HTMX directives. | ||
| hx_trigger="load delay:1000", | ||
| hx_get=f"/users?rerenders={rerenders+1}", | ||
| hx_get=f"/users?rerenders={rerenders + 1}", | ||
| hx_swap="outerHTML", | ||
| # Send the next component variant in an X-Component header. | ||
| hx_headers=f'{{"X-Component": "{next_variant}"}}', | ||
|
|
@@ -107,37 +102,33 @@ Most of this code is basic Python and `htmy` usage (including the `hx_*` `HTMX` | |
| - The use of `RouteParams.from_context()` to get access to every route parameter (resolved FastAPI dependency) as a mapping. | ||
| - The `context["user-agent"]` lookup that accesses a value from the context which will be added by a _request processor_ later in the example. | ||
|
|
||
| We need one last `htmy` component, the index page. Most of this component is just the basic HTML document structure with some TailwindCSS styling and metadata. There is also a bit of `HTMX` in the `body` for lazy loading the actual page content, the user list we just created. | ||
| We need one last `htmy` component, the index page. Most of this component (component factory to be more precise) is just the basic HTML document structure with some TailwindCSS styling and metadata. There is also a bit of `HTMX` in the `body` for lazy loading the actual page content, the user list we just created. | ||
|
|
||
| ```python | ||
| @dataclass | ||
| class IndexPage: | ||
| """Index page with TailwindCSS styling.""" | ||
|
|
||
| def htmy(self, context: Context) -> Component: | ||
| return ( | ||
| html.DOCTYPE.html, | ||
| html.html( | ||
| html.head( | ||
| # Some metadata | ||
| html.title("FastHX + HTMY example"), | ||
| html.meta.charset(), | ||
| html.meta.viewport(), | ||
| # TailwindCSS | ||
| html.script(src="https://cdn.tailwindcss.com"), | ||
| # HTMX | ||
| html.script(src="https://unpkg.com/[email protected]"), | ||
| ), | ||
| html.body( | ||
| # Page content: lazy-loaded user list. | ||
| html.div(hx_get="/users", hx_trigger="load", hx_swap="outerHTML"), | ||
| class_=( | ||
| "h-screen w-screen flex flex-col items-center justify-center " | ||
| " gap-4 bg-slate-800 text-white" | ||
| ), | ||
| def index_page(_: Any) -> Component: | ||
| return ( | ||
| html.DOCTYPE.html, | ||
| html.html( | ||
| html.head( | ||
| # Some metadata | ||
| html.title("FastHX + HTMY example"), | ||
| html.meta.charset(), | ||
| html.meta.viewport(), | ||
| # TailwindCSS | ||
| html.script(src="https://cdn.tailwindcss.com"), | ||
| # HTMX | ||
| html.script(src="https://unpkg.com/[email protected]"), | ||
| ), | ||
| html.body( | ||
| # Page content: lazy-loaded user list. | ||
| html.div(hx_get="/users", hx_trigger="load", hx_swap="outerHTML"), | ||
| class_=( | ||
| "h-screen w-screen flex flex-col items-center justify-center " | ||
| " gap-4 bg-slate-800 text-white" | ||
| ), | ||
| ), | ||
| ) | ||
| ), | ||
| ) | ||
| ``` | ||
|
|
||
| With all the components ready, we can now create the `FastAPI` and `fasthx.htmy.HTMY` instances: | ||
|
|
@@ -159,11 +150,11 @@ Note how we added a _request processor_ function to the `HTMY` instance that tak | |
|
|
||
| All that remains now is the routing. We need two routes: one that serves the index page, and one that renders the ordered or unordered user list. | ||
|
|
||
| The index page route is trivial. The `htmy.page()` decorator expects a component factory (well more precisely a `fasthx.ComponentSelector`) that accepts the route's return value and returns an `htmy` component. Since `IndexPage` has no properties, we use a simple `lambda` to create such a function: | ||
| The index page route is trivial. The `htmy.page()` decorator expects a component factory (well more precisely a `fasthx.ComponentSelector`) that accepts the route's return value and returns an `htmy` component. `index_page` is implemented exactly like this, so we can use it directly in the decorator: | ||
|
|
||
| ```python | ||
| @app.get("/") | ||
| @htmy.page(lambda _: IndexPage()) | ||
| @htmy.page(index_page) | ||
| def index() -> None: | ||
| """The index page of the application.""" | ||
| ... | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.