omf_web 1.2.3 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,596 +21,595 @@
21
21
 
22
22
  module MaRuKu; module In; module Markdown; module BlockLevelParser
23
23
 
24
- include Helpers
25
- include MaRuKu::Strings
26
- include MaRuKu::In::Markdown::SpanLevelParser
27
-
28
- class BlockContext < Array
29
- def describe
30
- n = 5
31
- desc = size > n ? self[-n,n] : self
32
- "Last #{n} elements: "+
33
- desc.map{|x| "\n -" + x.inspect}.join
34
- end
35
- end
36
-
37
- # Splits the string and calls parse_lines_as_markdown
38
- def parse_text_as_markdown(text)
39
- lines = split_lines(text)
40
- src = LineSource.new(lines)
41
- return parse_blocks(src)
42
- end
43
-
44
- # Input is a LineSource
45
- def parse_blocks(src)
46
- output = BlockContext.new
47
-
48
- # run state machine
49
- while src.cur_line
50
-
51
- next if check_block_extensions(src, output, src.cur_line)
24
+ include Helpers
25
+ include MaRuKu::Strings
26
+ include MaRuKu::In::Markdown::SpanLevelParser
27
+
28
+ class BlockContext < Array
29
+ def describe
30
+ n = 5
31
+ desc = size > n ? self[-n,n] : self
32
+ "Last #{n} elements: "+
33
+ desc.map{|x| "\n -" + x.inspect}.join
34
+ end
35
+ end
36
+
37
+ # Splits the string and calls parse_lines_as_markdown
38
+ def parse_text_as_markdown(text)
39
+ lines = split_lines(text)
40
+ src = LineSource.new(lines)
41
+ return parse_blocks(src)
42
+ end
43
+
44
+ # Input is a LineSource
45
+ def parse_blocks(src)
46
+ output = BlockContext.new
47
+
48
+ # run state machine
49
+ while src.cur_line
50
+
51
+ next if check_block_extensions(src, output, src.cur_line)
52
52
 
53
53
  # Prints detected type (useful for debugging)
54
- # puts "#{src.cur_line.md_type}|#{src.cur_line}"
55
- case src.cur_line.md_type
56
- when :empty;
57
- output.push :empty
58
- src.ignore_line
59
- when :ial
60
- m = InlineAttributeList.match src.shift_line
61
- content = m[1] || ""
54
+ #puts "PARSE>>>> #{src.cur_line.md_type}|#{src.cur_line}"
55
+ case src.cur_line.md_type
56
+ when :empty;
57
+ output.push :empty
58
+ src.ignore_line
59
+ when :ial
60
+ m = InlineAttributeList.match src.shift_line
61
+ content = m[1] || ""
62
62
  # puts "Content: #{content.inspect}"
63
- src2 = CharSource.new(content, src)
64
- interpret_extension(src2, output, [nil])
65
- when :ald
66
- output.push read_ald(src)
67
- when :text
68
- # paragraph, or table, or definition list
69
- read_text_material(src, output)
70
- when :header2, :hrule
71
- # hrule
72
- src.shift_line
73
- output.push md_hrule()
74
- when :header3
75
- output.push read_header3(src)
76
- when :ulist, :olist
77
- list_type = src.cur_line.md_type == :ulist ? :ul : :ol
78
- li = read_list_item(src)
79
- # append to current list if we have one
80
- if output.last.kind_of?(MDElement) &&
81
- output.last.node_type == list_type then
82
- output.last.children << li
83
- else
84
- output.push md_el(list_type, [li])
85
- end
86
- when :quote; output.push read_quote(src)
87
- when :code; e = read_code(src); output << e if e
88
- when :raw_html; e = read_raw_html(src); output << e if e
89
-
90
- when :footnote_text; output.push read_footnote_text(src)
91
- when :ref_definition
92
- if src.parent && (src.cur_index == 0)
93
- read_text_material(src, output)
94
- else
95
- read_ref_definition(src, output)
96
- end
97
- when :abbreviation; output.push read_abbreviation(src)
98
- when :xml_instr; read_xml_instruction(src, output)
99
- when :metadata;
100
- maruku_error "Please use the new meta-data syntax: \n"+
101
- " http://maruku.rubyforge.org/proposal.html\n", src
102
- src.ignore_line
103
- else # warn if we forgot something
104
- md_type = src.cur_line.md_type
105
- line = src.cur_line
106
- maruku_error "Ignoring line '#{line}' type = #{md_type}", src
107
- src.shift_line
108
- end
109
- end
110
-
111
- merge_ial(output, src, output)
112
- output.delete_if {|x| x.kind_of?(MDElement) &&
113
- x.node_type == :ial}
114
-
115
- # get rid of empty line markers
116
- output.delete_if {|x| x == :empty}
117
- # See for each list if we can omit the paragraphs and use li_span
118
- # TODO: do this after
119
- output.each do |c|
120
- # Remove paragraphs that we can get rid of
121
- if [:ul,:ol].include? c.node_type
122
- if c.children.all? {|li| !li.want_my_paragraph} then
123
- c.children.each do |d|
124
- d.node_type = :li_span
125
- d.children = d.children[0].children
126
- end
127
- end
128
- end
129
- if c.node_type == :definition_list
130
- if c.children.all?{|defi| !defi.want_my_paragraph} then
131
- c.children.each do |definition|
132
- definition.definitions.each do |dd|
133
- dd.children = dd.children[0].children
134
- end
135
- end
136
- end
137
- end
138
- end
139
-
140
- output
141
- end
142
-
143
- def read_text_material(src, output)
144
- if src.cur_line =~ MightBeTableHeader and
145
- (src.next_line && src.next_line =~ TableSeparator)
146
- output.push read_table(src)
147
- elsif [:header1,:header2].include? src.next_line.md_type
148
- output.push read_header12(src)
149
- elsif eventually_comes_a_def_list(src)
150
- definition = read_definition(src)
151
- if output.last.kind_of?(MDElement) &&
152
- output.last.node_type == :definition_list then
153
- output.last.children << definition
154
- else
155
- output.push md_el(:definition_list, [definition])
156
- end
157
- else # Start of a paragraph
158
- output.push read_paragraph(src)
159
- end
160
- end
161
-
162
-
163
- def read_ald(src)
164
- if (l=src.shift_line) =~ AttributeDefinitionList
165
- id = $1; al=$2;
166
- al = read_attribute_list(CharSource.new(al,src), context=nil, break_on=[nil])
167
- self.ald[id] = al;
168
- return md_ald(id, al)
169
- else
170
- maruku_error "Bug Bug:\n#{l.inspect}"
171
- return nil
172
- end
173
- end
174
-
175
- # reads a header (with ----- or ========)
176
- def read_header12(src)
177
- line = src.shift_line.strip
178
- al = nil
179
- # Check if there is an IAL
180
- if new_meta_data? and line =~ /^(.*)\{(.*)\}\s*$/
181
- line = $1.strip
182
- ial = $2
183
- al = read_attribute_list(CharSource.new(ial,src), context=nil, break_on=[nil])
184
- end
185
- text = parse_lines_as_span [ line ]
186
- level = src.cur_line.md_type == :header2 ? 2 : 1;
187
- src.shift_line
188
- return md_header(level, text, al, src.cur_index)
189
- end
190
-
191
- # reads a header like '#### header ####'
192
- def read_header3(src)
63
+ src2 = CharSource.new(content, src)
64
+ interpret_extension(src2, output, [nil])
65
+ when :ald
66
+ output.push read_ald(src)
67
+ when :text
68
+ # paragraph, or table, or definition list
69
+ read_text_material(src, output)
70
+ when :header2, :hrule
71
+ src.shift_line
72
+ output.push md_hrule()
73
+ when :header3
74
+ output.push read_header3(src)
75
+ when :ulist, :olist
76
+ list_type = src.cur_line.md_type == :ulist ? :ul : :ol
77
+ li = read_list_item(src)
78
+ # append to current list if we have one
79
+ if output.last.kind_of?(MDElement) &&
80
+ output.last.node_type == list_type then
81
+ output.last.children << li
82
+ else
83
+ output.push md_el(list_type, [li])
84
+ end
85
+ when :quote; output.push read_quote(src)
86
+ when :code; e = read_code(src); output << e if e
87
+ when :raw_html; e = read_raw_html(src); output << e if e
88
+
89
+ when :footnote_text; output.push read_footnote_text(src)
90
+ when :ref_definition
91
+ if src.parent && (src.cur_index == 0)
92
+ read_text_material(src, output)
93
+ else
94
+ read_ref_definition(src, output)
95
+ end
96
+ when :abbreviation; output.push read_abbreviation(src)
97
+ when :xml_instr; read_xml_instruction(src, output)
98
+ when :metadata;
99
+ maruku_error "Please use the new meta-data syntax: \n"+
100
+ " http://maruku.rubyforge.org/proposal.html\n", src
101
+ src.ignore_line
102
+ else # warn if we forgot something
103
+ md_type = src.cur_line.md_type
104
+ line = src.cur_line
105
+ maruku_error "Ignoring line '#{line}' type = #{md_type}", src
106
+ src.shift_line
107
+ end
108
+ end
109
+
110
+ merge_ial(output, src, output)
111
+ output.delete_if {|x| x.kind_of?(MDElement) &&
112
+ x.node_type == :ial}
113
+
114
+ # get rid of empty line markers
115
+ output.delete_if {|x| x == :empty}
116
+ # See for each list if we can omit the paragraphs and use li_span
117
+ # TODO: do this after
118
+ output.each do |c|
119
+ # Remove paragraphs that we can get rid of
120
+ if [:ul,:ol].include? c.node_type
121
+ if c.children.all? {|li| !li.want_my_paragraph} then
122
+ c.children.each do |d|
123
+ d.node_type = :li_span
124
+ d.children = d.children[0].children
125
+ end
126
+ end
127
+ end
128
+ if c.node_type == :definition_list
129
+ if c.children.all?{|defi| !defi.want_my_paragraph} then
130
+ c.children.each do |definition|
131
+ definition.definitions.each do |dd|
132
+ dd.children = dd.children[0].children
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ output
140
+ end
141
+
142
+ def read_text_material(src, output)
143
+ if src.cur_line =~ MightBeTableHeader and
144
+ (src.next_line && src.next_line =~ TableSeparator)
145
+ output.push read_table(src)
146
+ elsif [:header1,:header2].include? src.next_line.md_type
147
+ output.push read_header12(src)
148
+ elsif eventually_comes_a_def_list(src)
149
+ definition = read_definition(src)
150
+ if output.last.kind_of?(MDElement) &&
151
+ output.last.node_type == :definition_list then
152
+ output.last.children << definition
153
+ else
154
+ output.push md_el(:definition_list, [definition])
155
+ end
156
+ else # Start of a paragraph
157
+ output.push read_paragraph(src)
158
+ end
159
+ end
160
+
161
+
162
+ def read_ald(src)
163
+ if (l=src.shift_line) =~ AttributeDefinitionList
164
+ id = $1; al=$2;
165
+ al = read_attribute_list(CharSource.new(al,src), context=nil, break_on=[nil])
166
+ self.ald[id] = al;
167
+ return md_ald(id, al)
168
+ else
169
+ maruku_error "Bug Bug:\n#{l.inspect}"
170
+ return nil
171
+ end
172
+ end
173
+
174
+ # reads a header (with ----- or ========)
175
+ def read_header12(src)
176
+ line = src.shift_line.strip
177
+ al = nil
178
+ # Check if there is an IAL
179
+ if new_meta_data? and line =~ /^(.*)\{(.*)\}\s*$/
180
+ line = $1.strip
181
+ ial = $2
182
+ al = read_attribute_list(CharSource.new(ial,src), context=nil, break_on=[nil])
183
+ end
184
+ text = parse_lines_as_span [ line ]
185
+ level = src.cur_line.md_type == :header2 ? 2 : 1;
186
+ src.shift_line
187
+ return md_header(level, text, al, src.cur_index)
188
+ end
189
+
190
+ # reads a header like '#### header ####'
191
+ def read_header3(src)
193
192
  # puts "READ_H3: #{src.inspect}"
194
- line = src.shift_line.strip
195
- al = nil
196
- # Check if there is an IAL
197
- if new_meta_data? and line =~ /^(.*)\{(.*)\}\s*$/
198
- line = $1.strip
199
- ial = $2
200
- al = read_attribute_list(CharSource.new(ial,src), context=nil, break_on=[nil])
201
- end
202
- level = num_leading_hashes(line)
203
- text = parse_lines_as_span [strip_hashes(line)]
204
- return md_header(level, text, al, src.cur_index)
205
- end
206
-
207
- def read_xml_instruction(src, output)
208
- m = /^\s*<\?((\w+)\s*)?(.*)$/.match src.shift_line
209
- raise "BugBug" if not m
210
- target = m[2] || ''
211
- code = m[3]
212
- until code =~ /\?>/
213
- code += "\n"+src.shift_line
214
- end
215
- if not code =~ (/\?>\s*$/)
216
- garbage = (/\?>(.*)$/.match(code))[1]
217
- maruku_error "Trailing garbage on last line: #{garbage.inspect}:\n"+
218
- add_tabs(code, 1, '|'), src
219
- end
220
- code.gsub!(/\?>\s*$/, '')
221
-
222
- if target == 'mrk' && MaRuKu::Globals[:unsafe_features]
223
- result = safe_execute_code(self, code)
224
- if result
225
- if result.kind_of? String
226
- raise "Not expected"
227
- else
228
- output.push(*result)
229
- end
230
- end
231
- else
232
- output.push md_xml_instr(target, code)
233
- end
234
- end
235
-
236
- def read_raw_html(src)
237
- h = HTMLHelper.new
238
- begin
239
- h.eat_this(l=src.shift_line)
193
+ line = src.shift_line.strip
194
+ al = nil
195
+ # Check if there is an IAL
196
+ if new_meta_data? and line =~ /^(.*)\{(.*)\}\s*$/
197
+ line = $1.strip
198
+ ial = $2
199
+ al = read_attribute_list(CharSource.new(ial,src), context=nil, break_on=[nil])
200
+ end
201
+ level = num_leading_hashes(line)
202
+ text = parse_lines_as_span [strip_hashes(line)]
203
+ return md_header(level, text, al, src.cur_index)
204
+ end
205
+
206
+ def read_xml_instruction(src, output)
207
+ m = /^\s*<\?((\w+)\s*)?(.*)$/.match src.shift_line
208
+ raise "BugBug" if not m
209
+ target = m[2] || ''
210
+ code = m[3]
211
+ until code =~ /\?>/
212
+ code += "\n"+src.shift_line
213
+ end
214
+ if not code =~ (/\?>\s*$/)
215
+ garbage = (/\?>(.*)$/.match(code))[1]
216
+ maruku_error "Trailing garbage on last line: #{garbage.inspect}:\n"+
217
+ add_tabs(code, 1, '|'), src
218
+ end
219
+ code.gsub!(/\?>\s*$/, '')
220
+
221
+ if target == 'mrk' && MaRuKu::Globals[:unsafe_features]
222
+ result = safe_execute_code(self, code)
223
+ if result
224
+ if result.kind_of? String
225
+ raise "Not expected"
226
+ else
227
+ output.push(*result)
228
+ end
229
+ end
230
+ else
231
+ output.push md_xml_instr(target, code)
232
+ end
233
+ end
234
+
235
+ def read_raw_html(src)
236
+ h = HTMLHelper.new
237
+ begin
238
+ h.eat_this(l=src.shift_line)
240
239
  # puts "\nBLOCK:\nhtml -> #{l.inspect}"
241
- while src.cur_line and not h.is_finished?
242
- l=src.shift_line
240
+ while src.cur_line and not h.is_finished?
241
+ l=src.shift_line
243
242
  # puts "html -> #{l.inspect}"
244
- h.eat_this "\n"+l
245
- end
246
- rescue Exception => e
247
- ex = e.inspect + e.backtrace.join("\n")
248
- maruku_error "Bad block-level HTML:\n#{add_tabs(ex,1,'|')}\n", src
249
- end
250
- if not (h.rest =~ /^\s*$/)
251
- maruku_error "Could you please format this better?\n"+
252
- "I see that #{h.rest.inspect} is left after the raw HTML.", src
253
- end
254
- raw_html = h.stuff_you_read
255
-
256
- return md_html(raw_html)
257
- end
258
-
259
- def read_paragraph(src)
260
- lines = [src.shift_line]
261
- while src.cur_line
262
- # :olist does not break
263
- case t = src.cur_line.md_type
264
- when :quote,:header3,:empty,:ref_definition,:ial #,:xml_instr,:raw_html
265
- break
266
- when :olist,:ulist
267
- break if src.next_line.md_type == t
268
- end
269
- break if src.cur_line.strip.size == 0
270
- break if [:header1,:header2].include? src.next_line.md_type
271
- break if any_matching_block_extension?(src.cur_line)
272
-
273
- lines << src.shift_line
274
- end
243
+ h.eat_this "\n"+l
244
+ end
245
+ rescue Exception => e
246
+ ex = e.inspect + e.backtrace.join("\n")
247
+ maruku_error "Bad block-level HTML:\n#{add_tabs(ex,1,'|')}\n", src
248
+ end
249
+ if not (h.rest =~ /^\s*$/)
250
+ maruku_error "Could you please format this better?\n"+
251
+ "I see that #{h.rest.inspect} is left after the raw HTML.", src
252
+ end
253
+ raw_html = h.stuff_you_read
254
+
255
+ return md_html(raw_html)
256
+ end
257
+
258
+ def read_paragraph(src)
259
+ lines = [src.shift_line]
260
+ while src.cur_line
261
+ # :olist does not break
262
+ case t = src.cur_line.md_type
263
+ when :quote,:header3,:empty,:ref_definition,:ial #,:xml_instr,:raw_html
264
+ break
265
+ when :olist,:ulist
266
+ break if src.next_line.md_type == t
267
+ end
268
+ break if src.cur_line.strip.size == 0
269
+ break if [:header1,:header2].include? src.next_line.md_type
270
+ break if any_matching_block_extension?(src.cur_line)
271
+
272
+ lines << src.shift_line
273
+ end
275
274
  # dbg_describe_ary(lines, 'PAR')
276
- children = parse_lines_as_span(lines, src)
275
+ children = parse_lines_as_span(lines, src)
277
276
 
278
- return md_par(children, nil, src.cur_index)
279
- end
277
+ return md_par(children, nil, src.cur_index)
278
+ end
280
279
 
281
- # Reads one list item, either ordered or unordered.
282
- def read_list_item(src)
283
- parent_offset = src.cur_index
280
+ # Reads one list item, either ordered or unordered.
281
+ def read_list_item(src)
282
+ parent_offset = src.cur_index
284
283
 
285
- item_type = src.cur_line.md_type
286
- first = src.shift_line
284
+ item_type = src.cur_line.md_type
285
+ first = src.shift_line
287
286
 
288
- indentation, ial = spaces_before_first_char(first)
289
- al = read_attribute_list(CharSource.new(ial,src), context=nil, break_on=[nil]) if ial
290
- break_list = [:ulist, :olist, :ial]
291
- # Ugly things going on inside `read_indented_content`
292
- lines, want_my_paragraph =
293
- read_indented_content(src,indentation, break_list, item_type)
287
+ indentation, ial = spaces_before_first_char(first)
288
+ al = read_attribute_list(CharSource.new(ial,src), context=nil, break_on=[nil]) if ial
289
+ break_list = [:ulist, :olist, :ial]
290
+ # Ugly things going on inside `read_indented_content`
291
+ lines, want_my_paragraph =
292
+ read_indented_content(src,indentation, break_list, item_type)
294
293
 
295
- # add first line
296
- # Strip first '*', '-', '+' from first line
297
- stripped = first[indentation, first.size-1]
298
- lines.unshift stripped
294
+ # add first line
295
+ # Strip first '*', '-', '+' from first line
296
+ stripped = first[indentation, first.size-1]
297
+ lines.unshift stripped
299
298
 
300
- # dbg_describe_ary(lines, 'LIST ITEM ')
299
+ # dbg_describe_ary(lines, 'LIST ITEM ')
301
300
 
302
- src2 = LineSource.new(lines, src, parent_offset)
303
- children = parse_blocks(src2)
304
- with_par = want_my_paragraph || (children.size>1)
301
+ src2 = LineSource.new(lines, src, parent_offset)
302
+ children = parse_blocks(src2)
303
+ with_par = want_my_paragraph || (children.size>1)
305
304
 
306
- return md_li(children, with_par, al)
307
- end
305
+ return md_li(children, with_par, al)
306
+ end
308
307
 
309
- def read_abbreviation(src)
310
- if not (l=src.shift_line) =~ Abbreviation
311
- maruku_error "Bug: it's Andrea's fault. Tell him.\n#{l.inspect}"
312
- end
308
+ def read_abbreviation(src)
309
+ if not (l=src.shift_line) =~ Abbreviation
310
+ maruku_error "Bug: it's Andrea's fault. Tell him.\n#{l.inspect}"
311
+ end
313
312
 
314
- abbr = $1
315
- desc = $2
313
+ abbr = $1
314
+ desc = $2
316
315
 
317
- if (not abbr) or (abbr.size==0)
318
- maruku_error "Bad abbrev. abbr=#{abbr.inspect} desc=#{desc.inspect}"
319
- end
316
+ if (not abbr) or (abbr.size==0)
317
+ maruku_error "Bad abbrev. abbr=#{abbr.inspect} desc=#{desc.inspect}"
318
+ end
320
319
 
321
- self.abbreviations[abbr] = desc
320
+ self.abbreviations[abbr] = desc
322
321
 
323
- return md_abbr_def(abbr, desc)
324
- end
322
+ return md_abbr_def(abbr, desc)
323
+ end
325
324
 
326
- def read_footnote_text(src)
327
- parent_offset = src.cur_index
325
+ def read_footnote_text(src)
326
+ parent_offset = src.cur_index
328
327
 
329
- first = src.shift_line
328
+ first = src.shift_line
330
329
 
331
- if not first =~ FootnoteText
332
- maruku_error "Bug (it's Andrea's fault)"
333
- end
330
+ if not first =~ FootnoteText
331
+ maruku_error "Bug (it's Andrea's fault)"
332
+ end
334
333
 
335
- id = $1
336
- text = $2
334
+ id = $1
335
+ text = $2
337
336
 
338
- # Ugly things going on inside `read_indented_content`
339
- indentation = 4 #first.size-text.size
337
+ # Ugly things going on inside `read_indented_content`
338
+ indentation = 4 #first.size-text.size
340
339
 
341
340
  # puts "id =_#{id}_; text=_#{text}_ indent=#{indentation}"
342
341
 
343
- break_list = [:footnote_text, :ref_definition, :definition, :abbreviation]
344
- item_type = :footnote_text
345
- lines, want_my_paragraph =
346
- read_indented_content(src,indentation, break_list, item_type)
342
+ break_list = [:footnote_text, :ref_definition, :definition, :abbreviation]
343
+ item_type = :footnote_text
344
+ lines, want_my_paragraph =
345
+ read_indented_content(src,indentation, break_list, item_type)
347
346
 
348
- # add first line
349
- if text && text.strip != "" then lines.unshift text end
347
+ # add first line
348
+ if text && text.strip != "" then lines.unshift text end
350
349
 
351
350
  # dbg_describe_ary(lines, 'FOOTNOTE')
352
- src2 = LineSource.new(lines, src, parent_offset)
353
- children = parse_blocks(src2)
354
-
355
- e = md_footnote(id, children)
356
- self.footnotes[id] = e
357
- return e
358
- end
359
-
360
-
361
- # This is the only ugly function in the code base.
362
- # It is used to read list items, descriptions, footnote text
363
- def read_indented_content(src, indentation, break_list, item_type)
364
- lines =[]
365
- # collect all indented lines
366
- saw_empty = false; saw_anything_after = false
367
- while src.cur_line
351
+ src2 = LineSource.new(lines, src, parent_offset)
352
+ children = parse_blocks(src2)
353
+
354
+ e = md_footnote(id, children)
355
+ self.footnotes[id] = e
356
+ return e
357
+ end
358
+
359
+
360
+ # This is the only ugly function in the code base.
361
+ # It is used to read list items, descriptions, footnote text
362
+ def read_indented_content(src, indentation, break_list, item_type)
363
+ lines =[]
364
+ # collect all indented lines
365
+ saw_empty = false; saw_anything_after = false
366
+ while src.cur_line
368
367
  # puts "Reading indent = #{indentation} #{src.cur_line.inspect}"
369
- #puts "#{src.cur_line.md_type} #{src.cur_line.inspect}"
370
- if src.cur_line.md_type == :empty
371
- saw_empty = true
372
- lines << src.shift_line
373
- next
374
- end
375
-
376
- # after a white line
377
- if saw_empty
378
- # we expect things to be properly aligned
379
- if (ns=number_of_leading_spaces(src.cur_line)) < indentation
380
- #puts "breaking for spaces, only #{ns}: #{src.cur_line}"
381
- break
382
- end
383
- saw_anything_after = true
384
- else
368
+ #puts "#{src.cur_line.md_type} #{src.cur_line.inspect}"
369
+ if src.cur_line.md_type == :empty
370
+ saw_empty = true
371
+ lines << src.shift_line
372
+ next
373
+ end
374
+
375
+ # after a white line
376
+ if saw_empty
377
+ # we expect things to be properly aligned
378
+ if (ns=number_of_leading_spaces(src.cur_line)) < indentation
379
+ #puts "breaking for spaces, only #{ns}: #{src.cur_line}"
380
+ break
381
+ end
382
+ saw_anything_after = true
383
+ else
385
384
  # if src.cur_line[0] != ?\
386
- break if break_list.include? src.cur_line.md_type
385
+ break if break_list.include? src.cur_line.md_type
387
386
  # end
388
387
  # break if src.cur_line.md_type != :text
389
- end
388
+ end
390
389
 
391
390
 
392
- stripped = strip_indent(src.shift_line, indentation)
393
- lines << stripped
391
+ stripped = strip_indent(src.shift_line, indentation)
392
+ lines << stripped
394
393
 
395
- #puts "Accepted as #{stripped.inspect}"
394
+ #puts "Accepted as #{stripped.inspect}"
396
395
 
397
- # You are only required to indent the first line of
398
- # a child paragraph.
399
- if stripped.md_type == :text
400
- while src.cur_line && (src.cur_line.md_type == :text)
401
- lines << strip_indent(src.shift_line, indentation)
402
- end
403
- end
404
- end
396
+ # You are only required to indent the first line of
397
+ # a child paragraph.
398
+ if stripped.md_type == :text
399
+ while src.cur_line && (src.cur_line.md_type == :text)
400
+ lines << strip_indent(src.shift_line, indentation)
401
+ end
402
+ end
403
+ end
405
404
 
406
- want_my_paragraph = saw_anything_after ||
407
- (saw_empty && (src.cur_line && (src.cur_line.md_type == item_type)))
405
+ want_my_paragraph = saw_anything_after ||
406
+ (saw_empty && (src.cur_line && (src.cur_line.md_type == item_type)))
408
407
 
409
408
  # dbg_describe_ary(lines, 'LI')
410
- # create a new context
409
+ # create a new context
411
410
 
412
- while lines.last && (lines.last.md_type == :empty)
413
- lines.pop
414
- end
411
+ while lines.last && (lines.last.md_type == :empty)
412
+ lines.pop
413
+ end
415
414
 
416
- return lines, want_my_paragraph
417
- end
415
+ return lines, want_my_paragraph
416
+ end
418
417
 
419
418
 
420
- def read_quote(src)
421
- parent_offset = src.cur_index
419
+ def read_quote(src)
420
+ parent_offset = src.cur_index
422
421
 
423
- lines = []
424
- # collect all indented lines
425
- while src.cur_line && src.cur_line.md_type == :quote
426
- lines << unquote(src.shift_line)
427
- end
422
+ lines = []
423
+ # collect all indented lines
424
+ while src.cur_line && src.cur_line.md_type == :quote
425
+ lines << unquote(src.shift_line)
426
+ end
428
427
  # dbg_describe_ary(lines, 'QUOTE')
429
428
 
430
- src2 = LineSource.new(lines, src, parent_offset)
431
- children = parse_blocks(src2)
432
- return md_quote(children)
433
- end
429
+ src2 = LineSource.new(lines, src, parent_offset)
430
+ children = parse_blocks(src2)
431
+ return md_quote(children)
432
+ end
434
433
 
435
- def read_code(src)
436
- # collect all indented lines
437
- lines = []
438
- while src.cur_line && ([:code, :empty].include? src.cur_line.md_type)
439
- lines << strip_indent(src.shift_line, 4)
440
- end
434
+ def read_code(src)
435
+ # collect all indented lines
436
+ lines = []
437
+ while src.cur_line && ([:code, :empty].include? src.cur_line.md_type)
438
+ lines << strip_indent(src.shift_line, 4)
439
+ end
441
440
 
442
- #while lines.last && (lines.last.md_type == :empty )
443
- while lines.last && lines.last.strip.size == 0
444
- lines.pop
445
- end
441
+ #while lines.last && (lines.last.md_type == :empty )
442
+ while lines.last && lines.last.strip.size == 0
443
+ lines.pop
444
+ end
446
445
 
447
- while lines.first && lines.first.strip.size == 0
448
- lines.shift
449
- end
446
+ while lines.first && lines.first.strip.size == 0
447
+ lines.shift
448
+ end
450
449
 
451
- return nil if lines.empty?
450
+ return nil if lines.empty?
452
451
 
453
- source = lines.join("\n")
452
+ source = lines.join("\n")
454
453
 
455
454
  # dbg_describe_ary(lines, 'CODE')
456
455
 
457
- return md_codeblock(source)
458
- end
456
+ return md_codeblock(source)
457
+ end
459
458
 
460
- # Reads a series of metadata lines with empty lines in between
461
- def read_metadata(src)
462
- hash = {}
463
- while src.cur_line
464
- case src.cur_line.md_type
465
- when :empty; src.shift_line
466
- when :metadata; hash.merge! parse_metadata(src.shift_line)
467
- else break
468
- end
469
- end
470
- hash
471
- end
459
+ # Reads a series of metadata lines with empty lines in between
460
+ def read_metadata(src)
461
+ hash = {}
462
+ while src.cur_line
463
+ case src.cur_line.md_type
464
+ when :empty; src.shift_line
465
+ when :metadata; hash.merge! parse_metadata(src.shift_line)
466
+ else break
467
+ end
468
+ end
469
+ hash
470
+ end
472
471
 
473
472
 
474
- def read_ref_definition(src, out)
475
- line = src.shift_line
473
+ def read_ref_definition(src, out)
474
+ line = src.shift_line
476
475
 
477
476
 
478
- # if link is incomplete, shift next line
479
- if src.cur_line && !([:footnote_text, :ref_definition, :definition, :abbreviation].include? src.cur_line.md_type) &&
480
- ([1,2,3].include? number_of_leading_spaces(src.cur_line) )
481
- line += " "+ src.shift_line
482
- end
477
+ # if link is incomplete, shift next line
478
+ if src.cur_line && !([:footnote_text, :ref_definition, :definition, :abbreviation].include? src.cur_line.md_type) &&
479
+ ([1,2,3].include? number_of_leading_spaces(src.cur_line) )
480
+ line += " "+ src.shift_line
481
+ end
483
482
 
484
483
  # puts "total= #{line}"
485
484
 
486
- match = LinkRegex.match(line)
487
- if not match
488
- maruku_error "Link does not respect format: '#{line}'"
489
- return
490
- end
485
+ match = LinkRegex.match(line)
486
+ if not match
487
+ maruku_error "Link does not respect format: '#{line}'"
488
+ return
489
+ end
491
490
 
492
- id = match[1]; url = match[2]; title = match[3];
493
- id = sanitize_ref_id(id)
491
+ id = match[1]; url = match[2]; title = match[3];
492
+ id = sanitize_ref_id(id)
494
493
 
495
- hash = self.refs[id] = {:url=>url,:title=>title}
494
+ hash = self.refs[id] = {:url=>url,:title=>title}
496
495
 
497
- stuff=match[4]
496
+ stuff=match[4]
498
497
 
499
- if stuff
500
- stuff.split.each do |couple|
498
+ if stuff
499
+ stuff.split.each do |couple|
501
500
  # puts "found #{couple}"
502
- k, v = couple.split('=')
503
- v ||= ""
504
- if v[0,1]=='"' then v = v[1, v.size-2] end
501
+ k, v = couple.split('=')
502
+ v ||= ""
503
+ if v[0,1]=='"' then v = v[1, v.size-2] end
505
504
  # puts "key:_#{k}_ value=_#{v}_"
506
- hash[k.to_sym] = v
507
- end
508
- end
505
+ hash[k.to_sym] = v
506
+ end
507
+ end
509
508
  # puts hash.inspect
510
509
 
511
- out.push md_ref_def(id, url, meta={:title=>title})
512
- end
510
+ out.push md_ref_def(id, url, meta={:title=>title})
511
+ end
513
512
 
514
- def split_cells(s)
513
+ def split_cells(s)
515
514
  # s.strip.split('|').select{|x|x.strip.size>0}.map{|x|x.strip}
516
515
  # changed to allow empty cells
517
- s.strip.split('|').select{|x|x.size>0}.map{|x|x.strip}
518
- end
519
-
520
- def read_table(src)
521
- head = split_cells(src.shift_line).map{|s| md_el(:head_cell, parse_lines_as_span([s])) }
522
-
523
- separator=split_cells(src.shift_line)
524
-
525
- align = separator.map { |s| s =~ Sep
526
- if $1 and $2 then :center elsif $2 then :right else :left end }
527
-
528
- num_columns = align.size
529
-
530
- if head.size != num_columns
531
- maruku_error "Table head does not have #{num_columns} columns: \n#{head.inspect}"
532
- tell_user "I will ignore this table."
533
- # XXX try to recover
534
- return md_br()
535
- end
536
-
537
- rows = []
538
-
539
- while src.cur_line && src.cur_line =~ /\|/
540
- row = split_cells(src.shift_line).map{|s|
541
- md_el(:cell, parse_lines_as_span([s]))}
542
- if head.size != num_columns
543
- maruku_error "Row does not have #{num_columns} columns: \n#{row.inspect}"
544
- tell_user "I will ignore this table."
545
- # XXX try to recover
546
- return md_br()
547
- end
548
- rows << row
549
- end
550
-
551
- children = (head+rows).flatten
552
- return md_el(:table, children, {:align => align})
553
- end
554
-
555
- # If current line is text, a definition list is coming
556
- # if 1) text,empty,[text,empty]*,definition
557
-
558
- def eventually_comes_a_def_list(src)
559
- future = src.tell_me_the_future
560
- ok = future =~ %r{^t+e?d}x
516
+ s.strip.split('|').select{|x|x.size>0}.map{|x|x.strip}
517
+ end
518
+
519
+ def read_table(src)
520
+ head = split_cells(src.shift_line).map{|s| md_el(:head_cell, parse_lines_as_span([s])) }
521
+
522
+ separator=split_cells(src.shift_line)
523
+
524
+ align = separator.map { |s| s =~ Sep
525
+ if $1 and $2 then :center elsif $2 then :right else :left end }
526
+
527
+ num_columns = align.size
528
+
529
+ if head.size != num_columns
530
+ maruku_error "Table head does not have #{num_columns} columns: \n#{head.inspect}"
531
+ tell_user "I will ignore this table."
532
+ # XXX try to recover
533
+ return md_br()
534
+ end
535
+
536
+ rows = []
537
+
538
+ while src.cur_line && src.cur_line =~ /\|/
539
+ row = split_cells(src.shift_line).map{|s|
540
+ md_el(:cell, parse_lines_as_span([s]))}
541
+ if head.size != num_columns
542
+ maruku_error "Row does not have #{num_columns} columns: \n#{row.inspect}"
543
+ tell_user "I will ignore this table."
544
+ # XXX try to recover
545
+ return md_br()
546
+ end
547
+ rows << row
548
+ end
549
+
550
+ children = (head+rows).flatten
551
+ return md_el(:table, children, {:align => align})
552
+ end
553
+
554
+ # If current line is text, a definition list is coming
555
+ # if 1) text,empty,[text,empty]*,definition
556
+
557
+ def eventually_comes_a_def_list(src)
558
+ future = src.tell_me_the_future
559
+ ok = future =~ %r{^t+e?d}x
561
560
  # puts "future: #{future} - #{ok}"
562
- ok
563
- end
561
+ ok
562
+ end
564
563
 
565
564
 
566
- def read_definition(src)
567
- # Read one or more terms
568
- terms = []
569
- while src.cur_line && src.cur_line.md_type == :text
570
- terms << md_el(:definition_term, parse_lines_as_span([src.shift_line]))
571
- end
565
+ def read_definition(src)
566
+ # Read one or more terms
567
+ terms = []
568
+ while src.cur_line && src.cur_line.md_type == :text
569
+ terms << md_el(:definition_term, parse_lines_as_span([src.shift_line]))
570
+ end
572
571
  # dbg_describe_ary(terms, 'DT')
573
572
 
574
- want_my_paragraph = false
573
+ want_my_paragraph = false
575
574
 
576
- raise "Chunky Bacon!" if not src.cur_line
575
+ raise "Chunky Bacon!" if not src.cur_line
577
576
 
578
- # one optional empty
579
- if src.cur_line.md_type == :empty
580
- want_my_paragraph = true
581
- src.shift_line
582
- end
577
+ # one optional empty
578
+ if src.cur_line.md_type == :empty
579
+ want_my_paragraph = true
580
+ src.shift_line
581
+ end
583
582
 
584
- raise "Chunky Bacon!" if src.cur_line.md_type != :definition
583
+ raise "Chunky Bacon!" if src.cur_line.md_type != :definition
585
584
 
586
- # Read one or more definitions
587
- definitions = []
588
- while src.cur_line && src.cur_line.md_type == :definition
589
- parent_offset = src.cur_index
585
+ # Read one or more definitions
586
+ definitions = []
587
+ while src.cur_line && src.cur_line.md_type == :definition
588
+ parent_offset = src.cur_index
590
589
 
591
- first = src.shift_line
592
- first =~ Definition
593
- first = $1
590
+ first = src.shift_line
591
+ first =~ Definition
592
+ first = $1
594
593
 
595
- # I know, it's ugly!!!
594
+ # I know, it's ugly!!!
596
595
 
597
- lines, w_m_p =
598
- read_indented_content(src,4, [:definition], :definition)
599
- want_my_paragraph ||= w_m_p
596
+ lines, w_m_p =
597
+ read_indented_content(src,4, [:definition], :definition)
598
+ want_my_paragraph ||= w_m_p
600
599
 
601
- lines.unshift first
600
+ lines.unshift first
602
601
 
603
602
  # dbg_describe_ary(lines, 'DD')
604
- src2 = LineSource.new(lines, src, parent_offset)
605
- children = parse_blocks(src2)
606
- definitions << md_el(:definition_data, children)
607
- end
608
-
609
- return md_el(:definition, terms+definitions, {
610
- :terms => terms,
611
- :definitions => definitions,
612
- :want_my_paragraph => want_my_paragraph})
613
- end
603
+ src2 = LineSource.new(lines, src, parent_offset)
604
+ children = parse_blocks(src2)
605
+ definitions << md_el(:definition_data, children)
606
+ end
607
+
608
+ return md_el(:definition, terms+definitions, {
609
+ :terms => terms,
610
+ :definitions => definitions,
611
+ :want_my_paragraph => want_my_paragraph})
612
+ end
614
613
  end # BlockLevelParser
615
614
  end # MaRuKu
616
615
  end