asciidoctor-fb2 0.2.1 → 0.3.1
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 +4 -4
- data/.github/workflows/ci.yml +1 -2
- data/CHANGELOG.adoc +30 -1
- data/README.adoc +1 -1
- data/asciidoctor-fb2.gemspec +5 -4
- data/data/fb2.css +3 -0
- data/lib/asciidoctor_fb2.rb +89 -13
- data/lib/asciidoctor_fb2/version.rb +1 -1
- metadata +24 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fefb6e896cf8679642198ac1ffe5222916781f71cbb775130bf32eeb00b375b4
|
4
|
+
data.tar.gz: 5100ec044994316213786b065115f6214ca4dd29c4f8655fc3a9ffc42726d258
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '099b2149b1dacc1a1239725ce386afdc48ff7429a6aa7e0108af80db0c84630c176ec6adf96090f671c7a51bd1140590d920133ba4de76788e239fe490951317'
|
7
|
+
data.tar.gz: 7418059f5dd43b7f77087acac3af70764e80af4dc676be995c9d421edd01dd89008b11926c36151b6832b1c137684236cad3b00a12b6798a5747d23690089c7c
|
data/.github/workflows/ci.yml
CHANGED
data/CHANGELOG.adoc
CHANGED
@@ -1,12 +1,41 @@
|
|
1
1
|
= {project-name} Changelog
|
2
2
|
:project-name: Asciidoctor FB2
|
3
3
|
:project-handle: asciidoctor-fb2
|
4
|
-
:slug:
|
4
|
+
:slug: asciidoctor/{project-handle}
|
5
5
|
:uri-project: https://github.com/{slug}
|
6
6
|
|
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.1 (2020-11-29) - @slonopotamus
|
11
|
+
|
12
|
+
* fix crash on `+toc::[]+` macro
|
13
|
+
* avoid adding `notes` body to FB2 if document doesn't have any footnotes
|
14
|
+
* fix invalid XML syntax for table cells
|
15
|
+
|
16
|
+
== 0.3.0 (2020-11-25) - @slonopotamus
|
17
|
+
|
18
|
+
* output MIME type for FB2 embedded binary files. https://github.com/slonopotamus/asciidoctor-fb2/issues/19[#19]
|
19
|
+
* handle `+image:file[]+` syntax for `+:front-cover-image:+` document attribute. https://github.com/slonopotamus/asciidoctor-fb2/issues/19[#19]
|
20
|
+
|
21
|
+
== 0.2.4 (2020-11-24) - @slonopotamus
|
22
|
+
|
23
|
+
* add support for table captions
|
24
|
+
* fix images from subfolders not loaded in Calibre
|
25
|
+
* add initial CSS support
|
26
|
+
|
27
|
+
== 0.2.3 (2020-11-24) - @slonopotamus
|
28
|
+
|
29
|
+
* add support for literal blocks
|
30
|
+
* fix crash for `menu` inline macro without submenu. https://github.com/slonopotamus/asciidoctor-fb2/issues/15[#15]
|
31
|
+
* add initial support for sidebar
|
32
|
+
|
33
|
+
== 0.2.2 (2020-11-24) - @slonopotamus
|
34
|
+
|
35
|
+
* do not crash on inline line break macro. https://github.com/slonopotamus/asciidoctor-fb2/issues/14[#14]
|
36
|
+
* add support for verses
|
37
|
+
* add support for quotes
|
38
|
+
|
10
39
|
== 0.2.1 (2020-11-24) - @slonopotamus
|
11
40
|
|
12
41
|
* add support for `kbd` inline macro. https://github.com/slonopotamus/asciidoctor-fb2/issues/13[#13]
|
data/README.adoc
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
Marat Radchenko <marat@slonopotamus.org>
|
3
3
|
:project-name: Asciidoctor FB2
|
4
4
|
:project-handle: asciidoctor-fb2
|
5
|
-
:slug:
|
5
|
+
:slug: asciidoctor/{project-handle}
|
6
6
|
:uri-project: https://github.com/{slug}
|
7
7
|
:uri-ci: {uri-project}/actions?query=branch%3Amaster
|
8
8
|
:uri-gem: https://rubygems.org/gems/{project-handle}
|
data/asciidoctor-fb2.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.authors = ['Marat Radchenko']
|
9
9
|
s.email = ['marat@slonopotamus.org']
|
10
10
|
s.summary = 'Converts AsciiDoc documents to FB2 e-book formats'
|
11
|
-
s.homepage = 'https://github.com/
|
11
|
+
s.homepage = 'https://github.com/asciidoctor/asciidoctor-fb2'
|
12
12
|
s.license = 'MIT'
|
13
13
|
s.required_ruby_version = '>= 2.4.0'
|
14
14
|
|
@@ -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.
|
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', '~>
|
28
|
-
s.add_development_dependency 'rubocop-rspec', '~>
|
28
|
+
s.add_development_dependency 'rubocop', '~> 1.4.0'
|
29
|
+
s.add_development_dependency 'rubocop-rspec', '~> 2.0.0'
|
29
30
|
end
|
data/data/fb2.css
ADDED
data/lib/asciidoctor_fb2.rb
CHANGED
@@ -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
|
|
@@ -75,7 +82,7 @@ module Asciidoctor
|
|
75
82
|
#{node.content}
|
76
83
|
</section>)
|
77
84
|
@book.bodies << FB2rb::Body.new(nil, body)
|
78
|
-
|
85
|
+
unless node.document.footnotes.empty?
|
79
86
|
notes = []
|
80
87
|
node.document.footnotes.each do |footnote|
|
81
88
|
notes << %(<section id="note-#{footnote.index}">
|
@@ -108,6 +115,11 @@ module Asciidoctor
|
|
108
115
|
end
|
109
116
|
end
|
110
117
|
|
118
|
+
# @param _node [Asciidoctor::Block]
|
119
|
+
def convert_toc(_node)
|
120
|
+
''
|
121
|
+
end
|
122
|
+
|
111
123
|
# @param node [Asciidoctor::Block]
|
112
124
|
def convert_paragraph(node)
|
113
125
|
lines = [
|
@@ -119,8 +131,47 @@ module Asciidoctor
|
|
119
131
|
lines * "\n"
|
120
132
|
end
|
121
133
|
|
134
|
+
# @param node [Asciidoctor::Block]
|
135
|
+
def convert_quote(node)
|
136
|
+
citetitle = node.attr('citetitle')
|
137
|
+
citetitle_tag = citetitle.nil_or_empty? ? '' : %(<subtitle>#{citetitle}</subtitle>)
|
138
|
+
|
139
|
+
author = node.attr('attribution')
|
140
|
+
author_tag = author.nil_or_empty? ? '' : %(<text-author>#{node.attr('attribution')}</text-author>)
|
141
|
+
|
142
|
+
%(<cite>
|
143
|
+
#{citetitle_tag}
|
144
|
+
<p>#{node.content}</p>
|
145
|
+
#{author_tag}
|
146
|
+
</cite>)
|
147
|
+
end
|
148
|
+
|
149
|
+
# @param node [Asciidoctor::Block]
|
150
|
+
def convert_verse(node)
|
151
|
+
body = node.content&.split("\n\n")&.map do |stanza|
|
152
|
+
%(<stanza>\n<v>#{stanza.split("\n") * "</v>\n<v>"}</v>\n</stanza>)
|
153
|
+
end&.join("\n")
|
154
|
+
|
155
|
+
citetitle = node.attr('citetitle')
|
156
|
+
citetitle_tag = citetitle.nil_or_empty? ? '' : %(<title>#{citetitle}</title>)
|
157
|
+
|
158
|
+
author = node.attr('attribution')
|
159
|
+
author_tag = author.nil_or_empty? ? '' : %(<text-author>#{node.attr('attribution')}</text-author>)
|
160
|
+
|
161
|
+
%(<poem>
|
162
|
+
#{citetitle_tag}
|
163
|
+
#{body}
|
164
|
+
#{author_tag}
|
165
|
+
</poem>)
|
166
|
+
end
|
167
|
+
|
122
168
|
# @param node [Asciidoctor::Block]
|
123
169
|
def convert_listing(node)
|
170
|
+
convert_literal(node)
|
171
|
+
end
|
172
|
+
|
173
|
+
# @param node [Asciidoctor::Block]
|
174
|
+
def convert_literal(node)
|
124
175
|
lines = []
|
125
176
|
node.content.split("\n").each do |line|
|
126
177
|
lines << %(<p><code>#{line}</code></p>)
|
@@ -152,15 +203,20 @@ module Asciidoctor
|
|
152
203
|
caret = ' <strong>›</strong> '
|
153
204
|
menu = node.attr('menu')
|
154
205
|
menuitem = node.attr('menuitem')
|
155
|
-
submenus = node.attr('submenus')
|
206
|
+
submenus = node.attr('submenus') * %(</b>#{caret}<b>)
|
156
207
|
|
157
208
|
result = %(<strong>#{menu}</strong>)
|
158
|
-
result += %(#{caret}<strong>#{submenus}</strong>) unless submenus.
|
159
|
-
result += %(#{caret}<strong>#{menuitem}</strong>) unless menuitem.
|
209
|
+
result += %(#{caret}<strong>#{submenus}</strong>) unless submenus.nil_or_empty?
|
210
|
+
result += %(#{caret}<strong>#{menuitem}</strong>) unless menuitem.nil_or_empty?
|
160
211
|
|
161
212
|
result
|
162
213
|
end
|
163
214
|
|
215
|
+
# @param node [Asciidoctor::Inline]
|
216
|
+
def convert_inline_break(node)
|
217
|
+
node.text
|
218
|
+
end
|
219
|
+
|
164
220
|
# @param node [Asciidoctor::Inline]
|
165
221
|
def convert_inline_button(node)
|
166
222
|
%([<strong>#{node.text}</strong>])
|
@@ -168,7 +224,7 @@ module Asciidoctor
|
|
168
224
|
|
169
225
|
# @param node [Asciidoctor::Inline]
|
170
226
|
def convert_inline_kbd(node)
|
171
|
-
%(<strong>#{node.attr('keys')
|
227
|
+
%(<strong>#{node.attr('keys') * '</strong>+<strong>'}</strong>)
|
172
228
|
end
|
173
229
|
|
174
230
|
# @param node [Asciidoctor::Inline]
|
@@ -199,13 +255,13 @@ module Asciidoctor
|
|
199
255
|
|
200
256
|
# @param node [Asciidoctor::Inline]
|
201
257
|
def convert_inline_image(node)
|
202
|
-
image_attrs = register_binary(node, node.image_uri(node.target))
|
258
|
+
image_attrs = register_binary(node, node.image_uri(node.target), 'image')
|
203
259
|
%(<image #{image_attrs * ' '}/>)
|
204
260
|
end
|
205
261
|
|
206
262
|
# @param node [Asciidoctor::Block]
|
207
263
|
def convert_image(node)
|
208
|
-
image_attrs = register_binary(node, node.image_uri(node.attr('target')))
|
264
|
+
image_attrs = register_binary(node, node.image_uri(node.attr('target')), 'image')
|
209
265
|
image_attrs << %(title="#{node.captioned_title}") if node.title?
|
210
266
|
image_attrs << %(id="#{node.id}") if node.id
|
211
267
|
%(<p><image #{image_attrs * ' '}/></p>)
|
@@ -218,9 +274,15 @@ module Asciidoctor
|
|
218
274
|
doc
|
219
275
|
end
|
220
276
|
|
277
|
+
def determine_mime_type(filename, media_type)
|
278
|
+
mime_types = MIME::Types.type_for(filename)
|
279
|
+
mime_types.delete_if { |x| x.media_type != media_type }
|
280
|
+
mime_types.empty? ? nil : mime_types[0].content_type
|
281
|
+
end
|
282
|
+
|
221
283
|
# @param node [Asciidoctor::AbstractNode]
|
222
284
|
# @param target [String]
|
223
|
-
def register_binary(node, target) # rubocop:disable Metrics/MethodLength
|
285
|
+
def register_binary(node, target, media_type) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
224
286
|
unless Asciidoctor::Helpers.uriish?(target)
|
225
287
|
out_dir = node.attr('outdir', nil, true) || doc_option(node.document, :to_dir)
|
226
288
|
fs_path = File.join(out_dir, target)
|
@@ -230,7 +292,12 @@ module Asciidoctor
|
|
230
292
|
end
|
231
293
|
|
232
294
|
if File.readable?(fs_path)
|
233
|
-
|
295
|
+
# Calibre fails to load images if they contain path separators
|
296
|
+
target.sub!('/', '_')
|
297
|
+
target.sub!('\\', '_')
|
298
|
+
|
299
|
+
mime_type = determine_mime_type(target, media_type)
|
300
|
+
@book.add_binary(target, fs_path, mime_type)
|
234
301
|
target = %(##{target})
|
235
302
|
end
|
236
303
|
end
|
@@ -248,6 +315,13 @@ module Asciidoctor
|
|
248
315
|
lines * "\n"
|
249
316
|
end
|
250
317
|
|
318
|
+
# @param node [Asciidoctor::Block]
|
319
|
+
def convert_sidebar(node)
|
320
|
+
title_tag = node.title.nil_or_empty? ? '' : %(<p><strong>#{node.title}</strong></p>)
|
321
|
+
%(#{title_tag}
|
322
|
+
#{node.content})
|
323
|
+
end
|
324
|
+
|
251
325
|
# @param node [Asciidoctor::List]
|
252
326
|
def convert_ulist(node)
|
253
327
|
lines = []
|
@@ -310,7 +384,9 @@ module Asciidoctor
|
|
310
384
|
|
311
385
|
# @param node [Asciidoctor::Table]
|
312
386
|
def convert_table(node) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
313
|
-
lines = [
|
387
|
+
lines = []
|
388
|
+
lines << %(<subtitle>#{node.captioned_title}</subtitle>) if node.title?
|
389
|
+
lines << '<table>'
|
314
390
|
node.rows.to_h.each do |tsec, rows| # rubocop:disable Metrics/BlockLength
|
315
391
|
next if rows.empty?
|
316
392
|
|
@@ -326,7 +402,7 @@ module Asciidoctor
|
|
326
402
|
when :literal
|
327
403
|
%(<p><pre>#{cell.text}</pre></p>)
|
328
404
|
else
|
329
|
-
(cell_content = cell.content).empty? ? '' : %(<p>#{cell_content
|
405
|
+
(cell_content = cell.content).empty? ? '' : %(<p>#{cell_content * "</p>\n<p>"}</p>)
|
330
406
|
end
|
331
407
|
end
|
332
408
|
|
@@ -337,7 +413,7 @@ module Asciidoctor
|
|
337
413
|
]
|
338
414
|
cell_attrs << %(colspan="#{cell.colspan}") if cell.colspan
|
339
415
|
cell_attrs << %(rowspan="#{cell.rowspan}") if cell.rowspan
|
340
|
-
lines << %(<#{cell_tag_name} #{cell_attrs * ' '}
|
416
|
+
lines << %(<#{cell_tag_name} #{cell_attrs * ' '}>#{cell_content}</#{cell_tag_name}>)
|
341
417
|
end
|
342
418
|
lines << '</tr>'
|
343
419
|
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.
|
4
|
+
version: 0.3.1
|
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-
|
11
|
+
date: 2020-11-29 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.
|
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.
|
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:
|
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:
|
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:
|
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:
|
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
|
@@ -136,7 +151,7 @@ files:
|
|
136
151
|
- tasks/console.rake
|
137
152
|
- tasks/rspec.rake
|
138
153
|
- tasks/rubocop.rake
|
139
|
-
homepage: https://github.com/
|
154
|
+
homepage: https://github.com/asciidoctor/asciidoctor-fb2
|
140
155
|
licenses:
|
141
156
|
- MIT
|
142
157
|
metadata: {}
|