From d8becc44a22eabccd5c8d722f08049dd81c907b7 Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Mon, 29 Feb 2016 20:31:32 +0200 Subject: [PATCH 01/85] Initial static files --- initial-slides.md | 31 + static/css/index.css | 40 + static/js/index.js | 54 + static/js/save.js | 19 + static/js/slides.js | 73 + static/revealjs/Gruntfile.js | 174 + static/revealjs/LICENSE | 19 + static/revealjs/README.md | 950 ++++ static/revealjs/css/print/paper.css | 202 + static/revealjs/css/print/pdf.css | 157 + static/revealjs/css/reveal.css | 1109 +++++ static/revealjs/css/reveal.min.css | 7 + static/revealjs/css/reveal.scss | 1316 +++++ static/revealjs/css/theme/README.md | 25 + static/revealjs/css/theme/beige.css | 265 + static/revealjs/css/theme/black.css | 261 + static/revealjs/css/theme/blood.css | 291 ++ static/revealjs/css/theme/league.css | 267 + static/revealjs/css/theme/moon.css | 265 + static/revealjs/css/theme/night.css | 259 + static/revealjs/css/theme/serif.css | 261 + static/revealjs/css/theme/simple.css | 261 + static/revealjs/css/theme/sky.css | 268 ++ static/revealjs/css/theme/solarized.css | 265 + static/revealjs/css/theme/source/beige.scss | 39 + static/revealjs/css/theme/source/black.scss | 49 + static/revealjs/css/theme/source/blood.scss | 91 + static/revealjs/css/theme/source/league.scss | 34 + static/revealjs/css/theme/source/moon.scss | 57 + static/revealjs/css/theme/source/night.scss | 35 + static/revealjs/css/theme/source/serif.scss | 35 + static/revealjs/css/theme/source/simple.scss | 38 + static/revealjs/css/theme/source/sky.scss | 46 + .../revealjs/css/theme/source/solarized.scss | 63 + static/revealjs/css/theme/source/white.scss | 49 + .../revealjs/css/theme/template/mixins.scss | 29 + .../revealjs/css/theme/template/settings.scss | 43 + static/revealjs/css/theme/template/theme.scss | 339 ++ static/revealjs/css/theme/white.css | 261 + static/revealjs/js/ace-1.1.8/ace.js | 11 + static/revealjs/js/ace-1.1.8/ext-beautify.js | 5 + static/revealjs/js/ace-1.1.8/ext-chromevox.js | 5 + .../js/ace-1.1.8/ext-elastic_tabstops_lite.js | 5 + static/revealjs/js/ace-1.1.8/ext-emmet.js | 5 + .../revealjs/js/ace-1.1.8/ext-error_marker.js | 5 + .../js/ace-1.1.8/ext-keybinding_menu.js | 5 + .../js/ace-1.1.8/ext-language_tools.js | 5 + static/revealjs/js/ace-1.1.8/ext-linking.js | 5 + static/revealjs/js/ace-1.1.8/ext-modelist.js | 5 + static/revealjs/js/ace-1.1.8/ext-old_ie.js | 5 + static/revealjs/js/ace-1.1.8/ext-searchbox.js | 5 + .../js/ace-1.1.8/ext-settings_menu.js | 5 + .../revealjs/js/ace-1.1.8/ext-spellcheck.js | 5 + static/revealjs/js/ace-1.1.8/ext-split.js | 5 + .../js/ace-1.1.8/ext-static_highlight.js | 5 + static/revealjs/js/ace-1.1.8/ext-statusbar.js | 5 + static/revealjs/js/ace-1.1.8/ext-textarea.js | 5 + static/revealjs/js/ace-1.1.8/ext-themelist.js | 5 + .../revealjs/js/ace-1.1.8/ext-whitespace.js | 5 + .../revealjs/js/ace-1.1.8/keybinding-emacs.js | 1 + .../revealjs/js/ace-1.1.8/keybinding-vim.js | 1 + static/revealjs/js/ace-1.1.8/mode-abap.js | 1 + .../js/ace-1.1.8/mode-actionscript.js | 1 + static/revealjs/js/ace-1.1.8/mode-ada.js | 1 + .../revealjs/js/ace-1.1.8/mode-apache_conf.js | 1 + .../revealjs/js/ace-1.1.8/mode-applescript.js | 1 + static/revealjs/js/ace-1.1.8/mode-asciidoc.js | 1 + .../js/ace-1.1.8/mode-assembly_x86.js | 1 + .../revealjs/js/ace-1.1.8/mode-autohotkey.js | 1 + .../revealjs/js/ace-1.1.8/mode-batchfile.js | 1 + static/revealjs/js/ace-1.1.8/mode-c9search.js | 1 + static/revealjs/js/ace-1.1.8/mode-c_cpp.js | 1 + static/revealjs/js/ace-1.1.8/mode-cirru.js | 1 + static/revealjs/js/ace-1.1.8/mode-clojure.js | 1 + static/revealjs/js/ace-1.1.8/mode-cobol.js | 1 + static/revealjs/js/ace-1.1.8/mode-coffee.js | 1 + .../revealjs/js/ace-1.1.8/mode-coldfusion.js | 1 + static/revealjs/js/ace-1.1.8/mode-csharp.js | 1 + static/revealjs/js/ace-1.1.8/mode-css.js | 1 + static/revealjs/js/ace-1.1.8/mode-curly.js | 1 + static/revealjs/js/ace-1.1.8/mode-d.js | 1 + static/revealjs/js/ace-1.1.8/mode-dart.js | 1 + static/revealjs/js/ace-1.1.8/mode-diff.js | 1 + static/revealjs/js/ace-1.1.8/mode-django.js | 1 + .../revealjs/js/ace-1.1.8/mode-dockerfile.js | 1 + static/revealjs/js/ace-1.1.8/mode-dot.js | 1 + static/revealjs/js/ace-1.1.8/mode-eiffel.js | 1 + static/revealjs/js/ace-1.1.8/mode-ejs.js | 1 + static/revealjs/js/ace-1.1.8/mode-elixir.js | 1 + static/revealjs/js/ace-1.1.8/mode-elm.js | 1 + static/revealjs/js/ace-1.1.8/mode-erlang.js | 1 + static/revealjs/js/ace-1.1.8/mode-forth.js | 1 + static/revealjs/js/ace-1.1.8/mode-ftl.js | 1 + static/revealjs/js/ace-1.1.8/mode-gcode.js | 1 + static/revealjs/js/ace-1.1.8/mode-gherkin.js | 1 + .../revealjs/js/ace-1.1.8/mode-gitignore.js | 1 + static/revealjs/js/ace-1.1.8/mode-glsl.js | 1 + static/revealjs/js/ace-1.1.8/mode-golang.js | 1 + static/revealjs/js/ace-1.1.8/mode-groovy.js | 1 + static/revealjs/js/ace-1.1.8/mode-haml.js | 1 + .../revealjs/js/ace-1.1.8/mode-handlebars.js | 1 + static/revealjs/js/ace-1.1.8/mode-haskell.js | 1 + static/revealjs/js/ace-1.1.8/mode-haxe.js | 1 + static/revealjs/js/ace-1.1.8/mode-html.js | 1 + .../revealjs/js/ace-1.1.8/mode-html_ruby.js | 1 + static/revealjs/js/ace-1.1.8/mode-ini.js | 1 + static/revealjs/js/ace-1.1.8/mode-io.js | 1 + static/revealjs/js/ace-1.1.8/mode-jack.js | 1 + static/revealjs/js/ace-1.1.8/mode-jade.js | 1 + static/revealjs/js/ace-1.1.8/mode-java.js | 1 + .../revealjs/js/ace-1.1.8/mode-javascript.js | 1 + static/revealjs/js/ace-1.1.8/mode-json.js | 1 + static/revealjs/js/ace-1.1.8/mode-jsoniq.js | 1 + static/revealjs/js/ace-1.1.8/mode-jsp.js | 1 + static/revealjs/js/ace-1.1.8/mode-jsx.js | 1 + static/revealjs/js/ace-1.1.8/mode-julia.js | 1 + static/revealjs/js/ace-1.1.8/mode-latex.js | 1 + static/revealjs/js/ace-1.1.8/mode-less.js | 1 + static/revealjs/js/ace-1.1.8/mode-liquid.js | 1 + static/revealjs/js/ace-1.1.8/mode-lisp.js | 1 + .../revealjs/js/ace-1.1.8/mode-livescript.js | 1 + static/revealjs/js/ace-1.1.8/mode-logiql.js | 1 + static/revealjs/js/ace-1.1.8/mode-lsl.js | 1 + static/revealjs/js/ace-1.1.8/mode-lua.js | 1 + static/revealjs/js/ace-1.1.8/mode-luapage.js | 1 + static/revealjs/js/ace-1.1.8/mode-lucene.js | 1 + static/revealjs/js/ace-1.1.8/mode-makefile.js | 1 + static/revealjs/js/ace-1.1.8/mode-markdown.js | 1 + static/revealjs/js/ace-1.1.8/mode-matlab.js | 1 + static/revealjs/js/ace-1.1.8/mode-mel.js | 1 + static/revealjs/js/ace-1.1.8/mode-mushcode.js | 1 + static/revealjs/js/ace-1.1.8/mode-mysql.js | 1 + static/revealjs/js/ace-1.1.8/mode-nix.js | 1 + .../revealjs/js/ace-1.1.8/mode-objectivec.js | 1 + static/revealjs/js/ace-1.1.8/mode-ocaml.js | 1 + static/revealjs/js/ace-1.1.8/mode-pascal.js | 1 + static/revealjs/js/ace-1.1.8/mode-perl.js | 1 + static/revealjs/js/ace-1.1.8/mode-pgsql.js | 1 + static/revealjs/js/ace-1.1.8/mode-php.js | 1 + .../revealjs/js/ace-1.1.8/mode-plain_text.js | 1 + .../revealjs/js/ace-1.1.8/mode-powershell.js | 1 + static/revealjs/js/ace-1.1.8/mode-praat.js | 1 + static/revealjs/js/ace-1.1.8/mode-prolog.js | 1 + .../revealjs/js/ace-1.1.8/mode-properties.js | 1 + static/revealjs/js/ace-1.1.8/mode-protobuf.js | 1 + static/revealjs/js/ace-1.1.8/mode-python.js | 1 + static/revealjs/js/ace-1.1.8/mode-r.js | 1 + static/revealjs/js/ace-1.1.8/mode-rdoc.js | 1 + static/revealjs/js/ace-1.1.8/mode-rhtml.js | 1 + static/revealjs/js/ace-1.1.8/mode-ruby.js | 1 + static/revealjs/js/ace-1.1.8/mode-rust.js | 1 + static/revealjs/js/ace-1.1.8/mode-sass.js | 1 + static/revealjs/js/ace-1.1.8/mode-scad.js | 1 + static/revealjs/js/ace-1.1.8/mode-scala.js | 1 + static/revealjs/js/ace-1.1.8/mode-scheme.js | 1 + static/revealjs/js/ace-1.1.8/mode-scss.js | 1 + static/revealjs/js/ace-1.1.8/mode-sh.js | 1 + static/revealjs/js/ace-1.1.8/mode-sjs.js | 1 + static/revealjs/js/ace-1.1.8/mode-smarty.js | 1 + static/revealjs/js/ace-1.1.8/mode-snippets.js | 1 + .../js/ace-1.1.8/mode-soy_template.js | 1 + static/revealjs/js/ace-1.1.8/mode-space.js | 1 + static/revealjs/js/ace-1.1.8/mode-sql.js | 1 + static/revealjs/js/ace-1.1.8/mode-stylus.js | 1 + static/revealjs/js/ace-1.1.8/mode-svg.js | 1 + static/revealjs/js/ace-1.1.8/mode-tcl.js | 1 + static/revealjs/js/ace-1.1.8/mode-tex.js | 1 + static/revealjs/js/ace-1.1.8/mode-text.js | 0 static/revealjs/js/ace-1.1.8/mode-textile.js | 1 + static/revealjs/js/ace-1.1.8/mode-toml.js | 1 + static/revealjs/js/ace-1.1.8/mode-twig.js | 1 + .../revealjs/js/ace-1.1.8/mode-typescript.js | 1 + static/revealjs/js/ace-1.1.8/mode-vala.js | 1 + static/revealjs/js/ace-1.1.8/mode-vbscript.js | 1 + static/revealjs/js/ace-1.1.8/mode-velocity.js | 1 + static/revealjs/js/ace-1.1.8/mode-verilog.js | 1 + static/revealjs/js/ace-1.1.8/mode-vhdl.js | 1 + static/revealjs/js/ace-1.1.8/mode-xml.js | 1 + static/revealjs/js/ace-1.1.8/mode-xquery.js | 1 + static/revealjs/js/ace-1.1.8/mode-yaml.js | 1 + static/revealjs/js/ace-1.1.8/snippets/abap.js | 1 + .../js/ace-1.1.8/snippets/actionscript.js | 1 + static/revealjs/js/ace-1.1.8/snippets/ada.js | 1 + .../js/ace-1.1.8/snippets/apache_conf.js | 1 + .../js/ace-1.1.8/snippets/applescript.js | 1 + .../js/ace-1.1.8/snippets/asciidoc.js | 1 + .../js/ace-1.1.8/snippets/assembly_x86.js | 1 + .../js/ace-1.1.8/snippets/autohotkey.js | 1 + .../js/ace-1.1.8/snippets/batchfile.js | 1 + .../js/ace-1.1.8/snippets/c9search.js | 1 + .../revealjs/js/ace-1.1.8/snippets/c_cpp.js | 1 + .../revealjs/js/ace-1.1.8/snippets/cirru.js | 1 + .../revealjs/js/ace-1.1.8/snippets/clojure.js | 1 + .../revealjs/js/ace-1.1.8/snippets/cobol.js | 1 + .../revealjs/js/ace-1.1.8/snippets/coffee.js | 1 + .../js/ace-1.1.8/snippets/coldfusion.js | 1 + .../revealjs/js/ace-1.1.8/snippets/csharp.js | 1 + static/revealjs/js/ace-1.1.8/snippets/css.js | 1 + .../revealjs/js/ace-1.1.8/snippets/curly.js | 1 + static/revealjs/js/ace-1.1.8/snippets/d.js | 1 + static/revealjs/js/ace-1.1.8/snippets/dart.js | 1 + static/revealjs/js/ace-1.1.8/snippets/diff.js | 1 + .../revealjs/js/ace-1.1.8/snippets/django.js | 1 + .../js/ace-1.1.8/snippets/dockerfile.js | 1 + static/revealjs/js/ace-1.1.8/snippets/dot.js | 1 + .../revealjs/js/ace-1.1.8/snippets/eiffel.js | 1 + static/revealjs/js/ace-1.1.8/snippets/ejs.js | 1 + .../revealjs/js/ace-1.1.8/snippets/elixir.js | 1 + static/revealjs/js/ace-1.1.8/snippets/elm.js | 1 + .../revealjs/js/ace-1.1.8/snippets/erlang.js | 1 + .../revealjs/js/ace-1.1.8/snippets/forth.js | 1 + static/revealjs/js/ace-1.1.8/snippets/ftl.js | 1 + .../revealjs/js/ace-1.1.8/snippets/gcode.js | 1 + .../revealjs/js/ace-1.1.8/snippets/gherkin.js | 1 + .../js/ace-1.1.8/snippets/gitignore.js | 1 + static/revealjs/js/ace-1.1.8/snippets/glsl.js | 1 + .../revealjs/js/ace-1.1.8/snippets/golang.js | 1 + .../revealjs/js/ace-1.1.8/snippets/groovy.js | 1 + static/revealjs/js/ace-1.1.8/snippets/haml.js | 1 + .../js/ace-1.1.8/snippets/handlebars.js | 1 + .../revealjs/js/ace-1.1.8/snippets/haskell.js | 1 + static/revealjs/js/ace-1.1.8/snippets/haxe.js | 1 + static/revealjs/js/ace-1.1.8/snippets/html.js | 1 + .../js/ace-1.1.8/snippets/html_ruby.js | 1 + static/revealjs/js/ace-1.1.8/snippets/ini.js | 1 + static/revealjs/js/ace-1.1.8/snippets/io.js | 1 + static/revealjs/js/ace-1.1.8/snippets/jack.js | 1 + static/revealjs/js/ace-1.1.8/snippets/jade.js | 1 + static/revealjs/js/ace-1.1.8/snippets/java.js | 1 + .../js/ace-1.1.8/snippets/javascript.js | 1 + static/revealjs/js/ace-1.1.8/snippets/json.js | 1 + .../revealjs/js/ace-1.1.8/snippets/jsoniq.js | 1 + static/revealjs/js/ace-1.1.8/snippets/jsp.js | 1 + static/revealjs/js/ace-1.1.8/snippets/jsx.js | 1 + .../revealjs/js/ace-1.1.8/snippets/julia.js | 1 + .../revealjs/js/ace-1.1.8/snippets/latex.js | 1 + static/revealjs/js/ace-1.1.8/snippets/less.js | 1 + .../revealjs/js/ace-1.1.8/snippets/liquid.js | 1 + static/revealjs/js/ace-1.1.8/snippets/lisp.js | 1 + .../js/ace-1.1.8/snippets/livescript.js | 1 + .../revealjs/js/ace-1.1.8/snippets/logiql.js | 1 + static/revealjs/js/ace-1.1.8/snippets/lsl.js | 1 + static/revealjs/js/ace-1.1.8/snippets/lua.js | 1 + .../revealjs/js/ace-1.1.8/snippets/luapage.js | 1 + .../revealjs/js/ace-1.1.8/snippets/lucene.js | 1 + .../js/ace-1.1.8/snippets/makefile.js | 1 + .../js/ace-1.1.8/snippets/markdown.js | 1 + .../revealjs/js/ace-1.1.8/snippets/matlab.js | 1 + static/revealjs/js/ace-1.1.8/snippets/mel.js | 1 + .../js/ace-1.1.8/snippets/mushcode.js | 1 + .../revealjs/js/ace-1.1.8/snippets/mysql.js | 1 + static/revealjs/js/ace-1.1.8/snippets/nix.js | 1 + .../js/ace-1.1.8/snippets/objectivec.js | 1 + .../revealjs/js/ace-1.1.8/snippets/ocaml.js | 1 + .../revealjs/js/ace-1.1.8/snippets/pascal.js | 1 + static/revealjs/js/ace-1.1.8/snippets/perl.js | 1 + .../revealjs/js/ace-1.1.8/snippets/pgsql.js | 1 + static/revealjs/js/ace-1.1.8/snippets/php.js | 1 + .../js/ace-1.1.8/snippets/plain_text.js | 1 + .../js/ace-1.1.8/snippets/powershell.js | 1 + .../revealjs/js/ace-1.1.8/snippets/praat.js | 1 + .../revealjs/js/ace-1.1.8/snippets/prolog.js | 1 + .../js/ace-1.1.8/snippets/properties.js | 1 + .../js/ace-1.1.8/snippets/protobuf.js | 1 + .../revealjs/js/ace-1.1.8/snippets/python.js | 1 + static/revealjs/js/ace-1.1.8/snippets/r.js | 1 + static/revealjs/js/ace-1.1.8/snippets/rdoc.js | 1 + .../revealjs/js/ace-1.1.8/snippets/rhtml.js | 1 + static/revealjs/js/ace-1.1.8/snippets/ruby.js | 1 + static/revealjs/js/ace-1.1.8/snippets/rust.js | 1 + static/revealjs/js/ace-1.1.8/snippets/sass.js | 1 + static/revealjs/js/ace-1.1.8/snippets/scad.js | 1 + .../revealjs/js/ace-1.1.8/snippets/scala.js | 1 + .../revealjs/js/ace-1.1.8/snippets/scheme.js | 1 + static/revealjs/js/ace-1.1.8/snippets/scss.js | 1 + static/revealjs/js/ace-1.1.8/snippets/sh.js | 1 + static/revealjs/js/ace-1.1.8/snippets/sjs.js | 1 + .../revealjs/js/ace-1.1.8/snippets/smarty.js | 1 + .../js/ace-1.1.8/snippets/snippets.js | 1 + .../js/ace-1.1.8/snippets/soy_template.js | 1 + .../revealjs/js/ace-1.1.8/snippets/space.js | 1 + static/revealjs/js/ace-1.1.8/snippets/sql.js | 1 + .../revealjs/js/ace-1.1.8/snippets/stylus.js | 1 + static/revealjs/js/ace-1.1.8/snippets/svg.js | 1 + static/revealjs/js/ace-1.1.8/snippets/tcl.js | 1 + static/revealjs/js/ace-1.1.8/snippets/tex.js | 1 + static/revealjs/js/ace-1.1.8/snippets/text.js | 1 + .../revealjs/js/ace-1.1.8/snippets/textile.js | 1 + static/revealjs/js/ace-1.1.8/snippets/toml.js | 1 + static/revealjs/js/ace-1.1.8/snippets/twig.js | 1 + .../js/ace-1.1.8/snippets/typescript.js | 1 + static/revealjs/js/ace-1.1.8/snippets/vala.js | 1 + .../js/ace-1.1.8/snippets/vbscript.js | 1 + .../js/ace-1.1.8/snippets/velocity.js | 1 + .../revealjs/js/ace-1.1.8/snippets/verilog.js | 1 + static/revealjs/js/ace-1.1.8/snippets/vhdl.js | 1 + static/revealjs/js/ace-1.1.8/snippets/xml.js | 1 + .../revealjs/js/ace-1.1.8/snippets/xquery.js | 1 + static/revealjs/js/ace-1.1.8/snippets/yaml.js | 1 + .../revealjs/js/ace-1.1.8/theme-ambiance.js | 1 + static/revealjs/js/ace-1.1.8/theme-chaos.js | 1 + static/revealjs/js/ace-1.1.8/theme-chrome.js | 1 + static/revealjs/js/ace-1.1.8/theme-clouds.js | 1 + .../js/ace-1.1.8/theme-clouds_midnight.js | 1 + static/revealjs/js/ace-1.1.8/theme-cobalt.js | 1 + .../js/ace-1.1.8/theme-crimson_editor.js | 1 + static/revealjs/js/ace-1.1.8/theme-dawn.js | 1 + .../js/ace-1.1.8/theme-dreamweaver.js | 1 + static/revealjs/js/ace-1.1.8/theme-eclipse.js | 1 + static/revealjs/js/ace-1.1.8/theme-github.js | 1 + .../js/ace-1.1.8/theme-idle_fingers.js | 1 + .../js/ace-1.1.8/theme-katzenmilch.js | 1 + .../revealjs/js/ace-1.1.8/theme-kr_theme.js | 1 + static/revealjs/js/ace-1.1.8/theme-kuroir.js | 1 + .../revealjs/js/ace-1.1.8/theme-merbivore.js | 1 + .../js/ace-1.1.8/theme-merbivore_soft.js | 1 + .../js/ace-1.1.8/theme-mono_industrial.js | 1 + static/revealjs/js/ace-1.1.8/theme-monokai.js | 1 + .../js/ace-1.1.8/theme-pastel_on_dark.js | 1 + .../js/ace-1.1.8/theme-solarized_dark.js | 1 + .../js/ace-1.1.8/theme-solarized_light.js | 1 + .../revealjs/js/ace-1.1.8/theme-terminal.js | 1 + .../revealjs/js/ace-1.1.8/theme-textmate.js | 1 + .../revealjs/js/ace-1.1.8/theme-tomorrow.js | 1 + .../js/ace-1.1.8/theme-tomorrow_night.js | 1 + .../js/ace-1.1.8/theme-tomorrow_night_blue.js | 1 + .../ace-1.1.8/theme-tomorrow_night_bright.js | 1 + .../theme-tomorrow_night_eighties.js | 1 + .../revealjs/js/ace-1.1.8/theme-twilight.js | 1 + .../js/ace-1.1.8/theme-vibrant_ink.js | 1 + static/revealjs/js/ace-1.1.8/theme-xcode.js | 1 + static/revealjs/js/ace-1.1.8/worker-coffee.js | 1 + static/revealjs/js/ace-1.1.8/worker-css.js | 1 + static/revealjs/js/ace-1.1.8/worker-html.js | 1 + .../js/ace-1.1.8/worker-javascript.js | 1 + static/revealjs/js/ace-1.1.8/worker-json.js | 1 + static/revealjs/js/ace-1.1.8/worker-lua.js | 1 + static/revealjs/js/ace-1.1.8/worker-php.js | 1 + static/revealjs/js/ace-1.1.8/worker-xquery.js | 1 + static/revealjs/js/jquery-2.1.3.min.js | 4 + static/revealjs/js/jquery-debounce-1.0.5.js | 71 + static/revealjs/js/reveal.js | 4276 +++++++++++++++++ static/revealjs/js/reveal.min.js | 9 + static/revealjs/lib/css/zenburn.css | 117 + .../revealjs/lib/font/league-gothic/LICENSE | 2 + .../lib/font/league-gothic/league-gothic.css | 10 + .../lib/font/league-gothic/league-gothic.eot | Bin 0 -> 25696 bytes .../lib/font/league-gothic/league-gothic.ttf | Bin 0 -> 64256 bytes .../lib/font/league-gothic/league-gothic.woff | Bin 0 -> 30764 bytes .../revealjs/lib/font/source-sans-pro/LICENSE | 45 + .../source-sans-pro-italic.eot | Bin 0 -> 75720 bytes .../source-sans-pro-italic.ttf | Bin 0 -> 238084 bytes .../source-sans-pro-italic.woff | Bin 0 -> 98556 bytes .../source-sans-pro-regular.eot | Bin 0 -> 88070 bytes .../source-sans-pro-regular.ttf | Bin 0 -> 288008 bytes .../source-sans-pro-regular.woff | Bin 0 -> 114324 bytes .../source-sans-pro-semibold.eot | Bin 0 -> 89897 bytes .../source-sans-pro-semibold.ttf | Bin 0 -> 284640 bytes .../source-sans-pro-semibold.woff | Bin 0 -> 115648 bytes .../source-sans-pro-semibolditalic.eot | Bin 0 -> 75706 bytes .../source-sans-pro-semibolditalic.ttf | Bin 0 -> 240944 bytes .../source-sans-pro-semibolditalic.woff | Bin 0 -> 98816 bytes .../font/source-sans-pro/source-sans-pro.css | 39 + static/revealjs/lib/js/classList.js | 2 + static/revealjs/lib/js/head.min.js | 8 + static/revealjs/lib/js/html5shiv.js | 7 + static/revealjs/package.json | 48 + static/revealjs/plugin/highlight/highlight.js | 30 + static/revealjs/plugin/leap/leap.js | 159 + static/revealjs/plugin/markdown/example.html | 129 + static/revealjs/plugin/markdown/example.md | 31 + static/revealjs/plugin/markdown/markdown.js | 393 ++ static/revealjs/plugin/markdown/marked.js | 37 + static/revealjs/plugin/math/math.js | 64 + static/revealjs/plugin/multiplex/client.js | 13 + static/revealjs/plugin/multiplex/index.js | 56 + static/revealjs/plugin/multiplex/master.js | 51 + static/revealjs/plugin/notes-server/client.js | 60 + static/revealjs/plugin/notes-server/index.js | 66 + .../revealjs/plugin/notes-server/notes.html | 396 ++ static/revealjs/plugin/notes/notes.html | 406 ++ static/revealjs/plugin/notes/notes.js | 122 + static/revealjs/plugin/print-pdf/print-pdf.js | 48 + static/revealjs/plugin/remotes/remotes.js | 39 + static/revealjs/plugin/search/search.js | 196 + static/revealjs/plugin/zoom-js/zoom.js | 278 ++ static/slides.html | 49 + templates/index.html | 30 + 388 files changed, 15723 insertions(+) create mode 100644 initial-slides.md create mode 100644 static/css/index.css create mode 100644 static/js/index.js create mode 100644 static/js/save.js create mode 100644 static/js/slides.js create mode 100644 static/revealjs/Gruntfile.js create mode 100644 static/revealjs/LICENSE create mode 100644 static/revealjs/README.md create mode 100644 static/revealjs/css/print/paper.css create mode 100644 static/revealjs/css/print/pdf.css create mode 100644 static/revealjs/css/reveal.css create mode 100644 static/revealjs/css/reveal.min.css create mode 100644 static/revealjs/css/reveal.scss create mode 100644 static/revealjs/css/theme/README.md create mode 100644 static/revealjs/css/theme/beige.css create mode 100644 static/revealjs/css/theme/black.css create mode 100644 static/revealjs/css/theme/blood.css create mode 100644 static/revealjs/css/theme/league.css create mode 100644 static/revealjs/css/theme/moon.css create mode 100644 static/revealjs/css/theme/night.css create mode 100644 static/revealjs/css/theme/serif.css create mode 100644 static/revealjs/css/theme/simple.css create mode 100644 static/revealjs/css/theme/sky.css create mode 100644 static/revealjs/css/theme/solarized.css create mode 100644 static/revealjs/css/theme/source/beige.scss create mode 100644 static/revealjs/css/theme/source/black.scss create mode 100644 static/revealjs/css/theme/source/blood.scss create mode 100644 static/revealjs/css/theme/source/league.scss create mode 100644 static/revealjs/css/theme/source/moon.scss create mode 100644 static/revealjs/css/theme/source/night.scss create mode 100644 static/revealjs/css/theme/source/serif.scss create mode 100644 static/revealjs/css/theme/source/simple.scss create mode 100644 static/revealjs/css/theme/source/sky.scss create mode 100644 static/revealjs/css/theme/source/solarized.scss create mode 100644 static/revealjs/css/theme/source/white.scss create mode 100644 static/revealjs/css/theme/template/mixins.scss create mode 100644 static/revealjs/css/theme/template/settings.scss create mode 100644 static/revealjs/css/theme/template/theme.scss create mode 100644 static/revealjs/css/theme/white.css create mode 100644 static/revealjs/js/ace-1.1.8/ace.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-beautify.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-chromevox.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-elastic_tabstops_lite.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-emmet.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-error_marker.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-keybinding_menu.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-language_tools.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-linking.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-modelist.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-old_ie.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-searchbox.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-settings_menu.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-spellcheck.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-split.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-static_highlight.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-statusbar.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-textarea.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-themelist.js create mode 100644 static/revealjs/js/ace-1.1.8/ext-whitespace.js create mode 100644 static/revealjs/js/ace-1.1.8/keybinding-emacs.js create mode 100644 static/revealjs/js/ace-1.1.8/keybinding-vim.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-abap.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-actionscript.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-ada.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-apache_conf.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-applescript.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-asciidoc.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-assembly_x86.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-autohotkey.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-batchfile.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-c9search.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-c_cpp.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-cirru.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-clojure.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-cobol.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-coffee.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-coldfusion.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-csharp.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-css.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-curly.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-d.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-dart.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-diff.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-django.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-dockerfile.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-dot.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-eiffel.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-ejs.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-elixir.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-elm.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-erlang.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-forth.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-ftl.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-gcode.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-gherkin.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-gitignore.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-glsl.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-golang.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-groovy.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-haml.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-handlebars.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-haskell.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-haxe.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-html.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-html_ruby.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-ini.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-io.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-jack.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-jade.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-java.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-javascript.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-json.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-jsoniq.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-jsp.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-jsx.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-julia.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-latex.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-less.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-liquid.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-lisp.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-livescript.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-logiql.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-lsl.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-lua.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-luapage.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-lucene.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-makefile.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-markdown.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-matlab.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-mel.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-mushcode.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-mysql.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-nix.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-objectivec.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-ocaml.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-pascal.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-perl.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-pgsql.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-php.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-plain_text.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-powershell.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-praat.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-prolog.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-properties.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-protobuf.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-python.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-r.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-rdoc.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-rhtml.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-ruby.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-rust.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-sass.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-scad.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-scala.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-scheme.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-scss.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-sh.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-sjs.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-smarty.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-snippets.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-soy_template.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-space.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-sql.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-stylus.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-svg.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-tcl.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-tex.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-text.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-textile.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-toml.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-twig.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-typescript.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-vala.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-vbscript.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-velocity.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-verilog.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-vhdl.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-xml.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-xquery.js create mode 100644 static/revealjs/js/ace-1.1.8/mode-yaml.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/abap.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/actionscript.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/ada.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/apache_conf.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/applescript.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/asciidoc.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/assembly_x86.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/autohotkey.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/batchfile.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/c9search.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/c_cpp.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/cirru.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/clojure.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/cobol.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/coffee.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/coldfusion.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/csharp.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/css.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/curly.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/d.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/dart.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/diff.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/django.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/dockerfile.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/dot.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/eiffel.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/ejs.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/elixir.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/elm.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/erlang.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/forth.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/ftl.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/gcode.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/gherkin.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/gitignore.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/glsl.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/golang.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/groovy.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/haml.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/handlebars.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/haskell.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/haxe.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/html.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/html_ruby.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/ini.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/io.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/jack.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/jade.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/java.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/javascript.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/json.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/jsoniq.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/jsp.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/jsx.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/julia.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/latex.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/less.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/liquid.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/lisp.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/livescript.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/logiql.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/lsl.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/lua.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/luapage.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/lucene.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/makefile.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/markdown.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/matlab.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/mel.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/mushcode.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/mysql.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/nix.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/objectivec.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/ocaml.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/pascal.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/perl.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/pgsql.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/php.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/plain_text.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/powershell.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/praat.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/prolog.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/properties.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/protobuf.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/python.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/r.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/rdoc.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/rhtml.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/ruby.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/rust.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/sass.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/scad.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/scala.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/scheme.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/scss.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/sh.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/sjs.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/smarty.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/snippets.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/soy_template.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/space.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/sql.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/stylus.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/svg.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/tcl.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/tex.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/text.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/textile.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/toml.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/twig.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/typescript.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/vala.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/vbscript.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/velocity.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/verilog.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/vhdl.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/xml.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/xquery.js create mode 100644 static/revealjs/js/ace-1.1.8/snippets/yaml.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-ambiance.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-chaos.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-chrome.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-clouds.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-clouds_midnight.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-cobalt.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-crimson_editor.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-dawn.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-dreamweaver.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-eclipse.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-github.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-idle_fingers.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-katzenmilch.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-kr_theme.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-kuroir.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-merbivore.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-merbivore_soft.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-mono_industrial.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-monokai.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-pastel_on_dark.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-solarized_dark.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-solarized_light.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-terminal.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-textmate.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-tomorrow.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-tomorrow_night.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-tomorrow_night_blue.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-tomorrow_night_bright.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-tomorrow_night_eighties.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-twilight.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-vibrant_ink.js create mode 100644 static/revealjs/js/ace-1.1.8/theme-xcode.js create mode 100644 static/revealjs/js/ace-1.1.8/worker-coffee.js create mode 100644 static/revealjs/js/ace-1.1.8/worker-css.js create mode 100644 static/revealjs/js/ace-1.1.8/worker-html.js create mode 100644 static/revealjs/js/ace-1.1.8/worker-javascript.js create mode 100644 static/revealjs/js/ace-1.1.8/worker-json.js create mode 100644 static/revealjs/js/ace-1.1.8/worker-lua.js create mode 100644 static/revealjs/js/ace-1.1.8/worker-php.js create mode 100644 static/revealjs/js/ace-1.1.8/worker-xquery.js create mode 100644 static/revealjs/js/jquery-2.1.3.min.js create mode 100644 static/revealjs/js/jquery-debounce-1.0.5.js create mode 100644 static/revealjs/js/reveal.js create mode 100644 static/revealjs/js/reveal.min.js create mode 100644 static/revealjs/lib/css/zenburn.css create mode 100644 static/revealjs/lib/font/league-gothic/LICENSE create mode 100644 static/revealjs/lib/font/league-gothic/league-gothic.css create mode 100755 static/revealjs/lib/font/league-gothic/league-gothic.eot create mode 100755 static/revealjs/lib/font/league-gothic/league-gothic.ttf create mode 100755 static/revealjs/lib/font/league-gothic/league-gothic.woff create mode 100644 static/revealjs/lib/font/source-sans-pro/LICENSE create mode 100755 static/revealjs/lib/font/source-sans-pro/source-sans-pro-italic.eot create mode 100755 static/revealjs/lib/font/source-sans-pro/source-sans-pro-italic.ttf create mode 100755 static/revealjs/lib/font/source-sans-pro/source-sans-pro-italic.woff create mode 100755 static/revealjs/lib/font/source-sans-pro/source-sans-pro-regular.eot create mode 100755 static/revealjs/lib/font/source-sans-pro/source-sans-pro-regular.ttf create mode 100755 static/revealjs/lib/font/source-sans-pro/source-sans-pro-regular.woff create mode 100755 static/revealjs/lib/font/source-sans-pro/source-sans-pro-semibold.eot create mode 100755 static/revealjs/lib/font/source-sans-pro/source-sans-pro-semibold.ttf create mode 100755 static/revealjs/lib/font/source-sans-pro/source-sans-pro-semibold.woff create mode 100755 static/revealjs/lib/font/source-sans-pro/source-sans-pro-semibolditalic.eot create mode 100755 static/revealjs/lib/font/source-sans-pro/source-sans-pro-semibolditalic.ttf create mode 100755 static/revealjs/lib/font/source-sans-pro/source-sans-pro-semibolditalic.woff create mode 100644 static/revealjs/lib/font/source-sans-pro/source-sans-pro.css create mode 100644 static/revealjs/lib/js/classList.js create mode 100644 static/revealjs/lib/js/head.min.js create mode 100644 static/revealjs/lib/js/html5shiv.js create mode 100644 static/revealjs/package.json create mode 100644 static/revealjs/plugin/highlight/highlight.js create mode 100644 static/revealjs/plugin/leap/leap.js create mode 100644 static/revealjs/plugin/markdown/example.html create mode 100644 static/revealjs/plugin/markdown/example.md create mode 100755 static/revealjs/plugin/markdown/markdown.js create mode 100644 static/revealjs/plugin/markdown/marked.js create mode 100755 static/revealjs/plugin/math/math.js create mode 100644 static/revealjs/plugin/multiplex/client.js create mode 100644 static/revealjs/plugin/multiplex/index.js create mode 100644 static/revealjs/plugin/multiplex/master.js create mode 100644 static/revealjs/plugin/notes-server/client.js create mode 100644 static/revealjs/plugin/notes-server/index.js create mode 100644 static/revealjs/plugin/notes-server/notes.html create mode 100644 static/revealjs/plugin/notes/notes.html create mode 100644 static/revealjs/plugin/notes/notes.js create mode 100644 static/revealjs/plugin/print-pdf/print-pdf.js create mode 100644 static/revealjs/plugin/remotes/remotes.js create mode 100644 static/revealjs/plugin/search/search.js create mode 100644 static/revealjs/plugin/zoom-js/zoom.js create mode 100644 static/slides.html create mode 100644 templates/index.html diff --git a/initial-slides.md b/initial-slides.md new file mode 100644 index 0000000..1146ae4 --- /dev/null +++ b/initial-slides.md @@ -0,0 +1,31 @@ +# Hacker Slides + +### Hack together simple slides + +--- + +## The Basics + +- Separate slides using '`---`' on a blank line +- Write github flavored markdown +- Click 'Present' (top right) when you're ready to talk + +--- + +## Quick tips + +- There is also a speaker view, with notes - press '`s`' +- Press '`?`' with focus on the presentation for shortcuts +- You can use html when necessary +- Share the 'Present' URL with anyone you like! + +Note: +- Anything after `Note:` will only appear here + +--- + +## Learn more + +- [RevealJS Demo/Manual](http://lab.hakim.se/reveal-js) +- [RevealJS Project/README](https://github.com/hakimel/reveal.js) +- [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown) diff --git a/static/css/index.css b/static/css/index.css new file mode 100644 index 0000000..81a28eb --- /dev/null +++ b/static/css/index.css @@ -0,0 +1,40 @@ +body { + margin: 0 0 0 0; +} +#edit-pane { + position: fixed; + top: 0; + width: 40%; + height: 100%; + font-size: 16px; +} +#edit-pane #controls { + color: #2e2e2e; + position: absolute; + right: 0; + top: 0; + z-index: 1; + margin: 5px 5px 0 0; +} +#edit-pane #controls a { + font-weight: bold; + text-decoration: none; + color: #2e2e2e; +} +#editor { + width: 100%; + height: 100%; + font-size: 16px; +} +#preview { + position: absolute; + left: 40%; + top: 0; + right: 0; + bottom: 0; +} +#preview iframe { + height: 100%; + width: 100%; + border: none; +} diff --git a/static/js/index.js b/static/js/index.js new file mode 100644 index 0000000..0518c2c --- /dev/null +++ b/static/js/index.js @@ -0,0 +1,54 @@ +$(function() { + + function slideSeparatorLines(text) { + var lines = text.split('\n'); + + var separatorLineNumbers = []; + + for (i = 0; i < lines.length; i++) { + var line = lines[i]; + if (line === '---') { + separatorLineNumbers.push(i); + } + } + + return separatorLineNumbers; + } + + function currentCursorSlide(cursorLine) { + var text = ace.edit("editor").getValue(); + var separatorPositions = slideSeparatorLines(text); + var slideNumber = separatorPositions.length; + separatorPositions.every(function(pos, num) { + if (pos >= cursorLine) { + slideNumber = num; + return false; + } + return true; + }); + return slideNumber; + } + + + var editor = ace.edit("editor"); + editor.setTheme("ace/theme/chrome"); + editor.getSession().setMode("ace/mode/markdown"); + editor.getSession().setUseWrapMode(true); + editor.setShowPrintMargin(true); + + $.get('/slides.md', function(data) { + editor.setValue(data, -1); + }); + + ace.edit('editor').getSession().selection.on('changeCursor', function(e) { + var cursorRow = ace.edit('editor').getCursorPosition().row; + var currentSlide = currentCursorSlide(cursorRow); + $('#slides-frame')[0].contentWindow.postMessage(JSON.stringify({ + method: 'slide', + args: [currentSlide] + }), window.location.origin); + }); +}); + + + diff --git a/static/js/save.js b/static/js/save.js new file mode 100644 index 0000000..835edb1 --- /dev/null +++ b/static/js/save.js @@ -0,0 +1,19 @@ +$(function() { + function reloadMarkdown() { + $('#slides-frame')[0].contentWindow.postMessage(JSON.stringify({ + method: 'reloadMarkdown' + }), window.location.origin); + } + + window.save = function() { + var editor = ace.edit("editor"); + + $.ajax("/slides.md", { + type: 'put', + data: editor.getValue(), + success: reloadMarkdown + }); + }; + + $('#editor').keyup($.debounce(window.save, 300)); +}); diff --git a/static/js/slides.js b/static/js/slides.js new file mode 100644 index 0000000..929d858 --- /dev/null +++ b/static/js/slides.js @@ -0,0 +1,73 @@ +function isPreview() { + return !!window.location.search.match(/preview/gi); +} + +function initializeReveal() { + // Full list of configuration options available at: + // https://github.com/hakimel/reveal.js#configuration + Reveal.initialize({ + controls: true, + progress: true, + history: true, + center: true, + transition: 'slide', // none/fade/slide/convex/concave/zoom + transitionSpeed: isPreview() ? 'fast' : 'default', + embedded: isPreview() ? true : false, + + // Optional reveal.js plugins + dependencies: [ + { src: '/static/revealjs/lib/js/classList.js', condition: function() { return !document.body.classList; } }, + { src: '/static/revealjs/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, + { src: '/static/revealjs/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); }, callback: function() { externalLinksInNewWindow(); } }, + { src: '/static/revealjs/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }, + { src: '/static/revealjs/plugin/zoom-js/zoom.js', async: true }, + { src: '/static/revealjs/plugin/notes/notes.js', async: true } + ] + }); +} + +function highlightAnyCodeBlocks() { + $(document).ready(function() { + $('pre code').each(function(i, block) { + hljs.highlightBlock(block); + }); + }); +} + +function insertMarkdownReference() { + var markdownReference = $('
', { + 'data-markdown': "/slides.md", + 'data-separator': "^-( *)-( *)-( *-*)*", + 'data-separator-notes': "^Note:", + 'data-charset': "utf-8" + }); + + $('.slides').html(markdownReference); +} + +function scrollToCurrentSlide() { + var i = Reveal.getIndices(); + Reveal.slide(i.h, i.v, i.f); +} + +function reloadMarkdown() { + insertMarkdownReference(); + RevealMarkdown.initialize(); + highlightAnyCodeBlocks(); + scrollToCurrentSlide(); +} + +function externalLinksInNewWindow() { + $(document.links).filter(function() { + return this.hostname != window.location.hostname; + }).attr('target', '_blank'); +} + +insertMarkdownReference(); +initializeReveal(); + +// Monkey patch Reveal so we can reload markdown through an +// inter window message (using the reveal rpc api) +// (yes, reveal has an rpc api!) +// see save.js +Reveal.reloadMarkdown = reloadMarkdown; diff --git a/static/revealjs/Gruntfile.js b/static/revealjs/Gruntfile.js new file mode 100644 index 0000000..3e67b9f --- /dev/null +++ b/static/revealjs/Gruntfile.js @@ -0,0 +1,174 @@ +/* global module:false */ +module.exports = function(grunt) { + var port = grunt.option('port') || 8000; + // Project configuration + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + meta: { + banner: + '/*!\n' + + ' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' + + ' * http://lab.hakim.se/reveal-js\n' + + ' * MIT licensed\n' + + ' *\n' + + ' * Copyright (C) 2015 Hakim El Hattab, http://hakim.se\n' + + ' */' + }, + + qunit: { + files: [ 'test/*.html' ] + }, + + uglify: { + options: { + banner: '<%= meta.banner %>\n' + }, + build: { + src: 'js/reveal.js', + dest: 'js/reveal.min.js' + } + }, + + sass: { + core: { + files: { + 'css/reveal.css': 'css/reveal.scss', + } + }, + themes: { + files: { + 'css/theme/black.css': 'css/theme/source/black.scss', + 'css/theme/white.css': 'css/theme/source/white.scss', + 'css/theme/league.css': 'css/theme/source/league.scss', + 'css/theme/beige.css': 'css/theme/source/beige.scss', + 'css/theme/night.css': 'css/theme/source/night.scss', + 'css/theme/serif.css': 'css/theme/source/serif.scss', + 'css/theme/simple.css': 'css/theme/source/simple.scss', + 'css/theme/sky.css': 'css/theme/source/sky.scss', + 'css/theme/moon.css': 'css/theme/source/moon.scss', + 'css/theme/solarized.css': 'css/theme/source/solarized.scss', + 'css/theme/blood.css': 'css/theme/source/blood.scss' + } + } + }, + + autoprefixer: { + dist: { + src: 'css/reveal.css' + } + }, + + cssmin: { + compress: { + files: { + 'css/reveal.min.css': [ 'css/reveal.css' ] + } + } + }, + + jshint: { + options: { + curly: false, + eqeqeq: true, + immed: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + eqnull: true, + browser: true, + expr: true, + globals: { + head: false, + module: false, + console: false, + unescape: false, + define: false, + exports: false + } + }, + files: [ 'Gruntfile.js', 'js/reveal.js' ] + }, + + connect: { + server: { + options: { + port: port, + base: '.', + livereload: true, + open: true + } + } + }, + + zip: { + 'reveal-js-presentation.zip': [ + 'index.html', + 'css/**', + 'js/**', + 'lib/**', + 'images/**', + 'plugin/**' + ] + }, + + watch: { + options: { + livereload: true + }, + js: { + files: [ 'Gruntfile.js', 'js/reveal.js' ], + tasks: 'js' + }, + theme: { + files: [ 'css/theme/source/*.scss', 'css/theme/template/*.scss' ], + tasks: 'css-themes' + }, + css: { + files: [ 'css/reveal.scss' ], + tasks: 'css-core' + }, + html: { + files: [ 'index.html'] + } + } + + }); + + // Dependencies + grunt.loadNpmTasks( 'grunt-contrib-qunit' ); + grunt.loadNpmTasks( 'grunt-contrib-jshint' ); + grunt.loadNpmTasks( 'grunt-contrib-cssmin' ); + grunt.loadNpmTasks( 'grunt-contrib-uglify' ); + grunt.loadNpmTasks( 'grunt-contrib-watch' ); + grunt.loadNpmTasks( 'grunt-sass' ); + grunt.loadNpmTasks( 'grunt-contrib-connect' ); + grunt.loadNpmTasks( 'grunt-autoprefixer' ); + grunt.loadNpmTasks( 'grunt-zip' ); + + // Default task + grunt.registerTask( 'default', [ 'css', 'js' ] ); + + // JS task + grunt.registerTask( 'js', [ 'jshint', 'uglify', 'qunit' ] ); + + // Theme CSS + grunt.registerTask( 'css-themes', [ 'sass:themes' ] ); + + // Core framework CSS + grunt.registerTask( 'css-core', [ 'sass:core', 'autoprefixer', 'cssmin' ] ); + + // All CSS + grunt.registerTask( 'css', [ 'sass', 'autoprefixer', 'cssmin' ] ); + + // Package presentation to archive + grunt.registerTask( 'package', [ 'default', 'zip' ] ); + + // Serve presentation locally + grunt.registerTask( 'serve', [ 'connect', 'watch' ] ); + + // Run tests + grunt.registerTask( 'test', [ 'jshint', 'qunit' ] ); + +}; diff --git a/static/revealjs/LICENSE b/static/revealjs/LICENSE new file mode 100644 index 0000000..0962307 --- /dev/null +++ b/static/revealjs/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2015 Hakim El Hattab, http://hakim.se + +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. \ No newline at end of file diff --git a/static/revealjs/README.md b/static/revealjs/README.md new file mode 100644 index 0000000..7532908 --- /dev/null +++ b/static/revealjs/README.md @@ -0,0 +1,950 @@ +# reveal.js [![Build Status](https://travis-ci.org/hakimel/reveal.js.svg?branch=master)](https://travis-ci.org/hakimel/reveal.js) + +A framework for easily creating beautiful presentations using HTML. [Check out the live demo](http://lab.hakim.se/reveal-js/). + +reveal.js comes with a broad range of features including [nested slides](https://github.com/hakimel/reveal.js#markup), [Markdown contents](https://github.com/hakimel/reveal.js#markdown), [PDF export](https://github.com/hakimel/reveal.js#pdf-export), [speaker notes](https://github.com/hakimel/reveal.js#speaker-notes) and a [JavaScript API](https://github.com/hakimel/reveal.js#api). It's best viewed in a modern browser but [fallbacks](https://github.com/hakimel/reveal.js/wiki/Browser-Support) are available to make sure your presentation can still be viewed elsewhere. + + +#### More reading: +- [Installation](#installation): Step-by-step instructions for getting reveal.js running on your computer. +- [Changelog](https://github.com/hakimel/reveal.js/releases): Up-to-date version history. +- [Examples](https://github.com/hakimel/reveal.js/wiki/Example-Presentations): Presentations created with reveal.js, add your own! +- [Browser Support](https://github.com/hakimel/reveal.js/wiki/Browser-Support): Explanation of browser support and fallbacks. + +## Online Editor + +Presentations are written using HTML or Markdown but there's also an online editor for those of you who prefer a graphical interface. Give it a try at [http://slides.com](http://slides.com). + + +## Instructions + +### Markup + +Markup hierarchy needs to be ``
`` where the ``
`` represents one slide and can be repeated indefinitely. If you place multiple ``
``'s inside of another ``
`` they will be shown as vertical slides. The first of the vertical slides is the "root" of the others (at the top), and it will be included in the horizontal sequence. For example: + +```html +
+
+
Single Horizontal Slide
+
+
Vertical Slide 1
+
Vertical Slide 2
+
+
+
+``` + +### Markdown + +It's possible to write your slides using Markdown. To enable Markdown, add the ```data-markdown``` attribute to your ```
``` elements and wrap the contents in a ``` +
+``` + +#### External Markdown + +You can write your content as a separate file and have reveal.js load it at runtime. Note the separator arguments which determine how slides are delimited in the external file. The ```data-charset``` attribute is optional and specifies which charset to use when loading the external file. + +When used locally, this feature requires that reveal.js [runs from a local web server](#full-setup). + +```html +
+
+``` + +#### Element Attributes + +Special syntax (in html comment) is available for adding attributes to Markdown elements. This is useful for fragments, amongst other things. + +```html +
+ +
+``` + +#### Slide Attributes + +Special syntax (in html comment) is available for adding attributes to the slide `
` elements generated by your Markdown. + +```html +
+ +
+``` + + +### Configuration + +At the end of your page you need to initialize reveal by running the following code. Note that all config values are optional and will default as specified below. + +```javascript +Reveal.initialize({ + + // Display controls in the bottom right corner + controls: true, + + // Display a presentation progress bar + progress: true, + + // Display the page number of the current slide + slideNumber: false, + + // Push each slide change to the browser history + history: false, + + // Enable keyboard shortcuts for navigation + keyboard: true, + + // Enable the slide overview mode + overview: true, + + // Vertical centering of slides + center: true, + + // Enables touch navigation on devices with touch input + touch: true, + + // Loop the presentation + loop: false, + + // Change the presentation direction to be RTL + rtl: false, + + // Turns fragments on and off globally + fragments: true, + + // Flags if the presentation is running in an embedded mode, + // i.e. contained within a limited portion of the screen + embedded: false, + + // Flags if we should show a help overlay when the questionmark + // key is pressed + help: true, + + // Number of milliseconds between automatically proceeding to the + // next slide, disabled when set to 0, this value can be overwritten + // by using a data-autoslide attribute on your slides + autoSlide: 0, + + // Stop auto-sliding after user input + autoSlideStoppable: true, + + // Enable slide navigation via mouse wheel + mouseWheel: false, + + // Hides the address bar on mobile devices + hideAddressBar: true, + + // Opens links in an iframe preview overlay + previewLinks: false, + + // Transition style + transition: 'default', // none/fade/slide/convex/concave/zoom + + // Transition speed + transitionSpeed: 'default', // default/fast/slow + + // Transition style for full page slide backgrounds + backgroundTransition: 'default', // none/fade/slide/convex/concave/zoom + + // Number of slides away from the current that are visible + viewDistance: 3, + + // Parallax background image + parallaxBackgroundImage: '', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'" + + // Parallax background size + parallaxBackgroundSize: '' // CSS syntax, e.g. "2100px 900px" + + +}); +``` + + +The configuration can be updated after initialization using the ```configure``` method: + +```javascript +// Turn autoSlide off +Reveal.configure({ autoSlide: 0 }); + +// Start auto-sliding every 5s +Reveal.configure({ autoSlide: 5000 }); +``` + + +### Dependencies + +Reveal.js doesn't _rely_ on any third party scripts to work but a few optional libraries are included by default. These libraries are loaded as dependencies in the order they appear, for example: + +```javascript +Reveal.initialize({ + dependencies: [ + // Cross-browser shim that fully implements classList - https://github.com/eligrey/classList.js/ + { src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } }, + + // Interpret Markdown in
elements + { src: 'plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, + { src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, + + // Syntax highlight for elements + { src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }, + + // Zoom in and out with Alt+click + { src: 'plugin/zoom-js/zoom.js', async: true }, + + // Speaker notes + { src: 'plugin/notes/notes.js', async: true }, + + // Remote control your reveal.js presentation using a touch device + { src: 'plugin/remotes/remotes.js', async: true }, + + // MathJax + { src: 'plugin/math/math.js', async: true } + ] +}); +``` + +You can add your own extensions using the same syntax. The following properties are available for each dependency object: +- **src**: Path to the script to load +- **async**: [optional] Flags if the script should load after reveal.js has started, defaults to false +- **callback**: [optional] Function to execute when the script has loaded +- **condition**: [optional] Function which must return true for the script to be loaded + + +### Presentation Size + +All presentations have a normal size, that is the resolution at which they are authored. The framework will automatically scale presentations uniformly based on this size to ensure that everything fits on any given display or viewport. + +See below for a list of configuration options related to sizing, including default values: + +```javascript +Reveal.initialize({ + + ... + + // The "normal" size of the presentation, aspect ratio will be preserved + // when the presentation is scaled to fit different resolutions. Can be + // specified using percentage units. + width: 960, + height: 700, + + // Factor of the display size that should remain empty around the content + margin: 0.1, + + // Bounds for smallest/largest possible scale to apply to content + minScale: 0.2, + maxScale: 1.0 + +}); +``` + + +### Auto-sliding + +Presentations can be configure to progress through slides automatically, without any user input. To enable this you will need to tell the framework how many milliseconds it should wait between slides: + +```javascript +// Slide every five seconds +Reveal.configure({ + autoSlide: 5000 +}); +``` +When this is turned on a control element will appear that enables users to pause and resume auto-sliding. Alternatively, sliding can be paused or resumed by pressing »a« on the keyboard. Sliding is paused automatically as soon as the user starts navigating. You can disable these controls by specifying ```autoSlideStoppable: false``` in your reveal.js config. + +You can also override the slide duration for individual slides and fragments by using the ```data-autoslide``` attribute: + +```html +
+

After 2 seconds the first fragment will be shown.

+

After 10 seconds the next fragment will be shown.

+

Now, the fragment is displayed for 2 seconds before the next slide is shown.

+
+``` + +Whenever the auto-slide mode is resumed or paused the ```autoslideresumed``` and ```autoslidepaused``` events are fired. + + +### Keyboard Bindings + +If you're unhappy with any of the default keyboard bindings you can override them using the ```keyboard``` config option: + +```javascript +Reveal.configure({ + keyboard: { + 13: 'next', // go to the next slide when the ENTER key is pressed + 27: function() {}, // do something custom when ESC is pressed + 32: null // don't do anything when SPACE is pressed (i.e. disable a reveal.js default binding) + } +}); +``` + +### Lazy Loading + +When working on presentation with a lot of media or iframe content it's important to load lazily. Lazy loading means that reveal.js will only load content for the few slides nearest to the current slide. The number of slides that are preloaded is determined by the `viewDistance` configuration option. + +To enable lazy loading all you need to do is change your "src" attributes to "data-src" as shown below. This is supported for image, video, audio and iframe elements. + +```html +
+ + ${2}\nsnippet iframe.\n ${3}\nsnippet iframe#\n ${3}\nsnippet img\n ${2}${3}\nsnippet img.\n ${3}${4}\nsnippet img#\n ${3}${4}\nsnippet input\n ${5}\nsnippet input.\n ${6}\nsnippet input:text\n ${4}\nsnippet input:submit\n ${4}\nsnippet input:hidden\n ${4}\nsnippet input:button\n ${4}\nsnippet input:image\n ${5}\nsnippet input:checkbox\n ${3}\nsnippet input:radio\n ${3}\nsnippet input:color\n ${4}\nsnippet input:date\n ${4}\nsnippet input:datetime\n ${4}\nsnippet input:datetime-local\n ${4}\nsnippet input:email\n ${4}\nsnippet input:file\n ${4}\nsnippet input:month\n ${4}\nsnippet input:number\n ${4}\nsnippet input:password\n ${4}\nsnippet input:range\n ${4}\nsnippet input:reset\n ${4}\nsnippet input:search\n ${4}\nsnippet input:time\n ${4}\nsnippet input:url\n ${4}\nsnippet input:week\n ${4}\nsnippet ins\n ${1}\nsnippet kbd\n ${1}\nsnippet keygen\n ${1}\nsnippet label\n \nsnippet label:i\n \n ${7}\nsnippet label:s\n \n \nsnippet legend\n ${1}\nsnippet legend+\n ${1}\nsnippet li\n
  • ${1}
  • \nsnippet li.\n
  • ${2}
  • \nsnippet li+\n
  • ${1}
  • \n li+${2}\nsnippet lia\n
  • ${1}
  • \nsnippet lia+\n
  • ${1}
  • \n lia+${3}\nsnippet link\n ${5}\nsnippet link:atom\n ${2}\nsnippet link:css\n ${4}\nsnippet link:favicon\n ${2}\nsnippet link:rss\n ${2}\nsnippet link:touch\n ${2}\nsnippet map\n \n ${2}\n \nsnippet map.\n \n ${3}\n \nsnippet map#\n \n ${5}${6}\n ${7}\nsnippet mark\n ${1}\nsnippet menu\n \n ${1}\n \nsnippet menu:c\n \n ${1}\n \nsnippet menu:t\n \n ${1}\n \nsnippet meta\n ${3}\nsnippet meta:compat\n ${3}\nsnippet meta:refresh\n ${3}\nsnippet meta:utf\n ${3}\nsnippet meter\n ${1}\nsnippet nav\n \nsnippet nav.\n \nsnippet nav#\n \nsnippet noscript\n \nsnippet object\n \n ${3}\n ${4}\n# Embed QT Movie\nsnippet movie\n \n \n \n \n \n ${6}\nsnippet ol\n
      \n ${1}\n
    \nsnippet ol.\n
      \n ${2}\n
    \nsnippet ol+\n
      \n
    1. ${1}
    2. \n li+${2}\n
    \nsnippet opt\n \nsnippet opt+\n \n opt+${3}\nsnippet optt\n \nsnippet optgroup\n \n \n opt+${3}\n \nsnippet output\n ${1}\nsnippet p\n

    ${1}

    \nsnippet param\n ${3}\nsnippet pre\n
    \n		${1}\n	
    \nsnippet progress\n ${1}\nsnippet q\n ${1}\nsnippet rp\n ${1}\nsnippet rt\n ${1}\nsnippet ruby\n \n ${1}\n \nsnippet s\n ${1}\nsnippet samp\n \n ${1}\n \nsnippet script\n +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + +
    +
    + + + + + + + + diff --git a/static/revealjs/plugin/markdown/example.md b/static/revealjs/plugin/markdown/example.md new file mode 100644 index 0000000..6f6f577 --- /dev/null +++ b/static/revealjs/plugin/markdown/example.md @@ -0,0 +1,31 @@ +# Markdown Demo + + + +## External 1.1 + +Content 1.1 + +Note: This will only appear in the speaker notes window. + + +## External 1.2 + +Content 1.2 + + + +## External 2 + +Content 2.1 + + + +## External 3.1 + +Content 3.1 + + +## External 3.2 + +Content 3.2 diff --git a/static/revealjs/plugin/markdown/markdown.js b/static/revealjs/plugin/markdown/markdown.js new file mode 100755 index 0000000..9afee06 --- /dev/null +++ b/static/revealjs/plugin/markdown/markdown.js @@ -0,0 +1,393 @@ +/** + * The reveal.js markdown plugin. Handles parsing of + * markdown inside of presentations as well as loading + * of external markdown documents. + */ +(function( root, factory ) { + if( typeof exports === 'object' ) { + module.exports = factory( require( './marked' ) ); + } + else { + // Browser globals (root is window) + root.RevealMarkdown = factory( root.marked ); + root.RevealMarkdown.initialize(); + } +}( this, function( marked ) { + + if( typeof marked === 'undefined' ) { + throw 'The reveal.js Markdown plugin requires marked to be loaded'; + } + + if( typeof hljs !== 'undefined' ) { + marked.setOptions({ + highlight: function( lang, code ) { + return hljs.highlightAuto( lang, code ).value; + } + }); + } + + var DEFAULT_SLIDE_SEPARATOR = '^\n---\n$', + DEFAULT_NOTES_SEPARATOR = 'note:', + DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\.element\\\s*?(.+?)$', + DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\\.slide:\\\s*?(\\\S.+?)$'; + + + /** + * Retrieves the markdown contents of a slide section + * element. Normalizes leading tabs/whitespace. + */ + function getMarkdownFromSlide( section ) { + + var template = section.querySelector( 'script' ); + + // strip leading whitespace so it isn't evaluated as code + var text = ( template || section ).textContent; + + var leadingWs = text.match( /^\n?(\s*)/ )[1].length, + leadingTabs = text.match( /^\n?(\t*)/ )[1].length; + + if( leadingTabs > 0 ) { + text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' ); + } + else if( leadingWs > 1 ) { + text = text.replace( new RegExp('\\n? {' + leadingWs + '}'), '\n' ); + } + + return text; + + } + + /** + * Given a markdown slide section element, this will + * return all arguments that aren't related to markdown + * parsing. Used to forward any other user-defined arguments + * to the output markdown slide. + */ + function getForwardedAttributes( section ) { + + var attributes = section.attributes; + var result = []; + + for( var i = 0, len = attributes.length; i < len; i++ ) { + var name = attributes[i].name, + value = attributes[i].value; + + // disregard attributes that are used for markdown loading/parsing + if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue; + + if( value ) { + result.push( name + '=' + value ); + } + else { + result.push( name ); + } + } + + return result.join( ' ' ); + + } + + /** + * Inspects the given options and fills out default + * values for what's not defined. + */ + function getSlidifyOptions( options ) { + + options = options || {}; + options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR; + options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR; + options.attributes = options.attributes || ''; + + return options; + + } + + /** + * Helper function for constructing a markdown slide. + */ + function createMarkdownSlide( content, options ) { + + options = getSlidifyOptions( options ); + + var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) ); + + if( notesMatch.length === 2 ) { + content = notesMatch[0] + ''; + } + + return ''; + + } + + /** + * Parses a data string into multiple slides based + * on the passed in separator arguments. + */ + function slidify( markdown, options ) { + + options = getSlidifyOptions( options ); + + var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ), + horizontalSeparatorRegex = new RegExp( options.separator ); + + var matches, + lastIndex = 0, + isHorizontal, + wasHorizontal = true, + content, + sectionStack = []; + + // iterate until all blocks between separators are stacked up + while( matches = separatorRegex.exec( markdown ) ) { + notes = null; + + // determine direction (horizontal by default) + isHorizontal = horizontalSeparatorRegex.test( matches[0] ); + + if( !isHorizontal && wasHorizontal ) { + // create vertical stack + sectionStack.push( [] ); + } + + // pluck slide content from markdown input + content = markdown.substring( lastIndex, matches.index ); + + if( isHorizontal && wasHorizontal ) { + // add to horizontal stack + sectionStack.push( content ); + } + else { + // add to vertical stack + sectionStack[sectionStack.length-1].push( content ); + } + + lastIndex = separatorRegex.lastIndex; + wasHorizontal = isHorizontal; + } + + // add the remaining slide + ( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) ); + + var markdownSections = ''; + + // flatten the hierarchical stack, and insert
    tags + for( var i = 0, len = sectionStack.length; i < len; i++ ) { + // vertical + if( sectionStack[i] instanceof Array ) { + markdownSections += '
    '; + + sectionStack[i].forEach( function( child ) { + markdownSections += '
    ' + createMarkdownSlide( child, options ) + '
    '; + } ); + + markdownSections += '
    '; + } + else { + markdownSections += '
    ' + createMarkdownSlide( sectionStack[i], options ) + '
    '; + } + } + + return markdownSections; + + } + + /** + * Parses any current data-markdown slides, splits + * multi-slide markdown into separate sections and + * handles loading of external markdown. + */ + function processSlides() { + + var sections = document.querySelectorAll( '[data-markdown]'), + section; + + for( var i = 0, len = sections.length; i < len; i++ ) { + + section = sections[i]; + + if( section.getAttribute( 'data-markdown' ).length ) { + + var xhr = new XMLHttpRequest(), + url = section.getAttribute( 'data-markdown' ); + + datacharset = section.getAttribute( 'data-charset' ); + + // see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes + if( datacharset != null && datacharset != '' ) { + xhr.overrideMimeType( 'text/html; charset=' + datacharset ); + } + + xhr.onreadystatechange = function() { + if( xhr.readyState === 4 ) { + // file protocol yields status code 0 (useful for local debug, mobile applications etc.) + if ( ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 0 ) { + + section.outerHTML = slidify( xhr.responseText, { + separator: section.getAttribute( 'data-separator' ), + verticalSeparator: section.getAttribute( 'data-separator-vertical' ), + notesSeparator: section.getAttribute( 'data-separator-notes' ), + attributes: getForwardedAttributes( section ) + }); + + } + else { + + section.outerHTML = '
    ' + + 'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' + + 'Check your browser\'s JavaScript console for more details.' + + '

    Remember that you need to serve the presentation HTML from a HTTP server.

    ' + + '
    '; + + } + } + }; + + xhr.open( 'GET', url, false ); + + try { + xhr.send(); + } + catch ( e ) { + alert( 'Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e ); + } + + } + else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-separator-vertical' ) || section.getAttribute( 'data-separator-notes' ) ) { + + section.outerHTML = slidify( getMarkdownFromSlide( section ), { + separator: section.getAttribute( 'data-separator' ), + verticalSeparator: section.getAttribute( 'data-separator-vertical' ), + notesSeparator: section.getAttribute( 'data-separator-notes' ), + attributes: getForwardedAttributes( section ) + }); + + } + else { + section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) ); + } + } + + } + + /** + * Check if a node value has the attributes pattern. + * If yes, extract it and add that value as one or several attributes + * the the terget element. + * + * You need Cache Killer on Chrome to see the effect on any FOM transformation + * directly on refresh (F5) + * http://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development/7000899#answer-11786277 + */ + function addAttributeInElement( node, elementTarget, separator ) { + + var mardownClassesInElementsRegex = new RegExp( separator, 'mg' ); + var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"=]+?)\"", 'mg' ); + var nodeValue = node.nodeValue; + if( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) { + + var classes = matches[1]; + nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( mardownClassesInElementsRegex.lastIndex ); + node.nodeValue = nodeValue; + while( matchesClass = mardownClassRegex.exec( classes ) ) { + elementTarget.setAttribute( matchesClass[1], matchesClass[2] ); + } + return true; + } + return false; + } + + /** + * Add attributes to the parent element of a text node, + * or the element of an attribute node. + */ + function addAttributes( section, element, previousElement, separatorElementAttributes, separatorSectionAttributes ) { + + if ( element != null && element.childNodes != undefined && element.childNodes.length > 0 ) { + previousParentElement = element; + for( var i = 0; i < element.childNodes.length; i++ ) { + childElement = element.childNodes[i]; + if ( i > 0 ) { + j = i - 1; + while ( j >= 0 ) { + aPreviousChildElement = element.childNodes[j]; + if ( typeof aPreviousChildElement.setAttribute == 'function' && aPreviousChildElement.tagName != "BR" ) { + previousParentElement = aPreviousChildElement; + break; + } + j = j - 1; + } + } + parentSection = section; + if( childElement.nodeName == "section" ) { + parentSection = childElement ; + previousParentElement = childElement ; + } + if ( typeof childElement.setAttribute == 'function' || childElement.nodeType == Node.COMMENT_NODE ) { + addAttributes( parentSection, childElement, previousParentElement, separatorElementAttributes, separatorSectionAttributes ); + } + } + } + + if ( element.nodeType == Node.COMMENT_NODE ) { + if ( addAttributeInElement( element, previousElement, separatorElementAttributes ) == false ) { + addAttributeInElement( element, section, separatorSectionAttributes ); + } + } + } + + /** + * Converts any current data-markdown slides in the + * DOM to HTML. + */ + function convertSlides() { + + var sections = document.querySelectorAll( '[data-markdown]'); + + for( var i = 0, len = sections.length; i < len; i++ ) { + + var section = sections[i]; + + // Only parse the same slide once + if( !section.getAttribute( 'data-markdown-parsed' ) ) { + + section.setAttribute( 'data-markdown-parsed', true ) + + var notes = section.querySelector( 'aside.notes' ); + var markdown = getMarkdownFromSlide( section ); + + section.innerHTML = marked( markdown ); + addAttributes( section, section, null, section.getAttribute( 'data-element-attributes' ) || + section.parentNode.getAttribute( 'data-element-attributes' ) || + DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR, + section.getAttribute( 'data-attributes' ) || + section.parentNode.getAttribute( 'data-attributes' ) || + DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR); + + // If there were notes, we need to re-add them after + // having overwritten the section's HTML + if( notes ) { + section.appendChild( notes ); + } + + } + + } + + } + + // API + return { + + initialize: function() { + processSlides(); + convertSlides(); + }, + + // TODO: Do these belong in the API? + processSlides: processSlides, + convertSlides: convertSlides, + slidify: slidify + + }; + +})); diff --git a/static/revealjs/plugin/markdown/marked.js b/static/revealjs/plugin/markdown/marked.js new file mode 100644 index 0000000..ca558fb --- /dev/null +++ b/static/revealjs/plugin/markdown/marked.js @@ -0,0 +1,37 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed) + * https://github.com/chjj/marked + */ + +(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){3,} *\n*/,blockquote:/^( *>[^\n]+(\n[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,def:/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, +text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr",/\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b";block.html=replace(block.html)("comment",/\x3c!--[\s\S]*?--\x3e/)("closed", +/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1", +"\\2")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm)if(this.options.tables)this.rules=block.tables;else this.rules=block.gfm}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)}; +Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1)this.tokens.push({type:"space"})}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm, +"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g, +"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i ?/gm,"");this.token(cap,top);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length); +bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i1&&b.length>1)){src=cap.slice(i+ +1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item[item.length-1]==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:cap[1]==="pre"||cap[1]==="script",text:cap[0]});continue}if(top&& +(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^\x3c!--[\s\S]*?--\x3e|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, +code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, +em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal; +if(!this.links)throw new Error("Tokens array requires a `links` property.");if(this.options.gfm)if(this.options.breaks)this.rules=inline.breaks;else this.rules=inline.gfm;else if(this.options.pedantic)this.rules=inline.pedantic}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length); +out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1][6]===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=''+text+"";continue}if(cap=this.rules.url.exec(src)){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=''+text+"";continue}if(cap=this.rules.tag.exec(src)){src=src.substring(cap[0].length); +out+=this.options.sanitize?escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);out+=this.outputLink(cap,{href:cap[2],title:cap[3]});continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0][0];src=cap[0].substring(1)+src;continue}out+=this.outputLink(cap,link);continue}if(cap=this.rules.strong.exec(src)){src= +src.substring(cap[0].length);out+=""+this.output(cap[2]||cap[1])+"";continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=""+this.output(cap[2]||cap[1])+"";continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=""+escape(cap[2],true)+"";continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+="
    ";continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=""+ +this.output(cap[1])+"";continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=escape(cap[0]);continue}if(src)throw new Error("Infinite loop on byte: "+src.charCodeAt(0));}return out};InlineLexer.prototype.outputLink=function(cap,link){if(cap[0][0]!=="!")return'"+this.output(cap[1])+"";else return''+escape(cap[1])+'"};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/--/g,"\u2014").replace(/'([^']*)'/g,"\u2018$1\u2019").replace(/"([^"]*)"/g,"\u201c$1\u201d").replace(/\.{3}/g,"\u2026")};InlineLexer.prototype.mangle=function(text){var out="",l=text.length,i=0,ch;for(;i0.5)ch="x"+ch.toString(16);out+="&#"+ch+";"}return out};function Parser(options){this.tokens=[];this.token=null; +this.options=options||marked.defaults}Parser.parse=function(src,options){var parser=new Parser(options);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options);this.tokens=src.reverse();var out="";while(this.next())out+=this.tok();return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text; +while(this.peek().type==="text")body+="\n"+this.next().text;return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case "space":return"";case "hr":return"
    \n";case "heading":return""+this.inline.output(this.token.text)+"\n";case "code":if(this.options.highlight){var code=this.options.highlight(this.token.text,this.token.lang);if(code!=null&&code!==this.token.text){this.token.escaped=true;this.token.text=code}}if(!this.token.escaped)this.token.text= +escape(this.token.text,true);return"
    "+this.token.text+"
    \n";case "table":var body="",heading,i,row,cell,j;body+="\n\n";for(i=0;i'+heading+"\n":""+heading+"\n"}body+="\n\n";body+="\n";for(i=0;i'+cell+"\n":""+cell+"\n"}body+="\n"}body+="\n";return"\n"+body+"
    \n";case "blockquote_start":var body="";while(this.next().type!=="blockquote_end")body+=this.tok();return"
    \n"+body+"
    \n";case "list_start":var type=this.token.ordered?"ol":"ul",body="";while(this.next().type!=="list_end")body+= +this.tok();return"<"+type+">\n"+body+"\n";case "list_item_start":var body="";while(this.next().type!=="list_item_end")body+=this.token.type==="text"?this.parseText():this.tok();return"
  • "+body+"
  • \n";case "loose_item_start":var body="";while(this.next().type!=="list_item_end")body+=this.tok();return"
  • "+body+"
  • \n";case "html":return!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;case "paragraph":return"

    "+this.inline.output(this.token.text)+ +"

    \n";case "text":return"

    "+this.parseText()+"

    \n"}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i= +1,target,key;for(;iAn error occured:

    "+escape(e.message+"",true)+"
    ";throw e;}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:""};marked.Parser=Parser;marked.parser=Parser.parse;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output; +marked.parse=marked;if(typeof exports==="object")module.exports=marked;else if(typeof define==="function"&&define.amd)define(function(){return marked});else this.marked=marked}).call(function(){return this||(typeof window!=="undefined"?window:global)}()); diff --git a/static/revealjs/plugin/math/math.js b/static/revealjs/plugin/math/math.js new file mode 100755 index 0000000..d55d9d1 --- /dev/null +++ b/static/revealjs/plugin/math/math.js @@ -0,0 +1,64 @@ +/** + * A plugin which enables rendering of math equations inside + * of reveal.js slides. Essentially a thin wrapper for MathJax. + * + * @author Hakim El Hattab + */ +var RevealMath = window.RevealMath || (function(){ + + var options = Reveal.getConfig().math || {}; + options.mathjax = options.mathjax || 'http://cdn.mathjax.org/mathjax/latest/MathJax.js'; + options.config = options.config || 'TeX-AMS_HTML-full'; + + loadScript( options.mathjax + '?config=' + options.config, function() { + + MathJax.Hub.Config({ + messageStyle: 'none', + tex2jax: { inlineMath: [['$','$'],['\\(','\\)']] }, + skipStartupTypeset: true + }); + + // Typeset followed by an immediate reveal.js layout since + // the typesetting process could affect slide height + MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub ] ); + MathJax.Hub.Queue( Reveal.layout ); + + // Reprocess equations in slides when they turn visible + Reveal.addEventListener( 'slidechanged', function( event ) { + + MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, event.currentSlide ] ); + + } ); + + } ); + + function loadScript( url, callback ) { + + var head = document.querySelector( 'head' ); + var script = document.createElement( 'script' ); + script.type = 'text/javascript'; + script.src = url; + + // Wrapper for callback to make sure it only fires once + var finish = function() { + if( typeof callback === 'function' ) { + callback.call(); + callback = null; + } + } + + script.onload = finish; + + // IE + script.onreadystatechange = function() { + if ( this.readyState === 'loaded' ) { + finish(); + } + } + + // Normal browsers + head.appendChild( script ); + + } + +})(); diff --git a/static/revealjs/plugin/multiplex/client.js b/static/revealjs/plugin/multiplex/client.js new file mode 100644 index 0000000..e6179f6 --- /dev/null +++ b/static/revealjs/plugin/multiplex/client.js @@ -0,0 +1,13 @@ +(function() { + var multiplex = Reveal.getConfig().multiplex; + var socketId = multiplex.id; + var socket = io.connect(multiplex.url); + + socket.on(multiplex.id, function(data) { + // ignore data from sockets that aren't ours + if (data.socketId !== socketId) { return; } + if( window.location.host === 'localhost:1947' ) return; + + Reveal.slide(data.indexh, data.indexv, data.indexf, 'remote'); + }); +}()); diff --git a/static/revealjs/plugin/multiplex/index.js b/static/revealjs/plugin/multiplex/index.js new file mode 100644 index 0000000..6f5d8b1 --- /dev/null +++ b/static/revealjs/plugin/multiplex/index.js @@ -0,0 +1,56 @@ +var express = require('express'); +var fs = require('fs'); +var io = require('socket.io'); +var crypto = require('crypto'); + +var app = express.createServer(); +var staticDir = express.static; + +io = io.listen(app); + +var opts = { + port: 1948, + baseDir : __dirname + '/../../' +}; + +io.sockets.on('connection', function(socket) { + socket.on('slidechanged', function(slideData) { + if (typeof slideData.secret == 'undefined' || slideData.secret == null || slideData.secret === '') return; + if (createHash(slideData.secret) === slideData.socketId) { + slideData.secret = null; + socket.broadcast.emit(slideData.socketId, slideData); + }; + }); +}); + +app.configure(function() { + [ 'css', 'js', 'plugin', 'lib' ].forEach(function(dir) { + app.use('/' + dir, staticDir(opts.baseDir + dir)); + }); +}); + +app.get("/", function(req, res) { + res.writeHead(200, {'Content-Type': 'text/html'}); + fs.createReadStream(opts.baseDir + '/index.html').pipe(res); +}); + +app.get("/token", function(req,res) { + var ts = new Date().getTime(); + var rand = Math.floor(Math.random()*9999999); + var secret = ts.toString() + rand.toString(); + res.send({secret: secret, socketId: createHash(secret)}); +}); + +var createHash = function(secret) { + var cipher = crypto.createCipher('blowfish', secret); + return(cipher.final('hex')); +}; + +// Actually listen +app.listen(opts.port || null); + +var brown = '\033[33m', + green = '\033[32m', + reset = '\033[0m'; + +console.log( brown + "reveal.js:" + reset + " Multiplex running on port " + green + opts.port + reset ); \ No newline at end of file diff --git a/static/revealjs/plugin/multiplex/master.js b/static/revealjs/plugin/multiplex/master.js new file mode 100644 index 0000000..b6a7eb7 --- /dev/null +++ b/static/revealjs/plugin/multiplex/master.js @@ -0,0 +1,51 @@ +(function() { + // Don't emit events from inside of notes windows + if ( window.location.search.match( /receiver/gi ) ) { return; } + + var multiplex = Reveal.getConfig().multiplex; + + var socket = io.connect(multiplex.url); + + var notify = function( slideElement, indexh, indexv, origin ) { + if( typeof origin === 'undefined' && origin !== 'remote' ) { + var nextindexh; + var nextindexv; + + var fragmentindex = Reveal.getIndices().f; + if (typeof fragmentindex == 'undefined') { + fragmentindex = 0; + } + + if (slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION') { + nextindexh = indexh; + nextindexv = indexv + 1; + } else { + nextindexh = indexh + 1; + nextindexv = 0; + } + + var slideData = { + indexh : indexh, + indexv : indexv, + indexf : fragmentindex, + nextindexh : nextindexh, + nextindexv : nextindexv, + secret: multiplex.secret, + socketId : multiplex.id + }; + + socket.emit('slidechanged', slideData); + } + } + + Reveal.addEventListener( 'slidechanged', function( event ) { + notify( event.currentSlide, event.indexh, event.indexv, event.origin ); + } ); + + var fragmentNotify = function( event ) { + notify( Reveal.getCurrentSlide(), Reveal.getIndices().h, Reveal.getIndices().v, event.origin ); + }; + + Reveal.addEventListener( 'fragmentshown', fragmentNotify ); + Reveal.addEventListener( 'fragmenthidden', fragmentNotify ); +}()); \ No newline at end of file diff --git a/static/revealjs/plugin/notes-server/client.js b/static/revealjs/plugin/notes-server/client.js new file mode 100644 index 0000000..628586f --- /dev/null +++ b/static/revealjs/plugin/notes-server/client.js @@ -0,0 +1,60 @@ +(function() { + + // don't emit events from inside the previews themselves + if( window.location.search.match( /receiver/gi ) ) { return; } + + var socket = io.connect( window.location.origin ), + socketId = Math.random().toString().slice( 2 ); + + console.log( 'View slide notes at ' + window.location.origin + '/notes/' + socketId ); + + window.open( window.location.origin + '/notes/' + socketId, 'notes-' + socketId ); + + /** + * Posts the current slide data to the notes window + */ + function post() { + + var slideElement = Reveal.getCurrentSlide(), + notesElement = slideElement.querySelector( 'aside.notes' ); + + var messageData = { + notes: '', + markdown: false, + socketId: socketId, + state: Reveal.getState() + }; + + // Look for notes defined in a slide attribute + if( slideElement.hasAttribute( 'data-notes' ) ) { + messageData.notes = slideElement.getAttribute( 'data-notes' ); + } + + // Look for notes defined in an aside element + if( notesElement ) { + messageData.notes = notesElement.innerHTML; + messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string'; + } + + socket.emit( 'statechanged', messageData ); + + } + + // When a new notes window connects, post our current state + socket.on( 'connect', function( data ) { + post(); + } ); + + // Monitor events that trigger a change in state + Reveal.addEventListener( 'slidechanged', post ); + Reveal.addEventListener( 'fragmentshown', post ); + Reveal.addEventListener( 'fragmenthidden', post ); + Reveal.addEventListener( 'overviewhidden', post ); + Reveal.addEventListener( 'overviewshown', post ); + Reveal.addEventListener( 'paused', post ); + Reveal.addEventListener( 'resumed', post ); + + // Post the initial state + post(); + +}()); diff --git a/static/revealjs/plugin/notes-server/index.js b/static/revealjs/plugin/notes-server/index.js new file mode 100644 index 0000000..df917f1 --- /dev/null +++ b/static/revealjs/plugin/notes-server/index.js @@ -0,0 +1,66 @@ +var express = require('express'); +var fs = require('fs'); +var io = require('socket.io'); +var _ = require('underscore'); +var Mustache = require('mustache'); + +var app = express.createServer(); +var staticDir = express.static; + +io = io.listen(app); + +var opts = { + port : 1947, + baseDir : __dirname + '/../../' +}; + +io.sockets.on( 'connection', function( socket ) { + + socket.on( 'connect', function( data ) { + socket.broadcast.emit( 'connect', data ); + }); + + socket.on( 'statechanged', function( data ) { + socket.broadcast.emit( 'statechanged', data ); + }); + +}); + +app.configure( function() { + + [ 'css', 'js', 'images', 'plugin', 'lib' ].forEach( function( dir ) { + app.use( '/' + dir, staticDir( opts.baseDir + dir ) ); + }); + +}); + +app.get('/', function( req, res ) { + + res.writeHead( 200, { 'Content-Type': 'text/html' } ); + fs.createReadStream( opts.baseDir + '/index.html' ).pipe( res ); + +}); + +app.get( '/notes/:socketId', function( req, res ) { + + fs.readFile( opts.baseDir + 'plugin/notes-server/notes.html', function( err, data ) { + res.send( Mustache.to_html( data.toString(), { + socketId : req.params.socketId + })); + }); + +}); + +// Actually listen +app.listen( opts.port || null ); + +var brown = '\033[33m', + green = '\033[32m', + reset = '\033[0m'; + +var slidesLocation = 'http://localhost' + ( opts.port ? ( ':' + opts.port ) : '' ); + +console.log( brown + 'reveal.js - Speaker Notes' + reset ); +console.log( '1. Open the slides at ' + green + slidesLocation + reset ); +console.log( '2. Click on the link your JS console to go to the notes page' ); +console.log( '3. Advance through your slides and your notes will advance automatically' ); diff --git a/static/revealjs/plugin/notes-server/notes.html b/static/revealjs/plugin/notes-server/notes.html new file mode 100644 index 0000000..72d0317 --- /dev/null +++ b/static/revealjs/plugin/notes-server/notes.html @@ -0,0 +1,396 @@ + + + + + + reveal.js - Slide Notes + + + + + + +
    +
    UPCOMING:
    +
    +
    +

    Time Click to Reset

    +
    + 0:00 AM +
    +
    + 00:00:00 +
    +
    +
    + + +
    + + + + + + + + diff --git a/static/revealjs/plugin/notes/notes.html b/static/revealjs/plugin/notes/notes.html new file mode 100644 index 0000000..0cc8cf6 --- /dev/null +++ b/static/revealjs/plugin/notes/notes.html @@ -0,0 +1,406 @@ + + + + + + reveal.js - Slide Notes + + + + + + +
    +
    UPCOMING:
    +
    +
    +

    Time Click to Reset

    +
    + 0:00 AM +
    +
    + 00:00:00 +
    +
    +
    + + +
    + + + + + diff --git a/static/revealjs/plugin/notes/notes.js b/static/revealjs/plugin/notes/notes.js new file mode 100644 index 0000000..27199af --- /dev/null +++ b/static/revealjs/plugin/notes/notes.js @@ -0,0 +1,122 @@ +/** + * Handles opening of and synchronization with the reveal.js + * notes window. + * + * Handshake process: + * 1. This window posts 'connect' to notes window + * - Includes URL of presentation to show + * 2. Notes window responds with 'connected' when it is available + * 3. This window proceeds to send the current presentation state + * to the notes window + */ +var RevealNotes = (function() { + + function openNotes() { + var jsFileLocation = document.querySelector('script[src$="notes.js"]').src; // this js file path + jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, ''); // the js folder path + var notesPopup = window.open( jsFileLocation + 'notes.html', 'reveal.js - Notes', 'width=1100,height=700' ); + + /** + * Connect to the notes window through a postmessage handshake. + * Using postmessage enables us to work in situations where the + * origins differ, such as a presentation being opened from the + * file system. + */ + function connect() { + // Keep trying to connect until we get a 'connected' message back + var connectInterval = setInterval( function() { + notesPopup.postMessage( JSON.stringify( { + namespace: 'reveal-notes', + type: 'connect', + url: window.location.protocol + '//' + window.location.host + window.location.pathname, + state: Reveal.getState() + } ), '*' ); + }, 500 ); + + window.addEventListener( 'message', function( event ) { + var data = JSON.parse( event.data ); + if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) { + clearInterval( connectInterval ); + onConnected(); + } + } ); + } + + /** + * Posts the current slide data to the notes window + */ + function post() { + + var slideElement = Reveal.getCurrentSlide(), + notesElement = slideElement.querySelector( 'aside.notes' ); + + var messageData = { + namespace: 'reveal-notes', + type: 'state', + notes: '', + markdown: false, + state: Reveal.getState() + }; + + // Look for notes defined in a slide attribute + if( slideElement.hasAttribute( 'data-notes' ) ) { + messageData.notes = slideElement.getAttribute( 'data-notes' ); + } + + // Look for notes defined in an aside element + if( notesElement ) { + messageData.notes = notesElement.innerHTML; + messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string'; + } + + notesPopup.postMessage( JSON.stringify( messageData ), '*' ); + + } + + /** + * Called once we have established a connection to the notes + * window. + */ + function onConnected() { + + // Monitor events that trigger a change in state + Reveal.addEventListener( 'slidechanged', post ); + Reveal.addEventListener( 'fragmentshown', post ); + Reveal.addEventListener( 'fragmenthidden', post ); + Reveal.addEventListener( 'overviewhidden', post ); + Reveal.addEventListener( 'overviewshown', post ); + Reveal.addEventListener( 'paused', post ); + Reveal.addEventListener( 'resumed', post ); + + // Post the initial state + post(); + + } + + connect(); + } + + if( !/receiver/i.test( window.location.search ) ) { + + // If the there's a 'notes' query set, open directly + if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) { + openNotes(); + } + + // Open the notes when the 's' key is hit + document.addEventListener( 'keydown', function( event ) { + // Disregard the event if the target is editable or a + // modifier is present + if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return; + + if( event.keyCode === 83 ) { + event.preventDefault(); + openNotes(); + } + }, false ); + + } + + return { open: openNotes }; + +})(); diff --git a/static/revealjs/plugin/print-pdf/print-pdf.js b/static/revealjs/plugin/print-pdf/print-pdf.js new file mode 100644 index 0000000..86dc4df --- /dev/null +++ b/static/revealjs/plugin/print-pdf/print-pdf.js @@ -0,0 +1,48 @@ +/** + * phantomjs script for printing presentations to PDF. + * + * Example: + * phantomjs print-pdf.js "http://lab.hakim.se/reveal-js?print-pdf" reveal-demo.pdf + * + * By Manuel Bieh (https://github.com/manuelbieh) + */ + +// html2pdf.js +var page = new WebPage(); +var system = require( 'system' ); + +var slideWidth = system.args[3] ? system.args[3].split( 'x' )[0] : 960; +var slideHeight = system.args[3] ? system.args[3].split( 'x' )[1] : 700; + +page.viewportSize = { + width: slideWidth, + height: slideHeight +}; + +// TODO +// Something is wrong with these config values. An input +// paper width of 1920px actually results in a 756px wide +// PDF. +page.paperSize = { + width: Math.round( slideWidth * 2 ), + height: Math.round( slideHeight * 2 ), + border: 0 +}; + +var inputFile = system.args[1] || 'index.html?print-pdf'; +var outputFile = system.args[2] || 'slides.pdf'; + +if( outputFile.match( /\.pdf$/gi ) === null ) { + outputFile += '.pdf'; +} + +console.log( 'Printing PDF (Paper size: '+ page.paperSize.width + 'x' + page.paperSize.height +')' ); + +page.open( inputFile, function( status ) { + window.setTimeout( function() { + console.log( 'Printed succesfully' ); + page.render( outputFile ); + phantom.exit(); + }, 1000 ); +} ); + diff --git a/static/revealjs/plugin/remotes/remotes.js b/static/revealjs/plugin/remotes/remotes.js new file mode 100644 index 0000000..ba0dbad --- /dev/null +++ b/static/revealjs/plugin/remotes/remotes.js @@ -0,0 +1,39 @@ +/** + * Touch-based remote controller for your presentation courtesy + * of the folks at http://remotes.io + */ + +(function(window){ + + /** + * Detects if we are dealing with a touch enabled device (with some false positives) + * Borrowed from modernizr: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touch.js + */ + var hasTouch = (function(){ + return ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch; + })(); + + /** + * Detects if notes are enable and the current page is opened inside an /iframe + * this prevents loading Remotes.io several times + */ + var isNotesAndIframe = (function(){ + return window.RevealNotes && !(self == top); + })(); + + if(!hasTouch && !isNotesAndIframe){ + head.ready( 'remotes.ne.min.js', function() { + new Remotes("preview") + .on("swipe-left", function(e){ Reveal.right(); }) + .on("swipe-right", function(e){ Reveal.left(); }) + .on("swipe-up", function(e){ Reveal.down(); }) + .on("swipe-down", function(e){ Reveal.up(); }) + .on("tap", function(e){ Reveal.next(); }) + .on("zoom-out", function(e){ Reveal.toggleOverview(true); }) + .on("zoom-in", function(e){ Reveal.toggleOverview(false); }) + ; + } ); + + head.js('https://hakim-static.s3.amazonaws.com/reveal-js/remotes.ne.min.js'); + } +})(window); \ No newline at end of file diff --git a/static/revealjs/plugin/search/search.js b/static/revealjs/plugin/search/search.js new file mode 100644 index 0000000..ae6582e --- /dev/null +++ b/static/revealjs/plugin/search/search.js @@ -0,0 +1,196 @@ +/* + * Handles finding a text string anywhere in the slides and showing the next occurrence to the user + * by navigatating to that slide and highlighting it. + * + * By Jon Snyder , February 2013 + */ + +var RevealSearch = (function() { + + var matchedSlides; + var currentMatchedIndex; + var searchboxDirty; + var myHilitor; + +// Original JavaScript code by Chirp Internet: www.chirp.com.au +// Please acknowledge use of this code by including this header. +// 2/2013 jon: modified regex to display any match, not restricted to word boundaries. + +function Hilitor(id, tag) +{ + + var targetNode = document.getElementById(id) || document.body; + var hiliteTag = tag || "EM"; + var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM|SPAN)$"); + var colors = ["#ff6", "#a0ffff", "#9f9", "#f99", "#f6f"]; + var wordColor = []; + var colorIdx = 0; + var matchRegex = ""; + var matchingSlides = []; + + this.setRegex = function(input) + { + input = input.replace(/^[^\w]+|[^\w]+$/g, "").replace(/[^\w'-]+/g, "|"); + matchRegex = new RegExp("(" + input + ")","i"); + } + + this.getRegex = function() + { + return matchRegex.toString().replace(/^\/\\b\(|\)\\b\/i$/g, "").replace(/\|/g, " "); + } + + // recursively apply word highlighting + this.hiliteWords = function(node) + { + if(node == undefined || !node) return; + if(!matchRegex) return; + if(skipTags.test(node.nodeName)) return; + + if(node.hasChildNodes()) { + for(var i=0; i < node.childNodes.length; i++) + this.hiliteWords(node.childNodes[i]); + } + if(node.nodeType == 3) { // NODE_TEXT + if((nv = node.nodeValue) && (regs = matchRegex.exec(nv))) { + //find the slide's section element and save it in our list of matching slides + var secnode = node.parentNode; + while (secnode.nodeName != 'SECTION') { + secnode = secnode.parentNode; + } + + var slideIndex = Reveal.getIndices(secnode); + var slidelen = matchingSlides.length; + var alreadyAdded = false; + for (var i=0; i < slidelen; i++) { + if ( (matchingSlides[i].h === slideIndex.h) && (matchingSlides[i].v === slideIndex.v) ) { + alreadyAdded = true; + } + } + if (! alreadyAdded) { + matchingSlides.push(slideIndex); + } + + if(!wordColor[regs[0].toLowerCase()]) { + wordColor[regs[0].toLowerCase()] = colors[colorIdx++ % colors.length]; + } + + var match = document.createElement(hiliteTag); + match.appendChild(document.createTextNode(regs[0])); + match.style.backgroundColor = wordColor[regs[0].toLowerCase()]; + match.style.fontStyle = "inherit"; + match.style.color = "#000"; + + var after = node.splitText(regs.index); + after.nodeValue = after.nodeValue.substring(regs[0].length); + node.parentNode.insertBefore(match, after); + } + } + }; + + // remove highlighting + this.remove = function() + { + var arr = document.getElementsByTagName(hiliteTag); + while(arr.length && (el = arr[0])) { + el.parentNode.replaceChild(el.firstChild, el); + } + }; + + // start highlighting at target node + this.apply = function(input) + { + if(input == undefined || !input) return; + this.remove(); + this.setRegex(input); + this.hiliteWords(targetNode); + return matchingSlides; + }; + +} + + function openSearch() { + //ensure the search term input dialog is visible and has focus: + var inputbox = document.getElementById("searchinput"); + inputbox.style.display = "inline"; + inputbox.focus(); + inputbox.select(); + } + + function toggleSearch() { + var inputbox = document.getElementById("searchinput"); + if (inputbox.style.display !== "inline") { + openSearch(); + } + else { + inputbox.style.display = "none"; + myHilitor.remove(); + } + } + + function doSearch() { + //if there's been a change in the search term, perform a new search: + if (searchboxDirty) { + var searchstring = document.getElementById("searchinput").value; + + //find the keyword amongst the slides + myHilitor = new Hilitor("slidecontent"); + matchedSlides = myHilitor.apply(searchstring); + currentMatchedIndex = 0; + } + + //navigate to the next slide that has the keyword, wrapping to the first if necessary + if (matchedSlides.length && (matchedSlides.length <= currentMatchedIndex)) { + currentMatchedIndex = 0; + } + if (matchedSlides.length > currentMatchedIndex) { + Reveal.slide(matchedSlides[currentMatchedIndex].h, matchedSlides[currentMatchedIndex].v); + currentMatchedIndex++; + } + } + + var dom = {}; + dom.wrapper = document.querySelector( '.reveal' ); + + if( !dom.wrapper.querySelector( '.searchbox' ) ) { + var searchElement = document.createElement( 'div' ); + searchElement.id = "searchinputdiv"; + searchElement.classList.add( 'searchdiv' ); + searchElement.style.position = 'absolute'; + searchElement.style.top = '10px'; + searchElement.style.left = '10px'; + //embedded base64 search icon Designed by Sketchdock - http://www.sketchdock.com/: + searchElement.innerHTML = ''; + dom.wrapper.appendChild( searchElement ); + } + + document.getElementById("searchbutton").addEventListener( 'click', function(event) { + doSearch(); + }, false ); + + document.getElementById("searchinput").addEventListener( 'keyup', function( event ) { + switch (event.keyCode) { + case 13: + event.preventDefault(); + doSearch(); + searchboxDirty = false; + break; + default: + searchboxDirty = true; + } + }, false ); + + // Open the search when the 's' key is hit (yes, this conflicts with the notes plugin, disabling for now) + /* + document.addEventListener( 'keydown', function( event ) { + // Disregard the event if the target is editable or a + // modifier is present + if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return; + + if( event.keyCode === 83 ) { + event.preventDefault(); + openSearch(); + } + }, false ); +*/ + return { open: openSearch }; +})(); diff --git a/static/revealjs/plugin/zoom-js/zoom.js b/static/revealjs/plugin/zoom-js/zoom.js new file mode 100644 index 0000000..da2c10a --- /dev/null +++ b/static/revealjs/plugin/zoom-js/zoom.js @@ -0,0 +1,278 @@ +// Custom reveal.js integration +(function(){ + var isEnabled = true; + + document.querySelector( '.reveal' ).addEventListener( 'mousedown', function( event ) { + var modifier = ( Reveal.getConfig().zoomKey ? Reveal.getConfig().zoomKey : 'alt' ) + 'Key'; + + var zoomPadding = 20; + var revealScale = Reveal.getScale(); + + if( event[ modifier ] && isEnabled ) { + event.preventDefault(); + + var bounds = event.target.getBoundingClientRect(); + + zoom.to({ + x: ( bounds.left * revealScale ) - zoomPadding, + y: ( bounds.top * revealScale ) - zoomPadding, + width: ( bounds.width * revealScale ) + ( zoomPadding * 2 ), + height: ( bounds.height * revealScale ) + ( zoomPadding * 2 ), + pan: false + }); + } + } ); + + Reveal.addEventListener( 'overviewshown', function() { isEnabled = false; } ); + Reveal.addEventListener( 'overviewhidden', function() { isEnabled = true; } ); +})(); + +/*! + * zoom.js 0.3 (modified for use with reveal.js) + * http://lab.hakim.se/zoom-js + * MIT licensed + * + * Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se + */ +var zoom = (function(){ + + // The current zoom level (scale) + var level = 1; + + // The current mouse position, used for panning + var mouseX = 0, + mouseY = 0; + + // Timeout before pan is activated + var panEngageTimeout = -1, + panUpdateInterval = -1; + + // Check for transform support so that we can fallback otherwise + var supportsTransforms = 'WebkitTransform' in document.body.style || + 'MozTransform' in document.body.style || + 'msTransform' in document.body.style || + 'OTransform' in document.body.style || + 'transform' in document.body.style; + + if( supportsTransforms ) { + // The easing that will be applied when we zoom in/out + document.body.style.transition = 'transform 0.8s ease'; + document.body.style.OTransition = '-o-transform 0.8s ease'; + document.body.style.msTransition = '-ms-transform 0.8s ease'; + document.body.style.MozTransition = '-moz-transform 0.8s ease'; + document.body.style.WebkitTransition = '-webkit-transform 0.8s ease'; + } + + // Zoom out if the user hits escape + document.addEventListener( 'keyup', function( event ) { + if( level !== 1 && event.keyCode === 27 ) { + zoom.out(); + } + } ); + + // Monitor mouse movement for panning + document.addEventListener( 'mousemove', function( event ) { + if( level !== 1 ) { + mouseX = event.clientX; + mouseY = event.clientY; + } + } ); + + /** + * Applies the CSS required to zoom in, prefers the use of CSS3 + * transforms but falls back on zoom for IE. + * + * @param {Object} rect + * @param {Number} scale + */ + function magnify( rect, scale ) { + + var scrollOffset = getScrollOffset(); + + // Ensure a width/height is set + rect.width = rect.width || 1; + rect.height = rect.height || 1; + + // Center the rect within the zoomed viewport + rect.x -= ( window.innerWidth - ( rect.width * scale ) ) / 2; + rect.y -= ( window.innerHeight - ( rect.height * scale ) ) / 2; + + if( supportsTransforms ) { + // Reset + if( scale === 1 ) { + document.body.style.transform = ''; + document.body.style.OTransform = ''; + document.body.style.msTransform = ''; + document.body.style.MozTransform = ''; + document.body.style.WebkitTransform = ''; + } + // Scale + else { + var origin = scrollOffset.x +'px '+ scrollOffset.y +'px', + transform = 'translate('+ -rect.x +'px,'+ -rect.y +'px) scale('+ scale +')'; + + document.body.style.transformOrigin = origin; + document.body.style.OTransformOrigin = origin; + document.body.style.msTransformOrigin = origin; + document.body.style.MozTransformOrigin = origin; + document.body.style.WebkitTransformOrigin = origin; + + document.body.style.transform = transform; + document.body.style.OTransform = transform; + document.body.style.msTransform = transform; + document.body.style.MozTransform = transform; + document.body.style.WebkitTransform = transform; + } + } + else { + // Reset + if( scale === 1 ) { + document.body.style.position = ''; + document.body.style.left = ''; + document.body.style.top = ''; + document.body.style.width = ''; + document.body.style.height = ''; + document.body.style.zoom = ''; + } + // Scale + else { + document.body.style.position = 'relative'; + document.body.style.left = ( - ( scrollOffset.x + rect.x ) / scale ) + 'px'; + document.body.style.top = ( - ( scrollOffset.y + rect.y ) / scale ) + 'px'; + document.body.style.width = ( scale * 100 ) + '%'; + document.body.style.height = ( scale * 100 ) + '%'; + document.body.style.zoom = scale; + } + } + + level = scale; + + if( document.documentElement.classList ) { + if( level !== 1 ) { + document.documentElement.classList.add( 'zoomed' ); + } + else { + document.documentElement.classList.remove( 'zoomed' ); + } + } + } + + /** + * Pan the document when the mosue cursor approaches the edges + * of the window. + */ + function pan() { + var range = 0.12, + rangeX = window.innerWidth * range, + rangeY = window.innerHeight * range, + scrollOffset = getScrollOffset(); + + // Up + if( mouseY < rangeY ) { + window.scroll( scrollOffset.x, scrollOffset.y - ( 1 - ( mouseY / rangeY ) ) * ( 14 / level ) ); + } + // Down + else if( mouseY > window.innerHeight - rangeY ) { + window.scroll( scrollOffset.x, scrollOffset.y + ( 1 - ( window.innerHeight - mouseY ) / rangeY ) * ( 14 / level ) ); + } + + // Left + if( mouseX < rangeX ) { + window.scroll( scrollOffset.x - ( 1 - ( mouseX / rangeX ) ) * ( 14 / level ), scrollOffset.y ); + } + // Right + else if( mouseX > window.innerWidth - rangeX ) { + window.scroll( scrollOffset.x + ( 1 - ( window.innerWidth - mouseX ) / rangeX ) * ( 14 / level ), scrollOffset.y ); + } + } + + function getScrollOffset() { + return { + x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset, + y: window.scrollY !== undefined ? window.scrollY : window.pageYOffset + } + } + + return { + /** + * Zooms in on either a rectangle or HTML element. + * + * @param {Object} options + * - element: HTML element to zoom in on + * OR + * - x/y: coordinates in non-transformed space to zoom in on + * - width/height: the portion of the screen to zoom in on + * - scale: can be used instead of width/height to explicitly set scale + */ + to: function( options ) { + + // Due to an implementation limitation we can't zoom in + // to another element without zooming out first + if( level !== 1 ) { + zoom.out(); + } + else { + options.x = options.x || 0; + options.y = options.y || 0; + + // If an element is set, that takes precedence + if( !!options.element ) { + // Space around the zoomed in element to leave on screen + var padding = 20; + var bounds = options.element.getBoundingClientRect(); + + options.x = bounds.left - padding; + options.y = bounds.top - padding; + options.width = bounds.width + ( padding * 2 ); + options.height = bounds.height + ( padding * 2 ); + } + + // If width/height values are set, calculate scale from those values + if( options.width !== undefined && options.height !== undefined ) { + options.scale = Math.max( Math.min( window.innerWidth / options.width, window.innerHeight / options.height ), 1 ); + } + + if( options.scale > 1 ) { + options.x *= options.scale; + options.y *= options.scale; + + magnify( options, options.scale ); + + if( options.pan !== false ) { + + // Wait with engaging panning as it may conflict with the + // zoom transition + panEngageTimeout = setTimeout( function() { + panUpdateInterval = setInterval( pan, 1000 / 60 ); + }, 800 ); + + } + } + } + }, + + /** + * Resets the document zoom state to its default. + */ + out: function() { + clearTimeout( panEngageTimeout ); + clearInterval( panUpdateInterval ); + + magnify( { x: 0, y: 0 }, 1 ); + + level = 1; + }, + + // Alias + magnify: function( options ) { this.to( options ) }, + reset: function() { this.out() }, + + zoomLevel: function() { + return level; + } + } + +})(); + + + diff --git a/static/slides.html b/static/slides.html new file mode 100644 index 0000000..07fabf8 --- /dev/null +++ b/static/slides.html @@ -0,0 +1,49 @@ + + + + + + + reveal.js - The HTML Presentation Framework + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + + + + + + diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..13e340d --- /dev/null +++ b/templates/index.html @@ -0,0 +1,30 @@ + + + + + + + Hacker Slides + + + + + +
    + +
    +
    + +
    + +
    + + + + + + + + From 50a780483f0e840d0d7957e6bf35221ad856e1cf Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Mon, 29 Feb 2016 21:16:20 +0200 Subject: [PATCH 02/85] Draft version. --- .gitignore | 24 +++++++++++++++++++++++ app_test.go | 40 ++++++++++++++++++++++++++++++++++++++ main.go | 46 ++++++++++++++++++++++++++++++++++++++++++++ templates/index.tmpl | 34 ++++++++++++++++++++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 .gitignore create mode 100644 app_test.go create mode 100644 main.go create mode 100644 templates/index.tmpl diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2bdf995 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +bin/ +src/ diff --git a/app_test.go b/app_test.go new file mode 100644 index 0000000..8ed18a2 --- /dev/null +++ b/app_test.go @@ -0,0 +1,40 @@ +package main + +import ( + . "github.com/franela/goblin" + "net/http" + "net/http/httptest" + "testing" +) + +func performRequest(method, path string) *httptest.ResponseRecorder { + app := NewApp() + req, _ := http.NewRequest(method, path, nil) + w := httptest.NewRecorder() + app.ServeHTTP(w, req) + return w +} + +func Test(t *testing.T) { + g := Goblin(t) + g.Describe("App api", func() { + + g.It("Should return 200 on / ", func() { + w := performRequest("GET", "/") + g.Assert(w.Code).Equal(200) + }) + + g.It("Should return 200 on /slides.md ", func() { + w := performRequest("GET", "/slides.md") + g.Assert(w.Code).Equal(200) + }) + + g.It("Should return 200 on PUT /slides.md ", func() { + w := performRequest("PUT", "/slides.md") + g.Assert(w.Code).Equal(200) + }) + + g.It("Should works") + + }) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..14e9f9d --- /dev/null +++ b/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "github.com/gin-gonic/gin" + "io/ioutil" +) + +var DB = make(map[string]string) + +func NewApp() *gin.Engine { + + r := gin.Default() + + r.GET("/slides.md", func(c *gin.Context) { + body, err := ioutil.ReadFile("initial-slides.md") + if err != nil { + panic(err) + } + c.String(200, string(body)) + }) + + r.GET("/", func(c *gin.Context) { + c.HTML(200, "index.tmpl", gin.H{ + "pubTo": "Users", + }) + }) + + // Get user value + r.GET("/user/:name", func(c *gin.Context) { + user := c.Params.ByName("name") + value, ok := DB[user] + if ok { + c.JSON(200, gin.H{"user": user, "value": value}) + } else { + c.JSON(200, gin.H{"user": user, "status": "no value"}) + } + }) + + return r + +} + +func main() { + r := NewApp() + r.Run(":8080") +} diff --git a/templates/index.tmpl b/templates/index.tmpl new file mode 100644 index 0000000..c9c3948 --- /dev/null +++ b/templates/index.tmpl @@ -0,0 +1,34 @@ +{{ define "users/index.tmpl" }} + + + + + + + + Hacker Slides + + + + + +
    + +
    +
    + +
    + +
    + + + + + + + + + +{{ end }} From e341b3fd8d88a2c5dc3b63e4013683583981d2fd Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Mon, 29 Feb 2016 21:29:47 +0200 Subject: [PATCH 03/85] Tests --- app_test.go | 12 +++++++----- main.go | 14 ++++++++++---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/app_test.go b/app_test.go index 8ed18a2..a7a1449 100644 --- a/app_test.go +++ b/app_test.go @@ -2,14 +2,16 @@ package main import ( . "github.com/franela/goblin" + "github.com/gin-gonic/gin" "net/http" "net/http/httptest" "testing" ) func performRequest(method, path string) *httptest.ResponseRecorder { - app := NewApp() - req, _ := http.NewRequest(method, path, nil) + gin.SetMode("test") + app := NewApp() + req, _ := http.NewRequest(method, path, nil) w := httptest.NewRecorder() app.ServeHTTP(w, req) return w @@ -20,17 +22,17 @@ func Test(t *testing.T) { g.Describe("App api", func() { g.It("Should return 200 on / ", func() { - w := performRequest("GET", "/") + w := performRequest("GET", "/") g.Assert(w.Code).Equal(200) }) g.It("Should return 200 on /slides.md ", func() { - w := performRequest("GET", "/slides.md") + w := performRequest("GET", "/slides.md") g.Assert(w.Code).Equal(200) }) g.It("Should return 200 on PUT /slides.md ", func() { - w := performRequest("PUT", "/slides.md") + w := performRequest("PUT", "/slides.md") g.Assert(w.Code).Equal(200) }) diff --git a/main.go b/main.go index 14e9f9d..5d8af2c 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,14 @@ func NewApp() *gin.Engine { r := gin.Default() + r.LoadHTMLGlob("templates/*.tmpl") + + r.GET("/", func(c *gin.Context) { + c.HTML(200, "index.tmpl", gin.H{ + "pubTo": "Users", + }) + }) + r.GET("/slides.md", func(c *gin.Context) { body, err := ioutil.ReadFile("initial-slides.md") if err != nil { @@ -19,10 +27,8 @@ func NewApp() *gin.Engine { c.String(200, string(body)) }) - r.GET("/", func(c *gin.Context) { - c.HTML(200, "index.tmpl", gin.H{ - "pubTo": "Users", - }) + r.PUT("/slides.md", func(c *gin.Context) { + c.String(403, "") }) // Get user value From 6603399d96db457d3f7ce4781c72c0a9b873cca7 Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Mon, 29 Feb 2016 21:42:00 +0200 Subject: [PATCH 04/85] First working version --- main.go | 16 +++------------- templates/index.html | 30 ------------------------------ templates/index.tmpl | 3 +-- 3 files changed, 4 insertions(+), 45 deletions(-) delete mode 100644 templates/index.html diff --git a/main.go b/main.go index 5d8af2c..d4d38c5 100644 --- a/main.go +++ b/main.go @@ -11,10 +11,11 @@ func NewApp() *gin.Engine { r := gin.Default() - r.LoadHTMLGlob("templates/*.tmpl") + r.LoadHTMLGlob("templates/index.tmpl") + r.Static("/static", "./static") r.GET("/", func(c *gin.Context) { - c.HTML(200, "index.tmpl", gin.H{ + c.HTML(200, "users/index.tmpl", gin.H{ "pubTo": "Users", }) }) @@ -31,17 +32,6 @@ func NewApp() *gin.Engine { c.String(403, "") }) - // Get user value - r.GET("/user/:name", func(c *gin.Context) { - user := c.Params.ByName("name") - value, ok := DB[user] - if ok { - c.JSON(200, gin.H{"user": user, "value": value}) - } else { - c.JSON(200, gin.H{"user": user, "status": "no value"}) - } - }) - return r } diff --git a/templates/index.html b/templates/index.html deleted file mode 100644 index 13e340d..0000000 --- a/templates/index.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - Hacker Slides - - - - - -
    - -
    -
    - -
    - -
    - - - - - - - - diff --git a/templates/index.tmpl b/templates/index.tmpl index c9c3948..b3c2d48 100644 --- a/templates/index.tmpl +++ b/templates/index.tmpl @@ -14,11 +14,10 @@ -
    From d70f7d37b205ba27e02e6de82d10ae48d256b0ab Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Mon, 29 Feb 2016 22:01:13 +0200 Subject: [PATCH 05/85] Tag --- main.go | 5 ++++- templates/index.tmpl | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index d4d38c5..bb443df 100644 --- a/main.go +++ b/main.go @@ -25,11 +25,14 @@ func NewApp() *gin.Engine { if err != nil { panic(err) } + ioutil.WriteFile("slides.md", body, 0644) c.String(200, string(body)) }) r.PUT("/slides.md", func(c *gin.Context) { - c.String(403, "") + body, _ := ioutil.ReadAll(c.Request.Body); + ioutil.WriteFile("slides.md", body, 0644) + c.String(200, "") }) return r diff --git a/templates/index.tmpl b/templates/index.tmpl index b3c2d48..d07e382 100644 --- a/templates/index.tmpl +++ b/templates/index.tmpl @@ -14,7 +14,7 @@ From 23ecf33cc160f3afac670bfd57a5d68139b9070a Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Mon, 29 Feb 2016 22:23:47 +0200 Subject: [PATCH 06/85] Almost working --- main.go | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/main.go b/main.go index bb443df..404f50c 100644 --- a/main.go +++ b/main.go @@ -1,37 +1,68 @@ package main import ( + "fmt" + "github.com/atrox/haikunatorgo" + "github.com/gin-gonic/contrib/sessions" "github.com/gin-gonic/gin" "io/ioutil" + "os" ) -var DB = make(map[string]string) - func NewApp() *gin.Engine { r := gin.Default() + store := sessions.NewCookieStore([]byte("secret")) + r.Use(sessions.Sessions("mysession", store)) + r.LoadHTMLGlob("templates/index.tmpl") - r.Static("/static", "./static") + r.Static("/static", "./static") r.GET("/", func(c *gin.Context) { + haikunator := haikunator.NewHaikunator() + haikunator.TokenLength = 0 + name := haikunator.Haikunate() + path := fmt.Sprintf("%s.md", name) + session := sessions.Default(c) + session.Set("name", path) + session.Save() c.HTML(200, "users/index.tmpl", gin.H{ - "pubTo": "Users", + "pubTo": path, }) }) r.GET("/slides.md", func(c *gin.Context) { - body, err := ioutil.ReadFile("initial-slides.md") + session := sessions.Default(c) + val := session.Get("name") + path, ok := val.(string) + if !ok { + panic("unlucky") + } + if _, err := os.Stat(path); err != nil { + body, err := ioutil.ReadFile("initial-slides.md") + if err != nil { + panic(err) + } + ioutil.WriteFile(path, body, 0644) + } + + body, err := ioutil.ReadFile(path) if err != nil { panic(err) } - ioutil.WriteFile("slides.md", body, 0644) c.String(200, string(body)) }) r.PUT("/slides.md", func(c *gin.Context) { - body, _ := ioutil.ReadAll(c.Request.Body); - ioutil.WriteFile("slides.md", body, 0644) + session := sessions.Default(c) + val := session.Get("name") + path, ok := val.(string) + if !ok { + panic("unlucky") + } + body, _ := ioutil.ReadAll(c.Request.Body) + ioutil.WriteFile(path, body, 0644) c.String(200, "") }) From 20d1b189cae9302a563607c22ad7f4010d6a390d Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Mon, 29 Feb 2016 22:34:47 +0200 Subject: [PATCH 07/85] Cleaned up --- .gitignore | 1 + main.go | 10 +++++++--- templates/index.tmpl | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 2bdf995..ebb631c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ _testmain.go *.exe bin/ src/ +slides/ diff --git a/main.go b/main.go index 404f50c..bbf9698 100644 --- a/main.go +++ b/main.go @@ -23,10 +23,11 @@ func NewApp() *gin.Engine { haikunator := haikunator.NewHaikunator() haikunator.TokenLength = 0 name := haikunator.Haikunate() - path := fmt.Sprintf("%s.md", name) + path := fmt.Sprintf("slides/%s.md", name) session := sessions.Default(c) session.Set("name", path) session.Save() + c.HTML(200, "users/index.tmpl", gin.H{ "pubTo": path, }) @@ -37,14 +38,17 @@ func NewApp() *gin.Engine { val := session.Get("name") path, ok := val.(string) if !ok { - panic("unlucky") + c.String(400, "No context") } if _, err := os.Stat(path); err != nil { + // coppy sapmle markdown file to the path body, err := ioutil.ReadFile("initial-slides.md") if err != nil { panic(err) } ioutil.WriteFile(path, body, 0644) + c.String(200, string(body)) + return } body, err := ioutil.ReadFile(path) @@ -59,7 +63,7 @@ func NewApp() *gin.Engine { val := session.Get("name") path, ok := val.(string) if !ok { - panic("unlucky") + c.String(400, "No context") } body, _ := ioutil.ReadAll(c.Request.Body) ioutil.WriteFile(path, body, 0644) diff --git a/templates/index.tmpl b/templates/index.tmpl index d07e382..f3dd8a4 100644 --- a/templates/index.tmpl +++ b/templates/index.tmpl @@ -14,7 +14,7 @@ From 1357663bf7cacf9b6c96675b81313fd31d162c9a Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Tue, 1 Mar 2016 20:14:44 +0200 Subject: [PATCH 08/85] WIP testing and logging --- app_test.go | 17 +++++++++++++---- main.go | 28 ++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/app_test.go b/app_test.go index a7a1449..a285258 100644 --- a/app_test.go +++ b/app_test.go @@ -8,10 +8,15 @@ import ( "testing" ) -func performRequest(method, path string) *httptest.ResponseRecorder { +const Cookie = "Set-Cookie" + +func client(method, path, session string) *httptest.ResponseRecorder { gin.SetMode("test") app := NewApp() req, _ := http.NewRequest(method, path, nil) + if len(session) != 0 { + req.Header.Set(Cookie, session) + } w := httptest.NewRecorder() app.ServeHTTP(w, req) return w @@ -20,19 +25,23 @@ func performRequest(method, path string) *httptest.ResponseRecorder { func Test(t *testing.T) { g := Goblin(t) g.Describe("App api", func() { + var session string g.It("Should return 200 on / ", func() { - w := performRequest("GET", "/") + w := client("GET", "/", "") + g.Assert(w.Code).Equal(200) + session = w.HeaderMap.Get(Cookie) + }) g.It("Should return 200 on /slides.md ", func() { - w := performRequest("GET", "/slides.md") + w := client("GET", "/slides.md", session) g.Assert(w.Code).Equal(200) }) g.It("Should return 200 on PUT /slides.md ", func() { - w := performRequest("PUT", "/slides.md") + w := client("PUT", "/slides.md", session) g.Assert(w.Code).Equal(200) }) diff --git a/main.go b/main.go index bbf9698..8cbacb0 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + log "github.com/Sirupsen/logrus" "github.com/atrox/haikunatorgo" "github.com/gin-gonic/contrib/sessions" "github.com/gin-gonic/gin" @@ -9,12 +10,14 @@ import ( "os" ) +const SessionHeader = "slide-session" + func NewApp() *gin.Engine { r := gin.Default() store := sessions.NewCookieStore([]byte("secret")) - r.Use(sessions.Sessions("mysession", store)) + r.Use(sessions.Sessions(SessionHeader, store)) r.LoadHTMLGlob("templates/index.tmpl") r.Static("/static", "./static") @@ -24,6 +27,9 @@ func NewApp() *gin.Engine { haikunator.TokenLength = 0 name := haikunator.Haikunate() path := fmt.Sprintf("slides/%s.md", name) + log.WithFields(log.Fields{ + "path": path, + }).Info("A new session") session := sessions.Default(c) session.Set("name", path) session.Save() @@ -33,15 +39,22 @@ func NewApp() *gin.Engine { }) }) + r.GET("/slides.md", func(c *gin.Context) { session := sessions.Default(c) val := session.Get("name") + if val == nil { + c.String(400, "No context") + } + log.WithFields(log.Fields{ + "path": val, + }).Info("Got session") path, ok := val.(string) if !ok { c.String(400, "No context") } if _, err := os.Stat(path); err != nil { - // coppy sapmle markdown file to the path + // copy sample markdown file to the path body, err := ioutil.ReadFile("initial-slides.md") if err != nil { panic(err) @@ -61,12 +74,23 @@ func NewApp() *gin.Engine { r.PUT("/slides.md", func(c *gin.Context) { session := sessions.Default(c) val := session.Get("name") + if val == nil { + c.String(400, "No context") + } + log.WithFields(log.Fields{ + "path": val, + }).Info("Got session") path, ok := val.(string) if !ok { c.String(400, "No context") + return } body, _ := ioutil.ReadAll(c.Request.Body) ioutil.WriteFile(path, body, 0644) + log.WithFields(log.Fields{ + "size": len(body), + "file": path, + }).Info("Wrote to file") c.String(200, "") }) From 8ddd1d61bbd757efeab8eb09c21a2b3cd03eb24a Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Tue, 1 Mar 2016 20:40:13 +0200 Subject: [PATCH 09/85] Added session to tests --- app_test.go | 20 ++++++++++---------- main.go | 12 +++++++----- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/app_test.go b/app_test.go index a285258..39f8ce5 100644 --- a/app_test.go +++ b/app_test.go @@ -1,21 +1,22 @@ package main import ( - . "github.com/franela/goblin" - "github.com/gin-gonic/gin" "net/http" "net/http/httptest" "testing" + + . "github.com/franela/goblin" + "github.com/gin-gonic/gin" ) const Cookie = "Set-Cookie" -func client(method, path, session string) *httptest.ResponseRecorder { +func client(method, path, cookie string) *httptest.ResponseRecorder { gin.SetMode("test") app := NewApp() req, _ := http.NewRequest(method, path, nil) - if len(session) != 0 { - req.Header.Set(Cookie, session) + if len(cookie) != 0 { + req.Header.Set("Cookie", cookie) } w := httptest.NewRecorder() app.ServeHTTP(w, req) @@ -25,23 +26,22 @@ func client(method, path, session string) *httptest.ResponseRecorder { func Test(t *testing.T) { g := Goblin(t) g.Describe("App api", func() { - var session string + var cookie string g.It("Should return 200 on / ", func() { w := client("GET", "/", "") g.Assert(w.Code).Equal(200) - session = w.HeaderMap.Get(Cookie) - + cookie = w.HeaderMap.Get(Cookie) }) g.It("Should return 200 on /slides.md ", func() { - w := client("GET", "/slides.md", session) + w := client("GET", "/slides.md", cookie) g.Assert(w.Code).Equal(200) }) g.It("Should return 200 on PUT /slides.md ", func() { - w := client("PUT", "/slides.md", session) + w := client("PUT", "/slides.md", cookie) g.Assert(w.Code).Equal(200) }) diff --git a/main.go b/main.go index 8cbacb0..b4fbc14 100644 --- a/main.go +++ b/main.go @@ -2,12 +2,13 @@ package main import ( "fmt" - log "github.com/Sirupsen/logrus" - "github.com/atrox/haikunatorgo" - "github.com/gin-gonic/contrib/sessions" - "github.com/gin-gonic/gin" "io/ioutil" "os" + + log "github.com/Sirupsen/logrus" + haikunator "github.com/atrox/haikunatorgo" + "github.com/gin-gonic/contrib/sessions" + "github.com/gin-gonic/gin" ) const SessionHeader = "slide-session" @@ -39,12 +40,12 @@ func NewApp() *gin.Engine { }) }) - r.GET("/slides.md", func(c *gin.Context) { session := sessions.Default(c) val := session.Get("name") if val == nil { c.String(400, "No context") + return } log.WithFields(log.Fields{ "path": val, @@ -76,6 +77,7 @@ func NewApp() *gin.Engine { val := session.Get("name") if val == nil { c.String(400, "No context") + return } log.WithFields(log.Fields{ "path": val, From 5b877cfbdcdcbc677152673d09704943ee0bcdd1 Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Wed, 2 Mar 2016 23:55:10 +0200 Subject: [PATCH 10/85] Updates for urls --- app_test.go | 15 ++++++++++++++ main.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/app_test.go b/app_test.go index 39f8ce5..b2f4766 100644 --- a/app_test.go +++ b/app_test.go @@ -45,6 +45,21 @@ func Test(t *testing.T) { g.Assert(w.Code).Equal(200) }) + g.It("Should return list of slides ", func() { + w := client("GET", "/stash", cookie) + g.Assert(w.Code).Equal(200) + }) + + g.It("Should return specific slide in preview", func() { + w := client("GET", "/published/shy-cell.md", cookie) + g.Assert(w.Code).Equal(200) + }) + + g.It("Should return specific slide in edit mode", func() { + w := client("GET", "/stash/edit/shy-cell.md", cookie) + g.Assert(w.Code).Equal(200) + }) + g.It("Should works") }) diff --git a/main.go b/main.go index b4fbc14..4c37334 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,9 @@ package main import ( "fmt" "io/ioutil" + "net/http" "os" + "strings" log "github.com/Sirupsen/logrus" haikunator "github.com/atrox/haikunatorgo" @@ -24,6 +26,12 @@ func NewApp() *gin.Engine { r.Static("/static", "./static") r.GET("/", func(c *gin.Context) { + + fname := c.Param("name") + log.WithFields(log.Fields{ + "name": fname, + }).Info("Restore?") + haikunator := haikunator.NewHaikunator() haikunator.TokenLength = 0 name := haikunator.Haikunate() @@ -96,6 +104,57 @@ func NewApp() *gin.Engine { c.String(200, "") }) + r.GET("/stash", func(c *gin.Context) { + files, err := ioutil.ReadDir("slides") + if err != nil { + log.Fatal(err) + } + var stash []string + for _, file := range files { + stash = append(stash, file.Name()) + } + c.JSON(200, gin.H{ + "data": stash, + }) + }) + + r.GET("/stash/edit/:name", func(c *gin.Context) { + + name := c.Param("name") + log.WithFields(log.Fields{ + "name": name, + }).Info("Restore session?") + + if strings.HasSuffix(name, ".md") { + name = name[0 : len(name)-3] + } + path := fmt.Sprintf("slides/%s.md", name) + session := sessions.Default(c) + session.Set("name", path) + session.Save() + + c.HTML(200, "users/index.tmpl", gin.H{ + "pubTo": path, + }) + }) + + r.GET("/published/:name", func(c *gin.Context) { + + name := c.Param("name") + log.WithFields(log.Fields{ + "name": name, + }).Info("Published") + + if strings.HasSuffix(name, ".md") { + name = name[0 : len(name)-3] + } + path := fmt.Sprintf("slides/%s.md", name) + session := sessions.Default(c) + session.Set("name", path) + session.Save() + c.Redirect(http.StatusMovedPermanently, "static/preview") + }) + return r } From b94899938dd909c0358f81988b9ee8af51555261 Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Thu, 3 Mar 2016 11:38:57 +0200 Subject: [PATCH 11/85] All tests passes --- app_test.go | 22 ++++++++++++++++++--- main.go | 13 ++++++------ templates/index.tmpl | 4 ++-- static/slides.html => templates/slides.tmpl | 2 ++ 4 files changed, 30 insertions(+), 11 deletions(-) rename static/slides.html => templates/slides.tmpl (98%) diff --git a/app_test.go b/app_test.go index b2f4766..c6edb76 100644 --- a/app_test.go +++ b/app_test.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "net/http" "net/http/httptest" "testing" @@ -12,9 +13,14 @@ import ( const Cookie = "Set-Cookie" func client(method, path, cookie string) *httptest.ResponseRecorder { + return request(method, path, cookie, "") +} + +func request(method, path, cookie string, body string) *httptest.ResponseRecorder { gin.SetMode("test") app := NewApp() - req, _ := http.NewRequest(method, path, nil) + payload := bytes.NewBufferString(body) + req, _ := http.NewRequest(method, path, payload) if len(cookie) != 0 { req.Header.Set("Cookie", cookie) } @@ -41,7 +47,7 @@ func Test(t *testing.T) { }) g.It("Should return 200 on PUT /slides.md ", func() { - w := client("PUT", "/slides.md", cookie) + w := request("PUT", "/slides.md", cookie, "whatever") g.Assert(w.Code).Equal(200) }) @@ -51,7 +57,7 @@ func Test(t *testing.T) { }) g.It("Should return specific slide in preview", func() { - w := client("GET", "/published/shy-cell.md", cookie) + w := client("GET", "/published/slides/shy-cell.md", cookie) g.Assert(w.Code).Equal(200) }) @@ -60,6 +66,16 @@ func Test(t *testing.T) { g.Assert(w.Code).Equal(200) }) + g.It("Should return specific slide in preview without session", func() { + w := client("GET", "/published/slides/shy-cell.md", "") + g.Assert(w.Code).Equal(200) + }) + + g.It("Should return specific slide in edit mode without session", func() { + w := client("GET", "/stash/edit/shy-cell.md", "") + g.Assert(w.Code).Equal(200) + }) + g.It("Should works") }) diff --git a/main.go b/main.go index 4c37334..87052bf 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,6 @@ package main import ( "fmt" "io/ioutil" - "net/http" "os" "strings" @@ -22,7 +21,7 @@ func NewApp() *gin.Engine { store := sessions.NewCookieStore([]byte("secret")) r.Use(sessions.Sessions(SessionHeader, store)) - r.LoadHTMLGlob("templates/index.tmpl") + r.LoadHTMLGlob("templates/*.tmpl") r.Static("/static", "./static") r.GET("/", func(c *gin.Context) { @@ -43,7 +42,7 @@ func NewApp() *gin.Engine { session.Set("name", path) session.Save() - c.HTML(200, "users/index.tmpl", gin.H{ + c.HTML(200, "index.tmpl", gin.H{ "pubTo": path, }) }) @@ -133,12 +132,12 @@ func NewApp() *gin.Engine { session.Set("name", path) session.Save() - c.HTML(200, "users/index.tmpl", gin.H{ + c.HTML(200, "index.tmpl", gin.H{ "pubTo": path, }) }) - r.GET("/published/:name", func(c *gin.Context) { + r.GET("/published/slides/:name", func(c *gin.Context) { name := c.Param("name") log.WithFields(log.Fields{ @@ -152,7 +151,9 @@ func NewApp() *gin.Engine { session := sessions.Default(c) session.Set("name", path) session.Save() - c.Redirect(http.StatusMovedPermanently, "static/preview") + c.HTML(200, "slides.tmpl", gin.H{ + "pubTo": path, + }) }) return r diff --git a/templates/index.tmpl b/templates/index.tmpl index f3dd8a4..496411f 100644 --- a/templates/index.tmpl +++ b/templates/index.tmpl @@ -1,4 +1,4 @@ -{{ define "users/index.tmpl" }} +{{ define "index.tmpl" }} @@ -14,7 +14,7 @@ diff --git a/static/slides.html b/templates/slides.tmpl similarity index 98% rename from static/slides.html rename to templates/slides.tmpl index 07fabf8..719ab66 100644 --- a/static/slides.html +++ b/templates/slides.tmpl @@ -1,3 +1,4 @@ +{{ define "slides.tmpl" }} @@ -47,3 +48,4 @@ +{{ end }} From 2b1515722a1852726cb8bb912455d429b5957f6b Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Thu, 3 Mar 2016 11:58:58 +0200 Subject: [PATCH 12/85] Initial readme file --- Readme.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Readme.md diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..1184005 --- /dev/null +++ b/Readme.md @@ -0,0 +1,23 @@ +## Hacker Slides + +This repo is a reworked version of [Sandstorm Hacker Slides](https://github.com/jacksingleton/hacker-slides) which features easy set up run outside of Sandstorm and without vagrant-spk. Likewise you can publish and edit your previous slides in markdown. + +To build and run it locally +```go +go get +go run main.go + +[GIN-debug] Listening and serving HTTP on :8080 +``` + +And then you can just open [http://127.0.0.2:8080](http://127.0.0.2:8080) and it's ready to use. + +### Todos: +- Docker image + + +Getting Help +------------ + +For **feature requests** and **bug reports** submit an issue +to the GitHub issue tracker From f9ca49080f65d2099bac7513e25aebcc86b8f47c Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Thu, 3 Mar 2016 12:04:42 +0200 Subject: [PATCH 13/85] Fix link in template --- Readme.md | 6 ++++-- templates/index.tmpl | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 1184005..27188fc 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,8 @@ ## Hacker Slides -This repo is a reworked version of [Sandstorm Hacker Slides](https://github.com/jacksingleton/hacker-slides) which features easy set up run outside of Sandstorm and without vagrant-spk. Likewise you can publish and edit your previous slides in markdown. +This repo is a reworked version of [Sandstorm Hacker Slides](https://github.com/jacksingleton/hacker-slides) which features easy set up run outside of Sandstorm and without vagrant-spk. Likewise you can publish and edit your previous slides in markdown. + +![foo](https://sc-cdn.scaleengine.net/i/520e2f4a8ca107b0263936507120027e.png) To build and run it locally ```go @@ -20,4 +22,4 @@ Getting Help ------------ For **feature requests** and **bug reports** submit an issue -to the GitHub issue tracker +to the GitHub issue tracker diff --git a/templates/index.tmpl b/templates/index.tmpl index 496411f..7a8630e 100644 --- a/templates/index.tmpl +++ b/templates/index.tmpl @@ -19,7 +19,7 @@
    - +
    From 137c2b23c7e5ebe5b99225a775c520518fd30ea0 Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Thu, 3 Mar 2016 15:09:12 +0200 Subject: [PATCH 14/85] LICENSE --- LICENSE | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f290371 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ + +The MIT License (MIT) + +Copyright (c) <2016> Alex Myasoedov, msoedov@gmail.com + +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. From aeb68a3b79f020ba7df6ec8ca903a543cc23137e Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Fri, 4 Mar 2016 11:13:48 +0200 Subject: [PATCH 15/85] Session helper --- main.go | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/main.go b/main.go index 87052bf..0cd8c2f 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "io/ioutil" "os" @@ -47,12 +48,13 @@ func NewApp() *gin.Engine { }) }) - r.GET("/slides.md", func(c *gin.Context) { + mustHaveSession := func(c *gin.Context) (string, error) { session := sessions.Default(c) val := session.Get("name") + emptySession := errors.New("Emtpy session") if val == nil { c.String(400, "No context") - return + return "", emptySession } log.WithFields(log.Fields{ "path": val, @@ -60,6 +62,15 @@ func NewApp() *gin.Engine { path, ok := val.(string) if !ok { c.String(400, "No context") + return "", emptySession + } + return path, nil + } + + r.GET("/slides.md", func(c *gin.Context) { + path, err := mustHaveSession(c) + if err != nil { + return } if _, err := os.Stat(path); err != nil { // copy sample markdown file to the path @@ -80,18 +91,8 @@ func NewApp() *gin.Engine { }) r.PUT("/slides.md", func(c *gin.Context) { - session := sessions.Default(c) - val := session.Get("name") - if val == nil { - c.String(400, "No context") - return - } - log.WithFields(log.Fields{ - "path": val, - }).Info("Got session") - path, ok := val.(string) - if !ok { - c.String(400, "No context") + path, err := mustHaveSession(c) + if err != nil { return } body, _ := ioutil.ReadAll(c.Request.Body) From 5569a0b5410b5f392b56c3bfdb181ccd2eb29535 Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Fri, 4 Mar 2016 11:20:26 +0200 Subject: [PATCH 16/85] Session secret key --- main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 0cd8c2f..60185b5 100644 --- a/main.go +++ b/main.go @@ -13,14 +13,14 @@ import ( "github.com/gin-gonic/gin" ) -const SessionHeader = "slide-session" +const sessionHeader = "slide-session" func NewApp() *gin.Engine { r := gin.Default() store := sessions.NewCookieStore([]byte("secret")) - r.Use(sessions.Sessions(SessionHeader, store)) + r.Use(sessions.Sessions(sessionHeader, store)) r.LoadHTMLGlob("templates/*.tmpl") r.Static("/static", "./static") From f9650c26e1124dec7f3311bb598996261980d68a Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Sat, 5 Mar 2016 12:15:16 +0200 Subject: [PATCH 17/85] Update Readme.md --- Readme.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 27188fc..3e1f2a3 100644 --- a/Readme.md +++ b/Readme.md @@ -1,8 +1,13 @@ ## Hacker Slides -This repo is a reworked version of [Sandstorm Hacker Slides](https://github.com/jacksingleton/hacker-slides) which features easy set up run outside of Sandstorm and without vagrant-spk. Likewise you can publish and edit your previous slides in markdown. +This repo is a reworked version of [Sandstorm Hacker Slides](https://github.com/jacksingleton/hacker-slides) which features easy set up run outside of Sandstorm and without vagrant-spk. Likewise you can publish and edit your previous markdown slides which is not supported in the original version. + +| Edit mode | Published | +|:-------------:|:-------:|:-------:| +|![1st](https://sc-cdn.scaleengine.net/i/520e2f4a8ca107b0263936507120027e.png)|![1st](https://sc-cdn.scaleengine.net/i/7ae0d31a40b0b9e7acc3f131754874cf.png)| +|![2nd](https://sc-cdn.scaleengine.net/i/5acba66070e24f76bc7f20224adc611e.png)|![2nd](https://sc-cdn.scaleengine.net/i/fee3e1374cb13b1d8c292becb7f514ae.png)| + -![foo](https://sc-cdn.scaleengine.net/i/520e2f4a8ca107b0263936507120027e.png) To build and run it locally ```go @@ -12,7 +17,7 @@ go run main.go [GIN-debug] Listening and serving HTTP on :8080 ``` -And then you can just open [http://127.0.0.2:8080](http://127.0.0.2:8080) and it's ready to use. +And then you can just open [http://127.0.0.1:8080](http://127.0.0.1:8080) and it's ready to use with sample slides. ### Todos: - Docker image From 8e161e80545a969e94eb21dc0b4543ed4f27942c Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Sat, 5 Mar 2016 12:26:01 +0200 Subject: [PATCH 18/85] Make it Linguist friendly --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..583fe84 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +static/* linguist-vendored \ No newline at end of file From a751a0fd6597bfc36e33c95586a458bd49eefc0b Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Sun, 6 Mar 2016 20:41:16 +0200 Subject: [PATCH 19/85] Travis --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..5423fe1 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: go + +before_install: + mkdir slides + +install: + go get github.com/franela/goblin + + go get . From 158991d9fd7397676d6f78a95f55ec65aeebc1e2 Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Sun, 6 Mar 2016 21:10:33 +0200 Subject: [PATCH 20/85] Add travis build status --- Readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Readme.md b/Readme.md index 3e1f2a3..24d822d 100644 --- a/Readme.md +++ b/Readme.md @@ -1,5 +1,7 @@ ## Hacker Slides +[![Build Status](https://travis-ci.org/msoedov/hacker-slides.svg?branch=master)](https://travis-ci.org/msoedov/hacker-slides) + This repo is a reworked version of [Sandstorm Hacker Slides](https://github.com/jacksingleton/hacker-slides) which features easy set up run outside of Sandstorm and without vagrant-spk. Likewise you can publish and edit your previous markdown slides which is not supported in the original version. | Edit mode | Published | From a9b2695e23146854114d714aed435b64e34b266f Mon Sep 17 00:00:00 2001 From: Peter Faseun Date: Fri, 7 Oct 2016 18:04:38 -0400 Subject: [PATCH 21/85] Fix haikunator invocation --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 60185b5..ff808bb 100644 --- a/main.go +++ b/main.go @@ -32,7 +32,7 @@ func NewApp() *gin.Engine { "name": fname, }).Info("Restore?") - haikunator := haikunator.NewHaikunator() + haikunator := haikunator.New() haikunator.TokenLength = 0 name := haikunator.Haikunate() path := fmt.Sprintf("slides/%s.md", name) From 97d3c9eefaf0331bbb1a0c167ef7d620237a08a5 Mon Sep 17 00:00:00 2001 From: Marcos Caputo Date: Sun, 29 Jan 2017 12:24:04 -0200 Subject: [PATCH 22/85] Add Dockerfile docker build -t hacker-slides:0.1 . docker run -p 8000:8080 hacker-slides:0.1 --- Dockerfile | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bb4c047 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM golang:onbuild + +RUN mkdir -p /app + +WORKDIR /app + +ADD . /app + +RUN go build ./main.go + +CMD ["./main"] From bd64005c48550970f8ff3cada9ff3bd97ebf6275 Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Tue, 7 Feb 2017 20:02:35 -0500 Subject: [PATCH 23/85] Make build --- .dockerignore | 4 ++++ .gitignore | 1 + Makefile | 10 ++++++++++ 3 files changed, 15 insertions(+) create mode 100644 .dockerignore create mode 100644 Makefile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..56e3fce --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +.git/ +.idea/ +*.swp + diff --git a/.gitignore b/.gitignore index ebb631c..c6d3bfd 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ _testmain.go bin/ src/ slides/ +main diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0249bdf --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +REPO=msoedov/hacker-slides + + +build: + @GOOS=linux CGO_ENABLE=0 go build main.go + @docker build -t $(REPO) . + +push: + @docker push $(REPO) + From 72af9f7e5fb5a086a2cd34735dfd2fab93a4672b Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Tue, 7 Feb 2017 20:02:51 -0500 Subject: [PATCH 24/85] Ligtweight dockerfile --- Dockerfile | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index bb4c047..694b958 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,8 @@ -FROM golang:onbuild - -RUN mkdir -p /app +FROM alpine:3.5 WORKDIR /app ADD . /app - -RUN go build ./main.go - +EXPOSE 8080 +ENV GIN_MODE=release CMD ["./main"] From 7b61c3eb5e6b89aebd6bb09b26c967000ea411a7 Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Tue, 7 Feb 2017 20:03:07 -0500 Subject: [PATCH 25/85] Docs and starting prompt --- Readme.md | 7 +++++++ main.go | 1 + 2 files changed, 8 insertions(+) diff --git a/Readme.md b/Readme.md index 24d822d..39b5e33 100644 --- a/Readme.md +++ b/Readme.md @@ -21,6 +21,13 @@ go run main.go And then you can just open [http://127.0.0.1:8080](http://127.0.0.1:8080) and it's ready to use with sample slides. +Run with docker + +```shell +docker run -it -p 8080:8080 -v $(pwd)/slides:/app/slides msoedov/hacker-slides +``` + + ### Todos: - Docker image diff --git a/main.go b/main.go index ff808bb..9460784 100644 --- a/main.go +++ b/main.go @@ -163,5 +163,6 @@ func NewApp() *gin.Engine { func main() { r := NewApp() + log.Info("Started http://0.0.0.0:8080") r.Run(":8080") } From 045296dc8464390e31f7fe4f5eb6541e3a5fcf08 Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Tue, 7 Feb 2017 20:06:16 -0500 Subject: [PATCH 26/85] Fix test --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0249bdf..6acc056 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,9 @@ REPO=msoedov/hacker-slides +default: repo + +repo: + @echo $(REPO) build: @GOOS=linux CGO_ENABLE=0 go build main.go @@ -7,4 +11,3 @@ build: push: @docker push $(REPO) - From a535f8fecd226e84b8a02aa2b935559b8135f0f7 Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Wed, 1 Mar 2017 19:07:23 -0500 Subject: [PATCH 27/85] Updated reveal.js --- .dockerignore | 2 +- package.json | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 package.json diff --git a/.dockerignore b/.dockerignore index 56e3fce..47ca910 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,4 @@ .git/ .idea/ *.swp - +*.go diff --git a/package.json b/package.json new file mode 100644 index 0000000..0743e52 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "reveal.js": "^3.4.1" + } +} From 9c26469d81a355b0c12b005ac9a6b4c25c62dfdb Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Wed, 1 Mar 2017 19:08:04 -0500 Subject: [PATCH 28/85] Accept port as a command line param --- main.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 9460784..3e506d3 100644 --- a/main.go +++ b/main.go @@ -163,6 +163,15 @@ func NewApp() *gin.Engine { func main() { r := NewApp() + port := "8080" + if len(os.Args) > 1 { + port = os.Args[1] + } else { + envPort := os.Getenv("PORT") + if len(envPort) > 0 { + port = envPort + } + } log.Info("Started http://0.0.0.0:8080") - r.Run(":8080") + r.Run(fmt.Sprintf(":%s", port)) } From 931bd2d082e7e99e5a1fd02d70216d6cf220c289 Mon Sep 17 00:00:00 2001 From: Alex Myasoedov Date: Wed, 1 Mar 2017 19:09:54 -0500 Subject: [PATCH 29/85] Add updated reveal.js --- static/reveal.js/.npmignore | 13 + static/reveal.js/.travis.yml | 5 + static/reveal.js/CONTRIBUTING.md | 23 + static/reveal.js/Gruntfile.js | 187 + static/reveal.js/LICENSE | 19 + static/reveal.js/README.md | 1170 ++++ static/reveal.js/bower.json | 27 + static/reveal.js/css/print/paper.css | 203 + static/reveal.js/css/print/pdf.css | 171 + static/reveal.js/css/reveal.css | 1365 +++++ static/reveal.js/css/reveal.scss | 1446 +++++ static/reveal.js/css/theme/README.md | 21 + static/reveal.js/css/theme/beige.css | 296 + static/reveal.js/css/theme/black.css | 292 + static/reveal.js/css/theme/blood.css | 315 ++ static/reveal.js/css/theme/league.css | 298 + static/reveal.js/css/theme/moon.css | 296 + static/reveal.js/css/theme/night.css | 290 + static/reveal.js/css/theme/serif.css | 292 + static/reveal.js/css/theme/simple.css | 295 + static/reveal.js/css/theme/sky.css | 299 + static/reveal.js/css/theme/solarized.css | 296 + static/reveal.js/css/theme/source/beige.scss | 39 + static/reveal.js/css/theme/source/black.scss | 49 + static/reveal.js/css/theme/source/blood.scss | 78 + static/reveal.js/css/theme/source/league.scss | 34 + static/reveal.js/css/theme/source/moon.scss | 57 + static/reveal.js/css/theme/source/night.scss | 34 + static/reveal.js/css/theme/source/serif.scss | 35 + static/reveal.js/css/theme/source/simple.scss | 43 + static/reveal.js/css/theme/source/sky.scss | 46 + .../reveal.js/css/theme/source/solarized.scss | 63 + static/reveal.js/css/theme/source/white.scss | 49 + .../reveal.js/css/theme/template/mixins.scss | 29 + .../css/theme/template/settings.scss | 43 + .../reveal.js/css/theme/template/theme.scss | 352 ++ static/reveal.js/css/theme/white.css | 292 + static/reveal.js/demo.html | 410 ++ static/reveal.js/index.html | 50 + static/reveal.js/js/reveal.js | 4961 +++++++++++++++++ static/reveal.js/lib/css/zenburn.css | 80 + .../reveal.js/lib/font/league-gothic/LICENSE | 2 + .../lib/font/league-gothic/league-gothic.css | 10 + .../lib/font/league-gothic/league-gothic.eot | Bin 0 -> 25696 bytes .../lib/font/league-gothic/league-gothic.ttf | Bin 0 -> 64256 bytes .../lib/font/league-gothic/league-gothic.woff | Bin 0 -> 30764 bytes .../lib/font/source-sans-pro/LICENSE | 45 + .../source-sans-pro-italic.eot | Bin 0 -> 75720 bytes .../source-sans-pro-italic.ttf | Bin 0 -> 238084 bytes .../source-sans-pro-italic.woff | Bin 0 -> 98556 bytes .../source-sans-pro-regular.eot | Bin 0 -> 88070 bytes .../source-sans-pro-regular.ttf | Bin 0 -> 288008 bytes .../source-sans-pro-regular.woff | Bin 0 -> 114324 bytes .../source-sans-pro-semibold.eot | Bin 0 -> 89897 bytes .../source-sans-pro-semibold.ttf | Bin 0 -> 284640 bytes .../source-sans-pro-semibold.woff | Bin 0 -> 115648 bytes .../source-sans-pro-semibolditalic.eot | Bin 0 -> 75706 bytes .../source-sans-pro-semibolditalic.ttf | Bin 0 -> 240944 bytes .../source-sans-pro-semibolditalic.woff | Bin 0 -> 98816 bytes .../font/source-sans-pro/source-sans-pro.css | 39 + static/reveal.js/lib/js/classList.js | 2 + static/reveal.js/lib/js/head.min.js | 9 + static/reveal.js/lib/js/html5shiv.js | 7 + static/reveal.js/node_modules/.bin/grunt | 1 + static/reveal.js/node_modules/.bin/mustache | 1 + static/reveal.js/package.json | 45 + .../reveal.js/plugin/highlight/highlight.js | 78 + static/reveal.js/plugin/markdown/example.html | 129 + static/reveal.js/plugin/markdown/example.md | 31 + static/reveal.js/plugin/markdown/markdown.js | 411 ++ static/reveal.js/plugin/markdown/marked.js | 6 + static/reveal.js/plugin/math/math.js | 67 + static/reveal.js/plugin/multiplex/client.js | 13 + static/reveal.js/plugin/multiplex/index.js | 64 + static/reveal.js/plugin/multiplex/master.js | 31 + .../reveal.js/plugin/multiplex/package.json | 19 + .../reveal.js/plugin/notes-server/client.js | 65 + static/reveal.js/plugin/notes-server/index.js | 69 + .../reveal.js/plugin/notes-server/notes.html | 585 ++ static/reveal.js/plugin/notes/notes.html | 609 ++ static/reveal.js/plugin/notes/notes.js | 136 + .../reveal.js/plugin/print-pdf/print-pdf.js | 48 + static/reveal.js/plugin/search/search.js | 196 + static/reveal.js/plugin/zoom-js/zoom.js | 288 + .../reveal.js/test/examples/assets/image1.png | Bin 0 -> 21991 bytes .../reveal.js/test/examples/assets/image2.png | Bin 0 -> 10237 bytes static/reveal.js/test/examples/barebones.html | 41 + .../test/examples/embedded-media.html | 49 + static/reveal.js/test/examples/math.html | 185 + .../test/examples/slide-backgrounds.html | 144 + .../test/examples/slide-transitions.html | 101 + static/reveal.js/test/qunit-1.12.0.css | 244 + static/reveal.js/test/qunit-1.12.0.js | 2212 ++++++++ static/reveal.js/test/simple.md | 12 + .../test-markdown-element-attributes.html | 134 + .../test/test-markdown-element-attributes.js | 46 + .../test/test-markdown-external.html | 36 + .../reveal.js/test/test-markdown-external.js | 24 + .../reveal.js/test/test-markdown-options.html | 41 + .../reveal.js/test/test-markdown-options.js | 26 + .../test/test-markdown-slide-attributes.html | 128 + .../test/test-markdown-slide-attributes.js | 47 + static/reveal.js/test/test-markdown.html | 52 + static/reveal.js/test/test-markdown.js | 15 + static/reveal.js/test/test-pdf.html | 83 + static/reveal.js/test/test-pdf.js | 15 + static/reveal.js/test/test.html | 86 + static/reveal.js/test/test.js | 597 ++ 108 files changed, 21687 insertions(+) create mode 100644 static/reveal.js/.npmignore create mode 100644 static/reveal.js/.travis.yml create mode 100644 static/reveal.js/CONTRIBUTING.md create mode 100644 static/reveal.js/Gruntfile.js create mode 100644 static/reveal.js/LICENSE create mode 100644 static/reveal.js/README.md create mode 100644 static/reveal.js/bower.json create mode 100644 static/reveal.js/css/print/paper.css create mode 100644 static/reveal.js/css/print/pdf.css create mode 100644 static/reveal.js/css/reveal.css create mode 100644 static/reveal.js/css/reveal.scss create mode 100644 static/reveal.js/css/theme/README.md create mode 100644 static/reveal.js/css/theme/beige.css create mode 100644 static/reveal.js/css/theme/black.css create mode 100644 static/reveal.js/css/theme/blood.css create mode 100644 static/reveal.js/css/theme/league.css create mode 100644 static/reveal.js/css/theme/moon.css create mode 100644 static/reveal.js/css/theme/night.css create mode 100644 static/reveal.js/css/theme/serif.css create mode 100644 static/reveal.js/css/theme/simple.css create mode 100644 static/reveal.js/css/theme/sky.css create mode 100644 static/reveal.js/css/theme/solarized.css create mode 100644 static/reveal.js/css/theme/source/beige.scss create mode 100644 static/reveal.js/css/theme/source/black.scss create mode 100644 static/reveal.js/css/theme/source/blood.scss create mode 100644 static/reveal.js/css/theme/source/league.scss create mode 100644 static/reveal.js/css/theme/source/moon.scss create mode 100644 static/reveal.js/css/theme/source/night.scss create mode 100644 static/reveal.js/css/theme/source/serif.scss create mode 100644 static/reveal.js/css/theme/source/simple.scss create mode 100644 static/reveal.js/css/theme/source/sky.scss create mode 100644 static/reveal.js/css/theme/source/solarized.scss create mode 100644 static/reveal.js/css/theme/source/white.scss create mode 100644 static/reveal.js/css/theme/template/mixins.scss create mode 100644 static/reveal.js/css/theme/template/settings.scss create mode 100644 static/reveal.js/css/theme/template/theme.scss create mode 100644 static/reveal.js/css/theme/white.css create mode 100644 static/reveal.js/demo.html create mode 100644 static/reveal.js/index.html create mode 100644 static/reveal.js/js/reveal.js create mode 100644 static/reveal.js/lib/css/zenburn.css create mode 100644 static/reveal.js/lib/font/league-gothic/LICENSE create mode 100644 static/reveal.js/lib/font/league-gothic/league-gothic.css create mode 100755 static/reveal.js/lib/font/league-gothic/league-gothic.eot create mode 100755 static/reveal.js/lib/font/league-gothic/league-gothic.ttf create mode 100755 static/reveal.js/lib/font/league-gothic/league-gothic.woff create mode 100644 static/reveal.js/lib/font/source-sans-pro/LICENSE create mode 100755 static/reveal.js/lib/font/source-sans-pro/source-sans-pro-italic.eot create mode 100755 static/reveal.js/lib/font/source-sans-pro/source-sans-pro-italic.ttf create mode 100755 static/reveal.js/lib/font/source-sans-pro/source-sans-pro-italic.woff create mode 100755 static/reveal.js/lib/font/source-sans-pro/source-sans-pro-regular.eot create mode 100755 static/reveal.js/lib/font/source-sans-pro/source-sans-pro-regular.ttf create mode 100755 static/reveal.js/lib/font/source-sans-pro/source-sans-pro-regular.woff create mode 100755 static/reveal.js/lib/font/source-sans-pro/source-sans-pro-semibold.eot create mode 100755 static/reveal.js/lib/font/source-sans-pro/source-sans-pro-semibold.ttf create mode 100755 static/reveal.js/lib/font/source-sans-pro/source-sans-pro-semibold.woff create mode 100755 static/reveal.js/lib/font/source-sans-pro/source-sans-pro-semibolditalic.eot create mode 100755 static/reveal.js/lib/font/source-sans-pro/source-sans-pro-semibolditalic.ttf create mode 100755 static/reveal.js/lib/font/source-sans-pro/source-sans-pro-semibolditalic.woff create mode 100644 static/reveal.js/lib/font/source-sans-pro/source-sans-pro.css create mode 100644 static/reveal.js/lib/js/classList.js create mode 100644 static/reveal.js/lib/js/head.min.js create mode 100644 static/reveal.js/lib/js/html5shiv.js create mode 120000 static/reveal.js/node_modules/.bin/grunt create mode 120000 static/reveal.js/node_modules/.bin/mustache create mode 100644 static/reveal.js/package.json create mode 100644 static/reveal.js/plugin/highlight/highlight.js create mode 100644 static/reveal.js/plugin/markdown/example.html create mode 100644 static/reveal.js/plugin/markdown/example.md create mode 100755 static/reveal.js/plugin/markdown/markdown.js create mode 100644 static/reveal.js/plugin/markdown/marked.js create mode 100755 static/reveal.js/plugin/math/math.js create mode 100644 static/reveal.js/plugin/multiplex/client.js create mode 100644 static/reveal.js/plugin/multiplex/index.js create mode 100644 static/reveal.js/plugin/multiplex/master.js create mode 100644 static/reveal.js/plugin/multiplex/package.json create mode 100644 static/reveal.js/plugin/notes-server/client.js create mode 100644 static/reveal.js/plugin/notes-server/index.js create mode 100644 static/reveal.js/plugin/notes-server/notes.html create mode 100644 static/reveal.js/plugin/notes/notes.html create mode 100644 static/reveal.js/plugin/notes/notes.js create mode 100644 static/reveal.js/plugin/print-pdf/print-pdf.js create mode 100644 static/reveal.js/plugin/search/search.js create mode 100644 static/reveal.js/plugin/zoom-js/zoom.js create mode 100644 static/reveal.js/test/examples/assets/image1.png create mode 100644 static/reveal.js/test/examples/assets/image2.png create mode 100644 static/reveal.js/test/examples/barebones.html create mode 100644 static/reveal.js/test/examples/embedded-media.html create mode 100644 static/reveal.js/test/examples/math.html create mode 100644 static/reveal.js/test/examples/slide-backgrounds.html create mode 100644 static/reveal.js/test/examples/slide-transitions.html create mode 100644 static/reveal.js/test/qunit-1.12.0.css create mode 100644 static/reveal.js/test/qunit-1.12.0.js create mode 100644 static/reveal.js/test/simple.md create mode 100644 static/reveal.js/test/test-markdown-element-attributes.html create mode 100644 static/reveal.js/test/test-markdown-element-attributes.js create mode 100644 static/reveal.js/test/test-markdown-external.html create mode 100644 static/reveal.js/test/test-markdown-external.js create mode 100644 static/reveal.js/test/test-markdown-options.html create mode 100644 static/reveal.js/test/test-markdown-options.js create mode 100644 static/reveal.js/test/test-markdown-slide-attributes.html create mode 100644 static/reveal.js/test/test-markdown-slide-attributes.js create mode 100644 static/reveal.js/test/test-markdown.html create mode 100644 static/reveal.js/test/test-markdown.js create mode 100644 static/reveal.js/test/test-pdf.html create mode 100644 static/reveal.js/test/test-pdf.js create mode 100644 static/reveal.js/test/test.html create mode 100644 static/reveal.js/test/test.js diff --git a/static/reveal.js/.npmignore b/static/reveal.js/.npmignore new file mode 100644 index 0000000..e7b4f21 --- /dev/null +++ b/static/reveal.js/.npmignore @@ -0,0 +1,13 @@ +.idea/ +*.iml +*.iws +*.eml +out/ +.DS_Store +.svn +log/*.log +tmp/** +node_modules/ +.sass-cache +css/reveal.min.css +js/reveal.min.js \ No newline at end of file diff --git a/static/reveal.js/.travis.yml b/static/reveal.js/.travis.yml new file mode 100644 index 0000000..264c6ec --- /dev/null +++ b/static/reveal.js/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 4.1.1 +before_script: + - npm install -g grunt-cli \ No newline at end of file diff --git a/static/reveal.js/CONTRIBUTING.md b/static/reveal.js/CONTRIBUTING.md new file mode 100644 index 0000000..c2091e8 --- /dev/null +++ b/static/reveal.js/CONTRIBUTING.md @@ -0,0 +1,23 @@ +## Contributing + +Please keep the [issue tracker](http://github.com/hakimel/reveal.js/issues) limited to **bug reports**, **feature requests** and **pull requests**. + + +### Personal Support +If you have personal support or setup questions the best place to ask those are [StackOverflow](http://stackoverflow.com/questions/tagged/reveal.js). + + +### Bug Reports +When reporting a bug make sure to include information about which browser and operating system you are on as well as the necessary steps to reproduce the issue. If possible please include a link to a sample presentation where the bug can be tested. + + +### Pull Requests +- Should follow the coding style of the file you work in, most importantly: + - Tabs to indent + - Single-quoted strings +- Should be made towards the **dev branch** +- Should be submitted from a feature/topic branch (not your master) + + +### Plugins +Please do not submit plugins as pull requests. They should be maintained in their own separate repository. More information here: https://github.com/hakimel/reveal.js/wiki/Plugin-Guidelines diff --git a/static/reveal.js/Gruntfile.js b/static/reveal.js/Gruntfile.js new file mode 100644 index 0000000..96a4f52 --- /dev/null +++ b/static/reveal.js/Gruntfile.js @@ -0,0 +1,187 @@ +/* global module:false */ +module.exports = function(grunt) { + var port = grunt.option('port') || 8000; + var root = grunt.option('root') || '.'; + + if (!Array.isArray(root)) root = [root]; + + // Project configuration + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + meta: { + banner: + '/*!\n' + + ' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' + + ' * http://lab.hakim.se/reveal-js\n' + + ' * MIT licensed\n' + + ' *\n' + + ' * Copyright (C) 2016 Hakim El Hattab, http://hakim.se\n' + + ' */' + }, + + qunit: { + files: [ 'test/*.html' ] + }, + + uglify: { + options: { + banner: '<%= meta.banner %>\n' + }, + build: { + src: 'js/reveal.js', + dest: 'js/reveal.min.js' + } + }, + + sass: { + core: { + files: { + 'css/reveal.css': 'css/reveal.scss', + } + }, + themes: { + files: [ + { + expand: true, + cwd: 'css/theme/source', + src: ['*.scss'], + dest: 'css/theme', + ext: '.css' + } + ] + } + }, + + autoprefixer: { + dist: { + src: 'css/reveal.css' + } + }, + + cssmin: { + compress: { + files: { + 'css/reveal.min.css': [ 'css/reveal.css' ] + } + } + }, + + jshint: { + options: { + curly: false, + eqeqeq: true, + immed: true, + esnext: true, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + eqnull: true, + browser: true, + expr: true, + globals: { + head: false, + module: false, + console: false, + unescape: false, + define: false, + exports: false + } + }, + files: [ 'Gruntfile.js', 'js/reveal.js' ] + }, + + connect: { + server: { + options: { + port: port, + base: root, + livereload: true, + open: true + } + }, + + }, + + zip: { + 'reveal-js-presentation.zip': [ + 'index.html', + 'css/**', + 'js/**', + 'lib/**', + 'images/**', + 'plugin/**', + '**.md' + ] + }, + + watch: { + js: { + files: [ 'Gruntfile.js', 'js/reveal.js' ], + tasks: 'js' + }, + theme: { + files: [ 'css/theme/source/*.scss', 'css/theme/template/*.scss' ], + tasks: 'css-themes' + }, + css: { + files: [ 'css/reveal.scss' ], + tasks: 'css-core' + }, + html: { + files: root.map(path => path + '/*.html') + }, + markdown: { + files: root.map(path => path + '/*.md') + }, + options: { + livereload: true + } + }, + + retire: { + js: ['js/reveal.js', 'lib/js/*.js', 'plugin/**/*.js'], + node: ['.'], + options: {} + } + + }); + + // Dependencies + grunt.loadNpmTasks( 'grunt-contrib-qunit' ); + grunt.loadNpmTasks( 'grunt-contrib-jshint' ); + grunt.loadNpmTasks( 'grunt-contrib-cssmin' ); + grunt.loadNpmTasks( 'grunt-contrib-uglify' ); + grunt.loadNpmTasks( 'grunt-contrib-watch' ); + grunt.loadNpmTasks( 'grunt-sass' ); + grunt.loadNpmTasks( 'grunt-contrib-connect' ); + grunt.loadNpmTasks( 'grunt-autoprefixer' ); + grunt.loadNpmTasks( 'grunt-zip' ); + grunt.loadNpmTasks( 'grunt-retire' ); + + // Default task + grunt.registerTask( 'default', [ 'css', 'js' ] ); + + // JS task + grunt.registerTask( 'js', [ 'jshint', 'uglify', 'qunit' ] ); + + // Theme CSS + grunt.registerTask( 'css-themes', [ 'sass:themes' ] ); + + // Core framework CSS + grunt.registerTask( 'css-core', [ 'sass:core', 'autoprefixer', 'cssmin' ] ); + + // All CSS + grunt.registerTask( 'css', [ 'sass', 'autoprefixer', 'cssmin' ] ); + + // Package presentation to archive + grunt.registerTask( 'package', [ 'default', 'zip' ] ); + + // Serve presentation locally + grunt.registerTask( 'serve', [ 'connect', 'watch' ] ); + + // Run tests + grunt.registerTask( 'test', [ 'jshint', 'qunit' ] ); + +}; diff --git a/static/reveal.js/LICENSE b/static/reveal.js/LICENSE new file mode 100644 index 0000000..924cd89 --- /dev/null +++ b/static/reveal.js/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2016 Hakim El Hattab, http://hakim.se, and reveal.js contributors + +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. \ No newline at end of file diff --git a/static/reveal.js/README.md b/static/reveal.js/README.md new file mode 100644 index 0000000..8878842 --- /dev/null +++ b/static/reveal.js/README.md @@ -0,0 +1,1170 @@ +# reveal.js [![Build Status](https://travis-ci.org/hakimel/reveal.js.svg?branch=master)](https://travis-ci.org/hakimel/reveal.js) Slides + +A framework for easily creating beautiful presentations using HTML. [Check out the live demo](http://lab.hakim.se/reveal-js/). + +reveal.js comes with a broad range of features including [nested slides](https://github.com/hakimel/reveal.js#markup), [Markdown contents](https://github.com/hakimel/reveal.js#markdown), [PDF export](https://github.com/hakimel/reveal.js#pdf-export), [speaker notes](https://github.com/hakimel/reveal.js#speaker-notes) and a [JavaScript API](https://github.com/hakimel/reveal.js#api). There's also a fully featured visual editor and platform for sharing reveal.js presentations at [slides.com](https://slides.com?ref=github). + +## Table of contents +- [Online Editor](#online-editor) +- [Instructions](#instructions) + - [Markup](#markup) + - [Markdown](#markdown) + - [Element Attributes](#element-attributes) + - [Slide Attributes](#slide-attributes) +- [Configuration](#configuration) +- [Presentation Size](#presentation-size) +- [Dependencies](#dependencies) +- [Ready Event](#ready-event) +- [Auto-sliding](#auto-sliding) +- [Keyboard Bindings](#keyboard-bindings) +- [Touch Navigation](#touch-navigation) +- [Lazy Loading](#lazy-loading) +- [API](#api) + - [Slide Changed Event](#slide-changed-event) + - [Presentation State](#presentation-state) + - [Slide States](#slide-states) + - [Slide Backgrounds](#slide-backgrounds) + - [Parallax Background](#parallax-background) + - [Slide Transitions](#slide-transitions) + - [Internal links](#internal-links) + - [Fragments](#fragments) + - [Fragment events](#fragment-events) + - [Code syntax highlighting](#code-syntax-highlighting) + - [Slide number](#slide-number) + - [Overview mode](#overview-mode) + - [Fullscreen mode](#fullscreen-mode) + - [Embedded media](#embedded-media) + - [Stretching elements](#stretching-elements) + - [postMessage API](#postmessage-api) +- [PDF Export](#pdf-export) +- [Theming](#theming) +- [Speaker Notes](#speaker-notes) + - [Share and Print Speaker Notes](#share-and-print-speaker-notes) + - [Server Side Speaker Notes](#server-side-speaker-notes) +- [Multiplexing](#multiplexing) + - [Master presentation](#master-presentation) + - [Client presentation](#client-presentation) + - [Socket.io server](#socketio-server) +- [MathJax](#mathjax) +- [Installation](#installation) + - [Basic setup](#basic-setup) + - [Full setup](#full-setup) + - [Folder Structure](#folder-structure) +- [License](#license) + +#### More reading +- [Changelog](https://github.com/hakimel/reveal.js/releases): Up-to-date version history. +- [Examples](https://github.com/hakimel/reveal.js/wiki/Example-Presentations): Presentations created with reveal.js, add your own! +- [Browser Support](https://github.com/hakimel/reveal.js/wiki/Browser-Support): Explanation of browser support and fallbacks. +- [Plugins](https://github.com/hakimel/reveal.js/wiki/Plugins,-Tools-and-Hardware): A list of plugins that can be used to extend reveal.js. + +## Online Editor + +Presentations are written using HTML or Markdown but there's also an online editor for those of you who prefer a graphical interface. Give it a try at [https://slides.com](https://slides.com?ref=github). + + +## Instructions + +### Markup + +Here's a barebones example of a fully working reveal.js presentation: +```html + + + + + + +
    +
    +
    Slide 1
    +
    Slide 2
    +
    +
    + + + + +``` + +The presentation markup hierarchy needs to be `.reveal > .slides > section` where the `section` represents one slide and can be repeated indefinitely. If you place multiple `section` elements inside of another `section` they will be shown as vertical slides. The first of the vertical slides is the "root" of the others (at the top), and will be included in the horizontal sequence. For example: + +```html +
    +
    +
    Single Horizontal Slide
    +
    +
    Vertical Slide 1
    +
    Vertical Slide 2
    +
    +
    +
    +``` + +### Markdown + +It's possible to write your slides using Markdown. To enable Markdown, add the `data-markdown` attribute to your `
    ` elements and wrap the contents in a ` +
    +``` + +#### External Markdown + +You can write your content as a separate file and have reveal.js load it at runtime. Note the separator arguments which determine how slides are delimited in the external file: the `data-separator` attribute defines a regular expression for horizontal slides (defaults to `^\r?\n---\r?\n$`, a newline-bounded horizontal rule) and `data-separator-vertical` defines vertical slides (disabled by default). The `data-separator-notes` attribute is a regular expression for specifying the beginning of the current slide's speaker notes (defaults to `note:`). The `data-charset` attribute is optional and specifies which charset to use when loading the external file. + +When used locally, this feature requires that reveal.js [runs from a local web server](#full-setup). The following example customises all available options: + +```html +
    +
    +``` + +#### Element Attributes + +Special syntax (in html comment) is available for adding attributes to Markdown elements. This is useful for fragments, amongst other things. + +```html +
    + +
    +``` + +#### Slide Attributes + +Special syntax (in html comment) is available for adding attributes to the slide `
    ` elements generated by your Markdown. + +```html +
    + +
    +``` + +#### Configuring *marked* + +We use [marked](https://github.com/chjj/marked) to parse Markdown. To customise marked's rendering, you can pass in options when [configuring Reveal](#configuration): + +```javascript +Reveal.initialize({ + // Options which are passed into marked + // See https://github.com/chjj/marked#options-1 + markdown: { + smartypants: true + } +}); +``` + +### Configuration + +At the end of your page you need to initialize reveal by running the following code. Note that all config values are optional and will default as specified below. + +```javascript +Reveal.initialize({ + + // Display controls in the bottom right corner + controls: true, + + // Display a presentation progress bar + progress: true, + + // Display the page number of the current slide + slideNumber: false, + + // Push each slide change to the browser history + history: false, + + // Enable keyboard shortcuts for navigation + keyboard: true, + + // Enable the slide overview mode + overview: true, + + // Vertical centering of slides + center: true, + + // Enables touch navigation on devices with touch input + touch: true, + + // Loop the presentation + loop: false, + + // Change the presentation direction to be RTL + rtl: false, + + // Randomizes the order of slides each time the presentation loads + shuffle: false, + + // Turns fragments on and off globally + fragments: true, + + // Flags if the presentation is running in an embedded mode, + // i.e. contained within a limited portion of the screen + embedded: false, + + // Flags if we should show a help overlay when the questionmark + // key is pressed + help: true, + + // Flags if speaker notes should be visible to all viewers + showNotes: false, + + // Number of milliseconds between automatically proceeding to the + // next slide, disabled when set to 0, this value can be overwritten + // by using a data-autoslide attribute on your slides + autoSlide: 0, + + // Stop auto-sliding after user input + autoSlideStoppable: true, + + // Use this method for navigation when auto-sliding + autoSlideMethod: Reveal.navigateNext, + + // Enable slide navigation via mouse wheel + mouseWheel: false, + + // Hides the address bar on mobile devices + hideAddressBar: true, + + // Opens links in an iframe preview overlay + previewLinks: false, + + // Transition style + transition: 'slide', // none/fade/slide/convex/concave/zoom + + // Transition speed + transitionSpeed: 'default', // default/fast/slow + + // Transition style for full page slide backgrounds + backgroundTransition: 'fade', // none/fade/slide/convex/concave/zoom + + // Number of slides away from the current that are visible + viewDistance: 3, + + // Parallax background image + parallaxBackgroundImage: '', // e.g. "'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg'" + + // Parallax background size + parallaxBackgroundSize: '', // CSS syntax, e.g. "2100px 900px" + + // Number of pixels to move the parallax background per slide + // - Calculated automatically unless specified + // - Set to 0 to disable movement along an axis + parallaxBackgroundHorizontal: null, + parallaxBackgroundVertical: null + +}); +``` + + +The configuration can be updated after initialization using the ```configure``` method: + +```javascript +// Turn autoSlide off +Reveal.configure({ autoSlide: 0 }); + +// Start auto-sliding every 5s +Reveal.configure({ autoSlide: 5000 }); +``` + + +### Presentation Size + +All presentations have a normal size, that is the resolution at which they are authored. The framework will automatically scale presentations uniformly based on this size to ensure that everything fits on any given display or viewport. + +See below for a list of configuration options related to sizing, including default values: + +```javascript +Reveal.initialize({ + + ... + + // The "normal" size of the presentation, aspect ratio will be preserved + // when the presentation is scaled to fit different resolutions. Can be + // specified using percentage units. + width: 960, + height: 700, + + // Factor of the display size that should remain empty around the content + margin: 0.1, + + // Bounds for smallest/largest possible scale to apply to content + minScale: 0.2, + maxScale: 1.5 + +}); +``` + +If you wish to disable this behavior and do your own scaling (e.g. using media queries), try these settings: + +```javascript +Reveal.initialize({ + + ... + + width: "100%", + height: "100%", + margin: 0, + minScale: 1, + maxScale: 1 +}); +``` + +### Dependencies + +Reveal.js doesn't _rely_ on any third party scripts to work but a few optional libraries are included by default. These libraries are loaded as dependencies in the order they appear, for example: + +```javascript +Reveal.initialize({ + dependencies: [ + // Cross-browser shim that fully implements classList - https://github.com/eligrey/classList.js/ + { src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } }, + + // Interpret Markdown in
    elements + { src: 'plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, + { src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, + + // Syntax highlight for elements + { src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }, + + // Zoom in and out with Alt+click + { src: 'plugin/zoom-js/zoom.js', async: true }, + + // Speaker notes + { src: 'plugin/notes/notes.js', async: true }, + + // MathJax + { src: 'plugin/math/math.js', async: true } + ] +}); +``` + +You can add your own extensions using the same syntax. The following properties are available for each dependency object: +- **src**: Path to the script to load +- **async**: [optional] Flags if the script should load after reveal.js has started, defaults to false +- **callback**: [optional] Function to execute when the script has loaded +- **condition**: [optional] Function which must return true for the script to be loaded + +To load these dependencies, reveal.js requires [head.js](http://headjs.com/) *(a script loading library)* to be loaded before reveal.js. + +### Ready Event + +A 'ready' event is fired when reveal.js has loaded all non-async dependencies and is ready to start navigating. To check if reveal.js is already 'ready' you can call `Reveal.isReady()`. + +```javascript +Reveal.addEventListener( 'ready', function( event ) { + // event.currentSlide, event.indexh, event.indexv +} ); +``` + +Note that we also add a `.ready` class to the `.reveal` element so that you can hook into this with CSS. + +### Auto-sliding + +Presentations can be configured to progress through slides automatically, without any user input. To enable this you will need to tell the framework how many milliseconds it should wait between slides: + +```javascript +// Slide every five seconds +Reveal.configure({ + autoSlide: 5000 +}); +``` +When this is turned on a control element will appear that enables users to pause and resume auto-sliding. Alternatively, sliding can be paused or resumed by pressing »a« on the keyboard. Sliding is paused automatically as soon as the user starts navigating. You can disable these controls by specifying ```autoSlideStoppable: false``` in your reveal.js config. + +You can also override the slide duration for individual slides and fragments by using the ```data-autoslide``` attribute: + +```html +
    +

    After 2 seconds the first fragment will be shown.

    +

    After 10 seconds the next fragment will be shown.

    +

    Now, the fragment is displayed for 2 seconds before the next slide is shown.

    +
    +``` + +To override the method used for navigation when auto-sliding, you can specify the ```autoSlideMethod``` setting. To only navigate along the top layer and ignore vertical slides, set this to ```Reveal.navigateRight```. + +Whenever the auto-slide mode is resumed or paused the ```autoslideresumed``` and ```autoslidepaused``` events are fired. + + +### Keyboard Bindings + +If you're unhappy with any of the default keyboard bindings you can override them using the ```keyboard``` config option: + +```javascript +Reveal.configure({ + keyboard: { + 13: 'next', // go to the next slide when the ENTER key is pressed + 27: function() {}, // do something custom when ESC is pressed + 32: null // don't do anything when SPACE is pressed (i.e. disable a reveal.js default binding) + } +}); +``` + +### Touch Navigation + +You can swipe to navigate through a presentation on any touch-enabled device. Horizontal swipes change between horizontal slides, vertical swipes change between vertical slides. If you wish to disable this you can set the `touch` config option to false when initializing reveal.js. + +If there's some part of your content that needs to remain accessible to touch events you'll need to highlight this by adding a `data-prevent-swipe` attribute to the element. One common example where this is useful is elements that need to be scrolled. + + +### Lazy Loading + +When working on presentation with a lot of media or iframe content it's important to load lazily. Lazy loading means that reveal.js will only load content for the few slides nearest to the current slide. The number of slides that are preloaded is determined by the `viewDistance` configuration option. + +To enable lazy loading all you need to do is change your "src" attributes to "data-src" as shown below. This is supported for image, video, audio and iframe elements. Lazy loaded iframes will also unload when the containing slide is no longer visible. + +```html +
    + + + +
    +``` + + +### API + +The ``Reveal`` object exposes a JavaScript API for controlling navigation and reading state: + +```javascript +// Navigation +Reveal.slide( indexh, indexv, indexf ); +Reveal.left(); +Reveal.right(); +Reveal.up(); +Reveal.down(); +Reveal.prev(); +Reveal.next(); +Reveal.prevFragment(); +Reveal.nextFragment(); + +// Randomize the order of slides +Reveal.shuffle(); + +// Shows a help overlay with keyboard shortcuts +Reveal.showHelp(); + +// Toggle presentation states, optionally pass true/false to force on/off +Reveal.toggleOverview(); +Reveal.togglePause(); +Reveal.toggleAutoSlide(); + +// Change a config value at runtime +Reveal.configure({ controls: true }); + +// Returns the present configuration options +Reveal.getConfig(); + +// Fetch the current scale of the presentation +Reveal.getScale(); + +// Retrieves the previous and current slide elements +Reveal.getPreviousSlide(); +Reveal.getCurrentSlide(); + +Reveal.getIndices(); // { h: 0, v: 0 } } +Reveal.getProgress(); // 0-1 +Reveal.getTotalSlides(); + +// Returns the speaker notes for the current slide +Reveal.getSlideNotes(); + +// State checks +Reveal.isFirstSlide(); +Reveal.isLastSlide(); +Reveal.isOverview(); +Reveal.isPaused(); +Reveal.isAutoSliding(); +``` + +### Slide Changed Event + +A 'slidechanged' event is fired each time the slide is changed (regardless of state). The event object holds the index values of the current slide as well as a reference to the previous and current slide HTML nodes. + +Some libraries, like MathJax (see [#226](https://github.com/hakimel/reveal.js/issues/226#issuecomment-10261609)), get confused by the transforms and display states of slides. Often times, this can be fixed by calling their update or render function from this callback. + +```javascript +Reveal.addEventListener( 'slidechanged', function( event ) { + // event.previousSlide, event.currentSlide, event.indexh, event.indexv +} ); +``` + +### Presentation State + +The presentation's current state can be fetched by using the `getState` method. A state object contains all of the information required to put the presentation back as it was when `getState` was first called. Sort of like a snapshot. It's a simple object that can easily be stringified and persisted or sent over the wire. + +```javascript +Reveal.slide( 1 ); +// we're on slide 1 + +var state = Reveal.getState(); + +Reveal.slide( 3 ); +// we're on slide 3 + +Reveal.setState( state ); +// we're back on slide 1 +``` + +### Slide States + +If you set ``data-state="somestate"`` on a slide ``
    ``, "somestate" will be applied as a class on the document element when that slide is opened. This allows you to apply broad style changes to the page based on the active slide. + +Furthermore you can also listen to these changes in state via JavaScript: + +```javascript +Reveal.addEventListener( 'somestate', function() { + // TODO: Sprinkle magic +}, false ); +``` + +### Slide Backgrounds + +Slides are contained within a limited portion of the screen by default to allow them to fit any display and scale uniformly. You can apply full page backgrounds outside of the slide area by adding a ```data-background``` attribute to your ```
    ``` elements. Four different types of backgrounds are supported: color, image, video and iframe. + +##### Color Backgrounds +All CSS color formats are supported, like rgba() or hsl(). +```html +
    +

    Color

    +
    +``` + +##### Image Backgrounds +By default, background images are resized to cover the full page. Available options: + +| Attribute | Default | Description | +| :--------------------------- | :--------- | :---------- | +| data-background-image | | URL of the image to show. GIFs restart when the slide opens. | +| data-background-size | cover | See [background-size](https://developer.mozilla.org/docs/Web/CSS/background-size) on MDN. | +| data-background-position | center | See [background-position](https://developer.mozilla.org/docs/Web/CSS/background-position) on MDN. | +| data-background-repeat | no-repeat | See [background-repeat](https://developer.mozilla.org/docs/Web/CSS/background-repeat) on MDN. | +```html +
    +

    Image

    +
    +
    +

    This background image will be sized to 100px and repeated

    +
    +``` + +##### Video Backgrounds +Automatically plays a full size video behind the slide. + +| Attribute | Default | Description | +| :--------------------------- | :------ | :---------- | +| data-background-video | | A single video source, or a comma separated list of video sources. | +| data-background-video-loop | false | Flags if the video should play repeatedly. | +| data-background-video-muted | false | Flags if the audio should be muted. | + +```html +
    +

    Video

    +
    +``` + +##### Iframe Backgrounds +Embeds a web page as a background. Note that since the iframe is in the background layer, behind your slides, it is not possible to interact with the embedded page. +```html +
    +

    Iframe

    +
    +``` + +##### Background Transitions +Backgrounds transition using a fade animation by default. This can be changed to a linear sliding transition by passing ```backgroundTransition: 'slide'``` to the ```Reveal.initialize()``` call. Alternatively you can set ```data-background-transition``` on any section with a background to override that specific transition. + + +### Parallax Background + +If you want to use a parallax scrolling background, set the first two config properties below when initializing reveal.js (the other two are optional). + +```javascript +Reveal.initialize({ + + // Parallax background image + parallaxBackgroundImage: '', // e.g. "https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg" + + // Parallax background size + parallaxBackgroundSize: '', // CSS syntax, e.g. "2100px 900px" - currently only pixels are supported (don't use % or auto) + + // Number of pixels to move the parallax background per slide + // - Calculated automatically unless specified + // - Set to 0 to disable movement along an axis + parallaxBackgroundHorizontal: 200, + parallaxBackgroundVertical: 50 + +}); +``` + +Make sure that the background size is much bigger than screen size to allow for some scrolling. [View example](http://lab.hakim.se/reveal-js/?parallaxBackgroundImage=https%3A%2F%2Fs3.amazonaws.com%2Fhakim-static%2Freveal-js%2Freveal-parallax-1.jpg¶llaxBackgroundSize=2100px%20900px). + + + +### Slide Transitions +The global presentation transition is set using the ```transition``` config value. You can override the global transition for a specific slide by using the ```data-transition``` attribute: + +```html +
    +

    This slide will override the presentation transition and zoom!

    +
    + +
    +

    Choose from three transition speeds: default, fast or slow!

    +
    +``` + +You can also use different in and out transitions for the same slide: + +```html +
    + The train goes on … +
    +
    + and on … +
    +
    + and stops. +
    +
    + (Passengers entering and leaving) +
    +
    + And it starts again. +
    +``` + + +### Internal links + +It's easy to link between slides. The first example below targets the index of another slide whereas the second targets a slide with an ID attribute (```
    ```): + +```html +Link +Link +``` + +You can also add relative navigation links, similar to the built in reveal.js controls, by appending one of the following classes on any element. Note that each element is automatically given an ```enabled``` class when it's a valid navigation route based on the current slide. + +```html + + + + + + +``` + + +### Fragments +Fragments are used to highlight individual elements on a slide. Every element with the class ```fragment``` will be stepped through before moving on to the next slide. Here's an example: http://lab.hakim.se/reveal-js/#/fragments + +The default fragment style is to start out invisible and fade in. This style can be changed by appending a different class to the fragment: + +```html +
    +

    grow

    +

    shrink

    +

    fade-out

    +

    fade-up (also down, left and right!)

    +

    visible only once

    +

    blue only once

    +

    highlight-red

    +

    highlight-green

    +

    highlight-blue

    +
    +``` + +Multiple fragments can be applied to the same element sequentially by wrapping it, this will fade in the text on the first step and fade it back out on the second. + +```html +
    + + I'll fade in, then out + +
    +``` + +The display order of fragments can be controlled using the ```data-fragment-index``` attribute. + +```html +
    +

    Appears last

    +

    Appears first

    +

    Appears second

    +
    +``` + +### Fragment events + +When a slide fragment is either shown or hidden reveal.js will dispatch an event. + +Some libraries, like MathJax (see #505), get confused by the initially hidden fragment elements. Often times this can be fixed by calling their update or render function from this callback. + +```javascript +Reveal.addEventListener( 'fragmentshown', function( event ) { + // event.fragment = the fragment DOM element +} ); +Reveal.addEventListener( 'fragmenthidden', function( event ) { + // event.fragment = the fragment DOM element +} ); +``` + +### Code syntax highlighting + +By default, Reveal is configured with [highlight.js](https://highlightjs.org/) for code syntax highlighting. Below is an example with clojure code that will be syntax highlighted. When the `data-trim` attribute is present, surrounding whitespace is automatically removed. HTML will be escaped by default. To avoid this, for example if you are using `` to call out a line of code, add the `data-noescape` attribute to the `` element. + +```html +
    +
    
    +(def lazy-fib
    +  (concat
    +   [0 1]
    +   ((fn rfib [a b]
    +        (lazy-cons (+ a b) (rfib b (+ a b)))) 0 1)))
    +	
    +
    +``` + +### Slide number +If you would like to display the page number of the current slide you can do so using the ```slideNumber``` configuration value. + +```javascript +// Shows the slide number using default formatting +Reveal.configure({ slideNumber: true }); + +// Slide number formatting can be configured using these variables: +// "h.v": horizontal . vertical slide number (default) +// "h/v": horizontal / vertical slide number +// "c": flattened slide number +// "c/t": flattened slide number / total slides +Reveal.configure({ slideNumber: 'c/t' }); + +``` + + +### Overview mode + +Press "Esc" or "o" keys to toggle the overview mode on and off. While you're in this mode, you can still navigate between slides, +as if you were at 1,000 feet above your presentation. The overview mode comes with a few API hooks: + +```javascript +Reveal.addEventListener( 'overviewshown', function( event ) { /* ... */ } ); +Reveal.addEventListener( 'overviewhidden', function( event ) { /* ... */ } ); + +// Toggle the overview mode programmatically +Reveal.toggleOverview(); +``` + +### Fullscreen mode +Just press »F« on your keyboard to show your presentation in fullscreen mode. Press the »ESC« key to exit fullscreen mode. + + +### Embedded media +Embedded HTML5 `