pukiwiki2md 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +9 -0
- data/.travis.yml +7 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +21 -0
- data/README.md +26 -0
- data/Rakefile +15 -0
- data/bin/console +6 -0
- data/bin/setup +7 -0
- data/lib/pukiwiki2md.rb +9 -0
- data/lib/pukiwiki2md/parser.rb +8 -0
- data/lib/pukiwiki2md/rules/block.rb +213 -0
- data/lib/pukiwiki2md/rules/inline.rb +160 -0
- data/lib/pukiwiki2md/rules/primitive.rb +25 -0
- data/lib/pukiwiki2md/transform.rb +179 -0
- data/lib/pukiwiki2md/version.rb +3 -0
- data/pukiwiki2md.gemspec +30 -0
- metadata +146 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6d68fd20bf5c92ec87a72c89d63831eefac2aa974280ca8ef3050c01f378e817
|
4
|
+
data.tar.gz: 710a068e8f14ac3786f8991edcfc6d16acd2a1bce40ac1c24cf7fd41c94a52c9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 834efe10b229cf5792e7d13f35e6c5e6560eb66ada3942204d80a8f66b919b7bad480361772c3b7cfb36aae13f6b6cd359013d9c8a57d5e85aee5b53d6101c60
|
7
|
+
data.tar.gz: 443881723b7ff3c96c4982185a7041fc69fb6403b7d0fafdf806d5c6241f3c990e451aa7847f4ff049c96c394ffe0560fce283fa2dd4cad183e50bfe1696e33d
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 sunaot
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# Pukiwiki2md
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/sunaot/pukiwiki2md.svg?branch=master)](https://travis-ci.org/sunaot/pukiwiki2md)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/github/sunaot/pukiwiki2md/badge.svg?branch=master)](https://coveralls.io/github/sunaot/pukiwiki2md?branch=master)
|
5
|
+
|
6
|
+
Pukiwiki2md is a PEG (Parsing Expression Grammar) implementation of PukiWiki parser and transforms PukiWiki notation to Markdown notation. You can use it as a converter with a little code as follows:
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
|
10
|
+
```
|
11
|
+
parser = Pukiwiki2md::Parser.new
|
12
|
+
transform = Pukiwiki2md::Transform.new
|
13
|
+
tree = parser.parse(wiki_text)
|
14
|
+
markdown_text = transform.apply(tree)
|
15
|
+
```
|
16
|
+
|
17
|
+
|
18
|
+
## Contributing
|
19
|
+
|
20
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/sunaot/pukiwiki2md.
|
21
|
+
|
22
|
+
|
23
|
+
## License
|
24
|
+
|
25
|
+
`pukiwiki2md` gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
26
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'coveralls/rake/task'
|
5
|
+
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
7
|
+
t.libs << "test"
|
8
|
+
t.test_files = FileList['test/**/*_test.rb']
|
9
|
+
t.options = '-p'
|
10
|
+
end
|
11
|
+
Coveralls::RakeTask.new
|
12
|
+
CLOBBER.include('coverage')
|
13
|
+
|
14
|
+
task :test_with_coveralls => [:test, 'coveralls:push']
|
15
|
+
task :default => :test
|
data/bin/console
ADDED
data/bin/setup
ADDED
data/lib/pukiwiki2md.rb
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
module Pukiwiki2md
|
2
|
+
BlockElementRules = proc {
|
3
|
+
class << self
|
4
|
+
def markup(char, name)
|
5
|
+
rule(name.to_sym) {
|
6
|
+
str(char)
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
def keyword(tag, name)
|
11
|
+
rule(name.to_sym) {
|
12
|
+
str(tag.to_s).as(name.to_sym) >> eol
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
rule(:expression) {
|
18
|
+
page_text >> space?
|
19
|
+
}
|
20
|
+
|
21
|
+
rule(:page_text) {
|
22
|
+
page_components.repeat.as(:page_components)
|
23
|
+
}
|
24
|
+
|
25
|
+
rule(:page_components) {
|
26
|
+
block_separator |
|
27
|
+
contents
|
28
|
+
}
|
29
|
+
|
30
|
+
rule(:contents) {
|
31
|
+
header |
|
32
|
+
quote |
|
33
|
+
horizontal_line | # must be prior to list (ul)
|
34
|
+
list |
|
35
|
+
preformatted |
|
36
|
+
block_margin |
|
37
|
+
separator_line |
|
38
|
+
child_pages |
|
39
|
+
table |
|
40
|
+
block_attachment |
|
41
|
+
clear |
|
42
|
+
toc |
|
43
|
+
paragraph
|
44
|
+
}
|
45
|
+
|
46
|
+
rule(:paragraph) {
|
47
|
+
(match('[ *>\-\+]').absent? >> inline_text.as(:line) >> eol).repeat(1).as(:paragraph_lines)
|
48
|
+
}
|
49
|
+
|
50
|
+
rule(:quote) {
|
51
|
+
(gt >> space? >> inline_text.maybe.as(:line) >> eol).repeat(1).as(:quote_lines)
|
52
|
+
}
|
53
|
+
|
54
|
+
rule(:list) {
|
55
|
+
(unordered_list | ordered_list | definition_list)
|
56
|
+
}
|
57
|
+
|
58
|
+
rule(:unordered_list) {
|
59
|
+
ulist_item.repeat(1).as(:unordered_list)
|
60
|
+
}
|
61
|
+
|
62
|
+
rule(:ulist_item) {
|
63
|
+
minus.repeat(1,3).as(:minus) >> space? >> inline_text.maybe.as(:item) >> eol
|
64
|
+
}
|
65
|
+
|
66
|
+
rule(:ordered_list) {
|
67
|
+
olist_item.repeat(1).as(:ordered_list)
|
68
|
+
}
|
69
|
+
|
70
|
+
rule(:olist_item) {
|
71
|
+
plus.repeat(1,3).as(:plus) >> space? >> inline_text.maybe.as(:item) >> eol
|
72
|
+
}
|
73
|
+
|
74
|
+
rule(:definition_list) {
|
75
|
+
dlist_item.repeat(1).as(:definition_list)
|
76
|
+
}
|
77
|
+
|
78
|
+
rule(:dlist_item) {
|
79
|
+
dlist_term >> dlist_description >> eol
|
80
|
+
}
|
81
|
+
|
82
|
+
rule(:dlist_term) {
|
83
|
+
colon.repeat(1,3).as(:colon) >> space? >> dlist_term_text.maybe.as(:term)
|
84
|
+
}
|
85
|
+
|
86
|
+
rule(:dlist_term_text) {
|
87
|
+
(vertical_bar.absent? >> any).repeat(1)
|
88
|
+
}
|
89
|
+
|
90
|
+
rule(:dlist_description) {
|
91
|
+
vertical_bar >> space? >> string.maybe.as(:description)
|
92
|
+
}
|
93
|
+
|
94
|
+
rule(:preformatted) {
|
95
|
+
(monospace >> string.maybe.as(:line) >> eol).repeat(1).as(:preformatted_lines)
|
96
|
+
}
|
97
|
+
|
98
|
+
rule(:header) {
|
99
|
+
star.repeat(1,6).as(:star) >> space? >> inline_text_with_fragment.maybe.as(:header) >> eol
|
100
|
+
}
|
101
|
+
|
102
|
+
# Ignore `LEFT:`, `CENTER:`, `RIGHT:`
|
103
|
+
|
104
|
+
# PukiWiki spec:
|
105
|
+
# - `----abc` is available (no space needed).
|
106
|
+
# - PukiWiki regards `---` as an unordered list.
|
107
|
+
rule(:horizontal_line) {
|
108
|
+
(str('----') >> string.repeat.maybe).as(:horizontal_line) >> eol
|
109
|
+
}
|
110
|
+
|
111
|
+
rule(:block_attachment) {
|
112
|
+
str('#ref(').as(:l) >> block_attachment_path >> str(')').as(:r) >> eol
|
113
|
+
}
|
114
|
+
|
115
|
+
rule(:block_attachment_path) {
|
116
|
+
space? >> (
|
117
|
+
block_attachment_image_url.as(:block_image_url) |
|
118
|
+
block_attachment_file_url.as(:block_file_url) |
|
119
|
+
block_attachment_image.as(:block_image) |
|
120
|
+
block_attachment_file.as(:block_file)
|
121
|
+
) >> space?
|
122
|
+
}
|
123
|
+
|
124
|
+
rule(:block_attachment_file_url) {
|
125
|
+
scheme >> str('://') >> block_attachment_file
|
126
|
+
}
|
127
|
+
|
128
|
+
rule(:block_attachment_image_url) {
|
129
|
+
scheme >> str('://') >> block_attachment_image
|
130
|
+
}
|
131
|
+
|
132
|
+
rule(:block_attachment_file) {
|
133
|
+
(str(')').absent? >> any).repeat(1)
|
134
|
+
}
|
135
|
+
|
136
|
+
rule(:block_attachment_image) {
|
137
|
+
block_attachment_image_base >> image_extension
|
138
|
+
}
|
139
|
+
|
140
|
+
rule(:block_attachment_image_base) {
|
141
|
+
((rparen|image_extension).absent? >> any).repeat(1)
|
142
|
+
}
|
143
|
+
|
144
|
+
rule(:image_extension) { dot >> (jpg|gif|png) }
|
145
|
+
|
146
|
+
rule(:jpg) { str('jpg') | str('jpeg') | str('JPG') | str('JPEG') }
|
147
|
+
|
148
|
+
rule(:gif) { str('gif') | str('GIF') }
|
149
|
+
|
150
|
+
rule(:png) { str('png') | str('PNG') }
|
151
|
+
|
152
|
+
rule(:block_separator) {
|
153
|
+
eol.repeat(1).as(:block_separator)
|
154
|
+
}
|
155
|
+
|
156
|
+
rule(:table) {
|
157
|
+
table_rows
|
158
|
+
}
|
159
|
+
|
160
|
+
rule(:table_rows) {
|
161
|
+
table_top_row >> table_other_rows.maybe.as(:other_rows)
|
162
|
+
}
|
163
|
+
|
164
|
+
rule(:table_top_row) {
|
165
|
+
table_header_row.as(:header) |
|
166
|
+
table_false_header_row.as(:top_row)
|
167
|
+
}
|
168
|
+
|
169
|
+
rule(:table_other_rows) {
|
170
|
+
table_detail_row.repeat(1)
|
171
|
+
}
|
172
|
+
|
173
|
+
rule(:table_header_row) {
|
174
|
+
vertical_bar >> table_cells >> str('h') >> eol
|
175
|
+
}
|
176
|
+
|
177
|
+
rule(:table_false_header_row) {
|
178
|
+
vertical_bar >> table_cells >> eol
|
179
|
+
}
|
180
|
+
|
181
|
+
rule(:table_detail_row) {
|
182
|
+
vertical_bar >> table_cells.as(:row) >> eol
|
183
|
+
}
|
184
|
+
|
185
|
+
rule(:table_cells) {
|
186
|
+
(table_cell.maybe.as(:cell) >> vertical_bar).repeat(1)
|
187
|
+
}
|
188
|
+
|
189
|
+
rule(:table_cell) {
|
190
|
+
(vertical_bar.absent? >> char).repeat
|
191
|
+
}
|
192
|
+
|
193
|
+
# Ignore forms (comment, pcomment, article, vote)
|
194
|
+
|
195
|
+
markup('~', :tilde)
|
196
|
+
markup('>', :gt)
|
197
|
+
markup('-', :minus)
|
198
|
+
markup('+', :plus)
|
199
|
+
markup(':', :colon)
|
200
|
+
markup('|', :vertical_bar)
|
201
|
+
markup(' ', :monospace)
|
202
|
+
markup(',', :comma)
|
203
|
+
markup('.', :dot)
|
204
|
+
markup('*', :star)
|
205
|
+
markup('(', :lparen)
|
206
|
+
markup(')', :rparen)
|
207
|
+
keyword('#br', :block_margin)
|
208
|
+
keyword('#clear', :clear)
|
209
|
+
keyword('#hr', :separator_line)
|
210
|
+
keyword('#contents', :toc)
|
211
|
+
keyword('#ls', :child_pages)
|
212
|
+
}
|
213
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module Pukiwiki2md
|
2
|
+
InlineElementRules = proc {
|
3
|
+
rule(:inline_text) {
|
4
|
+
inline_text_item.repeat(1).as(:inline_text)
|
5
|
+
}
|
6
|
+
|
7
|
+
rule(:inline_text_item) {
|
8
|
+
enclosed_text |
|
9
|
+
inline_function_text |
|
10
|
+
plain_text
|
11
|
+
}
|
12
|
+
|
13
|
+
rule(:inline_text_with_fragment) {
|
14
|
+
(enclosed_text |
|
15
|
+
inline_function_text |
|
16
|
+
fragment |
|
17
|
+
plain_text_for_header).repeat(1).as(:inline_text)
|
18
|
+
}
|
19
|
+
|
20
|
+
rule(:enclosed_text) {
|
21
|
+
italic | # must be prior to strong
|
22
|
+
strong |
|
23
|
+
deleted |
|
24
|
+
footnote
|
25
|
+
}
|
26
|
+
|
27
|
+
rule(:inline_function_text) {
|
28
|
+
break_line |
|
29
|
+
inline_attachment |
|
30
|
+
outbound_link |
|
31
|
+
inner_link
|
32
|
+
}
|
33
|
+
|
34
|
+
rule(:fragment) {
|
35
|
+
(str('[#') >> fragment_hash >> str(']')).as(:fragment)
|
36
|
+
}
|
37
|
+
|
38
|
+
rule(:fragment_hash) {
|
39
|
+
match('[a-z0-9]').repeat(8,8)
|
40
|
+
}
|
41
|
+
|
42
|
+
rule(:plain_text) {
|
43
|
+
(enclosed_text.absent? >> inline_function_text.absent? >> char).repeat(1).as(:plain_text)
|
44
|
+
}
|
45
|
+
|
46
|
+
rule(:plain_text_for_header) {
|
47
|
+
(enclosed_text.absent? >>
|
48
|
+
inline_function_text.absent? >>
|
49
|
+
fragment.absent? >>
|
50
|
+
char).repeat(1).as(:plain_text)
|
51
|
+
}
|
52
|
+
|
53
|
+
rule(:strong) {
|
54
|
+
str("''").as(:l) >> strong_text.as(:strong) >> str("''").as(:r)
|
55
|
+
}
|
56
|
+
|
57
|
+
rule(:strong_text) {
|
58
|
+
(str("''").absent? >> char).repeat(1)
|
59
|
+
}
|
60
|
+
|
61
|
+
rule(:italic) {
|
62
|
+
str("'''").as(:l) >> italic_text.as(:italic) >> str("'''").as(:r)
|
63
|
+
}
|
64
|
+
|
65
|
+
rule(:italic_text) {
|
66
|
+
(str("'''").absent? >> char).repeat(1)
|
67
|
+
}
|
68
|
+
|
69
|
+
rule(:deleted) {
|
70
|
+
str('%%').as(:l) >> deleted_text.as(:deleted) >> str('%%').as(:r)
|
71
|
+
}
|
72
|
+
|
73
|
+
rule(:deleted_text) {
|
74
|
+
(str('%%').absent? >> char).repeat(1)
|
75
|
+
}
|
76
|
+
|
77
|
+
rule(:footnote) {
|
78
|
+
str('((').as(:l) >> footnote_text.as(:footnote) >> str('))').as(:r)
|
79
|
+
}
|
80
|
+
|
81
|
+
rule(:footnote_text) {
|
82
|
+
(str('))').absent? >> char).repeat(1)
|
83
|
+
}
|
84
|
+
|
85
|
+
rule(:break_line) { str('&br;') }
|
86
|
+
|
87
|
+
rule(:inline_attachment) {
|
88
|
+
str('&ref(').as(:l) >> inline_attachment_path >> str(');').as(:r)
|
89
|
+
}
|
90
|
+
|
91
|
+
rule(:inline_attachment_path) {
|
92
|
+
space? >> (
|
93
|
+
inline_attachment_image_url.as(:image_url) |
|
94
|
+
inline_attachment_file_url.as(:file_url) |
|
95
|
+
inline_attachment_image.as(:image) |
|
96
|
+
inline_attachment_file.as(:file)
|
97
|
+
) >> space?
|
98
|
+
}
|
99
|
+
|
100
|
+
rule(:inline_attachment_image_url) {
|
101
|
+
scheme >> str('://') >> inline_attachment_image
|
102
|
+
}
|
103
|
+
|
104
|
+
rule(:inline_attachment_file_url) {
|
105
|
+
scheme >> str('://') >> inline_attachment_file
|
106
|
+
}
|
107
|
+
|
108
|
+
rule(:inline_attachment_image) {
|
109
|
+
inline_attachment_image_base >> image_extension
|
110
|
+
}
|
111
|
+
|
112
|
+
rule(:inline_attachment_file) {
|
113
|
+
(str(');').absent? >> char).repeat(1)
|
114
|
+
}
|
115
|
+
|
116
|
+
rule(:inline_attachment_image_base) {
|
117
|
+
((str(');')|image_extension).absent? >> char).repeat(1)
|
118
|
+
}
|
119
|
+
|
120
|
+
# [[name>alias]] could be used as an alias name for WikiName page, but this library ignores it and parses only outbound link URL.
|
121
|
+
rule(:outbound_link) {
|
122
|
+
str('[[') >> space? >>
|
123
|
+
link_text.as(:link_text) >>
|
124
|
+
link_separator >> space? >>
|
125
|
+
link_url.as(:link_url) >>
|
126
|
+
str(']]')
|
127
|
+
}
|
128
|
+
|
129
|
+
rule(:link_text) {
|
130
|
+
link_text_body_1st_part >>
|
131
|
+
(link_separator >> space? >> link_text_body_2nd_part).repeat
|
132
|
+
}
|
133
|
+
|
134
|
+
rule(:link_text_body) {
|
135
|
+
(link_separator.absent? >> char).repeat(1)
|
136
|
+
}
|
137
|
+
|
138
|
+
rule(:link_text_body_1st_part) {
|
139
|
+
link_text_body.maybe >> link_separator.present?
|
140
|
+
}
|
141
|
+
|
142
|
+
rule(:link_text_body_2nd_part) {
|
143
|
+
scheme.absent? >> link_text_body.maybe >> link_separator.present?
|
144
|
+
}
|
145
|
+
|
146
|
+
rule(:link_url) {
|
147
|
+
scheme >> str('://') >> (str(']]').absent? >> char).repeat(1)
|
148
|
+
}
|
149
|
+
|
150
|
+
rule(:link_separator) { match('[:>]') }
|
151
|
+
|
152
|
+
rule(:inner_link) {
|
153
|
+
str('[[').as(:l) >> inner_link_text.as(:inner_link) >> str(']]').as(:r)
|
154
|
+
}
|
155
|
+
|
156
|
+
rule(:inner_link_text) {
|
157
|
+
(str(']]').absent? >> char).repeat(1)
|
158
|
+
}
|
159
|
+
}
|
160
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Pukiwiki2md
|
2
|
+
PrimitiveElementRules = proc {
|
3
|
+
rule(:space) {
|
4
|
+
match('[ \t]').repeat(1)
|
5
|
+
}
|
6
|
+
|
7
|
+
rule(:space?) {
|
8
|
+
space.maybe
|
9
|
+
}
|
10
|
+
|
11
|
+
rule(:eol) {
|
12
|
+
match('[\r\n]')
|
13
|
+
}
|
14
|
+
|
15
|
+
rule(:string) {
|
16
|
+
(eol.absent? >> any).repeat(1)
|
17
|
+
}
|
18
|
+
|
19
|
+
rule(:char) {
|
20
|
+
eol.absent? >> any
|
21
|
+
}
|
22
|
+
|
23
|
+
rule(:scheme) { str('http') >> str('s').maybe }
|
24
|
+
}
|
25
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'uri'
|
2
|
+
module Pukiwiki2md
|
3
|
+
class AttachmentURL
|
4
|
+
attr_reader :url
|
5
|
+
|
6
|
+
def initialize(url)
|
7
|
+
@url = url
|
8
|
+
end
|
9
|
+
|
10
|
+
def basename
|
11
|
+
File.basename(URI.parse(@url).path)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Transform < Parslet::Transform
|
16
|
+
EOL = END_OF_LINE = "\n"
|
17
|
+
INDENT = ' '
|
18
|
+
|
19
|
+
rule(:line => simple(:s)) { s.to_s + EOL }
|
20
|
+
|
21
|
+
rule(:page_components => sequence(:components)) { components.join }
|
22
|
+
|
23
|
+
# header
|
24
|
+
rule(:star => simple(:star), :header => simple(:s)) do
|
25
|
+
[ '#' * star.length, ' ', s, EOL ].join
|
26
|
+
end
|
27
|
+
|
28
|
+
# fragment
|
29
|
+
rule(:fragment => simple(:x)) do
|
30
|
+
''
|
31
|
+
end
|
32
|
+
|
33
|
+
# quote
|
34
|
+
rule(:quote_lines => sequence(:lines)) { lines.map {|s| "> #{s}" }.join }
|
35
|
+
|
36
|
+
# pre
|
37
|
+
rule(:preformatted_lines => sequence(:lines)) {
|
38
|
+
"```\n" + lines.join + "```\n"
|
39
|
+
}
|
40
|
+
|
41
|
+
# ul
|
42
|
+
rule(:unordered_list => sequence(:lines)) { lines.join }
|
43
|
+
rule(:minus => simple(:minus), :item => simple(:s)) do
|
44
|
+
[INDENT * (minus.length-1), '*', ' ', s, EOL].join
|
45
|
+
end
|
46
|
+
|
47
|
+
# ol
|
48
|
+
rule(:ordered_list => sequence(:lines)) { lines.join }
|
49
|
+
rule(:plus => simple(:plus), :item => simple(:s)) do
|
50
|
+
[INDENT * (plus.length-1), '1.', ' ', s, EOL].join
|
51
|
+
end
|
52
|
+
|
53
|
+
# dl
|
54
|
+
rule(:definition_list => sequence(:lines)) { ["<dl>", EOL, *lines, "</dl>", EOL].join }
|
55
|
+
rule(:colon => simple(:colon), :term => simple(:term), :description => simple(:desc)) do
|
56
|
+
[ INDENT, "<dt>#{term}</dt>", EOL,
|
57
|
+
INDENT, "<dd>#{desc}</dd>", EOL ].join
|
58
|
+
end
|
59
|
+
|
60
|
+
# break
|
61
|
+
rule(:block_margin => simple(:s)) { '<br />' + EOL }
|
62
|
+
|
63
|
+
# separator line
|
64
|
+
rule(:separator_line => simple(:s)) { '---' + EOL }
|
65
|
+
|
66
|
+
# horizontal line
|
67
|
+
rule(:horizontal_line => simple(:s)) { '---' + EOL }
|
68
|
+
|
69
|
+
# #clear: ignore
|
70
|
+
rule(:clear => simple(:s)) { ['<!---', INDENT+'clear', '--->'].join("\n") + EOL }
|
71
|
+
|
72
|
+
# #contents: not supported
|
73
|
+
rule(:toc => simple(:s)) { ['<!---', INDENT+'toc', '--->'].join("\n") + EOL }
|
74
|
+
|
75
|
+
# #ls: not supported
|
76
|
+
rule(:child_pages => simple(:s)) { ['<!---', INDENT+'ls', '--->'].join("\n") + EOL }
|
77
|
+
|
78
|
+
# paragraph
|
79
|
+
rule(:paragraph_lines => sequence(:lines)) { lines.join }
|
80
|
+
|
81
|
+
# block separator
|
82
|
+
rule(:block_separator => simple(:s)) { EOL }
|
83
|
+
|
84
|
+
# table
|
85
|
+
rule(:header => sequence(:cells), :other_rows => sequence(:rows)) {
|
86
|
+
[ %(|#{cells.join('|')}|),
|
87
|
+
%(|#{Array.new(cells.size, ' --- ').join('|')}|),
|
88
|
+
*rows ].join("\n") + EOL
|
89
|
+
}
|
90
|
+
|
91
|
+
rule(:header => sequence(:cells), :other_rows => simple(:not_found)) {
|
92
|
+
[ %(|#{cells.join('|')}|),
|
93
|
+
%(|#{Array.new(cells.size, ' --- ').join('|')}|),
|
94
|
+
].join("\n") + EOL
|
95
|
+
}
|
96
|
+
|
97
|
+
rule(:top_row => sequence(:cells), :other_rows => sequence(:rows)) {
|
98
|
+
[ %(|#{Array.new(cells.size, ' ').join('|')}|),
|
99
|
+
%(|#{Array.new(cells.size, ' --- ').join('|')}|),
|
100
|
+
%(|#{cells.join('|')}|),
|
101
|
+
*rows ].join("\n") + EOL
|
102
|
+
}
|
103
|
+
|
104
|
+
rule(:top_row => sequence(:cells), :other_rows => simple(:not_found)) {
|
105
|
+
[ %(|#{Array.new(cells.size, ' ').join('|')}|),
|
106
|
+
%(|#{Array.new(cells.size, ' --- ').join('|')}|),
|
107
|
+
%(|#{cells.join('|')}|),
|
108
|
+
].join("\n") + EOL
|
109
|
+
}
|
110
|
+
|
111
|
+
rule(:row => sequence(:cells)) {
|
112
|
+
%(|#{cells.join('|')}|)
|
113
|
+
}
|
114
|
+
|
115
|
+
rule(:cell => simple(:c)) { c }
|
116
|
+
|
117
|
+
# block attachment
|
118
|
+
rule(:block_image_url => simple(:url), :l => simple(:l), :r => simple(:r)) {
|
119
|
+
attachment = AttachmentURL.new(url)
|
120
|
+
"![#{attachment.basename}](#{attachment.url})" + EOL
|
121
|
+
}
|
122
|
+
|
123
|
+
rule(:block_file_url => simple(:url), :l => simple(:l), :r => simple(:r)) {
|
124
|
+
attachment = AttachmentURL.new(url)
|
125
|
+
"[#{attachment.basename}](#{attachment.url})" + EOL
|
126
|
+
}
|
127
|
+
|
128
|
+
rule(:block_image => simple(:image), :l => simple(:l), :r => simple(:r)) {
|
129
|
+
"![#{image}](#{image})" + EOL
|
130
|
+
}
|
131
|
+
|
132
|
+
rule(:block_file => simple(:file), :l => simple(:l), :r => simple(:r)) {
|
133
|
+
"[#{file}](#{file})" + EOL
|
134
|
+
}
|
135
|
+
|
136
|
+
# inline attachment
|
137
|
+
rule(:image_url => simple(:url), :l => simple(:l), :r => simple(:r)) {
|
138
|
+
attachment = AttachmentURL.new(url)
|
139
|
+
"![#{attachment.basename}](#{attachment.url})"
|
140
|
+
}
|
141
|
+
|
142
|
+
rule(:file_url => simple(:url), :l => simple(:l), :r => simple(:r)) {
|
143
|
+
attachment = AttachmentURL.new(url)
|
144
|
+
"[#{attachment.basename}](#{attachment.url})"
|
145
|
+
}
|
146
|
+
|
147
|
+
rule(:image => simple(:image), :l => simple(:l), :r => simple(:r)) {
|
148
|
+
"![#{image}](#{image})"
|
149
|
+
}
|
150
|
+
|
151
|
+
rule(:file => simple(:file), :l => simple(:l), :r => simple(:r)) {
|
152
|
+
"[#{file}](#{file})"
|
153
|
+
}
|
154
|
+
|
155
|
+
# strong
|
156
|
+
rule(:strong => simple(:strong), :l => simple(:l), :r => simple(:r)) { " **#{strong}** " }
|
157
|
+
|
158
|
+
# italic
|
159
|
+
rule(:italic => simple(:italic), :l => simple(:l), :r => simple(:r)) { " _#{italic}_ " }
|
160
|
+
|
161
|
+
# deleted
|
162
|
+
rule(:deleted => simple(:deleted), :l => simple(:l), :r => simple(:r)) { " ~~#{deleted}~~ " }
|
163
|
+
|
164
|
+
# footnote
|
165
|
+
rule(:footnote => simple(:footnote), :l => simple(:l), :r => simple(:r)) { "(#{footnote})" }
|
166
|
+
|
167
|
+
# plain_text
|
168
|
+
rule(:plain_text => simple(:txt)) { txt }
|
169
|
+
|
170
|
+
# inline_text
|
171
|
+
rule(:inline_text => sequence(:inline_text)) { inline_text.join }
|
172
|
+
|
173
|
+
# outbound_link
|
174
|
+
rule(:link_text => simple(:text), :link_url => simple(:url)) { "[#{text}](#{url})" }
|
175
|
+
|
176
|
+
# inner_link
|
177
|
+
rule(:inner_link => simple(:name), :l => simple(:l), :r => simple(:r)) { "[#{name}]" }
|
178
|
+
end
|
179
|
+
end
|
data/pukiwiki2md.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'pukiwiki2md/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "pukiwiki2md"
|
8
|
+
spec.version = Pukiwiki2md::VERSION
|
9
|
+
spec.authors = ["sunaot"]
|
10
|
+
spec.email = ["sunao.tanabe@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A Ruby library for converting PukiWiki notation text to Markdown.}
|
13
|
+
spec.description = %q{Pukiwiki2md is a PEG implementation of PukiWiki parser and transforms PukiWiki notation to Markdown notation.}
|
14
|
+
spec.homepage = "https://github.com/sunaot/pukiwiki2md"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_dependency "parslet", "~> 1.8"
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
28
|
+
spec.add_development_dependency "simplecov"
|
29
|
+
spec.add_development_dependency "coveralls"
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pukiwiki2md
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.8.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- sunaot
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-08-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: parslet
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.8'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.14'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.14'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: coveralls
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Pukiwiki2md is a PEG implementation of PukiWiki parser and transforms
|
98
|
+
PukiWiki notation to Markdown notation.
|
99
|
+
email:
|
100
|
+
- sunao.tanabe@gmail.com
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- ".coveralls.yml"
|
106
|
+
- ".gitignore"
|
107
|
+
- ".travis.yml"
|
108
|
+
- Gemfile
|
109
|
+
- LICENSE.txt
|
110
|
+
- README.md
|
111
|
+
- Rakefile
|
112
|
+
- bin/console
|
113
|
+
- bin/setup
|
114
|
+
- lib/pukiwiki2md.rb
|
115
|
+
- lib/pukiwiki2md/parser.rb
|
116
|
+
- lib/pukiwiki2md/rules/block.rb
|
117
|
+
- lib/pukiwiki2md/rules/inline.rb
|
118
|
+
- lib/pukiwiki2md/rules/primitive.rb
|
119
|
+
- lib/pukiwiki2md/transform.rb
|
120
|
+
- lib/pukiwiki2md/version.rb
|
121
|
+
- pukiwiki2md.gemspec
|
122
|
+
homepage: https://github.com/sunaot/pukiwiki2md
|
123
|
+
licenses:
|
124
|
+
- MIT
|
125
|
+
metadata: {}
|
126
|
+
post_install_message:
|
127
|
+
rdoc_options: []
|
128
|
+
require_paths:
|
129
|
+
- lib
|
130
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
requirements: []
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 2.7.6
|
143
|
+
signing_key:
|
144
|
+
specification_version: 4
|
145
|
+
summary: A Ruby library for converting PukiWiki notation text to Markdown.
|
146
|
+
test_files: []
|