File: html.rb

package info (click to toggle)
ruby-rugments 1.0.0~beta8-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 820 kB
  • sloc: ruby: 10,293; makefile: 2
file content (138 lines) | stat: -rw-r--r-- 3,772 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
require 'cgi'

module Rugments
  module Formatters
    class HTML < Formatter
      tag('html')

      def initialize(
          nowrap: false,
          cssclass: 'highlight',
          linenos: nil,
          linenostart: 1,
          lineanchors: false,
          lineanchorsid: 'L',
          anchorlinenos: false,
          inline_theme: nil
        )
        @nowrap = nowrap
        @cssclass = cssclass
        @linenos = linenos
        @linenostart = linenostart
        @lineanchors = lineanchors
        @lineanchorsid = lineanchorsid
        @anchorlinenos = anchorlinenos
        @inline_theme = inline_theme
      end

      def format(tokens)
        case
        when @linenos == 'table'
          format_tableized(tokens)
        when @linenos == 'inline'
          format_untableized(tokens)
        else
          format_untableized(tokens)
        end
      end

      private

      def format_untableized(tokens)
        data = process_tokens(tokens)

        html = ''
        html << "<pre class=\"#{@cssclass}\"><code>" unless @nowrap
        html << create_lines(data[:code])
        html << "</code></pre>\n" unless @nowrap
        html
      end

      def format_tableized(tokens)
        data = process_tokens(tokens)

        html = ''
        html << "<div class=\"#{@cssclass}\">\n" unless @nowrap
        html << "<table><tbody>\n"
        html << "<td class=\"linenos\"><pre>"
        html << create_linenos(data[:numbers])
        html << "</pre></td>\n"
        html << "<td class=\"lines\"><pre><code>"
        html << create_lines(data[:code])
        html << "</code></pre></td>\n"
        html << "</tbody></table>\n"
        html << "</div>\n" unless @nowrap
      end

      def process_tokens(tokens)
        num_lines = 0
        last_val = ''
        formatted = ''

        tokens.each do |tok, val|
          last_val = val
          num_lines += val.scan(/\n/).size
          formatted << span(tok, val)
        end

        numbers = (@linenostart..num_lines + @linenostart - 1).to_a

        { numbers: numbers, code: formatted }
      end

      def create_linenos(numbers)
        if @anchorlinenos
          numbers.map! do |number|
            "<a href=\"##{@lineanchorsid}#{number}\">#{number}</a>"
          end
        end
        numbers.join("\n")
      end

      def create_lines(formatted)
        if @lineanchors
          lines = formatted.split("\n")
          lines = lines.each_with_index.map do |line, index|
            number = index + @linenostart

            if @linenos == 'inline'
              "<a name=\"L#{number}\"></a>" \
              "<span class=\"linenos\">#{number}</span><span id=\"#{@lineanchorsid}#{number}\" class=\"line\">#{line}</span>"
            else
              "<span id=\"#{@lineanchorsid}#{number}\" class=\"line\">#{line}</span>"
            end
          end
          lines.join("\n")
        else
          if @linenos == 'inline'
            lines = formatted.split("\n")
            lines = lines.each_with_index.map do |line, index|
              number = index + @linenostart
              "<span class=\"linenos\">#{number}</span>#{line}"
            end
            lines.join("\n")
          else
            formatted
          end
        end
      end

      def span(tok, val)
        # http://stackoverflow.com/a/1600584/2587286
        val = CGI.escapeHTML(val)

        if tok.shortname.empty?
          val
        else
          if @inline_theme
            theme = Theme.find(@inline_theme).new
            rules = theme.style_for(tok).rendered_rules
            "<span style=\"#{rules.to_a.join(';')}\">#{val}</span>"
          else
            "<span class=\"#{tok.shortname}\">#{val}</span>"
          end
        end
      end
    end
  end
end