review 5.3.0 → 5.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby-tex.yml +1 -1
- data/.github/workflows/ruby.yml +1 -1
- data/.rubocop.yml +1 -322
- data/NEWS.ja.md +48 -0
- data/NEWS.md +48 -0
- data/README.md +9 -8
- data/bin/review +1 -1
- data/bin/review-catalog-converter +15 -15
- data/bin/review-check +7 -7
- data/bin/review-compile +6 -8
- data/bin/review-index +1 -1
- data/bin/review-preproc +1 -1
- data/bin/review-validate +2 -2
- data/doc/config.yml.sample +7 -1
- data/doc/config.yml.sample-simple +1 -1
- data/lib/review/book/base.rb +3 -3
- data/lib/review/book/book_unit.rb +1 -1
- data/lib/review/book/chapter.rb +1 -1
- data/lib/review/book/index.rb +3 -3
- data/lib/review/book/part.rb +12 -13
- data/lib/review/book/volume.rb +1 -1
- data/lib/review/builder.rb +10 -12
- data/lib/review/catalog.rb +5 -5
- data/lib/review/compiler.rb +13 -13
- data/lib/review/configure.rb +5 -2
- data/lib/review/epub2html.rb +12 -12
- data/lib/review/epubmaker/content.rb +1 -1
- data/lib/review/epubmaker/epubcommon.rb +44 -42
- data/lib/review/epubmaker/epubv2.rb +2 -1
- data/lib/review/epubmaker/epubv3.rb +5 -4
- data/lib/review/epubmaker/producer.rb +3 -3
- data/lib/review/epubmaker/reviewheaderlistener.rb +1 -1
- data/lib/review/epubmaker.rb +32 -31
- data/lib/review/extentions/string.rb +1 -1
- data/lib/review/htmlbuilder.rb +16 -15
- data/lib/review/htmlutils.rb +17 -17
- data/lib/review/i18n.rb +3 -3
- data/lib/review/idgxmlbuilder.rb +22 -21
- data/lib/review/idgxmlmaker.rb +15 -13
- data/lib/review/index_builder.rb +4 -20
- data/lib/review/init.rb +4 -4
- data/lib/review/latexbuilder.rb +30 -32
- data/lib/review/lineinput.rb +3 -3
- data/lib/review/location.rb +1 -1
- data/lib/review/logger.rb +21 -21
- data/lib/review/makerhelper.rb +3 -3
- data/lib/review/markdownbuilder.rb +6 -6
- data/lib/review/pdfmaker.rb +23 -19
- data/lib/review/plaintextbuilder.rb +5 -5
- data/lib/review/preprocessor/repository.rb +1 -1
- data/lib/review/preprocessor.rb +5 -5
- data/lib/review/textmaker.rb +20 -18
- data/lib/review/textutils.rb +3 -5
- data/lib/review/topbuilder.rb +71 -12
- data/lib/review/update.rb +16 -8
- data/lib/review/version.rb +1 -1
- data/lib/review/webmaker.rb +32 -32
- data/lib/review/webtocprinter.rb +10 -10
- data/lib/review/yamlloader.rb +35 -2
- data/review.gemspec +1 -0
- data/samples/sample-book/src/config.yml +0 -1
- data/templates/html/_titlepage.html.erb +9 -17
- data/templates/opf/opf_manifest_epubv2.opf.erb +1 -1
- data/templates/opf/opf_manifest_epubv3.opf.erb +1 -1
- data/test/book_test_helper.rb +10 -10
- data/test/test_epub3maker.rb +3 -3
- data/test/test_epubmaker.rb +14 -29
- data/test/test_epubmaker_cmd.rb +2 -2
- data/test/test_htmlbuilder.rb +4 -5
- data/test/test_idgxmlbuilder.rb +10 -10
- data/test/test_idgxmlmaker_cmd.rb +1 -1
- data/test/test_img_math.rb +11 -2
- data/test/test_latexbuilder.rb +2 -3
- data/test/test_pdfmaker_cmd.rb +10 -10
- data/test/test_textmaker_cmd.rb +1 -1
- data/test/test_topbuilder.rb +151 -11
- data/test/test_yamlloader.rb +28 -42
- metadata +8 -7
data/lib/review/preprocessor.rb
CHANGED
@@ -70,11 +70,11 @@ module ReVIEW
|
|
70
70
|
direc = parse_directive(line, 1, 'eval')
|
71
71
|
path = expand(direc.arg)
|
72
72
|
@leave_content = File.extname(path) == '.re'
|
73
|
-
if direc['eval']
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
73
|
+
ent = if direc['eval']
|
74
|
+
evaluate(path, ent)
|
75
|
+
else
|
76
|
+
@repository.fetch_file(path)
|
77
|
+
end
|
78
78
|
replace_block(f, line, ent, false) # FIXME: turn off lineno: tmp
|
79
79
|
|
80
80
|
when /\A\#@map(?:range)?/
|
data/lib/review/textmaker.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2018-
|
1
|
+
# Copyright (c) 2018-2022 Kenshi Muto
|
2
2
|
#
|
3
3
|
# This program is free software.
|
4
4
|
# You can distribute or modify this program under the terms of
|
@@ -74,9 +74,14 @@ module ReVIEW
|
|
74
74
|
cmd_config, yamlfile = parse_opts(args)
|
75
75
|
error! "#{yamlfile} not found." unless File.exist?(yamlfile)
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
begin
|
78
|
+
@config = ReVIEW::Configure.create(maker: 'textmaker',
|
79
|
+
yamlfile: yamlfile,
|
80
|
+
config: cmd_config)
|
81
|
+
rescue ReVIEW::ConfigError => e
|
82
|
+
error! e.message
|
83
|
+
end
|
84
|
+
|
80
85
|
@img_math = ReVIEW::ImgMath.new(@config, path_name: '_review_math_text')
|
81
86
|
|
82
87
|
I18n.setup(@config['language'])
|
@@ -111,12 +116,11 @@ module ReVIEW
|
|
111
116
|
|
112
117
|
def build_body(basetmpdir, _yamlfile)
|
113
118
|
base_path = Pathname.new(@basedir)
|
114
|
-
builder =
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
end
|
119
|
+
builder = if @plaintext
|
120
|
+
ReVIEW::PLAINTEXTBuilder.new(img_math: @img_math)
|
121
|
+
else
|
122
|
+
ReVIEW::TOPBuilder.new(img_math: @img_math)
|
123
|
+
end
|
120
124
|
@converter = ReVIEW::Converter.new(@book, builder)
|
121
125
|
@book.parts.each do |part|
|
122
126
|
if part.name.present?
|
@@ -142,13 +146,11 @@ module ReVIEW
|
|
142
146
|
end
|
143
147
|
|
144
148
|
def build_chap(chap, base_path, basetmpdir, ispart)
|
145
|
-
filename =
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
filename = Pathname.new(chap.path).relative_path_from(base_path).to_s
|
151
|
-
end
|
149
|
+
filename = if ispart.present?
|
150
|
+
chap.path
|
151
|
+
else
|
152
|
+
Pathname.new(chap.path).relative_path_from(base_path).to_s
|
153
|
+
end
|
152
154
|
id = File.basename(filename).sub(/\.re\Z/, '')
|
153
155
|
if @buildonly && !@buildonly.include?(id)
|
154
156
|
warn "skip #{id}.re"
|
@@ -159,7 +161,7 @@ module ReVIEW
|
|
159
161
|
|
160
162
|
begin
|
161
163
|
@converter.convert(filename, File.join(basetmpdir, textfile))
|
162
|
-
rescue => e
|
164
|
+
rescue StandardError => e
|
163
165
|
@compile_errors = true
|
164
166
|
error "compile error in #{filename} (#{e.class})"
|
165
167
|
error e.message
|
data/lib/review/textutils.rb
CHANGED
@@ -72,13 +72,11 @@ module ReVIEW
|
|
72
72
|
end
|
73
73
|
|
74
74
|
# lazy than rule 3, but it looks better
|
75
|
-
if lazy
|
76
|
-
if (%i[F W H].include?(Unicode::Eaw.property(tail)) &&
|
75
|
+
if lazy && ((%i[F W H].include?(Unicode::Eaw.property(tail)) &&
|
77
76
|
tail !~ /\p{Hangul}/) ||
|
78
77
|
(%i[F W H].include?(Unicode::Eaw.property(head)) &&
|
79
|
-
head !~ /\p{Hangul}/)
|
80
|
-
|
81
|
-
end
|
78
|
+
head !~ /\p{Hangul}/))
|
79
|
+
space = nil
|
82
80
|
end
|
83
81
|
end
|
84
82
|
space
|
data/lib/review/topbuilder.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2008-
|
1
|
+
# Copyright (c) 2008-2022 Minero Aoki, Kenshi Muto
|
2
2
|
# 2002-2006 Minero Aoki
|
3
3
|
#
|
4
4
|
# This program is free software.
|
@@ -262,13 +262,61 @@ module ReVIEW
|
|
262
262
|
blank
|
263
263
|
end
|
264
264
|
|
265
|
+
def table_rows(sepidx, rows)
|
266
|
+
if sepidx
|
267
|
+
sepidx.times do
|
268
|
+
tr(rows.shift.map { |s| th(s) })
|
269
|
+
end
|
270
|
+
if !@book.config['textmaker'] || !@book.config['textmaker']['th_bold']
|
271
|
+
puts '-' * 12
|
272
|
+
end
|
273
|
+
rows.each do |cols|
|
274
|
+
tr(cols.map { |s| td(s) })
|
275
|
+
end
|
276
|
+
else
|
277
|
+
rows.each do |cols|
|
278
|
+
h, *cs = *cols
|
279
|
+
tr([th(h)] + cs.map { |s| td(s) })
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
265
284
|
def th(str)
|
266
|
-
|
285
|
+
if @book.config['textmaker'] && @book.config['textmaker']['th_bold']
|
286
|
+
"★#{str}☆"
|
287
|
+
else
|
288
|
+
str
|
289
|
+
end
|
267
290
|
end
|
268
291
|
|
269
292
|
def table_end
|
270
293
|
end
|
271
294
|
|
295
|
+
def imgtable(lines, id, caption = nil, metric = nil)
|
296
|
+
metrics = parse_metric('top', metric)
|
297
|
+
metrics = " #{metrics}" if metrics.present?
|
298
|
+
blank
|
299
|
+
puts "◆→開始:#{@titles['table']}←◆"
|
300
|
+
if caption_top?('table') && caption.present?
|
301
|
+
table_header(id, caption)
|
302
|
+
end
|
303
|
+
|
304
|
+
if @chapter.image_bound?(id)
|
305
|
+
puts "◆→#{@chapter.image(id).path}#{metrics}←◆"
|
306
|
+
else
|
307
|
+
warn "image not bound: #{id}", location: location
|
308
|
+
lines.each do |line|
|
309
|
+
puts line
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
if !caption_top?('table') && caption.present?
|
314
|
+
table_header(id, caption)
|
315
|
+
end
|
316
|
+
puts "◆→終了:#{@titles['table']}←◆"
|
317
|
+
blank
|
318
|
+
end
|
319
|
+
|
272
320
|
def comment(lines, comment = nil)
|
273
321
|
return unless @book.config['draft']
|
274
322
|
|
@@ -314,8 +362,9 @@ module ReVIEW
|
|
314
362
|
|
315
363
|
def compile_kw(word, alt)
|
316
364
|
if alt
|
317
|
-
|
318
|
-
else
|
365
|
+
"★#{word}☆(#{alt.strip})"
|
366
|
+
else
|
367
|
+
"★#{word}☆"
|
319
368
|
end
|
320
369
|
end
|
321
370
|
|
@@ -398,7 +447,7 @@ module ReVIEW
|
|
398
447
|
def inline_icon(id)
|
399
448
|
begin
|
400
449
|
"◆→画像 #{@chapter.image(id).path.sub(%r{\A\./}, '')}←◆"
|
401
|
-
rescue
|
450
|
+
rescue StandardError
|
402
451
|
warn "image not bound: #{id}", location: location
|
403
452
|
"◆→画像 #{id}←◆"
|
404
453
|
end
|
@@ -495,27 +544,37 @@ module ReVIEW
|
|
495
544
|
), __FILE__, __LINE__ - 11
|
496
545
|
end
|
497
546
|
|
498
|
-
def indepimage(
|
547
|
+
def indepimage(lines, id, caption = nil, metric = nil)
|
499
548
|
metrics = parse_metric('top', metric)
|
500
549
|
metrics = " #{metrics}" if metrics.present?
|
501
550
|
blank
|
551
|
+
puts "◆→開始:#{@titles['image']}←◆"
|
502
552
|
if caption_top?('image') && caption.present?
|
503
|
-
|
553
|
+
indepimage_header(id, caption)
|
554
|
+
blank
|
504
555
|
end
|
505
|
-
|
506
|
-
puts "
|
507
|
-
|
556
|
+
if @chapter.image_bound?(id)
|
557
|
+
puts "◆→#{@chapter.image(id).path}#{metrics}←◆"
|
558
|
+
else
|
508
559
|
warn "image not bound: #{id}", location: location
|
509
|
-
|
560
|
+
lines.each do |line|
|
561
|
+
puts line
|
562
|
+
end
|
510
563
|
end
|
511
564
|
if !caption_top?('image') && caption.present?
|
512
|
-
|
565
|
+
blank
|
566
|
+
indepimage_header(id, caption)
|
513
567
|
end
|
568
|
+
puts "◆→終了:#{@titles['image']}←◆"
|
514
569
|
blank
|
515
570
|
end
|
516
571
|
|
517
572
|
alias_method :numberlessimage, :indepimage
|
518
573
|
|
574
|
+
def indepimage_header(_id, caption)
|
575
|
+
puts "図#{I18n.t('caption_prefix_idgxml')}#{compile_inline(caption)}"
|
576
|
+
end
|
577
|
+
|
519
578
|
def inline_code(str)
|
520
579
|
"△#{str}☆"
|
521
580
|
end
|
data/lib/review/update.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (c) 2018-
|
2
|
+
# Copyright (c) 2018-2022 Kenshi Muto
|
3
3
|
#
|
4
4
|
# This program is free software.
|
5
5
|
# You can distribute or modify this program under the terms of
|
@@ -165,7 +165,7 @@ module ReVIEW
|
|
165
165
|
|
166
166
|
Dir.glob(File.join(dir, '*.yml')).sort.each do |yml|
|
167
167
|
begin
|
168
|
-
config =
|
168
|
+
config = YAMLLoader.safe_load_file(yml)
|
169
169
|
if config['language'].present?
|
170
170
|
language = config['language']
|
171
171
|
end
|
@@ -226,9 +226,11 @@ module ReVIEW
|
|
226
226
|
|
227
227
|
def check_own_files(dir)
|
228
228
|
if File.exist?(File.join(dir, 'layouts/layout.tex.erb'))
|
229
|
+
# rubocop:disable Style/SoleNestedConditional
|
229
230
|
unless confirm('** There is custom layouts/layout.tex.erb file. Updating may break to make PDF until you fix layout.tex.erb. Do you really proceed to update? **', [], nil)
|
230
231
|
raise ApplicationError
|
231
232
|
end
|
233
|
+
# rubocop:enable Style/SoleNestedConditional
|
232
234
|
end
|
233
235
|
|
234
236
|
if File.exist?(File.join(dir, 'review-ext.rb'))
|
@@ -238,7 +240,7 @@ module ReVIEW
|
|
238
240
|
|
239
241
|
def update_version
|
240
242
|
@config_ymls.each do |yml|
|
241
|
-
config =
|
243
|
+
config = YAMLLoader.safe_load_file(yml)
|
242
244
|
if config['review_version'].to_f.round(1) == TARGET_VERSION.to_f.round(1)
|
243
245
|
next
|
244
246
|
end
|
@@ -265,10 +267,12 @@ module ReVIEW
|
|
265
267
|
target_rakefile = File.join(dir, 'Rakefile')
|
266
268
|
if File.exist?(target_rakefile)
|
267
269
|
if Digest::SHA256.hexdigest(File.read(target_rakefile)) != Digest::SHA256.hexdigest(File.read(master_rakefile))
|
270
|
+
# rubocop:disable Style/SoleNestedConditional
|
268
271
|
if confirm('%s will be overridden with Re:VIEW version (%s). Do you really proceed?', ['Rakefile', master_rakefile])
|
269
272
|
FileUtils.mv(target_rakefile, "#{target_rakefile}-old")
|
270
273
|
FileUtils.cp(master_rakefile, target_rakefile)
|
271
274
|
end
|
275
|
+
# rubocop:enable Style/SoleNestedConditional
|
272
276
|
end
|
273
277
|
else
|
274
278
|
@logger.info t('new file %s is created.', [target_rakefile]) unless @force
|
@@ -278,12 +282,14 @@ module ReVIEW
|
|
278
282
|
master_rakefile = File.join(@review_dir, 'samples/sample-book/src/lib/tasks/review.rake')
|
279
283
|
target_rakefile = File.join(taskdir, 'review.rake')
|
280
284
|
if File.exist?(target_rakefile)
|
285
|
+
# rubocop:disable Style/SoleNestedConditional
|
281
286
|
if Digest::SHA256.hexdigest(File.read(target_rakefile)) != Digest::SHA256.hexdigest(File.read(master_rakefile))
|
282
287
|
if confirm('%s will be overridden with Re:VIEW version (%s). Do you really proceed?', ['lib/tasks/review.rake', master_rakefile])
|
283
288
|
FileUtils.mv(target_rakefile, "#{target_rakefile}-old")
|
284
289
|
FileUtils.cp(master_rakefile, target_rakefile)
|
285
290
|
end
|
286
291
|
end
|
292
|
+
# rubocop:enable Style/SoleNestedConditional
|
287
293
|
else
|
288
294
|
@logger.info t('new file %s is created.', [target_rakefile]) unless @force
|
289
295
|
FileUtils.cp(master_rakefile, target_rakefile)
|
@@ -292,11 +298,13 @@ module ReVIEW
|
|
292
298
|
|
293
299
|
def update_epub_version
|
294
300
|
@epub_ymls.each do |yml|
|
295
|
-
config =
|
301
|
+
config = YAMLLoader.safe_load_file(yml)
|
296
302
|
if config['epubversion'].present? && config['epubversion'].to_f < EPUB_VERSION.to_f
|
303
|
+
# rubocop:disable Style/SoleNestedConditional
|
297
304
|
if confirm("%s: Update '%s' to '%s' from '%s'?", [File.basename(yml), 'epubversion', EPUB_VERSION, config['epubversion']])
|
298
305
|
rewrite_yml(yml, 'epubversion', EPUB_VERSION)
|
299
306
|
end
|
307
|
+
# rubocop:enable Style/SoleNestedConditional
|
300
308
|
end
|
301
309
|
if !config['htmlversion'].present? || config['htmlversion'].to_f >= HTML_VERSION.to_f
|
302
310
|
next
|
@@ -310,7 +318,7 @@ module ReVIEW
|
|
310
318
|
|
311
319
|
def update_locale
|
312
320
|
@locale_ymls.each do |yml|
|
313
|
-
config =
|
321
|
+
config = YAMLLoader.safe_load_file(yml)
|
314
322
|
if !config['chapter_quote'].present? || config['chapter_quote'].scan('%s').size != 1
|
315
323
|
next
|
316
324
|
end
|
@@ -324,7 +332,7 @@ module ReVIEW
|
|
324
332
|
|
325
333
|
def update_tex_parameters
|
326
334
|
@tex_ymls.each do |yml|
|
327
|
-
config =
|
335
|
+
config = YAMLLoader.safe_load_file(yml)
|
328
336
|
unless config['texdocumentclass']
|
329
337
|
next
|
330
338
|
end
|
@@ -510,7 +518,7 @@ module ReVIEW
|
|
510
518
|
|
511
519
|
def update_tex_command
|
512
520
|
@tex_ymls.each do |yml|
|
513
|
-
config =
|
521
|
+
config = YAMLLoader.safe_load_file(yml)
|
514
522
|
if !config['texcommand'] || config['texcommand'] !~ /\s+-/
|
515
523
|
next
|
516
524
|
end
|
@@ -535,7 +543,7 @@ module ReVIEW
|
|
535
543
|
|
536
544
|
def update_dvi_command
|
537
545
|
@tex_ymls.each do |yml|
|
538
|
-
config =
|
546
|
+
config = YAMLLoader.safe_load_file(yml)
|
539
547
|
if !config['dvicommand'] || config['dvicommand'] !~ /\s+-/
|
540
548
|
next
|
541
549
|
end
|
data/lib/review/version.rb
CHANGED
data/lib/review/webmaker.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2016-
|
1
|
+
# Copyright (c) 2016-2022 Masayoshi Takahashi, Masanori Kado, Kenshi Muto
|
2
2
|
#
|
3
3
|
# This program is free software.
|
4
4
|
# You can distribute or modify this program under the terms of
|
@@ -78,9 +78,13 @@ module ReVIEW
|
|
78
78
|
cmd_config, yamlfile = parse_opts(args)
|
79
79
|
error! "#{yamlfile} not found." unless File.exist?(yamlfile)
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
81
|
+
begin
|
82
|
+
@config = ReVIEW::Configure.create(maker: 'webmaker',
|
83
|
+
yamlfile: yamlfile,
|
84
|
+
config: cmd_config)
|
85
|
+
rescue ReVIEW::ConfigError => e
|
86
|
+
error! e.message
|
87
|
+
end
|
84
88
|
|
85
89
|
@config['htmlext'] = 'html'
|
86
90
|
@img_math = ReVIEW::ImgMath.new(@config)
|
@@ -97,7 +101,7 @@ module ReVIEW
|
|
97
101
|
end
|
98
102
|
|
99
103
|
def generate_html_files(yamlfile)
|
100
|
-
@basedir = File.dirname(yamlfile)
|
104
|
+
@basedir = File.absolute_path(File.dirname(yamlfile))
|
101
105
|
@path = build_path
|
102
106
|
remove_old_files(@path)
|
103
107
|
Dir.mkdir(@path)
|
@@ -146,19 +150,27 @@ module ReVIEW
|
|
146
150
|
def build_part(part, basetmpdir, htmlfile)
|
147
151
|
@title = h("#{ReVIEW::I18n.t('part', part.number)} #{part.name.strip}")
|
148
152
|
File.open("#{basetmpdir}/#{htmlfile}", 'w') do |f|
|
149
|
-
@
|
150
|
-
@
|
151
|
-
@body
|
152
|
-
@body << %Q(<h2 class="part-title">#{part.name.strip}</h2>\n) if part.name.strip.present?
|
153
|
-
@body << "</div>\n"
|
154
|
-
|
153
|
+
@part_number = part.number
|
154
|
+
@part_title = part.name.strip
|
155
|
+
@body = ReVIEW::Template.generate(path: template_name(localfile: '_part_body.html.erb', systemfile: 'html/_part_body.html.erb'), binding: binding)
|
155
156
|
@language = @config['language']
|
156
157
|
@stylesheets = @config['stylesheet']
|
157
158
|
f.write ReVIEW::Template.generate(path: template_name, binding: binding)
|
158
159
|
end
|
159
160
|
end
|
160
161
|
|
161
|
-
def template_name
|
162
|
+
def template_name(localfile: 'layout-web.html.erb', systemfile: nil)
|
163
|
+
if @basedir
|
164
|
+
layoutfile = File.join(@basedir, 'layouts', localfile)
|
165
|
+
if File.exist?(layoutfile)
|
166
|
+
return layoutfile
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
if systemfile
|
171
|
+
return systemfile
|
172
|
+
end
|
173
|
+
|
162
174
|
if @config['htmlversion'].to_i == 5
|
163
175
|
'web/html/layout-html5.html.erb'
|
164
176
|
else
|
@@ -167,13 +179,11 @@ module ReVIEW
|
|
167
179
|
end
|
168
180
|
|
169
181
|
def build_chap(chap, base_path, basetmpdir, ispart)
|
170
|
-
filename =
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
filename = Pathname.new(chap.path).relative_path_from(base_path).to_s
|
176
|
-
end
|
182
|
+
filename = if ispart.present?
|
183
|
+
chap.path
|
184
|
+
else
|
185
|
+
Pathname.new(chap.path).relative_path_from(base_path).to_s
|
186
|
+
end
|
177
187
|
id = File.basename(filename).sub(/\.re\Z/, '')
|
178
188
|
|
179
189
|
if @buildonly && !@buildonly.include?(id)
|
@@ -219,7 +229,7 @@ module ReVIEW
|
|
219
229
|
|
220
230
|
if FileTest.directory?("#{resdir}/#{fname}")
|
221
231
|
recursive_copy_files("#{resdir}/#{fname}", "#{destdir}/#{fname}", allow_exts)
|
222
|
-
elsif
|
232
|
+
elsif /\.(#{allow_exts.join('|')})\Z/i.match?(fname)
|
223
233
|
FileUtils.mkdir_p(destdir)
|
224
234
|
FileUtils.cp("#{resdir}/#{fname}", destdir)
|
225
235
|
end
|
@@ -274,18 +284,8 @@ module ReVIEW
|
|
274
284
|
|
275
285
|
def build_titlepage(basetmpdir, htmlfile)
|
276
286
|
@title = h('titlepage')
|
277
|
-
File.open(
|
278
|
-
@body = ''
|
279
|
-
@body << %Q(<div class="titlepage">)
|
280
|
-
@body << %Q(<h1 class="tp-title">#{h(@config.name_of('booktitle'))}</h1>)
|
281
|
-
if @config['aut']
|
282
|
-
@body << %Q(<h2 class="tp-author">#{join_with_separator(@config.names_of('aut'), ReVIEW::I18n.t('names_splitter'))}</h2>)
|
283
|
-
end
|
284
|
-
if @config['pbl']
|
285
|
-
@body << %Q(<h3 class="tp-publisher">#{join_with_separator(@config.names_of('pbl'), ReVIEW::I18n.t('names_splitter'))}</h3>)
|
286
|
-
end
|
287
|
-
@body << '</div>'
|
288
|
-
|
287
|
+
File.open(File.join(basetmpdir, htmlfile), 'w') do |f|
|
288
|
+
@body = ReVIEW::Template.generate(path: template_name(localfile: '_titlepage.html.erb', systemfile: 'html/_titlepage.html.erb'), binding: binding)
|
289
289
|
@language = @config['language']
|
290
290
|
@stylesheets = @config['stylesheet']
|
291
291
|
f.write ReVIEW::Template.generate(path: template_name, binding: binding)
|
data/lib/review/webtocprinter.rb
CHANGED
@@ -41,16 +41,16 @@ EOT
|
|
41
41
|
next
|
42
42
|
end
|
43
43
|
|
44
|
-
if path.start_with?('.')
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
if result.level == 0
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
44
|
+
content << if path.start_with?('.')
|
45
|
+
"<li>#{escape(result.headline)}"
|
46
|
+
else
|
47
|
+
%Q(<li><a href="#{path}">#{escape(result.headline)}</a>)
|
48
|
+
end
|
49
|
+
content << if result.level == 0
|
50
|
+
"\n<ul>" # part
|
51
|
+
else
|
52
|
+
"</li>\n"
|
53
|
+
end
|
54
54
|
end
|
55
55
|
content << "</ul>\n"
|
56
56
|
end
|
data/lib/review/yamlloader.rb
CHANGED
@@ -2,6 +2,39 @@ require 'yaml'
|
|
2
2
|
|
3
3
|
module ReVIEW
|
4
4
|
class YAMLLoader
|
5
|
+
def self.safe_load_file(file)
|
6
|
+
if YAML.respond_to?(:safe_load_file)
|
7
|
+
YAML.safe_load_file(file, aliases: true, permitted_classes: [Date])
|
8
|
+
else
|
9
|
+
File.open(file, 'rt:bom|utf-8') do |f|
|
10
|
+
begin
|
11
|
+
# < Ruby 3.1
|
12
|
+
YAML.safe_load(f, filename: file, aliases: true, permitted_classes: [Date])
|
13
|
+
rescue ArgumentError
|
14
|
+
# < Ruby 2.7
|
15
|
+
YAML.safe_load(f, [Date])
|
16
|
+
rescue Psych::DisallowedClass
|
17
|
+
# < Ruby 2.5
|
18
|
+
YAML.safe_load(File.read(file), [Date])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.safe_load(s)
|
25
|
+
if YAML.respond_to?(:safe_load_file)
|
26
|
+
YAML.safe_load(s, aliases: true, permitted_classes: [Date])
|
27
|
+
else
|
28
|
+
begin
|
29
|
+
# < Ruby 3.1
|
30
|
+
YAML.safe_load(s, aliases: true, permitted_classes: [Date])
|
31
|
+
rescue ArgumentError, Psych::DisallowedClass
|
32
|
+
# < Ruby 2.7
|
33
|
+
YAML.safe_load(s, [Date])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
5
38
|
def initialize
|
6
39
|
end
|
7
40
|
|
@@ -17,8 +50,8 @@ module ReVIEW
|
|
17
50
|
|
18
51
|
while file_queue.present?
|
19
52
|
current_file = file_queue.shift
|
20
|
-
current_yaml =
|
21
|
-
if current_yaml.instance_of?(FalseClass)
|
53
|
+
current_yaml = YAMLLoader.safe_load_file(current_file)
|
54
|
+
if current_yaml.instance_of?(FalseClass) || current_yaml.nil?
|
22
55
|
raise "#{File.basename(current_file)} is malformed."
|
23
56
|
end
|
24
57
|
|
data/review.gemspec
CHANGED
@@ -12,6 +12,7 @@ Gem::Specification.new do |gem|
|
|
12
12
|
gem.summary = 'Re:VIEW: a easy-to-use digital publishing system'
|
13
13
|
gem.description = 'Re:VIEW is a digital publishing system for books and ebooks. It supports InDesign, EPUB and LaTeX.'
|
14
14
|
gem.required_rubygems_version = Gem::Requirement.new('>= 0') if gem.respond_to?(:required_rubygems_version=)
|
15
|
+
gem.metadata = { 'rubygems_mfa_required' => 'true' }
|
15
16
|
|
16
17
|
gem.files = `git ls-files`.split("\n")
|
17
18
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -1,20 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
<div class="titlepage">
|
2
|
+
<h1 class="tp-title"><%= h(@config.name_of('booktitle')) %></h1>
|
3
|
+
<% if @config['subtitle'] %>
|
4
|
+
<h2 class="tp-subtitle"><%= h(@config.name_of('subtitle')) %></h2>
|
4
5
|
<% end %>
|
5
|
-
<% if @
|
6
|
-
|
7
|
-
<br />
|
8
|
-
<br />
|
9
|
-
</p>
|
10
|
-
<h2 class="tp-author"><%= h(@author_str) %></h2>
|
6
|
+
<% if @config['aut'] %>
|
7
|
+
<h2 class="tp-author"><%= h(@config.names_of('aut').join(ReVIEW::I18n.t('names_splitter'))) %></h2>
|
11
8
|
<% end %>
|
12
|
-
<% if @
|
13
|
-
|
14
|
-
<br />
|
15
|
-
<br />
|
16
|
-
<br />
|
17
|
-
<br />
|
18
|
-
</p>
|
19
|
-
<h3 class="tp-publisher"><%= h(@publisher_str) %></h3>
|
9
|
+
<% if @config['pbl'] %>
|
10
|
+
<h3 class="tp-publisher"><%= h(@config.names_of('pbl').join(ReVIEW::I18n.t('names_splitter'))) %></h3>
|
20
11
|
<% end %>
|
12
|
+
</div>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<% if @config['toc'] && @config['mytoc'] %>
|
5
5
|
<item id="toc" href="<%= @config['bookname'] %>-toc.<%= @config['htmlext'] %>" media-type="application/xhtml+xml"/>
|
6
6
|
<% end %>
|
7
|
-
<% @items.each do |item| %>
|
7
|
+
<% @items.sort_by { |x| x.id }.each do |item| %>
|
8
8
|
<item id="<%= item.id %>" href="<%= item.file %>" media-type="<%= item.media %>"/>
|
9
9
|
<% end %>
|
10
10
|
</manifest>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<% if @coverimage %>
|
5
5
|
<item properties="cover-image" id="cover-<%= @coverimage.id %>" href="<%= @coverimage.file %>" media-type="<%= @coverimage.media %>"/>
|
6
6
|
<% end %>
|
7
|
-
<% @items.each do |item| %>
|
7
|
+
<% @items.sort_by { |x| x.id }.each do |item| %>
|
8
8
|
<item id="<%= item.id %>" href="<%= item.file %>" media-type="<%= item.media %>"<%= item.properties_attribute %>/>
|
9
9
|
<% end %>
|
10
10
|
</manifest>
|
data/test/book_test_helper.rb
CHANGED
@@ -20,11 +20,11 @@ module BookTestHelper
|
|
20
20
|
created_files[filename] = path
|
21
21
|
end
|
22
22
|
conf_path = File.expand_path('config.yml', dir)
|
23
|
-
if File.exist?(conf_path)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
config = if File.exist?(conf_path)
|
24
|
+
ReVIEW::Configure.create(yamlfile: conf_path)
|
25
|
+
else
|
26
|
+
ReVIEW::Configure.values
|
27
|
+
end
|
28
28
|
book = Book::Base.new(dir, config: config)
|
29
29
|
yield(dir, book, created_files)
|
30
30
|
end
|
@@ -34,11 +34,11 @@ module BookTestHelper
|
|
34
34
|
def get_instance_variables(obj)
|
35
35
|
obj.instance_variables.each_with_object({}) do |name, memo|
|
36
36
|
value = obj.instance_variable_get(name)
|
37
|
-
if value.instance_variables.empty?
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
memo[name] = if value.instance_variables.empty?
|
38
|
+
value
|
39
|
+
else
|
40
|
+
get_instance_variables(value)
|
41
|
+
end
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|