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