{"id":47818711,"url":"https://github.com/byteface/luadom","last_synced_at":"2026-04-03T19:00:40.459Z","repository":{"id":343669962,"uuid":"1158767166","full_name":"byteface/luadom","owner":"byteface","description":"A tiny DOM-ish HTML builder for Lua","archived":false,"fork":false,"pushed_at":"2026-02-15T22:11:58.000Z","size":41,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-03-11T15:50:31.580Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/byteface.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-15T22:03:11.000Z","updated_at":"2026-02-17T07:05:13.000Z","dependencies_parsed_at":"2026-04-03T19:00:26.241Z","dependency_job_id":null,"html_url":"https://github.com/byteface/luadom","commit_stats":null,"previous_names":["byteface/luadom"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/byteface/luadom","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byteface%2Fluadom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byteface%2Fluadom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byteface%2Fluadom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byteface%2Fluadom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/byteface","download_url":"https://codeload.github.com/byteface/luadom/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/byteface%2Fluadom/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31371616,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T17:53:18.093Z","status":"ssl_error","status_checked_at":"2026-04-03T17:53:17.617Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-03T19:00:21.458Z","updated_at":"2026-04-03T19:00:40.440Z","avatar_url":"https://github.com/byteface.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# luadom\n\n[![LuaRocks](https://img.shields.io/luarocks/v/luadom/luadom?label=LuaRocks)](https://luarocks.org/modules/luadom/luadom)\n[![LuaRocks Downloads](https://img.shields.io/luarocks/dt/luadom/luadom?label=Downloads)](https://luarocks.org/modules/luadom/luadom)\n[![CI](https://github.com/byteface/luadom/actions/workflows/ci.yml/badge.svg)](https://github.com/byteface/luadom/actions/workflows/ci.yml)\n[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n[![Latest Tag](https://img.shields.io/github/v/tag/byteface/luadom?label=Tag)](https://github.com/byteface/luadom/tags)\n\nA tiny DOM-ish HTML builder for Lua inspired by [domonic](https://github.com/byteface/domonic). Build HTML with tag functions, props tables, and a DOM-style query API, then render to a string. This is server-side only.\n\n## Requirements\n\n- Lua 5.1+ (tested with 5.4)\n- LuaRocks (for packaging/publishing and examples)\n\n## Installing LuaRocks\n\nmacOS (Homebrew):\n\n```sh\nbrew install lua\nbrew install luarocks\n```\n\nLinux/Unix:\n\nUse the official LuaRocks install instructions (tarball build) from their site (the Quick Start section shows the current commands).\n\nWindows:\n\nUse the official LuaRocks Windows installer instructions.\n\nReference links:\n\n```text\nhttps://luarocks.org/\nhttps://formulae.brew.sh/formula/luarocks\nhttps://github.com/luarocks/luarocks/wiki/Installation-instructions-for-Windows/91bc512e3f7298e27ad1a8cbfab4c5075adf1187\n```\n\n## Quick Start\n\n1. From this folder, run the basic example:\n\n```sh\nlua examples/helloworld.lua\n```\n\n2. Open `index.html` to see the output.\n\n## Examples\n\n- Basic: `lua examples/helloworld.lua`\n- Full homepage showcase: `lua examples/homepage.lua`\n- More examples: see `examples/README.md`\n\nAll examples that render files write to `index.html` in the project root.\n\n## Examples (More)\n\nSee `examples/README.md` for runnable examples, including servers using LuaSocket, lua-http, and Lapis.\n\n## Usage\n\nMinimal example:\n\n```lua\nrequire(\"html\")\n\nlocal page = html(\n  head(\n    meta({ charset = \"utf-8\" }),\n    title(\"Hello World\")\n  ),\n  body(\n    div({ _class = \"container\" },\n      h1(\"Hello World\"),\n      p(\"Generated with luadom.\")\n    )\n  )\n)\n\nlocal html_out = render(page)\nprint(html_out)\n```\n\nIf you prefer explicit namespacing instead of globals:\n\n```lua\nlocal dom = require(\"luadom\")\n\nlocal page = dom.html(\n  dom.body(\n    dom.h1(\"Hello\")\n  )\n)\n\nlocal html_out = dom.render(page)\n```\n\n## Props and Attributes\n\nProps are passed as the first argument using a Lua table:\n\n```lua\ndiv({\n  id = \"main\",\n  _class = \"hero\",\n  style = { padding = \"16px\", background = \"#fff\" },\n  hidden = true,\n  data = { role = \"banner\" },\n}, \"Hello\")\n```\n\nNotes:\n\n- `_class` is converted to `class`\n- `for_` is converted to `for` (since `for` is a Lua keyword)\n- SVG/DOM sugar: `strokeWidth`, `textAnchor`, `fontSize`, `stopColor`, etc. are mapped to their dashed forms.\n- `style` can be a table and will be rendered as CSS\n- `data` can be a table and becomes `data-*` attributes\n- `true` renders boolean attributes (e.g. `hidden`)\n- When using `require(\"html\")`, global tag names can collide with Lua globals. We remap:\n  - `table` -\u003e HTML `\u003ctable\u003e` tag (original Lua table library is available as `table_lib`)\n  - `select` -\u003e HTML `\u003cselect\u003e` tag (original Lua `select` is available as `select_fn`)\n- Use `raw(...)` for `\u003cscript\u003e` or `\u003cstyle\u003e` contents to avoid escaping.\n\n## Query Helpers (DOM-style)\n\nAvailable on any node:\n\n```lua\nlocal root = html(...)\nlocal el = root:querySelector(\".card\")\nlocal by_id = root:getElementById(\"main\")\nlocal all = root:getElementsByTagName(\"section\")\n```\n\nSelector support includes:\n\n- Tag name (e.g. `\"div\"`)\n- Id (e.g. `\"#main\"`)\n- Class (e.g. `\".card\"`)\n- Compound selectors (e.g. `\"section.card#main\"`)\n- Descendant and child (`\"div span\"`, `\"div \u003e span\"`)\n- Attribute selectors (`\"[title=x]\"`, `\"[data-role=hero]\"`)\n- Attribute operators (`^=`, `$=`, `*=`) (e.g. `\"[title^=hello]\"`)\n- Selector lists (`\"div, span\"`)\n- Pseudo-classes: `:first-child`, `:last-child`, `:nth-child(n)`\n- Sibling combinators: `+`, `~`\n- `:not(...)` (simple selector)\n\n## DOM Methods\n\nAvailable on element nodes:\n\n- `matches(selector)`\n- `closest(selector)`\n- `contains(node)`\n- `appendChild(node)`\n- `removeChild(node)`\n- `replaceChild(newNode, oldNode)`\n- `cloneNode(deep)`\n- `setAttribute(name, value)`\n- `getAttribute(name)`\n- `removeAttribute(name)`\n- `textContent([value])`\n- `innerHTML([value])` (setter stores raw HTML)\n- `addClass(...)`, `removeClass(...)`, `toggleClass(class, force)`, `hasClass(class)`\n- `classList()` (returns `add/remove/toggle/contains`)\n- `style()` and `dataset()` helpers (table accessors)\n- `parentNode()`, `childNodes()`, `firstChild()`, `lastChild()`, `nextSibling()`, `previousSibling()`\n- Node constants (`ELEMENT_NODE`, `TEXT_NODE`, etc.) available via `dom.__node_constants`\n\n## Tag Validation\n\nAll tags are created dynamically. Non-standard tags will warn by default (custom elements with a dash are allowed).\n\n```lua\nlocal dom = require(\"luadom\")\n\n-- modes: \"warn\" (default), \"error\", \"off\"\ndom.setTagValidation(\"warn\")\n```\n\n## Pretty Rendering\n\n```lua\nlocal html = dom.renderPretty(page)\n```\n\nOptions:\n\n```lua\ndom.render(page, { pretty = true, indent = \"  \", newline = \"\\n\" })\n```\n\n## JS-style Timers\n\nThese are cooperative and run in Lua (server-side).\n\n```lua\nlocal id = dom.setTimeout(function()\n  print(\"fired\")\nend, 1000)\n\ndom.setInterval(function()\n  print(\"tick\")\nend, 500)\n\n-- manually advance timers\ndom.tickTimers()\n\n-- intervals with 0ms fire on every tick\n\n-- or run a loop for N milliseconds\ndom.runTimers(2000)\n```\n\n## JS Helpers\n\n`dom.console` provides `log`, `warn`, `error`.  \n`dom.document` provides `createElement`, `createElementNS`, `createTextNode`, `createDocumentFragment`, `createComment`, `createHTMLDocument`.\n`dom.Document` creates a document wrapper with `head` and `body`.\n\n## Files\n\n- `dom.lua` - core nodes, rendering, selectors\n- `luadom.lua` - tag factory and public API\n- `html.lua` - global helpers (`div(...)`, `render(...)`, etc.)\n- `js.lua` - JS-style timer helpers\n- `svg.lua` - SVG tag helpers (similar to `html.lua`)\n- `examples/` - runnable examples\n\n## Notes\n\nThis is a server-side HTML builder. It does not execute JS or provide a browser runtime. HTML parsing is not included. A `\u003c!doctype html\u003e` is automatically prepended when rendering a root `\u003chtml\u003e` element (disable via `{ doctype = false }`).\n\n## Tests\n\nRun the test suite:\n\n```sh\nlua tests/run.lua\n```\n\nGitHub Actions runs this on Lua 5.1–5.4.\n\n## Docs (LDoc)\n\nInstall and generate docs:\n\n```sh\nluarocks install ldoc\nldoc .\n```\n\nOutput will be in `docs/`.\n\nSource files for docs live in `docs-src/`.\n\n## Troubleshooting\n\nCommand not found: `luarocks`\n\n- Install LuaRocks (see \"Installing LuaRocks\" above).\n\nModule not found (e.g. `module 'socket' not found`)\n\n- Install the dependency with LuaRocks, e.g. `luarocks install luasocket`.\n\n## Publishing (LuaRocks)\n\nThis section shows how to package and publish `luadom` to LuaRocks.\n\n### 1) Add metadata files\n\nCreate a `rockspec` file (example below) and a `LICENSE` file. Pick a license (MIT is common).\n\nExample `luadom-2026.02.08-1.rockspec`:\n\n```lua\npackage = \"luadom\"\nversion = \"2026.02.08-1\"\n\nsource = {\n  url = \"git://github.com/byteface/luadom.git\",\n  tag = \"v2026.02.08\",\n}\n\ndescription = {\n  summary = \"DOM-ish HTML builder for Lua\",\n  detailed = \"Build HTML with tag functions, props tables, and a DOM-style query API.\",\n  homepage = \"https://github.com/byteface/luadom\",\n  license = \"MIT\",\n}\n\ndependencies = {\n  \"lua \u003e= 5.1\",\n}\n\nbuild = {\n  type = \"builtin\",\n  modules = {\n    [\"luadom\"] = \"luadom.lua\",\n    [\"dom\"] = \"dom.lua\",\n    [\"html\"] = \"html.lua\",\n  }\n}\n```\n\n### 2) Tag a release\n\n```sh\ngit tag v2026.02.08\ngit push origin v2026.02.08\n```\n\n### 3) Build \u0026 test the rock locally\n\n```sh\nluarocks pack luadom-2026.02.08-1.rockspec\nluarocks install luadom-2026.02.08-1.rockspec\nlua -e 'require(\"luadom\")'\n```\n\n### 4) Publish to LuaRocks\n\n```sh\nluarocks upload luadom-2026.02.08-1.rockspec\n```\n\n### 5) Install from LuaRocks (users)\n\n```sh\nluarocks install luadom\n```\n\n### Versioning\n\nThis project uses date-based versioning. Update the rockspec version and git tag together (e.g., `2026.03.01-1` and `v2026.03.01`).\n\n## Next Ideas\n\n- More complete CSS selector support\n- Pretty/indented HTML rendering\n- Timer helpers (`setTimeout`, `setInterval`) with a small scheduler\n- LuaRock packaging\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbyteface%2Fluadom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbyteface%2Fluadom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbyteface%2Fluadom/lists"}