So, after a discussion on #haskell, I decided to try writing a simple HTML DSL in Haskell. In about 15 minutes, I had a rather rudimentary implementation, and after a day or so of working, I’ve got a somewhat useful DSL for writing HTML, and pretty printing it.
The main type behind the package is:
data HTML a = Doctype String String String [HTML a]
| Content a
| Text String
| Node Tag Attrs [HTML a]
| NoContent Tag Attrs
| Comment String
deriving Show
where
type Attr = (String, String)
type Attrs = [Attr]
data Tag = Html
| ARef
| BlockQuote
| Body
...
| Title
| TR
| UL
I’ve also provided helper functions to make this an actual DSL (I guess?):
example :: HTML ()
example =
doctype "html PUBLIC" "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [
xhtml [
header [
title "My random page",
meta "name" "Alex"
],
body [
comment "This is a comment",
para [
text "The hr tag defines a horizontal rule:"
],
hr,
para [
text "This is a paragraph"
],
hr,
para [
text "This is a paragraph"
],
table [
tr [
td [
text "data"
],
td [
text "more data"
]
],
tr [
td [
text "more data"
]
]
]
]
]
]
produces:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head >
<title >
My random page
</title>
<meta name="name" content="Alex"/>
</head>
<body >
<!-- This is a comment -->
<p >
The hr tag defines a horizontal rule:
</p>
<hr />
<p >
This is a paragraph
</p>
<hr />
<p >
This is a paragraph
</p>
<table >
<tr >
<td >
data
</td>
<td >
more data
</td>
</tr>
<tr >
<td >
more data
</td>
</tr>
</table>
</body>
</html>
I don’t claim that anyone should use this (there’s a good chance I won’t be releasing it, unless someone really wants me to), but I’m still quite proud of it.