asciidoctor-fb2 0.2.0 → 0.3.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
2
  SHA256:
3
- metadata.gz: 5b60e7a379175a8473e96c61ed95598104689ac84def256f01ec626d850025af
4
- data.tar.gz: 96c60b98e0245a9aa4d61037d538f31b623dfd53e0c24407428c784a2753f9c9
3
+ metadata.gz: 2fe8aeff6fa259f44c96b2adcc9f2f2074e68b918f1dc4ec0d509691b34b67e4
4
+ data.tar.gz: 6ca94abe536faeeb639bea944ac21a90b6cabe6de42ad733fe7879148665441d
5
5
  SHA512:
6
- metadata.gz: 13bc939cf1450190c85b87e51333c6d58f3e2d3b2181be4c9a5af8705dd645900cd00a1290f74f68adfed42ad1570cfc4c6ed8974940b7317e5c524b96824b74
7
- data.tar.gz: 314760eafb08dfda7c44087dab1d7d6a5309ac45f134612a455b84e894d1b8b328beb06d65be37e7e7a7d20de4bc589841a461c3b50c2e666264c8b8ae505ee6
6
+ metadata.gz: b18f5a752a529d7a13e7beb1cc30c097914d2696a39f1bfdb736a748b16ee2fcf32544a6fa6b5166b8611a524411a812acc4530550e366a19210dab66ac3cdd2
7
+ data.tar.gz: 8d6eee70a2a3bbaa328f8f2d9056cf4a25150b0bb6d398323d6ab509cb8a43489171c564492720b21acfda4b52bb0060867d11ad608a76371ba8cbf3565ced2a
@@ -7,6 +7,34 @@
7
7
  This document provides a high-level view of the changes to the {project-name} by release.
8
8
  For a detailed view of what has changed, refer to the {uri-project}/commits/master[commit history] on GitHub.
9
9
 
10
+ == 0.3.0 (2020-11-25) - @slonopotamus
11
+
12
+ * output MIME type for FB2 embedded binary files. https://github.com/slonopotamus/asciidoctor-fb2/issues/19[#19]
13
+ * handle `+image:file[]+` syntax for `+:front-cover-image:+` document attribute. https://github.com/slonopotamus/asciidoctor-fb2/issues/19[#19]
14
+
15
+ == 0.2.4 (2020-11-24) - @slonopotamus
16
+
17
+ * add support for table captions
18
+ * fix images from subfolders not loaded in Calibre
19
+ * add initial CSS support
20
+
21
+ == 0.2.3 (2020-11-24) - @slonopotamus
22
+
23
+ * add support for literal blocks
24
+ * fix crash for `menu` inline macro without submenu. https://github.com/slonopotamus/asciidoctor-fb2/issues/15[#15]
25
+ * add initial support for sidebar
26
+
27
+ == 0.2.2 (2020-11-24) - @slonopotamus
28
+
29
+ * do not crash on inline line break macro. https://github.com/slonopotamus/asciidoctor-fb2/issues/14[#14]
30
+ * add support for verses
31
+ * add support for quotes
32
+
33
+ == 0.2.1 (2020-11-24) - @slonopotamus
34
+
35
+ * add support for `kbd` inline macro. https://github.com/slonopotamus/asciidoctor-fb2/issues/13[#13]
36
+ * add support for `btn` inline macro
37
+
10
38
  == 0.2.0 (2020-11-23) - @slonopotamus
11
39
 
12
40
  * add support for cover image via `+:front-cover-image:+` attribute. https://github.com/slonopotamus/asciidoctor-fb2/issues/3[#3]
@@ -19,11 +19,12 @@ Gem::Specification.new do |s|
19
19
  s.require_paths = ['lib']
20
20
 
21
21
  s.add_runtime_dependency 'asciidoctor', '~> 2.0'
22
- s.add_runtime_dependency 'fb2rb', '~> 0.3.0'
22
+ s.add_runtime_dependency 'fb2rb', '~> 0.4.0'
23
+ s.add_runtime_dependency 'mime-types', '~> 3.0'
23
24
 
24
25
  s.add_development_dependency 'asciidoctor-diagram', '~> 2.0'
25
26
  s.add_development_dependency 'rake', '~> 13.0'
26
27
  s.add_development_dependency 'rspec', '~> 3.10.0'
27
- s.add_development_dependency 'rubocop', '~> 0.93.0'
28
- s.add_development_dependency 'rubocop-rspec', '~> 1.44.0'
28
+ s.add_development_dependency 'rubocop', '~> 1.4.0'
29
+ s.add_development_dependency 'rubocop-rspec', '~> 2.0.0'
29
30
  end
@@ -0,0 +1,3 @@
1
+ body {
2
+ text-align: justify
3
+ }
@@ -3,14 +3,18 @@
3
3
  require 'asciidoctor'
4
4
  require 'asciidoctor/converter'
5
5
  require 'fb2rb'
6
+ require 'mime/types'
6
7
 
7
8
  module Asciidoctor
8
9
  module FB2
10
+ DATA_DIR = File.expand_path(File.join(__dir__, '..', 'data'))
11
+
9
12
  # Converts AsciiDoc documents to FB2 e-book formats
10
13
  class Converter < Asciidoctor::Converter::Base # rubocop:disable Metrics/ClassLength
11
14
  include ::Asciidoctor::Writer
12
15
 
13
16
  CSV_DELIMITER_REGEX = /\s*,\s*/.freeze
17
+ IMAGE_ATTRIBUTE_VALUE_RX = /^image:{1,2}(.*?)\[(.*?)\]$/.freeze
14
18
 
15
19
  register_for 'fb2'
16
20
 
@@ -25,6 +29,8 @@ module Asciidoctor
25
29
  # @param node [Asciidoctor::Document]
26
30
  def convert_document(node) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
27
31
  @book = FB2rb::Book.new
32
+ @book.add_stylesheet('text/css', File.join(DATA_DIR, 'fb2.css'))
33
+
28
34
  document_info = @book.description.document_info
29
35
  title_info = @book.description.title_info
30
36
 
@@ -58,8 +64,9 @@ module Asciidoctor
58
64
  title_info.date = document_info.date = fb2date
59
65
 
60
66
  unless (cover_image = node.attr('front-cover-image')).nil?
67
+ cover_image = Regexp.last_match(1) if cover_image =~ IMAGE_ATTRIBUTE_VALUE_RX
61
68
  cover_image_path = node.image_uri(cover_image)
62
- register_binary(node, cover_image_path)
69
+ register_binary(node, cover_image_path, 'image')
63
70
  title_info.coverpage = FB2rb::Coverpage.new([%(##{cover_image_path})])
64
71
  end
65
72
 
@@ -119,8 +126,47 @@ module Asciidoctor
119
126
  lines * "\n"
120
127
  end
121
128
 
129
+ # @param node [Asciidoctor::Block]
130
+ def convert_quote(node)
131
+ citetitle = node.attr('citetitle')
132
+ citetitle_tag = citetitle.nil_or_empty? ? '' : %(<subtitle>#{citetitle}</subtitle>)
133
+
134
+ author = node.attr('attribution')
135
+ author_tag = author.nil_or_empty? ? '' : %(<text-author>#{node.attr('attribution')}</text-author>)
136
+
137
+ %(<cite>
138
+ #{citetitle_tag}
139
+ <p>#{node.content}</p>
140
+ #{author_tag}
141
+ </cite>)
142
+ end
143
+
144
+ # @param node [Asciidoctor::Block]
145
+ def convert_verse(node)
146
+ body = node.content&.split("\n\n")&.map do |stanza|
147
+ %(<stanza>\n<v>#{stanza.split("\n") * "</v>\n<v>"}</v>\n</stanza>)
148
+ end&.join("\n")
149
+
150
+ citetitle = node.attr('citetitle')
151
+ citetitle_tag = citetitle.nil_or_empty? ? '' : %(<title>#{citetitle}</title>)
152
+
153
+ author = node.attr('attribution')
154
+ author_tag = author.nil_or_empty? ? '' : %(<text-author>#{node.attr('attribution')}</text-author>)
155
+
156
+ %(<poem>
157
+ #{citetitle_tag}
158
+ #{body}
159
+ #{author_tag}
160
+ </poem>)
161
+ end
162
+
122
163
  # @param node [Asciidoctor::Block]
123
164
  def convert_listing(node)
165
+ convert_literal(node)
166
+ end
167
+
168
+ # @param node [Asciidoctor::Block]
169
+ def convert_literal(node)
124
170
  lines = []
125
171
  node.content.split("\n").each do |line|
126
172
  lines << %(<p><code>#{line}</code></p>)
@@ -152,15 +198,30 @@ module Asciidoctor
152
198
  caret = '&#160;<strong>&#8250;</strong> '
153
199
  menu = node.attr('menu')
154
200
  menuitem = node.attr('menuitem')
155
- submenus = node.attr('submenus').join(%(</b>#{caret}<b>))
201
+ submenus = node.attr('submenus') * %(</b>#{caret}<b>)
156
202
 
157
203
  result = %(<strong>#{menu}</strong>)
158
- result += %(#{caret}<strong>#{submenus}</strong>) unless submenus.empty?
159
- result += %(#{caret}<strong>#{menuitem}</strong>) unless menuitem.empty?
204
+ result += %(#{caret}<strong>#{submenus}</strong>) unless submenus.nil_or_empty?
205
+ result += %(#{caret}<strong>#{menuitem}</strong>) unless menuitem.nil_or_empty?
160
206
 
161
207
  result
162
208
  end
163
209
 
210
+ # @param node [Asciidoctor::Inline]
211
+ def convert_inline_break(node)
212
+ node.text
213
+ end
214
+
215
+ # @param node [Asciidoctor::Inline]
216
+ def convert_inline_button(node)
217
+ %([<strong>#{node.text}</strong>])
218
+ end
219
+
220
+ # @param node [Asciidoctor::Inline]
221
+ def convert_inline_kbd(node)
222
+ %(<strong>#{node.attr('keys') * '</strong>+<strong>'}</strong>)
223
+ end
224
+
164
225
  # @param node [Asciidoctor::Inline]
165
226
  def convert_inline_anchor(node) # rubocop:disable Metrics/MethodLength
166
227
  case node.type
@@ -189,13 +250,13 @@ module Asciidoctor
189
250
 
190
251
  # @param node [Asciidoctor::Inline]
191
252
  def convert_inline_image(node)
192
- image_attrs = register_binary(node, node.image_uri(node.target))
253
+ image_attrs = register_binary(node, node.image_uri(node.target), 'image')
193
254
  %(<image #{image_attrs * ' '}/>)
194
255
  end
195
256
 
196
257
  # @param node [Asciidoctor::Block]
197
258
  def convert_image(node)
198
- image_attrs = register_binary(node, node.image_uri(node.attr('target')))
259
+ image_attrs = register_binary(node, node.image_uri(node.attr('target')), 'image')
199
260
  image_attrs << %(title="#{node.captioned_title}") if node.title?
200
261
  image_attrs << %(id="#{node.id}") if node.id
201
262
  %(<p><image #{image_attrs * ' '}/></p>)
@@ -208,9 +269,15 @@ module Asciidoctor
208
269
  doc
209
270
  end
210
271
 
272
+ def determine_mime_type(filename, media_type)
273
+ mime_types = MIME::Types.type_for(filename)
274
+ mime_types.delete_if { |x| x.media_type != media_type }
275
+ mime_types.empty? ? nil : mime_types[0].content_type
276
+ end
277
+
211
278
  # @param node [Asciidoctor::AbstractNode]
212
279
  # @param target [String]
213
- def register_binary(node, target) # rubocop:disable Metrics/MethodLength
280
+ def register_binary(node, target, media_type) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
214
281
  unless Asciidoctor::Helpers.uriish?(target)
215
282
  out_dir = node.attr('outdir', nil, true) || doc_option(node.document, :to_dir)
216
283
  fs_path = File.join(out_dir, target)
@@ -220,7 +287,12 @@ module Asciidoctor
220
287
  end
221
288
 
222
289
  if File.readable?(fs_path)
223
- @book.add_binary(target, fs_path)
290
+ # Calibre fails to load images if they contain path separators
291
+ target.sub!('/', '_')
292
+ target.sub!('\\', '_')
293
+
294
+ mime_type = determine_mime_type(target, media_type)
295
+ @book.add_binary(target, fs_path, mime_type)
224
296
  target = %(##{target})
225
297
  end
226
298
  end
@@ -238,6 +310,13 @@ module Asciidoctor
238
310
  lines * "\n"
239
311
  end
240
312
 
313
+ # @param node [Asciidoctor::Block]
314
+ def convert_sidebar(node)
315
+ title_tag = node.title.nil_or_empty? ? '' : %(<p><strong>#{node.title}</strong></p>)
316
+ %(#{title_tag}
317
+ #{node.content})
318
+ end
319
+
241
320
  # @param node [Asciidoctor::List]
242
321
  def convert_ulist(node)
243
322
  lines = []
@@ -300,7 +379,9 @@ module Asciidoctor
300
379
 
301
380
  # @param node [Asciidoctor::Table]
302
381
  def convert_table(node) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
303
- lines = ['<table>']
382
+ lines = []
383
+ lines << %(<subtitle>#{node.captioned_title}</subtitle>) if node.title?
384
+ lines << '<table>'
304
385
  node.rows.to_h.each do |tsec, rows| # rubocop:disable Metrics/BlockLength
305
386
  next if rows.empty?
306
387
 
@@ -316,7 +397,7 @@ module Asciidoctor
316
397
  when :literal
317
398
  %(<p><pre>#{cell.text}</pre></p>)
318
399
  else
319
- (cell_content = cell.content).empty? ? '' : %(<p>#{cell_content.join "</p>\n<p>"}</p>)
400
+ (cell_content = cell.content).empty? ? '' : %(<p>#{cell_content * "</p>\n<p>"}</p>)
320
401
  end
321
402
  end
322
403
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Asciidoctor
4
4
  module FB2
5
- VERSION = '0.2.0'
5
+ VERSION = '0.3.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-fb2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marat Radchenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-23 00:00:00.000000000 Z
11
+ date: 2020-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -30,14 +30,28 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.3.0
33
+ version: 0.4.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.3.0
40
+ version: 0.4.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: mime-types
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: asciidoctor-diagram
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -86,28 +100,28 @@ dependencies:
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: 0.93.0
103
+ version: 1.4.0
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: 0.93.0
110
+ version: 1.4.0
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: rubocop-rspec
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
115
  - - "~>"
102
116
  - !ruby/object:Gem::Version
103
- version: 1.44.0
117
+ version: 2.0.0
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
- version: 1.44.0
124
+ version: 2.0.0
111
125
  description:
112
126
  email:
113
127
  - marat@slonopotamus.org
@@ -129,6 +143,7 @@ files:
129
143
  - Rakefile
130
144
  - asciidoctor-fb2.gemspec
131
145
  - bin/asciidoctor-fb2
146
+ - data/fb2.css
132
147
  - lib/asciidoctor_fb2.rb
133
148
  - lib/asciidoctor_fb2/version.rb
134
149
  - tasks/bundler.rake