Make component with only innerHTML
I'd like to make a SolidJS component with only innerHTML.
This is what I have currently, but I'd love to get rid of the <div>
The reason is that I'm getting "tokens" from my Markdown processor, which is like a h1, h2, etc. level splitting of the document.
I'm displaying those tokens in a For component in Solid.
The above, div based component works, but breaks CSS, so I cannot write sibling selectors, everything is now wrapped in a dummy div.
Is there any possible way in Solid, which would allow me not to put those dummy divs?
Ideally I'd love to do something like this, similar to
<> and </>.
Is this possible to do something like this in Solid?
The reason I'm using a for loop over a Markdown token list is fine-grained reactivity, I only want to update the last part of the document, as the streaming Markdown comes in.18 Replies
I think the only way for this is to append the content to a root container the good old vanilla style e.g.
https://playground.solidjs.com/anonymous/9a86b9fd-7504-479e-b334-854487a245f8
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
But this way I loose fine-grained-reactivity, don't I? This way it's basically not Solid anymore, just a direct DOM manipulation.
it will also cause the whole markdown elements to be recreated with each change
you could try to render html to individual divs like before
but then take its children and append them to md root instead
Little correction:
moved the Root “md” atop the for loop and doesn’t wrap it anymore:
https://playground.solidjs.com/anonymous/c7baa8a6-cac6-4218-a7e3-3f3205d1f471
I don’t see elements to be recreated if elements are appended to content. Haven’t tested with inserting elements in the middle.
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
But does it handle the last HTML string changing over time?
So a streaming markdown document comes in, it'll look something like this:
->
->
->
->
The current solution takes care of it with <For> and reconcile, only modifying the actually changed part.
If I manually append then I think it'll be duplicated.
👆true
It would probably make sense to use something like
markdown-it to convert the markdown to structured data and then render the elements with Dynamic.I'm using marked to conver the markdown to HTML, splitting it into "tokens". What would markdown-it offer which would help me?
How can I use Dynamic for this?
instead of transforming md to html
transform it to ast (structured data)
which can be rendered with solid like any other data
Diffing it with Index instead of For probably
also fwiw I’ve make a library specifically for rendering streamed markdown:
https://github.com/thetarnav/streaming-markdown
GitHub
GitHub - thetarnav/streaming-markdown: 🔴Ⓜ️⬇️ Streaming m...
🔴Ⓜ️⬇️ Streaming markdown à la ChatGPT (WIP). Contribute to thetarnav/streaming-markdown development by creating an account on GitHub.
Nice one, what's the chance!
Also the demo is really nice on the homepage. But once you have the AST, how do you render it in Solid? At one point you have the same problem as I, when you need to make something like innerHTML on a root level of a component.
I think my problem could be solved by getting one level deeper and calling DOM Expressions directly, but I never used it.
no you just readers ast like any other data
without using innerHtml
md “ast” should give you a tree of tokens with their type and additional attributes
which should be easily renderable with some recursive component
You mean the whole tree gets in one component, without using <For>, right?
But then you have to reimplement the For's built-in diffing.
But I have a feeling DOM Expressions is made for exactly this, I just don't know how do use it 🙂
You’d pass the tree into the For/Index and then render each element (recursively) until you hit the "innerText".
I think I need to look into how does For work internally, and maybe I can modify it such that it doesn't need to return a wrapper.
No he means:
1. Turn markdown into ast representing the html
2. Walk down that ast in a recursive component
2. Would be something like
I don't yet see how would it do the diffing. There is no "key" on the AST I could use.
The good thing on a 1-level deep array of HTML strings is that reconcile does a perfect work of diffing, so For can just render it.
But maybe I could use Dynamic for this.
Because in your usecase there is only new content concatenated at the end you don't have to diff at all: simply use
<Index/> to iterate over the children
The key then would be the child's indexOK, that's true. And it should handle changes in the last child I believe.