Created
July 16, 2011 17:28
-
-
Save lancejpollard/1086568 to your computer and use it in GitHub Desktop.
Kramdown+Albino(Pygments)でハイライト
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "rubygems" | |
require "kramdown" | |
require "albino" | |
class Kramdown::Parser::AlbinoKramdown < Kramdown::Parser::Kramdown | |
def replace_code(code, ptrn, f = false) | |
if /\A\|(.+?)(!?)\|(?!\Z)/ =~ code then | |
lang = $1 | |
run = $2 | |
code.sub!(/\A\|.+?(!?)\|\n?/, "") | |
@src.scan(ptrn) if ptrn | |
if lang != "none" | |
pcode = Albino.new(code, lang, :html).colorize | |
pcode.sub!(/\A<div class="highlight"><pre>/, (f ? "<code class=\"highlight\" data-lang=\"#{lang}\">":"<pre class=\"highlight\"><code data-lang=\"#{lang}\">")) | |
pcode.sub!(/\n?<\/pre>\n?<\/div>\Z/, (f ? "</code>":"</code></pre>")) | |
@src.string.insert(@src.pos, pcode) | |
else | |
if f | |
@src.string.insert(@src.pos, "`"+code+"`") | |
else | |
@src.string.insert(@src.pos, "\n~~~\n"+code.chomp+"\n~~~") | |
end | |
return false | |
end | |
true | |
else | |
false | |
end | |
end | |
def parse_codeblock | |
data = @src.check(CODEBLOCK_MATCH) | |
data.gsub!(/\n( {0,3}\S)/, ' \1') | |
data.gsub!(INDENT, '') | |
replace_code(data,CODEBLOCK_MATCH) || super | |
end | |
def parse_codeblock_fenced | |
if @src.check(FENCED_CODEBLOCK_MATCH) | |
#@src.scan(FENCED_CODEBLOCK_MATCH) | |
replace_code(@src[2], FENCED_CODEBLOCK_MATCH) || super | |
else | |
false | |
end | |
end | |
def parse_codespan | |
f = @src.pos | |
result = @src.scan(CODESPAN_DELIMITER) | |
simple = (result.length == 1) | |
reset_pos = @src.pos | |
if simple && @src.pre_match =~ /\s\Z/ && @src.match?(/\s/) | |
add_text(result) | |
return | |
end | |
if text = @src.scan_until(/#{result}/) | |
text.sub!(/#{result}\Z/, "") | |
if !simple | |
text = text[1..-1] if text[0..0] == " " | |
text = text[0..-2] if text[-1..-1] == " " | |
end | |
unless replace_code(text,nil,true) | |
@src.pos = f | |
super | |
else | |
true | |
end | |
else | |
@src.pos = reset_pos | |
add_text(result) | |
end | |
end | |
end | |
Kramdown::Options.define(:id, String, "", "id") do |s| | |
s.gsub(/([^0-9A-Za-z]|:)/,"_") | |
end | |
class Kramdown::Parser::HebologKramdown < Kramdown::Parser::AlbinoKramdown | |
def initialize(source, options) | |
@id = options[:id] | |
super | |
@span_parsers.delete(:smart_quotes) | |
@span_parsers.delete(:parse_typographic_syms) | |
end | |
def parse_footnote_definition | |
@src.pos += @src.matched_size | |
el = Element.new(:footnote_def) | |
parse_blocks(el, @src[2].gsub(INDENT, '')) | |
warning("Duplicate footnote name '#{@src[1]}' - overwriting") if @footnotes[@id+":"+@src[1]] | |
(@footnotes[@id+":"+@src[1]] = {})[:content] = el | |
@tree.children << Element.new(:eob, :footnote_def) | |
true | |
end | |
def parse_footnote_marker | |
@src.pos += @src.matched_size | |
fn_def = @footnotes[@id+":"+@src[1]] | |
if fn_def | |
valid = fn_def[:marker] && fn_def[:stack][0..-2].zip(fn_def[:stack][1..-1]).all? do |par, child| | |
par.children.include?(child) | |
end | |
if !fn_def[:marker] || !valid | |
fn_def[:marker] = Element.new(:footnote, fn_def[:content], nil, :name => @id+":"+@src[1]) | |
fn_def[:stack] = [@stack.map {|s| s.first}, @tree, fn_def[:marker]].flatten.compact | |
@tree.children << fn_def[:marker] | |
else | |
warning("Footnote marker '#{@src[1]}' already appeared in document, ignoring newly found marker") | |
add_text(@src.matched) | |
end | |
else | |
warning("Footnote definition for '#{@src[1]}' not found") | |
add_text(@src.matched) | |
end | |
end | |
def parse_link | |
result = @src.scan(LINK_START) | |
reset_pos = @src.pos | |
link_type = (result =~ /^!/ ? :img : :a) | |
# no nested links allowed | |
if link_type == :a && (@tree.type == :img || @tree.type == :a || @stack.any? {|t,s| t && (t.type == :img || t.type == :a)}) | |
add_text(result) | |
return | |
end | |
el = Element.new(link_type) | |
count = 1 | |
found = parse_spans(el, LINK_BRACKET_STOP_RE) do | |
count = count + (@src[1] ? -1 : 1) | |
count - el.children.select {|c| c.type == :img}.size == 0 | |
end | |
if !found || (link_type == :a && el.children.empty?) | |
@src.pos = reset_pos | |
add_text(result) | |
return | |
end | |
alt_text = extract_string([email protected], @src) | |
@src.scan(LINK_BRACKET_STOP_RE) | |
# reference style link or no link url | |
if @src.scan(LINK_INLINE_ID_RE) || [email protected](/\(/) | |
link_id = normalize_link_id(@src[1] || alt_text) | |
if @link_defs.has_key?(link_id) | |
add_link(el, @link_defs[link_id].first, @link_defs[link_id].last, alt_text) | |
elsif link_id.match(/^post:(\d+)$/) | |
postid = $1.to_i | |
post = Post.find(postid) | |
el.children.last.value = post.title.chomp if alt_text==link_id | |
add_link(el, Baseurl + "/#{postid}", post.title.chomp) | |
elsif link_id.match(/^tag:(.+)$/) | |
tagname = $1 | |
el.children.last.value = $1 if alt_text==link_id | |
add_link(el, Baseurl + "/tag/#{CGI.escape(tagname)}", CGI.escapeHTML(tagname)) | |
else | |
warning("No link definition for link ID '#{link_id}' found") | |
@src.pos = reset_pos | |
add_text(result) | |
end | |
return | |
end | |
# link url in parentheses | |
if @src.scan(/\(<(.*?)>/) | |
link_url = @src[1] | |
if @src.scan(/\)/) | |
add_link(el, link_url, nil, alt_text) | |
return | |
end | |
else | |
link_url = '' | |
nr_of_brackets = 0 | |
while temp = @src.scan_until(LINK_PAREN_STOP_RE) | |
link_url << temp | |
if @src[2] | |
nr_of_brackets -= 1 | |
break if nr_of_brackets == 0 | |
elsif @src[1] | |
nr_of_brackets += 1 | |
else | |
break | |
end | |
end | |
link_url = link_url[1..-2] | |
link_url.strip! | |
if nr_of_brackets == 0 | |
add_link(el, link_url, nil, alt_text) | |
return | |
end | |
end | |
if @src.scan(LINK_INLINE_TITLE_RE) | |
add_link(el, link_url, @src[2], alt_text) | |
else | |
@src.pos = reset_pos | |
add_text(result) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment