diff --git a/docs/README.md b/docs/README.md index 008fdd0..8a9cbfb 100644 --- a/docs/README.md +++ b/docs/README.md @@ -25,7 +25,7 @@ print( ) ``` -**And get HTML:** +**And Get HTML:** ```html @@ -44,14 +44,14 @@ print( ``` -## Motivation for this project +## Motivation for This Project At [Personalkollen](https://personalkollen.se/start/), where htpy was originally developed we often found ourselves hitting walls when using classic templates. htpy was created to improve the productiveness and experience of generating HTML from a Python backend. -## Key features +## Key Features - **Leverage static types:** Use [mypy](https://mypy.readthedocs.io/en/stable/) or [pyright](https://github.com/microsoft/pyright) to type check your code. @@ -84,7 +84,7 @@ scale from a single small Flask project to bigger applications. [Common patterns](https://htpy.dev/common-patterns/) can give you some ideas that you can build upon yourself. -## The syntax +## The Syntax Child elements are specified using the `[]` syntax. This may look strange at first but it has some nice benefits. This clearly separates attributes from diff --git a/docs/common-patterns.md b/docs/common-patterns.md index 1529b01..4b2fe0e 100644 --- a/docs/common-patterns.md +++ b/docs/common-patterns.md @@ -1,4 +1,4 @@ -# Common patterns +# Common Patterns htpy itself is a library that does not impose any particular structure for your code. You have the full power of Python @@ -9,7 +9,7 @@ General programming practices on how to structure modules, functions and classes This page describes common scenarios and patterns that may help you structure your own project in a good way. -## File/module structure +## File/Module Structure It is generally a good idea to keep your HTML pages/components separate from HTTP request handling and "business logic". @@ -41,7 +41,7 @@ def greeting_page(*, name: str) -> Element: return html[body[h1[f"hi {name}!"]]] ``` -## Using a base layout +## Using a Base Layout A common feature of template languages is to "extend" a base/parent template and specify placeholders. This can be achieved with a `base_layout` function: @@ -88,7 +88,7 @@ def about_page() -> Element: ``` -## UI components +## UI Components Creating higher level wrappers for common UI components can be a good idea to reduce repetition. diff --git a/docs/django.md b/docs/django.md index d428cf0..ca9250f 100644 --- a/docs/django.md +++ b/docs/django.md @@ -1,10 +1,11 @@ -# Usage with Django +# Usage With Django htpy is not tied to any specific web framework. Nonetheless, htpy works great when combined with Django. This page contains information and useful techniques on how to combine htpy and Django. -## Returning a htpy response +## Returning a htpy Response + htpy elements can be passed directly to `HttpResponse`: ```py title="views.py" @@ -15,7 +16,7 @@ def my_view(request): return HttpResponse(html[body[div["Hi Django!"]]]) ``` -## Using htpy as part of an existing Django template +## Using htpy as Part of an Existing Django Template htpy elements are marked as "safe" and can be injected directly into Django templates. This can be useful if you want to start using htpy gradually in an @@ -26,7 +27,9 @@ existing template based Django project: My Django Site - {{ content }} + + {{ content }} + ``` @@ -42,7 +45,7 @@ def index(request): }) ``` -## Render a Django form +## Render a Django Form CSRF token, form widgets and errors can be directly used within htpy elements: @@ -105,8 +108,7 @@ def my_form_success_page() -> Element: ) ``` - -## Implement custom form widgets with htpy +## Implement Custom Form Widgets With htpy You can implement a custom form widget directly with htpy like this: diff --git a/docs/html2htpy.md b/docs/html2htpy.md index ecce817..f5b0fb1 100644 --- a/docs/html2htpy.md +++ b/docs/html2htpy.md @@ -1,4 +1,4 @@ -# Convert HTML to htpy code +# Convert HTML to htpy Code Maybe you already have a bunch of HTML, or templates that you would like to migrate to htpy. We got you covered. The utility command `html2htpy` ships with `htpy`, and can be used to transform existing @@ -78,7 +78,7 @@ html(lang="en")[ ] ``` -## Piping input/stdin stream +## Piping Input/Stdin Stream You can also pipe input to htpy, for example `cat demo.html | html2htpy`. @@ -103,7 +103,7 @@ pbpaste | html2htpy > output.py powershell Get-Clipboard | html2htpy > output.py ``` -## Formatting the output +## Formatting the Output `html2htpy` can format the output Python code using `black` or `ruff`. Select the preferred formatter with the `-f`/`--format` flag. Options are `auto`, `ruff`, `black` and `none`. @@ -111,7 +111,7 @@ Select the preferred formatter with the `-f`/`--format` flag. Options are `auto` By default, the selection will be `auto`, formatting if it finds a formatter on path, prefering `ruff` if it's available. If no formatters are available on path, the output will not be formatted. -## Import options +## Import Options You have a couple of options regarding imports with the `-i`/`--imports` flag. Options are `yes` (default), `h`, `no`. @@ -129,7 +129,7 @@ h.section("#main-section.hero.is-link")[ ] ``` -## Explicit id and class kwargs +## Explicit ID and Class Kwargs If you prefer the explicit `id="id", class_="class"` kwargs syntax over the default htpy shorthand `#id.class` syntax, you can get it by passing the `--no-shorthand` flag. @@ -139,7 +139,7 @@ If you prefer the explicit `id="id", class_="class"` kwargs syntax over the defa ``` -#### Default shorthand yield `#id.class` +#### Default Shorthand Yield `#id.class` ```py title="$ html2htpy example.html" from htpy import p, section @@ -149,7 +149,7 @@ section("#main-section.hero.is-link")[ ] ``` -#### No shorthand yields kwargs `id`, `class_` +#### No Shorthand Yields Kwargs `id`, `class_` ```py title="$ html2htpy --no-shorthand example.html" from htpy import p, section @@ -159,7 +159,7 @@ section(id="main-section", class_="hero is-link")[ ] ``` -## Template interpolation to f-strings +## Template Interpolation to f-strings `html2htpy` will try to convert template variables to pythonic f-strings: diff --git a/docs/references.md b/docs/references.md index 2fe1185..9037c45 100644 --- a/docs/references.md +++ b/docs/references.md @@ -1,10 +1,10 @@ # References -## Projects that use htpy +## Projects That Use htpy - [voterbowl.org](https://voterbowl.org) - College students win prizes by checking if they are registered to vote: [Github repository](https://github.com/front-seat/voterbowl/tree/main/server/vb/components). -## Similar libraries and tools +## Similar Libraries and Tools htpy was heavily inspired by many other libraries that came before it. @@ -18,7 +18,7 @@ htpy was heavily inspired by many other libraries that came before it. - [h by Adam Johnson](https://github.com/adamchainz/h) - Similar to htpy, uses call syntax (`()`) for attributes and getitem (`[]`) for children. - [lxml.builder](https://lxml.de/apidoc/lxml.builder.html) - lxml's `E` allows creating XML/XHTML documents from Python. -## Articles about HTML generation without templates +## Articles About HTML Generation Without Templates - [Jeff Atwood - You're Doing It Wrong](https://blog.codinghorror.com/youre-doing-it-wrong/) - Stack Overflow co-founder Jeff Atwood - [Tavis Rudd - Throw out your templates](https://github.com/tavisrudd/throw_out_your_templates) - Tavis Rudd, creator of Python template language "Cheetah" argues for creating HTML without templates. diff --git a/docs/static-typing.md b/docs/static-typing.md index 09eb73d..774fbc3 100644 --- a/docs/static-typing.md +++ b/docs/static-typing.md @@ -1,4 +1,4 @@ -# Static typing +# Static Typing htpy was designed to be used with static typing. Since you define all your own data/components with regular Python, a static type checker like mypy will catch @@ -17,13 +17,13 @@ def greeting(user: User) -> Element: # mypy: error: "User" has no attribute "first_name" [attr-defined] ``` -## Autocompletion of HTML elements +## Autocompletion of HTML Elements htpy ships with type annotations for all HTML elements. If your editor supports it, it will show you useful auto completions: ![Screenshot of autocomplete in VS Code.](assets/autocomplete.webp "Using autocomplete in VS Code.") -## `Element` and `VoidElement` classes +## `Element` and `VoidElement` Classes The base types/classes in htpy are `Element` and `VoidElement`. `Element` are all regular HTML elements that can have children such as `
`, `` and diff --git a/docs/streaming.md b/docs/streaming.md index 03f1df8..403df6b 100644 --- a/docs/streaming.md +++ b/docs/streaming.md @@ -1,4 +1,4 @@ -# Streaming of contents +# Streaming of Contents Internally, htpy is built with generators. Most of the time, you would render the full page with `str()`, but htpy can also incrementally generate pages which @@ -26,7 +26,7 @@ CSS files in the `` tag before dynamic content, the browser can start working on loading the CSS and styling the page while the server keeps generating the rest of the page. -## Using generators and callables as children +## Using Generators and Callables as Children Django's querysets are [lazily evaluated](https://docs.djangoproject.com/en/5.0/topics/db/queries/#querysets-are-lazy). @@ -47,7 +47,7 @@ def article_list(request): ]) ``` -## Using callables to delay evalutation +## Using Callables to Delay Evalutation Pass a callable that does not accept any arguements as child to delay the evaluation. diff --git a/docs/usage.md b/docs/usage.md index 011e829..59dcf3e 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -20,7 +20,7 @@ Elements can be arbitrarily nested:

Lorem ipsum

``` -### Text/strings +### Text/Strings It is possible to pass a string directly: @@ -41,7 +41,7 @@ and safe to directly insert variable data via f-strings:

hello bobby </h1>

``` -### Conditional rendering +### Conditional Rendering `None` will not render anything. This can be useful to conditionally render some content. @@ -63,7 +63,7 @@ and safe to directly insert variable data via f-strings:
Enter a valid email address.
``` -### Loops / iterating over children +### Loops / Iterating Over Children You can pass a list, tuple or generator to generate multiple children: @@ -88,7 +88,7 @@ A `list` can be used similar to a [JSX fragment](https://react.dev/reference/rea
``` -### Custom elements / web components +### Custom Elements / Web Components [Custom elements / web components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements) @@ -101,7 +101,7 @@ used in Python identifiers, use underscore (`_`) instead: hi! ``` -### Injecting markup +### Injecting Markup If you have HTML markup that you want to insert without further escaping, wrap it in `Markup` from the [markupsafe](https://markupsafe.palletsprojects.com/) @@ -138,7 +138,7 @@ The [HTML doctype](https://developer.mozilla.org/en-US/docs/Glossary/Doctype) is HTML attributes are defined by calling the element. They can be specified in a couple of different ways. -### Elements without attributes +### Elements Without Attributes Some elements do not have attributes, they can be specified by just the element itself: @@ -148,7 +148,7 @@ Some elements do not have attributes, they can be specified by just the element
``` -### Keyword arguments +### Keyword Arguments Attributes can be specified via keyword arguments: @@ -174,7 +174,7 @@ Attributes that contains dashes `-` can be specified using underscores:
``` -### id/class shorthand +### Id/Class Shorthand Defining `id` and `class` attributes is common when writing HTML. A string shorthand that looks like a CSS selector can be used to quickly define id and classes: @@ -197,7 +197,7 @@ that looks like a CSS selector can be used to quickly define id and classes:
``` -### Attributes as dict +### Attributes as Dict Attributes can also be specified as a `dict`. This is useful when using attributes that are reserved Python keywords (like `for` or `class`), when the @@ -216,7 +216,7 @@ dynamically. ``` -### Boolean attributes +### Boolean Attributes In HTML, boolean attributes such as `disabled` are considered "true" when they exist. Specifying an attribute as `True` will make it appear (without a value). @@ -235,7 +235,7 @@ HTML. ``` -### Conditionally mixing CSS classes +### Conditionally Mixing CSS Classes To make it easier to mix CSS classes, the `class` attribute accepts a list of class names or a dict. Falsey values will be ignored. @@ -251,7 +251,7 @@ accepts a list of class names or a dict. Falsey values will be ignored. >>> ``` -### Combining modes +### Combining Modes Attributes via id/class shorthand, keyword arguments and dictionary can be combined: @@ -261,7 +261,7 @@ Attributes via id/class shorthand, keyword arguments and dictionary can be combi ``` -## Iterating of the output +## Iterating of the Output Iterating over a htpy element will yield the resulting contents in chunks as they are rendered: