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 = {
'&' => '&',
'<' => '<',
'>' => '>',
}.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
|