jekyll-printing-press 1.0.0rc1

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.
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+ require_relative '../document'
5
+ require_relative '../renderers/imposition'
6
+
7
+ module Jekyll
8
+ module Pandoc
9
+ module Documents
10
+ # An imposed document is a PDF with pages arranged for printing
11
+ # and folding.
12
+ class Imposed < Jekyll::Pandoc::Document
13
+ # Do nothing, content is not read, but Jekyll expects a String
14
+ #
15
+ # @return [nil]
16
+ def read_content(**)
17
+ self.content = ''
18
+ nil
19
+ end
20
+
21
+ # Adds relations to source documents
22
+ #
23
+ # @return [nil]
24
+ def read_post_data
25
+ if data.key? 'uuid'
26
+ require 'securerandom'
27
+ data['uuid'] = SecureRandom.uuid
28
+ end
29
+
30
+ source_document.source_document.data['imposed'] =
31
+ source_document.data['imposed'] = self
32
+
33
+ source_document.source_document.data['formats'] << self
34
+
35
+ nil
36
+ end
37
+
38
+ # Imposition
39
+ #
40
+ # @return [Jekyll::Pandoc::Renderers::Imposition]
41
+ def renderer
42
+ @renderer ||= Jekyll::Pandoc::Renderers::Imposition.new(site, self)
43
+ end
44
+
45
+ # The file is always binary
46
+ #
47
+ # @return [TrueClass]
48
+ def binary?
49
+ true
50
+ end
51
+
52
+ # PDFs can't be rendered with Liquid
53
+ #
54
+ # @return [FalseClass]
55
+ def render_with_liquid?
56
+ false
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+ require 'jekyll/utils'
5
+ require_relative '../document'
6
+ require_relative '../utils'
7
+
8
+ module Jekyll
9
+ module Pandoc
10
+ module Documents
11
+ # A document composed of several documents
12
+ class Multiple < Jekyll::Pandoc::Document
13
+ # Documents group
14
+ #
15
+ # @return [Array]
16
+ attr_reader :source_documents
17
+
18
+ # @param path [String]
19
+ # @param relations [Hash]
20
+ def initialize(path, relations = {})
21
+ @source_documents = relations[:source_documents]
22
+ relations[:source_document] = self
23
+ super
24
+
25
+ Jekyll::Utils.deep_merge_hashes!(data, relations[:data])
26
+ end
27
+
28
+ # Data must be provided externally
29
+ #
30
+ # @return [Hash]
31
+ def data
32
+ @data ||= { 'multiple' => true }
33
+ end
34
+
35
+ # The content is a concatenated string of source_documents
36
+ # content with their titles.
37
+ #
38
+ # The ID is attached to a title so you can map IDs to metadata
39
+ # on a Pandoc filter later.
40
+ #
41
+ # @return [nil]
42
+ def read_content(**)
43
+ self.content = source_documents.map do |doc|
44
+ ["\n\n# #{doc['title']} {##{extract_id(doc)} data-chapter-title=true}", doc.content]
45
+ end.flatten.join("\n\n")
46
+
47
+ nil
48
+ end
49
+
50
+ # Generates a data hash from source documents so they can be
51
+ # accessed later as Pandoc metadata. For instance, to generate
52
+ # authors per chapter.
53
+ #
54
+ # @return [nil]
55
+ def read_post_data
56
+ data['uuid'] ||= SecureRandom.uuid
57
+
58
+ source_documents.each do |doc|
59
+ data[extract_id(doc)] = Jekyll::Pandoc::Utils.sanitize_data doc.data
60
+ end
61
+
62
+ nil
63
+ end
64
+
65
+ private
66
+
67
+ # Extracts an ID from a document
68
+ #
69
+ # @return [String]
70
+ def extract_id(document)
71
+ document['uuid'] || document.id.tr('/', '-').sub(/\A-/, '')
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Pandoc
5
+ # Generates all Pandoc documents and adds them to the site. The
6
+ # documents are not written, just prepared for later rendering and
7
+ # writing following Jekyll's process.
8
+ #
9
+ # @see Jekyll::Site#generate
10
+ # @see Jekyll::Generator
11
+ class Generator < ::Jekyll::Generator
12
+ safe true
13
+ priority :highest
14
+
15
+ # Site
16
+ #
17
+ # @return [Jekyll::Site]
18
+ attr_reader :site
19
+
20
+ # Pandoc collections
21
+ #
22
+ # @return [Hash]
23
+ attr_reader :collections
24
+
25
+ # Generate documents for every format.
26
+ #
27
+ # @return [nil]
28
+ def generate(site)
29
+ @site = site
30
+ @collections = {}
31
+
32
+ return unless generate?
33
+
34
+ setup
35
+ generate_documents!
36
+ end
37
+
38
+ private
39
+
40
+ # Do nothing for now
41
+ def setup; end
42
+
43
+ # Source documents. Every generator know how to fetch its own
44
+ # documents.
45
+ #
46
+ # @return [Array]
47
+ def source_documents
48
+ raise NotImplementedError
49
+ end
50
+
51
+ # This method knows how to collect documents, and generate
52
+ # collections and Pandoc documents.
53
+ #
54
+ # @return [nil]
55
+ def generate_documents!
56
+ raise NotImplementedError
57
+ end
58
+
59
+ # @return [Hash]
60
+ def config
61
+ site.config['pandoc']
62
+ end
63
+
64
+ # Jekyll runs every Jekyll::Generator descendant, but we don't
65
+ # want to run this one, just use it as a template.
66
+ #
67
+ # @return [Boolean]
68
+ def generate?
69
+ self.class != Jekyll::Pandoc::Generator
70
+ end
71
+
72
+ # Creates or finds a collection by a label, performs basic
73
+ # configuration and brings everything else from site
74
+ # configuration.
75
+ #
76
+ # @param label [String]
77
+ # @return [Hash]
78
+ def collection_for(label)
79
+ site.collections[label] ||=
80
+ Jekyll::Collection.new(site, label).tap do |col|
81
+ # Allow to configure the collection
82
+ # @see https://jekyllrb.com/docs/collections/
83
+ col.metadata['output'] = true unless col.metadata.key? 'output'
84
+ # Follow the same permalink structure unless otherwise
85
+ # specified.
86
+ unless site.config.dig('collections', label, 'permalink')
87
+ col.metadata['permalink'] =
88
+ site.posts.url_template
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../generator'
4
+ require_relative '../documents/bound'
5
+
6
+ module Jekyll
7
+ module Pandoc
8
+ module Generators
9
+ # Generates a ready for print PDF for use in a binding machine.
10
+ class Binder < Jekyll::Pandoc::Generator
11
+ priority :high
12
+
13
+ private
14
+
15
+ # Only generate if the site asks for imposition
16
+ #
17
+ # @return [Boolean]
18
+ def generate?
19
+ site.config.dig('pandoc', 'printing', 'formats')&.include? 'binder'
20
+ end
21
+
22
+ # Only PDFs are imposed
23
+ #
24
+ # @return [Array]
25
+ def source_documents
26
+ @source_documents ||= site.collections['pdf'].docs
27
+ end
28
+
29
+ # Generate a {Jekyll::Pandoc::Documents::Bound} per document
30
+ #
31
+ # @return [nil]
32
+ def generate_documents!
33
+ source_documents.each do |document|
34
+ collection_for('bound').tap do |col|
35
+ col.docs << Jekyll::Pandoc::Documents::Bound.new(document.path, site: site, collection: col,
36
+ source_document: document).tap(&:read)
37
+ end
38
+ end
39
+
40
+ nil
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../generator'
4
+ require_relative 'multiple'
5
+
6
+ module Jekyll
7
+ module Pandoc
8
+ module Generators
9
+ class Category < Jekyll::Pandoc::Generator
10
+ include Multiple
11
+
12
+ priority :high
13
+
14
+ private
15
+
16
+ # Group posts by categories
17
+ #
18
+ # @return [String]
19
+ def generator_type
20
+ @generator_type ||= 'categories'
21
+ end
22
+
23
+ # Groups documents by category
24
+ #
25
+ # @return [Array]
26
+ def source_documents
27
+ @source_documents ||= site.categories.to_a
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../generator'
4
+ require_relative '../documents/imposed'
5
+
6
+ module Jekyll
7
+ module Pandoc
8
+ module Generators
9
+ # Generates a ready for print PDF by creating 4-pages sheets.
10
+ class Imposition < Jekyll::Pandoc::Generator
11
+ priority :high
12
+
13
+ private
14
+
15
+ # Only generate if the site asks for imposition
16
+ #
17
+ # @return [Boolean]
18
+ def generate?
19
+ site.config.dig('pandoc', 'printing', 'formats')&.include? 'imposition'
20
+ end
21
+
22
+ # Only PDFs are imposed
23
+ #
24
+ # @return [Array]
25
+ def source_documents
26
+ @source_documents ||= site.collections['pdf'].docs
27
+ end
28
+
29
+ # Generate a {Jekyll::Pandoc::Documents::Imposed} per document
30
+ #
31
+ # @return [nil]
32
+ def generate_documents!
33
+ source_documents.each do |document|
34
+ collection_for('imposed').tap do |col|
35
+ col.docs << Jekyll::Pandoc::Documents::Imposed.new(document.path, site: site, collection: col,
36
+ source_document: document).tap(&:read)
37
+ end
38
+ end
39
+
40
+ nil
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tempfile'
4
+ require 'jekyll/utils'
5
+ require_relative '../documents/multiple'
6
+
7
+ module Jekyll
8
+ module Pandoc
9
+ module Generators
10
+ # Mixin for multiple-file generators
11
+ module Multiple
12
+ private
13
+
14
+ # Generator type
15
+ #
16
+ # @return [String]
17
+ def generator_type
18
+ raise NotImplementedError
19
+ end
20
+
21
+ # Must return an Array of grouped documents (an Array of Arrays)
22
+ #
23
+ # @return [Array]
24
+ def source_documents
25
+ raise NotImplementedError
26
+ end
27
+
28
+ # @return [Boolean]
29
+ def generate?
30
+ config['documents']&.include? generator_type
31
+ end
32
+
33
+ # Generates a temporary file on site source per each document
34
+ # group and passes data as a relation.
35
+ #
36
+ # @return [nil]
37
+ def generate_documents!
38
+ source_documents.each do |(title, documents)|
39
+ config.available_formats.each do |format|
40
+ next if format == :html5
41
+
42
+ data = {
43
+ 'title' => title,
44
+ 'slug' => Jekyll::Utils.slugify(title, mode: 'pretty'),
45
+ 'data' => Time.now
46
+ }
47
+ label = format.to_s
48
+ file = Tempfile.new([data['slug'], '.markdown'], site.source)
49
+
50
+ collection_for(label).tap do |col|
51
+ col.docs << Jekyll::Pandoc::Documents::Multiple.new(file.path, site: site, collection: col,
52
+ source_documents: documents, data: data).tap(&:read)
53
+ end
54
+ end
55
+ end
56
+
57
+ nil
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../document'
4
+ require_relative '../generator'
5
+
6
+ module Jekyll
7
+ module Pandoc
8
+ class Generator
9
+ # Generates Pandoc documents from Jekyll posts collection. Each
10
+ # format is a collection.
11
+ class Posts < Generator
12
+ priority :highest
13
+
14
+ private
15
+
16
+ # Only generate if aggregating posts is enabled
17
+ #
18
+ # @return [Boolean]
19
+ def generate?
20
+ config['documents']&.include? 'posts'
21
+ end
22
+
23
+ # Documents to generate from
24
+ #
25
+ # @return [Array]
26
+ def source_documents
27
+ @source_documents ||= site.posts.docs.reject(&:asset_file?)
28
+ end
29
+
30
+ # Generate a Pandoc document for each format and adds it to
31
+ # a collection.
32
+ #
33
+ # HTML5 is already generated by
34
+ # {Jekyll::Converters::Markdown::Pandoc}
35
+ #
36
+ # @return [nil]
37
+ def generate_documents!
38
+ source_documents.each do |document|
39
+ config.available_formats.each do |format|
40
+ next if format == :html5
41
+
42
+ collection_for(format.to_s).tap do |col|
43
+ col.docs << Document.new(document.path, site: site, collection: col,
44
+ source_document: document).tap(&:read)
45
+ end
46
+ end
47
+ end
48
+
49
+ nil
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../generator'
4
+ require_relative 'multiple'
5
+
6
+ module Jekyll
7
+ module Pandoc
8
+ module Generators
9
+ class Site < Jekyll::Pandoc::Generator
10
+ include Multiple
11
+
12
+ priority :high
13
+
14
+ private
15
+
16
+ # All posts
17
+ #
18
+ # @return [String]
19
+ def generator_type
20
+ @generator_type ||= 'site'
21
+ end
22
+
23
+ # All posts
24
+ #
25
+ # @return [Array]
26
+ def source_documents
27
+ @source_documents ||= [ [ site.config['title'], site.posts.docs.reject(&:asset_file?) ] ]
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'paru/pandoc'
4
+
5
+ module Jekyll
6
+ module Pandoc
7
+ # Creates a Paru::Pandoc with options from configuration
8
+ module ParuHelper
9
+ extend self
10
+
11
+ # Returns a Paru::Pandoc with options set
12
+ #
13
+ # @param options [Hash]
14
+ # @return [Paru::Pandoc]
15
+ def from(options)
16
+ Paru::Pandoc.new.tap do |paru|
17
+ options.each do |option, value|
18
+ paru.send option, value
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ \documentclass[{{ sheetsize }},10pt]{article}
2
+
3
+ \usepackage{pgfpages}
4
+ \usepackage{pdfpages}
5
+
6
+ \pgfpagesuselayout{ {{- nup }} on 1}[{{ sheetsize }},{{ options }}]
7
+
8
+ \begin{document}
9
+ \includepdf[pages={ {{- pages | join: ',' -}} }]{ {{- path -}} }
10
+ \end{document}