review-retrovert 0.9.11 → 0.10.0

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.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +1 -1
  3. data/.pinact.yaml +12 -0
  4. data/.ruby-version +1 -1
  5. data/Dockerfile +2 -1
  6. data/Dockerfile.local +13 -0
  7. data/Gemfile.lock +62 -35
  8. data/Rakefile +9 -0
  9. data/aqua.yaml +20 -0
  10. data/hooks/post_push +14 -1
  11. data/lib/review/retrovert/cli.rb +6 -0
  12. data/lib/review/retrovert/converter.rb +38 -0
  13. data/lib/review/retrovert/version.rb +1 -1
  14. data/lib/review/retrovert/yamlconfig.rb +38 -1
  15. data/review-retrovert.gemspec +18 -4
  16. data/zizmor.yml +5 -0
  17. metadata +53 -127
  18. data/.github/FUNDING.yml +0 -4
  19. data/.github/workflows/docker-build.yml +0 -26
  20. data/.github/workflows/release.yml +0 -26
  21. data/.github/workflows/retrovert.yml +0 -91
  22. data/testdata/mybook/.gitignore +0 -13
  23. data/testdata/mybook/.textlintrc +0 -11
  24. data/testdata/mybook/README.md +0 -43
  25. data/testdata/mybook/Rakefile +0 -24
  26. data/testdata/mybook/catalog.yml +0 -60
  27. data/testdata/mybook/config-noretrovert.yml +0 -404
  28. data/testdata/mybook/config-retrovert.yml +0 -16
  29. data/testdata/mybook/config-starter.yml +0 -264
  30. data/testdata/mybook/config.yml +0 -404
  31. data/testdata/mybook/contents/00-preface.re +0 -129
  32. data/testdata/mybook/contents/01-install.re +0 -305
  33. data/testdata/mybook/contents/02-tutorial.re +0 -1228
  34. data/testdata/mybook/contents/03-syntax.re +0 -4610
  35. data/testdata/mybook/contents/04-customize.re +0 -1064
  36. data/testdata/mybook/contents/05-faq.re +0 -606
  37. data/testdata/mybook/contents/06-bestpractice.re +0 -1343
  38. data/testdata/mybook/contents/91-compare.re +0 -418
  39. data/testdata/mybook/contents/92-filelist.re +0 -125
  40. data/testdata/mybook/contents/93-background.re +0 -267
  41. data/testdata/mybook/contents/99-postface.re +0 -39
  42. data/testdata/mybook/contents/r0-inner.re +0 -2
  43. data/testdata/mybook/contents/r0-root.re +0 -49
  44. data/testdata/mybook/contents/table.csv +0 -4
  45. data/testdata/mybook/contents/test.txt +0 -1
  46. data/testdata/mybook/contents/ut.re +0 -5
  47. data/testdata/mybook/css/normalize.css +0 -349
  48. data/testdata/mybook/css/webstyle.css +0 -692
  49. data/testdata/mybook/data/terms.txt +0 -3
  50. data/testdata/mybook/data/words.txt +0 -15
  51. data/testdata/mybook/images/03-syntax/favicon-16x16.png +0 -0
  52. data/testdata/mybook/images/03-syntax/figure_heretop.png +0 -0
  53. data/testdata/mybook/images/03-syntax/index-page.png +0 -0
  54. data/testdata/mybook/images/03-syntax/order-detail.png +0 -0
  55. data/testdata/mybook/images/03-syntax/tw-icon1.jpg +0 -0
  56. data/testdata/mybook/images/03-syntax/tw-icon2.jpg +0 -0
  57. data/testdata/mybook/images/03-syntax/tw-icon3.jpg +0 -0
  58. data/testdata/mybook/images/03-syntax/tw-icon4.jpg +0 -0
  59. data/testdata/mybook/images/04-customize/caption_pagebreak.png +0 -0
  60. data/testdata/mybook/images/04-customize/chaptitlepage_sample.png +0 -0
  61. data/testdata/mybook/images/04-customize/section_decoration_samples.png +0 -0
  62. data/testdata/mybook/images/05-faq/codeblock_rpadding1.png +0 -0
  63. data/testdata/mybook/images/05-faq/codeblock_rpadding2.png +0 -0
  64. data/testdata/mybook/images/05-faq/dummy-image.png +0 -0
  65. data/testdata/mybook/images/06-bestpractice/figure_heretop.png +0 -0
  66. data/testdata/mybook/images/06-bestpractice/font_beramono.png +0 -0
  67. data/testdata/mybook/images/06-bestpractice/heading_design1.png +0 -0
  68. data/testdata/mybook/images/06-bestpractice/heading_design2.png +0 -0
  69. data/testdata/mybook/images/06-bestpractice/margin_book.png +0 -0
  70. data/testdata/mybook/images/06-bestpractice/multiline-title.png +0 -0
  71. data/testdata/mybook/images/06-bestpractice/preface_numbered.png +0 -0
  72. data/testdata/mybook/images/06-bestpractice/program_border.png +0 -0
  73. data/testdata/mybook/images/06-bestpractice/sechead_design_4.png +0 -0
  74. data/testdata/mybook/images/06-bestpractice/section_title_wlines.png +0 -0
  75. data/testdata/mybook/images/06-bestpractice/titlepage-samples.png +0 -0
  76. data/testdata/mybook/images/93-background/bug913.png +0 -0
  77. data/testdata/mybook/images/93-background/slide2.png +0 -0
  78. data/testdata/mybook/images/avatar-b.png +0 -0
  79. data/testdata/mybook/images/avatar-g.png +0 -0
  80. data/testdata/mybook/images/avatar-r.png +0 -0
  81. data/testdata/mybook/images/caution-icon.png +0 -0
  82. data/testdata/mybook/images/cover_a5.pdf +0 -0
  83. data/testdata/mybook/images/cover_b5.pdf +0 -0
  84. data/testdata/mybook/images/info-icon.png +0 -0
  85. data/testdata/mybook/images/tw-icon.jpg +0 -0
  86. data/testdata/mybook/images/warning-icon.png +0 -0
  87. data/testdata/mybook/layouts/layout.epub.erb +0 -29
  88. data/testdata/mybook/layouts/layout.html5.erb +0 -108
  89. data/testdata/mybook/layouts/layout.tex.erb +0 -432
  90. data/testdata/mybook/layouts/layout.tex.erb.orig +0 -386
  91. data/testdata/mybook/lib/hooks/beforetexcompile.rb +0 -55
  92. data/testdata/mybook/lib/ruby/review-book.rb +0 -64
  93. data/testdata/mybook/lib/ruby/review-builder.rb +0 -1342
  94. data/testdata/mybook/lib/ruby/review-cli.rb +0 -58
  95. data/testdata/mybook/lib/ruby/review-compiler.rb +0 -1176
  96. data/testdata/mybook/lib/ruby/review-epubbuilder.rb +0 -33
  97. data/testdata/mybook/lib/ruby/review-epubmaker.rb +0 -609
  98. data/testdata/mybook/lib/ruby/review-htmlbuilder.rb +0 -949
  99. data/testdata/mybook/lib/ruby/review-latexbuilder.rb +0 -1065
  100. data/testdata/mybook/lib/ruby/review-maker.rb +0 -346
  101. data/testdata/mybook/lib/ruby/review-markdownbuilder.rb +0 -945
  102. data/testdata/mybook/lib/ruby/review-markdownmaker.rb +0 -91
  103. data/testdata/mybook/lib/ruby/review-monkeypatch.rb +0 -93
  104. data/testdata/mybook/lib/ruby/review-pdfmaker.rb +0 -546
  105. data/testdata/mybook/lib/ruby/review-textbuilder.rb +0 -36
  106. data/testdata/mybook/lib/ruby/review-tocparser.rb +0 -285
  107. data/testdata/mybook/lib/ruby/review-webmaker.rb +0 -448
  108. data/testdata/mybook/lib/tasks/mytasks.rake +0 -31
  109. data/testdata/mybook/lib/tasks/review.rake +0 -156
  110. data/testdata/mybook/lib/tasks/review.rake.orig +0 -72
  111. data/testdata/mybook/lib/tasks/starter.rake +0 -470
  112. data/testdata/mybook/locale.yml +0 -6
  113. data/testdata/mybook/review-ext.rb +0 -206
  114. data/testdata/mybook/sty/indexstyle.ist +0 -25
  115. data/testdata/mybook/sty/jumoline.sty +0 -310
  116. data/testdata/mybook/sty/mycolophon.sty +0 -81
  117. data/testdata/mybook/sty/mystyle.sty +0 -8
  118. data/testdata/mybook/sty/mytextsize.sty +0 -94
  119. data/testdata/mybook/sty/mytitlepage.sty +0 -126
  120. data/testdata/mybook/sty/review-base.sty +0 -276
  121. data/testdata/mybook/sty/reviewmacro.sty +0 -60
  122. data/testdata/mybook/sty/starter-codeblock.sty +0 -463
  123. data/testdata/mybook/sty/starter-color.sty +0 -134
  124. data/testdata/mybook/sty/starter-font.sty +0 -112
  125. data/testdata/mybook/sty/starter-heading.sty +0 -561
  126. data/testdata/mybook/sty/starter-misc.sty +0 -894
  127. data/testdata/mybook/sty/starter-note.sty +0 -180
  128. data/testdata/mybook/sty/starter-section.sty +0 -262
  129. data/testdata/mybook/sty/starter-talklist.sty +0 -105
  130. data/testdata/mybook/sty/starter-toc.sty +0 -72
  131. data/testdata/mybook/sty/starter-util.sty +0 -39
  132. data/testdata/mybook/sty/starter.sty +0 -36
  133. data/testdata/mybook/sty/ut.sty +0 -26
  134. data/testdata/mybook/style.css +0 -597
  135. data/testdata/mybook/ut-catalog.yml +0 -61
  136. data/testdata/mybook/ut-config-starter.yml +0 -3
  137. data/testdata/mybook/ut-config.yml +0 -404
@@ -1,1176 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- ###
4
- ### ReVIEW::Compilerクラスとその関連クラスを拡張する
5
- ###
6
-
7
- require 'set'
8
- require 'review/compiler'
9
-
10
-
11
- module ReVIEW
12
-
13
- defined?(Compiler) or raise "internal error: Compiler not found."
14
-
15
-
16
- class Compiler
17
-
18
- #------------------------------ original code
19
-
20
- =begin
21
-
22
- def initialize(strategy)
23
- @strategy = strategy
24
- end
25
-
26
- attr_reader :strategy
27
-
28
- def compile(chap)
29
- @chapter = chap
30
- do_compile
31
- @strategy.result
32
- end
33
-
34
- class SyntaxElement
35
- def initialize(name, type, argc, &block)
36
- @name = name
37
- @type = type
38
- @argc_spec = argc
39
- @checker = block
40
- end
41
-
42
- attr_reader :name
43
-
44
- def check_args(args)
45
- unless @argc_spec === args.size
46
- raise CompileError, "wrong # of parameters (block command //#{@name}, expect #{@argc_spec} but #{args.size})"
47
- end
48
- if @checker
49
- @checker.call(*args)
50
- end
51
- end
52
-
53
- def min_argc
54
- case @argc_spec
55
- when Range then @argc_spec.begin
56
- when Integer then @argc_spec
57
- else
58
- raise TypeError, "argc_spec is not Range/Integer: #{inspect}"
59
- end
60
- end
61
-
62
- def block_required?
63
- @type == :block
64
- end
65
-
66
- def block_allowed?
67
- @type == :block or @type == :optional
68
- end
69
- end
70
-
71
- SYNTAX = {}
72
-
73
- def self.defblock(name, argc, optional = false, &block)
74
- defsyntax name, (optional ? :optional : :block), argc, &block
75
- end
76
-
77
- def self.defsingle(name, argc, &block)
78
- defsyntax name, :line, argc, &block
79
- end
80
-
81
- def self.defsyntax(name, type, argc, &block)
82
- SYNTAX[name] = SyntaxElement.new(name, type, argc, &block)
83
- end
84
-
85
- def self.definline(name)
86
- INLINE[name] = InlineSyntaxElement.new(name)
87
- end
88
-
89
- def syntax_defined?(name)
90
- SYNTAX.key?(name.to_sym)
91
- end
92
-
93
- def syntax_descriptor(name)
94
- SYNTAX[name.to_sym]
95
- end
96
-
97
- class InlineSyntaxElement
98
- def initialize(name)
99
- @name = name
100
- end
101
-
102
- attr_reader :name
103
- end
104
-
105
- INLINE = {}
106
-
107
- def inline_defined?(name)
108
- INLINE.key?(name.to_sym)
109
- end
110
-
111
- defblock :read, 0
112
- defblock :lead, 0
113
- defblock :list, 2..3
114
- defblock :emlist, 0..2
115
- defblock :cmd, 0..1
116
- defblock :table, 0..2
117
- defblock :imgtable, 0..2
118
- defblock :emtable, 0..1
119
- defblock :quote, 0
120
- defblock :image, 2..3, true
121
- defblock :source, 0..2
122
- defblock :listnum, 2..3
123
- defblock :emlistnum, 0..2
124
- defblock :bibpaper, 2..3, true
125
- defblock :doorquote, 1
126
- defblock :talk, 0
127
- defblock :texequation, 0
128
- defblock :graph, 1..3
129
- defblock :indepimage, 1..3, true
130
- defblock :numberlessimage, 1..3, true
131
-
132
- defblock :address, 0
133
- defblock :blockquote, 0
134
- defblock :bpo, 0
135
- defblock :flushright, 0
136
- defblock :centering, 0
137
- defblock :note, 0..1
138
- defblock :memo, 0..1
139
- defblock :info, 0..1
140
- defblock :important, 0..1
141
- defblock :caution, 0..1
142
- defblock :notice, 0..1
143
- defblock :warning, 0..1
144
- defblock :tip, 0..1
145
- defblock :box, 0..1
146
- defblock :comment, 0..1, true
147
- defblock :embed, 0..1
148
-
149
- defsingle :footnote, 2
150
- defsingle :noindent, 0
151
- defsingle :blankline, 0
152
- defsingle :pagebreak, 0
153
- defsingle :hr, 0
154
- defsingle :parasep, 0
155
- defsingle :label, 1
156
- defsingle :raw, 1
157
- defsingle :tsize, 1
158
- defsingle :include, 1
159
- defsingle :olnum, 1
160
- defsingle :firstlinenum, 1
161
-
162
- definline :chapref
163
- definline :chap
164
- definline :title
165
- definline :img
166
- definline :imgref
167
- definline :icon
168
- definline :list
169
- definline :table
170
- definline :fn
171
- definline :kw
172
- definline :ruby
173
- definline :bou
174
- definline :ami
175
- definline :b
176
- definline :dtp
177
- definline :code
178
- definline :bib
179
- definline :hd
180
- definline :href
181
- definline :recipe
182
- definline :column
183
- definline :tcy
184
-
185
- definline :abbr
186
- definline :acronym
187
- definline :cite
188
- definline :dfn
189
- definline :em
190
- definline :kbd
191
- definline :q
192
- definline :samp
193
- definline :strong
194
- definline :var
195
- definline :big
196
- definline :small
197
- definline :del
198
- definline :ins
199
- definline :sup
200
- definline :sub
201
- definline :tt
202
- definline :i
203
- definline :tti
204
- definline :ttb
205
- definline :u
206
- definline :raw
207
- definline :br
208
- definline :m
209
- definline :uchar
210
- definline :idx
211
- definline :hidx
212
- definline :comment
213
- definline :include
214
- definline :tcy
215
- definline :embed
216
- definline :pageref
217
-
218
- private
219
-
220
- def do_compile
221
- f = LineInput.new(StringIO.new(@chapter.content))
222
- @strategy.bind self, @chapter, Location.new(@chapter.basename, f)
223
- tagged_section_init
224
- while f.next?
225
- case f.peek
226
- when /\A\#@/
227
- f.gets # Nothing to do
228
- when /\A=+[\[\s\{]/
229
- compile_headline f.gets
230
- when /\A\s+\*/
231
- compile_ulist f
232
- when /\A\s+\d+\./
233
- compile_olist f
234
- when /\A\s*:\s/
235
- compile_dlist f
236
- when %r{\A//\}}
237
- f.gets
238
- error 'block end seen but not opened'
239
- when %r{\A//[a-z]+}
240
- name, args, lines = read_command(f)
241
- syntax = syntax_descriptor(name)
242
- unless syntax
243
- error "unknown command: //#{name}"
244
- compile_unknown_command args, lines
245
- next
246
- end
247
- compile_command syntax, args, lines
248
- when %r{\A//}
249
- line = f.gets
250
- warn "`//' seen but is not valid command: #{line.strip.inspect}"
251
- if block_open?(line)
252
- warn 'skipping block...'
253
- read_block(f, false)
254
- end
255
- else
256
- if f.peek.strip.empty?
257
- f.gets
258
- next
259
- end
260
- compile_paragraph f
261
- end
262
- end
263
- close_all_tagged_section
264
- end
265
-
266
- def compile_headline(line)
267
- @headline_indexs ||= [@chapter.number.to_i - 1]
268
- m = /\A(=+)(?:\[(.+?)\])?(?:\{(.+?)\})?(.*)/.match(line)
269
- level = m[1].size
270
- tag = m[2]
271
- label = m[3]
272
- caption = m[4].strip
273
- index = level - 1
274
- if tag
275
- if tag !~ %r{\A/}
276
- if caption.empty?
277
- warn 'headline is empty.'
278
- end
279
- close_current_tagged_section(level)
280
- open_tagged_section(tag, level, label, caption)
281
- else
282
- open_tag = tag[1..-1]
283
- prev_tag_info = @tagged_section.pop
284
- if prev_tag_info.nil? || prev_tag_info.first != open_tag
285
- error "#{open_tag} is not opened."
286
- end
287
- close_tagged_section(*prev_tag_info)
288
- end
289
- else
290
- if caption.empty?
291
- warn 'headline is empty.'
292
- end
293
- if @headline_indexs.size > (index + 1)
294
- @headline_indexs = @headline_indexs[0..index]
295
- end
296
- if @headline_indexs[index].nil?
297
- @headline_indexs[index] = 0
298
- end
299
- @headline_indexs[index] += 1
300
- close_current_tagged_section(level)
301
- @strategy.headline level, label, caption
302
- end
303
- end
304
-
305
- def close_current_tagged_section(level)
306
- while @tagged_section.last and @tagged_section.last[1] >= level
307
- close_tagged_section(* @tagged_section.pop)
308
- end
309
- end
310
-
311
- def headline(level, label, caption)
312
- @strategy.headline level, label, caption
313
- end
314
-
315
- def tagged_section_init
316
- @tagged_section = []
317
- end
318
-
319
- def open_tagged_section(tag, level, label, caption)
320
- mid = "#{tag}_begin"
321
- unless @strategy.respond_to?(mid)
322
- error "strategy does not support tagged section: #{tag}"
323
- headline level, label, caption
324
- return
325
- end
326
- @tagged_section.push [tag, level]
327
- @strategy.__send__ mid, level, label, caption
328
- end
329
-
330
- def close_tagged_section(tag, level)
331
- mid = "#{tag}_end"
332
- if @strategy.respond_to?(mid)
333
- @strategy.__send__ mid, level
334
- else
335
- error "strategy does not support block op: #{mid}"
336
- end
337
- end
338
-
339
- def close_all_tagged_section
340
- until @tagged_section.empty?
341
- close_tagged_section(* @tagged_section.pop)
342
- end
343
- end
344
-
345
- def compile_ulist(f)
346
- level = 0
347
- f.while_match(/\A\s+\*|\A\#@/) do |line|
348
- next if line =~ /\A\#@/
349
-
350
- buf = [text(line.sub(/\*+/, '').strip)]
351
- f.while_match(/\A\s+(?!\*)\S/) do |cont|
352
- buf.push text(cont.strip)
353
- end
354
-
355
- line =~ /\A\s+(\*+)/
356
- current_level = $1.size
357
- if level == current_level
358
- @strategy.ul_item_end
359
- # body
360
- @strategy.ul_item_begin buf
361
- elsif level < current_level # down
362
- level_diff = current_level - level
363
- level = current_level
364
- (1..(level_diff - 1)).to_a.reverse_each do |i|
365
- @strategy.ul_begin { i }
366
- @strategy.ul_item_begin []
367
- end
368
- @strategy.ul_begin { level }
369
- @strategy.ul_item_begin buf
370
- elsif level > current_level # up
371
- level_diff = level - current_level
372
- level = current_level
373
- (1..level_diff).to_a.reverse_each do |i|
374
- @strategy.ul_item_end
375
- @strategy.ul_end { level + i }
376
- end
377
- @strategy.ul_item_end
378
- # body
379
- @strategy.ul_item_begin buf
380
- end
381
- end
382
-
383
- (1..level).to_a.reverse_each do |i|
384
- @strategy.ul_item_end
385
- @strategy.ul_end { i }
386
- end
387
- end
388
-
389
- def compile_olist(f)
390
- @strategy.ol_begin
391
- f.while_match(/\A\s+\d+\.|\A\#@/) do |line|
392
- next if line =~ /\A\#@/
393
-
394
- num = line.match(/(\d+)\./)[1]
395
- buf = [text(line.sub(/\d+\./, '').strip)]
396
- f.while_match(/\A\s+(?!\d+\.)\S/) do |cont|
397
- buf.push text(cont.strip)
398
- end
399
- @strategy.ol_item buf, num
400
- end
401
- @strategy.ol_end
402
- end
403
-
404
- def compile_dlist(f)
405
- @strategy.dl_begin
406
- while /\A\s*:/ =~ f.peek
407
- @strategy.dt text(f.gets.sub(/\A\s*:/, '').strip)
408
- desc = f.break(/\A(\S|\s*:|\s+\d+\.\s|\s+\*\s)/).map { |line| text(line.strip) }
409
- @strategy.dd(desc)
410
- f.skip_blank_lines
411
- f.skip_comment_lines
412
- end
413
- @strategy.dl_end
414
- end
415
-
416
- def compile_paragraph(f)
417
- buf = []
418
- f.until_match(%r{\A//|\A\#@}) do |line|
419
- break if line.strip.empty?
420
- buf.push text(line.sub(/^(\t+)\s*/) { |m| '<!ESCAPETAB!>' * m.size }.strip.gsub('<!ESCAPETAB!>', "\t"))
421
- end
422
- @strategy.paragraph buf
423
- end
424
-
425
- def read_command(f)
426
- line = f.gets
427
- name = line.slice(/[a-z]+/).to_sym
428
- ignore_inline = (name == :embed)
429
- args = parse_args(line.sub(%r{\A//[a-z]+}, '').rstrip.chomp('{'), name)
430
- @strategy.doc_status[name] = true
431
- lines = block_open?(line) ? read_block(f, ignore_inline) : nil
432
- @strategy.doc_status[name] = nil
433
- [name, args, lines]
434
- end
435
-
436
- def block_open?(line)
437
- line.rstrip[-1, 1] == '{'
438
- end
439
-
440
- def read_block(f, ignore_inline)
441
- head = f.lineno
442
- buf = []
443
- f.until_match(%r{\A//\}}) do |line|
444
- if ignore_inline
445
- buf.push line
446
- elsif line !~ /\A\#@/
447
- buf.push text(line.rstrip)
448
- end
449
- end
450
- unless %r{\A//\}} =~ f.peek
451
- error "unexpected EOF (block begins at: #{head})"
452
- return buf
453
- end
454
- f.gets # discard terminator
455
- buf
456
- end
457
-
458
- def parse_args(str, _name = nil)
459
- return [] if str.empty?
460
- scanner = StringScanner.new(str)
461
- words = []
462
- while word = scanner.scan(/(\[\]|\[.*?[^\\]\])/)
463
- w2 = word[1..-2].gsub(/\\(.)/) do
464
- ch = $1
465
- (ch == ']' or ch == '\\') ? ch : '\\' + ch
466
- end
467
- words << w2
468
- end
469
- unless scanner.eos?
470
- error "argument syntax error: #{scanner.rest} in #{str.inspect}"
471
- return []
472
- end
473
- words
474
- end
475
-
476
- def compile_command(syntax, args, lines)
477
- unless @strategy.respond_to?(syntax.name)
478
- error "strategy does not support command: //#{syntax.name}"
479
- compile_unknown_command args, lines
480
- return
481
- end
482
- begin
483
- syntax.check_args args
484
- rescue CompileError => err
485
- error err.message
486
- args = ['(NoArgument)'] * syntax.min_argc
487
- end
488
- if syntax.block_allowed?
489
- compile_block syntax, args, lines
490
- else
491
- if lines
492
- error "block is not allowed for command //#{syntax.name}; ignore"
493
- end
494
- compile_single syntax, args
495
- end
496
- end
497
-
498
- def compile_unknown_command(args, lines)
499
- @strategy.unknown_command args, lines
500
- end
501
-
502
- def compile_block(syntax, args, lines)
503
- @strategy.__send__(syntax.name, (lines || default_block(syntax)), *args)
504
- end
505
-
506
- def default_block(syntax)
507
- if syntax.block_required?
508
- error "block is required for //#{syntax.name}; use empty block"
509
- end
510
- []
511
- end
512
-
513
- def compile_single(syntax, args)
514
- @strategy.__send__(syntax.name, *args)
515
- end
516
-
517
- def replace_fence(str)
518
- str.gsub(/@<(\w+)>([$|])(.+?)(\2)/) do
519
- op = $1
520
- arg = $3.gsub('@', "\x01").gsub('\\}') { '\\\\}' }.gsub('}') { '\}' }.sub(/(?:\\)+$/) { |m| '\\\\' * m.size }
521
- "@<#{op}>{#{arg}}"
522
- end
523
- end
524
-
525
- def text(str)
526
- return '' if str.empty?
527
- words = replace_fence(str).split(/(@<\w+>\{(?:[^\}\\]|\\.)*?\})/, -1)
528
- words.each do |w|
529
- if w.scan(/@<\w+>/).size > 1 && !/\A@<raw>/.match(w)
530
- error "`@<xxx>' seen but is not valid inline op: #{w}"
531
- end
532
- end
533
- result = @strategy.nofunc_text(words.shift)
534
- until words.empty?
535
- result << compile_inline(words.shift.gsub(/\\\}/, '}').gsub(/\\\\/, '\\'))
536
- result << @strategy.nofunc_text(words.shift)
537
- end
538
- result.gsub("\x01", '@')
539
- rescue => err
540
- error err.message
541
- end
542
- public :text # called from strategy
543
-
544
- def compile_inline(str)
545
- op, arg = /\A@<(\w+)>\{(.*?)\}\z/.match(str).captures
546
- unless inline_defined?(op)
547
- raise CompileError, "no such inline op: #{op}"
548
- end
549
- unless @strategy.respond_to?("inline_#{op}")
550
- raise "strategy does not support inline op: @<#{op}>"
551
- end
552
- @strategy.__send__("inline_#{op}", arg)
553
- rescue => err
554
- error err.message
555
- @strategy.nofunc_text(str)
556
- end
557
-
558
- def warn(msg)
559
- @strategy.warn msg
560
- end
561
-
562
- def error(msg)
563
- @strategy.error msg
564
- end
565
-
566
- =end
567
-
568
- #------------------------------
569
-
570
- ## ブロック命令
571
- defblock :program, 0..3 ## プログラム
572
- defblock :terminal, 0..3 ## ターミナル
573
- defblock :output, 0..3 ## 出力結果
574
- defblock :sideimage, 2..3 ## テキストの横に画像を表示
575
- defblock :abstract, 0 ## 章の概要
576
- defblock :chapterauthor, 1 ## 章の著者
577
- defblock :talklist, 0..1 ## 会話リスト
578
- defblock :talk, 1..3, true ## 会話項目
579
- defblock :t, 1..3, true ## 会話項目(ショートカット用)
580
- defblock :desclist, 0..1 ## キーと説明文のリスト
581
- defblock :desc, 1..2, true ## キーと説明文のリスト
582
- defblock :list, 0..3 ## (上書き)
583
- defblock :listnum, 0..3 ## (上書き)
584
- defblock :note, 0..2 ## (上書き)
585
- defblock :texequation, 0..2 ## (上書き)
586
- defblock :table, 0..3 ## (上書き)
587
- defblock :imgtable, 0..3 ## (上書き)
588
-
589
- defsingle :makechaptitlepage, 0..1 ## 章扉をつける
590
- defsingle :needvspace, 2 ## 縦方向のスペースがなければ改ページ
591
- defsingle :paragraphend, 0 ## 段の終わりにスペースを入れる
592
- defsingle :subparagraphend, 0## 小段の終わりにスペースを入れる(あれば)
593
- defsingle :vspace, 2 ## 縦方向の空きを入れる(\vspace)
594
- defsingle :addvspace, 2 ## 縦方向の空きを入れる(\addvspace)
595
- defsingle :tsize, 1..2 ## (上書き)
596
-
597
- ## インライン命令
598
- definline :par ## 箇条書き内で改段落するのに使う
599
- definline :balloon ## コード内でのふきだし説明(Re:VIEW3から追加)
600
- definline :eq ## 数式を参照
601
- definline :secref ## 節(Section)や項(Subsection)を参照
602
- definline :noteref ## ノートを参照
603
- definline :hlink ## @<href>{}の代わり
604
- definline :term ## @<idx>{}かつゴシック体
605
- definline :termnoidx ## ゴシック体にするだけで索引には登録しない
606
- definline :file ## ファイル名
607
- definline :userinput ## ユーザ入力
608
- definline :nop ## 引数をそのまま表示 (No Operation)
609
- definline :letitgo ## (nopのエイリアス名)
610
- definline :foldhere ## 折り返し箇所を手動で指定
611
- definline :cursor ## ターミナルでのカーソル
612
- definline :qq ## 「``」と「''」で囲う
613
- definline :weak ## 目立たせない(@<strong>{} の反対)
614
- definline :small ## 文字サイズを小さく
615
- definline :xsmall ## 文字サイズをもっと小さく
616
- definline :xxsmall ## 文字サイズをもっともっと小さく
617
- definline :large ## 文字サイズを大きく
618
- definline :xlarge ## 文字サイズをもっと大きく
619
- definline :xxlarge ## 文字サイズをもっともっと大きく
620
- definline :xstrong ## 文字を大きくした@<strong>{}
621
- definline :xxstrong ## 文字をもっと大きくした@<strong>{}
622
- definline :w ## キーに対応した単語に展開
623
- definline :wb ## キーに対応した単語に展開、かつ太字で表示
624
- definline :W ## キーに対応した単語に展開、かつ強調表示
625
-
626
- private
627
-
628
- ## パーサを再帰呼び出しに対応させる
629
-
630
- def do_compile
631
- f = LineInput.new(StringIO.new(@chapter.content))
632
- @strategy.bind self, @chapter, Location.new(@chapter.basename, f)
633
- tagged_section_init()
634
- parse_document(f, false)
635
- close_all_tagged_section()
636
- end
637
-
638
- BLOCK_END_REXP = /\A\/\/\}\s*$/
639
-
640
- def parse_document(f, block_cmd)
641
- while f.next?
642
- case f.peek
643
- when /\A\#@/
644
- f.gets # Nothing to do
645
- when /\A=+[\[\s\{]/
646
- if block_cmd #+
647
- line = f.gets #+
648
- error "'#{line.strip}': should close '//#{block_cmd}' block before sectioning." #+
649
- end #+
650
- compile_headline f.gets
651
- #when /\A\s+\*/ #-
652
- # compile_ulist f #-
653
- when LIST_ITEM_REXP #+
654
- compile_list(f) #+
655
- when /\A\s+\d+\./
656
- compile_olist f
657
- when /\A\s*:\s/
658
- compile_dlist f
659
- #when %r{\A//\}} #-
660
- when BLOCK_END_REXP #+
661
- return if block_cmd #+
662
- f.gets
663
- #error 'block end seen but not opened' #-
664
- error "'//}': block-end found, but no block command opened." #+
665
- #when %r{\A//[a-z]+} #-
666
- # name, args, lines = read_command(f) #-
667
- # syntax = syntax_descriptor(name) #-
668
- # unless syntax #-
669
- # error "unknown command: //#{name}" #-
670
- # compile_unknown_command args, lines #-
671
- # next #-
672
- # end #-
673
- # compile_command syntax, args, lines #-
674
- when /\A\/\/\w+/ #+
675
- parse_block_command(f) #+
676
- when %r{\A//}
677
- line = f.gets
678
- warn "`//' seen but is not valid command: #{line.strip.inspect}"
679
- if block_open?(line)
680
- warn 'skipping block...'
681
- read_block(f, false)
682
- end
683
- else
684
- if f.peek.strip.empty?
685
- f.gets
686
- next
687
- end
688
- compile_paragraph f
689
- end
690
- end
691
- end
692
-
693
- ## コードブロックのタブ展開を、LaTeXコマンドの展開より先に行うよう変更。
694
- ##
695
- ## ・たとえば '\\' を '\\textbackslash{}' に展開してからタブを空白文字に
696
- ## 展開しても、正しい展開にはならないことは明らか。先にタブを空白文字に
697
- ## 置き換えてから、'\\' を '\\textbackslash{}' に展開すべき。
698
- ## ・またタブ文字の展開は、本来はBuilderではなくCompilerで行うべきだが、
699
- ## Re:VIEWの設計がまずいのでそうなっていない。
700
- ## ・'//table' と '//embed' ではタブ文字の展開は行わない。
701
- def read_block_for(cmdname, f) # 追加
702
- disable_comment = cmdname == :embed # '//embed' では行コメントを読み飛ばさない
703
- ignore_inline = _ignore_inline?(cmdname) # '//embed' と '//table' ではインライン命令を解釈しない
704
- enable_detab = cmdname !~ /\A(?:em)?table\z/ # '//table' ではタブ展開しない
705
- f.enable_comment(false) if disable_comment
706
- lines = read_block(f, ignore_inline, enable_detab) { "//#{cmdname}" }
707
- f.enable_comment(true) if disable_comment
708
- return lines
709
- end
710
- def _ignore_inline?(cmdname)
711
- return RAW_BLOCK_COMMANDS[cmdname]
712
- end
713
- def read_block(f, ignore_inline, enable_detab=true) # 上書き
714
- head = f.lineno
715
- buf = []
716
- builder = @strategy #+
717
- #f.until_match(%r{\A//\}}) do |line| #-
718
- f.until_match(BLOCK_END_REXP) do |line| #+
719
- if ignore_inline
720
- buf.push line
721
- elsif line !~ /\A\#@/
722
- #buf.push text(line.rstrip) #-
723
- line = line.rstrip #+
724
- line = builder.detab(line) if enable_detab #+
725
- buf << parse_text(line) #+
726
- end
727
- end
728
- #unless %r{\A//\}} =~ f.peek #-
729
- unless f.peek() =~ BLOCK_END_REXP #+
730
- if block_given? #+
731
- error "#{yield} (at line #{head}): block command not closed." #+
732
- else #+
733
- error "unexpected EOF (block begins at: #{head})"
734
- end #+
735
- return buf
736
- end
737
- f.gets # discard terminator
738
- buf
739
- end
740
-
741
- RAW_BLOCK_COMMANDS = {
742
- embed: true,
743
- raw: true,
744
- table: true,
745
- list: true,
746
- emlist: true,
747
- listnum: true,
748
- emlistnum: true,
749
- source: true,
750
- program: true,
751
- terminal: true,
752
- cmd: true,
753
- output: true,
754
- }
755
-
756
- ## ブロック命令を入れ子可能に変更('//note' と '//quote')
757
-
758
- def parse_block_command(f)
759
- line = f.gets()
760
- lineno = f.lineno
761
- line =~ /\A\/\/(\w+)(\[.*\])?(\{)?$/ or
762
- error "'#{line.strip}': invalid block command format."
763
- cmdname = $1.intern; argstr = $2; curly = $3
764
- ##
765
- prev = @strategy.doc_status[cmdname]
766
- @strategy.doc_status[cmdname] = true
767
- ## 引数を取り出す
768
- syntax = syntax_descriptor(cmdname) or
769
- error "'//#{cmdname}': unknown command"
770
- args = parse_args(argstr || "", cmdname)
771
- begin
772
- syntax.check_args args
773
- rescue CompileError => err
774
- error err.message
775
- end
776
- ## ブロックをとらないコマンドにブロックが指定されていたらエラー
777
- if curly && !syntax.block_allowed?
778
- error "'//#{cmdname}': this command should not take block (but given)."
779
- end
780
- ## ブロックの入れ子をサポートしてあれば、再帰的にパースする
781
- handler = "on_#{cmdname}_block"
782
- builder = @strategy
783
- if builder.respond_to?(handler)
784
- if curly
785
- builder.__send__(handler, *args) do
786
- parse_document(f, cmdname)
787
- end
788
- s = f.peek()
789
- f.peek() =~ BLOCK_END_REXP or
790
- error "'//#{cmdname}': not closed (reached to EOF)"
791
- f.gets() ## '//}' を読み捨てる
792
- else
793
- builder.__send__(handler, *args)
794
- end
795
- ## そうでなければ、従来と同じようにパースする
796
- elsif builder.respond_to?(cmdname)
797
- if !syntax.block_allowed?
798
- builder.__send__(cmdname, *args)
799
- elsif curly
800
- lines = read_block_for(cmdname, f)
801
- builder.__send__(cmdname, lines, *args)
802
- else
803
- lines = default_block(syntax)
804
- builder.__send__(cmdname, lines, *args)
805
- end
806
- else
807
- error "'//#{cmdname}': #{builder.class.name} not support this command"
808
- end
809
- ##
810
- @strategy.doc_status[cmdname] = prev
811
- end
812
-
813
- ## 箇条書きの文法を拡張
814
-
815
- LIST_ITEM_REXP = /\A( +)(\*+|\-+) +/ # '*' は unordred list、'-' は ordered list
816
-
817
- def compile_list(f)
818
- line = f.gets()
819
- line =~ LIST_ITEM_REXP
820
- indent = $1
821
- char = $2[0]
822
- $2.length == 1 or
823
- error "#{$2[0]=='*'?'un':''}ordered list should start with level 1"
824
- line = parse_list(f, line, indent, char, 1)
825
- f.ungets(line)
826
- end
827
-
828
- def parse_list(f, line, indent, char, level)
829
- if char != '*' && line =~ LIST_ITEM_REXP
830
- start_num, _ = $'.lstrip().split(/\s+/, 2)
831
- end
832
- st = @strategy
833
- char == '*' ? st.ul_begin { level } : st.ol_begin(start_num) { level }
834
- while line =~ LIST_ITEM_REXP # /\A( +)(\*+|\-+) +/
835
- $1 == indent or
836
- error "mismatched indentation of #{$2[0]=='*'?'un':''}ordered list"
837
- mark = $2
838
- text = $'
839
- if mark.length == level
840
- break unless mark[0] == char
841
- line = parse_item(f, text.lstrip(), indent, char, level)
842
- elsif mark.length < level
843
- break
844
- else
845
- raise "internal error"
846
- end
847
- end
848
- char == '*' ? st.ul_end { level } : st.ol_end { level }
849
- return line
850
- end
851
-
852
- def parse_item(f, text, indent, char, level)
853
- if char != '*'
854
- num, text = text.split(/\s+/, 2)
855
- text ||= ''
856
- end
857
- #
858
- buf = [parse_text(text)]
859
- while (line = f.gets()) && line =~ /\A( +)/ && $1.length > indent.length
860
- buf << parse_text(line)
861
- end
862
- #
863
- st = @strategy
864
- char == '*' ? st.ul_item_begin(buf) : st.ol_item_begin(buf, num)
865
- rexp = LIST_ITEM_REXP # /\A( +)(\*+|\-+) +/
866
- while line =~ rexp && $2.length > level
867
- $2.length == level + 1 or
868
- error "invalid indentation level of (un)ordred list"
869
- line = parse_list(f, line, indent, $2[0], $2.length)
870
- end
871
- char == '*' ? st.ul_item_end() : st.ol_item_end()
872
- #
873
- return line
874
- end
875
-
876
- def compile_dlist(f)
877
- @strategy.dl_begin()
878
- while /\A\s*:/ =~ f.peek()
879
- dtext = f.gets.sub(/\A\s*:/, '').strip
880
- @strategy.dt(parse_text(dtext))
881
- buf = []
882
- li_rexp = LIST_ITEM_REXP
883
- indent = nil
884
- first_p = true
885
- @strategy.dl_dd_begin()
886
- while (line = f.peek()) =~ /\A( [ \t]+|\t\s*)/ || line =~ /\A\s*$/
887
- indent ||= $1
888
- if indent
889
- line =~ /\A\s*$/ || line.start_with?(indent) or
890
- warn "` : #{dtext}': indent mismatched (maybe space and tab are mixed)"
891
- if _dl_start_list?(line, indent, li_rexp)
892
- buf, first_p = _dl_par(buf, first_p) unless buf.empty?
893
- compile_list(f)
894
- @strategy.noindent # disable indent just after ordered/unordered list
895
- next
896
- end
897
- end
898
- if line =~ /\A\s*$/
899
- buf, first_p = _dl_par(buf, first_p) unless buf.empty?
900
- else
901
- buf << parse_text(line)
902
- end
903
- f.gets()
904
- end
905
- _, _ = _dl_par(buf, first_p) unless buf.empty?
906
- @strategy.dl_dd_end()
907
- f.skip_blank_lines()
908
- f.skip_comment_lines()
909
- end
910
- @strategy.dl_end()
911
- end
912
-
913
- def _dl_start_list?(line, indent, li_rexp)
914
- return line.start_with?(indent) && line.sub(indent, '') =~ li_rexp && line =~ li_rexp
915
- end
916
-
917
- def _dl_par(buf, first_p)
918
- return buf, first_p if buf.empty?
919
- if first_p
920
- @strategy.puts buf.join
921
- else
922
- @strategy.paragraph(buf)
923
- end
924
- return [], false
925
- end
926
-
927
- public
928
-
929
- ## 入れ子のインライン命令をパースできるよう上書き
930
- def parse_text(line)
931
- stack = []
932
- tag_name = nil
933
- close_char = nil
934
- items = [""]
935
- nestable = true
936
- scan_inline_command(line) do |text, s1, s2, s3|
937
- if s1 # ex: '@<code>{', '@<b>{', '@<m>$'
938
- if nestable
939
- items << text
940
- stack.push([tag_name, close_char, items])
941
- s1 =~ /\A@<(\w+)>([{$|])\z/ or raise "internal error"
942
- tag_name = $1
943
- close_char = $2 == '{' ? '}' : $2
944
- items = [""]
945
- nestable = false if ignore_nested_inline_command?(tag_name)
946
- else
947
- items[-1] << text << s1
948
- end
949
- elsif s2 # '\}' or '\\' (not '\$' nor '\|')
950
- text << (close_char == '}' ? s2[1] : s2)
951
- items[-1] << text
952
- elsif s3 # '}', '$', or '|'
953
- items[-1] << text
954
- if close_char == s3
955
- items.delete_if {|x| x.empty? }
956
- elem = [tag_name, {}, items]
957
- tag_name, close_char, items = stack.pop()
958
- items << elem << ""
959
- nestable = true
960
- else
961
- items[-1] << s3
962
- end
963
- else
964
- if items.length == 1 && items[-1].empty?
965
- items[-1] = text
966
- else
967
- items[-1] << text
968
- end
969
- end
970
- end
971
- if tag_name
972
- error "inline command '@<#{tag_name}>' not closed."
973
- end
974
- items.delete_if {|x| x.empty? }
975
- #
976
- return compile_inline_command(items)
977
- end
978
-
979
- alias text parse_text
980
-
981
- private
982
-
983
- def scan_inline_command(line)
984
- pos = 0
985
- line.scan(/(\@<\w+>[{$|])|(\\[\\}])|([}$|])/) do
986
- m = Regexp.last_match
987
- text = line[pos, m.begin(0)-pos]
988
- pos = m.end(0)
989
- yield text, $1, $2, $3
990
- end
991
- remained = pos == 0 ? line : line[pos..-1]
992
- yield remained, nil, nil, nil
993
- end
994
-
995
- def compile_inline_command(items)
996
- buf = ""
997
- strategy = @strategy
998
- items.each do |x|
999
- case x
1000
- when String
1001
- buf << strategy.nofunc_text(x)
1002
- when Array
1003
- tag_name, attrs, children = x
1004
- op = tag_name
1005
- inline_defined?(op) or
1006
- raise CompileError, "no such inline op: #{op}"
1007
- if strategy.respond_to?("on_inline_#{op}")
1008
- buf << strategy.__send__("on_inline_#{op}") {|both_p|
1009
- if !both_p
1010
- compile_inline_command(children)
1011
- else
1012
- [compile_inline_command(children), children]
1013
- end
1014
- }
1015
- elsif strategy.respond_to?("inline_#{op}")
1016
- children.empty? || children.all? {|x| x.is_a?(String) } or
1017
- error "'@<#{op}>' does not support nested inline commands."
1018
- buf << strategy.__send__("inline_#{op}", children[0])
1019
- else
1020
- error "strategy does not support inline op: @<#{op}> (strategy.class=#{strategy.class})"
1021
- end
1022
- else
1023
- raise "internal error: x=#{x.inspect}"
1024
- end
1025
- end
1026
- buf
1027
- end
1028
-
1029
- def ignore_nested_inline_command?(tag_name)
1030
- return IGNORE_NESTED_INLINE_COMMANDS.include?(tag_name)
1031
- end
1032
-
1033
- IGNORE_NESTED_INLINE_COMMANDS = Set.new(['m', 'raw', 'embed', 'idx', 'hidx', 'term'])
1034
-
1035
- end
1036
-
1037
-
1038
- ## コメント「#@#」を読み飛ばす(ただし //embed では読み飛ばさない)
1039
- class LineInput
1040
-
1041
- def initialize(f)
1042
- super
1043
- @enable_comment = true
1044
- end
1045
-
1046
- def enable_comment(flag)
1047
- @enable_comment = flag
1048
- end
1049
-
1050
- def gets
1051
- line = super
1052
- if @enable_comment
1053
- while line && line =~ /\A\#\@\#/
1054
- line = super
1055
- end
1056
- end
1057
- return line
1058
- end
1059
-
1060
- end
1061
-
1062
-
1063
- class Catalog
1064
-
1065
- def parts_with_chaps
1066
- ## catalog.ymlの「CHAPS:」がnullのときエラーになるのを防ぐ
1067
- (@yaml['CHAPS'] || []).flatten.compact
1068
- end
1069
-
1070
- end
1071
-
1072
-
1073
- class Book::ListIndex
1074
-
1075
- ## '//program' と '//terminal' と '//output' をサポートするよう拡張
1076
- def self.item_type # override
1077
- #'(list|listnum)' # original
1078
- '(list|listnum|program|terminal|output)'
1079
- end
1080
-
1081
- ## '//list' や '//terminal' のラベル(第1引数)を省略できるよう拡張
1082
- def self.parse(src, *args) # override
1083
- items = []
1084
- seq = 1
1085
- src.grep(%r{\A//#{item_type()}}) do |line|
1086
- if id = line.slice(/\[(.*?)\]/, 1)
1087
- next if id.empty? # 追加
1088
- items.push item_class().new(id, seq)
1089
- seq += 1
1090
- ReVIEW.logger.warn "warning: no ID of #{item_type()} in #{line}" if id.empty?
1091
- end
1092
- end
1093
- new(items, *args)
1094
- end
1095
-
1096
- end
1097
-
1098
-
1099
- ## ノートブロック(//note)のラベル用
1100
- class Book::NoteIndex < Book::Index # create new class for '//note'
1101
- Item = Struct.new(:id, :caption)
1102
-
1103
- def self.parse(src_lines)
1104
- rexp = /\A\/\/note\[([^\]]+)\]\[(.*?[^\\])\]/ # $1: label, $2: caption
1105
- items = src_lines.grep(rexp) {|line|
1106
- label = $1.strip(); caption = $2.gsub(/\\\]/, ']')
1107
- next if label.empty?
1108
- label =~ /\A[-_a-zA-Z0-9]+\z/ or
1109
- error "'#{line}': invalid label (only alphabet, number, '_' or '-' available)"
1110
- Item.new(label, caption)
1111
- }.compact()
1112
- self.new(items)
1113
- end
1114
-
1115
- end
1116
-
1117
-
1118
- ## 数式(//texequation)のラベル用
1119
- class Book::EquationIndex < Book::Index
1120
- def self.item_type
1121
- '(texequation)'
1122
- end
1123
- end
1124
-
1125
-
1126
- module Book::Compilable
1127
-
1128
- def note(id)
1129
- note_index()[id]
1130
- end
1131
-
1132
- def note_index
1133
- @note_index ||= Book::NoteIndex.parse(lines())
1134
- @note_index
1135
- end
1136
-
1137
- def equation(id)
1138
- equation_index()[id]
1139
- end
1140
-
1141
- def equation_index
1142
- @equation_index ||= Book::EquationIndex.parse(lines())
1143
- @equation_index
1144
- end
1145
-
1146
- def content # override
1147
- ## //list[?] や //terminal[?] の '?' をランダム文字列に置き換える。
1148
- ## こうすると、重複しないラベルをいちいち指定しなくても、ソースコードや
1149
- ## ターミナルにリスト番号がつく。ただし @<list>{} での参照はできない。
1150
- unless @_done
1151
- pat1 = Book::ListIndex.item_type # == '(list|listnum|program|terminal|output)'
1152
- pat2 = Book::TableIndex.item_type # == '(table|imgtable)'
1153
- pat = "#{pat1[1..-2]}|#{pat2[1..-2]}"
1154
- @content = @content.gsub(/^\/\/(#{pat})\[\?\]/) { "//#{$1}[#{_random_label()}]" }
1155
- ## 改行コードを「\n」に統一する
1156
- @content = @content.gsub(/\r\n/, "\n")
1157
- ## (experimental) 範囲コメント('#@+++' '#@---')を行コメント('#@#')に変換
1158
- @content = @content.gsub(/^\#\@\+\+\+$.*?^\#\@\-\-\-$/m) { $&.gsub(/^/, '#@#') }
1159
- @_done = true
1160
- end
1161
- @content
1162
- end
1163
-
1164
- module_function
1165
-
1166
- def _random_label
1167
- #"_" + rand().to_s[2..10]
1168
- "_" + RANDOM.rand().to_s[2..10]
1169
- end
1170
-
1171
- RANDOM = Random.new(22360679)
1172
-
1173
- end
1174
-
1175
-
1176
- end