]> git.immae.eu Git - github/fretlink/blazeT.git/commitdiff
Initial
authorJohannes Gerer <oss@johannesgerer.com>
Wed, 26 Oct 2016 00:07:02 +0000 (02:07 +0200)
committerJohannes Gerer <oss@johannesgerer.com>
Wed, 26 Oct 2016 00:07:02 +0000 (02:07 +0200)
47 files changed:
.gitignore [new file with mode: 0644]
.travis.yml [new file with mode: 0644]
LICENSE [new file with mode: 0644]
Makefile [new file with mode: 0644]
README.md [new file with mode: 0644]
Setup.hs [new file with mode: 0644]
blazeT.cabal [new file with mode: 0644]
src/BackwardsCompatibilty.hs [new file with mode: 0644]
src/Benchmarks/BenchmarkUtils.hs [new file with mode: 0644]
src/Benchmarks/BlazeTBenchmarks.hs [new file with mode: 0644]
src/Benchmarks/HtmlBenchmarks.hs [new file with mode: 0644]
src/Benchmarks/LICENSE [new file with mode: 0644]
src/Benchmarks/RunHtmlBenchmarks.hs [new file with mode: 0644]
src/Benchmarks/ServerChunkSize.hs [new file with mode: 0644]
src/Benchmarks/bigtable/erb.rb [new file with mode: 0644]
src/Benchmarks/bigtable/erubis.rb [new file with mode: 0644]
src/Benchmarks/bigtable/hamlet.hs [new file with mode: 0644]
src/Benchmarks/bigtable/html-minimalist.hs [new file with mode: 0644]
src/Benchmarks/bigtable/html.hs [new file with mode: 0644]
src/Benchmarks/bigtable/php.php [new file with mode: 0644]
src/Benchmarks/bigtable/xhtml.hs [new file with mode: 0644]
src/Text/BlazeT.hs [new file with mode: 0644]
src/Text/BlazeT/Html.hs [new file with mode: 0644]
src/Text/BlazeT/Html4/FrameSet.hs [new file with mode: 0644]
src/Text/BlazeT/Html4/FrameSet/Attributes.hs [new file with mode: 0644]
src/Text/BlazeT/Html4/Strict.hs [new file with mode: 0644]
src/Text/BlazeT/Html4/Strict/Attributes.hs [new file with mode: 0644]
src/Text/BlazeT/Html4/Transitional.hs [new file with mode: 0644]
src/Text/BlazeT/Html4/Transitional/Attributes.hs [new file with mode: 0644]
src/Text/BlazeT/Html5.hs [new file with mode: 0644]
src/Text/BlazeT/Html5/Attributes.hs [new file with mode: 0644]
src/Text/BlazeT/Internal.hs [new file with mode: 0644]
src/Text/BlazeT/Renderer/Pretty.hs [new file with mode: 0644]
src/Text/BlazeT/Renderer/String.hs [new file with mode: 0644]
src/Text/BlazeT/Renderer/Text.hs [new file with mode: 0644]
src/Text/BlazeT/Renderer/Utf8.hs [new file with mode: 0644]
src/Text/BlazeT/XHtml1/FrameSet.hs [new file with mode: 0644]
src/Text/BlazeT/XHtml1/FrameSet/Attributes.hs [new file with mode: 0644]
src/Text/BlazeT/XHtml1/Strict.hs [new file with mode: 0644]
src/Text/BlazeT/XHtml1/Strict/Attributes.hs [new file with mode: 0644]
src/Text/BlazeT/XHtml1/Transitional.hs [new file with mode: 0644]
src/Text/BlazeT/XHtml1/Transitional/Attributes.hs [new file with mode: 0644]
src/Text/BlazeT/XHtml5.hs [new file with mode: 0644]
src/Text/BlazeT/XHtml5/Attributes.hs [new file with mode: 0644]
src/Util/GenerateHtmlCombinators.hs [new file with mode: 0644]
src/Util/GenerateHtmlTCombinators.hs [new file with mode: 0755]
src/Util/Sanitize.hs [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..da61294
--- /dev/null
@@ -0,0 +1,21 @@
+dist
+dist-*
+cabal-dev
+*.o
+*.hi
+*.chi
+*.chs.h
+*.dyn_o
+*.dyn_hi
+.hpc
+.hsenv
+.cabal-sandbox/
+cabal.sandbox.config
+*.prof
+*.aux
+*.hp
+*.eventlog
+.stack-work/
+cabal.project.local
+report.html
+src/Benchmarks/RunHtmlBenchmarks
diff --git a/.travis.yml b/.travis.yml
new file mode 100644 (file)
index 0000000..fbf2adb
--- /dev/null
@@ -0,0 +1,182 @@
+# from https://docs.haskellstack.org/en/stable/GUIDE/#travis-with-caching
+
+# Use new container infrastructure to enable caching
+sudo: false
+
+# Choose a lightweight base image; we provide our own build tools.
+language: c
+
+# Caching so the next build will be fast too.
+cache:
+  directories:
+  - $HOME/.ghc
+  - $HOME/.cabal
+  - $HOME/.stack
+
+# The different configurations we want to test. We have BUILD=cabal which uses
+# cabal-install, and BUILD=stack which uses Stack. More documentation on each
+# of those below.
+#
+# We set the compiler values here to tell Travis to use a different
+# cache file per set of arguments.
+#
+# If you need to have different apt packages for each combination in the
+# matrix, you can use a line such as:
+#     addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
+matrix:
+  include:
+  # We grab the appropriate GHC and cabal-install versions from hvr's PPA. See:
+  # https://github.com/hvr/multi-ghc-travis
+  #- env: BUILD=cabal GHCVER=7.0.4 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
+  #  compiler: ": #GHC 7.0.4"
+  #  addons: {apt: {packages: [cabal-install-1.16,ghc-7.0.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
+  #- env: BUILD=cabal GHCVER=7.2.2 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
+  #  compiler: ": #GHC 7.2.2"
+  #  addons: {apt: {packages: [cabal-install-1.16,ghc-7.2.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
+  #- env: BUILD=cabal GHCVER=7.4.2 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
+  #  compiler: ": #GHC 7.4.2"
+  #  addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
+  - env: BUILD=cabal GHCVER=7.6.3 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
+    compiler: ": #GHC 7.6.3"
+    addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
+  - env: BUILD=cabal GHCVER=7.8.4 CABALVER=1.18 HAPPYVER=1.19.5 ALEXVER=3.1.7
+    compiler: ": #GHC 7.8.4"
+    addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
+  - env: BUILD=cabal GHCVER=7.10.3 CABALVER=1.22 HAPPYVER=1.19.5 ALEXVER=3.1.7
+    compiler: ": #GHC 7.10.3"
+    addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
+  - env: BUILD=cabal GHCVER=8.0.1 CABALVER=1.24 HAPPYVER=1.19.5 ALEXVER=3.1.7
+    compiler: ": #GHC 8.0.1"
+    addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
+
+  # Build with the newest GHC and cabal-install. This is an accepted failure,
+  # see below.
+  - env: BUILD=cabal GHCVER=head  CABALVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7
+    compiler: ": #GHC HEAD"
+    addons: {apt: {packages: [cabal-install-head,ghc-head,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
+
+  # # The Stack builds. We can pass in arbitrary Stack arguments via the ARGS
+  # # variable, such as using --stack-yaml to point to a different file.
+  # - env: BUILD=stack ARGS=""
+  #   compiler: ": #stack default"
+  #   addons: {apt: {packages: [ghc-7.10.3], sources: [hvr-ghc]}}
+
+  # - env: BUILD=stack ARGS="--resolver lts-2"
+  #   compiler: ": #stack 7.8.4"
+  #   addons: {apt: {packages: [ghc-7.8.4], sources: [hvr-ghc]}}
+
+  # - env: BUILD=stack ARGS="--resolver lts-3"
+  #   compiler: ": #stack 7.10.2"
+  #   addons: {apt: {packages: [ghc-7.10.2], sources: [hvr-ghc]}}
+
+  # - env: BUILD=stack ARGS="--resolver lts-6"
+  #   compiler: ": #stack 7.10.3"
+  #   addons: {apt: {packages: [ghc-7.10.3], sources: [hvr-ghc]}}
+
+  # # Nightly builds are allowed to fail
+  # - env: BUILD=stack ARGS="--resolver nightly"
+  #   compiler: ": #stack nightly"
+  #   addons: {apt: {packages: [libgmp,libgmp-dev]}}
+
+  # # Build on OS X in addition to Linux
+  # - env: BUILD=stack ARGS=""
+  #   compiler: ": #stack default osx"
+  #   os: osx
+
+  # - env: BUILD=stack ARGS="--resolver lts-2"
+  #   compiler: ": #stack 7.8.4 osx"
+  #   os: osx
+
+  # - env: BUILD=stack ARGS="--resolver lts-3"
+  #   compiler: ": #stack 7.10.2 osx"
+  #   os: osx
+
+  # - env: BUILD=stack ARGS="--resolver lts-6"
+  #   compiler: ": #stack 7.10.3 osx"
+  #   os: osx
+
+  # - env: BUILD=stack ARGS="--resolver nightly"
+  #   compiler: ": #stack nightly osx"
+  #   os: osx
+
+  allow_failures:
+  - env: BUILD=cabal GHCVER=head  CABALVER=head HAPPYVER=1.19.5 ALEXVER=3.1.7
+  # - env: BUILD=stack ARGS="--resolver nightly"
+
+before_install:
+# Using compiler above sets CC to an invalid value, so unset it
+- unset CC
+
+# We want to always allow newer versions of packages when building on GHC HEAD
+- CABALARGS=""
+- if [ "x$GHCVER" = "xhead" ]; then CABALARGS=--allow-newer; fi
+
+# Download and unpack the stack executable
+- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$HOME/.local/bin:/opt/alex/$ALEXVER/bin:/opt/happy/$HAPPYVER/bin:$HOME/.cabal/bin:$PATH
+- mkdir -p ~/.local/bin
+- |
+  if [ `uname` = "Darwin" ]
+  then
+    travis_retry curl --insecure -L https://www.stackage.org/stack/osx-x86_64 | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin
+  else
+    travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
+  fi
+
+  # Use the more reliable S3 mirror of Hackage
+  mkdir -p $HOME/.cabal
+  echo 'remote-repo: hackage.haskell.org:http://hackage.fpcomplete.com/' > $HOME/.cabal/config
+  echo 'remote-repo-cache: $HOME/.cabal/packages' >> $HOME/.cabal/config
+
+  if [ "$CABALVER" != "1.16" ]
+  then
+    echo 'jobs: $ncpus' >> $HOME/.cabal/config
+  fi
+
+# Get the list of packages from the stack.yaml file
+- PACKAGES=$(stack --install-ghc query locals | grep '^ *path' | sed 's@^ *path:@@')
+
+install:
+- echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
+- if [ -f configure.ac ]; then autoreconf -i; fi
+- |
+  set -ex
+  case "$BUILD" in
+    stack)
+      stack --no-terminal --install-ghc $ARGS test --bench --only-dependencies
+      ;;
+    cabal)
+      cabal --version
+      travis_retry cabal update
+      cabal install --only-dependencies --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES
+      ;;
+  esac
+  set +ex
+
+script:
+- |
+  set -ex
+  case "$BUILD" in
+    stack)
+      stack --no-terminal $ARGS test --bench --no-run-benchmarks --haddock --no-haddock-deps
+      ;;
+    cabal)
+      cabal install --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES
+
+      ORIGDIR=$(pwd)
+      for dir in $PACKAGES
+      do
+        cd $dir
+        cabal check || [ "$CABALVER" == "1.16" ]
+        cabal sdist
+        PKGVER=$(cabal info . | awk '{print $2;exit}')
+        SRC_TGZ=$PKGVER.tar.gz
+        cd dist
+        tar zxfv "$SRC_TGZ"
+        cd "$PKGVER"
+        cabal configure --enable-tests
+        cabal build
+        cd $ORIGDIR
+      done
+      ;;
+  esac
+  set +ex
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..d45d10d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016 Johannes Gerer
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..04b0ff9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,61 @@
+# Copyright Jasper Van der Jeugt 2010
+
+# All rights reserved.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+
+#     * Redistributions in binary form must reproduce the above
+#       copyright notice, this list of conditions and the following
+#       disclaimer in the documentation and/or other materials provided
+#       with the distribution.
+
+#     * Neither the name of Jasper Van der Jeugt nor the names of other
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+################################################################################
+# Configuration
+################################################################################
+
+GHC = cabal exec -- ghc
+GHCI = ghci
+GHC_FLAGS = -O2 -fforce-recomp -ibenchmarks -isrc -itests -fsimpl-tick-factor=200
+
+BENCHMARK_FLAGS = --resamples 10000
+
+################################################################################
+# Benchmarks
+################################################################################
+
+benchmark:
+       $(GHC) $(GHC_FLAGS) --make -main-is Benchmarks.RunHtmlBenchmarks src/Benchmarks/RunHtmlBenchmarks.hs
+       ./src/Benchmarks/RunHtmlBenchmarks $(BENCHMARK_FLAGS) -o report.html
+
+benchmark-bigtable-non-haskell:
+       ruby benchmarks/bigtable/erb.rb
+       ruby benchmarks/bigtable/erubis.rb
+       php -n benchmarks/bigtable/php.php
+
+
+################################################################################
+# generate combinators
+################################################################################
+
+combinators:
+       runghc -isrc Util.GenerateHtmlTCombinators
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..0169fab
--- /dev/null
+++ b/README.md
@@ -0,0 +1,87 @@
+# blazeT [![Build Status](https://travis-ci.org/johannesgerer/blazeT.svg?branch=master)](https://travis-ci.org/johannesgerer/blazeT) [![Hackage](https://img.shields.io/hackage/v/blazeT.svg)](https://hackage.haskell.org/package/blazeT)
+
+A true monad (transformer) version of the
+[blaze-markup](https://hackage.haskell.org/package/blaze-markup) and
+[blaze-html](https://hackage.haskell.org/package/blaze-html)
+libraries.
+
+# Why?
+
+While blaze's `Markup` and `Html` types have `Monad` instances and can
+leverage the the concise `do` notation, they do not satisfy
+the
+[Monad Laws](https://hackage.haskell.org/package/base-4.8.0.0/docs/Control-Monad.html#t:Monad) and
+thus cannot be used as Monads, let alone Monad transformers.
+
+## Use Cases
+
+The `MarkupT` Monad Transformer enables us to write Markup (e.g. HTML)
+templates that have access to all those Monads you cannot live without
+anymore.
+
+Accessing an environment
+([MonadReader](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Reader-Class.html)),
+accumulating log or other diagnostic output
+([MonadWriter](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Writer-Class.html)),
+doing `IO` (like database access) are the first things that come to
+mind.
+
+The initial reason of existence of this library is its use
+in [Lykah](http://johannesgerer.com/Lykah), which powers my personal
+website
+[http://johannesgerer.com](http://johannesgerer.com/johannesgerer.com). In
+Lykah, the HTML templates have access to the whole site structure (to
+build things like menus) and automatically check, insert and keep
+track of referenced pages and assets, which turns out to be very
+useful for the task of static website generation.
+
+# How to use it?
+
+## Backwards compatible
+
+The library is intended to serve as a drop-in replacement for the
+`blaze-markup` and `blaze-html` libraries and should be backwards
+compatible:
+
+Simply replace your `module Text.Blaze.*` imports with `module
+Text.BlazeT.*` and it should give the same results.
+
+For usage of blaze check out
+their [documentation](https://jaspervdj.be/blaze/).
+
+## Unleash the monads
+
+
+
+# Implementation
+
+... is located
+in
+[Text.BlazeT.Internals](https://hackage.haskell.org/package/blazeT/docs/Text-BlazeT-Internals.html).
+
+Everything build around the simple `newtype` definition of the
+`MarkupT` transformer, which makes use of the fact that `Blaze.Markup`
+is
+a
+[Monoid](https://hackage.haskell.org/package/base-4.7.0.2/docs/Data-Monoid.html) and
+which is basically a `WriterT` transformer writing `Blaze.Markup`:
+
+```Haskell
+newtype MarkupT m a = MarkupT { fromMarkupT :: WriterT B.Markup m a }
+```
+
+Wrappers used to lift all `Blaze` entities into `BlazeT` are trivially
+expressible using basic `WriterT` class methods. Wrapping `Blaze.Markup` is simply `WriterT.tell`:
+
+```Haskell
+wrapMarkupT :: Monad m => B.Markup -> MarkupT m ()
+wrapMarkupT = tell
+```
+Wrapping functions that modify `Blaze.Markup` is simply  `WriterT.censor`:
+
+```Haskell
+wrapMarkupT2 :: Monad m => (B.Markup -> B.Markup) -> MarkupT m a -> MarkupT m a
+wrapMarkupT2 = censor
+```
+
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644 (file)
index 0000000..c67c506
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,13 @@
+import Distribution.Simple
+import Distribution.Simple.Setup
+import Distribution.Simple.Haddock
+main = do
+  defaultMainWithHooks simpleUserHooks{
+    haddockHook = \p l h f -> haddockHook simpleUserHooks p l h f{
+        haddockHoogle       = Flag True,
+        haddockHtml         = Flag True,
+        haddockExecutables  = Flag True,
+        haddockHscolour     = Flag True
+        }
+    }
+
diff --git a/blazeT.cabal b/blazeT.cabal
new file mode 100644 (file)
index 0000000..eb3907e
--- /dev/null
@@ -0,0 +1,100 @@
+Name:             blazeT
+Version:          0.0.1
+Homepage:
+Bug-Reports:      http://github.com/johannesgerer/blazeT/issues
+License:          MIT
+License-file:     LICENSE
+Author:           Johannes Gerer
+Maintainer:       Johannes Gerer <oss@johannesgerer.com>
+Homepage:         http://johannesgerer.com/blazeT
+Stability:        Experimental
+Category:         Text, Data, Web
+Synopsis:         A true monad (transformer) version of the blaze-markup and blaze-html libraries
+Tested-with:      GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1
+Description:
+   A true monad (transformer) version of the blaze-markup and blaze-html libraries, implemented as as a very thin wrapper around and strict superset of these libraries.
+   .
+   See <https://github.com/johannesgerer/blazeT Readme> on Github.
+
+
+
+Build-type:    Custom
+Cabal-version: >= 1.8
+
+Extra-source-files:
+  README.md
+  src/Util/GenerateHtmlCombinators.hs
+  src/Util/Sanitize.hs
+  src/Util/GenerateHtmlTCombinators.hs
+
+Custom-setup
+  setup-depends:  base >= 4.0.0.0 && < 5, Cabal
+
+Library
+  -- Default-Language: Haskell2010              
+  Hs-source-dirs: src
+  Ghc-Options:    -Wall
+                  -fsimpl-tick-factor=200
+                  -- -ddump-simpl-stats
+                  -- -ddump-to-file
+  Exposed-modules:
+    Text.BlazeT
+    Text.BlazeT.Internal
+    Text.BlazeT.Html
+    Text.BlazeT.Renderer.Utf8
+    Text.BlazeT.Renderer.String
+    Text.BlazeT.Renderer.Pretty
+    Text.BlazeT.Renderer.Text
+    Text.BlazeT.Html4.FrameSet
+    Text.BlazeT.Html4.Strict
+    Text.BlazeT.Html4.Transitional
+    Text.BlazeT.Html5
+    Text.BlazeT.XHtml1.FrameSet
+    Text.BlazeT.XHtml1.Strict
+    Text.BlazeT.XHtml1.Transitional
+    Text.BlazeT.XHtml5
+    Text.BlazeT.Html4.FrameSet.Attributes
+    Text.BlazeT.Html4.Strict.Attributes
+    Text.BlazeT.Html4.Transitional.Attributes
+    Text.BlazeT.Html5.Attributes
+    Text.BlazeT.XHtml1.FrameSet.Attributes
+    Text.BlazeT.XHtml1.Strict.Attributes
+    Text.BlazeT.XHtml1.Transitional.Attributes
+    Text.BlazeT.XHtml5.Attributes
+
+  Build-depends:
+    base >= 4.0.0.0 && < 5
+    ,blaze-markup >= 0.6.0.0
+    ,blaze-html >= 0.6.0.0
+    ,blaze-builder >= 0.2
+    ,text
+    ,bytestring
+    ,mtl
+    ,transformers
+
+-- Test-suite blaze-markup-tests
+--   Type:           exitcode-stdio-1.0
+--   Hs-source-dirs: src tests
+--   Main-is:        TestSuite.hs
+--   Ghc-options:    -Wall
+
+--   Other-modules:
+--     Text.Blaze.Tests
+--     Text.Blaze.Tests.Util
+
+--   Build-depends:
+--     HUnit                      >= 1.2 && < 1.3,
+--     QuickCheck                 >= 2.4 && < 2.8,
+--     containers                 >= 0.3 && < 0.6,
+--     test-framework             >= 0.4 && < 0.9,
+--     test-framework-hunit       >= 0.3 && < 0.4,
+--     test-framework-quickcheck2 >= 0.3 && < 0.4,
+--     -- Copied from regular dependencies...
+--     base          >= 4    && < 5,
+--     blaze-builder >= 0.2  && < 0.4,
+--     text          >= 0.10 && < 1.2,
+--     bytestring    >= 0.9  && < 0.11
+
+Source-repository head
+  Type:     git
+  Location: http://github.com/johannesgerer/blazeT
\ No newline at end of file
diff --git a/src/BackwardsCompatibilty.hs b/src/BackwardsCompatibilty.hs
new file mode 100644 (file)
index 0000000..a8733ed
--- /dev/null
@@ -0,0 +1,29 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE NoMonomorphismRestriction #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE CPP #-}
+
+import Text.Blaze.Html5.Attributes
+#if 1
+import Text.BlazeT
+import Text.BlazeT.Html5 hiding (main)
+import Text.BlazeT.Renderer.Utf8
+#else
+import Text.Blaze
+import Text.Blaze.Html5 hiding (main)
+import Text.Blaze.Renderer.Utf8
+#endif
+
+main :: IO ()
+main = print $ renderMarkup $ do
+  docType
+  -- "some text" -- does not work
+  html $ do text "some text" -- does not work
+            br
+  ("wow" :: Markup) -- overloaded strings
+  text "asd" ! href "asd"
+  string "string" ! href "asd"
+  toMarkup ("more text" :: String)
+  html "wow"
+  html ! src "asd" $ br
+
diff --git a/src/Benchmarks/BenchmarkUtils.hs b/src/Benchmarks/BenchmarkUtils.hs
new file mode 100644 (file)
index 0000000..4b9546c
--- /dev/null
@@ -0,0 +1,107 @@
+-- | This is a module which contains some ad-hoc HTML combinators for use when
+-- benchmarking
+--
+{-# LANGUAGE OverloadedStrings, NoMonomorphismRestriction #-}
+module Benchmarks.BenchmarkUtils
+    ( Html
+    , toHtml
+
+    , tr
+    , td
+    , html
+    , head
+    , title
+    , body
+    , div
+    , h1
+    , h2
+    , p
+    , ol
+    , li
+    , table
+    , img
+    , id
+    ) where
+
+import Prelude hiding (div, head, id)
+import Text.Blaze
+import Text.Blaze.Internal
+
+type Html = Markup
+
+toHtml :: ToMarkup a => a -> Html
+toHtml = toMarkup
+
+tr :: Html  -- ^ Inner HTML.
+   -> Html  -- ^ Resulting HTML.
+tr = Parent "tr" "<tr" "</tr>"
+{-# INLINE tr #-}
+
+td :: Html  -- ^ Inner HTML.
+   -> Html  -- ^ Resulting HTML.
+td = Parent "td" "<td" "</td>"
+{-# INLINE td #-}
+
+html :: Html  -- ^ Inner HTML.
+     -> Html  -- ^ Resulting HTML.
+html = Parent "html" "<html" "</html>"
+{-# INLINE html #-}
+
+head :: Html  -- ^ Inner HTML.
+     -> Html  -- ^ Resulting HTML.
+head = Parent "head" "<head" "</head>"
+{-# INLINE head #-}
+
+title :: Html  -- ^ Inner HTML.
+      -> Html  -- ^ Resulting HTML.
+title = Parent "title" "<title" "</title>"
+{-# INLINE title #-}
+
+body :: Html  -- ^ Inner HTML.
+     -> Html  -- ^ Resulting HTML.
+body = Parent "body" "<body" "</body>"
+{-# INLINE body #-}
+
+div :: Html  -- ^ Inner HTML.
+    -> Html  -- ^ Resulting HTML.
+div = Parent "div" "<div" "</div>"
+{-# INLINE div #-}
+
+h1 :: Html  -- ^ Inner HTML.
+   -> Html  -- ^ Resulting HTML.
+h1 = Parent "h1" "<h1" "</h1>"
+{-# INLINE h1 #-}
+
+h2 :: Html  -- ^ Inner HTML.
+   -> Html  -- ^ Resulting HTML.
+h2 = Parent "h2" "<h2" "</h2>"
+{-# INLINE h2 #-}
+
+p :: Html  -- ^ Inner HTML.
+  -> Html  -- ^ Resulting HTML.
+p = Parent "p" "<p" "</p>"
+{-# INLINE p #-}
+
+ol :: Html  -- ^ Inner HTML.
+   -> Html  -- ^ Resulting HTML.
+ol = Parent "ol" "<ol" "</ol>"
+{-# INLINE ol #-}
+
+li :: Html  -- ^ Inner HTML.
+   -> Html  -- ^ Resulting HTML.
+li = Parent "li" "<li" "</li>"
+{-# INLINE li #-}
+
+table :: Html  -- ^ Inner HTML.
+      -> Html  -- ^ Resulting HTML.
+table = Parent "table" "<table" "</table>"
+{-# INLINE table #-}
+
+img :: Html  -- ^ Resulting HTML.
+img = Leaf "img" "<img" ">"
+{-# INLINE img #-}
+
+id :: AttributeValue  -- ^ Attribute value.
+   -> Attribute       -- ^ Resulting attribute.
+id = attribute "id" " id=\""
+{-# INLINE id #-}
diff --git a/src/Benchmarks/BlazeTBenchmarks.hs b/src/Benchmarks/BlazeTBenchmarks.hs
new file mode 100644 (file)
index 0000000..83a38ad
--- /dev/null
@@ -0,0 +1,133 @@
+-- | This is a collection of HTML benchmarks for BlazeMarkup.
+--
+{-# LANGUAGE OverloadedStrings, ExistentialQuantification, RankNTypes #-}
+{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
+module Benchmarks.BlazeTBenchmarks where
+
+import           Data.Monoid (Monoid, mempty, mconcat, mappend)
+import           Prelude hiding (div, id,map)
+import qualified Prelude as P
+
+import           Text.BlazeT
+import           Text.BlazeT.Html5
+import qualified Text.BlazeT.Html5 as H
+import qualified Text.BlazeT.Html5.Attributes as A
+
+-- | Description of an HTML benchmark
+--
+data HtmlBenchmark = forall a. HtmlBenchmark
+    String       -- ^ Name.
+    (a -> Html)  -- ^ Rendering function.
+    a            -- ^ Data.
+    Html         -- ^ Longer description.
+
+-- | List containing all benchmarks.
+--
+benchmarks :: [HtmlBenchmark]
+benchmarks =
+    [ HtmlBenchmark "bigTable" bigTable bigTableData $
+        let h = toHtml $ length bigTableData
+            w = toHtml $ length $ P.head bigTableData
+        in (string "Rendering of a big (") >> h >> (string "x") >> w >> ") HTML table"
+    , HtmlBenchmark "basic" basic basicData
+        "A simple, small basic template with a few holes to fill in"
+    , HtmlBenchmark "wideTree" wideTree wideTreeData $
+        (string "A very wide tree (") >> toHtml (length wideTreeData) >> " elements)"
+    , HtmlBenchmark "wideTreeEscaping" wideTree wideTreeEscapingData $ do
+        (string "A very wide tree (") >> toHtml (length wideTreeData) >> (string " elements)")
+        " with lots of escaping"
+    , HtmlBenchmark "deepTree" deepTree deepTreeData $ do
+        (string "A really deep tree (") >> toHtml deepTreeData >> " nested templates)"
+    , HtmlBenchmark "manyAttributes" manyAttributes manyAttributesData $ do
+        (string "A single element with ") >> toHtml (length manyAttributesData)
+        " attributes."
+    , HtmlBenchmark "customAttribute" customAttributes customAttributesData $
+        "Creating custom attributes"
+    ]
+
+rows :: Int
+rows = 1000
+
+bigTableData :: [[Int]]
+bigTableData = replicate rows [1..10]
+{-# NOINLINE bigTableData #-}
+
+basicData :: (String, String, [String])
+basicData = ("Just a test", "joe", items)
+{-# NOINLINE basicData #-}
+
+items :: [String]
+items = fmap (("Number " `mappend`) . show) [1 :: Int .. 14]
+{-# NOINLINE items #-}
+
+wideTreeData :: [String]
+wideTreeData = take 5000 $
+    cycle ["λf.(λx.fxx)(λx.fxx)", "These old days", "Foobar", "lol", "x âˆˆ A"]
+{-# NOINLINE wideTreeData #-}
+
+wideTreeEscapingData :: [String]
+wideTreeEscapingData = take 1000 $
+    cycle ["<><>", "\"lol\"", "<&>", "'>>'"]
+{-# NOINLINE wideTreeEscapingData #-}
+
+deepTreeData :: Int
+deepTreeData = 1000
+{-# NOINLINE deepTreeData #-}
+
+manyAttributesData :: [String]
+manyAttributesData = wideTreeData
+
+customAttributesData :: [(String, String)]
+customAttributesData = zip wideTreeData wideTreeData
+
+-- | Render the argument matrix as an HTML table.
+--
+bigTable :: [[Int]]  -- ^ Matrix.
+         -> Html     -- ^ Result.
+bigTable t = table $ mconcat $ fmap row t
+  where
+    row r = tr $ mconcat $ fmap (td . toHtml) r
+
+-- | Render a simple HTML page with some data.
+--
+basic :: (String, String, [String])  -- ^ (Title, User, Items)
+      -> Html                        -- ^ Result.
+basic (title', user, items') = html $ do
+    H.head $ title $ toHtml title'
+    body $ do
+        div ! A.id "header" $ (h1 $ toHtml title')
+        p $ "Hello, " `mappend` toHtml user `mappend` "!"
+        p $ "Hello, me!"
+        p $ "Hello, world!"
+        h2 $ "loop"
+        ol $ mconcat $ fmap (li . toHtml) items'
+        div ! A.id "footer" $ mempty
+
+-- | A benchmark producing a very wide but very shallow tree.
+--
+wideTree :: [String]  -- ^ Text to create a tree from.
+         -> Html      -- ^ Result.
+wideTree = div . mapM_ ((p ! A.id "foo") . toHtml)
+
+-- | Create a very deep tree.
+--
+deepTree :: Int   -- ^ Depth of the tree.
+         -> Html  -- ^ Result.
+deepTree 0 = "foo"
+deepTree n = p $ table $ tr $ td $ div $ deepTree (n - 1)
+
+-- | Create an element with many attributes.
+--
+manyAttributes :: [String]  -- ^ List of attribute values.
+               -> Html      -- ^ Result.
+manyAttributes = foldl setAttribute img
+  where
+    setAttribute html' value' = html' ! A.id (toValue value')
+    {-# INLINE setAttribute #-}
+
+customAttributes :: [(String, String)]  -- ^ List of attribute name, value pairs
+                 -> Html                -- ^ Result
+customAttributes = foldl setAttribute img
+  where
+    setAttribute html' (name, value') =
+        html' ! customAttribute (stringTag name) (toValue value')
diff --git a/src/Benchmarks/HtmlBenchmarks.hs b/src/Benchmarks/HtmlBenchmarks.hs
new file mode 100644 (file)
index 0000000..3070d52
--- /dev/null
@@ -0,0 +1,132 @@
+-- | This is a collection of HTML benchmarks for BlazeMarkup.
+--
+{-# LANGUAGE OverloadedStrings, ExistentialQuantification #-}
+{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
+module Benchmarks.HtmlBenchmarks where
+
+import Data.Monoid (Monoid, mempty, mconcat, mappend)
+import Prelude hiding (div, id)
+import qualified Prelude as P
+
+import Benchmarks.BenchmarkUtils
+import Text.Blaze
+import qualified Benchmarks.BenchmarkUtils as H
+
+-- | Description of an HTML benchmark
+--
+data HtmlBenchmark = forall a. HtmlBenchmark
+    { hName :: String       -- ^ Name.
+    , hR :: (a -> Html)  -- ^ Rendering function.
+    , hD :: a            -- ^ Data.
+    , hH :: Html }         -- ^ Longer description.
+
+-- | List containing all benchmarks.
+--
+benchmarks :: [HtmlBenchmark]
+benchmarks =
+    [ HtmlBenchmark "bigTable" bigTable bigTableData $
+        let h = toHtml $ length bigTableData
+            w = toHtml $ length $ P.head bigTableData
+        in "Rendering of a big (" >> h >> "x" >> w >> ") HTML table"
+    , HtmlBenchmark "basic" basic basicData
+        "A simple, small basic template with a few holes to fill in"
+    , HtmlBenchmark "wideTree" wideTree wideTreeData $
+        "A very wide tree (" >> toHtml (length wideTreeData) >> " elements)"
+    , HtmlBenchmark "wideTreeEscaping" wideTree wideTreeEscapingData $ do
+        "A very wide tree (" >> toHtml (length wideTreeData) >> " elements)"
+        " with lots of escaping"
+    , HtmlBenchmark "deepTree" deepTree deepTreeData $ do
+        "A really deep tree (" >> toHtml deepTreeData >> " nested templates)"
+    , HtmlBenchmark "manyAttributes" manyAttributes manyAttributesData $ do
+        "A single element with " >> toHtml (length manyAttributesData)
+        " attributes."
+    , HtmlBenchmark "customAttribute" customAttributes customAttributesData $
+        "Creating custom attributes"
+    ]
+
+rows :: Int
+rows = 1000
+
+bigTableData :: [[Int]]
+bigTableData = replicate rows [1..10]
+{-# NOINLINE bigTableData #-}
+
+basicData :: (String, String, [String])
+basicData = ("Just a test", "joe", items)
+{-# NOINLINE basicData #-}
+
+items :: [String]
+items = map (("Number " `mappend`) . show) [1 :: Int .. 14]
+{-# NOINLINE items #-}
+
+wideTreeData :: [String]
+wideTreeData = take 5000 $
+    cycle ["λf.(λx.fxx)(λx.fxx)", "These old days", "Foobar", "lol", "x âˆˆ A"]
+{-# NOINLINE wideTreeData #-}
+
+wideTreeEscapingData :: [String]
+wideTreeEscapingData = take 1000 $
+    cycle ["<><>", "\"lol\"", "<&>", "'>>'"]
+{-# NOINLINE wideTreeEscapingData #-}
+
+deepTreeData :: Int
+deepTreeData = 1000
+{-# NOINLINE deepTreeData #-}
+
+manyAttributesData :: [String]
+manyAttributesData = wideTreeData
+
+customAttributesData :: [(String, String)]
+customAttributesData = zip wideTreeData wideTreeData
+
+-- | Render the argument matrix as an HTML table.
+--
+bigTable :: [[Int]]  -- ^ Matrix.
+         -> Html     -- ^ Result.
+bigTable t = table $ mconcat $ map row t
+  where
+    row r = tr $ mconcat $ map (td . toHtml) r
+
+-- | Render a simple HTML page with some data.
+--
+basic :: (String, String, [String])  -- ^ (Title, User, Items)
+      -> Html                        -- ^ Result.
+basic (title', user, items') = html $ do
+    H.head $ title $ toHtml title'
+    body $ do
+        div ! id "header" $ (h1 $ toHtml title')
+        p $ "Hello, " `mappend` toHtml user `mappend` "!"
+        p $ "Hello, me!"
+        p $ "Hello, world!"
+        h2 $ "loop"
+        ol $ mconcat $ map (li . toHtml) items'
+        div ! id "footer" $ mempty
+
+-- | A benchmark producing a very wide but very shallow tree.
+--
+wideTree :: [String]  -- ^ Text to create a tree from.
+         -> Html      -- ^ Result.
+wideTree = div . mapM_ ((p ! id "foo") . toHtml)
+
+-- | Create a very deep tree.
+--
+deepTree :: Int   -- ^ Depth of the tree.
+         -> Html  -- ^ Result.
+deepTree 0 = "foo"
+deepTree n = p $ table $ tr $ td $ div $ deepTree (n - 1)
+
+-- | Create an element with many attributes.
+--
+manyAttributes :: [String]  -- ^ List of attribute values.
+               -> Html      -- ^ Result.
+manyAttributes = foldl setAttribute img
+  where
+    setAttribute html' value' = html' ! id (toValue value')
+    {-# INLINE setAttribute #-}
+
+customAttributes :: [(String, String)]  -- ^ List of attribute name, value pairs
+                 -> Html                -- ^ Result
+customAttributes = foldl setAttribute img
+  where
+    setAttribute html' (name, value') =
+        html' ! customAttribute (stringTag name) (toValue value')
diff --git a/src/Benchmarks/LICENSE b/src/Benchmarks/LICENSE
new file mode 100644 (file)
index 0000000..8122505
--- /dev/null
@@ -0,0 +1,30 @@
+Copyright Jasper Van der Jeugt 2010
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Jasper Van der Jeugt nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/Benchmarks/RunHtmlBenchmarks.hs b/src/Benchmarks/RunHtmlBenchmarks.hs
new file mode 100644 (file)
index 0000000..04c28ff
--- /dev/null
@@ -0,0 +1,36 @@
+-- | This is a module which runs the 'HtmlBenchmarks' module using the different
+-- renderers available.
+--
+module Benchmarks.RunHtmlBenchmarks where
+
+import Criterion.Main
+import qualified Data.Text.Lazy as LT
+import Data.List
+import qualified Data.ByteString.Lazy as LB
+
+import qualified Text.Blaze.Renderer.Utf8 as Utf8
+import qualified Text.Blaze.Renderer.String as String
+import qualified Text.Blaze.Renderer.Text as Text
+
+import Benchmarks.HtmlBenchmarks (HtmlBenchmark (..), benchmarks)
+import qualified Benchmarks.BlazeTBenchmarks as BT (HtmlBenchmark (..), benchmarks)
+import qualified Text.BlazeT.Renderer.Utf8 as TUtf8
+import qualified Text.BlazeT.Renderer.String as TString
+import qualified Text.BlazeT.Renderer.Text as TText
+
+-- | Function to run the benchmarks using criterion
+--
+main :: IO ()
+main = defaultMain $ zipWith g benchmarks BT.benchmarks
+  where
+    g x y = bgroup (hName x) $ benchHtml x ++ benchHtml2 y
+    benchHtml  (HtmlBenchmark _ f x _) = 
+        [ bench "Utf8"   $ nf (LB.length .  Utf8.renderMarkup . f) x
+        , bench "String" $ nf (String.renderMarkup . f) x
+        , bench "Text"   $ nf (LT.length . Text.renderMarkup . f) x
+        ]
+    benchHtml2 (BT.HtmlBenchmark _ f x _) =
+        [ bench "BlazeT.Utf8"   $ nf (LB.length .  TUtf8.renderMarkup . f) x
+        , bench "BlazeT.String" $ nf (TString.renderMarkup . f) x
+        , bench "BlazeT.Text"   $ nf (LT.length . TText.renderMarkup . f) x
+        ]
diff --git a/src/Benchmarks/ServerChunkSize.hs b/src/Benchmarks/ServerChunkSize.hs
new file mode 100644 (file)
index 0000000..7b01c68
--- /dev/null
@@ -0,0 +1,52 @@
+-- | A benchmark for measuring the impact of lazy bytestring chunk size on
+-- server performance.
+--
+{-# LANGUAGE OverloadedStrings #-}
+module Main where
+
+import Control.Concurrent (forkIO)
+import Control.Monad (forever)
+import Data.Monoid (mappend)
+import Network (listenOn, PortID (PortNumber))
+import Network.Socket (accept, sClose)
+import Prelude hiding (putStrLn)
+import System.Environment (getArgs)
+
+import Network.Socket.ByteString (recv, send)
+import Network.Socket.ByteString.Lazy (sendAll)
+import qualified Data.ByteString.Char8 as SBC
+import qualified Data.ByteString.Lazy as LB
+
+-- | Generate a 128k response, with a given chunk size.
+--
+makeResponse :: Int            -- ^ Chunk size.
+             -> LB.ByteString  -- ^ Result.
+makeResponse chunkSize =
+    let chunks = createChunks chunkSize totalSize
+    in LB.fromChunks chunks
+  where
+    -- A 64 kilobyte response.
+    totalSize = 128 * 1024
+
+    createChunks c s
+      | c < s     = SBC.replicate c 'a' : createChunks c (s - c)
+      | otherwise = SBC.replicate s 'a' : []
+
+main :: IO ()
+main = do
+    args <- getArgs
+    let port = PortNumber $ fromIntegral $ (read $ head args :: Int)
+        chunkSize = read $ args !! 1
+
+    socket <- listenOn port
+    forever $ do
+        (s, _) <- accept socket
+        forkIO (respond chunkSize s)
+  where
+    respond chunkSize s = do
+        _ <- recv s 1024
+        _ <- send s $ "HTTP/1.1 200 OK\r\n"
+            `mappend` "Content-Type: text/html; charset=UTF-8\r\n"
+            `mappend` "\r\n"
+        sendAll s $ makeResponse chunkSize
+        sClose s
diff --git a/src/Benchmarks/bigtable/erb.rb b/src/Benchmarks/bigtable/erb.rb
new file mode 100644 (file)
index 0000000..c3a675a
--- /dev/null
@@ -0,0 +1,32 @@
+# BigTable benchmark implemented in ERB.
+#
+require 'erb'
+require 'benchmark'
+include ERB::Util
+
+table = (1 .. 1000).map do |_| (1 .. 10) end
+
+template = ERB.new <<-EOF
+<table>
+  <% table.each do |row| %>
+    <tr>
+      <% row.each do |value| %>
+        <td>
+            <%= value %>
+        </td>
+      <% end %>
+    </tr>
+  <% end %>
+</table>
+EOF
+
+number_runs = 100
+start_time = Time.now.to_f
+number_runs.times do
+    template.result(binding)
+end
+end_time = Time.now.to_f
+
+# start_time and end_time are both in seconds now
+ms = (end_time - start_time) * 1000 / number_runs
+puts "\"ERB\", #{ms}"
diff --git a/src/Benchmarks/bigtable/erubis.rb b/src/Benchmarks/bigtable/erubis.rb
new file mode 100644 (file)
index 0000000..9a1edf9
--- /dev/null
@@ -0,0 +1,31 @@
+# BigTable benchmark implemented in erubis
+#
+require 'erubis'
+require 'benchmark'
+
+table = (1 .. 1000).map do |_| (1 .. 10) end
+
+template = Erubis::Eruby.new <<-EOF
+<table>
+  <% table.each do |row| %>
+    <tr>
+      <% row.each do |value| %>
+        <td>
+            <%= value %>
+        </td>
+      <% end %>
+    </tr>
+  <% end %>
+</table>
+EOF
+
+number_runs = 100
+start_time = Time.now.to_f
+number_runs.times do
+    template.result(binding)
+end
+end_time = Time.now.to_f
+
+# start_time and end_time are both in seconds now
+ms = (end_time - start_time) * 1000 / number_runs
+puts "\"Erubis\", #{ms}"
diff --git a/src/Benchmarks/bigtable/hamlet.hs b/src/Benchmarks/bigtable/hamlet.hs
new file mode 100644 (file)
index 0000000..2778f2d
--- /dev/null
@@ -0,0 +1,33 @@
+-- | BigTable benchmark implemented using Hamlet.
+--
+{-# LANGUAGE QuasiQuotes #-}
+module Main where
+
+import Criterion.Main
+import Text.Hamlet
+import Text.Hamlet.Monad
+import Numeric (showInt)
+import Data.Text (Text)
+import qualified Data.Text as T
+import Data.Maybe (fromJust)
+
+main = defaultMain
+    [ bench "bigTable" $ nf bigTable bigTableData
+    ]
+  where
+    rows :: Int
+    rows = 1000
+
+    bigTableData :: [[Int]]
+    bigTableData = replicate rows [1..10]
+    {-# NOINLINE bigTableData #-}
+
+bigTable rows = fromJust $ hamletToText undefined [$hamlet|
+%table
+    $forall rows row
+        %tr
+            $forall row cell
+                %td $showInt'.cell$
+|]
+  where
+    showInt' i = Encoded $ T.pack $ showInt i ""
diff --git a/src/Benchmarks/bigtable/html-minimalist.hs b/src/Benchmarks/bigtable/html-minimalist.hs
new file mode 100644 (file)
index 0000000..2a52751
--- /dev/null
@@ -0,0 +1,20 @@
+-- | BigTable benchmark using the html-minimalist package from hackage.
+--
+import Text.HTML.Light hiding (map)
+import Criterion.Main
+
+bigTable :: [[Int]] -> String
+bigTable t =
+    renderXHTML xhtml_1_0_strict $ html [] $ return $ table [] $ map row t
+  where
+    row r = tr [] $ map (td [] . return . cdata . show) r
+
+main = defaultMain
+    [ bench "bigTable" $ nf bigTable myTable ]
+  where
+    rows :: Int
+    rows = 1000
+
+    myTable :: [[Int]]
+    myTable = replicate rows [1..10]
+    {-# NOINLINE myTable #-}
diff --git a/src/Benchmarks/bigtable/html.hs b/src/Benchmarks/bigtable/html.hs
new file mode 100644 (file)
index 0000000..57a62b3
--- /dev/null
@@ -0,0 +1,19 @@
+-- | BigTable benchmark using the HTML package from hackage.
+--
+import Text.Html
+import Criterion.Main
+
+bigTable :: [[Int]] -> String
+bigTable t = renderHtml $ table $ concatHtml $ map row t
+  where
+    row r = tr $ concatHtml $ map (td . stringToHtml . show) r
+
+main = defaultMain
+    [ bench "bigTable" $ nf bigTable myTable ]
+  where
+    rows :: Int
+    rows = 1000
+
+    myTable :: [[Int]]
+    myTable = replicate rows [1..10]
+    {-# NOINLINE myTable #-}
diff --git a/src/Benchmarks/bigtable/php.php b/src/Benchmarks/bigtable/php.php
new file mode 100644 (file)
index 0000000..f2e51a4
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+$table = array_fill(0, 1000, array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+
+function test_bigtable($table) {
+       ob_start();
+?>
+<table>
+<?php foreach($table as $row) { ?>
+<tr>
+<?php foreach($row as $value) { ?>
+<td><?php echo $value; ?></td>
+<?php } ?>
+</tr>
+<?php } ?>
+</table>
+<?php
+       return ob_get_clean();
+}
+
+$request_count = 1000;
+
+$start = microtime(true);
+for ($i = 0; $i < $request_count; $i++)
+{
+  test_bigtable($table);
+}
+$elapsed = microtime(true) - $start;
+$time_per_request = ($elapsed / $request_count) * 1000;
+echo "\"PHP\", $time_per_request\n";
+?>
diff --git a/src/Benchmarks/bigtable/xhtml.hs b/src/Benchmarks/bigtable/xhtml.hs
new file mode 100644 (file)
index 0000000..993994c
--- /dev/null
@@ -0,0 +1,19 @@
+-- | BigTable benchmark using the XHTML package from hackage.
+--
+import Text.XHtml.Strict
+import Criterion.Main
+
+bigTable :: [[Int]] -> String
+bigTable t = renderHtml $ table $ concatHtml $ map row t
+  where
+    row r = tr $ concatHtml $ map (td . stringToHtml . show) r
+
+main = defaultMain
+    [ bench "bigTable" $ nf bigTable myTable ]
+  where
+    rows :: Int
+    rows = 1000
+
+    myTable :: [[Int]]
+    myTable = replicate rows [1..10]
+    {-# NOINLINE myTable #-}
diff --git a/src/Text/BlazeT.hs b/src/Text/BlazeT.hs
new file mode 100644 (file)
index 0000000..27228fa
--- /dev/null
@@ -0,0 +1,81 @@
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE RankNTypes #-}
+module Text.BlazeT
+  (
+      -- * Important types.
+      Markup
+    , Tag
+    , Attribute
+    , AttributeValue
+
+      -- * Creating attributes.
+    , dataAttribute
+    , customAttribute
+
+      -- * Converting values to Markup.
+    , ToMarkup (..)
+    , text
+    , preEscapedText
+    , lazyText
+    , preEscapedLazyText
+    , string
+    , preEscapedString
+    , unsafeByteString
+    , unsafeLazyByteString
+
+      -- * Comments
+    , textComment
+    , lazyTextComment
+    , stringComment
+    , unsafeByteStringComment
+    , unsafeLazyByteStringComment
+
+      -- * Creating tags.
+    , textTag
+    , stringTag
+
+      -- * Converting values to attribute values.
+    , B.ToValue (..)
+    , textValue
+    , preEscapedTextValue
+    , lazyTextValue
+    , preEscapedLazyTextValue
+    , stringValue
+    , preEscapedStringValue
+    , unsafeByteStringValue
+    , unsafeLazyByteStringValue
+
+      -- * Setting attributes
+    , (!)
+    , (!?)
+
+      -- * Modifiying Markup trees
+    , contents
+
+    -- * BlazeT new stuff
+    ,MarkupM
+    ,Markup2
+    ,mapMarkupT
+    ,MarkupT
+    ,runMarkup
+    ,runMarkupT
+    ,execMarkup
+    ,execMarkupT
+    ) where
+
+import qualified Text.Blaze as B
+import           Text.BlazeT.Internal
+
+class ToMarkup a where
+  toMarkup :: a -> Markup
+  preEscapedToMarkup :: a -> Markup
+
+-- test :: (ToMarkup a, Monad m) => a -> MarkupT m ()
+-- test = toMarkup
+
+instance B.ToMarkup a => ToMarkup a where
+  toMarkup = wrapMarkup . B.toMarkup
+  {-# INLINE toMarkup #-}
+  preEscapedToMarkup = wrapMarkup . B.preEscapedToMarkup
+  {-# INLINE preEscapedToMarkup #-}
diff --git a/src/Text/BlazeT/Html.hs b/src/Text/BlazeT/Html.hs
new file mode 100644 (file)
index 0000000..4a21c03
--- /dev/null
@@ -0,0 +1,22 @@
+{-# LANGUAGE RankNTypes #-}
+module Text.BlazeT.Html
+    ( module Text.BlazeT
+    , Html
+    , toHtml
+    , preEscapedToHtml
+    -- * BlazeT new stuff
+    ,HtmlM
+    ,HtmlT
+    ) where
+
+import Text.BlazeT
+
+type HtmlT = MarkupT
+type HtmlM = MarkupM
+type Html = Markup
+
+toHtml ::(ToMarkup a) => a -> Html
+toHtml = toMarkup
+
+preEscapedToHtml ::(ToMarkup a) => a -> Html
+preEscapedToHtml = preEscapedToMarkup
diff --git a/src/Text/BlazeT/Html4/FrameSet.hs b/src/Text/BlazeT/Html4/FrameSet.hs
new file mode 100644 (file)
index 0000000..5d6ec03
--- /dev/null
@@ -0,0 +1,198 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module wraps all exports of "Text.Blaze.Html4.FrameSet" using 'wrapMarkup' and 'wrapMarkup'.
+-}
+module Text.BlazeT.Html4.FrameSet
+   (module Text.BlazeT.Html4.FrameSet
+   ,module Text.BlazeT.Html
+   ) where
+import qualified Text.Blaze.Html4.FrameSet
+import           Text.BlazeT
+import           Text.BlazeT.Html
+import           Text.BlazeT.Internal
+
+docTypeHtml :: Markup2
+docTypeHtml = wrapMarkup2 Text.Blaze.Html4.FrameSet.docTypeHtml
+a :: Markup2
+a = wrapMarkup2 Text.Blaze.Html4.FrameSet.a
+abbr :: Markup2
+abbr = wrapMarkup2 Text.Blaze.Html4.FrameSet.abbr
+acronym :: Markup2
+acronym = wrapMarkup2 Text.Blaze.Html4.FrameSet.acronym
+address :: Markup2
+address = wrapMarkup2 Text.Blaze.Html4.FrameSet.address
+b :: Markup2
+b = wrapMarkup2 Text.Blaze.Html4.FrameSet.b
+bdo :: Markup2
+bdo = wrapMarkup2 Text.Blaze.Html4.FrameSet.bdo
+big :: Markup2
+big = wrapMarkup2 Text.Blaze.Html4.FrameSet.big
+blockquote :: Markup2
+blockquote = wrapMarkup2 Text.Blaze.Html4.FrameSet.blockquote
+body :: Markup2
+body = wrapMarkup2 Text.Blaze.Html4.FrameSet.body
+button :: Markup2
+button = wrapMarkup2 Text.Blaze.Html4.FrameSet.button
+caption :: Markup2
+caption = wrapMarkup2 Text.Blaze.Html4.FrameSet.caption
+cite :: Markup2
+cite = wrapMarkup2 Text.Blaze.Html4.FrameSet.cite
+code :: Markup2
+code = wrapMarkup2 Text.Blaze.Html4.FrameSet.code
+colgroup :: Markup2
+colgroup = wrapMarkup2 Text.Blaze.Html4.FrameSet.colgroup
+dd :: Markup2
+dd = wrapMarkup2 Text.Blaze.Html4.FrameSet.dd
+del :: Markup2
+del = wrapMarkup2 Text.Blaze.Html4.FrameSet.del
+dfn :: Markup2
+dfn = wrapMarkup2 Text.Blaze.Html4.FrameSet.dfn
+div :: Markup2
+div = wrapMarkup2 Text.Blaze.Html4.FrameSet.div
+dl :: Markup2
+dl = wrapMarkup2 Text.Blaze.Html4.FrameSet.dl
+dt :: Markup2
+dt = wrapMarkup2 Text.Blaze.Html4.FrameSet.dt
+em :: Markup2
+em = wrapMarkup2 Text.Blaze.Html4.FrameSet.em
+fieldset :: Markup2
+fieldset = wrapMarkup2 Text.Blaze.Html4.FrameSet.fieldset
+form :: Markup2
+form = wrapMarkup2 Text.Blaze.Html4.FrameSet.form
+h1 :: Markup2
+h1 = wrapMarkup2 Text.Blaze.Html4.FrameSet.h1
+h2 :: Markup2
+h2 = wrapMarkup2 Text.Blaze.Html4.FrameSet.h2
+h3 :: Markup2
+h3 = wrapMarkup2 Text.Blaze.Html4.FrameSet.h3
+h4 :: Markup2
+h4 = wrapMarkup2 Text.Blaze.Html4.FrameSet.h4
+h5 :: Markup2
+h5 = wrapMarkup2 Text.Blaze.Html4.FrameSet.h5
+h6 :: Markup2
+h6 = wrapMarkup2 Text.Blaze.Html4.FrameSet.h6
+head :: Markup2
+head = wrapMarkup2 Text.Blaze.Html4.FrameSet.head
+html :: Markup2
+html = wrapMarkup2 Text.Blaze.Html4.FrameSet.html
+i :: Markup2
+i = wrapMarkup2 Text.Blaze.Html4.FrameSet.i
+ins :: Markup2
+ins = wrapMarkup2 Text.Blaze.Html4.FrameSet.ins
+kbd :: Markup2
+kbd = wrapMarkup2 Text.Blaze.Html4.FrameSet.kbd
+label :: Markup2
+label = wrapMarkup2 Text.Blaze.Html4.FrameSet.label
+legend :: Markup2
+legend = wrapMarkup2 Text.Blaze.Html4.FrameSet.legend
+li :: Markup2
+li = wrapMarkup2 Text.Blaze.Html4.FrameSet.li
+map :: Markup2
+map = wrapMarkup2 Text.Blaze.Html4.FrameSet.map
+noscript :: Markup2
+noscript = wrapMarkup2 Text.Blaze.Html4.FrameSet.noscript
+object :: Markup2
+object = wrapMarkup2 Text.Blaze.Html4.FrameSet.object
+ol :: Markup2
+ol = wrapMarkup2 Text.Blaze.Html4.FrameSet.ol
+optgroup :: Markup2
+optgroup = wrapMarkup2 Text.Blaze.Html4.FrameSet.optgroup
+option :: Markup2
+option = wrapMarkup2 Text.Blaze.Html4.FrameSet.option
+p :: Markup2
+p = wrapMarkup2 Text.Blaze.Html4.FrameSet.p
+pre :: Markup2
+pre = wrapMarkup2 Text.Blaze.Html4.FrameSet.pre
+q :: Markup2
+q = wrapMarkup2 Text.Blaze.Html4.FrameSet.q
+samp :: Markup2
+samp = wrapMarkup2 Text.Blaze.Html4.FrameSet.samp
+script :: Markup2
+script = wrapMarkup2 Text.Blaze.Html4.FrameSet.script
+select :: Markup2
+select = wrapMarkup2 Text.Blaze.Html4.FrameSet.select
+small :: Markup2
+small = wrapMarkup2 Text.Blaze.Html4.FrameSet.small
+span :: Markup2
+span = wrapMarkup2 Text.Blaze.Html4.FrameSet.span
+strong :: Markup2
+strong = wrapMarkup2 Text.Blaze.Html4.FrameSet.strong
+style :: Markup2
+style = wrapMarkup2 Text.Blaze.Html4.FrameSet.style
+sub :: Markup2
+sub = wrapMarkup2 Text.Blaze.Html4.FrameSet.sub
+sup :: Markup2
+sup = wrapMarkup2 Text.Blaze.Html4.FrameSet.sup
+table :: Markup2
+table = wrapMarkup2 Text.Blaze.Html4.FrameSet.table
+tbody :: Markup2
+tbody = wrapMarkup2 Text.Blaze.Html4.FrameSet.tbody
+td :: Markup2
+td = wrapMarkup2 Text.Blaze.Html4.FrameSet.td
+textarea :: Markup2
+textarea = wrapMarkup2 Text.Blaze.Html4.FrameSet.textarea
+tfoot :: Markup2
+tfoot = wrapMarkup2 Text.Blaze.Html4.FrameSet.tfoot
+th :: Markup2
+th = wrapMarkup2 Text.Blaze.Html4.FrameSet.th
+thead :: Markup2
+thead = wrapMarkup2 Text.Blaze.Html4.FrameSet.thead
+title :: Markup2
+title = wrapMarkup2 Text.Blaze.Html4.FrameSet.title
+tr :: Markup2
+tr = wrapMarkup2 Text.Blaze.Html4.FrameSet.tr
+tt :: Markup2
+tt = wrapMarkup2 Text.Blaze.Html4.FrameSet.tt
+ul :: Markup2
+ul = wrapMarkup2 Text.Blaze.Html4.FrameSet.ul
+var :: Markup2
+var = wrapMarkup2 Text.Blaze.Html4.FrameSet.var
+applet :: Markup2
+applet = wrapMarkup2 Text.Blaze.Html4.FrameSet.applet
+center :: Markup2
+center = wrapMarkup2 Text.Blaze.Html4.FrameSet.center
+dir :: Markup2
+dir = wrapMarkup2 Text.Blaze.Html4.FrameSet.dir
+font :: Markup2
+font = wrapMarkup2 Text.Blaze.Html4.FrameSet.font
+iframe :: Markup2
+iframe = wrapMarkup2 Text.Blaze.Html4.FrameSet.iframe
+isindex :: Markup2
+isindex = wrapMarkup2 Text.Blaze.Html4.FrameSet.isindex
+menu :: Markup2
+menu = wrapMarkup2 Text.Blaze.Html4.FrameSet.menu
+noframes :: Markup2
+noframes = wrapMarkup2 Text.Blaze.Html4.FrameSet.noframes
+s :: Markup2
+s = wrapMarkup2 Text.Blaze.Html4.FrameSet.s
+u :: Markup2
+u = wrapMarkup2 Text.Blaze.Html4.FrameSet.u
+frameset :: Markup2
+frameset = wrapMarkup2 Text.Blaze.Html4.FrameSet.frameset
+docType :: Markup
+docType = wrapMarkup Text.Blaze.Html4.FrameSet.docType
+area :: Markup
+area = wrapMarkup Text.Blaze.Html4.FrameSet.area
+br :: Markup
+br = wrapMarkup Text.Blaze.Html4.FrameSet.br
+col :: Markup
+col = wrapMarkup Text.Blaze.Html4.FrameSet.col
+hr :: Markup
+hr = wrapMarkup Text.Blaze.Html4.FrameSet.hr
+link :: Markup
+link = wrapMarkup Text.Blaze.Html4.FrameSet.link
+img :: Markup
+img = wrapMarkup Text.Blaze.Html4.FrameSet.img
+input :: Markup
+input = wrapMarkup Text.Blaze.Html4.FrameSet.input
+meta :: Markup
+meta = wrapMarkup Text.Blaze.Html4.FrameSet.meta
+param :: Markup
+param = wrapMarkup Text.Blaze.Html4.FrameSet.param
+basefont :: Markup
+basefont = wrapMarkup Text.Blaze.Html4.FrameSet.basefont
+frame :: Markup
+frame = wrapMarkup Text.Blaze.Html4.FrameSet.frame
+
diff --git a/src/Text/BlazeT/Html4/FrameSet/Attributes.hs b/src/Text/BlazeT/Html4/FrameSet/Attributes.hs
new file mode 100644 (file)
index 0000000..d806f29
--- /dev/null
@@ -0,0 +1,11 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module simply reexports the corresponding @blaze-html@ module.
+-}
+module Text.BlazeT.Html4.FrameSet.Attributes
+   (module Text.Blaze.Html4.FrameSet.Attributes
+   ) where
+import Text.Blaze.Html4.FrameSet.Attributes
+
diff --git a/src/Text/BlazeT/Html4/Strict.hs b/src/Text/BlazeT/Html4/Strict.hs
new file mode 100644 (file)
index 0000000..90fd65a
--- /dev/null
@@ -0,0 +1,172 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module wraps all exports of "Text.Blaze.Html4.Strict" using 'wrapMarkup' and 'wrapMarkup'.
+-}
+module Text.BlazeT.Html4.Strict
+   (module Text.BlazeT.Html4.Strict
+   ,module Text.BlazeT.Html
+   ) where
+import qualified Text.Blaze.Html4.Strict
+import           Text.BlazeT
+import           Text.BlazeT.Html
+import           Text.BlazeT.Internal
+
+docTypeHtml :: Markup2
+docTypeHtml = wrapMarkup2 Text.Blaze.Html4.Strict.docTypeHtml
+a :: Markup2
+a = wrapMarkup2 Text.Blaze.Html4.Strict.a
+abbr :: Markup2
+abbr = wrapMarkup2 Text.Blaze.Html4.Strict.abbr
+acronym :: Markup2
+acronym = wrapMarkup2 Text.Blaze.Html4.Strict.acronym
+address :: Markup2
+address = wrapMarkup2 Text.Blaze.Html4.Strict.address
+b :: Markup2
+b = wrapMarkup2 Text.Blaze.Html4.Strict.b
+bdo :: Markup2
+bdo = wrapMarkup2 Text.Blaze.Html4.Strict.bdo
+big :: Markup2
+big = wrapMarkup2 Text.Blaze.Html4.Strict.big
+blockquote :: Markup2
+blockquote = wrapMarkup2 Text.Blaze.Html4.Strict.blockquote
+body :: Markup2
+body = wrapMarkup2 Text.Blaze.Html4.Strict.body
+button :: Markup2
+button = wrapMarkup2 Text.Blaze.Html4.Strict.button
+caption :: Markup2
+caption = wrapMarkup2 Text.Blaze.Html4.Strict.caption
+cite :: Markup2
+cite = wrapMarkup2 Text.Blaze.Html4.Strict.cite
+code :: Markup2
+code = wrapMarkup2 Text.Blaze.Html4.Strict.code
+colgroup :: Markup2
+colgroup = wrapMarkup2 Text.Blaze.Html4.Strict.colgroup
+dd :: Markup2
+dd = wrapMarkup2 Text.Blaze.Html4.Strict.dd
+del :: Markup2
+del = wrapMarkup2 Text.Blaze.Html4.Strict.del
+dfn :: Markup2
+dfn = wrapMarkup2 Text.Blaze.Html4.Strict.dfn
+div :: Markup2
+div = wrapMarkup2 Text.Blaze.Html4.Strict.div
+dl :: Markup2
+dl = wrapMarkup2 Text.Blaze.Html4.Strict.dl
+dt :: Markup2
+dt = wrapMarkup2 Text.Blaze.Html4.Strict.dt
+em :: Markup2
+em = wrapMarkup2 Text.Blaze.Html4.Strict.em
+fieldset :: Markup2
+fieldset = wrapMarkup2 Text.Blaze.Html4.Strict.fieldset
+form :: Markup2
+form = wrapMarkup2 Text.Blaze.Html4.Strict.form
+h1 :: Markup2
+h1 = wrapMarkup2 Text.Blaze.Html4.Strict.h1
+h2 :: Markup2
+h2 = wrapMarkup2 Text.Blaze.Html4.Strict.h2
+h3 :: Markup2
+h3 = wrapMarkup2 Text.Blaze.Html4.Strict.h3
+h4 :: Markup2
+h4 = wrapMarkup2 Text.Blaze.Html4.Strict.h4
+h5 :: Markup2
+h5 = wrapMarkup2 Text.Blaze.Html4.Strict.h5
+h6 :: Markup2
+h6 = wrapMarkup2 Text.Blaze.Html4.Strict.h6
+head :: Markup2
+head = wrapMarkup2 Text.Blaze.Html4.Strict.head
+html :: Markup2
+html = wrapMarkup2 Text.Blaze.Html4.Strict.html
+i :: Markup2
+i = wrapMarkup2 Text.Blaze.Html4.Strict.i
+ins :: Markup2
+ins = wrapMarkup2 Text.Blaze.Html4.Strict.ins
+kbd :: Markup2
+kbd = wrapMarkup2 Text.Blaze.Html4.Strict.kbd
+label :: Markup2
+label = wrapMarkup2 Text.Blaze.Html4.Strict.label
+legend :: Markup2
+legend = wrapMarkup2 Text.Blaze.Html4.Strict.legend
+li :: Markup2
+li = wrapMarkup2 Text.Blaze.Html4.Strict.li
+map :: Markup2
+map = wrapMarkup2 Text.Blaze.Html4.Strict.map
+noscript :: Markup2
+noscript = wrapMarkup2 Text.Blaze.Html4.Strict.noscript
+object :: Markup2
+object = wrapMarkup2 Text.Blaze.Html4.Strict.object
+ol :: Markup2
+ol = wrapMarkup2 Text.Blaze.Html4.Strict.ol
+optgroup :: Markup2
+optgroup = wrapMarkup2 Text.Blaze.Html4.Strict.optgroup
+option :: Markup2
+option = wrapMarkup2 Text.Blaze.Html4.Strict.option
+p :: Markup2
+p = wrapMarkup2 Text.Blaze.Html4.Strict.p
+pre :: Markup2
+pre = wrapMarkup2 Text.Blaze.Html4.Strict.pre
+q :: Markup2
+q = wrapMarkup2 Text.Blaze.Html4.Strict.q
+samp :: Markup2
+samp = wrapMarkup2 Text.Blaze.Html4.Strict.samp
+script :: Markup2
+script = wrapMarkup2 Text.Blaze.Html4.Strict.script
+select :: Markup2
+select = wrapMarkup2 Text.Blaze.Html4.Strict.select
+small :: Markup2
+small = wrapMarkup2 Text.Blaze.Html4.Strict.small
+span :: Markup2
+span = wrapMarkup2 Text.Blaze.Html4.Strict.span
+strong :: Markup2
+strong = wrapMarkup2 Text.Blaze.Html4.Strict.strong
+style :: Markup2
+style = wrapMarkup2 Text.Blaze.Html4.Strict.style
+sub :: Markup2
+sub = wrapMarkup2 Text.Blaze.Html4.Strict.sub
+sup :: Markup2
+sup = wrapMarkup2 Text.Blaze.Html4.Strict.sup
+table :: Markup2
+table = wrapMarkup2 Text.Blaze.Html4.Strict.table
+tbody :: Markup2
+tbody = wrapMarkup2 Text.Blaze.Html4.Strict.tbody
+td :: Markup2
+td = wrapMarkup2 Text.Blaze.Html4.Strict.td
+textarea :: Markup2
+textarea = wrapMarkup2 Text.Blaze.Html4.Strict.textarea
+tfoot :: Markup2
+tfoot = wrapMarkup2 Text.Blaze.Html4.Strict.tfoot
+th :: Markup2
+th = wrapMarkup2 Text.Blaze.Html4.Strict.th
+thead :: Markup2
+thead = wrapMarkup2 Text.Blaze.Html4.Strict.thead
+title :: Markup2
+title = wrapMarkup2 Text.Blaze.Html4.Strict.title
+tr :: Markup2
+tr = wrapMarkup2 Text.Blaze.Html4.Strict.tr
+tt :: Markup2
+tt = wrapMarkup2 Text.Blaze.Html4.Strict.tt
+ul :: Markup2
+ul = wrapMarkup2 Text.Blaze.Html4.Strict.ul
+var :: Markup2
+var = wrapMarkup2 Text.Blaze.Html4.Strict.var
+docType :: Markup
+docType = wrapMarkup Text.Blaze.Html4.Strict.docType
+area :: Markup
+area = wrapMarkup Text.Blaze.Html4.Strict.area
+br :: Markup
+br = wrapMarkup Text.Blaze.Html4.Strict.br
+col :: Markup
+col = wrapMarkup Text.Blaze.Html4.Strict.col
+hr :: Markup
+hr = wrapMarkup Text.Blaze.Html4.Strict.hr
+link :: Markup
+link = wrapMarkup Text.Blaze.Html4.Strict.link
+img :: Markup
+img = wrapMarkup Text.Blaze.Html4.Strict.img
+input :: Markup
+input = wrapMarkup Text.Blaze.Html4.Strict.input
+meta :: Markup
+meta = wrapMarkup Text.Blaze.Html4.Strict.meta
+param :: Markup
+param = wrapMarkup Text.Blaze.Html4.Strict.param
+
diff --git a/src/Text/BlazeT/Html4/Strict/Attributes.hs b/src/Text/BlazeT/Html4/Strict/Attributes.hs
new file mode 100644 (file)
index 0000000..18d1fe2
--- /dev/null
@@ -0,0 +1,11 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module simply reexports the corresponding @blaze-html@ module.
+-}
+module Text.BlazeT.Html4.Strict.Attributes
+   (module Text.Blaze.Html4.Strict.Attributes
+   ) where
+import Text.Blaze.Html4.Strict.Attributes
+
diff --git a/src/Text/BlazeT/Html4/Transitional.hs b/src/Text/BlazeT/Html4/Transitional.hs
new file mode 100644 (file)
index 0000000..a6dead6
--- /dev/null
@@ -0,0 +1,194 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module wraps all exports of "Text.Blaze.Html4.Transitional" using 'wrapMarkup' and 'wrapMarkup'.
+-}
+module Text.BlazeT.Html4.Transitional
+   (module Text.BlazeT.Html4.Transitional
+   ,module Text.BlazeT.Html
+   ) where
+import qualified Text.Blaze.Html4.Transitional
+import           Text.BlazeT
+import           Text.BlazeT.Html
+import           Text.BlazeT.Internal
+
+docTypeHtml :: Markup2
+docTypeHtml = wrapMarkup2 Text.Blaze.Html4.Transitional.docTypeHtml
+a :: Markup2
+a = wrapMarkup2 Text.Blaze.Html4.Transitional.a
+abbr :: Markup2
+abbr = wrapMarkup2 Text.Blaze.Html4.Transitional.abbr
+acronym :: Markup2
+acronym = wrapMarkup2 Text.Blaze.Html4.Transitional.acronym
+address :: Markup2
+address = wrapMarkup2 Text.Blaze.Html4.Transitional.address
+b :: Markup2
+b = wrapMarkup2 Text.Blaze.Html4.Transitional.b
+bdo :: Markup2
+bdo = wrapMarkup2 Text.Blaze.Html4.Transitional.bdo
+big :: Markup2
+big = wrapMarkup2 Text.Blaze.Html4.Transitional.big
+blockquote :: Markup2
+blockquote = wrapMarkup2 Text.Blaze.Html4.Transitional.blockquote
+body :: Markup2
+body = wrapMarkup2 Text.Blaze.Html4.Transitional.body
+button :: Markup2
+button = wrapMarkup2 Text.Blaze.Html4.Transitional.button
+caption :: Markup2
+caption = wrapMarkup2 Text.Blaze.Html4.Transitional.caption
+cite :: Markup2
+cite = wrapMarkup2 Text.Blaze.Html4.Transitional.cite
+code :: Markup2
+code = wrapMarkup2 Text.Blaze.Html4.Transitional.code
+colgroup :: Markup2
+colgroup = wrapMarkup2 Text.Blaze.Html4.Transitional.colgroup
+dd :: Markup2
+dd = wrapMarkup2 Text.Blaze.Html4.Transitional.dd
+del :: Markup2
+del = wrapMarkup2 Text.Blaze.Html4.Transitional.del
+dfn :: Markup2
+dfn = wrapMarkup2 Text.Blaze.Html4.Transitional.dfn
+div :: Markup2
+div = wrapMarkup2 Text.Blaze.Html4.Transitional.div
+dl :: Markup2
+dl = wrapMarkup2 Text.Blaze.Html4.Transitional.dl
+dt :: Markup2
+dt = wrapMarkup2 Text.Blaze.Html4.Transitional.dt
+em :: Markup2
+em = wrapMarkup2 Text.Blaze.Html4.Transitional.em
+fieldset :: Markup2
+fieldset = wrapMarkup2 Text.Blaze.Html4.Transitional.fieldset
+form :: Markup2
+form = wrapMarkup2 Text.Blaze.Html4.Transitional.form
+h1 :: Markup2
+h1 = wrapMarkup2 Text.Blaze.Html4.Transitional.h1
+h2 :: Markup2
+h2 = wrapMarkup2 Text.Blaze.Html4.Transitional.h2
+h3 :: Markup2
+h3 = wrapMarkup2 Text.Blaze.Html4.Transitional.h3
+h4 :: Markup2
+h4 = wrapMarkup2 Text.Blaze.Html4.Transitional.h4
+h5 :: Markup2
+h5 = wrapMarkup2 Text.Blaze.Html4.Transitional.h5
+h6 :: Markup2
+h6 = wrapMarkup2 Text.Blaze.Html4.Transitional.h6
+head :: Markup2
+head = wrapMarkup2 Text.Blaze.Html4.Transitional.head
+html :: Markup2
+html = wrapMarkup2 Text.Blaze.Html4.Transitional.html
+i :: Markup2
+i = wrapMarkup2 Text.Blaze.Html4.Transitional.i
+ins :: Markup2
+ins = wrapMarkup2 Text.Blaze.Html4.Transitional.ins
+kbd :: Markup2
+kbd = wrapMarkup2 Text.Blaze.Html4.Transitional.kbd
+label :: Markup2
+label = wrapMarkup2 Text.Blaze.Html4.Transitional.label
+legend :: Markup2
+legend = wrapMarkup2 Text.Blaze.Html4.Transitional.legend
+li :: Markup2
+li = wrapMarkup2 Text.Blaze.Html4.Transitional.li
+map :: Markup2
+map = wrapMarkup2 Text.Blaze.Html4.Transitional.map
+noscript :: Markup2
+noscript = wrapMarkup2 Text.Blaze.Html4.Transitional.noscript
+object :: Markup2
+object = wrapMarkup2 Text.Blaze.Html4.Transitional.object
+ol :: Markup2
+ol = wrapMarkup2 Text.Blaze.Html4.Transitional.ol
+optgroup :: Markup2
+optgroup = wrapMarkup2 Text.Blaze.Html4.Transitional.optgroup
+option :: Markup2
+option = wrapMarkup2 Text.Blaze.Html4.Transitional.option
+p :: Markup2
+p = wrapMarkup2 Text.Blaze.Html4.Transitional.p
+pre :: Markup2
+pre = wrapMarkup2 Text.Blaze.Html4.Transitional.pre
+q :: Markup2
+q = wrapMarkup2 Text.Blaze.Html4.Transitional.q
+samp :: Markup2
+samp = wrapMarkup2 Text.Blaze.Html4.Transitional.samp
+script :: Markup2
+script = wrapMarkup2 Text.Blaze.Html4.Transitional.script
+select :: Markup2
+select = wrapMarkup2 Text.Blaze.Html4.Transitional.select
+small :: Markup2
+small = wrapMarkup2 Text.Blaze.Html4.Transitional.small
+span :: Markup2
+span = wrapMarkup2 Text.Blaze.Html4.Transitional.span
+strong :: Markup2
+strong = wrapMarkup2 Text.Blaze.Html4.Transitional.strong
+style :: Markup2
+style = wrapMarkup2 Text.Blaze.Html4.Transitional.style
+sub :: Markup2
+sub = wrapMarkup2 Text.Blaze.Html4.Transitional.sub
+sup :: Markup2
+sup = wrapMarkup2 Text.Blaze.Html4.Transitional.sup
+table :: Markup2
+table = wrapMarkup2 Text.Blaze.Html4.Transitional.table
+tbody :: Markup2
+tbody = wrapMarkup2 Text.Blaze.Html4.Transitional.tbody
+td :: Markup2
+td = wrapMarkup2 Text.Blaze.Html4.Transitional.td
+textarea :: Markup2
+textarea = wrapMarkup2 Text.Blaze.Html4.Transitional.textarea
+tfoot :: Markup2
+tfoot = wrapMarkup2 Text.Blaze.Html4.Transitional.tfoot
+th :: Markup2
+th = wrapMarkup2 Text.Blaze.Html4.Transitional.th
+thead :: Markup2
+thead = wrapMarkup2 Text.Blaze.Html4.Transitional.thead
+title :: Markup2
+title = wrapMarkup2 Text.Blaze.Html4.Transitional.title
+tr :: Markup2
+tr = wrapMarkup2 Text.Blaze.Html4.Transitional.tr
+tt :: Markup2
+tt = wrapMarkup2 Text.Blaze.Html4.Transitional.tt
+ul :: Markup2
+ul = wrapMarkup2 Text.Blaze.Html4.Transitional.ul
+var :: Markup2
+var = wrapMarkup2 Text.Blaze.Html4.Transitional.var
+applet :: Markup2
+applet = wrapMarkup2 Text.Blaze.Html4.Transitional.applet
+center :: Markup2
+center = wrapMarkup2 Text.Blaze.Html4.Transitional.center
+dir :: Markup2
+dir = wrapMarkup2 Text.Blaze.Html4.Transitional.dir
+font :: Markup2
+font = wrapMarkup2 Text.Blaze.Html4.Transitional.font
+iframe :: Markup2
+iframe = wrapMarkup2 Text.Blaze.Html4.Transitional.iframe
+isindex :: Markup2
+isindex = wrapMarkup2 Text.Blaze.Html4.Transitional.isindex
+menu :: Markup2
+menu = wrapMarkup2 Text.Blaze.Html4.Transitional.menu
+noframes :: Markup2
+noframes = wrapMarkup2 Text.Blaze.Html4.Transitional.noframes
+s :: Markup2
+s = wrapMarkup2 Text.Blaze.Html4.Transitional.s
+u :: Markup2
+u = wrapMarkup2 Text.Blaze.Html4.Transitional.u
+docType :: Markup
+docType = wrapMarkup Text.Blaze.Html4.Transitional.docType
+area :: Markup
+area = wrapMarkup Text.Blaze.Html4.Transitional.area
+br :: Markup
+br = wrapMarkup Text.Blaze.Html4.Transitional.br
+col :: Markup
+col = wrapMarkup Text.Blaze.Html4.Transitional.col
+hr :: Markup
+hr = wrapMarkup Text.Blaze.Html4.Transitional.hr
+link :: Markup
+link = wrapMarkup Text.Blaze.Html4.Transitional.link
+img :: Markup
+img = wrapMarkup Text.Blaze.Html4.Transitional.img
+input :: Markup
+input = wrapMarkup Text.Blaze.Html4.Transitional.input
+meta :: Markup
+meta = wrapMarkup Text.Blaze.Html4.Transitional.meta
+param :: Markup
+param = wrapMarkup Text.Blaze.Html4.Transitional.param
+basefont :: Markup
+basefont = wrapMarkup Text.Blaze.Html4.Transitional.basefont
+
diff --git a/src/Text/BlazeT/Html4/Transitional/Attributes.hs b/src/Text/BlazeT/Html4/Transitional/Attributes.hs
new file mode 100644 (file)
index 0000000..2fc0d97
--- /dev/null
@@ -0,0 +1,11 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module simply reexports the corresponding @blaze-html@ module.
+-}
+module Text.BlazeT.Html4.Transitional.Attributes
+   (module Text.Blaze.Html4.Transitional.Attributes
+   ) where
+import Text.Blaze.Html4.Transitional.Attributes
+
diff --git a/src/Text/BlazeT/Html5.hs b/src/Text/BlazeT/Html5.hs
new file mode 100644 (file)
index 0000000..8e93bf9
--- /dev/null
@@ -0,0 +1,234 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module wraps all exports of "Text.Blaze.Html5" using 'wrapMarkup' and 'wrapMarkup'.
+-}
+module Text.BlazeT.Html5
+   (module Text.BlazeT.Html5
+   ,module Text.BlazeT.Html
+   ) where
+import qualified Text.Blaze.Html5
+import           Text.BlazeT
+import           Text.BlazeT.Html
+import           Text.BlazeT.Internal
+
+docTypeHtml :: Markup2
+docTypeHtml = wrapMarkup2 Text.Blaze.Html5.docTypeHtml
+a :: Markup2
+a = wrapMarkup2 Text.Blaze.Html5.a
+abbr :: Markup2
+abbr = wrapMarkup2 Text.Blaze.Html5.abbr
+address :: Markup2
+address = wrapMarkup2 Text.Blaze.Html5.address
+article :: Markup2
+article = wrapMarkup2 Text.Blaze.Html5.article
+aside :: Markup2
+aside = wrapMarkup2 Text.Blaze.Html5.aside
+audio :: Markup2
+audio = wrapMarkup2 Text.Blaze.Html5.audio
+b :: Markup2
+b = wrapMarkup2 Text.Blaze.Html5.b
+bdo :: Markup2
+bdo = wrapMarkup2 Text.Blaze.Html5.bdo
+blockquote :: Markup2
+blockquote = wrapMarkup2 Text.Blaze.Html5.blockquote
+body :: Markup2
+body = wrapMarkup2 Text.Blaze.Html5.body
+button :: Markup2
+button = wrapMarkup2 Text.Blaze.Html5.button
+canvas :: Markup2
+canvas = wrapMarkup2 Text.Blaze.Html5.canvas
+caption :: Markup2
+caption = wrapMarkup2 Text.Blaze.Html5.caption
+cite :: Markup2
+cite = wrapMarkup2 Text.Blaze.Html5.cite
+code :: Markup2
+code = wrapMarkup2 Text.Blaze.Html5.code
+colgroup :: Markup2
+colgroup = wrapMarkup2 Text.Blaze.Html5.colgroup
+command :: Markup2
+command = wrapMarkup2 Text.Blaze.Html5.command
+datalist :: Markup2
+datalist = wrapMarkup2 Text.Blaze.Html5.datalist
+dd :: Markup2
+dd = wrapMarkup2 Text.Blaze.Html5.dd
+del :: Markup2
+del = wrapMarkup2 Text.Blaze.Html5.del
+details :: Markup2
+details = wrapMarkup2 Text.Blaze.Html5.details
+dfn :: Markup2
+dfn = wrapMarkup2 Text.Blaze.Html5.dfn
+div :: Markup2
+div = wrapMarkup2 Text.Blaze.Html5.div
+dl :: Markup2
+dl = wrapMarkup2 Text.Blaze.Html5.dl
+dt :: Markup2
+dt = wrapMarkup2 Text.Blaze.Html5.dt
+em :: Markup2
+em = wrapMarkup2 Text.Blaze.Html5.em
+fieldset :: Markup2
+fieldset = wrapMarkup2 Text.Blaze.Html5.fieldset
+figcaption :: Markup2
+figcaption = wrapMarkup2 Text.Blaze.Html5.figcaption
+figure :: Markup2
+figure = wrapMarkup2 Text.Blaze.Html5.figure
+footer :: Markup2
+footer = wrapMarkup2 Text.Blaze.Html5.footer
+form :: Markup2
+form = wrapMarkup2 Text.Blaze.Html5.form
+h1 :: Markup2
+h1 = wrapMarkup2 Text.Blaze.Html5.h1
+h2 :: Markup2
+h2 = wrapMarkup2 Text.Blaze.Html5.h2
+h3 :: Markup2
+h3 = wrapMarkup2 Text.Blaze.Html5.h3
+h4 :: Markup2
+h4 = wrapMarkup2 Text.Blaze.Html5.h4
+h5 :: Markup2
+h5 = wrapMarkup2 Text.Blaze.Html5.h5
+h6 :: Markup2
+h6 = wrapMarkup2 Text.Blaze.Html5.h6
+head :: Markup2
+head = wrapMarkup2 Text.Blaze.Html5.head
+header :: Markup2
+header = wrapMarkup2 Text.Blaze.Html5.header
+hgroup :: Markup2
+hgroup = wrapMarkup2 Text.Blaze.Html5.hgroup
+html :: Markup2
+html = wrapMarkup2 Text.Blaze.Html5.html
+i :: Markup2
+i = wrapMarkup2 Text.Blaze.Html5.i
+iframe :: Markup2
+iframe = wrapMarkup2 Text.Blaze.Html5.iframe
+ins :: Markup2
+ins = wrapMarkup2 Text.Blaze.Html5.ins
+kbd :: Markup2
+kbd = wrapMarkup2 Text.Blaze.Html5.kbd
+label :: Markup2
+label = wrapMarkup2 Text.Blaze.Html5.label
+legend :: Markup2
+legend = wrapMarkup2 Text.Blaze.Html5.legend
+li :: Markup2
+li = wrapMarkup2 Text.Blaze.Html5.li
+main :: Markup2
+main = wrapMarkup2 Text.Blaze.Html5.main
+map :: Markup2
+map = wrapMarkup2 Text.Blaze.Html5.map
+mark :: Markup2
+mark = wrapMarkup2 Text.Blaze.Html5.mark
+menu :: Markup2
+menu = wrapMarkup2 Text.Blaze.Html5.menu
+meter :: Markup2
+meter = wrapMarkup2 Text.Blaze.Html5.meter
+nav :: Markup2
+nav = wrapMarkup2 Text.Blaze.Html5.nav
+noscript :: Markup2
+noscript = wrapMarkup2 Text.Blaze.Html5.noscript
+object :: Markup2
+object = wrapMarkup2 Text.Blaze.Html5.object
+ol :: Markup2
+ol = wrapMarkup2 Text.Blaze.Html5.ol
+optgroup :: Markup2
+optgroup = wrapMarkup2 Text.Blaze.Html5.optgroup
+option :: Markup2
+option = wrapMarkup2 Text.Blaze.Html5.option
+output :: Markup2
+output = wrapMarkup2 Text.Blaze.Html5.output
+p :: Markup2
+p = wrapMarkup2 Text.Blaze.Html5.p
+pre :: Markup2
+pre = wrapMarkup2 Text.Blaze.Html5.pre
+progress :: Markup2
+progress = wrapMarkup2 Text.Blaze.Html5.progress
+q :: Markup2
+q = wrapMarkup2 Text.Blaze.Html5.q
+rp :: Markup2
+rp = wrapMarkup2 Text.Blaze.Html5.rp
+rt :: Markup2
+rt = wrapMarkup2 Text.Blaze.Html5.rt
+ruby :: Markup2
+ruby = wrapMarkup2 Text.Blaze.Html5.ruby
+samp :: Markup2
+samp = wrapMarkup2 Text.Blaze.Html5.samp
+script :: Markup2
+script = wrapMarkup2 Text.Blaze.Html5.script
+section :: Markup2
+section = wrapMarkup2 Text.Blaze.Html5.section
+select :: Markup2
+select = wrapMarkup2 Text.Blaze.Html5.select
+small :: Markup2
+small = wrapMarkup2 Text.Blaze.Html5.small
+span :: Markup2
+span = wrapMarkup2 Text.Blaze.Html5.span
+strong :: Markup2
+strong = wrapMarkup2 Text.Blaze.Html5.strong
+style :: Markup2
+style = wrapMarkup2 Text.Blaze.Html5.style
+sub :: Markup2
+sub = wrapMarkup2 Text.Blaze.Html5.sub
+summary :: Markup2
+summary = wrapMarkup2 Text.Blaze.Html5.summary
+sup :: Markup2
+sup = wrapMarkup2 Text.Blaze.Html5.sup
+table :: Markup2
+table = wrapMarkup2 Text.Blaze.Html5.table
+tbody :: Markup2
+tbody = wrapMarkup2 Text.Blaze.Html5.tbody
+td :: Markup2
+td = wrapMarkup2 Text.Blaze.Html5.td
+textarea :: Markup2
+textarea = wrapMarkup2 Text.Blaze.Html5.textarea
+tfoot :: Markup2
+tfoot = wrapMarkup2 Text.Blaze.Html5.tfoot
+th :: Markup2
+th = wrapMarkup2 Text.Blaze.Html5.th
+thead :: Markup2
+thead = wrapMarkup2 Text.Blaze.Html5.thead
+time :: Markup2
+time = wrapMarkup2 Text.Blaze.Html5.time
+title :: Markup2
+title = wrapMarkup2 Text.Blaze.Html5.title
+tr :: Markup2
+tr = wrapMarkup2 Text.Blaze.Html5.tr
+ul :: Markup2
+ul = wrapMarkup2 Text.Blaze.Html5.ul
+var :: Markup2
+var = wrapMarkup2 Text.Blaze.Html5.var
+video :: Markup2
+video = wrapMarkup2 Text.Blaze.Html5.video
+docType :: Markup
+docType = wrapMarkup Text.Blaze.Html5.docType
+area :: Markup
+area = wrapMarkup Text.Blaze.Html5.area
+base :: Markup
+base = wrapMarkup Text.Blaze.Html5.base
+br :: Markup
+br = wrapMarkup Text.Blaze.Html5.br
+col :: Markup
+col = wrapMarkup Text.Blaze.Html5.col
+embed :: Markup
+embed = wrapMarkup Text.Blaze.Html5.embed
+hr :: Markup
+hr = wrapMarkup Text.Blaze.Html5.hr
+img :: Markup
+img = wrapMarkup Text.Blaze.Html5.img
+input :: Markup
+input = wrapMarkup Text.Blaze.Html5.input
+keygen :: Markup
+keygen = wrapMarkup Text.Blaze.Html5.keygen
+link :: Markup
+link = wrapMarkup Text.Blaze.Html5.link
+menuitem :: Markup
+menuitem = wrapMarkup Text.Blaze.Html5.menuitem
+meta :: Markup
+meta = wrapMarkup Text.Blaze.Html5.meta
+param :: Markup
+param = wrapMarkup Text.Blaze.Html5.param
+source :: Markup
+source = wrapMarkup Text.Blaze.Html5.source
+track :: Markup
+track = wrapMarkup Text.Blaze.Html5.track
+wbr :: Markup
+wbr = wrapMarkup Text.Blaze.Html5.wbr
+
diff --git a/src/Text/BlazeT/Html5/Attributes.hs b/src/Text/BlazeT/Html5/Attributes.hs
new file mode 100644 (file)
index 0000000..1bcd773
--- /dev/null
@@ -0,0 +1,11 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module simply reexports the corresponding @blaze-html@ module.
+-}
+module Text.BlazeT.Html5.Attributes
+   (module Text.Blaze.Html5.Attributes
+   ) where
+import Text.Blaze.Html5.Attributes
+
diff --git a/src/Text/BlazeT/Internal.hs b/src/Text/BlazeT/Internal.hs
new file mode 100644 (file)
index 0000000..24ef1fe
--- /dev/null
@@ -0,0 +1,238 @@
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE CPP #-}
+#if MIN_VERSION_blaze_markup(0,7,1)
+#define PRE_BUILDER
+#endif
+module Text.BlazeT.Internal
+    (
+      -- * Important types.
+      B.ChoiceString (..)
+    , B.StaticString (..)
+    , MarkupM
+    , Markup
+    , B.Tag
+    , B.Attribute
+    , B.AttributeValue
+
+      -- * Creating custom tags and attributes.
+    , customParent
+    , customLeaf
+    , B.attribute
+    , B.dataAttribute
+    , B.customAttribute
+
+      -- * Converting values to Markup.
+    , text
+    , preEscapedText
+    , lazyText
+    , preEscapedLazyText
+    , textBuilder
+    , preEscapedTextBuilder
+    , string
+    , preEscapedString
+    , unsafeByteString
+    , unsafeLazyByteString
+
+      -- * Comments
+    , B.textComment
+    , B.lazyTextComment
+    , B.stringComment
+    , B.unsafeByteStringComment
+    , B.unsafeLazyByteStringComment
+
+      -- * Converting values to tags.
+    , B.textTag
+    , B.stringTag
+
+      -- * Converting values to attribute values.
+    , B.textValue
+    , B.preEscapedTextValue
+    , B.lazyTextValue
+    , B.preEscapedLazyTextValue
+    , B.textBuilderValue
+    , B.preEscapedTextBuilderValue
+    , B.stringValue
+    , B.preEscapedStringValue
+    , B.unsafeByteStringValue
+    , B.unsafeLazyByteStringValue
+
+      -- * Setting attributes
+    , B.Attributable
+    , (B.!)
+    , (B.!?)
+
+      -- * Modifying Markup elements
+    , contents
+    , external
+
+      -- * Querying Markup elements
+    , null
+
+    -- * BlazeT new stuff
+    ,Markup2
+    ,mapMarkupT
+    ,MarkupT
+    ,runMarkup
+    ,runMarkupT
+    ,execMarkup
+    ,execMarkupT
+    ,wrapMarkup
+    ,wrapMarkupT
+    ,wrapMarkup2
+    ,wrapMarkupT2
+  ) where
+
+import           Control.Monad.Identity
+import           Control.Monad.Trans.Class
+import           Control.Monad.Writer.Strict
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BL
+import           Data.String
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as LT
+import qualified Data.Text.Lazy.Builder as LTB
+import qualified Text.Blaze as B
+import qualified Text.Blaze.Internal as B
+
+newtype MarkupT m a= MarkupT { fromMarkupT :: WriterT B.Markup m a }
+                     deriving (Functor
+#if MIN_VERSION_base(4,8,0)
+                              ,Applicative
+#endif
+                              ,Monad
+                              ,MonadWriter B.Markup
+                              ,MonadTrans
+                              )
+
+-- | Map both the return value and markup of a computation using the
+-- given function
+mapMarkupT :: (m (a,B.Markup) -> n (b,B.Markup)) -> MarkupT m a -> MarkupT n b
+mapMarkupT f = MarkupT . mapWriterT f . fromMarkupT
+{-# INLINE mapMarkupT #-}
+
+type MarkupM = MarkupT Identity
+type Markup = forall m . Monad m => MarkupT m ()
+type Markup2 = forall m . Monad m => MarkupT m () -> MarkupT m ()
+
+runMarkupT :: MarkupT m a -> m (a,B.Markup)
+runMarkupT = runWriterT . fromMarkupT
+{-# INLINE runMarkupT #-}
+
+execMarkupT :: Monad m => MarkupT m a -> m B.Markup
+execMarkupT = liftM snd . runMarkupT
+{-# INLINE execMarkupT #-}
+
+runMarkup :: MarkupM a -> (a,B.Markup)
+runMarkup = runIdentity . runMarkupT
+{-# INLINE runMarkup #-}
+
+execMarkup :: MarkupM a -> B.Markup
+execMarkup = snd . runMarkup
+{-# INLINE execMarkup #-}
+
+-- instance MonadTrans MarkupT where
+
+
+instance (Monad m,Monoid a) => Monoid (MarkupT m a) where
+  mempty = return mempty
+  {-# INLINE mempty #-}
+  a `mappend` b = do {a' <- a; b >>= return . (mappend a')}
+  {-# INLINE mappend #-}
+
+
+instance Monad m => B.Attributable (MarkupT m a) where
+  h ! a = wrapMarkupT2 (B.! a) h
+  {-# INLINE (!) #-}
+
+instance Monad m => B.Attributable (a -> MarkupT m b) where
+  h ! a = \x -> wrapMarkupT2 (B.! a) $ h x
+  {-# INLINE (!) #-}
+
+instance Monad m => IsString (MarkupT m ()) where
+  fromString = wrapMarkup . fromString
+  {-# INLINE fromString #-}
+
+wrapMarkupT :: Monad m => B.Markup -> MarkupT m ()
+wrapMarkupT = tell
+{-# INLINE wrapMarkupT #-}
+
+wrapMarkup :: B.Markup -> Markup
+wrapMarkup = wrapMarkupT
+{-# INLINE wrapMarkup #-}
+
+wrapMarkupT2 ::  Monad m => (B.Markup -> B.Markup)
+                 -> MarkupT m a -> MarkupT m a
+wrapMarkupT2 = censor
+{-# INLINE wrapMarkupT2 #-}
+
+wrapMarkup2 :: (B.Markup -> B.Markup) -> Markup2
+wrapMarkup2 = wrapMarkupT2
+{-# INLINE wrapMarkup2 #-}
+
+unsafeByteString :: BS.ByteString -> Markup
+unsafeByteString = wrapMarkup . B.unsafeByteString
+{-# INLINE unsafeByteString #-}
+
+-- | Insert a lazy 'BL.ByteString'. See 'unsafeByteString' for reasons why this
+-- is an unsafe operation.
+--
+unsafeLazyByteString :: BL.ByteString  -- ^ Value to insert
+                     -> Markup         -- ^ Resulting HTML fragment
+unsafeLazyByteString = wrapMarkup . B.unsafeLazyByteString
+{-# INLINE unsafeLazyByteString #-}
+
+external :: Monad m => MarkupT m a -> MarkupT m a
+external = wrapMarkupT2  B.external
+{-# INLINE external #-}
+
+contents :: Monad m => MarkupT m a -> MarkupT m a
+contents = wrapMarkupT2  B.contents
+{-# INLINE contents #-}
+
+customParent ::B.Tag -> Markup2
+customParent = wrapMarkup2 . B.customParent
+{-# INLINE customParent #-}
+
+customLeaf :: B.Tag -> Bool -> Markup
+customLeaf = fmap wrapMarkup . B.customLeaf
+{-# INLINE customLeaf #-}
+
+preEscapedText :: T.Text -> Markup
+preEscapedText = wrapMarkup . B.preEscapedText
+{-# INLINE preEscapedText #-}
+
+preEscapedLazyText :: LT.Text -> Markup
+preEscapedLazyText = wrapMarkup . B.preEscapedLazyText
+{-# INLINE preEscapedLazyText #-}
+
+preEscapedTextBuilder :: LTB.Builder -> Markup
+textBuilder :: LTB.Builder -> Markup
+
+#ifdef PRE_BUILDER
+preEscapedTextBuilder = wrapMarkup . B.preEscapedTextBuilder
+textBuilder = wrapMarkup . B.textBuilder
+{-# INLINE preEscapedTextBuilder #-}
+{-# INLINE textBuilder #-}
+#else
+preEscapedTextBuilder = error "This function needs blaze-markup 0.7.1.0"
+textBuilder = error "This function needs blaze-markup 0.7.1.0"
+#endif
+
+preEscapedString :: String -> Markup
+preEscapedString = wrapMarkup . B.preEscapedString
+{-# INLINE preEscapedString #-}
+
+string :: String -> Markup
+string = wrapMarkup . B.string
+{-# INLINE string #-}
+
+text :: T.Text -> Markup
+text = wrapMarkup . B.text
+{-# INLINE text #-}
+
+lazyText :: LT.Text -> Markup
+lazyText = wrapMarkup . B.lazyText
+{-# INLINE lazyText #-}
diff --git a/src/Text/BlazeT/Renderer/Pretty.hs b/src/Text/BlazeT/Renderer/Pretty.hs
new file mode 100644 (file)
index 0000000..8977c94
--- /dev/null
@@ -0,0 +1,22 @@
+module Text.BlazeT.Renderer.Pretty
+    ( renderMarkup
+    , renderHtml
+    , renderMarkupT
+    , renderHtmlT
+  ) where
+
+import           Control.Monad
+import           Control.Monad.Identity
+import qualified Text.Blaze.Renderer.Pretty as BU
+import           Text.BlazeT
+
+renderMarkup :: MarkupM a -> String
+renderMarkup = runIdentity . renderMarkupT
+renderMarkupT :: Monad m => MarkupT m a -> m String
+renderMarkupT = liftM BU.renderMarkup . execMarkupT
+
+renderHtml :: MarkupM a -> String
+renderHtml = renderMarkup
+renderHtmlT :: Monad m => MarkupT m a -> m String
+renderHtmlT = renderMarkupT
+
diff --git a/src/Text/BlazeT/Renderer/String.hs b/src/Text/BlazeT/Renderer/String.hs
new file mode 100644 (file)
index 0000000..0a2de8a
--- /dev/null
@@ -0,0 +1,27 @@
+module Text.BlazeT.Renderer.String
+    ( fromChoiceString
+    , renderMarkup
+    , renderHtml
+    , renderMarkupT
+    , renderHtmlT
+  ) where
+
+import           Control.Monad
+import           Control.Monad.Identity
+import           Text.Blaze.Internal (ChoiceString)
+import qualified Text.Blaze.Renderer.String as BU
+import           Text.BlazeT
+
+fromChoiceString :: ChoiceString -> String -> String       
+fromChoiceString = BU.fromChoiceString
+
+renderMarkup :: MarkupM a -> String
+renderMarkup = runIdentity . renderMarkupT
+renderMarkupT :: Monad m => MarkupT m a -> m String
+renderMarkupT = liftM BU.renderMarkup . execMarkupT
+
+renderHtml :: MarkupM a -> String
+renderHtml = renderMarkup
+renderHtmlT :: Monad m => MarkupT m a -> m String
+renderHtmlT = renderMarkupT
+
diff --git a/src/Text/BlazeT/Renderer/Text.hs b/src/Text/BlazeT/Renderer/Text.hs
new file mode 100644 (file)
index 0000000..31181eb
--- /dev/null
@@ -0,0 +1,75 @@
+module Text.BlazeT.Renderer.Text
+    ( renderMarkupBuilderT
+    , renderMarkupBuilder
+    , renderMarkupBuilderWithT
+    , renderMarkupT
+    , renderMarkupWithT
+    , renderHtmlBuilderT
+    , renderHtmlBuilderWithT
+    , renderHtmlT
+    , renderHtmlWithT
+    , renderMarkupBuilderWith
+    , renderMarkup
+    , renderMarkupWith
+    , renderHtmlBuilder
+    , renderHtmlBuilderWith
+    , renderHtml
+    , renderHtmlWith
+  ) where
+
+import           Control.Monad
+import           Data.ByteString (ByteString)
+import           Control.Monad.Identity
+import           Data.Text (Text)
+import qualified Data.Text.Lazy as L
+import qualified Data.Text.Lazy.Builder as B
+import qualified Text.Blaze.Html.Renderer.Text as BH
+import qualified Text.Blaze.Renderer.Text as BU
+import           Text.BlazeT
+
+renderMarkupBuilder :: MarkupM a -> B.Builder
+renderMarkupBuilder = runIdentity . renderMarkupBuilderT
+
+renderMarkupBuilderT :: Monad m => MarkupT m a -> m B.Builder
+renderMarkupBuilderT = liftM BU.renderMarkupBuilder . execMarkupT
+
+renderHtmlBuilder :: MarkupM a -> B.Builder
+renderHtmlBuilder = renderMarkupBuilder
+
+renderHtmlBuilderT :: Monad m => MarkupT m a -> m B.Builder
+renderHtmlBuilderT = renderMarkupBuilderT
+
+renderMarkup :: MarkupM a -> L.Text
+renderMarkup = runIdentity . renderMarkupT
+renderMarkupT :: Monad m => MarkupT m a -> m L.Text
+renderMarkupT = liftM BU.renderMarkup . execMarkupT
+
+renderHtml :: MarkupM a -> L.Text
+renderHtml = renderMarkup
+renderHtmlT :: Monad m => MarkupT m a -> m L.Text
+renderHtmlT = renderMarkupT
+
+renderMarkupWithT :: Monad m => (ByteString -> Text) -> MarkupT m a -> m L.Text
+renderMarkupWithT g = liftM (BU.renderMarkupWith g) . execMarkupT
+
+renderMarkupWith :: (ByteString -> Text) -> MarkupM a -> L.Text
+renderMarkupWith g = runIdentity . renderMarkupWithT g
+
+renderHtmlWithT :: Monad m => (ByteString -> Text) -> MarkupT m a -> m L.Text
+renderHtmlWithT g = liftM (BH.renderHtmlWith g) . execMarkupT
+
+renderHtmlWith :: (ByteString -> Text) -> MarkupM a -> L.Text
+renderHtmlWith g = runIdentity . renderHtmlWithT g
+
+renderHtmlBuilderWithT :: Monad m => (ByteString -> Text) -> MarkupT m a -> m B.Builder       
+renderHtmlBuilderWithT g = liftM (BH.renderHtmlBuilderWith g) . execMarkupT
+
+renderHtmlBuilderWith :: (ByteString -> Text) -> MarkupM a -> B.Builder       
+renderHtmlBuilderWith g = runIdentity . renderHtmlBuilderWithT g
+
+
+renderMarkupBuilderWithT :: Monad m => (ByteString -> Text) -> MarkupT m a -> m B.Builder      
+renderMarkupBuilderWithT g = liftM (BU.renderMarkupBuilderWith g) . execMarkupT
+
+renderMarkupBuilderWith :: (ByteString -> Text) -> MarkupM a -> B.Builder       
+renderMarkupBuilderWith g = runIdentity . renderMarkupBuilderWithT g
diff --git a/src/Text/BlazeT/Renderer/Utf8.hs b/src/Text/BlazeT/Renderer/Utf8.hs
new file mode 100644 (file)
index 0000000..292f81f
--- /dev/null
@@ -0,0 +1,66 @@
+{-# OPTIONS_GHC -fsimpl-tick-factor=230 #-}
+
+-- the above option was not needed with
+  --   ,blaze-html >= 0.6.0.0 && < 0.7.0.0
+  --   ,blaze-builder >= 0.2
+  --   ,text  < 1.2
+
+module Text.BlazeT.Renderer.Utf8
+    (
+    renderMarkupBuilder
+    , renderMarkup
+    , renderMarkupToByteStringIO
+    , renderHtmlBuilder
+    , renderHtml
+    , renderHtmlToByteStringIO
+
+    -- * new BlazeT stuff
+    , renderMarkupBuilderT
+    , renderMarkupT
+    , renderMarkupToByteStringIOT
+    , renderHtmlToByteStringIOT
+    , renderHtmlBuilderT
+    , renderHtmlT
+  ) where
+
+import qualified Blaze.ByteString.Builder as B
+import           Control.Monad
+import           Control.Monad.Identity
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BL
+import qualified Text.Blaze.Renderer.Utf8 as BU
+import           Text.BlazeT
+
+renderMarkupBuilder :: MarkupM a -> B.Builder
+renderMarkupBuilder = runIdentity . renderMarkupBuilderT
+
+renderMarkupBuilderT :: Monad m => MarkupT m a -> m B.Builder
+renderMarkupBuilderT = liftM BU.renderMarkupBuilder . execMarkupT
+
+renderHtmlBuilder :: MarkupM a -> B.Builder
+renderHtmlBuilder = renderMarkupBuilder
+
+renderHtmlBuilderT :: Monad m => MarkupT m a -> m B.Builder
+renderHtmlBuilderT = renderMarkupBuilderT
+
+renderMarkup :: MarkupM a -> BL.ByteString
+renderMarkup = runIdentity . renderMarkupT
+renderMarkupT :: Monad m => MarkupT m a -> m BL.ByteString
+renderMarkupT = liftM BU.renderMarkup . execMarkupT
+
+renderHtml :: MarkupM a -> BL.ByteString
+renderHtml = renderMarkup
+renderHtmlT :: Monad m => MarkupT m a -> m BL.ByteString
+renderHtmlT = renderMarkupT
+
+renderMarkupToByteStringIO :: (BS.ByteString -> IO ()) -> MarkupM a -> IO ()
+renderMarkupToByteStringIO g = runIdentity . renderMarkupToByteStringIOT g 
+renderMarkupToByteStringIOT :: Monad m => (BS.ByteString -> IO ()) ->
+                               MarkupT m a -> m (IO ())
+renderMarkupToByteStringIOT g = liftM (BU.renderMarkupToByteStringIO g) . execMarkupT
+
+renderHtmlToByteStringIO :: (BS.ByteString -> IO ()) -> MarkupM a -> IO ()
+renderHtmlToByteStringIO g = runIdentity . renderMarkupToByteStringIOT g 
+renderHtmlToByteStringIOT :: Monad m => (BS.ByteString -> IO ()) ->
+                             MarkupT m a -> m (IO ())
+renderHtmlToByteStringIOT g = liftM (BU.renderMarkupToByteStringIO g) . execMarkupT
diff --git a/src/Text/BlazeT/XHtml1/FrameSet.hs b/src/Text/BlazeT/XHtml1/FrameSet.hs
new file mode 100644 (file)
index 0000000..57edcd5
--- /dev/null
@@ -0,0 +1,198 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module wraps all exports of "Text.Blaze.XHtml1.FrameSet" using 'wrapMarkup' and 'wrapMarkup'.
+-}
+module Text.BlazeT.XHtml1.FrameSet
+   (module Text.BlazeT.XHtml1.FrameSet
+   ,module Text.BlazeT.Html
+   ) where
+import qualified Text.Blaze.XHtml1.FrameSet
+import           Text.BlazeT
+import           Text.BlazeT.Html
+import           Text.BlazeT.Internal
+
+docTypeHtml :: Markup2
+docTypeHtml = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.docTypeHtml
+a :: Markup2
+a = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.a
+abbr :: Markup2
+abbr = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.abbr
+acronym :: Markup2
+acronym = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.acronym
+address :: Markup2
+address = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.address
+b :: Markup2
+b = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.b
+bdo :: Markup2
+bdo = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.bdo
+big :: Markup2
+big = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.big
+blockquote :: Markup2
+blockquote = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.blockquote
+body :: Markup2
+body = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.body
+button :: Markup2
+button = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.button
+caption :: Markup2
+caption = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.caption
+cite :: Markup2
+cite = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.cite
+code :: Markup2
+code = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.code
+colgroup :: Markup2
+colgroup = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.colgroup
+dd :: Markup2
+dd = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.dd
+del :: Markup2
+del = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.del
+dfn :: Markup2
+dfn = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.dfn
+div :: Markup2
+div = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.div
+dl :: Markup2
+dl = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.dl
+dt :: Markup2
+dt = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.dt
+em :: Markup2
+em = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.em
+fieldset :: Markup2
+fieldset = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.fieldset
+form :: Markup2
+form = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.form
+h1 :: Markup2
+h1 = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.h1
+h2 :: Markup2
+h2 = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.h2
+h3 :: Markup2
+h3 = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.h3
+h4 :: Markup2
+h4 = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.h4
+h5 :: Markup2
+h5 = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.h5
+h6 :: Markup2
+h6 = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.h6
+head :: Markup2
+head = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.head
+html :: Markup2
+html = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.html
+i :: Markup2
+i = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.i
+ins :: Markup2
+ins = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.ins
+kbd :: Markup2
+kbd = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.kbd
+label :: Markup2
+label = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.label
+legend :: Markup2
+legend = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.legend
+li :: Markup2
+li = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.li
+map :: Markup2
+map = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.map
+noscript :: Markup2
+noscript = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.noscript
+object :: Markup2
+object = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.object
+ol :: Markup2
+ol = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.ol
+optgroup :: Markup2
+optgroup = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.optgroup
+option :: Markup2
+option = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.option
+p :: Markup2
+p = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.p
+pre :: Markup2
+pre = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.pre
+q :: Markup2
+q = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.q
+samp :: Markup2
+samp = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.samp
+script :: Markup2
+script = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.script
+select :: Markup2
+select = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.select
+small :: Markup2
+small = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.small
+span :: Markup2
+span = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.span
+strong :: Markup2
+strong = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.strong
+style :: Markup2
+style = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.style
+sub :: Markup2
+sub = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.sub
+sup :: Markup2
+sup = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.sup
+table :: Markup2
+table = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.table
+tbody :: Markup2
+tbody = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.tbody
+td :: Markup2
+td = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.td
+textarea :: Markup2
+textarea = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.textarea
+tfoot :: Markup2
+tfoot = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.tfoot
+th :: Markup2
+th = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.th
+thead :: Markup2
+thead = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.thead
+title :: Markup2
+title = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.title
+tr :: Markup2
+tr = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.tr
+tt :: Markup2
+tt = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.tt
+ul :: Markup2
+ul = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.ul
+var :: Markup2
+var = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.var
+applet :: Markup2
+applet = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.applet
+center :: Markup2
+center = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.center
+dir :: Markup2
+dir = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.dir
+font :: Markup2
+font = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.font
+iframe :: Markup2
+iframe = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.iframe
+isindex :: Markup2
+isindex = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.isindex
+menu :: Markup2
+menu = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.menu
+noframes :: Markup2
+noframes = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.noframes
+s :: Markup2
+s = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.s
+u :: Markup2
+u = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.u
+frameset :: Markup2
+frameset = wrapMarkup2 Text.Blaze.XHtml1.FrameSet.frameset
+docType :: Markup
+docType = wrapMarkup Text.Blaze.XHtml1.FrameSet.docType
+area :: Markup
+area = wrapMarkup Text.Blaze.XHtml1.FrameSet.area
+br :: Markup
+br = wrapMarkup Text.Blaze.XHtml1.FrameSet.br
+col :: Markup
+col = wrapMarkup Text.Blaze.XHtml1.FrameSet.col
+hr :: Markup
+hr = wrapMarkup Text.Blaze.XHtml1.FrameSet.hr
+link :: Markup
+link = wrapMarkup Text.Blaze.XHtml1.FrameSet.link
+img :: Markup
+img = wrapMarkup Text.Blaze.XHtml1.FrameSet.img
+input :: Markup
+input = wrapMarkup Text.Blaze.XHtml1.FrameSet.input
+meta :: Markup
+meta = wrapMarkup Text.Blaze.XHtml1.FrameSet.meta
+param :: Markup
+param = wrapMarkup Text.Blaze.XHtml1.FrameSet.param
+basefont :: Markup
+basefont = wrapMarkup Text.Blaze.XHtml1.FrameSet.basefont
+frame :: Markup
+frame = wrapMarkup Text.Blaze.XHtml1.FrameSet.frame
+
diff --git a/src/Text/BlazeT/XHtml1/FrameSet/Attributes.hs b/src/Text/BlazeT/XHtml1/FrameSet/Attributes.hs
new file mode 100644 (file)
index 0000000..af4ecbe
--- /dev/null
@@ -0,0 +1,11 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module simply reexports the corresponding @blaze-html@ module.
+-}
+module Text.BlazeT.XHtml1.FrameSet.Attributes
+   (module Text.Blaze.XHtml1.FrameSet.Attributes
+   ) where
+import Text.Blaze.XHtml1.FrameSet.Attributes
+
diff --git a/src/Text/BlazeT/XHtml1/Strict.hs b/src/Text/BlazeT/XHtml1/Strict.hs
new file mode 100644 (file)
index 0000000..0bca241
--- /dev/null
@@ -0,0 +1,172 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module wraps all exports of "Text.Blaze.XHtml1.Strict" using 'wrapMarkup' and 'wrapMarkup'.
+-}
+module Text.BlazeT.XHtml1.Strict
+   (module Text.BlazeT.XHtml1.Strict
+   ,module Text.BlazeT.Html
+   ) where
+import qualified Text.Blaze.XHtml1.Strict
+import           Text.BlazeT
+import           Text.BlazeT.Html
+import           Text.BlazeT.Internal
+
+docTypeHtml :: Markup2
+docTypeHtml = wrapMarkup2 Text.Blaze.XHtml1.Strict.docTypeHtml
+a :: Markup2
+a = wrapMarkup2 Text.Blaze.XHtml1.Strict.a
+abbr :: Markup2
+abbr = wrapMarkup2 Text.Blaze.XHtml1.Strict.abbr
+acronym :: Markup2
+acronym = wrapMarkup2 Text.Blaze.XHtml1.Strict.acronym
+address :: Markup2
+address = wrapMarkup2 Text.Blaze.XHtml1.Strict.address
+b :: Markup2
+b = wrapMarkup2 Text.Blaze.XHtml1.Strict.b
+bdo :: Markup2
+bdo = wrapMarkup2 Text.Blaze.XHtml1.Strict.bdo
+big :: Markup2
+big = wrapMarkup2 Text.Blaze.XHtml1.Strict.big
+blockquote :: Markup2
+blockquote = wrapMarkup2 Text.Blaze.XHtml1.Strict.blockquote
+body :: Markup2
+body = wrapMarkup2 Text.Blaze.XHtml1.Strict.body
+button :: Markup2
+button = wrapMarkup2 Text.Blaze.XHtml1.Strict.button
+caption :: Markup2
+caption = wrapMarkup2 Text.Blaze.XHtml1.Strict.caption
+cite :: Markup2
+cite = wrapMarkup2 Text.Blaze.XHtml1.Strict.cite
+code :: Markup2
+code = wrapMarkup2 Text.Blaze.XHtml1.Strict.code
+colgroup :: Markup2
+colgroup = wrapMarkup2 Text.Blaze.XHtml1.Strict.colgroup
+dd :: Markup2
+dd = wrapMarkup2 Text.Blaze.XHtml1.Strict.dd
+del :: Markup2
+del = wrapMarkup2 Text.Blaze.XHtml1.Strict.del
+dfn :: Markup2
+dfn = wrapMarkup2 Text.Blaze.XHtml1.Strict.dfn
+div :: Markup2
+div = wrapMarkup2 Text.Blaze.XHtml1.Strict.div
+dl :: Markup2
+dl = wrapMarkup2 Text.Blaze.XHtml1.Strict.dl
+dt :: Markup2
+dt = wrapMarkup2 Text.Blaze.XHtml1.Strict.dt
+em :: Markup2
+em = wrapMarkup2 Text.Blaze.XHtml1.Strict.em
+fieldset :: Markup2
+fieldset = wrapMarkup2 Text.Blaze.XHtml1.Strict.fieldset
+form :: Markup2
+form = wrapMarkup2 Text.Blaze.XHtml1.Strict.form
+h1 :: Markup2
+h1 = wrapMarkup2 Text.Blaze.XHtml1.Strict.h1
+h2 :: Markup2
+h2 = wrapMarkup2 Text.Blaze.XHtml1.Strict.h2
+h3 :: Markup2
+h3 = wrapMarkup2 Text.Blaze.XHtml1.Strict.h3
+h4 :: Markup2
+h4 = wrapMarkup2 Text.Blaze.XHtml1.Strict.h4
+h5 :: Markup2
+h5 = wrapMarkup2 Text.Blaze.XHtml1.Strict.h5
+h6 :: Markup2
+h6 = wrapMarkup2 Text.Blaze.XHtml1.Strict.h6
+head :: Markup2
+head = wrapMarkup2 Text.Blaze.XHtml1.Strict.head
+html :: Markup2
+html = wrapMarkup2 Text.Blaze.XHtml1.Strict.html
+i :: Markup2
+i = wrapMarkup2 Text.Blaze.XHtml1.Strict.i
+ins :: Markup2
+ins = wrapMarkup2 Text.Blaze.XHtml1.Strict.ins
+kbd :: Markup2
+kbd = wrapMarkup2 Text.Blaze.XHtml1.Strict.kbd
+label :: Markup2
+label = wrapMarkup2 Text.Blaze.XHtml1.Strict.label
+legend :: Markup2
+legend = wrapMarkup2 Text.Blaze.XHtml1.Strict.legend
+li :: Markup2
+li = wrapMarkup2 Text.Blaze.XHtml1.Strict.li
+map :: Markup2
+map = wrapMarkup2 Text.Blaze.XHtml1.Strict.map
+noscript :: Markup2
+noscript = wrapMarkup2 Text.Blaze.XHtml1.Strict.noscript
+object :: Markup2
+object = wrapMarkup2 Text.Blaze.XHtml1.Strict.object
+ol :: Markup2
+ol = wrapMarkup2 Text.Blaze.XHtml1.Strict.ol
+optgroup :: Markup2
+optgroup = wrapMarkup2 Text.Blaze.XHtml1.Strict.optgroup
+option :: Markup2
+option = wrapMarkup2 Text.Blaze.XHtml1.Strict.option
+p :: Markup2
+p = wrapMarkup2 Text.Blaze.XHtml1.Strict.p
+pre :: Markup2
+pre = wrapMarkup2 Text.Blaze.XHtml1.Strict.pre
+q :: Markup2
+q = wrapMarkup2 Text.Blaze.XHtml1.Strict.q
+samp :: Markup2
+samp = wrapMarkup2 Text.Blaze.XHtml1.Strict.samp
+script :: Markup2
+script = wrapMarkup2 Text.Blaze.XHtml1.Strict.script
+select :: Markup2
+select = wrapMarkup2 Text.Blaze.XHtml1.Strict.select
+small :: Markup2
+small = wrapMarkup2 Text.Blaze.XHtml1.Strict.small
+span :: Markup2
+span = wrapMarkup2 Text.Blaze.XHtml1.Strict.span
+strong :: Markup2
+strong = wrapMarkup2 Text.Blaze.XHtml1.Strict.strong
+style :: Markup2
+style = wrapMarkup2 Text.Blaze.XHtml1.Strict.style
+sub :: Markup2
+sub = wrapMarkup2 Text.Blaze.XHtml1.Strict.sub
+sup :: Markup2
+sup = wrapMarkup2 Text.Blaze.XHtml1.Strict.sup
+table :: Markup2
+table = wrapMarkup2 Text.Blaze.XHtml1.Strict.table
+tbody :: Markup2
+tbody = wrapMarkup2 Text.Blaze.XHtml1.Strict.tbody
+td :: Markup2
+td = wrapMarkup2 Text.Blaze.XHtml1.Strict.td
+textarea :: Markup2
+textarea = wrapMarkup2 Text.Blaze.XHtml1.Strict.textarea
+tfoot :: Markup2
+tfoot = wrapMarkup2 Text.Blaze.XHtml1.Strict.tfoot
+th :: Markup2
+th = wrapMarkup2 Text.Blaze.XHtml1.Strict.th
+thead :: Markup2
+thead = wrapMarkup2 Text.Blaze.XHtml1.Strict.thead
+title :: Markup2
+title = wrapMarkup2 Text.Blaze.XHtml1.Strict.title
+tr :: Markup2
+tr = wrapMarkup2 Text.Blaze.XHtml1.Strict.tr
+tt :: Markup2
+tt = wrapMarkup2 Text.Blaze.XHtml1.Strict.tt
+ul :: Markup2
+ul = wrapMarkup2 Text.Blaze.XHtml1.Strict.ul
+var :: Markup2
+var = wrapMarkup2 Text.Blaze.XHtml1.Strict.var
+docType :: Markup
+docType = wrapMarkup Text.Blaze.XHtml1.Strict.docType
+area :: Markup
+area = wrapMarkup Text.Blaze.XHtml1.Strict.area
+br :: Markup
+br = wrapMarkup Text.Blaze.XHtml1.Strict.br
+col :: Markup
+col = wrapMarkup Text.Blaze.XHtml1.Strict.col
+hr :: Markup
+hr = wrapMarkup Text.Blaze.XHtml1.Strict.hr
+link :: Markup
+link = wrapMarkup Text.Blaze.XHtml1.Strict.link
+img :: Markup
+img = wrapMarkup Text.Blaze.XHtml1.Strict.img
+input :: Markup
+input = wrapMarkup Text.Blaze.XHtml1.Strict.input
+meta :: Markup
+meta = wrapMarkup Text.Blaze.XHtml1.Strict.meta
+param :: Markup
+param = wrapMarkup Text.Blaze.XHtml1.Strict.param
+
diff --git a/src/Text/BlazeT/XHtml1/Strict/Attributes.hs b/src/Text/BlazeT/XHtml1/Strict/Attributes.hs
new file mode 100644 (file)
index 0000000..c7e07d4
--- /dev/null
@@ -0,0 +1,11 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module simply reexports the corresponding @blaze-html@ module.
+-}
+module Text.BlazeT.XHtml1.Strict.Attributes
+   (module Text.Blaze.XHtml1.Strict.Attributes
+   ) where
+import Text.Blaze.XHtml1.Strict.Attributes
+
diff --git a/src/Text/BlazeT/XHtml1/Transitional.hs b/src/Text/BlazeT/XHtml1/Transitional.hs
new file mode 100644 (file)
index 0000000..b1e6aad
--- /dev/null
@@ -0,0 +1,194 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module wraps all exports of "Text.Blaze.XHtml1.Transitional" using 'wrapMarkup' and 'wrapMarkup'.
+-}
+module Text.BlazeT.XHtml1.Transitional
+   (module Text.BlazeT.XHtml1.Transitional
+   ,module Text.BlazeT.Html
+   ) where
+import qualified Text.Blaze.XHtml1.Transitional
+import           Text.BlazeT
+import           Text.BlazeT.Html
+import           Text.BlazeT.Internal
+
+docTypeHtml :: Markup2
+docTypeHtml = wrapMarkup2 Text.Blaze.XHtml1.Transitional.docTypeHtml
+a :: Markup2
+a = wrapMarkup2 Text.Blaze.XHtml1.Transitional.a
+abbr :: Markup2
+abbr = wrapMarkup2 Text.Blaze.XHtml1.Transitional.abbr
+acronym :: Markup2
+acronym = wrapMarkup2 Text.Blaze.XHtml1.Transitional.acronym
+address :: Markup2
+address = wrapMarkup2 Text.Blaze.XHtml1.Transitional.address
+b :: Markup2
+b = wrapMarkup2 Text.Blaze.XHtml1.Transitional.b
+bdo :: Markup2
+bdo = wrapMarkup2 Text.Blaze.XHtml1.Transitional.bdo
+big :: Markup2
+big = wrapMarkup2 Text.Blaze.XHtml1.Transitional.big
+blockquote :: Markup2
+blockquote = wrapMarkup2 Text.Blaze.XHtml1.Transitional.blockquote
+body :: Markup2
+body = wrapMarkup2 Text.Blaze.XHtml1.Transitional.body
+button :: Markup2
+button = wrapMarkup2 Text.Blaze.XHtml1.Transitional.button
+caption :: Markup2
+caption = wrapMarkup2 Text.Blaze.XHtml1.Transitional.caption
+cite :: Markup2
+cite = wrapMarkup2 Text.Blaze.XHtml1.Transitional.cite
+code :: Markup2
+code = wrapMarkup2 Text.Blaze.XHtml1.Transitional.code
+colgroup :: Markup2
+colgroup = wrapMarkup2 Text.Blaze.XHtml1.Transitional.colgroup
+dd :: Markup2
+dd = wrapMarkup2 Text.Blaze.XHtml1.Transitional.dd
+del :: Markup2
+del = wrapMarkup2 Text.Blaze.XHtml1.Transitional.del
+dfn :: Markup2
+dfn = wrapMarkup2 Text.Blaze.XHtml1.Transitional.dfn
+div :: Markup2
+div = wrapMarkup2 Text.Blaze.XHtml1.Transitional.div
+dl :: Markup2
+dl = wrapMarkup2 Text.Blaze.XHtml1.Transitional.dl
+dt :: Markup2
+dt = wrapMarkup2 Text.Blaze.XHtml1.Transitional.dt
+em :: Markup2
+em = wrapMarkup2 Text.Blaze.XHtml1.Transitional.em
+fieldset :: Markup2
+fieldset = wrapMarkup2 Text.Blaze.XHtml1.Transitional.fieldset
+form :: Markup2
+form = wrapMarkup2 Text.Blaze.XHtml1.Transitional.form
+h1 :: Markup2
+h1 = wrapMarkup2 Text.Blaze.XHtml1.Transitional.h1
+h2 :: Markup2
+h2 = wrapMarkup2 Text.Blaze.XHtml1.Transitional.h2
+h3 :: Markup2
+h3 = wrapMarkup2 Text.Blaze.XHtml1.Transitional.h3
+h4 :: Markup2
+h4 = wrapMarkup2 Text.Blaze.XHtml1.Transitional.h4
+h5 :: Markup2
+h5 = wrapMarkup2 Text.Blaze.XHtml1.Transitional.h5
+h6 :: Markup2
+h6 = wrapMarkup2 Text.Blaze.XHtml1.Transitional.h6
+head :: Markup2
+head = wrapMarkup2 Text.Blaze.XHtml1.Transitional.head
+html :: Markup2
+html = wrapMarkup2 Text.Blaze.XHtml1.Transitional.html
+i :: Markup2
+i = wrapMarkup2 Text.Blaze.XHtml1.Transitional.i
+ins :: Markup2
+ins = wrapMarkup2 Text.Blaze.XHtml1.Transitional.ins
+kbd :: Markup2
+kbd = wrapMarkup2 Text.Blaze.XHtml1.Transitional.kbd
+label :: Markup2
+label = wrapMarkup2 Text.Blaze.XHtml1.Transitional.label
+legend :: Markup2
+legend = wrapMarkup2 Text.Blaze.XHtml1.Transitional.legend
+li :: Markup2
+li = wrapMarkup2 Text.Blaze.XHtml1.Transitional.li
+map :: Markup2
+map = wrapMarkup2 Text.Blaze.XHtml1.Transitional.map
+noscript :: Markup2
+noscript = wrapMarkup2 Text.Blaze.XHtml1.Transitional.noscript
+object :: Markup2
+object = wrapMarkup2 Text.Blaze.XHtml1.Transitional.object
+ol :: Markup2
+ol = wrapMarkup2 Text.Blaze.XHtml1.Transitional.ol
+optgroup :: Markup2
+optgroup = wrapMarkup2 Text.Blaze.XHtml1.Transitional.optgroup
+option :: Markup2
+option = wrapMarkup2 Text.Blaze.XHtml1.Transitional.option
+p :: Markup2
+p = wrapMarkup2 Text.Blaze.XHtml1.Transitional.p
+pre :: Markup2
+pre = wrapMarkup2 Text.Blaze.XHtml1.Transitional.pre
+q :: Markup2
+q = wrapMarkup2 Text.Blaze.XHtml1.Transitional.q
+samp :: Markup2
+samp = wrapMarkup2 Text.Blaze.XHtml1.Transitional.samp
+script :: Markup2
+script = wrapMarkup2 Text.Blaze.XHtml1.Transitional.script
+select :: Markup2
+select = wrapMarkup2 Text.Blaze.XHtml1.Transitional.select
+small :: Markup2
+small = wrapMarkup2 Text.Blaze.XHtml1.Transitional.small
+span :: Markup2
+span = wrapMarkup2 Text.Blaze.XHtml1.Transitional.span
+strong :: Markup2
+strong = wrapMarkup2 Text.Blaze.XHtml1.Transitional.strong
+style :: Markup2
+style = wrapMarkup2 Text.Blaze.XHtml1.Transitional.style
+sub :: Markup2
+sub = wrapMarkup2 Text.Blaze.XHtml1.Transitional.sub
+sup :: Markup2
+sup = wrapMarkup2 Text.Blaze.XHtml1.Transitional.sup
+table :: Markup2
+table = wrapMarkup2 Text.Blaze.XHtml1.Transitional.table
+tbody :: Markup2
+tbody = wrapMarkup2 Text.Blaze.XHtml1.Transitional.tbody
+td :: Markup2
+td = wrapMarkup2 Text.Blaze.XHtml1.Transitional.td
+textarea :: Markup2
+textarea = wrapMarkup2 Text.Blaze.XHtml1.Transitional.textarea
+tfoot :: Markup2
+tfoot = wrapMarkup2 Text.Blaze.XHtml1.Transitional.tfoot
+th :: Markup2
+th = wrapMarkup2 Text.Blaze.XHtml1.Transitional.th
+thead :: Markup2
+thead = wrapMarkup2 Text.Blaze.XHtml1.Transitional.thead
+title :: Markup2
+title = wrapMarkup2 Text.Blaze.XHtml1.Transitional.title
+tr :: Markup2
+tr = wrapMarkup2 Text.Blaze.XHtml1.Transitional.tr
+tt :: Markup2
+tt = wrapMarkup2 Text.Blaze.XHtml1.Transitional.tt
+ul :: Markup2
+ul = wrapMarkup2 Text.Blaze.XHtml1.Transitional.ul
+var :: Markup2
+var = wrapMarkup2 Text.Blaze.XHtml1.Transitional.var
+applet :: Markup2
+applet = wrapMarkup2 Text.Blaze.XHtml1.Transitional.applet
+center :: Markup2
+center = wrapMarkup2 Text.Blaze.XHtml1.Transitional.center
+dir :: Markup2
+dir = wrapMarkup2 Text.Blaze.XHtml1.Transitional.dir
+font :: Markup2
+font = wrapMarkup2 Text.Blaze.XHtml1.Transitional.font
+iframe :: Markup2
+iframe = wrapMarkup2 Text.Blaze.XHtml1.Transitional.iframe
+isindex :: Markup2
+isindex = wrapMarkup2 Text.Blaze.XHtml1.Transitional.isindex
+menu :: Markup2
+menu = wrapMarkup2 Text.Blaze.XHtml1.Transitional.menu
+noframes :: Markup2
+noframes = wrapMarkup2 Text.Blaze.XHtml1.Transitional.noframes
+s :: Markup2
+s = wrapMarkup2 Text.Blaze.XHtml1.Transitional.s
+u :: Markup2
+u = wrapMarkup2 Text.Blaze.XHtml1.Transitional.u
+docType :: Markup
+docType = wrapMarkup Text.Blaze.XHtml1.Transitional.docType
+area :: Markup
+area = wrapMarkup Text.Blaze.XHtml1.Transitional.area
+br :: Markup
+br = wrapMarkup Text.Blaze.XHtml1.Transitional.br
+col :: Markup
+col = wrapMarkup Text.Blaze.XHtml1.Transitional.col
+hr :: Markup
+hr = wrapMarkup Text.Blaze.XHtml1.Transitional.hr
+link :: Markup
+link = wrapMarkup Text.Blaze.XHtml1.Transitional.link
+img :: Markup
+img = wrapMarkup Text.Blaze.XHtml1.Transitional.img
+input :: Markup
+input = wrapMarkup Text.Blaze.XHtml1.Transitional.input
+meta :: Markup
+meta = wrapMarkup Text.Blaze.XHtml1.Transitional.meta
+param :: Markup
+param = wrapMarkup Text.Blaze.XHtml1.Transitional.param
+basefont :: Markup
+basefont = wrapMarkup Text.Blaze.XHtml1.Transitional.basefont
+
diff --git a/src/Text/BlazeT/XHtml1/Transitional/Attributes.hs b/src/Text/BlazeT/XHtml1/Transitional/Attributes.hs
new file mode 100644 (file)
index 0000000..1881806
--- /dev/null
@@ -0,0 +1,11 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module simply reexports the corresponding @blaze-html@ module.
+-}
+module Text.BlazeT.XHtml1.Transitional.Attributes
+   (module Text.Blaze.XHtml1.Transitional.Attributes
+   ) where
+import Text.Blaze.XHtml1.Transitional.Attributes
+
diff --git a/src/Text/BlazeT/XHtml5.hs b/src/Text/BlazeT/XHtml5.hs
new file mode 100644 (file)
index 0000000..102a993
--- /dev/null
@@ -0,0 +1,234 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module wraps all exports of "Text.Blaze.XHtml5" using 'wrapMarkup' and 'wrapMarkup'.
+-}
+module Text.BlazeT.XHtml5
+   (module Text.BlazeT.XHtml5
+   ,module Text.BlazeT.Html
+   ) where
+import qualified Text.Blaze.XHtml5
+import           Text.BlazeT
+import           Text.BlazeT.Html
+import           Text.BlazeT.Internal
+
+docTypeHtml :: Markup2
+docTypeHtml = wrapMarkup2 Text.Blaze.XHtml5.docTypeHtml
+a :: Markup2
+a = wrapMarkup2 Text.Blaze.XHtml5.a
+abbr :: Markup2
+abbr = wrapMarkup2 Text.Blaze.XHtml5.abbr
+address :: Markup2
+address = wrapMarkup2 Text.Blaze.XHtml5.address
+article :: Markup2
+article = wrapMarkup2 Text.Blaze.XHtml5.article
+aside :: Markup2
+aside = wrapMarkup2 Text.Blaze.XHtml5.aside
+audio :: Markup2
+audio = wrapMarkup2 Text.Blaze.XHtml5.audio
+b :: Markup2
+b = wrapMarkup2 Text.Blaze.XHtml5.b
+bdo :: Markup2
+bdo = wrapMarkup2 Text.Blaze.XHtml5.bdo
+blockquote :: Markup2
+blockquote = wrapMarkup2 Text.Blaze.XHtml5.blockquote
+body :: Markup2
+body = wrapMarkup2 Text.Blaze.XHtml5.body
+button :: Markup2
+button = wrapMarkup2 Text.Blaze.XHtml5.button
+canvas :: Markup2
+canvas = wrapMarkup2 Text.Blaze.XHtml5.canvas
+caption :: Markup2
+caption = wrapMarkup2 Text.Blaze.XHtml5.caption
+cite :: Markup2
+cite = wrapMarkup2 Text.Blaze.XHtml5.cite
+code :: Markup2
+code = wrapMarkup2 Text.Blaze.XHtml5.code
+colgroup :: Markup2
+colgroup = wrapMarkup2 Text.Blaze.XHtml5.colgroup
+command :: Markup2
+command = wrapMarkup2 Text.Blaze.XHtml5.command
+datalist :: Markup2
+datalist = wrapMarkup2 Text.Blaze.XHtml5.datalist
+dd :: Markup2
+dd = wrapMarkup2 Text.Blaze.XHtml5.dd
+del :: Markup2
+del = wrapMarkup2 Text.Blaze.XHtml5.del
+details :: Markup2
+details = wrapMarkup2 Text.Blaze.XHtml5.details
+dfn :: Markup2
+dfn = wrapMarkup2 Text.Blaze.XHtml5.dfn
+div :: Markup2
+div = wrapMarkup2 Text.Blaze.XHtml5.div
+dl :: Markup2
+dl = wrapMarkup2 Text.Blaze.XHtml5.dl
+dt :: Markup2
+dt = wrapMarkup2 Text.Blaze.XHtml5.dt
+em :: Markup2
+em = wrapMarkup2 Text.Blaze.XHtml5.em
+fieldset :: Markup2
+fieldset = wrapMarkup2 Text.Blaze.XHtml5.fieldset
+figcaption :: Markup2
+figcaption = wrapMarkup2 Text.Blaze.XHtml5.figcaption
+figure :: Markup2
+figure = wrapMarkup2 Text.Blaze.XHtml5.figure
+footer :: Markup2
+footer = wrapMarkup2 Text.Blaze.XHtml5.footer
+form :: Markup2
+form = wrapMarkup2 Text.Blaze.XHtml5.form
+h1 :: Markup2
+h1 = wrapMarkup2 Text.Blaze.XHtml5.h1
+h2 :: Markup2
+h2 = wrapMarkup2 Text.Blaze.XHtml5.h2
+h3 :: Markup2
+h3 = wrapMarkup2 Text.Blaze.XHtml5.h3
+h4 :: Markup2
+h4 = wrapMarkup2 Text.Blaze.XHtml5.h4
+h5 :: Markup2
+h5 = wrapMarkup2 Text.Blaze.XHtml5.h5
+h6 :: Markup2
+h6 = wrapMarkup2 Text.Blaze.XHtml5.h6
+head :: Markup2
+head = wrapMarkup2 Text.Blaze.XHtml5.head
+header :: Markup2
+header = wrapMarkup2 Text.Blaze.XHtml5.header
+hgroup :: Markup2
+hgroup = wrapMarkup2 Text.Blaze.XHtml5.hgroup
+html :: Markup2
+html = wrapMarkup2 Text.Blaze.XHtml5.html
+i :: Markup2
+i = wrapMarkup2 Text.Blaze.XHtml5.i
+iframe :: Markup2
+iframe = wrapMarkup2 Text.Blaze.XHtml5.iframe
+ins :: Markup2
+ins = wrapMarkup2 Text.Blaze.XHtml5.ins
+kbd :: Markup2
+kbd = wrapMarkup2 Text.Blaze.XHtml5.kbd
+label :: Markup2
+label = wrapMarkup2 Text.Blaze.XHtml5.label
+legend :: Markup2
+legend = wrapMarkup2 Text.Blaze.XHtml5.legend
+li :: Markup2
+li = wrapMarkup2 Text.Blaze.XHtml5.li
+main :: Markup2
+main = wrapMarkup2 Text.Blaze.XHtml5.main
+map :: Markup2
+map = wrapMarkup2 Text.Blaze.XHtml5.map
+mark :: Markup2
+mark = wrapMarkup2 Text.Blaze.XHtml5.mark
+menu :: Markup2
+menu = wrapMarkup2 Text.Blaze.XHtml5.menu
+meter :: Markup2
+meter = wrapMarkup2 Text.Blaze.XHtml5.meter
+nav :: Markup2
+nav = wrapMarkup2 Text.Blaze.XHtml5.nav
+noscript :: Markup2
+noscript = wrapMarkup2 Text.Blaze.XHtml5.noscript
+object :: Markup2
+object = wrapMarkup2 Text.Blaze.XHtml5.object
+ol :: Markup2
+ol = wrapMarkup2 Text.Blaze.XHtml5.ol
+optgroup :: Markup2
+optgroup = wrapMarkup2 Text.Blaze.XHtml5.optgroup
+option :: Markup2
+option = wrapMarkup2 Text.Blaze.XHtml5.option
+output :: Markup2
+output = wrapMarkup2 Text.Blaze.XHtml5.output
+p :: Markup2
+p = wrapMarkup2 Text.Blaze.XHtml5.p
+pre :: Markup2
+pre = wrapMarkup2 Text.Blaze.XHtml5.pre
+progress :: Markup2
+progress = wrapMarkup2 Text.Blaze.XHtml5.progress
+q :: Markup2
+q = wrapMarkup2 Text.Blaze.XHtml5.q
+rp :: Markup2
+rp = wrapMarkup2 Text.Blaze.XHtml5.rp
+rt :: Markup2
+rt = wrapMarkup2 Text.Blaze.XHtml5.rt
+ruby :: Markup2
+ruby = wrapMarkup2 Text.Blaze.XHtml5.ruby
+samp :: Markup2
+samp = wrapMarkup2 Text.Blaze.XHtml5.samp
+script :: Markup2
+script = wrapMarkup2 Text.Blaze.XHtml5.script
+section :: Markup2
+section = wrapMarkup2 Text.Blaze.XHtml5.section
+select :: Markup2
+select = wrapMarkup2 Text.Blaze.XHtml5.select
+small :: Markup2
+small = wrapMarkup2 Text.Blaze.XHtml5.small
+span :: Markup2
+span = wrapMarkup2 Text.Blaze.XHtml5.span
+strong :: Markup2
+strong = wrapMarkup2 Text.Blaze.XHtml5.strong
+style :: Markup2
+style = wrapMarkup2 Text.Blaze.XHtml5.style
+sub :: Markup2
+sub = wrapMarkup2 Text.Blaze.XHtml5.sub
+summary :: Markup2
+summary = wrapMarkup2 Text.Blaze.XHtml5.summary
+sup :: Markup2
+sup = wrapMarkup2 Text.Blaze.XHtml5.sup
+table :: Markup2
+table = wrapMarkup2 Text.Blaze.XHtml5.table
+tbody :: Markup2
+tbody = wrapMarkup2 Text.Blaze.XHtml5.tbody
+td :: Markup2
+td = wrapMarkup2 Text.Blaze.XHtml5.td
+textarea :: Markup2
+textarea = wrapMarkup2 Text.Blaze.XHtml5.textarea
+tfoot :: Markup2
+tfoot = wrapMarkup2 Text.Blaze.XHtml5.tfoot
+th :: Markup2
+th = wrapMarkup2 Text.Blaze.XHtml5.th
+thead :: Markup2
+thead = wrapMarkup2 Text.Blaze.XHtml5.thead
+time :: Markup2
+time = wrapMarkup2 Text.Blaze.XHtml5.time
+title :: Markup2
+title = wrapMarkup2 Text.Blaze.XHtml5.title
+tr :: Markup2
+tr = wrapMarkup2 Text.Blaze.XHtml5.tr
+ul :: Markup2
+ul = wrapMarkup2 Text.Blaze.XHtml5.ul
+var :: Markup2
+var = wrapMarkup2 Text.Blaze.XHtml5.var
+video :: Markup2
+video = wrapMarkup2 Text.Blaze.XHtml5.video
+docType :: Markup
+docType = wrapMarkup Text.Blaze.XHtml5.docType
+area :: Markup
+area = wrapMarkup Text.Blaze.XHtml5.area
+base :: Markup
+base = wrapMarkup Text.Blaze.XHtml5.base
+br :: Markup
+br = wrapMarkup Text.Blaze.XHtml5.br
+col :: Markup
+col = wrapMarkup Text.Blaze.XHtml5.col
+embed :: Markup
+embed = wrapMarkup Text.Blaze.XHtml5.embed
+hr :: Markup
+hr = wrapMarkup Text.Blaze.XHtml5.hr
+img :: Markup
+img = wrapMarkup Text.Blaze.XHtml5.img
+input :: Markup
+input = wrapMarkup Text.Blaze.XHtml5.input
+keygen :: Markup
+keygen = wrapMarkup Text.Blaze.XHtml5.keygen
+link :: Markup
+link = wrapMarkup Text.Blaze.XHtml5.link
+menuitem :: Markup
+menuitem = wrapMarkup Text.Blaze.XHtml5.menuitem
+meta :: Markup
+meta = wrapMarkup Text.Blaze.XHtml5.meta
+param :: Markup
+param = wrapMarkup Text.Blaze.XHtml5.param
+source :: Markup
+source = wrapMarkup Text.Blaze.XHtml5.source
+track :: Markup
+track = wrapMarkup Text.Blaze.XHtml5.track
+wbr :: Markup
+wbr = wrapMarkup Text.Blaze.XHtml5.wbr
+
diff --git a/src/Text/BlazeT/XHtml5/Attributes.hs b/src/Text/BlazeT/XHtml5/Attributes.hs
new file mode 100644 (file)
index 0000000..e878108
--- /dev/null
@@ -0,0 +1,11 @@
+-- !! DO NOT EDIT
+{-|
+(Automatically generated by @src\/Util\/GenerateHtmlTCombinators.hs:49@)
+
+This module simply reexports the corresponding @blaze-html@ module.
+-}
+module Text.BlazeT.XHtml5.Attributes
+   (module Text.Blaze.XHtml5.Attributes
+   ) where
+import Text.Blaze.XHtml5.Attributes
+
diff --git a/src/Util/GenerateHtmlCombinators.hs b/src/Util/GenerateHtmlCombinators.hs
new file mode 100644 (file)
index 0000000..83da65b
--- /dev/null
@@ -0,0 +1,519 @@
+-- taken from https://github.com/jaspervdj/blaze-html/blob/2c4513e30ce768517b8d7b7b154d438f55217006/src/Util/GenerateHtmlCombinators.hs
+
+-- Copyright Jasper Van der Jeugt 2010
+
+-- All rights reserved.
+
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+
+--     * Redistributions of source code must retain the above copyright
+--       notice, this list of conditions and the following disclaimer.
+
+--     * Redistributions in binary form must reproduce the above
+--       copyright notice, this list of conditions and the following
+--       disclaimer in the documentation and/or other materials provided
+--       with the distribution.
+
+--     * Neither the name of Jasper Van der Jeugt nor the names of other
+--       contributors may be used to endorse or promote products derived
+--       from this software without specific prior written permission.
+
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  
+{-# 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 $ toHtml \"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 $ toHtml \"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"
+        , "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", "kbd", "label"
+        , "legend", "li", "main", "map", "mark", "menu", "meter", "nav"
+        , "noscript", "object", "ol", "optgroup", "option", "output", "p"
+        , "pre", "progress", "q", "rp", "rt", "ruby", "samp", "script"
+        , "section", "select", "small", "span", "strong", "style", "sub"
+        , "summary", "sup", "table", "tbody", "td", "textarea", "tfoot", "th"
+        , "thead", "time", "title", "tr", "ul", "var", "video"
+        ]
+    , leafs =
+        -- http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#void-elements
+        [ "area", "base", "br", "col", "embed", "hr", "img", "input", "keygen"
+        , "link", "menuitem", "meta", "param", "source", "track", "wbr"
+        ]
+    , 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"
+        , "itemscope", "itemtype"
+        , "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
+    }
+
+-- | XHTML 5.0
+--
+xhtml5 :: HtmlVariant
+xhtml5 = HtmlVariant
+    { version = ["XHtml5"]
+    , docType = ["<!DOCTYPE HTML>"]
+    , parents = parents html5
+    , leafs = leafs html5
+    , attributes = attributes html5
+    , selfClosing = True
+    }
+
+
+-- | 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
+    , xhtml5
+    ]
+
+main :: IO ()
+main = mapM_ (writeHtmlVariant . snd) $ M.toList htmlVariants
diff --git a/src/Util/GenerateHtmlTCombinators.hs b/src/Util/GenerateHtmlTCombinators.hs
new file mode 100755 (executable)
index 0000000..0dd5444
--- /dev/null
@@ -0,0 +1,62 @@
+{-# LANGUAGE CPP #-}
+  
+module Util.GenerateHtmlTCombinators where
+
+import Control.Applicative
+import Data.List
+import Language.Haskell.TH
+import System.Directory
+import System.FilePath
+import Text.Printf
+import Text.Regex
+import Text.Regex.TDFA
+import Util.GenerateHtmlCombinators hiding (getModuleName, main)
+
+declare :: HtmlVariant -> [Dec]
+declare x = concatMap (\(w,ls) -> concatMap (g w) ls)
+            [(("wrapMarkup2","Markup2"),"docTypeHtml" : parents x)
+              ,(("wrapMarkup","Markup"),  "docType"     : leafs x)]
+  where g (w',t') l' =
+          [SigD l $ ConT t
+          ,ValD (VarP l) (NormalB (AppE (VarE w)
+          $ VarE $ mkName $ getModuleName "Blaze" x ++"."++l')) []]
+          where [w,t,l] = fmap mkName [w',t',l']
+                 
+
+
+writeSource :: HtmlVariant -> IO ()
+writeSource v = mapM_ g [True, False]
+  where
+    g attr = do
+      let path = if attr then "Attributes" else ""
+          name = (if attr then "." else "") ++ path
+          [mT,m] = ((++ name) . flip getModuleName v) <$>
+                   ["BlazeT","Blaze"]
+          exports = if attr then [m] else [mT, "Text.BlazeT.Html"]
+          f = (joinPath $ ["src","Text","BlazeT"] ++ version v
+               ++ [path]) <.> "hs"
+          body = if attr then "" else unlines $
+            map (printf "import           Text.BlazeT%s") ["", ".Html", ".Internal"]
+            ++ ["", show ( ppr_list $ declare v)]
+          quali = if attr then "" else "qualified "
+          docs True  = "This module simply reexports the corresponding @blaze-html@ module."
+          docs False = printf "This module wraps all exports of \"%s\" using 'wrapMarkup' and 'wrapMarkup'." m
+      createDirectoryIfMissing True $ takeDirectory $ f
+      writeFile f $ unlines $
+        ["-- !! DO NOT EDIT"
+        ,"{-|"
+        ,printf "(Automatically generated by @%s:%d@)\n"
+         (subRegex (mkRegex "/")  __FILE__ "\\\\/") ( __LINE__ :: Int)
+        ,docs attr
+        ,"-}"
+        ,"module "++ mT
+        ,"   (" ++ intercalate "\n   ," (map ("module "++) exports)
+        ,"   ) where"
+        ,"import "++ quali ++ m
+        , body]
+
+main = mapM_ writeSource htmlVariants
+        
+
+getModuleName :: String -> HtmlVariant -> String
+getModuleName base = (("Text."++base++".")++) . intercalate "." . version
diff --git a/src/Util/Sanitize.hs b/src/Util/Sanitize.hs
new file mode 100644 (file)
index 0000000..112bae1
--- /dev/null
@@ -0,0 +1,112 @@
+-- taken from https://github.com/jaspervdj/blaze-html/blob/2c4513e30ce768517b8d7b7b154d438f55217006/src/Util/Sanitize.hs
+
+-- Copyright Jasper Van der Jeugt 2010
+
+-- All rights reserved.
+
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+
+--     * Redistributions of source code must retain the above copyright
+--       notice, this list of conditions and the following disclaimer.
+
+--     * Redistributions in binary form must reproduce the above
+--       copyright notice, this list of conditions and the following
+--       disclaimer in the documentation and/or other materials provided
+--       with the distribution.
+
+--     * Neither the name of Jasper Van der Jeugt nor the names of other
+--       contributors may be used to endorse or promote products derived
+--       from this software without specific prior written permission.
+
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-- | 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"
+    ]