markdown_prawn 0.0.1.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +11 -0
- data/bin/md2pdf +12 -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 +25 -0
- data/lib/markdown_fragments/links_reference_fragment.rb +17 -0
- data/lib/markdown_fragments/list_fragment.rb +40 -0
- data/lib/markdown_fragments/markdown_fragment.rb +13 -0
- data/lib/markdown_fragments/paragraph_fragment.rb +21 -0
- data/lib/markdown_fragments.rb +7 -0
- data/lib/markdown_parser/file_parser.rb +18 -0
- data/lib/markdown_parser/parser.rb +213 -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/markdown_prawn.gemspec +21 -0
- data/test/fixtures/ordered_lists.mdown +3 -0
- data/test/fixtures/paragraphs.mdown +8 -0
- data/test/fixtures/unordered_lists.mdown +3 -0
- data/test/helper.rb +4 -0
- data/test/test_lists_handling.rb +24 -0
- data/test/test_paragraph_handling.rb +18 -0
- metadata +107 -0
data/Rakefile
ADDED
data/bin/md2pdf
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Markdown to PDF by Ryan Stenhouse <ryan@ryanstenhouse.eu>
|
4
|
+
# November 1st 2010
|
5
|
+
#
|
6
|
+
# Takes input from standard in, expected to be a markdown document
|
7
|
+
# and renders a PDF to standard out.
|
8
|
+
#
|
9
|
+
root = File.expand_path(File.dirname(__FILE__)+ '/../')
|
10
|
+
load root + '/markdown_prawn.rb'
|
11
|
+
content = $stdin.read
|
12
|
+
puts MarkdownPrawn::StringParser.new(content).to_pdf.render
|
@@ -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 @content.join(' '), arguments
|
8
|
+
pdf_object.move_down(@level * 2)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def _default_render_options
|
14
|
+
options = { :size => (40 - (8*@level)), :align => :left, :leading => 2, :weight => :bold }
|
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,25 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
class ImageFragment < MarkdownFragment
|
5
|
+
def render_on(pdf_object)
|
6
|
+
if is_remote_uri?
|
7
|
+
filename = @content.first.split('/').last
|
8
|
+
file_path = "#{Dir.tmpdir}/#{filename}"
|
9
|
+
content = Net::HTTP.get(URI.parse(@content.first))
|
10
|
+
File.open(file_path, 'w') do |f|
|
11
|
+
f.puts content
|
12
|
+
end
|
13
|
+
else
|
14
|
+
file_path = File.expand_path(@content.first)
|
15
|
+
end
|
16
|
+
pdf_object.image file_path
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def is_remote_uri?
|
22
|
+
!/^(http:|https:)/.match(@content.first).nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
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,40 @@
|
|
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
|
+
end
|
23
|
+
pdf_object.move_down(5)
|
24
|
+
end
|
25
|
+
|
26
|
+
def ordered?
|
27
|
+
@ordered == true
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def _default_render_options
|
33
|
+
options = {}
|
34
|
+
if Prawn::VERSION =~ /^0.1/ || Prawn::VERSION =~ /^1/
|
35
|
+
options = options.merge({:cell_style => { :inline_format => true}})
|
36
|
+
end
|
37
|
+
options
|
38
|
+
end
|
39
|
+
|
40
|
+
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,7 @@
|
|
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'
|
@@ -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,213 @@
|
|
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
|
+
@content.each_with_index do |line, index|
|
44
|
+
line = process_inline_formatting(line)
|
45
|
+
|
46
|
+
# Assume everything is part of a paragraph by default and
|
47
|
+
# add its content to the current in-scope paragraph object.
|
48
|
+
#
|
49
|
+
paragraph.content << line
|
50
|
+
if line == ""
|
51
|
+
unless paragraph.content.empty?
|
52
|
+
@document_structure << paragraph
|
53
|
+
paragraph = ParagraphFragment.new
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Deal with inline headings
|
58
|
+
#
|
59
|
+
unless /^(#+)(\s?)\S/.match(line).nil?
|
60
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
61
|
+
hashes = $1.dup
|
62
|
+
heading = HeadingFragment.new([line.gsub(hashes,'')])
|
63
|
+
heading.level = hashes.length
|
64
|
+
@document_structure << heading
|
65
|
+
end
|
66
|
+
|
67
|
+
# Deal with Level 1 Headings
|
68
|
+
#
|
69
|
+
if !/^(=)+$/.match(line).nil?
|
70
|
+
paragraph.content = paragraph.content.delete_if do |item|
|
71
|
+
item == line || item == @content[index - 1]
|
72
|
+
end
|
73
|
+
heading = HeadingFragment.new([@content[index - 1]])
|
74
|
+
heading.level = 1
|
75
|
+
@document_structure << heading
|
76
|
+
end
|
77
|
+
|
78
|
+
# Deal with Level 2 Headings or horizontal rules.
|
79
|
+
#
|
80
|
+
if !/^(-)+$/.match(line).nil?
|
81
|
+
if @content[index - 1].strip == ''
|
82
|
+
# Assume it's a horizontal rule
|
83
|
+
#
|
84
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
85
|
+
@document_structure << HorizontalRuleFragment.new
|
86
|
+
else
|
87
|
+
paragraph.content = paragraph.content.delete_if do |item|
|
88
|
+
item == line || item == @content[index - 1]
|
89
|
+
end
|
90
|
+
heading = HeadingFragment.new([@content[index - 1]])
|
91
|
+
heading.level = 2
|
92
|
+
@document_structure << heading
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Deal with all other kinds of horizontal rules
|
97
|
+
#
|
98
|
+
if !/^(\*+)(\s)?(\*+)(\s)?(\*+)/.match(line).nil? || !/^(-+)(\s)(-+)(\s)(-+)/.match(line).nil?
|
99
|
+
if @content[index - 1].strip == ''
|
100
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
101
|
+
@document_structure << HorizontalRuleFragment.new
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Try to deal with lists.
|
106
|
+
#
|
107
|
+
if in_list
|
108
|
+
# We're in a list just now.
|
109
|
+
#
|
110
|
+
|
111
|
+
# Remove the content from the paragraph where it will have
|
112
|
+
# automatically been appended
|
113
|
+
#
|
114
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
115
|
+
|
116
|
+
# Check to see if we've got a new list item.
|
117
|
+
#
|
118
|
+
if (!/^\s+\*\s/.match(line).nil? || !/^\s+\d+\.\s/.match(line).nil?)
|
119
|
+
|
120
|
+
# Find out if this new list item is for a different type of list
|
121
|
+
# and deal with that before adding the new list item.
|
122
|
+
#
|
123
|
+
if list.ordered? && !/^\s+\*\s/.match(line).nil?
|
124
|
+
@document_structure << list
|
125
|
+
list = ListFragment.new
|
126
|
+
elsif !list.ordered? && !/^\s+\d+\.\s/.match(line).nil?
|
127
|
+
@document_structure << list
|
128
|
+
list = ListFragment.new
|
129
|
+
list.ordered = true
|
130
|
+
end
|
131
|
+
|
132
|
+
# Remove the list style and add the new list item.
|
133
|
+
#
|
134
|
+
list.content << line.sub(/^\s+\*\s/,'').sub(/^\s+\d+\.\s/,'')
|
135
|
+
|
136
|
+
else
|
137
|
+
# If this line isn't a new list item, then it's a continuation for the current
|
138
|
+
# list item.
|
139
|
+
#
|
140
|
+
list.content[-1] += line
|
141
|
+
end
|
142
|
+
|
143
|
+
# If the current line is empty, then we're done with the list.
|
144
|
+
#
|
145
|
+
if line == ''
|
146
|
+
@document_structure << list
|
147
|
+
list = ListFragment.new
|
148
|
+
in_list = false
|
149
|
+
end
|
150
|
+
else
|
151
|
+
# Not currently in a list, but we've detected a list item
|
152
|
+
#
|
153
|
+
if (!/^\s+\*\s/.match(line).nil? || !/^\s+\d+\.\s/.match(line).nil?)
|
154
|
+
ordered = false
|
155
|
+
ordered = true if !/^\s+\d+\.\s/.match(line).nil?
|
156
|
+
list = ListFragment.new
|
157
|
+
list.ordered = ordered
|
158
|
+
list.content << line.sub(/^\s+\*\s/,'').sub(/^\s+\d+\.\s/,'')
|
159
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
160
|
+
in_list = true
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
# Deal with a link reference by adding it ot the list of references
|
166
|
+
#
|
167
|
+
if !/^(\[\S+\]){1}:\s(\S+)\s?(.+)?/.match(line).nil?
|
168
|
+
reference, url, title = $1, $2, $3
|
169
|
+
paragraph.content = paragraph.content.delete_if { |i| i == line }
|
170
|
+
@links_list[:urls_seen] << url
|
171
|
+
@links_list[:object].content << [ reference, url, "#{title}" ]
|
172
|
+
end
|
173
|
+
|
174
|
+
# Deal with inline images
|
175
|
+
#
|
176
|
+
line.scan(/(?:^|\s)?(\!\[(?:.+?)\]\((.+?)\))/) do |val|
|
177
|
+
line.gsub(val[0],'')
|
178
|
+
@document_structure << ImageFragment.new([val[1]])
|
179
|
+
end
|
180
|
+
end
|
181
|
+
if !list.content.empty? && ! @document_structure.include?(list)
|
182
|
+
@document_structure << list
|
183
|
+
list = ListFragment.new
|
184
|
+
end
|
185
|
+
@document_structure << paragraph unless paragraph.content == ''
|
186
|
+
@document_structure << @links_list[:object] if !@links_list[:urls_seen].empty?
|
187
|
+
end
|
188
|
+
|
189
|
+
private
|
190
|
+
|
191
|
+
def detab(string, tabwidth = 2)
|
192
|
+
string.split("\n").collect { |line|
|
193
|
+
line.gsub(/(.*?)\t/) do
|
194
|
+
$1 + ' ' * (tabwidth - $1.length % tabwidth)
|
195
|
+
end
|
196
|
+
}.join("\n")
|
197
|
+
end
|
198
|
+
|
199
|
+
# Only do Inline formatting for versions of Prawn which support it.
|
200
|
+
#
|
201
|
+
def process_inline_formatting(str)
|
202
|
+
breg = [ %r{ \b(\_\_) (\S|\S.*?\S) \1\b }x, %r{ (\*\*) (\S|\S.*?\S) \1 }x ]
|
203
|
+
ireg = [ %r{ (\*) (\S|\S.*?\S) \1 }x, %r{ \b(_) (\S|\S.*?\S) \1\b }x ]
|
204
|
+
if Prawn::VERSION =~ /^0.1/ || Prawn::VERSION =~ /^1/
|
205
|
+
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>} )
|
206
|
+
else
|
207
|
+
str.gsub(breg[0], %{\\2} ).gsub(breg[1], %{\\2} ).gsub(ireg[0], %{\\2} ).gsub(ireg[1], %{\\2} )
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
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")).split("\n")
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
description = "Markdown Parawn is a library and an executable strip which allow you to generate a PDF from any valid Markdown."
|
2
|
+
Gem::Specification.new do |spec|
|
3
|
+
spec.name = "markdown_prawn"
|
4
|
+
spec.version = '0.0.1.pre'
|
5
|
+
spec.platform = Gem::Platform::RUBY
|
6
|
+
spec.files = Dir.glob("{bin,lib,test}/**/**/*") +
|
7
|
+
["Rakefile", "markdown_prawn.gemspec"]
|
8
|
+
spec.require_path = "lib"
|
9
|
+
spec.required_ruby_version = '>= 1.8.7'
|
10
|
+
spec.required_rubygems_version = ">= 1.3.6"
|
11
|
+
|
12
|
+
spec.test_files = Dir[ "test/*_test.rb" ]
|
13
|
+
spec.has_rdoc = false
|
14
|
+
spec.author = "Ryan Stenhouse"
|
15
|
+
spec.email = "ryan@ryanstenhouse.eu"
|
16
|
+
spec.rubyforge_project = "markdown_prawn"
|
17
|
+
spec.add_dependency('prawn', '~>0.10')
|
18
|
+
spec.homepage = "http://ryanstenhouse.eu"
|
19
|
+
spec.summary = description
|
20
|
+
spec.description = description
|
21
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper.rb'
|
2
|
+
|
3
|
+
class TestListsHandling < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@unordered = MarkdownPrawn::FileParser.new(File.expand_path(File.dirname(__FILE__) + '/fixtures/unordered_lists.mdown'))
|
7
|
+
@ordered = MarkdownPrawn::FileParser.new(File.expand_path(File.dirname(__FILE__) + '/fixtures/ordered_lists.mdown'))
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_document_structure_is_correct_for_unordered_lists
|
11
|
+
@unordered.parse
|
12
|
+
assert !@unordered.document_structure.empty?
|
13
|
+
assert_equal ListFragment, @unordered.document_structure[0].class
|
14
|
+
assert_equal false, @unordered.document_structure[0].ordered?
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_document_structure_is_correct_for_ordered_lists
|
18
|
+
@ordered.parse
|
19
|
+
assert !@ordered.document_structure.empty?
|
20
|
+
assert_equal ListFragment, @ordered.document_structure[0].class
|
21
|
+
assert_equal true, @ordered.document_structure[0].ordered?
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper.rb'
|
2
|
+
|
3
|
+
class TestParagraphHandling < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@paragraphs = MarkdownPrawn::FileParser.new(File.expand_path(File.dirname(__FILE__) + '/fixtures/paragraphs.mdown'))
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_document_structure_is_correct_for_paragraphs
|
10
|
+
@paragraphs.parse
|
11
|
+
assert !@paragraphs.document_structure.empty?
|
12
|
+
assert_equal 2, @paragraphs.document_structure.nitems
|
13
|
+
@paragraphs.document_structure.each do |fragment|
|
14
|
+
assert_equal ParagraphFragment, fragment.class
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: markdown_prawn
|
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-01 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
|
+
description: Markdown Parawn is a library and an executable strip which allow you to generate a PDF from any valid Markdown.
|
38
|
+
email: ryan@ryanstenhouse.eu
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
files:
|
46
|
+
- bin/md2pdf
|
47
|
+
- lib/markdown_fragments.rb
|
48
|
+
- lib/markdown_parser/parser.rb
|
49
|
+
- lib/markdown_parser/file_parser.rb
|
50
|
+
- lib/markdown_parser/string_parser.rb
|
51
|
+
- lib/markdown_parser.rb
|
52
|
+
- lib/markdown_fragments/paragraph_fragment.rb
|
53
|
+
- lib/markdown_fragments/markdown_fragment.rb
|
54
|
+
- lib/markdown_fragments/image_fragment.rb
|
55
|
+
- lib/markdown_fragments/heading_fragment.rb
|
56
|
+
- lib/markdown_fragments/links_reference_fragment.rb
|
57
|
+
- lib/markdown_fragments/list_fragment.rb
|
58
|
+
- lib/markdown_fragments/horizontal_rule_fragment.rb
|
59
|
+
- lib/markdown_prawn_exceptions.rb
|
60
|
+
- test/test_lists_handling.rb
|
61
|
+
- test/test_paragraph_handling.rb
|
62
|
+
- test/fixtures/ordered_lists.mdown
|
63
|
+
- test/fixtures/paragraphs.mdown
|
64
|
+
- test/fixtures/unordered_lists.mdown
|
65
|
+
- test/helper.rb
|
66
|
+
- Rakefile
|
67
|
+
- markdown_prawn.gemspec
|
68
|
+
has_rdoc: true
|
69
|
+
homepage: http://ryanstenhouse.eu
|
70
|
+
licenses: []
|
71
|
+
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
hash: 57
|
83
|
+
segments:
|
84
|
+
- 1
|
85
|
+
- 8
|
86
|
+
- 7
|
87
|
+
version: 1.8.7
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 23
|
94
|
+
segments:
|
95
|
+
- 1
|
96
|
+
- 3
|
97
|
+
- 6
|
98
|
+
version: 1.3.6
|
99
|
+
requirements: []
|
100
|
+
|
101
|
+
rubyforge_project: markdown_prawn
|
102
|
+
rubygems_version: 1.3.7
|
103
|
+
signing_key:
|
104
|
+
specification_version: 3
|
105
|
+
summary: Markdown Parawn is a library and an executable strip which allow you to generate a PDF from any valid Markdown.
|
106
|
+
test_files: []
|
107
|
+
|