HF-249 bullet 3: generate built-in functions docs from the HF API (single source of truth)#1699
Conversation
|
Task linked: HF-249 HF function documentation available via API |
Performance comparison of head (490c6eb) vs base (40b6468) |
|
Paired tests PR: handsontable/hyperformula-tests#19 |
A traceability audit (run during HF-300) found migrated shortDescriptions that either misstate behavior or leak markup into the plain-text metadata API. Per Kuba's call (Slack #hyperformula-dev, 2026-07-15) they belong on the parent HF-249 branch, since the catalogue is becoming the single source of truth (docs/guide generated from it at build): - XNPV: was verbatim identical to NPV; now conveys its non-periodic/date-based nature. - MIRR: "modified internal value" -> "modified internal rate of return". - SPLIT/TEXT: dropped <br> + markdown (rendered literally through the API); TEXT now also mentions the stringifyCurrency option. - SECH: "given angle (in radians)" -> "given value" (the argument is a plain number). - BASE: "positive integer" -> "non-negative integer" (0 is accepted by the impl). - typos: MROUND "neares"/"multiplicity", Fischer->Fisher, densitity->density, skeweness->skewness (x2). Catalogue-only; docs/guide regenerates from these once #1699 lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ation preserves it (HF-249)
…API (HF-249) getAvailableFunctions/getFunctionDetails excluded the protected functions OFFSET and VERSION because they have no plugin for resolveFunctionMetadata to read arity from. A user can still call both from a formula, so they must be documented too: getListableFunctionIds (static and instance) now include the protected ids, and resolveFunctionMetadata resolves them from a new authored PROTECTED_FUNCTION_METADATA map together with their catalogue FunctionDoc entries in the lookup-and-reference and information categories.
…d VERSION (HF-249)
…venance comments (HF-249) Mirror buildAvailableFunctions' canonicalName tiebreaker in the built-in functions table renderer so equal localizedNames sort deterministically regardless of input order. Also soften the information/lookup-and-reference category file comments, which claimed full ownership by scripts/hf249-migrate-function-docs.ts even though they now carry hand-authored protected-function entries (VERSION, OFFSET).
…1692 refactor (HF-249) Rebasing #1699 onto the refactored #1692 combined that branch's protected-aware resolveFunctionMetadata (which surfaces VERSION/OFFSET) with #1692's rewritten static getFunctionDetails, which bails at `plugin === undefined` before reaching the protected path. Result: getAvailableFunctions listed VERSION/OFFSET but getFunctionDetails returned undefined for them, so the docs generator threw "No details for listed function VERSION". Handle the protected ids explicitly in the plugin-less branch, mirroring getAvailableFunctions, so the list and the details API agree again. Protected ids without a catalogue doc still resolve to undefined, so both stay consistent there. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…I drift gate (HF-249) Run docs:generate-functions as the first step of docs:build and docs:dev so the built-in-functions table is a build product of the catalogue, not a hand-kept artifact. With the table regenerated on every build it can never drift, so remove the redundant docs:functions:check CI step and its npm alias, and update DEV_DOCS to describe the build-time regeneration instead of a CI staleness check. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tion (HF-249) The catalogue short descriptions carry presentational markdown (<br>, links, footnote refs) that the guide table renders. Add stripDocMarkup and apply it when building Tier-2 details, so getFunctionDetails returns plain prose. The Tier-1 list entry keeps the raw markdown, so the generated table's links stay clickable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…g references (HF-249) The catalogue is now the source of truth and the guide is generated from it, so the one-time, reverse-direction migration script (guide -> catalogue) is a footgun. Delete it and soften the ~16 provenance comments that named it so they no longer point at a removed file, while keeping the note about SUM/SUMIF carrying hand-authored examples. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ue convention (HF-249) OFFSET was added to the catalogue on this branch before #1692 standardized every parameter name to snake_case, so after the rebase it was the lone PascalCase entry (Reference/Rows/Columns/Height/Width) among snake_case siblings. Align it, so getFunctionDetails('OFFSET') and the generated table read consistently. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4b5ef17 to
490c6eb
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 490c6eb. Configure here.
| "docs:code-examples:generate-all-js": "bash docs/code-examples-generator.sh --generateAll", | ||
| "docs:code-examples:format-all-ts": "bash docs/code-examples-generator.sh --formatAllTsExamples", | ||
| "snippets:extract": "node script/extract-doc-snippets.js", | ||
| "docs:generate-functions": "npm run tsnode scripts/generate-builtin-functions-doc.ts", |
There was a problem hiding this comment.
Drift check npm script missing
Medium Severity
The PR adds a --check mode on scripts/generate-builtin-functions-doc.ts for CI drift detection, but package.json only defines docs:generate-functions (write path). There is no docs:functions:check script to run --check, so the documented drift gate is easy to omit from CI unless callers hard-code the tsnode invocation.
Reviewed by Cursor Bugbot for commit 490c6eb. Configure here.
| // a user can call them from a formula: resolve them here from the authored catalogue doc and structural | ||
| // metadata instead of from a plugin. Functions without a catalogue entry stay unlisted. | ||
| if (FunctionRegistry.functionIsProtected(functionId) && FUNCTION_DOCS[functionId] !== undefined) { | ||
| return {doc: FUNCTION_DOCS[functionId], metadata: PROTECTED_FUNCTION_METADATA[functionId]} |
There was a problem hiding this comment.
Undefined protected metadata crashes
Low Severity
For protected function ids, resolveFunctionMetadata can return a catalogue doc with metadata set to PROTECTED_FUNCTION_METADATA[functionId] when that key is missing. buildFunctionDetails then reads metadata.repeatLastArgs without optional chaining on metadata, which throws when metadata is undefined.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 490c6eb. Configure here.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## feature/hf-249-function-metadata-api #1699 +/- ##
========================================================================
+ Coverage 96.43% 96.45% +0.01%
========================================================================
Files 192 195 +3
Lines 15589 15648 +59
Branches 3447 3458 +11
========================================================================
+ Hits 15034 15094 +60
+ Misses 555 554 -1
🚀 New features to boost your workflow:
|


HF-249 bullet 3 — the docs functions table is generated from HyperFormula (single source of truth)
Third in-scope bullet of HF-249: the built-in functions table in
docs/guide/built-in-functions.mdis generated from the public metadata API (getAvailableFunctions/getFunctionDetails), so function data lives in one place — the catalogue insrc/interpreter/functionMetadata/.What's here
src/interpreter/functionMetadata/(browser-safe, not exported from the package index):formatFunctionSyntax,renderBuiltinFunctionsTable,spliceFunctionsTable. Deterministic (pinnedIntl.Collator, LF, byte-idempotent).scripts/generate-builtin-functions-doc.ts(excluded from the npm package viatsconfig include:["src"]): sources data only from the API and splices the table between theAUTOGENERATED:FUNCTIONSmarkers; hand-written prose and footnote defs stay outside.npm run docs:generate-functionsruns as the first step ofdocs:buildanddocs:dev, so the committed table is a build product that can never drift. The olddocs:functions:checkCI drift-gate and its npm alias are removed.getFunctionDetailsreturns plain text (stripDocMarkup):<br>, links, and footnote refs are stripped from the details API, while the generated table keeps the raw markdown so its links stay clickable. The Tier-1getAvailableFunctionslist entries stay raw — they are the generator's source.getFunctionDetailsis now protected-aware so it agrees withgetAvailableFunctions. OFFSET's parameter names are snake_case, matching the Function metadata API: getAvailableFunctions / getFunctionDetails (HF-249) #1692 catalogue convention.docs → cataloguemigration script is deleted (the catalogue is now the source); its dangling provenance comments are softened.<a id="canonicalName">) on every row. The table documents 421 functions.Decisions to confirm (defaults taken — happy to flip)
docs:generate-functionsprepended todocs:build/docs:dev) rather than a VuePress plugin — simpler and deterministic.docs:functions:checkstep is removed as redundant.getFunctionDetails.shortDescriptionis plain text;getAvailableFunctionsentries stay raw markdown because they're the generator's source. This is the one field that differs across the two API tiers — flag if you'd prefer uniform stripping with the generator reading raw from the catalogue instead.Verification
npm run docs:buildgreen; the table is present and correct in the built site (421 functions incl. OFFSET/VERSION, snake_case syntax).tsc --noEmit+lintclean.feature/hf-249-docs-single-source, rebased onto the updated API tests (snake_case fixtures; OFFSET/VERSION now assert full details rather thanundefined).Base:
feature/hf-249-function-metadata-api(ships with the HF-249 API in #1692).Note
Medium Risk
Changes public metadata API surface (protected
VERSION/OFFSETnow listable) and replaces a large generated doc snapshot; runtime formula behavior is largely unchanged.Overview
The built-in functions guide is no longer hand-edited in bulk: the region between
AUTOGENERATED:FUNCTIONSmarkers inbuilt-in-functions.mdis produced fromgetAvailableFunctions/getFunctionDetails, withformatFunctionSyntax,renderBuiltinFunctionsTable, andspliceFunctionsTableinfunctionMetadata/. A dev scriptnpm run docs:generate-functionsrefreshes the file;--checkfails on byte drift or function-ID set changes.docs:devanddocs:buildrun generation first so the committed table stays aligned.The old docs → catalogue migration script is removed; catalogue edits in
src/interpreter/functionMetadata/are now the source.VERSIONandOFFSETare included in the metadata API and the generated table viaPROTECTED_FUNCTION_METADATAand catalogue entries, even though they are not ordinary registered plugins.getFunctionDetailsreturns plain-text descriptions (stripDocMarkup); the guide table keeps richer markup for links and footnotes.Minor doc tweaks: removed the standalone “Function metadata” section from the guide (covered by the API elsewhere), per-row anchors for deep links, and updated CHANGELOG / DEV_DOCS contributor notes.
Reviewed by Cursor Bugbot for commit 490c6eb. Bugbot is set up for automated code reviews on this repo. Configure here.