diff --git a/docs/how-to/convert-html.md b/docs/how-to/convert-html.md
new file mode 100644
index 0000000..ee6a2a4
--- /dev/null
+++ b/docs/how-to/convert-html.md
@@ -0,0 +1,143 @@
+# 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. This page describes how you can convert existing HTML to htpy code.
+
+The utility command `html2htpy` ships with `htpy`, and can be used to transform existing HTML into Python code (htpy!).
+
+Lets say you have an existing HTML file:
+
+```html title="index.html"
+
+
+
+
+
+ htpy Recipes
+
+
+
+
+
+
+ Recipe of the Day: Spaghetti Carbonara
+
+
This classic Italian dish is quick and easy to make.
+
+
+
+
+
+```
+
+Now, if you run the command, it outputs the corresponding Python code (htpy).
+
+```
+$ html2htpy index.html
+```
+
+```py
+from htpy import body, div, h1, h2, head, html, meta, p, span, title
+
+html(lang="en")[
+ head[
+ meta(charset="UTF-8"),
+ meta(name="viewport", content="width=device-width, initial-scale=1.0"),
+ title["htpy Recipes"],
+ ],
+ body[
+ div("#header")[
+ h1["Welcome to the cooking site"], p["Your go-to place for delicious recipes!"]
+ ],
+ div("#recipe-of-the-day.section")[
+ h2["Recipe of the Day: ", span(".highlight")["Spaghetti Carbonara"]],
+ p["This classic Italian dish is quick and easy to make."],
+ ],
+ div("#footer")[p["© 2024 My Cooking Site. All rights reserved."]],
+ ],
+]
+```
+
+## Convert HTML snippets from the clipboard
+
+This can be combined with other workflows in the way that you find most suitable.
+For example, you might pipe from your clipboard to htpy, and optionally direct the output to a file.
+
+### Linux
+
+```
+xclip -o -selection clipboard | html2htpy > output.py
+```
+
+### Mac
+
+```
+pbpaste | html2htpy > output.py
+```
+
+### Windows
+
+```
+powershell Get-Clipboard | html2htpy > output.py
+```
+
+## Converting Django/Jinja templates
+
+`html2htpy` will convert Django/Jinja-style template variables to f-strings:
+
+``` html title="input"
+hi {{ name }}!
+```
+
+``` py title="html2htpy output"
+
+from htpy import div
+
+div[f"hi { name }!"]
+
+```
+
+### Limitations
+
+Other typical template syntax, such as loops `{% for x in y %}`, can not be transformed this way,
+so you will often have to clean up a bit after `html2htpy` is done with its thing.
+
+See the example below:
+
+```html title="jinja.html"
+
+ {{ heading }}
+ Welcome to our cooking site, {{ user.name }}!
+
+ Recipe of the Day: {{ recipe.name }}
+ {{ recipe.description }}
+
+ Instructions:
+
+ {% for step in recipe.steps %}
+ - {{ step }}
+ {% endfor %}
+
+
+```
+
+```py title="$ html2htpy jinja.html"
+from htpy import body, h1, h2, h3, li, ol, p
+
+body[
+ h1[f"{ heading }"],
+ p[f"Welcome to our cooking site, { user.name }!"],
+ h2[f"Recipe of the Day: { recipe.name }"],
+ p[f"{ recipe.description }"],
+ h3["Instructions:"],
+ ol[" {% for step in recipe.steps %}", li[f"{ step }"], " {% endfor %}"],
+]
+```
+
+## VSCode Extension
+
+If you are using VSCode, you can install the [html2htpy](https://marketplace.visualstudio.com/items?itemName=dunderrrrrr.html2htpy) extension to quickly convert HTML to htpy code.
diff --git a/docs/html2htpy.md b/docs/html2htpy.md
deleted file mode 100644
index ce54722..0000000
--- a/docs/html2htpy.md
+++ /dev/null
@@ -1,205 +0,0 @@
-# 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
-html into Python code (htpy!).
-
-```
-$ html2htpy -h
-usage: html2htpy [-h] [-f {auto,ruff,black,none}] [-i {yes,h,no}] [--no-shorthand] [input]
-
-positional arguments:
- input input HTML from file or stdin
-
-options:
- -h, --help show this help message and exit
- -f {auto,ruff,black,none}, --format {auto,ruff,black,none}
- Select one of the following formatting options: auto, ruff, black or none
- -i {yes,h,no}, --imports {yes,h,no}
- Output mode for imports of found htpy elements
- --no-shorthand Use explicit `id` and `class_` kwargs instead of the shorthand #id.class syntax
-```
-
-Lets say you have an existing HTML file:
-
-```html title="index.html"
-
-
-
-
-
- htpy Recipes
-
-
-
-
-
-
- Recipe of the Day: Spaghetti Carbonara
-
-
This classic Italian dish is quick and easy to make.
-
-
-
-
-
-```
-
-Now, if you run the command, it outputs the corresponding Python code (htpy).
-
-```
-$ html2htpy index.html
-```
-
-```py
-from htpy import body, div, h1, h2, head, html, meta, p, span, title
-
-html(lang="en")[
- head[
- meta(charset="UTF-8"),
- meta(name="viewport", content="width=device-width, initial-scale=1.0"),
- title["htpy Recipes"],
- ],
- body[
- div("#header")[
- h1["Welcome to the cooking site"], p["Your go-to place for delicious recipes!"]
- ],
- div("#recipe-of-the-day.section")[
- h2["Recipe of the Day: ", span(".highlight")["Spaghetti Carbonara"]],
- p["This classic Italian dish is quick and easy to make."],
- ],
- div("#footer")[p["© 2024 My Cooking Site. All rights reserved."]],
- ],
-]
-```
-
-## Piping Input/Stdin Stream
-
-You can also pipe input to htpy, for example `cat demo.html | html2htpy`.
-
-This can be combined with other workflows in the way that you find most suitable.
-For example, you might pipe from your clipboard to htpy, and optionally direct the output to a file.
-
-#### Linux
-
-```
-xclip -o -selection clipboard | html2htpy > output.py
-```
-
-#### Mac
-
-```
-pbpaste | html2htpy > output.py
-```
-
-#### Windows
-
-```
-powershell Get-Clipboard | html2htpy > output.py
-```
-
-## 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`.
-
-By default, the selection will be `auto`, formatting if it finds a formatter on path, preferring `black` if it's available.
-If no formatters are available on path, the output will not be formatted.
-
-## Import Options
-
-You have a couple of options regarding imports with the `-i`/`--imports` flag.
-Options are `yes` (default), `h`, `no`.
-
-#### Module import of htpy: `--imports=h`
-
-Some people prefer to `import htpy as h` instead of importing individual elements from htpy.
-If this is you, you can use the `--imports=h` option to get corresponding output when using `html2htpy`.
-
-```py title="$ html2htpy --imports=h example.html"
-import htpy as h
-
-h.section("#main-section.hero.is-link")[
- h.p(".subtitle.is-3.is-spaced")["Welcome"]
-]
-```
-
-## 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.
-
-```html title="example.html"
-
-```
-
-#### Default Shorthand Yield `#id.class`
-
-```py title="$ html2htpy example.html"
-from htpy import p, section
-
-section("#main-section.hero.is-link")[
- p(".subtitle.is-3.is-spaced")["Welcome"]
-]
-```
-
-#### No Shorthand Yields Kwargs `id`, `class_`
-
-```py title="$ html2htpy --no-shorthand example.html"
-from htpy import p, section
-
-section(id="main-section", class_="hero is-link")[
- p(class_="subtitle is-3 is-spaced")["Welcome"]
-]
-```
-
-## Template Interpolation to f-strings
-
-`html2htpy` will try to convert template variables to pythonic f-strings:
-
-`template {{ variables }}` -> `f"template { variables }"`
-
-Note that other typical template syntax, such as loops `{% for x in y %}`, can not be transformed this way,
-so you will often have to clean up a bit after `html2htpy` is done with its thing.
-
-See the example below:
-
-```html title="jinja.html"
-
- {{ heading }}
- Welcome to our cooking site, {{ user.name }}!
-
- Recipe of the Day: {{ recipe.name }}
- {{ recipe.description }}
-
- Instructions:
-
- {% for step in recipe.steps %}
- - {{ step }}
- {% endfor %}
-
-
-```
-
-```py title="$ html2htpy jinja.html"
-from htpy import body, h1, h2, h3, li, ol, p
-
-body[
- h1[f"{ heading }"],
- p[f"Welcome to our cooking site, { user.name }!"],
- h2[f"Recipe of the Day: { recipe.name }"],
- p[f"{ recipe.description }"],
- h3["Instructions:"],
- ol[" {% for step in recipe.steps %}", li[f"{ step }"], " {% endfor %}"],
-]
-```
-
-## VSCode Extension
-
-If you are using VSCode, you can install the [html2htpy](https://marketplace.visualstudio.com/items?itemName=dunderrrrrr.html2htpy) extension to quickly convert HTML to htpy code.
\ No newline at end of file
diff --git a/docs/reference/html2htpy.md b/docs/reference/html2htpy.md
new file mode 100644
index 0000000..0918912
--- /dev/null
+++ b/docs/reference/html2htpy.md
@@ -0,0 +1,107 @@
+
+# The html2htpy CLI tool
+
+The `html2htpy` command converts HTML code to htpy Python code.
+
+Looking to convert existing HTML? See the [Convert HTML to htpy guide](../how-to/convert-html.md).
+
+```
+usage: html2htpy [-h] [-f {auto,ruff,black,none}] [-i {yes,h,no}] [--no-shorthand] [input]
+
+positional arguments:
+ input Input HTML file, e.g. home.html. Optional. If not specified, html2htpy will read from stdin.
+
+options:
+ -h, --help show this help message and exit
+ -f, --format {auto,ruff,black,none}
+
+ Format the output code with a code formatter.
+
+ auto (default):
+ - If black is installed (exists on PATH), use `black` for formatting.
+ - If ruff is installed (exists on PATH): Use `ruff format` for formatting.
+ - If neither black or ruff is installed, do not perform any formatting.
+
+ black:
+ Use the black formatter (https://black.readthedocs.io/en/stable/).
+
+ ruff:
+ Use the ruff formatter (https://docs.astral.sh/ruff/formatter/).
+
+ none:
+ Do not format the output code at all.
+ -i, --imports {yes,h,no}
+
+ Specify formatting for imports.
+
+ yes (default):
+ Add `from htpy import div, span` for all found elements.
+ h:
+ Add a single `import htpy as h`.
+ Reference elements with `h.div`, `h.span`.
+ no:
+ Do not add imports.
+ --no-shorthand Use explicit `id` and `class_` kwargs instead of the shorthand #id.class syntax.
+```
+
+## Import Options
+
+You have a couple of options regarding imports with the `-i`/`--imports` flag.
+Options are `yes` (default), `h`, `no`.
+
+#### Module import of htpy: `--imports=h`
+
+This mode will use `import htpy as h` instead of importing individual elements from htpy.
+
+```py title="$ html2htpy --imports=h example.html"
+import htpy as h
+
+h.section("#main-section.hero.is-link")[
+ h.p(".subtitle.is-3.is-spaced")["Welcome"]
+]
+```
+
+## id/classes conversion
+
+html2htpy supports multiple modes to handle id/class conversions:
+
+```html title="example.html"
+
+```
+
+### Shorthand
+By default, id/classes will be converted to the shorthand notation:
+
+```py title="$ html2htpy example.html"
+from htpy import p, section
+
+section("#main-section.hero.is-link")[
+ p(".subtitle.is-3.is-spaced")["Welcome"]
+]
+```
+
+### Explicit id/class attributes
+
+Use the `--no-shorthand` flag to get explicit `id` and `class_` asttributes:
+
+```py title="$ html2htpy --no-shorthand example.html"
+from htpy import p, section
+
+section(id="main-section", class_="hero is-link")[
+ p(class_="subtitle is-3 is-spaced")["Welcome"]
+]
+```
+
+## Django/Jinja variable conversion
+
+`html2htpy` will convert Django/Jinja-style template variables to f-strings:
+
+```
+$ echo 'hi {{ name }}!
' | html2htpy
+
+from htpy import div
+
+div[f"hi { name }!"]
+```
diff --git a/mkdocs.yml b/mkdocs.yml
index ee0c708..40140b2 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -28,12 +28,15 @@ nav:
- how-to/django.md
- how-to/async.md
- how-to/starlette.md
+ - how-to/convert-html.md
- common-patterns.md
- static-typing.md
- streaming.md
- - html2htpy.md
- faq.md
- references.md
+ - Reference:
+ - reference/html2htpy.md
+
markdown_extensions:
- admonition
- pymdownx.highlight:
@@ -59,3 +62,4 @@ plugins:
async.md: how-to/async.md
django.md: how-to/django.md
starlette.md: how-to/starlette.md
+ html2htpy.md: reference/html2htpy.md
diff --git a/src/htpy/html2htpy.py b/src/htpy/html2htpy.py
index d2cd5c6..fb28746 100644
--- a/src/htpy/html2htpy.py
+++ b/src/htpy/html2htpy.py
@@ -6,6 +6,7 @@
import shutil
import subprocess
import sys
+import textwrap
import typing as t
from abc import ABC, abstractmethod
from html.parser import HTMLParser
@@ -432,25 +433,56 @@ def _is_command_available(command: str) -> bool:
def main() -> None:
- parser = argparse.ArgumentParser(prog="html2htpy")
+ parser = argparse.ArgumentParser(
+ prog="html2htpy",
+ formatter_class=argparse.RawTextHelpFormatter,
+ )
parser.add_argument(
"-f",
"--format",
choices=["auto", "ruff", "black", "none"],
default="auto",
- help="Select one of the following formatting options: auto, ruff, black or none",
+ help=textwrap.dedent(
+ """
+ Format the output code with a code formatter.
+
+ auto (default):
+ - If black is installed (exists on PATH), use `black` for formatting.
+ - If ruff is installed (exists on PATH): Use `ruff format` for formatting.
+ - If neither black or ruff is installed, do not perform any formatting.
+
+ black:
+ Use the black formatter (https://black.readthedocs.io/en/stable/).
+
+ ruff:
+ Use the ruff formatter (https://docs.astral.sh/ruff/formatter/).
+
+ none:
+ Do not format the output code at all.
+ """,
+ ),
)
parser.add_argument(
"-i",
"--imports",
choices=["yes", "h", "no"],
- help="Output mode for imports of found htpy elements",
+ help=textwrap.dedent("""
+ Specify formatting for imports.
+
+ yes (default):
+ Add `from htpy import div, span` for all found elements.
+ h:
+ Add a single `import htpy as h`.
+ Reference elements with `h.div`, `h.span`.
+ no:
+ Do not add imports.
+ """),
default="yes",
)
parser.add_argument(
"--no-shorthand",
- help="Use explicit `id` and `class_` kwargs instead of the shorthand #id.class syntax",
+ help="Use explicit `id` and `class_` kwargs instead of the shorthand #id.class syntax.",
action="store_true",
)
parser.add_argument(
@@ -458,7 +490,10 @@ def main() -> None:
type=argparse.FileType("r"),
nargs="?",
default=sys.stdin,
- help="input HTML from file or stdin",
+ help=(
+ "Input HTML file, e.g. home.html. "
+ "Optional. If not specified, html2htpy will read from stdin."
+ ),
)
args = parser.parse_args()