jekyll-pandoc-multiple-formats-jekyll34 0.2.10 → 0.2.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +190 -0
- data/Rakefile +13 -0
- data/bin/imponer +62 -0
- data/jekyll-pandoc-multiple-formats-jekyll34-0.2.11.gem +0 -0
- data/jekyll-pandoc-multiple-formats-jekyll34.gemspec +29 -0
- data/lib/jekyll-pandoc-multiple-formats-jekyll34.rb +37 -0
- data/lib/jekyll-pandoc-multiple-formats-jekyll34/binder.rb +45 -0
- data/lib/jekyll-pandoc-multiple-formats-jekyll34/config.rb +40 -0
- data/lib/jekyll-pandoc-multiple-formats-jekyll34/converter.rb +81 -0
- data/lib/jekyll-pandoc-multiple-formats-jekyll34/generator.rb +110 -0
- data/lib/jekyll-pandoc-multiple-formats-jekyll34/imposition.rb +97 -0
- data/lib/jekyll-pandoc-multiple-formats-jekyll34/pandoc_file.rb +276 -0
- data/lib/jekyll-pandoc-multiple-formats-jekyll34/printer.rb +105 -0
- data/lib/jekyll-pandoc-multiple-formats-jekyll34/unite.rb +70 -0
- data/lib/jekyll-pandoc-multiple-formats-jekyll34/version.rb +3 -0
- data/test/fixtures/test.pdf +0 -0
- data/test/source/_layouts/nil.html +1 -0
- data/test/source/_posts/2014-01-01-test.markdown +10 -0
- data/test/source/_posts/2015-01-01-another_post.markdown +11 -0
- data/test/test_helper.rb +37 -0
- data/test/test_pandoc_file.rb +106 -0
- data/test/test_printer.rb +483 -0
- metadata +38 -6
@@ -0,0 +1,81 @@
|
|
1
|
+
# Copyright (c) 2012-2015 Nicolás Reynolds <fauno@endefensadelsl.org>
|
2
|
+
# 2012-2013 Mauricio Pasquier Juan <mpj@endefensadelsl.org>
|
3
|
+
# 2013 Brian Candler <b.candler@pobox.com>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
# Namespacing and metaprogramming FTW
|
25
|
+
module JekyllPandocMultipleFormats
|
26
|
+
# Determines the correct module where it lives the converter
|
27
|
+
def self.namespace
|
28
|
+
Jekyll::VERSION >= '1.0.0' ? Jekyll::Converters : Jekyll
|
29
|
+
end
|
30
|
+
|
31
|
+
# Determines the correct class name. Jekyll has the converters class kinda
|
32
|
+
# hardcoded
|
33
|
+
def self.class_name
|
34
|
+
Jekyll::VERSION >= '1.0.0' ? 'Markdown' : 'MarkdownConverter'
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.build
|
38
|
+
namespace::const_get(class_name).send :include, ConverterMethods
|
39
|
+
end
|
40
|
+
|
41
|
+
# When included in the correspondant markdown class this module redefines the
|
42
|
+
# three needed Converter instance methods
|
43
|
+
module ConverterMethods
|
44
|
+
def self.included(base)
|
45
|
+
base.class_eval do
|
46
|
+
# Just return html5
|
47
|
+
def convert(content)
|
48
|
+
flags = "#{@config['pandoc']['flags']} #{@config['pandoc']['site_flags']}"
|
49
|
+
|
50
|
+
output = ''
|
51
|
+
Dir::chdir(@config['source']) do
|
52
|
+
Open3::popen3("pandoc -t html5 #{flags}") do |stdin, stdout, stderr, thread|
|
53
|
+
stdin.puts content
|
54
|
+
stdin.close
|
55
|
+
|
56
|
+
output = stdout.read.strip
|
57
|
+
STDERR.print stderr.read
|
58
|
+
|
59
|
+
# Wait for the process to finish
|
60
|
+
thread.value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
output
|
65
|
+
end
|
66
|
+
|
67
|
+
def matches(ext)
|
68
|
+
rgx = '(' + @config['markdown_ext'].gsub(',','|') +')'
|
69
|
+
ext =~ Regexp.new(rgx, Regexp::IGNORECASE)
|
70
|
+
end
|
71
|
+
|
72
|
+
def output_ext(ext)
|
73
|
+
'.html'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Conjures the metamagic
|
81
|
+
JekyllPandocMultipleFormats.build
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# Copyright (c) 2012-2015 Nicolás Reynolds <fauno@endefensadelsl.org>
|
2
|
+
# 2012-2013 Mauricio Pasquier Juan <mpj@endefensadelsl.org>
|
3
|
+
# 2013 Brian Candler <b.candler@pobox.com>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
module Jekyll
|
25
|
+
|
26
|
+
class PandocGenerator < Generator
|
27
|
+
safe true
|
28
|
+
|
29
|
+
attr_accessor :site, :config
|
30
|
+
|
31
|
+
def generate(site)
|
32
|
+
@site ||= site
|
33
|
+
@config ||= JekyllPandocMultipleFormats::Config.new(@site.config['pandoc'])
|
34
|
+
|
35
|
+
return if @config.skip?
|
36
|
+
|
37
|
+
# we create a single array of files
|
38
|
+
@pandoc_files = []
|
39
|
+
|
40
|
+
@config.outputs.each_pair do |output, extra_flags|
|
41
|
+
@site.posts.docs.each do |post|
|
42
|
+
|
43
|
+
pandoc_file = PandocFile.new(@site, output, post)
|
44
|
+
next unless pandoc_file.write
|
45
|
+
|
46
|
+
@site.keep_files << pandoc_file.relative_path
|
47
|
+
@pandoc_files << pandoc_file
|
48
|
+
end
|
49
|
+
|
50
|
+
@site.post_attr_hash('categories').each_pair do |title, posts|
|
51
|
+
posts.sort!
|
52
|
+
pandoc_file = PandocFile.new(@site, output, posts, title)
|
53
|
+
|
54
|
+
if @site.keep_files.include? pandoc_file.relative_path
|
55
|
+
puts "#{pandoc_file.relative_path} is a category file AND a post file"
|
56
|
+
puts 'change the category name to fix this'
|
57
|
+
next
|
58
|
+
end
|
59
|
+
|
60
|
+
next unless pandoc_file.write
|
61
|
+
|
62
|
+
@site.keep_files << pandoc_file.relative_path
|
63
|
+
@pandoc_files << pandoc_file
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
@pandoc_files.each do |pandoc_file|
|
68
|
+
# If output is PDF, we also create the imposed PDF
|
69
|
+
if pandoc_file.pdf?
|
70
|
+
|
71
|
+
if @config.imposition?
|
72
|
+
|
73
|
+
imposed_file = JekyllPandocMultipleFormats::Imposition
|
74
|
+
.new(pandoc_file.path, pandoc_file.papersize,
|
75
|
+
pandoc_file.sheetsize, pandoc_file.signature)
|
76
|
+
|
77
|
+
imposed_file.write
|
78
|
+
@site.keep_files << imposed_file.relative_path(@site.dest)
|
79
|
+
end
|
80
|
+
|
81
|
+
# If output is PDF, we also create the imposed PDF
|
82
|
+
if @config.binder?
|
83
|
+
|
84
|
+
binder_file = JekyllPandocMultipleFormats::Binder
|
85
|
+
.new(pandoc_file.path, pandoc_file.papersize,
|
86
|
+
pandoc_file.sheetsize)
|
87
|
+
|
88
|
+
binder_file.write
|
89
|
+
@site.keep_files << binder_file.relative_path(@site.dest)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Add covers to PDFs after building ready for print files
|
93
|
+
if pandoc_file.has_cover?
|
94
|
+
# Generate the cover
|
95
|
+
next unless pandoc_file.pdf_cover!
|
96
|
+
united_output = pandoc_file.path.gsub(/\.pdf\Z/, '-cover.pdf')
|
97
|
+
united_file = JekyllPandocMultipleFormats::Unite
|
98
|
+
.new(united_output, [pandoc_file.pdf_cover,pandoc_file.path])
|
99
|
+
|
100
|
+
if united_file.write
|
101
|
+
# Replace the original file with the one with cover
|
102
|
+
FileUtils.rm_f(pandoc_file.path)
|
103
|
+
FileUtils.mv(united_output, pandoc_file.path)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# Copyright (c) 2012-2015 Nicolás Reynolds <fauno@endefensadelsl.org>
|
2
|
+
# 2012-2013 Mauricio Pasquier Juan <mpj@endefensadelsl.org>
|
3
|
+
# 2013 Brian Candler <b.candler@pobox.com>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
module JekyllPandocMultipleFormats
|
25
|
+
class Imposition < Printer
|
26
|
+
|
27
|
+
attr_accessor :rounded_pages, :blank_pages, :signature
|
28
|
+
|
29
|
+
def initialize(file, papersize = nil, sheetsize = nil, signature = nil, extra_options = nil)
|
30
|
+
super(file, papersize, sheetsize, extra_options)
|
31
|
+
@output_file = file.gsub(/\.pdf\Z/, '-imposed.pdf')
|
32
|
+
# Total pages must be modulo 4
|
33
|
+
@rounded_pages = round_to_nearest(@pages, 4)
|
34
|
+
@blank_pages = @rounded_pages - @pages
|
35
|
+
# If we don't use a signature, make a single fold
|
36
|
+
@signature = signature || @rounded_pages
|
37
|
+
# Also if we specified 0
|
38
|
+
@signature = @rounded_pages if signature == 0
|
39
|
+
|
40
|
+
render_template
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_nup
|
45
|
+
# 14 pages example:
|
46
|
+
# [ {}, 1, 2, {}, 14, 3, 4, 13, 12, 5, 6, 11, 10, 7, 8, 9 ]
|
47
|
+
#
|
48
|
+
# * Add {} to missing pages
|
49
|
+
# [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, {}, {}]
|
50
|
+
# * Take first half [ 1, 2, 3, 4, 5, 6, 7, 8 ]
|
51
|
+
# * Reverse second half [ {}, {}, 14, 13, 12, 11, 10, 9 ]
|
52
|
+
# * Intercalate the first half into the second half by two
|
53
|
+
# elements
|
54
|
+
# [ {}, 1, 2, {}, 14, 3, 4, 13, 12, 5, 6, 11, 10, 7, 8, 9 ]
|
55
|
+
#
|
56
|
+
# An array of numbered pages padded with blank pages ('{}')
|
57
|
+
#
|
58
|
+
# [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ] + [ '{}', '{}' ]
|
59
|
+
padded = @pages.times.map{|i|i+1} + Array.new(@blank_pages, '{}')
|
60
|
+
|
61
|
+
# If we have a signature, we have to split in groups up to the
|
62
|
+
# amount of pages per signature, and then continue with the rest
|
63
|
+
#
|
64
|
+
# If we have no signature, we assume it's equal to the total
|
65
|
+
# amount of pages, so you only have one fold
|
66
|
+
signed = padded.each_slice(@signature).to_a
|
67
|
+
folds = []
|
68
|
+
signed.each do |fold|
|
69
|
+
#
|
70
|
+
# Split in halves
|
71
|
+
# [ [ 1, 2, 3, 4, 5, 6, 7, 8 ],
|
72
|
+
# [ 9, 10, 11, 12, 13, 14, '{}', '{}' ] ]
|
73
|
+
halved = fold.each_slice(fold.size / 2).to_a
|
74
|
+
# Add a nil as last page. When we reverse it and intercalate by
|
75
|
+
# two pages, we'll have [nil, last_page] instead of
|
76
|
+
# [last_page,second_to_last_page]
|
77
|
+
#
|
78
|
+
# [ [ 1, 2, 3, 4, 5, 6, 7, 8 ],
|
79
|
+
# [ 9, 10, 11, 12, 13, 14, '{}', '{}', nil ] ]
|
80
|
+
halved.last << nil
|
81
|
+
# Reverse the second half and intercalate by two pages into the
|
82
|
+
# first one. Then remove nil elements and flatten the array.
|
83
|
+
#
|
84
|
+
# [ [ 1, 2, 3, 4, 5, 6, 7, 8 ],
|
85
|
+
# [ nil, '{}', '{}', 14, 13, 12, 11, 10 ] ]
|
86
|
+
#
|
87
|
+
# [ {}, 1, 2, {}, 14, 3, 4, 13, 12, 5, 6, 11, 10, 7, 8, 9 ]
|
88
|
+
folds << halved.last.reverse.each_slice(2).zip(halved.first.each_slice(2).to_a).flatten.compact
|
89
|
+
end
|
90
|
+
|
91
|
+
# Create the matrix of pages (N-Up) per fold
|
92
|
+
#
|
93
|
+
# ["{}", 1, "{}", 1, 2, "{}", 2, "{}", 14, 3, 14, 3, 4, 13, 4, 13, 12, 5, 12, 5, 6, 11, 6, 11, 10, 7, 10, 7, 8, 9, 8, 9]
|
94
|
+
folds.map { |o| o.each_slice(2).map{ |i| a=[]; (@nup/2).times { a = a+i }; a }}.flatten
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,276 @@
|
|
1
|
+
# Copyright (c) 2012-2015 Nicolás Reynolds <fauno@endefensadelsl.org>
|
2
|
+
# 2012-2013 Mauricio Pasquier Juan <mpj@endefensadelsl.org>
|
3
|
+
# 2013 Brian Candler <b.candler@pobox.com>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
module Jekyll
|
25
|
+
class PandocFile
|
26
|
+
include Convertible
|
27
|
+
|
28
|
+
|
29
|
+
attr_reader :format, :site, :config, :flags, :posts, :slug, :title, :url
|
30
|
+
attr_reader :papersize, :sheetsize, :signature
|
31
|
+
|
32
|
+
def initialize(site, format, posts, title = nil)
|
33
|
+
@site = site
|
34
|
+
@config = JekyllPandocMultipleFormats::Config.new(@site.config['pandoc']).config
|
35
|
+
@format = format
|
36
|
+
@flags = []
|
37
|
+
|
38
|
+
if posts.is_a? Array
|
39
|
+
@posts = posts
|
40
|
+
|
41
|
+
raise ArgumentError.new "'title' argument is required for multipost file" unless title
|
42
|
+
|
43
|
+
@title = title
|
44
|
+
else
|
45
|
+
@posts = [posts]
|
46
|
+
@title = posts.data['title'] unless title
|
47
|
+
end
|
48
|
+
|
49
|
+
@slug = Utils.slugify(title)
|
50
|
+
end
|
51
|
+
|
52
|
+
def path
|
53
|
+
# path is full destination path with all elements of permalink
|
54
|
+
path = @site.in_dest_dir(relative_path)
|
55
|
+
end
|
56
|
+
|
57
|
+
def relative_path
|
58
|
+
path = URL.unescape_path(url)
|
59
|
+
path.gsub! /^\//, ''
|
60
|
+
|
61
|
+
# but if the post is going to be index.html, use slug + format
|
62
|
+
# (ie /year/month/slug/slug.pdf)
|
63
|
+
if url.end_with? '/'
|
64
|
+
path = File.join(path, @slug)
|
65
|
+
path << '.'
|
66
|
+
path << @format
|
67
|
+
end
|
68
|
+
|
69
|
+
path
|
70
|
+
end
|
71
|
+
|
72
|
+
# if it's just one article, the url is the same except it's not html
|
73
|
+
# otherwise we use the permalink template with some placeholder
|
74
|
+
def url
|
75
|
+
@url = if single_post?
|
76
|
+
single_post.url.gsub(/\.html$/, ".#{@format}")
|
77
|
+
else
|
78
|
+
URL.new({
|
79
|
+
template: @config['bundle_permalink'],
|
80
|
+
placeholders: url_placeholders,
|
81
|
+
permalink: nil }).to_s
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def url_placeholders
|
86
|
+
{ output_ext: @format,
|
87
|
+
slug: @slug,
|
88
|
+
title: @title }
|
89
|
+
end
|
90
|
+
|
91
|
+
# adds post metadata as yaml metadata
|
92
|
+
def yaml_metadata
|
93
|
+
if single_post?
|
94
|
+
|
95
|
+
# if we were to merge config to data, the default options would
|
96
|
+
# take precedence
|
97
|
+
data = Jekyll::Utils.deep_merge_hashes @config, single_post.data
|
98
|
+
single_post.merge_data! data
|
99
|
+
|
100
|
+
|
101
|
+
# we extract the excerpt because it serializes as an object and
|
102
|
+
# breaks pandoc
|
103
|
+
metadata = single_post.data.reject{ |k| k == 'excerpt' }
|
104
|
+
|
105
|
+
if @config['date_format']
|
106
|
+
metadata['date'] = metadata['date'].strftime(@config['date_format'])
|
107
|
+
else
|
108
|
+
metadata.delete('date')
|
109
|
+
end
|
110
|
+
else
|
111
|
+
# we have to use this fugly syntax because jekyll doesn't do
|
112
|
+
# symbols
|
113
|
+
metadata = {
|
114
|
+
'date' => @config['date_format'] ? Date.today.strftime(@config['date_format']) : nil,
|
115
|
+
'title' => @title,
|
116
|
+
'author' => nil,
|
117
|
+
'papersize' => papersize,
|
118
|
+
'sheetsize' => sheetsize,
|
119
|
+
'signature' => signature
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
# fix page sizes, pandoc uses 'A4' while printer.rb uses
|
124
|
+
# 'a4paper'
|
125
|
+
%w[papersize sheetsize].each do |size|
|
126
|
+
metadata[size] = fix_size metadata[size]
|
127
|
+
end
|
128
|
+
|
129
|
+
metadata.to_yaml << "\n---\n"
|
130
|
+
end
|
131
|
+
|
132
|
+
def content
|
133
|
+
if single_post?
|
134
|
+
single_post.content
|
135
|
+
else
|
136
|
+
header_re = /^(#+.*\n*|.*\n[=-]+\n*)\Z/
|
137
|
+
bib_title = ""
|
138
|
+
@posts.map do |post|
|
139
|
+
bib_title = post.content.match(header_re).to_s if bib_title.empty?
|
140
|
+
# remove bibliography titles
|
141
|
+
# since pandoc does it's own bibliography output, it recommends
|
142
|
+
# leaving an empty chapter title to mark it as such
|
143
|
+
post.content.gsub(header_re, '')
|
144
|
+
# we add the first bibliography title we can find in the end
|
145
|
+
end.join("\n\n\n") << bib_title
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def write
|
150
|
+
FileUtils.mkdir_p(File.dirname(path))
|
151
|
+
# Remove the file before creating it
|
152
|
+
FileUtils.rm_f(path)
|
153
|
+
# Move to the source dir since everything will be relative to that
|
154
|
+
Dir::chdir(@site.config['source']) do
|
155
|
+
# Do the stuff
|
156
|
+
Open3::popen3(command) do |stdin, stdout, stderr, thread|
|
157
|
+
stdin.puts yaml_metadata
|
158
|
+
stdin.puts content
|
159
|
+
stdin.close
|
160
|
+
STDERR.print stderr.read
|
161
|
+
|
162
|
+
# Wait for the process to finish
|
163
|
+
thread.value
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
File.exists?(path)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Returns a cover, without checking if it exists
|
171
|
+
#
|
172
|
+
# It assumes covers are in PNG format
|
173
|
+
def cover
|
174
|
+
if single_post? && single_post.data['cover']
|
175
|
+
File.join(@site.config['source'], single_post.data['cover'])
|
176
|
+
else
|
177
|
+
File.join(@site.config['source'], @config['covers_dir'], "#{@slug}.png")
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Returns a PDF cover
|
182
|
+
def pdf_cover
|
183
|
+
cover.gsub(/\.[^\.]+\Z/, '.pdf')
|
184
|
+
end
|
185
|
+
|
186
|
+
def pdf_cover!
|
187
|
+
if has_cover? && !File.exists?(pdf_cover)
|
188
|
+
Open3::popen3("convert \"#{cover}\" \"#{pdf_cover}\"") do |stdin, stdout, stderr, thread|
|
189
|
+
STDERR.print stderr.read
|
190
|
+
|
191
|
+
# Wait for the process to finish
|
192
|
+
thread.value
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
File.exists?(pdf_cover)
|
197
|
+
end
|
198
|
+
|
199
|
+
def flags
|
200
|
+
return @flags.join ' ' unless @flags.empty?
|
201
|
+
|
202
|
+
@flags << @config['flags']
|
203
|
+
@flags << @config['outputs'][@format] if @config['outputs'].key?(@format)
|
204
|
+
@flags << '-o'
|
205
|
+
@flags << path
|
206
|
+
|
207
|
+
# Binary formats don't need a -t flag
|
208
|
+
unless binary?
|
209
|
+
@flags << '-t'
|
210
|
+
@flags << @format
|
211
|
+
end
|
212
|
+
|
213
|
+
if epub? && has_cover?
|
214
|
+
@flags << '--epub-cover-image'
|
215
|
+
@flags << cover
|
216
|
+
end
|
217
|
+
|
218
|
+
@flags.join ' '
|
219
|
+
end
|
220
|
+
|
221
|
+
def command
|
222
|
+
'pandoc ' << flags
|
223
|
+
end
|
224
|
+
|
225
|
+
def pdf?
|
226
|
+
@format == 'pdf'
|
227
|
+
end
|
228
|
+
|
229
|
+
def epub?
|
230
|
+
%w[epub epub3].include? @format
|
231
|
+
end
|
232
|
+
|
233
|
+
# These formats are binary files and must use the -o flag
|
234
|
+
def binary?
|
235
|
+
%w[pdf epub epub3 odt docx].include? @format
|
236
|
+
end
|
237
|
+
|
238
|
+
def single_post?
|
239
|
+
@posts.count == 1
|
240
|
+
end
|
241
|
+
|
242
|
+
def has_cover?
|
243
|
+
File.exists? cover
|
244
|
+
end
|
245
|
+
|
246
|
+
def papersize
|
247
|
+
@papersize ||= find_option 'papersize'
|
248
|
+
end
|
249
|
+
|
250
|
+
def sheetsize
|
251
|
+
@sheetsize ||= find_option 'sheetsize'
|
252
|
+
end
|
253
|
+
|
254
|
+
def signature
|
255
|
+
@signature ||= find_option 'signature'
|
256
|
+
end
|
257
|
+
|
258
|
+
private
|
259
|
+
|
260
|
+
def single_post
|
261
|
+
@posts.first
|
262
|
+
end
|
263
|
+
|
264
|
+
def find_option(name)
|
265
|
+
if @posts.any? { |p| p.data.key? name }
|
266
|
+
@posts.select { |p| p.data.key? name }.first.data[name]
|
267
|
+
else
|
268
|
+
@config[name]
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def fix_size(size)
|
273
|
+
size.gsub /paper$/, ''
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|