Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

PyConFR slides: First rehearsal

  • Loading branch information...
commit aa34eeae0a7f16b70a5a1973246259c29d2085f5 1 parent a74305b
@SimonSapin authored
Showing with 2,287 additions and 2 deletions.
  1. BIN  exyr/pages/2012/weasyprint-at-pyconfr/CSS21-intro.pdf
  2. +0 −2  exyr/pages/2012/weasyprint-at-pyconfr/Makefile
  3. BIN  exyr/pages/2012/weasyprint-at-pyconfr/PyConFR_2012_schedule.pdf
  4. +14 −0 exyr/pages/2012/weasyprint-at-pyconfr/build.py
  5. +277 −0 exyr/pages/2012/weasyprint-at-pyconfr/embedder.html
  6. BIN  exyr/pages/2012/weasyprint-at-pyconfr/frozen_demo/foo.pdf
  7. BIN  exyr/pages/2012/weasyprint-at-pyconfr/frozen_demo/foo.png
  8. +24 −0 exyr/pages/2012/weasyprint-at-pyconfr/frozen_demo/foo/graph_42:27.3:63_Lorem:ipsum:sit.svg
  9. +14 −0 exyr/pages/2012/weasyprint-at-pyconfr/frozen_demo/foo/index.html
  10. +14 −0 exyr/pages/2012/weasyprint-at-pyconfr/frozen_demo/index.html
  11. +10 −0 exyr/pages/2012/weasyprint-at-pyconfr/frozen_demo/static/style.css
  12. +518 −0 exyr/pages/2012/weasyprint-at-pyconfr/images/Architecture.svg
  13. BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/GTK.png
  14. BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/RightMarginBoxes.png
  15. BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/acid2-small.png
  16. BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/box_model.png
  17. BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/cairo.png
  18. +9 −0 exyr/pages/2012/weasyprint-at-pyconfr/images/kozea-logo.svg
  19. BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/lxml.png
  20. BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/python.png
  21. BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/weasyprint-logo.png
  22. +358 −0 exyr/pages/2012/weasyprint-at-pyconfr/onstage.html
  23. +8 −0 exyr/pages/2012/weasyprint-at-pyconfr/outline
  24. +100 −0 exyr/pages/2012/weasyprint-at-pyconfr/prism.css
  25. +7 −0 exyr/pages/2012/weasyprint-at-pyconfr/prism.js
  26. +934 −0 exyr/pages/2012/weasyprint-at-pyconfr/slides.html
View
BIN  exyr/pages/2012/weasyprint-at-pyconfr/CSS21-intro.pdf
Binary file not shown
View
2  exyr/pages/2012/weasyprint-at-pyconfr/Makefile
@@ -1,2 +0,0 @@
-PyConFR_2012_schedule.pdf: print.css
- weasyprint http://www.pycon.fr/2012/schedule/ -s $< $@
View
BIN  exyr/pages/2012/weasyprint-at-pyconfr/PyConFR_2012_schedule.pdf
Binary file not shown
View
14 exyr/pages/2012/weasyprint-at-pyconfr/build.py
@@ -0,0 +1,14 @@
+import os
+from weasyprint import HTML
+from flask_frozen import Freezer
+from flask_weasyprint.test_app import app
+
+ROOT = os.path.dirname(os.path.abspath(__file__))
+os.chdir(ROOT)
+
+app.config['FREEZER_DESTINATION'] = os.path.join(ROOT, 'frozen_demo')
+app.config['FREEZER_RELATIVE_URLS'] = True
+Freezer(app).freeze()
+
+HTML('http://www.pycon.fr/2012/schedule/').write_pdf(
+ 'PyConFR_2012_schedule.pdf', stylesheets=['print.css'])
View
277 exyr/pages/2012/weasyprint-at-pyconfr/embedder.html
@@ -0,0 +1,277 @@
+<!DOCTYPE html>
+
+<meta charset="utf8">
+<title>...</title>
+
+<div id="slides">
+ <iframe allowfullscreen mozallowfullscreen webkitallowfullscreen></iframe>
+</div>
+<div id="controls">
+ <button title="prev" id="back" onclick="Dz.back()">&#9664;</button>
+ <button title="next" id="forward" onclick="Dz.forward()">&#9654;</button>
+ <div id="rightcontrols">
+ <input onchange="Dz.setCursor(this.value)" size="2" id="slideidx" value="0" />/<span id="slidecount">...</span>
+ <button title="Go fullscreen or open in a new window" id="fullscreen" onclick="Dz.goFullscreen()">&#8689;</button>
+ </div>
+</div>
+
+<style>
+ html { height: 100%;}
+ body {
+ margin: 0;
+ background-color: black;
+ height: 100%;
+ width: 100%;
+ }
+ #slides, #controls {
+ left: 0;
+ position: absolute;
+ right: 0;
+ }
+ #controls {
+ color: white;
+ font-family: monospace;
+ height: 30px;
+ line-height: 30px;
+ padding: 5px;
+ }
+ #slides {
+ bottom: 40px;
+ top: 0;
+ }
+ iframe {
+ border: none;
+ background-color: white;
+ height: 100%;
+ width: 100%;
+ }
+ #controls {
+ bottom: 0;
+ float: right;
+ font-size: 13px;
+ text-align: center;
+ }
+ #controls button[disabled] {color: #333;}
+ button {
+ background-color: transparent;
+ border: none;
+ cursor: pointer;
+ color: #bbb;
+ padding: 0;
+ font-size: 20px;
+ line-height: 100%;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -o-user-select: none;
+ user-select: none;
+ position: relative;
+ }
+ button:hover {
+ color: white;
+ }
+ button:active {
+ top: 1px;
+ left: 1px;
+ }
+ #slideidx {
+ border: none;
+ background-color: rgba(255, 255, 255, 0.2);
+ color: white;
+ text-align: center;
+ }
+ #rightcontrols * { vertical-align: middle; }
+ #rightcontrols {
+ bottom: 4px;
+ position: absolute;
+ top: 4px;
+ right: 10px;
+ }
+ #fullscreen {-moz-transform: scaleX(-1);-webkit-transform: scaleX(-1);-o-transform: scaleX(-1);-ms-transform: scaleX(-1);transform: scaleX(-1);}
+</style>
+
+<script>
+ var Dz = {
+ view: null,
+ url: null,
+ idx: 1,
+ count: null,
+ iframe: null
+ };
+
+ Dz.init = function() {
+ this.loadIframe();
+ }
+
+ Dz.onkeydown = function(aEvent) {
+ // Don't intercept keyboard shortcuts
+ if (aEvent.altKey
+ || aEvent.ctrlKey
+ || aEvent.metaKey
+ || aEvent.shiftKey) {
+ return;
+ }
+ if ( aEvent.keyCode == 37 // left arrow
+ || aEvent.keyCode == 38 // up arrow
+ || aEvent.keyCode == 33 // page up
+ ) {
+ aEvent.preventDefault();
+ this.back();
+ }
+ if ( aEvent.keyCode == 39 // right arrow
+ || aEvent.keyCode == 40 // down arrow
+ || aEvent.keyCode == 34 // page down
+ ) {
+ aEvent.preventDefault();
+ this.forward();
+ }
+ if (aEvent.keyCode == 35) { // end
+ aEvent.preventDefault();
+ this.goEnd();
+ }
+ if (aEvent.keyCode == 36) { // home
+ aEvent.preventDefault();
+ this.goStart();
+ }
+ if (aEvent.keyCode == 32) { // space
+ aEvent.preventDefault();
+ this.toggleContent();
+ }
+ if (aEvent.keyCode == 70) { // f
+ aEvent.preventDefault();
+ this.goFullscreen();
+ }
+ }
+
+ Dz.onmessage = function(aEvent) {
+ if (aEvent.source === this.view) {
+ var argv = aEvent.data.split(" "), argc = argv.length;
+ argv.forEach(function(e, i, a) { a[i] = decodeURIComponent(e) });
+ if (argv[0] === "CURSOR" && argc === 2) {
+ var cursor = argv[1].split(".");
+ this.idx = ~~cursor[0];
+ this.step = ~~cursor[1];
+ $("#slideidx").value = this.idx;
+ $("#back").disabled = this.idx == 1;
+ $("#forward").disabled = this.idx == this.count;
+ }
+ if (argv[0] === "REGISTERED" && argc === 3) {
+ $("#slidecount").innerHTML = this.count = argv[2];
+ document.title = argv[1];
+ }
+ }
+ }
+
+ /* Get url from hash or prompt and store it */
+
+ Dz.getUrl = function() {
+ var u = window.location.hash.split("#")[1];
+ if (!u) {
+ u = window.prompt("What is the URL of the slides?");
+ if (u) {
+ window.location.hash = u.split("#")[0];
+ return u;
+ }
+ u = "<style>body{background-color:white;color:black}</style>";
+ u += "<strong>ERROR:</strong> No URL specified.<br>";
+ u += "Try<em>: " + document.location + "#yourslides.html</em>";
+ u = "data:text/html," + encodeURIComponent(u);
+ }
+ return u;
+ }
+
+ Dz.loadIframe = function() {
+ this.iframe = $("iframe");
+ this.iframe.src = this.url = this.getUrl();
+ this.iframe.onload = function() {
+ Dz.view = this.contentWindow;
+ Dz.postMsg(Dz.view, "REGISTER");
+ }
+ }
+
+ Dz.toggleContent = function() {
+ this.postMsg(this.view, "TOGGLE_CONTENT");
+ }
+
+ Dz.onhashchange = function() {
+ this.loadIframe();
+ }
+
+ Dz.back = function() {
+ this.postMsg(this.view, "BACK");
+ }
+
+ Dz.forward = function() {
+ this.postMsg(this.view, "FORWARD");
+ }
+
+ Dz.goStart = function() {
+ this.postMsg(this.view, "START");
+ }
+
+ Dz.goEnd = function() {
+ this.postMsg(this.view, "END");
+ }
+
+ Dz.setCursor = function(aCursor) {
+ this.postMsg(this.view, "SET_CURSOR", aCursor);
+ }
+
+ Dz.goFullscreen = function() {
+ var requestFullscreen = this.iframe.requestFullscreen || this.iframe.requestFullScreen || this.iframe.mozRequestFullScreen || this.iframe.webkitRequestFullScreen;
+ if (requestFullscreen) {
+ requestFullscreen.apply(this.iframe);
+ } else {
+ window.open(this.url + "#" + this.idx, '', 'width=800,height=600,personalbar=0,toolbar=0,scrollbars=1,resizable=1');
+ }
+ }
+
+ Dz.postMsg = function(aWin, aMsg) { // [arg0, [arg1...]]
+ aMsg = [aMsg];
+ for (var i = 2; i < arguments.length; i++)
+ aMsg.push(encodeURIComponent(arguments[i]));
+ aWin.postMessage(aMsg.join(" "), "*");
+ }
+
+ function init() {
+ Dz.init();
+ window.onkeydown = Dz.onkeydown.bind(Dz);
+ window.onhashchange = Dz.loadIframe.bind(Dz);
+ window.onmessage = Dz.onmessage.bind(Dz);
+ }
+
+ window.onload = init;
+</script>
+
+
+<script> // Helpers
+ if (!Function.prototype.bind) {
+ Function.prototype.bind = function (oThis) {
+
+ // closest thing possible to the ECMAScript 5 internal IsCallable
+ // function
+ if (typeof this !== "function")
+ throw new TypeError(
+ "Function.prototype.bind - what is trying to be fBound is not callable"
+ );
+
+ var aArgs = Array.prototype.slice.call(arguments, 1),
+ fToBind = this,
+ fNOP = function () {},
+ fBound = function () {
+ return fToBind.apply( this instanceof fNOP ? this : oThis || window,
+ aArgs.concat(Array.prototype.slice.call(arguments)));
+ };
+
+ fNOP.prototype = this.prototype;
+ fBound.prototype = new fNOP();
+
+ return fBound;
+ };
+ }
+
+ var $ = (HTMLElement.prototype.$ = function(aQuery) {
+ return this.querySelector(aQuery);
+ }).bind(document);
+
+</script>
View
BIN  exyr/pages/2012/weasyprint-at-pyconfr/frozen_demo/foo.pdf
Binary file not shown
View
BIN  exyr/pages/2012/weasyprint-at-pyconfr/frozen_demo/foo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
24 exyr/pages/2012/weasyprint-at-pyconfr/frozen_demo/foo/graph_42:27.3:63_Lorem:ipsum:sit.svg
@@ -0,0 +1,24 @@
+
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="400" height="250" viewBox="0 0 160 100">
+ <style>
+ text { text-anchor: middle; font-size: 10px }
+ </style>
+
+ <rect x="10" y="33.0"
+ width="40" height="42.0"
+ fill="#0C3795" stroke="#333" rx="5" ry="5" />
+ <text x="30" y="90">Lorem</text>
+
+ <rect x="60" y="47.7"
+ width="40" height="27.3"
+ fill="#752641" stroke="#333" rx="5" ry="5" />
+ <text x="80" y="90">ipsum</text>
+
+ <rect x="110" y="12.0"
+ width="40" height="63.0"
+ fill="#E47F00" stroke="#333" rx="5" ry="5" />
+ <text x="130" y="90">sit</text>
+
+ </svg>
+
View
14 exyr/pages/2012/weasyprint-at-pyconfr/frozen_demo/foo/index.html
@@ -0,0 +1,14 @@
+
+ <!doctype html>
+ <title>Test document</title>
+ <link rel=stylesheet href="../static/style.css" />
+ <body>
+ <section>
+ <h1><a href="http://packages.python.org/Flask-WeasyPrint/">
+ Flask-WeasyPrint</a> demo</h1>
+ <nav>Get this document <a href="../foo.pdf">as PDF</a> or
+ <a href="../foo.png">as PNG</a>.</nav>
+ <p>This vector graph was generated dynamically:</p>
+ <img src="graph_42:27.3:63_Lorem:ipsum:sit.svg">
+ </section>
+
View
14 exyr/pages/2012/weasyprint-at-pyconfr/frozen_demo/index.html
@@ -0,0 +1,14 @@
+
+ <!doctype html>
+ <title>Test document</title>
+ <link rel=stylesheet href="../static/style.css" />
+ <body>
+ <section>
+ <h1><a href="http://packages.python.org/Flask-WeasyPrint/">
+ Flask-WeasyPrint</a> demo</h1>
+ <nav>Get this document <a href="../foo.pdf">as PDF</a> or
+ <a href="../foo.png">as PNG</a>.</nav>
+ <p>This vector graph was generated dynamically:</p>
+ <img src="graph_42:27.3:63_Lorem:ipsum:sit.svg">
+ </section>
+
View
10 exyr/pages/2012/weasyprint-at-pyconfr/frozen_demo/static/style.css
@@ -0,0 +1,10 @@
+
+ html { font-family: Fontin Sans, sans-serif }
+ section { width: 80%; margin: 2em auto }
+ a { color: inherit }
+ img { width: 100%; max-width: 600px; box-sizing: border-box;
+ border: 1px solid #888; }
+
+ /* Print-specific styles, ignored when rendering to screen: */
+ @page { size: A5; margin: 1cm }
+ @media print { nav { display: none } }
View
518 exyr/pages/2012/weasyprint-at-pyconfr/images/Architecture.svg
@@ -0,0 +1,518 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16cm"
+ height="25cm"
+ viewBox="6 -1 317 485"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.2 r9819"
+ sodipodi:docname="Architecture.svg"
+ inkscape:export-filename="/home/simon/INSA/5IF/PFE2/rapport/Architecture.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <metadata
+ id="metadata264">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs262" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1026"
+ id="namedview260"
+ showgrid="false"
+ inkscape:zoom="1.0656711"
+ inkscape:cx="325.94882"
+ inkscape:cy="671.89527"
+ inkscape:window-x="0"
+ inkscape:window-y="26"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <polyline
+ id="polyline164"
+ points="126.032,179.5 160.257,179.5 160.257,53 174.669,53 "
+ style="fill:none;stroke:#000000;stroke-width:2"
+ transform="matrix(0.99870841,0,0,1,0.12224053,0)" />
+ <polygon
+ id="polygon168"
+ points="182.169,53 172.169,58 174.669,53 172.169,48 "
+ style="fill:none;stroke:#000000;stroke-width:2"
+ transform="matrix(0.99870841,0,0,1,0.12224053,0)" />
+ <polygon
+ id="polygon6"
+ points="139.93,73 7.806,73 22.3648,33 154.488,33 "
+ style="fill:#ffffff" />
+ <polygon
+ id="polygon8"
+ points="139.93,73 7.806,73 22.3648,33 154.488,33 "
+ style="fill:#8ae234;stroke:#376d04;stroke-width:2;stroke-opacity:1" />
+ <text
+ id="text10"
+ y="56.900002"
+ x="81.147202"
+ style="font-size:12.80000019px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan12"
+ y="56.900002"
+ x="81.147202">HTML document</tspan>
+ </text>
+ <polygon
+ id="polygon16"
+ points="307.788,73 177.764,73 192.323,33 322.346,33 "
+ style="fill:#ffffff" />
+ <polygon
+ id="polygon18"
+ points="307.788,73 177.764,73 192.323,33 322.346,33 "
+ style="fill:#8ae234;stroke:#376d04;stroke-width:2;stroke-opacity:1" />
+ <text
+ id="text20"
+ y="56.900002"
+ x="250.05499"
+ style="font-size:12.80000019px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan22"
+ y="56.900002"
+ x="250.05499">CSS stylesheets</tspan>
+ </text>
+ <polygon
+ id="polygon26"
+ points="118.18,199.5 29.556,199.5 44.1148,159.5 132.738,159.5 "
+ style="fill:#ffffff" />
+ <polygon
+ id="polygon28"
+ points="118.18,199.5 29.556,199.5 44.1148,159.5 132.738,159.5 "
+ style="fill:#8ae234;stroke:#376d04;stroke-width:2;stroke-opacity:1" />
+ <text
+ id="text30"
+ y="183.39999"
+ x="81.147202"
+ style="font-size:12.80000019px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan32"
+ y="183.39999"
+ x="81.147202">DOM tree</tspan>
+ </text>
+ <rect
+ id="rect36"
+ height="38"
+ width="102.75"
+ y="97.25"
+ x="29.7722"
+ style="fill:#ffffff" />
+ <rect
+ id="rect38"
+ height="38"
+ width="102.75"
+ y="97.25"
+ x="29.7722"
+ style="fill:#729fcf;stroke:#204a87;stroke-width:2" />
+ <text
+ id="text40"
+ y="120.15"
+ x="81.147202"
+ style="font-size:12.80000019px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan42"
+ y="120.15"
+ x="81.147202">HTML parser</tspan>
+ </text>
+ <rect
+ id="rect46"
+ height="38"
+ width="92.349998"
+ y="97.25"
+ x="203.88"
+ style="fill:#ffffff" />
+ <rect
+ id="rect48"
+ height="38"
+ width="92.349998"
+ y="97.25"
+ x="203.88"
+ style="fill:#729fcf;stroke:#204a87;stroke-width:2" />
+ <text
+ id="text50"
+ y="120.15"
+ x="250.05499"
+ style="font-size:12.80000019px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan52"
+ y="120.15"
+ x="250.05499">CSS parser</tspan>
+ </text>
+ <polygon
+ id="polygon56"
+ points="290.901,197.5 195.378,197.5 209.209,159.5 304.732,159.5 "
+ style="fill:#ffffff" />
+ <polygon
+ id="polygon58"
+ points="290.901,197.5 195.378,197.5 209.209,159.5 304.732,159.5 "
+ style="fill:#8ae234;stroke:#376d04;stroke-width:2;stroke-opacity:1" />
+ <text
+ id="text60"
+ y="182.39999"
+ x="250.05499"
+ style="font-size:12.80000019px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan62"
+ y="182.39999"
+ x="250.05499">Style rules</tspan>
+ </text>
+ <rect
+ id="rect66"
+ height="38"
+ width="76.400002"
+ y="223.75"
+ x="42.947201"
+ style="fill:#ffffff" />
+ <rect
+ id="rect68"
+ height="38"
+ width="76.400002"
+ y="223.75"
+ x="42.947201"
+ style="fill:#729fcf;stroke:#204a87;stroke-width:2" />
+ <text
+ id="text70"
+ y="246.64999"
+ x="81.147202"
+ style="font-size:12.80000019px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan72"
+ y="246.64999"
+ x="81.147202">Cascade</tspan>
+ </text>
+ <polygon
+ id="polygon76"
+ points="125.505,326 22.231,326 36.7898,286 140.063,286 "
+ style="fill:#ffffff" />
+ <polygon
+ id="polygon78"
+ points="125.505,326 22.231,326 36.7898,286 140.063,286 "
+ style="fill:#8ae234;stroke:#376d04;stroke-width:2;stroke-opacity:1" />
+ <text
+ id="text80"
+ y="309.89999"
+ x="81.147202"
+ style="font-size:12.80000019px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan82"
+ y="309.89999"
+ x="81.147202">Render tree</tspan>
+ </text>
+ <rect
+ id="rect86"
+ height="38"
+ width="65.550003"
+ y="287"
+ x="217.28"
+ style="fill:#ffffff" />
+ <rect
+ id="rect88"
+ height="38"
+ width="65.550003"
+ y="287"
+ x="217.28"
+ style="fill:#729fcf;stroke:#204a87;stroke-width:2" />
+ <text
+ id="text90"
+ y="309.89999"
+ x="250.05499"
+ style="font-size:12.80000019px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan92"
+ y="309.89999"
+ x="250.05499">Layout</tspan>
+ </text>
+ <rect
+ id="rect96"
+ height="38"
+ width="75.199997"
+ y="350.25"
+ x="43.547199"
+ style="fill:#ffffff" />
+ <rect
+ id="rect98"
+ height="38"
+ width="75.199997"
+ y="350.25"
+ x="43.547199"
+ style="fill:#729fcf;stroke:#204a87;stroke-width:2" />
+ <text
+ id="text100"
+ y="373.14999"
+ x="81.147202"
+ style="font-size:12.80000019px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan102"
+ y="373.14999"
+ x="81.147202">Drawing</tspan>
+ </text>
+ <polygon
+ id="polygon106"
+ points="106.463,452.5 41.273,452.5 55.8318,412.5 121.021,412.5 "
+ style="fill:#ffffff" />
+ <polygon
+ id="polygon108"
+ points="106.463,452.5 41.273,452.5 55.8318,412.5 121.021,412.5 "
+ style="fill:#8ae234;stroke:#376d04;stroke-width:2;stroke-opacity:1" />
+ <text
+ id="text110"
+ y="436.39999"
+ x="81.147202"
+ style="font-size:12.80000019px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan112"
+ y="436.39999"
+ x="81.147202">PDF</tspan>
+ </text>
+ <polyline
+ id="polyline116"
+ points="81.1472,74.0051 81.1472,74.0051 81.1472,86.5042 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon118"
+ points="81.1472,86.5042 86.1472,84.0042 81.1472,94.0042 76.1472,84.0042 "
+ style="fill:#000000" />
+ <polygon
+ id="polygon120"
+ points="81.1472,86.5042 86.1472,84.0042 81.1472,94.0042 76.1472,84.0042 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polyline
+ id="polyline124"
+ points="250.055,74.0051 250.055,74.0051 250.055,86.5042 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon126"
+ points="250.055,86.5042 255.055,84.0042 250.055,94.0042 245.055,84.0042 "
+ style="fill:#000000" />
+ <polygon
+ id="polygon128"
+ points="250.055,86.5042 255.055,84.0042 250.055,94.0042 245.055,84.0042 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polyline
+ id="polyline132"
+ points="81.1472,136.26 81.1472,136.26 81.1472,148.759 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon134"
+ points="81.1472,148.759 86.1472,146.259 81.1472,156.259 76.1472,146.259 "
+ style="fill:#000000" />
+ <polygon
+ id="polygon136"
+ points="81.1472,148.759 86.1472,146.259 81.1472,156.259 76.1472,146.259 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polyline
+ id="polyline140"
+ points="250.055,136.26 250.055,136.26 250.055,148.754 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon142"
+ points="250.055,148.754 255.055,146.254 250.055,156.254 245.055,146.254 "
+ style="fill:#000000" />
+ <polygon
+ id="polygon144"
+ points="250.055,148.754 255.055,146.254 250.055,156.254 245.055,146.254 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polyline
+ id="polyline148"
+ points="81.1472,200.505 81.1472,200.505 81.1472,213.004 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon150"
+ points="81.1472,213.004 86.1472,210.504 81.1472,220.504 76.1472,210.504 "
+ style="fill:#000000" />
+ <polygon
+ id="polygon152"
+ points="81.1472,213.004 86.1472,210.504 81.1472,220.504 76.1472,210.504 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polyline
+ id="polyline156"
+ points="243.14,197.5 243.14,242.75 129.083,242.75 "
+ style="fill:none;stroke:#000000;stroke-width:2"
+ transform="matrix(1.0569043,0,0,0.9802973,-6.4473643,4.78283)" />
+ <polygon
+ id="polygon158"
+ points="129.083,242.75 131.583,247.75 121.583,242.75 131.583,237.75 "
+ style="fill:#000000" />
+ <polygon
+ id="polygon160"
+ points="131.583,247.75 121.583,242.75 131.583,237.75 129.083,242.75 "
+ style="fill:none;stroke:#000000;stroke-width:2"
+ transform="matrix(0.99212662,0,0,1,1.9143334,0)" />
+ <polygon
+ id="polygon166"
+ points="174.669,53 172.169,48 182.169,53 172.169,58 "
+ style="fill:#000000" />
+ <polyline
+ id="polyline172"
+ points="144.413,306 206.536,306 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon174"
+ points="144.413,301 134.413,306 144.413,311 "
+ style="fill:#000000"
+ transform="translate(1.7085879,0)" />
+ <polygon
+ id="polygon176"
+ points="144.413,301 134.413,306 144.413,311 "
+ style="fill:none;stroke:#000000;stroke-width:2"
+ transform="translate(1.7085879,0)" />
+ <polygon
+ id="polygon178"
+ points="206.536,306 204.036,301 214.036,306 204.036,311 "
+ style="fill:#000000" />
+ <polygon
+ id="polygon180"
+ points="206.536,306 204.036,301 214.036,306 204.036,311 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polyline
+ id="polyline184"
+ points="81.1472,262.76 81.1472,262.76 81.1472,275.259 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon186"
+ points="81.1472,275.259 86.1472,272.759 81.1472,282.759 76.1472,272.759 "
+ style="fill:#000000" />
+ <polygon
+ id="polygon188"
+ points="81.1472,275.259 86.1472,272.759 81.1472,282.759 76.1472,272.759 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polyline
+ id="polyline192"
+ points="81.1472,327.005 81.1472,327.005 81.1472,339.504 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon194"
+ points="81.1472,339.504 86.1472,337.004 81.1472,347.004 76.1472,337.004 "
+ style="fill:#000000" />
+ <polygon
+ id="polygon196"
+ points="81.1472,339.504 86.1472,337.004 81.1472,347.004 76.1472,337.004 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polyline
+ id="polyline200"
+ points="81.1472,453.505 81.1472,467.174 81.1628,467.174 81.1628,471.108 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon202"
+ points="81.1628,471.108 86.1628,468.608 81.1628,478.608 76.1628,468.608 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polyline
+ id="polyline206"
+ points="81.1722,0.0859376 81.1722,16.0404 81.1472,16.0404 81.1472,22.2588 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon208"
+ points="81.1472,22.2588 86.1472,19.7588 81.1472,29.7588 76.1472,19.7588 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polyline
+ id="polyline212"
+ points="250.069,0.0625 250.069,16.0287 250.055,16.0287 250.055,22.2588 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon214"
+ points="250.055,22.2588 255.055,19.7588 250.055,29.7588 245.055,19.7588 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon218"
+ points="281.088,389.25 204.464,389.25 219.023,349.25 295.646,349.25 "
+ style="fill:#ffffff" />
+ <polygon
+ id="polygon220"
+ points="281.088,389.25 204.464,389.25 219.023,349.25 295.646,349.25 "
+ style="fill:#8ae234;stroke:#376d04;stroke-width:2;stroke-opacity:1" />
+ <text
+ id="text222"
+ y="373.14999"
+ x="250.05499"
+ style="font-size:12.79979992px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan224"
+ y="373.14999"
+ x="250.05499">Surface</tspan>
+ </text>
+ <rect
+ id="rect228"
+ height="38"
+ width="67.699997"
+ y="413.5"
+ x="216.205"
+ style="fill:#ffffff" />
+ <rect
+ id="rect230"
+ height="38"
+ width="67.699997"
+ y="413.5"
+ x="216.205"
+ style="fill:#729fcf;stroke:#204a87;stroke-width:2" />
+ <text
+ id="text232"
+ y="436.39999"
+ x="250.05499"
+ style="font-size:12.79979992px;font-style:normal;font-weight:normal;text-anchor:middle;fill:#000000;font-family:sanserif">
+ <tspan
+ id="tspan234"
+ y="436.39999"
+ x="250.05499">Writing</tspan>
+ </text>
+ <polyline
+ id="polyline238"
+ points="119.757,369.25 119.757,369.25 201.366,369.25 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon240"
+ points="201.366,369.25 198.866,364.25 208.866,369.25 198.866,374.25 "
+ style="fill:#000000" />
+ <polygon
+ id="polygon242"
+ points="201.366,369.25 198.866,364.25 208.866,369.25 198.866,374.25 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polyline
+ id="polyline246"
+ points="250.055,390.255 250.055,390.255 250.055,402.754 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon248"
+ points="250.055,402.754 255.055,400.254 250.055,410.254 245.055,400.254 "
+ style="fill:#000000" />
+ <polygon
+ id="polygon250"
+ points="250.055,402.754 255.055,400.254 250.055,410.254 245.055,400.254 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polyline
+ id="polyline254"
+ points="215.197,432.5 215.197,432.5 124.113,432.5 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+ <polygon
+ id="polygon256"
+ points="124.113,432.5 126.613,437.5 116.613,432.5 126.613,427.5 "
+ style="fill:#000000" />
+ <polygon
+ id="polygon258"
+ points="124.113,432.5 126.613,437.5 116.613,432.5 126.613,427.5 "
+ style="fill:none;stroke:#000000;stroke-width:2" />
+</svg>
View
BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/GTK.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/RightMarginBoxes.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/acid2-small.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/box_model.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/cairo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
9 exyr/pages/2012/weasyprint-at-pyconfr/images/kozea-logo.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<svg id="logo" xmlns="http://www.w3.org/2000/svg" width="240mm" height="80mm" viewBox="0 0 150 50" fill="#383a47" fill-rule="evenodd">
+ <path id="k" d="M 23,0 L 27,6 L 11,21 L 38,50 L 32,50 L 5,21 L 5,0 L 0,0 L 0,50 L 5,50 L 5,21"/>
+ <path id="o" d="M 54,33 C 62,25 54,12 33,13 C 32,34 46,42 54,33 Z M 43,6 C 19,6 22,40 44,40 C 66,40 66,6 43,6 Z" fill="#5c8182"/>
+ <circle id="dot" cx="46" cy="26" r="7" fill="#fd9105"/>
+ <path id="z" d="M 59,5 L 83,4 L 54,50 L 90,50 L 85,45 L 64,46 L 90,0 L 54,0 Z"/>
+ <path id="e" d="M 112,26 C 110,26 109,26 107,26 C 100,26 92,28 92,37 C 92,46 114,49 121,37 L 123,44 C 119,47 116,50 106,50 C 95,50 88,44 88,36 C 88,26 94,25 100,23 C 95,22 90,18 90,11 C 90,4 98,0 105,0 C 110,0 111,1 117,3 L 115,8 C 104,2 95,5 94,11 C 94,17 101,24 109,19 Z"/>
+ <path id="a" d="M 145,50 L 150,50 L 150,13 C 150,5 143,0 135,0 C 131,0 127,0 122,3 L 124,8 C 128,5 131,4 135,4 C 141,4 145,9 145,16 L 135,21 C 124,26 118,29 119,37 C 120,46 126,50 132,50 C 135,50 138,49 140,46 L 142,41 C 130,48 125,45 124,38 C 122,30 128,30 135,26 L 145,21 Z"/>
+</svg>
View
BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/lxml.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/python.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  exyr/pages/2012/weasyprint-at-pyconfr/images/weasyprint-logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
358 exyr/pages/2012/weasyprint-at-pyconfr/onstage.html
@@ -0,0 +1,358 @@
+<!DOCTYPE html>
+
+<meta charset="utf8">
+<title>DZSlides</title>
+
+<div id="present">
+ <iframe></iframe>
+</div>
+
+<div id="future">
+ <iframe></iframe>
+</div>
+
+<div id="slideidx" onclick="Dz.setCursor(prompt('Go to slide...','1'));">?</div>
+<div id="nextslideidx">?</div>
+
+<div id="notes">
+ <p id="content"></p>
+</div>
+
+<div id="slidecount">?</div>
+<button id="popup-button" onclick="Dz.popup()">Pop-up</button>
+
+<div id="time">
+ <span id="hours">00</span>:<span id="minutes">00</span>:<span id="seconds">00</span>
+</div>
+
+<style>
+ html, body {
+ height: 100%;
+ color: white;
+ }
+
+ body {
+ font-family: sans-serif;
+ overflow: hidden;
+ }
+
+ #present, #future {
+ bottom: 234px;
+ position: absolute;
+ top: 0;
+ z-index: 5;
+ }
+
+ #present {
+ left: 0;
+ right: 50%;
+ border-right: 4px solid #555;
+ }
+
+ #future {
+ left: 50%;
+ right: 0;
+ border-left: 4px solid #555;
+ }
+
+ #notes {
+ background: #EEE;
+ border-top: 8px solid #555;
+ bottom: 0;
+ color: #444;
+ font-size: 30px;
+ height: 226px;
+ left: 0;
+ padding: 0 250px 0 20px;
+ position: absolute;
+ right: 0;
+ overflow: auto;
+ }
+
+ #time {
+ background: #888;
+ border-top-left-radius: 10px;
+ border-top-right-radius: 10px;
+ bottom: 0;
+ font-size: 40px;
+ font-weight: bold;
+ height: 52px;
+ line-height: 52px;
+ right: 30px;
+ position: absolute;
+ text-align: center;
+ width: 200px;
+ }
+
+ iframe {
+ border: none;
+ height: 100%;
+ pointer-events: none;
+ width: 100%;
+ }
+
+ #slideidx,
+ #nextslideidx,
+ #slidecount {
+ background: #888;
+ font-size: 40px;
+ font-weight: bold;
+ height: 52px;
+ line-height: 52px;
+ margin: 0;
+ position: absolute;
+ text-align: center;
+ z-index: 10;
+ }
+
+ #slideidx,
+ #nextslideidx {
+ border-bottom: 4px solid #555;
+ bottom: 230px;
+ padding: 0 10px;
+ }
+
+ #slideidx {
+ border-right: 4px solid #555;
+ border-top-left-radius: 10px;
+ cursor: pointer;
+ right: 50%;
+ }
+
+ #nextslideidx {
+ border-left: 4px solid #555;
+ border-top-right-radius: 10px;
+ left: 50%;
+ }
+
+ #slidecount {
+ border-bottom-left-radius: 10px;
+ border-bottom-right-radius: 10px;
+ border-top: 4px solid #555;
+ bottom: 174px;
+ width: 200px;
+ right: 30px;
+ }
+
+ #popup-button {
+ bottom: 88px;
+ background: #888;
+ border: none;
+ border-radius: 10px;
+ color: #FFF;
+ cursor: pointer;
+ height: 52px;
+ font-size: 30px;
+ font-weight: bold;
+ position: absolute;
+ right: 30px;
+ width: 200px;
+ z-index: 10;
+ }
+</style>
+
+<script>
+ var Dz = {
+ views: {},
+ notes: null,
+ url: null,
+ idx: 1
+ };
+
+ Dz.init = function() {
+ this.startClock();
+ this.loadIframes();
+ }
+
+ Dz.onkeydown = function(aEvent) {
+ // Don't intercept keyboard shortcuts
+ if (aEvent.altKey
+ || aEvent.ctrlKey
+ || aEvent.metaKey
+ || aEvent.shiftKey) {
+ return;
+ }
+ if ( aEvent.keyCode == 37 // left arrow
+ || aEvent.keyCode == 38 // up arrow
+ || aEvent.keyCode == 33 // page up
+ ) {
+ aEvent.preventDefault();
+ this.back();
+ }
+ if ( aEvent.keyCode == 39 // right arrow
+ || aEvent.keyCode == 40 // down arrow
+ || aEvent.keyCode == 34 // page down
+ ) {
+ aEvent.preventDefault();
+ this.forward();
+ }
+ if (aEvent.keyCode == 35) { // end
+ aEvent.preventDefault();
+ this.goEnd();
+ }
+ if (aEvent.keyCode == 36) { // home
+ aEvent.preventDefault();
+ this.goStart();
+ }
+ if (aEvent.keyCode == 32) { // space
+ aEvent.preventDefault();
+ this.toggleContent();
+ }
+ }
+
+ Dz.onmessage = function(aEvent) {
+ var argv = aEvent.data.split(" "), argc = argv.length;
+ argv.forEach(function(e, i, a) { a[i] = decodeURIComponent(e) });
+ if (argv[0] === "CURSOR" && argc === 2) {
+ if (aEvent.source === this.views.present) {
+ var cursor = argv[1].split(".");
+ this.postMsg(this.views.present, "GET_NOTES");
+ this.idx = ~~cursor[0];
+ this.step = ~~cursor[1];
+ $("#slideidx").innerHTML = argv[1];
+ this.postMsg(this.views.future, "SET_CURSOR", this.idx + "." + (this.step + 1));
+ if (this.views.remote)
+ this.postMsg(this.views.remote, "SET_CURSOR", argv[1]);
+ } else {
+ $("#nextslideidx").innerHTML = +argv[1] < 0 ? "END" : argv[1];
+ }
+ }
+ if (aEvent.source === this.views.present) {
+ if (argv[0] === "NOTES" && argc === 2)
+ $("#notes > #content").innerHTML = this.notes = argv[1];
+ if (argv[0] === "REGISTERED" && argc === 3)
+ $("#slidecount").innerHTML = argv[2];
+ }
+ }
+
+ /* Get url from hash or prompt and store it */
+
+ Dz.getUrl = function() {
+ var u = window.location.hash.split("#")[1];
+ if (!u) {
+ u = window.prompt("What is the URL of the slides?");
+ if (u) {
+ window.location.hash = u.split("#")[0];
+ return u;
+ }
+ u = "<style>body{background-color:white;color:black}</style>";
+ u += "<strong>ERROR:</strong> No URL specified.<br>";
+ u += "Try<em>: " + document.location + "#yourslides.html</em>";
+ u = "data:text/html," + encodeURIComponent(u);
+ }
+ return u;
+ }
+
+ Dz.loadIframes = function() {
+ var present = $("#present iframe");
+ var future = $("#future iframe");
+ this.url = this.getUrl();
+ present.src = future.src = this.url + '?autoplay=0';
+ present.onload = future.onload = function() {
+ var id = this.parentNode.id;
+ Dz.views[id] = this.contentWindow;
+ if (Dz.views.present && Dz.views.future) {
+ Dz.postMsg(Dz.views.present, "REGISTER");
+ Dz.postMsg(Dz.views.future, "REGISTER");
+ }
+ }
+ }
+
+ Dz.toggleContent = function() {
+ if (this.views.remote)
+ this.postMsg(this.views.remote, "TOGGLE_CONTENT");
+ }
+
+ Dz.onhashchange = function() {
+ this.loadIframe();
+ }
+
+ Dz.back = function() {
+ this.postMsg(this.views.present, "BACK");
+ }
+
+ Dz.forward = function() {
+ this.postMsg(this.views.present, "FORWARD");
+ }
+
+ Dz.goStart = function() {
+ this.postMsg(this.views.present, "START");
+ }
+
+ Dz.goEnd = function() {
+ this.postMsg(this.views.present, "END");
+ }
+
+ Dz.setCursor = function(aCursor) {
+ this.postMsg(this.views.present, "SET_CURSOR", aCursor);
+ }
+
+ Dz.popup = function() {
+ this.views.remote = window.open(this.url + "#" + this.idx, 'slides', 'width=800,height=600,personalbar=0,toolbar=0,scrollbars=1,resizable=1');
+ }
+
+ Dz.postMsg = function(aWin, aMsg) { // [arg0, [arg1...]]
+ aMsg = [aMsg];
+ for (var i = 2; i < arguments.length; i++)
+ aMsg.push(encodeURIComponent(arguments[i]));
+ aWin.postMessage(aMsg.join(" "), "*");
+ }
+
+ Dz.startClock = function() {
+ var addZero = function(num) {
+ return num < 10 ? '0' + num : num;
+ }
+ setInterval(function() {
+ var now = new Date();
+ $("#hours").innerHTML = addZero(now.getHours());
+ $("#minutes").innerHTML = addZero(now.getMinutes());
+ $("#seconds").innerHTML = addZero(now.getSeconds());
+ }, 1000);
+ }
+
+ function init() {
+ Dz.init();
+ window.onkeydown = Dz.onkeydown.bind(Dz);
+ window.onhashchange = Dz.loadIframes.bind(Dz);
+ window.onmessage = Dz.onmessage.bind(Dz);
+ }
+
+ window.onload = init;
+</script>
+
+
+<script> // Helpers
+ if (!Function.prototype.bind) {
+ Function.prototype.bind = function (oThis) {
+
+ // closest thing possible to the ECMAScript 5 internal IsCallable
+ // function
+ if (typeof this !== "function")
+ throw new TypeError(
+ "Function.prototype.bind - what is trying to be fBound is not callable"
+ );
+
+ var aArgs = Array.prototype.slice.call(arguments, 1),
+ fToBind = this,
+ fNOP = function () {},
+ fBound = function () {
+ return fToBind.apply( this instanceof fNOP ? this : oThis || window,
+ aArgs.concat(Array.prototype.slice.call(arguments)));
+ };
+
+ fNOP.prototype = this.prototype;
+ fBound.prototype = new fNOP();
+
+ return fBound;
+ };
+ }
+
+ var $ = (HTMLElement.prototype.$ = function(aQuery) {
+ return this.querySelector(aQuery);
+ }).bind(document);
+
+ var $$ = (HTMLElement.prototype.$$ = function(aQuery) {
+ return this.querySelectorAll(aQuery);
+ }).bind(document);
+
+</script>
View
8 exyr/pages/2012/weasyprint-at-pyconfr/outline
@@ -0,0 +1,8 @@
+
+WeasyPrint est un outil open-source en Python qui convertit des documents web (HTML, CSS, SVG, …) en PDF. Il n’est pas basé sur WebKit ou Gecko mais a son propre moteur conçu pour la pagination.
+
+En plus d’une introduction au projet (objectifs, comparaison aux alternatives) seront présentés :
+
+Point de vue utilisateur : CSS pour le print (@media, centimètres vs pixels, contrôle des sauts de page, …); intégration de WeasyPrint avec d’autres outils tels que Flask ou docutils.
+
+De l’autre côté du miroir : vue générale du fonctionnement interne (parsing, cascade, modèle de boites, retours à la ligne et sauts de page, dessin); comment contribuer au projet.
View
100 exyr/pages/2012/weasyprint-at-pyconfr/prism.css
@@ -0,0 +1,100 @@
+/**
+ * prism.js default theme for JavaScript, CSS and HTML
+ * Based on dabblet (http://dabblet.com)
+ * @author Lea Verou
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+ color: black;
+ text-shadow: 0 1px white;
+ font-family: Consolas, Monaco, 'Andale Mono', monospace;
+ direction: ltr;
+ text-align: left;
+ white-space: pre;
+ word-spacing: normal;
+
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+
+ -webkit-hyphens: none;
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ hyphens: none;
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+ padding: 1em;
+ margin: .5em 0;
+ overflow: auto;
+}
+
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+ background: #f5f2f0;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+ padding: .1em;
+ border-radius: .3em;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+ color: slategray;
+}
+
+.token.punctuation {
+ color: #999;
+}
+
+.namespace {
+ opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number {
+ color: #905;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string {
+ color: #690;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+ color: #a67f59;
+ background: hsla(0,0%,100%,.5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+ color: #07a;
+}
+
+
+.token.regex,
+.token.important {
+ color: #e90;
+}
+
+.token.important {
+ font-weight: bold;
+}
+
+.token.entity {
+ cursor: help;
+}
View
7 exyr/pages/2012/weasyprint-at-pyconfr/prism.js
@@ -0,0 +1,7 @@
+/**
+ * Prism: Lightweight, robust, elegant syntax highlighting
+ * MIT license http://www.opensource.org/licenses/mit-license.php/
+ * @author Lea Verou http://lea.verou.me
+ */(function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={languages:{insertBefore:function(e,n,r,i){i=i||t.languages;var s=i[e],o={};for(var u in s)if(s.hasOwnProperty(u)){if(u==n)for(var a in r)r.hasOwnProperty(a)&&(o[a]=r[a]);o[u]=s[u]}return i[e]=o},DFS:function(e,n){for(var r in e){n.call(e,r,e[r]);Object.prototype.toString.call(e)==="[object Object]"&&t.languages.DFS(e[r],n)}}},highlightAll:function(e,n){var r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');for(var i=0,s;s=r[i++];)t.highlightElement(s,e===!0,n)},highlightElement:function(r,i,s){var o,u,a=r;while(a&&!e.test(a.className))a=a.parentNode;if(a){o=(a.className.match(e)||[,""])[1];u=t.languages[o]}if(!u)return;r.className=r.className.replace(e,"").replace(/\s+/g," ")+" language-"+o;a=r.parentNode;/pre/i.test(a.nodeName)&&(a.className=a.className.replace(e,"").replace(/\s+/g," ")+" language-"+o);var f=r.textContent.trim();if(!f)return;f=f.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\u00a0/g," ");var l={element:r,language:o,grammar:u,code:f};t.hooks.run("before-highlight",l);if(i&&self.Worker){var c=new Worker(t.filename);c.onmessage=function(e){l.highlightedCode=n.stringify(JSON.parse(e.data));l.element.innerHTML=l.highlightedCode;s&&s.call(l.element);t.hooks.run("after-highlight",l)};c.postMessage(JSON.stringify({language:l.language,code:l.code}))}else{l.highlightedCode=t.highlight(l.code,l.grammar);l.element.innerHTML=l.highlightedCode;s&&s.call(r);t.hooks.run("after-highlight",l)}},highlight:function(e,r){return n.stringify(t.tokenize(e,r))},tokenize:function(e,n){var r=t.Token,i=[e],s=n.rest;if(s){for(var o in s)n[o]=s[o];delete n.rest}e:for(var o in n){if(!n.hasOwnProperty(o)||!n[o])continue;var u=n[o],a=u.inside,f=!!u.lookbehind||0;u=u.pattern||u;for(var l=0;l<i.length;l++){var c=i[l];if(i.length>e.length)break e;if(c instanceof r)continue;u.lastIndex=0;var h=u.exec(c);if(h){f&&(f=h[1].length);var p=h.index-1+f,h=h[0].slice(f),d=h.length,v=p+d,m=c.slice(0,p+1),g=c.slice(v+1),y=[l,1];m&&y.push(m);var b=new r(o,a?t.tokenize(h,a):h);y.push(b);g&&y.push(g);Array.prototype.splice.apply(i,y)}}}return i},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[];r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(!r||!r.length)return;for(var i=0,s;s=r[i++];)s(n)}}},n=t.Token=function(e,t){this.type=e;this.content=t};n.stringify=function(e){if(typeof e=="string")return e;if(Object.prototype.toString.call(e)=="[object Array]"){for(var r=0;r<e.length;r++)e[r]=n.stringify(e[r]);return e.join("")}var i={type:e.type,content:n.stringify(e.content),tag:"span",classes:["token",e.type],attributes:{}};i.type=="comment"&&(i.attributes.spellcheck="true");t.hooks.run("wrap",i);var s="";for(var o in i.attributes)s+=o+'="'+(i.attributes[o]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+s+">"+i.content+"</"+i.tag+">"};if(!self.document){self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,i=n.code;self.postMessage(JSON.stringify(t.tokenize(i,t.languages[r])));self.close()},!1);return}var r=document.getElementsByTagName("script");r=r[r.length-1];if(r){t.filename=r.src;document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)}})();
+Prism.languages.markup={comment:/&lt;!--[\w\W]*?--(&gt;|&gt;)/g,prolog:/&lt;\?.+?\?&gt;/,doctype:/&lt;!DOCTYPE.+?&gt;/,cdata:/&lt;!\[CDATA\[[\w\W]+?]]&gt;/i,tag:{pattern:/&lt;\/?[\w:-]+\s*[\w\W]*?&gt;/gi,inside:{tag:{pattern:/^&lt;\/?[\w:-]+/i,inside:{punctuation:/^&lt;\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(('|")[\w\W]*?(\2)|[^\s>]+)/gi,inside:{punctuation:/=/g}},punctuation:/\/?&gt;/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/&amp;#?[\da-z]{1,8};/gi};Prism.hooks.add("wrap",function(e){e.type==="entity"&&(e.attributes.title=e.content.replace(/&amp;/,"&"))});
+Prism.languages.css={comment:/\/\*[\w\W]*?\*\//g,atrule:/@[\w-]+?(\s+[^;{]+)?(?=\s*{|\s*;)/gi,url:/url\((["']?).*?\1\)/gi,selector:/[^\{\}\s][^\{\}]*(?=\s*\{)/g,property:/(\b|\B)[a-z-]+(?=\s*:)/ig,string:/("|')(\\?.)*?\1/g,important:/\B!important\b/gi,ignore:/&(lt|gt|amp);/gi,punctuation:/[\{\};:]/g};Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{style:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,inside:{tag:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css}}});
View
934 exyr/pages/2012/weasyprint-at-pyconfr/slides.html
@@ -0,0 +1,934 @@
+<!DOCTYPE html>
+
+<meta charset="utf-8">
+<title>WeasyPrint</title>
+
+<section>
+ <h1 style="margin-bottom: 0"><img alt=WeasyPrint
+ src=images/weasyprint-logo.png style="width: 70%"></h1>
+ <p style="text-align: center; margin-top: 0">CSS → PDF</p>
+ <footer>
+ Simon Sapin, <img alt=Kozea src=images/kozea-logo.svg
+ style="height: 1.5em; margin-left: .5em"><br>
+ PyConFR 2012
+ </footer>
+ <details>
+ New CSS engine (like WebKit, Gecko), renders PDF<br>
+ Been at Kozea Working on it for ~1.5 years now.
+ </details>
+</section>
+
+<section>
+ <h2>PDF</h2>
+ <p>Hi-Fi documents for printing, archiving, …</p>
+ <p>How to generate them dynamically?</p>
+ <details>
+ Best document format for many use cases<br>
+ Invoices, expert reports, business cards, …
+ </details>
+</section>
+
+<section>
+ <h2>Flask</h2>
+ <pre><code
+><span style="color: #888">from flask import Flask
+app = Flask(__name__)</span>
+
+@app.route("/")
+def hello():
+ return "Hello World!"
+
+<span style="color: #888">if __name__ == "__main__":
+ app.run()</span></code></pre>
+ <details>
+ You know <a href="http://flask.pocoo.org/">Flask</a>.
+ Nice micro-framework for making Python web apps.
+ Tools to generate beautiful HTML/CSS/SVG documents.
+ What about PDF?
+ </details>
+</section>
+
+<section>
+ <h2>Flask-WeasyPrint</h2>
+ <pre><code
+><span style="color: #888">from flask import url_for</span>
+from flask_weasyprint import render_pdf
+
+@app.route("/hello.pdf")
+def hello_pdf():
+ return render_pdf(url_for('hello'))</code></pre>
+ <p><a href="frozen_demo/foo/index.html">Demo</a></p>
+ <details>
+ Once you have that, PDF is easy.<br>
+ WeasyPrint: like the <em>print</em> function of your browser, but with
+ a layout engine designed for print.<br>
+ </details>
+</section>
+
+<section>
+ <h2>Fetching a dynamic image: data flow</h2>
+ <dl>
+ <dt>Plain WeasyPrint</dt>
+ <dd>WeasyPrint engine → HTTP client → network
+ → HTTP server → WSGI → Flask</dd>
+ <dt>Flask-WeasyPrint</dt>
+ <dd>WeasyPrint engine → WSGI client → WSGI → Flask</dd>
+ </dl>
+ <details>
+ Flask-WeasyPrint: optimization only. Shortcuts the network and
+ stays within one Python thread/process.<br>
+ It’s standard WSGI: easy to adapt to other framework.
+ (The WSGI client is Flask’s <em>test client</em>.)
+ </details>
+</section>
+
+<section>
+ <h2>Generating PDF</h2>
+ <ul>
+ <li>LaTeX</li>
+ <li>ReportLab</li>
+ <li>LibreOffice</li>
+ </ul>
+ <ul>
+ <li>wkhtml2pdf (WebKit)</li>
+ <li>PrinceXML</li>
+ </ul>
+ <details>
+ LaTeX: inflexible stylesheets<br>
+ ReportLab open-source: imperative, no vector graphics<br>
+ LibreOffice: heavyweight, results not great<br>
+ WebKit: weak support for Paged Media, average font rendering,
+ hard to patch/fork<br>
+ PrinceXML: expensive, not open-source. But our most serious competitor.
+ </details>
+</section>
+
+<section>
+ <h2>NIH</h2>
+ <ul>
+ <li>2011-04: Let’s build a browser engine!</li>
+ <li>2011-10: v0.1</li>
+ <li>2012-02: v0.6, stable API</li>
+ <li>Today: v0.14</li>
+ <li>Real Soon<sup>®</sup>: v1.0</li>
+ </ul>
+ <details>
+ 0.14 is very stable already. There are only a few details I want
+ to take care of before calling it 1.0.
+ </details>
+</section>
+
+<section>
+ <h2>Features</h2>
+ <p><a href="http://weasyprint.org/features/">weasyprint.org/features</a></p>
+ <p>Raster and vector (SVG) images, PDF bookmarks, hyperlinks</p>
+ <p>CSS 2.1: 95%<sup>*</sup><br>
+ CSS 3: selectors, colors, 2D transforms, <strong>paged media</strong><br>
+ </p>
+ <details>
+ SVG images are rendered as vectors in the PDF output.<br>
+ Nothing scientific in the 95% figure, just a guesstimate.<br>
+ Paged media: fine page-break control, page-margin boxes<br>
+ (headers and footers, automatic numbering)
+ No <code>@font-face</code>, but can use any installed font.
+ </details>
+</section>
+
+<section>
+ <h2>Examples</h2>
+ <p><a href="PyConFR_2012_schedule.pdf">PyConFR 2012 schedule</a>
+ http://bit.ly/Qoe6F9</p>
+ <p><!-- TODO: switch back to the absolute URL before uploading.
+ <a href="http://weasyprint.org/samples/CSS21-intro.pdf">-->
+ <a href="CSS21-intro.pdf">CSS 2.1 intro</a>
+ http://bit.ly/URYCMp</p>
+ <p><img src=images/acid2-small.png></p>
+ <details>
+ Schedule: from the website + a custom stylesheet.<br>
+ CSS intro: Internal and external hyperlinks, bookmarks, page numbers,
+ 2D transforms<br>
+ Acid2: this is WeasyPrint’s PNG output.
+ </details>
+</section>
+
+<section>
+ <h2>Using WeasyPrint</h2>
+ <ul>
+ <li>HTML & CSS in, PDF or PNG out</li>
+ <li>Docs:
+ <a href="http://weasyprint.org/install/">weasyprint.org/install</a>
+ <a href="http://weasyprint.org/using/">weasyprint.org/using</a>
+ </li>
+ <li>Command-line API</li>
+ <li>Python API
+ <ul>
+ <li><code>base_url</code></li>
+ <li><code>url_fetcher</code></li>
+ </ul>
+ </li>
+ </ul>
+ <details>
+ See the docs for details. URLs, filenames, file objects, strings.
+ In Python, fine control on fetching of external resources.
+ </details>
+</section>
+
+<section>
+ <h2>CSS for print</h2>
+ <pre><code class=language-css
+>h1 { page-break-before: right }
+h1, h2, h3 {
+ page-break-after: avoid }
+table { page-break-inside: avoid }
+p { orphans: 3; widows: 3 }
+ </code></pre>
+ <details>
+ Just an overview, not a complete tutorial. Not much of this is
+ implemented in web browsers, so there is little doc around
+ besides the spec.<br>
+ Some "normal" CSS properties control page breaks.
+ </details>
+</section>
+
+<section>
+ <h2>CSS Paged Media Module</h2>
+ <p><a href="http://dev.w3.org/csswg/css3-page/">dev.w3.org/csswg/css3-page</a></p>
+ <p style="text-align: center"><img src=images/RightMarginBoxes.png
+ style="width: 30%"></p>
+ <details>
+ Pages can have margin, padding, borders, background, …<br>
+ Each page has up to 16 page-margin boxes (headers, footers, …)
+ </details>
+</section>
+
+<section>
+ <h2>CSS Paged Media Module</h2>
+ <pre><code class=language-css
+>@page { size: A4 landscape;
+ margin: 2cm }
+@page :left { @bottom-right {
+ content: counter(page) } }
+@media print { nav { display: none } }
+@media screen { /*...*/ }
+ </code></pre>
+ <details>
+ <code>@page</code> styles the page itself,
+ and <code>@bottom-right</code> is one of the 16 page-margin boxes.
+ <code>@media</code> can apply rules conditionally.
+ </details>
+</section>
+
+<section>
+ <h2>CSS length units</h2>
+ <p>Relative units: <code>%</code>, <code>em</code> and <code>ex</code>.</p>
+ <p>Absolute units: <code>1in = 2.54cm = 25.4mm = 72pt = 6pc
+ <strong>= 96px</strong></code>.</p>
+ <details>
+ CSS3 has more units, but the idea is the same.
+ Relative units are ultimately based on absolute units.
+ The ratios among absolute units is set in stone:
+ A CSS pixel is always one 96th of a CSS inch.
+ The scale needs to be anchored somehow. In PDF WeasyPrint anchors
+ on physical units, in PNG it defaults to 1 PNG pixel = 1 CSS px.
+ </details>
+</section>
+
+<section>
+ <h2>Architecture</h2>
+ <p>
+ <img src=images/Architecture.svg
+ style="width: 40%; float: left; margin: -1em 3em 0">
+ <img src=images/python.png style="width: 10%"><br>
+ <img src=images/lxml.png
+ style="width: 15%; position: relative; right: 2.5%"><br>
+ <img src=images/GTK.png style="width: 10%"><br>
+ <img src=images/cairo.png style="width: 10%">
+ </p>
+ <details>
+ Let’s open the box. The engine is of course in Python.
+ HTML is parsed with <a href="lxml.de/">lxml</a>, CSS with
+ <a href="http://packages.python.org/tinycss/ç">tinycss</a>.<br>
+ The <em>cascade</em> (C in CSS) handles selectors and rule priorities.
+ The <em>render tree</em> is made of rectangular <em>boxes</em>.
+ The <em>layout</em> splits them across lines and pages; and gives
+ them their position and size.<br>
+ We then paint on a <a href="http://cairographics.org/pycairo/">cairo</a>
+ surface, with <a href="http://pango.org/">Pango</a> handling the text.<br>
+ Priority: ease of implementation over runtime speed, but we still fix
+ obvious performance problems.
+ </details>
+</section>
+
+<section style="text-align: center">
+ <h2>CSS box model…</h2>
+ <p><img src=images/box_model.png
+ style="width: 70%; margin: -1em 0"></p>
+ <p>It’s complicated.</p>
+ <details>
+ No need to read this in details.<br>
+ The CSS 2.1 spec has dozen of pages describing this in details.
+ I had to read it many times, with a pen and paper. This is
+ what I got after many iterations.
+ </details>
+</section>
+
+<section>
+ <h2>Associated projects</h2>
+ <dl>
+ <dt>CairoSVG</dt>
+ <dd>Render SVG … to cairo. (PNG, PDF, …)</dd>
+ <dt>tinycss</dt>
+ <dd>CSS parser</dd>
+ <dt>cssselect</dt>
+ <dd>CSS 3 selectors → XPath 1.0 (lxml)</dd>
+ </dl>
+ <details>
+ Other projects of ours, used by WeasyPrint but can be used
+ independently.
+ </details>
+</section>
+
+<section style="text-align: center">
+ <h2>Thanks.</h2>
+ <h2>Questions?</h2>
+ <footer>
+ <a href="http://weasyprint.org">weasyprint.org</a><br>
+ <a href="https://github.com/Kozea">github.com/Kozea</a><br>
+ <a href="http://community.kozea.fr/">community.kozea.fr</a><br>
+ IRC: ##kozea @ Freenode
+ </footer>
+</section>
+
+<script src="prism.js"></script>
+<link rel=stylesheet href="prism.css">
+<!-- Your Style -->
+<!-- Define the style of your presentation -->
+
+<!-- Maybe a font from http://www.google.com/webfonts ? -->
+<link href='http://fonts.googleapis.com/css?family=Oswald' rel='stylesheet'>
+
+<style>
+ html, .view body { background-color: black; counter-reset: slideidx; }
+ body, .view section { background-color: white; border-radius: 12px; }
+ /* A section is a slide. It's size is 800x600, and this will never change */
+ section, .view head > title {
+ /* The font from Google */
+ font-family: 'Oswald', arial, serif;
+ font-size: 35px;
+ line-height: 1.5;
+ }
+
+ .view section:after {
+ counter-increment: slideidx;
+ content: counter(slideidx, decimal-leading-zero);
+ position: absolute; bottom: -80px; right: 100px;
+ color: white;
+ }
+
+ .view head > title {
+ color: white;
+ text-align: center;
+ margin: 1em 0 1em 0;
+ }
+
+
+ h1, h2 {
+ text-align: center;
+ font-size: 1.33em;
+ }
+
+ ul {
+ margin: 50px 180px;
+ }
+ ul ul {
+ margin: 0 0 0 1em;
+ line-height: 1.2;
+ }
+ p, h1, h2, h3, pre, dl {
+ margin: 1em;
+ }
+ a {
+ color: #00a !important;
+ }
+ pre {
+ font-size: 90%;
+ line-height: 1.2;
+ }
+ dd {
+ margin: 0 0 1em 1em;
+ }
+ dt {
+ color: #333;
+ }
+ dt::after {
+ content: ':';
+ }
+
+ blockquote {
+ height: 100%;
+ background-color: black;
+ color: white;
+ font-size: 60px;
+ padding: 50px;
+ }
+ blockquote:before {
+ content: open-quote;
+ }
+ blockquote:after {
+ content: close-quote;
+ }
+
+ /* Figures are displayed full-page, with the caption
+ on top of the image/video */
+ figure {
+ background-color: black;
+ width: 100%;
+ height: 100%;
+ }
+ figure > * {
+ position: absolute;
+ }
+ figure > img, figure > video {
+ width: 100%; height: 100%;
+ }
+ figcaption {
+ margin: 70px;
+ font-size: 50px;
+ }
+
+ footer {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ padding: 40px;
+ text-align: right;
+ background-color: #F3F4F8;
+ border-top: 1px solid #CCC;
+ border-radius: 0 0 12px 12px;
+ }
+
+ /* Transition effect */
+ /* Feel free to change the transition effect for original
+ animations. See here:
+ https://developer.mozilla.org/en/CSS/CSS_transitions
+ How to use CSS3 Transitions: */
+ section {
+ -moz-transition: left 400ms linear 0s;
+ -webkit-transition: left 400ms linear 0s;
+ -ms-transition: left 400ms linear 0s;
+ transition: left 400ms linear 0s;
+ }
+ .view section {
+ -moz-transition: none;
+ -webkit-transition: none;
+ -ms-transition: none;
+ transition: none;
+ }
+
+ .view section[aria-selected] {
+ border: 5px red solid;
+ }
+
+ /* Before */
+ section { left: -150%; }
+ /* Now */
+ section[aria-selected] { left: 0; }
+ /* After */
+ section[aria-selected] ~ section { left: +150%; }
+
+ /* Incremental elements */
+
+ /* By default, visible */
+ .incremental > * { opacity: 1; }
+
+ /* The current item */
+ .incremental > *[aria-selected] { opacity: 1; }
+
+ /* The items to-be-selected */
+ .incremental > *[aria-selected] ~ * { opacity: 0; }
+
+ /* The progressbar, at the bottom of the slides, show the global
+ progress of the presentation. */
+ #progress-bar div {
+ height: 2px;
+ background: #AAA;
+ }
+</style>
+
+<!-- {{{{ dzslides core
+#
+#
+# __ __ __ . __ ___ __
+# | \ / /__` | | | \ |__ /__`
+# |__/ /_ .__/ |___ | |__/ |___ .__/ core :€
+#
+#
+# The following block of code is not supposed to be edited.
+# But if you want to change the behavior of these slides,
+# feel free to hack it!
+#
+-->
+<div id="progress-bar"><div></div></div>
+
+<!-- Default Style -->
+<style>
+ * { margin: 0; padding: 0; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
+ details { display: none; }
+ body {
+ width: 800px; height: 600px;
+ margin-left: -400px; margin-top: -300px;
+ position: absolute; top: 50%; left: 50%;
+ overflow: hidden;
+ display: none;
+ }
+ .view body {
+ position: static;
+ margin: 0; padding: 0;
+ width: 100%; height: 100%;
+ display: inline-block;
+ overflow: visible; overflow-x: hidden;
+ /* undo Dz.onresize */
+ transform: none !important;
+ -moz-transform: none !important;
+ -webkit-transform: none !important;
+ -o-transform: none !important;
+ -ms-transform: none !important;
+ }
+ .view head, .view head > title { display: block }
+ section {
+ position: absolute;
+ pointer-events: none;
+ width: 100%; height: 100%;
+ }
+ .view section {
+ pointer-events: auto;
+ position: static;
+ width: 800px; height: 600px;
+ margin: -150px -200px;
+ float: left;
+
+ transform: scale(.4);
+ -moz-transform: scale(.4);
+ -webkit-transform: scale(.4);
+ -o-transform: scale(.4);
+ -ms-transform: scale(.4);
+ }
+ .view section > * { pointer-events: none; }
+ section[aria-selected] { pointer-events: auto; }
+ html { overflow: hidden; }
+ html.view { overflow: visible; }
+ body.loaded { display: block; }
+ .incremental {visibility: hidden; }
+ .incremental[active] {visibility: visible; }
+ #progress-bar{
+ bottom: 0;
+ position: absolute;
+ left: 15px;
+ right: 15px;
+ -moz-transition: width 400ms linear 0s;
+ -webkit-transition: width 400ms linear 0s;
+ -ms-transition: width 400ms linear 0s;
+ transition: width 400ms linear 0s;
+ }
+ .view #progress-bar {
+ display: none;
+ }
+</style>
+
+<script>
+ var Dz = {
+ remoteWindows: [],
+ idx: -1,
+ step: 0,
+ html: null,
+ slides: null,
+ progressBar : null,
+ params: {
+ autoplay: "1"
+ }
+ };
+
+ Dz.init = function() {
+ document.body.className = "loaded";
+ this.slides = Array.prototype.slice.call($$("body > section"));
+ this.progressBar = $("#progress-bar div");
+ this.html = document.body.parentNode;
+ this.setupParams();
+ this.onhashchange();
+ this.setupTouchEvents();
+ this.onresize();
+ this.setupView();
+ }
+
+ Dz.setupParams = function() {
+ var p = window.location.search.substr(1).split('&');
+ p.forEach(function(e, i, a) {
+ var keyVal = e.split('=');
+ Dz.params[keyVal[0]] = decodeURIComponent(keyVal[1]);
+ });
+ // Specific params handling
+ if (!+this.params.autoplay)
+ $$.forEach($$("video"), function(v){ v.controls = true });
+ }
+
+ Dz.onkeydown = function(aEvent) {
+ // Don't intercept keyboard shortcuts
+ if (aEvent.altKey
+ || aEvent.ctrlKey
+ || aEvent.metaKey
+ || aEvent.shiftKey) {
+ return;
+ }
+ if ( aEvent.keyCode == 37 // left arrow
+ || aEvent.keyCode == 38 // up arrow
+ || aEvent.keyCode == 33 // page up
+ ) {
+ aEvent.preventDefault();
+ this.back();
+ }
+ if ( aEvent.keyCode == 39 // right arrow
+ || aEvent.keyCode == 40 // down arrow
+ || aEvent.keyCode == 34 // page down
+ ) {
+ aEvent.preventDefault();
+ this.forward();
+ }
+ if (aEvent.keyCode == 35) { // end
+ aEvent.preventDefault();
+ this.goEnd();
+ }
+ if (aEvent.keyCode == 36) { // home
+ aEvent.preventDefault();
+ this.goStart();
+ }
+ if (aEvent.keyCode == 32) { // space
+ aEvent.preventDefault();
+ this.toggleContent();
+ }
+ if (aEvent.keyCode == 70) { // f
+ aEvent.preventDefault();
+ this.goFullscreen();
+ }
+ if (aEvent.keyCode == 79) { // o
+ aEvent.preventDefault();
+ this.toggleView();
+ }
+ }
+
+ /* Touch Events */
+
+ Dz.setupTouchEvents = function() {
+ var orgX, newX;
+ var tracking = false;
+
+ var db = document.body;
+ db.addEventListener("touchstart", start.bind(this), false);
+ db.addEventListener("touchmove", move.bind(this), false);
+
+ function start(aEvent) {
+ aEvent.preventDefault();
+ tracking = true;
+ orgX = aEvent.changedTouches[0].pageX;
+ }
+
+ function move(aEvent) {
+ if (!tracking) return;
+ newX = aEvent.changedTouches[0].pageX;
+ if (orgX - newX > 100) {
+ tracking = false;
+ this.forward();
+ } else {
+ if (orgX - newX < -100) {
+ tracking = false;
+ this.back();
+ }
+ }
+ }
+ }
+
+ Dz.setupView = function() {
+ document.body.addEventListener("click", function ( e ) {
+ if (!Dz.html.classList.contains("view")) return;
+ if (!e.target || e.target.nodeName != "SECTION") return;
+
+ Dz.html.classList.remove("view");
+ Dz.setCursor(Dz.slides.indexOf(e.target) + 1);
+ }, false);
+ }
+
+ /* Adapt the size of the slides to the window */
+
+ Dz.onresize = function() {
+ var db = document.body;
+ var sx = db.clientWidth / window.innerWidth;
+ var sy = db.clientHeight / window.innerHeight;
+ var transform = "scale(" + (1/Math.max(sx, sy)) + ")";
+
+ db.style.MozTransform = transform;
+ db.style.WebkitTransform = transform;
+ db.style.OTransform = transform;
+ db.style.msTransform = transform;
+ db.style.transform = transform;
+ }
+
+
+ Dz.getDetails = function(aIdx) {
+ var s = $("section:nth-of-type(" + aIdx + ")");
+ var d = s.$("details");
+ return d ? d.innerHTML : "";
+ }
+
+ Dz.onmessage = function(aEvent) {
+ var argv = aEvent.data.split(" "), argc = argv.length;
+ argv.forEach(function(e, i, a) { a[i] = decodeURIComponent(e) });
+ var win = aEvent.source;
+ if (argv[0] === "REGISTER" && argc === 1) {
+ this.remoteWindows.push(win);
+ this.postMsg(win, "REGISTERED", document.title, this.slides.length);
+ this.postMsg(win, "CURSOR", this.idx + "." + this.step);
+ return;
+ }
+ if (argv[0] === "BACK" && argc === 1)
+ this.back();
+ if (argv[0] === "FORWARD" && argc === 1)
+ this.forward();
+ if (argv[0] === "START" && argc === 1)
+ this.goStart();
+ if (argv[0] === "END" && argc === 1)
+ this.goEnd();
+ if (argv[0] === "TOGGLE_CONTENT" && argc === 1)
+ this.toggleContent();
+ if (argv[0] === "SET_CURSOR" && argc === 2)
+ window.location.hash = "#" + argv[1];
+ if (argv[0] === "GET_CURSOR" && argc === 1)
+ this.postMsg(win, "CURSOR", this.idx + "." + this.step);
+ if (argv[0] === "GET_NOTES" && argc === 1)
+ this.postMsg(win, "NOTES", this.getDetails(this.idx));
+ }
+
+ Dz.toggleContent = function() {
+ // If a Video is present in this new slide, play it.
+ // If a Video is present in the previous slide, stop it.
+ var s = $("section[aria-selected]");
+ if (s) {
+ var video = s.$("video");
+ if (video) {
+ if (video.ended || video.paused) {
+ video.play();
+ } else {
+ video.pause();
+ }
+ }
+ }
+ }
+
+ Dz.setCursor = function(aIdx, aStep) {
+ // If the user change the slide number in the URL bar, jump
+ // to this slide.
+ aStep = (aStep != 0 && typeof aStep !== "undefined") ? "." + aStep : ".0";
+ window.location.hash = "#" + aIdx + aStep;
+ }
+
+ Dz.onhashchange = function() {
+ var cursor = window.location.hash.split("#"),
+ newidx = 1,
+ newstep = 0;
+ if (cursor.length == 2) {
+ newidx = ~~cursor[1].split(".")[0];
+ newstep = ~~cursor[1].split(".")[1];
+ if (newstep > Dz.slides[newidx - 1].$$('.incremental > *').length) {
+ newstep = 0;
+ newidx++;
+ }
+ }
+ this.setProgress(newidx, newstep);
+ if (newidx != this.idx) {
+ this.setSlide(newidx);
+ }
+ if (newstep != this.step) {
+ this.setIncremental(newstep);
+ }
+ for (var i = 0; i < this.remoteWindows.length; i++) {
+ this.postMsg(this.remoteWindows[i], "CURSOR", this.idx + "." +</