Skip to content

Commit

Permalink
added sanitize, added node list render as table
Browse files Browse the repository at this point in the history
  • Loading branch information
shahrul committed Oct 20, 2024
1 parent fb2b748 commit a7e936c
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 84 deletions.
6 changes: 3 additions & 3 deletions .rockspec
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package = "luax"
version = "1.0.8-1"
version = "1.1.0-1"

source = {
url = "https://github.com/syarul/luax/archive/refs/tags/v1.0.8.tar.gz",
dir = "luax-1.0.8"
url = "https://github.com/syarul/luax/archive/refs/tags/v1.1.0.tar.gz",
dir = "luax-1.1.0"
}
description = {
summary = "HTML parse in Lua",
Expand Down
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

LuaX is Lua + XML Syntax extension with built-in decent parse. In retrospect it's akin to React JSX.

<a href="https://luarocks.org/modules/syarul/luax" rel="nofollow"><img alt="Luarocks Package" src="https://img.shields.io/badge/Luarocks-1.0.8-blue.svg" style="max-width:100%;"></a>
<a href="https://luarocks.org/modules/syarul/luax" rel="nofollow"><img alt="Luarocks Package" src="https://img.shields.io/badge/Luarocks-1.1.0-blue.svg" style="max-width:100%;"></a>
[![Lua CI](https://github.com/syarul/luax/actions/workflows/lua.yml/badge.svg)](https://github.com/syarul/luax/actions/workflows/lua.yml)

## Decent Parser
Expand Down Expand Up @@ -67,18 +67,17 @@ local filters = {
{ url = "#/completed", name = "Completed", selected = false },
}

local content = table.concat(map(filters, function(filter)
-- convert to string
return h(<li>
local content = map(filters, function(filter)
return <li>
<a
class={filter.selected and 'selected' or nil}
href={filter.url}
_="on click add .selected to me"
>
{filter.name}
</a>
</li>)
end), '\n')
</li>
end)

return <ul class="filters" _="on load set $filter to me">
{content}
Expand Down
75 changes: 33 additions & 42 deletions examples/web-component/app/test.luax
Original file line number Diff line number Diff line change
@@ -1,44 +1,35 @@
return <!DOCTYPE html>
<html>
<head>
<style>
button {
background-color: red;
display: block;
margin-top: 8px;
}
local function map(a, fcn)
local b = {}
for _, v in ipairs(a) do
table.insert(b, fcn(v))
end
return b
end

example-component::part(native) {
background-color: pink;
}
</style>
</head>
<body>
<example-component></example-component>
<button>Button in Light DOM</button>
<script>
// Use custom elements API v1 to register a new HTML tag and define its JS behavior
// using an ES6 class. Every instance of <fancy-tab> will have this same prototype.
customElements.define('example-component', class extends HTMLElement {
constructor() {
super(); // always call super() first in the constructor.
local filters = {
{ url = "#/", name = "All", selected = true },
{ url = "#/active", name = "Active", selected = false },
{ url = "#/completed", name = "Completed", selected = false },
}

// Attach a shadow root to <fancy-tabs>.
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `
<style>
div {
height: 150px;
width: 150px;
border: solid 2px;
}
</style>

<div part="native"></div>
<button>Button in Shadow DOM</button>
`;
}
});
</script>
</body>
</html>
local function list_filter(filter)
return <li>
<a
class={filter.selected and 'selected' or nil}
href={filter.url}
_="on click add .selected to me"
>
{filter.name or nil}
</a>
</li>
end

local content = map(filters, list_filter)

return <html>
<head>
</head>
<body>
{content}
</body>
</html>
9 changes: 1 addition & 8 deletions examples/web-component/server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,6 @@ local function get_headers(client, headers)
end
end

-- local function sanitize_text(str)
-- return (str:gsub("[<>&]", {
-- ["<"] = "&lt;",
-- [">"] = "&gt;",
-- ["&"] = "&amp;"
-- }))
-- end

local function render(client, status_code, body, custom_headers)
local header_string = "HTTP/1.1 " .. status_code .. "\r\n"
local headers = {
Expand Down Expand Up @@ -97,6 +89,7 @@ local function handler(client, request)
local parsed_url = url.parse(path)

if parsed_url.path == "/" then
-- printTable(app)
local html = h(app)
render(client, "200 OK", html)
elseif mimes[parsed_url.path:lower():match("[^.]*$")] and method == "GET" then
Expand Down
22 changes: 20 additions & 2 deletions h.lua
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,25 @@ setmetatable(_G, {
end
})

local function sanitize_value(str)
return (str:gsub("[<>&]", {
["<"] = "&lt;",
[">"] = "&gt;",
["&"] = "&amp;"
}))
end

local function h(element)
if type(element) ~= "table" then return element or "" end
local tkeys = {}
-- asume as nodeList
if type(element.atts) ~= "table" then
local node_list = {}
for _, k in ipairs(element) do
table.insert(node_list, h(k) or "")
end
return table.concat(node_list)
end
for k in pairs(element.atts) do table.insert(tkeys, k) end
if #tkeys then table.sort(tkeys) end
local atts = ""
Expand All @@ -72,7 +88,7 @@ local function h(element)
local v = element.atts[k]
if type(v) ~= "table" then
if k ~= "children" then
atts = atts .. " " .. k .. "=\"" .. v .. "\""
atts = atts .. " " .. k .. "=\"" .. sanitize_value(v) .. "\""
else
children = v
end
Expand All @@ -81,8 +97,10 @@ local function h(element)
for _, child in ipairs(element.children) do
if type(child) == "table" then
children = children .. h(child)
else
elseif element.tag == "script" then
children = children .. child
else
children = children .. sanitize_value(child)
end
end
if element.tag:lower() == "doctype" then
Expand Down
8 changes: 4 additions & 4 deletions test/17_table.luax
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ local function map(a, fcn)
end

function module.Filter(filters)
local content = table.concat(map(filters, function(filter)
return h(<li>
local content = map(filters, function(filter)
return <li>
<a
class={filter.selected and 'selected' or nil}
href={filter.url}
_="on click add .selected to me"
>
{filter.name or nil}
</a>
</li>)
end), '\n')
</li>
end)

return <ul class="filters" _="on load set $filter to me">
{content}
Expand Down
15 changes: 4 additions & 11 deletions test/18_filter.luax
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@

local h = require('luax')

local function map(a, fcn)
local b = {}
for _, v in ipairs(a) do
table.insert(b, fcn(v))
end
return b
end

local function fcn(filter)
return <li>
<a
Expand All @@ -22,9 +14,10 @@ local function fcn(filter)
end

local function list(filters)
local content = table.concat(map(filters, function(filter)
return h(fcn(filter))
end), '\n')
local content = {}
for _, filter in ipairs(filters) do
table.insert(content, fcn(filter))
end
return <ul class="todo-list">{content}</ul>
end

Expand Down
12 changes: 4 additions & 8 deletions test/test_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ describe("LuaX", function()
it("should return a HTML string when given input node", function()
local el = require("test.09_input2")
assert.is.equal(
'<input _="install TodoCheck" class="toggle" hx-patch="/toggle-todo?id=1&done=false" hx-swap="outerHTML" hx-target="closest <li/>" type="checkbox">',
'<input _="install TodoCheck" class="toggle" hx-patch="/toggle-todo?id=1&amp;done=false" hx-swap="outerHTML" hx-target="closest &lt;li/&gt;" type="checkbox">',
h(el))
end)

Expand All @@ -115,7 +115,7 @@ describe("LuaX", function()
it("should return a HTML string with deep node tree", function()
local el = require("test.12_test")
assert.is.equal(
[[<li _="on destroy my.querySelector('button').click()" class="test" id="1"><div class="view">todo A<label _="install TodoDblclick" hx-patch="/edit-todo?id=1&foo=test" hx-swap="outerHTML" hx-target="next input" hx-trigger="dblclick">todo A Label </label><button _="install Destroy" class="destroy" hx-delete="/remove-todo?id=1" hx-swap="outerHTML" hx-target="closest <li/>" hx-trigger="click"></button></div>todo A Value</li>]],
[[<li _="on destroy my.querySelector('button').click()" class="test" id="1"><div class="view">todo A<label _="install TodoDblclick" hx-patch="/edit-todo?id=1&amp;foo=test" hx-swap="outerHTML" hx-target="next input" hx-trigger="dblclick">todo A Label </label><button _="install Destroy" class="destroy" hx-delete="/remove-todo?id=1" hx-swap="outerHTML" hx-target="closest &lt;li/&gt;" hx-trigger="click"></button></div>todo A Value</li>]],
h(el))
end)

Expand All @@ -137,16 +137,12 @@ describe("LuaX", function()

it("should return a HTML string when given XML like syntax with table concat", function()
local el = require("test.17_table")
assert.is.equal([[<ul _="on load set $filter to me" class="filters"><li><a _="on click add .selected to me" class="selected" href="#/">All </a> </li>
<li><a _="on click add .selected to me" href="#/active">Active </a> </li>
<li><a _="on click add .selected to me" href="#/completed">Completed </a> </li> </ul>]], h(el.Filter(filters)))
assert.is.equal([[<ul _="on load set $filter to me" class="filters"><li><a _="on click add .selected to me" class="selected" href="#/">All </a> </li><li><a _="on click add .selected to me" href="#/active">Active </a> </li><li><a _="on click add .selected to me" href="#/completed">Completed </a> </li> </ul>]], h(el.Filter(filters)))
end)

it("should return a HTML string when given XML like syntax with table concat", function()
local el = require("test.18_filter")
assert.is.equal([[<ul class="todo-list"><li><a _="on click add .selected to me" class="selected" href="#/">All </a> </li>
<li><a _="on click add .selected to me" href="#/active">Active </a> </li>
<li><a _="on click add .selected to me" href="#/completed">Completed </a> </li></ul>]], h(el(filters)))
assert.is.equal([[<ul class="todo-list"><li><a _="on click add .selected to me" class="selected" href="#/">All </a> </li><li><a _="on click add .selected to me" href="#/active">Active </a> </li><li><a _="on click add .selected to me" href="#/completed">Completed </a> </li></ul>]], h(el(filters)))
end)

it("should return a HTML string when given XML like syntax with kebab-case tag", function()
Expand Down

0 comments on commit a7e936c

Please sign in to comment.