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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d440b7412142dae84f47b9653733a33f826d5057
4
- data.tar.gz: 515bbecc3fd4ee92fca7434812e4ca00a60d21ea
2
+ SHA256:
3
+ metadata.gz: 8e07bd5f6f7148fa8711de2c1cf860236e3e3da1dd4fd411246c11b15958ac49
4
+ data.tar.gz: 2995c7ec5a3fef4fee1d8a837d77d253b99998d7bfb2e6a2465e067b142e9da1
5
5
  SHA512:
6
- metadata.gz: 4a7fffa9f6cac1980f5dd80cb97bdafc73ba13fdf6c0879a74e2a63e14527ba4701146e32068f1da29776870e20a0c77b099d01e2d021755c47586c8f5d8ad64
7
- data.tar.gz: 9afd804f9f1d614dab9d21995d6ef08a3c944a43acafc2304fa091755c1bf5d3e4b4109daf502a16abe031d127b18d331a538060bac01e63e33094ad6930c166
6
+ metadata.gz: 44b913b44ff68a55071a0fbe5f88f7d8195872b6bc0deb39382d9b095b3a767d8c0b4cc183b80a9e32e001845bb421f5004b63a7189380981a8244ce8b07debe
7
+ data.tar.gz: ecb58a77471a62ad08a749bef069ae9642b9b318bcd2bb0c232326ec352d33bec34a952abfba672304fc712f0c6a41c27c506caa6cc40e898440892d086c7f81
@@ -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: 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 *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)
@@ -1,3 +1,5 @@
1
+ require_relative "base"
2
+
1
3
  module Bookify::Node
2
4
  class Blockquote < Base
3
5
  def render
@@ -1,3 +1,5 @@
1
+ require_relative "base"
2
+
1
3
  module Bookify::Node
2
4
  class Div < Base
3
5
  def render
@@ -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
- font :h1
8
+
7
9
  html = decode_html(node.inner_html.strip)
8
- outline.page title: html, destination: dest_xyz(0, pdf.y, nil, pdf.page)
9
- text html, align: :center
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
 
@@ -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
- 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
18
+ text html
19
+
8
20
  move_down 1
9
21
  stroke { horizontal_rule }
10
22
  move_down 10
@@ -1,3 +1,5 @@
1
+ require_relative "base"
2
+
1
3
  module Bookify::Node
2
4
  class H3 < Base
3
5
  def render
@@ -1,3 +1,5 @@
1
+ require_relative "base"
2
+
1
3
  module Bookify::Node
2
4
  class H4 < Base
3
5
  def render
@@ -1,3 +1,5 @@
1
+ require_relative "base"
2
+
1
3
  module Bookify::Node
2
4
  class Hr < Base
3
5
  def render
@@ -1,9 +1,11 @@
1
+ require_relative "base"
2
+
1
3
  module Bookify::Node
2
4
  class Image < Base
3
5
  def render
4
6
  options = {
5
7
  position: html_classes.include?("center") ? :center : :left,
6
- fit: [bounds.width, -1]
8
+ fit: [bounds.width, -1],
7
9
  }
8
10
 
9
11
  image node.attr(:src), options
@@ -1,3 +1,5 @@
1
+ require_relative "base"
2
+
1
3
  module Bookify::Node
2
4
  class List < Base
3
5
  PADDING = 3
@@ -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.gsub("\n", " "))
15
- font :primary
16
- text html, options
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
@@ -1,3 +1,5 @@
1
+ require_relative "base"
2
+
1
3
  module Bookify::Node
2
4
  class Table < Base
3
5
  def render
@@ -1,7 +1,5 @@
1
1
  class Bookify::Renderer
2
- MARKDOWN_CONVERTER = Redcarpet::Markdown.new(Redcarpet::Render::HTML, tables: true)
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: :landscape, columns: 2, output_file:, input_file: nil, input_text: nil)
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
- Prawn::Document.generate(output_file, margin: 50, page_layout: layout) do |pdf|
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 ||= 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)
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.0.0
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: 2019-12-24 00:00:00.000000000 Z
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
- rubyforge_project:
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.