nora_mark 0.2beta7 → 0.2beta8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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