review 5.1.1 → 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 +6 -2
- data/.github/workflows/ruby-win.yml +6 -2
- data/.github/workflows/ruby.yml +6 -2
- data/.rubocop.yml +5 -319
- data/NEWS.ja.md +149 -0
- data/NEWS.md +149 -1
- 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 +14 -23
- data/bin/review-index +1 -1
- data/bin/review-preproc +29 -35
- data/bin/review-validate +2 -2
- data/doc/config.yml.sample +9 -1
- data/doc/config.yml.sample-simple +1 -1
- data/doc/format.ja.md +29 -3
- data/doc/format.md +32 -3
- data/doc/writing_vertical.ja.md +6 -0
- data/lib/review/book/base.rb +3 -3
- data/lib/review/book/book_unit.rb +13 -3
- data/lib/review/book/chapter.rb +1 -1
- data/lib/review/book/index.rb +7 -4
- data/lib/review/book/part.rb +12 -13
- data/lib/review/book/volume.rb +1 -1
- data/lib/review/builder.rb +92 -65
- data/lib/review/catalog.rb +6 -5
- data/lib/review/compiler.rb +76 -57
- 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 +47 -45
- data/lib/review/epubmaker/epubv2.rb +2 -1
- data/lib/review/epubmaker/epubv3.rb +5 -4
- data/lib/review/epubmaker/producer.rb +6 -7
- data/lib/review/epubmaker/reviewheaderlistener.rb +1 -1
- data/lib/review/epubmaker.rb +56 -67
- data/lib/review/exception.rb +7 -0
- data/lib/review/extentions/string.rb +1 -1
- data/lib/review/htmlbuilder.rb +90 -34
- data/lib/review/htmlutils.rb +17 -17
- data/lib/review/i18n.rb +3 -3
- data/lib/review/i18n.yml +6 -0
- data/lib/review/idgxmlbuilder.rb +61 -39
- data/lib/review/idgxmlmaker.rb +27 -26
- data/lib/review/img_math.rb +12 -18
- data/lib/review/index_builder.rb +94 -53
- data/lib/review/init.rb +4 -4
- data/lib/review/latexbuilder.rb +84 -76
- data/lib/review/lineinput.rb +3 -3
- data/lib/review/location.rb +1 -1
- data/lib/review/loggable.rb +27 -0
- data/lib/review/logger.rb +69 -21
- data/lib/review/makerhelper.rb +8 -4
- data/lib/review/markdownbuilder.rb +21 -12
- data/lib/review/pdfmaker.rb +63 -42
- data/lib/review/plaintextbuilder.rb +16 -15
- data/lib/review/preprocessor/directive.rb +35 -0
- data/lib/review/preprocessor/line.rb +34 -0
- data/lib/review/preprocessor/repository.rb +177 -0
- data/lib/review/preprocessor.rb +94 -296
- data/lib/review/rstbuilder.rb +12 -3
- data/lib/review/template.rb +5 -1
- data/lib/review/textmaker.rb +32 -31
- data/lib/review/textutils.rb +5 -6
- data/lib/review/tocprinter.rb +12 -7
- data/lib/review/topbuilder.rb +96 -19
- data/lib/review/update.rb +16 -8
- data/lib/review/version.rb +1 -1
- data/lib/review/volumeprinter.rb +9 -9
- data/lib/review/webmaker.rb +45 -46
- data/lib/review/webtocprinter.rb +10 -10
- data/lib/review/yamlloader.rb +35 -2
- data/review.gemspec +2 -1
- data/samples/sample-book/src/config.yml +0 -1
- data/samples/sample-book/src/lib/tasks/review.rake +3 -1
- data/samples/sample-book/src/lib/tasks/z01_copy_sty.rake +2 -1
- data/samples/syntax-book/ch02.re +9 -0
- data/samples/syntax-book/lib/tasks/z01_copy_sty.rake +2 -1
- data/templates/html/_titlepage.html.erb +9 -17
- data/templates/latex/config.erb +3 -0
- data/templates/latex/review-jlreq/review-base.sty +4 -5
- data/templates/latex/review-jlreq/review-jlreq.cls +39 -5
- data/templates/latex/review-jsbook/review-base.sty +9 -3
- data/templates/latex/review-jsbook/review-jsbook.cls +32 -5
- data/templates/opf/opf_manifest_epubv2.opf.erb +1 -1
- data/templates/opf/opf_manifest_epubv3.opf.erb +1 -1
- data/test/assets/syntax_book_index_detail.txt +10 -8
- data/test/assets/test_template.tex +4 -1
- data/test/assets/test_template_backmatter.tex +4 -1
- data/test/book_test_helper.rb +10 -10
- data/test/test_book_chapter.rb +25 -2
- data/test/test_builder.rb +10 -8
- data/test/test_epub3maker.rb +3 -3
- data/test/test_epubmaker.rb +27 -37
- data/test/test_epubmaker_cmd.rb +14 -3
- data/test/test_htmlbuilder.rb +111 -31
- data/test/test_idgxmlbuilder.rb +41 -33
- data/test/test_idgxmlmaker_cmd.rb +1 -1
- data/test/test_img_math.rb +11 -2
- data/test/test_index.rb +30 -4
- data/test/test_latexbuilder.rb +46 -25
- data/test/test_latexbuilder_v2.rb +18 -10
- data/test/test_markdownbuilder.rb +13 -0
- data/test/test_pdfmaker.rb +19 -0
- data/test/test_pdfmaker_cmd.rb +10 -10
- data/test/test_plaintextbuilder.rb +46 -22
- data/test/test_preprocessor.rb +188 -1
- data/test/test_rstbuilder.rb +13 -0
- data/test/test_textmaker_cmd.rb +1 -1
- data/test/test_topbuilder.rb +195 -29
- data/test/test_yamlloader.rb +28 -42
- metadata +11 -6
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2013-
|
1
|
+
# Copyright (c) 2013-2021 KADO Masanori, Masayoshi Takahashi, Kenshi Muto
|
2
2
|
#
|
3
3
|
# This program is free software.
|
4
4
|
# You can distribute or modify this program under the terms of
|
@@ -18,6 +18,7 @@ module ReVIEW
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def builder_init_file
|
21
|
+
super
|
21
22
|
@noindent = nil
|
22
23
|
@blank_seen = nil
|
23
24
|
@ul_indent = 0
|
@@ -97,7 +98,7 @@ module ReVIEW
|
|
97
98
|
end
|
98
99
|
|
99
100
|
def ul_item_begin(lines)
|
100
|
-
puts ' ' * (@ul_indent - 1) + '* ' + join_lines_to_paragraph(lines)
|
101
|
+
puts (' ' * (@ul_indent - 1)) + '* ' + join_lines_to_paragraph(lines)
|
101
102
|
end
|
102
103
|
|
103
104
|
def ul_item_end
|
@@ -245,7 +246,7 @@ module ReVIEW
|
|
245
246
|
def inline_img(id)
|
246
247
|
"#{I18n.t('image')}#{@chapter.image(id).number}"
|
247
248
|
rescue KeyError
|
248
|
-
|
249
|
+
app_error "unknown image: #{id}"
|
249
250
|
end
|
250
251
|
|
251
252
|
def inline_dtp(str)
|
@@ -254,24 +255,24 @@ module ReVIEW
|
|
254
255
|
|
255
256
|
def inline_hd_chap(chap, id)
|
256
257
|
n = chap.headline_index.number(id)
|
257
|
-
if n.present? && chap.number && over_secnolevel?(n)
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
258
|
+
str = if n.present? && chap.number && over_secnolevel?(n)
|
259
|
+
I18n.t('hd_quote', [n, compile_inline(chap.headline(id).caption)])
|
260
|
+
else
|
261
|
+
I18n.t('hd_quote_without_number', compile_inline(chap.headline(id).caption))
|
262
|
+
end
|
262
263
|
if @book.config['chapterlink']
|
263
264
|
if @chapter == chap
|
264
265
|
anchor = 'h' + n.tr('.', '-')
|
265
266
|
%Q(<a href="##{anchor}">#{str}</a>)
|
266
267
|
else
|
267
|
-
warn 'MARKDOWNBuilder does not support links to other chapters'
|
268
|
+
warn 'MARKDOWNBuilder does not support links to other chapters', location: location
|
268
269
|
str
|
269
270
|
end
|
270
271
|
else
|
271
272
|
str
|
272
273
|
end
|
273
274
|
rescue KeyError
|
274
|
-
|
275
|
+
app_error "unknown headline: #{id}"
|
275
276
|
end
|
276
277
|
|
277
278
|
def indepimage(_lines, id, caption = '', _metric = nil)
|
@@ -360,6 +361,14 @@ module ReVIEW
|
|
360
361
|
"[^#{id}]"
|
361
362
|
end
|
362
363
|
|
364
|
+
def inline_endnote(id)
|
365
|
+
"<sup>#{I18n.t('html_endnote_refmark', @chapter.endnote(id).number)}</sup>"
|
366
|
+
end
|
367
|
+
|
368
|
+
def endnote_item(id)
|
369
|
+
puts "#{I18n.t('html_endnote_textmark', @chapter.endnote(id).number)}#{compile_inline(@chapter.endnote(id).content)}"
|
370
|
+
end
|
371
|
+
|
363
372
|
def inline_br(_str)
|
364
373
|
"\n"
|
365
374
|
end
|
@@ -400,8 +409,8 @@ module ReVIEW
|
|
400
409
|
def inline_icon(id)
|
401
410
|
begin
|
402
411
|
"![](#{@chapter.image(id).path.sub(%r{\A\./}, '')})"
|
403
|
-
rescue
|
404
|
-
warn "image not bound: #{id}"
|
412
|
+
rescue StandardError
|
413
|
+
warn "image not bound: #{id}", location: location
|
405
414
|
%Q(<pre>missing image: #{id}</pre>)
|
406
415
|
end
|
407
416
|
end
|
data/lib/review/pdfmaker.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2010-
|
1
|
+
# Copyright (c) 2010-2022 Kenshi Muto and Masayoshi Takahashi
|
2
2
|
#
|
3
3
|
# This program is free software.
|
4
4
|
# You can distribute or modify this program under the terms of
|
@@ -24,11 +24,12 @@ require 'review/makerhelper'
|
|
24
24
|
require 'review/template'
|
25
25
|
require 'review/latexbox'
|
26
26
|
require 'review/call_hook'
|
27
|
+
require 'review/loggable'
|
27
28
|
|
28
29
|
module ReVIEW
|
29
30
|
class PDFMaker
|
30
|
-
include FileUtils
|
31
31
|
include ReVIEW::LaTeXUtils
|
32
|
+
include Loggable
|
32
33
|
include ReVIEW::CallHook
|
33
34
|
|
34
35
|
attr_accessor :config, :basedir
|
@@ -38,13 +39,14 @@ module ReVIEW
|
|
38
39
|
@logger = ReVIEW.logger
|
39
40
|
@input_files = Hash.new { |h, key| h[key] = '' }
|
40
41
|
@mastertex = '__REVIEW_BOOK__'
|
42
|
+
@compile_errors = nil
|
41
43
|
end
|
42
44
|
|
43
45
|
def system_with_info(*args)
|
44
46
|
@logger.info args.join(' ')
|
45
47
|
out, status = Open3.capture2e(*args)
|
46
48
|
unless status.success?
|
47
|
-
|
49
|
+
error "execution error\n\nError log:\n#{out}"
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
@@ -52,19 +54,10 @@ module ReVIEW
|
|
52
54
|
@logger.info args.join(' ')
|
53
55
|
out, status = Open3.capture2e(*args)
|
54
56
|
unless status.success?
|
55
|
-
error "failed to run command: #{args.join(' ')}\n\nError log:\n"
|
57
|
+
error! "failed to run command: #{args.join(' ')}\n\nError log:\n#{out}"
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
|
-
def error(msg)
|
60
|
-
@logger.error msg
|
61
|
-
exit 1
|
62
|
-
end
|
63
|
-
|
64
|
-
def warn(msg)
|
65
|
-
@logger.warn msg
|
66
|
-
end
|
67
|
-
|
68
61
|
def pdf_filepath
|
69
62
|
File.join(@basedir, @config['bookname'] + '.pdf')
|
70
63
|
end
|
@@ -92,7 +85,7 @@ module ReVIEW
|
|
92
85
|
if ignore_errors
|
93
86
|
@logger.info 'compile error, but try to generate PDF file'
|
94
87
|
else
|
95
|
-
error 'compile error, No PDF file output.'
|
88
|
+
error! 'compile error, No PDF file output.'
|
96
89
|
end
|
97
90
|
end
|
98
91
|
|
@@ -126,11 +119,15 @@ module ReVIEW
|
|
126
119
|
|
127
120
|
def execute(*args)
|
128
121
|
cmd_config, yamlfile = parse_opts(args)
|
129
|
-
error "#{yamlfile} not found." unless File.exist?(yamlfile)
|
122
|
+
error! "#{yamlfile} not found." unless File.exist?(yamlfile)
|
130
123
|
|
131
|
-
|
132
|
-
|
133
|
-
|
124
|
+
begin
|
125
|
+
@config = ReVIEW::Configure.create(maker: 'pdfmaker',
|
126
|
+
yamlfile: yamlfile,
|
127
|
+
config: cmd_config)
|
128
|
+
rescue ReVIEW::ConfigError => e
|
129
|
+
error! e.message
|
130
|
+
end
|
134
131
|
|
135
132
|
I18n.setup(@config['language'])
|
136
133
|
@basedir = File.absolute_path(File.dirname(yamlfile))
|
@@ -143,11 +140,11 @@ module ReVIEW
|
|
143
140
|
|
144
141
|
# version 2 compatibility
|
145
142
|
unless @config['texdocumentclass']
|
146
|
-
if @config.check_version(2, exception: false)
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
143
|
+
@config['texdocumentclass'] = if @config.check_version(2, exception: false)
|
144
|
+
['jsbook', 'uplatex,oneside']
|
145
|
+
else
|
146
|
+
@config['_texdocumentclass']
|
147
|
+
end
|
151
148
|
end
|
152
149
|
|
153
150
|
begin
|
@@ -155,7 +152,7 @@ module ReVIEW
|
|
155
152
|
rescue ApplicationError => e
|
156
153
|
raise if @config['debug']
|
157
154
|
|
158
|
-
error
|
155
|
+
error! e.message
|
159
156
|
end
|
160
157
|
end
|
161
158
|
|
@@ -200,7 +197,7 @@ module ReVIEW
|
|
200
197
|
def build_pdf
|
201
198
|
template = template_content
|
202
199
|
Dir.chdir(@path) do
|
203
|
-
File.
|
200
|
+
File.write("./#{@mastertex}.tex", template)
|
204
201
|
|
205
202
|
call_hook('hook_beforetexcompile', Dir.pwd, @basedir, base_dir: @basedir)
|
206
203
|
|
@@ -217,7 +214,7 @@ module ReVIEW
|
|
217
214
|
makeindex_dic = ReVIEW::Configure.values['pdfmaker']['makeindex_dic']
|
218
215
|
else
|
219
216
|
unless @config['texcommand'].present?
|
220
|
-
error "texcommand isn't defined."
|
217
|
+
error! "texcommand isn't defined."
|
221
218
|
end
|
222
219
|
texcommand = @config['texcommand']
|
223
220
|
dvicommand = @config['dvicommand']
|
@@ -280,6 +277,9 @@ module ReVIEW
|
|
280
277
|
@config['usepackage'] = ''
|
281
278
|
@config['usepackage'] = "\\usepackage{#{@config['texstyle']}}" if @config['texstyle']
|
282
279
|
|
280
|
+
if @config['pdfmaker']['use_symlink']
|
281
|
+
logger.info 'use symlink'
|
282
|
+
end
|
283
283
|
copy_images(@config['imagedir'], File.join(@path, @config['imagedir']))
|
284
284
|
copy_sty(File.join(Dir.pwd, 'sty'), @path)
|
285
285
|
copy_sty(File.join(Dir.pwd, 'sty'), @path, 'fd')
|
@@ -293,7 +293,7 @@ module ReVIEW
|
|
293
293
|
FileUtils.cp(File.join(@path, "#{@mastertex}.pdf"), pdf_filepath)
|
294
294
|
@logger.success("built #{File.basename(pdf_filepath)}")
|
295
295
|
ensure
|
296
|
-
remove_entry_secure(@path) unless @config['debug']
|
296
|
+
FileUtils.remove_entry_secure(@path) unless @config['debug']
|
297
297
|
end
|
298
298
|
end
|
299
299
|
|
@@ -301,10 +301,10 @@ module ReVIEW
|
|
301
301
|
@logger.info "compiling #{filename}.tex"
|
302
302
|
begin
|
303
303
|
@converter.convert(filename + '.re', File.join(@path, filename + '.tex'))
|
304
|
-
rescue => e
|
304
|
+
rescue StandardError => e
|
305
305
|
@compile_errors = true
|
306
|
-
|
307
|
-
|
306
|
+
error "compile error in #{filename}.tex (#{e.class})"
|
307
|
+
error e.message
|
308
308
|
end
|
309
309
|
end
|
310
310
|
|
@@ -314,16 +314,24 @@ module ReVIEW
|
|
314
314
|
return unless File.exist?(from)
|
315
315
|
|
316
316
|
Dir.mkdir(to)
|
317
|
-
|
317
|
+
if @config['pdfmaker']['use_symlink']
|
318
|
+
ReVIEW::MakerHelper.copy_images_to_dir(from, to, use_symlink: true)
|
319
|
+
else
|
320
|
+
ReVIEW::MakerHelper.copy_images_to_dir(from, to)
|
321
|
+
end
|
318
322
|
end
|
319
323
|
|
320
324
|
def make_custom_page(file)
|
325
|
+
if file.nil?
|
326
|
+
return nil
|
327
|
+
end
|
328
|
+
|
321
329
|
file_sty = file.to_s.sub(/\.[^.]+\Z/, '.tex')
|
322
330
|
if File.exist?(file_sty)
|
323
|
-
|
331
|
+
File.read(file_sty)
|
332
|
+
else
|
333
|
+
warn "File #{file_sty} is not found."
|
324
334
|
end
|
325
|
-
|
326
|
-
nil
|
327
335
|
end
|
328
336
|
|
329
337
|
def join_with_separator(value, sep)
|
@@ -373,9 +381,9 @@ module ReVIEW
|
|
373
381
|
items.each_with_index do |item, rev|
|
374
382
|
editstr = edit == 0 ? ReVIEW::I18n.t('first_edition') : ReVIEW::I18n.t('nth_edition', (edit + 1).to_s)
|
375
383
|
revstr = ReVIEW::I18n.t('nth_impression', (rev + 1).to_s)
|
376
|
-
if
|
384
|
+
if /\A\d+-\d+-\d+\Z/.match?(item)
|
377
385
|
buf << ReVIEW::I18n.t('published_by1', [date_to_s(item), editstr + revstr])
|
378
|
-
elsif
|
386
|
+
elsif /\A(\d+-\d+-\d+)[\s ](.+)/.match?(item)
|
379
387
|
# custom date with string
|
380
388
|
item.match(/\A(\d+-\d+-\d+)[\s ](.+)/) { |m| buf << ReVIEW::I18n.t('published_by3', [date_to_s(m[1]), m[2]]) }
|
381
389
|
else
|
@@ -442,6 +450,10 @@ module ReVIEW
|
|
442
450
|
end
|
443
451
|
end
|
444
452
|
|
453
|
+
if @config['coverimage'] && !File.exist?(File.join(@config['imagedir'], @config['coverimage']))
|
454
|
+
raise ReVIEW::ConfigError, "coverimage #{@config['coverimage']} is not found."
|
455
|
+
end
|
456
|
+
|
445
457
|
@locale_latex = {}
|
446
458
|
part_tuple = I18n.get('part').split(/%[A-Za-z]{1,3}/, 2)
|
447
459
|
chapter_tuple = I18n.get('chapter').split(/%[A-Za-z]{1,3}/, 2)
|
@@ -457,7 +469,7 @@ module ReVIEW
|
|
457
469
|
begin
|
458
470
|
@boxsetting = ReVIEW::LaTeXBox.new.tcbox(@config)
|
459
471
|
rescue ReVIEW::ConfigError => e
|
460
|
-
error e
|
472
|
+
error! e
|
461
473
|
end
|
462
474
|
end
|
463
475
|
end
|
@@ -475,17 +487,24 @@ module ReVIEW
|
|
475
487
|
|
476
488
|
def template_content
|
477
489
|
template_dir = ReVIEW::Template::TEMPLATE_DIR
|
478
|
-
if @config.check_version('2', exception: false)
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
490
|
+
template_path = if @config.check_version('2', exception: false)
|
491
|
+
'./latex-compat2/layout.tex.erb'
|
492
|
+
else
|
493
|
+
'./latex/layout.tex.erb'
|
494
|
+
end
|
483
495
|
layout_file = File.join(@basedir, 'layouts', 'layout.tex.erb')
|
484
496
|
if File.exist?(layout_file)
|
485
497
|
template_dir = @basedir
|
486
498
|
template_path = 'layouts/layout.tex.erb'
|
487
499
|
end
|
488
500
|
ReVIEW::Template.generate(path: template_path, mode: '-', binding: binding, template_dir: template_dir)
|
501
|
+
rescue StandardError => e
|
502
|
+
if defined?(e.full_message)
|
503
|
+
error! "template or configuration error: #{e.full_message(highlight: false)}"
|
504
|
+
else
|
505
|
+
# <= Ruby 2.4
|
506
|
+
error! "template or configuration error: #{e.message}"
|
507
|
+
end
|
489
508
|
end
|
490
509
|
|
491
510
|
def copy_sty(dirname, copybase, extname = 'sty')
|
@@ -503,6 +522,8 @@ module ReVIEW
|
|
503
522
|
File.open(File.join(copybase, fname.sub(/\.erb\Z/, '')), 'w') do |f|
|
504
523
|
f.print erb_content(File.join(dirname, fname))
|
505
524
|
end
|
525
|
+
elsif @config['pdfmaker']['use_symlink']
|
526
|
+
FileUtils.ln_s(File.join(dirname, fname), copybase)
|
506
527
|
else
|
507
528
|
FileUtils.cp(File.join(dirname, fname), copybase)
|
508
529
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2018-
|
1
|
+
# Copyright (c) 2018-2021 Kenshi Muto
|
2
2
|
#
|
3
3
|
# This program is free software.
|
4
4
|
# You can distribute or modify this program under the terms of
|
@@ -42,12 +42,12 @@ module ReVIEW
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def builder_init_file
|
45
|
+
super
|
45
46
|
@section = 0
|
46
47
|
@subsection = 0
|
47
48
|
@subsubsection = 0
|
48
49
|
@subsubsubsection = 0
|
49
50
|
@blank_seen = true
|
50
|
-
@sec_counter = SecCounter.new(5, @chapter)
|
51
51
|
end
|
52
52
|
private :builder_init_file
|
53
53
|
|
@@ -74,6 +74,7 @@ module ReVIEW
|
|
74
74
|
private :blank
|
75
75
|
|
76
76
|
def result
|
77
|
+
check_printendnotes
|
77
78
|
solve_nest(@output.string)
|
78
79
|
end
|
79
80
|
|
@@ -85,11 +86,11 @@ module ReVIEW
|
|
85
86
|
if l =~ /\A\x01→(dl|ul|ol)←\x01/
|
86
87
|
clevel.push($1)
|
87
88
|
lines.push("\x01→END←\x01")
|
88
|
-
elsif
|
89
|
+
elsif %r{\A\x01→/(dl|ul|ol)←\x01}.match?(l)
|
89
90
|
clevel.pop
|
90
91
|
lines.push("\x01→END←\x01")
|
91
92
|
else
|
92
|
-
lines.push("\t" * clevel.size + l)
|
93
|
+
lines.push(("\t" * clevel.size) + l)
|
93
94
|
end
|
94
95
|
end
|
95
96
|
|
@@ -169,7 +170,7 @@ module ReVIEW
|
|
169
170
|
list_header(id, caption, lang)
|
170
171
|
end
|
171
172
|
rescue KeyError
|
172
|
-
|
173
|
+
app_error "no such list: #{id}"
|
173
174
|
end
|
174
175
|
blank
|
175
176
|
end
|
@@ -213,14 +214,14 @@ module ReVIEW
|
|
213
214
|
|
214
215
|
def emlistnum(lines, caption = nil, _lang = nil)
|
215
216
|
blank
|
216
|
-
if caption_top?('list')
|
217
|
-
puts compile_inline(caption)
|
217
|
+
if caption_top?('list') && caption.present?
|
218
|
+
puts compile_inline(caption)
|
218
219
|
end
|
219
220
|
lines.each_with_index do |line, i|
|
220
221
|
puts((i + 1).to_s.rjust(2) + ": #{line}")
|
221
222
|
end
|
222
|
-
|
223
|
-
puts compile_inline(caption)
|
223
|
+
if !caption_top?('list') && caption.present?
|
224
|
+
puts compile_inline(caption)
|
224
225
|
end
|
225
226
|
blank
|
226
227
|
end
|
@@ -238,7 +239,7 @@ module ReVIEW
|
|
238
239
|
list_header(id, caption, lang)
|
239
240
|
end
|
240
241
|
rescue KeyError
|
241
|
-
|
242
|
+
app_error "no such list: #{id}"
|
242
243
|
end
|
243
244
|
blank
|
244
245
|
end
|
@@ -337,7 +338,7 @@ module ReVIEW
|
|
337
338
|
def inline_fn(id)
|
338
339
|
" 注#{@chapter.footnote(id).number} "
|
339
340
|
rescue KeyError
|
340
|
-
|
341
|
+
app_error "unknown footnote: #{id}"
|
341
342
|
end
|
342
343
|
|
343
344
|
def compile_ruby(base, _ruby)
|
@@ -401,7 +402,7 @@ module ReVIEW
|
|
401
402
|
def inline_bib(id)
|
402
403
|
%Q(#{@chapter.bibpaper(id).number} )
|
403
404
|
rescue KeyError
|
404
|
-
|
405
|
+
app_error "unknown bib: #{id}"
|
405
406
|
end
|
406
407
|
|
407
408
|
def inline_hd_chap(chap, id)
|
@@ -412,7 +413,7 @@ module ReVIEW
|
|
412
413
|
I18n.t('hd_quote_without_number', compile_inline(chap.headline(id).caption))
|
413
414
|
end
|
414
415
|
rescue KeyError
|
415
|
-
|
416
|
+
app_error "unknown headline: #{id}"
|
416
417
|
end
|
417
418
|
|
418
419
|
def noindent
|
@@ -680,7 +681,7 @@ module ReVIEW
|
|
680
681
|
if @book.config['chapref']
|
681
682
|
chs2 = @book.config['chapref'].split(',')
|
682
683
|
if chs2.size != 3
|
683
|
-
|
684
|
+
app_error '--chapsplitter must have exactly 3 parameters with comma.'
|
684
685
|
end
|
685
686
|
chs = chs2
|
686
687
|
end
|
@@ -694,7 +695,7 @@ module ReVIEW
|
|
694
695
|
end
|
695
696
|
end
|
696
697
|
rescue KeyError
|
697
|
-
|
698
|
+
app_error "unknown chapter: #{id}"
|
698
699
|
end
|
699
700
|
|
700
701
|
def source(lines, caption = nil, _lang = nil)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Copyright (c) 2010-2021 Minero Aoki, Kenshi Muto
|
2
|
+
#
|
3
|
+
# This program is free software.
|
4
|
+
# You can distribute or modify this program under the terms of
|
5
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
6
|
+
# For details of the GNU LGPL, see the file "COPYING".
|
7
|
+
#
|
8
|
+
|
9
|
+
module ReVIEW
|
10
|
+
class Preprocessor
|
11
|
+
class Directive
|
12
|
+
def initialize(op, args, opts)
|
13
|
+
@op = op
|
14
|
+
@args = args
|
15
|
+
@opts = opts
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :op
|
19
|
+
attr_reader :args
|
20
|
+
attr_reader :opts
|
21
|
+
|
22
|
+
def arg
|
23
|
+
@args.first
|
24
|
+
end
|
25
|
+
|
26
|
+
def opt
|
27
|
+
@opts.first
|
28
|
+
end
|
29
|
+
|
30
|
+
def [](key)
|
31
|
+
@opts[key]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Copyright (c) 2010-2021 Minero Aoki, Kenshi Muto
|
2
|
+
#
|
3
|
+
# This program is free software.
|
4
|
+
# You can distribute or modify this program under the terms of
|
5
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
6
|
+
# For details of the GNU LGPL, see the file "COPYING".
|
7
|
+
#
|
8
|
+
|
9
|
+
module ReVIEW
|
10
|
+
class Preprocessor
|
11
|
+
class Line
|
12
|
+
def initialize(number, string)
|
13
|
+
@number = number
|
14
|
+
@string = string
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :number
|
18
|
+
attr_reader :string
|
19
|
+
alias_method :to_s, :string
|
20
|
+
|
21
|
+
def edit
|
22
|
+
self.class.new(@number, yield(@string))
|
23
|
+
end
|
24
|
+
|
25
|
+
def empty?
|
26
|
+
@string.strip.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
def num_indent
|
30
|
+
@string.slice(/\A\s*/).size
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|