jekyll-printing-press 1.0.0rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4a3b26467e087e03edaf35e1dc1ad9d6308db3cf0863b50e85cd567df62377ab
4
+ data.tar.gz: 6f40f3d1f0ff47d26352d7a22a2aa306caffeab3e2a58124af6b8431f9bbf12c
5
+ SHA512:
6
+ metadata.gz: cf9d1904526652fec66d92ba883d37f767490a68830e5704644167770d4c68317d591a91f38607ce66919717730fbd57d801469ebc20f0409d73ea9de420e459
7
+ data.tar.gz: a6f78d032bcae07dc0e4635ce9f0c0d65c56a7816ee2ebc6dabf30dc5d9cb63d7647f4c8c71fdc2eacd702836f64022fec854ce7259d70ccc5870242a9eb49b8
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2012-2021 fauno <fauno@endefensadelsl.org>
2
+ See CONTRIBUTORS.md
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,222 @@
1
+ # Another pandoc plugin for jekyll
2
+
3
+ This jekyll plugin was inspired by [jekyll-pandoc-plugin][1] but it was changed
4
+ to generate multiple outputs, rather than just using pandoc to generate jekyll
5
+ html posts. Besides, it doesn't require the 'pandoc-ruby' gem.
6
+
7
+ It's used on [En Defensa del Software Libre][0]. Please check [our
8
+ repo](https://github.com/edsl/endefensadelsl.org) if you like to see how
9
+ it works in production.
10
+
11
+ [0]: http://endefensadelsl.org
12
+ [1]: https://github.com/dsanson/jekyll-pandoc-plugin
13
+
14
+
15
+ ## What does it do
16
+
17
+ It replaces the html generation for pandoc. This means you will have
18
+ support for pandoc's markdown extensions, like ~strikethrough~ and
19
+ [@cite], tables and [a lot more stuff](http://pandoc.org/README.html).
20
+
21
+ It'll also generate the post in other formats you like, so your
22
+ blog can be made available in different formats at the same time. Epub
23
+ for ebook readers, mediawiki for copy&paste to wikis, etc.
24
+
25
+ If instructed, this plugin will also generate pdfs in ready for print
26
+ format.
27
+
28
+
29
+ ## Configuration
30
+
31
+ Add to `_config.yml`:
32
+
33
+ ```yaml
34
+
35
+ markdown: pandoc
36
+ pandoc:
37
+ skip:
38
+ full: false
39
+ posts: false
40
+ categories: false
41
+ bundle_permalink: ':output_ext/:slug.:output_ext'
42
+ papersize: 'a5paper'
43
+ sheetsize: 'a4paper'
44
+ imposition: true
45
+ binder: true
46
+ covers_dir: assets/covers
47
+ signature: 20
48
+ full_file: true
49
+
50
+ flags: '--smart'
51
+ site_flags: '--toc'
52
+ outputs:
53
+ latex:
54
+ pdf: '--latex-engine=xelatex'
55
+ epub: '--epub-chapter-level=2'
56
+ lang:
57
+ ar:
58
+ all: '-V mainfont="Amiri"'
59
+ pdf: '--include-in-header=_layouts/rtl.tex'
60
+ ```
61
+
62
+ * `markdown: pandoc` will instruct jekyll to use the pandoc html
63
+ converter.
64
+
65
+ * `skip` allows you to skip the other formats generation and proceed
66
+ with the regular jekyll site build. You can skip some of the
67
+ generation process or all of it. Older versions of this plugin
68
+ required `true` or `false` to skip the process altogether.
69
+
70
+ * `full_flags` if `full_file` is defined, these flags are used on it.
71
+ By default are set to `--top-level-division=part` so each category is
72
+ a different book part.
73
+
74
+ * `site_flags` are flags applied to the html generation
75
+
76
+ * `flags` is a string with the flags you will normally pass to `pandoc` on cli.
77
+ It's used on all output types.
78
+
79
+ * `outputs` is a hash of output formats (even markdown!). You can add
80
+ output-specific flags.
81
+
82
+ * `imposition` creates ready to print PDFs if you're creating PDF
83
+ output.
84
+
85
+ * `binder` creates ready to print PDFs
86
+
87
+ * `bundle_permalink` is the path of the bundled articles
88
+
89
+ * `papersize` is the page size for PDF. You can also use this option on
90
+ the front matter.
91
+
92
+ * `sheetsize` is the page size for ready the print PDF. You can also
93
+ use this option on the front matter.
94
+
95
+ * `covers_dir` the directory where covers are stored. If you have a
96
+ `lang` defined, it will append the language to the `covers_dir` when
97
+ looking for a category/full site cover, so you can have localized
98
+ covers.
99
+
100
+ * `signature` is the amount of pages per fold on the imposition version.
101
+ Specify `0` for a single fold of all the pages. You can also use this
102
+ option on the front matter.
103
+
104
+ * `full_file` generates a single file containing all articles, sectioned
105
+ by their main category (the first one defined if many).
106
+
107
+ * `lang` is a hash where you can define per-language flags. If you have
108
+ a `lang` attribute in your site config, this plugin will add the
109
+ `-V lang=XX` flag and any language-specific flag you want. You can
110
+ define language flags for `all` formats or for specific formats.
111
+
112
+ **IMPORTANT**: As of version 0.1.0 the syntax of the config changed.
113
+ Please upgrade your `_config.yml` accordingly.
114
+
115
+
116
+ ## Front Matter
117
+
118
+ ### Covers
119
+
120
+ Support for epub covers has been added. You can add the path to
121
+ a cover on the front matter of the article to have pandoc add a cover
122
+ image on the epub result.
123
+
124
+ ---
125
+ cover: images/awesome.png
126
+ ---
127
+
128
+ For categories or posts without a cover specified, the plugin looks for
129
+ a PNG file inside the `covers_dir` whose file name will be the
130
+ category/post slug.
131
+
132
+ Since 0.2.0, there's also support for PDF covers. If you have a PNG
133
+ cover, it will get converted to PDF. You can also provide a PDF cover
134
+ as long as it's the same file name as the PNG cover.
135
+
136
+ * Category cover: `assets/covers/the_category_slug.png`
137
+ * PDF cover: `assets/covers/the_slug.pdf`
138
+
139
+ ### Paper sizes
140
+
141
+ For PDFs, each article can have a `papersize` and a `sheetsize`. The
142
+ `papersize` indicates the page size, and the `sheetsize` indicates the
143
+ pages per fold size.
144
+
145
+ Only A* sizes from A7 to A0 are supported for now.
146
+
147
+ ---
148
+ papersize: a5paper
149
+ sheesize: a4paper
150
+ ---
151
+
152
+ This example will generate a 2 pages per A4 sheet.
153
+
154
+ ### Bundled articles
155
+
156
+ If articles share a category, the generator will create a PDF book
157
+ including all of them. The name of the category will become the title
158
+ of the book.
159
+
160
+ ---
161
+ category: [ 'En Defensa del Software Libre #0' ]
162
+ ---
163
+
164
+ The papersize will be the `papersize` of the first article found or the
165
+ default papersize on the `_config.yml` file. Same applies for
166
+ `sheetsize`.
167
+
168
+ NOTE: Authorship will be set to empty. This could change in the future.
169
+
170
+ ## Bibliography
171
+
172
+ If you have bibliography, pandoc recommends leaving an empty
173
+ section at the end of the document if you want to have a separate
174
+ section for it. For bundled articles, this plugin will remove the extra
175
+ sections and create one for everything at the end.
176
+
177
+ # Bibliography
178
+
179
+ <EOF>
180
+
181
+ You can also use the underlined version of the section title (aka
182
+ `settext style` vs `atx style`).
183
+
184
+
185
+ ## Layout
186
+
187
+ Add this liquid snippet on your `_layout/post.html` to generate links to the
188
+ other available formats from the post itself:
189
+
190
+ <ul>
191
+ {% for format in site.pandoc.outputs %}
192
+ {% capture extension %}{{ format | first }}{% endcapture %}
193
+ <li>
194
+ <a href="{{ page.url | remove:'.html' }}.{{ extension }}">
195
+ {{ extension }}
196
+ </a>
197
+ </li>
198
+ {% endfor %}
199
+ </ul>
200
+
201
+ ## How to install
202
+
203
+ Add this snippet to your `_config.yml` on jekyll 1.3
204
+
205
+ gems: [ 'jekyll-pandoc-multiple-formats' ]
206
+
207
+ Alternative, see
208
+ [here](https://github.com/fauno/jekyll-pandoc-multiple-formats/issues/7).
209
+
210
+
211
+ ## How to run
212
+
213
+ Execute `jekyll build` normally :D
214
+
215
+ ## Tectonic
216
+
217
+ If you want to use Tectonic, make sure it's installed into
218
+ `/usr/bin/tectonic` (or symlink it). It will be used instead of rtex
219
+ for imposition and adding covers.
220
+
221
+ It's specially useful if you're using unicode characters in your file
222
+ names.
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jekyll/pandoc/paru_helper'
4
+ require 'jekyll/pandoc/utils'
5
+
6
+ module Jekyll
7
+ module Converters
8
+ class Markdown
9
+ # Converts markdown content using Pandoc.
10
+ #
11
+ # A previous iteration of this converter monkeypatched Jekyll (10
12
+ # years ago!). Now we just use the method Jekyll provides which
13
+ # also provides caching.
14
+ #
15
+ # @see Jekyll::Converters::Markdown
16
+ # @see Jekyll::Converters::Markdown::KramdownParser
17
+ class Pandoc
18
+ # @return [Jekyll::Configuration]
19
+ attr_reader :config
20
+
21
+ # @param config [Jekyll::Configuration]
22
+ def initialize(config)
23
+ @config = config
24
+ end
25
+
26
+ # Convert the content into HTML
27
+ #
28
+ # @param content [String] Markdown
29
+ # @return [String] HTML
30
+ def convert(content)
31
+ parser << content
32
+ end
33
+
34
+ private
35
+
36
+ # Generates a parser from config
37
+ #
38
+ # @return [Paru::Pandoc]
39
+ def parser
40
+ @parser ||= Jekyll::Pandoc::ParuHelper.from(from: 'markdown+smart', to: 'html5',
41
+ metadata: 'title=Jekyll',
42
+ **config['pandoc'].options[:html5])
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jekyll/utils'
4
+
5
+ module Jekyll
6
+ module Pandoc
7
+ # Processes Pandoc configuration by merging common, per format and
8
+ # current locale options.
9
+ #
10
+ # There's no default configuration.
11
+ class Configuration
12
+ extend Forwardable
13
+
14
+ SPECIAL_OPTIONS = %w[common locales].freeze
15
+
16
+ # Jekyll site
17
+ #
18
+ # @return [Jekyll::Site]
19
+ attr_reader :site
20
+
21
+ # Processed options
22
+ #
23
+ # @return [Hash]
24
+ attr_reader :options
25
+
26
+ # Delegate key accessors to config
27
+ def_delegators :config, :[], :dig
28
+
29
+ # @param site [Jekyll::Site]
30
+ def initialize(site)
31
+ @site = site
32
+ @options = {}
33
+ end
34
+
35
+ # Configuration from site
36
+ #
37
+ # @return [Hash]
38
+ def config
39
+ @config ||= site.config['pandoc'] || {}
40
+ end
41
+
42
+ # Current locale. If you're using jekyll-locales, the site will
43
+ # be built once per locale, so the locale will be configured.
44
+ #
45
+ # @return [String,nil]
46
+ def current_locale
47
+ @current_locale ||= site.config['lang'] || site.config['locale']
48
+ end
49
+
50
+ # Available formats
51
+ #
52
+ # @return [Array]
53
+ def available_formats
54
+ @available_formats ||= ((config['options']&.keys || []) - SPECIAL_OPTIONS).map(&:to_sym).freeze
55
+ end
56
+
57
+ # Find PDF papersize
58
+ #
59
+ # @return [Symbol]
60
+ def papersize
61
+ @papersize ||= options.dig(:pdf, :variable).find do |v|
62
+ v.start_with? 'papersize='
63
+ end&.split('=', 2)&.last&.to_sym
64
+ end
65
+
66
+ # Merge all options and remove the ones disabled
67
+ #
68
+ # TODO: Process common first so it's not done for every format.
69
+ #
70
+ # @return [nil]
71
+ def process
72
+ return unless options.empty?
73
+
74
+ available_formats.each do |format|
75
+ options[format] =
76
+ paru_options(disable_options(reduce_options(format.to_s)))
77
+ end
78
+
79
+ nil
80
+ end
81
+
82
+ private
83
+
84
+ # @param format [String]
85
+ # @return [Hash]
86
+ def reduce_options(format)
87
+ [
88
+ config.dig('options', 'common'),
89
+ config.dig('options', 'locales', current_locale, 'common'),
90
+ config.dig('options', format),
91
+ config.dig('options', 'locales', current_locale)
92
+ ].compact.reduce do |config, next_config|
93
+ next_config = {} if next_config == true
94
+
95
+ Jekyll::Utils.deep_merge_hashes(config, next_config)
96
+ end
97
+ end
98
+
99
+ # Removes options with non truthy values
100
+ #
101
+ # @param options [Hash,nil]
102
+ # @return [Hash,nil]
103
+ def disable_options(options)
104
+ options&.select do |_, v|
105
+ v
106
+ end
107
+ end
108
+
109
+ # Convert options to Paru methods
110
+ #
111
+ # @param options [Hash,nil]
112
+ # @return [Hash,nil]
113
+ def paru_options(options)
114
+ options&.transform_keys do |k|
115
+ k.gsub('-', '_').to_sym
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,202 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tempfile'
4
+ require 'jekyll/document'
5
+ require_relative 'renderer'
6
+
7
+ module Jekyll
8
+ module Pandoc
9
+ # Represents a single document. Extends Jekyll::Document since it's
10
+ # the most complete class for managing documents. Either
11
+ # Convertible or Page are too constrained and would require to
12
+ # rewrite a lot of code.
13
+ class Document < Jekyll::Document
14
+ # Binary formats are treated specially because Pandoc writes them
15
+ # to disk, unless we were to use - as output file and read
16
+ # everything into memory.
17
+ #
18
+ # @return [Array]
19
+ BINARY_FORMATS = %i[pdf epub epub3 fb2 docx odt].freeze
20
+
21
+ # Site
22
+ #
23
+ # @return [Jekyll::Site]
24
+ attr_reader :site
25
+
26
+ # Collection
27
+ #
28
+ # @return [Jekyll::Collection]
29
+ attr_reader :collection
30
+
31
+ # Source document
32
+ #
33
+ # @return [Jekyll::Document]
34
+ attr_reader :source_document
35
+
36
+ # Content
37
+ #
38
+ # @return [String]
39
+ attr_accessor :content
40
+
41
+ # Output. Empty string if the file is in binary format
42
+ #
43
+ # @return [String]
44
+ attr_accessor :output
45
+
46
+ # @param path [String]
47
+ # @param relations [Hash]
48
+ def initialize(path, relations = {})
49
+ @source_document = relations[:source_document]
50
+ super
51
+ end
52
+
53
+ # Remove collection directory too so Jekyll doesn't confuse it
54
+ # with a category
55
+ #
56
+ # @return [String]
57
+ def relative_path
58
+ @relative_path ||= super.sub(source_document.collection.relative_directory, '')
59
+ end
60
+
61
+ # Temporary file where Pandoc writes binary formats
62
+ #
63
+ # @return [Tempfile]
64
+ def tempfile
65
+ @tempfile ||= Tempfile.new([data['slug'], output_ext])
66
+ end
67
+
68
+ # The path where the renderer wrote the actual contents for binary
69
+ # files.
70
+ #
71
+ # @return [String]
72
+ def rendered_path
73
+ tempfile.path
74
+ end
75
+
76
+ # Clone data from the source document
77
+ #
78
+ # @return [Hash]
79
+ def data
80
+ @data ||= source_document.data.dup
81
+ end
82
+
83
+ # Do nothing
84
+ def merge_defaults; end
85
+
86
+ # Duplicate the content
87
+ #
88
+ # @return [nil]
89
+ def read_content(**)
90
+ self.content = source_document.content.dup
91
+
92
+ nil
93
+ end
94
+
95
+ # "Read" data and adds itself to the source document data.
96
+ #
97
+ # @return [nil]
98
+ def read_post_data
99
+ # Assign a new UUIDv4 if the source document has one.
100
+ #
101
+ # TODO: How to assign the same UUID to every document?
102
+ if data.key? 'uuid'
103
+ require 'securerandom'
104
+ data['uuid'] = SecureRandom.uuid
105
+ end
106
+
107
+ data['binary'] = binary?
108
+
109
+ source_document.data['formats'] ||= []
110
+ source_document.data['formats'] << self
111
+ # Can't guarantee the front matter won't use the same key
112
+ source_document.data[collection.label] ||= self
113
+
114
+ nil
115
+ end
116
+
117
+ # The renderer will know how to convert this document to the
118
+ # needed format.
119
+ #
120
+ # @return [Jekyll::Pandoc::Renderer]
121
+ def renderer
122
+ @renderer ||= Renderer.new(site, self)
123
+ end
124
+
125
+ # If the format is binary, we need to copy the tempfile to the
126
+ # destination.
127
+ #
128
+ # @return [nil]
129
+ def write(dest)
130
+ super
131
+
132
+ return unless binary?
133
+
134
+ path = destination(dest)
135
+
136
+ FileUtils.rm path
137
+ FileUtils.cp rendered_path, path
138
+
139
+ nil
140
+ end
141
+
142
+ # Detect if the format is binary. The type is set from the
143
+ # collection label, which in turn is the Pandoc-supported format.
144
+ #
145
+ # @return [Boolean]
146
+ def binary?
147
+ BINARY_FORMATS.include? type
148
+ end
149
+
150
+ # Generate the destination from the URL and change .html to the
151
+ # output extension.
152
+ #
153
+ # @return [String]
154
+ def destination(dest)
155
+ super.sub(/\.html\z/, output_ext)
156
+ end
157
+
158
+ def url
159
+ @url ||= super.tap do |u|
160
+ u << data['slug'] << output_ext if u.end_with? '/'
161
+ end
162
+ end
163
+
164
+ # We don't have layouts (yet?)
165
+ #
166
+ # @return [FalseClass]
167
+ def place_in_layout?
168
+ false
169
+ end
170
+
171
+ # It's not an asset...
172
+ #
173
+ # @return [FalseClass]
174
+ def asset_file?
175
+ false
176
+ end
177
+
178
+ # Nor a SASS file...
179
+ #
180
+ # @return [FalseClass]
181
+ def sass_file?
182
+ false
183
+ end
184
+
185
+ # Or a CoffeeScript file...
186
+ #
187
+ # @return [FalseClass]
188
+ def coffeescript_file?
189
+ false
190
+ end
191
+
192
+ # No need to generate an excerpt either.
193
+ #
194
+ # @return [FalseClass]
195
+ def generate_excerpt?
196
+ false
197
+ end
198
+
199
+ def generate_excerpt; end
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../document'
4
+ require_relative '../renderers/binder'
5
+
6
+ module Jekyll
7
+ module Pandoc
8
+ module Documents
9
+ # A bound document is printed, cut and bound with pegament (or
10
+ # sewn, etc.)
11
+ class Bound < Jekyll::Pandoc::Document
12
+ def read_content(**)
13
+ self.content = ''
14
+ nil
15
+ end
16
+
17
+ # Adds relations to source documents
18
+ #
19
+ # @return [nil]
20
+ def read_post_data
21
+ if data.key? 'uuid'
22
+ require 'securerandom'
23
+ data['uuid'] = SecureRandom.uuid
24
+ end
25
+
26
+ source_document.source_document.data['bound'] =
27
+ source_document.data['bound'] = self
28
+
29
+ source_document.source_document.data['formats'] ||= []
30
+ source_document.source_document.data['formats'] << self
31
+
32
+ nil
33
+ end
34
+
35
+ # Binding
36
+ #
37
+ # @return [Jekyll::Pandoc::Renderers::Binder]
38
+ def renderer
39
+ @renderer ||= Jekyll::Pandoc::Renderers::Binder.new(site, self)
40
+ end
41
+
42
+ # The file is always binary
43
+ #
44
+ # @return [TrueClass]
45
+ def binary?
46
+ true
47
+ end
48
+
49
+ # PDFs can't be rendered with Liquid
50
+ #
51
+ # @return [FalseClass]
52
+ def render_with_liquid?
53
+ false
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end