bookify 2.2.0 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.
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.