From 61f8dd4da87bb4b8d536d81ea9430dad39cd975e Mon Sep 17 00:00:00 2001 From: Jonas Smedegaard Date: Thu, 24 May 2012 10:31:18 +0200 Subject: Add support for Slideous output. --- INSTALL | 1 + README | 49 +++--- pandoc.cabal | 6 +- slideous/slideous.css | 95 ++++++++++++ slideous/slideous.js | 321 ++++++++++++++++++++++++++++++++++++++++ src/Text/Pandoc.hs | 1 + src/Text/Pandoc/Shared.hs | 3 +- src/Text/Pandoc/Slides.hs | 2 +- src/Text/Pandoc/Writers/HTML.hs | 1 + src/pandoc.hs | 7 +- 10 files changed, 463 insertions(+), 23 deletions(-) create mode 100644 slideous/slideous.css create mode 100644 slideous/slideous.js diff --git a/INSTALL b/INSTALL index 94627de05..8c4a07e2b 100644 --- a/INSTALL +++ b/INSTALL @@ -119,6 +119,7 @@ you please, and copy the following data files to the same place: data/ s5/ slidy/ + slideous/ dzslides/ pcre-license.txt pcre3.dll diff --git a/README b/README index fda10c988..470ca18aa 100644 --- a/README +++ b/README @@ -18,8 +18,8 @@ another, and a command-line tool that uses this library. It can read slide shows), [ConTeXt], [RTF], [DocBook XML], [OpenDocument XML], [ODT], [Word docx], [GNU Texinfo], [MediaWiki markup], [EPUB], [Textile], [groff man] pages, [Emacs Org-Mode], [AsciiDoc], and [Slidy], -[DZSlides], or [S5] HTML slide shows. It can also produce [PDF] output -on systems where LaTeX is installed. +[Slideous], [DZSlides], or [S5] HTML slide shows. It can also produce +[PDF] output on systems where LaTeX is installed. Pandoc's enhanced version of markdown includes syntax for footnotes, tables, flexible ordered lists, definition lists, delimited code blocks, @@ -153,6 +153,7 @@ General options `docbook` (DocBook XML), `opendocument` (OpenDocument XML), `odt` (OpenOffice text document), `docx` (Word docx), `epub` (EPUB book), `asciidoc` (AsciiDoc), `slidy` (Slidy HTML and javascript slide show), + `slideous` (Slideous HTML and javascript slide show), `dzslides` (HTML5 + javascript slide show), `s5` (S5 HTML and javascript slide show), or `rtf` (rich text format). Note that `odt` and `epub` output will not be directed to *stdout*; an output filename must @@ -178,8 +179,8 @@ General options C:\Documents And Settings\USERNAME\Application Data\pandoc in Windows. A `reference.odt`, `reference.docx`, `default.csl`, - `epub.css`, `templates`, `slidy`, or `s5` directory placed in this - directory will override pandoc's normal defaults. + `epub.css`, `templates`, `slidy`, `slideous`, or `s5` directory + placed in this directory will override pandoc's normal defaults. `-v`, `--version` : Print version. @@ -199,7 +200,8 @@ Reader options `-R`, `--parse-raw` : Parse untranslatable HTML codes and LaTeX environments as raw HTML or LaTeX, instead of ignoring them. Affects only HTML and LaTeX - input. Raw HTML can be printed in markdown, reStructuredText, HTML, Slidy, + input. Raw HTML can be printed in markdown, reStructuredText, HTML, + Slidy, Slideous, DZSlides, and S5 output; raw LaTeX can be printed in markdown, reStructuredText, LaTeX, and ConTeXt output. The default is for the readers to omit untranslatable HTML codes and LaTeX environments. @@ -280,7 +282,7 @@ General writer options : Include an automatically generated table of contents (or, in the case of `latex`, `context`, and `rst`, an instruction to create one) in the output document. This option has no effect on `man`, - `docbook`, `slidy`, or `s5` output. + `docbook`, `slidy`, `slideous`, or `s5` output. `--no-highlight` : Disables syntax highlighting for code blocks and inlines, even when @@ -323,7 +325,8 @@ Options affecting specific writers in the sense that it needs no external files and no net access to be displayed properly by a browser. This option works only with HTML output formats, including `html`, `html5`, `html+lhs`, `html5+lhs`, `s5`, - `slidy`, and `dzslides`. Scripts, images, and stylesheets at absolute URLs + `slidy`, `slideous`, + and `dzslides`. Scripts, images, and stylesheets at absolute URLs will be downloaded; those at relative URLs will be sought first relative to the working directory, then relative to the user data directory (see `--data-dir`), and finally relative to pandoc's default data directory. @@ -378,7 +381,7 @@ Options affecting specific writers `--slide-level`=*NUMBER* : Specifies that headers with the specified level create - slides (for `beamer`, `s5`, `slidy`, `dzslides`). Headers + slides (for `beamer`, `s5`, `slidy`, `slideous`, `dzslides`). Headers above this level in the hierarchy are used to divide the slide show into sections; headers below this level create subheads within a slide. The default is to set the slide level @@ -683,6 +686,8 @@ depending on the output format, but include: `slidy-url` : base URL for Slidy documents (defaults to `http://www.w3.org/Talks/Tools/Slidy2`) +`slideous-url` +: base URL for Slideous documents (defaults to `default`) `s5-url` : base URL for S5 documents (defaults to `ui/default`) `fontsize` @@ -1698,7 +1703,7 @@ Docbook Docx ~ It will be rendered using OMML math markup. -HTML, Slidy, DZSlides, S5, EPUB +HTML, Slidy, Slideous, DZSlides, S5, EPUB ~ The way math is rendered in HTML will depend on the command-line options selected: @@ -1749,7 +1754,8 @@ Markdown allows you to insert raw HTML (or DocBook) anywhere in a document (except verbatim contexts, where `<`, `>`, and `&` are interpreted literally). -The raw HTML is passed through unchanged in HTML, S5, Slidy, DZSlides, EPUB, +The raw HTML is passed through unchanged in HTML, S5, Slidy, Slideous, +DZSlides, EPUB, Markdown, and Textile output, and suppressed in other formats. *Pandoc extension*. @@ -2070,9 +2076,9 @@ Producing slide shows with Pandoc ================================= You can use Pandoc to produce an HTML + javascript slide presentation -that can be viewed via a web browser. There are three ways to do this, -using [S5], [DZSlides], or [Slidy]. You can also produce a PDF slide -show using LaTeX [beamer]. +that can be viewed via a web browser. There are four ways to do this, +using [S5], [DZSlides], [Slidy], or [Slideous]. You can also produce a +PDF slide show using LaTeX [beamer]. Here's the markdown source for a simple slide show, `habits.txt`: @@ -2118,6 +2124,10 @@ for S5, for Slidy, + pandoc -t slideous -s habits.txt -o habits.html + +for Slideous, + pandoc -t dzslides -s habits.txt -o habits.html for DZSlides, or @@ -2164,11 +2174,14 @@ you can just use level 1 headers for all each slide. (In that case, level 1 will be the slide level.) But you can also structure the slide show into sections, as in the example above. -For Slidy and S5, the file produced by pandoc with the `-s/--standalone` +For Slidy, Slideous and S5, the file produced by pandoc with the +`-s/--standalone` option embeds a link to javascripts and CSS files, which are assumed to -be available at the relative path `s5/default` (for S5) or at the Slidy +be available at the relative path `s5/default` (for S5) or `slideous` +(for Slideous), or at the Slidy website at `w3.org` (for Slidy). (These paths can be changed by setting -the `slidy-url` or `s5-url` variables; see `--variable`, above.) For DZSlides, +the `slidy-url`, `slideous-url` or `s5-url` variables; see `--variable`, +above.) For DZSlides, the (relatively short) javascript and css are included in the file by default. Incremental lists @@ -2190,7 +2203,8 @@ Styling the slides ------------------ You can change the style of HTML slides by putting customized CSS files -in `$DATADIR/s5/default` (for S5) or `$DATADIR/slidy` (for Slidy), +in `$DATADIR/s5/default` (for S5), `$DATADIR/slidy` (for Slidy), +or `$DATADIR/slideous` (for Slideous), where `$DATADIR` is the user data directory (see `--data-dir`, above). The originals may be found in pandoc's system data directory (generally `$CABALDIR/pandoc-VERSION/s5/default`). Pandoc will look there for any @@ -2267,6 +2281,7 @@ Latter, Ralf Stephan, Eric Seidel, B. Scott Michel. [reStructuredText]: http://docutils.sourceforge.net/docs/ref/rst/introduction.html [S5]: http://meyerweb.com/eric/tools/s5/ [Slidy]: http://www.w3.org/Talks/Tools/Slidy/ +[Slideous]: http://goessner.net/articles/slideous/ [HTML]: http://www.w3.org/TR/html40/ [HTML 5]: http://www.w3.org/TR/html5/ [XHTML]: http://www.w3.org/TR/xhtml1/ diff --git a/pandoc.cabal b/pandoc.cabal index dc38e8787..b7d1093c8 100644 --- a/pandoc.cabal +++ b/pandoc.cabal @@ -20,7 +20,7 @@ Description: Pandoc is a Haskell library for converting from one markup markdown, reStructuredText, HTML, LaTeX, ConTeXt, Docbook, OpenDocument, ODT, Word docx, RTF, MediaWiki, Textile, groff man pages, plain text, Emacs Org-Mode, AsciiDoc, EPUB, - and S5 and Slidy HTML slide shows. + and S5, Slidy and Slideous HTML slide shows. . Pandoc extends standard markdown syntax with footnotes, embedded LaTeX, definition lists, tables, and other @@ -45,6 +45,7 @@ Data-Files: templates/default.rst, templates/default.plain, templates/default.mediawiki, templates/default.rtf, templates/default.s5, templates/default.slidy, + templates/default.slideous, templates/default.dzslides, templates/default.asciidoc, templates/default.textile, templates/default.org, templates/epub-titlepage.html, templates/epub-page.html, @@ -78,6 +79,9 @@ Data-Files: slidy/graphics/nofold-dim.gif, slidy/graphics/unfold-dim.gif, slidy/graphics/fold-dim.gif, + -- data for slideous writer + slideous/slideous.css, + slideous/slideous.js, -- data for dzslides writer dzslides/template.html, -- data for citeproc diff --git a/slideous/slideous.css b/slideous/slideous.css new file mode 100644 index 000000000..bfe6e608b --- /dev/null +++ b/slideous/slideous.css @@ -0,0 +1,95 @@ +/* This work is licensed under Creative Commons GNU LGPL License. + + License: http://creativecommons.org/licenses/LGPL/2.1/ + Version: 1.0 + + Author: Stefan Goessner/2005 + Web: http://goessner.net/ +*/ +@media screen, projection { +body { + background-color: #e3eee7; + padding: 0; + margin: 0; + color: #132; + border-color: #678; + font-size: 125%; +} +#statusbar { + display: none; + position: absolute; z-index: 10; + top: auto; bottom: 0; left: 0; right: 0; + height: 2em; + background-color: #f0fff8; + color: #132; + font-size: 75%; + padding: 0.5em 0.5em 0 2px; + border-top: solid 1px #000; +} +#statusbar button, #tocbox { + cursor: pointer; + color: #031; + background-color: #e0eee7; + margin: 1px; + padding: 0 0.5em; + border: inset 1px black; +} +#statusbar button:hover, #tocbox:hover { + color: #031; + background-color: #c0ccc6; + border: outset 1px black; +} +#tocbox { + width: 15em; +} +#eos { + visibility: hidden; + color: #021; + background-color: #fffafa; + border: inset 1px black; + font-size: 120%; +} +div.slide { + display: block; + margin: 0 0 2em 0; + padding: 0 150px; +} + +div.slide h1 { + background: #a0aaa4; + color: #f0fff8; + padding: 0 0.5em 0 0.5em; + margin: 0 -150px; + font-size: 120%; + border-bottom: solid 1px black; +} + +div.slide h1:before { content: "# "; } +div.handout { display: block; } + +body>#statusbar { /* ie6 hack for fixing the statusbar - in quirks mode */ + position: fixed; /* thanks to Anne van Kesteren and Arthur Steiner */ +} /* see http://limpid.nl/lab/css/fixed/footer */ +* html body { + overflow: hidden; +} +* html div.slide { + height: 100%; + padding-bottom: 2em; + overflow: auto; +} /* end ie6-hack */ + +} /* @media screen, projection */ + +@media print { +body { + color: black; + font-family: sans-serif; + font-size: 11pt; +} + +#statusbar { display: none; } +div.slide { page-break-after: always; } +div.handout { display: block; } + +} /* @media print */ diff --git a/slideous/slideous.js b/slideous/slideous.js new file mode 100644 index 000000000..3e7a63d4a --- /dev/null +++ b/slideous/slideous.js @@ -0,0 +1,321 @@ +/* This work is licensed under Creative Commons GNU LGPL License. + + License: http://creativecommons.org/licenses/LGPL/2.1/ + + Author: Stefan Goessner/2005-2006 + Web: http://goessner.net/ +*/ +var Slideous = { + version: 1.0, + // == user customisable === + clickables: { a: true, button: true, img: true, input: true, object: true, textarea: true, select: true, option: true }, + incrementables: { blockquote: { filter: "self, parent" }, + dd: { filter: "self, parent" }, + dt: { filter: "self, parent" }, + h2: { filter: "self, parent" }, + h3: { filter: "self, parent" }, + h4: { filter: "self, parent" }, + h5: { filter: "self, parent" }, + h6: { filter: "self, parent" }, + li: { filter: "self, parent" }, + p: { filter: "self" }, + pre: { filter: "self" }, + img: { filter: "self, parent" }, + object: { filter: "self, parent" }, + table: { filter: "self, parent" }, + td: { filter: "self, parent" }, + th: { filter: "self, parent" }, + tr: { filter: "parent, grandparent" } + }, + autoincrementables: { ol: true, ul: true, dl: true }, + autoincrement: false, + statusbar: true, + navbuttons: { incfontbutton: function(){Slideous.changefontsize(+Slideous.fontdelta);}, + decfontbutton: function(){Slideous.changefontsize(-Slideous.fontdelta);}, + contentbutton: function(){Slideous.gotoslide(Slideous.tocidx(), true, true);}, + homebutton: function(){Slideous.gotoslide(1, true, true);}, + prevslidebutton: function(){Slideous.previous(false);}, + previtembutton: function(){Slideous.previous(true);}, + nextitembutton: function(){Slideous.next(true);}, + nextslidebutton: function(){Slideous.next(false);}, + endbutton: function(){Slideous.gotoslide(Slideous.count,true,true);} }, + fontsize: 125, // in percent, corresponding to body.font-size in css file + fontdelta: 5, // increase/decrease fontsize by this value + mousesensitive: true, + tocidx: 0, + tocitems: { toc: "
  • {\$slidetitle}
  • ", + tocbox: "" }, + keydown: function(evt) { + evt = evt || window.event; + var key = evt.keyCode || evt.which; + if (key && !evt.ctrlKey && !evt.altKey) { + switch (key) { + case 33: // page up ... previous slide + Slideous.previous(false); evt.cancel = !Slideous.showall; break; + case 37: // left arrow ... previous item + Slideous.previous(true); evt.cancel = !Slideous.showall; break; + case 32: // space bar + case 39: // right arrow + Slideous.next(true); evt.cancel = !Slideous.showall; break; + case 13: // carriage return ... next slide + case 34: // page down + Slideous.next(false); evt.cancel = !Slideous.showall; break; + case 35: // end ... last slide (not recognised by opera) + Slideous.gotoslide(Slideous.count, true, true); evt.cancel = !Slideous.showall; break; + case 36: // home ... first slide (not recognised by opera) + Slideous.gotoslide(1, true, true); evt.cancel = !Slideous.showall; break; + case 65: // A ... show All + case 80: // P ... Print mode + Slideous.toggleshowall(!Slideous.showall); evt.cancel = true; break; + case 67: // C ... goto contents + Slideous.gotoslide(Slideous.tocidx, true, true); evt.cancel = true; break; + case 77: // M ... toggle mouse sensitivity + Slideous.mousenavigation(Slideous.mousesensitive = !Slideous.mousesensitive); evt.cancel = true; break; + case 83: // S ... toggle statusbar + Slideous.togglestatusbar(); evt.cancel = true; break; + case 61: // + ... increase fontsize + case 107: + Slideous.changefontsize(+Slideous.fontdelta); evt.cancel = true; break; + case 109: // - ... decrease fontsize + Slideous.changefontsize(-Slideous.fontdelta); evt.cancel = true; break; + default: break; + } + if (evt.cancel) evt.returnValue = false; + } + return !evt.cancel; + }, + + // == program logic === + count: 0, // # of slides .. + curidx: 0, // current slide index .. + mousedownpos: null, // last mouse down position .. + contentselected: false, // indicates content selection .. + showall: true, + init: function() { + Slideous.curidx = 1; + Slideous.importproperties(); + Slideous.registerslides(); + document.body.innerHTML = Slideous.injectproperties(document.body.innerHTML); + Slideous.buildtocs(); + Slideous.registeranchors(); + Slideous.toggleshowall(false); + Slideous.updatestatus(); + document.body.style.fontSize = Slideous.fontsize+"%"; + document.getElementById("s1").style.display = "block"; + document.onkeydown = Slideous.keydown; + Slideous.mousenavigation(Slideous.mousesensitive); + Slideous.registerbuttons(); + if (window.location.hash) + Slideous.gotoslide(window.location.hash.substr(2), true, true); + }, + registerslides: function() { + var div = document.getElementsByTagName("div"); + Slideous.count = 0; + for (var i in div) + if (Slideous.hasclass(div[i], "slide")) + div[i].setAttribute("id", "s"+(++Slideous.count)); + }, + registeranchors: function() { + var a = document.getElementsByTagName("a"), + loc = (window.location.hostname+window.location.pathname).replace(/\\/g, "/"); + for (var i in a) { + if (a[i].href && a[i].href.indexOf(loc) >= 0 && a[i].href.lastIndexOf("#") >= 0) { + a[i].href = "javascript:Slideous.gotoslide(" + a[i].href.substr(a[i].href.lastIndexOf("#")+2)+",true,true)"; + } + } + }, + registerbuttons: function() { + var button; + for (var b in Slideous.navbuttons) + if (button = document.getElementById(b)) + button.onclick = Slideous.navbuttons[b]; + }, + importproperties: function() { // from html meta section .. + var meta = document.getElementsByTagName("meta"), elem; + for (var i in meta) + if (meta[i].attributes && meta[i].attributes["name"] && meta[i].attributes["name"].value in Slideous) + switch (typeof(Slideous[meta[i].attributes["name"].value])) { + case "number": Slideous[meta[i].attributes["name"].value] = parseInt(meta[i].attributes["content"].value); break; + case "boolean": Slideous[meta[i].attributes["name"].value] = meta[i].attributes["content"].value == "true" ? true : false; break; + default: Slideous[meta[i].attributes["name"].value] = meta[i].attributes["content"].value; break; + } + }, + injectproperties: function(str) { + var meta = document.getElementsByTagName("meta"), elem; + for (var i in meta) { + if (meta[i].attributes && meta[i].attributes["name"]) + str = str.replace(new RegExp("{\\$"+meta[i].attributes["name"].value+"}","g"), meta[i].attributes["content"].value); + } + return str = str.replace(/{\$generator}/g, "Slideous") + .replace(/{\$version}/g, Slideous.version) + .replace(/{\$title}/g, document.title) + .replace(/{\$slidecount}/g, Slideous.count); + }, + buildtocs: function() { + var toc = document.getElementById("toc"), list = "", + tocbox = document.getElementById("tocbox"); + if (toc) { + for (var i=0; i 0 && i <= Slideous.count && i != Slideous.curidx) { + document.getElementById("s"+Slideous.curidx).style.display = "none"; + var slide = document.getElementById("s"+(Slideous.curidx=i)), item; + while (item = Slideous.firstitem(slide, showitems ? Slideous.isitemhidden : Slideous.isitemvisible)) + Slideous.displayitem(item, showitems); + slide.style.display = "block"; + if (updatestatus) + Slideous.updatestatus(); + } + }, + firstitem: function(root, filter) { + var found = filter(root); + for (var node=root.firstChild; node!=null && !found; node = node.nextSibling) + found = Slideous.firstitem(node, filter); + return found; + }, + lastitem: function(root, filter) { + var found = null; + for (var node=root.lastChild; node!=null && !found; node = node.previousSibling) + found = Slideous.lastitem(node, filter); + return found || filter(root); + }, + isitem: function(node, visible) { + var nodename; + return node && node.nodeType == 1 // elements only .. + && (nodename=node.nodeName.toLowerCase()) in Slideous.incrementables + && ( Slideous.incrementables[nodename].filter.match("\\bself\\b") && (Slideous.hasclass(node, "incremental") || (Slideous.autoincrement && nodename in Slideous.autoincrementables)) + || Slideous.incrementables[nodename].filter.match("\\bparent\\b") && (Slideous.hasclass(node.parentNode, "incremental") || (Slideous.autoincrement && node.parentNode.nodeName.toLowerCase() in Slideous.autoincrementables)) + || Slideous.incrementables[nodename].filter.match("\\bgrandparent\\b") && (Slideous.hasclass(node.parentNode.parentNode, "incremental") || (Slideous.autoincrement && node.parentNode.parentNode.nodeName.toLowerCase() in Slideous.autoincrementables)) + ) + && (visible ? (node.style.visibility != "hidden") + : (node.style.visibility == "hidden")) + ? node : null; + }, + isitemvisible: function(node) { return Slideous.isitem(node, true); }, + isitemhidden: function(node) { return Slideous.isitem(node, false); }, + displayitem: function(item, show) { + if (item) item.style.visibility = (show ? "visible" : "hidden"); + }, + updatestatus: function() { + if (Slideous.statusbar) { + var eos = document.getElementById("eos"), + idx = document.getElementById("slideidx"), + tocbox = document.getElementById("tocbox"); + if (eos) + eos.style.visibility = Slideous.firstitem(document.getElementById("s"+Slideous.curidx), Slideous.isitemhidden) != null + ? "visible" : "hidden"; + if (idx) + idx.innerHTML = Slideous.curidx; + if (tocbox) + tocbox.selectedIndex = Slideous.curidx-1; + } + }, + changefontsize: function(delta) { + document.body.style.fontSize = (Slideous.fontsize+=delta)+"%"; + }, + togglestatusbar: function() { + document.getElementById("statusbar").style.display = (Slideous.statusbar = !Slideous.statusbar) ? "block" : "none"; + }, + toggleshowall: function(showall) { + var slide, item; + for (var i=0; i return opt { optIncremental = True })) - "" -- "Make list items display incrementally in Slidy/S5" + "" -- "Make list items display incrementally in Slidy/Slideous/S5" , Option "" ["slide-level"] (ReqArg @@ -887,6 +887,7 @@ main = do let slideVariant = case writerName' of "s5" -> S5Slides "slidy" -> SlidySlides + "slideous" -> SlideousSlides "dzslides" -> DZSlides _ -> NoSlides @@ -1052,7 +1053,7 @@ main = do where result = w writerOptions doc2 ++ ['\n' | not standalone'] htmlFormat = writerName' `elem` ["html","html+lhs","html5","html5+lhs", - "s5","slidy","dzslides"] + "s5","slidy","slideous","dzslides"] selfcontain = if selfContained && htmlFormat then makeSelfContained datadir else return -- cgit v1.2.3