Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Zuppa

An HTML5 parser written in Zig, built for WebAssembly.

  • 100% pass rate on the html5lib-tests tree-construction suite (1,058 cases including fragments)
  • ~57 KB WASM binary (ReleaseSmall)
  • Single-pass tokenizer + tree builder
  • Full HTML5 parsing: adoption agency, active formatting reconstruction, foster parenting, implicit element insertion, SVG/MathML foreign content, fragment parsing

Quick start (JavaScript / TypeScript)

import { Zuppa } from 'zuppa';

const parser = await Zuppa.load();

const doc = parser.parse('<div class="hello">world</div>');
// { mode: "document", children: [{ type: "element", tag: "html", ... }] }

const frag = parser.parseFragment('<b>bold</b>', 'div');
// { mode: "fragment", children: [{ type: "element", tag: "b", ... }] }

Build

Requires Zig 0.14.0.

# Build the WASM binary
zig build -Doptimize=ReleaseSmall

# Output: zig-out/bin/zuppa.wasm

Test

# Native Zig tests
zig build test

# Full html5lib-tests suite (requires submodule)
git submodule update --init
zig build test

Use as a Zig dependency

Add to your build.zig.zon:

.dependencies = .{
    .zuppa = .{
        .url = "https://github.com/HaTheo/Zuppa/archive/refs/tags/v0.1.0.tar.gz",
        .hash = "...",
    },
},

Then in your Zig code:

const Parser = @import("zuppa").Parser;

var parser = Parser.init(allocator, html, null);
defer parser.deinit();
try parser.parse();
// Walk parser.nodes for the tree

WASM ABI

Export Signature Notes
zuppa_version () -> u32 Returns 1
zuppa_alloc (len: u32) -> ptr Allocate WASM memory
zuppa_free (ptr: u32, len: u32) -> void Free WASM memory
zuppa_parse (html_ptr, html_len) -> u32 Parse document. 1=ok, 0=err
zuppa_parse_fragment (html_ptr, html_len, ctx_ptr, ctx_len) -> u32 Parse fragment. 1=ok, 0=err
zuppa_result_ptr () -> u32 Pointer to JSON result
zuppa_result_len () -> u32 Length of JSON result
zuppa_result_free () -> void Free result buffer

Output format

{
  "mode": "document",
  "children": [
    {
      "type": "element",
      "tag": "html",
      "attrs": {},
      "children": [
        { "type": "element", "tag": "head", "attrs": {}, "children": [] },
        {
          "type": "element",
          "tag": "body",
          "attrs": {},
          "children": [
            { "type": "text", "content": "hello" }
          ]
        }
      ]
    }
  ]
}

Node types: element (tag + attrs + children), text (content), comment (content).

Architecture

src/
  parser.zig    HTML5 tokenizer + tree builder (single pass, ~3000 lines)
  emitter.zig   JSON serializer with HTML entity decoding
  wasm.zig      WASM ABI exports

License

MIT

About

An HTML5 parser written in Zig built for performant WebAssembly

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages