nora_mark 0.2beta7 → 0.2beta8

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.
@@ -2,6 +2,7 @@ module NoraMark
2
2
  class NodeSet
3
3
  include Enumerable
4
4
  def initialize(list = [])
5
+ list = list.to_ary if list.is_a? NodeSet
5
6
  @list = list
6
7
  end
7
8
 
@@ -20,5 +21,17 @@ module NoraMark
20
21
  def to_ary
21
22
  @list.dup
22
23
  end
24
+
25
+ def first
26
+ @list.first
27
+ end
28
+
29
+ def last
30
+ @list.last
31
+ end
32
+
33
+ def text
34
+ @list.inject('') {|r,n| r << n.text }
35
+ end
23
36
  end
24
37
  end
@@ -1,6 +1,6 @@
1
1
  module NoraMark
2
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)
3
+ def _node(klass, name, children_ = nil, ids: [], children: nil, classes: [], params: [], n: {}, attrs: [], template: nil, class_if_empty: nil, line_no: nil, body_empty: nil, raw_text: nil)
4
4
  children_arg = children || children_
5
5
  if !children_arg.nil?
6
6
  children_arg = children_arg.to_ary if children_arg.kind_of? NodeSet
@@ -8,31 +8,44 @@ module NoraMark
8
8
  children_arg = children_arg.map { |node| (node.is_a? String) ? Text.new(node, 0) : node }
9
9
  end
10
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?
11
+ node = klass.new(name, template.ids, template.classes, template.params, template.n, template.children, template.line_no)
12
+ node.ids = (node.ids ||[] + ids) if ids.size > 0
13
+ node.classes = (node.classes || [])
14
+ node.classes = node.classes + classes
15
+ if node.classes.size == 0 && class_if_empty
16
+ node.classes << class_if_empty
17
+ end
18
+ node.params = params if params.size > 0
19
+ node.n = n if n.size > 0
20
+ node.children = children_arg if !children_arg.nil?
21
+ node.attrs = template.attrs || attrs || {}
17
22
  else
18
- node = klass.new(name, ids, classes, parameters, named_parameters, children_arg, 0)
19
- node.reparent
23
+ node = klass.new(name, ids, classes || [], params, n, children_arg, 0)
24
+ node.attrs = attrs || {}
25
+ if node.classes.size == 0 && class_if_empty
26
+ node.classes << class_if_empty
27
+ end
20
28
  end
29
+ node.line_no = line_no
30
+ node.body_empty = body_empty
31
+ node.raw_text = raw_text
32
+ node.reparent
21
33
  node
22
34
  end
23
35
 
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)
36
+ def block(*args)
37
+ _node(Block, *args)
26
38
  end
27
39
 
28
- def text value
29
- Text.new(value, 0)
40
+ def inline(*args)
41
+ _node(Inline, *args)
30
42
  end
31
43
 
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)
44
+ def text value, raw_text: nil
45
+ text = Text.new(value, 0)
46
+ text.raw_text = raw_text
47
+ text
34
48
  end
35
49
 
36
-
37
50
  end
38
51
  end
@@ -1,24 +1,28 @@
1
1
  %% name = NoraMark::Parser
2
-
2
+ %% {
3
+ PARAMETER_END = /[,)]/
4
+ }
3
5
  %% ast-location = ::NoraMark
4
6
  %% 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
+ %% code_inline = ast CodeInline(ids, classes, params, named_params, content, line_no)
8
+ %% paragraph = ast Paragraph(ids, classes, params, named_params, raw_content, line_no)
9
+ %% paragraph_group = ast ParagraphGroup(ids, classes, params,named_params, raw_content, line_no)
7
10
  %% 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)
11
+ %% block = ast Block(name, ids, classes, params, named_params, raw_content, line_no)
12
+ %% newpage = ast Newpage(ids, classes, params, named_params, raw_content, line_no)
13
+ %% inline = ast Inline(name, ids, classes, params, named_params, raw_content, line_no)
14
+ %% ul_item = ast UlItem(ids, classes, params, named_params, raw_content, line_no)
15
+ %% unordered_list = ast UnorderedList(ids, classes, params, named_params, raw_content, line_no)
16
+ %% ol_item = ast OlItem(ids, classes, params, named_params, raw_content, line_no)
17
+ %% ordered_list = ast OrderedList(ids, classes, params,named_params, raw_content, line_no)
18
+ %% dl_item = ast DLItem(ids, classes, params, named_params, raw_content, line_no)
19
+ %% definition_list = ast DefinitionList(ids, classes, params, named_params, raw_content, line_no)
20
+ %% preformatted_block = ast PreformattedBlock(name, ids, classes, params, named_params, codelanguage, content, line_no)
18
21
  %% 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
+ %% h_section = ast HeadedSection(level, heading, params, named_params, raw_content, line_no)
23
+ %% page = ast Page(raw_content, line_no)
24
+ %% root = ast Root(raw_content)
25
+
22
26
 
23
27
  # line number
24
28
  ln = { current_line }
@@ -27,14 +31,14 @@ ln = { current_line }
27
31
  BOM = /\uFEFF/
28
32
  Eof = !.
29
33
  Space = ' ' | '\t'
30
- EofComment = Space* "#" (!Eof .)*
31
- Comment = Space* "#" (!Nl .)* Nl EmptyLine*
32
34
  - = Space*
35
+ EofComment = - "//" (!Eof .)*
36
+ Comment = - "//" (!Nl .)* Nl EmptyLine*
33
37
  EmptyLine = /^/ - (Nl | Comment | EofComment)
34
38
 
35
39
  Nl = /\r?\n/
36
40
  Le = Nl | Eof
37
- Word = < /[\w0-9]/ ( '-' | /[\w0-9]/ )* > { text }
41
+ Word = < /[\w]/ ( '-' | /[\w]/ )* > { text }
38
42
  Num = < [0-9]+ > { text.to_i }
39
43
 
40
44
  #common syntax
@@ -43,10 +47,11 @@ ClassNames = (ClassName)*:classnames { classnames }
43
47
  IdName = '#' Word:idname { idname }
44
48
  IdNames = (IdName)*:idnames { idnames }
45
49
 
46
- CommandName = Word:name IdNames?:idnames ClassNames?:classes ln:ln { {name: name, ids: idnames, classes: classes, ln:ln } }
47
- ParameterNormal = < /[^,)]/* > { text }
48
- ParameterQuoted = '"' < /[^"]/* > '"' - &/[,)]/ { text }
49
- ParameterSingleQuoted = "'" < /[^']/* > "'" - &/[,)]/ { text }
50
+ CommandName = Word:name IdNames?:idnames ClassNames?:classes ln:ln
51
+ { {name: name, ids: idnames, classes: classes, ln:ln } }
52
+ ParameterNormal = DocumentContentExcept(PARAMETER_END):content { content }
53
+ ParameterQuoted = '"' DocumentContentExcept('"'):content '"' - &/[,)]/ { content }
54
+ ParameterSingleQuoted = "'" DocumentContentExcept("'"):content "'" - &/[,)]/ { content }
50
55
  Parameter = (ParameterQuoted
51
56
  | ParameterSingleQuoted
52
57
  | ParameterNormal ):value { value }
@@ -65,79 +70,163 @@ NamedParameter = Word:key - ':' - NParameter:parameter { { key.to_sym => paramet
65
70
  NamedParameters = NamedParameter:parameter - ',' - NamedParameters:parameters { parameter.merge parameters }
66
71
  | NamedParameter:parameter { parameter }
67
72
 
68
- Command = CommandName:cn ('(' - Parameters:args - ')')? ('[' - NamedParameters:named_args - ']')? { cn.merge({ args: args || [] , named_args: named_args || {}}) }
73
+ Command = CommandName:cn
74
+ ('(' - Parameters:args - ')')?
75
+ ('[' - NamedParameters:named_args - ']')?
76
+ { cn.merge({ args: args || [] , named_args: named_args || {}}) }
69
77
 
70
78
  # paragraph
71
- ImplicitParagraph = - !ParagraphDelimiter Comment* DocumentLine:content ln:ln Comment* EofComment? ~paragraph([],[], [], [], content, ln)
79
+ ImplicitParagraph = - !ParagraphDelimiter
80
+ Comment*
81
+ DocumentLine:content ln:ln
82
+ Comment* EofComment?
83
+ ~paragraph([],[], [], {}, content, ln)
72
84
 
73
85
  # explicit paragraph
74
86
  ExplicitParagraphCommand = Command:c &{ c[:name] == 'p' }
75
- ExplicitParagraph = - ExplicitParagraphCommand:c ':' - DocumentContent?:content Le EmptyLine* ~paragraph(c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
87
+ ExplicitParagraph = - ExplicitParagraphCommand:c ':' -
88
+ DocumentContent?:content Le EmptyLine*
89
+ ~paragraph(c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
76
90
 
77
91
  Paragraph = ExplicitParagraph | ImplicitParagraph
78
92
 
79
93
  # paragraph_group
80
- ParagraphGroup = ln:ln Paragraph+:p EmptyLine* ~paragraph_group([],[],[],[],p, ln)
94
+ ParagraphGroup = ln:ln
95
+ Paragraph+:p
96
+ EmptyLine*
97
+ ~paragraph_group([],[],[],{},p, ln)
81
98
 
82
99
  # explicit block
83
100
  BlockHead = Command:command - '{' - Nl EmptyLine* { command }
84
101
  BlockEnd = - '}' - Le EmptyLine*
85
102
  BlockBody = (!BlockEnd Block)+:body { body }
86
- ExplicitBlock = - BlockHead:c - BlockBody:content - BlockEnd ~block(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
103
+ ExplicitBlock = - BlockHead:c -
104
+ BlockBody:content -
105
+ BlockEnd
106
+ ~block(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
87
107
 
88
108
  # preformatted block
89
109
  PreformattedCommand = Command:command &{ ['pre', 'code'].include? command[:name] }
90
- PreformattedCommandHeadSimple = PreformattedCommand:command - '{' - Nl { command }
91
- PreformattedCommandHeadComplex = PreformattedCommand:command - '{//' Word?:codelanguage - Nl { command.merge({codelanguage: codelanguage}) }
92
- PreformattedCommandHead = PreformattedCommandHeadComplex | PreformattedCommandHeadSimple
110
+ PreformattedCommandHeadSimple =
111
+ PreformattedCommand:command -
112
+ '{' - Nl
113
+ { command }
114
+ PreformattedCommandHeadComplex =
115
+ PreformattedCommand:command -
116
+ '{//' Word?:codelanguage - Nl
117
+ { command.merge({codelanguage: codelanguage}) }
118
+ PreformattedFence = - "```" Word?:codelanguage
119
+ ('(' - Parameters:args - ')')?
120
+ ('[' - NamedParameters:named_args - ']')? - Nl
121
+ { {codelanguage: codelanguage,
122
+ args: args || [],
123
+ named_args: named_args || {} } }
124
+
125
+ PreformattedCommandHead = PreformattedCommandHeadComplex |
126
+ PreformattedCommandHeadSimple |
127
+ PreformattedFence
93
128
  PreformatEndSimple = - '}' - Le EmptyLine*
94
129
  PreformatEndComplex = - '//}' - Le EmptyLine*
95
130
 
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])
131
+ PreformattedBlockSimple = - PreformattedCommandHeadSimple:c
132
+ (!PreformatEndSimple (CharString Nl))+:content
133
+ PreformatEndSimple
134
+ ~preformatted_block(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], c[:codelanguage], content, c[:ln])
98
135
 
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])
136
+ PreformattedBlockComplex = - PreformattedCommandHeadComplex:c
137
+ (!PreformatEndComplex (CharString Nl))+:content
138
+ PreformatEndComplex
139
+ ~preformatted_block(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], c[:codelanguage], content, c[:ln])
101
140
 
102
- PreformattedBlock = PreformattedBlockComplex | PreformattedBlockSimple
141
+ PreformattedBlockFence = - ln:ln PreformattedFence:c
142
+ (!"```" CharString Nl)+:content
143
+ - "```" - Le EmptyLine*
144
+ ~preformatted_block('code', [], [], c[:args], c[:named_args], c[:codelanguage], content, ln)
145
+
146
+ PreformattedBlock = PreformattedBlockComplex |
147
+ PreformattedBlockSimple |
148
+ PreformattedBlockFence
103
149
 
104
150
  # inline command
105
- Inline = ImgInline | CommonInline
106
- CommonInline = '[' Command:c '{' - DocumentContentExcept('}'):content '}' ']' ~inline(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
151
+ Inline = EscapedChar | ImgInline | MediaInline | CodeInline | CommonInline | FenceInline
152
+ CommonInline = '[' Command:c
153
+ '{' - DocumentContentExcept('}'):content '}'
154
+ ']'
155
+ ~inline(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
156
+
107
157
  ImgCommand = Command:c &{ c[:name] == 'img' && c[:args].size == 2}
108
- ImgInline = '[' ImgCommand:c ']' ~inline(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], nil, c[:ln])
158
+ ImgInline = '[' ImgCommand:c ']'
159
+ ~inline(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], nil, c[:ln])
160
+
161
+ MediaCommand
162
+ = Command:c &{ (c[:name] == 'video' || c[:name] == 'audio') && c[:args].size > 0}
163
+ MediaInline
164
+ = '[' MediaCommand:c
165
+ ('{' - DocumentContentExcept('}'):content '}')?
166
+ ']'
167
+ ~inline(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
168
+
169
+ FenceInline = '`' ln:ln CharStringExcept('`'):content '`' ~code_inline([], [], [], {}, content, ln)
170
+ CodeCommand = Command:c &{ c[:name] == 'code' }
171
+ CodeInline = '[' CodeCommand:c
172
+ '{' - CharStringExcept('}'):content '}'
173
+ ']'
174
+ ~code_inline(c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
175
+
176
+
177
+ EscapedChar = "\\" < /[`]/ > ln:ln ~text(text, ln)
178
+
109
179
 
110
180
  # special line commands
111
181
  CommandNameForSpecialLineCommand = NewpageCommand | ExplicitParagraphCommand
112
182
 
113
183
  # newpage
114
184
  NewpageCommand = Command:command &{ command[:name] == 'newpage' }
115
- Newpage = - NewpageCommand:c ':' - DocumentContent?:content - Nl ~newpage(c[:ids],c[:classes],c[:args], c[:named_args], content, c[:ln])
185
+ Newpage = - NewpageCommand:c ':' -
186
+ DocumentContent?:content - Nl
187
+ ~newpage(c[:ids],c[:classes],c[:args], c[:named_args], content, c[:ln])
116
188
 
117
189
 
118
190
  # unordered list
119
- UnorderedList = ln:ln UnorderedItem+:items ~unordered_list([],[],[],[], items, ln)
120
- UnorderedItem = ln:ln '*:' - DocumentContent:content Le ~ul_item([], [], [], [], content, ln)
121
-
191
+ UnorderedStart(n) = /^/ - < (/\*+/) > &{ text.length == n && text.size < 5 }
192
+ UnorderedList(n) = ln:ln UnorderedItem(n)+:items ~unordered_list([],[],[],{}, items, ln)
193
+ UnorderedItem(n) = UnorderedStart(n) ln:ln -
194
+ UnorderedItemBody(n):content
195
+ ~ul_item([], [], [], {}, content, ln)
196
+
197
+ UnorderedItemBody(n) = DocumentContent:content Nl
198
+ - &UnorderedStart(n + 1) ln:ln UnorderedList(n + 1):sub_ul
199
+ { content << sub_ul }
200
+ | DocumentContent:content Le { content }
122
201
  # ordered list
123
- OrderedList = ln:ln OrderedItem+:items ~ordered_list([],[],[], [], items, ln)
124
- OrderedItem = ln:ln Num ':' - DocumentContent:content Le ~ol_item([], [], [], [], content, ln)
202
+ OrderedList = ln:ln OrderedItem+:items ~ordered_list([],[],[], {}, items, ln)
203
+ OrderedItem = - ln:ln Num '.' - DocumentContent:content Le ~ol_item([], [], [], {}, content, ln)
125
204
 
126
205
  # definition list
127
- DefinitionList = ln:ln DefinitionItem+:items ~definition_list([], [], [], [], items, ln)
128
- DefinitionItem = - ln:ln ';:' - DocumentContentExcept(':'):term ':' - DocumentContent:definition Le ~dl_item([], [], [term], [], definition, ln)
206
+ DefinitionList = ln:ln DefinitionItem+:items ~definition_list([], [], [], {}, items, ln)
207
+ DefinitionItem = - ln:ln - ';:' -
208
+ DocumentContentExcept(':'):term ':' -
209
+ DocumentContent:definition Le
210
+ ~dl_item([], [], [term], {}, definition, ln)
129
211
 
130
212
  # long definition list
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)
133
-
134
- ItemsList = (UnorderedList
213
+ LongDefinitionList = ln:ln LongDefinitionItem+:items
214
+ ~definition_list([], [], [], {}, items, ln)
215
+ LongDefinitionItem = - ln:ln ';:' -
216
+ DocumentContentExcept('{'):term '{' - Nl
217
+ - BlockBody:definition -
218
+ BlockEnd
219
+ ~dl_item([], [], [term], {}, definition, ln)
220
+
221
+ ItemsList = (UnorderedList(1)
135
222
  | OrderedList
136
223
  | DefinitionList
137
224
  | LongDefinitionList)
138
225
 
139
226
  # generic line command
140
- LineCommand = - !CommandNameForSpecialLineCommand Command:c ':' - DocumentContent?:content - Le EmptyLine* ~block(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
227
+ LineCommand = - !CommandNameForSpecialLineCommand Command:c ':' -
228
+ DocumentContent?:content - Le EmptyLine*
229
+ ~block(c[:name], c[:ids], c[:classes], c[:args], c[:named_args], content, c[:ln])
141
230
 
142
231
  # blocks
143
232
  LineBlock = ItemsList | LineCommand
@@ -151,37 +240,80 @@ Block =
151
240
  {block}
152
241
 
153
242
  BlockDelimiter = BlockHead | BlockEnd
154
- ParagraphDelimiter = BlockDelimiter | PreformattedCommandHead | LineBlock | Newpage | HeadedStart
243
+ ParagraphDelimiter = BlockDelimiter |
244
+ PreformattedCommandHead |
245
+ LineBlock |
246
+ Newpage |
247
+ HeadedStart
155
248
 
156
249
  # markdown-style headings
157
- HStartMark(n) = < '='+ ':' > &{ text.length - 1 == n }
158
- HMarkupTerminator(n) = - < '='+ ':' > &{ text.length - 1 <= n } | - Eof
159
-
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])
162
-
163
- HeadedStart = HStart(1)
164
- | HStart(2)
165
- | HStart(3)
166
- | HStart(4)
250
+ HStartMark(n) = - < '#'+ > &{ text.length == n }
251
+ HMarkupTerminator(n) = - < '#'+ > - CharString:cs Le
252
+ &{ text.length <= n && !cs.strip.end_with?('{') } |
253
+ - Eof
254
+ HStartCommand(n)
255
+ = - HStartMark(n)
256
+ ('(' - Parameters:args - ')')?
257
+ ('[' - NamedParameters:named_args - ']')?
258
+ { { args: args || [] , named_args: named_args || {}} }
259
+
260
+ HStart(n) =
261
+ - HStartCommand(n):hsc
262
+ ln:ln - DocumentContent:s Le { hsc.merge({ level: n, heading: s, ln: ln}) }
263
+
264
+ HSection(n) = HStart(n):h
265
+ EmptyLine*
266
+ (!HMarkupTerminator(n) Block)*:content
267
+ EmptyLine*
268
+ ~h_section(h[:level], h[:heading], h[:args], h[:named_args], content, h[:ln])
269
+
270
+ BlockHStart(n) = - HStartCommand(n):hsc ln:ln -
271
+ DocumentContentExcept('{'):s - '{' - Nl
272
+ { hsc.merge({ level: n, heading: s, ln: ln}) }
273
+ ExplicitHSection(n) = BlockHStart(n):h
274
+ EmptyLine* -
275
+ BlockBody:content -
276
+ BlockEnd
277
+ ~h_section(h[:level], h[:heading], h[:args], h[:named_args], content, h[:ln])
278
+
279
+ HeadedStart = HStart(6)
167
280
  | HStart(5)
168
- | HStart(6)
169
-
170
- HeadedSection = HSection(1)
171
- | HSection(2)
172
- | HSection(3)
173
- | HSection(4)
174
- | HSection(5)
281
+ | HStart(4)
282
+ | HStart(3)
283
+ | HStart(2)
284
+ | HStart(1)
285
+ | BlockHStart(6)
286
+ | BlockHStart(5)
287
+ | BlockHStart(4)
288
+ | BlockHStart(3)
289
+ | BlockHStart(2)
290
+ | BlockHStart(1)
291
+
292
+ HeadedSection = ExplicitHSection(6)
293
+ | ExplicitHSection(5)
294
+ | ExplicitHSection(4)
295
+ | ExplicitHSection(3)
296
+ | ExplicitHSection(2)
297
+ | ExplicitHSection(1)
175
298
  | HSection(6)
299
+ | HSection(5)
300
+ | HSection(4)
301
+ | HSection(3)
302
+ | HSection(2)
303
+ | HSection(1)
176
304
 
177
305
  # frontmatter
178
306
  FrontmatterSeparator = - '---' - Nl
179
- Frontmatter = FrontmatterSeparator ln:ln (!FrontmatterSeparator ( CharString Nl))+:yaml FrontmatterSeparator EmptyLine* ~frontmatter(yaml, ln)
307
+ Frontmatter = FrontmatterSeparator ln:ln
308
+ (!FrontmatterSeparator ( CharString Nl))+:yaml
309
+ FrontmatterSeparator EmptyLine*
310
+ ~frontmatter(yaml, ln)
180
311
 
181
312
  # texts
182
313
  Char = < /[[:print:]]/ > { text }
183
314
  CharString = < Char* > { text }
184
- CharExcept(e) = Char:c &{ c != e }
315
+ CharExcept(e) = Char:c &{ e.is_a?(Regexp) ? e !~ c : e != c }
316
+ CharStringExcept(e) = < CharExcept(e)+ > { text }
185
317
  DocumentTextExcept(e) = < (!Inline CharExcept(e))+ > ln:ln ~text(text, ln)
186
318
  DocumentContentExcept(e) = (Inline | DocumentTextExcept(e))+:content { content }
187
319
  DocumentText = < (!Inline Char)+ > ln:ln ~text(text, ln)
@@ -189,8 +321,12 @@ DocumentContent = (Inline | DocumentText)+:content { content }
189
321
  DocumentLine = DocumentContent:content Le { content }
190
322
 
191
323
  #page
192
- Page = Frontmatter?:frontmatter - (!Newpage Block)*:blocks EmptyLine* ~page(([frontmatter] + blocks).select{ |x| !x.nil?}, 1)
193
- Pages = Page:page Newpage:newpage Pages:pages { [ page, newpage ] + pages }
324
+ Page = Frontmatter?:frontmatter -
325
+ (!Newpage Block)*:blocks
326
+ EmptyLine*
327
+ ~page(([frontmatter] + blocks).select{ |x| !x.nil?}, 1)
328
+
329
+ Pages = Page:page Newpage:newpage Pages:pages { pages.unshift(page) }
194
330
  | Page:page { [ page ] }
195
331
 
196
332
  #root