gridmd 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # gridmd
2
+
3
+ The **GridMD** reference implementation: a parser + linter and a two-way
4
+ `.gmd` ⇄ `.xlsx` converter, plus a bounded formula evaluator that *verifies*
5
+ cached values (SPEC §6 — writers must never fabricate caches). Strict
6
+ TypeScript, runs on [Bun](https://bun.sh), published to npm as `gridmd`.
7
+
8
+ This is the semantic reference for the cross-language conformance suite
9
+ (`../conformance/`): its canonical model dump defines the contract every other
10
+ implementation (`../go`, `../rust`, `../swift`) must match byte-for-byte.
11
+
12
+ ## Setup
13
+
14
+ ```bash
15
+ bun install # one lockfile (bun.lock), one runtime dep (yaml)
16
+ ```
17
+
18
+ Requires Bun ≥ 1.3. Node ≥ 20 is only needed to *run the published package*
19
+ (the built `dist/` is plain ESM); development uses Bun to run the `.ts` sources
20
+ directly.
21
+
22
+ ## Commands
23
+
24
+ ```bash
25
+ bun test # run the suite (bunfig gate: 100% line coverage)
26
+ bun run test:coverage # same, with the coverage table
27
+ bun run typecheck # tsc --noEmit (strict) over src, bin, test
28
+ bun run build # bundle dist/ (JS via bun build, .d.ts via tsc)
29
+
30
+ # dev tools (run the .ts sources directly; paths relative to js/)
31
+ bun run lint:example # lint ../examples/quarterly-report.gmd
32
+ bun run xlsx:example # → ../examples/quarterly-report.xlsx
33
+ bun run roundtrip:example # gmd → xlsx → gmd, then re-lint
34
+ bun run dump <file.gmd> # canonical conformance dump to stdout
35
+
36
+ # the CLIs directly (dev)
37
+ bun bin/gridmd-lint.ts [--lenient] <file.gmd> …
38
+ bun bin/gridmd-dump.ts <file.gmd> # conformance dump
39
+ bun bin/gridmd2xlsx.ts <file.gmd> [-o out.xlsx] [--strict]
40
+ bun bin/xlsx2gridmd.ts <file.xlsx> [-o out.gmd]
41
+ bun bin/gridmd-calc.ts <file.gmd> … # verify cached values
42
+ ```
43
+
44
+ ## Library API
45
+
46
+ ```ts
47
+ import {
48
+ lint, parseDocument,
49
+ buildWorkbookModel, writeXlsx, xlsxToGridmd, dumpModel,
50
+ verifyCachedValues, createEvaluator,
51
+ } from 'gridmd';
52
+ import type { WorkbookModel, Sheet, CellContent, Scalar, Diagnostic, LintResult } from 'gridmd';
53
+
54
+ const { doc, errors } = lint(source); // parse + validate
55
+ const model = buildWorkbookModel(doc); // → workbook model
56
+ const { buffer, report } = writeXlsx(model); // → .xlsx (Buffer) + fidelity report
57
+ const dump = dumpModel(model); // → canonical conformance JSON
58
+ const { gmd } = xlsxToGridmd(buffer); // .xlsx → GridMD
59
+ const { mismatches, unsupported } = verifyCachedValues(model);
60
+ ```
61
+
62
+ The full model/diagnostic shapes are exported as types (`Sheet`, `Cell`,
63
+ `CellContent`, `Scalar`, `WorkbookModel`, `ChartModel`, …).
64
+
65
+ ## Coverage gate
66
+
67
+ The `bunfig.toml` gate enforces **100 % line coverage** (`bun test` fails
68
+ otherwise). The suite hits every line of `src/**` — verified via lcov.
69
+
70
+ **Why line coverage and not function coverage?** Bun's *function*-coverage
71
+ metric has a confirmed false negative: it reports 98.8 % functions for
72
+ `src/calc.ts` and blames one anonymous arrow it cannot name (lcov emits **no**
73
+ `FN`/`FNDA` entry for it). To rule out a real gap, every function and callback
74
+ in `calc.ts` was instrumented with a file-based hit marker and the whole suite
75
+ run — **all of them fire**. So the code is genuinely 100 %-covered; the 98.8 %
76
+ is a Bun instrumentation artifact, not a missing test. Line coverage (the
77
+ metric Bun measures correctly, and the one the cross-language contract cares
78
+ about) is therefore the gate. This is the one documented coverage exception.
79
+
80
+ ## npm publishing
81
+
82
+ ```jsonc
83
+ // package.json (already configured)
84
+ "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" } }
85
+ "bin": { "gridmd-lint", "gridmd2xlsx", "xlsx2gridmd" } // → dist/bin/*.js (node shebang)
86
+ "files": ["dist"]
87
+ "prepublishOnly": "bun run build && bun test"
88
+ ```
89
+
90
+ `bun run build` produces `dist/index.js` (bundled, `yaml` kept external so
91
+ consumers dedupe it), `dist/bin/*.js` (node-runnable CLIs), and the `.d.ts`
92
+ type surface. `npm publish` runs `prepublishOnly` (build + full suite) first.
93
+ Consumers that touch the `Buffer`-typed APIs (`writeXlsx`, `zipRead/zipWrite`)
94
+ need `@types/node` — standard for a Node library.
95
+
96
+ ## CODING_PRACTICES adherence
97
+
98
+ Applies `~/Dev/bella-team-files/CODING_PRACTICES.md` §1 (TypeScript boundary
99
+ safety): explicit return types on exports; strict + `noUncheckedIndexedAccess`
100
+ + `verbatimModuleSyntax`; `catch (e: unknown)` with narrowing; exhaustive
101
+ switches with `never`/throw defaults; no `as`-casts on untrusted input; the
102
+ GridMD source is validated by the `lint` pass before any model is built.
103
+
104
+ ### Deliberate divergences
105
+
106
+ This is a zero-backend polyglot library, not a Next/Nest app, so the
107
+ Next/Nest-specific rules don't apply. Two intentional, contained divergences:
108
+
109
+ 1. **YAML-derived data is typed as a permissive `Meta` alias (`= any`), not a
110
+ web of speculative interfaces.** The `SPEC` allows `x-` extension keys and
111
+ open per-directive shapes, so directive metadata (`meta`/`props`/`body`,
112
+ frontmatter) enters as parsed YAML and is validated by the `lint` pass, not
113
+ the type system. The *stable* surface — scalars, cells, sheets, the
114
+ workbook model, diagnostics, the block tree — is fully, strictly typed
115
+ (`src/types.ts`), and the byte-identical conformance suite + 100 % line
116
+ coverage are the real validation. Typing the open YAML fully would have
117
+ risked the port's byte-for-byte guarantee for no safety gain. See the header
118
+ of `src/types.ts`.
119
+
120
+ 2. **The theme-tokens/no-`any` rule is relaxed only for that YAML surface**;
121
+ everywhere else (the model, XLSX emit/parse, the evaluator) is `any`-free.
122
+
123
+ The port's overriding invariant is **behaviour-identical, byte-identical
124
+ output**: the four conformance dumps, the example `.xlsx`, and the round-trip
125
+ `.gmd` are all verified byte-for-byte against the pre-migration JS reference.
126
+ ```