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
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Markita top level namespace
4
+ module Markita
5
+ # Markdown namespace
6
+ # :reek:InstanceVariableAssumption :reek:ClassVariable
7
+ class Markdown
8
+ # Module to isolate from Markdown
9
+ # :reek:DuplicateMethodCall
10
+ module Fold
11
+ RGX = /^[-.]{3} #/
12
+ METADATA = /^(\w+): (.*)$/
13
+ def self.scrape4metadata(line, metadata, attributes)
14
+ if (md = Fold::METADATA.match(line))
15
+ if (key = md[1]) == 'attributes'
16
+ attributes.push " #{md[2]}"
17
+ else
18
+ metadata[key] = md[2]
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ @@parsers << :fold
25
+
26
+ # category: method
27
+ # :reek:DuplicateMethodCall ok here
28
+ def fold
29
+ return false unless Fold::RGX.match?(@line)
30
+
31
+ # Fold with optional metadata
32
+ until Fold::RGX.match?(line_gets)
33
+ Fold.scrape4metadata(@line, @metadata, @attributes)
34
+ end
35
+ line_gets
36
+ true
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Markita top level namespace
4
+ module Markita
5
+ # Markdown namespace
6
+ # :reek:InstanceVariableAssumption :reek:ClassVariable
7
+ class Markdown
8
+ # Module to isolate from Markdown
9
+ module Footnotes
10
+ RGX = /^\[\^\d+\]:/
11
+ end
12
+
13
+ @@parsers << :footnotes
14
+
15
+ # :reek:TooManyStatements
16
+ def footnotes
17
+ return false unless (continue = Footnotes::RGX.match?(@line))
18
+
19
+ @html << "<small>\n"
20
+ while continue
21
+ @html << "#{inline(@line.chomp)}<br>\n"
22
+ continue = Footnotes::RGX.match?(line_gets)
23
+ end
24
+ @html << "</small>\n"
25
+ true
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Markita top level namespace
4
+ module Markita
5
+ # Markdown namespace
6
+ # :reek:InstanceVariableAssumption :reek:ClassVariable
7
+ class Markdown
8
+ # Module to isolate from Markdown
9
+ module Form
10
+ field = '(\w+:)?\[(\*)?(\w+)(=("[^"]+")(,"[^"]+")*)?\]'
11
+ FIELD = Regexp.new field
12
+ RGX = /^!( #{field})+/
13
+ POST = /!$/
14
+ ACTION = /\(([^()]*)\)!?$/
15
+
16
+ def self.input_select(field, name, values)
17
+ %( #{field}:<select name="#{name}">\n).tap do |html|
18
+ values.each do |value|
19
+ html << %( <option value="#{value}">#{value}</option>\n)
20
+ end
21
+ html << " </select>\n"
22
+ end
23
+ end
24
+
25
+ def self.input_text(field, type, name)
26
+ %( #{field}:<input type="#{type}" name="#{name}">\n)
27
+ end
28
+
29
+ # :reek:LongParameterList :reek:TooManyStatements
30
+ def self.input(type, field, name, values)
31
+ if field
32
+ if values.empty? then input_text(field, type, name)
33
+ elsif values.count > 1 then input_select(field, name, values)
34
+ else
35
+ input_defaulted(field, type, name, values)
36
+ end
37
+ elsif name == 'submit' then input_submit(values)
38
+ else
39
+ input_hidden(name, values)
40
+ end
41
+ end
42
+
43
+ def self.input_submit(values)
44
+ %( <input type="submit" value="#{values[0] || 'Submit'}">\n)
45
+ end
46
+
47
+ def self.input_hidden(name, values)
48
+ %( <input type="hidden" name="#{name}" value="#{values[0]}">\n)
49
+ end
50
+
51
+ # :reek:LongParameterList
52
+ def self.input_defaulted(field, type, name, values)
53
+ <<-INPUT
54
+ #{field}:<input type="#{type}" name="#{name}"
55
+ value="#{values[0]}">
56
+ INPUT
57
+ end
58
+
59
+ def self.match?(line) = RGX.match?(line)
60
+
61
+ # :reek:ControlParameter :reek:NilCheck :reek:LongParameterList
62
+ def self.maybe(yon, name, field, values)
63
+ return :NO if yon == :NO || (field.nil? && name == 'submit')
64
+ return yon unless field && values.count < 2
65
+
66
+ yon == :yes ? :no : :YES
67
+ end
68
+
69
+ # :reek:LongYieldList :reek:TooManyStatements
70
+ def self.scan(line)
71
+ line.scan(FIELD).each do |field, pwd, name, value|
72
+ field &&= field[0...-1]
73
+ values = value ? value[2...-1].split('","') : []
74
+ type = pwd ? 'password' : 'text'
75
+ yield field, type, name, values
76
+ end
77
+ end
78
+
79
+ def self.start(line, attributes)
80
+ method = POST.match?(line) ? ' method="post"' : ''
81
+ action = (mdt = ACTION.match(line)) ? %( action="#{mdt[1]}") : ''
82
+ %(<form#{action}#{method}#{attributes.shift}>\n)
83
+ end
84
+
85
+ def self.stop = %(</form>\n)
86
+
87
+ # :reek:ControlParameter
88
+ def self.submit(yon)
89
+ case yon
90
+ when :yes
91
+ %( <input type="submit">\n)
92
+ when :YES
93
+ %( <br>\n <input type="submit">\n)
94
+ else
95
+ ''
96
+ end
97
+ end
98
+ end
99
+
100
+ @@parsers << :form
101
+
102
+ # category: method
103
+ # :reek:TooManyStatements
104
+ # rubocop:disable Metrics/MethodLength
105
+ def form
106
+ return false unless Form.match?(@line)
107
+
108
+ yon = :yes # Append submit button?
109
+ @html << Form.start(@line, @attributes)
110
+ loop do
111
+ Form.scan(@line) do |field, type, name, values|
112
+ yon = Form.maybe(yon, name, field, values)
113
+ @html << Form.input(type, field, name, values)
114
+ end
115
+ break unless Form.match?(line_gets)
116
+
117
+ @html << " <br>\n"
118
+ end
119
+ @html << Form.submit(yon)
120
+ @html << Form.stop
121
+ true
122
+ end
123
+ # rubocop:enable Metrics/MethodLength
124
+ end
125
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Markita top level namespace
4
+ module Markita
5
+ # Markdown namespace
6
+ # :reek:InstanceVariableAssumption :reek:ClassVariable
7
+ class Markdown
8
+ # Module to isolate from Markdown
9
+ module Heading
10
+ RGX = /^(\#{1,6}) (.*)$/
11
+
12
+ def self.level_header(line)
13
+ mdt = RGX.match(line)
14
+ [mdt[1].length, mdt[2]] if mdt
15
+ end
16
+ end
17
+
18
+ @@parsers << :heading
19
+
20
+ # category: method
21
+ # :reek:TooManyStatements :reek:UncommunicativeVariableName
22
+ def heading
23
+ return false unless (n, header = Heading.level_header(@line))
24
+
25
+ id = header.gsub(/\([^()]*\)/, '').scan(/\w+/).join('+')
26
+ @html << %(<a id="#{id}">\n)
27
+ @html << " <h#{n}#{@attributes.shift}>#{inline(header)}</h#{n}>\n"
28
+ @html << "</a>\n"
29
+ line_gets
30
+ true
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Markita top level namespace
4
+ module Markita
5
+ # Markdown namespace
6
+ # :reek:InstanceVariableAssumption :reek:ClassVariable
7
+ class Markdown
8
+ # Module to isolate from Markdown
9
+ module HorizontalRule
10
+ RGX = /^---+$/
11
+ end
12
+
13
+ @@parsers << :horizontal_rule
14
+
15
+ # category: method
16
+ def horizontal_rule
17
+ return false unless HorizontalRule::RGX.match?(@line)
18
+
19
+ line_gets
20
+ # Display HR
21
+ @html << "<hr#{@attributes.shift}>\n"
22
+ true
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Markita top level namespace
4
+ module Markita
5
+ # Markdown namespace
6
+ # :reek:InstanceVariableAssumption :reek:ClassVariable
7
+ class Markdown
8
+ # Module to isolate from Markdown
9
+ module Image
10
+ RGX = /^!\[([^\[\]]+)\]\(([^()]+)\)$/
11
+
12
+ def self.attributes(line)
13
+ mdt = RGX.match(line)
14
+ [mdt[1], *mdt[2].strip.split(/\s+/, 2)] if mdt
15
+ end
16
+
17
+ def self.img_src(src, alt, att)
18
+ style = Image.style(alt)
19
+ size = Image.size(alt)
20
+ %(<img src="#{src}"#{style}#{size}alt="#{alt.strip}"#{att.shift}>\n)
21
+ end
22
+
23
+ def self.size(alt)
24
+ if (mdt = /(\d+)x(\d+)/.match(alt))
25
+ %(width="#{mdt[1]}" height="#{mdt[2]}" )
26
+ else
27
+ ''
28
+ end
29
+ end
30
+
31
+ # :reek:ControlParameter
32
+ def self.style(alt)
33
+ case alt
34
+ when /^:.*:$/
35
+ %( style="display: block; margin-left: auto; margin-right: auto;" )
36
+ when /:$/
37
+ %( style="float:left;" )
38
+ when /^:/
39
+ %( style="float:right;" )
40
+ else
41
+ ' '
42
+ end
43
+ end
44
+ end
45
+
46
+ @@parsers << :images
47
+
48
+ # category: method
49
+ # :reek:TooManyStatements
50
+ def images
51
+ return false unless (alt, src, href = Image.attributes(@line))
52
+
53
+ @html << %(<a href="#{href}">\n) if href
54
+ @html << Image.img_src(src, alt, @attributes)
55
+ @html << %(</a>\n) if href
56
+ line_gets
57
+ true
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Markita top level namespace
4
+ module Markita
5
+ # Markdown namespace
6
+ # :reek:InstanceVariableAssumption in markdown.rb
7
+ class Markdown
8
+ # Module to isolate from Markdown
9
+ # :reek:TooManyConstants
10
+ module Inline
11
+ # category: details
12
+
13
+ # When the writer does not mean to invoke a substitutions caused by a
14
+ # special character, that character can be escaped with a backslash.
15
+ # This is then replaced with its HTML entity.
16
+ ENTITY = /\\([<>*"~`_&;:\\])/
17
+ def self.entity(mdt) = "&##{mdt[1].ord};"
18
+
19
+ FOOTNOTE = /\[\^(\d+)\](:)?/
20
+ # :reek:ControlParameter
21
+ def self.footnote(mdt = nil, num: mdt[1], ref: mdt[2])
22
+ if ref
23
+ %(<a id="fn:#{num}" href="#fnref:#{num}">#{num}:</a>)
24
+ else
25
+ %(<a id="fnref:#{num}" href="#fn:#{num}"><sup>#{num}</sup></a>)
26
+ end
27
+ end
28
+
29
+ SUBSCRIPT = /\\\(([^()]+)\)/
30
+ def self.subscript(mdt) = "<sub>#{mdt[1]}</sub>"
31
+
32
+ SUPERSCRIPT = /\\\^\(([^()]+)\)/
33
+ def self.superscript(mdt) = "<sup>#{mdt[1]}</sup>"
34
+
35
+ URL = %r{(https?://[\w./&+?%-]+)}
36
+ def self.url(mdt, hrf = mdt[1]) = %(<a href="#{hrf}">#{hrf}</a>)
37
+
38
+ BOLD = /\*([^*]+)\*/
39
+ def self.bold(mdt) = "<b>#{mdt[1]}</b>"
40
+
41
+ CODE = /`([^`]+)`/
42
+ def self.code(mdt) = "<code>#{mdt[1].gsub('<', '&lt;')}</code>"
43
+
44
+ EMOJI = /:(\w+):/
45
+ EMOJIS = Hash[*File.read(PATH['emojis.tsv']).split(/\s+/)]
46
+ def self.emoji(mdt) = (emj = EMOJIS[mdt[1]]) ? "&#x#{emj};" : mdt[0]
47
+
48
+ ITALIC = /"([^"]+)"/
49
+ def self.italic(mdt) = "<i>#{mdt[1]}</i>"
50
+
51
+ STRIKE = /~([^~]+)~/
52
+ def self.strike(mdt) = "<s>#{mdt[1]}</s>"
53
+
54
+ UNDERLINE = /_([^_]+)_/
55
+ def self.underline(mdt) = "<u>#{mdt[1]}</u>"
56
+
57
+ ANCHOR = /\[([^\[\]]+)\]\(([^(")]+)\)/
58
+ def self.anchor(mdt)
59
+ href, title = mdt[2].split(/\s+/, 2).map(&:strip)
60
+ title = %( title="#{title}") if title
61
+ text = tag(mdt[1], EMOJI, method(:emoji))
62
+ %(<a href="#{href}"#{title}>#{text}</a>)
63
+ end
64
+
65
+ # category: algorithm
66
+
67
+ # :reek:DuplicateMethodCall :reek:TooManyStatements
68
+ # rubocop:disable Metrics/MethodLength
69
+ def self.tag(entry, regx, m2string, &block)
70
+ if (mdt = regx.match entry)
71
+ string = String.new
72
+ while mdt
73
+ pre_match = (block ? block.call(mdt.pre_match) : mdt.pre_match)
74
+ string << (pre_match + m2string[mdt])
75
+ post_match = mdt.post_match
76
+ mdt = regx.match(post_match)
77
+ end
78
+ string << (block ? block.call(post_match) : post_match)
79
+ return string
80
+ end
81
+ block ? block.call(entry) : entry
82
+ end
83
+
84
+ # :reek:NestedIterators :reek:TooManyStatements
85
+ # :reek:UncommunicativeVariableName
86
+ # rubocop:disable Metrics/AbcSize
87
+ def self.tags(line)
88
+ line = tag(line, ENTITY, method(:entity))
89
+ line = tag(line, CODE, method(:code)) do |string|
90
+ tag(string, ANCHOR, method(:anchor)) do |str|
91
+ tag(str, URL, method(:url)) do |s|
92
+ s = tag(s, EMOJI, method(:emoji))
93
+ s = tag(s, BOLD, method(:bold))
94
+ s = tag(s, ITALIC, method(:italic))
95
+ s = tag(s, STRIKE, method(:strike))
96
+ s = tag(s, UNDERLINE, method(:underline))
97
+ s = tag(s, FOOTNOTE, method(:footnote))
98
+ s = tag(s, SUPERSCRIPT, method(:superscript))
99
+ tag(s, SUBSCRIPT, method(:subscript))
100
+ end
101
+ end
102
+ end
103
+ line.sub(/ ?[ \\]$/, '<br>')
104
+ end
105
+ # rubocop:enable Metrics/AbcSize
106
+ # rubocop:enable Metrics/MethodLength
107
+ end
108
+
109
+ # category: method
110
+
111
+ # :reek:DuplicateMethodCall :reek:TooManyStatements
112
+ def inline(line)
113
+ line = Inline.tags(line)
114
+ line = Inline.tag(line, /[$](\w+)/, lambda do |mdt|
115
+ @metadata[mdt[1]] || mdt[0]
116
+ end)
117
+ Inline.tag(line, /<a href="(\d+)">/, lambda do |mdt|
118
+ key = mdt[1]
119
+ %(<a href="#{@metadata[key] || key}">)
120
+ end)
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Markita top level namespace
4
+ module Markita
5
+ # Markdown namespace
6
+ # :reek:InstanceVariableAssumption :reek:ClassVariable
7
+ class Markdown
8
+ # Module to isolate from Markdown
9
+ module List
10
+ # rubocop:disable Lint/MixedRegexpCaptureTypes
11
+ RGX = /^(?<spaces>\s{0,3})
12
+ (?<bullet>[*]|(\d+\.)|(-\s\[(\s|x)\]))
13
+ \s(?<text>\S.*)$/x
14
+ # rubocop:enable Lint/MixedRegexpCaptureTypes
15
+
16
+ def self.level_bullet_text(line)
17
+ mdt = RGX.match(line)
18
+ [mdt[:spaces].length, mdt[:bullet], mdt[:text]] if mdt
19
+ end
20
+
21
+ # :reek:ControlParameter
22
+ def self.style(check)
23
+ case check
24
+ when ' '
25
+ %q( style="list-style-type: '&#9744; '")
26
+ when 'x'
27
+ %q( style="list-style-type: '&#9745; '")
28
+ else
29
+ ''
30
+ end
31
+ end
32
+
33
+ def self.type(bullet)
34
+ bullet[0] =~ /\d/ ? 'ol' : 'ul'
35
+ end
36
+ end
37
+
38
+ @@parsers << :list
39
+
40
+ # category: method
41
+ # :reek:DuplicateMethodCall :reek:TooManyStatements
42
+ # rubocop:disable Metrics/MethodLength
43
+ # rubocop:disable Metrics/AbcSize
44
+ def list
45
+ return false unless (level, bullet, text = List.level_bullet_text(@line))
46
+
47
+ type = List.type(bullet)
48
+ @html << "<#{type}#{@attributes.shift}>\n"
49
+ loop do
50
+ style = List.style(bullet[3])
51
+ @html << " <li#{style}>#{inline(text)}</li>\n"
52
+ current, bullet, text = List.level_bullet_text(line_gets)
53
+ if current&.>(level)
54
+ list
55
+ current, bullet, text = List.level_bullet_text(@line)
56
+ end
57
+ break unless current.eql?(level) && type.eql?(List.type(bullet))
58
+ end
59
+ @html << "</#{type}>\n"
60
+ true
61
+ end
62
+ # rubocop:enable Metrics/AbcSize
63
+ # rubocop:enable Metrics/MethodLength
64
+ end
65
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Markita top level namespace
4
+ module Markita
5
+ # Markdown namespace
6
+ # :reek:InstanceVariableAssumption :reek:ClassVariable
7
+ class Markdown
8
+ # Module to isolate from Markdown
9
+ module Markup
10
+ RGX = /^ {0,3}<.*>$/
11
+ end
12
+
13
+ @@parsers << :html_markup
14
+
15
+ def html_markup
16
+ return false unless Markup::RGX.match(@line)
17
+
18
+ @html << @line
19
+ line_gets
20
+ true
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Markita top level namespace
4
+ module Markita
5
+ # Markdown namespace
6
+ # :reek:InstanceVariableAssumption :reek:ClassVariable
7
+ class Markdown
8
+ # Module to isolate from Markdown
9
+ module Script
10
+ RGX = /^<script/
11
+ end
12
+
13
+ @@parsers << :script
14
+
15
+ # :reek:TooManyStatements :reek:DuplicateMethodCall
16
+ def script
17
+ return false unless Script::RGX.match(@line)
18
+
19
+ @html << @line
20
+ while line_gets
21
+ @html << @line
22
+ break if %r{^</script>}.match?(@line)
23
+ end
24
+ line_gets if @line
25
+ true
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Markita top level namespace
4
+ module Markita
5
+ # Markdown namespace
6
+ # :reek:InstanceVariableAssumption :reek:ClassVariable
7
+ class Markdown
8
+ # Module to isolate from Markdown
9
+ module Split
10
+ RGX = /^:?\|:?$/
11
+
12
+ # :reek:ControlParameter :reek:DuplicateMethodCall
13
+ def self.table(code, attributes)
14
+ case code
15
+ when '|:'
16
+ %(<table><tr><td#{attributes.shift}>\n)
17
+ when '|'
18
+ %(</td><td#{attributes.shift}>\n)
19
+ when ':|:'
20
+ %(</td></tr><tr><td#{attributes.shift}>\n)
21
+ when ':|'
22
+ %(</td></tr></table>\n)
23
+ end
24
+ end
25
+ end
26
+
27
+ @@parsers << :splits
28
+
29
+ # category: method
30
+ def splits
31
+ return false unless Split::RGX.match? @line
32
+
33
+ @html << Split.table(@line.chomp, @attributes)
34
+ line_gets
35
+ true
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Markita top level namespace
4
+ module Markita
5
+ # Markdown namespace
6
+ # :reek:InstanceVariableAssumption :reek:ClassVariable
7
+ class Markdown
8
+ # Module to isolate from Markdown
9
+ module Table
10
+ RGX = /^\|.+\|$/
11
+ end
12
+
13
+ @@parsers << :table
14
+
15
+ # :reek:DuplicateMethodCall :reek:TooManyStatements
16
+ # :reek:UncommunicativeVariableName
17
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
18
+ # rubocop:disable Metrics/MethodLength, Layout/LineLength
19
+ def table
20
+ return false unless Table::RGX.match? @line
21
+
22
+ @html << "<table#{@attributes.shift}>\n"
23
+ @html << "<thead#{@attributes.shift}><tr><th>"
24
+ @html << @line[1...-1].split('|').map { inline(it.strip) }.join('</th><th>')
25
+ @html << "</th></tr></thead>\n"
26
+ align = []
27
+ while line_gets&.match? Table::RGX
28
+ @html << '<tr>'
29
+ @line[1...-1].split('|').each_with_index do |cell, i|
30
+ case cell
31
+ when /^\s*:-+:\s*$/
32
+ align[i] = ' align="center"'
33
+ @html << '<td><hr></td>'
34
+ when /^\s*-+:\s*$/
35
+ align[i] = ' align="right"'
36
+ @html << '<td><hr></td>'
37
+ when /^\s*:-+\s*$/
38
+ align[i] = ' align="left"'
39
+ @html << '<td><hr></td>'
40
+ else
41
+ @html << "<td#{align[i]}>#{inline(cell.strip)}</td>"
42
+ end
43
+ end
44
+ @html << "</tr>\n"
45
+ end
46
+ @html << "</table>\n"
47
+ true
48
+ end
49
+ # rubocop:enable Metrics/MethodLength, Layout/LineLength
50
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
51
+ end
52
+ end