packages feed

text-and-plots (empty) → 0.1.0.0

raw patch · 4 files changed

+248/−0 lines, 4 filesdep +aesondep +basedep +blaze-htmlsetup-changed

Dependencies added: aeson, base, blaze-html, bytestring, containers, markdown, unordered-containers

Files

+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2015 Anders Jellinggaard++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.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Text/DocL.hs view
@@ -0,0 +1,182 @@+{-|+Module      : Text.DocL+Copyright   : 2015 Anders Jellinggaard+License     : MIT+Maintainer  : anders.jel@gmail.com+Stability   : experimental++Haskell mini-language to create HTML documents with a mixture of markup and+plots based on the <http://c3js.org/ C3.js> library.++See the <https://github.com/andersjel/haskell-text-and-plots github page> for an+introduction.++Notes:++* The generated documents relies on <https://cdnjs.com/> to serve+  <http://c3js.org/ C3.js> and friends.++* This library should not be used on a public facing server with input supplied+  by the user. The library has not been properly vetted for security issues.+-}++module Text.DocL (+  Doc,+  -- * Markup+  text, header, markdown, html,+  -- * Output+  render, renderToFile,+  -- * Plotting+  Column, col, col',+  plot, plot', rawPlot,+  -- * Utilities+  linspace+  ) where++import Data.Aeson                    (ToJSON, object, toJSON, (.=))+import Data.Foldable+import Data.HashMap.Strict           (insert, unionWith)+import Data.Monoid+import Data.Sequence                 (Seq, singleton)+import Data.String                   (IsString (..))+import Text.Blaze.Html.Renderer.Utf8 (renderHtml)+import Text.Blaze.Html5              ((!))++import qualified Text.Markdown               as Markdown+import qualified Data.Aeson                  as Aeson+import qualified System.IO                   as IO+import qualified Text.Blaze.Html5            as H+import qualified Text.Blaze.Html5.Attributes as A+import qualified Data.ByteString.Lazy        as B++data Node = Chart Aeson.Value | Html H.Html++-- | Base type representing a document. This type allows composition via the+-- 'Monoid' instance.+newtype Doc = Doc (Seq Node) deriving Monoid++-- | Represent a column of a dataset where each row has type /a/. See 'col' for+-- details.+data Column a = Column+  { _header  :: String+  , _extract :: a -> Aeson.Value+  }++-- | Deep merge of two 'Aeson.Value's. Used to merge in options in 'plot''.+merge :: Aeson.Value -> Aeson.Value -> Aeson.Value+merge (Aeson.Object x) (Aeson.Object y) = Aeson.Object $ unionWith merge x y+merge _ x = x++-- | Polymorphic version of 'col'. This allows, for instance, 'Int' and 'String'+-- values to be used in plots. It is up to the caller to ensure that the values+-- make sense to <http://c3js.org/ C3.js>.+col' :: ToJSON b => String -> (a -> b) -> Column a+col' h f = Column h (toJSON . f)++-- | Data sets are supplied to 'plot' as a collection of elements of type /a/.+-- This function sets up a 'Column', which knows how to extract one 'Double'+-- value from each value of type /a/ in the collection.+--+-- The first argument to 'col' is the header of the column, which is used in the+-- legend of the plot.+--+-- The simplest plot that can be created consist of one column for the /x/+-- values and one column for the /y/ values.+--+-- @+--  -- Plot x² vs x.+--  plot [1..10] (col "x" id) [col "x²" $ \\x -> x*x]+-- @+col :: String -> (a -> Double) -> Column a+col = col'++-- | > plot ds x ys+--+-- Plots the data in /ds/ using the column /x/ for the values on the /x/-axis+-- and with one line on the plot for each column in /ys/. See also 'col'.+plot :: Foldable f => f a -> Column a -> [Column a] -> Doc+plot d x ys = plot' d x ys (Aeson.Object mempty)++-- | Same as 'plot', but takes a final argument which should be a "Data.Aeson"+-- object. This is merged with the configuration object supplied to+-- <http://c3js.org/ C3.js>. This allows the caller to customize the plot.+--+-- @+--  -- Plot x² vs x with the points hidden.+--  plot' [1..10] (col "x" id) [col "x²" $ \\x -> x*x] $+--    object ["point" .= object ["show" .= False]]+-- @+--+-- See <http://c3js.org/reference.html> for the many properties that can be used+-- here.+plot' :: Foldable f => f a -> Column a -> [Column a] -> Aeson.Value -> Doc+plot' d x ys options = rawPlot $ merge obj options+  where+    obj = object+      [ "data" .= object+        [ "rows" .= (toJSON (_header x : map _header ys) : map f (toList d))+        , "x" .= _header x+        ]+      ]+    f p = toJSON $ map (`_extract` p) (x:ys)++-- | This function sends the supplied json object directly to+-- <http://c3js.org/ C3.js>. This is the do-it-yourself option which exposes all+-- of <http://c3js.org/ C3.js>. The object receives a+-- <http://c3js.org/reference.html#bindto "bindto"> property,+-- targeting a @\<div\>@ tag placed appropriately.+rawPlot :: Aeson.ToJSON a => a -> Doc+rawPlot = Doc . singleton . Chart . Aeson.toJSON++-- | Creates a 'Doc' representing raw html.+html :: H.Html -> Doc+html = Doc . singleton . Html++-- | Creates a 'Doc' representing plain text. The string will be properly+-- escaped.+text :: String -> Doc+text = html . H.p . H.toMarkup++-- | Creates a 'Doc' representing @\<h1\>@ header tag. The string will be+-- properly escaped.+header :: String -> Doc+header = html . H.h1 . H.toMarkup++-- | Converts a string in+-- <http://en.wikipedia.org/wiki/Markdown markdown syntax> to a 'Doc'.+markdown :: String -> Doc+markdown = html . Markdown.markdown Markdown.def . fromString++-- | Render a document to a lazy 'B.ByteString'.+render :: Doc -> B.ByteString+render (Doc doc) = renderHtml html+  where+    dns = "https://cdnjs.cloudflare.com/ajax/libs/"+    html = H.docTypeHtml $ do+      H.head $ do+        H.link ! A.rel "stylesheet" ! A.href (dns <> "c3/0.4.9/c3.min.css")+        H.script ! A.charset "utf-8" ! A.src (dns <> "d3/3.5.3/d3.min.js") $+          mempty+        H.script ! A.charset "utf-8" ! A.src (dns <> "c3/0.4.9/c3.min.js") $+          mempty+      H.body $+        foldMap f (zip [(0::Int)..] $ toList doc)+    f (_, (Html t)) = t+    f (i, (Chart v)) = divTag <> scriptTag+      where+        name = "plot" <> show i+        divTag = H.div ! A.id (fromString name) $ mempty+        (Aeson.Object obj) = v+        obj' = insert "bindto" (fromString $ "#" <> name) obj+        json = H.unsafeLazyByteString $ Aeson.encode obj'+        scriptTag = H.script ! A.type_ "text/javascript" $+          H.preEscapedToMarkup $ "c3.generate(" <> json <> ");"++-- | If the file exists, it will be overwritten.+renderToFile :: FilePath -> Doc -> IO ()+renderToFile p = B.writeFile p . render++-- | /'linspace' x y n/ generates /n/ evenly spaced values from /x/ to /y/.+linspace :: Fractional a => a -> a -> Int -> [a]+linspace x y n = [x + (fromIntegral i)*d | i <- [0 .. n - 1]]+  where d = (y - x) / (fromIntegral n - 1)
+ text-and-plots.cabal view
@@ -0,0 +1,44 @@+name:                text-and-plots+version:             0.1.0.0+synopsis:+  EDSL to create HTML documents with plots based on the C3.js library.+description:+  Haskell mini-language to create HTML documents with a mixture of markup and+  plots based on the <http://c3js.org/ C3.js> library. See the+  <https://github.com/andersjel/haskell-text-and-plots github page> for an+  introduction.+homepage:            https://github.com/andersjel/haskell-text-and-plots+license:             MIT+license-file:        LICENSE+author:              Anders Jellinggaard+maintainer:          anders.jel@gmail.com+copyright:           (c) 2015 Anders Jellinggaard+category:            Text+build-type:          Simple+cabal-version:       >=1.10++source-repository head+  type:     git+  location: git://github.com/andersjel/haskell-text-and-plots.git++source-repository this+  type:     git+  location: git://github.com/andersjel/haskell-text-and-plots.git+  tag:      v0.1.0.0++library+  exposed-modules:+    Text.DocL+  build-depends:+    aeson                >=0.8.0.0  && <0.9,+    base                 >=4.7.0.0  && <4.8,+    blaze-html           >=0.7.0.0  && <0.8,+    bytestring           >=0.10.4.0 && <0.11,+    containers           >=0.5.5.1  && <0.6,+    markdown             >=0.1.7.1  && <0.2,+    unordered-containers >=0.2.3.3  && <0.3+  hs-source-dirs:      src+  default-language:    Haskell2010+  default-extensions:+    OverloadedStrings+    GeneralizedNewtypeDeriving