nora_mark 0.2beta6 → 0.2beta7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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