feat: add kitchen view command and parser skeleton (task 0003)
Cut the first complete thread through both layers with the smallest set
of node types.
@kitchen-md/core gains a pure, total `parse` returning a
`DocumentAST` of `{ frontmatter, blocks, diagnostics }`, built from a
minimal remark pipeline (remark-parse + remark-frontmatter) with an
internal translation layer to core's own types. This slice models
frontmatter passthrough, HeadingBlock, ParagraphBlock, and TextNode;
remark's mdast does not surface in the public API.
@kitchen-md/bin gains the `view` subcommand (commander) that reads a
file, calls `parse`, and passes the AST to a pure `render` that returns
an ANSI-styled string via chalk (auto-suppressed off a TTY). Frontmatter
prints as raw YAML followed by a separator, headings styled distinctly
by level, paragraphs as prose. A missing argument prints usage and a
missing/unreadable file a human-readable error, both exiting 1.
Richer blocks/inline plus raw fallbacks are task 0004; malformed
frontmatter diagnostics and the basic.md smoke test are task 0007.
This commit is contained in:
@@ -1,5 +1,33 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { runCli, stripAnsi } from "./test-support.ts";
|
||||
|
||||
const CLI = `${import.meta.dir}/index.ts`;
|
||||
|
||||
describe("cli — integration", () => {
|
||||
test.todo("invokes core parser and produces output for a real fixture file");
|
||||
test("invokes core parser and produces output for a real fixture file", async () => {
|
||||
const dir = mkdtempSync(join(tmpdir(), "kitchen-md-"));
|
||||
const file = join(dir, "recipe.md");
|
||||
writeFileSync(
|
||||
file,
|
||||
"---\ntitle: Test Recipe\nservings: 2\n---\n\n# Heading One\n\nA plain paragraph of prose.\n",
|
||||
);
|
||||
|
||||
try {
|
||||
const { exitCode, stdout } = await runCli(["view", file], CLI);
|
||||
const output = stripAnsi(stdout);
|
||||
|
||||
expect(exitCode).toBe(0);
|
||||
expect(output).toContain("title: Test Recipe");
|
||||
expect(output).toContain("servings: 2");
|
||||
expect(output).toMatch(/─+/);
|
||||
expect(output).toContain("Heading One");
|
||||
expect(output).toContain("A plain paragraph of prose.");
|
||||
} finally {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user