Class: HTMLPipeline::NodeFilter::SyntaxHighlightFilter

Inherits:
HTMLPipeline::NodeFilter show all
Defined in:
lib/html_pipeline/node_filter/syntax_highlight_filter.rb

Overview

HTML Filter that syntax highlights text inside code blocks.

Context options:

:highlight => String represents the language to pick lexer. Defaults to empty string.
:scope => String represents the class attribute adds to pre element after.
          Defaults to "highlight highlight-css" if highlights a css code block.

This filter does not write any additional information to the context hash.

Constant Summary collapse

SELECTOR =
Selma::Selector.new(match_element: "pre", match_text_within: "pre")

Instance Attribute Summary

Attributes inherited from HTMLPipeline::NodeFilter

#context

Attributes inherited from Filter

#context, #result

Instance Method Summary collapse

Methods inherited from HTMLPipeline::NodeFilter

call, #html, #reset!

Methods inherited from Filter

#base_url, call, #call, #has_ancestor?, #needs, #validate

Constructor Details

#initialize(context: {}, result: {}) ⇒ SyntaxHighlightFilter

Returns a new instance of SyntaxHighlightFilter.



17
18
19
20
21
# File 'lib/html_pipeline/node_filter/syntax_highlight_filter.rb', line 17

def initialize(context: {}, result: {})
  super
  # TODO: test the optionality of this
  @formatter = context[:formatter] || Rouge::Formatters::HTML.new
end

Instance Method Details

#handle_element(element) ⇒ Object



29
30
31
32
33
34
35
36
# File 'lib/html_pipeline/node_filter/syntax_highlight_filter.rb', line 29

def handle_element(element)
  default = context[:highlight]&.to_s
  @lang = element["lang"] || default

  scope = context.fetch(:scope, "highlight")

  element["class"] = "#{scope} #{scope}-#{@lang}" if include_lang?
end

#handle_text_chunk(text) ⇒ Object



38
39
40
41
42
43
44
45
# File 'lib/html_pipeline/node_filter/syntax_highlight_filter.rb', line 38

def handle_text_chunk(text)
  return if @lang.nil?
  return if (lexer = lexer_for(@lang)).nil?

  content = text.to_s

  text.replace(highlight_with_timeout_handling(content, lexer), as: :html)
end

#highlight_with_timeout_handling(text, lexer) ⇒ Object



47
48
49
50
51
# File 'lib/html_pipeline/node_filter/syntax_highlight_filter.rb', line 47

def highlight_with_timeout_handling(text, lexer)
  Rouge.highlight(text, lexer, @formatter)
rescue Timeout::Error => _e
  text
end

#include_lang?Boolean

Returns:

  • (Boolean)


57
58
59
# File 'lib/html_pipeline/node_filter/syntax_highlight_filter.rb', line 57

def include_lang?
  !@lang.nil? && !@lang.empty?
end

#lexer_for(lang) ⇒ Object



53
54
55
# File 'lib/html_pipeline/node_filter/syntax_highlight_filter.rb', line 53

def lexer_for(lang)
  Rouge::Lexer.find(lang)
end

#selectorObject



25
26
27
# File 'lib/html_pipeline/node_filter/syntax_highlight_filter.rb', line 25

def selector
  SELECTOR
end