Documentation for HAXElementSchema, the lightweight object format HAX uses as a virtual DOM representation before converting to real DOM nodes.
This is a companion repo to hax-schema. Where hax-schema explains the full haxProperties contract for element authoring, this repo focuses specifically on the element payload objects used in demoSchema, insertion, and conversion workflows.
HAXElementSchema is an object with this shape:
{
"tag": "my-tag",
"properties": {
"title": "Example title"
},
"content": "<p>Inner HTML content</p>",
"eventName": "insert-element"
}tag(required): lowercase HTML or custom-element tag name to create.properties(optional): key/value map of attributes and/or properties (see Runtime conversion behavior).content(optional): string content assigned as light DOM (innerHTML). Children can target named slots withslot="name".eventName(optional): set bynodeToHaxElement()(defaultinsert-element); not needed when authoring.description(optional): human label for one of severaldemoSchemavariants. HAX core does not read it.gizmo(runtime only): attached byhaxElementPrototype()when HAX builds a payload from search results. Never author it.x-*(optional): extension keys for tool-specific data. Every other key is rejected.
See a concrete object example in example.json, and more in examples/.
hax-element-schema.schema.json is JSON Schema draft 2020-12. scripts/validate.js validates a single element, an array of elements, or every demoSchema entry of a haxProperties file, and adds warnings for runtime behavior a schema cannot express (ignored innerHTML keys, stripped on* attributes, two keys that dash-case to the same attribute, <script> in content).
From npm (no install needed):
npx -p @haxtheweb/hax-element-schema hax-element-validate my-element.haxProperties.jsonFrom a clone:
npm install
node scripts/validate.js example.json examples/variants.json
node scripts/validate.js --json path/to/lib/my-element.haxProperties.json
npm testEvery demoSchema entry in the webcomponents monorepo (94 haxProperties files) passes.
- Use
propertiesfor values andcontentfor markup.innerHTML/innerTextkeys are ignored, andattributesis not a key. - Pick one spelling per value.
mediaTitleandmedia-titleboth become themedia-titleattribute, so use the camelCase JS property name. - Never use
null. It is written as the literal attribute value"null"; omit the key instead. falseremoves an attribute; it does not set a property to false. It cannot turn off a property whose default istrue(for example awesome-explosion'ssoundEnabled), so check the element's defaults first.- No event handlers,
srcdocor inline URLs.on*attributes are always stripped,srcdocis stripped from iframes, andjavascript:/vbscript:/data:URLs are stripped from URL attributes, so reference files (files/photo.jpg) instead of embedding them. - Inside haxProperties, the first
demoSchemaentry is what HAX inserts, so it should be a complete, good-looking default. Validate withscripts/validate.jsafter editing.
Inside a haxProperties file, demoSchema is an array of HAXElementSchema objects:
{
"demoSchema": [
{
"tag": "block-quote",
"properties": {
"citation": "Padmé Amidala: Star wars, Episode II"
},
"content": "<p>So this is how liberty dies... with thunderous applause</p>"
}
]
}See example.haxProperties.json for a full sample.
HAX uses this object shape as a lightweight virtual DOM payload during authoring operations. The object is passed around, transformed, and only materialized into actual nodes at insertion/render time.
Primary usage points in core:
-
Virtual DOM -> DOM conversion
haxElementToNode(haxSchema)creates real nodes fromtag,properties, andcontent.
Reference: https://github.com/haxtheweb/webcomponents/blob/master/elements/utils/utils.js -
DOM -> virtual DOM conversion
nodeToHaxElement(node, eventName)serializes existing nodes intoHAXElementSchema.
Reference: https://github.com/haxtheweb/webcomponents/blob/master/elements/utils/utils.js -
Prototype/factory creation of virtual DOM objects
haxElementPrototype(gizmo, properties, content)returns{ tag, properties, content, gizmo }.
Reference: https://github.com/haxtheweb/webcomponents/blob/master/elements/hax-body/lib/hax-store.js -
Tray insertion pipeline dispatches virtual DOM payloads
hax-trayresolvesdemoSchema[0]or builds a prototype object and dispatches it viahax-insert-content.
Reference: https://github.com/haxtheweb/webcomponents/blob/master/elements/hax-body/lib/hax-tray.js -
Store insertion pipeline consumes virtual DOM payloads
_haxStoreInsertContentconsumesdetail.tag/content/propertiesand converts to DOM viahaxElementToNodefor inline and replace flows.
Reference: https://github.com/haxtheweb/webcomponents/blob/master/elements/hax-body/lib/hax-store.js -
Keyboard shortcuts are modeled as virtual DOM snippets
Shortcut map entries areHAXElementSchema-style objects and are converted to nodes at runtime.
References: -
Duplicate workflow round-trips through virtual DOM
haxDuplicateNodeconverts DOM ->HAXElementSchema-> DOM to ensure clean cloning.
Reference: https://github.com/haxtheweb/webcomponents/blob/master/elements/hax-body/hax-body.js -
Dev helper insertion uses demoSchema virtual DOM
globalThis.Hax.addinserts usingschema.demoSchema[0]viahaxElementToNode.
Reference: https://github.com/haxtheweb/webcomponents/blob/master/elements/hax-body/lib/hax-store.js
In HAX core, conversion happens primarily in:
haxElementToNode(haxSchema)- converts schema object to a real DOM node.nodeToHaxElement(node, eventName)- converts a DOM node to schema.
Important behavior:
properties value |
What haxElementToNode() does |
|---|---|
| string / number | setAttribute(dash-case(key), value) |
true |
sets the boolean attribute |
false |
removes the attribute (it does not set the property to false) |
| array / plain object | assigned as an element property instead of an attribute |
null |
written as the string "null"; avoid |
innerHTML / innerText key |
ignored; use content |
on* key |
always stripped (along with any on* attribute that appears in content) |
srcdoc on iframe / webview |
stripped |
javascript: / vbscript: / data: value in a URL attribute (src, href, poster, *-src, *-url, ...) |
attribute stripped, here and in content |
contentbecomes light DOM (innerHTML) on conversion.iframeis rewritten towebviewin sandboxed (desktop) environments.nodeToHaxElement()goes the other way: it reads the node's declared properties and attributes intoproperties, its light DOM intocontent, and setseventName.
This repo includes hax-element-schema.schema.json, a machine-readable JSON Schema for validation and tooling support.
- Keep
HAXElementSchemadocumentation focused and easy to discover. - Provide canonical examples for docs, tests, and tooling.
- Offer a shared reference for systems that import/export HAX element payloads.
This package is versioned with the rest of the HAX ecosystem and is published by the ubiquity release (scripts/ubiquity-push.sh in haxtheweb/webcomponents), which runs commit-and-tag-version --release-as <ecosystem version>, pushes the tag and runs npm publish. To cut a release of just this package, run npm run release (tests, bumps the version and CHANGELOG, tags, pushes to master, publishes).