diff --git a/Util/BlazeFromHtml.hs b/Util/BlazeFromHtml.hs
deleted file mode 100644
--- a/Util/BlazeFromHtml.hs
+++ /dev/null
@@ -1,327 +0,0 @@
--- | A module for conversion from HTML to BlazeHtml Haskell code.
---
-module Main where
-
-import Control.Monad (forM_, when)
-import Control.Applicative ((<$>))
-import Data.List (isPrefixOf, stripPrefix)
-import Data.Maybe (listToMaybe, fromMaybe, fromJust)
-import Data.Char (toLower, isSpace)
-import Control.Arrow (first)
-import System.Environment (getArgs)
-import System.FilePath (dropExtension)
-import qualified Data.Map as M
-import System.Console.GetOpt
-
-import Text.HTML.TagSoup
-
-import Util.Sanitize (sanitize)
-import Util.GenerateHtmlCombinators hiding (main)
-
--- | Simple type to represent attributes.
---
-type Attributes = [(String, String)]
-
--- | Intermediate tree representation. This representation contains several
--- constructors aimed at pretty-printing.
---
-data Html = Parent String Attributes Html
-          | Block [Html]
-          | Text String
-          | Comment String
-          | Doctype
-          deriving (Show)
-
--- | Different combinator types.
---
-data CombinatorType = ParentCombinator
-                    | LeafCombinator
-                    | UnknownCombinator
-                    deriving (Eq, Show)
-
--- | Traverse the list of tags to produce an intermediate representation of the
--- HTML tree.
---
-makeTree :: HtmlVariant           -- ^ HTML variant used
-         -> Bool                  -- ^ Should ignore errors
-         -> [String]              -- ^ Stack of open tags
-         -> [Tag String]          -- ^ Tags to parse
-         -> (Html, [Tag String])  -- ^ (Result, unparsed part)
-makeTree _ ignore stack []
-    | null stack || ignore = (Block [], [])
-    | otherwise = error $ "Error: tags left open at the end: " ++ show stack
-makeTree variant ignore stack (TagPosition row _ : x : xs) = case x of
-    TagOpen tag attrs -> if toLower' tag == "!doctype"
-        then addHtml Doctype xs
-        else let tag' = toLower' tag
-                 (inner, t) = case combinatorType variant tag' of
-                    LeafCombinator -> (Block [], xs)
-                    _ -> makeTree variant ignore (tag' : stack) xs
-                 p = Parent tag' (map (first toLower') attrs) inner
-             in addHtml p t
-    -- The closing tag must match the stack. If it is a closing leaf, we can
-    -- ignore it
-    TagClose tag ->
-        let isLeafCombinator = combinatorType variant tag == LeafCombinator
-            matchesStack = listToMaybe stack == Just (toLower' tag)
-        in case (isLeafCombinator, matchesStack, ignore) of
-            -- It's a leaf combinator, don't care about this element
-            (True, _, _)          -> makeTree variant ignore stack xs
-            -- It's a parent and the stack doesn't match
-            (False, False, False) -> error $
-                "Line " ++ show row ++ ": " ++ show tag ++ " closed but "
-                        ++ show stack ++ " should be closed instead."
-            -- Stack might not match but we ignore it anyway
-            (False, _, _)         -> (Block [], xs)
-    TagText text -> addHtml (Text text) xs
-    TagComment comment -> addHtml (Comment comment) xs
-    _ -> makeTree variant ignore stack xs
-  where
-    addHtml html xs' = let (Block l, r) = makeTree variant ignore stack xs'
-                       in (Block (html : l), r)
-
-    toLower' = map toLower
-makeTree _ _ _ _ = error "TagSoup error"
-
--- | Remove empty text from the HTML.
---
-removeEmptyText :: Html -> Html
-removeEmptyText (Block b) = Block $ map removeEmptyText $ flip filter b $ \h ->
-    case h of Text text -> any (not . isSpace) text
-              _         -> True
-removeEmptyText (Parent tag attrs inner) =
-    Parent tag attrs $ removeEmptyText inner
-removeEmptyText x = x
-
--- | Try to eliminiate Block constructors as much as possible.
---
-minimizeBlocks :: Html -> Html
-minimizeBlocks (Parent t a (Block [x])) = minimizeBlocks $ Parent t a x
-minimizeBlocks (Parent t a x) = Parent t a $ minimizeBlocks x
-minimizeBlocks (Block x) = Block $ map minimizeBlocks x
-minimizeBlocks x = x
-
--- | Get the type of a combinator, using a given variant.
---
-combinatorType :: HtmlVariant -> String -> CombinatorType
-combinatorType variant combinator
-    | combinator == "docTypeHtml" = ParentCombinator
-    | combinator `elem` parents variant = ParentCombinator
-    | combinator `elem` leafs variant = LeafCombinator
-    | otherwise = UnknownCombinator
-
--- | Create a special @<html>@ parent that includes the docype.
---
-joinHtmlDoctype :: Html -> Html
-joinHtmlDoctype (Block (Doctype : Parent "html" attrs inner : xs)) =
-    Block $ Parent "docTypeHtml" attrs inner : xs
-joinHtmlDoctype x = x
-
--- | Produce the Blaze code from the HTML. The result is a list of lines.
---
-fromHtml :: HtmlVariant  -- ^ Used HTML variant
-         -> Bool         -- ^ Should ignore errors
-         -> Html         -- ^ HTML tree
-         -> [String]     -- ^ Resulting lines of code
-fromHtml _ _ Doctype = ["docType"]
-fromHtml _ _ (Text text) = ["\"" ++ concatMap escape (trim text) ++ "\""]
-  where
-    -- Remove whitespace on both ends of a string
-    trim = reverse . dropWhile isSpace . reverse . dropWhile isSpace
-    -- Escape a number of characters
-    escape '"'  = "\\\""
-    escape '\n' = "\\n"
-    escape x    = [x]
-fromHtml _ _ (Comment comment) = map ("-- " ++) $ lines comment
-fromHtml variant ignore (Block block) =
-    concatMap (fromHtml variant ignore) block
-fromHtml variant ignore (Parent tag attrs inner) =
-    case combinatorType variant tag of
-        -- Actual parent tags
-        ParentCombinator -> case inner of
-            (Block ls) -> if null ls
-                then [combinator ++
-                        (if null attrs then " " else " $ ") ++ "mempty"]
-                else (combinator ++ " $ do") :
-                        indent (fromHtml variant ignore inner)
-            -- We join non-block parents for better readability.
-            x -> let ls = fromHtml variant ignore x
-                     apply = if dropApply x then " " else " $ "
-                 in case ls of (y : ys) -> (combinator ++ apply ++ y) : ys
-                               [] -> [combinator]
-
-        -- Leaf tags
-        LeafCombinator -> [combinator]
-
-        -- Unknown tag
-        UnknownCombinator -> if ignore
-            then fromHtml variant ignore inner
-            else error $ "Tag " ++ tag ++ " is illegal in "
-                                       ++ show variant
-  where
-    combinator = qualifiedSanitize "H." tag ++ attributes'
-    attributes' = attrs >>= \(k, v) -> case k `elem` attributes variant of
-        True  -> " ! " ++ qualifiedSanitize "A." k ++ " " ++ show v
-        False
-            | "data-" `isPrefixOf` k -> " ! "
-                                     ++ "dataAttribute" ++ " "
-                                     ++ show (fromJust $ stripPrefix "data-" k)
-                                     ++ " " ++ show v
-            | ignore                 -> ""
-            | otherwise              -> error $ "Attribute "
-                                     ++ k ++ " is illegal in "
-                                     ++ show variant
-
-    -- Qualifies a tag with the given qualifier if needed, and sanitizes it.
-    qualifiedSanitize qualifier tag' =
-        (if isNameClash variant tag' then qualifier else "") ++ sanitize tag'
-
-    -- Check if we can drop the apply operator ($), for readability reasons.
-    -- This would change:
-    --
-    -- > p $ "Some text"
-    --
-    -- Into
-    --
-    -- > p "Some text"
-    --
-    dropApply (Parent _ _ _) = False
-    dropApply (Block _) = False
-    dropApply _ = null attrs
-
--- | Produce the code needed for initial imports.
---
-getImports :: HtmlVariant -> [String]
-getImports variant =
-    [ "{-# LANGUAGE OverloadedStrings #-}"
-    , ""
-    , import_ "Prelude"
-    , qualify "Prelude" "P"
-    , import_ "Data.Monoid (mempty)"
-    , ""
-    , import_ h
-    , qualify h "H"
-    , import_ a
-    , qualify a "A"
-    ]
-  where
-    import_ = ("import " ++)
-    qualify name short = "import qualified " ++ name ++ " as " ++ short
-    h = getModuleName variant
-    a = getAttributeModuleName variant
-
--- | Convert the HTML to blaze code.
---
-blazeFromHtml :: HtmlVariant  -- ^ Variant to use
-              -> Bool         -- ^ Produce standalone code
-              -> Bool         -- ^ Should we ignore errors
-              -> String       -- ^ Template name
-              -> String       -- ^ HTML code
-              -> String       -- ^ Resulting code
-blazeFromHtml variant standalone ignore name =
-    unlines . addSignature . fromHtml variant ignore
-            . joinHtmlDoctype . minimizeBlocks
-            . removeEmptyText . fst . makeTree variant ignore []
-            . parseTagsOptions parseOptions { optTagPosition = True }
-  where
-    addSignature body = if standalone then [ name ++ " :: Html"
-                                           , name ++ " = do"
-                                           ] ++ indent body
-                                      else body
-
--- | Indent block of code.
---
-indent :: [String] -> [String]
-indent = map ("    " ++)
-
--- | Main function
---
-main :: IO ()
-main = do
-    args <- getOpt Permute options <$> getArgs
-    case args of
-        (o, n, []) -> let v = getVariant o
-                          s = standalone' o
-                          i = ignore' o
-                      in do imports' v o
-                            main' v s i n
-        (_, _, _)  -> putStr help
-  where
-    -- No files given, work with stdin
-    main' variant standalone ignore [] = interact $
-        blazeFromHtml variant standalone ignore "template"
-
-    -- Handle all files
-    main' variant standalone ignore files = forM_ files $ \file -> do
-        body <- readFile file
-        putStrLn $ blazeFromHtml variant standalone ignore
-                                 (dropExtension file) body
-
-    -- Print imports if needed
-    imports' variant opts = when (standalone' opts) $
-        putStrLn $ unlines $ getImports variant
-
-    -- Should we produce standalone code?
-    standalone' opts = ArgStandalone `elem` opts
-
-    -- Should we ignore errors?
-    ignore' opts = ArgIgnoreErrors `elem` opts
-
-    -- Get the variant from the options
-    getVariant opts = fromMaybe defaultHtmlVariant $ listToMaybe $
-        flip concatMap opts $ \o -> case o of (ArgHtmlVariant x) -> [x]
-                                              _ -> []
-
--- | Help information.
---
-help :: String
-help = unlines $
-    [ "This is a tool to convert HTML code to BlazeHtml code. It is still"
-    , "experimental and the results might need to be edited manually."
-    , ""
-    , "USAGE"
-    , ""
-    , "  blaze-from-html [OPTIONS...] [FILES ...]"
-    , ""
-    , "When no files are given, it works as a filter."
-    , ""
-    , "EXAMPLE"
-    , ""
-    , "  blaze-from-html -v html4-strict index.html"
-    , ""
-    , "This converts the index.html file to Haskell code, writing to stdout."
-    , ""
-    , "OPTIONS"
-    , usageInfo "" options
-    , "VARIANTS"
-    , ""
-    ] ++
-    map (("  " ++) . fst) (M.toList htmlVariants) ++
-    [ ""
-    , "By default, " ++ show defaultHtmlVariant ++ " is used."
-    ]
-
--- | Options for the CLI program
---
-data Arg = ArgHtmlVariant HtmlVariant
-         | ArgStandalone
-         | ArgIgnoreErrors
-         deriving (Show, Eq)
-
--- | A description of the options
---
-options :: [OptDescr Arg]
-options =
-    [ Option "v" ["html-variant"] htmlVariantOption "HTML variant to use"
-    , Option "s" ["standalone"] (NoArg ArgStandalone) "Produce standalone code"
-    , Option "e" ["ignore-errors"] (NoArg ArgIgnoreErrors) "Ignore most errors"
-    ]
-  where
-    htmlVariantOption = flip ReqArg "VARIANT" $ \name -> ArgHtmlVariant $
-        fromMaybe (error $ "No HTML variant called " ++ name ++ " found.")
-                  (M.lookup name htmlVariants)
-
--- | The default HTML variant
---
-defaultHtmlVariant :: HtmlVariant
-defaultHtmlVariant = html5
diff --git a/Util/GenerateHtmlCombinators.hs b/Util/GenerateHtmlCombinators.hs
deleted file mode 100644
--- a/Util/GenerateHtmlCombinators.hs
+++ /dev/null
@@ -1,469 +0,0 @@
-{-# LANGUAGE CPP #-}
-
-#define DO_NOT_EDIT (doNotEdit __FILE__ __LINE__)
-
--- | Generates code for HTML tags.
---
-module Util.GenerateHtmlCombinators where
-
-import Control.Arrow ((&&&))
-import Data.List (sort, sortBy, intersperse, intercalate)
-import Data.Ord (comparing)
-import System.Directory (createDirectoryIfMissing)
-import System.FilePath ((</>), (<.>))
-import Data.Map (Map)
-import qualified Data.Map as M
-import Data.Char (toLower)
-import qualified Data.Set as S
-
-import Util.Sanitize (sanitize, prelude)
-
--- | Datatype for an HTML variant.
---
-data HtmlVariant = HtmlVariant
-    { version     :: [String]
-    , docType     :: [String]
-    , parents     :: [String]
-    , leafs       :: [String]
-    , attributes  :: [String]
-    , selfClosing :: Bool
-    } deriving (Eq)
-
-instance Show HtmlVariant where
-    show = map toLower . intercalate "-" . version
-
--- | Get the full module name for an HTML variant.
---
-getModuleName :: HtmlVariant -> String
-getModuleName = ("Text.Blaze." ++) . intercalate "." . version
-
--- | Get the attribute module name for an HTML variant.
---
-getAttributeModuleName :: HtmlVariant -> String
-getAttributeModuleName = (++ ".Attributes") . getModuleName
-
--- | Check if a given name causes a name clash.
---
-isNameClash :: HtmlVariant -> String -> Bool
-isNameClash v t
-    -- Both an element and an attribute
-    | (t `elem` parents v || t `elem` leafs v) && t `elem` attributes v = True
-    -- Already a prelude function
-    | sanitize t `S.member` prelude = True
-    | otherwise = False
-
--- | Write an HTML variant.
---
-writeHtmlVariant :: HtmlVariant -> IO ()
-writeHtmlVariant htmlVariant = do
-    -- Make a directory.
-    createDirectoryIfMissing True basePath
-
-    let tags =  zip parents' (repeat makeParent)
-             ++ zip leafs' (repeat (makeLeaf $ selfClosing htmlVariant))
-        sortedTags = sortBy (comparing fst) tags
-        appliedTags = map (\(x, f) -> f x) sortedTags
-
-    -- Write the main module.
-    writeFile' (basePath <.> "hs") $ removeTrailingNewlines $ unlines
-        [ DO_NOT_EDIT
-        , "{-# LANGUAGE OverloadedStrings #-}"
-        , "-- | This module exports HTML combinators used to create documents."
-        , "--"
-        , exportList modulName $ "module Text.Blaze"
-                                : "docType"
-                                : "docTypeHtml"
-                                : map (sanitize . fst) sortedTags
-        , DO_NOT_EDIT
-        , "import Prelude ((>>), (.))"
-        , ""
-        , "import Text.Blaze"
-        , "import Text.Blaze.Internal"
-        , ""
-        , makeDocType $ docType htmlVariant
-        , makeDocTypeHtml $ docType htmlVariant
-        , unlines appliedTags
-        ]
-
-    let sortedAttributes = sort attributes'
-
-    -- Write the attribute module.
-    writeFile' (basePath </> "Attributes.hs") $ removeTrailingNewlines $ unlines
-        [ DO_NOT_EDIT
-        , "-- | This module exports combinators that provide you with the"
-        , "-- ability to set attributes on HTML elements."
-        , "--"
-        , "{-# LANGUAGE OverloadedStrings #-}"
-        , exportList attributeModuleName $ map sanitize sortedAttributes
-        , DO_NOT_EDIT
-        , "import Prelude ()"
-        , ""
-        , "import Text.Blaze.Internal (Attribute, AttributeValue, attribute)"
-        , ""
-        , unlines (map makeAttribute sortedAttributes)
-        ]
-  where
-    basePath = "Text" </> "Blaze" </> foldl1 (</>) version'
-    modulName = getModuleName htmlVariant
-    attributeModuleName = getAttributeModuleName htmlVariant
-    attributes' = attributes htmlVariant
-    parents'    = parents htmlVariant
-    leafs'      = leafs htmlVariant
-    version'    = version htmlVariant
-    removeTrailingNewlines = reverse . drop 2 . reverse
-    writeFile' file content = do
-        putStrLn ("Generating " ++ file)
-        writeFile file content
-
--- | Create a string, consisting of @x@ spaces, where @x@ is the length of the
--- argument.
---
-spaces :: String -> String
-spaces = flip replicate ' ' . length
-
--- | Join blocks of code with a newline in between.
---
-unblocks :: [String] -> String
-unblocks = unlines . intersperse "\n"
-
--- | A warning to not edit the generated code.
---
-doNotEdit :: FilePath -> Int -> String
-doNotEdit fileName lineNumber = init $ unlines
-    [ "-- WARNING: The next block of code was automatically generated by"
-    , "-- " ++ fileName ++ ":" ++ show lineNumber
-    , "--"
-    ]
-
--- | Generate an export list for a Haskell module.
---
-exportList :: String   -- ^ Module name.
-           -> [String] -- ^ List of functions.
-           -> String   -- ^ Resulting string.
-exportList _    []            = error "exportList without functions."
-exportList name (f:functions) = unlines $
-    [ "module " ++ name
-    , "    ( " ++ f
-    ] ++
-    map ("    , " ++) functions ++
-    [ "    ) where"]
-
--- | Generate a function for a doctype.
---
-makeDocType :: [String] -> String
-makeDocType lines' = unlines
-    [ DO_NOT_EDIT
-    , "-- | Combinator for the document type. This should be placed at the top"
-    , "-- of every HTML page."
-    , "--"
-    , "-- Example:"
-    , "--"
-    , "-- > docType"
-    , "--"
-    , "-- Result:"
-    , "--"
-    , unlines (map ("-- > " ++) lines') ++ "--"
-    , "docType :: Html  -- ^ The document type HTML."
-    , "docType = preEscapedText " ++ show (unlines lines')
-    , "{-# INLINE docType #-}"
-    ]
-
--- | Generate a function for the HTML tag (including the doctype).
---
-makeDocTypeHtml :: [String]  -- ^ The doctype.
-                -> String    -- ^ Resulting combinator function.
-makeDocTypeHtml lines' = unlines
-    [ DO_NOT_EDIT
-    , "-- | Combinator for the @\\<html>@ element. This combinator will also"
-    , "-- insert the correct doctype."
-    , "--"
-    , "-- Example:"
-    , "--"
-    , "-- > docTypeHtml $ span $ text \"foo\""
-    , "--"
-    , "-- Result:"
-    , "--"
-    , unlines (map ("-- > " ++) lines') ++ "-- > <html><span>foo</span></html>"
-    , "--"
-    , "docTypeHtml :: Html  -- ^ Inner HTML."
-    , "            -> Html  -- ^ Resulting HTML."
-    , "docTypeHtml inner = docType >> html inner"
-    , "{-# INLINE docTypeHtml #-}"
-    ]
-
--- | Generate a function for an HTML tag that can be a parent.
---
-makeParent :: String -> String
-makeParent tag = unlines
-    [ DO_NOT_EDIT
-    , "-- | Combinator for the @\\<" ++ tag ++ ">@ element."
-    , "--"
-    , "-- Example:"
-    , "--"
-    , "-- > " ++ function ++ " $ span $ text \"foo\""
-    , "--"
-    , "-- Result:"
-    , "--"
-    , "-- > <" ++ tag ++ "><span>foo</span></" ++ tag ++ ">"
-    , "--"
-    , function        ++ " :: Html  -- ^ Inner HTML."
-    , spaces function ++ " -> Html  -- ^ Resulting HTML."
-    , function        ++ " = Parent \"" ++ tag ++ "\" \"<" ++ tag
-                      ++ "\" \"</" ++ tag ++ ">\"" ++ modifier
-    , "{-# INLINE " ++ function ++ " #-}"
-    ]
-  where
-    function = sanitize tag
-    modifier = if tag `elem` ["style", "script"] then " . external" else ""
-
--- | Generate a function for an HTML tag that must be a leaf.
---
-makeLeaf :: Bool    -- ^ Make leaf tags self-closing
-         -> String  -- ^ Tag for the combinator
-         -> String  -- ^ Combinator code
-makeLeaf closing tag = unlines
-    [ DO_NOT_EDIT
-    , "-- | Combinator for the @\\<" ++ tag ++ " />@ element."
-    , "--"
-    , "-- Example:"
-    , "--"
-    , "-- > " ++ function
-    , "--"
-    , "-- Result:"
-    , "--"
-    , "-- > <" ++ tag ++ " />"
-    , "--"
-    , function ++ " :: Html  -- ^ Resulting HTML."
-    , function ++ " = Leaf \"" ++ tag ++ "\" \"<" ++ tag ++ "\" " ++ "\""
-               ++ (if closing then " /" else "") ++ ">\""
-    , "{-# INLINE " ++ function ++ " #-}"
-    ]
-  where
-    function = sanitize tag
-
--- | Generate a function for an HTML attribute.
---
-makeAttribute :: String -> String
-makeAttribute name = unlines
-    [ DO_NOT_EDIT
-    , "-- | Combinator for the @" ++ name ++ "@ attribute."
-    , "--"
-    , "-- Example:"
-    , "--"
-    , "-- > div ! " ++ function ++ " \"bar\" $ \"Hello.\""
-    , "--"
-    , "-- Result:"
-    , "--"
-    , "-- > <div " ++ name ++ "=\"bar\">Hello.</div>"
-    , "--"
-    , function        ++ " :: AttributeValue  -- ^ Attribute value."
-    , spaces function ++ " -> Attribute       -- ^ Resulting attribute."
-    , function        ++ " = attribute \"" ++ name ++ "\" \" "
-                      ++ name ++ "=\\\"\""
-    , "{-# INLINE " ++ function ++ " #-}"
-    ]
-  where
-    function = sanitize name
-
--- | HTML 4.01 Strict.
--- A good reference can be found here: http://www.w3schools.com/tags/default.asp
---
-html4Strict :: HtmlVariant
-html4Strict = HtmlVariant
-    { version = ["Html4", "Strict"]
-    , docType =
-        [ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""
-        , "    \"http://www.w3.org/TR/html4/strict.dtd\">"
-        ]
-    , parents =
-        [ "a", "abbr", "acronym", "address", "b", "bdo", "big", "blockquote"
-        , "body" , "button", "caption", "cite", "code", "colgroup", "dd", "del"
-        , "dfn", "div" , "dl", "dt", "em", "fieldset", "form", "h1", "h2", "h3"
-        , "h4", "h5", "h6", "head", "html", "i", "ins" , "kbd", "label"
-        , "legend", "li", "map", "noscript", "object", "ol", "optgroup"
-        , "option", "p", "pre", "q", "samp", "script", "select", "small"
-        , "span", "strong", "style", "sub", "sup", "table", "tbody", "td"
-        , "textarea", "tfoot", "th", "thead", "title", "tr", "tt", "ul", "var"
-        ]
-    , leafs =
-        [ "area", "br", "col", "hr", "link", "img", "input",  "meta", "param"
-        ]
-    , attributes =
-        [ "abbr", "accept", "accesskey", "action", "align", "alt", "archive"
-        , "axis", "border", "cellpadding", "cellspacing", "char", "charoff"
-        , "charset", "checked", "cite", "class", "classid", "codebase"
-        , "codetype", "cols", "colspan", "content", "coords", "data", "datetime"
-        , "declare", "defer", "dir", "disabled", "enctype", "for", "frame"
-        , "headers", "height", "href", "hreflang", "http-equiv", "id", "label"
-        , "lang", "maxlength", "media", "method", "multiple", "name", "nohref"
-        , "onabort", "onblur", "onchange", "onclick", "ondblclick", "onfocus"
-        , "onkeydown", "onkeypress", "onkeyup", "onload", "onmousedown"
-        , "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onreset"
-        , "onselect", "onsubmit", "onunload", "profile", "readonly", "rel"
-        , "rev", "rows", "rowspan", "rules", "scheme", "scope", "selected"
-        , "shape", "size", "span", "src", "standby", "style", "summary"
-        , "tabindex", "title", "type", "usemap", "valign", "value", "valuetype"
-        , "width"
-        ]
-    , selfClosing = False
-    }
-
--- | HTML 4.0 Transitional
---
-html4Transitional :: HtmlVariant
-html4Transitional = HtmlVariant
-    { version = ["Html4", "Transitional"]
-    , docType =
-        [ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\""
-        , "    \"http://www.w3.org/TR/html4/loose.dtd\">"
-        ]
-    , parents = parents html4Strict ++
-        [ "applet", "center", "dir", "font", "iframe", "isindex", "menu"
-        , "noframes", "s", "u"
-        ]
-    , leafs = leafs html4Strict ++ ["basefont"]
-    , attributes = attributes html4Strict ++
-        [ "background", "bgcolor", "clear", "compact", "hspace", "language"
-        , "noshade", "nowrap", "start", "target", "vspace"
-        ]
-    , selfClosing = False
-    }
-
--- | HTML 4.0 FrameSet
---
-html4FrameSet :: HtmlVariant
-html4FrameSet = HtmlVariant
-    { version = ["Html4", "FrameSet"]
-    , docType =
-        [ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 FrameSet//EN\""
-        , "    \"http://www.w3.org/TR/html4/frameset.dtd\">"
-        ]
-    , parents = parents html4Transitional ++ ["frameset"]
-    , leafs = leafs html4Transitional ++ ["frame"]
-    , attributes = attributes html4Transitional ++
-        [ "frameborder", "scrolling"
-        ]
-    , selfClosing = False
-    }
-
--- | XHTML 1.0 Strict
---
-xhtml1Strict :: HtmlVariant
-xhtml1Strict = HtmlVariant
-    { version = ["XHtml1", "Strict"]
-    , docType =
-        [ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""
-        , "    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
-        ]
-    , parents = parents html4Strict
-    , leafs = leafs html4Strict
-    , attributes = attributes html4Strict
-    , selfClosing = True
-    }
-
--- | XHTML 1.0 Transitional
---
-xhtml1Transitional :: HtmlVariant
-xhtml1Transitional = HtmlVariant
-    { version = ["XHtml1", "Transitional"]
-    , docType =
-        [ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\""
-        , "    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
-        ]
-    , parents = parents html4Transitional
-    , leafs = leafs html4Transitional
-    , attributes = attributes html4Transitional
-    , selfClosing = True
-    }
-
--- | XHTML 1.0 FrameSet
---
-xhtml1FrameSet :: HtmlVariant
-xhtml1FrameSet = HtmlVariant
-    { version = ["XHtml1", "FrameSet"]
-    , docType =
-        [ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 FrameSet//EN\""
-        , "    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">"
-        ]
-    , parents = parents html4FrameSet
-    , leafs = leafs html4FrameSet
-    , attributes = attributes html4FrameSet
-    , selfClosing = True
-    }
-
--- | HTML 5.0
--- A good reference can be found here:
--- http://www.w3schools.com/html5/html5_reference.asp
---
-html5 :: HtmlVariant
-html5 = HtmlVariant
-    { version = ["Html5"]
-    , docType = ["<!DOCTYPE HTML>"]
-    , parents =
-        [ "a", "abbr", "address", "article", "aside", "audio", "b", "base"
-        , "bdo", "blockquote", "body", "button", "canvas", "caption", "cite"
-        , "code", "colgroup", "command", "datalist", "dd", "del", "details"
-        , "dfn", "div", "dl", "dt", "em", "fieldset", "figcaption", "figure"
-        , "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header"
-        , "hgroup", "html", "i", "iframe", "ins", "keygen", "kbd", "label"
-        , "legend", "li", "map", "mark", "menu", "meter", "nav", "noscript"
-        , "object", "ol", "optgroup", "option", "output", "p", "pre", "progress"
-        , "q", "rp", "rt", "ruby", "samp", "script", "section", "select"
-        , "small", "source", "span", "strong", "style", "sub", "summary", "sup"
-        , "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "time"
-        , "title", "tr", "ul", "var", "video"
-        ]
-    , leafs =
-        [ "area", "br", "col", "embed", "hr", "img", "input", "meta", "link"
-        , "param"
-        ]
-    , attributes =
-        [ "accept", "accept-charset", "accesskey", "action", "alt", "async"
-        , "autocomplete", "autofocus", "autoplay", "challenge", "charset"
-        , "checked", "cite", "class", "cols", "colspan", "content"
-        , "contenteditable", "contextmenu", "controls", "coords", "data"
-        , "datetime", "defer", "dir", "disabled", "draggable", "enctype", "for"
-        , "form", "formaction", "formenctype", "formmethod", "formnovalidate"
-        , "formtarget", "headers", "height", "hidden", "high", "href"
-        , "hreflang", "http-equiv", "icon", "id", "ismap", "item", "itemprop"
-        , "keytype", "label", "lang", "list", "loop", "low", "manifest", "max"
-        , "maxlength", "media", "method", "min", "multiple", "name"
-        , "novalidate", "onbeforeonload", "onbeforeprint", "onblur", "oncanplay"
-        , "oncanplaythrough", "onchange", "oncontextmenu", "onclick"
-        , "ondblclick", "ondrag", "ondragend", "ondragenter", "ondragleave"
-        , "ondragover", "ondragstart", "ondrop", "ondurationchange", "onemptied"
-        , "onended", "onerror", "onfocus", "onformchange", "onforminput"
-        , "onhaschange", "oninput", "oninvalid", "onkeydown", "onkeyup"
-        , "onload", "onloadeddata", "onloadedmetadata", "onloadstart"
-        , "onmessage", "onmousedown", "onmousemove", "onmouseout", "onmouseover"
-        , "onmouseup", "onmousewheel", "ononline", "onpagehide", "onpageshow"
-        , "onpause", "onplay", "onplaying", "onprogress", "onpropstate"
-        , "onratechange", "onreadystatechange", "onredo", "onresize", "onscroll"
-        , "onseeked", "onseeking", "onselect", "onstalled", "onstorage"
-        , "onsubmit", "onsuspend", "ontimeupdate", "onundo", "onunload"
-        , "onvolumechange", "onwaiting", "open", "optimum", "pattern", "ping"
-        , "placeholder", "preload", "pubdate", "radiogroup", "readonly", "rel"
-        , "required", "reversed", "rows", "rowspan", "sandbox", "scope"
-        , "scoped", "seamless", "selected", "shape", "size", "sizes", "span"
-        , "spellcheck", "src", "srcdoc", "start", "step", "style", "subject"
-        , "summary", "tabindex", "target", "title", "type", "usemap", "value"
-        , "width", "wrap", "xmlns"
-        ]
-    , selfClosing = False
-    }
-
--- | A map of HTML variants, per version, lowercase.
---
-htmlVariants :: Map String HtmlVariant
-htmlVariants = M.fromList $ map (show &&& id)
-    [ html4Strict
-    , html4Transitional
-    , html4FrameSet
-    , xhtml1Strict
-    , xhtml1Transitional
-    , xhtml1FrameSet
-    , html5
-    ]
-
-main :: IO ()
-main = mapM_ (writeHtmlVariant . snd) $ M.toList htmlVariants
diff --git a/Util/Sanitize.hs b/Util/Sanitize.hs
deleted file mode 100644
--- a/Util/Sanitize.hs
+++ /dev/null
@@ -1,76 +0,0 @@
--- | A program to sanitize an HTML tag to a Haskell function.
---
-module Util.Sanitize
-    ( sanitize
-    , keywords
-    , prelude
-    ) where
-
-import Data.Char (toLower, toUpper)
-import Data.Set (Set)
-import qualified Data.Set as S
-
--- | Sanitize a tag. This function returns a name that can be used as
--- combinator in haskell source code.
---
--- Examples:
---
--- > sanitize "class" == "class_"
--- > sanitize "http-equiv" == "httpEquiv"
---
-sanitize :: String -> String
-sanitize = appendUnderscore . removeDash . map toLower
-  where
-    -- Remove a dash, replacing it by camelcase notation
-    --
-    -- Example:
-    --
-    -- > removeDash "foo-bar" == "fooBar"
-    --
-    removeDash ('-' : x : xs) = toUpper x : removeDash xs
-    removeDash (x : xs) = x : removeDash xs
-    removeDash [] = []
-
-    appendUnderscore t | t `S.member` keywords = t ++ "_"
-                       | otherwise             = t
-
--- | A set of standard Haskell keywords, which cannot be used as combinators.
---
-keywords :: Set String
-keywords = S.fromList
-    [ "case", "class", "data", "default", "deriving", "do", "else", "if"
-    , "import", "in", "infix", "infixl", "infixr", "instance" , "let", "module"
-    , "newtype", "of", "then", "type", "where"
-    ]
-
--- | Set of functions from the Prelude, which we do not use as combinators.
---
-prelude :: Set String
-prelude = S.fromList
-    [ "abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf"
-    , "asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling"
-    , "compare", "concat", "concatMap", "const", "cos", "cosh", "curry", "cycle"
-    , "decodeFloat", "div", "divMod", "drop", "dropWhile", "either", "elem"
-    , "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo", "enumFromTo"
-    , "error", "even", "exp", "exponent", "fail", "filter", "flip"
-    , "floatDigits", "floatRadix", "floatRange", "floor", "fmap", "foldl"
-    , "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger", "fromIntegral"
-    , "fromRational", "fst", "gcd", "getChar", "getContents", "getLine", "head"
-    , "id", "init", "interact", "ioError", "isDenormalized", "isIEEE"
-    , "isInfinite", "isNaN", "isNegativeZero", "iterate", "last", "lcm"
-    , "length", "lex", "lines", "log", "logBase", "lookup", "map", "mapM"
-    , "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound"
-    , "minimum", "mod", "negate", "not", "notElem", "null", "odd", "or"
-    , "otherwise", "pi", "pred", "print", "product", "properFraction", "putChar"
-    , "putStr", "putStrLn", "quot", "quotRem", "read", "readFile", "readIO"
-    , "readList", "readLn", "readParen", "reads", "readsPrec", "realToFrac"
-    , "recip", "rem", "repeat", "replicate", "return", "reverse", "round"
-    , "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq", "sequence"
-    , "sequence_", "show", "showChar", "showList", "showParen", "showString"
-    , "shows", "showsPrec", "significand", "signum", "sin", "sinh", "snd"
-    , "span", "splitAt", "sqrt", "subtract", "succ", "sum", "tail", "take"
-    , "takeWhile", "tan", "tanh", "toEnum", "toInteger", "toRational"
-    , "truncate", "uncurry", "undefined", "unlines", "until", "unwords", "unzip"
-    , "unzip3", "userError", "words", "writeFile", "zip", "zip3", "zipWith"
-    , "zipWith3"
-    ]
diff --git a/blaze-from-html.cabal b/blaze-from-html.cabal
--- a/blaze-from-html.cabal
+++ b/blaze-from-html.cabal
@@ -1,5 +1,5 @@
 Name:          blaze-from-html
-Version:       0.3.2.0
+Version:       0.3.2.1
 Synopsis:      Tool to convert HTML to BlazeHtml code.
 Description:   Tool that converts HTML files to Haskell code, ready to be
                used with the BlazeHtml library.
@@ -15,8 +15,9 @@
 Cabal-version: >= 1.6
 
 Executable blaze-from-html
-  Ghc-Options: -Wall
-  Main-Is:     Util/BlazeFromHtml.hs
+  Ghc-Options:    -Wall
+  Hs-source-dirs: src
+  Main-Is:        Util/BlazeFromHtml.hs
 
   Other-Modules:
     Util.GenerateHtmlCombinators
diff --git a/src/Util/BlazeFromHtml.hs b/src/Util/BlazeFromHtml.hs
new file mode 100644
--- /dev/null
+++ b/src/Util/BlazeFromHtml.hs
@@ -0,0 +1,327 @@
+-- | A module for conversion from HTML to BlazeHtml Haskell code.
+--
+module Main where
+
+import Control.Monad (forM_, when)
+import Control.Applicative ((<$>))
+import Data.List (stripPrefix)
+import Data.Maybe (listToMaybe, fromMaybe)
+import Data.Char (toLower, isSpace)
+import Control.Arrow (first)
+import System.Environment (getArgs)
+import System.FilePath (dropExtension)
+import qualified Data.Map as M
+import System.Console.GetOpt
+
+import Text.HTML.TagSoup
+
+import Util.Sanitize (sanitize)
+import Util.GenerateHtmlCombinators hiding (main)
+
+-- | Simple type to represent attributes.
+--
+type Attributes = [(String, String)]
+
+-- | Intermediate tree representation. This representation contains several
+-- constructors aimed at pretty-printing.
+--
+data Html = Parent String Attributes Html
+          | Block [Html]
+          | Text String
+          | Comment String
+          | Doctype
+          deriving (Show)
+
+-- | Different combinator types.
+--
+data CombinatorType = ParentCombinator
+                    | LeafCombinator
+                    | UnknownCombinator
+                    deriving (Eq, Show)
+
+-- | Traverse the list of tags to produce an intermediate representation of the
+-- HTML tree.
+--
+makeTree :: HtmlVariant           -- ^ HTML variant used
+         -> Bool                  -- ^ Should ignore errors
+         -> [String]              -- ^ Stack of open tags
+         -> [Tag String]          -- ^ Tags to parse
+         -> (Html, [Tag String])  -- ^ (Result, unparsed part)
+makeTree _ ignore stack []
+    | null stack || ignore = (Block [], [])
+    | otherwise = error $ "Error: tags left open at the end: " ++ show stack
+makeTree variant ignore stack (TagPosition row _ : x : xs) = case x of
+    TagOpen tag attrs -> if toLower' tag == "!doctype"
+        then addHtml Doctype xs
+        else let tag' = toLower' tag
+                 (inner, t) = case combinatorType variant tag' of
+                    LeafCombinator -> (Block [], xs)
+                    _ -> makeTree variant ignore (tag' : stack) xs
+                 p = Parent tag' (map (first toLower') attrs) inner
+             in addHtml p t
+    -- The closing tag must match the stack. If it is a closing leaf, we can
+    -- ignore it
+    TagClose tag ->
+        let isLeafCombinator = combinatorType variant tag == LeafCombinator
+            matchesStack = listToMaybe stack == Just (toLower' tag)
+        in case (isLeafCombinator, matchesStack, ignore) of
+            -- It's a leaf combinator, don't care about this element
+            (True, _, _)          -> makeTree variant ignore stack xs
+            -- It's a parent and the stack doesn't match
+            (False, False, False) -> error $
+                "Line " ++ show row ++ ": " ++ show tag ++ " closed but "
+                        ++ show stack ++ " should be closed instead."
+            -- Stack might not match but we ignore it anyway
+            (False, _, _)         -> (Block [], xs)
+    TagText text -> addHtml (Text text) xs
+    TagComment comment -> addHtml (Comment comment) xs
+    _ -> makeTree variant ignore stack xs
+  where
+    addHtml html xs' = let (Block l, r) = makeTree variant ignore stack xs'
+                       in (Block (html : l), r)
+
+    toLower' = map toLower
+makeTree _ _ _ _ = error "TagSoup error"
+
+-- | Remove empty text from the HTML.
+--
+removeEmptyText :: Html -> Html
+removeEmptyText (Block b) = Block $ map removeEmptyText $ flip filter b $ \h ->
+    case h of Text text -> any (not . isSpace) text
+              _         -> True
+removeEmptyText (Parent tag attrs inner) =
+    Parent tag attrs $ removeEmptyText inner
+removeEmptyText x = x
+
+-- | Try to eliminiate Block constructors as much as possible.
+--
+minimizeBlocks :: Html -> Html
+minimizeBlocks (Parent t a (Block [x])) = minimizeBlocks $ Parent t a x
+minimizeBlocks (Parent t a x) = Parent t a $ minimizeBlocks x
+minimizeBlocks (Block x) = Block $ map minimizeBlocks x
+minimizeBlocks x = x
+
+-- | Get the type of a combinator, using a given variant.
+--
+combinatorType :: HtmlVariant -> String -> CombinatorType
+combinatorType variant combinator
+    | combinator == "docTypeHtml" = ParentCombinator
+    | combinator `elem` parents variant = ParentCombinator
+    | combinator `elem` leafs variant = LeafCombinator
+    | otherwise = UnknownCombinator
+
+-- | Create a special @<html>@ parent that includes the docype.
+--
+joinHtmlDoctype :: Html -> Html
+joinHtmlDoctype (Block (Doctype : Parent "html" attrs inner : xs)) =
+    Block $ Parent "docTypeHtml" attrs inner : xs
+joinHtmlDoctype x = x
+
+-- | Produce the Blaze code from the HTML. The result is a list of lines.
+--
+fromHtml :: HtmlVariant  -- ^ Used HTML variant
+         -> Bool         -- ^ Should ignore errors
+         -> Html         -- ^ HTML tree
+         -> [String]     -- ^ Resulting lines of code
+fromHtml _ _ Doctype = ["docType"]
+fromHtml _ _ (Text text) = ["\"" ++ concatMap escape (trim text) ++ "\""]
+  where
+    -- Remove whitespace on both ends of a string
+    trim = reverse . dropWhile isSpace . reverse . dropWhile isSpace
+    -- Escape a number of characters
+    escape '"'  = "\\\""
+    escape '\n' = "\\n"
+    escape x    = [x]
+fromHtml _ _ (Comment comment) = map ("-- " ++) $ lines comment
+fromHtml variant ignore (Block block) =
+    concatMap (fromHtml variant ignore) block
+fromHtml variant ignore (Parent tag attrs inner) =
+    case combinatorType variant tag of
+        -- Actual parent tags
+        ParentCombinator -> case inner of
+            (Block ls) -> if null ls
+                then [combinator ++
+                        (if null attrs then " " else " $ ") ++ "mempty"]
+                else (combinator ++ " $ do") :
+                        indent (fromHtml variant ignore inner)
+            -- We join non-block parents for better readability.
+            x -> let ls = fromHtml variant ignore x
+                     apply = if dropApply x then " " else " $ "
+                 in case ls of (y : ys) -> (combinator ++ apply ++ y) : ys
+                               [] -> [combinator]
+
+        -- Leaf tags
+        LeafCombinator -> [combinator]
+
+        -- Unknown tag
+        UnknownCombinator -> if ignore
+            then fromHtml variant ignore inner
+            else error $ "Tag " ++ tag ++ " is illegal in "
+                                       ++ show variant
+  where
+    combinator = qualifiedSanitize "H." tag ++ attributes'
+    attributes' = attrs >>= \(k, v) -> case k `elem` attributes variant of
+        True  -> " ! " ++ qualifiedSanitize "A." k ++ " " ++ show v
+        False -> case stripPrefix "data-" k of
+            Just prefix -> " ! "
+                        ++ "dataAttribute" ++ " "
+                        ++ show prefix
+                        ++ " " ++ show v
+            Nothing | ignore     -> ""
+                    | otherwise  -> error $ "Attribute "
+                                 ++ k ++ " is illegal in "
+                                 ++ show variant
+
+    -- Qualifies a tag with the given qualifier if needed, and sanitizes it.
+    qualifiedSanitize qualifier tag' =
+        (if isNameClash variant tag' then qualifier else "") ++ sanitize tag'
+
+    -- Check if we can drop the apply operator ($), for readability reasons.
+    -- This would change:
+    --
+    -- > p $ "Some text"
+    --
+    -- Into
+    --
+    -- > p "Some text"
+    --
+    dropApply (Parent _ _ _) = False
+    dropApply (Block _) = False
+    dropApply _ = null attrs
+
+-- | Produce the code needed for initial imports.
+--
+getImports :: HtmlVariant -> [String]
+getImports variant =
+    [ "{-# LANGUAGE OverloadedStrings #-}"
+    , ""
+    , import_ "Prelude"
+    , qualify "Prelude" "P"
+    , import_ "Data.Monoid (mempty)"
+    , ""
+    , import_ h
+    , qualify h "H"
+    , import_ a
+    , qualify a "A"
+    ]
+  where
+    import_ = ("import " ++)
+    qualify name short = "import qualified " ++ name ++ " as " ++ short
+    h = getModuleName variant
+    a = getAttributeModuleName variant
+
+-- | Convert the HTML to blaze code.
+--
+blazeFromHtml :: HtmlVariant  -- ^ Variant to use
+              -> Bool         -- ^ Produce standalone code
+              -> Bool         -- ^ Should we ignore errors
+              -> String       -- ^ Template name
+              -> String       -- ^ HTML code
+              -> String       -- ^ Resulting code
+blazeFromHtml variant standalone ignore name =
+    unlines . addSignature . fromHtml variant ignore
+            . joinHtmlDoctype . minimizeBlocks
+            . removeEmptyText . fst . makeTree variant ignore []
+            . parseTagsOptions parseOptions { optTagPosition = True }
+  where
+    addSignature body = if standalone then [ name ++ " :: Html"
+                                           , name ++ " = do"
+                                           ] ++ indent body
+                                      else body
+
+-- | Indent block of code.
+--
+indent :: [String] -> [String]
+indent = map ("    " ++)
+
+-- | Main function
+--
+main :: IO ()
+main = do
+    args <- getOpt Permute options <$> getArgs
+    case args of
+        (o, n, []) -> let v = getVariant o
+                          s = standalone' o
+                          i = ignore' o
+                      in do imports' v o
+                            main' v s i n
+        (_, _, _)  -> putStr help
+  where
+    -- No files given, work with stdin
+    main' variant standalone ignore [] = interact $
+        blazeFromHtml variant standalone ignore "template"
+
+    -- Handle all files
+    main' variant standalone ignore files = forM_ files $ \file -> do
+        body <- readFile file
+        putStrLn $ blazeFromHtml variant standalone ignore
+                                 (dropExtension file) body
+
+    -- Print imports if needed
+    imports' variant opts = when (standalone' opts) $
+        putStrLn $ unlines $ getImports variant
+
+    -- Should we produce standalone code?
+    standalone' opts = ArgStandalone `elem` opts
+
+    -- Should we ignore errors?
+    ignore' opts = ArgIgnoreErrors `elem` opts
+
+    -- Get the variant from the options
+    getVariant opts = fromMaybe defaultHtmlVariant $ listToMaybe $
+        flip concatMap opts $ \o -> case o of (ArgHtmlVariant x) -> [x]
+                                              _ -> []
+
+-- | Help information.
+--
+help :: String
+help = unlines $
+    [ "This is a tool to convert HTML code to BlazeHtml code. It is still"
+    , "experimental and the results might need to be edited manually."
+    , ""
+    , "USAGE"
+    , ""
+    , "  blaze-from-html [OPTIONS...] [FILES ...]"
+    , ""
+    , "When no files are given, it works as a filter."
+    , ""
+    , "EXAMPLE"
+    , ""
+    , "  blaze-from-html -v html4-strict index.html"
+    , ""
+    , "This converts the index.html file to Haskell code, writing to stdout."
+    , ""
+    , "OPTIONS"
+    , usageInfo "" options
+    , "VARIANTS"
+    , ""
+    ] ++
+    map (("  " ++) . fst) (M.toList htmlVariants) ++
+    [ ""
+    , "By default, " ++ show defaultHtmlVariant ++ " is used."
+    ]
+
+-- | Options for the CLI program
+--
+data Arg = ArgHtmlVariant HtmlVariant
+         | ArgStandalone
+         | ArgIgnoreErrors
+         deriving (Show, Eq)
+
+-- | A description of the options
+--
+options :: [OptDescr Arg]
+options =
+    [ Option "v" ["html-variant"] htmlVariantOption "HTML variant to use"
+    , Option "s" ["standalone"] (NoArg ArgStandalone) "Produce standalone code"
+    , Option "e" ["ignore-errors"] (NoArg ArgIgnoreErrors) "Ignore most errors"
+    ]
+  where
+    htmlVariantOption = flip ReqArg "VARIANT" $ \name -> ArgHtmlVariant $
+        fromMaybe (error $ "No HTML variant called " ++ name ++ " found.")
+                  (M.lookup name htmlVariants)
+
+-- | The default HTML variant
+--
+defaultHtmlVariant :: HtmlVariant
+defaultHtmlVariant = html5
diff --git a/src/Util/GenerateHtmlCombinators.hs b/src/Util/GenerateHtmlCombinators.hs
new file mode 100644
--- /dev/null
+++ b/src/Util/GenerateHtmlCombinators.hs
@@ -0,0 +1,470 @@
+{-# LANGUAGE CPP #-}
+
+#define DO_NOT_EDIT (doNotEdit __FILE__ __LINE__)
+
+-- | Generates code for HTML tags.
+--
+module Util.GenerateHtmlCombinators where
+
+import Control.Arrow ((&&&))
+import Data.List (sort, sortBy, intersperse, intercalate)
+import Data.Ord (comparing)
+import System.Directory (createDirectoryIfMissing)
+import System.FilePath ((</>), (<.>))
+import Data.Map (Map)
+import qualified Data.Map as M
+import Data.Char (toLower)
+import qualified Data.Set as S
+
+import Util.Sanitize (sanitize, prelude)
+
+-- | Datatype for an HTML variant.
+--
+data HtmlVariant = HtmlVariant
+    { version     :: [String]
+    , docType     :: [String]
+    , parents     :: [String]
+    , leafs       :: [String]
+    , attributes  :: [String]
+    , selfClosing :: Bool
+    } deriving (Eq)
+
+instance Show HtmlVariant where
+    show = map toLower . intercalate "-" . version
+
+-- | Get the full module name for an HTML variant.
+--
+getModuleName :: HtmlVariant -> String
+getModuleName = ("Text.Blaze." ++) . intercalate "." . version
+
+-- | Get the attribute module name for an HTML variant.
+--
+getAttributeModuleName :: HtmlVariant -> String
+getAttributeModuleName = (++ ".Attributes") . getModuleName
+
+-- | Check if a given name causes a name clash.
+--
+isNameClash :: HtmlVariant -> String -> Bool
+isNameClash v t
+    -- Both an element and an attribute
+    | (t `elem` parents v || t `elem` leafs v) && t `elem` attributes v = True
+    -- Already a prelude function
+    | sanitize t `S.member` prelude = True
+    | otherwise = False
+
+-- | Write an HTML variant.
+--
+writeHtmlVariant :: HtmlVariant -> IO ()
+writeHtmlVariant htmlVariant = do
+    -- Make a directory.
+    createDirectoryIfMissing True basePath
+
+    let tags =  zip parents' (repeat makeParent)
+             ++ zip leafs' (repeat (makeLeaf $ selfClosing htmlVariant))
+        sortedTags = sortBy (comparing fst) tags
+        appliedTags = map (\(x, f) -> f x) sortedTags
+
+    -- Write the main module.
+    writeFile' (basePath <.> "hs") $ removeTrailingNewlines $ unlines
+        [ DO_NOT_EDIT
+        , "{-# LANGUAGE OverloadedStrings #-}"
+        , "-- | This module exports HTML combinators used to create documents."
+        , "--"
+        , exportList modulName $ "module Text.Blaze.Html"
+                               : "docType"
+                               : "docTypeHtml"
+                               : map (sanitize . fst) sortedTags
+        , DO_NOT_EDIT
+        , "import Prelude ((>>), (.))"
+        , ""
+        , "import Text.Blaze"
+        , "import Text.Blaze.Internal"
+        , "import Text.Blaze.Html"
+        , ""
+        , makeDocType $ docType htmlVariant
+        , makeDocTypeHtml $ docType htmlVariant
+        , unlines appliedTags
+        ]
+
+    let sortedAttributes = sort attributes'
+
+    -- Write the attribute module.
+    writeFile' (basePath </> "Attributes.hs") $ removeTrailingNewlines $ unlines
+        [ DO_NOT_EDIT
+        , "-- | This module exports combinators that provide you with the"
+        , "-- ability to set attributes on HTML elements."
+        , "--"
+        , "{-# LANGUAGE OverloadedStrings #-}"
+        , exportList attributeModuleName $ map sanitize sortedAttributes
+        , DO_NOT_EDIT
+        , "import Prelude ()"
+        , ""
+        , "import Text.Blaze.Internal (Attribute, AttributeValue, attribute)"
+        , ""
+        , unlines (map makeAttribute sortedAttributes)
+        ]
+  where
+    basePath  = "src" </> "Text" </> "Blaze" </> foldl1 (</>) version'
+    modulName = getModuleName htmlVariant
+    attributeModuleName = getAttributeModuleName htmlVariant
+    attributes' = attributes htmlVariant
+    parents'    = parents htmlVariant
+    leafs'      = leafs htmlVariant
+    version'    = version htmlVariant
+    removeTrailingNewlines = reverse . drop 2 . reverse
+    writeFile' file content = do
+        putStrLn ("Generating " ++ file)
+        writeFile file content
+
+-- | Create a string, consisting of @x@ spaces, where @x@ is the length of the
+-- argument.
+--
+spaces :: String -> String
+spaces = flip replicate ' ' . length
+
+-- | Join blocks of code with a newline in between.
+--
+unblocks :: [String] -> String
+unblocks = unlines . intersperse "\n"
+
+-- | A warning to not edit the generated code.
+--
+doNotEdit :: FilePath -> Int -> String
+doNotEdit fileName lineNumber = init $ unlines
+    [ "-- WARNING: The next block of code was automatically generated by"
+    , "-- " ++ fileName ++ ":" ++ show lineNumber
+    , "--"
+    ]
+
+-- | Generate an export list for a Haskell module.
+--
+exportList :: String   -- ^ Module name.
+           -> [String] -- ^ List of functions.
+           -> String   -- ^ Resulting string.
+exportList _    []            = error "exportList without functions."
+exportList name (f:functions) = unlines $
+    [ "module " ++ name
+    , "    ( " ++ f
+    ] ++
+    map ("    , " ++) functions ++
+    [ "    ) where"]
+
+-- | Generate a function for a doctype.
+--
+makeDocType :: [String] -> String
+makeDocType lines' = unlines
+    [ DO_NOT_EDIT
+    , "-- | Combinator for the document type. This should be placed at the top"
+    , "-- of every HTML page."
+    , "--"
+    , "-- Example:"
+    , "--"
+    , "-- > docType"
+    , "--"
+    , "-- Result:"
+    , "--"
+    , unlines (map ("-- > " ++) lines') ++ "--"
+    , "docType :: Html  -- ^ The document type HTML."
+    , "docType = preEscapedText " ++ show (unlines lines')
+    , "{-# INLINE docType #-}"
+    ]
+
+-- | Generate a function for the HTML tag (including the doctype).
+--
+makeDocTypeHtml :: [String]  -- ^ The doctype.
+                -> String    -- ^ Resulting combinator function.
+makeDocTypeHtml lines' = unlines
+    [ DO_NOT_EDIT
+    , "-- | Combinator for the @\\<html>@ element. This combinator will also"
+    , "-- insert the correct doctype."
+    , "--"
+    , "-- Example:"
+    , "--"
+    , "-- > docTypeHtml $ span $ text \"foo\""
+    , "--"
+    , "-- Result:"
+    , "--"
+    , unlines (map ("-- > " ++) lines') ++ "-- > <html><span>foo</span></html>"
+    , "--"
+    , "docTypeHtml :: Html  -- ^ Inner HTML."
+    , "            -> Html  -- ^ Resulting HTML."
+    , "docTypeHtml inner = docType >> html inner"
+    , "{-# INLINE docTypeHtml #-}"
+    ]
+
+-- | Generate a function for an HTML tag that can be a parent.
+--
+makeParent :: String -> String
+makeParent tag = unlines
+    [ DO_NOT_EDIT
+    , "-- | Combinator for the @\\<" ++ tag ++ ">@ element."
+    , "--"
+    , "-- Example:"
+    , "--"
+    , "-- > " ++ function ++ " $ span $ text \"foo\""
+    , "--"
+    , "-- Result:"
+    , "--"
+    , "-- > <" ++ tag ++ "><span>foo</span></" ++ tag ++ ">"
+    , "--"
+    , function        ++ " :: Html  -- ^ Inner HTML."
+    , spaces function ++ " -> Html  -- ^ Resulting HTML."
+    , function        ++ " = Parent \"" ++ tag ++ "\" \"<" ++ tag
+                      ++ "\" \"</" ++ tag ++ ">\"" ++ modifier
+    , "{-# INLINE " ++ function ++ " #-}"
+    ]
+  where
+    function = sanitize tag
+    modifier = if tag `elem` ["style", "script"] then " . external" else ""
+
+-- | Generate a function for an HTML tag that must be a leaf.
+--
+makeLeaf :: Bool    -- ^ Make leaf tags self-closing
+         -> String  -- ^ Tag for the combinator
+         -> String  -- ^ Combinator code
+makeLeaf closing tag = unlines
+    [ DO_NOT_EDIT
+    , "-- | Combinator for the @\\<" ++ tag ++ " />@ element."
+    , "--"
+    , "-- Example:"
+    , "--"
+    , "-- > " ++ function
+    , "--"
+    , "-- Result:"
+    , "--"
+    , "-- > <" ++ tag ++ " />"
+    , "--"
+    , function ++ " :: Html  -- ^ Resulting HTML."
+    , function ++ " = Leaf \"" ++ tag ++ "\" \"<" ++ tag ++ "\" " ++ "\""
+               ++ (if closing then " /" else "") ++ ">\""
+    , "{-# INLINE " ++ function ++ " #-}"
+    ]
+  where
+    function = sanitize tag
+
+-- | Generate a function for an HTML attribute.
+--
+makeAttribute :: String -> String
+makeAttribute name = unlines
+    [ DO_NOT_EDIT
+    , "-- | Combinator for the @" ++ name ++ "@ attribute."
+    , "--"
+    , "-- Example:"
+    , "--"
+    , "-- > div ! " ++ function ++ " \"bar\" $ \"Hello.\""
+    , "--"
+    , "-- Result:"
+    , "--"
+    , "-- > <div " ++ name ++ "=\"bar\">Hello.</div>"
+    , "--"
+    , function        ++ " :: AttributeValue  -- ^ Attribute value."
+    , spaces function ++ " -> Attribute       -- ^ Resulting attribute."
+    , function        ++ " = attribute \"" ++ name ++ "\" \" "
+                      ++ name ++ "=\\\"\""
+    , "{-# INLINE " ++ function ++ " #-}"
+    ]
+  where
+    function = sanitize name
+
+-- | HTML 4.01 Strict.
+-- A good reference can be found here: http://www.w3schools.com/tags/default.asp
+--
+html4Strict :: HtmlVariant
+html4Strict = HtmlVariant
+    { version = ["Html4", "Strict"]
+    , docType =
+        [ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""
+        , "    \"http://www.w3.org/TR/html4/strict.dtd\">"
+        ]
+    , parents =
+        [ "a", "abbr", "acronym", "address", "b", "bdo", "big", "blockquote"
+        , "body" , "button", "caption", "cite", "code", "colgroup", "dd", "del"
+        , "dfn", "div" , "dl", "dt", "em", "fieldset", "form", "h1", "h2", "h3"
+        , "h4", "h5", "h6", "head", "html", "i", "ins" , "kbd", "label"
+        , "legend", "li", "map", "noscript", "object", "ol", "optgroup"
+        , "option", "p", "pre", "q", "samp", "script", "select", "small"
+        , "span", "strong", "style", "sub", "sup", "table", "tbody", "td"
+        , "textarea", "tfoot", "th", "thead", "title", "tr", "tt", "ul", "var"
+        ]
+    , leafs =
+        [ "area", "br", "col", "hr", "link", "img", "input",  "meta", "param"
+        ]
+    , attributes =
+        [ "abbr", "accept", "accesskey", "action", "align", "alt", "archive"
+        , "axis", "border", "cellpadding", "cellspacing", "char", "charoff"
+        , "charset", "checked", "cite", "class", "classid", "codebase"
+        , "codetype", "cols", "colspan", "content", "coords", "data", "datetime"
+        , "declare", "defer", "dir", "disabled", "enctype", "for", "frame"
+        , "headers", "height", "href", "hreflang", "http-equiv", "id", "label"
+        , "lang", "maxlength", "media", "method", "multiple", "name", "nohref"
+        , "onabort", "onblur", "onchange", "onclick", "ondblclick", "onfocus"
+        , "onkeydown", "onkeypress", "onkeyup", "onload", "onmousedown"
+        , "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onreset"
+        , "onselect", "onsubmit", "onunload", "profile", "readonly", "rel"
+        , "rev", "rows", "rowspan", "rules", "scheme", "scope", "selected"
+        , "shape", "size", "span", "src", "standby", "style", "summary"
+        , "tabindex", "title", "type", "usemap", "valign", "value", "valuetype"
+        , "width"
+        ]
+    , selfClosing = False
+    }
+
+-- | HTML 4.0 Transitional
+--
+html4Transitional :: HtmlVariant
+html4Transitional = HtmlVariant
+    { version = ["Html4", "Transitional"]
+    , docType =
+        [ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\""
+        , "    \"http://www.w3.org/TR/html4/loose.dtd\">"
+        ]
+    , parents = parents html4Strict ++
+        [ "applet", "center", "dir", "font", "iframe", "isindex", "menu"
+        , "noframes", "s", "u"
+        ]
+    , leafs = leafs html4Strict ++ ["basefont"]
+    , attributes = attributes html4Strict ++
+        [ "background", "bgcolor", "clear", "compact", "hspace", "language"
+        , "noshade", "nowrap", "start", "target", "vspace"
+        ]
+    , selfClosing = False
+    }
+
+-- | HTML 4.0 FrameSet
+--
+html4FrameSet :: HtmlVariant
+html4FrameSet = HtmlVariant
+    { version = ["Html4", "FrameSet"]
+    , docType =
+        [ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 FrameSet//EN\""
+        , "    \"http://www.w3.org/TR/html4/frameset.dtd\">"
+        ]
+    , parents = parents html4Transitional ++ ["frameset"]
+    , leafs = leafs html4Transitional ++ ["frame"]
+    , attributes = attributes html4Transitional ++
+        [ "frameborder", "scrolling"
+        ]
+    , selfClosing = False
+    }
+
+-- | XHTML 1.0 Strict
+--
+xhtml1Strict :: HtmlVariant
+xhtml1Strict = HtmlVariant
+    { version = ["XHtml1", "Strict"]
+    , docType =
+        [ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""
+        , "    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
+        ]
+    , parents = parents html4Strict
+    , leafs = leafs html4Strict
+    , attributes = attributes html4Strict
+    , selfClosing = True
+    }
+
+-- | XHTML 1.0 Transitional
+--
+xhtml1Transitional :: HtmlVariant
+xhtml1Transitional = HtmlVariant
+    { version = ["XHtml1", "Transitional"]
+    , docType =
+        [ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\""
+        , "    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
+        ]
+    , parents = parents html4Transitional
+    , leafs = leafs html4Transitional
+    , attributes = attributes html4Transitional
+    , selfClosing = True
+    }
+
+-- | XHTML 1.0 FrameSet
+--
+xhtml1FrameSet :: HtmlVariant
+xhtml1FrameSet = HtmlVariant
+    { version = ["XHtml1", "FrameSet"]
+    , docType =
+        [ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 FrameSet//EN\""
+        , "    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">"
+        ]
+    , parents = parents html4FrameSet
+    , leafs = leafs html4FrameSet
+    , attributes = attributes html4FrameSet
+    , selfClosing = True
+    }
+
+-- | HTML 5.0
+-- A good reference can be found here:
+-- http://www.w3schools.com/html5/html5_reference.asp
+--
+html5 :: HtmlVariant
+html5 = HtmlVariant
+    { version = ["Html5"]
+    , docType = ["<!DOCTYPE HTML>"]
+    , parents =
+        [ "a", "abbr", "address", "article", "aside", "audio", "b", "base"
+        , "bdo", "blockquote", "body", "button", "canvas", "caption", "cite"
+        , "code", "colgroup", "command", "datalist", "dd", "del", "details"
+        , "dfn", "div", "dl", "dt", "em", "fieldset", "figcaption", "figure"
+        , "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header"
+        , "hgroup", "html", "i", "iframe", "ins", "keygen", "kbd", "label"
+        , "legend", "li", "map", "mark", "menu", "meter", "nav", "noscript"
+        , "object", "ol", "optgroup", "option", "output", "p", "pre", "progress"
+        , "q", "rp", "rt", "ruby", "samp", "script", "section", "select"
+        , "small", "source", "span", "strong", "style", "sub", "summary", "sup"
+        , "table", "tbody", "td", "textarea", "tfoot", "th", "thead", "time"
+        , "title", "tr", "ul", "var", "video"
+        ]
+    , leafs =
+        [ "area", "br", "col", "embed", "hr", "img", "input", "meta", "link"
+        , "param"
+        ]
+    , attributes =
+        [ "accept", "accept-charset", "accesskey", "action", "alt", "async"
+        , "autocomplete", "autofocus", "autoplay", "challenge", "charset"
+        , "checked", "cite", "class", "cols", "colspan", "content"
+        , "contenteditable", "contextmenu", "controls", "coords", "data"
+        , "datetime", "defer", "dir", "disabled", "draggable", "enctype", "for"
+        , "form", "formaction", "formenctype", "formmethod", "formnovalidate"
+        , "formtarget", "headers", "height", "hidden", "high", "href"
+        , "hreflang", "http-equiv", "icon", "id", "ismap", "item", "itemprop"
+        , "keytype", "label", "lang", "list", "loop", "low", "manifest", "max"
+        , "maxlength", "media", "method", "min", "multiple", "name"
+        , "novalidate", "onbeforeonload", "onbeforeprint", "onblur", "oncanplay"
+        , "oncanplaythrough", "onchange", "oncontextmenu", "onclick"
+        , "ondblclick", "ondrag", "ondragend", "ondragenter", "ondragleave"
+        , "ondragover", "ondragstart", "ondrop", "ondurationchange", "onemptied"
+        , "onended", "onerror", "onfocus", "onformchange", "onforminput"
+        , "onhaschange", "oninput", "oninvalid", "onkeydown", "onkeyup"
+        , "onload", "onloadeddata", "onloadedmetadata", "onloadstart"
+        , "onmessage", "onmousedown", "onmousemove", "onmouseout", "onmouseover"
+        , "onmouseup", "onmousewheel", "ononline", "onpagehide", "onpageshow"
+        , "onpause", "onplay", "onplaying", "onprogress", "onpropstate"
+        , "onratechange", "onreadystatechange", "onredo", "onresize", "onscroll"
+        , "onseeked", "onseeking", "onselect", "onstalled", "onstorage"
+        , "onsubmit", "onsuspend", "ontimeupdate", "onundo", "onunload"
+        , "onvolumechange", "onwaiting", "open", "optimum", "pattern", "ping"
+        , "placeholder", "preload", "pubdate", "radiogroup", "readonly", "rel"
+        , "required", "reversed", "rows", "rowspan", "sandbox", "scope"
+        , "scoped", "seamless", "selected", "shape", "size", "sizes", "span"
+        , "spellcheck", "src", "srcdoc", "start", "step", "style", "subject"
+        , "summary", "tabindex", "target", "title", "type", "usemap", "value"
+        , "width", "wrap", "xmlns"
+        ]
+    , selfClosing = False
+    }
+
+-- | A map of HTML variants, per version, lowercase.
+--
+htmlVariants :: Map String HtmlVariant
+htmlVariants = M.fromList $ map (show &&& id)
+    [ html4Strict
+    , html4Transitional
+    , html4FrameSet
+    , xhtml1Strict
+    , xhtml1Transitional
+    , xhtml1FrameSet
+    , html5
+    ]
+
+main :: IO ()
+main = mapM_ (writeHtmlVariant . snd) $ M.toList htmlVariants
diff --git a/src/Util/Sanitize.hs b/src/Util/Sanitize.hs
new file mode 100644
--- /dev/null
+++ b/src/Util/Sanitize.hs
@@ -0,0 +1,80 @@
+-- | A program to sanitize an HTML tag to a Haskell function.
+--
+module Util.Sanitize
+    ( sanitize
+    , keywords
+    , prelude
+    ) where
+
+import Data.Char (toLower, toUpper)
+import Data.Set (Set)
+import qualified Data.Set as S
+
+-- | Sanitize a tag. This function returns a name that can be used as
+-- combinator in haskell source code.
+--
+-- Examples:
+--
+-- > sanitize "class" == "class_"
+-- > sanitize "http-equiv" == "httpEquiv"
+--
+sanitize :: String -> String
+sanitize str
+    | lower  == "doctypehtml" = "docTypeHtml"
+    | otherwise               = appendUnderscore $ removeDash lower
+  where
+    lower = map toLower str
+
+    -- Remove a dash, replacing it by camelcase notation
+    --
+    -- Example:
+    --
+    -- > removeDash "foo-bar" == "fooBar"
+    --
+    removeDash ('-' : x : xs) = toUpper x : removeDash xs
+    removeDash (x : xs) = x : removeDash xs
+    removeDash [] = []
+
+    appendUnderscore t | t `S.member` keywords = t ++ "_"
+                       | otherwise             = t
+
+-- | A set of standard Haskell keywords, which cannot be used as combinators.
+--
+keywords :: Set String
+keywords = S.fromList
+    [ "case", "class", "data", "default", "deriving", "do", "else", "if"
+    , "import", "in", "infix", "infixl", "infixr", "instance" , "let", "module"
+    , "newtype", "of", "then", "type", "where"
+    ]
+
+-- | Set of functions from the Prelude, which we do not use as combinators.
+--
+prelude :: Set String
+prelude = S.fromList
+    [ "abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf"
+    , "asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling"
+    , "compare", "concat", "concatMap", "const", "cos", "cosh", "curry", "cycle"
+    , "decodeFloat", "div", "divMod", "drop", "dropWhile", "either", "elem"
+    , "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo", "enumFromTo"
+    , "error", "even", "exp", "exponent", "fail", "filter", "flip"
+    , "floatDigits", "floatRadix", "floatRange", "floor", "fmap", "foldl"
+    , "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger", "fromIntegral"
+    , "fromRational", "fst", "gcd", "getChar", "getContents", "getLine", "head"
+    , "id", "init", "interact", "ioError", "isDenormalized", "isIEEE"
+    , "isInfinite", "isNaN", "isNegativeZero", "iterate", "last", "lcm"
+    , "length", "lex", "lines", "log", "logBase", "lookup", "map", "mapM"
+    , "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound"
+    , "minimum", "mod", "negate", "not", "notElem", "null", "odd", "or"
+    , "otherwise", "pi", "pred", "print", "product", "properFraction", "putChar"
+    , "putStr", "putStrLn", "quot", "quotRem", "read", "readFile", "readIO"
+    , "readList", "readLn", "readParen", "reads", "readsPrec", "realToFrac"
+    , "recip", "rem", "repeat", "replicate", "return", "reverse", "round"
+    , "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq", "sequence"
+    , "sequence_", "show", "showChar", "showList", "showParen", "showString"
+    , "shows", "showsPrec", "significand", "signum", "sin", "sinh", "snd"
+    , "span", "splitAt", "sqrt", "subtract", "succ", "sum", "tail", "take"
+    , "takeWhile", "tan", "tanh", "toEnum", "toInteger", "toRational"
+    , "truncate", "uncurry", "undefined", "unlines", "until", "unwords", "unzip"
+    , "unzip3", "userError", "words", "writeFile", "zip", "zip3", "zipWith"
+    , "zipWith3"
+    ]
