bookify 2.1.1 → 2.7.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: a42bf3c7616f841c546fc492437d850fdf78a3f1814fb326d9daaef407f7e802
4
- data.tar.gz: 404e2b27ad30b93b70517d748d5b3e1d0a01e0a07fb559f0033f8a8c39459e8e
3
+ metadata.gz: d51ebed7b740e8227ef917d1cb77b8b69697a3897679be78fc7e0d75224eab1a
4
+ data.tar.gz: 0e39ed24007b1ed3385ee72505d6060c3fa484b8b6cc54af9629355e935d122a
5
5
  SHA512:
6
- metadata.gz: 9277e6cf6924393c9d7bd411ce863b84a443ae96ac45c4b7d96e6a579b9b937a3e0fb4872a1b51c199bbd2dee71bea0356af4c895ae09a0e32c9f654834cdd7a
7
- data.tar.gz: 9692038f1a3d8f81a6e22389837d445918036df6c60e20d732943f7b3bd81865b07376cd7e1f193890e91a8eaab91894e3e5785f8834f501d8abd7a16a7fc4e0
6
+ metadata.gz: 9db685fcb9815e6888ed42b92c5c4c3d3b36536d689c31d7fbe0cd2b54657f46ffbad78189943e1ac31655c4a793ec2320c674eb89951b07e4cb0523df19a433
7
+ data.tar.gz: c69cc884d4af8bb320208932ddb6e68bdc848143cbcdfd19143a9e8dace6db447771734d2ceb715d3926ee52c91fdef0a83b57c48e5d243f3d0d62240922f00c
@@ -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: 12, 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
6
  move_down 5
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
6
  move_down 5
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
@@ -5,9 +5,12 @@ module Bookify::Node
5
5
  def render
6
6
  move_down 5
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,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.1
4
+ version: 2.7.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-08 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.