Commit 4239c6ff authored by Henrik Tramberend's avatar Henrik Tramberend
Browse files

Add decker version check for documents

parent d3fdf0d4
......@@ -22,8 +22,6 @@ import Text.Pandoc ()
import Text.Printf ()
import Utilities
version = "0.3.0"
main :: IO ()
main = do
dirs <- projectDirectories
......@@ -51,42 +49,40 @@ main = do
let everythingA = decksA <++> handoutsA <++> pagesA
let everythingPdfA = decksPdfA <++> handoutsPdfA <++> pagesPdfA
let cruft =
map
(combine (project dirs))
["index.md.generated", "server.log", "//.shake"]
map (combine (project dirs)) ["index.md.generated", "log/", "//.shake/"]
context <- makeActionContext dirs
runShakeInContext context options $
--
do
want ["html"]
--
phony "version" $ putNormal $ "decker version " ++ version
--
--
phony "version" $ putNormal $ "decker version " ++ deckerVersion
--
phony "decks" $ decksA >>= need
--
--
phony "html" $ everythingA <++> indexA >>= need
--
--
phony "pdf" $ pagesPdfA <++> handoutsPdfA <++> indexA >>= need
--
--
phony "pdf-decks" $ decksPdfA <++> indexA >>= need
--
--
phony "watch" $ do
need ["html"]
allMarkdownA <++> metaA <++> allImagesA >>= watchFiles
--
--
phony "server" $ do
need ["watch", "support"]
runHttpServer dirs True
--
--
phony "example" writeExampleProject
--
--
phony "index" $ need [index]
--
--
priority 2 $
"//*-deck.html" %> \out -> do
src <- calcSource "-deck.html" "-deck.md" out
markdownToHtmlDeck src out
--
--
priority 2 $
"//*-deck.pdf" %> \out -> do
let src = replaceSuffix "-deck.pdf" "-deck.html" out
......@@ -101,27 +97,27 @@ main = do
case code of
ExitFailure _ -> throw $ DecktapeException "Unknown."
ExitSuccess -> return ()
--
--
priority 2 $
"//*-handout.html" %> \out -> do
src <- calcSource "-handout.html" "-deck.md" out
markdownToHtmlHandout src out
--
--
priority 2 $
"//*-handout.pdf" %> \out -> do
src <- calcSource "-handout.pdf" "-deck.md" out
markdownToPdfHandout src out
--
--
priority 2 $
"//*-page.html" %> \out -> do
src <- calcSource "-page.html" "-page.md" out
markdownToHtmlPage src out
--
--
priority 2 $
"//*-page.pdf" %> \out -> do
src <- calcSource "-page.pdf" "-page.md" out
markdownToPdfPage src out
--
--
priority 2 $
index %> \out -> do
exists <- Development.Shake.doesFileExist indexSource
......@@ -130,20 +126,20 @@ main = do
then indexSource
else indexSource <.> "generated"
markdownToHtmlPage src out
--
--
indexSource <.> "generated" %> \out -> do
decks <- decksA
handouts <- handoutsA
pages <- pagesA
need $ decks ++ handouts ++ pages
writeIndex out (takeDirectory index) decks handouts pages
--
--
phony "clean" $ do
removeFilesAfter publicDir ["//"]
removeFilesAfter projectDir cruft
--
--
phony "help" $ liftIO $ putStr deckerHelpText
--
--
phony "plan" $ do
putNormal $ "project directory: " ++ projectDir
putNormal $ "public directory: " ++ publicDir
......@@ -154,15 +150,11 @@ main = do
allSourcesA >>= mapM_ putNormal
putNormal "targets:"
everythingA <++> everythingPdfA >>= mapM_ putNormal
--
-- phony "meta" $
-- do metaData <- metaA >>= readMetaData
-- liftIO $ B.putStr $ encodePretty defConfig metaData
--
--
phony "support" $ do
putNormal $ "# write embedded files for (" ++ supportDir ++ ")"
writeEmbeddedFiles deckerSupportDir supportDir
--
--
phony "publish" $ do
need ["support"]
everythingA <++> indexA >>= need
......
......@@ -76,16 +76,16 @@ executable decker
, mustache
default-language: Haskell2010
executable liveserver
hs-source-dirs: app
main-is: liveserver.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, decker
, directory
, random
, process
default-language: Haskell2010
-- executable liveserver
-- hs-source-dirs: app
-- main-is: liveserver.hs
-- ghc-options: -threaded -rtsopts -with-rtsopts=-N
-- build-depends: base
-- , decker
-- , directory
-- , random
-- , process
-- default-language: Haskell2010
test-suite decker-test
type: exitcode-stdio-1.0
......
......@@ -7,6 +7,7 @@ subtitle: Tutorial and Examples
title: Decker Slide Tool
transition: linear
ümläüte: Ümläüte
decker-version: 0.3.0
---
# Overview
......@@ -297,50 +298,5 @@ Your total score is 42.
- [Haskell](http://haskell.org)
- [Pandoc](), [Shake](), [Mustache](), [reveal.js]()
- [LaTeX](), [livereloadx](), [decktape.sh]()
- [LaTeX](), [decktape.sh]()
# `decker` Targets
## Specialized build tool
- `decker` is like `make` without the makefile
- Operates on the current directory and below
- Considers Markdown text files and YAML data files
## `decker` source files
- `*-deck.md` is a slide deck
- `*-page.md` is a one page document styled like an article
- `*.md` is a general document without any semantic attached
# `decker` generated targets
## Generated from `*-deck.md`
- `*-deck.html` a *reveal.js* based HTML slide deck
- `*-deck.pdf` a PDF version of that deck
- `*-handout.html` a HTML document containing only the speaker notes from the deck
- `*-handout.pdf` a PDF version of that handout
## Generated from `*-page.md`
- `*-page.hml` a HTML article page
- `*-page.pdf` a PDF version of that article
# Slide Header
# Installation {.section}
# Usage {.section}
# Decker Commands
## `decker`
- Recursively scans the current directory for Markdown files ending in `.md`
## `decker clean`
## `decker example`
## `decker server`
......@@ -4,26 +4,24 @@ A markdown based tool for slide deck creation.
## Usage
*decker* behaves very much like a build tool. It works recursively on the current
directory and all subdirectories. Markdown files ending on `.md` in those
directories are processed and converted to either a reveal.js slide show, a HTML
document, or a PDF document, depending on the file name.
*decker* behaves very much like a build tool. It works recursively on the current directory and all subdirectories. Markdown files ending on `.md` in those directories are processed and converted to either a reveal.js slide show, a single page HTML document, depending on the file name.
*decker* understands the notion of a *project directory*. The first directory above the current directory that contains a `.git/` directory is assumed to be the project directory. If `.git/` cannot be found, the current directory is used as the project directory. All path calculations are performed relative to the project directory.
The resulting HTML documents and all necessary resources are placed in the `public` directory within the project directory. The content of `public` is self-contained and can directly be served by any static HTML server. No external sites will be referenced during rendering of the slide decks.
`*-deck.md`
: Files with this ending are processed as silde decks. From one source file
potentially four different targets can be generated:
: Files with this ending are processed as silde decks. From one source file potentially four different targets can be generated:
- `*-deck.html` A reveal.js based slide show
- `*-handout.hmtl` A HTML document containing the speaker notes to the
slide show.
- `*-handout.hmtl` A HTML document containing the speaker notes to the slide show.
- `*-deck.pdf` A PDF version of the slide show
- `*-handout.pdf` A PDF version of the handout
`*-page.md`
: Markdown files ending on `*-page.md` are translated into corresponding HTML
or PDF documents.
: Markdown files ending on `*-page.md` are translated into corresponding single page HTML or PDF documents.
## *decker* targets
......@@ -31,68 +29,38 @@ decker help
: Prints this document to stdout in Markdown format.
decker html
: Builds HTML versions of all available documents.
decker pdf
: Builds PDF versions of all documents that are generated from
`*-deck.md` files.
: Builds HTML versions of all available documents. This is the default.
decker pdf-decks
: Builds PDF versions of all slide decks.
decker watch
: Builds HTML versions of all documents and then watches for document changes.
Each change to a watched document triggers a rebuild. Watching can be
terminated with `^C`.
: Builds HTML versions of all documents and then watches for document changes. Each change to a watched document triggers a rebuild. Watching can be terminated with `^C`.
decker server
: Like `decker watch`. Additionally a local web server is started that serves
the generated HTML files. The `index.html` document is automatically openend
in the browser. Changed files are automatically reloaded in the browser.
: Like `decker watch`. Additionally, a local web server is started that serves the generated HTML files. The `index.html` document is automatically openend in the browser. Changed files are automatically reloaded in the browser. The server can be terminated with `^C`.
decker example
: Write a few example files to the current directory. To start exploring decker
type
: Write a few example files to the current directory. To start exploring decker type
``` {.bash}
$ decker example
$ decker server
> mkdir first-contact
> cd first-contact
> decker example
> decker server
```
and make some changes to the Markdown files. `example-deck.md` contains the
source code for a slide deck that explains most of the features supported.
and make some changes to the Markdown files. `example-deck.md` contains the source code for a slide deck that explains most of the features supported.
decker clean
: Recursively removes all generated files from the current directory.
decker check
: Check for all required external depencies. If one of the programs is missing,
an error is generated. Required programs include:
- `pdflatex` as part of a complete LaTeX installation
- `decktape.sh` for the generation of PDF versions of slide decks
- `livereloadx` as live-reloading local webserver
- `rsync` to publish the documents to a remote location
decker plan
: Prints a list of all source files found below the current directory.
decker meta
: Pretty prints all meta data that can be found in `*.yaml` files in the
current directory and below. Meta data is mainly used to perform
substitutions in Markdown documents using the Mustache templating system.
: Pretty prints all meta data that can be found in `*.yaml` files in the current directory and below. Meta data is mainly used to perform substitutions in Markdown documents using the Mustache templating system.
decker publish
: Publish the generated files to a remote location using `rsync` if the
location is specified in the meta data. The keys `rsync-destination.host` and
`rsync-destination.path` specify the publishing destination.
decker clean-cache
: Remove all cached image files. Subsequent document builds will use the
original remote images.
## Installation
## Development
: Publish the generated files to a remote location using `rsync` if the location is specified in the meta data. The keys `rsync-destination.host` and `rsync-destination.path` specify the publishing destination.
......@@ -2,7 +2,8 @@
{-# LANGUAGE TemplateHaskell #-}
module Embed
( deckerHelpText
( deckerVersion
, deckerHelpText
, deckerExampleDir
, deckerSupportDir
, deckerTemplateDir
......@@ -18,8 +19,12 @@ module Embed
import qualified Data.ByteString.Char8 as B
import Data.FileEmbed
import Data.List
import Data.List.Extra
import Data.Maybe
deckerVersion :: String
deckerVersion = trim $ B.unpack $ $(makeRelativeToProject "VERSION" >>= embedFile)
deckerExampleDir :: [(FilePath, B.ByteString)]
deckerExampleDir = $(makeRelativeToProject "resource/example" >>= embedDir)
......
......@@ -24,6 +24,7 @@ import System.Directory
import System.FilePath.Posix
import System.Random
-- Logging and port configuration for the server.
serverConfig dirs port = do
let logDir = Project.log dirs
let accessLog = logDir </> "server-access.log"
......@@ -60,6 +61,7 @@ reloadAll state = withMVar state $ mapM_ send
send :: Client -> IO ()
send (cid, conn) = sendTextData conn ("reload!" :: Text)
-- Runs the server. Never returns.
runHttpServer :: MVar ServerState -> ProjectDirs -> Int -> IO ()
runHttpServer state dirs port = do
let documentRoot = public dirs
......@@ -67,33 +69,32 @@ runHttpServer state dirs port = do
simpleHttpServe config $
route
[ ("/reload", runWebSocketsSnap $ reloader state)
, ( "/reload.html"
, ( "/reload.html" -- Just for testing the thing.
, serveFile $ Project.project dirs </> "test" </> "reload.html")
, ( "/reload.js"
, serveFile $ Project.project dirs </> "test" </> "reload.js")
, ("/", serveDirectory documentRoot)
]
-- Starts a server in a new thread and returns the thread id.
-- | Starts a server in a new thread and returns the thread id.
startHttpServer :: ProjectDirs -> Int -> IO Server
startHttpServer dirs port = do
state <- initState
threadId <- forkIO $ runHttpServer state dirs port
return (threadId, state)
-- | Sends a reload messsage to all attached clients
reloadClients :: Server -> IO ()
reloadClients = reloadAll . snd
-- | Kill the server.
stopHttpServer :: Server -> IO ()
stopHttpServer = killThread . fst
-- connect :: Connection -> IO ()
-- just keep it open
-- Accepts a request and adds the connection to the client list. Then reads
-- reads the connection forever. Removes the client from the list on disconnect.
reloader :: MVar ServerState -> PendingConnection -> IO ()
reloader state pending = do
connection <- acceptRequest pending
cid <- randomIO
cid <- randomIO -- Use a random number as client id.
flip finally (removeClient state cid) $ do
addClient state (cid, connection)
-- putStrLn $ "reloader request from " ++ show cid
forever (receiveData connection :: IO Text)
......@@ -27,7 +27,6 @@ module Utilities
, adjustLocalUrl
, cacheRemoteFile
, cacheRemoteImages
, makeRelativeTo
, fixMustacheMarkup
, fixMustacheMarkupText
, globA
......@@ -51,8 +50,8 @@ import Data.Digest.Pure.MD5
import qualified Data.HashMap.Lazy as HashMap
import qualified Data.HashMap.Strict as H
import Data.IORef
import Data.List
import Data.List.Extra
import Data.List as List
import Data.List.Extra as List
import qualified Data.Map.Lazy as Map
import Data.Maybe
import qualified Data.Set as Set
......@@ -60,8 +59,6 @@ import qualified Data.Text as T
import qualified Data.Text.Encoding as E
import qualified Data.Vector as Vec
import qualified Data.Yaml as Y
-- import Debug.Trace
import Development.Shake
import Development.Shake.FilePath as SFP
import Embed
......@@ -270,6 +267,7 @@ invertPath fp = joinPath $ map (const "..") $ filter ("." /=) $ splitPath fp
-- | Write a markdown file to a HTML file using the page template.
markdownToHtmlDeck :: FilePath -> FilePath -> Action ()
markdownToHtmlDeck markdownFile out = do
putCurrentDocument out
supportDir <- getRelativeSupportDir out
let options =
pandocWriterOpts
......@@ -302,17 +300,33 @@ getPandocWriter format =
Left e -> throw $ PandocException e
_ -> throw $ PandocException $ "No writer for format: " ++ format
versionCheck :: Meta -> Action ()
versionCheck meta =
case lookupMeta "decker-version" meta of
Just (MetaInlines version) -> check $ stringify version
Just (MetaString version) -> check version
_ ->
putNormal $
" - Document version unspecified. This is decker version " ++
deckerVersion ++ "."
where
check version =
when (List.trim version /= List.trim deckerVersion) $
putNormal $
" - Document version " ++
version ++
". This is decker version " ++ deckerVersion ++ ". Expect problems."
-- | Reads a markdownfile, expands the included files, and substitutes mustache
-- template variables and calls need.
readAndPreprocessMarkdown :: FilePath -> Disposition -> Action Pandoc
readAndPreprocessMarkdown markdownFile disposition = do
putLoud $ "reading: " ++ markdownFile
dirs <- getProjectDirs
let baseDir = takeDirectory markdownFile
pandoc@(Pandoc meta _) <-
readMetaMarkdown markdownFile >>= processIncludes dirs baseDir
versionCheck meta
let method = provisioningFromMeta meta
let lazy = lookupBool "lazy" False meta
liftIO $
mapMetaResources (provisionMetaResource method dirs baseDir) pandoc >>=
mapResources (provisionExistingResource method dirs baseDir) >>=
......@@ -338,9 +352,15 @@ provisionMetaResource method dirs base (key, path)
| key `elem` compiletimeMetaKeys = findLocalFile dirs base path
provisionMetaResource _ _ _ (key, path) = return path
putCurrentDocument out = do
dirs <- getProjectDirs
let rel = makeRelative (public dirs) out
putNormal $ "# pandoc for (" ++ rel ++ ")"
-- | Write a markdown file to a HTML file using the page template.
markdownToHtmlPage :: FilePath -> FilePath -> Action ()
markdownToHtmlPage markdownFile out = do
putCurrentDocument out
supportDir <- getRelativeSupportDir out
let options =
pandocWriterOpts
......@@ -365,6 +385,7 @@ markdownToHtmlPage markdownFile out = do
-- | Write a markdown file to a PDF file using the handout template.
markdownToPdfPage :: FilePath -> FilePath -> Action ()
markdownToPdfPage markdownFile out = do
putCurrentDocument out
let options =
pandocWriterOpts
{ writerTemplate = Just pageLatexTemplate
......@@ -387,6 +408,7 @@ pandocMakePdf options processed out = do
-- | Write a markdown file to a HTML file using the handout template.
markdownToHtmlHandout :: FilePath -> FilePath -> Action ()
markdownToHtmlHandout markdownFile out = do
putCurrentDocument out
pandoc <- readAndPreprocessMarkdown markdownFile Handout
processed <- processPandocHandout "html" pandoc
supportDir <- getRelativeSupportDir out
......@@ -406,6 +428,7 @@ markdownToHtmlHandout markdownFile out = do
-- | Write a markdown file to a PDF file using the handout template.
markdownToPdfHandout :: FilePath -> FilePath -> Action ()
markdownToPdfHandout markdownFile out = do
putCurrentDocument out
pandoc <- readAndPreprocessMarkdown markdownFile Handout
processed <- processPandocHandout "latex" pandoc
let options =
......@@ -727,7 +750,6 @@ writePandocString :: String -> WriterOptions -> FilePath -> Pandoc -> Action ()
writePandocString format options out pandoc = do
let writer = getPandocWriter format
writeFile' out (writer options pandoc)
putNormal $ "# pandoc for (" ++ out ++ ")"
writeExampleProject :: Action ()
writeExampleProject = mapM_ writeOne deckerExampleDir
......
......@@ -33,7 +33,7 @@ waitForTwitch directories patterns = do
watchIt mgr done = mapM (watchInDir mgr done) directories
twitchPatterns =
map compile ["**/*.md", "**/*.yaml", "**/*.png", "**/*.jpg", "**/*.mp4"]
map compile ["**/*.md", "**/*.yaml", "**/*.png", "**/*.gif", "**/*.jpg", "**/*.mp4"]
waitForTwitchPassive files = do
let dirs = nub (map takeDirectory files)
......
......@@ -2,15 +2,16 @@
csl: 'acm-sig-proceedings.csl'
css:
- 'dummy.css'
- 'dummy.css'
- 'dummy.css'
decker-version: '0.2.0'
---
# Meta Resources
# Meta Resources
Resource references in meta data values
- `css:`
{{#css}}
- {{{.}}}
{{/css}}
- `csl: {{{csl}}}`
- Slide background should be gray
\ No newline at end of file
- `css:` {{\#css}}
- {{{.}}} {{/css}}
- `csl: {{{csl}}}`
- Slide background should be gray
decker-version: '0.3.0'
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment