I decided it might be nice to be able to do stuff like copy-pasting some git diff
output into a Glorpdown file.
In Glorpdown, preformated text is written between lines starting with ```
. So:
```
if foo("this") then
bar("that")
end
```
Becomes:
if foo("this") then
bar("that")
end
That stuff is already "pluggable" through the opening ```
line. I'd like to be able to do stuff like:
``` diff
if foo("this") then
- bar("that")
+ baz("that")
end
```
And have that be rendered as fairly sensible HTML.
Some pre-existing code for HTML-escaping a string:
local escapechar = {
["<"] = "<",
[">"] = ">",
['"'] = """,
["'"] = "'",
["&"] = "&"
}
function escape(str)
local res, _ = (str or ""):gsub("[<>\"'&]", escapechar)
return res
end
HTML has del
and ins
elements. Those are good.
Glorpdown is pretty line-based and a function for turning a line of diff-text into a string of HTML would fit right in:
function diff(line)
if line == "" then return "" end
local op, rest = line:match("(.)(.*)")
rest = escape(rest)
if op == "+" then return "<ins>" .. rest .. "</ins>" end
if op == "-" then return "<del>" .. rest .. "</del>" end
return rest
end
Can test it:
local str = [[
if foo("this") then
- bar("that")
+ baz("that")
end
]]
for line in str:gmatch("[^\n]*") do print(diff(line)) end
Seems fine.
Every line should start with a plus, minus or space. If it does not start with plus or minus it is treated like a space line. If we put unindented lines of regular code in in diff blocks, the diff
function is mostly going to just eat the first characters the lines:
local str = [[
if foo("this") then
bar("that")
baz("that")
end
]]
for line in str:gmatch("[^\n]*") do print(diff(line)) end
That's okay.
I grabbed some colours and stuff from the del example at MDN:
del { text-decoration: line-through; background-color: #ffbbbb; color: #555555; }
ins { text-decoration: none; background-color: #d4fcbc; color: #000000; }
There's a helper function for handling code/preformatted text called prewriterf
. It takes a class
argument, for adding a CSS class to the pre
elements it will create, and it returns a function that the rendering code can use when dealing with ```
lines and the lines between them. I've added a new argument, linef
to it. I've no idea what is up with my naming conventions but linef
should be a function that turns a line of text into a string of HTML. It used to just HTML-escape
all lines of code, so if linef
is not supplied as an argument it will default to the escape
function.
local function prewriterf(class)
local function prewriterf(class, linef)
class = class and (' class="' .. class .. '"') or ""
linef = linef or escape
return function(url)
return function (line)
if line.type == "<pre" then
return "<figure><pre" .. class .. "><code>"
elseif line.type == "pre" then
return escape(line.rest)
return linef(line.rest)
elseif line.type == "prebr" then
return "\n"
elseif line.type == "pre>" then
local res = "</code></pre>"
if not line.empty then
local caption = escape(line.rest)
res = res .. "<figcaption>"
.. strhtml(caption, url) .. "</figcaption>"
end
return res .. "</figure>"
else
error("unreachable: " .. line.type)
end
end
end
end
And then it's like, putting prewriterf
and diff
together and making the thing available by adding it to a key of the table that's used for deciding what to do with ```
blocks:
local function basepre()
return {
diff = prewriterf(nil, diff),
drawing = newdrawing,
img = img,
html = function(url)
return function(line)
if line.type == "<pre" then return ""
elseif line.type == "pre" then return line.rest
elseif line.type == "prebr" then return "\n"
elseif line.type == "pre>" then return ""
else error("unreachable: " .. line.type)
end
end
end
}
end
So now:
``` diff
if foo("this") then
- bar("that")
+ baz("that")
end
```
Becomes:
if foo("this") then
bar("that")
baz("that")
end
Okay good.
Anyway I like being able to just do stuff like that. I'm sure it's all stupidly designed and badly coded, but it's my stupid and bad which is like a very relatable and understandable stupid and bad for me. And for small things, I really prefer just making it instead of doing stuff like finding out if the tools I'm using already support this kind of thing, if there's something I can/must configure, or maybe a plugin I can add or make make myself, or some something like that.
Blep.