review-retrovert 0.9.7 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.dockerignore +9 -0
- data/.editorconfig +3 -0
- data/.github/workflows/retrovert.yml +20 -5
- data/.gitignore +1 -0
- data/.vscode/launch.json +48 -0
- data/Gemfile.lock +13 -4
- data/Makefile +24 -0
- data/docker/review.Dockerfile +10 -0
- data/lib/review/retrovert/converter.rb +374 -111
- data/lib/review/retrovert/reviewcompat.rb +57 -0
- data/lib/review/retrovert/reviewdef.rb +70 -0
- data/lib/review/retrovert/sty/{ird.sty → ird.sty.erb} +9 -1
- data/lib/review/retrovert/sty/review-retrovert-custom.sty.erb +6 -0
- data/lib/review/retrovert/utils.rb +35 -0
- data/lib/review/retrovert/version.rb +1 -1
- data/lib/review/retrovert/yamlconfig.rb +0 -1
- data/package-lock.json +6 -0
- data/package.json +1 -0
- data/review-retrovert.gemspec +5 -1
- data/testdata/mybook/.gitignore +3 -1
- data/testdata/mybook/.textlintrc +11 -0
- data/testdata/mybook/Rakefile +8 -0
- data/testdata/mybook/catalog.yml +36 -10
- data/testdata/mybook/config-starter.yml +134 -9
- data/testdata/mybook/config.yml +44 -15
- data/testdata/mybook/contents/00-preface.re +48 -2
- data/testdata/mybook/contents/01-install.re +38 -5
- data/testdata/mybook/contents/02-tutorial.re +333 -113
- data/testdata/mybook/contents/03-syntax.re +2370 -373
- data/testdata/mybook/contents/04-customize.re +424 -88
- data/testdata/mybook/contents/05-faq.re +288 -10
- data/testdata/mybook/contents/06-bestpractice.re +431 -59
- data/testdata/mybook/contents/91-compare.re +402 -2
- data/testdata/mybook/contents/92-filelist.re +14 -8
- data/testdata/mybook/contents/93-background.re +10 -10
- data/testdata/mybook/contents/99-postface.re +2 -1
- data/testdata/mybook/contents/r0-root.re +1 -1
- data/testdata/mybook/css/webstyle.css +180 -2
- data/testdata/mybook/data/terms.txt +3 -0
- data/testdata/mybook/data/words.txt +15 -0
- data/testdata/mybook/images/03-syntax/index-page.png +0 -0
- data/testdata/mybook/images/03-syntax/order-detail.png +0 -0
- data/testdata/mybook/images/04-customize/section_decoration_samples.png +0 -0
- data/testdata/mybook/images/05-faq/dummy-image.png +0 -0
- data/testdata/mybook/images/06-bestpractice/section_title_wlines.png +0 -0
- data/testdata/mybook/images/avatar-b.png +0 -0
- data/testdata/mybook/images/avatar-g.png +0 -0
- data/testdata/mybook/images/avatar-r.png +0 -0
- data/testdata/mybook/images/caution-icon.png +0 -0
- data/testdata/mybook/images/info-icon.png +0 -0
- data/testdata/mybook/images/warning-icon.png +0 -0
- data/testdata/mybook/layouts/layout.html5.erb +3 -1
- data/testdata/mybook/layouts/layout.tex.erb +265 -379
- data/testdata/mybook/layouts/layout.tex.erb.orig +386 -0
- data/testdata/mybook/lib/ruby/review-book.rb +64 -0
- data/testdata/mybook/lib/ruby/review-builder.rb +902 -63
- data/testdata/mybook/lib/ruby/review-compiler.rb +675 -22
- data/testdata/mybook/lib/ruby/review-epubbuilder.rb +33 -0
- data/testdata/mybook/lib/ruby/review-epubmaker.rb +10 -7
- data/testdata/mybook/lib/ruby/review-htmlbuilder.rb +354 -66
- data/testdata/mybook/lib/ruby/review-latexbuilder.rb +429 -146
- data/testdata/mybook/lib/ruby/review-maker.rb +117 -6
- data/testdata/mybook/lib/ruby/review-markdownbuilder.rb +945 -0
- data/testdata/mybook/lib/ruby/review-markdownmaker.rb +91 -0
- data/testdata/mybook/lib/ruby/review-monkeypatch.rb +2 -0
- data/testdata/mybook/lib/ruby/review-pdfmaker.rb +160 -82
- data/testdata/mybook/lib/ruby/review-webmaker.rb +20 -5
- data/testdata/mybook/lib/tasks/review.rake +14 -0
- data/testdata/mybook/lib/tasks/starter.rake +148 -4
- data/testdata/mybook/sty/indexstyle.ist +25 -0
- data/testdata/mybook/sty/mytextsize.sty +29 -0
- data/testdata/mybook/sty/mytitlepage.sty +34 -11
- data/testdata/mybook/sty/review-base.sty +276 -0
- data/testdata/mybook/sty/starter-codeblock.sty +237 -106
- data/testdata/mybook/sty/starter-color.sty +72 -17
- data/testdata/mybook/sty/starter-heading.sty +60 -13
- data/testdata/mybook/sty/starter-misc.sty +894 -0
- data/testdata/mybook/sty/starter-note.sty +67 -14
- data/testdata/mybook/sty/starter-talklist.sty +105 -0
- data/testdata/mybook/sty/starter-util.sty +35 -0
- data/testdata/mybook/sty/starter.sty +8 -526
- metadata +80 -4
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
##
|
|
6
6
|
|
|
7
7
|
require 'pathname'
|
|
8
|
+
require 'open3'
|
|
8
9
|
|
|
9
10
|
require 'review/logger'
|
|
10
11
|
require 'review/version'
|
|
@@ -34,9 +35,10 @@ module ReVIEW
|
|
|
34
35
|
@config.maker = @maker_name
|
|
35
36
|
@config.check_version(ReVIEW::VERSION) # may raise ReVIEW::ConfigError
|
|
36
37
|
#
|
|
37
|
-
yamlfile = File.join(@basedir, 'config-starter.yml')
|
|
38
|
-
yamldata = File.open(yamlfile) {|f| YAML.safe_load(f) }
|
|
39
|
-
|
|
38
|
+
#yamlfile = File.join(@basedir, 'config-starter.yml')
|
|
39
|
+
#yamldata = File.open(yamlfile) {|f| YAML.safe_load(f) }
|
|
40
|
+
#@starter_config = yamldata['starter']
|
|
41
|
+
@starter_config = @config['starter']
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
def self.execute(*args)
|
|
@@ -57,7 +59,7 @@ module ReVIEW
|
|
|
57
59
|
maker = nil
|
|
58
60
|
begin
|
|
59
61
|
maker = self.new(config_filename, cmdopts)
|
|
60
|
-
maker.generate()
|
|
62
|
+
return maker.generate()
|
|
61
63
|
rescue ApplicationError, ReVIEW::ConfigError => ex
|
|
62
64
|
raise if maker && maker.config['debug']
|
|
63
65
|
error(ex.message)
|
|
@@ -87,6 +89,8 @@ module ReVIEW
|
|
|
87
89
|
config.deep_merge!(additionals)
|
|
88
90
|
I18n.setup(config['language'])
|
|
89
91
|
#
|
|
92
|
+
validate_config(config)
|
|
93
|
+
#
|
|
90
94
|
if ENV['STARTER_CHAPTER'].present?
|
|
91
95
|
modify_config(config)
|
|
92
96
|
end
|
|
@@ -116,6 +120,76 @@ module ReVIEW
|
|
|
116
120
|
return book
|
|
117
121
|
end
|
|
118
122
|
|
|
123
|
+
def validate_config(config)
|
|
124
|
+
_validate_obsoletes(config)
|
|
125
|
+
_validate_pdffiles(config)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
private
|
|
129
|
+
|
|
130
|
+
def _validate_obsoletes(config)
|
|
131
|
+
d = config['pdfmaker']
|
|
132
|
+
return unless d
|
|
133
|
+
obsolete_keys = ['coverpdf_files', 'backcoverpdf_files', 'coverpdf_option']
|
|
134
|
+
if obsolete_keys.any? {|key| d.key?(key) }
|
|
135
|
+
errmsg = CONFIG_PDFFILES_ERRMSG
|
|
136
|
+
$stderr.puts "\033[0;31m\n#{errmsg}\033[0m"
|
|
137
|
+
error "obsolete config entry exists."
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
CONFIG_PDFFILES_ERRMSG = <<END
|
|
142
|
+
***** ERROR *****
|
|
143
|
+
'config.yml' contains old entries.
|
|
144
|
+
|
|
145
|
+
Please move the followings from 'config.yml' ...
|
|
146
|
+
|
|
147
|
+
* coverpdf_files:
|
|
148
|
+
* backcoverpdf_files:
|
|
149
|
+
* coverpdf_option:
|
|
150
|
+
|
|
151
|
+
into 'config-starter.yml' with renaming to ...
|
|
152
|
+
|
|
153
|
+
* frontcover_pdffile:
|
|
154
|
+
* backcover_pdffile:
|
|
155
|
+
* includepdf_option:
|
|
156
|
+
END
|
|
157
|
+
|
|
158
|
+
def _validate_pdffiles(config)
|
|
159
|
+
d = config['starter']
|
|
160
|
+
return unless d
|
|
161
|
+
imagedir = config['imagedir']
|
|
162
|
+
pdffile_keys = ['frontcover_pdffile', 'backcover_pdffile', 'titlepage_pdffile', 'colophon_pdffile']
|
|
163
|
+
pdffile_keys.each do |key|
|
|
164
|
+
[d[key]].flatten.compact.each do |pdffile|
|
|
165
|
+
pdffile = pdffile.gsub(/(<.*?>)?\*?\z/, '')
|
|
166
|
+
errmsg = _validate_pdffile(File.join(imagedir, pdffile))
|
|
167
|
+
error "(config-starter.yml) '#{key}: #{pdffile}': #{errmsg}" if errmsg
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
#
|
|
171
|
+
key = 'includepdf_option'; val = d[key]
|
|
172
|
+
if val.present?
|
|
173
|
+
val =~ /\Aoffset=/ or
|
|
174
|
+
error "(config-starter.yml) '#{key}: #{val}': unexpected value. only 'offset=...' available here."
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def _validate_pdffile(filepath)
|
|
179
|
+
filepath =~ /\.pdf\z/i or
|
|
180
|
+
return "expected pdf file ('*.pdf'), but not."
|
|
181
|
+
return _validate_file(filepath)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def _validate_file(filepath)
|
|
185
|
+
File.exist?(filepath) or return "file not found."
|
|
186
|
+
File.file?(filepath) or return "not a file."
|
|
187
|
+
File.readable?(filepath) or return "cannot read (permission denied?)."
|
|
188
|
+
return nil
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
protected
|
|
192
|
+
|
|
119
193
|
def system_or_raise(*args)
|
|
120
194
|
Kernel.system(*args) or raise("failed to run command: #{args.join(' ')}")
|
|
121
195
|
end
|
|
@@ -145,16 +219,48 @@ module ReVIEW
|
|
|
145
219
|
path
|
|
146
220
|
end
|
|
147
221
|
|
|
148
|
-
def
|
|
222
|
+
def echoback(cmd)
|
|
149
223
|
puts ""
|
|
150
224
|
puts "[#{@maker_name}]$ #{cmd}"
|
|
151
|
-
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def run_cmd(cmd)
|
|
228
|
+
time = @_usr_bin_time ? "time " : ""
|
|
229
|
+
echoback("#{time}#{cmd}")
|
|
230
|
+
return Kernel::system(cmd)
|
|
152
231
|
end
|
|
153
232
|
|
|
154
233
|
def run_cmd!(cmd)
|
|
155
234
|
run_cmd(cmd) or raise("failed to run command: #{cmd}")
|
|
156
235
|
end
|
|
157
236
|
|
|
237
|
+
def run_cmd_capturing_output(cmd, append=nil)
|
|
238
|
+
time = @_usr_bin_time ? "time " : ""
|
|
239
|
+
echoback("#{time}#{cmd}#{append}")
|
|
240
|
+
output, status = Open3.capture2(cmd)
|
|
241
|
+
return output, status.success?
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def usr_bin_time(&b)
|
|
245
|
+
result = nil
|
|
246
|
+
@_usr_bin_time = true
|
|
247
|
+
start_t = Time.now
|
|
248
|
+
ptime1 = Process.times
|
|
249
|
+
result = yield
|
|
250
|
+
end_t = Time.now
|
|
251
|
+
ptime2 = Process.times
|
|
252
|
+
@_usr_bin_time = false
|
|
253
|
+
#
|
|
254
|
+
real_time = end_t - start_t
|
|
255
|
+
user_time = ptime2.cutime - ptime1.cutime
|
|
256
|
+
sys_time = ptime2.cstime - ptime1.cstime
|
|
257
|
+
format = "%12.2f real %12.2f user %12.2f sys"
|
|
258
|
+
$stderr.puts format % [real_time, user_time, sys_time]
|
|
259
|
+
#
|
|
260
|
+
return result
|
|
261
|
+
end
|
|
262
|
+
protected :usr_bin_time
|
|
263
|
+
|
|
158
264
|
def call_hook(hookname)
|
|
159
265
|
d = @config[@maker_name]
|
|
160
266
|
return unless d.is_a?(Hash)
|
|
@@ -183,6 +289,11 @@ module ReVIEW
|
|
|
183
289
|
return File.join(c['bindir'], c['ruby_install_name']) + c['EXEEXT'].to_s
|
|
184
290
|
end
|
|
185
291
|
|
|
292
|
+
def colored_errmsg(msg)
|
|
293
|
+
#return msg unless $stderr.tty?
|
|
294
|
+
return "\033[0;31m#{msg}\033[0m"
|
|
295
|
+
end
|
|
296
|
+
|
|
186
297
|
end
|
|
187
298
|
|
|
188
299
|
|
|
@@ -0,0 +1,945 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
##
|
|
4
|
+
## Markdownへ変換する
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
require_relative './review-builder'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
module ReVIEW
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class MarkdownBuilder < Builder
|
|
14
|
+
|
|
15
|
+
def target_name
|
|
16
|
+
"markdown"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def extname
|
|
20
|
+
".md"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def headline(level, label, caption)
|
|
24
|
+
blank2() unless @output.pos == 0
|
|
25
|
+
print "#{'#' * level} "
|
|
26
|
+
print compile_inline(caption||'')
|
|
27
|
+
#print " {##{label}}" if label
|
|
28
|
+
puts ""
|
|
29
|
+
blank()
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def notoc_begin(level, label, caption)
|
|
33
|
+
blank2() unless @output.pos == 0
|
|
34
|
+
print "#{'#' * level} "
|
|
35
|
+
print compile_inline(caption||'')
|
|
36
|
+
#print " {##{label}}" if label
|
|
37
|
+
puts ""
|
|
38
|
+
blank()
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def notoc_end(level)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def column_begin(level, label, caption)
|
|
45
|
+
blank2()
|
|
46
|
+
puts "[column] #{compile_inline(caption||'')}"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def column_end(_level)
|
|
50
|
+
truncate_blank()
|
|
51
|
+
puts "[/column]"
|
|
52
|
+
blank2()
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def blank()
|
|
56
|
+
puts "" unless @output.string.end_with?("\n\n")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def blank2()
|
|
60
|
+
if @output.string.end_with?("\n\n\n")
|
|
61
|
+
elsif @output.string.end_with?("\n\n")
|
|
62
|
+
puts ""
|
|
63
|
+
else
|
|
64
|
+
puts ""
|
|
65
|
+
puts ""
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def twospaces()
|
|
70
|
+
if truncate_if_endwith?("\n")
|
|
71
|
+
puts " "
|
|
72
|
+
return true
|
|
73
|
+
else
|
|
74
|
+
false
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def nofunc_text(str)
|
|
79
|
+
if within_codeblock?() || within_context?(:code)
|
|
80
|
+
str
|
|
81
|
+
else
|
|
82
|
+
escape(str)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def escape(str)
|
|
87
|
+
str.to_s.gsub(/[&<>"']/, HTML_ESCAPE_TABLE)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
HTML_ESCAPE_TABLE = {
|
|
91
|
+
'&' => '&',
|
|
92
|
+
'<' => '<',
|
|
93
|
+
'>' => '>',
|
|
94
|
+
'"' => '"',
|
|
95
|
+
"'" => ''',
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
## 画像
|
|
99
|
+
|
|
100
|
+
def indepimage(lines, id, caption='', metric=nil)
|
|
101
|
+
image = @chapter.image(id)
|
|
102
|
+
image.bound? or
|
|
103
|
+
error "//image[#{id}]: image not found."
|
|
104
|
+
image_filepath = image.path
|
|
105
|
+
blank()
|
|
106
|
+
puts ""
|
|
107
|
+
if caption.present?
|
|
108
|
+
puts "<span class=\"caption\">▲#{compile_inline(caption)}</span>"
|
|
109
|
+
end
|
|
110
|
+
blank()
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def imgtable_image(id, caption, metric)
|
|
114
|
+
metrics = parse_metric('html', metric)
|
|
115
|
+
puts "<img src=\"#{@chapter.image(id).path.sub(%r{\A\./}, '')}\"#{metrics} />"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
protected
|
|
119
|
+
|
|
120
|
+
def _render_image(id, image_filepath, caption, opts)
|
|
121
|
+
puts ""
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
## コードブロック(//program, //terminal, //output)
|
|
125
|
+
|
|
126
|
+
def _render_codeblock(blockname, lines, id, caption_str, opts)
|
|
127
|
+
blank()
|
|
128
|
+
if caption_str.present?
|
|
129
|
+
puts "<span class=\"caption\">▼#{compile_inline(caption_str)}</span>"
|
|
130
|
+
puts ""
|
|
131
|
+
end
|
|
132
|
+
lang = opts['lang']
|
|
133
|
+
lang ||= 'terminal' if blockname == 'terminal' || blockname == 'cmd'
|
|
134
|
+
puts "```#{lang}"
|
|
135
|
+
lines.each do |line|
|
|
136
|
+
puts compile_inline(line)
|
|
137
|
+
end
|
|
138
|
+
puts "```"
|
|
139
|
+
blank()
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def _add_indent_mark(lines, indent_width)
|
|
143
|
+
space = " "
|
|
144
|
+
rexp = /\A( +)/
|
|
145
|
+
#
|
|
146
|
+
width = indent_width
|
|
147
|
+
mark = _codeblock_indentmark() # ex: '{\starterindentmark}'
|
|
148
|
+
indent = space * (width - 1) + mark
|
|
149
|
+
nchar = space.length
|
|
150
|
+
return lines.map {|line|
|
|
151
|
+
line.sub(rexp) {
|
|
152
|
+
m, n = ($1.length / nchar - 1).divmod width
|
|
153
|
+
"#{space}#{indent * m}#{space * n}"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
public
|
|
159
|
+
|
|
160
|
+
def list(lines, id=nil, caption=nil, lang=nil)
|
|
161
|
+
_codeblock("list", lines, id, caption, _codeblock_optstr(lang, false))
|
|
162
|
+
end
|
|
163
|
+
def listnum(lines, id=nil, caption=nil, lang=nil)
|
|
164
|
+
_codeblock("listnum", lines, id, caption, _codeblock_optstr(lang, true))
|
|
165
|
+
end
|
|
166
|
+
def emlist(lines, caption=nil, lang=nil)
|
|
167
|
+
_codeblock("emlist", lines, nil, caption, _codeblock_optstr(lang, false))
|
|
168
|
+
end
|
|
169
|
+
def emlistnum(lines, caption=nil, lang=nil)
|
|
170
|
+
_codeblock("emlistnum", lines, nil, caption, _codeblock_optstr(lang, true))
|
|
171
|
+
end
|
|
172
|
+
def source(lines, caption=nil, lang=nil)
|
|
173
|
+
_codeblock("source", lines, nil, caption, _codeblock_optstr(lang, false))
|
|
174
|
+
end
|
|
175
|
+
def cmd(lines, caption=nil, lang=nil)
|
|
176
|
+
lang ||= "shell-session"
|
|
177
|
+
_codeblock("cmd", lines, nil, caption, _codeblock_optstr(lang, false))
|
|
178
|
+
end
|
|
179
|
+
def _codeblock_optstr(lang, lineno_flag)
|
|
180
|
+
arr = []
|
|
181
|
+
arr << lang if lang
|
|
182
|
+
if lineno_flag
|
|
183
|
+
first_line_num = line_num()
|
|
184
|
+
arr << "lineno=#{first_line_num}"
|
|
185
|
+
arr << "linenowidth=0"
|
|
186
|
+
end
|
|
187
|
+
return arr.join(",")
|
|
188
|
+
end
|
|
189
|
+
private :_codeblock_optstr
|
|
190
|
+
|
|
191
|
+
protected
|
|
192
|
+
|
|
193
|
+
## @<secref>{}
|
|
194
|
+
|
|
195
|
+
def _build_secref(chap, num, title, parent_title)
|
|
196
|
+
s = ""
|
|
197
|
+
## 親セクションのタイトルがあれば使う
|
|
198
|
+
if parent_title
|
|
199
|
+
s << "「%s」内の" % parent_title # TODO: I18n化
|
|
200
|
+
end
|
|
201
|
+
## 対象セクションへのリンクを作成する
|
|
202
|
+
if @book.config['chapterlink']
|
|
203
|
+
filename = "#{chap.id}#{extname()}"
|
|
204
|
+
s << "[「#{title}」](#{filename})"
|
|
205
|
+
else
|
|
206
|
+
s << "「#{title}」"
|
|
207
|
+
end
|
|
208
|
+
return s
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
public
|
|
212
|
+
|
|
213
|
+
def ul_begin()
|
|
214
|
+
n = _enter_ul()
|
|
215
|
+
blank() if n == 1
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def ul_end()
|
|
219
|
+
n = _exit_ul()
|
|
220
|
+
blank() if n == 1
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def ul_item(lines)
|
|
224
|
+
n = _depth_ul()
|
|
225
|
+
sp = nil
|
|
226
|
+
lines.each do |line|
|
|
227
|
+
if !sp
|
|
228
|
+
puts "#{' ' * (n-1)}* #{line.strip}"
|
|
229
|
+
sp = ' ' * n
|
|
230
|
+
else
|
|
231
|
+
puts "#{sp}#{line.strip}"
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def _enter_ul
|
|
237
|
+
@_ul_depth ||= 0
|
|
238
|
+
@_ul_depth += 1
|
|
239
|
+
return @_ul_depth
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def _exit_ul
|
|
243
|
+
n = @_ul_depth
|
|
244
|
+
@_ul_depth -= 1
|
|
245
|
+
return n
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def _depth_ul
|
|
249
|
+
return @_ul_depth
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
## 順序つきリスト
|
|
253
|
+
|
|
254
|
+
def ol_begin(start_num=nil)
|
|
255
|
+
@_ol_types ||= [] # stack
|
|
256
|
+
case start_num
|
|
257
|
+
when nil
|
|
258
|
+
type = "1"; start = 1
|
|
259
|
+
when /\A(\d+)\.\z/
|
|
260
|
+
type = "1"; start = $1.to_i
|
|
261
|
+
when /\A([A-Z])\.\z/
|
|
262
|
+
type = "A"; start = $1.ord - 'A'.ord + 1
|
|
263
|
+
when /\A([a-z])\.\z/
|
|
264
|
+
type = "a"; start = $1.ord - 'a'.ord + 1
|
|
265
|
+
else
|
|
266
|
+
type = nil; start = nil
|
|
267
|
+
end
|
|
268
|
+
@_ol_types.push(type)
|
|
269
|
+
blank() if @_ol_types.length == 1
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def ol_end()
|
|
273
|
+
blank() if @_ol_types.length == 1
|
|
274
|
+
ol = !! @_ol_types.pop()
|
|
275
|
+
_ = ol
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def ol_item(lines, num)
|
|
279
|
+
n = @_ol_types.length
|
|
280
|
+
sp = nil
|
|
281
|
+
lines.each do |line|
|
|
282
|
+
if !sp
|
|
283
|
+
#s = num.length == 1 ? '. ' : '. '
|
|
284
|
+
#puts "#{num}#{s}#{line.strip}"
|
|
285
|
+
#sp = ' ' * n
|
|
286
|
+
puts "#{num}. #{line.strip}"
|
|
287
|
+
sp = ' ' * "#{num}. ".length
|
|
288
|
+
else
|
|
289
|
+
puts "#{sp}#{line.strip}"
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def ol_item_begin(lines, num)
|
|
295
|
+
n = @_ol_types.length
|
|
296
|
+
sp = nil
|
|
297
|
+
lines.each do |line|
|
|
298
|
+
if !sp
|
|
299
|
+
puts "#{' ' * (n-1)}- #{num} #{line.strip}"
|
|
300
|
+
sp = ' ' * n
|
|
301
|
+
else
|
|
302
|
+
puts "#{sp}#{line.strip}"
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def ol_item_end()
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def dl_begin()
|
|
311
|
+
blank()
|
|
312
|
+
puts "<dl>"
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def dl_end()
|
|
316
|
+
puts "</dl>"
|
|
317
|
+
blank()
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def dt(word)
|
|
321
|
+
#puts word
|
|
322
|
+
#puts "#{word}::"
|
|
323
|
+
puts "<dt>#{word}</dt>"
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def dl_dd_begin()
|
|
327
|
+
puts "<dd>"
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def dl_dd_end()
|
|
331
|
+
puts "</dd>"
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
## 画像横に文章
|
|
335
|
+
def _render_sideimage(filepath, imagewidth, opts, &b)
|
|
336
|
+
blank()
|
|
337
|
+
puts "<img src=\"#{filepath}\">"
|
|
338
|
+
blank()
|
|
339
|
+
yield
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
## 入れ子可能なブロック命令
|
|
343
|
+
|
|
344
|
+
def on_minicolumn(type, caption=nil, &b)
|
|
345
|
+
## ・タイトルと1つ目の文の間に空行がないと、
|
|
346
|
+
## textlintにタイトルも含めた1つの文だと認識されてしまい、
|
|
347
|
+
## 「一文が長すぎる」というエラーが頻発する。
|
|
348
|
+
## ・タイトルには末尾に「。」がないので、そのままだと
|
|
349
|
+
## 「文末に「。」がない」というエラーが頻発する。
|
|
350
|
+
## ・タイトルを <b></b> で囲むとこのエラーだけが出なくなる。
|
|
351
|
+
## (他のエラーは出るまま。)
|
|
352
|
+
with_context(:minicolumn) do
|
|
353
|
+
blank2()
|
|
354
|
+
puts "[#{type}] <b>#{compile_inline(caption||'')}</a>"
|
|
355
|
+
blank()
|
|
356
|
+
yield
|
|
357
|
+
blank()
|
|
358
|
+
puts "[/#{type}]"
|
|
359
|
+
blank2()
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
protected :on_minicolumn
|
|
363
|
+
|
|
364
|
+
def paragraph(lines)
|
|
365
|
+
lines.each do |line|
|
|
366
|
+
puts line
|
|
367
|
+
end
|
|
368
|
+
blank()
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
#### ブロック命令
|
|
372
|
+
|
|
373
|
+
def footnote(id, str)
|
|
374
|
+
@_fn_count ||= 0
|
|
375
|
+
@_fn_labels ||= {}
|
|
376
|
+
n = @_fn_labels[id]
|
|
377
|
+
blank() # necessary?
|
|
378
|
+
puts "[^#{n || 9999}]: #{compile_inline(str||'')}"
|
|
379
|
+
blank() # necessary?
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def texequation(lines, label=nil, caption=nil)
|
|
383
|
+
blank()
|
|
384
|
+
puts "```math"
|
|
385
|
+
puts lines
|
|
386
|
+
puts "```"
|
|
387
|
+
blank()
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
## 章 (Chapter) の概要
|
|
391
|
+
def on_abstract_block()
|
|
392
|
+
blank()
|
|
393
|
+
puts "[abstract]"; twospaces()
|
|
394
|
+
yield
|
|
395
|
+
truncate_blank(); twospaces()
|
|
396
|
+
puts "[/abstract]"
|
|
397
|
+
blank()
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
## 章 (Chapter) の著者
|
|
401
|
+
def on_chapterauthor_block(name)
|
|
402
|
+
puts "(著:#{name})"
|
|
403
|
+
blank()
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
## 会話リスト
|
|
407
|
+
def _render_talklist(opts, &b)
|
|
408
|
+
blank()
|
|
409
|
+
yield
|
|
410
|
+
blank()
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
## 会話項目
|
|
414
|
+
def on_talk_block(imagefile, name=nil, text=nil, &b)
|
|
415
|
+
if imagefile.present?
|
|
416
|
+
find_image_filepath(imagefile) or
|
|
417
|
+
error "//talk[#{imagefile}]: image file not found."
|
|
418
|
+
print "* [#{imagefile}] "
|
|
419
|
+
elsif name
|
|
420
|
+
print "* [#{name}] "
|
|
421
|
+
else
|
|
422
|
+
print "* "
|
|
423
|
+
end
|
|
424
|
+
if text.nil?
|
|
425
|
+
yield
|
|
426
|
+
else
|
|
427
|
+
puts compile_inline(text||'')
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
## キーと説明文のリスト
|
|
432
|
+
def _render_desclist(opts, &b)
|
|
433
|
+
blank()
|
|
434
|
+
bkup = @_desclist_opts
|
|
435
|
+
@_desclist_opts = opts
|
|
436
|
+
yield
|
|
437
|
+
@_desclist_opts = bkup
|
|
438
|
+
blank()
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
## キーと説明文
|
|
442
|
+
def _render_desc(key, &b)
|
|
443
|
+
opts = @_desclist_opts
|
|
444
|
+
puts "#{compile_inline(key)}:: "
|
|
445
|
+
yield
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
## 縦方向の空きを入れる
|
|
449
|
+
def _render_vspace(size)
|
|
450
|
+
blank()
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
## 章タイトルを独立したページに
|
|
454
|
+
def makechaptitlepage(option=nil)
|
|
455
|
+
blank()
|
|
456
|
+
puts ''
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
## 縦方向のスペースがなければ改ページ
|
|
460
|
+
def _render_needvspace(height)
|
|
461
|
+
blank()
|
|
462
|
+
puts ''
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
## 段(Paragraph)の終わりにスペースを入れる
|
|
466
|
+
def paragraphend()
|
|
467
|
+
blank()
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
## 小段(Subparagraph)の終わりにスペースを入れる(あれば)
|
|
471
|
+
def subparagraphend()
|
|
472
|
+
blank()
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
## 引用(複数段落に対応)
|
|
476
|
+
def blockquote(lines)
|
|
477
|
+
blank()
|
|
478
|
+
puts "[quote]"; twospaces()
|
|
479
|
+
puts lines
|
|
480
|
+
truncate_blank(); twospaces()
|
|
481
|
+
puts "[/quote]"
|
|
482
|
+
blank()
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
## 引用(//quote{ ... //})
|
|
486
|
+
## (入れ子対応なので、中に箇条書きや別のブロックを入れられる)
|
|
487
|
+
def on_quote_block()
|
|
488
|
+
blank()
|
|
489
|
+
puts "[quote]"; twospaces()
|
|
490
|
+
yield
|
|
491
|
+
truncate_blank(); twospaces()
|
|
492
|
+
puts "[/quote]"
|
|
493
|
+
blank()
|
|
494
|
+
end
|
|
495
|
+
def quote(lines)
|
|
496
|
+
on_quote_block() do
|
|
497
|
+
puts lines
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
## 引用 (====[quote] ... ====[/quote])
|
|
502
|
+
## (ブロック構文ではないので、中に別のブロックや箇条書きを入れられる)
|
|
503
|
+
def quote_begin(level, label, caption)
|
|
504
|
+
blank()
|
|
505
|
+
end
|
|
506
|
+
def quote_end(level)
|
|
507
|
+
blank()
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
## ノート(//note{ ... //})
|
|
511
|
+
## (入れ子対応なので、中に箇条書きや別のブロックを入れられる)
|
|
512
|
+
def on_note_block(label=nil, caption=nil)
|
|
513
|
+
## ・ノートのタイトルと1つ目の文の間に空行がないと、
|
|
514
|
+
## textlintにタイトルも含めた1つの文だと認識されてしまい、
|
|
515
|
+
## 「一文が長すぎる」というエラーが頻発する。
|
|
516
|
+
## ・ノートのタイトルには末尾に「。」がないので、そのままだと
|
|
517
|
+
## 「文末に「。」がない」というエラーが頻発する。
|
|
518
|
+
## ・タイトルを <b></b> で囲むとこのエラーだけが出なくなる。
|
|
519
|
+
## (他のエラーは出るまま。)
|
|
520
|
+
with_context(:minicolumn) do
|
|
521
|
+
blank2()
|
|
522
|
+
caption, label = label, nil if caption.nil?
|
|
523
|
+
puts "[note] <b>#{compile_inline(caption||'')}</a>"
|
|
524
|
+
blank()
|
|
525
|
+
yield
|
|
526
|
+
blank()
|
|
527
|
+
puts "[/note]"
|
|
528
|
+
blank2()
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
def note(lines, label=nil, caption=nil)
|
|
532
|
+
on_quote_block(label, caption) do
|
|
533
|
+
puts lines
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
## ノート (====[note] ... ====[/note])
|
|
538
|
+
## (ブロック構文ではないので、中に別のブロックや箇条書きを入れられる)
|
|
539
|
+
def note_begin(level, label, caption)
|
|
540
|
+
blank()
|
|
541
|
+
puts "[note] #{compile_inline(caption||'')}"; twospaces()
|
|
542
|
+
end
|
|
543
|
+
def note_end(level)
|
|
544
|
+
truncate_blank(); twospaces()
|
|
545
|
+
puts "[/note]"
|
|
546
|
+
blank()
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
## テーブル
|
|
550
|
+
def table(lines, id=nil, caption=nil, option=nil)
|
|
551
|
+
super
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
def table_header(id, caption, options)
|
|
555
|
+
if id.present?
|
|
556
|
+
begin
|
|
557
|
+
num = @chapter.table(id).number
|
|
558
|
+
rescue KeyError
|
|
559
|
+
error "no such table: #{id}"
|
|
560
|
+
end
|
|
561
|
+
s1 = I18n.t('table')
|
|
562
|
+
s2 = get_chap() \
|
|
563
|
+
? I18n.t('format_number_header', [get_chap(), num]) \
|
|
564
|
+
: I18n.t('format_number_header_without_chapter', [num])
|
|
565
|
+
s3 = I18n.t('caption_prefix')
|
|
566
|
+
puts "<p class=\"caption\">#{s1}#{s2}#{s3}#{compile_inline(caption||'')}</p>"
|
|
567
|
+
elsif caption.present?
|
|
568
|
+
puts "<p class=\"caption\">#{compile_inline(caption||'')}</p>"
|
|
569
|
+
end
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
def table_begin(_ncols, fontsize: nil)
|
|
573
|
+
if fontsize
|
|
574
|
+
puts "<table style=\"font-size:#{fontsize}\">"
|
|
575
|
+
else
|
|
576
|
+
puts "<table>"
|
|
577
|
+
end
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
def table_end
|
|
581
|
+
puts "</table>"
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
def th(s)
|
|
585
|
+
"<th>#{s}</th>"
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
def td(s)
|
|
589
|
+
"<td>#{s}</td>"
|
|
590
|
+
end
|
|
591
|
+
|
|
592
|
+
protected
|
|
593
|
+
|
|
594
|
+
def normalize_id(id)
|
|
595
|
+
id
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
def _table_before(id, caption, opts)
|
|
599
|
+
class_ = opts[:csv] ? "table table-nohline" : "table"
|
|
600
|
+
if id.present?
|
|
601
|
+
puts "<div id=\"#{normalize_id(id)}\" class=\"#{class_}\">"
|
|
602
|
+
else
|
|
603
|
+
puts "<div class=\"#{class_}\">"
|
|
604
|
+
end
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
def _table_after(id, caption, opts)
|
|
608
|
+
puts "</div>"
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
def _table_bottom(hline: false)
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
def _table_tr(cells, hline: false)
|
|
615
|
+
if hline
|
|
616
|
+
"<tr class=\"hline\">#{cells.join}</tr>"
|
|
617
|
+
else
|
|
618
|
+
"<tr>#{cells.join}</tr>"
|
|
619
|
+
end
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
public
|
|
623
|
+
|
|
624
|
+
## //imgtable
|
|
625
|
+
def imgtable(lines, id, caption=nil, option=nil)
|
|
626
|
+
super
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
protected
|
|
630
|
+
|
|
631
|
+
def _render_imgtable(id, caption, opts)
|
|
632
|
+
puts "<div id=\"#{normalize_id(id)}\" class=\"imgtable image\">"
|
|
633
|
+
table_header(id, caption, opts)
|
|
634
|
+
puts " <div>"
|
|
635
|
+
yield
|
|
636
|
+
puts " </div>"
|
|
637
|
+
puts "</div>"
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
def _render_imgtable_caption(caption)
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
def _render_imgtable_label(id)
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
public
|
|
647
|
+
|
|
648
|
+
#### インライン命令
|
|
649
|
+
|
|
650
|
+
def inline_fn(id)
|
|
651
|
+
@_fn_count ||= 0
|
|
652
|
+
@_fn_labels ||= {}
|
|
653
|
+
n = (@_fn_count += 1)
|
|
654
|
+
@_fn_labels[id] = n
|
|
655
|
+
return "[^#{n}]"
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
## 改段落(箇条書き内では空行を入れられないため)
|
|
659
|
+
def inline_par(arg)
|
|
660
|
+
#blank()
|
|
661
|
+
"<br>"
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
## ファイル名
|
|
665
|
+
def inline_file(str)
|
|
666
|
+
"`#{str}`"
|
|
667
|
+
end
|
|
668
|
+
def on_inline_file
|
|
669
|
+
"`#{yield}`"
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
## ユーザ入力
|
|
673
|
+
def inline_userinput(str)
|
|
674
|
+
str
|
|
675
|
+
end
|
|
676
|
+
def on_inline_userinput
|
|
677
|
+
yield
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
## 引数をそのまま表示 (No Operation)
|
|
681
|
+
def inline_nop(str)
|
|
682
|
+
str || ""
|
|
683
|
+
end
|
|
684
|
+
alias inline_letitgo inline_nop
|
|
685
|
+
|
|
686
|
+
## 目立たせない(@<strong>{} の反対)
|
|
687
|
+
def inline_weak(str)
|
|
688
|
+
str
|
|
689
|
+
end
|
|
690
|
+
def on_inline_weak
|
|
691
|
+
yield
|
|
692
|
+
end
|
|
693
|
+
|
|
694
|
+
## 文字を小さくする
|
|
695
|
+
def inline_small(str); str; end
|
|
696
|
+
def inline_xsmall(str); str; end
|
|
697
|
+
def inline_xxsmall(str); str; end
|
|
698
|
+
def on_inline_small(); yield; end
|
|
699
|
+
def on_inline_xsmall(); yield; end
|
|
700
|
+
def on_inline_xxsmall(); yield; end
|
|
701
|
+
|
|
702
|
+
## 文字を大きくする
|
|
703
|
+
def inline_large(str); str; end
|
|
704
|
+
def inline_xlarge(str); str; end
|
|
705
|
+
def inline_xxlarge(str); str; end
|
|
706
|
+
def on_inline_large(); yield; end
|
|
707
|
+
def on_inline_xlarge(); yield; end
|
|
708
|
+
def on_inline_xxlarge(); yield; end
|
|
709
|
+
|
|
710
|
+
## 文字を大きくした@<strong>{}
|
|
711
|
+
def inline_strong(str); str; end
|
|
712
|
+
def inline_xstrong(str); str; end
|
|
713
|
+
def inline_xxstrong(str); str; end
|
|
714
|
+
def on_inline_strong(); yield; end
|
|
715
|
+
def on_inline_xstrong(); yield; end
|
|
716
|
+
def on_inline_xxstrong(); yield; end
|
|
717
|
+
|
|
718
|
+
## コードブロック中で折り返し箇所を手動で指定する
|
|
719
|
+
def inline_foldhere(arg)
|
|
720
|
+
""
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
## ターミナルでのカーソル(背景が白、文字が黒)
|
|
724
|
+
def inline_cursor(str)
|
|
725
|
+
"[#{str}]"
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
## nestable inline commands
|
|
729
|
+
|
|
730
|
+
def on_inline_i() ; "*#{yield}*" ; end
|
|
731
|
+
#def on_inline_b() ; "**#{yield}**" ; end
|
|
732
|
+
#def on_inline_code() ; "`#{yield}`" ; end
|
|
733
|
+
def on_inline_tt() ; "<tt>#{yield}</tt>" ; end
|
|
734
|
+
def on_inline_del() ; "~~#{yield}~~" ; end
|
|
735
|
+
def on_inline_sub() ; "<sub>#{yield}</sub>" ; end
|
|
736
|
+
def on_inline_sup() ; "<sup>#{yield}</sup>" ; end
|
|
737
|
+
def on_inline_em() ; "<em>#{yield}</em>" ; end
|
|
738
|
+
def on_inline_strong(); "**#{yield}**" ; end
|
|
739
|
+
def on_inline_u() ; "<u>#{yield}</u>" ; end
|
|
740
|
+
def on_inline_ami() ; "<span class=\"ami\">#{yield}</span>"; end
|
|
741
|
+
def on_inline_balloon(); "← #{yield}"; end
|
|
742
|
+
|
|
743
|
+
def on_inline_b()
|
|
744
|
+
if within_codeblock?()
|
|
745
|
+
#"<b>#{yield}</b>"
|
|
746
|
+
yield
|
|
747
|
+
else
|
|
748
|
+
"**#{yield}**"
|
|
749
|
+
end
|
|
750
|
+
end
|
|
751
|
+
|
|
752
|
+
def on_inline_code()
|
|
753
|
+
with_context(:code) do
|
|
754
|
+
return "`#{yield}`"
|
|
755
|
+
end
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
## 「“」と「”」で囲む
|
|
759
|
+
def on_inline_qq()
|
|
760
|
+
"“#{yield}”"
|
|
761
|
+
end
|
|
762
|
+
|
|
763
|
+
def build_inline_href(url, escaped_label) # compile_href()をベースに改造
|
|
764
|
+
if escaped_label.present?
|
|
765
|
+
"[#{escaped_label}](#{url})"
|
|
766
|
+
else
|
|
767
|
+
url
|
|
768
|
+
end
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
def inline_hlink(str)
|
|
772
|
+
url, label = str.split(/, /, 2)
|
|
773
|
+
flag_link = @book.config['externallink']
|
|
774
|
+
return _inline_hyperlink(url, escape(label), flag_link)
|
|
775
|
+
end
|
|
776
|
+
|
|
777
|
+
def _inline_hyperlink(url, escaped_label, flag_link)
|
|
778
|
+
if flag_link
|
|
779
|
+
label = escaped_label || url
|
|
780
|
+
"<a href=\"#{url}\">#{label}</a>"
|
|
781
|
+
elsif escaped_label
|
|
782
|
+
I18n.t('external_link', [escaped_label, url])
|
|
783
|
+
else
|
|
784
|
+
escape_html(url)
|
|
785
|
+
end
|
|
786
|
+
end
|
|
787
|
+
private :_inline_hyperlink
|
|
788
|
+
|
|
789
|
+
def build_inline_ruby(escaped_word, escaped_yomi) # compile_ruby()をベースに改造
|
|
790
|
+
"#{escaped_word}(#{escaped_yomi})"
|
|
791
|
+
end
|
|
792
|
+
|
|
793
|
+
protected
|
|
794
|
+
|
|
795
|
+
## ノートを参照する
|
|
796
|
+
def build_noteref(chapter, label, caption)
|
|
797
|
+
"ノート「#{compile_inline(caption||'')}」"
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
## 数式を参照する
|
|
801
|
+
def build_eq(chapter, label, number)
|
|
802
|
+
s = "#{I18n.t('equation')}#{chapter.number}.#{number}"
|
|
803
|
+
"<a>#{escape(s)}</a>"
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
public
|
|
807
|
+
|
|
808
|
+
##########
|
|
809
|
+
|
|
810
|
+
def noindent()
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
def clearpage
|
|
814
|
+
blank2()
|
|
815
|
+
end
|
|
816
|
+
|
|
817
|
+
def on_flushright_block()
|
|
818
|
+
blank()
|
|
819
|
+
puts "[flushright]"; twospaces()
|
|
820
|
+
yield
|
|
821
|
+
truncate_blank(); twospaces()
|
|
822
|
+
puts "[/flushright]"
|
|
823
|
+
blank()
|
|
824
|
+
end
|
|
825
|
+
|
|
826
|
+
def on_centering_block()
|
|
827
|
+
blank()
|
|
828
|
+
puts "[centering]"; twospaces()
|
|
829
|
+
yield
|
|
830
|
+
truncate_blank(); twospaces()
|
|
831
|
+
puts "[/centering]"
|
|
832
|
+
blank()
|
|
833
|
+
end
|
|
834
|
+
|
|
835
|
+
def on_center_block()
|
|
836
|
+
blank()
|
|
837
|
+
puts "[center]"; twospaces()
|
|
838
|
+
yield
|
|
839
|
+
truncate_blank(); twospaces()
|
|
840
|
+
puts "[/center]"
|
|
841
|
+
blank()
|
|
842
|
+
end
|
|
843
|
+
|
|
844
|
+
def on_textleft_block()
|
|
845
|
+
blank()
|
|
846
|
+
puts "[textleft]"; twospaces()
|
|
847
|
+
yield
|
|
848
|
+
truncate_blank(); twospaces()
|
|
849
|
+
puts "[/textleft]"
|
|
850
|
+
blank()
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
def on_textright_block()
|
|
854
|
+
blank()
|
|
855
|
+
puts "[textright]"; twospaces()
|
|
856
|
+
yield
|
|
857
|
+
truncate_blank(); twospaces()
|
|
858
|
+
puts "[/textright]"
|
|
859
|
+
blank()
|
|
860
|
+
end
|
|
861
|
+
|
|
862
|
+
def on_textcenter_block()
|
|
863
|
+
blank()
|
|
864
|
+
puts "[textcenter]"; twospaces()
|
|
865
|
+
yield
|
|
866
|
+
truncate_blank(); twospaces()
|
|
867
|
+
puts "[/textcenter]"
|
|
868
|
+
blank()
|
|
869
|
+
end
|
|
870
|
+
|
|
871
|
+
def sampleoutputbegin(caption=nil)
|
|
872
|
+
blank()
|
|
873
|
+
if caption.present?
|
|
874
|
+
puts "<span class=\"caption\">▽#{compile_inline(caption)}</span>"
|
|
875
|
+
blank()
|
|
876
|
+
end
|
|
877
|
+
puts "----------------------------------------"
|
|
878
|
+
blank()
|
|
879
|
+
end
|
|
880
|
+
|
|
881
|
+
def sampleoutputend()
|
|
882
|
+
blank()
|
|
883
|
+
puts "----------------------------------------"
|
|
884
|
+
blank()
|
|
885
|
+
end
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
def on_inline_B()
|
|
889
|
+
"**#{yield}**"
|
|
890
|
+
end
|
|
891
|
+
|
|
892
|
+
def inline_br(_)
|
|
893
|
+
"<br>"
|
|
894
|
+
end
|
|
895
|
+
|
|
896
|
+
def inline_clearpage(_)
|
|
897
|
+
blank2()
|
|
898
|
+
end
|
|
899
|
+
|
|
900
|
+
def inline_m(str)
|
|
901
|
+
"$#{str}$"
|
|
902
|
+
end
|
|
903
|
+
|
|
904
|
+
def inline_icon(imagefile)
|
|
905
|
+
filepath = find_image_filepath(imagefile)
|
|
906
|
+
"<img src=\"#{filepath}\">"
|
|
907
|
+
end
|
|
908
|
+
|
|
909
|
+
def inline_par(arg)
|
|
910
|
+
"\n\n"
|
|
911
|
+
end
|
|
912
|
+
|
|
913
|
+
def inline_hd_chap(chap, id)
|
|
914
|
+
n = chap.headline_index.number(id)
|
|
915
|
+
if chap.number and @book.config['secnolevel'] >= n.split('.').size
|
|
916
|
+
str = I18n.t('chapter_quote', "#{n} #{compile_inline(chap.headline(id).caption)}")
|
|
917
|
+
else
|
|
918
|
+
str = I18n.t('chapter_quote', compile_inline(chap.headline(id).caption))
|
|
919
|
+
end
|
|
920
|
+
if @book.config['chapterlink']
|
|
921
|
+
anchor = 'h' + n.gsub('.', '-')
|
|
922
|
+
%Q(<a href="#{chap.id}#{extname}##{anchor}">#{str}</a>)
|
|
923
|
+
else
|
|
924
|
+
str
|
|
925
|
+
end
|
|
926
|
+
rescue KeyError
|
|
927
|
+
error "unknown headline: #{id}"
|
|
928
|
+
end
|
|
929
|
+
|
|
930
|
+
def inline_TeX(_)
|
|
931
|
+
"TeX"
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
def inline_LaTeX(_)
|
|
935
|
+
"LaTeX"
|
|
936
|
+
end
|
|
937
|
+
|
|
938
|
+
def inline_hearts(_)
|
|
939
|
+
":heart:"
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
end
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
end
|