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
data/lib/review/htmlutils.rb
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
|
10
10
|
begin
|
11
11
|
require 'cgi/escape'
|
12
|
-
rescue
|
12
|
+
rescue StandardError
|
13
13
|
require 'cgi/util'
|
14
14
|
end
|
15
15
|
|
@@ -60,13 +60,13 @@ module ReVIEW
|
|
60
60
|
def highlight_pygments(ops)
|
61
61
|
body = ops[:body] || ''
|
62
62
|
format = ops[:format] || ''
|
63
|
-
if ops[:lexer].present?
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
63
|
+
lexer = if ops[:lexer].present?
|
64
|
+
ops[:lexer]
|
65
|
+
elsif @book.config['highlight'] && @book.config['highlight']['lang']
|
66
|
+
@book.config['highlight']['lang'] # default setting
|
67
|
+
else
|
68
|
+
'text'
|
69
|
+
end
|
70
70
|
options = { nowrap: true, noclasses: true }
|
71
71
|
if ops[:linenum]
|
72
72
|
options[:nowrap] = false
|
@@ -93,13 +93,13 @@ module ReVIEW
|
|
93
93
|
|
94
94
|
def highlight_rouge(ops)
|
95
95
|
body = ops[:body] || ''
|
96
|
-
if ops[:lexer].present?
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
96
|
+
lexer = if ops[:lexer].present?
|
97
|
+
ops[:lexer]
|
98
|
+
elsif @book.config['highlight'] && @book.config['highlight']['lang']
|
99
|
+
@book.config['highlight']['lang'] # default setting
|
100
|
+
else
|
101
|
+
'text'
|
102
|
+
end
|
103
103
|
# format = ops[:format] || ''
|
104
104
|
|
105
105
|
first_line_num = 1 ## default
|
@@ -129,9 +129,9 @@ module ReVIEW
|
|
129
129
|
end
|
130
130
|
|
131
131
|
def normalize_id(id)
|
132
|
-
if
|
132
|
+
if /\A[a-z][a-z0-9_.-]*\Z/i.match?(id)
|
133
133
|
id
|
134
|
-
elsif
|
134
|
+
elsif /\A[0-9_.-][a-z0-9_.-]*\Z/i.match?(id)
|
135
135
|
"id_#{id}" # dummy prefix
|
136
136
|
else
|
137
137
|
"id_#{CGI.escape(id.gsub('_', '__')).tr('%', '_').tr('+', '-')}" # escape all
|
data/lib/review/i18n.rb
CHANGED
@@ -75,11 +75,11 @@ module ReVIEW
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def load_file(path)
|
78
|
-
@store =
|
78
|
+
@store = YAMLLoader.safe_load_file(path)
|
79
79
|
end
|
80
80
|
|
81
81
|
def update_localefile(path)
|
82
|
-
user_i18n =
|
82
|
+
user_i18n = YAMLLoader.safe_load_file(path)
|
83
83
|
locale = user_i18n['locale']
|
84
84
|
if locale
|
85
85
|
user_i18n.delete('locale')
|
@@ -171,7 +171,7 @@ module ReVIEW
|
|
171
171
|
args_matched = (frmt.count('%') <= args.size)
|
172
172
|
frmt.gsub!('##', '%%')
|
173
173
|
args_matched ? (frmt % args) : frmt
|
174
|
-
rescue
|
174
|
+
rescue StandardError
|
175
175
|
str
|
176
176
|
end
|
177
177
|
end
|
data/lib/review/i18n.yml
CHANGED
@@ -32,6 +32,8 @@ ja:
|
|
32
32
|
html_footnote_refmark: "*%s"
|
33
33
|
html_footnote_textmark: "[*%s] "
|
34
34
|
html_footnote_backmark: "⏎"
|
35
|
+
html_endnote_refmark: "(%s)"
|
36
|
+
html_endnote_textmark: "(%s) "
|
35
37
|
aut: "著 者"
|
36
38
|
csl: "監 修"
|
37
39
|
dsr: "デザイン"
|
@@ -120,6 +122,8 @@ en:
|
|
120
122
|
html_footnote_refmark: "*%s"
|
121
123
|
html_footnote_textmark: "[*%s] "
|
122
124
|
html_footnote_backmark: "⏎"
|
125
|
+
html_endnote_refmark: "(%s)"
|
126
|
+
html_endnote_textmark: "(%s) "
|
123
127
|
aut: "Author"
|
124
128
|
csl: "Consultant"
|
125
129
|
dsr: "Design"
|
@@ -188,6 +192,8 @@ zh-TW:
|
|
188
192
|
html_footnote_refmark: "*%s"
|
189
193
|
html_footnote_textmark: "[*%s] "
|
190
194
|
html_footnote_backmark: "⏎"
|
195
|
+
html_endnote_refmark: "(%s)"
|
196
|
+
html_endnote_textmark: "(%s) "
|
191
197
|
aut: "著作人"
|
192
198
|
csl: "監 修"
|
193
199
|
dsr: "美術編輯"
|
data/lib/review/idgxmlbuilder.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2008-
|
1
|
+
# Copyright (c) 2008-2022 Minero Aoki, Kenshi Muto
|
2
2
|
# 2002-2007 Minero Aoki
|
3
3
|
#
|
4
4
|
# This program is free software.
|
@@ -47,6 +47,7 @@ module ReVIEW
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def builder_init_file
|
50
|
+
super
|
50
51
|
@warns = []
|
51
52
|
@errors = []
|
52
53
|
@section = 0
|
@@ -77,13 +78,15 @@ module ReVIEW
|
|
77
78
|
end
|
78
79
|
|
79
80
|
def result
|
81
|
+
check_printendnotes
|
82
|
+
|
80
83
|
s = ''
|
81
84
|
if @secttags
|
82
85
|
s += '</sect4>' if @subsubsubsection > 0
|
83
86
|
s += '</sect3>' if @subsubsection > 0
|
84
87
|
s += '</sect2>' if @subsection > 0
|
85
88
|
s += '</sect>' if @section > 0
|
86
|
-
s += '</chapter>'
|
89
|
+
s += '</chapter>'
|
87
90
|
end
|
88
91
|
solve_nest(@output.string) + s + "</#{@rootelement}>\n"
|
89
92
|
end
|
@@ -200,7 +203,7 @@ module ReVIEW
|
|
200
203
|
|
201
204
|
def ol_begin
|
202
205
|
puts '<ol>'
|
203
|
-
@ol_num ||= 1
|
206
|
+
@ol_num ||= 1 # rubocop:disable Naming/MemoizedInstanceVariableName
|
204
207
|
end
|
205
208
|
|
206
209
|
def ol_item(lines, num)
|
@@ -265,7 +268,7 @@ module ReVIEW
|
|
265
268
|
I18n.t('column', compile_inline(chapter.column(id).caption))
|
266
269
|
end
|
267
270
|
rescue KeyError
|
268
|
-
|
271
|
+
app_error "unknown column: #{id}"
|
269
272
|
end
|
270
273
|
|
271
274
|
def inline_list(id)
|
@@ -436,7 +439,7 @@ module ReVIEW
|
|
436
439
|
print '</pre>'
|
437
440
|
image_header(id, caption) unless caption_top?('image')
|
438
441
|
puts '</img>'
|
439
|
-
warn "image not bound: #{id}"
|
442
|
+
warn "image not bound: #{id}", location: location
|
440
443
|
end
|
441
444
|
|
442
445
|
def image_header(id, caption)
|
@@ -454,11 +457,11 @@ module ReVIEW
|
|
454
457
|
caption_str = nil
|
455
458
|
if id
|
456
459
|
puts '<equationblock>'
|
457
|
-
if get_chap.nil?
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
460
|
+
caption_str = if get_chap.nil?
|
461
|
+
%Q(<caption>#{I18n.t('equation')}#{I18n.t('format_number_without_chapter', [@chapter.equation(id).number])}#{I18n.t('caption_prefix_idgxml')}#{compile_inline(caption)}</caption>)
|
462
|
+
else
|
463
|
+
%Q(<caption>#{I18n.t('equation')}#{I18n.t('format_number', [get_chap, @chapter.equation(id).number])}#{I18n.t('caption_prefix_idgxml')}#{compile_inline(caption)}</caption>)
|
464
|
+
end
|
462
465
|
puts caption_str if caption_top?('equation')
|
463
466
|
end
|
464
467
|
|
@@ -477,7 +480,7 @@ module ReVIEW
|
|
477
480
|
def table(lines, id = nil, caption = nil)
|
478
481
|
@tablewidth = nil
|
479
482
|
if @book.config['tableopt']
|
480
|
-
@tablewidth = @book.config['tableopt'].split(',')[0].to_f / @book.config['pt_to_mm_unit'].to_f
|
483
|
+
@tablewidth = @book.config['tableopt'].split(',')[0].to_f / @book.config['pt_to_mm_unit'].to_f # rubocop:disable Style/FloatDivision
|
481
484
|
end
|
482
485
|
@col = 0
|
483
486
|
|
@@ -502,7 +505,7 @@ module ReVIEW
|
|
502
505
|
table_header(id, caption)
|
503
506
|
end
|
504
507
|
rescue KeyError
|
505
|
-
|
508
|
+
app_error "no such table: #{id}"
|
506
509
|
end
|
507
510
|
puts '</table>'
|
508
511
|
@tsize = nil
|
@@ -512,7 +515,7 @@ module ReVIEW
|
|
512
515
|
sepidx = nil
|
513
516
|
rows = []
|
514
517
|
lines.each_with_index do |line, idx|
|
515
|
-
if /\A[=\-]{12}
|
518
|
+
if /\A[=\-]{12}/.match?(line)
|
516
519
|
sepidx ||= idx
|
517
520
|
next
|
518
521
|
end
|
@@ -524,7 +527,7 @@ module ReVIEW
|
|
524
527
|
col2 = rows[rows.length - 1].split(table_row_separator_regexp).length
|
525
528
|
@col = col2 if col2 > @col
|
526
529
|
end
|
527
|
-
|
530
|
+
app_error 'no rows in the table' if rows.empty?
|
528
531
|
[sepidx, rows]
|
529
532
|
end
|
530
533
|
|
@@ -537,13 +540,13 @@ module ReVIEW
|
|
537
540
|
cellwidth = @tsize.split(/\s*,\s*/)
|
538
541
|
totallength = 0
|
539
542
|
cellwidth.size.times do |n|
|
540
|
-
cellwidth[n] = cellwidth[n].to_f / @book.config['pt_to_mm_unit'].to_f
|
543
|
+
cellwidth[n] = cellwidth[n].to_f / @book.config['pt_to_mm_unit'].to_f # rubocop:disable Style/FloatDivision
|
541
544
|
totallength += cellwidth[n]
|
542
|
-
warn "total length exceeds limit for table: #{@table_id}" if totallength > @tablewidth
|
545
|
+
warn "total length exceeds limit for table: #{@table_id}", location: location if totallength > @tablewidth
|
543
546
|
end
|
544
547
|
if cellwidth.size < @col
|
545
548
|
cw = (@tablewidth - totallength) / (@col - cellwidth.size)
|
546
|
-
warn "auto cell sizing exceeds limit for table: #{@table_id}" if cw <= 0
|
549
|
+
warn "auto cell sizing exceeds limit for table: #{@table_id}", location: location if cw <= 0
|
547
550
|
(cellwidth.size..(@col - 1)).each { |i| cellwidth[i] = cw }
|
548
551
|
end
|
549
552
|
end
|
@@ -627,7 +630,7 @@ module ReVIEW
|
|
627
630
|
end
|
628
631
|
puts '</table>'
|
629
632
|
else
|
630
|
-
warn "image not bound: #{id}" if @strict
|
633
|
+
warn "image not bound: #{id}", location: location if @strict
|
631
634
|
image_dummy(id, caption, lines)
|
632
635
|
end
|
633
636
|
end
|
@@ -656,7 +659,25 @@ module ReVIEW
|
|
656
659
|
def inline_fn(id)
|
657
660
|
%Q(<footnote>#{compile_inline(@chapter.footnote(id).content.strip)}</footnote>)
|
658
661
|
rescue KeyError
|
659
|
-
|
662
|
+
app_error "unknown footnote: #{id}"
|
663
|
+
end
|
664
|
+
|
665
|
+
def inline_endnote(id)
|
666
|
+
%Q(<span type='endnoteref' idref='endnoteb-#{normalize_id(id)}'>(#{@chapter.endnote(id).number})</span>)
|
667
|
+
rescue KeyError
|
668
|
+
app_error "unknown endnote: #{id}"
|
669
|
+
end
|
670
|
+
|
671
|
+
def endnote_begin
|
672
|
+
puts '<endnotes>'
|
673
|
+
end
|
674
|
+
|
675
|
+
def endnote_end
|
676
|
+
puts '</endnotes>'
|
677
|
+
end
|
678
|
+
|
679
|
+
def endnote_item(id)
|
680
|
+
puts %Q(<endnote id='endnoteb-#{normalize_id(id)}'><span type='endnotenumber'>(#{@chapter.endnote(id).number})</span>\t#{compile_inline(@chapter.endnote(id).content)}</endnote>)
|
660
681
|
end
|
661
682
|
|
662
683
|
def compile_ruby(base, ruby)
|
@@ -666,8 +687,9 @@ module ReVIEW
|
|
666
687
|
def compile_kw(word, alt)
|
667
688
|
'<keyword>' +
|
668
689
|
if alt
|
669
|
-
|
670
|
-
else
|
690
|
+
escape("#{word}(#{alt.strip})")
|
691
|
+
else
|
692
|
+
escape(word)
|
671
693
|
end +
|
672
694
|
'</keyword>' +
|
673
695
|
%Q(<index value="#{escape(word)}" />) +
|
@@ -703,22 +725,22 @@ module ReVIEW
|
|
703
725
|
end
|
704
726
|
|
705
727
|
def inline_maru(str)
|
706
|
-
if
|
728
|
+
if /\A\d+\Z/.match?(str)
|
707
729
|
sprintf('&#x%x;', 9311 + str.to_i)
|
708
|
-
elsif
|
730
|
+
elsif /\A[A-Z]\Z/.match?(str)
|
709
731
|
begin
|
710
732
|
sprintf('&#x%x;', 9398 + str.codepoints.to_a[0] - 65)
|
711
733
|
rescue NoMethodError
|
712
734
|
sprintf('&#x%x;', 9398 + str[0] - 65)
|
713
735
|
end
|
714
|
-
elsif
|
736
|
+
elsif /\A[a-z]\Z/.match?(str)
|
715
737
|
begin
|
716
738
|
sprintf('&#x%x;', 9392 + str.codepoints.to_a[0] - 65)
|
717
739
|
rescue NoMethodError
|
718
740
|
sprintf('&#x%x;', 9392 + str[0] - 65)
|
719
741
|
end
|
720
742
|
else
|
721
|
-
|
743
|
+
app_error "can't parse maru: #{str}"
|
722
744
|
end
|
723
745
|
end
|
724
746
|
|
@@ -779,8 +801,8 @@ module ReVIEW
|
|
779
801
|
def inline_icon(id)
|
780
802
|
begin
|
781
803
|
%Q(<Image href="file://#{@chapter.image(id).path.sub(%r{\A\./}, '')}" type="inline" />)
|
782
|
-
rescue
|
783
|
-
warn "image not bound: #{id}"
|
804
|
+
rescue StandardError
|
805
|
+
warn "image not bound: #{id}", location: location
|
784
806
|
''
|
785
807
|
end
|
786
808
|
end
|
@@ -1121,16 +1143,16 @@ module ReVIEW
|
|
1121
1143
|
def indepimage(_lines, id, caption = nil, metric = nil)
|
1122
1144
|
metrics = parse_metric('idgxml', metric)
|
1123
1145
|
puts '<img>'
|
1124
|
-
if caption_top?('image')
|
1125
|
-
puts %Q(<caption>#{compile_inline(caption)}</caption>)
|
1146
|
+
if caption_top?('image') && caption.present?
|
1147
|
+
puts %Q(<caption>#{compile_inline(caption)}</caption>)
|
1126
1148
|
end
|
1127
1149
|
begin
|
1128
1150
|
puts %Q(<Image href="file://#{@chapter.image(id).path.sub(%r{\A\./}, '')}"#{metrics} />)
|
1129
|
-
rescue
|
1130
|
-
warn %Q(image not bound: #{id})
|
1151
|
+
rescue StandardError
|
1152
|
+
warn %Q(image not bound: #{id}), location: location
|
1131
1153
|
end
|
1132
|
-
|
1133
|
-
puts %Q(<caption>#{compile_inline(caption)}</caption>)
|
1154
|
+
if !caption_top?('image') && caption.present?
|
1155
|
+
puts %Q(<caption>#{compile_inline(caption)}</caption>)
|
1134
1156
|
end
|
1135
1157
|
puts '</img>'
|
1136
1158
|
end
|
@@ -1188,7 +1210,7 @@ module ReVIEW
|
|
1188
1210
|
if chs2.size == 3
|
1189
1211
|
chs = chs2
|
1190
1212
|
else
|
1191
|
-
|
1213
|
+
app_error '--chapsplitter must have exactly 3 parameters with comma.'
|
1192
1214
|
end
|
1193
1215
|
end
|
1194
1216
|
s = "#{chs[0]}#{@book.chapter_index.number(id)}#{chs[1]}#{@book.chapter_index.title(id)}#{chs[2]}"
|
@@ -1206,7 +1228,7 @@ module ReVIEW
|
|
1206
1228
|
end
|
1207
1229
|
end
|
1208
1230
|
rescue KeyError
|
1209
|
-
|
1231
|
+
app_error "unknown chapter: #{id}"
|
1210
1232
|
end
|
1211
1233
|
|
1212
1234
|
def inline_chap(id)
|
@@ -1216,7 +1238,7 @@ module ReVIEW
|
|
1216
1238
|
@book.chapter_index.number(id)
|
1217
1239
|
end
|
1218
1240
|
rescue KeyError
|
1219
|
-
|
1241
|
+
app_error "unknown chapter: #{id}"
|
1220
1242
|
end
|
1221
1243
|
|
1222
1244
|
def inline_title(id)
|
@@ -1227,7 +1249,7 @@ module ReVIEW
|
|
1227
1249
|
title
|
1228
1250
|
end
|
1229
1251
|
rescue KeyError
|
1230
|
-
|
1252
|
+
app_error "unknown chapter: #{id}"
|
1231
1253
|
end
|
1232
1254
|
|
1233
1255
|
def source(lines, caption = nil, lang = nil)
|
@@ -1270,7 +1292,7 @@ module ReVIEW
|
|
1270
1292
|
def inline_bib(id)
|
1271
1293
|
%Q(<span type='bibref' idref='#{id}'>[#{@chapter.bibpaper(id).number}]</span>)
|
1272
1294
|
rescue KeyError
|
1273
|
-
|
1295
|
+
app_error "unknown bib: #{id}"
|
1274
1296
|
end
|
1275
1297
|
|
1276
1298
|
def inline_hd_chap(chap, id)
|
@@ -1281,7 +1303,7 @@ module ReVIEW
|
|
1281
1303
|
I18n.t('hd_quote_without_number', compile_inline(chap.headline(id).caption))
|
1282
1304
|
end
|
1283
1305
|
rescue KeyError
|
1284
|
-
|
1306
|
+
app_error "unknown headline: #{id}"
|
1285
1307
|
end
|
1286
1308
|
|
1287
1309
|
def inline_recipe(id)
|
data/lib/review/idgxmlmaker.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2019-
|
1
|
+
# Copyright (c) 2019-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
|
@@ -16,10 +16,12 @@ require 'review/yamlloader'
|
|
16
16
|
require 'review/idgxmlbuilder'
|
17
17
|
require 'review/version'
|
18
18
|
require 'review/makerhelper'
|
19
|
+
require 'review/loggable'
|
19
20
|
|
20
21
|
module ReVIEW
|
21
22
|
class IDGXMLMaker
|
22
23
|
include MakerHelper
|
24
|
+
include Loggable
|
23
25
|
|
24
26
|
attr_accessor :config, :basedir
|
25
27
|
|
@@ -27,15 +29,7 @@ module ReVIEW
|
|
27
29
|
@basedir = nil
|
28
30
|
@logger = ReVIEW.logger
|
29
31
|
@plaintext = nil
|
30
|
-
|
31
|
-
|
32
|
-
def error(msg)
|
33
|
-
@logger.error "#{File.basename($PROGRAM_NAME, '.*')}: #{msg}"
|
34
|
-
exit 1
|
35
|
-
end
|
36
|
-
|
37
|
-
def warn(msg)
|
38
|
-
@logger.warn "#{File.basename($PROGRAM_NAME, '.*')}: #{msg}"
|
32
|
+
@compile_errors = nil
|
39
33
|
end
|
40
34
|
|
41
35
|
def self.execute(*args)
|
@@ -78,11 +72,15 @@ module ReVIEW
|
|
78
72
|
|
79
73
|
def execute(*args)
|
80
74
|
cmd_config, yamlfile = parse_opts(args)
|
81
|
-
error "#{yamlfile} not found." unless File.exist?(yamlfile)
|
75
|
+
error! "#{yamlfile} not found." unless File.exist?(yamlfile)
|
82
76
|
|
83
|
-
|
84
|
-
|
85
|
-
|
77
|
+
begin
|
78
|
+
@config = ReVIEW::Configure.create(maker: 'idgxmlmaker',
|
79
|
+
yamlfile: yamlfile,
|
80
|
+
config: cmd_config)
|
81
|
+
rescue ReVIEW::ConfigError => e
|
82
|
+
error! e.message
|
83
|
+
end
|
86
84
|
I18n.setup(@config['language'])
|
87
85
|
begin
|
88
86
|
generate_idgxml_files(yamlfile)
|
@@ -90,7 +88,7 @@ module ReVIEW
|
|
90
88
|
rescue ApplicationError => e
|
91
89
|
raise if @config['debug']
|
92
90
|
|
93
|
-
error
|
91
|
+
error! e.message
|
94
92
|
end
|
95
93
|
end
|
96
94
|
|
@@ -106,6 +104,10 @@ module ReVIEW
|
|
106
104
|
end
|
107
105
|
|
108
106
|
build_body(@path, yamlfile)
|
107
|
+
|
108
|
+
if @compile_errors
|
109
|
+
app_error 'compile error, No IDGXML file output.'
|
110
|
+
end
|
109
111
|
end
|
110
112
|
|
111
113
|
def apply_filter(xmlfile)
|
@@ -121,7 +123,7 @@ module ReVIEW
|
|
121
123
|
if s.success?
|
122
124
|
File.write(xmlfile, o) # override
|
123
125
|
end
|
124
|
-
rescue => e
|
126
|
+
rescue StandardError => e
|
125
127
|
warn("filter error for #{xmlfile}: #{e.message}")
|
126
128
|
end
|
127
129
|
end
|
@@ -161,13 +163,11 @@ module ReVIEW
|
|
161
163
|
end
|
162
164
|
|
163
165
|
def build_chap(chap, base_path, basetmpdir, ispart)
|
164
|
-
filename =
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
filename = Pathname.new(chap.path).relative_path_from(base_path).to_s
|
170
|
-
end
|
166
|
+
filename = if ispart.present?
|
167
|
+
chap.path
|
168
|
+
else
|
169
|
+
Pathname.new(chap.path).relative_path_from(base_path).to_s
|
170
|
+
end
|
171
171
|
id = File.basename(filename).sub(/\.re\Z/, '')
|
172
172
|
if @buildonly && !@buildonly.include?(id)
|
173
173
|
warn "skip #{id}.re"
|
@@ -179,9 +179,10 @@ module ReVIEW
|
|
179
179
|
begin
|
180
180
|
@converter.convert(filename, File.join(basetmpdir, xmlfile))
|
181
181
|
apply_filter(File.join(basetmpdir, xmlfile))
|
182
|
-
rescue => e
|
183
|
-
|
184
|
-
|
182
|
+
rescue StandardError => e
|
183
|
+
@compile_errors = true
|
184
|
+
error "compile error in #{filename} (#{e.class})"
|
185
|
+
error e.message
|
185
186
|
end
|
186
187
|
end
|
187
188
|
end
|
data/lib/review/img_math.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'shellwords'
|
3
|
+
require 'review/loggable'
|
3
4
|
|
4
5
|
module ReVIEW
|
5
6
|
class ImgMath
|
7
|
+
include Loggable
|
8
|
+
|
6
9
|
def initialize(config, path_name: '_review_math')
|
7
10
|
@config = config
|
8
11
|
@logger = ReVIEW.logger
|
@@ -50,7 +53,7 @@ module ReVIEW
|
|
50
53
|
cmd = "latex --interaction=nonstopmode --output-directory=#{tmpdir} #{tex_path} && dvipng -T tight -z9 -o #{img_path} #{dvi_path}"
|
51
54
|
out, status = Open3.capture2e(cmd)
|
52
55
|
unless status.success?
|
53
|
-
raise ApplicationError, "latex compile error\n\nError log:\n"
|
56
|
+
raise ApplicationError, "latex compile error\n\nError log:\n#{out}"
|
54
57
|
end
|
55
58
|
|
56
59
|
img_path
|
@@ -97,15 +100,14 @@ module ReVIEW
|
|
97
100
|
when 'dvipng'
|
98
101
|
make_math_images_dvipng(tmpdir, tex_path, math_real_dir)
|
99
102
|
else
|
100
|
-
error "unknown math converter error. imgmath_options/converter parameter should be 'pdfcrop' or 'dvipng'."
|
101
|
-
exit 1
|
103
|
+
error! "unknown math converter error. imgmath_options/converter parameter should be 'pdfcrop' or 'dvipng'."
|
102
104
|
end
|
103
105
|
rescue CompileError
|
104
106
|
FileUtils.cp([tex_path,
|
107
|
+
File.join(File.dirname(tex_path), '__IMGMATH_BODY__.tex'),
|
105
108
|
File.join(File.dirname(tex_path), '__IMGMATH__.log')],
|
106
109
|
math_real_dir)
|
107
|
-
error "LaTeX math compile error. See #{math_real_dir}/__IMGMATH__.log for details."
|
108
|
-
exit 1
|
110
|
+
error! "LaTeX math compile error. See #{math_real_dir}/__IMGMATH__.log for details."
|
109
111
|
end
|
110
112
|
end
|
111
113
|
@math_maps.clear
|
@@ -113,14 +115,6 @@ module ReVIEW
|
|
113
115
|
|
114
116
|
private
|
115
117
|
|
116
|
-
def error(msg)
|
117
|
-
@logger.error msg
|
118
|
-
end
|
119
|
-
|
120
|
-
def warn(msg)
|
121
|
-
@logger.warn msg
|
122
|
-
end
|
123
|
-
|
124
118
|
def default_imgmath_preamble
|
125
119
|
<<-EOB
|
126
120
|
\\documentclass[uplatex,a3paper,landscape]{jsarticle}
|
@@ -156,7 +150,7 @@ module ReVIEW
|
|
156
150
|
if File.exist?(dvi_path)
|
157
151
|
out, status = Open3.capture2e(*[@config['dvicommand'], @config['dvioptions'].shellsplit, dvi_path].flatten.compact)
|
158
152
|
if !status.success? || !File.exist?(pdf_path)
|
159
|
-
|
153
|
+
@logger.error "error in #{@config['dvicommand']}. Error log:\n#{out}"
|
160
154
|
raise CompileError
|
161
155
|
end
|
162
156
|
end
|
@@ -167,7 +161,7 @@ module ReVIEW
|
|
167
161
|
end
|
168
162
|
out, status = Open3.capture2e(*args)
|
169
163
|
unless status.success?
|
170
|
-
|
164
|
+
@logger.error "error in pdfcrop. Error log:\n#{out}"
|
171
165
|
raise CompileError
|
172
166
|
end
|
173
167
|
pdf_path = '__IMGMATH__pdfcrop.pdf'
|
@@ -192,7 +186,7 @@ module ReVIEW
|
|
192
186
|
end
|
193
187
|
out, status = Open3.capture2e(*args)
|
194
188
|
unless status.success?
|
195
|
-
|
189
|
+
@logger.error "error in pdf extracting. Error log:\n#{out}"
|
196
190
|
raise CompileError
|
197
191
|
end
|
198
192
|
|
@@ -209,7 +203,7 @@ module ReVIEW
|
|
209
203
|
end
|
210
204
|
out, status = Open3.capture2e(*args)
|
211
205
|
unless status.success?
|
212
|
-
|
206
|
+
@logger.error "error in pdf pixelizing. Error log:\n#{out}"
|
213
207
|
raise CompileError
|
214
208
|
end
|
215
209
|
end
|
@@ -235,7 +229,7 @@ module ReVIEW
|
|
235
229
|
end
|
236
230
|
out, status = Open3.capture2e(*args)
|
237
231
|
unless status.success?
|
238
|
-
|
232
|
+
@logger.error "error in dvipng. Error log:\n#{out}"
|
239
233
|
raise CompileError
|
240
234
|
end
|
241
235
|
end
|