Ian Maxon | d9e597c | 2015-10-16 18:48:06 -0700 | [diff] [blame^] | 1 | # We define the an additional option for the kramdown parser to look for |
| 2 | module Kramdown |
| 3 | module Options |
| 4 | define(:kramdown_default_lang, Symbol, nil, <<EOF) |
| 5 | Sets the default language for highlighting code blocks |
| 6 | |
| 7 | If no language is set for a code block, the default language is used |
| 8 | instead. The value has to be one of the languages supported by pygments |
| 9 | or nil if no default language should be used. |
| 10 | |
| 11 | Default: nil |
| 12 | Used by: PygmentsHtml converter |
| 13 | EOF |
| 14 | end |
| 15 | end |
| 16 | |
| 17 | # This class is a plugin for kramdown, to make it use pygments instead of coderay |
| 18 | # It has nothing to do with Jekyll, it is simply used by the custom converter below |
| 19 | module Kramdown |
| 20 | module Converter |
| 21 | class PygmentsHtml < Html |
| 22 | |
| 23 | begin |
| 24 | require 'pygments' |
| 25 | rescue LoadError |
| 26 | STDERR.puts 'You are missing a library required for syntax highlighting. Please run:' |
| 27 | STDERR.puts ' $ [sudo] gem install pygments' |
| 28 | raise FatalException.new("Missing dependency: Pygments") |
| 29 | end |
| 30 | |
| 31 | def convert_codeblock(el, indent) |
| 32 | attr = el.attr.dup |
| 33 | lang = extract_code_language!(attr) || @options[:kramdown_default_lang] |
| 34 | code = pygmentize(el.value, lang) |
| 35 | code_attr = {} |
| 36 | code_attr['class'] = "language-#{lang}" if lang |
| 37 | "#{' '*indent}<div class=\"highlight\"><pre#{html_attributes(attr)}><code#{html_attributes(code_attr)}>#{code}</code></pre></div>\n" |
| 38 | end |
| 39 | |
| 40 | def convert_codespan(el, indent) |
| 41 | attr = el.attr.dup |
| 42 | lang = extract_code_language!(attr) || @options[:kramdown_default_lang] |
| 43 | code = pygmentize(el.value, lang) |
| 44 | if lang |
| 45 | attr['class'] = "highlight" |
| 46 | if attr.has_key?('class') |
| 47 | attr['class'] += " language-#{lang}" |
| 48 | else |
| 49 | attr['class'] = "language-#{lang}" |
| 50 | end |
| 51 | end |
| 52 | "<code#{html_attributes(attr)}>#{code}</code>" |
| 53 | end |
| 54 | |
| 55 | def pygmentize(code, lang) |
| 56 | if lang |
| 57 | Pygments.highlight(code, |
| 58 | :lexer => lang, |
| 59 | :options => { :startinline => true, :encoding => 'utf-8', :nowrap => true }) |
| 60 | else |
| 61 | escape_html(code) |
| 62 | end |
| 63 | end |
| 64 | end |
| 65 | end |
| 66 | end |
| 67 | |
| 68 | # This class is the actual custom Jekyll converter. |
| 69 | class Jekyll::Converters::Markdown::KramdownPygments |
| 70 | |
| 71 | def initialize(config) |
| 72 | require 'kramdown' |
| 73 | @config = config |
| 74 | rescue LoadError |
| 75 | STDERR.puts 'You are missing a library required for Markdown. Please run:' |
| 76 | STDERR.puts ' $ [sudo] gem install kramdown' |
| 77 | raise FatalException.new("Missing dependency: kramdown") |
| 78 | end |
| 79 | |
| 80 | def convert(content) |
| 81 | html = Kramdown::Document.new(content, { |
| 82 | :auto_ids => @config['kramdown']['auto_ids'], |
| 83 | :footnote_nr => @config['kramdown']['footnote_nr'], |
| 84 | :entity_output => @config['kramdown']['entity_output'], |
| 85 | :toc_levels => @config['kramdown']['toc_levels'], |
| 86 | :smart_quotes => @config['kramdown']['smart_quotes'], |
| 87 | :kramdown_default_lang => @config['kramdown']['default_lang'], |
| 88 | :input => @config['kramdown']['input'] |
| 89 | }).to_pygments_html |
| 90 | return html; |
| 91 | end |
| 92 | end |