# KitchenMD — Domain Glossary A living glossary of canonical terms for this project. Implementation details belong in specs or code, not here. --- ## Annotation An inline sigil-based marker embedded in recipe prose that carries structured data. There are exactly three annotation types: **Ingredient**, **Cookware**, and **Timer**. An annotation is valid Markdown plain text — it does not break rendering in Obsidian or any standard Markdown renderer. Annotations follow CommonMark's inline processing rules: parsed wherever CommonMark processes inline content (paragraphs, headings, list items, blockquotes); ignored wherever CommonMark treats content as literal (code spans, code blocks, HTML comments, raw HTML blocks). ## Ingredient Annotation Syntax: `@name{quantity}` or `@name{quantity unit}` The `{` character terminates the name, so multi-word names work without escaping. The `{}` wrapper is mandatory — bare `@name` without braces is not valid. Quantity is optional; `@black pepper{}` is valid with no quantity. Valid quantity formats: integer (`2`), decimal (`0.5`), simple fraction (`1/2`), mixed number (`1 1/2`). Unit is optional and free-form — the format places no constraints on what unit string is written. When both quantity and unit are present, they are delimited by the last space inside the braces — so `@butter{1 1/2 tbsp}` parses as quantity `1 1/2`, unit `tbsp`. Valid name characters: any character except `{`, `}`, `@`, `$`, `~`. ## Cookware Annotation Syntax: `$name{}`, `$name{quantity}`, or `$name{quantity unit}` Same `{`-terminated name rule as Ingredient. The `{}` wrapper is mandatory. Quantity is optional; `$pan{}` is valid with no quantity. Quantity and unit follow the same rules as Ingredient: valid formats are integer, decimal, simple fraction, mixed number; unit is free-form; delimited by the last space inside the braces. Valid name characters: any character except `{`, `}`, `@`, `$`, `~`. ## Timer Annotation Syntax: `~N unit` or `~N-N unit` No braces. The `~` sigil is followed immediately by a number or `N–N` range, a space, then a time unit word from the known set. N follows the same format rules as ingredient/cookware quantity: integer, decimal, simple fraction, or mixed number. Supports natural range syntax: `~10-15 mins`. In range form, the `-` separator follows the first quantity expression — since negative quantities don't exist, the `-` is unambiguous. `~1/2-1 hr` parses as a range of 1/2 hr to 1 hr. The annotation terminates after the unit word — trailing prose is ignored. `~1 min more` parses as a timer of 1 min; "more" is plain text. Known unit set (aliases → canonical abbreviation): `sec`, `secs`, `second`, `seconds` → `s`; `min`, `mins`, `minute`, `minutes` → `min`; `hr`, `hrs`, `hour`, `hours` → `hr`. ## Recipe File A valid `.md` file that may contain any combination of Obsidian Flavored Markdown, YAML frontmatter, and Annotations. The file renders correctly in Obsidian without a plugin. A Recipe File contains prose instructions only — there is no separate ingredients list section. Ingredients are derived entirely by the Parser from inline Ingredient Annotations. ## Step The atomic unit of a recipe instruction. A step is a single non-empty line in a prose context, or a single ordered list item. Headings are not steps. Step numbers are section-local — they reset at each heading and do not change when steps are added to other sections. ## Combined Recipe A Recipe File whose purpose is to sequence steps from two or more other Recipe Files. It contains no steps or ingredients of its own — only Step References in the order they should be executed. ## Step Reference A KitchenMD extension of Obsidian transclusion syntax for embedding a specific step from another Recipe File. Syntax: - `![[filename#section-heading:N]]` — step N within a named section. - `![[filename#N]]` — step N in a headingless recipe (bare number, no section prefix). - `filename` — the Recipe File to reference (no `.md` extension, matching Obsidian wikilink convention). - `section-heading` — the heading text of the section containing the step. - `N` — the 1-based step number within that section or file. Examples: - `![[italian meatballs#rolling:2]]` — second step of the "rolling" section. - `![[basic brine#2]]` — second step of a headingless recipe. This syntax is a compatibility break with vanilla Obsidian: `#section:N` does not match any Obsidian heading anchor, so Step References will not render correctly without KitchenMD tooling. ## Frontmatter YAML metadata block at the top of a Recipe File (standard `---` delimiters). The parser passes frontmatter through as-is with no schema enforcement. Consumers are responsible for reading whatever fields they need. ## Sigil The single punctuation character that opens each annotation type: - `@` — Ingredient - `$` — Cookware - `~` — Timer ## Parser The TypeScript library (`@kitchen-md/core`) that accepts a Recipe File string and returns a structured data object. It is a pure function of its input string — no filesystem access. ## Structured Output The Document AST returned by the Parser for a given Recipe File. See **Document AST** for the exact shape. ## Document AST The full structured representation of a Recipe File returned by the Parser. Top-level shape: `{ frontmatter: Record, blocks: Block[] }`. `frontmatter` is the raw YAML metadata, passed through without schema enforcement. `blocks` is a flat, ordered list of Block nodes representing the document body in document order. The flat structure means headings and their following content are siblings, not parent/child. Consumers that need section grouping derive it by scanning for Heading nodes. Core defines its own AST node types; remark (the internal Markdown parser) is a private implementation detail and its types do not appear in the public API. See ADR 0002 and ADR 0003. ## Block A top-level node in the Document AST's `blocks` array. Each Block represents one logical unit of document structure: a heading, a paragraph, a list, a code block, etc. Block types are defined by core; the exact catalogue is not yet finalised — see open questions below. ## Inline Node A node representing inline content within a Block (e.g. within a paragraph or list item). Inline nodes include: plain text, emphasis, strong, code span, link, Wikilink, and the three Annotation types (Ingredient, Cookware, Timer). --- ## Open / Unresolved - **Block node type catalogue** — the exact set of Block types core defines (heading, paragraph, list, code block, blockquote, etc.) and how unrecognised types are represented. - **Unit normalisation** — the parser should normalise known aliases to a canonical abbreviation (`grams` → `g`, `kilograms` → `kg`); exact alias table and canonical forms are TBD. This is a parser concern, not a format constraint.