Skip to content

docs: generate component and page type documentation from forms-model types#380

Open
alexluckett wants to merge 41 commits intomainfrom
docs/components
Open

docs: generate component and page type documentation from forms-model types#380
alexluckett wants to merge 41 commits intomainfrom
docs/components

Conversation

@alexluckett
Copy link
Copy Markdown
Contributor

@alexluckett alexluckett commented May 1, 2026

Proposed change

Adds a build-time documentation generator that reads @defra/forms-model TypeScript declaration files and produces Markdown pages for every component type and page controller, keeping docs automatically in sync with model changes.

The generator walks the TypeScript AST to resolve full inheritance chains, intersection types, and indexed access types (e.g. DateFieldBase['options'] & { condition?: string }). Human-readable descriptions and cross-links are maintained in component-metadata.json.

Each component page includes a JSON example, properties table, options table, and schema constraints table. Each page controller page includes a JSON example and configuration table, with index pages for both sections. Also rewrites the plugin options docs as a table and adds custom controllers and custom filters sections.

This also fixes the documentation build-time issue when extra-long page names were encountered.

Jira ticket:

Technical summary

scripts/generate-component-docs.js runs pre-build and outputs into docs/features/components/ and docs/features/pages/ (both gitignored). It uses the TypeScript compiler API — rather than string parsing — to read @defra/forms-model's .d.ts files, so inheritance chains and complex type expressions resolve correctly. Descriptions and cross-links are kept separately in scripts/component-metadata.json so the generator stays logic-only.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Misc. (documentation, build updates, etc)

Checklist

  • You have executed this code locally and it performs as expected.
  • You have added tests to verify your code works.
  • You have added code comments and JSDoc, where appropriate.
  • There is no commented-out code.
  • You have added developer docs in README.md and docs/* (where appropriate, e.g. new features).
  • The tests are passing (npm run test).
  • The linting checks are passing (npm run lint).
  • The code has been formatted (npm run format).

@alexluckett alexluckett changed the title docs: generate component and page type documentation from forms-model types docs: Add component and page type documentation May 1, 2026
@alexluckett alexluckett changed the title docs: Add component and page type documentation docs: generate component and page type documentation from forms-model types May 1, 2026
alexluckett added 27 commits May 1, 2026 22:24
The @adobe/jsonschema2md tool slugifies JSON schema titles into filenames.
The @defra/forms-model v2 schema has deeply nested titles that compound on
each other (e.g. "Components (array)" → "Components (array) Item" →
"Components (array)  Item (object)"), producing filenames of ~252 chars.
As .md files they fit within the 255-byte OS limit, but Docusaurus writing
them as .html pushes them to 257+ bytes, causing ENAMETOOLONG on Linux CI.

Add simplifyNestedTitles() which strips the parent title prefix from child
titles before jsonschema2md runs (e.g. "Components (array) Item" → "Item").
The original title is passed down the hierarchy so multi-level stripping
works correctly. Whitespace is normalised when matching to handle the
double-space present in some schema titles.
Page metadata is now `controllerKey: description` strings only, matching
the shape of component metadata. Labels, controller values, sidebar
positions, unique properties, and JSON examples are all derived from the
TypeScript interfaces in @defra/forms-model at generation time.
- Add fs.existsSync guards for enumsDtsPath and formDefinitionDtsPath
- Warn when a page key in metadata.pages has no matching interface data
- Export pure functions and guard main() for testability
- Add 45 unit tests covering all exported pure functions
- Fix predocs:dev to run both generators (schema + component)
…component notes

- Remove BASE_OPTION_PROPS and BASE_PAGE_PROPS filters so all props appear
  in each component/page table, sorted alphabetically; props typed as
  undefined (e.g. section on PageSummary) are automatically excluded
- Derive CONTROLLER_INTERFACE_MAP from ControllerType enum instead of hardcoding
- Derive CONTROLLER_PATH_HINTS from ControllerPath enum instead of hardcoding
- Remove PAGES_WITHOUT_NEXT; derive from uniqueProps at example generation time
- Remove GEOSPATIAL_NAMES and payment category; geospatial/payment components
  now appear under Input fields
- Add componentLinks metadata for HiddenField (pre-populate state) and all
  five geospatial components (map/API key requirement)
- Document ordnanceSurveyApiKey/Secret in plugin-options.md with a
  Geospatial map section
- Add pageProperties descriptions for all universal page props
…eferences

- Fix features/index.md heading links — relative paths from an index page
  require the parent directory name to resolve correctly against the base URL
- Add componentLinks note on FileUploadField pointing to FileUploadPageController
- Add pageLinks support to generatePageMd for page-level supplementary notes
- Add pageLinks note on FileUploadPageController pointing to file-upload.md guide
alexluckett added 11 commits May 1, 2026 22:24
…ops collection

- Collect all non-universal top-level component properties (anything not in
  type/name/title/id/options/schema) from the full inheritance chain
- Render them in a new ## Properties table above ## Options
- Remove hasList and hasContent flags — now redundant
- Surface hint and shortDescription (inherited from FormFieldBase) with descriptions
- Add list and hint descriptions to component-metadata.json
…t prop

- Hoist UNIVERSAL set to module level (was recreated on every interface iteration)
- Extract parseSourceFile helper to deduplicate read+parse+allInterfaces setup
- Exclude `next` from page props — v2 engine derives routing from pages[] order and condition
H3 subheadings under Steps 1, 6 and Foundational knowledge caused the
theme to render those H2s as non-interactive spans rather than anchor
links. Adding <!-- no-sidebar --> excludes them from sidebar generation
so every top-level step appears as a link.
- Rewrite Foundational knowledge section for conciseness
- Promote "Optional dependencies" to a proper heading
- Align CDP wording in Step 4 (both items now say "If you are on CDP")
- Remove redundant "as files" in Step 6 intro
- Fix trailing "and" on conditions bullet, expand pages bullet description
- Add missing node:path, @hapi/vision and nunjucks imports to Step 3
- Add @hapi/vision registration block (was listed as a dependency but
  never shown being registered in the full example)
- Fix viewContext return object: missing comma and string key syntax
- Add SESSION_COOKIE_PASSWORD as a required env var in Step 5
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 1, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant