asciidoctor-fb2 0.2.1 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: {}
|