show_off_pdf 0.0.1.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING.md +13 -0
- data/HACKING.md +15 -0
- data/LICENSE +115 -0
- data/README.md +0 -0
- data/bin/showoff2pdf +13 -0
- data/example/one/01_slide.md +36 -0
- data/example/one/images.png +0 -0
- data/example/showoff.json +11 -0
- data/example.pdf +0 -0
- data/lib/markdown_fragments/code_fragment.rb +32 -0
- data/lib/markdown_fragments/heading_fragment.rb +20 -0
- data/lib/markdown_fragments/horizontal_rule_fragment.rb +25 -0
- data/lib/markdown_fragments/image_fragment.rb +87 -0
- data/lib/markdown_fragments/links_reference_fragment.rb +17 -0
- data/lib/markdown_fragments/list_fragment.rb +41 -0
- data/lib/markdown_fragments/markdown_fragment.rb +13 -0
- data/lib/markdown_fragments/page_break_fragment.rb +5 -0
- data/lib/markdown_fragments/paragraph_fragment.rb +21 -0
- data/lib/markdown_fragments/presenter_notes_fragment.rb +10 -0
- data/lib/markdown_fragments.rb +10 -0
- data/lib/markdown_parser/file_parser.rb +18 -0
- data/lib/markdown_parser/parser.rb +243 -0
- data/lib/markdown_parser/string_parser.rb +11 -0
- data/lib/markdown_parser.rb +5 -0
- data/lib/markdown_prawn_exceptions.rb +6 -0
- data/lib/show_off_slide.rb +42 -0
- data/lib/show_off_slide_stream.rb +27 -0
- data/lib/show_off_utils.rb +19 -0
- data/show_off_pdf-0.0.1.pre.gem +0 -0
- data/show_off_pdf.gemspec +23 -0
- data/show_off_pdf.rb +9 -0
- metadata +156 -0
data/COPYING.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copying / License Permissions
|
2
|
+
=============================
|
3
|
+
showoff2pdf was created by Ryan Stenhouse <ryan@ryanstenhouse.eu>.
|
4
|
+
|
5
|
+
This work is made available under the terms of the Creative Commons by
|
6
|
+
Attibution, Non Commercial Share-Alike (UK:Scotland) license.
|
7
|
+
|
8
|
+
(Yes, that is quite a long winded title).
|
9
|
+
|
10
|
+
You can [read the copy of the licence][1] on the [creative commons][1]
|
11
|
+
website.
|
12
|
+
|
13
|
+
[1]: http://creativecommons.org/licenses/by-nc-sa/2.5/scotland/
|
data/HACKING.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Hacking on showoff2pdf
|
2
|
+
=========================
|
3
|
+
|
4
|
+
Hacking on showoff2pdf is strongly encouraged. There are
|
5
|
+
numerous areas (particularly the parser) which could do with
|
6
|
+
a lot of improvement.
|
7
|
+
|
8
|
+
The process for accepting patches is as follows:
|
9
|
+
|
10
|
+
1. Fork the repository
|
11
|
+
2. Make your changes
|
12
|
+
3. Have some tests for your changes
|
13
|
+
4. Submit a pull request
|
14
|
+
|
15
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
Creative Commons
|
2
|
+
|
3
|
+
|
4
|
+
Attribution - Non-commercial - Share-Alike 2.5 Scotland
|
5
|
+
|
6
|
+
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENCE DOES NOT CREATE AN AGENT-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE.
|
7
|
+
Licence
|
8
|
+
|
9
|
+
This Creative Commons Scotland public licence enables You to Use the Work worldwide for non-commercial purposes provided that You keep to the terms of this Licence.
|
10
|
+
|
11
|
+
'The Licensor' (the Person offering the Work under the terms and conditions of this Licence)
|
12
|
+
|
13
|
+
and
|
14
|
+
|
15
|
+
'You' (the Person acquiring rights under this Licence)
|
16
|
+
|
17
|
+
agree as follows:
|
18
|
+
|
19
|
+
1. Definitions of Capitalised Words
|
20
|
+
|
21
|
+
"Collective Work" means a work made up of the Work in its entirety in unmodified form, along with other work, assembled into a collective whole.
|
22
|
+
"Derivative Work" means a work that Uses the Work (or any substantial part of the Work) in any material form whatsoever (such as a translation, dramatisation, or abridgment), other than (i) as a whole and in unmodified form or (ii) by modifying it as may be technically necessary to Use it in a different mode or format; but a Collective Work is not a Derivative Work for the purpose of this Licence.
|
23
|
+
"Derogatory Treatment" means derogatory treatment as defined by section 80 of the Copyright Design and Patents Act 1988, except as allowed by that Act: and it has that meaning wherever that treatment may take place and whoever may carry it out.
|
24
|
+
"Licence Elements" means the following licence attributes indicated in the title of this Licence: Attribution, Non-commercial, Share-Alike.
|
25
|
+
"Original Author" means the Person who created the Work.
|
26
|
+
"Person" means a natural person or a body of persons corporate or incorporate.
|
27
|
+
"Use", as a verb, means doing any act which is restricted by copyright, whether in the original medium or any other; and includes modifying the Work as may be technically necessary to Use it in a different mode or format.
|
28
|
+
"Work" means the work protected by copyright which is offered under the terms of this Licence, and includes the Work as incorporated in any Collective Work.
|
29
|
+
Words in the singular include the plural and vice versa.
|
30
|
+
2. The Rights Granted
|
31
|
+
|
32
|
+
2.1 The Licensor grants to You a worldwide, royalty-free, non-exclusive, licence to Use the Work for the duration of its copyright.
|
33
|
+
|
34
|
+
So you may, for example:
|
35
|
+
|
36
|
+
copy the Work, or create Derivative Works or incorporate it into a Collective Work;
|
37
|
+
copy Derivative Works, or the Work as incorporated in any Collective Work; and
|
38
|
+
publish, perform or communicate the Work and/or Derivative Works and/or the Work as incorporated in any Collective Work to anyone;
|
39
|
+
in any medium whether now known or created in the future.
|
40
|
+
|
41
|
+
2.2 However, this Licence does not allow you to:
|
42
|
+
|
43
|
+
use the work in any way primarily intended for commercial advantage or payment; but exchange for other copyrighted work without payment (whether by means of digital file-sharing or otherwise) is not to be taken to be so intended;
|
44
|
+
impose any terms or any technological measures on the Work, or a Derivative Work, that alter or restrict the terms of this Licence or any rights granted under it or have the effect or intent of restricting the ability of any person to exercise those rights;
|
45
|
+
sublicense the Work; or
|
46
|
+
subject the Work to Derogatory Treatment.
|
47
|
+
2.3 You must, if you publish or distribute the Work or any Derivative Work to anyone else in any way, give reasonable credit to the Original Author as follows:
|
48
|
+
|
49
|
+
by giving the name of the Original Author if that has been supplied; or a pseudonym if that has been supplied instead; and/or the name of any other person if that has been supplied for attribution in place of the Original Author;
|
50
|
+
by giving the title of the Work if that has been supplied;
|
51
|
+
by giving the Uniform Resource Identifier of the Work if that has been supplied, but you need not do so if this does not refer to its copyright terms or to its licensing information;
|
52
|
+
in the case of a Derivative Work, by identifying how the Work has been used (for example, "French translation of the Work by X", or "Screenplay based on original work by X"); and
|
53
|
+
in the case of a Derivative Work or a Collective Work, placing that credit in the same place, and at least as prominently, as any comparable authorship credit.
|
54
|
+
But, if what you are publishing or distributing is a Derivative Work or a Collective Work, you must remove any of these credits if you are asked to do so by the Licensor and if it is practicable to do so.
|
55
|
+
These are important conditions of this licence and if you fail to do so you will be in material breach of its terms.
|
56
|
+
|
57
|
+
2.4 The Original Author asserts the right to be identified as the original author of the Work; but only as and when required by clause 2.3 above.
|
58
|
+
|
59
|
+
2.5 You must also, if you publish or distribute the Work or any Derivative Work to anyone else in any way:
|
60
|
+
|
61
|
+
include a copy of this Licence (or its Uniform Resource Identifier) with it; and
|
62
|
+
keep intact any copyright notices for the Work and notices that refer to this Licence.
|
63
|
+
These are important conditions of this licence and if you fail to do so you will be in material breach of its terms.
|
64
|
+
|
65
|
+
2.6 Each time You publish the Work or any Derivative Work to anyone else in any way, the Licensor offers to the recipient a licence to the Work on the same terms and conditions as this Licence.
|
66
|
+
|
67
|
+
2.7 Any Derivative Work you create must be under a licence which is either one with the same terms and conditions as this Licence, or a later version of this Licence with the same Licence Elements as this Licence, or another Creative Commons licence with the same Licence Elements as this Licence (for example, Attribution-Noncommercial-ShareAlike 2.5 Slovenia).
|
68
|
+
|
69
|
+
2.8 And:
|
70
|
+
|
71
|
+
the right to collect royalties for any commercial use of the Work is reserved;
|
72
|
+
the right to collect payments via a licensing body or collecting society for any commercial use of the Work is reserved;
|
73
|
+
the right to collect payments under the Public Lending Right scheme (or any public scheme that provides payment for public borrowing or use) is reserved;
|
74
|
+
the right to release the Work under different terms, or to stop distributing the Work, is reserved; and
|
75
|
+
all other rights not expressly granted by the Licensor are reserved.
|
76
|
+
2.9 This Licence does not affect any rights that You or anyone else may independently have under any applicable law (including fair dealing, fair use, or any other legally recognised limitation or exception to copyright infringement) to make any Use of this Work.
|
77
|
+
|
78
|
+
3. Warranties and Disclaimer
|
79
|
+
|
80
|
+
3.1 The Work is licensed by the Licensor "as is" and without any warranty of any kind, either express or implied, whether of title, of accuracy, of fitness for purpose, or otherwise.
|
81
|
+
|
82
|
+
4. Limit of Liability
|
83
|
+
|
84
|
+
4.1 Subject to any liability which may not be excluded or limited by law, the Licensor shall not be liable for, and expressly excludes, all liability for loss or damage however and whenever caused to anyone by any Use under this Licence, whether by You or by anyone else, and whether caused by any fault on the part of the Licensor or not. If liability may not be excluded by law, it is limited to actual and direct financial loss to the extent it is caused by proved negligence on the part of the Licensor.
|
85
|
+
|
86
|
+
5. Termination
|
87
|
+
|
88
|
+
5.1 Any breach by You of the terms of this licence (for example, by distributing the work licensed without attributing authorship as appropriate) entitles the Licensor to terminate this Licence with immediate effect and without notice to you. Persons who have received the Work, Derivative Works, or Collective Works from You under this Licence, however, will not have their licences terminated provided their use is in full compliance with this Licence or a licence granted under clause 2.6 of this Licence.
|
89
|
+
|
90
|
+
5.2 If You are not in breach of the terms of this licence, the Licensor may not terminate your rights under it.
|
91
|
+
|
92
|
+
5.3 Unless terminated under clause 5.1, this Licence is granted to you for the duration of copyright in the Work.
|
93
|
+
|
94
|
+
6. General
|
95
|
+
|
96
|
+
6.1 If any provision of this Licence is held to be invalid or unenforceable, that shall not affect the validity or enforceability of the remainder of the terms of this Licence.
|
97
|
+
|
98
|
+
6.2 This Licence is the entire agreement between the parties with respect to the Work licensed here. It replaces any earlier understandings, agreements or representations with respect to the Work not specified here.
|
99
|
+
|
100
|
+
6.3 If You are in breach of the terms of this Licence (for example, by distributing the work licensed without attributing authorship as appropriate) you will not be entitled to rely on the terms of this Licence or to complain of any breach by the Licensor.
|
101
|
+
|
102
|
+
6.4 Neither You, nor anyone else, may enforce any provision of this Licence by specific implement or interdict.
|
103
|
+
|
104
|
+
6.5 This Licence is governed by the law of Scotland and the parties accept the exclusive jurisdiction of the Courts of Scotland to decide any action or claim directed against the Licensor.
|
105
|
+
|
106
|
+
6.6 If there is any dispute as to the meaning or effect of any provision of this Licence, it must so far as possible be read and given effect in a way that is compatible with the provisions of the Creative Commons generic licence, version 2.5, which has the same Licence Elements.
|
107
|
+
|
108
|
+
The Notice below is not part of this licence.
|
109
|
+
|
110
|
+
Creative Commons is not a party to this Licence, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this licence. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor.
|
111
|
+
|
112
|
+
Except for the limited purpose of indicating to the public that the Work is licensed under the Creative Commons Public Licence, neither party will use the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time.
|
113
|
+
|
114
|
+
Creative Commons may be contacted at http://creativecommons.org/.
|
115
|
+
|
data/README.md
ADDED
File without changes
|
data/bin/showoff2pdf
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require File.dirname(__FILE__) + '/../show_off_pdf'
|
4
|
+
paths = []
|
5
|
+
images = []
|
6
|
+
ShowOffUtils.showoff_sections.each do |section|
|
7
|
+
paths << Dir.glob(File.expand_path("./#{section}/*.{md,mdown}"))
|
8
|
+
images << Dir.glob(File.expand_path("./#{section}/**/*.{png,jpg,jpeg}"))
|
9
|
+
end
|
10
|
+
paths.flatten!
|
11
|
+
images.flatten!
|
12
|
+
ImageFragment._image_assets = images
|
13
|
+
puts ShowoffSlideStream.new(paths).to_pdf.render
|
@@ -0,0 +1,36 @@
|
|
1
|
+
!SLIDE
|
2
|
+
.notes It even parses out slide notes when entered all on one line with the notes class. Try it out!
|
3
|
+
# Introducing showoff2pdf #
|
4
|
+
|
5
|
+
* Uses on Prawn to dynamically generate PDF
|
6
|
+
files form Markdown Slides
|
7
|
+
* Favours sensible defaults to make readable
|
8
|
+
and printable documents
|
9
|
+
* Just depends on Ruby and Prawn (--pre)
|
10
|
+
* Based on my Markdown Prawn library
|
11
|
+
|
12
|
+
!SLIDE
|
13
|
+
#Supported features#
|
14
|
+
|
15
|
+
![images](./images.png)
|
16
|
+
|
17
|
+
##Multi
|
18
|
+
###Level
|
19
|
+
####Headings
|
20
|
+
|
21
|
+
!SLIDE
|
22
|
+
#Supported features continued
|
23
|
+
|
24
|
+
$ cat slide.md | ./md2pdf > slide.pdf
|
25
|
+
$ formatting for command line segments
|
26
|
+
|
27
|
+
|
28
|
+
!SLIDE
|
29
|
+
.notes I'm happy to accept any patches for this; so please get in touch. There's still a lot that needs to be done!
|
30
|
+
# What doesn't work #
|
31
|
+
|
32
|
+
* Custom CSS styles and the like will not be
|
33
|
+
preserved, if you want that, then use Prince
|
34
|
+
* For obvious reasons, executing Ruby or JavaScript
|
35
|
+
won't work.
|
36
|
+
* A lot of inline HTML will be silently dropped.
|
Binary file
|
data/example.pdf
ADDED
Binary file
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class CodeFragment < MarkdownFragment
|
2
|
+
attr_accessor :ordered
|
3
|
+
|
4
|
+
def render_on(pdf_object, options = {})
|
5
|
+
arguments = _default_render_options.merge(options)
|
6
|
+
width = ((pdf_object.bounds.width / 100) * 90)
|
7
|
+
data = []
|
8
|
+
|
9
|
+
@content.each_with_index do |item, i|
|
10
|
+
# Strip any un-needed white space
|
11
|
+
#
|
12
|
+
item = item.gsub(/\s\s+/,' ')
|
13
|
+
data << [ "<font name=\"Courier\">#{item}</font>" ]
|
14
|
+
end
|
15
|
+
|
16
|
+
pdf_object.table data, arguments.merge({:width => width}) do
|
17
|
+
cells.borders = []
|
18
|
+
end
|
19
|
+
pdf_object.move_down(5)
|
20
|
+
end
|
21
|
+
|
22
|
+
def ordered?
|
23
|
+
@ordered == true
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def _default_render_options
|
29
|
+
options = {:cell_style => { :inline_format => true}}
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class HeadingFragment < MarkdownFragment
|
2
|
+
attr_accessor :level
|
3
|
+
|
4
|
+
def render_on(pdf_object, options = {})
|
5
|
+
arguments = _default_render_options.merge(options)
|
6
|
+
pdf_object.move_down(@level * 2)
|
7
|
+
pdf_object.text "<b>#{@content.join(' ')}</b>", arguments
|
8
|
+
pdf_object.move_down(@level * 2)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def _default_render_options
|
14
|
+
options = { :size => (50 - (10*@level)), :align => :left, :leading => 2, :inline_format => true }
|
15
|
+
if Prawn::VERSION =~ /^0.1/ || Prawn::VERSION =~ /^1/
|
16
|
+
options.merge({:inline_format => true})
|
17
|
+
end
|
18
|
+
options
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class HorizontalRuleFragment < MarkdownFragment
|
2
|
+
|
3
|
+
def render_on(pdf_object, options = {})
|
4
|
+
pdf_object.move_down(3)
|
5
|
+
old_width = pdf_object.line_width
|
6
|
+
pdf_object.line_width = 3
|
7
|
+
pdf_object.horizontal_rule
|
8
|
+
pdf_object.stroke
|
9
|
+
pdf_object.line_width = old_width
|
10
|
+
pdf_object.move_down(3)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def _default_render_options
|
16
|
+
options = { :size => 12, :align => :left, :leading => 2 }
|
17
|
+
if Prawn::VERSION =~ /^0.1/ || Prawn::VERSION =~ /^1/
|
18
|
+
options = options.merge({:inline_format => true})
|
19
|
+
else
|
20
|
+
options = options.merge({:inline_format => false})
|
21
|
+
end
|
22
|
+
options
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
class ImageFragment < MarkdownFragment
|
5
|
+
def self._image_assets=(value)
|
6
|
+
@@_image_assets = value
|
7
|
+
end
|
8
|
+
|
9
|
+
def self._image_assets
|
10
|
+
@@_image_assets
|
11
|
+
end
|
12
|
+
|
13
|
+
def render_on(pdf_object)
|
14
|
+
if is_remote_uri?
|
15
|
+
filename = @content.first.split('/').last
|
16
|
+
file_path = "#{Dir.tmpdir}/#{filename}"
|
17
|
+
content = Net::HTTP.get(URI.parse(@content.first))
|
18
|
+
File.open(file_path, 'w') do |f|
|
19
|
+
f.puts content
|
20
|
+
end
|
21
|
+
else
|
22
|
+
if !ImageFragment._image_assets.nil?
|
23
|
+
ImageFragment._image_assets.each do |image|
|
24
|
+
if image =~ /#{@content.first}$/
|
25
|
+
file_path = image
|
26
|
+
end
|
27
|
+
end
|
28
|
+
else
|
29
|
+
file_path = @content.first
|
30
|
+
end
|
31
|
+
end
|
32
|
+
if file_path =~ /.png$/
|
33
|
+
width, height = IO.read(file_path)[0x10..0x18].unpack('NN')
|
34
|
+
else
|
35
|
+
width = JPEG.new(file_path).width
|
36
|
+
height = JPEG.new(file_path).height
|
37
|
+
end
|
38
|
+
pdf_object.image file_path, :width => width, :height => height, :scale => 0.8
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def is_remote_uri?
|
44
|
+
!/^(http:|https:)/.match(@content.first).nil?
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
class JPEG
|
50
|
+
attr_reader :width, :height, :bits
|
51
|
+
|
52
|
+
def initialize(file)
|
53
|
+
if file.kind_of? IO
|
54
|
+
examine(file)
|
55
|
+
else
|
56
|
+
File.open(file, 'rb') { |io| examine(io) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def examine(io)
|
62
|
+
raise 'malformed JPEG' unless io.getc == 0xFF && io.getc == 0xD8 # SOI
|
63
|
+
|
64
|
+
class << io
|
65
|
+
def readint; (readchar << 8) + readchar; end
|
66
|
+
def readframe; read(readint - 2); end
|
67
|
+
def readsof; [readint, readchar, readint, readint, readchar]; end
|
68
|
+
def next
|
69
|
+
c = readchar while c != 0xFF
|
70
|
+
c = readchar while c == 0xFF
|
71
|
+
c
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
while marker = io.next
|
76
|
+
case marker
|
77
|
+
when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers
|
78
|
+
length, @bits, @height, @width, components = io.readsof
|
79
|
+
raise 'malformed JPEG' unless length == 8 + components * 3
|
80
|
+
when 0xD9, 0xDA: break # EOI, SOS
|
81
|
+
when 0xFE: @comment = io.readframe # COM
|
82
|
+
when 0xE1: io.readframe # APP1, contains EXIF tag
|
83
|
+
else io.readframe # ignore frame
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class LinksReferenceFragment < MarkdownFragment
|
2
|
+
|
3
|
+
def render_on(pdf_object)
|
4
|
+
|
5
|
+
pdf_object.move_down(10)
|
6
|
+
pdf_object.horizontal_rule
|
7
|
+
pdf_object.stroke
|
8
|
+
pdf_object.move_down(4)
|
9
|
+
pdf_object.text "Hyperlink References:"
|
10
|
+
pdf_object.move_down(4)
|
11
|
+
pdf_object.table @content do
|
12
|
+
cells.borders = []
|
13
|
+
end
|
14
|
+
pdf_object.move_down(4)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class ListFragment < MarkdownFragment
|
2
|
+
attr_accessor :ordered
|
3
|
+
|
4
|
+
def render_on(pdf_object, options = {})
|
5
|
+
bullet = '• '
|
6
|
+
arguments = _default_render_options.merge(options)
|
7
|
+
width = ((pdf_object.bounds.width / 100) * 90)
|
8
|
+
data = []
|
9
|
+
|
10
|
+
@content.each_with_index do |item, i|
|
11
|
+
# Strip any un-needed white space
|
12
|
+
#
|
13
|
+
item = item.gsub(/\s\s+/,' ')
|
14
|
+
if ordered?
|
15
|
+
bullet = "#{i+1}."
|
16
|
+
end
|
17
|
+
data << [bullet,item]
|
18
|
+
end
|
19
|
+
|
20
|
+
pdf_object.table data, arguments.merge({:width => width}) do
|
21
|
+
cells.borders = []
|
22
|
+
column(0).style( { :width => 20 })
|
23
|
+
end
|
24
|
+
pdf_object.move_down(5)
|
25
|
+
end
|
26
|
+
|
27
|
+
def ordered?
|
28
|
+
@ordered == true
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def _default_render_options
|
34
|
+
options = {}
|
35
|
+
if Prawn::VERSION =~ /^0.1/ || Prawn::VERSION =~ /^1/
|
36
|
+
options = options.merge({:cell_style => { :inline_format => true}})
|
37
|
+
end
|
38
|
+
options
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class MarkdownFragment
|
2
|
+
attr_accessor :content
|
3
|
+
|
4
|
+
def initialize(content = [])
|
5
|
+
@content = content
|
6
|
+
end
|
7
|
+
|
8
|
+
# Renders the current fragment on the supplied prawn PDF Object. By Default,
|
9
|
+
# it will just join content and add it as text - not too useful.
|
10
|
+
def render_on(pdf_object)
|
11
|
+
pdf_object.text @content.join(' ')
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class ParagraphFragment < MarkdownFragment
|
2
|
+
|
3
|
+
def render_on(pdf_object, options = {})
|
4
|
+
arguments = _default_render_options.merge(options)
|
5
|
+
pdf_object.move_down(3)
|
6
|
+
pdf_object.text @content.join(' '), arguments
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def _default_render_options
|
12
|
+
options = { :size => 12, :align => :left, :leading => 2 }
|
13
|
+
if Prawn::VERSION =~ /^0.1/ || Prawn::VERSION =~ /^1/
|
14
|
+
options = options.merge({:inline_format => true})
|
15
|
+
else
|
16
|
+
options = options.merge({:inline_format => false})
|
17
|
+
end
|
18
|
+
options
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class PresenterNotesFragment < MarkdownFragment
|
2
|
+
def render_on(pdf)
|
3
|
+
pdf.bounding_box([0,50], :width => pdf.bounds.width, :height => 150) do
|
4
|
+
pdf.horizontal_rule
|
5
|
+
pdf.stroke
|
6
|
+
pdf.move_down(5)
|
7
|
+
pdf.text "<b>Slide notes:</b> #{@content.first}", :inline_format => true, :size => 8
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/markdown_fragments/markdown_fragment.rb'
|
2
|
+
require File.dirname(__FILE__) + '/markdown_fragments/paragraph_fragment.rb'
|
3
|
+
require File.dirname(__FILE__) + '/markdown_fragments/heading_fragment.rb'
|
4
|
+
require File.dirname(__FILE__) + '/markdown_fragments/list_fragment.rb'
|
5
|
+
require File.dirname(__FILE__) + '/markdown_fragments/image_fragment.rb'
|
6
|
+
require File.dirname(__FILE__) + '/markdown_fragments/horizontal_rule_fragment.rb'
|
7
|
+
require File.dirname(__FILE__) + '/markdown_fragments/links_reference_fragment.rb'
|
8
|
+
require File.dirname(__FILE__) + '/markdown_fragments/code_fragment.rb'
|
9
|
+
require File.dirname(__FILE__) + '/markdown_fragments/page_break_fragment.rb'
|
10
|
+
require File.dirname(__FILE__) + '/markdown_fragments/presenter_notes_fragment.rb'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module MarkdownPrawn
|
2
|
+
class FileParser < Parser
|
3
|
+
|
4
|
+
# Give this the path to a file and (if it exists), it'll generate
|
5
|
+
# a PDF version of the markdown there.
|
6
|
+
#
|
7
|
+
def initialize(file_path)
|
8
|
+
file_path = File.expand_path(file_path)
|
9
|
+
if !File.exist?(file_path)
|
10
|
+
raise Errno::ENOENT.new("#{file_path} could not be found") and return
|
11
|
+
else
|
12
|
+
@content = detab(IO.read(file_path).gsub(/\r\n?/, "\n")).split("\n")
|
13
|
+
end
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../markdown_fragments.rb'
|
2
|
+
|
3
|
+
module MarkdownPrawn
|
4
|
+
|
5
|
+
# Horribly bodgy and wrong markdown parser which should just about do
|
6
|
+
# for a proof of concept. Some of the code comes from mislav's original
|
7
|
+
# BlueCloth since I cant find the source of a newer versoin.
|
8
|
+
#
|
9
|
+
class Parser
|
10
|
+
attr_accessor :links_list, :images_list, :document_structure
|
11
|
+
|
12
|
+
def initialize(document_structure = [])
|
13
|
+
@links_list = { :urls_seen => [], :object => LinksReferenceFragment.new }
|
14
|
+
@document_structure = []
|
15
|
+
@images_list = []
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns a Prawn::Document, accepts the same options as Prawn does when creating
|
19
|
+
# a new document, but defaults to creating pages in Portrait and at A4 size.
|
20
|
+
#
|
21
|
+
# Uses parse! rather than parse to ensure that the slate is always clean when
|
22
|
+
# generating the PDF.
|
23
|
+
#
|
24
|
+
def to_pdf(options = {})
|
25
|
+
parse!
|
26
|
+
options = options.merge({ :page_layout => :portrait, :page_size => 'A4' })
|
27
|
+
pdf = Prawn::Document.new(options)
|
28
|
+
@document_structure.each { |markdown_fragment| markdown_fragment.render_on(pdf) }
|
29
|
+
pdf
|
30
|
+
end
|
31
|
+
|
32
|
+
# Clears out the current sate of +@document_structure+ and then parses +@content+ content
|
33
|
+
#
|
34
|
+
def parse!
|
35
|
+
@document_structure = []
|
36
|
+
parse
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse
|
40
|
+
paragraph = ParagraphFragment.new
|
41
|
+
list = ListFragment.new
|
42
|
+
in_list = false
|
43
|
+
in_code_block = false
|
44
|
+
code = CodeFragment.new
|
45
|
+
|
46
|
+
|
47
|
+
@content.each_with_index do |line, index|
|
48
|
+
line = process_inline_formatting(line)
|
49
|
+
|
50
|
+
# Assume everything is part of a paragraph by default and
|
51
|
+
# add its content to the current in-scope paragraph object.
|
52
|
+
#
|
53
|
+
paragraph.content << line
|
54
|
+
if line == ""
|
55
|
+
unless paragraph.content.empty?
|
56
|
+
@document_structure << paragraph
|
57
|
+
paragraph = ParagraphFragment.new
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Deal with inline headings
|
62
|
+
#
|
63
|
+
unless /^(#+)(\s?)\S/.match(line).nil?
|
64
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
65
|
+
hashes = $1.dup
|
66
|
+
heading = HeadingFragment.new([line.gsub(hashes,'')])
|
67
|
+
heading.level = hashes.length
|
68
|
+
@document_structure << heading
|
69
|
+
end
|
70
|
+
|
71
|
+
# Deal with Level 1 Headings
|
72
|
+
#
|
73
|
+
if !/^(=)+$/.match(line).nil?
|
74
|
+
paragraph.content = paragraph.content.delete_if do |item|
|
75
|
+
item == line || item == @content[index - 1]
|
76
|
+
end
|
77
|
+
heading = HeadingFragment.new([@content[index - 1]])
|
78
|
+
heading.level = 1
|
79
|
+
@document_structure << heading
|
80
|
+
end
|
81
|
+
|
82
|
+
# Deal with Level 2 Headings or horizontal rules.
|
83
|
+
#
|
84
|
+
if !/^(-)+$/.match(line).nil?
|
85
|
+
if @content[index - 1].strip == ''
|
86
|
+
# Assume it's a horizontal rule
|
87
|
+
#
|
88
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
89
|
+
@document_structure << HorizontalRuleFragment.new
|
90
|
+
else
|
91
|
+
paragraph.content = paragraph.content.delete_if do |item|
|
92
|
+
item == line || item == @content[index - 1]
|
93
|
+
end
|
94
|
+
heading = HeadingFragment.new([@content[index - 1]])
|
95
|
+
heading.level = 2
|
96
|
+
@document_structure << heading
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Deal with all other kinds of horizontal rules
|
101
|
+
#
|
102
|
+
if !/^(\*+)(\s)?(\*+)(\s)?(\*+)/.match(line).nil? || !/^(-+)(\s)(-+)(\s)(-+)/.match(line).nil?
|
103
|
+
if @content[index - 1].strip == ''
|
104
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
105
|
+
@document_structure << HorizontalRuleFragment.new
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# Try to deal with lists.
|
111
|
+
#
|
112
|
+
if in_list
|
113
|
+
# We're in a list just now.
|
114
|
+
#
|
115
|
+
|
116
|
+
# Remove the content from the paragraph where it will have
|
117
|
+
# automatically been appended
|
118
|
+
#
|
119
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
120
|
+
|
121
|
+
# Check to see if we've got a new list item.
|
122
|
+
#
|
123
|
+
if (!/^(\s*)?\*\s/.match(line).nil? || !/^(\s*)?\d+\.\s/.match(line).nil?)
|
124
|
+
|
125
|
+
# Find out if this new list item is for a different type of list
|
126
|
+
# and deal with that before adding the new list item.
|
127
|
+
#
|
128
|
+
if list.ordered? && !/^(\s*)?\*\s/.match(line).nil?
|
129
|
+
@document_structure << list
|
130
|
+
list = ListFragment.new
|
131
|
+
elsif !list.ordered? && !/^(\s*)?\d+\.\s/.match(line).nil?
|
132
|
+
@document_structure << list
|
133
|
+
list = ListFragment.new
|
134
|
+
list.ordered = true
|
135
|
+
end
|
136
|
+
|
137
|
+
# Remove the list style and add the new list item.
|
138
|
+
#
|
139
|
+
list.content << line.sub(/^(\s*)?\*\s/,'').sub(/^(\s*)?\d+\.\s/,'')
|
140
|
+
|
141
|
+
else
|
142
|
+
# If this line isn't a new list item, then it's a continuation for the current
|
143
|
+
# list item.
|
144
|
+
#
|
145
|
+
list.content[-1] += line
|
146
|
+
end
|
147
|
+
|
148
|
+
# If the current line is empty, then we're done with the list.
|
149
|
+
#
|
150
|
+
if line == ''
|
151
|
+
@document_structure << list
|
152
|
+
list = ListFragment.new
|
153
|
+
in_list = false
|
154
|
+
end
|
155
|
+
else
|
156
|
+
# Not currently in a list, but we've detected a list item
|
157
|
+
#
|
158
|
+
if (!/^(\s*)?\*\s/.match(line).nil? || !/^(\s*)?\d+\.\s/.match(line).nil?)
|
159
|
+
ordered = false
|
160
|
+
ordered = true if !/^\s+\d+\.\s/.match(line).nil?
|
161
|
+
list = ListFragment.new
|
162
|
+
list.ordered = ordered
|
163
|
+
list.content << line.sub(/^(\s*)?\*\s/,'').sub(/^(\s*)?\d+\.\s/,'')
|
164
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
165
|
+
in_list = true
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
# Try to deal with code blocks
|
171
|
+
#
|
172
|
+
if in_code_block
|
173
|
+
if (!/(\s{4,})(\$\s)?(\w{1,})/.match(line).nil? || !/(\t{1,})(\$\s)?(\w{1,})/.match(line).nil? )
|
174
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
175
|
+
code.content << line
|
176
|
+
end
|
177
|
+
if line == ''
|
178
|
+
@document_structure << code
|
179
|
+
code = CodeFragment.new
|
180
|
+
in_code_block = false
|
181
|
+
end
|
182
|
+
else
|
183
|
+
if (!/(\s{4,})(\$\s)?(\w{1,})/.match(line).nil? || !/(\t{1,})(\$\s)?(\w{1,})/.match(line).nil? )
|
184
|
+
code = CodeFragment.new
|
185
|
+
code.content << line
|
186
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
187
|
+
in_code_block = true
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Deal with a link reference by adding it ot the list of references
|
192
|
+
#
|
193
|
+
if !/^(\[\S+\]){1}:\s(\S+)\s?(.+)?/.match(line).nil?
|
194
|
+
reference, url, title = $1, $2, $3
|
195
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
196
|
+
@links_list[:urls_seen] << url
|
197
|
+
@links_list[:object].content << [ reference, url, "#{title}" ]
|
198
|
+
end
|
199
|
+
|
200
|
+
# Deal with inline images
|
201
|
+
#
|
202
|
+
line.scan(/(?:^|\s)?(\!\[(?:.+?)\]\((.+?)\))/) do |val|
|
203
|
+
paragraph.content[-1] = paragraph.content[-1].gsub(val[0],'')
|
204
|
+
@document_structure << ImageFragment.new([val[1]])
|
205
|
+
end
|
206
|
+
end
|
207
|
+
if !list.content.empty? && ! @document_structure.include?(list)
|
208
|
+
@document_structure << list
|
209
|
+
list = ListFragment.new
|
210
|
+
end
|
211
|
+
if !code.content.empty? && !@document_structure.include?(code)
|
212
|
+
@document_structure << code
|
213
|
+
code = CodeFragment.new
|
214
|
+
end
|
215
|
+
@document_structure << paragraph unless paragraph.content == ''
|
216
|
+
@document_structure << @links_list[:object] if !@links_list[:urls_seen].empty?
|
217
|
+
end
|
218
|
+
|
219
|
+
private
|
220
|
+
|
221
|
+
def detab(string, tabwidth = 2)
|
222
|
+
string.split("\n").collect { |line|
|
223
|
+
line.gsub(/(.*?)\t/) do
|
224
|
+
$1 + ' ' * (tabwidth - $1.length % tabwidth)
|
225
|
+
end
|
226
|
+
}.join("\n")
|
227
|
+
end
|
228
|
+
|
229
|
+
# Only do Inline formatting for versions of Prawn which support it.
|
230
|
+
#
|
231
|
+
def process_inline_formatting(str)
|
232
|
+
breg = [ %r{ \b(\_\_) (\S|\S.*?\S) \1\b }x, %r{ (\*\*) (\S|\S.*?\S) \1 }x ]
|
233
|
+
ireg = [ %r{ (\*) (\S|\S.*?\S) \1 }x, %r{ \b(_) (\S|\S.*?\S) \1\b }x ]
|
234
|
+
if Prawn::VERSION =~ /^0.1/ || Prawn::VERSION =~ /^1/
|
235
|
+
str.gsub(breg[0], %{<b>\\2</b>} ).gsub(breg[1], %{<b>\\2</b>} ).gsub(ireg[0], %{<i>\\2</i>} ).gsub(ireg[1], %{<i>\\2</i>} )
|
236
|
+
else
|
237
|
+
str.gsub(breg[0], %{\\2} ).gsub(breg[1], %{\\2} ).gsub(ireg[0], %{\\2} ).gsub(ireg[1], %{\\2} )
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module MarkdownPrawn
|
2
|
+
class StringParser < Parser
|
3
|
+
# Take a string or an object which responds to to_s and attemps to
|
4
|
+
# parse markdown in it.
|
5
|
+
def initialize(string_to_convert)
|
6
|
+
string_to_convert = string_to_convert.to_s
|
7
|
+
@content = detab(string_to_convert.gsub(/\r\n?/, "\n")).strip.split("\n")
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class ShowOffSlide
|
2
|
+
attr_accessor :components, :content
|
3
|
+
|
4
|
+
def initialize(content = '', options = {})
|
5
|
+
@components = []
|
6
|
+
@options = { :size => 'A4', :layout => :landscape }.merge(options)
|
7
|
+
@content = content
|
8
|
+
end
|
9
|
+
|
10
|
+
def render_on(pdf)
|
11
|
+
parse if @components.empty?
|
12
|
+
pdf.start_new_page(@options)
|
13
|
+
pdf.font_size(20)
|
14
|
+
@components.each { |c| c.render_on(pdf) }
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def parse
|
20
|
+
|
21
|
+
s =/(\s)?.notes\s(.*)(\n)?/.match(@content)
|
22
|
+
if !s.nil?
|
23
|
+
@slide_notes = $2
|
24
|
+
@content.gsub!(".notes #{@slide_notes}",'')
|
25
|
+
else
|
26
|
+
@slide_notes = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
sp = MarkdownPrawn::StringParser.new(@content)
|
30
|
+
sp.parse!
|
31
|
+
#@components << ParagraphFragment.new([@content])
|
32
|
+
@components = sp.document_structure
|
33
|
+
if @slide_notes
|
34
|
+
@components << PresenterNotesFragment.new([@slide_notes])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def default_options
|
39
|
+
{ :align => :center }
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class ShowoffSlideStream
|
2
|
+
def initialize(paths_for_markdown)
|
3
|
+
content = ''
|
4
|
+
paths_for_markdown.each { |p| content << IO.read(p) }
|
5
|
+
@slides = []
|
6
|
+
content.split(/!SLIDE/).each do |slide|
|
7
|
+
@slides << ShowOffSlide.new(CGI.unescapeHTML(slide))
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_pdf
|
12
|
+
pdf = Prawn::Document.new(:page_size => 'A4', :page_layout => :portrait)
|
13
|
+
pdf.text ShowOffUtils.showoff_title, :size => 45, :inline_format => true
|
14
|
+
pdf.text "by <b>#{ShowOffUtils.showoff_author}</b>", :size => 30, :inline_format => true
|
15
|
+
pdf.move_down(200)
|
16
|
+
pdf.text ShowOffUtils.showoff_description, :size => 20
|
17
|
+
pdf.bounding_box([0,100], :width => pdf.bounds.width, :height => 150) do
|
18
|
+
pdf.horizontal_rule
|
19
|
+
pdf.stroke
|
20
|
+
pdf.move_down(5)
|
21
|
+
pdf.text 'Generated by <b>showoff2pdf</b> by Ryan Stenhouse', :inline_format => true
|
22
|
+
pdf.text '<link href="http://github.com/HHRy"><u>http://github.com/HHRy</u></link> | <link href="http://ryanstenhouse.eu"><u>http://ryanstenhouse.eu</u></link>', :inline_format => true
|
23
|
+
end
|
24
|
+
@slides.each { |slide| slide.render_on(pdf) }
|
25
|
+
pdf
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class ShowOffUtils
|
2
|
+
def self.showoff_author(dir = '.')
|
3
|
+
index = File.join(dir, ShowOffUtils::SHOWOFF_JSON_FILE )
|
4
|
+
order = nil
|
5
|
+
if File.exists?(index)
|
6
|
+
data = JSON.parse(File.read(index))
|
7
|
+
data.is_a?(Hash) && data['author'] || "Anonymous"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.showoff_description(dir = '.')
|
12
|
+
index = File.join(dir, ShowOffUtils::SHOWOFF_JSON_FILE )
|
13
|
+
order = nil
|
14
|
+
if File.exists?(index)
|
15
|
+
data = JSON.parse(File.read(index))
|
16
|
+
data.is_a?(Hash) && data['description'] || ""
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
Binary file
|
@@ -0,0 +1,23 @@
|
|
1
|
+
description = "ShowOff slides can now be translated into semi-useful PDF documents for printing out and handing out at your talks, using Markdown Prawn and the Prawn libary."
|
2
|
+
Gem::Specification.new do |spec|
|
3
|
+
spec.name = "show_off_pdf"
|
4
|
+
spec.version = '0.0.1.pre'
|
5
|
+
spec.platform = Gem::Platform::RUBY
|
6
|
+
spec.files = Dir.glob("{bin,lib,.}/**/**/*") +
|
7
|
+
["README.md","COPYING.md",'LICENSE', "show_off_pdf.gemspec"]
|
8
|
+
spec.require_path = "lib"
|
9
|
+
spec.required_ruby_version = '>= 1.8.7'
|
10
|
+
spec.required_rubygems_version = ">= 1.3.6"
|
11
|
+
spec.test_files = Dir[ "test/*_test.rb" ]
|
12
|
+
spec.has_rdoc = false
|
13
|
+
spec.author = "Ryan Stenhouse"
|
14
|
+
spec.email = "ryan@ryanstenhouse.eu"
|
15
|
+
spec.rubyforge_project = "show_off_pdf"
|
16
|
+
spec.add_dependency('prawn', '~>0.10')
|
17
|
+
spec.add_dependency('showoff', '~>0.3.2')
|
18
|
+
|
19
|
+
spec.homepage = "http://ryanstenhouse.eu"
|
20
|
+
spec.summary = description
|
21
|
+
spec.description = description
|
22
|
+
spec.executables << 'showoff2pdf'
|
23
|
+
end
|
data/show_off_pdf.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'prawn'
|
4
|
+
require File.dirname(__FILE__) + '/lib/markdown_parser.rb'
|
5
|
+
require File.dirname(__FILE__) + '/lib/show_off_utils.rb'
|
6
|
+
require File.dirname(__FILE__) + '/lib/show_off_slide_stream.rb'
|
7
|
+
require File.dirname(__FILE__) + '/lib/show_off_slide.rb'
|
8
|
+
require 'cgi'
|
9
|
+
require 'showoff'
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: show_off_pdf
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 961915968
|
5
|
+
prerelease: true
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
- pre
|
11
|
+
version: 0.0.1.pre
|
12
|
+
platform: ruby
|
13
|
+
authors:
|
14
|
+
- Ryan Stenhouse
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2010-11-16 00:00:00 +00:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: prawn
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 31
|
31
|
+
segments:
|
32
|
+
- 0
|
33
|
+
- 10
|
34
|
+
version: "0.10"
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: showoff
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 23
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
- 3
|
49
|
+
- 2
|
50
|
+
version: 0.3.2
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
description: ShowOff slides can now be translated into semi-useful PDF documents for printing out and handing out at your talks, using Markdown Prawn and the Prawn libary.
|
54
|
+
email: ryan@ryanstenhouse.eu
|
55
|
+
executables:
|
56
|
+
- showoff2pdf
|
57
|
+
extensions: []
|
58
|
+
|
59
|
+
extra_rdoc_files: []
|
60
|
+
|
61
|
+
files:
|
62
|
+
- bin/showoff2pdf
|
63
|
+
- lib/markdown_fragments/code_fragment.rb
|
64
|
+
- lib/markdown_fragments/heading_fragment.rb
|
65
|
+
- lib/markdown_fragments/horizontal_rule_fragment.rb
|
66
|
+
- lib/markdown_fragments/image_fragment.rb
|
67
|
+
- lib/markdown_fragments/links_reference_fragment.rb
|
68
|
+
- lib/markdown_fragments/list_fragment.rb
|
69
|
+
- lib/markdown_fragments/markdown_fragment.rb
|
70
|
+
- lib/markdown_fragments/page_break_fragment.rb
|
71
|
+
- lib/markdown_fragments/paragraph_fragment.rb
|
72
|
+
- lib/markdown_fragments/presenter_notes_fragment.rb
|
73
|
+
- lib/markdown_fragments.rb
|
74
|
+
- lib/markdown_parser/file_parser.rb
|
75
|
+
- lib/markdown_parser/parser.rb
|
76
|
+
- lib/markdown_parser/string_parser.rb
|
77
|
+
- lib/markdown_parser.rb
|
78
|
+
- lib/markdown_prawn_exceptions.rb
|
79
|
+
- lib/show_off_slide.rb
|
80
|
+
- lib/show_off_slide_stream.rb
|
81
|
+
- lib/show_off_utils.rb
|
82
|
+
- ./bin/showoff2pdf
|
83
|
+
- ./COPYING.md
|
84
|
+
- ./example/one/01_slide.md
|
85
|
+
- ./example/one/images.png
|
86
|
+
- ./example/showoff.json
|
87
|
+
- ./example.pdf
|
88
|
+
- ./HACKING.md
|
89
|
+
- ./lib/markdown_fragments/code_fragment.rb
|
90
|
+
- ./lib/markdown_fragments/heading_fragment.rb
|
91
|
+
- ./lib/markdown_fragments/horizontal_rule_fragment.rb
|
92
|
+
- ./lib/markdown_fragments/image_fragment.rb
|
93
|
+
- ./lib/markdown_fragments/links_reference_fragment.rb
|
94
|
+
- ./lib/markdown_fragments/list_fragment.rb
|
95
|
+
- ./lib/markdown_fragments/markdown_fragment.rb
|
96
|
+
- ./lib/markdown_fragments/page_break_fragment.rb
|
97
|
+
- ./lib/markdown_fragments/paragraph_fragment.rb
|
98
|
+
- ./lib/markdown_fragments/presenter_notes_fragment.rb
|
99
|
+
- ./lib/markdown_fragments.rb
|
100
|
+
- ./lib/markdown_parser/file_parser.rb
|
101
|
+
- ./lib/markdown_parser/parser.rb
|
102
|
+
- ./lib/markdown_parser/string_parser.rb
|
103
|
+
- ./lib/markdown_parser.rb
|
104
|
+
- ./lib/markdown_prawn_exceptions.rb
|
105
|
+
- ./lib/show_off_slide.rb
|
106
|
+
- ./lib/show_off_slide_stream.rb
|
107
|
+
- ./lib/show_off_utils.rb
|
108
|
+
- ./LICENSE
|
109
|
+
- ./README.md
|
110
|
+
- ./show_off_pdf-0.0.1.pre.gem
|
111
|
+
- ./show_off_pdf.gemspec
|
112
|
+
- ./show_off_pdf.rb
|
113
|
+
- README.md
|
114
|
+
- COPYING.md
|
115
|
+
- LICENSE
|
116
|
+
- show_off_pdf.gemspec
|
117
|
+
has_rdoc: true
|
118
|
+
homepage: http://ryanstenhouse.eu
|
119
|
+
licenses: []
|
120
|
+
|
121
|
+
post_install_message:
|
122
|
+
rdoc_options: []
|
123
|
+
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
hash: 57
|
132
|
+
segments:
|
133
|
+
- 1
|
134
|
+
- 8
|
135
|
+
- 7
|
136
|
+
version: 1.8.7
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
hash: 23
|
143
|
+
segments:
|
144
|
+
- 1
|
145
|
+
- 3
|
146
|
+
- 6
|
147
|
+
version: 1.3.6
|
148
|
+
requirements: []
|
149
|
+
|
150
|
+
rubyforge_project: show_off_pdf
|
151
|
+
rubygems_version: 1.3.7
|
152
|
+
signing_key:
|
153
|
+
specification_version: 3
|
154
|
+
summary: ShowOff slides can now be translated into semi-useful PDF documents for printing out and handing out at your talks, using Markdown Prawn and the Prawn libary.
|
155
|
+
test_files: []
|
156
|
+
|