jaml-lang
v0.1.2
Published
JAML (Jimbo's Ante Markup Language) authoring contract: typed POCO + Zod schema + completion vocab, generated from the Motely C# enums.
Downloads
0
Maintainers
Readme
jaml-lang
The JAML authoring contract: a typed Zod schema + an editor-agnostic language service + the completion vocabulary, all generated from the Motely C# enums.
JAML (Jimbo's Ante Markup Language) is the YAML dialect you write Balatro
seed-search filters in. This package is the fast structural front gate for
that language — validation, completions, hover, and document symbols — usable
from any editor, the browser, or Node. The Motely WASM engine's parseJaml
remains the final semantic authority; this is the cheap, synchronous layer in
front of it.
name: Demo
deck: Erratic
stake: White
must:
- joker: WeeJoker
antes: [1, 2]
should:
- voucher: Telescope
score: 100Install
npm install jaml-langESM-only ("type": "module"). Ships compiled .js + .d.ts — no build step on
your side.
Usage
Validate
getDiagnostics(text) returns YAML syntax errors and structural issues
(bad enum values, unknown keys), each with an LSP-style 0-based range.
import { getDiagnostics, Severity } from "jaml-lang";
const errors = getDiagnostics(`name: X\nmust:\n - joker: NotARealJoker\n`)
.filter(d => d.severity === Severity.Error);
// -> [{ message: "...NotARealJoker...", severity: 0, range: {...} }]Or validate a parsed object directly with the schema:
import { JamlConfigSchema } from "jaml-lang";
JamlConfigSchema.parse({ name: "X", must: [{ joker: "Blueprint" }] }); // throws on bad shapeComplete
getCompletions(text, offset) is context-aware — it knows whether you're typing
a root key, a clause field, or an enum value, and answers accordingly.
import { getCompletions } from "jaml-lang";
const head = `must:\n - joker: We`;
getCompletions(head, head.length);
// -> [{ label: "WeeJoker", kind: "enum", ... }, ...]Hover & outline
import { getHover, getDocumentSymbols } from "jaml-lang";
getHover(`must:\n - joker: WeeJoker\n`, 12); // -> { contents: "...joker..." } | null
getDocumentSymbols(`must:\n - joker: WeeJoker\n`); // -> [{ name: "must", children: [...] }]Raw vocabulary
Every value you can legally type in a .jaml file, as readonly string tuples
generated from the C# source of truth (jokers, vouchers, tarots, decks, …):
import { Vocab } from "jaml-lang";
// import { MotelyJoker } from "jaml-lang/vocab"; // also works
Vocab.MotelyJoker; // ["Joker", "GreedyJoker", ..., "Perkeo"] (150)
Vocab.MotelyVoucher; // ["Overstock", ...] (32)Entry points
| Import | What |
|---|---|
| jaml-lang | everything — service fns, JamlConfigSchema + types, Vocab namespace |
| jaml-lang/service | just the language-service functions + types |
| jaml-lang/vocab | just the generated enum tuples |
API
| Export | Signature | Purpose |
|---|---|---|
| getDiagnostics | (text) => Diagnostic[] | YAML syntax + structural (Zod) issues |
| getCompletions | (text, offset) => CompletionItem[] | context-aware keys + enum values |
| getHover | (text, offset) => Hover \| null | docs for the symbol under the cursor |
| getDocumentSymbols | (text) => DocumentSymbol[] | must/should/mustNot outline |
| mergeDiagnostics | (fast, authoritative) => Diagnostic[] | fold engine parseJaml results onto the fast gate (layer 2) |
| JamlConfigSchema | z.ZodType | the authoring shape; .parse() / z.infer<> |
| Vocab | namespace of readonly string[] | generated enum tuples |
All ranges/positions are 0-based (LSP convention), so adapting to
vscode-languageserver or a CodeMirror linter is a thin mapping.
How it stays correct
Vocab is generated by codegen/gen-vocab.mjs from Motely/Enums/*.cs, and the
package's prepublishOnly re-runs that generation before every publish — so the
shipped vocabulary can't drift from the engine. Two validation layers:
- This package (layer 1) — fast, synchronous, runs anywhere.
- Motely WASM
parseJaml(layer 2) — authoritative semantics; merge its diagnostics in viamergeDiagnosticswherever the engine is available (an LSP server in Node, a Web Worker in the browser).
License
MIT © pifreak
