{-# LANGUAGE OverloadedStrings #-} -- -- -- Usage: -- ./playtutorial dname -- Run through the tutorials, creating output files for each visualization: -- -- /.html -- /.vg.json -- -- These files are written to the indicated directory, which will be created -- if necessary, and will over-write any existing files. The directory name -- can contain multiple new directories (e.g. "foo/bar" will create "foo" -- if needed). -- -- The default schema is used. -- -- The idea is that the vega-cli routines [1] can be used to convert the -- specification to PNG or SVG, the the HTML version provides a test -- case (and also access to the Vega Editor). -- -- [1] https://vega.github.io/vega/usage/#cli -- -- Of course, we now need to manage npm/node with nix -- https://unix.stackexchange.com/questions/379842/how-to-install-npm-packages-in-nixos -- -- Should add to default.nix -- -- nix-shell -p nodejs -- npm install vega-cli -- npm install canvas -- ./node_modules/.bin/vg2png stripplot.vg.json stripplot.png -- -- but this fails. Unclear why, tickets suggest installing 'node-canvas', -- which I did. Can run -- -- ./node_modules/.bin/vg2svg -h stripplot.vg.json stripplot.svg -- -- but the output is meaningless (no data), even when -b is given. module Main where import qualified Data.Aeson.Encode.Pretty as AP import qualified Data.ByteString.Lazy.Char8 as BL import qualified Data.Text as T import qualified Graphics.Vega.Tutorials.VegaLite as VL import Control.Monad (forM_) import Data.Aeson ((.=), object) import Graphics.Vega.VegaLite hiding (name) import System.Directory (createDirectoryIfMissing) import System.Environment (getArgs, getProgName) import System.Exit (exitFailure) import System.FilePath ((), FilePath) import System.IO (hPutStrLn, stderr) -- Could use TH to get at the tutorials, but for now hard code the names. -- The intro visualization used in the API documentation (not in -- the tutorial). -- vl1 :: VegaLite vl1 = let desc = "A very exciting bar chart" dat = dataFromRows [Parse [("start", FoDate "%Y-%m-%d")]] . dataRow [("start", Str "2011-03-25"), ("count", Number 23)] . dataRow [("start", Str "2011-04-02"), ("count", Number 45)] . dataRow [("start", Str "2011-04-12"), ("count", Number 3)] barOpts = [MOpacity 0.4, MColor "teal"] enc = encoding . position X [PName "start", PmType Temporal, PAxis [AxTitle "Inception date"]] . position Y [PName "count", PmType Quantitative] in toVegaLite [description desc, background "white" , dat [], mark Bar barOpts, enc []] -- Associate a name with each visualization -- vl :: [(String, VegaLite)] vl = [ ("api-vl1", vl1) , ("stripplot", VL.stripPlot) , ("stripplotwithbackground", VL.stripPlotWithBackground) , ("stripploty", VL.stripPlotY) , ("stripplotwithcolor", VL.stripPlotWithColor) , ("stripplotwithcolorordinal", VL.stripPlotWithColorOrdinal) , ("parallaxhistogram", VL.parallaxHistogram) , ("gmaghistogram", VL.gmagHistogram) , ("yloghistogram", VL.ylogHistogram) , ("gmaghistogramwithcolor", VL.gmagHistogramWithColor) , ("gmaglinewithcolor", VL.gmagLineWithColor) , ("yhistogram", VL.yHistogram) , ("pointplot", VL.pointPlot) , ("posplot", VL.posPlot) , ("skyplot", VL.skyPlot) , ("smallmultiples", VL.smallMultiples) , ("smallmultiples2", VL.smallMultiples2) , ("baseplot", VL.basePlot) , ("layeredplot", VL.layeredPlot) , ("layereddiversion", VL.layeredDiversion) , ("concatenatedplot", VL.concatenatedPlot) , ("concatenatedplot2", VL.concatenatedPlot2) , ("repeatplot", VL.repeatPlot) , ("splomplot", VL.splomPlot) , ("singleselection", VL.singleSelection) , ("nearestselection", VL.nearestSelection) , ("multiselection", VL.multiSelection) , ("eventselection", VL.eventSelection) , ("intervalselection", VL.intervalSelection) , ("intervalselectiony", VL.intervalSelectionY) , ("transformselection", VL.transformSelection) , ("widgetselection", VL.widgetSelection) , ("bindscales", VL.bindScales) , ("coordinatedviews", VL.coordinatedViews) , ("coordinatedviews2", VL.coordinatedViews2) , ("contextandfocus", VL.contextAndFocus) , ("crossfilter", VL.crossFilter) , ("errormanual", VL.errorManual) , ("errorauto", VL.errorAuto) , ("errorbars", VL.errorBars) , ("errorband", VL.errorBand) , ("errorbox", VL.errorBox) , ("comparingerrors", VL.comparingErrors) , ("combinedplot", VL.combinedPlot) ] run :: FilePath -> IO () run outdir = forM_ vl $ \(name, spec) -> do putStrLn (" . " <> name) let htmlFile = prefix <> ".html" specFile = prefix <> ".vg.json" prefix = outdir name opts = object [T.pack "downloadFileName" .= name] toHtmlFileWith (Just opts) htmlFile spec BL.writeFile specFile (AP.encodePretty (fromVL spec)) usage :: IO () usage = do pName <- getProgName hPutStrLn stderr ("Usage: " <> pName <> " directory") exitFailure main :: IO () main = do args <- getArgs case args of [dname] -> do createDirectoryIfMissing True dname run dname _ -> usage