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 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,6 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.prepend File.dirname(__FILE__) + "/../lib"
3
+ require "md2starter/command"
4
+
5
+ cmd = MD2Starter::Command.new(ARGV)
6
+ cmd.run
@@ -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
@@ -0,0 +1,3 @@
1
+ module MD2Starter
2
+ VERSION = "1.0.0"
3
+ 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: []