Add web.html.[un]escape

This commit is contained in:
Lars Mueller 2022-01-04 13:42:46 +01:00
parent ba4ce3254b
commit 005be9fbf5
4 changed files with 57 additions and 0 deletions

19
build/html_entities.lua Normal file

@ -0,0 +1,19 @@
-- Generate lookup table for HTML entities out of https://html.spec.whatwg.org/entities.json
-- Requires https://github.com/brunoos/luasec to fetch the JSON
local https = require 'ssl.https'
local res, code = https.request"https://html.spec.whatwg.org/entities.json"
assert(code == 200)
local entity_map = {}
for entity, chars in pairs(assert(modlib.json:read_string(res))) do
entity_map[entity:sub(2, #entity - 1)] = table.concat(modlib.table.map(chars.codepoints, modlib.text.utf8))
end
local entries = {}
for entity, chars in pairs(entity_map) do
table.insert(entries, ("[%q] = %q"):format(entity, chars))
end
local serialized = [[-- HTML entity lookup table generated by build/html_entities.lua. Do not edit.
return {]] .. table.concat(entries, ", ") .. "}"
local loaded = assert(loadstring(serialized))
setfenv(loaded, {})
assert(modlib.table.equals(entity_map, loaded()))
modlib.file.write(modlib.mod.get_resource("modlib", "web", "html", "entities.lua"), serialized)

@ -153,6 +153,8 @@ if minetest then
modlib.conf.build_setting_tree() modlib.conf.build_setting_tree()
end end
-- Run build scripts
-- dofile(modlib.mod.get_resource("modlib", "build", "html_entities.lua"))
--[[ --[[
--modlib.mod.include"test.lua" --modlib.mod.include"test.lua"

@ -324,6 +324,14 @@ do
end) end)
end end
do
local text = "<tag> & '\""
local escaped = web.html.escape(text)
assert(web.html.unescape(escaped) == text)
assert(web.html.unescape("&#42;") == _G.string.char(42))
assert(web.html.unescape("&#x42;") == _G.string.char(0x42))
end
if not _G.minetest then return end if not _G.minetest then return end
assert(minetest.luon:read_string(minetest.luon:write_string(ItemStack""))) assert(minetest.luon:read_string(minetest.luon:write_string(ItemStack"")))

28
web.lua Normal file

@ -0,0 +1,28 @@
-- TODO incorporate https://github.com/minetest/minetest/pull/11578
return {
html = setmetatable({
escape = function(text)
return text:gsub(".", {
["<"] = "&lt;",
[">"] = "&gt;",
["&"] = "&amp;",
["'"] = "&apos;",
['"'] = "&quot;",
})
end
}, {__index = function(self, key)
if key == "unescape" then
local func = assert(loadfile(modlib.mod.get_resource("modlib", "web", "html", "entities.lua")))
setfenv(func, {})
local named_entities = assert(func())
local function unescape(text)
return text
:gsub("&([A-Za-z]+);", named_entities) -- named
:gsub("&#(%d+);", function(digits) return modlib.text.utf8(tonumber(digits)) end) -- decimal
:gsub("&#x(%x+);", function(digits) return modlib.text.utf8(tonumber(digits, 16)) end) -- hex
end
self.unescape = unescape
return unescape
end
end})
}