import { BlockDefinition, BuildComponentOptions, ComponentOptions, ComponentRegistryEntry, EvaluatedBlock, ForgeComponent, RenderedBlock } from "@ministryofjustice/hmpps-forge/core/components"; import { Forge, ForgeRouterAdapter } from "@ministryofjustice/hmpps-forge/core"; import { GeneratorRegistry } from "@ministryofjustice/hmpps-forge/core/authoring"; import { ForgeRenderer, NodeId, RenderBlock, RenderContext } from "@ministryofjustice/hmpps-forge/core/framework"; import express from "express"; import nunjucks from "nunjucks"; //#region forge-express-nunjucks/src/adapter/createExpressRouter.d.ts /** * Options for {@link createExpressRouter}. Passed through verbatim to the * `NunjucksRenderer` the router builds, so each mounted router gets its own * renderer configuration. */ interface ExpressForgeRouterOptions { /** * Nunjucks environment used to load and render page templates. The same * environment is handed to components at render time via their `renderer` * parameter, so component templates and macros resolve against it too. */ nunjucksEnv: nunjucks.Environment; /** * Template used when neither the step nor its journey ancestors resolve a * `view.template`. The `.njk` extension is appended automatically when not * present. * * @default 'form-step' */ defaultTemplate?: string; /** * When true, the `blocks` array handed to page templates carries `{ html, block }` * entries pairing each rendered string with its `RenderBlock` data (id, variant, * block type, and evaluated properties including any authored `metadata`). * When false, `blocks` is plain rendered HTML strings. * * @default false */ includeBlockData?: boolean; } declare function createExpressRouter(forge: Forge, options: ExpressForgeRouterOptions): express.Router; //#endregion //#region forge-express-nunjucks/src/adapter/ExpressFrameworkAdapter.d.ts /** * @deprecated Build the router directly with `createExpressRouter(forge, options)`. */ interface ExpressForgeAdapter extends ForgeRouterAdapter { build(forge: Forge): express.Router; } /** * @deprecated Build the router directly with `createExpressRouter(forge, options)`. */ declare const ExpressFrameworkAdapter: { configure(options: ExpressForgeRouterOptions): ExpressForgeAdapter; }; //#endregion //#region forge-express-nunjucks/src/renderer/NunjucksRenderer.d.ts interface NunjucksRendererOptions { /** * Nunjucks environment used to load and render page templates. The same * environment is handed to components at render time via their `renderer` * parameter, so component templates and macros resolve against it too. * Compiled templates are cached per renderer instance. */ nunjucksEnv: nunjucks.Environment; /** * Template used when neither the step nor its journey ancestors resolve a * `view.template`. The `.njk` extension is appended automatically when not * present. * * @default 'form-step' */ defaultTemplate?: string; /** * When true, the `blocks` array handed to page templates carries `{ html, block }` * entries pairing each rendered string with its `RenderBlock` data (id, variant, * block type, and evaluated properties including any authored `metadata`), * index-aligned with `RenderContext.blocks` - invisible blocks stay in the array * with `html: ''`. When false, `blocks` is plain rendered HTML strings. * * @default false * * @example * ```njk * {% for entry in blocks %} * {% if entry.block.properties.metadata.region == 'sidebar' %} * {{ entry.html | safe }} * {% endif %} * {% endfor %} * ``` */ includeBlockData?: boolean; } declare class NunjucksRenderer implements ForgeRenderer { private static readonly TEMPLATE_EXTENSION; private static readonly FALLBACK_TEMPLATE; private readonly nunjucksEnv; private readonly defaultTemplate; private readonly includeBlockData; private readonly templateCache; private readonly cachedRenderer; constructor(options: NunjucksRendererOptions); renderBlock(entry: ComponentRegistryEntry, block: EvaluatedBlock): string; /** Bracket a block's HTML with paired comment markers so devtools can locate it in the rendered DOM. */ markBlock(nodeId: NodeId, output: string): string; wrapNestedBlock(block: BlockDefinition, output: string): RenderedBlock; assemblePage(context: RenderContext, renderedBlocks: readonly string[], requestState: Record): string; private buildTemplateBlocks; private resolveTemplate; private renderTemplate; } //#endregion //#region forge-express-nunjucks/src/renderer/types.d.ts /** Page-level block entry passed to templates when the renderer is configured with `includeBlockData: true` */ interface TemplateBlock { html: string; block: RenderBlock; } //#endregion //#region forge-express-nunjucks/src/utils/buildNunjucksComponent.d.ts /** * Render function for Nunjucks components. * Receives the evaluated block and a nunjucks environment (passed as renderer by TemplateRenderer). */ type NunjucksComponentRenderer = (block: EvaluatedBlock, nunjucksEnv: nunjucks.Environment) => string; /** * Creates a Nunjucks component that receives its renderer at render time. * * Prefer `nunjucksComponent` for new components - one block interface plus one call * replaces the props interface, block interface, wrapper function and this registration. * This function will be deprecated once the built-in components have moved over. * * @param variant - The block variant identifier * @param render - Render function that receives (block, nunjucksEnv) * @param options - Optional input schema and fixed-shape `multiple` flag for the entry * @returns A component ready for registration with Forge * * @example * ```typescript * export const myTextInput = buildNunjucksComponent( * 'myTextInput', * (block, nunjucksEnv) => { * return nunjucksEnv.render('components/text-input.njk', { block }) * } * ) * ``` */ declare const buildNunjucksComponent: (variant: string, render: NunjucksComponentRenderer, options?: BuildComponentOptions) => ComponentRegistryEntry; //#endregion //#region forge-express-nunjucks/src/utils/nunjucksComponent.d.ts /** * Defines a Nunjucks component from a single block interface - `component()` with the * renderer pinned, so the render callback receives a typed `nunjucks.Environment`. * * @example * ```typescript * export interface MyTextInput extends FieldBlockDefinition { * label: ResolvableString * } * * export const MyTextInput = nunjucksComponent('myTextInput', { * field: true, * render: (props, nunjucksEnv) => * nunjucksEnv.render('components/text-input.njk', { params: { name: props.code } }), * }) * ``` */ declare function nunjucksComponent(variant: string, options: ComponentOptions): ForgeComponent; //#endregion //#region forge-express-nunjucks/src/generators/nunjucksGenerators.d.ts /** * Shape for the Nunjucks-backed generator. */ interface NunjucksStringGeneratorProps { template: string; data?: Record; } declare const nunjucksGenerators: GeneratorRegistry>; declare const NunjucksGenerators: { /** * Render a Nunjucks template to a ResolvableString expression. * * Values interpolated via `{{ name }}` are HTML-escaped automatically. Use * `{{ name | safe }}` when the value is trusted HTML. Forge evaluates * expressions inside `data` before the template runs, so the template sees * resolved primitives only. * * Templates are intentionally restricted to inline display composition: * `{% import %}`, `{% from %}`, `{% include %}`, `{% extends %}`, and * `{% macro %}` are rejected at author-call time. If you need reusable * composition logic, extract a custom generator or component instead. */ String(props: import("@ministryofjustice/hmpps-forge/core/authoring").Resolvable): import("@ministryofjustice/hmpps-forge/core/authoring").ChainableGenerator; }; //#endregion export { type ExpressForgeAdapter, type ExpressForgeRouterOptions, ExpressFrameworkAdapter, type NunjucksComponentRenderer, NunjucksGenerators, NunjucksRenderer, type NunjucksRendererOptions, type TemplateBlock, buildNunjucksComponent, createExpressRouter, nunjucksComponent, nunjucksGenerators as nunjucksFunctions };