md2starter 1.0.0
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 +7 -0
- data/README.md +45 -0
- data/bin/md2starter +6 -0
- data/lib/md2starter/command.rb +104 -0
- data/lib/md2starter/markdown.rb +16 -0
- data/lib/md2starter/version.rb +3 -0
- data/lib/md2starter.rb +25 -0
- data/lib/redcarpet/render/review.rb +423 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6283930429a2e7bb005c3661db87f3366b7698f9519ce5489c0ba20088306118
|
4
|
+
data.tar.gz: 6d14a75e7ce890f428840b26db1f01429bfc32e0812d49de5415bc7efad0dda0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cc9056b8b44529d196912ca81a76abf82458a15df7fcb90f3bd576ea71705a7f870e55d1c8dbfaa42409e9af0246b197e3139c4c58ee96c8444bc10d56fdb868
|
7
|
+
data.tar.gz: 0b848d9e1a16f7452c20db33a7b5b5cbd0d244c37111da6a45a6910c7a55223f750ee2c7e194deafe73c489247ff03399dec8fbf7966d89232fdb355fa1e0628
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# MD2Starter
|
2
|
+
|
3
|
+
MD2Starter is a CLI tool to convert from Markdown into [Re:VIEW Starter](https://kauplan.org/reviewstarter/).
|
4
|
+
This command uses Redcarpet gem to parse markdown.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Install it yourself as:
|
9
|
+
|
10
|
+
$ gem install md2starter
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
You may convert files using the included executables `md2starter`.
|
15
|
+
|
16
|
+
$ md2starter -h
|
17
|
+
Usage: md2starter INPUT_FILENAME_OR_DIRECTORY [OUTPUT_FILENAME_OR_DIRECTORY] [options]
|
18
|
+
--trace Show a full traceback on error
|
19
|
+
-d, --delete Delete markdown files
|
20
|
+
-m, --math Math markdown enable
|
21
|
+
-h, --help Show this message
|
22
|
+
-v, --version Print version
|
23
|
+
|
24
|
+
See [USAGE.md](./USAGE.md) for more information on Markdown and Starter format notation.
|
25
|
+
|
26
|
+
## License
|
27
|
+
|
28
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
29
|
+
|
30
|
+
## History
|
31
|
+
|
32
|
+
### v1.0.0
|
33
|
+
- Initial release
|
34
|
+
|
35
|
+
## Author
|
36
|
+
|
37
|
+
[Atelier Mirai](https://atelier-mirai.net)
|
38
|
+
|
39
|
+
## Thanks
|
40
|
+
|
41
|
+
This Gem is based on [html2slim](https://github.com/slim-template/html2slim) and [md2review](https://github.com/takahashim/md2review). We thank the authors.
|
42
|
+
|
43
|
+
## OFFICIAL REPOSITORY
|
44
|
+
|
45
|
+
[https://github.com/Atelier-Mirai/md2starter](https://github.com/Atelier-Mirai/md2starter)
|
data/bin/md2starter
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'md2starter'
|
3
|
+
include MD2Starter
|
4
|
+
|
5
|
+
module MD2Starter
|
6
|
+
class Command
|
7
|
+
def initialize(args)
|
8
|
+
@args = args
|
9
|
+
@options = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
@opts = OptionParser.new(&method(:set_opts))
|
14
|
+
@opts.parse!(@args)
|
15
|
+
process!
|
16
|
+
exit 0
|
17
|
+
rescue Exception => ex
|
18
|
+
raise ex if @options[:trace] || SystemExit === ex
|
19
|
+
$stderr.print "#{ex.class}: " if ex.class != RuntimeError
|
20
|
+
$stderr.puts ex.message
|
21
|
+
$stderr.puts ' Use --trace for backtrace.'
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def set_opts(opts)
|
28
|
+
opts.banner = "Usage: md2starter INPUT_FILENAME_OR_DIRECTORY [OUTPUT_FILENAME_OR_DIRECTORY] [options]"
|
29
|
+
|
30
|
+
opts.on('--trace', :NONE, 'Show a full traceback on error') do
|
31
|
+
@options[:trace] = true
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
35
|
+
puts opts
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on_tail('-v', '--version', 'Print version') do
|
40
|
+
puts "md2starter #{MD2Starter::VERSION}"
|
41
|
+
exit
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on('-d', '--delete', "Delete markdown files") do
|
45
|
+
@options[:delete] = true
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on('-m', '--math', "Math markdown enable") do
|
49
|
+
@options[:math] = true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def process!
|
54
|
+
args = @args.dup
|
55
|
+
|
56
|
+
@options[:input] = file = args.shift
|
57
|
+
@options[:input] = file = "-" unless file
|
58
|
+
@options[:output] = destination = args.shift
|
59
|
+
|
60
|
+
if file == "-"
|
61
|
+
puts @opts.to_s
|
62
|
+
exit
|
63
|
+
end
|
64
|
+
|
65
|
+
if File.directory?(@options[:input])
|
66
|
+
Dir["#{@options[:input]}/**/*.md"].each { |file| _process(file, destination) }
|
67
|
+
else
|
68
|
+
_process(file, destination)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def input_is_dir?
|
75
|
+
File.directory? @options[:input]
|
76
|
+
end
|
77
|
+
|
78
|
+
def _process(file, destination = nil)
|
79
|
+
require 'fileutils'
|
80
|
+
starter_file = file.sub(/\.md/, '.re')
|
81
|
+
|
82
|
+
if input_is_dir? && destination
|
83
|
+
FileUtils.mkdir_p(File.dirname(starter_file).sub(@options[:input].chomp('/'), destination))
|
84
|
+
starter_file.sub!(@options[:input].chomp('/'), destination)
|
85
|
+
else
|
86
|
+
starter_file = destination || starter_file
|
87
|
+
end
|
88
|
+
|
89
|
+
fail(ArgumentError, "Source and destination files can't be the same.") if @options[:input] != '-' && file == starter_file
|
90
|
+
|
91
|
+
in_file = if @options[:input] == "-"
|
92
|
+
$stdin
|
93
|
+
else
|
94
|
+
File.open(file, 'r')
|
95
|
+
end
|
96
|
+
|
97
|
+
@options[:output] = starter_file && starter_file != '-' ? File.open(starter_file, 'w') : $stdout
|
98
|
+
@options[:output].puts MD2Starter.convert!(in_file, @options)
|
99
|
+
@options[:output].close
|
100
|
+
|
101
|
+
File.delete(file) if @options[:delete]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "redcarpet"
|
2
|
+
require "redcarpet/render/review"
|
3
|
+
|
4
|
+
module MD2Starter
|
5
|
+
class Markdown
|
6
|
+
def initialize(render_options, parser_options)
|
7
|
+
## Redcarpet only
|
8
|
+
render = Redcarpet::Render::ReVIEW.new(render_options)
|
9
|
+
@markdown = Redcarpet::Markdown.new(render, parser_options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def render(text)
|
13
|
+
@markdown.render(text)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/md2starter.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative "md2starter/version"
|
2
|
+
require_relative "md2starter/markdown"
|
3
|
+
|
4
|
+
module MD2Starter
|
5
|
+
class << self
|
6
|
+
def convert!(input, options)
|
7
|
+
render_extensions = {}
|
8
|
+
render_extensions[:link_in_footnote] = false
|
9
|
+
render_extensions[:table_caption] = true
|
10
|
+
render_extensions[:math] = options[:math] ? true : false
|
11
|
+
|
12
|
+
parse_extensions = {}
|
13
|
+
parse_extensions[:tables] = true
|
14
|
+
parse_extensions[:strikethrough] = true
|
15
|
+
parse_extensions[:fenced_code_blocks] = true
|
16
|
+
parse_extensions[:footnotes] = true
|
17
|
+
parse_extensions[:no_intra_emphasis] = true
|
18
|
+
parse_extensions[:autolink] = true
|
19
|
+
|
20
|
+
md = MD2Starter::Markdown.new(render_extensions, parse_extensions)
|
21
|
+
md_doc = open(input).read
|
22
|
+
starter_doc = md.render(md_doc)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,423 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'digest/md5'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module Redcarpet
|
7
|
+
module Render
|
8
|
+
class ReVIEW < Base
|
9
|
+
|
10
|
+
# initialize
|
11
|
+
########################################################################
|
12
|
+
def initialize(render_extensions={})
|
13
|
+
super()
|
14
|
+
@math = render_extensions[:math]
|
15
|
+
@links = {}
|
16
|
+
@math_inline_buf = []
|
17
|
+
@math_block_buf = []
|
18
|
+
@ruby_buf = []
|
19
|
+
end
|
20
|
+
|
21
|
+
# preprocess
|
22
|
+
########################################################################
|
23
|
+
def preprocess(text)
|
24
|
+
b_counter = -1
|
25
|
+
while %r|\$\$(.+?)\$\$| =~ text
|
26
|
+
text.sub!(%r|\$\$(.+?)\$\$|) do
|
27
|
+
b_counter += 1
|
28
|
+
@math_block_buf[b_counter] = $1
|
29
|
+
"〓MATHBLOCK:#{b_counter}:〓"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
if @math
|
34
|
+
i_counter = -1
|
35
|
+
while %r|\$(.+?)\$| =~ text
|
36
|
+
text.sub!(%r|\$(.+?)\$|) do
|
37
|
+
i_counter += 1
|
38
|
+
@math_inline_buf[i_counter] = $1
|
39
|
+
"〓MATHINLINE:#{i_counter}:〓"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# るび
|
45
|
+
r_counter = -1
|
46
|
+
while %r|\{(.+?\|.+?)\}| =~ text
|
47
|
+
text.sub!(%r|\{(.+?\|.+?)\}|) do
|
48
|
+
r_counter += 1
|
49
|
+
@ruby_buf[r_counter] = $1
|
50
|
+
"〓RUBY:#{r_counter}:〓"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
text
|
55
|
+
end
|
56
|
+
|
57
|
+
# normal text
|
58
|
+
########################################################################
|
59
|
+
def normal_text(text)
|
60
|
+
text
|
61
|
+
end
|
62
|
+
|
63
|
+
# escape
|
64
|
+
########################################################################
|
65
|
+
def escape_inline(text)
|
66
|
+
## } -> \}
|
67
|
+
## \} -> \\\}
|
68
|
+
## .} -> .\}
|
69
|
+
text.gsub(/(.)?}/) do
|
70
|
+
if $1 == '\\'
|
71
|
+
replaced = '\\\\\\}'
|
72
|
+
elsif $1
|
73
|
+
replaced = $1 + '\\}'
|
74
|
+
else
|
75
|
+
replaced = '\\}'
|
76
|
+
end
|
77
|
+
replaced
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def escape_href(text)
|
82
|
+
text.to_s.gsub(/,/){ '\\,' }
|
83
|
+
end
|
84
|
+
alias_method :escape_comma, :escape_href
|
85
|
+
|
86
|
+
# block code
|
87
|
+
########################################################################
|
88
|
+
def block_code(code, language)
|
89
|
+
code_text = normal_text(code).chomp
|
90
|
+
lang = ""
|
91
|
+
caption = ""
|
92
|
+
|
93
|
+
if language
|
94
|
+
# lang, caption = "java: main.java".split(":").map(&:strip)
|
95
|
+
lang, caption = language.split(":").map(&:strip)
|
96
|
+
|
97
|
+
# if language =~ /caption=\"(.*)\"/
|
98
|
+
# caption = "["+$1+"]"
|
99
|
+
# else
|
100
|
+
# caption = "[][#{language}]"
|
101
|
+
# end
|
102
|
+
end
|
103
|
+
|
104
|
+
if lang == "math"
|
105
|
+
"//texequation[][#{caption}]{\n#{code.chomp}\n//}\n\n"
|
106
|
+
elsif lang == "output"
|
107
|
+
"//output[][#{caption}]{\n#{code_text}\n//}\n\n"
|
108
|
+
elsif lang == "terminal"
|
109
|
+
"//terminal[][#{caption}]{\n#{code_text}\n//}\n\n"
|
110
|
+
elsif lang == "note"
|
111
|
+
"//note[][#{caption}]{\n#{code_text}\n//}\n\n"
|
112
|
+
elsif lang == "memo"
|
113
|
+
"//memo[#{caption}]{\n#{code_text}\n//}\n\n"
|
114
|
+
elsif lang == "tip"
|
115
|
+
"//tip[#{caption}]{\n#{code_text}\n//}\n\n"
|
116
|
+
elsif lang == "info"
|
117
|
+
"//info[#{caption}]{\n#{code_text}\n//}\n\n"
|
118
|
+
elsif lang == "warning"
|
119
|
+
"//warning[#{caption}]{\n#{code_text}\n//}\n\n"
|
120
|
+
elsif lang == "important"
|
121
|
+
"//important[#{caption}]{\n#{code_text}\n//}\n\n"
|
122
|
+
elsif lang == "caution"
|
123
|
+
"//caution[#{caption}]{\n#{code_text}\n//}\n\n"
|
124
|
+
elsif lang == "notice"
|
125
|
+
"//notice[#{caption}]{\n#{code_text}\n//}\n\n"
|
126
|
+
elsif lang == "column"
|
127
|
+
"===[column] #{caption}\n#{code_text}\n\n===[/column]\n\n"
|
128
|
+
elsif lang == "flushright"
|
129
|
+
"//flushright{\n#{code_text}\n//}\n\n"
|
130
|
+
elsif lang == "centering"
|
131
|
+
"//centering{\n#{code_text}\n//}\n\n"
|
132
|
+
elsif lang == "abstract"
|
133
|
+
if caption.nil? || caption == "toc=on"
|
134
|
+
"//abstract{\n#{code_text}\n//}\n\n//makechaptitlepage[toc=on]\n\n"
|
135
|
+
else
|
136
|
+
"//abstract{\n#{code_text}\n//}\n\n"
|
137
|
+
end
|
138
|
+
elsif lang == "chapterauthor"
|
139
|
+
if caption.nil? || caption.empty?
|
140
|
+
"//chapterauthor[#{code_text}]\n\n"
|
141
|
+
else
|
142
|
+
"//chapterauthor[#{caption}]\n\n"
|
143
|
+
end
|
144
|
+
elsif lang == "include"
|
145
|
+
filename = File&.basename(caption.to_s)
|
146
|
+
"//list[][#{filename}][file=source/#{caption},1]{\n//}\n\n"
|
147
|
+
elsif lang == "image" || lang == "sideimage"
|
148
|
+
if !code_text.empty?
|
149
|
+
link = caption + '&content=' + code_text
|
150
|
+
else
|
151
|
+
link = caption
|
152
|
+
end
|
153
|
+
title = ""
|
154
|
+
alt_text = ""
|
155
|
+
image(link, title, alt_text) + "\n\n"
|
156
|
+
else
|
157
|
+
"//list[][#{caption}][1]{\n#{code_text}\n//}\n\n"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# codespan
|
162
|
+
########################################################################
|
163
|
+
def codespan(code)
|
164
|
+
"@<code>{#{escape_inline(code)}}"
|
165
|
+
end
|
166
|
+
|
167
|
+
def block_quote(quote)
|
168
|
+
quote_text = normal_text(quote).chomp
|
169
|
+
quote_text.gsub!(/\A\n\n/, '')
|
170
|
+
"//quote{\n#{quote_text}//}\n\n"
|
171
|
+
end
|
172
|
+
|
173
|
+
def block_html(raw_html)
|
174
|
+
html_text = raw_html.chomp
|
175
|
+
|
176
|
+
# html コメントなら 何も出力しない
|
177
|
+
if html_text[0..3] == "<!--" && html_text[-3..-1] == "-->"
|
178
|
+
return
|
179
|
+
end
|
180
|
+
|
181
|
+
# エラーメッセージを表示
|
182
|
+
warning = "XXX: BLOCK_HTML: YOU SHOULD REWRITE IT"
|
183
|
+
"\n//list[][]{\n#{warning}\n#{html_text}\n//}\n"
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
# header
|
188
|
+
########################################################################
|
189
|
+
def header(title, level, anchor="")
|
190
|
+
"#{"="*level} #{title}\n"
|
191
|
+
end
|
192
|
+
|
193
|
+
# table
|
194
|
+
########################################################################
|
195
|
+
def paragraph(text)
|
196
|
+
if text =~ /\ATable:(.*)\z/
|
197
|
+
@table_caption = $1.strip
|
198
|
+
"" # no output line
|
199
|
+
elsif text =~ /\Achapterauthor:(.*)\z/
|
200
|
+
@chapterauthor = $1.strip
|
201
|
+
"//chapterauthor[#{@chapterauthor}]\n\n"
|
202
|
+
elsif text =~ /\Ainclude:(.*)\z/
|
203
|
+
link = $1.strip
|
204
|
+
filename = File.basename(link)
|
205
|
+
"//list[][#{filename}][file=source/#{link},1]{\n//}\n\n"
|
206
|
+
else
|
207
|
+
# "\n\n#{text}\n\n"
|
208
|
+
"#{text}\n\n"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def table(header, body)
|
213
|
+
body.chomp!
|
214
|
+
|
215
|
+
if @table_caption
|
216
|
+
caption = @table_caption
|
217
|
+
@table_caption = nil
|
218
|
+
end
|
219
|
+
|
220
|
+
column_count = 0
|
221
|
+
body.each_line do |line|
|
222
|
+
column_count = line.split(",").size
|
223
|
+
break
|
224
|
+
end
|
225
|
+
|
226
|
+
tsize = "//tsize[][#{'|l'*column_count+'|'}]\n"
|
227
|
+
"#{tsize}//table[][#{caption}][csv=on,headerrows=1]{\n#{header}#{body}\n//}\n\n"
|
228
|
+
end
|
229
|
+
|
230
|
+
def table_row(content)
|
231
|
+
@sep = nil
|
232
|
+
content+"\n"
|
233
|
+
end
|
234
|
+
|
235
|
+
def table_cell(content, alignment)
|
236
|
+
sep = @sep
|
237
|
+
@sep = ", "
|
238
|
+
if content == ""
|
239
|
+
content = " "
|
240
|
+
end
|
241
|
+
"#{sep}#{content}"
|
242
|
+
end
|
243
|
+
|
244
|
+
# image
|
245
|
+
########################################################################
|
246
|
+
def image(link, title, alt_text)
|
247
|
+
allowed_params = %w(width border side sep boxwidth content caption)
|
248
|
+
|
249
|
+
path, query = link.split("?")
|
250
|
+
filename = File.basename(path, ".*")
|
251
|
+
|
252
|
+
if query
|
253
|
+
query.gsub!("&", ",")
|
254
|
+
hash = query.split(",").map { |attr| attr&.split("=") }.to_h
|
255
|
+
|
256
|
+
# Remove unauthorized parameters
|
257
|
+
hash.each do |key, value|
|
258
|
+
!allowed_params.include? key and hash.delete(key)
|
259
|
+
end
|
260
|
+
|
261
|
+
if hash.key? "caption"
|
262
|
+
alt_text = hash["caption"]
|
263
|
+
hash.delete("caption")
|
264
|
+
end
|
265
|
+
|
266
|
+
# for sideimage
|
267
|
+
sideimage = "side" if hash.key? "side"
|
268
|
+
width = hash.delete("width") if sideimage
|
269
|
+
content = hash.delete("content")
|
270
|
+
content << "\n" if content
|
271
|
+
option = hash.map { |k, v| [k, v].join("=") }.join(",")
|
272
|
+
end
|
273
|
+
|
274
|
+
if sideimage
|
275
|
+
"//sideimage[#{filename}][#{width}][#{option}]{\n#{content}//}"
|
276
|
+
else
|
277
|
+
"//image[#{filename}][#{alt_text}][#{option}]"
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
# link
|
282
|
+
########################################################################
|
283
|
+
def autolink(link, link_type)
|
284
|
+
"@<href>{#{link}}"
|
285
|
+
end
|
286
|
+
|
287
|
+
def link(link, title, content)
|
288
|
+
if content == "include"
|
289
|
+
filename = File.basename(link)
|
290
|
+
"//list[][#{filename}][file=source/#{link},1]{\n//}"
|
291
|
+
else
|
292
|
+
"@<href>{#{link},#{content}}"
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
# decoration
|
297
|
+
########################################################################
|
298
|
+
def emphasis(text)
|
299
|
+
sandwitch_link('b', text)
|
300
|
+
end
|
301
|
+
|
302
|
+
def double_emphasis(text)
|
303
|
+
"@<B>{#{escape_inline(text)}}"
|
304
|
+
end
|
305
|
+
|
306
|
+
def strikethrough(text)
|
307
|
+
"@<del>{#{escape_inline(text)}}"
|
308
|
+
end
|
309
|
+
|
310
|
+
# list
|
311
|
+
########################################################################
|
312
|
+
def list(content, list_type)
|
313
|
+
ret = ""
|
314
|
+
content.each_line do |item|
|
315
|
+
case list_type
|
316
|
+
when :ordered
|
317
|
+
if item =~ /^ +(\d+\.) (.*)/
|
318
|
+
## XXX not support yet in Re:VIEW
|
319
|
+
ret << " #{$1} #{$2.chomp}" << "\n"
|
320
|
+
else
|
321
|
+
ret << " 1. " << item
|
322
|
+
end
|
323
|
+
when :unordered
|
324
|
+
if item =~ /^ (\*+) (.*)/
|
325
|
+
ret << " *#{$1} #{$2.chomp}" << "\n"
|
326
|
+
else
|
327
|
+
ret << " * " << item
|
328
|
+
end
|
329
|
+
else
|
330
|
+
# :nocov:
|
331
|
+
raise "invalid type: #{list_type}"
|
332
|
+
# :nocov:
|
333
|
+
end
|
334
|
+
end
|
335
|
+
ret << "\n"
|
336
|
+
ret
|
337
|
+
end
|
338
|
+
|
339
|
+
def list_item(content, list_type)
|
340
|
+
content.gsub!(%r<\n//(image|indepimage)\[([^\]]*?)\][^\{]*({\n//})?\n>){
|
341
|
+
"@<icon>{"+$2+"}\n"
|
342
|
+
}
|
343
|
+
case list_type
|
344
|
+
when :ordered
|
345
|
+
item = content.gsub(/\n(\s+[^0-9])/){ $1 }.gsub(/\n(\s+[0-9]+[^.])/){ $1 }.strip
|
346
|
+
"#{item}\n"
|
347
|
+
when :unordered
|
348
|
+
item = content.gsub(/\n(\s*[^* ])/){ $1 }.strip
|
349
|
+
"#{item}\n"
|
350
|
+
else
|
351
|
+
# :nocov:
|
352
|
+
raise "invalid type: #{list_type}"
|
353
|
+
# :nocov:
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
# hr / br
|
358
|
+
########################################################################
|
359
|
+
def hrule
|
360
|
+
"//hr\n\n"
|
361
|
+
end
|
362
|
+
|
363
|
+
def linebreak
|
364
|
+
"@<br>{}\n"
|
365
|
+
end
|
366
|
+
|
367
|
+
# footnote
|
368
|
+
########################################################################
|
369
|
+
def footnote_ref(number)
|
370
|
+
"@<fn>{#{number}}"
|
371
|
+
end
|
372
|
+
|
373
|
+
def footnotes(text)
|
374
|
+
"#{text}"
|
375
|
+
end
|
376
|
+
|
377
|
+
def footnote_def(text, number)
|
378
|
+
"//footnote[#{number}][#{text.strip}]\n"
|
379
|
+
end
|
380
|
+
|
381
|
+
# ruby
|
382
|
+
########################################################################
|
383
|
+
def ruby(text)
|
384
|
+
rt, rb = text.split(/\|/, 2)
|
385
|
+
"@<ruby>{#{escape_inline(rt)},#{escape_inline(rb)}}"
|
386
|
+
end
|
387
|
+
|
388
|
+
# postprocess
|
389
|
+
########################################################################
|
390
|
+
def postprocess(text)
|
391
|
+
text = text.gsub(%r|^[ \t]+(//image\[[^\]]+\]\[[^\]]+\]{$\n^//})|, '\1')
|
392
|
+
while %r|〓MATHBLOCK:(\d+):〓| =~ text
|
393
|
+
# text.sub!(%r|〓MATHBLOCK:(\d+):〓|){ "\n//texequation[][]{\n" + escape_inline(@math_block_buf[$1.to_i]) + "\n//}\n" }
|
394
|
+
text.sub!(%r|〓MATHBLOCK:(\d+):〓|){ "\n//texequation[][]{\n" + (@math_block_buf[$1.to_i]) + "\n//}\n" }
|
395
|
+
end
|
396
|
+
|
397
|
+
while %r|〓MATHINLINE:(\d+):〓| =~ text
|
398
|
+
text.sub!(%r|〓MATHINLINE:(\d+):〓|){ "@<m>{" + escape_inline(@math_inline_buf[$1.to_i]) + "}" }
|
399
|
+
end
|
400
|
+
|
401
|
+
while %r|〓RUBY:(\d+):〓| =~ text
|
402
|
+
text.sub!(%r|〓RUBY:(\d+):〓|){ ruby(@ruby_buf[$1.to_i]) }
|
403
|
+
end
|
404
|
+
|
405
|
+
text + @links.map { |key, link| footnote_def(link, key) }.join
|
406
|
+
end
|
407
|
+
|
408
|
+
def remove_inline_markups(text)
|
409
|
+
text.gsub(/@<(?:b|strong|tt)>{([^}]*)}/, '\1')
|
410
|
+
end
|
411
|
+
|
412
|
+
def sandwitch_link(op, text)
|
413
|
+
head, match, tail = text.partition(/@<href>{(?:\\,|[^}])*}/)
|
414
|
+
|
415
|
+
if match.empty? && tail.empty?
|
416
|
+
return "@<#{op}>{#{escape_inline(text)}}"
|
417
|
+
end
|
418
|
+
|
419
|
+
sandwitch_link(op, head) + match + sandwitch_link(op, tail)
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|
423
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: md2starter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Atelier Mirai
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-11-13 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A converter from Markdown to Re:VIEW Starter. It uses redcarpet.
|
14
|
+
email:
|
15
|
+
- contact@atelier-mirai.net
|
16
|
+
executables:
|
17
|
+
- md2starter
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- README.md
|
22
|
+
- bin/md2starter
|
23
|
+
- lib/md2starter.rb
|
24
|
+
- lib/md2starter/command.rb
|
25
|
+
- lib/md2starter/markdown.rb
|
26
|
+
- lib/md2starter/version.rb
|
27
|
+
- lib/redcarpet/render/review.rb
|
28
|
+
homepage: https://github.com/Atelier-Mirai/md2starter
|
29
|
+
licenses:
|
30
|
+
- MIT
|
31
|
+
metadata:
|
32
|
+
homepage_uri: https://github.com/Atelier-Mirai/md2starter
|
33
|
+
source_code_uri: https://github.com/Atelier-Mirai/md2starter
|
34
|
+
changelog_uri: https://github.com/Atelier-Mirai/md2starter/blob/master/CHANGELOG.md
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.6.0
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubygems_version: 3.3.7
|
51
|
+
signing_key:
|
52
|
+
specification_version: 4
|
53
|
+
summary: A converter from Markdown to Re:VIEW Starter.
|
54
|
+
test_files: []
|