File: html.rb

package info (click to toggle)
ruby-rouge 4.6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,836 kB
  • sloc: ruby: 38,168; sed: 2,071; perl: 152; makefile: 8
file content (57 lines) | stat: -rw-r--r-- 1,578 bytes parent folder | download | duplicates (2)
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
# -*- coding: utf-8 -*- #
# frozen_string_literal: true

module Rouge
  module Formatters
    # Transforms a token stream into HTML output.
    class HTML < Formatter
      TABLE_FOR_ESCAPE_HTML = {
        '&' => '&amp;',
        '<' => '&lt;',
        '>' => '&gt;',
      }.freeze

      ESCAPE_REGEX = /[&<>]/.freeze

      tag 'html'

      # @yield the html output.
      def stream(tokens, &b)
        tokens.each { |tok, val| yield span(tok, val) }
      end

      def span(tok, val)
        return val if escape?(tok)

        safe_span(tok, escape_special_html_chars(val))
      end

      def safe_span(tok, safe_val)
        if tok == Token::Tokens::Text
          safe_val
        else
          shortname = tok.shortname or raise "unknown token: #{tok.inspect} for #{safe_val.inspect}"

          "<span class=\"#{shortname}\">#{safe_val}</span>"
        end
      end

      private

      # A performance-oriented helper method to escape `&`, `<` and `>` for the rendered
      # HTML from this formatter.
      #
      # `String#gsub` will always return a new string instance irrespective of whether
      # a substitution occurs. This method however invokes `String#gsub` only if
      # a substitution is imminent.
      #
      # Returns either the given `value` argument string as is or a new string with the
      # special characters replaced with their escaped counterparts.
      def escape_special_html_chars(value)
        return value unless value =~ ESCAPE_REGEX

        value.gsub(ESCAPE_REGEX, TABLE_FOR_ESCAPE_HTML)
      end
    end
  end
end