bookify 2.1.0 → 2.6.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: f23a775e5028eaf16b107b248c9dffa70db37f9a
4
- data.tar.gz: e7d2856954ca690cd95eabeee2fa5fe6813bcb7b
2
+ SHA256:
3
+ metadata.gz: 4255cf2b6bf6760ab6e48f513e5b72d39c76a524052a900801445462743cfd20
4
+ data.tar.gz: d8ddad7073160d14d02bcfcc366f7067af49f0bd73edbaba0739ee3db0e2f57b
5
5
  SHA512:
6
- metadata.gz: fe2864dff4466b630ea3bda1c62801da54ade54536c1c5b708303a19dfb64383bb3bea17ae9e1d5d228803b1902e9d01d8026fe85338dc106838808bf529d437
7
- data.tar.gz: 414358a289aed313ab20f212e9d811045e26f194c9df23a40d801bc0125157ac937b45b3a2beccfc957eb1fcc0269e2946d1dad9d2a51ab41fbc822695aa3b5c
6
+ metadata.gz: bfa67e29bf649746630e7352d5892d46616a9cd463ff937fd06dd6b5d4c69f870af036e33d993af1fd9a8ea49c2e80eb116da3c3191bdd5552a0e82f413375a2
7
+ data.tar.gz: c37247ac47f1df3703933e78b546f6ccea7c6e10964abbad50b0a23e4460e335c167376aa5d03ca34832ef7ab93f27cc0f6c1077c67cc156618ecc29a9774fcd
@@ -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,3 +1,6 @@
1
+ require_relative "base"
2
+ require "open-uri"
3
+
1
4
  module Bookify::Node
2
5
  class Image < Base
3
6
  def render
@@ -6,8 +9,15 @@ module Bookify::Node
6
9
  fit: [bounds.width, -1]
7
10
  }
8
11
 
9
- image node.attr(:src), options
12
+ image image_from_node(node), options
10
13
  move_down 15
11
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
12
22
  end
13
23
  end
@@ -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, :column_spacer, :margin
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,7 +17,7 @@ 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, column_spacer: nil, margin: 50)
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
@@ -27,17 +25,21 @@ class Bookify::Renderer
27
25
  @input_text = input_text
28
26
  @column_spacer = column_spacer
29
27
  @margin = margin
28
+ @page_size = page_size
30
29
  end
31
30
 
32
31
  def render
33
- Prawn::Document.generate(output_file, margin: margin, 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|
34
36
  font_path = "#{File.dirname(__FILE__)}/../../fonts"
35
37
 
36
38
  pdf.font_families["Book Antiqua"] = {
37
39
  normal: {file: "#{font_path}/BookAntiqua.ttf"},
38
40
  bold: {file: "#{font_path}/BookAntiqua-Bold.ttf"},
39
41
  italic: {file: "#{font_path}/BookAntiqua-Italic.ttf"},
40
- bold_italic: {file: "#{font_path}/BookAntiqua-BoldItalic.ttf"},
42
+ bold_italic: {file: "#{font_path}/BookAntiqua-BoldItalic.ttf"}
41
43
  }
42
44
 
43
45
  pdf.fill_color "000000"
@@ -48,6 +50,14 @@ class Bookify::Renderer
48
50
  pdf.column_box [0, pdf.cursor], columns: columns, width: pdf.bounds.width, spacer: (column_spacer || pdf.font_size) do
49
51
  doc.children.each { |c| Bookify::Node.render(c, pdf) }
50
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
51
61
  end
52
62
  end
53
63
 
@@ -62,6 +72,10 @@ class Bookify::Renderer
62
72
  end
63
73
 
64
74
  def html
65
- @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)
66
80
  end
67
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.1.0
4
+ version: 2.6.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-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,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.