Class: Marvi::Highlighter

Inherits:
Object
  • Object
show all
Defined in:
lib/marvi/highlighter.rb

Constant Summary collapse

DEFAULT_COLOR =
:white
FALLBACK_COLOR =
:green
TOKEN_COLOR_RULES =

Ordered so longer qualnames win over their prefixes (e.g. “Literal.String” before “Literal”).

[
  ["Comment", :cyan],
  ["Keyword", :yellow],
  ["Literal.String", :green],
  ["Literal.Number", :magenta],
  ["Literal", :magenta],
  ["Name.Function", :cyan],
  ["Name.Class", :cyan],
  ["Name.Namespace", :cyan],
  ["Name.Tag", :cyan],
  ["Name.Attribute", :cyan],
  ["Name.Decorator", :cyan],
  ["Name.Constant", :magenta],
  ["Name.Builtin", :magenta],
  ["Operator", :white],
  ["Punctuation", :white],
  ["Error", :magenta]
].freeze
COMMENT_PREFIX =
"Comment"

Class Method Summary collapse

Class Method Details

.comment?(token) ⇒ Boolean

Returns:

  • (Boolean)


76
77
78
79
# File 'lib/marvi/highlighter.rb', line 76

def self.comment?(token)
  qual = token.qualname
  qual == COMMENT_PREFIX || qual.start_with?("#{COMMENT_PREFIX}.")
end

.fallback(code, bg_color) ⇒ Object



45
46
47
# File 'lib/marvi/highlighter.rb', line 45

def self.fallback(code, bg_color)
  code.split("\n", -1).map { |line| [Span.new(text: line, color: FALLBACK_COLOR, bg_color: bg_color)] }
end

.lines(code, lang, bg_color: :dark) ⇒ Object



32
33
34
35
36
# File 'lib/marvi/highlighter.rb', line 32

def self.lines(code, lang, bg_color: :dark)
  lexer = resolve_lexer(lang)
  return fallback(code, bg_color) if lexer.nil?
  tokens_to_lines(lexer.lex(code), bg_color)
end

.resolve_lexer(lang) ⇒ Object



38
39
40
41
42
43
# File 'lib/marvi/highlighter.rb', line 38

def self.resolve_lexer(lang)
  return nil if lang.nil? || lang.empty?
  Rouge::Lexer.find(lang)
rescue
  nil
end

.token_color(token) ⇒ Object



68
69
70
71
72
73
74
# File 'lib/marvi/highlighter.rb', line 68

def self.token_color(token)
  qual = token.qualname
  TOKEN_COLOR_RULES.each do |prefix, color|
    return color if qual == prefix || qual.start_with?("#{prefix}.")
  end
  DEFAULT_COLOR
end

.tokens_to_lines(tokens, bg_color) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/marvi/highlighter.rb', line 49

def self.tokens_to_lines(tokens, bg_color)
  current = []
  lines = []
  tokens.each do |tok, val|
    color = token_color(tok)
    italic = comment?(tok)
    val.split("\n", -1).each_with_index do |part, idx|
      if idx > 0
        lines << current
        current = []
      end
      next if part.empty?
      current << Span.new(text: part, italic: italic, color: color, bg_color: bg_color)
    end
  end
  lines << current
  lines
end