nora_mark 0.2beta6 → 0.2beta7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +86 -2
- data/example/nora-simple-ja.css +19 -0
- data/example/nora-simple.css +6 -15
- data/example/noramark-reference-ja.nora +23 -1
- data/example/noramark-reference-ja_00001.xhtml +39 -23
- data/lib/nora_mark/html/abstract_node_writer.rb +1 -1
- data/lib/nora_mark/html/context.rb +4 -3
- data/lib/nora_mark/html/generator.rb +58 -27
- data/lib/nora_mark/html/pages.rb +50 -37
- data/lib/nora_mark/html/paragraph_writer.rb +3 -3
- data/lib/nora_mark/html/tag_writer.rb +8 -7
- data/lib/nora_mark/node.rb +258 -2
- data/lib/nora_mark/node_builder.rb +18 -0
- data/lib/nora_mark/node_set.rb +24 -0
- data/lib/nora_mark/node_util.rb +38 -0
- data/lib/nora_mark/parser.kpeg +72 -57
- data/lib/nora_mark/parser.kpeg.rb +766 -246
- data/lib/nora_mark/transformer.rb +43 -0
- data/lib/nora_mark/version.rb +1 -1
- data/lib/nora_mark.rb +28 -11
- data/spec/nokogiri_test_helper.rb +9 -9
- data/spec/nora_mark_spec.rb +236 -9
- metadata +7 -2
@@ -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
|
-
|
96
|
+
write_nodeset(node.children)
|
96
97
|
end
|
97
98
|
|
98
|
-
def
|
99
|
-
return if
|
100
|
-
|
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.
|
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
|
data/lib/nora_mark/node.rb
CHANGED
@@ -2,14 +2,15 @@ require 'yaml'
|
|
2
2
|
|
3
3
|
module NoraMark
|
4
4
|
class Node
|
5
|
-
|
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
|
data/lib/nora_mark/parser.kpeg
CHANGED
@@ -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,
|
7
|
-
%% br = ast Breakline()
|
8
|
-
%%
|
9
|
-
%%
|
10
|
-
%%
|
11
|
-
%%
|
12
|
-
%%
|
13
|
-
%%
|
14
|
-
%%
|
15
|
-
%%
|
16
|
-
%%
|
17
|
-
%%
|
18
|
-
%%
|
19
|
-
%%
|
20
|
-
%%
|
21
|
-
%%
|
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
|
-
- =
|
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
|
-
|
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 =
|
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 =
|
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 =
|
76
|
-
PreformattedCommandHeadComplex =
|
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 =
|
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 =
|
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 = -
|
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 =
|
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 =
|
144
|
+
Block =
|
131
145
|
(PreformattedBlock
|
132
146
|
| HeadedSection
|
133
147
|
| LineBlock
|
134
148
|
| ExplicitBlock
|
135
149
|
| ParagraphGroup ):block
|
136
|
-
|
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)
|
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
|
197
|
+
root = BOM? EmptyLine* Pages:pages EofComment? Eof ~root(pages)
|
183
198
|
|
184
199
|
|
185
200
|
|