From 5841ae5de80148eb435434a825d25d8a08384d15 Mon Sep 17 00:00:00 2001 From: alexion Date: Wed, 8 Jul 2026 23:29:09 -0400 Subject: [PATCH] chore: add Biome and document design decisions from grill session - Add @biomejs/biome 2.5.3 with 2-space indent, double quotes, trailing commas - Add lint and format scripts to root package.json - Update CONTEXT.md: resolve Structured Output shape, add Document AST, Block, Inline Node terms - Add ADR 0002 (remark as internal Markdown parser) - Add ADR 0003 (core defines own AST types) - Add spec: core-parser (Parser implementation and Document AST) - Add spec: cli-view (kitchen view command) --- .claude/CONTEXT.md | 28 +++- ...0002-remark-as-internal-markdown-parser.md | 39 ++++++ .../adr/0003-core-defines-own-ast-types.md | 39 ++++++ .claude/spec/cli-view.md | 96 +++++++++++++ .claude/spec/core-parser.md | 126 ++++++++++++++++++ biome.json | 38 ++++++ bun.lock | 19 +++ package.json | 10 +- 8 files changed, 390 insertions(+), 5 deletions(-) create mode 100644 .claude/adr/0002-remark-as-internal-markdown-parser.md create mode 100644 .claude/adr/0003-core-defines-own-ast-types.md create mode 100644 .claude/spec/cli-view.md create mode 100644 .claude/spec/core-parser.md create mode 100644 biome.json diff --git a/.claude/CONTEXT.md b/.claude/CONTEXT.md index 2b94f2f..5b98e12 100644 --- a/.claude/CONTEXT.md +++ b/.claude/CONTEXT.md @@ -103,12 +103,34 @@ It is a pure function of its input string — no filesystem access. ## Structured Output -The data object returned by the Parser for a given Recipe File. -Shape is not yet fully specified — see open questions below. +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 -- **Structured Output shape** — exact fields, types, and nesting of the parse result. +- **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. diff --git a/.claude/adr/0002-remark-as-internal-markdown-parser.md b/.claude/adr/0002-remark-as-internal-markdown-parser.md new file mode 100644 index 0000000..235a680 --- /dev/null +++ b/.claude/adr/0002-remark-as-internal-markdown-parser.md @@ -0,0 +1,39 @@ +# ADR 0002 — remark as Core's Internal Markdown Parser + +**Status**: Accepted + +## Context + +`@kitchen-md/core` must parse CommonMark Markdown (plus Obsidian Flavored Markdown extensions) to build a Document AST. +The spec requires that Annotations follow CommonMark's inline processing rules — they are parsed inside paragraphs and list items, and ignored inside code spans and code blocks. +Correctly detecting those boundaries from scratch requires a complete CommonMark implementation. + +Two approaches were considered: + +**Option A — Use remark/unified** +remark is a CommonMark-compliant Markdown parser that produces mdast (a typed Markdown AST). +It has a plugin/transform architecture: OFM extensions (wikilinks, transclusion) are handled by existing community plugins (`remark-wiki-link`), and KitchenMD annotations are handled by a custom transform plugin that walks mdast text nodes and splits them into annotation nodes. +TypeScript support is first-class. + +**Option B — Build the Markdown parser from scratch** +Write a custom CommonMark parser as part of `@kitchen-md/core`, with no external Markdown dependency. + +## Decision + +**Option A** — remark/unified as core's internal Markdown parser. + +## Rationale + +CommonMark is a large, precisely specified standard. +Building a correct implementation from scratch is significant work with no unique value to the project — the interesting problems are annotation parsing and document rendering, not Markdown tokenisation. + +The "built from scratch" statement in the project spec refers to not forking Cooklang's parser, not to avoiding all external dependencies. + +remark's plugin architecture maps cleanly to core's needs: one plugin for OFM wikilinks, one plugin for KitchenMD annotations, both operating as transform passes over an existing mdast. + +## Consequences + +- remark and its plugin ecosystem are build-time dependencies of `@kitchen-md/core`. +- remark must remain a private implementation detail — its types must not appear in core's public API (see ADR 0003). +- OFM support requires `remark-wiki-link` (and the underlying `micromark-extension-wiki-link` / `mdast-util-wiki-link`). +- KitchenMD annotation parsing is implemented as a custom remark transform plugin within core. diff --git a/.claude/adr/0003-core-defines-own-ast-types.md b/.claude/adr/0003-core-defines-own-ast-types.md new file mode 100644 index 0000000..51a672d --- /dev/null +++ b/.claude/adr/0003-core-defines-own-ast-types.md @@ -0,0 +1,39 @@ +# ADR 0003 — Core Defines Its Own AST Types + +**Status**: Accepted + +## Context + +remark produces mdast — a well-typed Markdown AST with its own node type definitions. +`@kitchen-md/core` builds its Document AST on top of remark's output. +Two options exist for what core exposes in its public API: + +**Option A — Expose mdast types directly** +Core re-exports remark's node types, augmented with KitchenMD annotation nodes via TypeScript module augmentation. +Consumers import `@kitchen-md/core` and receive mdast-typed nodes. + +**Option B — Core defines its own AST types** +Core defines its own `DocumentAST`, `Block`, and `InlineNode` types. +remark is an internal implementation detail; its types never appear in the public API. +Consumers import only from `@kitchen-md/core`. + +## Decision + +**Option B** — core defines its own AST types. + +## Rationale + +The public API is a long-lived contract with multiple future consumers: the `kitchen` CLI, and the future Obsidian plugin. +Leaking mdast into that contract means any remark major version that changes mdast types breaks all consumers, even if core's own logic is unchanged. + +mdast also exposes many node types that are irrelevant to KitchenMD consumers. +Core's own types can be a clean, minimal vocabulary scoped to what consumers actually need. + +The future Obsidian plugin should not need to know or care that remark is involved. + +## Consequences + +- Core maintains its own type definitions for all public AST nodes (Document AST, Block types, Inline Node types). +- An internal translation layer maps remark's mdast nodes to core's types before returning from the Parser. +- Changing core's internal Markdown parser in the future does not require a public API change. +- Consumers do not take a transitive dependency on remark. diff --git a/.claude/spec/cli-view.md b/.claude/spec/cli-view.md new file mode 100644 index 0000000..47b5f0e --- /dev/null +++ b/.claude/spec/cli-view.md @@ -0,0 +1,96 @@ +## Problem Statement + +`@kitchen-md/bin` has an empty CLI entry point. +Users have no way to view a Recipe File in the terminal — they must open a text editor or Markdown viewer to read a recipe. +The `kitchen` binary exists in the scaffold but accepts no commands and produces no output. + +## Solution + +Implement the `kitchen view ` subcommand. +It reads a Recipe File from disk, passes the content to `@kitchen-md/core`'s `parse` function, and walks the resulting Document AST through a renderer that produces ANSI-styled terminal output. +Markdown structure is styled for readability; KitchenMD annotations are rendered as their raw source text for now. + +## User Stories + +1. As a CLI user, I want to run `kitchen view ` and see the recipe rendered in the terminal so that I can read it without opening a text editor. +2. As a CLI user, I want headings styled distinctly by level so that I can scan the recipe's structure at a glance. +3. As a CLI user, I want bold and italic text preserved in the terminal output so that emphasis in the recipe prose is visible. +4. As a CLI user, I want frontmatter shown as raw YAML before the recipe body so that I can see the recipe's metadata. +5. As a CLI user, I want wikilinks rendered distinctly from surrounding prose so that cross-references are visually identifiable. +6. As a CLI user, I want a clear error message when the file does not exist so that I am not left with a cryptic failure. +7. As a CLI user, I want the binary to exit with a non-zero code on error so that shell scripts can detect failure. +8. As a CLI user, I want ANSI styling suppressed automatically when output is piped so that downstream tools receive clean text. + +## Implementation Decisions + +- commander is used for argument parsing. + The `view` subcommand takes a single required positional argument: the path to a Recipe File. + No flags or options beyond the file path are implemented at this stage. + +- The entry point reads the file from disk, passes the content string to `parse` from `@kitchen-md/core`, and passes the returned `DocumentAST` to the renderer. + File I/O is confined to the entry point. + +- The renderer is a pure function `render(ast: DocumentAST): string`. + It walks the Document AST and returns an ANSI-styled string. + It has no filesystem access and no side effects. + The separation between the entry point (file I/O + commander) and the renderer (pure AST walk) allows the renderer to be tested without invoking a subprocess. + +- **Rendering rules:** + - Frontmatter: serialised back to YAML and printed before the document body, followed by a visual separator. + - `HeadingBlock`: bold text; level 1 is the most visually prominent, with levels 2–6 progressively less so. + - `ParagraphBlock`: inline-rendered text followed by a blank line. + - `ListBlock`: each item on its own line, preceded by a bullet character (unordered) or sequential number (ordered). + - `CodeBlock`: literal text content, rendered as-is with no syntax highlighting. + - `ThematicBreakBlock`: a horizontal rule character string. + - `TextNode`: plain string output. + - `EmphasisNode` (italic): chalk italic. + - `StrongNode` (bold): chalk bold. + - `CodeSpanNode`: a visually distinct style (e.g. chalk dim or inverse). + - `LinkNode`: rendered as the inline content only; href is not shown. + - `WikilinkNode`: display text (or target if no display text), rendered with an underline or distinct colour. + - `TransclusionNode`: rendered as its raw source text (e.g. `![[file#section:1]]`). + - `IngredientNode`, `CookwareNode`, `TimerNode`: rendered as their raw annotation source text (e.g. `@flour{200 g}`, `$pan{}`, `~2-3 mins`). + Distinct annotation styling is out of scope for this spec. + +- chalk is used for all ANSI styling. + chalk auto-detects whether stdout is a TTY and disables colour codes when output is piped, satisfying user story 8 without an explicit flag. + +- **Error handling:** + - If the file path argument is missing, commander prints usage to stderr and exits with code 1. + - If the file does not exist or cannot be read, the entry point prints a human-readable error message to stderr and exits with code 1. + - No other error conditions are handled at this stage; parse errors from `@kitchen-md/core` are not expected (the parser is resilient to any valid Markdown string). + +## Testing Decisions + +- Two seams are tested: + + **Renderer unit tests** — given a `DocumentAST` constructed inline in the test, assert the `render` function's output with ANSI codes stripped. + Tests cover every Block type, every Inline Node type, frontmatter output, and the visual separator between frontmatter and body. + No subprocess invocation; no filesystem access. + + **Smoke tests** — invoke the `kitchen view` binary as a subprocess, capture stdout, strip ANSI codes, and assert the plain text content. + Smoke tests use `fixtures/basic.md` as input and assert that the output contains the expected rendered text for the fixture's headings, paragraphs, frontmatter, and wikilinks. + Smoke tests use Bun's subprocess API, consistent with the project scaffold's smoke test approach. + +- ANSI colour and weight choices are visual decisions verified by inspection, not automated test assertions. + Assertions operate on stripped plain text only. + +- Tests are co-located with source and follow the naming conventions established in the project scaffold. + +## Out of Scope + +- Distinct styling for KitchenMD annotation nodes (Ingredient, Cookware, Timer). + Annotations render as raw source text in this spec. +- Pager support. +- Multiple file arguments. +- `--no-color` flag (chalk auto-detects TTY). +- Syntax highlighting for code blocks. +- Formatted frontmatter display (title, servings, tags as a styled header). +- Any subcommand other than `view`. + +## Further Notes + +- Annotation raw source text (`@flour{200 g}`, `$pan{}`, `~2-3 mins`) reads naturally as plain text in the terminal. + This matches how Recipe Files render in Obsidian without a plugin — the format is designed to be readable without tooling. +- The renderer's purity is intentional. + Keeping file I/O in the entry point and rendering in a pure function is the minimum seam needed for deterministic unit tests without subprocess overhead. diff --git a/.claude/spec/core-parser.md b/.claude/spec/core-parser.md new file mode 100644 index 0000000..95e182d --- /dev/null +++ b/.claude/spec/core-parser.md @@ -0,0 +1,126 @@ +## Problem Statement + +`@kitchen-md/core` has an empty entry point. +There is no Parser implementation, no public API, and no AST types. +Tooling that needs to extract structured data from Recipe Files — the CLI, and eventually an Obsidian plugin — has nothing to build on. + +## Solution + +Implement the Parser in `@kitchen-md/core`: a pure function that accepts a Recipe File string and returns a Document AST. +The Parser uses remark internally to handle CommonMark and OFM syntax, runs a custom annotation transform to surface Ingredient, Cookware, and Timer nodes, and exposes a clean public API using core's own types — no remark internals leak through. + +## User Stories + +1. As a tooling user, I want to call `parse` with a Recipe File string and receive a Document AST so that I can build structured tooling without writing a parser myself. +2. As a tooling user, I want frontmatter passed through as a plain object so that I can read whatever fields I need without the parser imposing a schema. +3. As a tooling user, I want heading blocks in the Document AST so that I can render or reason about document structure. +4. As a tooling user, I want paragraph blocks with typed inline nodes so that I can render prose and distinguish plain text from structured content. +5. As a tooling user, I want list blocks with ordered and unordered variants so that recipe steps written as lists are represented faithfully. +6. As a tooling user, I want code blocks passed through without annotation parsing so that example syntax in documentation is not mistakenly extracted as recipe data. +7. As a tooling user, I want wikilinks represented as typed Inline Nodes so that I can render or process `[[links]]` distinctly from plain text. +8. As a tooling user, I want transclusions — including KitchenMD Step References — represented as typed Inline Nodes so that tooling can resolve them. +9. As a tooling user, I want Ingredient Annotations represented as Inline Nodes carrying name, quantity, and unit so that I can extract ingredient data from any recipe prose. +10. As a tooling user, I want Cookware Annotations represented as Inline Nodes carrying name and optional quantity so that I can extract equipment requirements. +11. As a tooling user, I want Timer Annotations represented as Inline Nodes carrying a value or range and a canonical unit so that I can extract timing information. +12. As a tooling user, I want annotations inside code spans and code blocks to be ignored so that the parser follows CommonMark inline processing rules. +13. As a future Obsidian plugin author, I want to import `@kitchen-md/core` without taking a transitive dependency on remark so that my plugin bundle does not include remark's internals. + +## Implementation Decisions + +- The public API exports a single `parse` function. + Given a Recipe File string, it returns a `DocumentAST`. + It is a pure function — no filesystem access, no side effects. + +- `DocumentAST` top-level shape: `{ frontmatter, blocks }`. + - `frontmatter` — the raw parsed YAML metadata as a plain object, passed through without schema enforcement. + Empty object when no frontmatter is present. + - `blocks` — a flat, ordered array of Block nodes representing the document body. + The flat structure means headings are siblings of their following content, not parents of it. + See ADR 0003 and the Document AST entry in the domain glossary. + +- **Block types** (initial set): + - `HeadingBlock` — level (1–6) and an inline content array. + - `ParagraphBlock` — an inline content array. + - `ListBlock` — ordered flag and an array of list items, each carrying an inline content array. + - `CodeBlock` — optional language identifier and a literal text string. + Annotation parsing does not run on code block content. + - `ThematicBreakBlock` — no content fields. + - `RawBlock` — carries the raw text of any remark node type not explicitly modelled above. + Ensures forward compatibility when the fixture or future files use block types not yet in the catalogue. + +- **Inline Node types**: + - `TextNode` — a literal string of plain text. + - `EmphasisNode` — an inline content array (italic). + - `StrongNode` — an inline content array (bold). + - `CodeSpanNode` — a literal string. + Annotation parsing does not run on code span content. + - `LinkNode` — href string and an inline content array. + - `WikilinkNode` — target (filename without extension) and optional display text. + Covers both `[[link]]` and `[[link|display]]`. + - `TransclusionNode` — target and optional anchor string. + Covers `![[link]]`, `![[link#heading]]`, and KitchenMD Step References (`![[file#section:N]]` and `![[file#N]]`). + The anchor is passed through as-is; Step Reference resolution is out of scope for the parser. + - `IngredientNode` — name, optional quantity string, optional unit string. + - `CookwareNode` — name, optional quantity string, optional unit string. + - `TimerNode` — value string (single) or value + high strings (range), and a canonical unit abbreviation. + +- remark is used internally as the CommonMark parser (see ADR 0002). + OFM wikilinks and transclusions are handled by `remark-wiki-link` and its underlying micromark and mdast-util packages. + KitchenMD annotations are processed by a custom remark transform plugin that walks mdast text nodes outside code contexts and splits them into annotation Inline Nodes. + remark types do not appear in `@kitchen-md/core`'s public API (see ADR 0003). + An internal translation layer maps remark's mdast output to core's own types before returning. + +- Annotation parsing naturally respects CommonMark inline scoping: the annotation transform plugin operates only on mdast text nodes, which do not appear inside code spans or code blocks. + No additional scoping logic is required. + +- Timer unit aliases are normalised to canonical abbreviations at parse time (`mins` → `min`, `hours` → `hr`, etc.). + The full alias table is defined in the Timer Annotation entry of the domain glossary. + +- Quantity strings are preserved as-is (e.g. `"1 1/2"`, `"0.5"`, `"1/2"`). + No numeric coercion or arithmetic is performed at the parser level. + +- Core's own types are defined in a dedicated types module within `@kitchen-md/core` and re-exported from the package entry point alongside `parse`. + +## Testing Decisions + +- All tests assert the public `parse` function's output. + No remark internals, no transform plugin internals, no mdast types appear in tests. + +- **Unit tests** use inline raw strings only — no filesystem access. + Each test passes a Recipe File string to `parse` and asserts the returned Document AST. + Coverage must include: + - Frontmatter passthrough (arbitrary fields, empty frontmatter, no frontmatter) + - Each Block type: heading (all levels), paragraph, ordered list, unordered list, code block, thematic break + - Each Inline Node type: plain text, emphasis, strong, code span, link, WikilinkNode, TransclusionNode + - Ingredient Annotation: name, quantity, unit; multi-word name; unit-less quantity; no quantity + - Cookware Annotation: name with quantity and unit; name with no quantity; multi-word name + - Timer Annotation: single value form; range form; all supported unit aliases normalised to canonical form + - Annotations embedded mid-sentence (not at the start of a line) + - Annotations inside code spans — not extracted + - Annotations inside code blocks — not extracted + - A Step Reference transclusion — anchor passed through as-is + +- **Integration tests** pass the content of `fixtures/basic.md` through `parse` and assert the complete Document AST, covering all annotation types, OFM features, and frontmatter together in a single realistic input. + +- Tests are co-located with the source module and follow the `{module}_test.ts` naming convention established in the project scaffold. + +## Out of Scope + +- Quantity arithmetic or numeric normalisation (e.g. `1/2` → `0.5`). + Quantities are preserved as strings. +- Unit normalisation for Ingredient and Cookware units. + Those units are free-form and passed through as-is. +- Step counting and Step Reference resolution. + The parser surfaces `TransclusionNode` with the raw anchor; resolution is a consumer concern. +- Combined Recipe validation. +- Aisle mapping. +- Shopping list generation. +- CLI implementation (covered by the cli-view spec). + +## Further Notes + +- The "built from scratch" statement in the project spec refers to not forking Cooklang's parser. + Using remark as an internal dependency is consistent with that intent — see ADR 0002. +- The annotation transform plugin running only on text nodes is what enforces CommonMark scoping for free, without any explicit code-span or code-block detection logic in the plugin itself. +- `RawBlock` is a safety valve, not a target. + Implementation should aim to model all block types that appear in recipe fixtures explicitly. diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..bec3779 --- /dev/null +++ b/biome.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.5.3/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": false + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineWidth": 100 + }, + "linter": { + "enabled": true, + "rules": { + "preset": "recommended" + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double", + "trailingCommas": "all", + "semicolons": "always" + } + }, + "assist": { + "enabled": true, + "actions": { + "source": { + "organizeImports": "on" + } + } + } +} diff --git a/bun.lock b/bun.lock index b61c851..9142b64 100644 --- a/bun.lock +++ b/bun.lock @@ -5,6 +5,7 @@ "": { "name": "kitchen-md", "devDependencies": { + "@biomejs/biome": "^2.5.3", "bun-types": "latest", }, }, @@ -24,6 +25,24 @@ }, }, "packages": { + "@biomejs/biome": ["@biomejs/biome@2.5.3", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.5.3", "@biomejs/cli-darwin-x64": "2.5.3", "@biomejs/cli-linux-arm64": "2.5.3", "@biomejs/cli-linux-arm64-musl": "2.5.3", "@biomejs/cli-linux-x64": "2.5.3", "@biomejs/cli-linux-x64-musl": "2.5.3", "@biomejs/cli-win32-arm64": "2.5.3", "@biomejs/cli-win32-x64": "2.5.3" }, "bin": { "biome": "bin/biome" } }, "sha512-MrJswFdei9EfDwwUy2tQrPDpK0AO+RmMFvBoaaJ6ayBc3sUbHdCE+XG5N8vp+5So41ZupZJQm0roHFFhMGVD7A=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.5.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QhYP9muVQ0nUO5zztFuPbEwi4+94sJWVjaZds9aMi1l/KNZBiUjdiSUrGHsTaMGDXrYl+r4AS2sUKfgH3w+V3g=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.5.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-NC1Ss13UaW7QZX+y8j44bF7AP0jSJdBl6iRhe0MAkvaSqZy+mWg3GaXsrb+eSoHoGDBtaXWEbMVV0iVN2cZ7cQ=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.5.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-ksx1KWeyYW18ILL04msF/J4ZBtBDN33znYK8Z/aNv/vlBVxL9/g3mGP+omgHJKy4+KWbK87vcmmpmurfNjSgiA=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.5.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-fccix0w6xp6csCXgxeC0dU/3ecgRQal0y+cv2SP9ajNlhe7Yrk2Ug7UDe2j9AT9ZDYitkXpvUKgZjjuoYeP4Vg=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.5.3", "", { "os": "linux", "cpu": "x64" }, "sha512-yMkJtilsgvILDcVkh187aVLTb64xYsrxYajx5kym+r1ULkO5HUOfu9AYKLGQbOVLwJtT2utNw7hhFNg+17mUYA=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.5.3", "", { "os": "linux", "cpu": "x64" }, "sha512-O/yU9YKRUiHhmcjF2f38PSjseVk3G4VLWYc0G2HWpzdBVREV6G8IGWIVEFf7MFPfWIzNUIvPsEjeAZQIOgnLcQ=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.5.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-cX5z+GYwRcqEok0AH3KSfQGgqYd0Nomfp6Fbe1uiTtELE38hdH2k842wQ9wLNaF/JJ7r4rjJQ4VR+ce+fRmQbw=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.5.3", "", { "os": "win32", "cpu": "x64" }, "sha512-ExSaJWi4/u6+GXCszlSKpWSjKNbDseAYqqkCznsCsZ/4uidZ/BEqsCc5/3ctlq6dfIubdIIRSVLC/PG9xPl70Q=="], + "@kitchen-md/bin": ["@kitchen-md/bin@workspace:packages/bin"], "@kitchen-md/core": ["@kitchen-md/core@workspace:packages/core"], diff --git a/package.json b/package.json index e0218f4..7efc269 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,17 @@ "name": "kitchen-md", "version": "0.0.0", "private": true, - "workspaces": ["packages/core", "packages/bin"], + "workspaces": [ + "packages/core", + "packages/bin" + ], "scripts": { - "test": "bun test" + "test": "bun test", + "lint": "biome check .", + "format": "biome check --write ." }, "devDependencies": { + "@biomejs/biome": "^2.5.3", "bun-types": "latest" } }