diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b96b18b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+slides/*
diff --git a/Readme.md b/Readme.md
index 4cb4725..401120b 100644
--- a/Readme.md
+++ b/Readme.md
@@ -50,6 +50,14 @@ dictumst. Fusce faucibus sagittis sapien vel posuere.
```ruby
['a', 'b'].map(&:uppercase)
````
+
+## Exporting
-# GistDeck by noah and todd
+You can export your deck as a stack of PNGs or as a single PDF using our
+phantomjs plugin
+
+1. `sudo npm install -g phantomjs`
+2. `phantomjs rasterize.js [directory] [width] [height]`
+3. `convert slides/* -compress jpeg -resize 1024x768 -units PixelsPerInch -density 150x150 output.pdf # requires ImageMagick`
+# GistDeck by noah and todd
diff --git a/gist.html b/gist.html
index b0448ca..44b0bda 100644
--- a/gist.html
+++ b/gist.html
@@ -12,8 +12,8 @@
-
-
+
+
@@ -25,13 +25,12 @@
+
diff --git a/gistdeck.js b/gistdeck.js
index 5c54a17..e1f8b93 100644
--- a/gistdeck.js
+++ b/gistdeck.js
@@ -1,4 +1,4 @@
-(function() {
+function gistdeck() {
// Cache window and slides jQuery selectors
var $window = $(window);
@@ -11,6 +11,20 @@
.addClass('gistdeck-css')
.appendTo('head');
+ $('[id$=-css]').each(function() {
+ // Using ajax to grab contents of CSS file because gist doesn't
+ // provide the right content-type to make it a style link
+ // No problems with same-origin policy when script is run from gist.github.com
+ $.ajax({
+ url: $(this).find('.file-actions a:last').attr('href'),
+ success: function(data) {
+ $( '' )
+ .addClass('gistdeck-css')
+ .appendTo('head');
+ }
+ });
+ });
+
// Set gap before all slides but first, and after slides container, equal to the window height
$slides.not($slides.first()).css('margin-top', $window.height());
$('.markdown-body').css('margin-bottom', $window.height());
@@ -90,4 +104,6 @@
initialize();
}
-})();
+};
+
+module.exports = gistdeck;
diff --git a/rasterize.js b/rasterize.js
new file mode 100644
index 0000000..470adeb
--- /dev/null
+++ b/rasterize.js
@@ -0,0 +1,92 @@
+var gistdeck = require( './gistdeck' ),
+ page = require( 'webpage' ).create(),
+ system = require( 'system' ),
+ address, outputDir,
+ viewportWidth = 1024,
+ viewportHeight = 768;
+
+if ( system.args.length < 2 || system.args.length > 5 ) {
+ console.log( 'Usage: rasterize.js URL [directory width height]' );
+ phantom.exit( 1 );
+} else {
+ address = system.args[1];
+ outputDir = system.args[2];
+ viewportWidth = system.args[3] || viewportWidth;
+ viewportHeight = system.args[4] || viewportHeight;
+ page.viewportSize = { width: viewportWidth, height: viewportHeight };
+
+ function pad(n, width, z) {
+ z = z || '0';
+ n = n + '';
+ return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
+ }
+
+ page.open( address, function (status) {
+ if ( status !== 'success' ) {
+ console.log( 'Unable to load that gist!' );
+ phantom.exit();
+ } else {
+
+ // Set timeout for page/images to load
+ window.setTimeout( function() {
+ console.log( 'Generating Images...' );
+ page.evaluate( function( gistdeck, viewportHeight ) {
+ document.height = viewportHeight;
+
+ gistdeck();
+ }, gistdeck, viewportHeight );
+
+ // Set timeout again to let gistdeck styles load
+ setTimeout( function() {
+ var i = 0,
+ scroll,
+ totalHeight,
+ roughCount,
+ numLen,
+ data = page.evaluate( function() {
+ return {
+ scroll: $(document).scrollTop(),
+ winHeight: $('.markdown-body').height()
+ };
+ });
+
+ scroll = data.scroll;
+ totalHeight = data.winHeight;
+ roughCount = Math.round( totalHeight / viewportHeight );
+ numLen = ( roughCount + '' ).length + 1;
+
+ // Keep advancing and taking screen shots until we reach the last slide
+ while( totalHeight - scroll > viewportHeight ) {
+
+ var data = page.evaluate( function(i) {
+ var e = $.Event( 'keydown.gistdeck', {which: 39 } ),
+ $doc = $(document);
+
+ // Programmatically hit the right arrow key
+ // to navigate slides
+ // We have to hit it i times because phantomJS doesn't save
+ // our scrollTop
+ for( var j = 0; j < i; j++ ) {
+ $doc.trigger(e);
+ }
+
+ return {
+ scroll: $(document).scrollTop(),
+ winHeight: $('.markdown-body').height()
+ };
+ }, i);
+
+ scroll = data.scroll;
+ totalHeight = data.winHeight;
+
+ // Take snapshot relative to scroll position
+ page.clipRect = { top: scroll, left: 0, width: viewportWidth, height: viewportHeight };
+ page.render( ( outputDir ? outputDir : 'slides' ) + '/slide-' + pad(i+1, numLen) + '.png' );
+ i++;
+ }
+ phantom.exit();
+ }, 2000 );
+ }, 2000);
+ }
+ });
+}