markita 4.1.230214 → 6.0.250327
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/README.md +194 -237
- data/bin/markita +16 -19
- data/lib/markita/base.rb +37 -38
- data/lib/markita/config.rb +41 -10
- data/lib/markita/html.rb +35 -20
- data/lib/markita/markdown/attributes.rb +23 -0
- data/lib/markita/markdown/blockquote.rb +41 -0
- data/lib/markita/markdown/code.rb +44 -0
- data/lib/markita/markdown/code_block.rb +29 -0
- data/lib/markita/markdown/definitions.rb +42 -0
- data/lib/markita/markdown/embed.rb +63 -0
- data/lib/markita/markdown/empty.rb +22 -0
- data/lib/markita/markdown/fold.rb +39 -0
- data/lib/markita/markdown/footnotes.rb +28 -0
- data/lib/markita/markdown/form.rb +125 -0
- data/lib/markita/markdown/heading.rb +33 -0
- data/lib/markita/markdown/horizontal_rule.rb +25 -0
- data/lib/markita/markdown/image.rb +60 -0
- data/lib/markita/markdown/inline.rb +123 -0
- data/lib/markita/markdown/list.rb +65 -0
- data/lib/markita/markdown/markup.rb +23 -0
- data/lib/markita/markdown/script.rb +28 -0
- data/lib/markita/markdown/split.rb +38 -0
- data/lib/markita/markdown/table.rb +52 -0
- data/lib/markita/markdown.rb +51 -498
- data/lib/markita/plug/about.rb +28 -17
- data/lib/markita/plug/favicon.rb +14 -10
- data/lib/markita/plug/highlight.rb +18 -12
- data/lib/markita/plug/login.rb +35 -28
- data/lib/markita/plug/navigation.rb +4 -1
- data/lib/markita/plug/plugs.rb +7 -1
- data/lib/markita/plug/readme.rb +8 -4
- data/lib/markita/preprocess.rb +52 -23
- data/lib/markita/refinement.rb +21 -0
- data/lib/markita/requires.rb +29 -0
- data/lib/markita.rb +15 -24
- metadata +52 -116
data/lib/markita/markdown.rb
CHANGED
@@ -1,521 +1,74 @@
|
|
1
|
-
|
2
|
-
class Markdown
|
3
|
-
ROUGE = Rouge::Formatters::HTML.new
|
4
|
-
PARSERS = []
|
5
|
-
|
6
|
-
def initialize(title)
|
7
|
-
@title = title
|
8
|
-
@line=@html=@file=@opt=nil
|
9
|
-
@metadata = {}
|
10
|
-
end
|
11
|
-
|
12
|
-
def start
|
13
|
-
@html << HTML.header(@title)
|
14
|
-
@line = HTML.navigation
|
15
|
-
end
|
16
|
-
|
17
|
-
def finish
|
18
|
-
if (title=@metadata['Title'])
|
19
|
-
@html << %(<script> document.title = "#{title}" </script>\n)
|
20
|
-
end
|
21
|
-
@html << HTML.footer
|
22
|
-
@line = nil
|
23
|
-
end
|
24
|
-
|
25
|
-
def default
|
26
|
-
@html << @line
|
27
|
-
@line = @file.gets
|
28
|
-
end
|
29
|
-
|
30
|
-
def init(fh)
|
31
|
-
@file,@html,@opt = Preprocess.new(fh),'',{}
|
32
|
-
end
|
33
|
-
|
34
|
-
def parse(fh)
|
35
|
-
init(fh)
|
36
|
-
start
|
37
|
-
PARSERS.detect{method(_1).call} or default while @line
|
38
|
-
finish
|
39
|
-
end
|
40
|
-
|
41
|
-
def markdown(string)
|
42
|
-
parse StringIO.new string
|
43
|
-
@html
|
44
|
-
end
|
45
|
-
|
46
|
-
def filepath(filepath)
|
47
|
-
File.open(filepath, 'r'){|fh| parse fh}
|
48
|
-
@html
|
49
|
-
end
|
50
|
-
|
51
|
-
Ux = /_([^_]+)_/
|
52
|
-
U = ->(m){"<u>#{m[1]}</u>"}
|
53
|
-
|
54
|
-
Sx = /~([^~]+)~/
|
55
|
-
S = ->(m){"<s>#{m[1]}</s>"}
|
56
|
-
|
57
|
-
Ix = /"([^"]+)"/
|
58
|
-
I = ->(m){"<i>#{m[1]}</i>"}
|
59
|
-
|
60
|
-
Bx = /\*([^*]+)\*/
|
61
|
-
B = ->(m){"<b>#{m[1]}</b>"}
|
62
|
-
|
63
|
-
CODEx = /`([^`]+)`/
|
64
|
-
CODE = ->(m){"<code>#{m[1].gsub('<','<')}</code>"}
|
65
|
-
|
66
|
-
Ax = /\[([^\[\]]+)\]\(([^()]+)\)/
|
67
|
-
def anchor(m)
|
68
|
-
href = ((_=m[2]).match?(/^\d+$/) and @metadata[_] or _)
|
69
|
-
text = Markdown.tag(m[1], EMOJIx, EMOJI)
|
70
|
-
%(<a href="#{href}">#{text}</a>)
|
71
|
-
end
|
72
|
-
|
73
|
-
URLx = %r{(https?://[\w./&+?%-]+)}
|
74
|
-
URL = ->(m){%(<a href="#{m[1]}">#{m[1]}</a>)}
|
75
|
-
|
76
|
-
EMOJIx = /:(\w+):/
|
77
|
-
EMOJI = ->(m){(_=EMOJIS[m[1]])? "&#x#{_};" : m[0]}
|
78
|
-
|
79
|
-
FOOTNOTEx = /\[\^(\d+)\](:)?/
|
80
|
-
FOOTNOTE = lambda do |m|
|
81
|
-
if m[2]
|
82
|
-
%(<a id="fn:#{m[1]}" href="#fnref:#{m[1]}">#{m[1]}:</a>)
|
83
|
-
else
|
84
|
-
%(<a id="fnref:#{m[1]}" href="#fn:#{m[1]}"><sup>#{m[1]}</sup></a>)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def self.tag(entry, regx, m2string, &block)
|
89
|
-
if (m=regx.match entry)
|
90
|
-
string = ''
|
91
|
-
while m
|
92
|
-
pre_match = (block ? block.call(m.pre_match) : m.pre_match)
|
93
|
-
string << pre_match + m2string[m]
|
94
|
-
post_match = m.post_match
|
95
|
-
m = regx.match(post_match)
|
96
|
-
end
|
97
|
-
string << (block ? block.call(post_match) : post_match)
|
98
|
-
return string
|
99
|
-
end
|
100
|
-
block ? block.call(entry) : entry
|
101
|
-
end
|
102
|
-
|
103
|
-
def inline(entry)
|
104
|
-
string = Markdown.tag(entry, CODEx, CODE) do |entry|
|
105
|
-
Markdown.tag(entry, Ax, method(:anchor)) do |entry|
|
106
|
-
Markdown.tag(entry, URLx, URL) do |entry|
|
107
|
-
entry = Markdown.tag(entry, EMOJIx, EMOJI)
|
108
|
-
entry = Markdown.tag(entry, Bx, B)
|
109
|
-
entry = Markdown.tag(entry, Ix, I)
|
110
|
-
entry = Markdown.tag(entry, Sx, S)
|
111
|
-
entry = Markdown.tag(entry, Ux, U)
|
112
|
-
Markdown.tag(entry, FOOTNOTEx, FOOTNOTE)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
string.sub(/ $/,'<br>')
|
117
|
-
end
|
118
|
-
|
119
|
-
# Empty
|
120
|
-
EMPTY = /^$/
|
121
|
-
PARSERS << :empty
|
122
|
-
def empty
|
123
|
-
EMPTY.match?(@line) or return false
|
124
|
-
@line = @file.gets
|
125
|
-
true
|
126
|
-
end
|
127
|
-
|
128
|
-
# Ordered list
|
129
|
-
ORDERED = /^( {0,3})\d+\. (\S.*)$/
|
130
|
-
PARSERS << :ordered
|
131
|
-
def ordered(md=nil)
|
132
|
-
md ||= ORDERED.match(@line) or return false
|
133
|
-
level = md[1].length
|
134
|
-
@html << "<ol#{@opt[:attributes]}>\n"
|
135
|
-
@opt.delete(:attributes)
|
136
|
-
while md && level==md[1].length
|
137
|
-
@html << " <li>#{inline(md[2])}</li>\n"
|
138
|
-
next unless (md=(@line=@file.gets)&.match ORDERED) && level<md[1].length
|
139
|
-
ordered(md)
|
140
|
-
md = @line&.match(ORDERED)
|
141
|
-
end
|
142
|
-
@html << "</ol>\n"
|
143
|
-
true
|
144
|
-
end
|
1
|
+
# frozen_string_literal: true
|
145
2
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
while md
|
154
|
-
@html << inline(@line)
|
155
|
-
while (@line=@file.gets)&.start_with?('<')
|
156
|
-
@html << @line # Exceptional HTML injection into the paragraph
|
157
|
-
end
|
158
|
-
md = @line&.match PARAGRAPHS
|
159
|
-
end
|
160
|
-
@html << "</p>\n"
|
161
|
-
true
|
162
|
-
end
|
3
|
+
# Markita top level namespace
|
4
|
+
module Markita
|
5
|
+
# The markdown parser.
|
6
|
+
# :reek:ClassVariable :reek:TooManyInstanceVariables
|
7
|
+
# rubocop:disable Style/ClassVars
|
8
|
+
class Markdown
|
9
|
+
ROUGE = Rouge::Formatters::HTML.new
|
163
10
|
|
164
|
-
|
165
|
-
UNORDERED = /^( {0,3})[*] (\S.*)$/
|
166
|
-
PARSERS << :unordered
|
167
|
-
def unordered(md=nil)
|
168
|
-
md ||= UNORDERED.match(@line) or return false
|
169
|
-
level = md[1].length
|
170
|
-
@html << "<ul#{@opt[:attributes]}>\n"
|
171
|
-
@opt.delete(:attributes)
|
172
|
-
while md && level==md[1].length
|
173
|
-
@html << " <li>#{inline(md[2])}</li>\n"
|
174
|
-
next unless (md=(@line=@file.gets)&.match UNORDERED) && level<md[1].length
|
175
|
-
unordered(md)
|
176
|
-
md = @line&.match(UNORDERED)
|
177
|
-
end
|
178
|
-
@html << "</ul>\n"
|
179
|
-
true
|
180
|
-
end
|
11
|
+
@@parsers = []
|
181
12
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
@html << "<ul#{@opt[:attributes]}>\n"
|
188
|
-
@opt.delete(:attributes)
|
189
|
-
while md
|
190
|
-
x,t = md[1],md[2]
|
191
|
-
li = x=='x' ?
|
192
|
-
%q(<li style="list-style-type: '☑ '">) :
|
193
|
-
%q(<li style="list-style-type: '☐ '">)
|
194
|
-
@html << " #{li}#{inline(t)}</li>\n"
|
195
|
-
md = (@line=@file.gets)&.match BALLOTS
|
13
|
+
def initialize(title)
|
14
|
+
@title = title
|
15
|
+
@line = @html = @line_getter = nil
|
16
|
+
@metadata = {}
|
17
|
+
@attributes = []
|
196
18
|
end
|
197
|
-
@html << "</ul>\n"
|
198
|
-
true
|
199
|
-
end
|
200
19
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
def definitions
|
205
|
-
md = DEFINITIONS.match(@line) or return false
|
206
|
-
@html << "<dl#{@opt[:attributes]}>\n"
|
207
|
-
@opt.delete(:attributes)
|
208
|
-
while md
|
209
|
-
case md[1]
|
210
|
-
when /(.*): (.*)$/
|
211
|
-
@html << "<dt>#{inline $1.strip}</dt>\n"
|
212
|
-
@html << "<dd>#{inline $2.strip}</dd>\n"
|
213
|
-
when /(.*):$/
|
214
|
-
@html << "<dt>#{inline $1.strip}</dt>\n"
|
215
|
-
else
|
216
|
-
@html << "<dd>#{inline md[1].strip}</dd>\n"
|
20
|
+
def finish
|
21
|
+
if (title = @metadata['Title'])
|
22
|
+
@html << %(<script> document.title = "#{title}" </script>\n)
|
217
23
|
end
|
218
|
-
|
24
|
+
@html << Html.footer
|
25
|
+
@line = nil
|
219
26
|
end
|
220
|
-
@html << "</dl>\n"
|
221
|
-
true
|
222
|
-
end
|
223
27
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
md = HEADERS.match(@line) or return false
|
229
|
-
i,header = md[1].length,md[2]
|
230
|
-
id = header.gsub(/\([^()]*\)/,'').scan(/\w+/).join('+')
|
231
|
-
@html << %(<a id="#{id}">\n)
|
232
|
-
@html << " <h#{i}#{@opt[:attributes]}>#{inline(header)}</h#{i}>\n"
|
233
|
-
@html << "</a>\n"
|
234
|
-
@opt.delete(:attributes)
|
235
|
-
@line = @file.gets
|
236
|
-
true
|
237
|
-
end
|
238
|
-
|
239
|
-
# Block-quote
|
240
|
-
BLOCKQS = /^( {0,3})> (.*)$/
|
241
|
-
PARSERS << :blockqs
|
242
|
-
def blockqs(md=nil)
|
243
|
-
md ||= BLOCKQS.match(@line) or return false
|
244
|
-
level = md[1].length
|
245
|
-
@html << "<blockquote#{@opt[:attributes]}>\n"
|
246
|
-
@opt.delete(:attributes)
|
247
|
-
while md && level==md[1].length
|
248
|
-
@html << inline(md[2])
|
249
|
-
@html << "\n"
|
250
|
-
next unless (md=(@line=@file.gets)&.match BLOCKQS) && level<md[1].length
|
251
|
-
blockqs(md)
|
252
|
-
md = @line&.match(BLOCKQS)
|
28
|
+
# init(fh: String || File) -> void
|
29
|
+
def init(line_getter)
|
30
|
+
@line_getter = Preprocess.new(line_getter)
|
31
|
+
@html = String.new
|
253
32
|
end
|
254
|
-
@html << "</blockquote>\n"
|
255
|
-
true
|
256
|
-
end
|
257
33
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
def codes
|
262
|
-
md = CODES.match(@line) or return false
|
263
|
-
lang = Rouge::Lexer.find md[1]
|
264
|
-
klass = lang ? ' class="highlight"' : nil
|
265
|
-
@html << "<pre#{klass}#{@opt[:attributes]}><code>\n"
|
266
|
-
@opt.delete(:attributes)
|
267
|
-
code = ''
|
268
|
-
code << @line while (@line=@file.gets) && !CODES.match?(@line)
|
269
|
-
@html << (lang ? ROUGE.format(lang.new.lex(code)) : code)
|
270
|
-
@html << "</code></pre>\n"
|
271
|
-
@line = @file.gets if @line # then it's code close and thus need next @line.
|
272
|
-
true
|
273
|
-
end
|
274
|
-
|
275
|
-
# Script
|
276
|
-
SCRIPT = /^<script/
|
277
|
-
PARSERS << :script
|
278
|
-
def script
|
279
|
-
SCRIPT.match(@line) or return false
|
280
|
-
@html << @line
|
281
|
-
while (@line=@file.gets)
|
282
|
-
@html << @line
|
283
|
-
break if %r{^</script>}.match?(@line)
|
34
|
+
def start
|
35
|
+
@html << Html.header(@title)
|
36
|
+
@line = Html.navigation
|
284
37
|
end
|
285
|
-
@line = @file.gets if @line
|
286
|
-
true
|
287
|
-
end
|
288
38
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
@html << "<pre#{@opt[:attributes]}>\n"
|
295
|
-
@opt.delete(:attributes)
|
296
|
-
while md
|
297
|
-
@html << md[1]
|
298
|
-
@html << "\n"
|
299
|
-
md = (@line=@file.gets)&.match PREFORMS
|
39
|
+
def parse(line_getter)
|
40
|
+
init(line_getter)
|
41
|
+
start
|
42
|
+
parsers_detect or default while @line
|
43
|
+
finish
|
300
44
|
end
|
301
|
-
@html << "</pre>\n"
|
302
|
-
true
|
303
|
-
end
|
304
45
|
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
md = METADATAS.match(@line) or return false
|
309
|
-
while md
|
310
|
-
@metadata[md[1]] = md[2]
|
311
|
-
md = (@line=@file.gets)&.match METADATAS
|
46
|
+
def filepath(filepath)
|
47
|
+
File.open(filepath, 'r') { parse it }
|
48
|
+
@html
|
312
49
|
end
|
313
|
-
true
|
314
|
-
end
|
315
50
|
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
def hrs
|
320
|
-
HRS.match? @line or return false
|
321
|
-
@line = @file.gets
|
322
|
-
if metadata
|
323
|
-
# Optional closing HRS
|
324
|
-
@line = @file.gets if @line&.match? HRS
|
325
|
-
else
|
326
|
-
# Display HR
|
327
|
-
@html << "<hr#{@opt[:attributes]}>\n"
|
328
|
-
@opt.delete(:attributes)
|
51
|
+
def markdown(string)
|
52
|
+
parse StringIO.new string
|
53
|
+
@html
|
329
54
|
end
|
330
|
-
true
|
331
|
-
end
|
332
55
|
|
333
|
-
|
334
|
-
TABLES = /^\|.+\|$/
|
335
|
-
PARSERS << :tables
|
336
|
-
def tables
|
337
|
-
TABLES.match? @line or return false
|
338
|
-
@html << "<table#{@opt[:attributes]}>\n"
|
339
|
-
@opt.delete(:attributes)
|
340
|
-
@html << '<thead><tr><th>'
|
341
|
-
@html << @line[1...-1].split('|').map{inline(_1.strip)}.join('</th><th>')
|
342
|
-
@html << "</th></tr></thead>\n"
|
343
|
-
align = []
|
344
|
-
while (@line=@file.gets)&.match? TABLES
|
345
|
-
@html << '<tr>'
|
346
|
-
@line[1...-1].split('|').each_with_index do |cell, i|
|
347
|
-
case cell
|
348
|
-
when /^\s*:-+:\s*$/
|
349
|
-
align[i] = ' align="center"'
|
350
|
-
@html << '<td><hr></td>'
|
351
|
-
when /^\s*-+:\s*$/
|
352
|
-
align[i] = ' align="right"'
|
353
|
-
@html << '<td><hr></td>'
|
354
|
-
when /^\s*:-+\s*$/
|
355
|
-
align[i] = ' align="left"'
|
356
|
-
@html << '<td><hr></td>'
|
357
|
-
else
|
358
|
-
@html << "<td#{align[i]}>#{inline(cell.strip)}</td>"
|
359
|
-
end
|
360
|
-
end
|
361
|
-
@html << "</tr>\n"
|
362
|
-
end
|
363
|
-
@html << "</table>\n"
|
364
|
-
true
|
365
|
-
end
|
366
|
-
|
367
|
-
# Splits
|
368
|
-
SPLITS = /^:?\|:?$/
|
369
|
-
PARSERS << :splits
|
370
|
-
def splits
|
371
|
-
SPLITS.match? @line or return false
|
372
|
-
case @line.chomp
|
373
|
-
when '|:'
|
374
|
-
@html << %(<table><tr><td#{@opt[:attributes]}>\n)
|
375
|
-
when '|'
|
376
|
-
@html << %(</td><td#{@opt[:attributes]}>\n)
|
377
|
-
when ':|:'
|
378
|
-
@html << %(</td></tr><tr><td#{@opt[:attributes]}>\n)
|
379
|
-
when ':|'
|
380
|
-
@html << %(</td></tr></table>\n)
|
381
|
-
end
|
382
|
-
@opt.delete(:attributes)
|
383
|
-
@line = @file.gets
|
384
|
-
true
|
385
|
-
end
|
386
|
-
|
387
|
-
# Image
|
388
|
-
IMAGES = /^!\[([^\[\]]+)\]\(([^()]+)\)$/
|
389
|
-
PARSERS << :images
|
390
|
-
def images
|
391
|
-
md = IMAGES.match(@line) or return false
|
392
|
-
alt,src,href=md[1],*md[2].strip.split(/\s+/,2)
|
393
|
-
style = ' '
|
394
|
-
case alt
|
395
|
-
when /^:.*:$/
|
396
|
-
style =
|
397
|
-
%( style="display: block; margin-left: auto; margin-right: auto;" )
|
398
|
-
when /:$/
|
399
|
-
style = %( style="float:left;" )
|
400
|
-
when /^:/
|
401
|
-
style = %( style="float:right;" )
|
402
|
-
end
|
403
|
-
if /(\d+)x(\d+)/.match alt
|
404
|
-
style << %(width="#{$1}" height="#{$2}" )
|
405
|
-
end
|
406
|
-
@html << %(<a href="#{href}">\n) if href
|
407
|
-
@html <<
|
408
|
-
%(<img src="#{src}"#{style}alt="#{alt.strip}"#{@opt[:attributes]}>\n)
|
409
|
-
@html << %(</a>\n) if href
|
410
|
-
@opt.delete(:attributes)
|
411
|
-
@line = @file.gets
|
412
|
-
true
|
413
|
-
end
|
414
|
-
|
415
|
-
# Forms
|
416
|
-
FIELD = '(\w+:)?\[(\*)?(\w+)(=("[^"]+")(,"[^"]+")*)?\]'
|
417
|
-
FIELDS = Regexp.new FIELD
|
418
|
-
FORMS = Regexp.new "^!( #{FIELD})+"
|
419
|
-
PARSERS << :forms
|
420
|
-
def forms
|
421
|
-
md = FORMS.match(@line) or return false
|
422
|
-
fields,nl,submit = 0,false,nil
|
423
|
-
action = (_=/\(([^()]*)\)!?$/.match(@line))? %( action="#{_[1]}") : nil
|
424
|
-
method = @line.match?(/!$/) ? ' method="post"' : nil
|
425
|
-
@html << %(<form#{action}#{method}#{@opt[:attributes]}>\n)
|
426
|
-
@opt.delete(:attributes)
|
427
|
-
while md
|
428
|
-
@html << " <br>\n" if nl
|
429
|
-
@line.scan(FIELDS).each do |field, pwd, name, value|
|
430
|
-
field &&= field[0...-1]
|
431
|
-
value &&= value[2...-1]
|
432
|
-
if field
|
433
|
-
type = pwd ? 'password' : 'text'
|
434
|
-
if value
|
435
|
-
if (values = value.split('","')).length > 1
|
436
|
-
@html << %(#{field}:<select name="#{name}">\n)
|
437
|
-
values.each do |value|
|
438
|
-
fields += 1
|
439
|
-
@html << %( <option value="#{value}">#{value}</option>\n)
|
440
|
-
end
|
441
|
-
@html << "</select>\n"
|
442
|
-
else
|
443
|
-
fields += 1
|
444
|
-
@html << %( #{field}:<input type="#{type}" name="#{name}")
|
445
|
-
@html << %( value="#{value}">\n)
|
446
|
-
end
|
447
|
-
else
|
448
|
-
fields += 1
|
449
|
-
@html << %( #{field}:<input type="#{type}" name="#{name}">\n)
|
450
|
-
end
|
451
|
-
elsif name=='submit'
|
452
|
-
submit = value
|
453
|
-
else
|
454
|
-
@html << %( <input type="hidden" name="#{name}" value="#{value}">\n)
|
455
|
-
end
|
456
|
-
end
|
457
|
-
md=(@line=@file.gets)&.match(FORMS) and nl=true
|
458
|
-
end
|
459
|
-
if submit || fields!=1
|
460
|
-
submit ||= 'Submit'
|
461
|
-
@html << " <br>\n" if nl
|
462
|
-
@html << %( <input type="submit" value="#{submit}">\n)
|
463
|
-
end
|
464
|
-
@html << %(</form>\n)
|
465
|
-
true
|
466
|
-
end
|
467
|
-
|
468
|
-
# Embed text
|
469
|
-
EMBED_TEXTS = /^!> (#{PAGE_KEY}\.\w+)$/
|
470
|
-
PARSERS << :embed_texts
|
471
|
-
def embed_texts
|
472
|
-
md = EMBED_TEXTS.match(@line) or return false
|
473
|
-
if File.exist?(filename=File.join(ROOT, md[1]))
|
474
|
-
extension,lang = filename.split('.').last,nil
|
475
|
-
unless extension=='html'
|
476
|
-
lang = Rouge::Lexer.find(extension) unless extension=='txt'
|
477
|
-
klass = lang ? ' class="highlight"' : nil
|
478
|
-
@html << "<pre#{klass}#{@opt[:attributes]}>"
|
479
|
-
@opt.delete(:attributes)
|
480
|
-
@html << '<code>' if lang
|
481
|
-
@html << "\n"
|
482
|
-
end
|
483
|
-
code = File.read(filename)
|
484
|
-
@html << (lang ? ROUGE.format(lang.new.lex(code)) : code)
|
485
|
-
unless extension=='html'
|
486
|
-
@html << '</code>' if lang
|
487
|
-
@html << '</pre>'
|
488
|
-
@html << "\n"
|
489
|
-
end
|
490
|
-
else
|
491
|
-
@html << @line
|
492
|
-
end
|
493
|
-
@line = @file.gets
|
494
|
-
true
|
495
|
-
end
|
56
|
+
def parsers_detect = @@parsers.detect { method(it).call }
|
496
57
|
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
58
|
+
# Defaults to paragraph
|
59
|
+
# :reek:DuplicateMethodCall :reek:TooManyStatements
|
60
|
+
def default
|
61
|
+
# Let html take the original @html String and set @html to String.new('')
|
62
|
+
html = @html
|
63
|
+
@html = String.new
|
64
|
+
html << "<p#{@attributes.shift}>\n"
|
65
|
+
html << inline(@line)
|
66
|
+
html << inline(@line) while line_gets && !parsers_detect
|
67
|
+
html << "</p>\n#{@html}"
|
68
|
+
@html = html # Give back the original String to @html
|
506
69
|
end
|
507
|
-
@html << "</small>\n"
|
508
|
-
true
|
509
|
-
end
|
510
70
|
|
511
|
-
|
512
|
-
ATTRIBUTES = /^\{:( .*)\}/
|
513
|
-
PARSERS << :attributes
|
514
|
-
def attributes
|
515
|
-
md = ATTRIBUTES.match(@line) or return false
|
516
|
-
@opt[:attributes] = md[1]
|
517
|
-
@line = md.post_match
|
518
|
-
true
|
71
|
+
def line_gets = @line = @line_getter.gets
|
519
72
|
end
|
520
|
-
|
73
|
+
# rubocop:enable Style/ClassVars
|
521
74
|
end
|
data/lib/markita/plug/about.rb
CHANGED
@@ -1,33 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Markita namespace
|
1
4
|
module Markita
|
2
|
-
class
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
# Base class of the Sinatra Markita application
|
6
|
+
class Base
|
7
|
+
# About namespace to support the /about.html route
|
8
|
+
module About
|
9
|
+
ABOUT_TEXT = <<~TEXT.freeze
|
6
10
|
# [Markita](https://github.com/carlosjhr64/markita)
|
7
11
|
|
8
12
|
* VERSION: #{VERSION}
|
9
|
-
* ROOT: #{ROOT.sub(%r{^/home/\w+/},'~/')}
|
13
|
+
* ROOT: #{ROOT.sub(%r{^/home/\w+/}, '~/')}
|
10
14
|
* ARGV: #{ARGV.join(' ')}
|
11
15
|
* START_TIME: #{START_TIME}
|
12
16
|
|
13
17
|
## Plug.html routes:
|
14
18
|
|
15
19
|
TEXT
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
|
21
|
+
def self.plugs
|
22
|
+
Base.routes['GET'].each do |route|
|
23
|
+
path = route[0].to_s
|
24
|
+
next unless %r{^/\w+\.html$}.match? path
|
25
|
+
|
26
|
+
yield path, File.basename(path, '.*')
|
27
|
+
end
|
21
28
|
end
|
22
|
-
|
23
|
-
|
29
|
+
|
30
|
+
def self.page
|
31
|
+
text = ABOUT_TEXT.dup
|
32
|
+
plugs { |path, basename| text << "* [#{basename}](#{path})\n" }
|
33
|
+
if defined? Favicon && Favicon::ICO
|
34
|
+
text << "\n\n"
|
35
|
+
end
|
36
|
+
text
|
24
37
|
end
|
25
|
-
text
|
26
38
|
end
|
27
|
-
end
|
28
39
|
|
29
|
-
|
30
|
-
|
40
|
+
get '/about.html' do
|
41
|
+
Markdown.new('About').markdown About.page
|
42
|
+
end
|
31
43
|
end
|
32
44
|
end
|
33
|
-
end
|
data/lib/markita/plug/favicon.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Markita namespace
|
1
4
|
module Markita
|
2
|
-
|
3
|
-
|
4
|
-
%( <link rel="icon" type="image/x-icon" href="/favicon.ico">\n)
|
5
|
+
Html.header_links <<
|
6
|
+
%(<link rel="icon" type="image/x-icon" href="/favicon.ico">\n)
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
# Base class of the Sinatra Markita application
|
9
|
+
class Base
|
10
|
+
module Favicon
|
11
|
+
ICO = File.read PATH['favicon.ico']
|
12
|
+
end
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
14
|
+
get '/favicon.ico' do
|
15
|
+
headers 'Content-Type' => 'image/x-icon'
|
16
|
+
Favicon::ICO
|
17
|
+
end
|
13
18
|
end
|
14
19
|
end
|
15
|
-
end
|