# \[ANN\] Kelpie.jl: An HTML templating engine in pure Julia

**URL:** <https://discourse.julialang.org/t/ann-kelpie-jl-an-html-templating-engine-in-pure-julia/79004>\
**Category:** Package Announcements\
**Tags:** package, announcement, web, html\
**Created:** [April 4, 2022, 12:59pm UTC](https://discourse.julialang.org/t/ann-kelpie-jl-an-html-templating-engine-in-pure-julia/79004 "2022-04-04T12:59:01Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![MillironX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/millironx/32/28274_2.png) [@MillironX](https://discourse.julialang.org/u/MillironX)\
**Post date:** [April 4, 2022, 12:59pm UTC](https://discourse.julialang.org/t/ann-kelpie-jl-an-html-templating-engine-in-pure-julia/79004/1 "2022-04-04T12:59:01Z")

</div>

> **[GitHub - MillironX/Kelpie.jl: :dog2: I accidentally built an HTML templating...](https://github.com/MillironX/Kelpie.jl)**
>
> :dog2: I accidentally built an HTML templating engine in Julia - GitHub - MillironX/Kelpie.jl: :dog2: I accidentally built an HTML templating engine in Julia

Kelpie wraps [EzXML.jl](https://github.com/JuliaIO/EzXML.jl) nodes with functions taken from the names of HTML5 elements (e.g. `a`, `img`, `nav`, etc.). Each function takes the content of the element as a positional argument, and translates all keyword arguments into attributes. For example

```html
<a href="https://julialang.org" class="card-link">Julia</a>

```

is represented in Kelpie as

```julia
a("Julia"; href="https://julialang.org", class="card-link")

```

This package happened almost entirely by accident: I was writing a script to display a combination of biological sequences in a webpage using [BioJulia](https://biojulia.net) and [EzXML.jl](https://github.com/JuliaIO/EzXML.jl) and got tired of having to manually link all my nodes together. So I started writing wrapper functions, then I got tired of writing those, so I converted to a generated function, and Kelpie was born. Once I started chaining function calls, I noticed that the syntax looked a lot like [Pug](https://pugjs.org), so I named it after a different dog breed.

I’m still learning the full capabilities of my new creation, but it should be really easy to insert into [Genie](https://genieframework.com) projects (I haven’t tried yet). It is way more capable than its flat-nosed counterpart, as Julia function calls from any package can be inserted right into a webpage directly. Documentation and testing will be more fleshed out in the coming weeks as I play around with it more.

Enjoy! 😄

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [April 4, 2022, 2:36pm UTC](https://discourse.julialang.org/t/ann-kelpie-jl-an-html-templating-engine-in-pure-julia/79004/2 "2022-04-04T14:36:32Z")

</div>

Cool 🙂  
Did you know of [Hyperscript.jl](https://github.com/JuliaWeb/Hyperscript.jl), which does seem to do something similar?

---

<div class="post-metadata">

**Author:** ![MillironX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/millironx/32/28274_2.png) [@MillironX](https://discourse.julialang.org/u/MillironX)\
**Post date:** [April 4, 2022, 3:08pm UTC](https://discourse.julialang.org/t/ann-kelpie-jl-an-html-templating-engine-in-pure-julia/79004/3 "2022-04-04T15:08:42Z")

</div>

I hadn’t seen Hyperscript.jl. It’s a cool approach, too.

---

<div class="post-metadata">

**Author:** ![lawless-m](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lawless-m/32/30869_2.png) [@lawless-m](https://discourse.julialang.org/u/lawless-m)\
**Post date:** [April 4, 2022, 3:44pm UTC](https://discourse.julialang.org/t/ann-kelpie-jl-an-html-templating-engine-in-pure-julia/79004/4 "2022-04-04T15:44:46Z")

</div>

Hi I haven’t tried it, although I think it’s a great idea.  
How does it cope with some problematic HTML I know about:

- invalid julia names of tags
- attributes as values
- invalid kw argument names

```julia
<!DOCTYPE html>

<input type="checkbox" checked>

<p data-56="some data">

<option selected>

<!-- what about comments -->

```

---

<div class="post-metadata">

**Author:** ![MillironX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/millironx/32/28274_2.png) [@MillironX](https://discourse.julialang.org/u/MillironX)\
**Post date:** [April 4, 2022, 3:59pm UTC](https://discourse.julialang.org/t/ann-kelpie-jl-an-html-templating-engine-in-pure-julia/79004/5 "2022-04-04T15:59:57Z")

</div>

1. Invalid names of tags are edge cases with special wrapper functions (i.e. `<div>` → `html_div()`)
2. Attributes as values are invalid XHTML afaik, and won’t be supported
3. Kelpie translates underscores in kwargs names to dashes: this is undocumented right now, and will probably change to something more robust later
4. My goal with Kelpie is to make machine-readable HTML out of human-readable Julia, so I don’t plan to add support for comments

---

<div class="post-metadata">

**Author:** ![lawless-m](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lawless-m/32/30869_2.png) [@lawless-m](https://discourse.julialang.org/u/lawless-m)\
**Post date:** [April 4, 2022, 4:05pm UTC](https://discourse.julialang.org/t/ann-kelpie-jl-an-html-templating-engine-in-pure-julia/79004/6 "2022-04-04T16:05:17Z")

</div>

Oh. Your headlines says HTML Templating, not XHTML

well, all the best
