nora_mark 0.2beta6 → 0.2beta7

Sign up to get free protection for your applications and to get access to all the features.
@@ -24,9 +24,10 @@ module NoraMark
24
24
  end
25
25
 
26
26
  def attr_string(attrs)
27
+ return '' if attrs.nil?
27
28
  attrs.map do
28
29
  |name, vals|
29
- if vals.size == 0
30
+ if vals.nil? || vals.size == 0
30
31
  ''
31
32
  else
32
33
  " #{name}='#{vals.join(' ')}'"
@@ -76,7 +77,7 @@ module NoraMark
76
77
 
77
78
  def write(node)
78
79
  @node_preprocessors.each { |x| node = instance_exec node.dup, &x }
79
- @context.enable_pgroup, saved_ep = !(node.parameters.include?('wo-pgroup') || !@context.enable_pgroup), @context.enable_pgroup
80
+ @context.enable_pgroup, saved_ep = !((node.parameters || []).include?('wo-pgroup') || !@context.enable_pgroup), @context.enable_pgroup
80
81
  tag_start node
81
82
  write_body node unless node.body_empty
82
83
  tag_end node unless node.body_empty
@@ -92,17 +93,17 @@ module NoraMark
92
93
  end
93
94
 
94
95
  def write_children(node)
95
- write_array(node.content)
96
+ write_nodeset(node.children)
96
97
  end
97
98
 
98
- def write_array(array)
99
- return if array.nil? || array.size == 0
100
- array.each { |x| @generator.to_html x }
99
+ def write_nodeset(nodeset)
100
+ return if nodeset.nil? || nodeset.size == 0
101
+ nodeset.each { |x| @generator.to_html x }
101
102
  @generator.context.chop_last_space if (@param[:chop_last_space])
102
103
  end
103
104
 
104
105
  def children_not_empty(node)
105
- !node.content.nil? && node.content.size > 0 && node.content.reject { |x| x.nil? }.size > 0
106
+ !node.children.nil? && node.children.size > 0 && node.children.reject { |x| x.nil? }.size > 0
106
107
  end
107
108
  end
108
109
  end
@@ -2,14 +2,15 @@ require 'yaml'
2
2
 
3
3
  module NoraMark
4
4
  class Node
5
- attr_accessor :content, :ids, :classes, :no_tag, :attrs, :name, :body_empty
5
+ include Enumerable
6
+ attr_accessor :content, :ids, :classes, :no_tag, :attrs, :name, :body_empty, :line_no
7
+ attr_accessor :parent, :first_child, :last_child, :prev, :next, :holders
6
8
 
7
9
  def named_parameters=(named_parameters)
8
10
  @named_parameters = named_parameters
9
11
  end
10
12
 
11
13
  def named_parameters
12
- @named_parameters = Hash[*(parameters.select { |x| x.include?(':') }.map { |x| v = x.split(':', 2); [v[0].strip.to_sym, v[1]]}.flatten)] if !@parameters.nil?
13
14
  @named_parameters ||= {}
14
15
  end
15
16
 
@@ -20,9 +21,264 @@ module NoraMark
20
21
  def parameters
21
22
  @parameters ||= []
22
23
  end
24
+
25
+ def each
26
+ node = self
27
+ while !node.nil?
28
+ yield node
29
+ node = node.next
30
+ end
31
+ end
32
+
33
+ def match?(selector)
34
+ selector = build_selector(selector)
35
+ selector.inject(true) {
36
+ |result, selector|
37
+ result && selector.call(self)
38
+ }
39
+ end
40
+
41
+ def modify_selector(k,v)
42
+ case k
43
+ when :type
44
+ proc { | node | node.kind_of? NoraMark.const_get(v) }
45
+ when :name
46
+ proc { | node | node.name == v }
47
+ when :id
48
+ proc { | node | (node.ids || []).contain? v }
49
+ when :class
50
+ proc { | node | (node.class || []).contain? v }
51
+ when :proc
52
+ v
53
+ else
54
+ raise 'no selector'
55
+ end
56
+ end
57
+
58
+ def build_selector(selector)
59
+ if selector.is_a? String
60
+ selector = { name: selector }
61
+ end
62
+ selector.map { |k,v| modify_selector(k,v) }
63
+ end
64
+
65
+ def ancestors(selector = {})
66
+ result = []
67
+ node = parent
68
+ while !node.nil?
69
+ result << node if node.match?(selector)
70
+ node = node.parent
71
+ end
72
+ result
73
+ end
74
+
75
+ def reparent
76
+ return if @content.nil?
77
+
78
+ @content.each {|node| node.remove }
79
+
80
+ @first_child = @content.first
81
+ @last_child = @content.last
82
+ @content.inject(nil) do |prev, child_node|
83
+ child_node.prev = prev
84
+ prev.next = child_node if !prev.nil?
85
+ child_node.parent = self
86
+ child_node.reparent
87
+ child_node
88
+ end
89
+ @content = nil
90
+ @children = nil
91
+ end
92
+
93
+ def children
94
+ return [] if @first_child.nil?
95
+ return @children ||= NodeSet.new(@first_child.collect { |node| node })
96
+ end
97
+
98
+ def children=(x)
99
+ @content = x.to_ary
100
+ reparent
101
+ end
102
+
103
+ def children_replaced
104
+ @children = nil
105
+ end
106
+
107
+ def unlink
108
+ @parent = nil
109
+ @prev = nil
110
+ @next = nil
111
+ end
112
+
113
+ def remove
114
+ @parent.first_child = @next if !@parent.nil? && @parent.first_child == self
115
+ @parent.last_child = @prev if !@parent.nil? && @parent.last_child == self
116
+ @next.prev = @prev unless @next.nil?
117
+ @prev.next = @next unless @prev.nil?
118
+ @parent.children_replaced unless @parent.nil?
119
+ unlink
120
+ end
121
+
122
+ def replace(node)
123
+ node.parent = @parent
124
+ @parent.first_child = node if (@parent.first_child == self)
125
+ @parent.last_child = node if (@parent.last_child == self)
126
+
127
+ node.prev = @prev
128
+ node.next = @next
129
+
130
+ @prev.next = node unless @prev.nil?
131
+ @next.prev = node unless @next.nil?
132
+
133
+ node.reparent
134
+ node.parent.children_replaced
135
+
136
+ unlink
137
+ end
138
+
139
+ def prepend_child(node)
140
+ node.remove
141
+ node.reparent
142
+ if self.children.size == 0
143
+ @content = [ node ]
144
+ reparent
145
+ else
146
+ @first_child.prev = node
147
+ node.next = @first_child
148
+ node.parent = self
149
+ @first_child = node
150
+ children_replaced
151
+ end
152
+ end
153
+
154
+ def append_child(node)
155
+ node.remove
156
+ node.reparent
157
+ if self.children.size == 0
158
+ @content = [ node ]
159
+ reparent
160
+ else
161
+ @last_child.next = node
162
+ node.prev = @last_child
163
+ node.parent = self
164
+ @last_child = node
165
+ children_replaced
166
+ end
167
+ end
168
+
169
+ def all_nodes
170
+ return [] if @first_child.nil?
171
+ @first_child.inject([]) do
172
+ |result, node|
173
+ result << node
174
+ result + node.all_nodes
175
+ end
176
+ end
177
+
178
+ def clone
179
+ @content = nil
180
+ all_nodes.each { |node| @content = nil }
181
+ Marshal.restore Marshal.dump self
182
+ end
183
+
184
+ def get_text
185
+ children.inject("") do
186
+ |result, node|
187
+ result << node.get_text
188
+ end
189
+ end
190
+ end
191
+
192
+ class Root < Node
193
+ attr_accessor :document_name
194
+ end
195
+
196
+ class Page < Node
197
+ attr_accessor :page_no
198
+ end
199
+
200
+ class DLItem < Node
201
+ def reparent
202
+ super
203
+ @parameters[0].inject(nil) do
204
+ |prev, child_node|
205
+ child_node.prev = prev
206
+ prev.next = child_node if !prev.nil?
207
+ child_node.parent = self
208
+ child_node.reparent
209
+ child_node
210
+ end
211
+ end
212
+ def get_text
213
+ @parameters[0].inject('') do
214
+ |result, node|
215
+ result << node.get_text
216
+ end << super
217
+ end
23
218
  end
24
219
 
220
+ class Block < Node
221
+ def heading_info
222
+ @name =~ /h([1-6])/
223
+ return {} if $1.nil?
224
+ {level: $1.to_i, id: @ids[0], text: get_text }
225
+ end
226
+ end
227
+
228
+ class HeadedSection < Node
229
+ def heading_info
230
+ {level: @level, id: (named_parameters[:heading_id] || [])[0], text: @heading.map(&:get_text).join('')}
231
+ end
232
+
233
+ def reparent
234
+ super
235
+ @heading.inject(nil) do
236
+ |prev, child_node|
237
+ child_node.prev = prev
238
+ prev.next = child_node if !prev.nil?
239
+ child_node.parent = self
240
+ child_node.reparent
241
+ child_node
242
+ end
243
+ end
244
+
245
+ def get_text
246
+ @heading[0].inject('') do
247
+ |result, node|
248
+ result << node.get_text
249
+ end << super
250
+ end
251
+
252
+ end
253
+ class Text < Node
254
+ def reparent
255
+ # do nothing.
256
+ end
257
+
258
+ def get_text
259
+ @content
260
+ end
261
+ end
262
+
263
+
264
+ class PreformattedBlock < Node
265
+ def reparent
266
+ # do nothing.
267
+ end
268
+ def get_text
269
+ @content.join "\n"
270
+ end
271
+ end
272
+
25
273
  class Frontmatter < Node
274
+ def reparent
275
+ # do nothing.
276
+ end
277
+
278
+ def get_text
279
+ @content.join "\n"
280
+ end
281
+
26
282
  def yaml
27
283
  @yaml ||= YAML.load(@content.join("\n"))
28
284
  @yaml
@@ -0,0 +1,18 @@
1
+ module NoraMark
2
+ class NodeBuilder
3
+ include NodeUtil
4
+ def initialize(original_node, options)
5
+ @node = original_node
6
+ @options = options
7
+ end
8
+
9
+ def modify(&block)
10
+ instance_eval &block
11
+ end
12
+
13
+ def replace(&block)
14
+ new_node = instance_eval &block
15
+ @node.replace new_node
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ module NoraMark
2
+ class NodeSet
3
+ include Enumerable
4
+ def initialize(list = [])
5
+ @list = list
6
+ end
7
+
8
+ def [](n)
9
+ @list[n]
10
+ end
11
+
12
+ def size
13
+ @list.size
14
+ end
15
+
16
+ def each(&block)
17
+ @list.each(&block)
18
+ end
19
+
20
+ def to_ary
21
+ @list.dup
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,38 @@
1
+ module NoraMark
2
+ module NodeUtil
3
+ def _node(klass, name, children = nil, ids: nil, children_: nil, classes: nil, parameters: nil, named_parameters: nil, attrs: nil, template: nil)
4
+ children_arg = children || children_
5
+ if !children_arg.nil?
6
+ children_arg = children_arg.to_ary if children_arg.kind_of? NodeSet
7
+ children_arg = [ children_arg ] if !children_arg.kind_of? Array
8
+ children_arg = children_arg.map { |node| (node.is_a? String) ? Text.new(node, 0) : node }
9
+ end
10
+ if !template.nil?
11
+ node = klass.new(name, template.ids, template.classes, template.parameters, template.named_parameters, template.children, template.line_no)
12
+ node.ids = (node.ids ||[] + ids) if !ids.nil?
13
+ node.classes = (node.classes || []) + classes if !classes.nil?
14
+ node.parameters = parameters if !parameters.nil?
15
+ node.named_parameters = named_parameters if !named_parameters.nil?
16
+ node.content = children_arg if !children_arg.nil?
17
+ else
18
+ node = klass.new(name, ids, classes, parameters, named_parameters, children_arg, 0)
19
+ node.reparent
20
+ end
21
+ node
22
+ end
23
+
24
+ def block(name, children = nil, ids: nil, children_: nil, classes: nil, parameters: nil, named_parameters: nil, attrs: nil, template: nil)
25
+ _node(Block, name, children, ids: ids, children_: children_, classes: classes, parameters: parameters, named_parameters: named_parameters, attrs: attrs, template: template)
26
+ end
27
+
28
+ def text value
29
+ Text.new(value, 0)
30
+ end
31
+
32
+ def inline(name, children = nil, ids: nil, children_: nil, classes: nil, parameters: nil, named_parameters: nil, attrs: nil, template: nil)
33
+ _node(Inline, name, children, ids: ids, children_: children_, classes: classes, parameters: parameters, named_parameters: named_parameters, attrs: attrs, template: template)
34
+ end
35
+
36
+
37
+ end
38
+ end
@@ -1,24 +1,27 @@
1
1
  %% name = NoraMark::Parser
2
2
 
3
3
  %% ast-location = ::NoraMark
4
- %% text = ast Text(content)
5
- %% paragraph = ast Paragraph(ids, classes, parameters, content)
6
- %% paragraph_group = ast ParagraphGroup(ids, classes, parameters, content)
7
- %% br = ast Breakline()
8
- %% line_command = ast LineCommand(name, ids, classes, parameters, content)
9
- %% block = ast Block(name, ids, classes, parameters, content)
10
- %% newpage = ast Newpage(ids, classes, parameters, content)
11
- %% inline = ast Inline(name, ids, classes, parameters, content)
12
- %% ul_item = ast UlItem(ids, classes, parameters, content)
13
- %% unordered_list = ast UnorderedList(ids, classes, parameters, content)
14
- %% ol_item = ast OlItem(ids, classes, parameters, content)
15
- %% ordered_list = ast OrderedList(ids, classes, parameters, content)
16
- %% dl_item = ast DLItem(ids, classes, parameters, content)
17
- %% definition_list = ast DefinitionList(ids, classes, parameters, content)
18
- %% preformatted_block = ast PreformattedBlock(name, ids, classes, parameters, codelanguage, content)
19
- %% frontmatter = ast Frontmatter(content)
20
- %% h_section = ast HeadedSection(level, heading, content)
21
- %% page = ast Page(content)
4
+ %% text = ast Text(content, line_no)
5
+ %% paragraph = ast Paragraph(ids, classes, parameters, named_parameters, content, line_no)
6
+ %% paragraph_group = ast ParagraphGroup(ids, classes, parameters,named_parameters, content, line_no)
7
+ %% br = ast Breakline(line_no)
8
+ %% block = ast Block(name, ids, classes, parameters, named_parameters, content, line_no)
9
+ %% newpage = ast Newpage(ids, classes, parameters, named_parameters, content, line_no)
10
+ %% inline = ast Inline(name, ids, classes, parameters, named_parameters, content, line_no)
11
+ %% ul_item = ast UlItem(ids, classes, parameters, named_parameters, content, line_no)
12
+ %% unordered_list = ast UnorderedList(ids, classes, parameters, named_parameters, content, line_no)
13
+ %% ol_item = ast OlItem(ids, classes, parameters, named_parameters, content, line_no)
14
+ %% ordered_list = ast OrderedList(ids, classes, parameters,named_parameters, content, line_no)
15
+ %% dl_item = ast DLItem(ids, classes, parameters, named_parameters, content, line_no)
16
+ %% definition_list = ast DefinitionList(ids, classes, parameters, named_parameters, content, line_no)
17
+ %% preformatted_block = ast PreformattedBlock(name, ids, classes, parameters, named_parameters, codelanguage, content, line_no)
18
+ %% frontmatter = ast Frontmatter(content, line_no)
19
+ %% h_section = ast HeadedSection(level, heading, content, line_no)
20
+ %% page = ast Page(content, line_no)
21
+ %% root = ast Root(content)
22
+
23
+ # line number
24
+ ln = { current_line }
22
25
 
23
26
  # literals
24
27
  BOM = /\uFEFF/
@@ -26,8 +29,9 @@ Eof = !.
26
29
  Space = ' ' | '\t'
27
30
  EofComment = Space* "#" (!Eof .)*
28
31
  Comment = Space* "#" (!Nl .)* Nl EmptyLine*
29
- - = ( Space )*
32
+ - = Space*
30
33
  EmptyLine = /^/ - (Nl | Comment | EofComment)
34
+
31
35
  Nl = /\r?\n/
32
36
  Le = Nl | Eof
33
37
  Word = < /[\w0-9]/ ( '-' | /[\w0-9]/ )* > { text }
@@ -39,7 +43,7 @@ ClassNames = (ClassName)*:classnames { classnames }
39
43
  IdName = '#' Word:idname { idname }
40
44
  IdNames = (IdName)*:idnames { idnames }
41
45
 
42
- CommandName = Word:name IdNames?:idnames ClassNames?:classes { {name: name, ids: idnames, classes: classes} }
46
+ CommandName = Word:name IdNames?:idnames ClassNames?:classes ln:ln { {name: name, ids: idnames, classes: classes, ln:ln } }
43
47
  ParameterNormal = < /[^,)]/* > { text }
44
48
  ParameterQuoted = '"' < /[^"]/* > '"' - &/[,)]/ { text }
45
49
  ParameterSingleQuoted = "'" < /[^']/* > "'" - &/[,)]/ { text }
@@ -47,103 +51,114 @@ Parameter = (ParameterQuoted
47
51
  | ParameterSingleQuoted
48
52
  | ParameterNormal ):value { value }
49
53
 
54
+ NParameterNormal = < /[^,\]]/* > { text }
55
+ NParameterQuoted = '"' < /[^"]/* > '"' - &/[,\]]/ { text }
56
+ NParameterSingleQuoted = "'" < /[^']/* > "'" - &/[,\]]/ { text }
57
+ NParameter = (NParameterQuoted
58
+ | NParameterSingleQuoted
59
+ | NParameterNormal ):value { value }
60
+
50
61
  Parameters = Parameter:parameter ',' - Parameters:parameters { [ parameter ] + parameters }
51
62
  | Parameter:parameter { [ parameter ] }
52
63
 
53
- Command = CommandName:cn ('(' - Parameters:args - ')')? { args ||= []; cn.merge({ args: args }) }
64
+ NamedParameter = Word:key - ':' - NParameter:parameter { { key.to_sym => parameter } }
65
+ NamedParameters = NamedParameter:parameter - ',' - NamedParameters:parameters { parameter.merge parameters }
66
+ | NamedParameter:parameter { parameter }
67
+
68
+ Command = CommandName:cn ('(' - Parameters:args - ')')? ('[' - NamedParameters:named_args - ']')? { cn.merge({ args: args || [] , named_args: named_args || {}}) }
54
69
 
55
70
  # paragraph
56
- ImplicitParagraph = - !ParagraphDelimiter Comment* DocumentLine:content Comment* EofComment? ~paragraph([],[], [], content)
71
+ ImplicitParagraph = - !ParagraphDelimiter Comment* DocumentLine:content ln:ln Comment* EofComment? ~paragraph([],[], [], [], content, ln)
57
72
 
58
73
  # explicit paragraph
59
74
  ExplicitParagraphCommand = Command:c &{ c[:name] == 'p' }
60
- ExplicitParagraph = - ExplicitParagraphCommand:c ':' - DocumentContent?:content Le EmptyLine* ~paragraph(c[:ids], c[:classes], c[:args], content)
75
+ ExplicitParagraph = - ExplicitParagraphCommand:c ':' - DocumentContent?:content Le EmptyLine* ~paragraph(c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
61
76
 
62
77
  Paragraph = ExplicitParagraph | ImplicitParagraph
63
78
 
64
79
  # paragraph_group
65
- ParagraphGroup = Paragraph+:p EmptyLine* ~paragraph_group([],[],[],p)
80
+ ParagraphGroup = ln:ln Paragraph+:p EmptyLine* ~paragraph_group([],[],[],[],p, ln)
66
81
 
67
82
  # explicit block
68
- BlockHead = - Command:command - '{' - Nl EmptyLine* { command }
83
+ BlockHead = Command:command - '{' - Nl EmptyLine* { command }
69
84
  BlockEnd = - '}' - Le EmptyLine*
70
85
  BlockBody = (!BlockEnd Block)+:body { body }
71
- ExplicitBlock = BlockHead:c - BlockBody:content - BlockEnd ~block(c[:name], c[:ids], c[:classes], c[:args], content)
86
+ ExplicitBlock = - BlockHead:c - BlockBody:content - BlockEnd ~block(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
72
87
 
73
88
  # preformatted block
74
89
  PreformattedCommand = Command:command &{ ['pre', 'code'].include? command[:name] }
75
- PreformattedCommandHeadSimple = - PreformattedCommand:command - '{' - Nl { command }
76
- PreformattedCommandHeadComplex = - PreformattedCommand:command - '{//' Word?:codelanguage - Nl { command.merge({codelanguage: codelanguage}) }
90
+ PreformattedCommandHeadSimple = PreformattedCommand:command - '{' - Nl { command }
91
+ PreformattedCommandHeadComplex = PreformattedCommand:command - '{//' Word?:codelanguage - Nl { command.merge({codelanguage: codelanguage}) }
77
92
  PreformattedCommandHead = PreformattedCommandHeadComplex | PreformattedCommandHeadSimple
78
93
  PreformatEndSimple = - '}' - Le EmptyLine*
79
94
  PreformatEndComplex = - '//}' - Le EmptyLine*
80
95
 
81
- PreformattedBlockSimple = PreformattedCommandHeadSimple:c (!PreformatEndSimple (CharString Nl))+:content PreformatEndSimple
82
- ~preformatted_block(c[:name], c[:ids], c[:classes], c[:args], c[:codelanguage], content)
96
+ PreformattedBlockSimple = - PreformattedCommandHeadSimple:c (!PreformatEndSimple (CharString Nl))+:content PreformatEndSimple
97
+ ~preformatted_block(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], c[:codelanguage], content, c[:ln])
83
98
 
84
- PreformattedBlockComplex = PreformattedCommandHeadComplex:c (!PreformatEndComplex (CharString Nl))+:content PreformatEndComplex
85
- ~preformatted_block(c[:name], c[:ids], c[:classes], c[:args], c[:codelanguage], content)
99
+ PreformattedBlockComplex = - PreformattedCommandHeadComplex:c (!PreformatEndComplex (CharString Nl))+:content PreformatEndComplex
100
+ ~preformatted_block(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], c[:codelanguage], content, c[:ln])
86
101
 
87
102
  PreformattedBlock = PreformattedBlockComplex | PreformattedBlockSimple
88
103
 
89
104
  # inline command
90
105
  Inline = ImgInline | CommonInline
91
- CommonInline = '[' Command:c '{' - DocumentContentExcept('}'):content '}' ']' ~inline(c[:name], c[:ids], c[:classes], c[:args], content)
106
+ CommonInline = '[' Command:c '{' - DocumentContentExcept('}'):content '}' ']' ~inline(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
92
107
  ImgCommand = Command:c &{ c[:name] == 'img' && c[:args].size == 2}
93
- ImgInline = '[' ImgCommand:c ']' ~inline(c[:name], c[:ids], c[:classes], c[:args], nil)
108
+ ImgInline = '[' ImgCommand:c ']' ~inline(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], nil, c[:ln])
94
109
 
95
110
  # special line commands
96
111
  CommandNameForSpecialLineCommand = NewpageCommand | ExplicitParagraphCommand
97
112
 
98
113
  # newpage
99
114
  NewpageCommand = Command:command &{ command[:name] == 'newpage' }
100
- Newpage = - NewpageCommand:c ':' - DocumentContent?:content - Nl ~newpage(c[:ids],c[:classes],c[:args], content)
115
+ Newpage = - NewpageCommand:c ':' - DocumentContent?:content - Nl ~newpage(c[:ids],c[:classes],c[:args], c[:named_args], content, c[:ln])
101
116
 
102
117
 
103
118
  # unordered list
104
- UnorderedList = UnorderedItem+:items ~unordered_list([],[],[], items)
105
- UnorderedItem = '*:' - DocumentContent:content Le ~ul_item([], [], [], content)
119
+ UnorderedList = ln:ln UnorderedItem+:items ~unordered_list([],[],[],[], items, ln)
120
+ UnorderedItem = ln:ln '*:' - DocumentContent:content Le ~ul_item([], [], [], [], content, ln)
106
121
 
107
122
  # ordered list
108
- OrderedList = OrderedItem+:items ~ordered_list([],[],[], items)
109
- OrderedItem = Num ':' - DocumentContent:content Le ~ol_item([], [], [], content)
123
+ OrderedList = ln:ln OrderedItem+:items ~ordered_list([],[],[], [], items, ln)
124
+ OrderedItem = ln:ln Num ':' - DocumentContent:content Le ~ol_item([], [], [], [], content, ln)
110
125
 
111
126
  # definition list
112
- DefinitionList = DefinitionItem+:items ~definition_list([], [], [], items)
113
- DefinitionItem = - ';:' - DocumentContentExcept(':'):term ':' - DocumentContent:definition Le ~dl_item([], [], [term], definition)
127
+ DefinitionList = ln:ln DefinitionItem+:items ~definition_list([], [], [], [], items, ln)
128
+ DefinitionItem = - ln:ln ';:' - DocumentContentExcept(':'):term ':' - DocumentContent:definition Le ~dl_item([], [], [term], [], definition, ln)
114
129
 
115
130
  # long definition list
116
- LongDefinitionList = LongDefinitionItem+:items ~definition_list([], [], [], items)
117
- LongDefinitionItem = - ';:' - DocumentContentExcept('{'):term '{' - Nl - BlockBody:definition - BlockEnd ~dl_item([], [], [term], definition)
131
+ LongDefinitionList = ln:ln LongDefinitionItem+:items ~definition_list([], [], [], [], items, ln)
132
+ LongDefinitionItem = - ln:ln ';:' - DocumentContentExcept('{'):term '{' - Nl - BlockBody:definition - BlockEnd ~dl_item([], [], [term], [], definition, ln)
118
133
 
119
- ItemsList = UnorderedList
134
+ ItemsList = (UnorderedList
120
135
  | OrderedList
121
136
  | DefinitionList
122
- | LongDefinitionList
123
-
137
+ | LongDefinitionList)
124
138
 
125
139
  # generic line command
126
- LineCommand = - !CommandNameForSpecialLineCommand Command:c ':' - DocumentContent?:content - Le EmptyLine* ~line_command(c[:name], c[:ids], c[:classes], c[:args], content)
140
+ LineCommand = - !CommandNameForSpecialLineCommand Command:c ':' - DocumentContent?:content - Le EmptyLine* ~block(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
127
141
 
128
142
  # blocks
129
143
  LineBlock = ItemsList | LineCommand
130
- Block = EmptyLine*
144
+ Block =
131
145
  (PreformattedBlock
132
146
  | HeadedSection
133
147
  | LineBlock
134
148
  | ExplicitBlock
135
149
  | ParagraphGroup ):block
136
- EmptyLine* {block}
150
+ EmptyLine*
151
+ {block}
137
152
 
138
153
  BlockDelimiter = BlockHead | BlockEnd
139
154
  ParagraphDelimiter = BlockDelimiter | PreformattedCommandHead | LineBlock | Newpage | HeadedStart
140
155
 
141
156
  # markdown-style headings
142
157
  HStartMark(n) = < '='+ ':' > &{ text.length - 1 == n }
143
- HMarkupTerminator(n) = - < '='+ ':' > &{ text.length - 1 <= n }
158
+ HMarkupTerminator(n) = - < '='+ ':' > &{ text.length - 1 <= n } | - Eof
144
159
 
145
- HStart(n) = - HStartMark(n) - DocumentContent:s Le { { level: n, heading: s } }
146
- HSection(n) = HStart(n):h (!HMarkupTerminator(n) !Eof Block)*:content ~h_section(h[:level], h[:heading], content)
160
+ HStart(n) = - HStartMark(n) ln:ln - DocumentContent:s Le { { level: n, heading: s, ln: ln} }
161
+ HSection(n) = HStart(n):h EmptyLine* (!HMarkupTerminator(n) Block)*:content EmptyLine* ~h_section(h[:level], h[:heading], content, h[:ln])
147
162
 
148
163
  HeadedStart = HStart(1)
149
164
  | HStart(2)
@@ -161,25 +176,25 @@ HeadedSection = HSection(1)
161
176
 
162
177
  # frontmatter
163
178
  FrontmatterSeparator = - '---' - Nl
164
- Frontmatter = FrontmatterSeparator (!FrontmatterSeparator ( CharString Nl))+:yaml FrontmatterSeparator EmptyLine* ~frontmatter(yaml)
179
+ Frontmatter = FrontmatterSeparator ln:ln (!FrontmatterSeparator ( CharString Nl))+:yaml FrontmatterSeparator EmptyLine* ~frontmatter(yaml, ln)
165
180
 
166
181
  # texts
167
182
  Char = < /[[:print:]]/ > { text }
168
183
  CharString = < Char* > { text }
169
184
  CharExcept(e) = Char:c &{ c != e }
170
- DocumentTextExcept(e) = < (!Inline CharExcept(e))+ > ~text(text)
185
+ DocumentTextExcept(e) = < (!Inline CharExcept(e))+ > ln:ln ~text(text, ln)
171
186
  DocumentContentExcept(e) = (Inline | DocumentTextExcept(e))+:content { content }
172
- DocumentText = < (!Inline Char)+ > ~text(text)
187
+ DocumentText = < (!Inline Char)+ > ln:ln ~text(text, ln)
173
188
  DocumentContent = (Inline | DocumentText)+:content { content }
174
189
  DocumentLine = DocumentContent:content Le { content }
175
190
 
176
191
  #page
177
- Page = Frontmatter?:frontmatter - (!Newpage Block)*:blocks ~page(([frontmatter] + blocks).select{ |x| !x.nil?})
192
+ Page = Frontmatter?:frontmatter - (!Newpage Block)*:blocks EmptyLine* ~page(([frontmatter] + blocks).select{ |x| !x.nil?}, 1)
178
193
  Pages = Page:page Newpage:newpage Pages:pages { [ page, newpage ] + pages }
179
194
  | Page:page { [ page ] }
180
195
 
181
196
  #root
182
- root = BOM? Pages:pages - EofComment? Eof { pages }
197
+ root = BOM? EmptyLine* Pages:pages EofComment? Eof ~root(pages)
183
198
 
184
199
 
185
200