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.
- 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
|
|