arti_mark 0.0.1.beta4 → 0.1.beta1
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 +12 -0
- data/README.md +2 -2
- data/Rakefile +10 -0
- data/arti_mark.gemspec +4 -2
- data/lib/arti_mark/block_image_parser.rb +2 -2
- data/lib/arti_mark/{context.rb → html/context.rb} +6 -1
- data/lib/arti_mark/html/generator.rb +159 -0
- data/lib/arti_mark/html/header_writer.rb +32 -0
- data/lib/arti_mark/html/result.rb +27 -0
- data/lib/arti_mark/html/tag_writer.rb +110 -0
- data/lib/arti_mark/html/util.rb +12 -0
- data/lib/arti_mark/html/writer_selector.rb +24 -0
- data/lib/arti_mark/parser.kpeg +97 -0
- data/lib/arti_mark/parser.kpeg.rb +2533 -0
- data/lib/arti_mark/parser.rb +31 -0
- data/lib/arti_mark/version.rb +1 -1
- data/lib/arti_mark.rb +10 -21
- data/spec/arti_mark_spec.rb +108 -218
- metadata +40 -17
- data/lib/arti_mark/result.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62679290ba21c0b408d4fff89c820958fa789ff6
|
4
|
+
data.tar.gz: a16462606130c072726ce1d86bb0e677ce267ed3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33bdc6ff8f9b6bf47352876b60fbac750a6ea4f616c9f85197af9ce9a08d9773ac33ef6450ee4f63b33ac6bb6696eefa03a7f394c6d46243eb9ced1cc8977122
|
7
|
+
data.tar.gz: 946a6ef094042486ab500081851c7d8d19e613ae356d5fe0fc98c67eeb3780fe9dd271543f98f6a0cb2f9655849b6976d195126f02c6c951b9efd79c3c555e1c
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# version 0.1beta1 (pre NoraText)
|
2
|
+
|
3
|
+
* Totally rewrite using kpeg.
|
4
|
+
* degrage : toc feature removed (for the old toc feature is so poor)
|
5
|
+
* degrade : removed custom BlockParser. Instead of the feature, easy and powerful customization will be introduced in NoraText 0.1)
|
6
|
+
* markup change: alternate block notation starting with 'd{---' has removed
|
7
|
+
* markup change: inline image notation is changed form [img(alt-text){src}] to [img(src, alt)]
|
8
|
+
|
9
|
+
* will change the name from ArtiMark to NoraText on next release 0.1rc1
|
10
|
+
|
11
|
+
|
12
|
+
|
data/README.md
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
ArtiMark is a simple text markup language. It is designed to create XHTML files for EPUB books. It is optimized for Japanese text for the present.
|
4
4
|
|
5
|
-
**CAUTION This is very early alpha version, so it's not stable at all
|
5
|
+
**CAUTION This is very early alpha version, so it's not stable at all.**
|
6
6
|
|
7
|
-
|
7
|
+
Reimplemented new version will be released on the end of Feb. 2014. Some syntax will be changed on the new version. The name of the library may change.
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
data/Rakefile
CHANGED
@@ -1,2 +1,12 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
2
|
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
rule(/\.kpeg\.rb/ => proc {|task_name| task_name.sub(/kpeg\.rb$/, 'kpeg')}) do
|
5
|
+
|t|
|
6
|
+
system "kpeg -f #{t.prerequisites[0]}"
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "run rspec"
|
10
|
+
task :test => ["lib/arti_mark/parser.kpeg.rb"] do
|
11
|
+
system 'rspec'
|
12
|
+
end
|
data/arti_mark.gemspec
CHANGED
@@ -15,6 +15,8 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = ArtiMark::VERSION
|
17
17
|
|
18
|
-
gem.
|
19
|
-
gem.
|
18
|
+
gem.required_ruby_version = '>= 2.0.0'
|
19
|
+
gem.add_dependency "kpeg"
|
20
|
+
gem.add_development_dependency "rspec", "~> 2.14"
|
21
|
+
gem.add_development_dependency "nokogiri", "~> 1.6.0"
|
20
22
|
end
|
@@ -19,8 +19,8 @@ module ArtiMark
|
|
19
19
|
|
20
20
|
r << "<div#{ids_string(lexed[:ids])}#{class_string(lexed[:cls])}>"
|
21
21
|
r << "<p>#{caption}</p>" if !caption.nil? && caption.size > 0 && caption_before
|
22
|
-
r << "<img src='#{src}' alt='#{alt}' />"
|
23
|
-
r << "<p>#{caption}</p>" if !caption.nil? && caption.size > 0 && !caption_before
|
22
|
+
r << "<img src='#{src}' alt='#{escape_html alt}' />"
|
23
|
+
r << "<p>#{escape_html caption}</p>" if !caption.nil? && caption.size > 0 && !caption_before
|
24
24
|
r << "</div>\n"
|
25
25
|
end
|
26
26
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module ArtiMark
|
2
|
+
module Html
|
2
3
|
class Context
|
3
4
|
attr_accessor :title, :head_inserters, :toc, :lang, :stylesheets, :enable_pgroup
|
4
5
|
def initialize(param = {})
|
@@ -25,7 +26,10 @@ module ArtiMark
|
|
25
26
|
ret
|
26
27
|
end
|
27
28
|
end
|
28
|
-
|
29
|
+
def chop_last_space
|
30
|
+
@pages.last.sub!(/[[:space:]]+$/, '')
|
31
|
+
end
|
32
|
+
|
29
33
|
def head_inserter(&block)
|
30
34
|
head_inserters << block
|
31
35
|
end
|
@@ -91,3 +95,4 @@ module ArtiMark
|
|
91
95
|
end
|
92
96
|
end
|
93
97
|
end
|
98
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'arti_mark/html/util'
|
3
|
+
require 'arti_mark/html/result'
|
4
|
+
require 'arti_mark/html/context'
|
5
|
+
require 'arti_mark/html/tag_writer'
|
6
|
+
require 'arti_mark/html/header_writer'
|
7
|
+
require 'arti_mark/html/writer_selector'
|
8
|
+
module ArtiMark
|
9
|
+
module Html
|
10
|
+
class Generator
|
11
|
+
include Util
|
12
|
+
attr_reader :context
|
13
|
+
def initialize(param = {})
|
14
|
+
@context = Context.new(param)
|
15
|
+
article_writer = TagWriter.create('article', self)
|
16
|
+
link_writer = TagWriter.create('a', self, trailer: '',
|
17
|
+
item_preprocessor: proc do |item|
|
18
|
+
(item[:attrs] ||= {}).merge!({:href => [ item[:args][0] ]})
|
19
|
+
item
|
20
|
+
end)
|
21
|
+
|
22
|
+
header_writer = HeaderWriter.new self
|
23
|
+
|
24
|
+
@writers = {
|
25
|
+
:paragraph =>
|
26
|
+
TagWriter.create('p', self, chop_last_space: true,
|
27
|
+
item_preprocessor: proc do |item|
|
28
|
+
add_class(item, 'noindent') if item[:children][0] =~/^(「|『|()/ # TODO: should be plaggable}
|
29
|
+
item
|
30
|
+
end
|
31
|
+
),
|
32
|
+
:paragraph_group =>
|
33
|
+
TagWriter.create("div", self,
|
34
|
+
item_preprocessor: proc do |item|
|
35
|
+
add_class item, 'pgroup'
|
36
|
+
item[:no_tag] = true unless @context.enable_pgroup
|
37
|
+
item
|
38
|
+
end
|
39
|
+
),
|
40
|
+
|
41
|
+
:block =>
|
42
|
+
WriterSelector.new(self,
|
43
|
+
{
|
44
|
+
'd' => TagWriter.create('div', self),
|
45
|
+
'art' => article_writer,
|
46
|
+
'article' => article_writer
|
47
|
+
}),
|
48
|
+
:line_command =>
|
49
|
+
WriterSelector.new(self,
|
50
|
+
{
|
51
|
+
'image' =>
|
52
|
+
TagWriter.create('div', self,
|
53
|
+
item_preprocessor: proc do |item|
|
54
|
+
add_class_if_empty item, 'img-wrap'
|
55
|
+
item
|
56
|
+
end,
|
57
|
+
write_body_preprocessor: proc do |item|
|
58
|
+
src = item[:args][0].strip
|
59
|
+
alt = (item[:args][1] || '').strip
|
60
|
+
caption_before = item[:named_args][:caption_before]
|
61
|
+
if caption_before && children_not_empty(item)
|
62
|
+
output "<p>"; write_children item; output "</p>"
|
63
|
+
end
|
64
|
+
output "<img src='#{src}' alt='#{escape_html alt}' />"
|
65
|
+
if !caption_before && children_not_empty(item)
|
66
|
+
output "<p>"; write_children item; output "</p>"
|
67
|
+
end
|
68
|
+
:done
|
69
|
+
end
|
70
|
+
),
|
71
|
+
'newpage' =>
|
72
|
+
TagWriter.create('div', self,
|
73
|
+
item_preprocessor: proc do |item|
|
74
|
+
item[:no_tag] = true
|
75
|
+
item
|
76
|
+
end,
|
77
|
+
write_body_preprocessor: proc do |item|
|
78
|
+
title = nil
|
79
|
+
if item[:args].size > 0 && item[:args][0].size > 0
|
80
|
+
title = escape_html item[:args].first
|
81
|
+
end
|
82
|
+
@context.start_html(title)
|
83
|
+
:done
|
84
|
+
end
|
85
|
+
),
|
86
|
+
|
87
|
+
}),
|
88
|
+
:inline =>
|
89
|
+
WriterSelector.new(self,
|
90
|
+
{
|
91
|
+
'link' => link_writer,
|
92
|
+
'l' => link_writer,
|
93
|
+
's' => TagWriter.create('span', self),
|
94
|
+
'img' =>
|
95
|
+
TagWriter.create('img', self,
|
96
|
+
item_preprocessor: proc do |item|
|
97
|
+
item[:no_body] = true #TODO : it is not just an item's attribute, 'img_inline' has no body. maybe should specify in parser.{rb|kpeg}
|
98
|
+
(item[:attrs] ||= {}).merge!({:src => [item[:args][0] ]})
|
99
|
+
item[:attrs].merge!({:alt => [ escape_html(item[:args][1].strip)]}) if (item[:args].size > 1 && item[:args][1].size > 0)
|
100
|
+
item
|
101
|
+
end) ,
|
102
|
+
'tcy' =>
|
103
|
+
TagWriter.create('span', self,
|
104
|
+
item_preprocessor: proc do |item|
|
105
|
+
add_class item, 'tcy'
|
106
|
+
item
|
107
|
+
end),
|
108
|
+
'ruby' =>
|
109
|
+
TagWriter.create('ruby', self,
|
110
|
+
write_body_preprocessor: proc do |item|
|
111
|
+
write_children item
|
112
|
+
output "<rp>(</rp><rt>#{escape_html item[:args][0].strip}</rt><rp>)</rp>"
|
113
|
+
:done
|
114
|
+
end),
|
115
|
+
|
116
|
+
},
|
117
|
+
trailer_default:''
|
118
|
+
),
|
119
|
+
:ol => TagWriter.create('ol', self),
|
120
|
+
:ul => TagWriter.create('ul', self),
|
121
|
+
:li => TagWriter.create('li', self),
|
122
|
+
:dl => TagWriter.create('dl', self),
|
123
|
+
:dtdd =>
|
124
|
+
TagWriter.create('', self, chop_last_space: true, item_preprocessor: proc do |item| item[:no_tag] = true; item end,
|
125
|
+
write_body_preprocessor: proc do |item|
|
126
|
+
output "<dt>"; write_array item[:args][0]; output "</dt>"
|
127
|
+
output "<dd>"; write_array item[:args][1]; output "</dd>"
|
128
|
+
:done
|
129
|
+
end),
|
130
|
+
# headers
|
131
|
+
:stylesheets => header_writer,
|
132
|
+
:title => header_writer,
|
133
|
+
:lang => header_writer,
|
134
|
+
}
|
135
|
+
end
|
136
|
+
|
137
|
+
def convert(parsed_result)
|
138
|
+
parsed_result.each {
|
139
|
+
|item|
|
140
|
+
to_html(item)
|
141
|
+
}
|
142
|
+
@context.result
|
143
|
+
end
|
144
|
+
def to_html(item)
|
145
|
+
if item.is_a? String
|
146
|
+
@context << escape_html(item)
|
147
|
+
else
|
148
|
+
writer = @writers[item[:type]]
|
149
|
+
if writer.nil?
|
150
|
+
warn "can't find html generator for \"#{item}\""
|
151
|
+
@context << escape_html(item[:raw_text])
|
152
|
+
else
|
153
|
+
writer.write(item)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ArtiMark
|
2
|
+
module Html
|
3
|
+
class HeaderWriter
|
4
|
+
include Util
|
5
|
+
def initialize(generator)
|
6
|
+
@generator = generator
|
7
|
+
@context = generator.context
|
8
|
+
@writers = {
|
9
|
+
:stylesheets => proc do |item|
|
10
|
+
@context.stylesheets.concat( item[:stylesheets].map do
|
11
|
+
|s|
|
12
|
+
if s =~ /^(.+?\.css):\((.+?)\)$/
|
13
|
+
[$1, $2]
|
14
|
+
else
|
15
|
+
s
|
16
|
+
end
|
17
|
+
end)
|
18
|
+
end,
|
19
|
+
:title => proc do |item|
|
20
|
+
@context.title = escape_html item[:title].strip
|
21
|
+
end,
|
22
|
+
:lang => proc do |item|
|
23
|
+
@context.lang = escape_html item[:lang].strip
|
24
|
+
end
|
25
|
+
}
|
26
|
+
end
|
27
|
+
def write(item)
|
28
|
+
@writers[item[:type]].call item
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ArtiMark
|
2
|
+
module Html
|
3
|
+
class Context
|
4
|
+
class Result < Array
|
5
|
+
def initialize
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
def write_as_files(prefix, format='%03d')
|
10
|
+
self.each_with_index {
|
11
|
+
|converted, i|
|
12
|
+
File.open("#{prefix}_#{format%(i+1)}.xhtml", 'w+') {
|
13
|
+
|file|
|
14
|
+
file << converted
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
def write_as_single_file(filename)
|
19
|
+
File.open(filename, 'w+') {
|
20
|
+
|file|
|
21
|
+
file << self[0]
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module ArtiMark
|
2
|
+
module Html
|
3
|
+
class TagWriter
|
4
|
+
include Util
|
5
|
+
attr_accessor :trailer, :item_preprocessors, :write_body_preprocessors
|
6
|
+
|
7
|
+
def self.create(tag_name, generator, item_preprocessor: nil, write_body_preprocessor: nil, trailer: "\n", chop_last_space: false)
|
8
|
+
instance = TagWriter.new(tag_name, generator, chop_last_space: chop_last_space)
|
9
|
+
instance.item_preprocessors << item_preprocessor unless item_preprocessor.nil?
|
10
|
+
instance.write_body_preprocessors << write_body_preprocessor unless write_body_preprocessor.nil?
|
11
|
+
instance.trailer = trailer
|
12
|
+
yield instance if block_given?
|
13
|
+
instance
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(tag_name, generator, **param)
|
17
|
+
@tag_name = tag_name
|
18
|
+
@generator = generator
|
19
|
+
@context = generator.context
|
20
|
+
@trailer = trailer
|
21
|
+
@item_preprocessors = []
|
22
|
+
@write_body_preprocessors = []
|
23
|
+
@param = param
|
24
|
+
end
|
25
|
+
|
26
|
+
def attr_string(attrs)
|
27
|
+
attrs.map do
|
28
|
+
|name, vals|
|
29
|
+
if vals.size == 0
|
30
|
+
''
|
31
|
+
else
|
32
|
+
" #{name}='#{vals.join(' ')}'"
|
33
|
+
end
|
34
|
+
end.join('')
|
35
|
+
end
|
36
|
+
|
37
|
+
def class_string(cls_array)
|
38
|
+
attr_string({'class' => cls_array})
|
39
|
+
end
|
40
|
+
|
41
|
+
def ids_string(ids_array)
|
42
|
+
attr_string({'id' => ids_array})
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_class(item, cls)
|
46
|
+
(item[:classes] ||= []) << cls
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_class_if_empty(item, cls)
|
50
|
+
add_class(item, cls) if item[:classes].nil? || item[:classes].size == 0
|
51
|
+
end
|
52
|
+
|
53
|
+
def tag_start(item)
|
54
|
+
return if item[:no_tag]
|
55
|
+
ids = item[:ids] || []
|
56
|
+
classes = item[:classes] || []
|
57
|
+
attr = item[:attrs] || {}
|
58
|
+
tag_name = @tag_name || item[:name]
|
59
|
+
@context << "<#{tag_name}#{ids_string(ids)}#{class_string(classes)}#{attr_string(attr)}"
|
60
|
+
if item[:no_body]
|
61
|
+
@context << " />"
|
62
|
+
else
|
63
|
+
@context << ">"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def output(string)
|
68
|
+
@context << string
|
69
|
+
end
|
70
|
+
|
71
|
+
def tag_end(item)
|
72
|
+
return if item[:no_tag]
|
73
|
+
tag_name = @tag_name || item[:name]
|
74
|
+
@context << "</#{tag_name}>#{@trailer}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def write(item)
|
78
|
+
@item_preprocessors.each { |x| item = instance_exec item.dup, &x }
|
79
|
+
@context.enable_pgroup, saved_ep = !(item[:args].include?('wo-pgroup') || !@context.enable_pgroup), @context.enable_pgroup
|
80
|
+
tag_start item
|
81
|
+
write_body item if !item[:no_body]
|
82
|
+
tag_end item if !item[:no_body]
|
83
|
+
@context.enable_pgroup = saved_ep
|
84
|
+
end
|
85
|
+
|
86
|
+
def write_body(item)
|
87
|
+
@write_body_preprocessors.each {
|
88
|
+
|x|
|
89
|
+
return if instance_exec(item, &x) == :done
|
90
|
+
}
|
91
|
+
write_children item
|
92
|
+
end
|
93
|
+
|
94
|
+
def write_children(item)
|
95
|
+
write_array(item[:children])
|
96
|
+
end
|
97
|
+
|
98
|
+
def write_array(array)
|
99
|
+
return if array.nil? || array.size == 0
|
100
|
+
array.each { |x| @generator.to_html x }
|
101
|
+
@generator.context.chop_last_space if (@param[:chop_last_space])
|
102
|
+
end
|
103
|
+
|
104
|
+
def children_not_empty(item)
|
105
|
+
!item[:children].nil? && item[:children].size > 0 && item[:children].select { |x| (x.is_a? String) ? x.size >0 : !x.nil? }.size > 0
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ArtiMark
|
2
|
+
module Html
|
3
|
+
class WriterSelector
|
4
|
+
def initialize(generator, tag_writers = {}, trailer_default: "\n" )
|
5
|
+
@generator = generator
|
6
|
+
@common_tag_writer = TagWriter.create(nil, @generator, trailer: trailer_default)
|
7
|
+
@tag_writers = tag_writers
|
8
|
+
if !trailer_default.nil?
|
9
|
+
@tag_writers.each { |k, t|
|
10
|
+
if t.is_a? TagWriter
|
11
|
+
t.trailer = trailer_default
|
12
|
+
end
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def write(item)
|
19
|
+
writer = @tag_writers[item[:name]] || @common_tag_writer
|
20
|
+
writer.write(item)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
%% name = ArtiMark::Parser
|
2
|
+
|
3
|
+
# literals
|
4
|
+
eof = !.
|
5
|
+
space = ' ' | '\t'
|
6
|
+
eof_comment = lh space* "#" (!eof .)*
|
7
|
+
comment = lh space* "#" (!nl .)* nl
|
8
|
+
|
9
|
+
- = ( space | comment )*
|
10
|
+
empty_line = lh - nl
|
11
|
+
nl = /\r?\n/
|
12
|
+
lh = /^/
|
13
|
+
le = nl | /$/
|
14
|
+
word = < /[\w0-9]/ ( '-' | /[\w0-9]/ )* > { text }
|
15
|
+
num = < [0-9]+ > { text.to_i }
|
16
|
+
|
17
|
+
#common syntax
|
18
|
+
classname = '.' word:classname { classname }
|
19
|
+
classnames = (classname)*:classnames { classnames }
|
20
|
+
idname = '#' word:idname { idname }
|
21
|
+
idnames = (idname)*:idnames { idnames }
|
22
|
+
|
23
|
+
commandname = word:name idnames?:idnames classnames?:classes { {:name => name, :ids => idnames, :classes => classes} }
|
24
|
+
parameter = < ( /[^,)]/* | '"' /[^"]/* '"' | "'" /[^']/* "'" ) > { text }
|
25
|
+
parameters = < parameter (',' parameter)* > { text }
|
26
|
+
command = commandname:commandname ('(' - parameters:arg - ')')? { arg ||= ''; commandname.merge({ :args => arg.split(',') }) }
|
27
|
+
|
28
|
+
# paragraph
|
29
|
+
implicit_paragraph = < (!paragraph_delimiter - documentline - ):paragraph > { create_item(:paragraph, nil, paragraph, raw: text) }
|
30
|
+
paragraph = explicit_paragraph | implicit_paragraph
|
31
|
+
|
32
|
+
# paragraph_group
|
33
|
+
paragraph_group = < (paragraph nl | paragraph )+:paragraphs empty_line* > { create_item(:paragraph_group, nil, paragraphs, raw: text) }
|
34
|
+
|
35
|
+
# explicit block
|
36
|
+
blockhead = lh - command:command - '{' - le { command }
|
37
|
+
blockend = lh - '}' - le
|
38
|
+
blockbody = (!blockend block)+:body { body }
|
39
|
+
explicit_block = < blockhead:head blockbody:body blockend > { create_item(:block, head, body, raw: text) }
|
40
|
+
|
41
|
+
# inline command
|
42
|
+
inline = img_inline | common_inline
|
43
|
+
common_inline = < '[' command:command '{' documentcontent_except('}'):content '}' ']' > { create_item(:inline, command, content, raw: text) }
|
44
|
+
|
45
|
+
#img inline
|
46
|
+
img_command = command:command &{ command[:name] == 'img' && command[:args].size == 2}
|
47
|
+
img_inline = < '[' img_command:command ']' > { create_item(:inline, command, nil, raw: text) }
|
48
|
+
|
49
|
+
# special line commands
|
50
|
+
# newpage
|
51
|
+
newpage = line_command:item &{ item[:name] == 'newpage' }
|
52
|
+
# explicit paragraph
|
53
|
+
explicit_paragraph_command = command:command &{ command[:name] == 'p' }
|
54
|
+
explicit_paragraph = < lh - explicit_paragraph_command:command ':' documentcontent?:content le > { create_item(:paragraph, command, content, raw:text) }
|
55
|
+
|
56
|
+
# unordered list
|
57
|
+
unordered_list = < unordered_item+:items > { create_item(:ul, nil, items, raw: text) }
|
58
|
+
unordered_item = < lh '*:' documentcontent:content le > { create_item(:li, nil, content, raw: text) }
|
59
|
+
|
60
|
+
# ordered list
|
61
|
+
ordered_list = < ordered_item+:items > { create_item(:ol, nil, items, raw: text) }
|
62
|
+
ordered_item = < lh num ':' documentcontent:content le > { create_item(:li, nil, content, raw: text) }
|
63
|
+
|
64
|
+
# definition list
|
65
|
+
definition_list = < definition_item+:items > { create_item(:dl, nil, items, raw: text) }
|
66
|
+
definition_item = < lh ';:' - documentcontent_except(':'):term ':' - documentcontent:definition le > { create_item(:dtdd, {:args => [term, definition]}, nil, raw: text) }
|
67
|
+
|
68
|
+
items_list = unordered_list | ordered_list | definition_list
|
69
|
+
|
70
|
+
|
71
|
+
# generic line command
|
72
|
+
line_command = < lh - (!explicit_paragraph_command command):command ':' documentcontent?:content le > { create_item(:line_command, command, content, raw: text) }
|
73
|
+
|
74
|
+
# blocks
|
75
|
+
block = items_list | line_command | explicit_block | paragraph_group | empty_line+
|
76
|
+
block_delimiter = blockhead | blockend | newpage
|
77
|
+
paragraph_delimiter = block | block_delimiter
|
78
|
+
|
79
|
+
# texts
|
80
|
+
char = < /[[:print:]]/ > { text }
|
81
|
+
charstring = < char* > { text }
|
82
|
+
char_except(e) = char:c &{ c != e }
|
83
|
+
charstring_except(e) = < char_except(e)* > { text }
|
84
|
+
documentcontent_except(e) = (inline | !inline char_except(e))+:content ~parse_text(content)
|
85
|
+
documentcontent = (inline | !inline char)+:content ~parse_text(content)
|
86
|
+
documentline = lh documentcontent:content /$/ { content }
|
87
|
+
|
88
|
+
#header
|
89
|
+
stylesheets = < lh - 'stylesheets:' (!le charstring):stylesheets le > { create_item(:stylesheets, {:stylesheets => stylesheets.split(',').map(&:strip)}, nil, raw:text) }
|
90
|
+
title = < lh - 'title:' (!le charstring):title le > { create_item(:title, {:title => title }, nil, raw:text) }
|
91
|
+
lang = < lh - 'lang:' (!le charstring):lang le > { create_item(:lang, {:lang => lang }, nil, raw:text) }
|
92
|
+
header = stylesheets | title | lang
|
93
|
+
|
94
|
+
#root
|
95
|
+
root = header*:headers block*:blocks eof_comment? eof { headers + blocks }
|
96
|
+
|
97
|
+
|