any2pdf 1.1.2 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/any2pdf.gemspec +1 -1
- data/bin/any2pdf +23 -222
- data/data/pandoc-template.html +8 -0
- data/lib/any2pdf.rb +4 -0
- data/lib/any2pdf/html2pdf.rb +137 -0
- data/lib/any2pdf/md2html.rb +65 -0
- data/lib/any2pdf/metadata.rb +41 -0
- data/lib/any2pdf/style.rb +21 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88abea5eeb8466229a5540bf50f94c2c261fd9da
|
4
|
+
data.tar.gz: c362c3cb62dc9d186bfbfe3500c38695b5bef39b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f64c048509335cbf727aa1fac4d2c9a685e8da289188bfbbdd2ec1a7f3e10a9c2b9a080b23851d8a1c0fac689273455b0a3d7b87c930b3952e53c76155432e46
|
7
|
+
data.tar.gz: d4488d1ec52a0a7d2920c8af780bd7fb57dddb2eabb68cb19ffd76761abdb2c7c144eacb0fc86c02d3f72cbc616db31048c727f35b6a3617d5ac87d279060a98
|
data/any2pdf.gemspec
CHANGED
data/bin/any2pdf
CHANGED
@@ -1,12 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require 'pdfkit'
|
4
3
|
require 'trollop'
|
5
|
-
require 'nokogiri'
|
6
|
-
require 'css_parser'
|
7
|
-
require 'uri'
|
8
|
-
require 'erb'
|
9
4
|
require 'zlog'
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
require 'any2pdf'
|
10
7
|
|
11
8
|
opts = Trollop::options do
|
12
9
|
banner "usage: any2pdf <file>"
|
@@ -16,6 +13,7 @@ opts = Trollop::options do
|
|
16
13
|
opt :stylesheet, "stylesheet to load", :default => ""
|
17
14
|
opt :input, "input file", :default => ""
|
18
15
|
opt :landscape, "if you want landscape instead of portrait"
|
16
|
+
opt :gitinfo, "if you want to add the current commit ID, date, and tag"
|
19
17
|
opt :view_cmd, "command used for viewing", :default => "v %s"
|
20
18
|
opt :view, "what to view (pdf|html|none)", :default => "none"
|
21
19
|
opt :renderer, "what engine to use for pdf creation (pdfkit|xelatex)", default: "pdfkit", type: :string
|
@@ -23,6 +21,7 @@ opts = Trollop::options do
|
|
23
21
|
opt :toc_level, "which depth if headings to include in ToC", :default => 2, :type => :int
|
24
22
|
opt :numbering, "whether to add numbering to all headings"
|
25
23
|
opt :embed, "when active embed js/css files instad of just linking to them"
|
24
|
+
opt :clean, "clean up when done"
|
26
25
|
end
|
27
26
|
|
28
27
|
Zlog.init_stdout loglevel: :warn if not opts[:verbose] and not opts[:debug]
|
@@ -37,228 +36,25 @@ Trollop::die :toc_level, "must not be higher than 6" if opts[:toc_level] > 6
|
|
37
36
|
mdfile = ARGV.first
|
38
37
|
Trollop::die :input, "must be supplied" if mdfile.nil?
|
39
38
|
Trollop::die :input, "#{mdfile} must exist" if not File::exists?(mdfile)
|
39
|
+
htmlfile = mdfile.sub(/.md$/,".html")
|
40
|
+
tmpmdfile = ".~" + mdfile
|
40
41
|
|
41
|
-
|
42
|
-
path = File::expand_path(f)
|
43
|
-
return path if File::exists?(path)
|
44
|
-
return nil
|
45
|
-
end
|
46
|
-
|
47
|
-
def get_style( stylename, type = "css" )
|
48
|
-
rel_path = File.expand_path('../Gemfile/../data', File.dirname(__FILE__))
|
49
|
-
|
50
|
-
if not stylename.nil? and not stylename.empty?
|
51
|
-
a =
|
52
|
-
get_existing(stylename) ||
|
53
|
-
get_existing("#{rel_path}/#{stylename}.#{type}") ||
|
54
|
-
get_existing("#{rel_path}/#{stylename}")
|
55
|
-
return a if not a.nil?
|
56
|
-
Log.warn "couldn't find stylesheet #{stylename}. Trying default.\n"
|
57
|
-
end
|
58
|
-
|
59
|
-
# try default, if the user supplied crap...
|
60
|
-
a = get_existing("#{rel_path}/default.#{type}")
|
61
|
-
return a if not a.nil?
|
62
|
-
Log.error "Couldn't find internal stylesheet in #{rel_path}/default.#{type}. Something is seriously wrong! try reinstalling?\n"
|
63
|
-
""
|
64
|
-
end
|
65
|
-
|
66
|
-
def embed_html( raw, source )
|
67
|
-
begin
|
68
|
-
require 'websnap'
|
69
|
-
w = WebSnap.new( nil, nil )
|
70
|
-
|
71
|
-
# parse raw html contents
|
72
|
-
Log.info "embedding html via websnap"
|
73
|
-
h = Nokogiri::HTML(raw)
|
74
|
-
|
75
|
-
# embed all parts into the html
|
76
|
-
w.spiderHtmlElements( 'file://'+File::expand_path(source), h )
|
77
|
-
|
78
|
-
# return the resulting html as string
|
79
|
-
h.to_s
|
80
|
-
rescue LoadError
|
81
|
-
return raw
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def md2html(file, opts, stylefile)
|
86
|
-
return nil if not file.end_with?(".md")
|
87
|
-
htmlfile = file.sub(/.md$/,".html")
|
88
|
-
htmlfile_raw = htmlfile+".raw.html"
|
89
|
-
|
90
|
-
rel_path = File.expand_path('../Gemfile/../data', File.dirname(__FILE__))
|
91
|
-
|
92
|
-
# prep-work for including style and script
|
93
|
-
style_e = lambda{|f,o| "<style type=\"text/css\" #{o}>\n#{File::read(f)}\n</style>" }
|
94
|
-
style_l = lambda{|f,o| "<link rel=\"stylesheet\" href=\"#{f}\" #{o} />" }
|
95
|
-
script_e = lambda{|f,o| "<script #{o}>\n#{File::read(f)}\n</script>" }
|
96
|
-
script_l = lambda{|f,o| "<script src=\"#{f}\" #{o} ></script>"}
|
97
|
-
style = opts[:embed] ? style_e : style_l
|
98
|
-
script = opts[:embed] ? script_e : script_l
|
99
|
-
|
100
|
-
# get all fields in the heading
|
101
|
-
raw_heading = [
|
102
|
-
# start with stylesheets
|
103
|
-
style.( rel_path+"/boilerplate.css", ''),
|
104
|
-
style.( File::expand_path(stylefile), '' ),
|
105
|
-
style.( rel_path+"/print.css", 'media="print"'),
|
106
|
-
script.( rel_path+"/jquery-1.9.0.min.js", '' ),
|
107
|
-
( opts[:toc] ? script.( rel_path+"/toc_generator.js", '' ) : '' )
|
108
|
-
].join("\n\n")
|
109
|
-
|
110
|
-
# create the html
|
111
|
-
`pandoc "#{file}" -o "#{htmlfile_raw}" --template #{rel_path}/pandoc-template.html --toc`
|
112
|
-
raw_html = File::read htmlfile_raw
|
113
|
-
File.delete htmlfile_raw
|
114
|
-
|
115
|
-
# additional options
|
116
|
-
toc_level = opts[:toc_level]
|
117
|
-
number_headings = (opts[:numbering] == true)
|
118
|
-
|
119
|
-
# actually create the result file
|
120
|
-
renderer = ERB.new(File::read(rel_path + "/template.html.erb"))
|
121
|
-
html = embed_html( renderer.result(binding), file )
|
122
|
-
|
123
|
-
# save the html to file
|
124
|
-
File::write htmlfile, html
|
125
|
-
htmlfile
|
126
|
-
end
|
127
|
-
|
128
|
-
def get_style_options style_file
|
129
|
-
return {} unless File::file? style_file
|
130
|
-
|
131
|
-
declarations = []
|
132
|
-
|
133
|
-
css = CssParser::Parser.new
|
134
|
-
css.load_file! style_file
|
135
|
-
css.each_rule_set do |rule|
|
136
|
-
if rule.selectors.include? '#pdf'
|
137
|
-
rule.each_declaration do |id, params|
|
138
|
-
declarations.push [id, params]
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
# check all rules
|
144
|
-
opts = {}
|
145
|
-
declarations.each do |field,value|
|
146
|
-
if field == 'margin'
|
147
|
-
vals = value.split(' ');
|
148
|
-
if vals.length == 4
|
149
|
-
opts[:margin_top] = vals[0]
|
150
|
-
opts[:margin_right] = vals[1]
|
151
|
-
opts[:margin_bottom] = vals[2]
|
152
|
-
opts[:margin_left] = vals[3]
|
153
|
-
end
|
154
|
-
if vals.length == 2
|
155
|
-
opts[:margin_top] = vals[0]
|
156
|
-
opts[:margin_right] = vals[1]
|
157
|
-
opts[:margin_bottom] = vals[0]
|
158
|
-
opts[:margin_left] = vals[1]
|
159
|
-
end
|
160
|
-
if vals.length == 1
|
161
|
-
opts[:margin_top] = vals[0]
|
162
|
-
opts[:margin_right] = vals[0]
|
163
|
-
opts[:margin_bottom] = vals[0]
|
164
|
-
opts[:margin_left] = vals[0]
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
end
|
42
|
+
any2pdf = Any2Pdf.new
|
169
43
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
def pdfkit_html2pdf( file, outfile, opts )
|
174
|
-
styles = []
|
175
|
-
styles << opts.stylesheet
|
176
|
-
|
177
|
-
style_opts = get_style_options opts.stylesheet
|
178
|
-
|
179
|
-
# find css files
|
180
|
-
dom = Nokogiri::parse( File::open(file).read() )
|
181
|
-
dom.css("link").each do |e|
|
182
|
-
styles << e.attr("href")
|
183
|
-
end
|
184
|
-
|
185
|
-
# update the html links to make sure that local links (relative) work
|
186
|
-
( dom.css("@src") + dom.css("@href") ).
|
187
|
-
find_all{|src| (src.value =~ URI::regexp) == nil }.
|
188
|
-
each{|src| src.value = File::expand_path(src.value) }
|
189
|
-
|
190
|
-
options = {
|
191
|
-
footer_right: "[page]/[topage]",
|
192
|
-
orientation: (( opts[:landscape] ) ? "landscape" : "portrait" ),
|
193
|
-
page_size: 'A4',
|
194
|
-
}.merge(style_opts)
|
195
|
-
html = dom.to_s
|
196
|
-
kit = PDFKit.new(html, options)
|
197
|
-
|
198
|
-
styles.compact.each do |style|
|
199
|
-
kit.stylesheets << style if File::exists?(style)
|
200
|
-
end
|
201
|
-
|
202
|
-
kit.to_file(outfile)
|
203
|
-
end
|
204
|
-
|
205
|
-
def xelatex_html2pdf( file, outfile, opts )
|
206
|
-
puts outfile
|
207
|
-
texfile = "#{outfile}".sub(/[.]pdf$/, '.tex')
|
208
|
-
|
209
|
-
cmd = "pandoc \"#{file}\" --listings -o \"#{texfile}\""
|
210
|
-
Log.debug "convert html to tex: #{cmd}"
|
211
|
-
`#{cmd}`
|
212
|
-
|
213
|
-
verb_opts = "mathescape,
|
214
|
-
linenos,
|
215
|
-
numbersep=5pt,
|
216
|
-
frame=single,
|
217
|
-
framesep=1mm,
|
218
|
-
bgcolor=colorcode_bg".gsub("\n",'')
|
44
|
+
# Metadata
|
45
|
+
mdfile = any2pdf.fill_in_metadata(mdfile, tmpmdfile) if opts[:gitinfo]
|
219
46
|
|
220
|
-
|
221
|
-
|
222
|
-
# \begin{lstlisting}[language=bash]
|
223
|
-
# convert it to minted
|
224
|
-
gsub(/\\begin{lstlisting}\[language=([^\]]*)\]/){'\begin{minted}['+verb_opts+']{'+$1+'}'}.
|
225
|
-
gsub(/\\begin{lstlisting}/, '\begin{minted}['+verb_opts+']{bash}').
|
226
|
-
gsub(/\\lstinline(.)(.*?)\1/){ '\colorbox{colorcode_bg}{\lstinline'+$1+$2+$1+'}' }.
|
227
|
-
gsub(/\\end{lstlisting}/, '\end{minted}')
|
228
|
-
|
229
|
-
tex_style = get_style( opts[:stylesheet], 'tex' )
|
230
|
-
File::write texfile, File::read(tex_style).sub(/CONTENT/, tex)
|
231
|
-
|
232
|
-
cmd = "xelatex -shell-escape \"#{texfile}\""
|
233
|
-
Log.debug "convert tex to pdf: #{cmd}"
|
234
|
-
`#{cmd}`
|
235
|
-
end
|
236
|
-
|
237
|
-
def html2pdf(file, opts)
|
238
|
-
Log.debug "running html2pdf on '#{file}'"
|
239
|
-
return nil if not file.end_with?(".html")
|
240
|
-
pdffile = file.sub(/.html$/,".pdf")
|
241
|
-
pdffile = opts.output if not opts.output.nil? and not opts.output.empty?
|
242
|
-
Log.debug "output pdf will be '#{pdffile}'"
|
243
|
-
|
244
|
-
case opts[:renderer]
|
245
|
-
when 'pdfkit'
|
246
|
-
pdfkit_html2pdf file, pdffile, opts
|
247
|
-
when 'xelatex'
|
248
|
-
xelatex_html2pdf file, pdffile, opts
|
249
|
-
else
|
250
|
-
Log.abort "Can't find renderer '#{opts[:renderer]}'. Please use a supported renderer!"
|
251
|
-
end
|
252
|
-
|
253
|
-
pdffile
|
254
|
-
end
|
255
|
-
|
256
|
-
style = get_style( opts[:stylesheet] )
|
47
|
+
# Stylesheet
|
48
|
+
style = any2pdf.get_style( opts[:stylesheet] )
|
257
49
|
Log.info "using stylesheet: #{style}\n"
|
258
|
-
|
259
|
-
|
50
|
+
|
51
|
+
# HTML
|
52
|
+
htmlfile = any2pdf.md2html(mdfile, htmlfile, opts, style)
|
53
|
+
Log.warn "ww input was not an md-file, trying to convert it to pdf as html..." if htmlfile.nil?
|
260
54
|
Log.ok "htmlfile: #{htmlfile}\n" if not htmlfile.nil?
|
261
|
-
|
55
|
+
|
56
|
+
# PDF
|
57
|
+
pdffile = any2pdf.html2pdf(mdfile, opts) || any2pdf.html2pdf(htmlfile, opts)
|
262
58
|
Log.abort "couldn't convert file from html to pdf..." if pdffile.nil?
|
263
59
|
Log.ok "output: #{pdffile}\n" if not pdffile.nil?
|
264
60
|
|
@@ -277,3 +73,8 @@ if not cmd.empty?
|
|
277
73
|
Log.info "view with: '#{cmd}'"
|
278
74
|
system cmd
|
279
75
|
end
|
76
|
+
|
77
|
+
if opts[:clean]
|
78
|
+
File::delete( tmpmdfile ) if File::file? tmpmdfile
|
79
|
+
File::delete( htmlfile ) if File::file? htmlfile
|
80
|
+
end
|
data/data/pandoc-template.html
CHANGED
@@ -14,6 +14,14 @@ $if(title)$
|
|
14
14
|
$if(date)$
|
15
15
|
<h3 class="date fixed-heading">$date$</h3>
|
16
16
|
$endif$
|
17
|
+
$if(git_commit)$
|
18
|
+
<h3 class="git-info fixed-heading">
|
19
|
+
$if(git_tag)$<span class="git-tag">$git_tag$</span>$endif$$if(git_commit)$<span class="git-commit">$git_commit$</span>$endif$$if(git_date)$<span class="git-date">$git_date$</span>$endif$
|
20
|
+
</h3>
|
21
|
+
$endif$
|
22
|
+
$if(copyright)$
|
23
|
+
<h5 class="copyright">$copyright$</h5>
|
24
|
+
$endif$
|
17
25
|
</header>
|
18
26
|
$endif$
|
19
27
|
|
data/lib/any2pdf.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'css_parser'
|
4
|
+
require 'pdfkit'
|
5
|
+
|
6
|
+
class Any2Pdf
|
7
|
+
def pdfkit_html2pdf( file, outfile, opts )
|
8
|
+
styles = []
|
9
|
+
styles << opts.stylesheet
|
10
|
+
|
11
|
+
style_opts = get_style_options opts.stylesheet
|
12
|
+
|
13
|
+
# find css files
|
14
|
+
dom = Nokogiri::parse( File::open(file).read() )
|
15
|
+
dom.css("link").each do |e|
|
16
|
+
styles << e.attr("href")
|
17
|
+
end
|
18
|
+
|
19
|
+
# update the html links to make sure that local links (relative) work
|
20
|
+
( dom.css("@src") + dom.css("@href") ).
|
21
|
+
find_all{|src| (src.value =~ URI::regexp) == nil }.
|
22
|
+
each{|src| src.value = File::expand_path(src.value) }
|
23
|
+
|
24
|
+
options = {
|
25
|
+
footer_right: "[page]/[topage]",
|
26
|
+
orientation: (( opts[:landscape] ) ? "landscape" : "portrait" ),
|
27
|
+
page_size: 'A4',
|
28
|
+
}.merge(style_opts)
|
29
|
+
html = dom.to_s
|
30
|
+
kit = PDFKit.new(html, options)
|
31
|
+
|
32
|
+
styles.compact.each do |style|
|
33
|
+
kit.stylesheets << style if File::exists?(style)
|
34
|
+
end
|
35
|
+
|
36
|
+
kit.to_file(outfile)
|
37
|
+
end
|
38
|
+
|
39
|
+
def xelatex_html2pdf( file, outfile, opts )
|
40
|
+
puts outfile
|
41
|
+
texfile = "#{outfile}".sub(/[.]pdf$/, '.tex')
|
42
|
+
|
43
|
+
cmd = "pandoc \"#{file}\" --listings -o \"#{texfile}\""
|
44
|
+
Log.debug "convert html to tex: #{cmd}"
|
45
|
+
`#{cmd}`
|
46
|
+
|
47
|
+
verb_opts = "mathescape,
|
48
|
+
linenos,
|
49
|
+
numbersep=5pt,
|
50
|
+
frame=single,
|
51
|
+
framesep=1mm,
|
52
|
+
bgcolor=colorcode_bg".gsub("\n",'')
|
53
|
+
|
54
|
+
tex = File::read(texfile).
|
55
|
+
# all verbatim stuff is in lstlistings like this:
|
56
|
+
# \begin{lstlisting}[language=bash]
|
57
|
+
# convert it to minted
|
58
|
+
gsub(/\\begin{lstlisting}\[language=([^\]]*)\]/){'\begin{minted}['+verb_opts+']{'+$1+'}'}.
|
59
|
+
gsub(/\\begin{lstlisting}/, '\begin{minted}['+verb_opts+']{bash}').
|
60
|
+
gsub(/\\lstinline(.)(.*?)\1/){ '\colorbox{colorcode_bg}{\lstinline'+$1+$2+$1+'}' }.
|
61
|
+
gsub(/\\end{lstlisting}/, '\end{minted}')
|
62
|
+
|
63
|
+
tex_style = get_style( opts[:stylesheet], 'tex' )
|
64
|
+
File::write texfile, File::read(tex_style).sub(/CONTENT/, tex)
|
65
|
+
|
66
|
+
cmd = "xelatex -shell-escape \"#{texfile}\""
|
67
|
+
Log.debug "convert tex to pdf: #{cmd}"
|
68
|
+
`#{cmd}`
|
69
|
+
end
|
70
|
+
|
71
|
+
def html2pdf(file, opts)
|
72
|
+
Log.debug "running html2pdf on '#{file}'"
|
73
|
+
return nil if not file.end_with?(".html")
|
74
|
+
pdffile = file.sub(/.html$/,".pdf")
|
75
|
+
pdffile = opts.output if not opts.output.nil? and not opts.output.empty?
|
76
|
+
Log.debug "output pdf will be '#{pdffile}'"
|
77
|
+
|
78
|
+
case opts[:renderer]
|
79
|
+
when 'pdfkit'
|
80
|
+
pdfkit_html2pdf file, pdffile, opts
|
81
|
+
when 'xelatex'
|
82
|
+
xelatex_html2pdf file, pdffile, opts
|
83
|
+
else
|
84
|
+
Log.abort "Can't find renderer '#{opts[:renderer]}'. Please use a supported renderer!"
|
85
|
+
end
|
86
|
+
|
87
|
+
pdffile
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def get_style_options style_file
|
93
|
+
return {} unless File::file? style_file
|
94
|
+
|
95
|
+
declarations = []
|
96
|
+
|
97
|
+
css = CssParser::Parser.new
|
98
|
+
css.load_file! style_file
|
99
|
+
css.each_rule_set do |rule|
|
100
|
+
if rule.selectors.include? '#pdf'
|
101
|
+
rule.each_declaration do |id, params|
|
102
|
+
declarations.push [id, params]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# check all rules
|
108
|
+
opts = {}
|
109
|
+
declarations.each do |field,value|
|
110
|
+
if field == 'margin'
|
111
|
+
vals = value.split(' ');
|
112
|
+
if vals.length == 4
|
113
|
+
opts[:margin_top] = vals[0]
|
114
|
+
opts[:margin_right] = vals[1]
|
115
|
+
opts[:margin_bottom] = vals[2]
|
116
|
+
opts[:margin_left] = vals[3]
|
117
|
+
end
|
118
|
+
if vals.length == 2
|
119
|
+
opts[:margin_top] = vals[0]
|
120
|
+
opts[:margin_right] = vals[1]
|
121
|
+
opts[:margin_bottom] = vals[0]
|
122
|
+
opts[:margin_left] = vals[1]
|
123
|
+
end
|
124
|
+
if vals.length == 1
|
125
|
+
opts[:margin_top] = vals[0]
|
126
|
+
opts[:margin_right] = vals[0]
|
127
|
+
opts[:margin_bottom] = vals[0]
|
128
|
+
opts[:margin_left] = vals[0]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
opts
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
class Any2Pdf
|
4
|
+
def embed_html( raw, source )
|
5
|
+
begin
|
6
|
+
require 'websnap'
|
7
|
+
w = WebSnap.new( nil, nil )
|
8
|
+
|
9
|
+
# parse raw html contents
|
10
|
+
Log.info "embedding html via websnap"
|
11
|
+
h = Nokogiri::HTML(raw)
|
12
|
+
|
13
|
+
# embed all parts into the html
|
14
|
+
w.spiderHtmlElements( 'file://'+File::expand_path(source), h )
|
15
|
+
|
16
|
+
# return the resulting html as string
|
17
|
+
h.to_s
|
18
|
+
rescue LoadError
|
19
|
+
return raw
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def md2html(file, outfile, opts, stylefile)
|
24
|
+
return nil if not file.end_with?(".md")
|
25
|
+
outfile_raw = outfile+".raw.html"
|
26
|
+
|
27
|
+
rel_path = File.expand_path('../../data', File.dirname(__FILE__))
|
28
|
+
|
29
|
+
# prep-work for including style and script
|
30
|
+
style_e = lambda{|f,o| "<style type=\"text/css\" #{o}>\n#{File::read(f)}\n</style>" }
|
31
|
+
style_l = lambda{|f,o| "<link rel=\"stylesheet\" href=\"#{f}\" #{o} />" }
|
32
|
+
script_e = lambda{|f,o| "<script #{o}>\n#{File::read(f)}\n</script>" }
|
33
|
+
script_l = lambda{|f,o| "<script src=\"#{f}\" #{o} ></script>"}
|
34
|
+
style = opts[:embed] ? style_e : style_l
|
35
|
+
script = opts[:embed] ? script_e : script_l
|
36
|
+
|
37
|
+
# get all fields in the heading
|
38
|
+
raw_heading = [
|
39
|
+
# start with stylesheets
|
40
|
+
style.( rel_path+"/boilerplate.css", ''),
|
41
|
+
style.( File::expand_path(stylefile), '' ),
|
42
|
+
style.( rel_path+"/print.css", 'media="print"'),
|
43
|
+
script.( rel_path+"/jquery-1.9.0.min.js", '' ),
|
44
|
+
( opts[:toc] ? script.( rel_path+"/toc_generator.js", '' ) : '' )
|
45
|
+
].join("\n\n")
|
46
|
+
|
47
|
+
# create the html
|
48
|
+
`pandoc "#{file}" -o "#{outfile_raw}" --template #{rel_path}/pandoc-template.html --toc`
|
49
|
+
raw_html = File::read outfile_raw
|
50
|
+
File.delete outfile_raw
|
51
|
+
|
52
|
+
# additional options
|
53
|
+
toc_level = opts[:toc_level]
|
54
|
+
number_headings = (opts[:numbering] == true)
|
55
|
+
|
56
|
+
# actually create the result file
|
57
|
+
renderer = ERB.new(File::read(rel_path + "/template.html.erb"))
|
58
|
+
html = embed_html( renderer.result(binding), file )
|
59
|
+
|
60
|
+
# save the html to file
|
61
|
+
File::write outfile, html
|
62
|
+
outfile
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Any2Pdf
|
2
|
+
|
3
|
+
def fill_in_metadata( path, tmpfile )
|
4
|
+
tag = `git describe --tags --abbrev=0`.chomp
|
5
|
+
gitlog = `git log -1 --pretty=format:'%h %ct'`
|
6
|
+
commit, date = gitlog.split(" ")
|
7
|
+
if commit == "" || date == nil
|
8
|
+
Log.warn "Can't find git info for latest commit. Ignoring."
|
9
|
+
return path
|
10
|
+
end
|
11
|
+
Log.info "Adding git metadata: #{tag} #{commit} #{date}"
|
12
|
+
|
13
|
+
time = Time.at( date.to_i )
|
14
|
+
timestamp = "%04d-%02d-%02d" % [ time.year, time.month, time.day ]
|
15
|
+
|
16
|
+
content = File::read(path)
|
17
|
+
info = ["---",
|
18
|
+
"git_commit: #{commit}",
|
19
|
+
"git_date: #{timestamp}",
|
20
|
+
(tag == "" ) ? nil : "git_tag: #{tag}"
|
21
|
+
].compact.join("\n") + "\n"
|
22
|
+
|
23
|
+
if content.start_with?("---\n")
|
24
|
+
nu = content.sub("---\n",info)
|
25
|
+
else
|
26
|
+
nu = info + "---\n" + content
|
27
|
+
end
|
28
|
+
|
29
|
+
File::write( tmpfile, nu )
|
30
|
+
tmpfile
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def get_existing( f )
|
36
|
+
path = File::expand_path(f)
|
37
|
+
return path if File::exists?(path)
|
38
|
+
return nil
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Any2Pdf
|
2
|
+
def get_style( stylename, type = "css" )
|
3
|
+
rel_path = File.expand_path('../../data', File.dirname(__FILE__))
|
4
|
+
|
5
|
+
if not stylename.nil? and not stylename.empty?
|
6
|
+
a =
|
7
|
+
get_existing(stylename) ||
|
8
|
+
get_existing("#{rel_path}/#{stylename}.#{type}") ||
|
9
|
+
get_existing("#{rel_path}/#{stylename}")
|
10
|
+
return a if not a.nil?
|
11
|
+
Log.warn "couldn't find stylesheet #{stylename}. Trying default.\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
# try default, if the user supplied crap...
|
15
|
+
a = get_existing("#{rel_path}/default.#{type}")
|
16
|
+
return a if not a.nil?
|
17
|
+
Log.error "Couldn't find internal stylesheet in #{rel_path}/default.#{type}. Something is seriously wrong! try reinstalling?\n"
|
18
|
+
""
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: any2pdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominik Richter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pdfkit
|
@@ -104,6 +104,11 @@ files:
|
|
104
104
|
- data/telekom.css
|
105
105
|
- data/template.html.erb
|
106
106
|
- data/toc_generator.js
|
107
|
+
- lib/any2pdf.rb
|
108
|
+
- lib/any2pdf/html2pdf.rb
|
109
|
+
- lib/any2pdf/md2html.rb
|
110
|
+
- lib/any2pdf/metadata.rb
|
111
|
+
- lib/any2pdf/style.rb
|
107
112
|
homepage:
|
108
113
|
licenses: []
|
109
114
|
metadata: {}
|