spotifyovercastrssapple-podcasts

elm-markdown

We discuss the elm-markdown's approach to extensiblility, the markdown specification, and some advanced uses.
October 11, 2021
#41

dillonkearns/elm-markdown's Core Tools for Extensibility

Transcript

[00:00:00]
Hello, Jeroen.
[00:00:01]
Hello, Dillon.
[00:00:02]
Well, it's been a while since this library was initially released, but I think this is
[00:00:09]
a pretty good time to finally talk about LMarkdown, my Markdown parsing package, Dillon Kern's
[00:00:15]
LMarkdown.
[00:00:17]
We just had a big milestone with Google Summer of Code and completed a lot of the core parsing
[00:00:23]
features.
[00:00:24]
So I think this is a good time to discuss it.
[00:00:26]
Very cool.
[00:00:27]
All right.
[00:00:28]
And maybe for the sake of people who don't know what Markdown is, can you explain what
[00:00:32]
Markdown is?
[00:00:34]
Yes.
[00:00:35]
So I think of Markdown as you're trying not to write low level HTML directly.
[00:00:43]
You're trying to write something that's a little bit more high level.
[00:00:45]
So instead of writing H1s and H2s, you just put a hash space heading name, and then you
[00:00:55]
write text and it becomes part of a paragraph.
[00:00:57]
You put something between stars and it becomes italic.
[00:01:02]
You put something between double stars and it becomes bold.
[00:01:05]
And a lot of developers will be familiar with this from working in readmes in GitHub or
[00:01:11]
documentation for Elm package documentation.
[00:01:14]
Sometimes writing in certain chat applications will support that.
[00:01:19]
So it's basically like a higher level way to write things.
[00:01:22]
And it turns out to be very handy for documentation tasks like that.
[00:01:28]
If it's a very technical team, you might use it for marketing type things.
[00:01:33]
If it's less technical, you might have a rich text editor that under the hood is actually
[00:01:38]
creating strings of Markdown text.
[00:01:41]
Or sometimes people use different rich text formats.
[00:01:44]
A lot of these CMS content management systems are using their own sort of custom formats
[00:01:51]
that are actually just JSON data structures under the hood rather than Markdown.
[00:01:56]
But Markdown is very common these days.
[00:01:59]
Yeah, I kind of view it like Microsoft Word or Google Docs, but way easier to write.
[00:02:08]
You don't need any special application.
[00:02:11]
It's just a text file and then it renders quite nicely.
[00:02:15]
Exactly.
[00:02:16]
And it's designed somewhat to look like it renders to a certain extent.
[00:02:21]
So it brings attention to, you know, if you have two hashes, two number signs, and that's
[00:02:28]
an H2 level two heading, then it sort of stands out like a level two heading.
[00:02:35]
And if you have, you know, lists with dash list item dash list item two dash list item
[00:02:42]
three, then it looks like a list and then it's going to render as bullet points and
[00:02:47]
you can do a numbered list and you can write one for each item in the numbered list, but
[00:02:52]
it's going to turn it into a numbered list rather than those explicit numbers.
[00:02:56]
So it's a more high level way to express things that sort of looks like the markup that you're
[00:03:01]
describing and you can sort of read it as raw text or you can render it to something
[00:03:07]
and display it, and it's also designed to be very lenient about how it parses things
[00:03:14]
to behave like humans think.
[00:03:16]
So like, well, for example, if you don't properly close a tag, then it's just going to render
[00:03:22]
that as raw text.
[00:03:24]
It's not going to give a parsing error.
[00:03:26]
And so there are some very complicated rules to the markdown parser.
[00:03:30]
Actually it might seem simple because as a human you write it and it's simple, but there
[00:03:34]
are some strange cases where, you know, like if you write a paragraph and it has a number
[00:03:42]
in the middle of the text and you start the next line with, you know, two period for some
[00:03:49]
reason.
[00:03:50]
I can't remember, there's like an example that they show in the markdown spec.
[00:03:53]
The markdown spec is gigantic, but the point is things that might be clear to a human with
[00:03:59]
context are not necessarily clear to a parser.
[00:04:03]
And markdown is designed to be friendly to humans more so than friendly to parsers.
[00:04:09]
It's not like a form.
[00:04:10]
And you know, so it feels very lightweight when you're writing it as a human and it feels
[00:04:14]
like it sort of understands what you mean because there are all these rules and there
[00:04:19]
are actually some ambiguities in the spec.
[00:04:22]
There's like a tool called Babelmark that you can input markdown and it spits out all
[00:04:28]
these different render outputs from different parsing libraries because there are actually
[00:04:33]
some places in the markdown spec where it is not explicitly defined.
[00:04:37]
I know where there's wiggle room, which is which is strange.
[00:04:40]
In fact, the a little little bit of history about the markdown spec originally John Gruber,
[00:04:47]
who's sort of a blogger who writes a lot about Apple products, created this not specification,
[00:04:54]
but this concept of markdown and used it for his own blog, daring fireball.
[00:05:00]
I'm guessing because it was lazy.
[00:05:02]
Yeah, and he wanted a nice way to produce content for his blog in a lightweight way.
[00:05:09]
And you know, he's sort of like a tech technical person and wanted to be able to just pull
[00:05:14]
up an editor and write some posts.
[00:05:16]
And then people started adopting adopting it.
[00:05:20]
But then there were all these different interpretations of it.
[00:05:22]
And he didn't want there to be a single specification.
[00:05:26]
So some like Jeff Atwood and some other folks were sort of pushing for creating a specification
[00:05:32]
for it.
[00:05:33]
And John Gruber actually did not want to make a specification.
[00:05:37]
He was opposed to it.
[00:05:39]
And in fact, that's why there's now a spec called common mark because it's not called
[00:05:44]
the markdown spec, because John Gruber created markdown.
[00:05:48]
He didn't want there to be a specification for markdown.
[00:05:50]
He wanted it to be sort of something that you can interpret how you want to and there's
[00:05:56]
not a single way to interpret it, which is not how we tend to think of it today, because
[00:06:01]
common mark sort of took over in people's minds the concept of markdown.
[00:06:05]
But it's called common mark because John Gruber said, hey, if you're going to create a specification,
[00:06:11]
give it a different name.
[00:06:12]
Yeah, I'm guessing it's because he wanted everyone to be able to write markdown the
[00:06:17]
one the way they wanted to, and then render it the way they wanted to.
[00:06:22]
Yes.
[00:06:23]
But then the thing is, a lot of people adopted it, and then tooling needed to be created
[00:06:28]
for it, and they needed to do it in a way that is common.
[00:06:33]
Exactly.
[00:06:34]
Exactly.
[00:06:35]
And that's actually a very good segue to Dillon Kern's LMarkdown, because that sort of was
[00:06:43]
the goal of that library was to solve some of those problems, but not by creating a new
[00:06:51]
specification or by not having a specification, but rather by providing some ways to extend,
[00:06:59]
to render in a custom way, to extend the types of things that you can render through this
[00:07:04]
formal markdown specification.
[00:07:06]
So that was really the motivation for creating Dillon Kern's LMarkdown.
[00:07:12]
So as you say, you have different tooling, you have syntax highlighting in VS code, in
[00:07:20]
GitHub editors, you have different contexts that are rendering markdown in their own way.
[00:07:26]
So having some sort of standardization is really nice.
[00:07:29]
Typically these days we think of markdown as GitHub flavored markdown, which is an add
[00:07:34]
on to CommonMark.
[00:07:35]
It's like a superset of the CommonMark specification.
[00:07:40]
Just to be clear, GitHub flavored markdown is the name of the thing.
[00:07:44]
Yes.
[00:07:45]
Exactly.
[00:07:46]
So there is a specification document, it's very long, called GitHub flavored markdown,
[00:07:50]
and the first 90, 95% of the document is just the CommonMark specification document.
[00:07:57]
And then the remaining 5 to 10% of the document is a couple of additions for the GitHub specification.
[00:08:03]
For example, auto links, to do items, a few small things like that.
[00:08:11]
To do items?
[00:08:12]
Yeah.
[00:08:13]
Checkboxes.
[00:08:14]
Checkboxes.
[00:08:15]
Yeah, sure.
[00:08:16]
Which I make use of quite a bit.
[00:08:17]
I really like that feature.
[00:08:19]
So that's not part of CommonMark, that's part of GitHub flavored markdown.
[00:08:23]
So yeah, it's quite nice to be able to edit something in GitHub, see the syntax highlighting
[00:08:30]
there, edit it in VS code, edit it in Ulysses or different markdown editing tools.
[00:08:35]
I use a macOS tool called BareNotes, which displays your raw markdown, but visually it
[00:08:47]
will make headings look bigger and bold look bold, but you see the star characters and
[00:08:53]
the hash characters in line.
[00:08:55]
So it's just a really nice way to edit text and display text, and it's portable, you can
[00:09:00]
copy it and paste it into different places.
[00:09:03]
So to me, as you say, having that universal specification is really nice.
[00:09:09]
But then that leaves you with the problem of, well, what if you want to go beyond what
[00:09:14]
the specification was designed for and extend it?
[00:09:18]
So that was the problem that I was trying to tackle with Dillon Kern's Elm Markdown.
[00:09:25]
So the core tools that help with that problem are, number one, the custom renderers allow
[00:09:33]
you to render to any output format.
[00:09:36]
You can render to Elm UI, you can render to HTML, you can render to Elm CSS, you can render
[00:09:40]
to a string with like ANSI terminal coloring.
[00:09:45]
You can even get more nuance than that, which we can get into.
[00:09:49]
The second thing is you have HTML handlers.
[00:09:54]
So this is really key.
[00:09:55]
So the Markdown specification...
[00:09:59]
Which one?
[00:10:00]
Well, CommonMark and GitHub flavored Markdown allow for HTML to be included in the Markdown.
[00:10:09]
So sometimes you'll see this where people will insert an image tag into a review or
[00:10:15]
things like that, right?
[00:10:17]
Or comments.
[00:10:19]
That's right.
[00:10:20]
So comments, which usually will just be rendered directly as comments into the rendered HTML.
[00:10:28]
And so my vision for Elm Markdown was that I don't believe that it's a great idea in
[00:10:38]
general to put low level HTML into your Markdown.
[00:10:44]
Because imagine that you have like a marketing person is editing some content for a post
[00:10:51]
or a landing page.
[00:10:54]
They're probably doing it with like a rich text editor function, but maybe it's outputting
[00:10:59]
it into Markdown.
[00:11:00]
You really shouldn't be putting low level HTML.
[00:11:03]
And if you do, it should be abstracted somehow, right?
[00:11:06]
So that's just too low level.
[00:11:08]
You shouldn't directly put the HTML.
[00:11:10]
What do you mean with low level HTML?
[00:11:12]
Do you mean like images?
[00:11:13]
Do you mean like paragraphs?
[00:11:15]
Right.
[00:11:16]
Yeah.
[00:11:17]
So let's say you're putting a button in there and the button has some styling, right?
[00:11:22]
So if you put like, where should that live?
[00:11:25]
Well, if you put a button that says like, click now to sign up for this workshop, you
[00:11:30]
know, and you put in some styling, you put in some classes or some inline styles or whatever.
[00:11:39]
Well, then when you want to do another button, are you copy pasting that somewhere else?
[00:11:43]
It just, it seems like the wrong level of abstraction for Markdown because Markdown
[00:11:47]
is intended to be a high level abstraction.
[00:11:49]
You don't put H1s and put classes in your H1s.
[00:11:53]
And that's sort of the point.
[00:11:55]
The point is you just say this is a level one heading, this is a level two heading.
[00:12:00]
It's more, it's more markup than styling, right?
[00:12:05]
And it's designed for that separation and to be high level.
[00:12:08]
In my view, at least that's the vision of Dillon Kern's LMarkdown, right?
[00:12:11]
And so what should you do instead?
[00:12:14]
Well, to me it should be sort of like just in a high level way using HTML, almost like
[00:12:20]
you would with like a web component or something to encapsulate this as a button and not represent
[00:12:26]
the low level details of how to do that, but say what it is.
[00:12:30]
It is a button and then leave it to the renderer to do that.
[00:12:33]
It could be a web component.
[00:12:34]
In the case of Dillon Kern's LMarkdown, it's custom HTML handlers.
[00:12:39]
Yeah.
[00:12:40]
So you kind of want to separate the contents of the Markdown from the display of it, which
[00:12:47]
is going to be the website's job.
[00:12:49]
Exactly.
[00:12:50]
Because you don't have like functions to extract these abstractions in Markdown.
[00:12:57]
It's just markup.
[00:12:58]
So you should be as declarative and terse as possible to just say, this is a button
[00:13:03]
and be as minimal in describing it as possible and leave the details of how to present that
[00:13:10]
elsewhere so that you can properly abstract it.
[00:13:13]
So that's sort of what HTML handlers are for.
[00:13:15]
So for that example, if you wanted to render a button, in your Dillon Kern's LMarkdown renderer,
[00:13:22]
you would say, when I see an HTML tag called signup button, I want these attributes.
[00:13:30]
So you can say, I need a message attribute or whatever information you want to pass along.
[00:13:38]
And then you define something that renders to your view type given that input data of
[00:13:43]
the message.
[00:13:45]
And it gives you the parsed children.
[00:13:47]
So if you have Markdown within that HTML button, you could have like a list.
[00:13:52]
Well, you probably wouldn't have a list of things, but you could have something in bold
[00:13:56]
inside of the button.
[00:13:57]
You get that in your renderer and you can just pass that through and display that.
[00:14:01]
So that's sort of like the philosophy of how Dillon Kern's LMarkdown tries to be extensible,
[00:14:07]
just like John Gruber was trying to solve that problem by saying, hey, implement the
[00:14:11]
spec however you want to.
[00:14:14]
Dillon Kern's LMarkdown says, no, like write high level HTML tags.
[00:14:19]
And then in your specific implementation, you decide what to do with those HTML tags.
[00:14:26]
If you're displaying it in something else, you could use a web component to display it.
[00:14:30]
You could use a React library to display it.
[00:14:32]
It doesn't matter, but just give me the high level information and let the implementation
[00:14:37]
decide how to present that.
[00:14:39]
Yeah.
[00:14:40]
So you follow the GitHub flavored Markdown specification.
[00:14:43]
And then for anything else that you want to be custom or if you want to add some sort
[00:14:50]
of extensibility to the document, then you do it through HTML tags, matchers and renders.
[00:14:58]
Exactly.
[00:14:59]
Is that right?
[00:15:00]
Exactly right.
[00:15:01]
Yeah.
[00:15:02]
So I said there were three key pieces of providing extensibility.
[00:15:06]
The first one I mentioned was being able to customize what you render to.
[00:15:10]
If you want to render to Elm UI or Elm CSS or Elm HTML or a string, you can do all of
[00:15:17]
those things.
[00:15:18]
The second one being the HTML handlers we just talked about.
[00:15:21]
And the third one is, well, Elm is very nice, I think, for working with data.
[00:15:29]
That's one of the places where Elm really shines is transforming data, working with
[00:15:33]
nicely typed data.
[00:15:35]
And well, you parse Markdown and what do you get?
[00:15:38]
You get data.
[00:15:39]
It's the Markdown blocks, the abstract syntax tree.
[00:15:43]
I feel like we need to step back a tiny bit because you talk about parsing and rendering.
[00:15:51]
So what is this library?
[00:15:53]
Is it a parser?
[00:15:54]
Is it a renderer?
[00:15:57]
Is it something else?
[00:15:58]
Good question.
[00:15:59]
Because you have a lot of parts to this library.
[00:16:04]
I think it's nice to explain how it's split up.
[00:16:07]
That's a great, great idea.
[00:16:08]
So is it a parser?
[00:16:10]
Absolutely.
[00:16:11]
Is it a renderer?
[00:16:12]
Those are...
[00:16:14]
Can you use them separately also?
[00:16:16]
You can.
[00:16:17]
You can just run a parser if that's all you want for whatever reason.
[00:16:22]
If you don't want to use the renderer, then you can just...
[00:16:27]
In fact, I'll give a concrete example of that.
[00:16:30]
So on my incremental Elm.com site, I use the Markdown parser, Dillon Kern's Elm Markdown,
[00:16:38]
to parse all of my notes and get back references.
[00:16:43]
We've discussed this before.
[00:16:44]
So any notes that link to each other...
[00:16:47]
So if you're on a given note page, if you're on the page, Jeroen's Hierarchy of Constraints,
[00:16:53]
for example, the most famous note, then you can see other notes that link back to that
[00:17:00]
note.
[00:17:02]
And how does it do that?
[00:17:03]
Well, it parses the Markdown and it has nothing to do with rendering.
[00:17:06]
I'm just extracting data.
[00:17:07]
So I can run the Markdown parser and I can go look for anything that's a link in there.
[00:17:14]
Dillon Kern's Elm Markdown also provides an API for folding over Markdown blocks because
[00:17:22]
you can have nested Markdown blocks and nested Markdown inlines.
[00:17:26]
What do we use if folding?
[00:17:29]
Folding?
[00:17:30]
Well, so if you want to look for all links...
[00:17:34]
Okay, so it's to collect things, for instance?
[00:17:37]
Right.
[00:17:38]
So in this case, we're looking for all these links.
[00:17:41]
Well, you could have a paragraph, but you could also have...
[00:17:45]
There are these types of container blocks.
[00:17:48]
So you could have a list, which is a container block, and then you could have a nested list
[00:17:55]
within that list, which is another container block.
[00:17:57]
And then you could have a link within that nested list.
[00:18:02]
Well, you don't want to go through and manually traverse that.
[00:18:05]
You could, but it would be a lot of work.
[00:18:08]
So the library provides a few helpers to help you do that traversal so you don't have to
[00:18:14]
manually and just say, hey, just go through all of the Markdown blocks and pass them to
[00:18:21]
me and I want to fold it up into this result.
[00:18:24]
And so it provides that type of helper.
[00:18:29]
It's kind of like Elm Review.
[00:18:32]
You traverse through an AST, and while that is pretty simple in theory, there's a lot
[00:18:38]
of things you need to know.
[00:18:42]
What does this node contain?
[00:18:45]
What children should it allow to visit?
[00:18:48]
So it makes the visitor pretty complex.
[00:18:54]
So your fold function makes that easy.
[00:18:57]
It makes it easy.
[00:18:58]
It makes it so you're not going to make a mistake implementing that and you don't have
[00:19:02]
to worry about the little details.
[00:19:04]
So yeah, and Elm is great for traversing these data structures and transforming things and
[00:19:10]
extracting data.
[00:19:11]
It just really shines because the types are so explicit and it's so nice to map over and
[00:19:17]
transform things.
[00:19:19]
So I really enjoy using these helpers to parse the AST and then extract information from
[00:19:27]
it.
[00:19:28]
So that's one use case that you can use it for.
[00:19:33]
Also you can transform the AST.
[00:19:38]
You can transform the blocks.
[00:19:44]
As I was saying before, the three different areas that Dillonkern's Elm Markdown provides
[00:19:49]
you with ways to sort of extend the way you're presenting things.
[00:19:54]
This is the third way, is sort of transforming the Markdown blocks as data.
[00:20:00]
Because you can, let's say you wanted to take any links that are HTTP and turn them into
[00:20:10]
HTTPS.
[00:20:11]
Or you could even validate it.
[00:20:14]
You could turn it into results and then if you're using Elm pages, you could use that
[00:20:19]
to give a build error because you can sort of take these data sources in Elm pages and
[00:20:26]
turn a result into something that's going to give you a build error.
[00:20:30]
You could also, I imagine, find script tags and remove them if you allowed parsing them
[00:20:36]
because I think you have an option for that.
[00:20:39]
Or you could, if you were really interested in my hierarchy of constraints article, you
[00:20:47]
could make that bold everywhere you see it.
[00:20:49]
That's right.
[00:20:50]
Exactly.
[00:20:51]
Exactly.
[00:20:52]
And you could, there are all sorts of things you could do.
[00:20:54]
You could take level two headings.
[00:20:57]
If something has multiple level one headings, which would be an accessibility problem, then
[00:21:03]
you could clean that up in a transformation step.
[00:21:06]
You could also add slugs to those.
[00:21:09]
You could, yeah, absolutely.
[00:21:10]
Or IDs, I guess.
[00:21:11]
Yep, exactly.
[00:21:12]
You can add slugs to headings.
[00:21:14]
You can extract a table of contents.
[00:21:19]
If you wanted to, you could add a transformation step that actually takes the AST, finds all
[00:21:25]
the headings, and actually inserts markdown blocks for presenting a table of contents.
[00:21:35]
But also, if you wanted to do it another way, which actually I tend to go this way, I would
[00:21:41]
just do a step to extract the headings from the markdown blocks, the parsed markdown blocks,
[00:21:48]
and then I would take that as a data structure and render that as its own thing, rather than
[00:21:55]
just prepending a table of contents markdown block structure at the front of the markdown
[00:22:02]
blocks.
[00:22:03]
I would just extract the table of contents data and then render it, pass that data to
[00:22:08]
some Elm code and render it.
[00:22:10]
But there are so many possibilities.
[00:22:13]
I just really think that Elm shines in this regard.
[00:22:17]
That's one of my favorite features of Dillon Kern's Elm Markdown.
[00:22:21]
There's one interesting thing you said quite a while ago.
[00:22:24]
You said that markdown is designed not to be able to have parsing errors.
[00:22:30]
Yes.
[00:22:31]
But that is not the case in Elm Markdown.
[00:22:33]
That's true.
[00:22:34]
That is actually a future goal.
[00:22:38]
One of the goals that I have is to clarify the HTML handling in a more formal specification.
[00:22:47]
So this is...
[00:22:48]
Oh no, you're going to make a new specification?
[00:22:51]
Well, so, okay.
[00:22:53]
Essentially the goal of Dillon Kern's Elm Markdown is to be a 100% compliant markdown parser,
[00:23:01]
GitHub flavored markdown parser, essentially, possibly with an option to toggle between
[00:23:07]
common mark versus GitHub flavored markdown.
[00:23:10]
I'm not sure yet, but 100% compliant with the specification except for HTML handling
[00:23:18]
because the HTML handling, it's intentionally deviating.
[00:23:22]
So HTML handling in raw markdown is actually very strange.
[00:23:31]
You can write an opening tag.
[00:23:34]
You could say opening tag div style equals color red.
[00:23:41]
And then on the next line, you could write some text.
[00:23:45]
This is with the color red.
[00:23:47]
And then never write a closing tag.
[00:23:50]
And it's just going to make that next line red.
[00:23:54]
And then lines after that will not be red.
[00:23:56]
Wait, only the next line?
[00:23:58]
It always throws me off.
[00:24:00]
I can link to an example that we can give in the notes and you'll see probably, I'll
[00:24:05]
link to a Babel mark example and you can see probably you'll have wide variation in how
[00:24:10]
this is actually handled.
[00:24:11]
But I think, yeah, it's essentially going to take the next line and it's going to say,
[00:24:17]
oh, I didn't find a closing HTML tag, so I'm just going to close it after the next line,
[00:24:23]
something like that.
[00:24:24]
But if there's a closing one, like 10 or a hundred lines later, then...
[00:24:29]
Actually it won't.
[00:24:31]
I don't think it does.
[00:24:33]
It will still only be the next line?
[00:24:35]
Yes.
[00:24:36]
And then I think it will consider that closing HTML tag to be a new opening HTML tag.
[00:24:42]
So you could even write like as an opening HTML tag.
[00:24:46]
Yeah, it's very strange.
[00:24:47]
I'll include some examples in the show notes.
[00:24:51]
So the new tag would be of type slash div or something?
[00:24:57]
I think it would turn it into an opening tag if there's no...
[00:25:00]
Yeah, but what would be the tag slash div or something?
[00:25:04]
It would be an opening div tag.
[00:25:07]
If you just write a closing div tag, I think it will treat it as an opening.
[00:25:12]
It's very strange.
[00:25:14]
It's nonsensical, really.
[00:25:17]
There's no way you will predict correctly what it's going to do.
[00:25:21]
And if you did, then you might want to get that checked out.
[00:25:27]
So yeah, it's very arbitrary.
[00:25:32]
I don't know.
[00:25:33]
I don't understand the default specification for HTML handling.
[00:25:37]
But so Dillon Kern's LMarkdown doesn't intend to just deal with HTML in the regular way
[00:25:45]
anyway.
[00:25:46]
So it uses HTML as a way of saying, hey, this is like HTML is valid markdown, but we're
[00:25:52]
going to treat HTML as a special thing that behaves more like you would expect, where
[00:25:56]
you have an opening tag, it's going to look until it finds a closing tag.
[00:26:01]
And then when you do that closing tag, everything between those two is part of that tag, as
[00:26:07]
you would expect.
[00:26:08]
That's like an intentional divergence in the specification for Dillon Kern's LMarkdown.
[00:26:14]
But the only place it intends to diverge is with regards to the HTML handling.
[00:26:19]
Okay.
[00:26:20]
So if it doesn't find the closing tag, then you got a parse failure, right?
[00:26:27]
So that's one thing I'm trying to decide on.
[00:26:31]
I think there are a few directions that could go.
[00:26:35]
But what I'm thinking about is you can handle it as a fallback.
[00:26:39]
So it just treats it as text, as if it was the opening div.
[00:26:44]
If it doesn't find a closing div, it just says, I'm just going to pretend I didn't see
[00:26:49]
that opening div.
[00:26:50]
I'm going to pretend it was just the raw letters, open, left bracket, div, close, and then everything
[00:26:59]
that came after it, I'll just render as I normally would if there was no opening div
[00:27:02]
there.
[00:27:03]
Which is usually the case with Markdown.
[00:27:05]
Like when it looks like something Markdownish, but isn't properly formatted, then it's just
[00:27:11]
plain text.
[00:27:12]
Exactly.
[00:27:13]
Which is nice because you might have some non validated user input that you need to
[00:27:17]
display somehow.
[00:27:20]
And if it looks a little broken, at least it displays something.
[00:27:24]
And you might also be like typing in your editor and seeing previews as you type and
[00:27:30]
you're not quite done.
[00:27:32]
And you don't want the whole page to just disappear.
[00:27:34]
You want to be able to see as you're typing so you can preview it.
[00:27:37]
So those are a couple of reasons that that can actually be like a nice design.
[00:27:42]
Now another possibility would be to have, I've been considering a possible design to
[00:27:48]
like catch errors like that and then give you the possibility to treat it like a fallback
[00:27:53]
or say, hey, take all these warnings and turn them into errors.
[00:27:58]
So you could either just say, I just want to display something, show me the fallbacks,
[00:28:03]
don't give me any errors and never parse with any errors.
[00:28:06]
It will never parse with errors.
[00:28:08]
Or just give me the errors and I want to deal with them.
[00:28:12]
When you do have a parsing error, do you still get whatever was parsed before somehow available?
[00:28:19]
Or do you just get an error saying, hey, I expected a closing HTML tag here?
[00:28:26]
I guess there are different ways you could deal with it.
[00:28:30]
You could potentially have like a special, when you parse your markdown blocks, you could
[00:28:35]
potentially parse it into something where you could treat each individual block where
[00:28:39]
a block could be an error.
[00:28:41]
It could be a block with an error and then the renderer could be given that information.
[00:28:47]
So you could render it with red around it and render it with the fallback or so.
[00:28:53]
These are some errors that I'm not a hundred percent clear on yet, but that is the goal
[00:28:58]
is to be, to at least have a way, whatever other decisions are made to be able to just
[00:29:05]
render something and know you're going to get something on the screen without errors
[00:29:09]
with fallbacks at least.
[00:29:11]
So right now it does give you an error if you have an unclosed HTML tag.
[00:29:17]
So you do need to deal with the error case when you parse it, you might have an error
[00:29:22]
in your result.
[00:29:23]
It kind of feels weird when you know that marketing can fail, but it makes a lot of
[00:29:30]
sense.
[00:29:31]
Yeah.
[00:29:32]
It's sort of in between these two worlds of like markdown can't fail.
[00:29:36]
Elm likes to be explicit and know about failures and deal with them.
[00:29:39]
You've handled everything.
[00:29:41]
So it's a tricky balance.
[00:29:43]
I mean, like do you even have like an option to say if a link isn't closed, fail?
[00:29:52]
Right now the way it deals with that is just with doing the default markdown behavior,
[00:30:00]
which is part of the specification.
[00:30:03]
So if you go through, like there are about 1400 tests in this test suite, which are all
[00:30:10]
of the examples from the common mark or GitHub flavored markdown specification documents.
[00:30:15]
It runs all of them and checks the output and there's a certain HTML output that's the
[00:30:22]
standard.
[00:30:23]
So the standard renderer, when it gives you the standard markdown output format, it checks
[00:30:28]
that against the entire set of all the examples from the specification and those corner cases
[00:30:34]
around unmatched inlines like emphasis and strong, the bold and italic and that sort
[00:30:41]
of thing, or unclosed links, they're all explicitly there in the test cases and it handles it
[00:30:47]
like standard markdown.
[00:30:48]
Now it could in the future be that it handles it that way, but it gives you the opportunity
[00:30:55]
to see where these things that probably are a mistake happened.
[00:31:00]
So you could deal with them or show a warning or present it with an error around it or something
[00:31:04]
like that.
[00:31:05]
That's a direction I'm considering, but for now it's just standard markdown parsing.
[00:31:09]
Yeah, makes sense.
[00:31:10]
But I do feel like I would never want to publish a blog post where something looks like a link,
[00:31:18]
but it isn't.
[00:31:19]
Yeah.
[00:31:20]
Unless I really want to show, hey, this is how you do a broken link or something.
[00:31:24]
Right.
[00:31:25]
Exactly.
[00:31:26]
Now that said, I'm sure there's a markdown linting tool that does that and it's not a
[00:31:33]
bad idea to just use those two.
[00:31:35]
So sometimes that can be a reasonable solution, but it is extremely powerful to be able to
[00:31:42]
do these types of validations in Elm, especially in tandem with Elm pages.
[00:31:48]
It can be really cool to have very highly customizable validations that you can turn
[00:31:53]
into build errors.
[00:31:55]
So we mentioned that we can extend markdown by use of HTML tags.
[00:32:01]
Do you have any plans of allowing additional parsing features like James Carlson's Elm
[00:32:09]
Markdown version parses something like math expressions?
[00:32:15]
Yeah, it parses math expressions and like a poetry syntax.
[00:32:22]
So I've thought about this idea of extensibility, like we discussed, is very much at the heart
[00:32:30]
of the Elm Markdown philosophy, Dillon Kern's Elm Markdown.
[00:32:33]
Now I think that having these HTML handlers is a pretty good tool for extending presentation.
[00:32:43]
You can do a lot with that.
[00:32:46]
And I do like, kind of like we talked about that John Gruber's vision of markdown was
[00:32:52]
sort of, hey, here's this convention I'm using, but I don't want to nail it down into a convention.
[00:32:59]
I want people to have the freedom to experiment and build their own things.
[00:33:04]
And then the common mark specification was sort of trying to say, well, let's standardize.
[00:33:10]
This is like something that a lot of people are using.
[00:33:12]
Then we can build tooling around it and use it in a sort of tooling agnostic way.
[00:33:19]
Well, you sort of start to lose that benefit if you start diverging from the specification.
[00:33:26]
If you start doing custom parsing, it kind of goes against those benefits.
[00:33:34]
So it's not obvious which direction would make sense in that regard.
[00:33:43]
That said, I do really like being able, like personally, I really like using Wiki links,
[00:33:49]
which is like this convention that people sometimes use where you put double square
[00:33:54]
brackets around something and it will, and then you type the name of a note and that
[00:34:01]
will link to a note, which is different than the standard markdown link syntax, which is
[00:34:07]
like the name is in square brackets and then the URL comes after that in parentheses.
[00:34:16]
So the Wiki link, it's used in a lot of sort of second brain, you know, Zettelkasten type
[00:34:24]
systems to sort of interconnect notes so they can refer to each other.
[00:34:28]
And I have like some tooling in VS code, like this foam research ecosystem.
[00:34:33]
It's a play on like Rome research, but it's trying to create a similar system in your
[00:34:38]
VS code using extensions.
[00:34:41]
And it leverages that syntax.
[00:34:43]
And I would love to be able to parse Wiki links.
[00:34:46]
So I've considered like maybe it would make sense to have some way of extending like inline
[00:34:51]
parsing, but I'm not really sure.
[00:34:56]
It also complexifies the AST a lot, right?
[00:34:59]
Yes.
[00:35:00]
In the parser.
[00:35:01]
Right.
[00:35:02]
In the parser.
[00:35:03]
If you need another inline block or you call it inlines, inline elements.
[00:35:08]
Yes.
[00:35:09]
But like, do you try the parser that you got as an argument at every place?
[00:35:17]
Right.
[00:35:18]
As a fallback, as a first item, it gets hard.
[00:35:22]
Exactly.
[00:35:23]
It's providing a very low level way to hook into the parser, which maybe you like break
[00:35:28]
something in an irreparable way and you know, Hey, whose fault is that?
[00:35:33]
Is that the user's fault or the library?
[00:35:35]
It's your fault at that point, right?
[00:35:37]
It's yours.
[00:35:38]
Right.
[00:35:39]
So you have to take responsibility for the user having a good experience, right?
[00:35:44]
And so where does that start and end?
[00:35:47]
And if you're providing foot guns or things that become foot guns, you have to really
[00:35:53]
think hard before you make that call.
[00:35:56]
So I think, yeah, I'm still on the fence about that.
[00:36:01]
Yeah.
[00:36:02]
I guess one thing you can do is try to make the code base really nice so that people can
[00:36:07]
copy paste your library and extend it.
[00:36:09]
Right.
[00:36:10]
I mean, why not?
[00:36:11]
Right.
[00:36:12]
Yeah, it's true.
[00:36:13]
It's true.
[00:36:14]
Yeah.
[00:36:15]
But it's a lot of work.
[00:36:16]
Yeah.
[00:36:17]
Well, I think the code base is, I mean, it's, I'm very proud of the test suite in particular,
[00:36:22]
the automation around that.
[00:36:23]
That was like probably the biggest, like one of the biggest investments I made was just
[00:36:28]
making a really solid test suite.
[00:36:30]
And that runs the entire end to end specification and a lot of, lot of additional tests.
[00:36:35]
Well, it was nice to have a specification in the first place, right?
[00:36:39]
Absolutely.
[00:36:40]
As a test suite.
[00:36:41]
That's right.
[00:36:42]
Yeah.
[00:36:43]
Exactly.
[00:36:44]
Yeah.
[00:36:45]
And yeah, and a lot of people have contributed.
[00:36:48]
So a big thanks to everybody who's contributed in Hacktoberfest and just in general, there've
[00:36:55]
been a lot of people really generously contributing some really cool features.
[00:37:00]
So I couldn't, this is very much a community project.
[00:37:03]
Like it's, you know, I, and I try to sort of make the technical foundations and automated,
[00:37:11]
you know, automations around testing and, and all that a solid.
[00:37:15]
And I try to create like a clear, solid vision.
[00:37:18]
And I think that's like, you know, something I'm really trying to give this project and,
[00:37:24]
but so many contributions have come from the community.
[00:37:26]
It's been really great.
[00:37:27]
Yeah.
[00:37:28]
So we had, I mentioned earlier, we had a Google Summer of Code.
[00:37:33]
We finished a lot of the the core parsing features.
[00:37:37]
So the really big headline was so Jin Yi who was working on this project for Google Summer
[00:37:43]
of Code this year did an amazing job pushing through the nested list parsing, which was
[00:37:48]
the really big item.
[00:37:49]
So that's, that's huge.
[00:37:51]
Yeah.
[00:37:52]
We've also got some, I'll link to some videos.
[00:37:55]
I've got some videos where I do some pairing with with some contributors to the project
[00:38:00]
too.
[00:38:01]
So lots of great community contributions.
[00:38:03]
So I think at this point, like the only, the only part of the parser that is not implemented
[00:38:11]
besides, you know, some minor edge cases and bugs, which, you know, it's, it's a giant
[00:38:16]
spec.
[00:38:17]
I'm sure, you know, it, it's probably never going to be a hundred percent compliant in
[00:38:22]
every way.
[00:38:23]
You go to like this Babelmark parser where you can see output from all these different
[00:38:27]
markdown parsers and there are always little places where things diverge.
[00:38:32]
But but the, the main thing that's not implemented at this point are auto links, which is like
[00:38:38]
a GitHub play with markdown feature that will take HTTPS colon slash slash google.com and
[00:38:45]
turn that into a link.
[00:38:46]
So that's sort of the last big remaining feature.
[00:38:51]
You mean, so you don't have to put in brackets at all?
[00:38:54]
Exactly.
[00:38:55]
Yeah.
[00:38:56]
Oh, yeah.
[00:38:57]
And Stephen Redikoff, I hope I'm pronouncing his name correctly, but he has a work in progress
[00:39:04]
pull request on that.
[00:39:05]
So hopefully we can get that in at some point, but yeah, otherwise it's, it's pretty compliant.
[00:39:12]
And then the last big piece is getting an explicit specification for the HTML handling.
[00:39:19]
But at this point it's, it's a mature markdown parser and those are sort of the big upcoming
[00:39:26]
changes.
[00:39:27]
Yeah.
[00:39:28]
So maybe let's talk about the alternatives that we have in the Elm community.
[00:39:33]
The main one that I think most people know is the Elm Explorations markdown package.
[00:39:39]
Yes.
[00:39:40]
Do you know what, do you want to explain what the differences are with your version?
[00:39:44]
Yeah.
[00:39:45]
So the obvious one is Dillon Kern's Elm markdown is pure Elm parser.
[00:39:51]
It's written entirely in with Elm parser library, actually except for the the inline parsing
[00:39:59]
like the links and italics and bold, because that is not a parser.
[00:40:05]
It is not a traditional parser that the Elm parser library is designed to work with because
[00:40:11]
it actually goes from the end of the inline text to the beginning of the inline text and
[00:40:18]
does a pass adding characters to these lists of delimit delimiters and handling fallbacks
[00:40:26]
if certain closing elements aren't found and there are very specific precedence rules and
[00:40:31]
is not a traditional parser.
[00:40:33]
It's very odd.
[00:40:36]
Seems complex.
[00:40:37]
It's very complex and it's just not what Elm parser is designed to do.
[00:40:41]
Elm parser is designed to just go through character by character, fail if something
[00:40:45]
is not as expected, which is not what markdown inlines do.
[00:40:49]
Yeah, but it is mostly because Markdown in a way has no spec in the sense that it can't
[00:40:57]
fail.
[00:40:58]
So you have to fall back to something.
[00:41:01]
Right.
[00:41:02]
Always.
[00:41:03]
Right.
[00:41:04]
Well, I would say it has a specification for exactly that for the way in which it does
[00:41:09]
not fail.
[00:41:12]
The specific ways in which it does not fail to parse.
[00:41:14]
So yeah, Elm parser is designed to find failures and say, hey, this isn't valid.
[00:41:20]
Now I mean, you know, Matt Griffith did some really cool work creating like fault tolerant
[00:41:25]
parsing for his markup library, Elm markup, which is like a custom syntax different than
[00:41:32]
markdown and designed to be extensible.
[00:41:36]
And he did some really cool work.
[00:41:39]
We can link to a talk he gave at Oslo Elm days.
[00:41:43]
So, you know, he was he was able to build a fault tolerant parser that's able to handle
[00:41:50]
failures gracefully.
[00:41:51]
So yeah, so Dillon Kern's Elm Markdown is written in all Elm, whereas Elm Explorations Markdown
[00:41:59]
is written.
[00:42:00]
It's literally just, you know, taking this marked.js library and it just like copied
[00:42:07]
it into some kernel code.
[00:42:09]
It was, I think, meant as a sort of temporary thing.
[00:42:12]
But yeah, that is what powers the Elm Package documentation website.
[00:42:19]
And it, you know, it does a good job.
[00:42:23]
It's fast.
[00:42:24]
It's faster than Dillon Kern's Elm Markdown.
[00:42:26]
Although actually Matt Griffith has been, you know, he's got this great Elm Optimize
[00:42:32]
Level 2 package that we've talked about, this NPM tool.
[00:42:36]
And he uses Dillon Kern's Elm Markdown as one of the benchmarks.
[00:42:40]
And he's optimized it a lot, which is pretty cool.
[00:42:42]
Do you know if it's faster than the JavaScript version with those optimizations?
[00:42:48]
I don't think so.
[00:42:50]
But I'm not sure.
[00:42:51]
But I mean, honestly, it's not really something you're going to notice.
[00:42:56]
I mean, it's like you, you know, you'll blink your eye in more time than you'll parse something.
[00:43:02]
So like, unless you're parsing like a Markdown version of War and Peace, like it's probably
[00:43:09]
not going to be a problem for you.
[00:43:11]
Yeah.
[00:43:12]
Although that you bring this argument like that, it surprises me as since you're the
[00:43:18]
author of Elm Pages and you care about performance.
[00:43:21]
I, well, okay.
[00:43:22]
So it's a very good point, but I care about performance a lot.
[00:43:26]
But this is a rabbit hole that we should try not to go too far down.
[00:43:32]
But I think that the proper way to do it, which actually we talked about in our Elm
[00:43:36]
Pages 2.0 episode, I run the Markdown parser and serialize the AST using the data source
[00:43:44]
dot distill functionality in Elm Pages, which means you actually don't run Elm Markdown
[00:43:49]
at all in the client.
[00:43:51]
It's already parsed.
[00:43:53]
So that helps sort of bypass that problem.
[00:43:55]
So I think that's now longer term, I think it would be really interesting to be able
[00:44:00]
to just output static Markdown parts of the page in a way that doesn't require JavaScript.
[00:44:08]
It just is there as HTML and the Elm virtual DOM is able to adopt it.
[00:44:13]
That's something I'm exploring, but the broader point being those are the ways that I see
[00:44:19]
optimizing performance of these things.
[00:44:22]
Yeah.
[00:44:23]
Yeah.
[00:44:24]
This sounds like a rabbit hole.
[00:44:25]
So let's get away from it.
[00:44:27]
Most definitely a rabbit hole.
[00:44:29]
Yes.
[00:44:30]
But yeah, so Elm Explorations Markdown does not parse into an intermediary AST, which
[00:44:38]
to me is like one of my favorite features of being able to use a Markdown parser in
[00:44:43]
Elm.
[00:44:44]
So that's one difference.
[00:44:45]
Another difference is Elm Explorations Markdown.
[00:44:48]
Now it's very convenient and inconvenient at the same time.
[00:44:53]
If you want to include syntax highlighting, you can include Highlight.js, HL.js in the
[00:45:00]
global scope of the page, and it will pick that up and use that to syntax highlight code
[00:45:06]
snippets in your Markdown.
[00:45:09]
But if you don't want to use Highlight.js, if you want to use something else, you can't.
[00:45:16]
If you want to have more control over it, or like in the case of what I do with Elm
[00:45:25]
pages, I use a data source to use a tool called Shiki to use full VS code grammars to get
[00:45:34]
syntax highlighting and put that onto the page.
[00:45:38]
It's limiting.
[00:45:39]
So it's really a hack, the pulling in the globally scoped Highlight.js and requiring
[00:45:45]
that to be on the page.
[00:45:47]
It's sort of a hack.
[00:45:48]
I think it was intended as a short term solution.
[00:45:52]
I think Dillon Kern's Elm Markdown provides a more flexible option there.
[00:45:58]
But if you just need something that you don't really need much customization on, you don't
[00:46:02]
want to think about it, you don't want to worry about custom HTML handlers or extending
[00:46:08]
it, you just want to put out some Markdown on the page, then it's totally reasonable
[00:46:15]
to just use Elm Exploration Markdown.
[00:46:16]
In that case, it might be overkill to use Dillon Kern's Elm Markdown if you don't need
[00:46:21]
any of those features.
[00:46:23]
So I have wanted to use Markdown for a few years already.
[00:46:29]
You know where I'm going, right?
[00:46:33]
I wrote Elm Review documentation, which tries to find problems in your Elm documentation,
[00:46:40]
which is written in Markdown.
[00:46:43]
I just made a release.
[00:46:45]
So I did use Elm Markdown.
[00:46:48]
So tell me about that.
[00:46:50]
So the issue with Elm Markdown is it parses the Markdown just fine.
[00:46:57]
No issues there as far as I can see.
[00:47:00]
But it doesn't tell me where the thing I'm looking at is.
[00:47:04]
Because Elm Review needs to know where's the location of this link so that it can put squiggly
[00:47:11]
lines under it or to fix it, to change it.
[00:47:16]
And that was a problem for me.
[00:47:18]
So in the end, what I did was following someone else's suggestion, Lou Bird, L U E Bird, was
[00:47:28]
to use a parser, but a custom one and then try it iteratively until it finds all the
[00:47:36]
links and all the sections and stuff like that.
[00:47:39]
So yeah, I'm watching.
[00:47:40]
That's a lot of work.
[00:47:42]
It was more work than I expected.
[00:47:45]
I started based on Lou's solution already.
[00:47:50]
And then I still had to change quite a lot of things, unfortunately.
[00:47:54]
So why don't we have access to the range, to the position?
[00:47:59]
I see.
[00:48:00]
Yes.
[00:48:01]
How can we make that happen?
[00:48:02]
It would be great to make it more usable with Elm Review, yeah.
[00:48:10]
It's a good question.
[00:48:12]
I guess one of the challenges is that you could build a markdown block structure that
[00:48:18]
wasn't from being parsed.
[00:48:20]
So that's one challenge.
[00:48:21]
What do you do there?
[00:48:22]
And then another challenge is just it kind of clutters up the data types in a way that
[00:48:28]
makes it a little more inconvenient to use for users for most of their use cases.
[00:48:33]
So we should discuss it more.
[00:48:36]
It would be interesting.
[00:48:37]
And one thing I would definitely like to do is I would like to have more information from
[00:48:42]
the AST that it can give you some really cool possibilities.
[00:48:47]
Like for example, I know some there's a markdown based slide tool that I really like called
[00:48:54]
Dexet and it gives you a few features that sort of take advantage of places that you
[00:49:02]
can sort of put metadata within markdown.
[00:49:04]
So for example, if you do a code snippet, which you can do like a code fence with triple
[00:49:10]
back ticks.
[00:49:11]
So then you kind of like a multi line code snippet.
[00:49:15]
You can do triple back ticks and then you can put the name of the language that you're
[00:49:20]
going to syntax highlight with.
[00:49:21]
So you could put Elm or JS.
[00:49:25]
So sometimes, so Dillon Kern's Elm markdown gives you access to that language, but it
[00:49:32]
sort of throws away the rest of it, but it could actually extract that information as
[00:49:38]
part of the AST.
[00:49:40]
And that gives you the opportunity to play around with that.
[00:49:43]
For example, in Dexet, they use that to put lines that you highlight.
[00:49:48]
So you could put two dash three and it'll highlight lines two and three.
[00:49:53]
So at the moment with Elm markdown, you would parse the language as Elm colon two, colon
[00:50:00]
three or something?
[00:50:01]
I think it might parse the language as Elm and then discard it.
[00:50:04]
I need to check on that.
[00:50:08]
Because formally this specification says something about that.
[00:50:12]
So but yeah, things like that can provide some interesting possibilities for extensibility.
[00:50:17]
Now like adding information about what actual spaces are behind things and that sort of
[00:50:24]
thing could be that's probably not in scope of having a concrete syntax tree that would
[00:50:30]
allow you to parse and then output to the same data that was parsed because that's just
[00:50:37]
not what it's designed for.
[00:50:41]
But I don't know, possibly having some regions that tell you what point in the file things
[00:50:46]
came from could be interesting.
[00:50:48]
One use case for this would be like writing a markdown linter.
[00:50:52]
The thing is, there are already plenty of markdown linters out there.
[00:50:56]
Exactly.
[00:50:57]
Right.
[00:50:58]
Yeah.
[00:50:59]
But it is, you know, I mean, you never know the possibilities that open up.
[00:51:03]
And when you have, you know, this is maybe a topic for another conversation, but I'm
[00:51:10]
really fascinated by the like emergent dynamics when you when you create an ecosystem where
[00:51:18]
people have tools to build off of.
[00:51:21]
So I think Elm Review is like a great case study of this that we see all these really
[00:51:26]
cool innovations because nobody needs to ask your permission.
[00:51:31]
Nobody needs your help to build it.
[00:51:33]
There's documentation, there's a nice API and people go build things and then people
[00:51:38]
install it and publish it.
[00:51:40]
They can see the errors and fixes and VS code and in their GitHub actions and everything.
[00:51:45]
And you have this, you know, things can really thrive because, you know, people can just
[00:51:50]
build things with this nice language, nicely typed information, nice, nice, nice platform
[00:51:56]
for doing that.
[00:51:57]
So you never know, like if you create these types of tools, like if Elm Markdown had more
[00:52:02]
capabilities for doing that sort of thing, maybe we'd have a flourishing ecosystem.
[00:52:06]
I certainly have had a lot of fun doing sort of unexpected transformations like parsing
[00:52:12]
out back references in my notes.
[00:52:16]
And there's so much more you could do.
[00:52:18]
Like if you look at unified JS, there's this like ecosystem of like this.
[00:52:26]
It's actually like hard to keep in your head straight what the different splits of the
[00:52:31]
tool are as with many things in the JavaScript ecosystem.
[00:52:34]
Things are like split out into these micro composable pieces that you're like, okay,
[00:52:38]
which part is responsible for what again?
[00:52:40]
But anyway, there's this like, there's this ecosystem of like Markdown parsing and transforming
[00:52:46]
plugins in the React ecosystem, remark and unified JS.
[00:52:51]
And I'll put a link to it in the show notes.
[00:52:54]
And you know, it's really cool.
[00:52:55]
Like you have all these plugins that people publish.
[00:52:58]
And I think it would be really cool to see that sort of thing with transformations for
[00:53:04]
Dillon Kern's L Markdown blocks where you could have, you know, people publishing packages
[00:53:09]
for gathering up a table of contents.
[00:53:11]
I mean, I have that in examples, but it would be, and I use it all the time, but it would
[00:53:17]
be nice to package it up nicely so people can use it and create a little ecosystem of
[00:53:21]
doing cool Markdown transformations because Elm is very good for that, you know?
[00:53:26]
So yeah.
[00:53:28]
So is this the right place to segue into L Markdown transforms?
[00:53:33]
Yeah, I think so.
[00:53:36]
So yeah, that's a really cool package that our friend Philip built and he built it to,
[00:53:45]
partially, you know, Philip and I had a lot of conversations about like these ideas that
[00:53:50]
he had for a different way to approach the renderer in L Markdown.
[00:53:54]
You know, we figured it would make sense for him to explore it in a separate package, but
[00:53:59]
it's sort of proven to be a very good approach that I would love to fold back into the core
[00:54:06]
package.
[00:54:07]
So that's something we're exploring right now.
[00:54:09]
So what does it do?
[00:54:10]
What's the goal of that package at the moment?
[00:54:14]
That package.
[00:54:15]
So, and maybe we should talk first a little bit more about the renderer functionality
[00:54:20]
because I think we haven't fully covered that.
[00:54:23]
So the renderer, so how it works is you give it a big record that tells you how do I handle,
[00:54:34]
you know, a strikethrough, a paragraph, a block quote, you know, emphasis strong, which
[00:54:40]
are bold and italics.
[00:54:42]
And you just give it a function that says, you know, here's the, you know, here are the
[00:54:48]
children of this thing, renderer, how do you want to render a paragraph?
[00:54:52]
And you could render it with Elm HTML.
[00:54:55]
You could render it with Elm CSS.
[00:54:57]
You could render a paragraph with Elm UI.
[00:55:00]
You could render a paragraph as plain text to just, oh, a paragraph.
[00:55:05]
You just put a new line before and after, for example, whatever it might be.
[00:55:10]
Am I right in understanding that it's pretty much just a fold?
[00:55:14]
Yeah.
[00:55:15]
The fold that we spoke about before.
[00:55:18]
Absolutely.
[00:55:19]
But made in a way that is more easily extensible or like you already have like a default options
[00:55:27]
for that.
[00:55:28]
Yes.
[00:55:29]
The Elm Markdown package ships with a default HTML renderer that you can just use to get
[00:55:34]
the standard HTML output.
[00:55:35]
So if you don't want to customize your renderer at all and you want to use the standard, you
[00:55:39]
know, lists parsed to just a list element and they have a certain class on them, if
[00:55:44]
the starting number is a certain thing and that sort of thing, then you can just do that.
[00:55:48]
So if you didn't have this render function, then people would have to do a fold with a
[00:55:54]
big case expression or two, one for the blocks and one for the inlines, I'm guessing.
[00:56:00]
Yeah.
[00:56:01]
They do some big recursive call traversing through the, because it, yeah, it would not
[00:56:09]
be fun.
[00:56:10]
But yeah, it's essentially, it gives you the ability to render out to any custom format
[00:56:15]
and any data type.
[00:56:16]
And now, you know, I mentioned these different view types like HTML and, and you know, LMI
[00:56:23]
elements, but you can get way more sophisticated than that.
[00:56:27]
So if you wanted to render to results, so you could have like a result at any point,
[00:56:33]
you could do that.
[00:56:34]
If you want it to render to a function, why would you render to a function?
[00:56:38]
Well, if you wanted to display something interactive.
[00:56:44]
So, so B. Burdette has this really cool example of like a little scheme type in like Lisp
[00:56:53]
evaluator that he built.
[00:56:56]
And he built a little like implementation of these markdown cells where you can put
[00:57:02]
like a little cell using like HTML, HTML tag cell, and you can put data into it and you
[00:57:09]
can interpret Lisp expressions within, within them in your view.
[00:57:15]
And it does that because it, it renders to a function and you can pass in an interactive
[00:57:20]
model and it can update that model.
[00:57:22]
So you can have like stateful things that you render, you know, so the sky's the limit.
[00:57:28]
Yeah.
[00:57:29]
This was actually my first introduction to L Markdown.
[00:57:32]
Like I didn't even know L Markdown for anything else when I was introduced to this.
[00:57:38]
So yeah, my first introduction to L Markdown was, Hey, you can take Markdown and you can
[00:57:45]
make interactive things with it, which is not the main purpose, but does, does, does
[00:57:52]
highlight the potential of the library?
[00:57:56]
Yeah.
[00:57:57]
To me, that's what's really, you know, that's what's really interesting.
[00:58:00]
You know, I mean, like, like I, like I said at the top, the three, the three interesting
[00:58:05]
things I think are, you can parse the AST and manipulate it in Elm, which is awesome
[00:58:11]
and fold over it and all that you can customize renders and you can add these HTML handlers
[00:58:18]
and the customizable renderer output is amazing when you consider that you can render to any
[00:58:24]
type and that includes functions that depend on your model or that take in a dictionary
[00:58:29]
that has state and it can insert things into it and update things and remove things that
[00:58:35]
also includes, I think we mentioned this a little bit in the Elm pages 2.0 episode, you
[00:58:41]
can render to a data source.
[00:58:43]
And if you render to a data source, that means that you can, you know, I mean, the sky's
[00:58:50]
the limit.
[00:58:51]
You could, you could have a build error if there's an invalid link, right?
[00:58:55]
So you can do validation type things and turn that into a builder and a data source and
[00:58:58]
Elm pages, you could, you know, you could go and take a, take a link and use a data
[00:59:05]
source to follow that link and make sure it's valid or, you know, the sky's the limit.
[00:59:11]
You could also do a single pass for everything like extracting data and rendering.
[00:59:16]
Yeah.
[00:59:17]
Yeah.
[00:59:18]
I tend to think of, you know, using like, I mean, you know, Elm Markdown, I built Elm
[00:59:26]
Markdown as a, as a yak shave while building Elm pages.
[00:59:31]
Like I was like, I want, I want a tool that does this, that I can like put something in
[00:59:37]
GitHub and it's going to present it in a reasonable way.
[00:59:40]
And I can share a link that says, edit this page on GitHub.
[00:59:44]
And people can do that and see the preview and it's familiar Markdown syntax, but I want
[00:59:48]
it to be extensible.
[00:59:49]
I want to be able to validate it.
[00:59:51]
I want to be able to use Elm, all my Elm foo on it.
[00:59:54]
And so like the idea is like, I think of it as you're setting up the machinery for, you
[01:00:00]
know, validating and rendering your views and like, you're just doing that with Elm.
[01:00:06]
So you can do anything, you know, you can, you can do all sorts of stuff with that.
[01:00:09]
So, so that's renderers.
[01:00:12]
So Phillips library, Elm Markdown transforms, it provides a, a way to sort of traverse over
[01:00:21]
things and map them.
[01:00:22]
And it's, you know, I'm still working on coming up with like distilling it down to, to the
[01:00:30]
core of what it is.
[01:00:31]
It's one of those things that really hurts your brain, but it's incredible what you could
[01:00:34]
do with it because you can, you, you just have like much more ability to sort of map
[01:00:39]
things and, and transform them in multiple passes.
[01:00:42]
And if you were just with vanilla Dillon Kern's Elm Markdown try to, you know, render things
[01:00:49]
to a data source, it doesn't work.
[01:00:52]
It's not, it's not so easy to, to actually do a lot of work with that.
[01:00:56]
Yes.
[01:00:57]
It would be a lot of work and this removes some steps from that.
[01:00:59]
So I'm working on integrating like the concepts from this library into the core API, cause
[01:01:05]
I think it's a really good way.
[01:01:07]
It's it's basically like a nicer renderer.
[01:01:10]
It's the same concept, except instead of a big record of functions for how to do each
[01:01:14]
thing, you render to a custom type.
[01:01:17]
So yeah, that's definitely worth checking out what, what Philip has done there.
[01:01:20]
I'll link to it.
[01:01:21]
It hasn't been updated yet for the latest Elm Markdown and Elm pages, but I actually
[01:01:26]
have like a local fork of that.
[01:01:27]
Maybe I'll just make a pull request to, to his package and we can, can get that shipped
[01:01:32]
now.
[01:01:33]
Dillon promises you that it will be released before this episode is released, right Dillon?
[01:01:39]
Right?
[01:01:40]
Yeah, absolutely.
[01:01:41]
Well, so, you know, so much of this stuff, like there's so much you can do.
[01:01:44]
And part of it is like when it comes to just like dealing with the Markdown blocks and
[01:01:50]
transforming them and extracting table of contents and stuff, it's pretty straightforward
[01:01:55]
in a sense.
[01:01:56]
But then there are all these subtleties of the, the parsing specification and the rent,
[01:02:02]
you know, the way the render is designed and how you transform things that I feel like
[01:02:07]
I'm just like constantly tweaking and experimenting in my own little private private, not private
[01:02:15]
repos, but my own, you know, public repos, but in a little local fork in order to try
[01:02:22]
these different approaches because there's just so many, there's so much you can do with
[01:02:27]
it.
[01:02:28]
There are so many ways you can approach this design, but I'm always sort of iterating on
[01:02:31]
trying to find a way to, to integrate some of these more powerful things into the core
[01:02:35]
in a way that's intuitive.
[01:02:37]
So all in all, L Markdown was a fun little small hobby project in order to have something
[01:02:49]
nice for L pages.
[01:02:50]
Is that right?
[01:02:51]
Yes, it was.
[01:02:55]
I built it.
[01:02:56]
I built the initial prototype on a flight to India, which flights to India are very
[01:03:01]
long from California.
[01:03:04]
So yeah, I built the initial proof of concept on a flight while I was working on some L
[01:03:10]
pages stuff and I just really wanted something that operated this way and it was absolutely
[01:03:17]
a yak shape.
[01:03:18]
It was which is part of why, you know, I tried to build it in a way that was really hopefully
[01:03:27]
smooth and easy to contribute from community members and it's been really cool to see that
[01:03:33]
shape up because I knew that there were too many features that I wanted to build between
[01:03:38]
L pages and L Markdown to build every single part of the parser myself.
[01:03:41]
So it's been really cool to see that come together.
[01:03:44]
And you know, yeah, it's like I was saying earlier, like things get really exciting.
[01:03:50]
You know, if you build one feature, it's like, it's like you give someone a feature and they'll
[01:03:57]
be happy for a day.
[01:03:58]
But if you teach people how to build a feature, then they'll be happy for a lifetime.
[01:04:10]
But what do you do in the meantime?
[01:04:12]
If you teach someone, you don't have to fish anymore.
[01:04:16]
Or do you?
[01:04:17]
Oh, there's always plenty of work to do.
[01:04:19]
I don't think that's going to be a problem.
[01:04:24]
Same here.
[01:04:27]
More features to do.
[01:04:29]
Always more features.
[01:04:30]
All right.
[01:04:32]
So where can people go if they want to get started with L Markdown or to contribute to
[01:04:37]
L Markdown?
[01:04:38]
Good question.
[01:04:39]
So, well, I wrote a blog post announcing it.
[01:04:43]
I don't know when a year, year and a half ago, something like that.
[01:04:47]
2019.
[01:04:48]
Two years ago.
[01:04:49]
Oh my God.
[01:04:50]
Time flies.
[01:04:51]
What is it called?
[01:04:52]
Extensible Markdown Parting in Pure Elm.
[01:04:55]
So I actually gave it a reread this morning.
[01:04:59]
It's a pretty short post, but I think it summarizes the goals pretty well.
[01:05:03]
So check that out.
[01:05:05]
Check out the repo.
[01:05:06]
Check out the examples.
[01:05:07]
And we'll leave some examples to some of the really cool things people have built with
[01:05:11]
it.
[01:05:12]
So Philip built a very cool interactive sort of like, you know, click to edit like graphics
[01:05:18]
tool.
[01:05:19]
Like it's sort of changing the color and shape of these objects on the screen.
[01:05:24]
And you can click to apply or deselect these transformations and see how it changes what's
[01:05:31]
on the screen.
[01:05:32]
So that's like a cool thing he built with L Markdown on his website.
[01:05:37]
The Scheme Interpreter example is like a very cool use case for it.
[01:05:42]
I'll link to some of the stuff that I've done like in my incremental elm.com site.
[01:05:47]
I've been having a ton of fun using it to parse things and validate things and map things
[01:05:55]
into crazy transformations.
[01:05:57]
So yeah, check those things out.
[01:05:59]
Join the Markdown channel in the Elm Slack.
[01:06:02]
Let us know what you're doing.
[01:06:03]
I'd love to hear about it and feel free to ask questions there.
[01:06:07]
And if anybody is interested in sharing some of the things that they're working on in their
[01:06:13]
own personal projects, their own yakshaves, their own cool Elm experiments, Mario Rogic
[01:06:19]
has shared a link for a Google form that he created for the Elm online meetup.
[01:06:28]
So it's been really cool to see the great talks coming out of that meetup.
[01:06:32]
Or is it a meetdown?
[01:06:33]
It is a meetdown.
[01:06:36]
It's a meetdown.
[01:06:37]
It is a meetdown.
[01:06:38]
So if you're not familiar with it yet, we'll drop a link to the website for the Elm online
[01:06:45]
meetdown.
[01:06:46]
Check it out.
[01:06:47]
There's great stuff happening there.
[01:06:49]
And it would be great to see more people submitting talks.
[01:06:52]
There have already been a ton of great ones recently and they're getting posted on YouTube
[01:06:56]
now.
[01:06:57]
So yeah, check that out.
[01:06:59]
Submit something cool.
[01:07:00]
And Yaron, until next time.
[01:07:03]
Until next time.