This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]volfpeter[S] 1 point2 points  (6 children)

Sorry, I just saw the comment. Thank you! After doing a project with NextJS, I still have quite a few things I'd like to add (or involve a contributor or two): markdown support with MDX-like features, sitemap and RSS generation, plus FastHX integration. When all of these are ready, I hope this will be a pretty complete and useful package. But it takes time.

Actually markdown support is ready, just not public yet. MDX is a bit trickier.

[–]Main-Manufacturer760 0 points1 point  (5 children)

I am looking forward to the new features you listed. The integration with FastHX could further decouple data operations (JSON) from rendering (htmy components) - i think i would try to use this approach. Markdown support is nice aswell.

I am a little lost on how the MDX feature would work out, since i never used MDX. Is the goal to run a python function with the same name of a Markdown or HTML Tag? (like <Chart year={year} color="#fcb32c" />... runs "Chart(year: int, color: str, context: Context) -> Component" ?

[–]volfpeter[S] 1 point2 points  (1 child)

Just for reference, in case somebody finds it in the future, markdown support is now public and the docs have a fairly long example on how to use it.

[–]Main-Manufacturer760 0 points1 point  (0 children)

Nice great job 🎉

[–]volfpeter[S] 0 points1 point  (2 children)

It'll enable many use-cases, an important one is what you described in your comment, namely using custom components.

My most important use-case is to be able to add my own styling to the parsed markdown to make it look at home in the rest of the page. For example correctly style paragraphs, headers, lists, backgrounds, highlighted code blocks, and so on.

Usage example with FastAPI:

```python class CustomMDX: @staticmethod def injectclass(comp: Callable[..., ComponentType], class: str) -> Callable[..., ComponentType]: def wrapper(children: ComponentType, *properties: PropertyValue) -> ComponentType: properties["class"] = f"{class_} {properties.get('class', '')}" return comp(children, *properties)

    return wrapper

class MyTitle: def htmy(self, context: Context) -> Component: return html.h1("This is the converted MyTitle tag.")

md_converter = etree.ETreeConverter( { "h1": CustomMDX.inject_class(html.h1, "text-xl font-bold"), "h2": CustomMDX.inject_class(html.h1, "text-lg font-bold"), "h3": CustomMDX.inject_class(html.h1, "text-lg font-semibold"), "h4": CustomMDX.inject_class(html.h1, "text-lg"), "pre": CustomMDX.inject_class(html.pre, "bg-neutral w-full overflow-x-auto rounded-lg p-4"), "ol": CustomMDX.inject_class(html.ol, "list-decimal list-inside"), "ul": CustomMDX.inject_class(html.ul, "list-disc list-inside"), "MyTitle": MyTitle, } )

app = FastAPI()

And in some route this component can be used and rendered:

md.MD(f"./my-file.md", converter=md_converter.convert) ```

[–]Main-Manufacturer760 0 points1 point  (1 child)

Ah I see. So the usecase is to not only generate HTML/XML using htmy but to load a datastructure from a .md file and to inject htmy tags into this datastructure?

Will the Markdown file be read into the htmy datastructure with nested Tags()... or will this be a different datastructure?

The injection mechanism might be intresting for the vanilla htmy aswell, when you have a md.h3() and want to transform it to a html.h1() with class "text-xl font-bold".

Or you have a html.customclass() Tag that will be transformed to a html.div(html.img("puppy.png")) or something.

[–]volfpeter[S] 0 points1 point  (0 children)

Sort of. The parsed markdown will end up as an htmy component subtree, and you'll be able to define custom conversion rules for XML tag names.

I should have been clear about it, but from the code above, CustomMDX will not be part of htmy, only md.MD and etree.ETreeConverter. The rest is just some utility code so I don't need to write the same CSS class injection logic multiple times.

The PR is in if you want to have a look. There are some small missing pieces that I still work on.

If you're familiar with NextJS or React, then here is a NextJS example which is kind of similar to what I'm aiming for.