How to render a web page from Craft docs
Hello, I'm Eunjae. Today let me talk a little bit about rendering pages from Craft docs.
Craft lets you share docs via a secret link. If you open the link on the browser and inspect the network tab, you will see the page calls two APIs and render them on the frontend.
- page API
- comments API
I'm not interested in the comments API at the moment. The page API gives a response of a big JSON data. I had to read the JSON and understand how to render them.
Text decoration
How would you implement a component rendering this? I did an implementation that I'm satisfied with but I'm curious to hear what others think. pic.twitter.com/XO01OQYNBQ
— Eunjae Lee (@eunjae_lee) February 19, 2021
It was quite challenging. I re-did it a couple of times. The final implementation is to split the text into chunks. For example, to summarize the text from the image above, it's
"def" → bold
"cdefgh" → italic
"bcdef" → link
and we can re-write it as the following:
[
{
content: "a",
},
{
content: "b",
linkURL: "https://...",
},
{
content: "c",
isItalic: true,
linkURL: "https://...",
},
{
content: "def",
isBold: true,
isItalic: true,
linkURL: "https://...",
},
{
content: "gh",
isItalic: true,
},
{
content: "ijkl",
}
]
Actually, writing a code to split a string into pieces like that was complicated enough. Once it's done, then rendering it is easy. By the way, I've recently discovered an issue with this approach. It will have
...
<a href="...">b</a>
<a href="...">c</a>
<a href="...">def</a>
...
They all have the same URL but are fragmented. It means applying hover style will look weird. So it's again back in my TODO to fix this issue, but not urgent, I think.
List
Let's say there's a JSON like the following:
[
{
content: "item1",
indentLevel: 0,
},
{
content: "item2",
indentLevel: 0,
},
{
content: "item2-1",
indentLevel: 1,
},
{
content: "item2-2",
indentLevel: 1,
},
{
content: "item3",
indentLevel: 0,
},
]
It should be rendered like:
<ul>
<li>item1</li>
<li>
item2
<ul>
<li>item2-1</li>
<li>item2-2</li>
</ul>
</li>
<li>item3</li>
</ul>
It's obvious. But if you implement it, it's more complicated than it looks. The types of lists can be mixed, and the indentation can be inconsistent:
* abc
* def
* ghi
* jkl
1. hello
2. world
* nested
* suddenly too much nested
Actually, the Craft team has rendered it without ul
, li
, ... tags. They're all rendered as div
with a left margin according to the indentation level.
I could just do it, but Quill is a website generator. I think it should do more than that and render HTML as semantically as possible.
So I talked about rendering the web pages. Let me know if you enjoyed this newsletter or if you want to hear about other topics. Now that the rendering part is a little stable, I'm going to work on the authentication + user space + ... The foundation may take a while, but once it's done, I'm sure I can go fast.
Thanks for reading, and feel free to reply to me!