| name | litexml-authoring |
| description | Use when writing Haklex articles with Markdown plus LiteXML, choosing the appropriate Haklex node for content, authoring LiteXML fragments, or converting a LightXML/LiteXML string or file into Lexical SerializedEditorState JSON, Markdown, or Static Render HTML via the `litexml` CLI. |
| user_invocable | true |
LiteXML Authoring
Use this skill when an article needs Haklex-specific rich nodes, or when the user asks to convert LiteXML to Lexical JSON / Markdown / HTML via the litexml CLI.
The skill is split into a thin index (this file) plus per-topic references. Load the matching reference when you start the actual work — the index is intentionally short so the format decision table and node selection map fit in one read.
References
| File | When to load |
|---|
references/cli.md | Running the litexml binary — every flag, every input/output mode, every runtime caveat. |
references/nodes-structural.md | Authoring with structural tags (<p>, headings, lists, tables, links) and inline formatting (<b>, <em>, <code>, …). |
references/nodes-extensions.md | Authoring with Haklex extension tags (media, code, math, callouts, containers, footnotes, chat, poll, …). |
references/authoring-recipes.md | CDATA usage, block IDs, nested-content rules, similar-node disambiguation, validation, adding new nodes. |
packages/rich-editor/docs/markdown-flavor-litexml.md is the canonical tag contract — read it before changing any tag name or attribute schema.
Format decision
| Content requirement | Use |
|---|
| Plain prose, headings, simple links, lists, quotes, tables, code fences | Markdown |
| Any Haklex extension tag is required | LiteXML — for the whole fragment, including surrounding prose |
| A block needs stable identity for later edits | LiteXML with id="..." (maps to $.blockId) |
| Fresh poll/chat content | LiteXML without IDs — the reader mints them |
Once a fragment contains any LiteXML tag, all surrounding prose in that fragment must also be LiteXML. Markdown is not parsed inside a LiteXML fragment.
CLI quick start
pnpm --silent litexml input.xml --format json --compact
pnpm --silent litexml input.xml --format markdown
pnpm --silent litexml input.xml --format html --open
npx --yes -p @haklex/rich-litexml-cli litexml input.xml --format json
Full flag reference, output forms, theme/variant/lang options, error modes, validation pipelines: references/cli.md.
Node selection map
Detailed When / Avoid when / params / body rules for each tag live in nodes-structural.md and nodes-extensions.md. Use this table only to decide which reference to open.
| Need | Tag | Reference |
|---|
| Paragraph, heading, list, table, link, inline format | <p> / <h*> / <ul> / <ol> / <table> / <a> / <b> / <code> / … | structural |
Quote (with optional attribution) | <blockquote> | structural |
| Single image / multi-image / video / embed / link card | <img> / <gallery> / <video> / <embed> / <link-card> | extensions |
| Code (single / multi-file) | <codeblock> / <code-snippet> | extensions |
| Diagram (Mermaid / opaque) | <mermaid> / <excalidraw> | extensions |
| Math (inline / block) | <math> / <math display="block"> | extensions |
| Callout (semantic / page-wide) | <alert> / <banner> | extensions |
| Collapsible / nested doc / multi-column | <details> / <nested-doc> / <grid><cell> | extensions |
| Inline annotation | <spoiler> / <ruby> / <mention> / <tag> / <comment> | extensions |
| Footnote | <footnote> + <footnote-section> | extensions |
| Chat / poll | <chat> / <poll> | extensions |
| Internal review marker | <agent-diff> | extensions |
Cross-cutting rules
- Canonical lowercase tag names. Do not emit legacy aliases (
<linkcard>, <codesnippet>, <nesteddoc>, <code-block>).
- Quote every attribute value.
- Escape XML-sensitive text (
&, <, >, "). Use CDATA for opaque JSON, drawing snapshots, and multi-line code bodies.
<alert>, <banner>, <nested-doc>, <grid><cell> hold a fresh nested editor state — wrap their body in block tags (<p>, <h*>, …), not bare text.
- A fragment that mixes any extension tag with prose must be wholly LiteXML; Markdown syntax is not parsed inside.
Details, gotchas, and the full disambiguation matrix: references/authoring-recipes.md.
Validation
After producing or editing LiteXML, round-trip to compact JSON to confirm the registry parses every tag:
pnpm --silent litexml '<doc><p>Hello</p></doc>' --format json --compact
If the command succeeds but a downstream editor cannot materialize a node, the runtime is missing that Haklex node class — re-check the consumer's nodes registration, not the CLI.