Skip to content

Instantly share code, notes, and snippets.

@lancejpollard
Created July 16, 2011 17:28
Show Gist options
  • Save lancejpollard/1086568 to your computer and use it in GitHub Desktop.
Save lancejpollard/1086568 to your computer and use it in GitHub Desktop.
Kramdown+Albino(Pygments)でハイライト
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(reset_pos...@src.pos, @src)
@src.scan(LINK_BRACKET_STOP_RE)
# reference style link or no link url
if @src.scan(LINK_INLINE_ID_RE) || !@src.check(/\(/)
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