Class: Nanoc::Filters::ColorizeSyntax
- Inherits:
-
Nanoc::Filter
- Object
- Context
- Nanoc::Filter
- Nanoc::Filters::ColorizeSyntax
- Defined in:
- lib/nanoc/filters/colorize_syntax.rb
Constant Summary
- DEFAULT_COLORIZER =
The default colorizer to use for a language if the colorizer for that language is not overridden.
:coderay
- SIMON_HIGHLIGHT_OPT_MAP =
{ wrap: '-W', include_style: '-I', line_numbers: '-l', }
Constants inherited from Nanoc::Filter
Nanoc::Filter::TMP_BINARY_ITEMS_DIR
Instance Attribute Summary
Attributes inherited from Nanoc::Filter
Instance Method Summary (collapse)
-
- (String) coderay(code, language, params = {})
private
Runs the code through CodeRay.
-
- (Object) coderay_postprocess(_language, element)
Wraps the element in.
-
- (String) dummy(code, language, params = {})
Returns the input itself, not performing any code highlighting.
-
- (Object) parse(content, klass, is_fullpage)
private
Parses the given content using the given class.
-
- (String) pygmentize(code, language, params = {})
private
Runs the content through pygmentize, the command-line frontend for Pygments.
-
- (String) pygmentsrb(code, language, params = {})
private
Runs the content through Pygments via pygments.rb.
-
- (String) rouge(code, language, params = {})
private
Runs the content through [Rouge](https://github.com/jayferd/rouge/..
-
- (Object) rouge_postprocess(_language, element)
Removes the double wrapping.
-
- (String) run(content, params = {})
Syntax-highlights code blocks in the given content.
-
- (String) simon_highlight(code, language, params = {})
private
Runs the content through Highlight.
Methods inherited from Nanoc::Filter
#depend_on, #filename, from_binary?, #initialize, #output_filename, requires, setup, #setup_and_run, to_binary?, type
Methods included from PluginRegistry::PluginMethods
#all, #identifier, #identifiers, #named, #register
Methods inherited from Context
Constructor Details
This class inherits a constructor from Nanoc::Filter
Instance Method Details
- (String) coderay(code, language, params = {})
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Runs the code through CodeRay.
185 186 187 188 189 |
# File 'lib/nanoc/filters/colorize_syntax.rb', line 185 def coderay(code, language, params = {}) require 'coderay' ::CodeRay.scan(code, language).html(params) end |
- (Object) coderay_postprocess(_language, element)
Wraps the element in <div class="CodeRay"><div class="code">
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/nanoc/filters/colorize_syntax.rb', line 298 def coderay_postprocess(_language, element) # Skip if we're a free <code> return if element.parent.nil? # <div class="code"> div_inner = Nokogiri::XML::Node.new('div', element.document) div_inner['class'] = 'code' div_inner.children = element.dup # <div class="CodeRay"> div_outer = Nokogiri::XML::Node.new('div', element.document) div_outer['class'] = 'CodeRay' div_outer.children = div_inner # orig element element.swap div_outer end |
- (String) dummy(code, language, params = {})
Returns the input itself, not performing any code highlighting.
199 200 201 |
# File 'lib/nanoc/filters/colorize_syntax.rb', line 199 def dummy(code, language, params = {}) # rubocop:disable Lint/UnusedMethodArgument code end |
- (Object) parse(content, klass, is_fullpage)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Parses the given content using the given class. This method also handles an issue with Nokogiri on JRuby causing “cannot modify frozen string” errors.
160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/nanoc/filters/colorize_syntax.rb', line 160 def parse(content, klass, is_fullpage) if is_fullpage klass.parse(content, nil, 'UTF-8') else klass.fragment(content) end rescue => e if e. =~ /can't modify frozen string/ parse(content.dup, klass, is_fullpage) else raise e end end |
- (String) pygmentize(code, language, params = {})
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Runs the content through pygmentize, the command-line frontend for Pygments.
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/nanoc/filters/colorize_syntax.rb', line 215 def pygmentize(code, language, params = {}) check_availability('pygmentize', '-V') params[:encoding] ||= 'utf-8' params[:nowrap] ||= 'True' cmd = ['pygmentize', '-l', language, '-f', 'html'] cmd << '-O' << params.map { |k, v| "#{k}=#{v}" }.join(',') unless params.empty? stdout = StringIO.new stderr = $stderr piper = Nanoc::Extra::Piper.new(stdout: stdout, stderr: stderr) piper.run(cmd, code) stdout.string end |
- (String) pygmentsrb(code, language, params = {})
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Runs the content through Pygments via pygments.rb.
242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/nanoc/filters/colorize_syntax.rb', line 242 def pygmentsrb(code, language, params = {}) require 'pygments' args = params.dup args[:lexer] ||= language args[:options] ||= {} args[:options][:encoding] ||= 'utf-8' args[:options][:nowrap] ||= 'True' Pygments.highlight(code, args) end |
- (String) rouge(code, language, params = {})
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Runs the content through [Rouge](https://github.com/jayferd/rouge/.
325 326 327 328 329 330 331 332 333 334 |
# File 'lib/nanoc/filters/colorize_syntax.rb', line 325 def rouge(code, language, params = {}) require 'rouge' = { css_class: params.fetch(:css_class, 'highlight'), } formatter = Rouge::Formatters::HTML.new() lexer = Rouge::Lexer.find_fancy(language, code) || Rouge::Lexers::PlainText formatter.format(lexer.lex(code)) end |
- (Object) rouge_postprocess(_language, element)
Removes the double wrapping.
Before:
<pre class="highlight"><code>
After:
<pre><code class="language-ruby highlight">
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
# File 'lib/nanoc/filters/colorize_syntax.rb', line 345 def rouge_postprocess(_language, element) return if element.name != 'pre' code1 = element.xpath('code').first return if code1.nil? pre = code1.xpath('pre').first return if pre.nil? code2 = pre.xpath('code').first return if code2.nil? code1.inner_html = code2.inner_html code1['class'] = [code1['class'], pre['class']].compact.join(' ') end |
- (String) run(content, params = {})
Syntax-highlights code blocks in the given content. Code blocks should
be enclosed in pre
elements that contain a code
element. The code
element should have an indication of the language the code is in. There
are two possible ways of adding such an indication:
-
A HTML class starting with
language-
and followed by the code language, as specified by HTML5. For example,<code class="language-ruby">
. -
A comment on the very first line of the code block in the format
#!language
wherelanguage
is the language the code is in. For example,#!ruby
.
Options for individual colorizers will be taken from the #run
options’ value for the given colorizer. For example, if the filter is
invoked with a :coderay => coderay_options_hash
option, the
coderay_options_hash
hash will be passed to the CodeRay colorizer.
Currently, the following colorizers are supported:
:coderay
for Coderay:pygmentize
for pygmentize, the command-line frontend for Pygments:pygmentsrb
for pygments.rb, a Ruby interface for Pygments:simon_highlight
for Highlight:rouge
for Rouge
Additional colorizer implementations are welcome!
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 139 140 141 142 143 144 145 |
# File 'lib/nanoc/filters/colorize_syntax.rb', line 85 def run(content, params = {}) Nanoc::Extra::JRubyNokogiriWarner.check_and_warn # Take colorizers from parameters @colorizers = Hash.new(params[:default_colorizer] || DEFAULT_COLORIZER) (params[:colorizers] || {}).each_pair do |language, colorizer| @colorizers[language] = colorizer end # Determine syntax (HTML or XML) syntax = params[:syntax] || :html case syntax when :html klass = Nokogiri::HTML when :xml, :xhtml klass = Nokogiri::XML else raise "unknown syntax: #{syntax.inspect} (expected :html or :xml)" end # Colorize doc = parse(content, klass, params.fetch(:is_fullpage, false)) selector = params[:outside_pre] ? 'code' : 'pre > code' doc.css(selector).each do |element| # Get language has_class = false language = nil if element['class'] # Get language from class match = element['class'].match(/(^| )language-([^ ]+)/) language = match[2] if match has_class = true if language else # Get language from comment line match = element.inner_text.strip.split[0].match(/^#!([^\/][^\n]*)$/) language = match[1] if match element.content = element.content.sub(/^#!([^\/][^\n]*)$\n/, '') if language end # Give up if there is no hope left next if language.nil? # Highlight raw = strip(element.inner_text) highlighted_code = highlight(raw, language, params) element.children = Nokogiri::HTML.fragment(strip(highlighted_code), 'utf-8') # Add language-something class unless has_class klass = element['class'] || '' klass << ' ' unless [' ', nil].include?(klass[-1, 1]) klass << "language-#{language}" element['class'] = klass end highlight_postprocess(language, element.parent) end method = "to_#{syntax}".to_sym doc.send(method, encoding: 'UTF-8') end |
- (String) simon_highlight(code, language, params = {})
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Runs the content through Highlight.
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/nanoc/filters/colorize_syntax.rb', line 273 def simon_highlight(code, language, params = {}) check_availability('highlight', '--version') cmd = ['highlight', '--syntax', language, '--fragment'] params.each do |key, _value| if SIMON_HIGHLIGHT_OPT_MAP[key] cmd << SIMON_HIGHLIGHT_OPT_MAP[key] else # TODO: allow passing other options case key when :style cmd << '--style' << params[:style] end end end stdout = StringIO.new stderr = $stderr piper = Nanoc::Extra::Piper.new(stdout: stdout, stderr: stderr) piper.run(cmd, code) stdout.string end |