Created
August 11, 2011 13:11
-
-
Save stevedonovan/1139607 to your computer and use it in GitHub Desktop.
Script to convert Markdown source with code blocks into syntax-highlighted HTML.
This file contains 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
-- translate Markdown with code blocks into HTML | |
-- with syntax highlighting. | |
-- If article.md was the source, Lua was the language and we | |
-- wanted a preview: | |
-- lua prettify.lua article lua preview | |
-- Without the last argument it will just write out the HTML body. | |
-- Languages supported are 'lua', 'cpp', 'java' and 'go | |
-- Indented code blocks may begin with an explicit @lang name line; | |
-- if you do this then mark every code block explicitly | |
-- e.g | |
-- @lang lua | |
-- print "hello world" | |
-- | |
-- (any line) | |
-- | |
-- @lang go | |
-- fnt.Println("hello world" | |
-- | |
-- Needs markdown.lua and Penlight. | |
-- Steve Donovan, 2011 MIT license. | |
require 'pl' | |
require 'markdown' | |
local tnext = lexer.skipws | |
local concat = table.concat | |
local escaped_chars = { | |
['&'] = '&', | |
['<'] = '<', | |
['>'] = '>', | |
} | |
local escape_pat = '[&<>]' | |
local function escape(str) | |
return (str:gsub(escape_pat,escaped_chars)) | |
end | |
local function span(t,val) | |
return ('<span class="%s">%s</span>'):format(t,val) | |
end | |
local spans = {keyword=true,number=true,string=true,comment=true} | |
local jkeywords = { | |
final = true, extends = true, implements = true, | |
interface = true, import = true, throws = true, null = true | |
} | |
local gkeywords = { byte=true,chan=true,complex64=true, | |
complex128=true,defer=true,func=true,fallthrough=true, | |
float32=true,float64=true,string=true,uint=true,uintptr=true, | |
uint8=true,uint16=true,uint32=true,uint64=true, | |
var=true,len=true,map=true,package=true,range=true,select=true, | |
type=true,interface=true,int8=true,int16=true,int32=true, | |
int64=true,['nil']=true,func=true | |
} | |
local function prettify (code,lang) | |
local res = List() | |
res:append '<pre>\n' | |
local xkeywords = {} | |
local scanner | |
if lang == 'java' then | |
lang = 'cpp' | |
xkeywords = jkeywords | |
elseif lang == 'go' then | |
lang = 'cpp' | |
xkeywords = gkeywords | |
end | |
local tok = lexer[lang](code,{},{}) | |
local t,val = tok() | |
if not t then return nil,"empty file" end | |
while t do | |
val = escape(val) | |
if xkeywords[val] then | |
t = 'keyword' | |
end | |
if spans[t] then | |
res:append(span(t,val)) | |
else | |
res:append(val) | |
end | |
t,val = tok() | |
end | |
res:append '</pre>\n' | |
return res:join () | |
end | |
local function indent_line (line) | |
line = line:gsub('\t',' ') -- support for barbarians ;) | |
local indent = #line:match '^%s*' | |
return indent,line | |
end | |
function prettify_code_blocks (txt,lang) | |
local res, append = {}, table.insert | |
local getline = stringx.lines(txt) | |
local line = getline() | |
local indent,code,start_indent | |
while line do | |
indent,line = indent_line(line) | |
if indent >= 4 then -- indented code block | |
code = {} | |
while indent >= 4 do | |
if not start_indent then start_indent = indent end | |
append(code,line:sub(start_indent)) | |
line = getline() | |
if line == nil then break end | |
indent,line = indent_line(line) | |
end | |
code = concat(code,'\n') | |
local llang = code:match('^%s*@lang (%a+)') | |
if llang then | |
lang = llang | |
code = code:gsub('%s*@lang%s+%a+\n','') | |
end | |
code = prettify(code,lang) | |
append(res,code) | |
start_indent = nil | |
end | |
append(res,line) | |
line = getline() | |
end | |
return concat(res,'\n') | |
end | |
local function remove_spurious_lines (txt) | |
return txt:gsub('</p>%s*','</p>\n'):gsub('</pre>%s*','</pre>\n') | |
end | |
if #arg == 0 then | |
return print("markdown-file-without-extension language (preview)") | |
end | |
name = arg[1] | |
lang = arg[2] or 'lua' | |
preview = arg[3] | |
preamble = [[ | |
<html> | |
<head> | |
<style type="text/css"> | |
.keyword {font-weight: bold; color: #6666AA; } | |
.number { color: #AA6666; } | |
.string { color: #8888AA; } | |
.comment { color: #666600; } | |
pre { font-weight: bold; } | |
</style> | |
</head> | |
<body> | |
]] | |
coda = [[ | |
</body></html> | |
]] | |
text = utils.readfile(name..'.md') | |
text = prettify_code_blocks(text,lang) | |
text = markdown(text) | |
text = remove_spurious_lines(text) | |
if preview then | |
text = preamble .. text .. coda | |
end | |
utils.writefile(name..'.html',text) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment