bookify 2.0.0 → 2.5.0
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.
- checksums.yaml +5 -5
- data/lib/bookify.rb +4 -0
- data/lib/bookify/markdown.rb +44 -0
- data/lib/bookify/node/base.rb +7 -7
- data/lib/bookify/node/blockquote.rb +2 -0
- data/lib/bookify/node/div.rb +2 -0
- data/lib/bookify/node/h1.rb +12 -3
- data/lib/bookify/node/h2.rb +14 -2
- data/lib/bookify/node/h3.rb +2 -0
- data/lib/bookify/node/h4.rb +2 -0
- data/lib/bookify/node/hr.rb +2 -0
- data/lib/bookify/node/image.rb +3 -1
- data/lib/bookify/node/list.rb +2 -0
- data/lib/bookify/node/paragraph.rb +8 -3
- data/lib/bookify/node/table.rb +2 -0
- data/lib/bookify/renderer.rb +24 -8
- data/lib/bookify/sections.rb +31 -0
- data/lib/prawn_ext/font_metric_cache.rb +29 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8e07bd5f6f7148fa8711de2c1cf860236e3e3da1dd4fd411246c11b15958ac49
|
4
|
+
data.tar.gz: 2995c7ec5a3fef4fee1d8a837d77d253b99998d7bfb2e6a2465e067b142e9da1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44b913b44ff68a55071a0fbe5f88f7d8195872b6bc0deb39382d9b095b3a767d8c0b4cc183b80a9e32e001845bb421f5004b63a7189380981a8244ce8b07debe
|
7
|
+
data.tar.gz: ecb58a77471a62ad08a749bef069ae9642b9b318bcd2bb0c232326ec352d33bec34a952abfba672304fc712f0c6a41c27c506caa6cc40e898440892d086c7f81
|
data/lib/bookify.rb
CHANGED
@@ -6,10 +6,14 @@ require "prawn/table"
|
|
6
6
|
require "redcarpet"
|
7
7
|
require "htmlentities"
|
8
8
|
|
9
|
+
require_relative "prawn_ext/font_metric_cache"
|
10
|
+
|
9
11
|
module Bookify
|
10
12
|
end
|
11
13
|
|
12
14
|
Dir["#{File.dirname(__FILE__)}/bookify/node/*.rb"].each { |f| require f }
|
13
15
|
|
16
|
+
require_relative "bookify/markdown"
|
14
17
|
require_relative "bookify/node"
|
15
18
|
require_relative "bookify/renderer"
|
19
|
+
require_relative "bookify/sections"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Bookify::Markdown < Redcarpet::Render::HTML
|
2
|
+
@@preprocessors = []
|
3
|
+
@@postprocessors = []
|
4
|
+
|
5
|
+
def preprocess(string)
|
6
|
+
Bookify::Markdown.preprocessors.each do |preproc|
|
7
|
+
string = preproc.call(string)
|
8
|
+
end
|
9
|
+
|
10
|
+
string
|
11
|
+
end
|
12
|
+
|
13
|
+
def postprocess(string)
|
14
|
+
Bookify::Markdown.postprocessors.each do |postproc|
|
15
|
+
string = postproc.call(string)
|
16
|
+
end
|
17
|
+
|
18
|
+
string
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.add_preprocessor(preprocessor)
|
22
|
+
@@preprocessors << preprocessor
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.reset_preprocessors
|
26
|
+
@@preprocessors = []
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.preprocessors
|
30
|
+
@@preprocessors
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.add_postprocessor(postprocessor)
|
34
|
+
@@postprocessors << postprocessor
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.reset_postprocessors
|
38
|
+
@@postprocessors = []
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.postprocessors
|
42
|
+
@@postprocessors
|
43
|
+
end
|
44
|
+
end
|
data/lib/bookify/node/base.rb
CHANGED
@@ -3,10 +3,10 @@ module Bookify::Node
|
|
3
3
|
attr_accessor :node, :pdf
|
4
4
|
|
5
5
|
FONTS = {
|
6
|
-
h1:
|
7
|
-
h2:
|
8
|
-
h3:
|
9
|
-
h4:
|
6
|
+
h1: ["Book Antiqua", size: 16, style: :bold],
|
7
|
+
h2: ["Book Antiqua", size: 12, style: :bold],
|
8
|
+
h3: ["Book Antiqua", size: 11, style: :bold],
|
9
|
+
h4: ["Book Antiqua", size: 10, style: :bold],
|
10
10
|
primary: ["Book Antiqua", size: 10]
|
11
11
|
}
|
12
12
|
|
@@ -27,12 +27,12 @@ module Bookify::Node
|
|
27
27
|
(element.attr(:class) || "").split(" ")
|
28
28
|
end
|
29
29
|
|
30
|
-
def font(name)
|
31
|
-
pdf.font
|
30
|
+
def font(name, &block)
|
31
|
+
pdf.font(*FONTS[name], &block)
|
32
32
|
end
|
33
33
|
|
34
34
|
def clean_html(html)
|
35
|
-
html.
|
35
|
+
html.delete("\n").gsub(/\s+/, " ")
|
36
36
|
end
|
37
37
|
|
38
38
|
def decode_html(html)
|
data/lib/bookify/node/div.rb
CHANGED
data/lib/bookify/node/h1.rb
CHANGED
@@ -1,12 +1,21 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
1
3
|
module Bookify::Node
|
2
4
|
class H1 < Base
|
3
5
|
def render
|
4
6
|
break_if_close_to_bottom(250)
|
5
7
|
move_down 20 unless pdf.y == page_top
|
6
|
-
|
8
|
+
|
7
9
|
html = decode_html(node.inner_html.strip)
|
8
|
-
|
9
|
-
|
10
|
+
dest = dest_xyz(0, pdf.y, nil, pdf.page)
|
11
|
+
|
12
|
+
Bookify::Sections.add(:h1, html, dest)
|
13
|
+
add_dest(html, dest)
|
14
|
+
|
15
|
+
font :h1 do
|
16
|
+
text html, align: :center
|
17
|
+
end
|
18
|
+
|
10
19
|
move_down 10
|
11
20
|
end
|
12
21
|
|
data/lib/bookify/node/h2.rb
CHANGED
@@ -1,10 +1,22 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
1
3
|
module Bookify::Node
|
2
4
|
class H2 < Base
|
3
5
|
def render
|
4
|
-
font :h2
|
5
6
|
move_down 5
|
6
7
|
break_if_close_to_bottom
|
7
|
-
|
8
|
+
|
9
|
+
html = decode_html(node.inner_html.strip)
|
10
|
+
dest = dest_xyz(0, pdf.y, nil, pdf.page)
|
11
|
+
parent_h1 = Bookify::Sections.current_h1_title
|
12
|
+
|
13
|
+
Bookify::Sections.add(:h2, html, dest)
|
14
|
+
add_dest(html, dest)
|
15
|
+
add_dest("#{parent_h1}/#{html}", dest) if parent_h1
|
16
|
+
|
17
|
+
font :h2
|
18
|
+
text html
|
19
|
+
|
8
20
|
move_down 1
|
9
21
|
stroke { horizontal_rule }
|
10
22
|
move_down 10
|
data/lib/bookify/node/h3.rb
CHANGED
data/lib/bookify/node/h4.rb
CHANGED
data/lib/bookify/node/hr.rb
CHANGED
data/lib/bookify/node/image.rb
CHANGED
data/lib/bookify/node/list.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
1
3
|
module Bookify::Node
|
2
4
|
class Paragraph < Base
|
3
5
|
def render
|
@@ -11,9 +13,12 @@ module Bookify::Node
|
|
11
13
|
align: html_classes.include?("center") ? :center : :left
|
12
14
|
}
|
13
15
|
|
14
|
-
html = clean_html(node.inner_html.
|
15
|
-
|
16
|
-
|
16
|
+
html = clean_html(node.inner_html.tr("\n", " "))
|
17
|
+
|
18
|
+
font :primary do
|
19
|
+
text html, options
|
20
|
+
end
|
21
|
+
|
17
22
|
move_down 10
|
18
23
|
end
|
19
24
|
end
|
data/lib/bookify/node/table.rb
CHANGED
data/lib/bookify/renderer.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
class Bookify::Renderer
|
2
|
-
|
3
|
-
|
4
|
-
attr_accessor :input_file, :output_file, :layout, :columns, :input_text
|
2
|
+
attr_accessor :input_file, :output_file, :layout, :columns, :input_text, :column_spacer, :margin, :page_size
|
5
3
|
|
6
4
|
def self.from_args(args)
|
7
5
|
if ["-l", "--landscape"].include?(args[0])
|
@@ -19,23 +17,29 @@ class Bookify::Renderer
|
|
19
17
|
new(layout: layout, columns: columns, input_file: input_file, output_file: output_file)
|
20
18
|
end
|
21
19
|
|
22
|
-
def initialize(layout: :
|
20
|
+
def initialize(layout: :portrait, columns: 2, output_file:, input_file: nil, input_text: nil, column_spacer: nil, margin: 50, page_size: nil)
|
23
21
|
@layout = layout
|
24
22
|
@columns = columns
|
25
23
|
@output_file = output_file
|
26
24
|
@input_file = input_file
|
27
25
|
@input_text = input_text
|
26
|
+
@column_spacer = column_spacer
|
27
|
+
@margin = margin
|
28
|
+
@page_size = page_size
|
28
29
|
end
|
29
30
|
|
30
31
|
def render
|
31
|
-
|
32
|
+
doc_opts = {margin: margin, page_layout: layout, page_size: page_size}.compact
|
33
|
+
Bookify::Sections.reset
|
34
|
+
|
35
|
+
Prawn::Document.generate(output_file, doc_opts) do |pdf|
|
32
36
|
font_path = "#{File.dirname(__FILE__)}/../../fonts"
|
33
37
|
|
34
38
|
pdf.font_families["Book Antiqua"] = {
|
35
39
|
normal: {file: "#{font_path}/BookAntiqua.ttf"},
|
36
40
|
bold: {file: "#{font_path}/BookAntiqua-Bold.ttf"},
|
37
41
|
italic: {file: "#{font_path}/BookAntiqua-Italic.ttf"},
|
38
|
-
bold_italic: {file: "#{font_path}/BookAntiqua-BoldItalic.ttf"}
|
42
|
+
bold_italic: {file: "#{font_path}/BookAntiqua-BoldItalic.ttf"}
|
39
43
|
}
|
40
44
|
|
41
45
|
pdf.fill_color "000000"
|
@@ -43,9 +47,17 @@ class Bookify::Renderer
|
|
43
47
|
pdf.line_width(0.5)
|
44
48
|
pdf.default_leading 0.5
|
45
49
|
|
46
|
-
pdf.column_box [0, pdf.cursor], columns: columns, width: pdf.bounds.width do
|
50
|
+
pdf.column_box [0, pdf.cursor], columns: columns, width: pdf.bounds.width, spacer: (column_spacer || pdf.font_size) do
|
47
51
|
doc.children.each { |c| Bookify::Node.render(c, pdf) }
|
48
52
|
end
|
53
|
+
|
54
|
+
Bookify::Sections.all.each do |section|
|
55
|
+
pdf.outline.section(section[:title], destination: section[:dest]) do
|
56
|
+
section[:subsections].each do |subsection|
|
57
|
+
pdf.outline.page title: subsection[:title], destination: subsection[:dest]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
49
61
|
end
|
50
62
|
end
|
51
63
|
|
@@ -60,6 +72,10 @@ class Bookify::Renderer
|
|
60
72
|
end
|
61
73
|
|
62
74
|
def html
|
63
|
-
@html ||=
|
75
|
+
@html ||= markdown_converter.render(markdown)
|
76
|
+
end
|
77
|
+
|
78
|
+
def markdown_converter
|
79
|
+
Redcarpet::Markdown.new(Bookify::Markdown, tables: true)
|
64
80
|
end
|
65
81
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Bookify
|
2
|
+
module Sections
|
3
|
+
InvalidLevel = Class.new(StandardError)
|
4
|
+
|
5
|
+
@@sections = []
|
6
|
+
|
7
|
+
def self.add(level, title, dest)
|
8
|
+
case level
|
9
|
+
when :h1
|
10
|
+
@@sections << {title: title, dest: dest, subsections: []}
|
11
|
+
when :h2
|
12
|
+
return if @@sections.empty?
|
13
|
+
@@sections.last[:subsections] << {title: title, dest: dest}
|
14
|
+
else
|
15
|
+
raise InvalidLevel, level
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.all
|
20
|
+
@@sections
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.current_h1_title
|
24
|
+
@@sections.any? ? @@sections.last[:title] : nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.reset
|
28
|
+
@@sections = []
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# https://github.com/prawnpdf/prawn/issues/1140
|
2
|
+
|
3
|
+
module Prawn
|
4
|
+
class FontMetricCache
|
5
|
+
def width_of(string, options)
|
6
|
+
f = if options[:style]
|
7
|
+
# override style with :style => :bold
|
8
|
+
@document.find_font(@document.font.family, style: options[:style])
|
9
|
+
else
|
10
|
+
@document.font
|
11
|
+
end
|
12
|
+
|
13
|
+
encoded_string = f.normalize_encoding(string)
|
14
|
+
|
15
|
+
key = CacheEntry.new(f.hash, options, encoded_string)
|
16
|
+
|
17
|
+
@cache[key] ||= f.compute_width_of(encoded_string, options)
|
18
|
+
|
19
|
+
length = @cache[key]
|
20
|
+
|
21
|
+
character_count = @document.font.character_count(encoded_string)
|
22
|
+
if character_count.positive?
|
23
|
+
length += @document.character_spacing * (character_count - 1)
|
24
|
+
end
|
25
|
+
|
26
|
+
length
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bookify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joey Schoblaska
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-06-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- fonts/BookAntiqua-Italic.ttf
|
108
108
|
- fonts/BookAntiqua.ttf
|
109
109
|
- lib/bookify.rb
|
110
|
+
- lib/bookify/markdown.rb
|
110
111
|
- lib/bookify/node.rb
|
111
112
|
- lib/bookify/node/base.rb
|
112
113
|
- lib/bookify/node/blockquote.rb
|
@@ -121,6 +122,8 @@ files:
|
|
121
122
|
- lib/bookify/node/paragraph.rb
|
122
123
|
- lib/bookify/node/table.rb
|
123
124
|
- lib/bookify/renderer.rb
|
125
|
+
- lib/bookify/sections.rb
|
126
|
+
- lib/prawn_ext/font_metric_cache.rb
|
124
127
|
homepage: https://github.com/joeyschoblaska/bookify
|
125
128
|
licenses:
|
126
129
|
- MIT
|
@@ -140,8 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
143
|
- !ruby/object:Gem::Version
|
141
144
|
version: '0'
|
142
145
|
requirements: []
|
143
|
-
|
144
|
-
rubygems_version: 2.6.14
|
146
|
+
rubygems_version: 3.1.2
|
145
147
|
signing_key:
|
146
148
|
specification_version: 4
|
147
149
|
summary: Transform Markdown docs into two-column PDFs.
|