review 2.0.0.beta1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +66 -1
  3. data/.rubocop_todo.yml +617 -0
  4. data/.travis.yml +16 -1
  5. data/ChangeLog +48 -0
  6. data/Dockerfile +22 -0
  7. data/Gemfile +0 -1
  8. data/README.md +97 -0
  9. data/Rakefile +10 -11
  10. data/appveyor.yml +9 -0
  11. data/bin/review +46 -0
  12. data/bin/review-check +8 -21
  13. data/bin/review-compile +26 -43
  14. data/bin/review-index +9 -22
  15. data/bin/review-init +21 -25
  16. data/bin/review-preproc +9 -13
  17. data/bin/review-validate +1 -1
  18. data/bin/review-vol +3 -17
  19. data/bin/review-webmaker +15 -0
  20. data/doc/NEWS.ja.md +534 -0
  21. data/doc/NEWS.md +538 -0
  22. data/doc/catalog.ja.md +10 -18
  23. data/doc/catalog.md +5 -9
  24. data/doc/config.yml.sample +319 -0
  25. data/doc/customize_epub.ja.md +42 -0
  26. data/doc/format.ja.md +320 -288
  27. data/doc/format.md +277 -170
  28. data/doc/format_idg.ja.md +82 -175
  29. data/doc/pdfmaker.ja.md +61 -0
  30. data/doc/pdfmaker.md +65 -0
  31. data/doc/quickstart.ja.md +88 -98
  32. data/doc/quickstart.md +72 -110
  33. data/doc/sample.css +41 -0
  34. data/doc/writing_vertical.ja.md +55 -0
  35. data/doc/writing_vertical.md +5 -0
  36. data/lib/epubmaker/content.rb +3 -3
  37. data/lib/epubmaker/epubcommon.rb +173 -145
  38. data/lib/epubmaker/epubv2.rb +24 -77
  39. data/lib/epubmaker/epubv3.rb +72 -73
  40. data/lib/epubmaker/producer.rb +54 -30
  41. data/lib/lineinput.rb +48 -0
  42. data/lib/review/book.rb +0 -1
  43. data/lib/review/book/base.rb +47 -27
  44. data/lib/review/book/chapter.rb +48 -19
  45. data/lib/review/book/compilable.rb +10 -14
  46. data/lib/review/book/index.rb +10 -19
  47. data/lib/review/book/page_metric.rb +0 -10
  48. data/lib/review/book/part.rb +17 -3
  49. data/lib/review/builder.rb +84 -68
  50. data/lib/review/catalog.rb +5 -1
  51. data/lib/review/compiler.rb +327 -4657
  52. data/lib/review/configure.rb +84 -10
  53. data/lib/review/converter.rb +28 -0
  54. data/lib/review/epubbuilder.rb +1 -1
  55. data/lib/review/epubmaker.rb +142 -158
  56. data/lib/review/ewbbuilder.rb +5 -5
  57. data/lib/review/exception.rb +1 -1
  58. data/lib/review/extentions.rb +1 -1
  59. data/lib/review/extentions/hash.rb +15 -0
  60. data/lib/review/extentions/string.rb +2 -1
  61. data/lib/review/htmlbuilder.rb +364 -348
  62. data/lib/review/htmltoc.rb +44 -0
  63. data/lib/review/htmlutils.rb +12 -6
  64. data/lib/review/i18n.rb +78 -6
  65. data/lib/review/i18n.yml +7 -4
  66. data/lib/review/idgxmlbuilder.rb +226 -267
  67. data/lib/review/latexbuilder.rb +281 -274
  68. data/lib/review/latexutils.rb +56 -49
  69. data/lib/review/makerhelper.rb +8 -4
  70. data/lib/review/markdownbuilder.rb +80 -124
  71. data/lib/review/pdfmaker.rb +197 -138
  72. data/lib/review/preprocessor.rb +16 -67
  73. data/lib/review/template.rb +24 -0
  74. data/lib/review/textbuilder.rb +1 -1
  75. data/lib/review/textutils.rb +18 -24
  76. data/lib/review/tocparser.rb +51 -106
  77. data/lib/review/tocprinter.rb +61 -117
  78. data/lib/review/topbuilder.rb +119 -126
  79. data/lib/review/unfold.rb +2 -2
  80. data/lib/review/version.rb +1 -1
  81. data/lib/review/webmaker.rb +302 -0
  82. data/lib/review/webtocprinter.rb +48 -0
  83. data/lib/review/yamlloader.rb +47 -0
  84. data/review.gemspec +3 -3
  85. data/templates/html/layout-html5.html.erb +17 -0
  86. data/templates/html/layout-xhtml1.html.erb +20 -0
  87. data/{lib/review → templates/latex}/layout.tex.erb +107 -115
  88. data/templates/ncx/epubv2.ncx.erb +11 -0
  89. data/templates/opf/epubv2.opf.erb +21 -0
  90. data/templates/opf/epubv3.opf.erb +18 -0
  91. data/templates/web/html/layout-html5.html.erb +56 -0
  92. data/templates/web/html/layout-xhtml1.html.erb +20 -0
  93. data/templates/xml/container.xml.erb +6 -0
  94. data/test/assets/test.xml.erb +3 -0
  95. data/test/assets/test_template.tex +28 -71
  96. data/test/assets/test_template_backmatter.tex +1 -9
  97. data/test/sample-book/src/Rakefile +12 -3
  98. data/{doc/sample.yml → test/sample-book/src/config-epub2.yml} +92 -147
  99. data/test/sample-book/src/config.yml +40 -154
  100. data/test/sample-book/src/style-web.css +45 -0
  101. data/test/sample-book/src/style.css +23 -1
  102. data/test/test.re +1 -1
  103. data/test/test_book.rb +15 -17
  104. data/test/test_book_chapter.rb +2 -80
  105. data/test/test_book_part.rb +1 -1
  106. data/test/test_builder.rb +28 -6
  107. data/test/test_catalog.rb +17 -0
  108. data/test/test_compiler.rb +14 -59
  109. data/test/test_configure.rb +94 -0
  110. data/test/test_converter.rb +21 -0
  111. data/test/test_epub3maker.rb +155 -3
  112. data/test/test_epubmaker.rb +245 -30
  113. data/test/test_epubmaker_cmd.rb +2 -2
  114. data/test/test_extentions_hash.rb +60 -0
  115. data/test/test_helper.rb +4 -47
  116. data/test/test_htmlbuilder.rb +282 -175
  117. data/test/test_htmltoc.rb +33 -0
  118. data/test/test_i18n.rb +134 -70
  119. data/test/test_idgxmlbuilder.rb +58 -39
  120. data/test/test_latexbuilder.rb +132 -14
  121. data/test/test_lineinput.rb +5 -26
  122. data/test/test_makerhelper.rb +6 -4
  123. data/test/test_markdownbuilder.rb +23 -5
  124. data/test/test_pdfmaker.rb +86 -20
  125. data/test/test_pdfmaker_cmd.rb +1 -3
  126. data/test/test_review_ext.rb +1 -1
  127. data/test/test_template.rb +27 -0
  128. data/test/test_textutils.rb +36 -0
  129. data/test/test_tocparser.rb +25 -0
  130. data/test/test_topbuilder.rb +34 -2
  131. data/test/test_yamlloader.rb +188 -0
  132. metadata +71 -29
  133. data/README.rdoc +0 -81
  134. data/bin/review-epubmaker-legacy +0 -1024
  135. data/doc/ruby-uuid/README +0 -11
  136. data/doc/ruby-uuid/README.ja +0 -34
  137. data/lib/review/compiler/literals_1_8.kpeg +0 -19
  138. data/lib/review/compiler/literals_1_8.rb +0 -432
  139. data/lib/review/compiler/literals_1_9.kpeg +0 -22
  140. data/lib/review/compiler/literals_1_9.rb +0 -435
  141. data/lib/review/extentions/array.rb +0 -25
  142. data/lib/review/htmllayout.rb +0 -41
  143. data/lib/review/inaobuilder.rb +0 -357
  144. data/lib/review/location.rb +0 -24
  145. data/lib/review/node.rb +0 -267
  146. data/lib/review/review.kpeg +0 -724
  147. data/lib/uuid.rb +0 -312
  148. data/rubocop-todo.yml +0 -456
  149. data/test/test_inaobuilder.rb +0 -247
  150. data/test/test_uuid.rb +0 -157
@@ -1,267 +0,0 @@
1
- require 'json'
2
-
3
- module ReVIEW
4
- class Node
5
- attr_accessor :content
6
-
7
- def to_raw
8
- to_s_by(:to_raw)
9
- end
10
-
11
- def to_doc
12
- to_s_by(:to_doc)
13
- end
14
-
15
- def to_s_by(meth)
16
- if content.kind_of? String
17
- @content
18
- elsif content == nil
19
- nil
20
- elsif !content.kind_of? Array
21
- @content.__send__(meth)
22
- else
23
- ##@content.map(&meth).join("")
24
- @content.map{|o| o.__send__(meth)}.join("")
25
- end
26
- end
27
-
28
- def to_json(*args)
29
- if content.kind_of? String
30
- val = '"'+@content.gsub(/\"/,'\\"').gsub(/\n/,'\\n')+'"'
31
- elsif content == nil
32
- val = "null"
33
- elsif !content.kind_of? Array
34
- val = @content.to_json
35
- else
36
- val = "["+@content.map(&:to_json).join(",")+"]"
37
- end
38
- '{"ruleName":"' + self.class.to_s.sub(/ReVIEW::/,"").sub(/Node$/,"") + '",' +
39
- "\"offset\":#{position.pos},\"line\":#{position.line},\"column\":#{position.col}," +
40
- '"childNodes":' + val +
41
- '}'
42
- end
43
-
44
- def inspect
45
- self.to_json
46
- end
47
-
48
- end
49
-
50
- class HeadlineNode < Node
51
-
52
- def to_doc
53
- content_str = super
54
- cmd = @cmd ? @cmd.to_doc : nil
55
- label = @label
56
- @compiler.compile_headline(@level, cmd, label, content_str)
57
- end
58
-
59
- def to_json
60
- '{"ruleName":"' + self.class.to_s.sub(/ReVIEW::/,"").sub(/Node$/,"") + '",' +
61
- %Q|"cmd":"#{@cmd.to_json}",|+
62
- %Q|"label":"#{@label.to_json}",|+
63
- "\"offset\":#{position.pos},\"line\":#{position.line},\"column\":#{position.col}," +
64
- '"childNodes":' + @content.to_json + '}'
65
- end
66
- end
67
-
68
- class ParagraphNode < Node
69
-
70
- def to_doc
71
- #content = @content.map(&:to_doc)
72
- content = super.split(/\n/)
73
- @compiler.compile_paragraph(content)
74
- end
75
- end
76
-
77
- class BlockElementNode < Node
78
-
79
- def to_doc
80
- # content_str = super
81
- args = @args.map(&:to_doc)
82
- if @content
83
- content_lines = @content.map(&:to_doc)
84
- else
85
- content_lines = nil
86
- end
87
- @compiler.compile_command(@name, @args, content_lines, self)
88
- end
89
-
90
- def parse_args(*patterns)
91
- patterns.map.with_index do |pattern, i|
92
- if @args[i]
93
- @args[i].__send__("to_#{pattern}")
94
- else
95
- nil
96
- end
97
- end
98
- end
99
- end
100
-
101
- class CodeBlockElementNode < Node
102
-
103
- def to_doc
104
- # content_str = super
105
- args = @args.map(&:to_doc)
106
- if @content
107
- content_lines = raw_lines
108
- else
109
- content_lines = nil
110
- end
111
- @compiler.compile_command(@name, @args, content_lines, self)
112
- end
113
-
114
- def parse_args(*patterns)
115
- patterns.map.with_index do |pattern, i|
116
- if @args[i]
117
- @args[i].__send__("to_#{pattern}")
118
- else
119
- nil
120
- end
121
- end
122
- end
123
-
124
- def raw_lines
125
- self.content.to_doc.split(/\n/)
126
- end
127
- end
128
-
129
-
130
- class InlineElementNode < Node
131
-
132
- def to_raw
133
- content_str = super
134
- "@<#{@symbol.to_s}>{#{content_str}}"
135
- end
136
-
137
- def to_doc
138
- #content_str = super
139
- @compiler.compile_inline(@symbol, @content)
140
- end
141
-
142
- def to_json
143
- '{"ruleName":"' + self.class.to_s.sub(/ReVIEW::/,"").sub(/Node$/,"") + '",' +
144
- %Q|"symbol":"#{@symbol}",| +
145
- "\"offset\":#{position.pos},\"line\":#{position.line},\"column\":#{position.col}," +
146
- '"childNodes":[' + @content.map(&:to_json).join(",") + ']}'
147
- end
148
- end
149
-
150
- class InlineElementContentNode < Node
151
- end
152
-
153
- class TextNode < Node
154
-
155
- def to_raw
156
- content_str = super
157
- content_str.to_s
158
- end
159
-
160
- def to_doc
161
- content_str = super
162
- @compiler.compile_text(content_str)
163
- end
164
-
165
- def to_json(*args)
166
- val = '"'+@content.gsub(/\"/,'\\"').gsub(/\n/,'\\n')+'"'
167
- '{"ruleName":"' + self.class.to_s.sub(/ReVIEW::/,"").sub(/Node$/,"") + '",' +
168
- "\"offset\":#{position.pos},\"line\":#{position.line},\"column\":#{position.col}," +
169
- '"text":' + val + '}'
170
- end
171
- end
172
-
173
- class NewLineNode < Node
174
-
175
- def to_doc
176
- ""
177
- end
178
- end
179
-
180
- class RawNode < Node
181
-
182
- def to_doc
183
- @compiler.compile_raw(@builder, @content.join(""))
184
- end
185
- end
186
-
187
- class BracketArgNode < Node
188
- end
189
-
190
- class BraceArgNode < Node
191
- end
192
-
193
- class SinglelineCommentNode < Node
194
- def to_doc
195
- ""
196
- end
197
- end
198
-
199
- class SinglelineContentNode < Node
200
- end
201
-
202
- class UlistNode < Node
203
- def to_doc
204
- @compiler.compile_ulist(@content)
205
- end
206
- end
207
-
208
- class UlistElementNode < Node
209
- def level=(level)
210
- @level = level
211
- end
212
-
213
- def to_doc
214
- @content.map(&:to_doc).join("")
215
- end
216
-
217
- def concat(elem)
218
- @content << elem
219
- end
220
- end
221
-
222
- class OlistNode < Node
223
- def to_doc
224
- @compiler.compile_olist(@content)
225
- end
226
- end
227
-
228
- class OlistElementNode < Node
229
- def num=(num)
230
- @num = num
231
- end
232
-
233
- def to_doc
234
- @content.map(&:to_doc).join("")
235
- end
236
-
237
- def concat(elem)
238
- @content << elem
239
- end
240
- end
241
-
242
- class DlistNode < Node
243
- def to_doc
244
- @compiler.compile_dlist(@content)
245
- end
246
- end
247
-
248
- class DlistElementNode < Node
249
- def to_doc
250
- @content.map(&:to_doc).join("")
251
- end
252
- end
253
-
254
- class DocumentNode < Node
255
- end
256
-
257
- class ColumnNode < Node
258
-
259
- def to_doc
260
- level = @level
261
- label = @label
262
- caption = @caption ? @caption.to_doc : nil
263
- @compiler.compile_column(level, label, caption, @content)
264
- end
265
- end
266
-
267
- end
@@ -1,724 +0,0 @@
1
- %% name = ReVIEW::Compiler
2
-
3
- %% {
4
- class Error; end
5
- class Position
6
- attr_accessor :pos, :line, :col
7
- def initialize(compiler)
8
- @pos = compiler.pos
9
- @line = compiler.current_line
10
- @col = compiler.current_column
11
- end
12
- end
13
-
14
- require 'review/location'
15
- require 'review/extentions'
16
- require 'review/preprocessor'
17
- require 'review/exception'
18
- require 'review/node'
19
- require 'lineinput'
20
- if RUBY_VERSION > '1.9' then
21
- require 'review/compiler/literals_1_9'
22
- else
23
- require 'review/compiler/literals_1_8'
24
- end
25
-
26
- ## redifine Compiler.new
27
- def initialize(strategy)
28
- @strategy = strategy
29
- @current_column = nil
30
- @chapter = nil
31
- end
32
-
33
- attr_accessor :strategy
34
-
35
- def compile(chap)
36
- @chapter = chap
37
- do_compile
38
- @strategy.result
39
- end
40
-
41
- def do_compile
42
- @strategy.bind self, @chapter, ReVIEW::Location.new(@chapter.basename, self)
43
- setup_parser(@chapter.content)
44
- parse()
45
- convert_ast
46
- end
47
-
48
- def convert_ast
49
- ast = @strategy.ast
50
- convert_column(ast)
51
- if $DEBUG
52
- File.open("review-dump.json","w") do |f|
53
- f.write(ast.to_json)
54
- end
55
- end
56
- @strategy.output << ast.to_doc
57
- end
58
-
59
- def flush_column(new_content)
60
- if @current_column
61
- new_content << @current_column
62
- @current_column = nil
63
- end
64
- end
65
-
66
- def convert_column(ast)
67
- @column_stack = []
68
- content = ast.content
69
- new_content = []
70
- @current_content = new_content
71
- content.each do |elem|
72
- if elem.kind_of?(ReVIEW::HeadlineNode) && elem.cmd && elem.cmd.to_doc == "column"
73
- flush_column(new_content)
74
- @current_content = []
75
- @current_column = ReVIEW::ColumnNode.new(elem.compiler, elem.position, elem.level,
76
- elem.label, elem.content, @current_content)
77
- next
78
- elsif elem.kind_of?(ReVIEW::HeadlineNode) && elem.cmd && elem.cmd.to_doc =~ %r|^/|
79
- cmd_name = elem.cmd.to_doc[1..-1]
80
- if cmd_name != "column"
81
- raise ReVIEW::CompileError, "#{cmd_name} is not opened."
82
- end
83
- flush_column(new_content)
84
- @current_content = new_content
85
- next
86
- elsif elem.kind_of?(ReVIEW::HeadlineNode) && @current_column && elem.level <= @current_column.level
87
- flush_column(new_content)
88
- @current_content = new_content
89
- end
90
- @current_content << elem
91
- end
92
- flush_column(new_content)
93
- ast.content = new_content
94
- ast
95
- end
96
-
97
- def compile_text(text)
98
- @strategy.nofunc_text(text)
99
- end
100
-
101
- class SyntaxElement
102
- def initialize(name, type, argc, esc, &block)
103
- @name = name
104
- @type = type
105
- @argc_spec = argc
106
- @esc_patterns = esc
107
- @checker = block
108
- end
109
-
110
- attr_reader :name
111
-
112
- def check_args(args)
113
- unless @argc_spec === args.size
114
- raise ReVIEW::CompileError, "wrong # of parameters (block command //#{@name}, expect #{@argc_spec} but #{args.size})"
115
- end
116
- @checker.call(*args) if @checker
117
- end
118
-
119
- def min_argc
120
- case @argc_spec
121
- when Range then @argc_spec.begin
122
- when Integer then @argc_spec
123
- else
124
- raise TypeError, "argc_spec is not Range/Integer: #{inspect()}"
125
- end
126
- end
127
-
128
- def parse_args(args)
129
- if @esc_patterns
130
- args.map.with_index do |pattern, i|
131
- if @esc_patterns[i]
132
- args[i].__send__("to_#{@esc_patterns[i]}")
133
- else
134
- args[i].to_doc
135
- end
136
- end
137
- else
138
- args.map(&:to_doc)
139
- end
140
- end
141
-
142
- def block_required?
143
- @type == :block or @type == :code_block
144
- end
145
-
146
- def block_allowed?
147
- @type == :block or @type == :code_block or @type == :optional or @type == :optional_code_block
148
- end
149
-
150
- def code_block?
151
- @type == :code_block or @type == :optional_code_block
152
- end
153
- end
154
-
155
- SYNTAX = {}
156
-
157
- def self.defblock(name, argc, optional = false, esc = nil, &block)
158
- defsyntax(name, (optional ? :optional : :block), argc, esc, &block)
159
- end
160
-
161
- def self.defcodeblock(name, argc, optional = false, esc = nil, &block)
162
- defsyntax(name, (optional ? :optional_code_block : :code_block), argc, esc, &block)
163
- end
164
-
165
- def self.defsingle(name, argc, esc = nil, &block)
166
- defsyntax name, :line, argc, esc, &block
167
- end
168
-
169
- def self.defsyntax(name, type, argc, esc = nil, &block)
170
- SYNTAX[name] = SyntaxElement.new(name, type, argc, esc, &block)
171
- end
172
-
173
- def syntax_defined?(name)
174
- SYNTAX.key?(name.to_sym)
175
- end
176
-
177
- def syntax_descriptor(name)
178
- SYNTAX[name.to_sym]
179
- end
180
-
181
- class InlineSyntaxElement
182
- def initialize(name)
183
- @name = name
184
- end
185
-
186
- attr_reader :name
187
- end
188
-
189
- INLINE = {}
190
-
191
- def self.definline(name)
192
- INLINE[name] = InlineSyntaxElement.new(name)
193
- end
194
-
195
- def inline_defined?(name)
196
- INLINE.key?(name.to_sym)
197
- end
198
-
199
- defblock :read, 0
200
- defblock :lead, 0
201
- defblock :quote, 0
202
- defblock :bibpaper, 2..3, true, [:raw, :doc, :doc]
203
- defblock :doorquote, 1, false, [:doc]
204
- defblock :talk, 0
205
- defblock :graph, 1..3, false, [:raw, :raw, :doc]
206
-
207
- defcodeblock :emlist, 0..2, false, [:doc, :raw]
208
- defcodeblock :cmd, 0..1, false, [:doc]
209
- defcodeblock :source, 0..1, false, [:doc]
210
- defcodeblock :list, 2..3, false, [:raw, :doc, :raw]
211
- defcodeblock :listnum, 2..3, false, [:raw, :doc, :raw]
212
- defcodeblock :emlistnum, 0..2, false, [:doc, :raw]
213
- defcodeblock :texequation, 0, false
214
- defcodeblock :table, 0..2, [:raw, :doc]
215
- defcodeblock :image, 2..3, true, [:raw,:doc,:raw]
216
- defcodeblock :box, 0..1, false, [:doc]
217
-
218
- defblock :address, 0
219
- defblock :blockquote, 0
220
- defblock :bpo, 0
221
- defblock :flushright, 0
222
- defblock :centering, 0
223
- defblock :note, 0..1
224
- defblock :comment, 0..1, true
225
-
226
- defsingle :footnote, 2, [:raw, :doc]
227
- defsingle :noindent, 0
228
- defsingle :linebreak, 0
229
- defsingle :pagebreak, 0
230
- defsingle :indepimage, 1..3, [:raw, :doc, :raw]
231
- defsingle :numberlessimage, 1..3, [:raw, :doc, :raw]
232
- defsingle :hr, 0
233
- defsingle :parasep, 0
234
- defsingle :label, 1, [:raw]
235
- defsingle :raw, 1, [:raw]
236
- defsingle :tsize, 1, [:raw]
237
- defsingle :include, 1, [:raw]
238
- defsingle :olnum, 1, [:raw]
239
-
240
- definline :chapref
241
- definline :chap
242
- definline :title
243
- definline :img
244
- definline :imgref
245
- definline :icon
246
- definline :list
247
- definline :table
248
- definline :fn
249
- definline :kw
250
- definline :ruby
251
- definline :bou
252
- definline :ami
253
- definline :b
254
- definline :dtp
255
- definline :code
256
- definline :bib
257
- definline :hd
258
- definline :href
259
- definline :recipe
260
- definline :column
261
-
262
- definline :abbr
263
- definline :acronym
264
- definline :cite
265
- definline :dfn
266
- definline :em
267
- definline :kbd
268
- definline :q
269
- definline :samp
270
- definline :strong
271
- definline :var
272
- definline :big
273
- definline :small
274
- definline :del
275
- definline :ins
276
- definline :sup
277
- definline :sub
278
- definline :tt
279
- definline :i
280
- definline :tti
281
- definline :ttb
282
- definline :u
283
- definline :raw
284
- definline :br
285
- definline :m
286
- definline :uchar
287
- definline :idx
288
- definline :hidx
289
- definline :comment
290
- definline :include
291
-
292
-
293
- def compile_column(level, label, caption, content)
294
- buf = ""
295
- buf << @strategy.__send__("column_begin", level, label, caption)
296
- buf << content.to_doc
297
- buf << @strategy.__send__("column_end", level)
298
- buf
299
- end
300
-
301
- def compile_command(name, args, lines, node)
302
- syntax = syntax_descriptor(name)
303
- if !syntax || (!@strategy.respond_to?(syntax.name) && !@strategy.respond_to?("node_#{syntax.name}"))
304
- error "strategy does not support command: //#{name}"
305
- compile_unknown_command args, lines
306
- return
307
- end
308
- begin
309
- syntax.check_args args
310
- rescue ReVIEW::CompileError => err
311
- error err.message
312
- args = ['(NoArgument)'] * syntax.min_argc
313
- end
314
- if syntax.block_allowed?
315
- compile_block(syntax, args, lines, node)
316
- else
317
- if lines
318
- error "block is not allowed for command //#{syntax.name}; ignore"
319
- end
320
- compile_single(syntax, args, node)
321
- end
322
- end
323
-
324
- def compile_headline(level, tag, label, caption)
325
- buf = ""
326
- @headline_indexs ||= [0] ## XXX
327
- caption ||= ""
328
- caption.strip!
329
- index = level - 1
330
- if @headline_indexs.size > (index + 1)
331
- @headline_indexs = @headline_indexs[0..index]
332
- end
333
- @headline_indexs[index] = 0 if @headline_indexs[index].nil?
334
- @headline_indexs[index] += 1
335
- buf << @strategy.headline(level, label, caption)
336
- buf
337
- end
338
-
339
- def comment(text)
340
- @strategy.comment(text)
341
- end
342
-
343
- def compile_ulist(content)
344
- buf0 = ""
345
- level = 0
346
- content.each do |element|
347
- current_level, buf = element.level, element.to_doc
348
- if level == current_level
349
- buf0 << @strategy.ul_item_end
350
- # body
351
- buf0 << @strategy.ul_item_begin([buf])
352
- elsif level < current_level # down
353
- level_diff = current_level - level
354
- level = current_level
355
- (1..(level_diff - 1)).to_a.reverse.each do |i|
356
- buf0 << @strategy.ul_begin{i}
357
- buf0 << @strategy.ul_item_begin([])
358
- end
359
- buf0 << @strategy.ul_begin{level}
360
- buf0 << @strategy.ul_item_begin([buf])
361
- elsif level > current_level # up
362
- level_diff = level - current_level
363
- level = current_level
364
- (1..level_diff).to_a.reverse.each do |i|
365
- buf0 << @strategy.ul_item_end
366
- buf0 << @strategy.ul_end{level + i}
367
- end
368
- buf0 << @strategy.ul_item_end
369
- # body
370
- buf0 <<@strategy.ul_item_begin([buf])
371
- end
372
- end
373
-
374
- (1..level).to_a.reverse.each do |i|
375
- buf0 << @strategy.ul_item_end
376
- buf0 << @strategy.ul_end{i}
377
- end
378
- buf0
379
- end
380
-
381
- def compile_olist(content)
382
- buf0 = ""
383
- buf0 << @strategy.ol_begin
384
- content.each do |element|
385
- ## XXX 1st arg should be String, not Array
386
- buf0 << @strategy.ol_item(element.to_doc.split(/\n/), element.num)
387
- end
388
- buf0 << @strategy.ol_end
389
- buf0
390
- end
391
-
392
- def compile_dlist(content)
393
- buf = ""
394
- buf << @strategy.dl_begin
395
- content.each do |element|
396
- buf << @strategy.dt(element.text.to_doc)
397
- buf << @strategy.dd(element.content.map{|s| s.to_doc})
398
- end
399
- buf << @strategy.dl_end
400
- buf
401
- end
402
-
403
-
404
- def compile_unknown_command(args, lines)
405
- @strategy.unknown_command(args, lines)
406
- end
407
-
408
- def compile_block(syntax, args, lines, node)
409
- node_name = "node_#{syntax.name}".to_sym
410
- if @strategy.respond_to?(node_name)
411
- @strategy.__send__(node_name, node)
412
- else
413
- args_conv = syntax.parse_args(args)
414
- @strategy.__send__(syntax.name, (lines || default_block(syntax)), *args_conv)
415
- end
416
- end
417
-
418
- def default_block(syntax)
419
- if syntax.block_required?
420
- error "block is required for //#{syntax.name}; use empty block"
421
- end
422
- []
423
- end
424
-
425
- def compile_single(syntax, args, node)
426
- node_name = "node_#{syntax.name}".to_sym
427
- if @strategy.respond_to?(node_name)
428
- @strategy.__send__(node_name, node)
429
- else
430
- args_conv = syntax.parse_args(args)
431
- @strategy.__send__(syntax.name, *args_conv)
432
- end
433
- end
434
-
435
-
436
- def compile_inline(op, args)
437
- unless inline_defined?(op)
438
- raise ReVIEW::CompileError, "no such inline op: #{op}"
439
- end
440
- if @strategy.respond_to?("node_inline_#{op}")
441
- return @strategy.__send__("node_inline_#{op}", args)
442
- end
443
- unless @strategy.respond_to?("inline_#{op}")
444
- raise "strategy does not support inline op: @<#{op}>"
445
- end
446
- if !args
447
- @strategy.__send__("inline_#{op}", "")
448
- else
449
- @strategy.__send__("inline_#{op}", *(args.map(&:to_doc)))
450
- end
451
- rescue => err
452
- error err.message
453
- end
454
-
455
- def compile_paragraph(buf)
456
- @strategy.paragraph buf
457
- end
458
-
459
- def compile_raw(builders, content)
460
- c = @strategy.class.to_s.gsub(/ReVIEW::/, '').gsub(/Builder/, '').downcase
461
- if !builders || builders.include?(c)
462
- content.gsub("\\n", "\n")
463
- else
464
- ""
465
- end
466
- end
467
-
468
- def warn(msg)
469
- @strategy.warn msg
470
- end
471
-
472
- def error(msg)
473
- @strategy.error msg
474
- end
475
-
476
- def check_indent(s)
477
- s.size >= @list_stack.last.size
478
- end
479
-
480
- def check_nested_indent(s)
481
- s.size >= @list_stack.last.size + 2
482
- end
483
-
484
- def position
485
- Position.new(self)
486
- end
487
-
488
-
489
- }
490
-
491
- %% ast-location = ::ReVIEW
492
- %% headline = ast HeadlineNode(compiler, position, level, cmd, label, content)
493
- %% paragraph = ast ParagraphNode(compiler, position, content)
494
- %% block_element = ast BlockElementNode(compiler, position, name, args, content)
495
- %% code_block_element = ast CodeBlockElementNode(compiler, position, name, args, content)
496
- %% inline_element = ast InlineElementNode(compiler, position, symbol, content)
497
- %% inline_element_content = ast InlineElementContentNode(compiler, position, content)
498
- %% text = ast TextNode(compiler, position, content)
499
- %% raw = ast RawNode(compiler, builder, position, content)
500
- %% brace = ast BraceNode(compiler, position, content)
501
- %% singleline_content = ast SinglelineContentNode(compiler, position, content)
502
- %% singleline_comment = ast SinglelineCommentNode(compiler, position, content)
503
- %% ulist = ast UlistNode(compiler, position, content)
504
- %% ulist_element = ast UlistElementNode(compiler, position, level, content)
505
- %% olist = ast OlistNode(compiler, position, content)
506
- %% olist_element = ast OlistElementNode(compiler, position, num, content)
507
- %% dlist = ast DlistNode(compiler, position, content)
508
- %% dlist_element = ast DlistElementNode(compiler, position, text, content)
509
- %% bracket_arg = ast BracketArgNode(compiler, position, content)
510
- %% document = ast DocumentNode(compiler, position, content)
511
- %% column = ast ColumnNode(compiler, position, level, label, caption, content)
512
- %% newline = ast NewLineNode(compiler, position, content)
513
-
514
- # %% dummy
515
-
516
- root = Start
517
-
518
- Start = &. { @list_stack = Array.new } Document:c { @strategy.ast = c }
519
-
520
- ## a Document is a set of Blocks
521
- Document = BOM? Block*:c ~document(self, position, c)
522
-
523
- ## ignore leading blank lines
524
- Block = BlankLine*:c { c }
525
- ( SinglelineComment:c
526
- | Headline:c
527
- | BlockElement:c
528
- | Ulist:c
529
- | Olist:c
530
- | Dlist:c
531
- | Paragraph:c
532
- ) { c }
533
-
534
- BlankLine = Newline
535
-
536
- SinglelineComment = ("#@" < NonNewline+ > EOL) ~singleline_comment(self, position, text)
537
-
538
- Headline = HeadlinePrefix:level BracketArg?:cmd BraceArg?:label Space* SinglelineContent?:caption EOL ~headline(self, position, level, cmd, label, caption)
539
-
540
- HeadlinePrefix = < /={1,5}/ > { text.length }
541
-
542
- Paragraph = ParagraphLine+:c ~paragraph(self, position, c.flatten)
543
-
544
- ParagraphLine = !Headline !SinglelineComment !BlockElement !Ulist !Olist !Dlist SinglelineContent:c Newline { c }
545
-
546
- # There are 3 types of Block Element: raw Block, Code Block, and Normal Block
547
- BlockElement = ( "//raw[" RawBlockBuilderSelect?:b RawBlockElementArg*:r1 "]" Space* EOL
548
- ~raw(self, position, b, r1)
549
- | !"//raw" "//" ElementName:symbol &{ syntax = syntax_descriptor(symbol); syntax && syntax.code_block? } BracketArg*:args "{" Space* Newline CodeBlockElementContents?:contents "//}" Space* EOL
550
- ~code_block_element(self, position, symbol, args, contents)
551
- | !"//raw" "//" ElementName:symbol BracketArg*:args "{" Space* Newline BlockElementContents?:contents "//}" Space* EOL
552
- ~block_element(self, position, symbol, args, contents)
553
- | !"//raw" "//" ElementName:symbol BracketArg*:args Space* EOL ~block_element(self, position, symbol, args, nil)
554
- )
555
-
556
- RawBlockBuilderSelect = "|" Space* RawBlockBuilderSelectSub:c Space* "|" { c }
557
-
558
- RawBlockBuilderSelectSub = ( < AlphanumericAscii+ >:c1 Space* "," Space* RawBlockBuilderSelectSub:c2
559
- { [text] + c2 }
560
- | < AlphanumericAscii+ >:c1
561
- { [text] }
562
- )
563
-
564
- RawBlockElementArg = !"]" ( "\\]" { "]" }
565
- | "\\n" { "\n" }
566
- | < NonNewline > { text }
567
- )
568
-
569
- BracketArg = "[" BracketArgInline*:content "]" ~bracket_arg(self, position, content)
570
-
571
- ## XXX '\' (excpet '\]' and '\\' ) => '\' is ???
572
- BracketArgInline = ( InlineElement:c { c }
573
- | "\\]" ~text(self, position, "]")
574
- | "\\\\" ~text(self, position, "\\")
575
- | < /[^\r\n\]]/ > ~text(self, position, text)
576
- )
577
-
578
- BraceArg = "{" < /([^\r\n}\\]|\\[^\r\n])*/ > "}" { text }
579
-
580
- ## Standard BlockElement has nested blocks. Texts in content of block are parsed as Paragraph.
581
- BlockElementContents = BlockElementContent+:c { c }
582
-
583
- ### Headline is prohibited.
584
- ### Note: do not allow "//}" at front of Paragraph.
585
- BlockElementContent = ( SinglelineComment:c { c }
586
- | BlockElement:c { c }
587
- | Ulist:c
588
- | Dlist:c
589
- | Olist:c
590
- | BlankLine:c { c }
591
- | BlockElementParagraph:c { c }
592
- )
593
-
594
- ## it's like Paragraph, but it's in a block, so do not allow '//}\n'
595
- BlockElementParagraph = BlockElementParagraphLine+:c ~paragraph(self, position, c.flatten)
596
- BlockElementParagraphLine = !"//}" !BlankLine !SinglelineComment !BlockElement !Ulist !Olist !Dlist SinglelineContent:c Newline { c }
597
-
598
- ## In CodeBlockElementContents, newline should no be ingored. So we use TextNode instead of NewLineNode.
599
- CodeBlockElementContents = CodeBlockElementContent+:c { c }
600
- CodeBlockElementContent = ( SinglelineComment:c { c }
601
- | BlankLine:c { ::ReVIEW::TextNode.new(self, position, "\n") }
602
- | !"//}" SinglelineContent:c Newline { [c, ::ReVIEW::TextNode.new(self, position, "\n")] }
603
- )
604
-
605
- ## Ulist and Olist
606
-
607
- Bullet = "*"
608
- Enumerator = < /[0-9]+/ > { num = text } "." { num.to_i }
609
-
610
- Ulist = Indent+:s Bullet+:b Space+ { @list_stack.push(s) } UlistItemBlock:item
611
- { if b.size > 1 then item.level = b.size end }
612
- (UlistItem | UlistItemMore | NestedList)*:items &{ s == @list_stack.pop }
613
- ~ulist(self, position, items.unshift(item))
614
-
615
- Olist = Indent+:s Enumerator:e Space+ { @list_stack.push(s) } OlistItemBlock:item
616
- { item.num = e }
617
- (OlistItem | NestedList)*:items &{ s == @list_stack.pop }
618
- ~olist(self, position, items.unshift(item))
619
-
620
- UlistItemBlock = ListItemFirstLine:c ListItemLine*:d ~ulist_element(self, position, @list_stack.size, d.unshift(c))
621
- OlistItemBlock = ListItemFirstLine:c ListItemLine*:d ~olist_element(self, position, 0, d.unshift(c))
622
-
623
- ListItemFirstLine = SinglelineContent:c Newline { c }
624
- ListItemLine = Indent+:s !Bullet !Enumerator !Space SinglelineContent:c &{ check_indent(s) } Newline { c }
625
-
626
- UlistItemMore = Indent+:s Bullet Bullet+:b Space+ &{ check_indent(s) } UlistItemBlock:item { item.level = b.size+1; item }
627
-
628
- UlistItem = Indent+:s Bullet Space+ &{ check_indent(s) } UlistItemBlock:item { item }
629
- OlistItem = Indent+:s Enumerator:e Space+ &{ check_indent(s) } OlistItemBlock:item { item.num = e; item }
630
-
631
- ## NestedList is markdown-like indented syntax.
632
- ## You can write nested Ulist and Olist with this syntax.
633
-
634
- NestedList = (NestedUlist | NestedOlist)
635
-
636
- NestedUlist = Indent+:s Bullet Space+ &{ check_nested_indent(s) } { @list_stack.push(s) } UlistItemBlock:item
637
- (UlistItem | NestedList)*:items &{ s == @list_stack.pop }
638
- ~ulist(self, position, items.unshift(item))
639
- NestedOlist = Indent+:s Enumerator:e Space+ &{ check_nested_indent(s) } { @list_stack.push(s) } OlistItemBlock:item
640
- { item.num = e }
641
- (OlistItem | NestedList)*:items &{ s == @list_stack.pop }
642
- ~olist(self, position, items.unshift(item))
643
-
644
- # Dlist
645
- Dlist = (DlistElement | SinglelineComment)+:content ~dlist(self, position, content)
646
-
647
- DlistElement = Indent* ":" Space+ SinglelineContent:text Newline DlistElementContent+:content ~dlist_element(self, position, text, content)
648
-
649
- DlistElementContent = (SinglelineComment:c { c }
650
- |Space+ SinglelineContent:c Newline { c }
651
- )
652
-
653
- SinglelineContent = Inline+:c ~singleline_content(self, position, c)
654
-
655
-
656
- # Inline Element and Non Inline Element
657
-
658
- Inline = ( InlineElement | NonInlineElement)
659
-
660
- NonInlineElement = !InlineElement < NonNewline > ~text(self, position, text)
661
-
662
- InlineElement = ( RawInlineElement:c { c }
663
- | !RawInlineElement "@<" InlineElementSymbol:symbol ">" "{" InlineElementContents?:contents "}" ~inline_element(self, position, symbol,contents)
664
- )
665
-
666
- RawInlineElement = "@<raw>{" RawBlockBuilderSelect?:builders RawInlineElementContent+:c "}" ~raw(self, position, builders,c)
667
-
668
- RawInlineElementContent = ( "\\}" { "}" }
669
- | < /[^\r\n\}]/ > { text }
670
- )
671
-
672
- InlineElementSymbol = < AlphanumericAscii+ > { text }
673
-
674
- InlineElementContents = !"}" InlineElementContentsSub:c { c }
675
-
676
- InlineElementContentsSub = !"}" ( Space* InlineElementContent:c1 Space* "," InlineElementContentsSub:c2 { [c1]+c2 }
677
- | Space* InlineElementContent:c1 Space* { [c1] }
678
- )
679
-
680
-
681
- InlineElementContent = InlineElementContentSub+:d { d }
682
-
683
- InlineElementContentSub = ( InlineElement:c { c }
684
- | !InlineElement QuotedInlineText:content ~inline_element_content(self, position, content)
685
- | !InlineElement InlineElementContentText+:content ~inline_element_content(self, position, content)
686
- )
687
-
688
- ## Quoted Inline Text is "..."
689
- ## In Quoted Inline Text, "\\" is "\", "\'" is "'", other characters are kept as is.
690
- QuotedInlineText = "\""
691
- ( "\\\"" { "\"" }
692
- | "\\\\" { "\\" }
693
- | < /[^"\r\n\\]/ > { text }
694
- )+:str "\"" ~text(self, position, str.join(""))
695
-
696
- ## XXX '\' (excpet '\}' and '\,' and '\\' ) => '\' is OK?
697
- InlineElementContentText = ( "\\}" ~text(self, position, "}")
698
- | "\\," ~text(self, position, ",")
699
- | "\\\\" ~text(self, position, "\\" )
700
- | "\\" ~text(self, position, "\\" )
701
- | !InlineElement < /[^\r\n\\},]/> ~text(self, position, text)
702
- )
703
-
704
- NonNewline = /[^\r\n]/
705
-
706
- Space = /[ \t]/
707
-
708
- Indent = " "
709
-
710
- EOL = (Newline|EOF)
711
-
712
- EOF = !.
713
-
714
- ElementName = < LowerAlphabetAscii+ > { text }
715
-
716
- %literals = ReVIEW::Compiler::Literals
717
- Alphanumeric = %literals.Alphanumeric
718
- AlphanumericAscii = %literals.AlphanumericAscii
719
- LowerAlphabetAscii = %literals.LowerAlphabetAscii
720
- Digit = %literals.Digit
721
- BOM = %literals.BOM
722
- Newline = %literals.Newline:n ~newline(self, position, "\n")
723
- NonAlphanumeric = %literals.NonAlphanumeric
724
- Spacechar = %literals.Spacechar