Class: Markita::Markdown

Inherits:
Object
  • Object
show all
Defined in:
lib/markita/markdown.rb,
lib/markita/markdown/code.rb,
lib/markita/markdown/fold.rb,
lib/markita/markdown/form.rb,
lib/markita/markdown/list.rb,
lib/markita/markdown/embed.rb,
lib/markita/markdown/empty.rb,
lib/markita/markdown/image.rb,
lib/markita/markdown/split.rb,
lib/markita/markdown/table.rb,
lib/markita/markdown/inline.rb,
lib/markita/markdown/markup.rb,
lib/markita/markdown/script.rb,
lib/markita/markdown/heading.rb,
lib/markita/markdown/footnotes.rb,
lib/markita/markdown/attributes.rb,
lib/markita/markdown/blockquote.rb,
lib/markita/markdown/code_block.rb,
lib/markita/markdown/definitions.rb,
lib/markita/markdown/horizontal_rule.rb

Overview

Markdown namespace :reek:InstanceVariableAssumption :reek:ClassVariable

Defined Under Namespace

Modules: Attributes, Blockquote, Code, CodeBlock, Definitions, Embed, Empty, Fold, Footnotes, Form, Heading, HorizontalRule, Image, Inline, List, Markup, Script, Split, Table

Constant Summary collapse

ROUGE =
Rouge::Formatters::HTML.new
@@parsers =
[]

Instance Method Summary collapse

Constructor Details

#initialize(title) ⇒ Markdown

Returns a new instance of Markdown.



13
14
15
16
17
18
# File 'lib/markita/markdown.rb', line 13

def initialize(title)
  @title = title
  @line = @html = @line_getter = nil
  @metadata = {}
  @attributes = []
end

Instance Method Details

#attributesObject



15
16
17
18
19
20
21
# File 'lib/markita/markdown/attributes.rb', line 15

def attributes
  return false unless (md = Attributes::RGX.match(@line))

  @attributes.push md[1]
  @line = md.post_match
  true
end

#blockquoteObject

category: method :reek:DuplicateMethodCall :reek:TooManyStatements rubocop:disable Metrics/MethodLength



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/markita/markdown/blockquote.rb', line 23

def blockquote
  return false unless (level, quote = Blockquote.level_quote(@line))

  @html << "<blockquote#{@attributes.shift}>\n"
  current = level
  while current.eql?(level)
    @html << "#{inline(quote)}\n"
    current, quote = Blockquote.level_quote(line_gets)
    next unless current&.>(level)

    blockquote
    level, quote = Blockquote.level_quote(@line)
  end
  @html << "</blockquote>\n"
  true
end

#codeObject

category: method :reek:TooManyStatements



34
35
36
37
38
39
40
41
42
# File 'lib/markita/markdown/code.rb', line 34

def code
  return false unless (klass, lang = Code.klass_lang(@line))

  @html << "<pre#{klass}#{@attributes.shift}><code>\n"
  @html << Code.code(@line_getter, lang)
  @html << "</code></pre>\n"
  line_gets
  true
end

#code_blockObject

category: method :reek:TooManyStatements



17
18
19
20
21
22
23
24
25
26
27
# File 'lib/markita/markdown/code_block.rb', line 17

def code_block
  return false unless (md = CodeBlock::RGX.match(@line))

  @html << "<pre#{@attributes.shift}>\n"
  while md
    @html << "#{md[1]}\n"
    md = CodeBlock::RGX.match(line_gets)
  end
  @html << "</pre>\n"
  true
end

#defaultObject

Defaults to paragraph :reek:DuplicateMethodCall :reek:TooManyStatements



60
61
62
63
64
65
66
67
68
69
# File 'lib/markita/markdown.rb', line 60

def default
  # Let html take the original @html String and set @html to String.new('')
  html = @html
  @html = String.new
  html << "<p#{@attributes.shift}>\n"
  html << inline(@line)
  html << inline(@line) while line_gets && !parsers_detect
  html << "</p>\n#{@html}"
  @html = html # Give back the original String to @html
end

#definitionsObject

category: method :reek:TooManyStatements



28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/markita/markdown/definitions.rb', line 28

def definitions
  return false unless (phrase = Definitions.phrase(@line))

  @html << "<dl#{@attributes.shift}>\n"
  while phrase
    term, definition = Definitions.split(phrase)
    @html << "<dt>#{inline term}</dt>\n" if term
    @html << "<dd>#{inline definition}</dd>\n" if definition
    phrase = Definitions.phrase(line_gets)
  end
  @html << "</dl>\n"
  true
end

#embedObject

category: method :reek:TooManyStatements rubocop:disable Metrics/MethodLength



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/markita/markdown/embed.rb', line 40

def embed
  return false unless (filename = Embed.filename(@line))

  if File.exist?(filename = File.join(ROOT, filename))
    code, klass, lang = Embed.ext_klass_lang(filename)
    if code
      @html << "<pre#{klass}#{@attributes.shift}>"
      @html << '<code>' if lang
      @html << "\n"
    end
    @html << Embed.code(filename, lang)
    if code
      @html << '</code>' if lang
      @html << "</pre>\n"
    end
  else
    @html << @line
  end
  line_gets
  true
end

#emptyObject



15
16
17
18
19
20
# File 'lib/markita/markdown/empty.rb', line 15

def empty
  return false unless Empty::RGX.match?(@line)

  line_gets
  true
end

#filepath(filepath) ⇒ Object



46
47
48
49
# File 'lib/markita/markdown.rb', line 46

def filepath(filepath)
  File.open(filepath, 'r') { parse it }
  @html
end

#finishObject



20
21
22
23
24
25
26
# File 'lib/markita/markdown.rb', line 20

def finish
  if (title = @metadata['Title'])
    @html << %(<script> document.title = "#{title}" </script>\n)
  end
  @html << Html.footer
  @line = nil
end

#foldObject

category: method :reek:DuplicateMethodCall ok here



28
29
30
31
32
33
34
35
36
37
# File 'lib/markita/markdown/fold.rb', line 28

def fold
  return false unless Fold::RGX.match?(@line)

  # Fold with optional metadata
  until Fold::RGX.match?(line_gets)
    Fold.(@line, @metadata, @attributes)
  end
  line_gets
  true
end

#footnotesObject

:reek:TooManyStatements



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/markita/markdown/footnotes.rb', line 16

def footnotes
  return false unless (continue = Footnotes::RGX.match?(@line))

  @html << "<small>\n"
  while continue
    @html << "#{inline(@line.chomp)}<br>\n"
    continue = Footnotes::RGX.match?(line_gets)
  end
  @html << "</small>\n"
  true
end

#formObject

category: method :reek:TooManyStatements rubocop:disable Metrics/MethodLength



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/markita/markdown/form.rb', line 105

def form
  return false unless Form.match?(@line)

  yon = :yes # Append submit button?
  @html << Form.start(@line, @attributes)
  loop do
    Form.scan(@line) do |field, type, name, values|
      yon = Form.maybe(yon, name, field, values)
      @html << Form.input(type, field, name, values)
    end
    break unless Form.match?(line_gets)

    @html << "  <br>\n"
  end
  @html << Form.submit(yon)
  @html << Form.stop
  true
end

#headingObject

category: method :reek:TooManyStatements :reek:UncommunicativeVariableName



22
23
24
25
26
27
28
29
30
31
# File 'lib/markita/markdown/heading.rb', line 22

def heading
  return false unless (n, header = Heading.level_header(@line))

  id = header.gsub(/\([^()]*\)/, '').scan(/\w+/).join('+')
  @html << %(<a id="#{id}">\n)
  @html << "  <h#{n}#{@attributes.shift}>#{inline(header)}</h#{n}>\n"
  @html << "</a>\n"
  line_gets
  true
end

#horizontal_ruleObject

category: method



16
17
18
19
20
21
22
23
# File 'lib/markita/markdown/horizontal_rule.rb', line 16

def horizontal_rule
  return false unless HorizontalRule::RGX.match?(@line)

  line_gets
  # Display HR
  @html << "<hr#{@attributes.shift}>\n"
  true
end

#html_markupObject



15
16
17
18
19
20
21
# File 'lib/markita/markdown/markup.rb', line 15

def html_markup
  return false unless Markup::RGX.match(@line)

  @html << @line
  line_gets
  true
end

#imagesObject

category: method :reek:TooManyStatements



50
51
52
53
54
55
56
57
58
# File 'lib/markita/markdown/image.rb', line 50

def images
  return false unless (alt, src, href = Image.attributes(@line))

  @html << %(<a href="#{href}">\n) if href
  @html << Image.img_src(src, alt, @attributes)
  @html << %(</a>\n) if href
  line_gets
  true
end

#init(line_getter) ⇒ Object

init(fh: String || File) -> void



29
30
31
32
# File 'lib/markita/markdown.rb', line 29

def init(line_getter)
  @line_getter = Preprocess.new(line_getter)
  @html = String.new
end

#inline(line) ⇒ Object

:reek:DuplicateMethodCall :reek:TooManyStatements



112
113
114
115
116
117
118
119
120
121
# File 'lib/markita/markdown/inline.rb', line 112

def inline(line)
  line = Inline.tags(line)
  line = Inline.tag(line, /[$](\w+)/, lambda do |mdt|
    @metadata[mdt[1]] || mdt[0]
  end)
  Inline.tag(line, /<a href="(\d+)">/, lambda do |mdt|
    key = mdt[1]
    %(<a href="#{@metadata[key] || key}">)
  end)
end

#line_getsObject



71
# File 'lib/markita/markdown.rb', line 71

def line_gets = @line = @line_getter.gets

#listObject

category: method :reek:DuplicateMethodCall :reek:TooManyStatements rubocop:disable Metrics/MethodLength rubocop:disable Metrics/AbcSize



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/markita/markdown/list.rb', line 44

def list
  return false unless (level, bullet, text = List.level_bullet_text(@line))

  type = List.type(bullet)
  @html << "<#{type}#{@attributes.shift}>\n"
  loop do
    style = List.style(bullet[3])
    @html << "  <li#{style}>#{inline(text)}</li>\n"
    current, bullet, text = List.level_bullet_text(line_gets)
    if current&.>(level)
      list
      current, bullet, text = List.level_bullet_text(@line)
    end
    break unless current.eql?(level) && type.eql?(List.type(bullet))
  end
  @html << "</#{type}>\n"
  true
end

#markdown(string) ⇒ Object



51
52
53
54
# File 'lib/markita/markdown.rb', line 51

def markdown(string)
  parse StringIO.new string
  @html
end

#parse(line_getter) ⇒ Object



39
40
41
42
43
44
# File 'lib/markita/markdown.rb', line 39

def parse(line_getter)
  init(line_getter)
  start
  parsers_detect or default while @line
  finish
end

#parsers_detectObject



56
# File 'lib/markita/markdown.rb', line 56

def parsers_detect = @@parsers.detect { method(it).call }

#scriptObject

:reek:TooManyStatements :reek:DuplicateMethodCall



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/markita/markdown/script.rb', line 16

def script
  return false unless Script::RGX.match(@line)

  @html << @line
  while line_gets
    @html << @line
    break if %r{^</script>}.match?(@line)
  end
  line_gets if @line
  true
end

#splitsObject

category: method



30
31
32
33
34
35
36
# File 'lib/markita/markdown/split.rb', line 30

def splits
  return false unless Split::RGX.match? @line

  @html << Split.table(@line.chomp, @attributes)
  line_gets
  true
end

#startObject



34
35
36
37
# File 'lib/markita/markdown.rb', line 34

def start
  @html << Html.header(@title)
  @line = Html.navigation
end

#tableObject

:reek:DuplicateMethodCall :reek:TooManyStatements :reek:UncommunicativeVariableName rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity rubocop:disable Metrics/MethodLength, Layout/LineLength



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/markita/markdown/table.rb', line 19

def table
  return false unless Table::RGX.match? @line

  @html << "<table#{@attributes.shift}>\n"
  @html << "<thead#{@attributes.shift}><tr><th>"
  @html << @line[1...-1].split('|').map { inline(it.strip) }.join('</th><th>')
  @html << "</th></tr></thead>\n"
  align = []
  while line_gets&.match? Table::RGX
    @html << '<tr>'
    @line[1...-1].split('|').each_with_index do |cell, i|
      case cell
      when /^\s*:-+:\s*$/
        align[i] = ' align="center"'
        @html << '<td><hr></td>'
      when /^\s*-+:\s*$/
        align[i] = ' align="right"'
        @html << '<td><hr></td>'
      when /^\s*:-+\s*$/
        align[i] = ' align="left"'
        @html << '<td><hr></td>'
      else
        @html << "<td#{align[i]}>#{inline(cell.strip)}</td>"
      end
    end
    @html << "</tr>\n"
  end
  @html << "</table>\n"
  true
end