review 4.0.0 → 5.1.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/ruby-tex.yml +31 -0
- data/.github/workflows/ruby-win.yml +45 -0
- data/.github/workflows/ruby.yml +27 -0
- data/.rubocop.yml +141 -38
- data/Dockerfile +21 -5
- data/NEWS.ja.md +338 -1
- data/NEWS.md +339 -2
- data/README.md +11 -7
- data/Rakefile +7 -2
- data/appveyor.yml +0 -20
- data/bin/review +2 -4
- data/bin/review-catalog-converter +4 -4
- data/bin/review-check +8 -12
- data/bin/review-checkdep +2 -5
- data/bin/review-compile +11 -20
- data/bin/review-epub2html +1 -4
- data/bin/review-epubmaker +3 -4
- data/bin/review-idgxmlmaker +1 -3
- data/bin/review-index +5 -86
- data/bin/review-init +1 -4
- data/bin/review-pdfmaker +1 -3
- data/bin/review-preproc +3 -5
- data/bin/review-textmaker +1 -3
- data/bin/review-update +1 -4
- data/bin/review-validate +5 -5
- data/bin/review-vol +5 -82
- data/bin/review-webmaker +1 -3
- data/doc/config.yml.sample +55 -12
- data/doc/config.yml.sample-simple +4 -3
- data/doc/format.ja.md +119 -17
- data/doc/format.md +106 -17
- data/doc/makeindex.ja.md +2 -2
- data/doc/pdfmaker.ja.md +42 -0
- data/doc/pdfmaker.md +41 -0
- data/doc/quickstart.ja.md +55 -25
- data/doc/quickstart.md +47 -17
- data/lib/review.rb +1 -1
- data/lib/review/book.rb +2 -2
- data/lib/review/book/base.rb +69 -30
- data/lib/review/book/bib.rb +21 -0
- data/lib/review/book/book_unit.rb +158 -0
- data/lib/review/book/chapter.rb +33 -26
- data/lib/review/book/index.rb +39 -206
- data/lib/review/book/index/item.rb +8 -2
- data/lib/review/book/page_metric.rb +7 -7
- data/lib/review/book/part.rb +26 -11
- data/lib/review/book/volume.rb +5 -5
- data/lib/review/builder.rb +124 -27
- data/lib/review/call_hook.rb +20 -0
- data/lib/review/catalog.rb +3 -2
- data/lib/review/compiler.rb +197 -91
- data/lib/review/configure.rb +95 -9
- data/lib/review/converter.rb +1 -1
- data/lib/review/epub2html.rb +6 -1
- data/lib/review/epubmaker.rb +116 -117
- data/lib/review/epubmaker/content.rb +113 -0
- data/lib/review/epubmaker/epubcommon.rb +372 -0
- data/lib/review/epubmaker/epubv2.rb +178 -0
- data/lib/review/epubmaker/epubv3.rb +231 -0
- data/lib/review/epubmaker/producer.rb +168 -0
- data/lib/review/epubmaker/reviewheaderlistener.rb +12 -2
- data/lib/review/epubmaker/zip_exporter.rb +84 -0
- data/lib/review/exception.rb +6 -0
- data/lib/review/extentions/string.rb +0 -4
- data/lib/review/htmlbuilder.rb +132 -87
- data/lib/review/htmlutils.rb +8 -11
- data/lib/review/i18n.rb +2 -1
- data/lib/review/idgxmlbuilder.rb +156 -76
- data/lib/review/idgxmlmaker.rb +22 -18
- data/lib/review/img_math.rb +245 -0
- data/lib/review/index_builder.rb +654 -0
- data/lib/review/init.rb +17 -18
- data/lib/review/latexbox.rb +58 -0
- data/lib/review/latexbuilder.rb +173 -43
- data/lib/review/latexutils.rb +9 -1
- data/lib/review/lineinput.rb +112 -2
- data/lib/review/logger.rb +42 -3
- data/lib/review/makerhelper.rb +12 -187
- data/lib/review/markdownbuilder.rb +51 -2
- data/lib/review/pdfmaker.rb +78 -73
- data/lib/review/plaintextbuilder.rb +98 -14
- data/lib/review/preprocessor.rb +18 -12
- data/lib/review/rstbuilder.rb +28 -9
- data/lib/review/sec_counter.rb +14 -0
- data/lib/review/template.rb +6 -0
- data/lib/review/textmaker.rb +21 -19
- data/lib/review/textutils.rb +3 -12
- data/lib/review/tocprinter.rb +242 -97
- data/lib/review/topbuilder.rb +91 -24
- data/lib/review/update.rb +12 -13
- data/lib/review/version.rb +1 -1
- data/lib/review/volumeprinter.rb +97 -0
- data/lib/review/webmaker.rb +34 -33
- data/lib/review/webtocprinter.rb +39 -35
- data/lib/review/yamlloader.rb +2 -1
- data/review.gemspec +5 -3
- data/samples/sample-book/src/.gitignore +1 -0
- data/samples/sample-book/src/config-ebook.yml +4 -0
- data/samples/sample-book/src/config-epub2.yml +1 -1
- data/samples/sample-book/src/config-jlreq-ebook.yml +4 -0
- data/samples/sample-book/src/config.yml +3 -3
- data/samples/sample-book/src/lib/tasks/review.rake +26 -6
- data/samples/syntax-book/Gemfile +1 -1
- data/samples/syntax-book/ch01.re +3 -1
- data/samples/syntax-book/ch02.re +28 -21
- data/samples/syntax-book/ch03.re +1 -1
- data/samples/syntax-book/config-jlreq-lualatex.yml +4 -0
- data/samples/syntax-book/config-print.yml +3 -0
- data/samples/syntax-book/config.yml +1 -1
- data/samples/syntax-book/images/img3-2.png +0 -0
- data/samples/syntax-book/lib/tasks/review.rake +23 -8
- data/templates/html/_colophon.html.erb +23 -0
- data/templates/html/_colophon_history.html.erb +9 -0
- data/templates/html/_cover.html.erb +10 -0
- data/templates/html/_part_body.html.erb +6 -0
- data/templates/html/_titlepage.html.erb +20 -0
- data/templates/html/layout-html5.html.erb +6 -0
- data/templates/html/layout-xhtml1.html.erb +6 -0
- data/templates/latex/config.erb +41 -29
- data/templates/latex/review-jlreq/README.md +3 -1
- data/templates/latex/review-jlreq/review-base.sty +47 -22
- data/templates/latex/review-jlreq/review-jlreq.cls +25 -24
- data/templates/latex/review-jlreq/review-style.sty +6 -1
- data/templates/latex/review-jlreq/review-tcbox.sty +348 -0
- data/templates/latex/review-jlreq/reviewmacro.sty +5 -0
- data/templates/latex/review-jsbook/README.md +7 -5
- data/templates/latex/review-jsbook/review-base.sty +47 -21
- data/templates/latex/review-jsbook/review-jsbook.cls +12 -2
- data/templates/latex/review-jsbook/review-style.sty +6 -1
- data/templates/latex/review-jsbook/review-tcbox.sty +348 -0
- data/templates/latex/review-jsbook/reviewmacro.sty +5 -0
- data/templates/opf/epubv2.opf.erb +7 -7
- data/templates/opf/epubv3.opf.erb +7 -7
- data/templates/opf/opf_manifest_epubv2.opf.erb +10 -0
- data/templates/opf/opf_manifest_epubv3.opf.erb +10 -0
- data/templates/opf/opf_metainfo_epubv2.opf.erb +17 -0
- data/templates/opf/opf_metainfo_epubv3.opf.erb +49 -0
- data/templates/opf/opf_tocx_epubv2.opf.erb +9 -0
- data/templates/opf/opf_tocx_epubv3.opf.erb +17 -0
- data/templates/web/html/layout-html5.html.erb +9 -8
- data/templates/web/html/layout-xhtml1.html.erb +6 -0
- data/test/assets/header_listener.html +35 -0
- data/test/assets/img_math/img1.png +0 -0
- data/test/assets/img_math/img2.png +0 -0
- data/test/assets/img_math/img3.png +0 -0
- data/test/assets/syntax_book_index_detail.txt +58 -0
- data/test/assets/test_template.tex +12 -9
- data/test/assets/test_template_backmatter.tex +12 -9
- data/test/book_test_helper.rb +11 -5
- data/test/run_test.rb +1 -1
- data/test/test_book.rb +62 -63
- data/test/test_book_chapter.rb +99 -56
- data/test/test_book_part.rb +3 -3
- data/test/test_builder.rb +24 -15
- data/test/test_catalog.rb +1 -0
- data/test/test_catalog_converter_cmd.rb +1 -1
- data/test/test_converter.rb +1 -0
- data/test/test_epub3maker.rb +170 -126
- data/test/test_epubmaker.rb +249 -129
- data/test/test_epubmaker_cmd.rb +14 -7
- data/test/test_helper.rb +23 -11
- data/test/test_htmlbuilder.rb +956 -76
- data/test/test_htmlutils.rb +0 -12
- data/test/test_i18n.rb +33 -33
- data/test/test_idgxmlbuilder.rb +568 -10
- data/test/test_idgxmlmaker_cmd.rb +50 -0
- data/test/test_image_finder.rb +52 -70
- data/test/test_img_math.rb +111 -0
- data/test/test_index.rb +62 -52
- data/test/test_indexbuilder.rb +52 -0
- data/test/test_latexbuilder.rb +1056 -30
- data/test/test_latexbuilder_v2.rb +52 -12
- data/test/test_lineinput.rb +20 -93
- data/test/test_logger.rb +7 -7
- data/test/test_makerhelper.rb +0 -12
- data/test/test_markdownbuilder.rb +32 -0
- data/test/test_pdfmaker.rb +100 -11
- data/test/test_pdfmaker_cmd.rb +101 -7
- data/test/test_plaintextbuilder.rb +531 -25
- data/test/test_review_ext.rb +2 -1
- data/test/test_reviewheaderlistener.rb +49 -0
- data/test/test_rstbuilder.rb +25 -1
- data/test/test_sec_counter.rb +156 -0
- data/test/test_template.rb +12 -2
- data/test/test_textmaker_cmd.rb +58 -0
- data/test/test_tocprinter.rb +46 -0
- data/test/test_topbuilder.rb +365 -10
- data/test/test_update.rb +44 -44
- data/test/test_webtocprinter.rb +75 -43
- data/test/test_zip_exporter.rb +5 -6
- data/vendor/gentombow/LICENSE +1 -1
- data/vendor/gentombow/Makefile +0 -1
- data/vendor/gentombow/bounddvi-en.pdf +0 -0
- data/vendor/gentombow/bounddvi-en.tex +1 -0
- data/vendor/gentombow/bounddvi.pdf +0 -0
- data/vendor/gentombow/bounddvi.sty +30 -7
- data/vendor/gentombow/bounddvi.tex +1 -0
- data/vendor/gentombow/create_archive.sh +1 -0
- data/vendor/gentombow/gentombow-ja.pdf +0 -0
- data/vendor/gentombow/gentombow-ja.tex +9 -0
- data/vendor/gentombow/gentombow.pdf +0 -0
- data/vendor/gentombow/gentombow.sty +32 -10
- data/vendor/gentombow/gentombow.tex +8 -0
- data/vendor/gentombow/tests/gentombow-01-pdfx.tex +8 -0
- data/vendor/gentombow/tests/gentombow-02-pdfx.tex +8 -0
- data/vendor/jsclasses/LICENSE +1 -1
- data/vendor/jsclasses/Makefile +3 -2
- data/vendor/jsclasses/create_archive.sh +5 -5
- data/vendor/jsclasses/jis/Makefile +3 -2
- data/vendor/jsclasses/jis/jsarticle.cls +74 -31
- data/vendor/jsclasses/jis/jsbook.cls +74 -31
- data/vendor/jsclasses/jis/jsclasses.dtx +176 -36
- data/vendor/jsclasses/jis/jsclasses.ins +15 -5
- data/vendor/jsclasses/jis/jslogo.dtx +4 -4
- data/vendor/jsclasses/jis/jslogo.ins +9 -0
- data/vendor/jsclasses/jis/jslogo.sty +4 -16
- data/vendor/jsclasses/jis/jspf.cls +73 -30
- data/vendor/jsclasses/jis/jsreport.cls +74 -31
- data/vendor/jsclasses/jis/jsverb.ins +9 -0
- data/vendor/jsclasses/jis/jsverb.sty +1 -13
- data/vendor/jsclasses/jis/kiyou.cls +74 -31
- data/vendor/jsclasses/jis/minijs.sty +65 -22
- data/vendor/jsclasses/jis/okumacro.dtx +4 -5
- data/vendor/jsclasses/jis/okumacro.ins +9 -0
- data/vendor/jsclasses/jis/okumacro.sty +4 -17
- data/vendor/jsclasses/jis/okuverb.ins +9 -0
- data/vendor/jsclasses/jis/okuverb.sty +1 -13
- data/vendor/jsclasses/jis/winjis.sty +23 -19
- data/vendor/jsclasses/jsarticle.cls +74 -31
- data/vendor/jsclasses/jsbook.cls +74 -31
- data/vendor/jsclasses/jsclasses.dtx +176 -36
- data/vendor/jsclasses/jsclasses.ins +15 -5
- data/vendor/jsclasses/jsclasses.pdf +0 -0
- data/vendor/jsclasses/jslogo.dtx +4 -4
- data/vendor/jsclasses/jslogo.ins +9 -0
- data/vendor/jsclasses/jslogo.pdf +0 -0
- data/vendor/jsclasses/jslogo.sty +4 -16
- data/vendor/jsclasses/jspf.cls +73 -30
- data/vendor/jsclasses/jsreport.cls +74 -31
- data/vendor/jsclasses/jsverb.ins +9 -0
- data/vendor/jsclasses/jsverb.pdf +0 -0
- data/vendor/jsclasses/jsverb.sty +1 -13
- data/vendor/jsclasses/kiyou.cls +74 -31
- data/vendor/jsclasses/minijs.sty +68 -22
- data/vendor/jsclasses/okumacro.dtx +4 -5
- data/vendor/jsclasses/okumacro.ins +9 -0
- data/vendor/jsclasses/okumacro.pdf +0 -0
- data/vendor/jsclasses/okumacro.sty +4 -17
- data/vendor/jsclasses/okuverb.ins +9 -0
- data/vendor/jsclasses/okuverb.pdf +0 -0
- data/vendor/jsclasses/okuverb.sty +1 -13
- data/vendor/jsclasses/tests/relfont.tex +10 -0
- data/vendor/jsclasses/winjis.sty +23 -19
- metadata +109 -20
- data/.rubocop_todo.yml +0 -7
- data/lib/epubmaker.rb +0 -23
- data/lib/epubmaker/content.rb +0 -110
- data/lib/epubmaker/epubcommon.rb +0 -441
- data/lib/epubmaker/epubv2.rb +0 -143
- data/lib/epubmaker/epubv3.rb +0 -233
- data/lib/epubmaker/producer.rb +0 -375
- data/lib/epubmaker/zip_exporter.rb +0 -81
- data/lib/lineinput.rb +0 -155
- data/lib/review/book/compilable.rb +0 -178
- data/lib/review/tocparser.rb +0 -271
- data/samples/syntax-book/review-ext.rb +0 -14
- data/test/test_tocparser.rb +0 -25
@@ -7,6 +7,15 @@
|
|
7
7
|
#
|
8
8
|
module ReVIEW
|
9
9
|
class EPUBMaker
|
10
|
+
# Listener class to scan HTML and get heading information
|
11
|
+
#
|
12
|
+
# The heading information this listener will retrieve is as follows:
|
13
|
+
#
|
14
|
+
# * level: Heading level (1..6)
|
15
|
+
# * id: HTMl ID attribute. Basically the `id` attribute of the h(1-6) element, but if there is an `a` element within the h(1-6) element, it will be its `id` attribute.
|
16
|
+
# * title: The title string of the headline. Usually, it is the text within the h(1-6) element, but if there is an `img` element, it will be the text with its `alt` attribute.
|
17
|
+
# * notoc: The `notoc` attribute of the headline element.
|
18
|
+
#
|
10
19
|
class ReVIEWHeaderListener
|
11
20
|
include REXML::StreamListener
|
12
21
|
def initialize(headlines)
|
@@ -18,10 +27,11 @@ module ReVIEW
|
|
18
27
|
def tag_start(name, attrs)
|
19
28
|
if name =~ /\Ah(\d+)/
|
20
29
|
raise "#{name}, #{attrs}" if @level.present?
|
30
|
+
|
21
31
|
@level = $1.to_i
|
22
32
|
@id = attrs['id'] if attrs['id'].present?
|
23
33
|
@notoc = attrs['notoc'] if attrs['notoc'].present?
|
24
|
-
elsif
|
34
|
+
elsif @level.present? # if in <hN> tag
|
25
35
|
if name == 'img' && attrs['alt'].present?
|
26
36
|
@content << attrs['alt']
|
27
37
|
elsif name == 'a' && attrs['id'].present?
|
@@ -49,7 +59,7 @@ module ReVIEW
|
|
49
59
|
|
50
60
|
def text(text)
|
51
61
|
if @level.present?
|
52
|
-
@content << text.
|
62
|
+
@content << text.tr("\t", ' ')
|
53
63
|
end
|
54
64
|
end
|
55
65
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Copyright (c) 2010-2017 Kenshi Muto and Masayoshi Takahashi
|
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
|
+
require 'pathname'
|
10
|
+
begin
|
11
|
+
require 'zip'
|
12
|
+
rescue LoadError
|
13
|
+
## I cannot find rubyzip library, so I use external zip command.
|
14
|
+
warn 'rubyzip not found, so use external zip command'
|
15
|
+
end
|
16
|
+
|
17
|
+
module ReVIEW
|
18
|
+
class EPUBMaker
|
19
|
+
##
|
20
|
+
# Export into zip file for EPUB producer.
|
21
|
+
#
|
22
|
+
class ZipExporter
|
23
|
+
attr_reader :tmpdir
|
24
|
+
|
25
|
+
def initialize(tmpdir, config)
|
26
|
+
@tmpdir = tmpdir
|
27
|
+
@config = config
|
28
|
+
end
|
29
|
+
|
30
|
+
def export_zip(epubfile)
|
31
|
+
if defined?(Zip)
|
32
|
+
export_zip_rubyzip(epubfile)
|
33
|
+
else
|
34
|
+
export_zip_extcmd(epubfile)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def export_zip_extcmd(epubfile)
|
39
|
+
stage1 = @config['epubmaker']['zip_stage1'].to_s.split
|
40
|
+
path1 = stage1[0] || 'zip'
|
41
|
+
opt1 = stage1[1] || '-0Xq'
|
42
|
+
stage2 = @config['epubmaker']['zip_stage2'].to_s.split
|
43
|
+
path2 = stage2[0] || 'zip'
|
44
|
+
opt2 = stage2[1] || '-Xr9Dq'
|
45
|
+
|
46
|
+
Dir.chdir(tmpdir) do
|
47
|
+
system(path1, opt1, epubfile, 'mimetype')
|
48
|
+
addpath = @config['epubmaker']['zip_addpath']
|
49
|
+
if addpath
|
50
|
+
system(path2, opt2, epubfile, 'META-INF', 'OEBPS', addpath)
|
51
|
+
else
|
52
|
+
system(path2, opt2, epubfile, 'META-INF', 'OEBPS')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def export_zip_rubyzip(epubfile)
|
58
|
+
Dir.chdir(tmpdir) do
|
59
|
+
Zip::OutputStream.open(epubfile) do |epub|
|
60
|
+
root_pathname = Pathname.new(tmpdir)
|
61
|
+
epub.put_next_entry('mimetype', nil, nil, Zip::Entry::STORED)
|
62
|
+
epub << 'application/epub+zip'
|
63
|
+
|
64
|
+
export_zip_rubyzip_addpath(epub, File.join(tmpdir, 'META-INF'), root_pathname)
|
65
|
+
export_zip_rubyzip_addpath(epub, File.join(tmpdir, 'OEBPS'), root_pathname)
|
66
|
+
if @config['zip_addpath'].present?
|
67
|
+
export_zip_rubyzip_addpath(epub, File.join(tmpdir, @config['zip_addpath']), root_pathname)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def export_zip_rubyzip_addpath(epub, dirname, rootdir)
|
74
|
+
Dir[File.join(dirname, '**', '**')].each do |path|
|
75
|
+
next if File.directory?(path)
|
76
|
+
|
77
|
+
relpath = Pathname.new(path).relative_path_from(rootdir)
|
78
|
+
epub.put_next_entry(relpath)
|
79
|
+
epub << File.binread(path)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/review/exception.rb
CHANGED
@@ -10,10 +10,16 @@
|
|
10
10
|
|
11
11
|
module ReVIEW
|
12
12
|
class Error < ::StandardError; end
|
13
|
+
|
13
14
|
class ApplicationError < Error; end
|
15
|
+
|
14
16
|
class ConfigError < ApplicationError; end
|
17
|
+
|
15
18
|
class CompileError < ApplicationError; end
|
19
|
+
|
16
20
|
class SyntaxError < CompileError; end
|
21
|
+
|
17
22
|
class FileNotFound < ApplicationError; end
|
23
|
+
|
18
24
|
class KeyError < CompileError; end
|
19
25
|
end
|
data/lib/review/htmlbuilder.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2008-
|
1
|
+
# Copyright (c) 2008-2020 Minero Aoki, Kenshi Muto, Masayoshi Takahashi,
|
2
2
|
# KADO Masanori
|
3
3
|
# 2002-2007 Minero Aoki
|
4
4
|
#
|
@@ -41,10 +41,6 @@ module ReVIEW
|
|
41
41
|
".#{@book.config['htmlext']}"
|
42
42
|
end
|
43
43
|
|
44
|
-
def builder_init
|
45
|
-
end
|
46
|
-
private :builder_init
|
47
|
-
|
48
44
|
def builder_init_file
|
49
45
|
@noindent = nil
|
50
46
|
@ol_num = nil
|
@@ -57,6 +53,7 @@ module ReVIEW
|
|
57
53
|
@first_line_num = nil
|
58
54
|
@body_ext = nil
|
59
55
|
@toc = nil
|
56
|
+
@javascripts = []
|
60
57
|
end
|
61
58
|
private :builder_init_file
|
62
59
|
|
@@ -78,6 +75,7 @@ module ReVIEW
|
|
78
75
|
if !File.exist?(layout_file) && File.exist?(File.join(@book.basedir, 'layouts', 'layout.erb'))
|
79
76
|
raise ReVIEW::ConfigError, 'layout.erb is obsoleted. Please use layout.html.erb.'
|
80
77
|
end
|
78
|
+
|
81
79
|
if File.exist?(layout_file)
|
82
80
|
if ENV['REVIEW_SAFE_MODE'].to_i & 4 > 0
|
83
81
|
warn %Q(user's layout is prohibited in safe mode. ignored.)
|
@@ -92,7 +90,7 @@ module ReVIEW
|
|
92
90
|
def result
|
93
91
|
# default XHTML header/footer
|
94
92
|
@title = strip_html(compile_inline(@chapter.title))
|
95
|
-
@body = @output.string
|
93
|
+
@body = solve_nest(@output.string)
|
96
94
|
@language = @book.config['language']
|
97
95
|
@stylesheets = @book.config['stylesheet']
|
98
96
|
@next = @chapter.next_chapter
|
@@ -104,9 +102,28 @@ module ReVIEW
|
|
104
102
|
@toc = ReVIEW::WEBTOCPrinter.book_to_string(@book)
|
105
103
|
end
|
106
104
|
|
105
|
+
if @book.config['math_format'] == 'mathjax'
|
106
|
+
@javascripts.push(%Q(<script>MathJax = { tex: { inlineMath: [['\\\\(', '\\\\)']] }, svg: { fontCache: 'global' } };</script>))
|
107
|
+
@javascripts.push(%Q(<script type="text/javascript" id="MathJax-script" async="true" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>))
|
108
|
+
end
|
109
|
+
|
107
110
|
ReVIEW::Template.load(layoutfile).result(binding)
|
108
111
|
end
|
109
112
|
|
113
|
+
def solve_nest(s)
|
114
|
+
check_nest
|
115
|
+
s.gsub("</dd>\n</dl>\n\x01→dl←\x01", '').
|
116
|
+
gsub("\x01→/dl←\x01", "</dd>\n</dl>←END\x01").
|
117
|
+
gsub("</li>\n</ul>\n\x01→ul←\x01", '').
|
118
|
+
gsub("\x01→/ul←\x01", "</li>\n</ul>←END\x01").
|
119
|
+
gsub("</li>\n</ol>\n\x01→ol←\x01", '').
|
120
|
+
gsub("\x01→/ol←\x01", "</li>\n</ol>←END\x01").
|
121
|
+
gsub("</dl>←END\x01\n<dl>", '').
|
122
|
+
gsub("</ul>←END\x01\n<ul>", '').
|
123
|
+
gsub("</ol>←END\x01\n<ol>", '').
|
124
|
+
gsub("←END\x01", '')
|
125
|
+
end
|
126
|
+
|
110
127
|
def xmlns_ops_prefix
|
111
128
|
if @book.config['epubversion'].to_i == 3
|
112
129
|
'epub'
|
@@ -139,6 +156,7 @@ module ReVIEW
|
|
139
156
|
@nonum_counter += 1
|
140
157
|
puts if level > 1
|
141
158
|
return unless caption.present?
|
159
|
+
|
142
160
|
if label
|
143
161
|
puts %Q(<h#{level} id="#{normalize_id(label)}">#{compile_inline(caption)}</h#{level}>)
|
144
162
|
else
|
@@ -154,6 +172,7 @@ module ReVIEW
|
|
154
172
|
@nonum_counter += 1
|
155
173
|
puts if level > 1
|
156
174
|
return unless caption.present?
|
175
|
+
|
157
176
|
if label
|
158
177
|
puts %Q(<h#{level} id="#{normalize_id(label)}" notoc="true">#{compile_inline(caption)}</h#{level}>)
|
159
178
|
else
|
@@ -169,6 +188,7 @@ module ReVIEW
|
|
169
188
|
@nonum_counter += 1
|
170
189
|
puts '' if level > 1
|
171
190
|
return unless caption.present?
|
191
|
+
|
172
192
|
if label
|
173
193
|
puts %Q(<a id="#{normalize_id(label)}" /><h#{level} id="#{normalize_id(label)}" hidden="true">#{compile_inline(caption)}</h#{level}>)
|
174
194
|
else
|
@@ -228,6 +248,7 @@ module ReVIEW
|
|
228
248
|
end
|
229
249
|
|
230
250
|
def captionblock(type, lines, caption)
|
251
|
+
check_nested_minicolumn
|
231
252
|
puts %Q(<div class="#{type}">)
|
232
253
|
if caption.present?
|
233
254
|
puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
|
@@ -286,15 +307,25 @@ module ReVIEW
|
|
286
307
|
end
|
287
308
|
|
288
309
|
def box(lines, caption = nil)
|
289
|
-
|
310
|
+
captionstr = nil
|
290
311
|
if caption.present?
|
291
|
-
|
312
|
+
captionstr = %Q(<p class="caption">#{compile_inline(caption)}</p>)
|
313
|
+
end
|
314
|
+
puts %Q(<div class="syntax">)
|
315
|
+
|
316
|
+
if caption_top?('list') && caption.present?
|
317
|
+
puts captionstr
|
292
318
|
end
|
319
|
+
|
293
320
|
print %Q(<pre class="syntax">)
|
294
321
|
lines.each do |line|
|
295
322
|
puts detab(line)
|
296
323
|
end
|
297
324
|
puts '</pre>'
|
325
|
+
|
326
|
+
if !caption_top?('list') && caption.present?
|
327
|
+
puts captionstr
|
328
|
+
end
|
298
329
|
puts '</div>'
|
299
330
|
end
|
300
331
|
|
@@ -302,6 +333,24 @@ module ReVIEW
|
|
302
333
|
captionblock('note', lines, caption)
|
303
334
|
end
|
304
335
|
|
336
|
+
CAPTION_TITLES.each do |name|
|
337
|
+
class_eval %Q(
|
338
|
+
def #{name}_begin(caption = nil)
|
339
|
+
check_nested_minicolumn
|
340
|
+
@doc_status[:minicolumn] = '#{name}'
|
341
|
+
puts %Q(<div class="#{name}">)
|
342
|
+
if caption.present?
|
343
|
+
puts %Q(<p class="caption">\#{compile_inline(caption)}</p>)
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
def #{name}_end
|
348
|
+
puts '</div>'
|
349
|
+
@doc_status[:minicolumn] = nil
|
350
|
+
end
|
351
|
+
), __FILE__, __LINE__ - 14
|
352
|
+
end
|
353
|
+
|
305
354
|
def ul_begin
|
306
355
|
puts '<ul>'
|
307
356
|
end
|
@@ -373,12 +422,7 @@ module ReVIEW
|
|
373
422
|
|
374
423
|
def list(lines, id, caption, lang = nil)
|
375
424
|
puts %Q(<div id="#{normalize_id(id)}" class="caption-code">)
|
376
|
-
|
377
|
-
list_header(id, caption, lang)
|
378
|
-
rescue KeyError
|
379
|
-
error "no such list: #{id}"
|
380
|
-
end
|
381
|
-
list_body(id, lines, lang)
|
425
|
+
super(lines, id, caption, lang)
|
382
426
|
puts '</div>'
|
383
427
|
end
|
384
428
|
|
@@ -403,8 +447,7 @@ module ReVIEW
|
|
403
447
|
|
404
448
|
def source(lines, caption = nil, lang = nil)
|
405
449
|
puts %Q(<div class="source-code">)
|
406
|
-
|
407
|
-
source_body(caption, lines, lang)
|
450
|
+
super(lines, caption, lang)
|
408
451
|
puts '</div>'
|
409
452
|
end
|
410
453
|
|
@@ -414,7 +457,7 @@ module ReVIEW
|
|
414
457
|
end
|
415
458
|
end
|
416
459
|
|
417
|
-
def source_body(
|
460
|
+
def source_body(lines, lang)
|
418
461
|
print %Q(<pre class="source">)
|
419
462
|
body = lines.inject('') { |i, j| i + detab(j) + "\n" }
|
420
463
|
lexer = lang
|
@@ -424,12 +467,7 @@ module ReVIEW
|
|
424
467
|
|
425
468
|
def listnum(lines, id, caption, lang = nil)
|
426
469
|
puts %Q(<div id="#{normalize_id(id)}" class="code">)
|
427
|
-
|
428
|
-
list_header(id, caption, lang)
|
429
|
-
rescue KeyError
|
430
|
-
error "no such list: #{id}"
|
431
|
-
end
|
432
|
-
listnum_body(lines, lang)
|
470
|
+
super(lines, id, caption, lang)
|
433
471
|
puts '</div>'
|
434
472
|
end
|
435
473
|
|
@@ -455,7 +493,7 @@ module ReVIEW
|
|
455
493
|
|
456
494
|
def emlist(lines, caption = nil, lang = nil)
|
457
495
|
puts %Q(<div class="emlist-code">)
|
458
|
-
if caption.present?
|
496
|
+
if caption_top?('list') && caption.present?
|
459
497
|
puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
|
460
498
|
end
|
461
499
|
class_names = ['emlist']
|
@@ -466,12 +504,15 @@ module ReVIEW
|
|
466
504
|
lexer = lang
|
467
505
|
puts highlight(body: body, lexer: lexer, format: 'html')
|
468
506
|
puts '</pre>'
|
507
|
+
if !caption_top?('list') && caption.present?
|
508
|
+
puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
|
509
|
+
end
|
469
510
|
puts '</div>'
|
470
511
|
end
|
471
512
|
|
472
513
|
def emlistnum(lines, caption = nil, lang = nil)
|
473
514
|
puts %Q(<div class="emlistnum-code">)
|
474
|
-
if caption.present?
|
515
|
+
if caption_top?('list') && caption.present?
|
475
516
|
puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
|
476
517
|
end
|
477
518
|
|
@@ -493,19 +534,29 @@ module ReVIEW
|
|
493
534
|
puts '</pre>'
|
494
535
|
end
|
495
536
|
|
537
|
+
if !caption_top?('list') && caption.present?
|
538
|
+
puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
|
539
|
+
end
|
540
|
+
|
496
541
|
puts '</div>'
|
497
542
|
end
|
498
543
|
|
499
544
|
def cmd(lines, caption = nil)
|
500
545
|
puts %Q(<div class="cmd-code">)
|
501
|
-
if caption.present?
|
546
|
+
if caption_top?('list') && caption.present?
|
502
547
|
puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
|
503
548
|
end
|
549
|
+
|
504
550
|
print %Q(<pre class="cmd">)
|
505
551
|
body = lines.inject('') { |i, j| i + detab(j) + "\n" }
|
506
552
|
lexer = 'shell-session'
|
507
553
|
puts highlight(body: body, lexer: lexer, format: 'html')
|
508
554
|
puts '</pre>'
|
555
|
+
|
556
|
+
if !caption_top?('list') && caption.present?
|
557
|
+
puts %Q(<p class="caption">#{compile_inline(caption)}</p>)
|
558
|
+
end
|
559
|
+
|
509
560
|
puts '</div>'
|
510
561
|
end
|
511
562
|
|
@@ -541,12 +592,13 @@ module ReVIEW
|
|
541
592
|
def texequation(lines, id = nil, caption = '')
|
542
593
|
if id
|
543
594
|
puts %Q(<div id="#{normalize_id(id)}" class="caption-equation">)
|
544
|
-
texequation_header(id, caption)
|
595
|
+
texequation_header(id, caption) if caption_top?('equation')
|
545
596
|
end
|
546
597
|
|
547
598
|
texequation_body(lines)
|
548
599
|
|
549
600
|
if id
|
601
|
+
texequation_header(id, caption) unless caption_top?('equation')
|
550
602
|
puts '</div>'
|
551
603
|
end
|
552
604
|
end
|
@@ -561,24 +613,27 @@ module ReVIEW
|
|
561
613
|
|
562
614
|
def texequation_body(lines)
|
563
615
|
puts %Q(<div class="equation">)
|
564
|
-
if @book.config['mathml'
|
565
|
-
|
566
|
-
|
616
|
+
if @book.config['math_format'] == 'mathml'
|
617
|
+
begin
|
618
|
+
require 'math_ml'
|
619
|
+
require 'math_ml/symbol/character_reference'
|
620
|
+
rescue LoadError
|
621
|
+
error 'not found math_ml'
|
622
|
+
end
|
567
623
|
p = MathML::LaTeX::Parser.new(symbol: MathML::Symbol::CharacterReference)
|
568
624
|
print p.parse(lines.join("\n") + "\n", true)
|
569
|
-
elsif @book.config['
|
625
|
+
elsif @book.config['math_format'] == 'mathjax'
|
626
|
+
puts "$$#{lines.join("\n")}$$"
|
627
|
+
elsif @book.config['math_format'] == 'imgmath'
|
570
628
|
fontsize = @book.config['imgmath_options']['fontsize'].to_f
|
571
629
|
lineheight = @book.config['imgmath_options']['lineheight'].to_f
|
572
630
|
math_str = "\\begin{equation*}\n\\fontsize{#{fontsize}}{#{lineheight}}\\selectfont\n#{lines.join("\n")}\n\\end{equation*}\n"
|
573
631
|
key = Digest::SHA256.hexdigest(math_str)
|
574
|
-
math_dir = File.join(@book.config['imagedir'], '_review_math')
|
575
|
-
Dir.mkdir(math_dir) unless Dir.exist?(math_dir)
|
576
|
-
img_path = File.join(math_dir, "_gen_#{key}.#{@book.config['imgmath_options']['format']}")
|
577
632
|
if @book.config.check_version('2', exception: false)
|
578
|
-
make_math_image(math_str,
|
633
|
+
img_path = @img_math.make_math_image(math_str, key)
|
579
634
|
puts %Q(<img src="#{img_path}" />)
|
580
635
|
else
|
581
|
-
defer_math_image(math_str,
|
636
|
+
img_path = @img_math.defer_math_image(math_str, key)
|
582
637
|
puts %Q(<img src="#{img_path}" class="math_gen_#{key}" alt="#{escape(lines.join(' '))}" />)
|
583
638
|
end
|
584
639
|
else
|
@@ -614,20 +669,22 @@ module ReVIEW
|
|
614
669
|
def image_image(id, caption, metric)
|
615
670
|
metrics = parse_metric('html', metric)
|
616
671
|
puts %Q(<div id="#{normalize_id(id)}" class="image">)
|
672
|
+
image_header(id, caption) if caption_top?('image')
|
617
673
|
puts %Q(<img src="#{@chapter.image(id).path.sub(%r{\A\./}, '')}" alt="#{escape(compile_inline(caption))}"#{metrics} />)
|
618
|
-
image_header(id, caption)
|
674
|
+
image_header(id, caption) unless caption_top?('image')
|
619
675
|
puts '</div>'
|
620
676
|
end
|
621
677
|
|
622
678
|
def image_dummy(id, caption, lines)
|
623
679
|
warn "image not bound: #{id}"
|
624
680
|
puts %Q(<div id="#{normalize_id(id)}" class="image">)
|
681
|
+
image_header(id, caption) if caption_top?('image')
|
625
682
|
puts %Q(<pre class="dummyimage">)
|
626
683
|
lines.each do |line|
|
627
684
|
puts detab(line)
|
628
685
|
end
|
629
686
|
puts '</pre>'
|
630
|
-
image_header(id, caption)
|
687
|
+
image_header(id, caption) unless caption_top?('image')
|
631
688
|
puts '</div>'
|
632
689
|
end
|
633
690
|
|
@@ -690,15 +747,19 @@ module ReVIEW
|
|
690
747
|
|
691
748
|
puts %Q(<div id="#{normalize_id(id)}" class="imgtable image">)
|
692
749
|
begin
|
693
|
-
if caption.present?
|
750
|
+
if caption_top?('table') && caption.present?
|
751
|
+
table_header(id, caption)
|
752
|
+
end
|
753
|
+
|
754
|
+
imgtable_image(id, caption, metric)
|
755
|
+
|
756
|
+
if !caption_top?('table') && caption.present?
|
694
757
|
table_header(id, caption)
|
695
758
|
end
|
696
759
|
rescue KeyError
|
697
760
|
error "no such table: #{id}"
|
698
761
|
end
|
699
762
|
|
700
|
-
imgtable_image(id, caption, metric)
|
701
|
-
|
702
763
|
puts '</div>'
|
703
764
|
end
|
704
765
|
|
@@ -713,6 +774,7 @@ module ReVIEW
|
|
713
774
|
|
714
775
|
def comment(lines, comment = nil)
|
715
776
|
return unless @book.config['draft']
|
777
|
+
|
716
778
|
lines ||= []
|
717
779
|
lines.unshift(escape(comment)) unless comment.blank?
|
718
780
|
str = lines.join('<br />')
|
@@ -735,7 +797,19 @@ module ReVIEW
|
|
735
797
|
def indepimage(lines, id, caption = '', metric = nil)
|
736
798
|
metrics = parse_metric('html', metric)
|
737
799
|
caption = '' unless caption.present?
|
800
|
+
caption_str = nil
|
801
|
+
if caption.present?
|
802
|
+
caption_str = <<-EOS
|
803
|
+
<p class="caption">
|
804
|
+
#{I18n.t('numberless_image')}#{I18n.t('caption_prefix')}#{compile_inline(caption)}
|
805
|
+
</p>
|
806
|
+
EOS
|
807
|
+
end
|
808
|
+
|
738
809
|
puts %Q(<div id="#{normalize_id(id)}" class="image">)
|
810
|
+
if caption_top?('image') && caption.present?
|
811
|
+
puts caption_str
|
812
|
+
end
|
739
813
|
begin
|
740
814
|
puts %Q(<img src="#{@chapter.image(id).path.sub(%r{\A\./}, '')}" alt="#{escape(compile_inline(caption))}"#{metrics} />)
|
741
815
|
rescue
|
@@ -749,10 +823,8 @@ module ReVIEW
|
|
749
823
|
end
|
750
824
|
end
|
751
825
|
|
752
|
-
if caption.present?
|
753
|
-
puts
|
754
|
-
puts %Q(#{I18n.t('numberless_image')}#{I18n.t('caption_prefix')}#{compile_inline(caption)})
|
755
|
-
puts '</p>'
|
826
|
+
if !caption_top?('image') && caption.present?
|
827
|
+
puts caption_str
|
756
828
|
end
|
757
829
|
puts '</div>'
|
758
830
|
end
|
@@ -913,22 +985,25 @@ module ReVIEW
|
|
913
985
|
end
|
914
986
|
|
915
987
|
def inline_m(str)
|
916
|
-
if @book.config['mathml'
|
917
|
-
|
918
|
-
|
988
|
+
if @book.config['math_format'] == 'mathml'
|
989
|
+
begin
|
990
|
+
require 'math_ml'
|
991
|
+
require 'math_ml/symbol/character_reference'
|
992
|
+
rescue LoadError
|
993
|
+
error 'not found math_ml'
|
994
|
+
end
|
919
995
|
parser = MathML::LaTeX::Parser.new(symbol: MathML::Symbol::CharacterReference)
|
920
996
|
%Q(<span class="equation">#{parser.parse(str, nil)}</span>)
|
921
|
-
elsif @book.config['
|
997
|
+
elsif @book.config['math_format'] == 'mathjax'
|
998
|
+
%Q(<span class="equation">\\( #{str} \\)</span>)
|
999
|
+
elsif @book.config['math_format'] == 'imgmath'
|
922
1000
|
math_str = '$' + str + '$'
|
923
1001
|
key = Digest::SHA256.hexdigest(str)
|
924
|
-
math_dir = File.join(@book.config['imagedir'], '_review_math')
|
925
|
-
Dir.mkdir(math_dir) unless Dir.exist?(math_dir)
|
926
|
-
img_path = File.join(math_dir, "_gen_#{key}.#{@book.config['imgmath_options']['format']}")
|
927
1002
|
if @book.config.check_version('2', exception: false)
|
928
|
-
make_math_image(math_str,
|
1003
|
+
img_path = @img_math.make_math_image(math_str, key)
|
929
1004
|
%Q(<span class="equation"><img src="#{img_path}" /></span>)
|
930
1005
|
else
|
931
|
-
defer_math_image(math_str,
|
1006
|
+
img_path = @img_math.defer_math_image(math_str, key)
|
932
1007
|
%Q(<span class="equation"><img src="#{img_path}" class="math_gen_#{key}" alt="#{escape(str)}" /></span>)
|
933
1008
|
end
|
934
1009
|
else
|
@@ -972,7 +1047,7 @@ module ReVIEW
|
|
972
1047
|
str = I18n.t('hd_quote_without_number', compile_inline(chap.headline(id).caption))
|
973
1048
|
end
|
974
1049
|
if @book.config['chapterlink']
|
975
|
-
anchor = 'h' + n.
|
1050
|
+
anchor = 'h' + n.tr('.', '-')
|
976
1051
|
%Q(<a href="#{chap.id}#{extname}##{anchor}">#{str}</a>)
|
977
1052
|
else
|
978
1053
|
str
|
@@ -989,7 +1064,7 @@ module ReVIEW
|
|
989
1064
|
|
990
1065
|
def inline_column_chap(chapter, id)
|
991
1066
|
if @book.config['chapterlink']
|
992
|
-
%Q(<a href="
|
1067
|
+
%Q(<a href="#{chapter.id}#{extname}##{column_label(id, chapter)}" class="columnref">#{I18n.t('column', compile_inline(chapter.column(id).caption))}</a>)
|
993
1068
|
else
|
994
1069
|
I18n.t('column', compile_inline(chapter.column(id).caption))
|
995
1070
|
end
|
@@ -1151,7 +1226,7 @@ module ReVIEW
|
|
1151
1226
|
%Q(<span class="balloon">#{escape_html(str)}</span>)
|
1152
1227
|
end
|
1153
1228
|
|
1154
|
-
def inline_raw(str)
|
1229
|
+
def inline_raw(str) # rubocop:disable Lint/UselessMethodDefinition
|
1155
1230
|
super(str)
|
1156
1231
|
end
|
1157
1232
|
|
@@ -1182,35 +1257,5 @@ module ReVIEW
|
|
1182
1257
|
def olnum(num)
|
1183
1258
|
@ol_num = num.to_i
|
1184
1259
|
end
|
1185
|
-
|
1186
|
-
def make_math_image(str, path, fontsize = 12)
|
1187
|
-
# Re:VIEW 2 compatibility
|
1188
|
-
fontsize2 = (fontsize * 1.2).round.to_i
|
1189
|
-
texsrc = <<-EOB
|
1190
|
-
\\documentclass[12pt]{article}
|
1191
|
-
\\usepackage[utf8]{inputenc}
|
1192
|
-
\\usepackage{amsmath}
|
1193
|
-
\\usepackage{amsthm}
|
1194
|
-
\\usepackage{amssymb}
|
1195
|
-
\\usepackage{amsfonts}
|
1196
|
-
\\usepackage{anyfontsize}
|
1197
|
-
\\usepackage{bm}
|
1198
|
-
\\pagestyle{empty}
|
1199
|
-
|
1200
|
-
\\begin{document}
|
1201
|
-
\\fontsize{#{fontsize}}{#{fontsize2}}\\selectfont #{str}
|
1202
|
-
\\end{document}
|
1203
|
-
EOB
|
1204
|
-
Dir.mktmpdir do |tmpdir|
|
1205
|
-
tex_path = File.join(tmpdir, 'tmpmath.tex')
|
1206
|
-
dvi_path = File.join(tmpdir, 'tmpmath.dvi')
|
1207
|
-
File.write(tex_path, texsrc)
|
1208
|
-
cmd = "latex --interaction=nonstopmode --output-directory=#{tmpdir} #{tex_path} && dvipng -T tight -z9 -o #{path} #{dvi_path}"
|
1209
|
-
out, status = Open3.capture2e(cmd)
|
1210
|
-
unless status.success?
|
1211
|
-
error "latex compile error\n\nError log:\n" + out
|
1212
|
-
end
|
1213
|
-
end
|
1214
|
-
end
|
1215
1260
|
end
|
1216
1261
|
end # module ReVIEW
|