tmtms-review 1.0.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 (107) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +9 -0
  3. data/COPYING +515 -0
  4. data/ChangeLog +2083 -0
  5. data/README.rdoc +50 -0
  6. data/Rakefile +56 -0
  7. data/VERSION +1 -0
  8. data/bin/review-check +178 -0
  9. data/bin/review-checkdep +63 -0
  10. data/bin/review-compile +205 -0
  11. data/bin/review-epubmaker +661 -0
  12. data/bin/review-epubmaker-ng +176 -0
  13. data/bin/review-index +118 -0
  14. data/bin/review-pdfmaker +208 -0
  15. data/bin/review-preproc +142 -0
  16. data/bin/review-validate +51 -0
  17. data/bin/review-vol +102 -0
  18. data/debian/README.Debian +12 -0
  19. data/debian/README.source +5 -0
  20. data/debian/changelog +5 -0
  21. data/debian/compat +1 -0
  22. data/debian/control +22 -0
  23. data/debian/copyright +62 -0
  24. data/debian/docs +6 -0
  25. data/debian/manpage.1.ex +59 -0
  26. data/debian/patches/path.diff +91 -0
  27. data/debian/patches/series +1 -0
  28. data/debian/review.install +13 -0
  29. data/debian/review.links +4 -0
  30. data/debian/rules +13 -0
  31. data/debian/source/format +1 -0
  32. data/doc/format.rdoc +582 -0
  33. data/doc/format_idg.rdoc +180 -0
  34. data/doc/libepubmaker/sample.yaml +90 -0
  35. data/doc/quickstart.rdoc +188 -0
  36. data/doc/ruby-uuid/README +11 -0
  37. data/doc/ruby-uuid/README.ja +34 -0
  38. data/doc/sample.css +108 -0
  39. data/doc/sample.yaml +62 -0
  40. data/lib/epubmaker.rb +28 -0
  41. data/lib/epubmaker/content.rb +82 -0
  42. data/lib/epubmaker/epubv2.rb +418 -0
  43. data/lib/epubmaker/epubv3.rb +249 -0
  44. data/lib/epubmaker/producer.rb +204 -0
  45. data/lib/epubmaker/resource.rb +66 -0
  46. data/lib/lineinput.rb +155 -0
  47. data/lib/review.rb +3 -0
  48. data/lib/review/book.rb +46 -0
  49. data/lib/review/book/base.rb +235 -0
  50. data/lib/review/book/chapter.rb +81 -0
  51. data/lib/review/book/compilable.rb +159 -0
  52. data/lib/review/book/index.rb +339 -0
  53. data/lib/review/book/page_metric.rb +38 -0
  54. data/lib/review/book/parameters.rb +97 -0
  55. data/lib/review/book/part.rb +44 -0
  56. data/lib/review/book/volume.rb +65 -0
  57. data/lib/review/builder.rb +444 -0
  58. data/lib/review/compiler.rb +550 -0
  59. data/lib/review/configure.rb +38 -0
  60. data/lib/review/epubbuilder.rb +18 -0
  61. data/lib/review/exception.rb +21 -0
  62. data/lib/review/extentions.rb +3 -0
  63. data/lib/review/extentions/object.rb +9 -0
  64. data/lib/review/extentions/string.rb +33 -0
  65. data/lib/review/htmlbuilder.rb +1097 -0
  66. data/lib/review/htmllayout.rb +19 -0
  67. data/lib/review/htmlutils.rb +36 -0
  68. data/lib/review/i18n.rb +30 -0
  69. data/lib/review/i18n.yaml +34 -0
  70. data/lib/review/idgxmlbuilder.rb +1145 -0
  71. data/lib/review/latexbuilder.rb +815 -0
  72. data/lib/review/latexindex.rb +35 -0
  73. data/lib/review/latexutils.rb +79 -0
  74. data/lib/review/preprocessor.rb +563 -0
  75. data/lib/review/review.tex.erb +232 -0
  76. data/lib/review/textbuilder.rb +17 -0
  77. data/lib/review/textutils.rb +66 -0
  78. data/lib/review/tocparser.rb +342 -0
  79. data/lib/review/tocprinter.rb +221 -0
  80. data/lib/review/topbuilder.rb +785 -0
  81. data/lib/review/unfold.rb +138 -0
  82. data/lib/uuid.rb +312 -0
  83. data/review.gemspec +141 -0
  84. data/test/CHAPS +2 -0
  85. data/test/bib.re +13 -0
  86. data/test/book_test_helper.rb +35 -0
  87. data/test/test.re +43 -0
  88. data/test/test_book.rb +598 -0
  89. data/test/test_book_chapter.rb +418 -0
  90. data/test/test_book_parameter.rb +42 -0
  91. data/test/test_book_part.rb +50 -0
  92. data/test/test_builder.rb +144 -0
  93. data/test/test_compiler.rb +44 -0
  94. data/test/test_epubmaker.rb +507 -0
  95. data/test/test_helper.rb +27 -0
  96. data/test/test_htmlbuilder.rb +554 -0
  97. data/test/test_htmlutils.rb +28 -0
  98. data/test/test_i18n.rb +64 -0
  99. data/test/test_idgxmlbuilder.rb +589 -0
  100. data/test/test_index.rb +31 -0
  101. data/test/test_latexbuilder.rb +656 -0
  102. data/test/test_lineinput.rb +198 -0
  103. data/test/test_preprocessor.rb +23 -0
  104. data/test/test_textutils.rb +68 -0
  105. data/test/test_topbuilder.rb +244 -0
  106. data/test/test_uuid.rb +156 -0
  107. metadata +161 -0
@@ -0,0 +1,550 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Copyright (c) 2002-2007 Minero Aoki
4
+ # Copyright (c) 2009-2010 Minero Aoki, Kenshi Muto
5
+ #
6
+ # This program is free software.
7
+ # You can distribute or modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ #
10
+
11
+ require 'review/extentions'
12
+ require 'review/preprocessor'
13
+ require 'review/exception'
14
+ require 'lineinput'
15
+
16
+ module ReVIEW
17
+
18
+ class Location
19
+ def initialize(filename, f)
20
+ @filename = filename
21
+ @f = f
22
+ end
23
+
24
+ attr_reader :filename
25
+
26
+ def lineno
27
+ @f.lineno
28
+ end
29
+
30
+ def string
31
+ begin
32
+ "#{@filename}:#{@f.lineno}"
33
+ rescue
34
+ "#{@filename}:nil"
35
+ end
36
+ end
37
+
38
+ alias to_s string
39
+ end
40
+
41
+
42
+ class Compiler
43
+
44
+ def initialize(strategy)
45
+ @strategy = strategy
46
+ end
47
+
48
+ attr_reader :strategy
49
+
50
+ def compile(chap)
51
+ @chapter = chap
52
+ do_compile
53
+ @strategy.result
54
+ end
55
+
56
+ class SyntaxElement
57
+ def initialize(name, type, argc, &block)
58
+ @name = name
59
+ @type = type
60
+ @argc_spec = argc
61
+ @checker = block
62
+ end
63
+
64
+ attr_reader :name
65
+
66
+ def check_args(args)
67
+ unless @argc_spec === args.size
68
+ raise CompileError, "wrong # of parameters (block command //#{@name}, expect #{@argc_spec} but #{args.size})"
69
+ end
70
+ @checker.call(*args) if @checker
71
+ end
72
+
73
+ def min_argc
74
+ case @argc_spec
75
+ when Range then @argc_spec.begin
76
+ when Integer then @argc_spec
77
+ else
78
+ raise TypeError, "argc_spec is not Range/Integer: #{inspect()}"
79
+ end
80
+ end
81
+
82
+ def block_required?
83
+ @type == :block
84
+ end
85
+
86
+ def block_allowed?
87
+ @type == :block or @type == :optional
88
+ end
89
+ end
90
+
91
+ SYNTAX = {}
92
+
93
+ def Compiler.defblock(name, argc, optional = false, &block)
94
+ defsyntax name, (optional ? :optional : :block), argc, &block
95
+ end
96
+
97
+ def Compiler.defsingle(name, argc, &block)
98
+ defsyntax name, :line, argc, &block
99
+ end
100
+
101
+ def Compiler.defsyntax(name, type, argc, &block)
102
+ SYNTAX[name] = SyntaxElement.new(name, type, argc, &block)
103
+ end
104
+
105
+ def syntax_defined?(name)
106
+ SYNTAX.key?(name.to_sym)
107
+ end
108
+
109
+ def syntax_descriptor(name)
110
+ SYNTAX[name.to_sym]
111
+ end
112
+
113
+ class InlineSyntaxElement
114
+ def initialize(name)
115
+ @name = name
116
+ end
117
+
118
+ attr_reader :name
119
+ end
120
+
121
+ INLINE = {}
122
+
123
+ def Compiler.definline(name)
124
+ INLINE[name] = InlineSyntaxElement.new(name)
125
+ end
126
+
127
+ def inline_defined?(name)
128
+ INLINE.key?(name.to_sym)
129
+ end
130
+
131
+ defblock :read, 0
132
+ defblock :lead, 0
133
+ defblock :list, 2
134
+ defblock :emlist, 0..1
135
+ defblock :cmd, 0..1
136
+ defblock :table, 0..2
137
+ defblock :quote, 0
138
+ defblock :image, 2..3, true
139
+ defblock :source, 1
140
+ defblock :listnum, 2
141
+ defblock :emlistnum, 0..1
142
+ defblock :bibpaper, 2..3, true
143
+ defblock :doorquote, 1
144
+ defblock :talk, 0
145
+ defblock :texequation, 0
146
+ defblock :graph, 1..3
147
+
148
+ defblock :address, 0
149
+ defblock :blockquote, 0
150
+ defblock :bpo, 0
151
+ defblock :flushright, 0
152
+ defblock :centering, 0
153
+ defblock :note, 0..1
154
+ defblock :box, 0..1
155
+
156
+ defsingle :footnote, 2
157
+ defsingle :comment, 1
158
+ defsingle :noindent, 0
159
+ defsingle :linebreak, 0
160
+ defsingle :pagebreak, 0
161
+ defsingle :indepimage, 1..3
162
+ defsingle :numberlessimage, 1..3
163
+ defsingle :hr, 0
164
+ defsingle :parasep, 0
165
+ defsingle :label, 1
166
+ defsingle :raw, 1
167
+ defsingle :tsize, 1
168
+ defsingle :include, 1
169
+ defsingle :olnum, 1
170
+
171
+ definline :chapref
172
+ definline :chap
173
+ definline :title
174
+ definline :img
175
+ definline :icon
176
+ definline :list
177
+ definline :table
178
+ definline :fn
179
+ definline :kw
180
+ definline :ruby
181
+ definline :bou
182
+ definline :ami
183
+ definline :b
184
+ definline :dtp
185
+ definline :code
186
+ definline :bib
187
+ definline :hd
188
+ definline :href
189
+ definline :recipe
190
+
191
+ definline :abbr
192
+ definline :acronym
193
+ definline :cite
194
+ definline :dfn
195
+ definline :em
196
+ definline :kbd
197
+ definline :q
198
+ definline :samp
199
+ definline :strong
200
+ definline :var
201
+ definline :big
202
+ definline :small
203
+ definline :del
204
+ definline :ins
205
+ definline :sup
206
+ definline :sub
207
+ definline :tt
208
+ definline :i
209
+ definline :tti
210
+ definline :ttb
211
+ definline :u
212
+ definline :raw
213
+ definline :br
214
+ definline :m
215
+ definline :uchar
216
+ definline :idx
217
+ definline :hidx
218
+ definline :comment
219
+ definline :include
220
+
221
+ private
222
+
223
+ def do_compile
224
+ f = LineInput.new(Preprocessor::Strip.new(StringIO.new(@chapter.content)))
225
+ @strategy.bind self, @chapter, Location.new(@chapter.basename, f)
226
+ tagged_section_init
227
+ while f.next?
228
+ case f.peek
229
+ when /\A\#@/
230
+ f.gets # Nothing to do
231
+ when /\A=+[\[\s\{]/
232
+ compile_headline f.gets
233
+ when %r<\A\s+\*>
234
+ compile_ulist f
235
+ when %r<\A\s+\d+\.>
236
+ compile_olist f
237
+ when %r<\A\s*:\s>
238
+ compile_dlist f
239
+ when %r<\A//\}>
240
+ f.gets
241
+ error 'block end seen but not opened'
242
+ when %r<\A//[a-z]+>
243
+ name, args, lines = read_command(f)
244
+ syntax = syntax_descriptor(name)
245
+ unless syntax
246
+ error "unknown command: //#{name}"
247
+ compile_unknown_command args, lines
248
+ next
249
+ end
250
+ compile_command syntax, args, lines
251
+ when %r<\A//>
252
+ line = f.gets
253
+ warn "`//' seen but is not valid command: #{line.strip.inspect}"
254
+ if block_open?(line)
255
+ warn "skipping block..."
256
+ read_block(f)
257
+ end
258
+ else
259
+ if f.peek.strip.empty?
260
+ f.gets
261
+ next
262
+ end
263
+ compile_paragraph f
264
+ end
265
+ end
266
+ close_all_tagged_section
267
+ end
268
+
269
+ def compile_headline(line)
270
+ @headline_indexs ||= [@chapter.number.to_i - 1]
271
+ m = /\A(=+)(?:\[(.+?)\])?(?:\{(.+?)\})?(.*)/.match(line)
272
+ level = m[1].size
273
+ tag = m[2]
274
+ label = m[3]
275
+ caption = m[4].strip
276
+ index = level - 1
277
+ if tag
278
+ if tag !~ /\A\//
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
+ unless prev_tag_info.first == open_tag
285
+ raise CompileError, "#{open_tag} is not opened."
286
+ end
287
+ close_tagged_section(*prev_tag_info)
288
+ end
289
+ else
290
+ if @headline_indexs.size > (index + 1)
291
+ @headline_indexs = @headline_indexs[0..index]
292
+ end
293
+ @headline_indexs[index] = 0 if @headline_indexs[index].nil?
294
+ @headline_indexs[index] += 1
295
+ close_current_tagged_section(level)
296
+ if ReVIEW.book.param["hdnumberingmode"]
297
+ caption = @chapter.on_CHAPS? ? "#{@headline_indexs.join('.')} #{caption}" : caption
298
+ warn "--hdnumberingmode is deprecated. use --level option."
299
+ end
300
+ @strategy.headline level, label, caption
301
+ end
302
+ end
303
+
304
+ def close_current_tagged_section(level)
305
+ while @tagged_section.last and @tagged_section.last[1] >= level
306
+ close_tagged_section(* @tagged_section.pop)
307
+ end
308
+ end
309
+
310
+ def headline(level, label, caption)
311
+ @strategy.headline level, label, caption
312
+ end
313
+
314
+ def tagged_section_init
315
+ @tagged_section = []
316
+ end
317
+
318
+ def open_tagged_section(tag, level, label, caption)
319
+ mid = "#{tag}_begin"
320
+ unless @strategy.respond_to?(mid)
321
+ error "strategy does not support tagged section: #{tag}"
322
+ headline level, label, caption
323
+ return
324
+ end
325
+ @tagged_section.push [tag, level]
326
+ @strategy.__send__ mid, level, label, caption
327
+ end
328
+
329
+ def close_tagged_section(tag, level)
330
+ mid = "#{tag}_end"
331
+ if @strategy.respond_to?(mid)
332
+ @strategy.__send__ mid, level
333
+ else
334
+ error "strategy does not support block op: #{mid}"
335
+ end
336
+ end
337
+
338
+ def close_all_tagged_section
339
+ until @tagged_section.empty?
340
+ close_tagged_section(* @tagged_section.pop)
341
+ end
342
+ end
343
+
344
+ def compile_ulist(f)
345
+ level = 0
346
+ f.while_match(/\A\s+\*|\A\#@/) do |line|
347
+ next if line =~ /\A\#@/
348
+
349
+ buf = [text(line.sub(/\*+/, '').strip)]
350
+ f.while_match(/\A\s+(?!\*)\S/) do |cont|
351
+ buf.push text(cont.strip)
352
+ end
353
+
354
+ line =~ /\A\s+(\*+)/
355
+ current_level = $1.size
356
+ if level == current_level
357
+ @strategy.ul_item_end
358
+ # body
359
+ @strategy.ul_item_begin buf
360
+ elsif level < current_level # down
361
+ level_diff = current_level - level
362
+ level = current_level
363
+ (1..(level_diff - 1)).to_a.reverse.each do |i|
364
+ @strategy.ul_begin {i}
365
+ @strategy.ul_item_begin []
366
+ end
367
+ @strategy.ul_begin {level}
368
+ @strategy.ul_item_begin buf
369
+ elsif level > current_level # up
370
+ level_diff = level - current_level
371
+ level = current_level
372
+ (1..level_diff).to_a.reverse.each do |i|
373
+ @strategy.ul_item_end
374
+ @strategy.ul_end {level + i}
375
+ @strategy.ul_item_end
376
+ end
377
+ # body
378
+ @strategy.ul_item_begin buf
379
+ end
380
+ end
381
+
382
+ (1..level).to_a.reverse.each do |i|
383
+ @strategy.ul_item_end
384
+ @strategy.ul_end {i}
385
+ end
386
+ end
387
+
388
+ def compile_olist(f)
389
+ @strategy.ol_begin
390
+ f.while_match(/\A\s+\d+\.|\A\#@/) do |line|
391
+ next if line =~ /\A\#@/
392
+
393
+ num = line.match(/(\d+)\./)[1]
394
+ buf = [text(line.sub(/\d+\./, '').strip)]
395
+ f.while_match(/\A\s+(?!\d+\.)\S/) do |cont|
396
+ buf.push text(cont.strip)
397
+ end
398
+ @strategy.ol_item buf, num
399
+ end
400
+ @strategy.ol_end
401
+ end
402
+
403
+ def compile_dlist(f)
404
+ @strategy.dl_begin
405
+ while /\A\s*:/ =~ f.peek
406
+ @strategy.dt text(f.gets.sub(/\A\s*:/, '').strip)
407
+ @strategy.dd f.break(/\A(\S|\s*:)/).map {|line| text(line.strip) }
408
+ f.skip_blank_lines
409
+ end
410
+ @strategy.dl_end
411
+ end
412
+
413
+ def compile_paragraph(f)
414
+ buf = []
415
+ f.until_match(%r<\A//|\A\#@>) do |line|
416
+ break if line.strip.empty?
417
+ buf.push text(line.sub(/^(\t+)\s*/) {|m| "<!ESCAPETAB!>" * m.size}.strip.gsub(/<!ESCAPETAB!>/, "\t"))
418
+ end
419
+ @strategy.paragraph buf
420
+ end
421
+
422
+ def read_command(f)
423
+ line = f.gets
424
+ name = line.slice(/[a-z]+/).intern
425
+ args = parse_args(line.sub(%r<\A//[a-z]+>, '').rstrip.chomp('{'), name)
426
+ lines = block_open?(line) ? read_block(f) : nil
427
+ return name, args, lines
428
+ end
429
+
430
+ def block_open?(line)
431
+ line.rstrip[-1,1] == '{'
432
+ end
433
+
434
+ def read_block(f)
435
+ head = f.lineno
436
+ buf = []
437
+ f.until_match(%r<\A//\}>) do |line|
438
+ unless line =~ /\A\#@/
439
+ buf.push text(line.rstrip)
440
+ end
441
+ end
442
+ unless %r<\A//\}> =~ f.peek
443
+ error "unexpected EOF (block begins at: #{head})"
444
+ return buf
445
+ end
446
+ f.gets # discard terminator
447
+ buf
448
+ end
449
+
450
+ def parse_args(str, name=nil)
451
+ return [] if str.empty?
452
+ scanner = StringScanner.new(str)
453
+ words = []
454
+ while word = scanner.scan(/(\[\]|\[.*?[^\\]\])/)
455
+ w2 = word[1..-2].gsub(/\\(.)/){
456
+ ch = $1
457
+ (ch == "]" or ch == "\\") ? ch : "\\" + ch
458
+ }
459
+ words << w2
460
+ end
461
+ if !scanner.eos?
462
+ error "argument syntax error: #{scanner.rest} in #{str.inspect}"
463
+ return []
464
+ end
465
+ return words
466
+ end
467
+
468
+ def compile_command(syntax, args, lines)
469
+ unless @strategy.respond_to?(syntax.name)
470
+ error "strategy does not support command: //#{syntax.name}"
471
+ compile_unknown_command args, lines
472
+ return
473
+ end
474
+ begin
475
+ syntax.check_args args
476
+ rescue CompileError => err
477
+ error err.message
478
+ args = ['(NoArgument)'] * syntax.min_argc
479
+ end
480
+ if syntax.block_allowed?
481
+ compile_block syntax, args, lines
482
+ else
483
+ if lines
484
+ error "block is not allowed for command //#{syntax.name}; ignore"
485
+ end
486
+ compile_single syntax, args
487
+ end
488
+ end
489
+
490
+ def compile_unknown_command(args, lines)
491
+ @strategy.unknown_command args, lines
492
+ end
493
+
494
+ def compile_block(syntax, args, lines)
495
+ @strategy.__send__(syntax.name, (lines || default_block(syntax)), *args)
496
+ end
497
+
498
+ def default_block(syntax)
499
+ if syntax.block_required?
500
+ error "block is required for //#{syntax.name}; use empty block"
501
+ end
502
+ []
503
+ end
504
+
505
+ def compile_single(syntax, args)
506
+ @strategy.__send__(syntax.name, *args)
507
+ end
508
+
509
+ def text(str)
510
+ return '' if str.empty?
511
+ words = str.split(/(@<\w+>\{(?:[^\}\\]|\\.)*?\})/, -1)
512
+ words.each do |w|
513
+ error "`@<xxx>' seen but is not valid inline op: #{w}" if w.scan(/@<\w+>/).size > 1 && !/\A@<raw>/.match(w)
514
+ end
515
+ result = @strategy.nofunc_text(words.shift)
516
+ until words.empty?
517
+ result << compile_inline(words.shift.gsub(/\\\}/, '}'))
518
+ result << @strategy.nofunc_text(words.shift)
519
+ end
520
+ result
521
+ rescue => err
522
+ error err.message
523
+ end
524
+ public :text # called from strategy
525
+
526
+ def compile_inline(str)
527
+ op, arg = /\A@<(\w+)>\{(.*?)\}\z/.match(str).captures
528
+ unless inline_defined?(op)
529
+ raise CompileError, "no such inline op: #{op}"
530
+ end
531
+ unless @strategy.respond_to?("inline_#{op}")
532
+ raise "strategy does not support inline op: @<#{op}>"
533
+ end
534
+ @strategy.__send__("inline_#{op}", arg)
535
+ rescue => err
536
+ error err.message
537
+ @strategy.nofunc_text(str)
538
+ end
539
+
540
+ def warn(msg)
541
+ @strategy.warn msg
542
+ end
543
+
544
+ def error(msg)
545
+ @strategy.error msg
546
+ end
547
+
548
+ end
549
+
550
+ end # module ReVIEW