bookify 2.0.0 → 2.5.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
- 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.