bookify 2.2.0 → 2.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5efda6174113c079df650774858604834a31f9c8730cc01526488186057fdb1e
4
- data.tar.gz: c469a5f6aa68441251a53e8daa8fc6c76335a03c71f30dcaf471852a1edf152f
3
+ metadata.gz: 23a677a6b7a9b17f6d796c2e592ecd6a257e64567453830317304937e222b478
4
+ data.tar.gz: 7ccbcdfab8abd3606dd5959af91bd931488513f301fe0bc1ecf5da3aa50d4b23
5
5
  SHA512:
6
- metadata.gz: 4521dca613962076e908c59acc7b7f1af57f23a667503969b5b32fd4d81495edde82018fb47bb891e5e5ae47967a40922a647d449c80e616a5770d7ea5fa9b15
7
- data.tar.gz: e7d33822d208f7ed34a690ef92da5a670db6a177dff1ec5ae0145e6ada1203f3d45c28d671c30777385aae939cc1f125aadbe86eccf1c6943d78a13b79153af6
6
+ metadata.gz: fa7ca38229470047590911625ec13963746cc6cf01b49e3a8bd6fcfeb6ec5eb556d7897dac641579b7ea68b1be0a72cd1a92e9ebc221eb90145e30bf690e210b
7
+ data.tar.gz: 0a2792823adcb885befd77f217d3fcd560f7ce0a0b28c2d40758e989eab6336b8c0dafa2c14aa44f03c150bf3ce1a1c4057c8add247a39c89057e5049d727b66
@@ -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
@@ -3,10 +3,10 @@ module Bookify::Node
3
3
  attr_accessor :node, :pdf
4
4
 
5
5
  FONTS = {
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],
6
+ h1: ["Book Antiqua", size: 18, style: :bold],
7
+ h2: ["Book Antiqua", size: 13, style: :bold],
8
+ h3: ["Book Antiqua", size: 12, style: :bold],
9
+ h4: ["Book Antiqua", size: 11, 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 *FONTS[name]
30
+ def font(name, &block)
31
+ pdf.font(*FONTS[name], &block)
32
32
  end
33
33
 
34
34
  def clean_html(html)
35
- html.gsub(/\n/, "").gsub(/\s+/, " ")
35
+ html.delete("\n").gsub(/\s+/, " ")
36
36
  end
37
37
 
38
38
  def decode_html(html)
@@ -4,12 +4,19 @@ module Bookify::Node
4
4
  class H1 < Base
5
5
  def render
6
6
  break_if_close_to_bottom(250)
7
- move_down 20 unless pdf.y == page_top
8
- font :h1
7
+ move_down 30 unless pdf.y == page_top
8
+
9
9
  html = decode_html(node.inner_html.strip)
10
- outline.page title: html, destination: dest_xyz(0, pdf.y, nil, pdf.page)
11
- text html, align: :center
12
- move_down 10
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
+
19
+ move_down 30
13
20
  end
14
21
 
15
22
  def page_top
@@ -3,10 +3,21 @@ require_relative "base"
3
3
  module Bookify::Node
4
4
  class H2 < Base
5
5
  def render
6
- font :h2
7
- move_down 5
6
+ move_down 15 unless pdf.y == page_top
8
7
  break_if_close_to_bottom
9
- text decode_html(node.inner_html.strip)
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 do
18
+ text html
19
+ end
20
+
10
21
  move_down 1
11
22
  stroke { horizontal_rule }
12
23
  move_down 10
@@ -3,11 +3,14 @@ require_relative "base"
3
3
  module Bookify::Node
4
4
  class H3 < Base
5
5
  def render
6
- font :h3
7
- move_down 5
6
+ move_down 5 unless pdf.y == page_top
8
7
  break_if_close_to_bottom
9
- text decode_html(node.inner_html.strip)
10
- move_down 2
8
+
9
+ font :h3 do
10
+ text decode_html(node.inner_html.strip)
11
+ end
12
+
13
+ move_down 5
11
14
  end
12
15
  end
13
16
  end
@@ -3,11 +3,14 @@ require_relative "base"
3
3
  module Bookify::Node
4
4
  class H4 < Base
5
5
  def render
6
- move_down 5
6
+ move_down 5 unless pdf.y == page_top
7
7
  break_if_close_to_bottom
8
- font :h4
9
- text decode_html(node.inner_html.strip)
10
- move_down 2
8
+
9
+ font :h4 do
10
+ text decode_html(node.inner_html.strip)
11
+ end
12
+
13
+ move_down 5
11
14
  end
12
15
  end
13
16
  end
@@ -1,15 +1,23 @@
1
1
  require_relative "base"
2
+ require "open-uri"
2
3
 
3
4
  module Bookify::Node
4
5
  class Image < Base
5
6
  def render
6
7
  options = {
7
8
  position: html_classes.include?("center") ? :center : :left,
8
- fit: [bounds.width, -1],
9
+ fit: [bounds.width, -1]
9
10
  }
10
11
 
11
- image node.attr(:src), options
12
+ image image_from_node(node), options
12
13
  move_down 15
13
14
  end
15
+
16
+ private
17
+
18
+ def image_from_node(node)
19
+ src = node.attr(:src)
20
+ /^https?\:\/\//.match?(src) ? URI.open(src) : src
21
+ end
14
22
  end
15
23
  end
@@ -13,9 +13,12 @@ module Bookify::Node
13
13
  align: html_classes.include?("center") ? :center : :left
14
14
  }
15
15
 
16
- html = clean_html(node.inner_html.gsub("\n", " "))
17
- font :primary
18
- text html, options
16
+ html = clean_html(node.inner_html.tr("\n", " "))
17
+
18
+ font :primary do
19
+ text html, options
20
+ end
21
+
19
22
  move_down 10
20
23
  end
21
24
  end
@@ -5,19 +5,20 @@ module Bookify::Node
5
5
  def render
6
6
  font :primary
7
7
 
8
- table table_data, header: true, width: bounds.width do
8
+ options = {
9
+ header: true,
10
+ width: bounds.width,
11
+ row_colors: ["FFFFFF", "EEEEEE"]
12
+ }
13
+
14
+ table table_data, options do
9
15
  cells.borders = []
10
16
 
11
- row(0).borders = [:top, :bottom]
12
- row(0).border_top_width = 0.5
17
+ row(0).borders = [:bottom]
13
18
  row(0).border_bottom_width = 0.5
14
19
  row(0).font_style = :bold
15
20
 
16
- row(-1).borders = [:bottom]
17
- row(-1).border_bottom_width = 0.5
18
-
19
- cells.columns(0).padding = [5, 5, 5, 0]
20
- cells.columns(-1).padding = [5, 0, 5, 5]
21
+ cells.padding = 5
21
22
  end
22
23
 
23
24
  move_down 15
@@ -1,6 +1,4 @@
1
1
  class Bookify::Renderer
2
- MARKDOWN_CONVERTER = Redcarpet::Markdown.new(Redcarpet::Render::HTML, tables: true)
3
-
4
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)
@@ -32,6 +30,7 @@ class Bookify::Renderer
32
30
 
33
31
  def render
34
32
  doc_opts = {margin: margin, page_layout: layout, page_size: page_size}.compact
33
+ Bookify::Sections.reset
35
34
 
36
35
  Prawn::Document.generate(output_file, doc_opts) do |pdf|
37
36
  font_path = "#{File.dirname(__FILE__)}/../../fonts"
@@ -40,7 +39,7 @@ class Bookify::Renderer
40
39
  normal: {file: "#{font_path}/BookAntiqua.ttf"},
41
40
  bold: {file: "#{font_path}/BookAntiqua-Bold.ttf"},
42
41
  italic: {file: "#{font_path}/BookAntiqua-Italic.ttf"},
43
- bold_italic: {file: "#{font_path}/BookAntiqua-BoldItalic.ttf"},
42
+ bold_italic: {file: "#{font_path}/BookAntiqua-BoldItalic.ttf"}
44
43
  }
45
44
 
46
45
  pdf.fill_color "000000"
@@ -51,6 +50,14 @@ class Bookify::Renderer
51
50
  pdf.column_box [0, pdf.cursor], columns: columns, width: pdf.bounds.width, spacer: (column_spacer || pdf.font_size) do
52
51
  doc.children.each { |c| Bookify::Node.render(c, pdf) }
53
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
54
61
  end
55
62
  end
56
63
 
@@ -65,6 +72,10 @@ class Bookify::Renderer
65
72
  end
66
73
 
67
74
  def html
68
- @html ||= MARKDOWN_CONVERTER.render(markdown)
75
+ @html ||= markdown_converter.render(markdown)
76
+ end
77
+
78
+ def markdown_converter
79
+ Redcarpet::Markdown.new(Bookify::Markdown, tables: true)
69
80
  end
70
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.2.0
4
+ version: 2.8.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: 2020-02-16 00:00:00.000000000 Z
11
+ date: 2020-06-16 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,7 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
143
  - !ruby/object:Gem::Version
141
144
  version: '0'
142
145
  requirements: []
143
- rubygems_version: 3.0.6
146
+ rubygems_version: 3.1.2
144
147
  signing_key:
145
148
  specification_version: 4
146
149
  summary: Transform Markdown docs into two-column PDFs.