This post outlines my efforts to bring in markdown focused workflow for creating presentations. The tool allows setting up automated workflow leveraging markdown and Reveal.js.
Reveal.js has teased me for many days to Leave powerpoint/impress and try it. I never gave it a serious thought, as my existing setup was working just fine. But as now i have started to use markdown a lot .I realised the need for clean plaintext version of data and capabilities to present it easily and quickly. So i started to read about reveal.js and how to use it.
General reading around reveal.js suggested that people were either writing HTML, directly copy pasting markdown or relying on external tools like pandoc.
So the general use case i observed is as following:
- Write slides in markdown.
- Convert slides from markdown to reveal.js format (using pandoc)
- Place converted index.html and git clone reveal.js in same folder.
- To present launch the html file in browser full screen.
Advantage of this approach:
- Markdown is neutral in nature if written properly
- No need of a server style hosting or running your own python simple server
- If even a word is changed the steps 1 and 2 needs to be repeated.
- Once those changes are done browser needs to be refreshed or reopened.
At this point i saw multiple set of repetitions, so wanted to optimise and automate this approach. This is the point where i identified that reveal.js also supports external markdown syntax (silly me for not reading the README carefully the first time). However it had one caveat, the markdown needs to be served via web server for browsers to pick it up.
This is what led to my current automated setup. In short this one screenshot should showcase how simple it becomes to run presentations using this.
So what i have as my current setup is
- A bash script called “present” (glue for all : the heart/brain)
- Folder where git clone of reveal.js is placed
- Customised index.html with placeholder text
So after doing this one time effort this is how my setup looks like.
- Write markdown in any arbitrary location.
- “present setup” (if md file name is anything other then presentation.md then specify it) : This still looks like how we do pandoc however the additional commands is where the beauty of the script lies in.
- “present” : This is one command which performs following operations
- Start a python simpleHTTP server
- Based on the predefined browser path, start a browser (chrome / chromium) with url of index file in it.
- “present print” : This performs similar steps (start webserver and lauch browser) but it also appends “?print-pdf” in the url which informs reveal.js to present slides in printable format.
- “present clean” : This will clean all the additional resource i.e. index.html and reveal.js
This setup allows me to continue working on markdown file and all i need to do is change file in markdown save and go back to browser refresh page to get the output reflected.
Once presentation is done and you close the browser then it automatically kills the python server that was started. (and hence not leaving stale bits.)
The fourth command : “present print” was added to ensure we are able to quickly create distributable copies of the presentation.
So without further ado here is the script
#!/bin/bash echo "Present : Reveal.js Workflow Automation" echo "Created by: Anant Shrivastava" RJSVER="3.0.0" CW=`pwd` BASE="$HOME/Work/Presentations/presentation_resources/reveal/" BASE_HTML=$BASE"/html" HEADLESS=0 if [ $# -gt 0 ] then if [ $1 == "headless" ] then HEADLESS=1 shift fi fi if [ $HEADLESS == 1 ] then echo "Headless mode selected ignoring browser check" else if [[ "$OSTYPE" == "darwin"* ]] then if [ -f "$HOME/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" ] then BROWSER="$HOME/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" elif [ -f "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" ] then BROWSER="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" elif [ -f "$HOME/Applications/Chromium.app/Contents/MacOS/Chromium" ] then BROWSER="$HOME/Applications/Chromium.app/Contents/MacOS/Chromium" elif [ -f "/Applications/Chromium.app/Contents/MacOS/Chromium" ] then BROWSER="/Applications/Chromium.app/Contents/MacOS/Chromium" else echo "Chromium / Chrome browser was not found to be installed" echo "Please install it to use this script properly" BROWSER="/Applications/Chromium.app/Contents/MacOS/Chromium" fi else if [ -f "/usr/bin/google-chrome" ] then BROWSER="/usr/bin/google-chrome" elif [ -f "/usr/bin/chromium-browser" ] then BROWSER="/usr/bin/chromium-browser" else echo "Chromium/Chrome browser was not found to be installed" echo "Please install it to use this script properly" BROWSER="/usr/bin/chromium-browser" fi fi fi BROWSER="$BROWSER" BROWSER_PROFILE="$HOME/.profiles_chromium/presentor" RESOURCES="$HOME/Work/Presentations/presentation_resources/resources/" MARKDOWN_MODULES="$HOME/Work/Presentations/presentation_resources/markdown_modules/" BASE_URL="https://github.com/anantshri/present/" DEF_NAME="presentation.md" if [ $# -eq 0 ] then if [ $HEADLESS == 0 ] then python2 -m SimpleHTTPServer 9099 & pid=$! $BROWSER --app="http://localhost:9099/" --disable-gpu --user-data-dir="$BROWSER_PROFILE" kill -KILL $pid else python2 -m SimpleHTTPServer 9099 fi elif [ $# -gt 0 ] then if [ $1 == "init" -o $1 == "update" ] then echo "checking if base is upto date or not" echo "if base is not present we will create directories at $BASE" if [ -d $BASE/reveal.js ] then echo "Folder already exist" echo "Reveal.js is fixed to specific version $RJSVER" echo "More update features are not yet implemented" #cd $BASE/reveal.js #git pull else mkdir -p $BASE mkdir -p $MARKDOWN_MODULES mkdir -p $RESOURCES mkdir -p $BROWSER_PROFILE cd $BASE echo "git cloning the reveal.js repository" git clone --branch $RJSVER https://github.com/hakimel/reveal.js/ mkdir $BASE_HTML #wget https://raw.githubusercontent.com/anantshri/present_revealjs_workflow_automation/master/index.html -O $BASE_HTML/index.html curl "https://raw.githubusercontent.com/anantshri/present_revealjs_workflow_automation/master/index.html" -o $BASE_HTML/index.html #wget https://raw.githubusercontent.com/anantshri/present_revealjs_workflow_automation/master/index_top.html -O $BASE_HTML/index_top.html curl "https://raw.githubusercontent.com/anantshri/present_revealjs_workflow_automation/master/index_top.html" -o $BASE_HTML/index_top.html #wget https://raw.githubusercontent.com/anantshri/present_revealjs_workflow_automation/master/index_bottom.html -O $BASE_HTML/index_bottom.html curl "https://raw.githubusercontent.com/anantshri/present_revealjs_workflow_automation/master/index_bottom.html" -o $BASE_HTML/index_bottom.html #wget https://raw.githubusercontent.com/anantshri/present_revealjs_workflow_automation/master/powerpoint_style.css -O $BASE_HTML/powerpoint_style.css curl "https://raw.githubusercontent.com/anantshri/present_revealjs_workflow_automation/master/powerpoint_style.css" -o $BASE_HTML/powerpoint_style.css echo "A sample html file is placed please change accordingly" #echo "Please place a templatized html file" #echo "Sample template is available at $BASE_URL/blob/master/index.html" pwd fi elif [ $1 == "require" ] then echo "setup via requirement files" if [ -f $2 ] then inp="" style="" #echo "testing this section" ln -s $MARKDOWN_MODULES ./markdown template1='<section data-markdown="' template2='" data-separator="\n---\n" data-separator-vertical="\n--\n" data-separator-notes="^Notes:"></section>' while read p; do #echo $MARKDOWN_MODULES$p if [ -f $p ] then inp="$inp $template1$p$template2" elif [ -f $MARKDOWN_MODULES$p ] then inp="$inp $template1"markdown/"$p$template2" #echo $inp else echo "$MARKDOWN_MODULES$p and / or $p file not found : ignoring" fi done<$2 # if style.css diff powerpoint_style.css is same then don't append. #if [ `diff $BASE_HTML/powerpoint_style.css ./style.css` ] #then # echo "powerpoint_style already uptodate" #else # echo "Adding powerpoint_style code in custom style.css" cat $BASE_HTML/powerpoint_style.css >> ./style.css #fi if [ -f style.css ] then style="<link rel='stylesheet' href='style.css'/>" fi #custom style cat $BASE_HTML/index_top.html > ./index.html echo $style >> ./index.html echo "</head><body><div class='reveal'><div class='slides'>" >> ./index.html ln -s $BASE/reveal.js/ ./reveal.js #mkdir reveal.js #cp -r $BASE/reveal.js/ ./reveal.js/ echo $inp >> ./index.html cat $BASE_HTML/index_bottom.html >> ./index.html ln -s $RESOURCES ./resources else echo "Please specify existing requirement file" fi elif [ $1 == "setup" ] then if [ $# -gt 1 -a -f $2 ] then echo "setup for specific slide md file" echo "File Name is " $2 DEF_NAME=$2 else echo "Invalid file name specified $2" exit fi echo "Setting up presentation for this folder" echo #mkdir reveal.js #cp -r $BASE/reveal.js/ ./reveal.js/ ln -s $BASE/reveal.js/ ./reveal.js #sed "s/#markdownfilename#/$DEF_NAME/g" $BASE_HTML/index.html > ./index.html style="" template1='<section data-markdown="' template2='" data-separator="\n---\n" data-separator-vertical="\n--\n" data-separator-notes="^Notes:"></section>' cat $BASE_HTML/powerpoint_style.css >> ./style.css if [ -f style.css ] then style="<link rel='stylesheet' href='style.css'/>" fi #custom style cat $BASE_HTML/index_top.html > ./index.html echo $style >> ./index.html echo "</head><body><div class='reveal'><div class='slides'>" >> ./index.html echo $template1"$2"$template2 >> ./index.html cat $BASE_HTML/index_bottom.html >> ./index.html ln -s $RESOURCES ./resources elif [ $1 == "clean" ] then echo "Lets clear everything then" if [ -d "resources" ] then rm resources fi if [ -d "markdown" ] then rm markdown fi if [ -d "reveal.js" ] then rm reveal.js fi if [ -f "index.html" ] then rm index.html fi if [ `diff $BASE_HTML/powerpoint_style.css ./style.css` ] then echo "Leaving style.css as is coz of custom code" else echo "removing style as it has no custom code added" rm style.css fi elif [ $1 == "print" ] then if [ -f "index.html" ] then if [ $HEADLESS == 0 ] then python2 -m SimpleHTTPServer 9099 & pid1=$! $BROWSER --app="http://localhost:9099/index.html?print-pdf" --disable-gpu --user-data-dir="$BROWSER_PROFILE" kill -KILL $pid1 else python2 -m SimpleHTTPServer 9099 fi else echo "Index file not found please run present setup first" fi else echo "Un-identified argument" echo "setup : setup reveal.js environment" echo "setup slide_name.md" echo "clean : clear out all files" fi fi echo "Thanks for using present service"
The project is available at github
I have uploaded the whole script over at github so that it can be used by others and can be overall improved. Feel free to fork it ,hack it and customise it to your satisfaction. (If you think the setup might help others feel free to share it across)