@formfeed/engine 0.3.9 → 0.3.11

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.
Files changed (49) hide show
  1. package/index.cjs +2471 -354
  2. package/index.js +2471 -354
  3. package/package.json +1 -1
  4. package/types/frame/fit.d.cts +13 -0
  5. package/types/frame/fit.d.ts +13 -0
  6. package/types/frame/fit.entry.d.cts +1 -0
  7. package/types/frame/fit.entry.d.ts +1 -0
  8. package/types/frame/stage.d.cts +22 -0
  9. package/types/frame/stage.d.ts +22 -0
  10. package/types/frame/stage.entry.d.cts +1 -0
  11. package/types/frame/stage.entry.d.ts +1 -0
  12. package/types/frame/text-edit.d.cts +75 -0
  13. package/types/frame/text-edit.d.ts +75 -0
  14. package/types/frame/text-edit.entry.d.cts +1 -0
  15. package/types/frame/text-edit.entry.d.ts +1 -0
  16. package/types/index.d.cts +21 -14
  17. package/types/index.d.ts +21 -14
  18. package/types/lib/assemble.d.cts +5 -0
  19. package/types/lib/assemble.d.ts +5 -0
  20. package/types/lib/design/emit.d.cts +20 -0
  21. package/types/lib/design/emit.d.ts +20 -0
  22. package/types/lib/design/fonts.d.cts +27 -0
  23. package/types/lib/design/fonts.d.ts +27 -0
  24. package/types/lib/design/hash.d.cts +6 -0
  25. package/types/lib/design/hash.d.ts +6 -0
  26. package/types/lib/design/index.d.cts +12 -0
  27. package/types/lib/design/index.d.ts +12 -0
  28. package/types/lib/design/layers.d.cts +12 -0
  29. package/types/lib/design/layers.d.ts +12 -0
  30. package/types/lib/design/parse.d.cts +25 -0
  31. package/types/lib/design/parse.d.ts +25 -0
  32. package/types/lib/design/starters.d.cts +14 -0
  33. package/types/lib/design/starters.d.ts +14 -0
  34. package/types/lib/design/types.d.cts +171 -0
  35. package/types/lib/design/types.d.ts +171 -0
  36. package/types/lib/dialect.d.cts +32 -0
  37. package/types/lib/dialect.d.ts +32 -0
  38. package/types/lib/generated/frames.d.cts +6 -0
  39. package/types/lib/generated/frames.d.ts +6 -0
  40. package/types/lib/preview.d.cts +16 -2
  41. package/types/lib/preview.d.ts +16 -2
  42. package/types/lib/source-edit.d.cts +112 -0
  43. package/types/lib/source-edit.d.ts +112 -0
  44. package/types/lib/source-positions.d.cts +12 -3
  45. package/types/lib/source-positions.d.ts +12 -3
  46. package/types/lib/source-scan.d.cts +61 -0
  47. package/types/lib/source-scan.d.ts +61 -0
  48. package/types/lib/translation.d.cts +17 -0
  49. package/types/lib/translation.d.ts +17 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formfeed/engine",
3
- "version": "0.3.9",
3
+ "version": "0.3.11",
4
4
  "description": "The Formfeed template engine (Jinja2, Liquid, Handlebars) for the browser and Node.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Fit text to its box (plan 16 §4.3): an element with `data-ff-fit="shrink"` and a fixed size gets
3
+ * the largest font size between its own CSS size and `data-ff-fit-min` (px) at which its text fits.
4
+ * `assembleDocument` adds this script when a document contains the attribute. It runs once the fonts
5
+ * are loaded and again whenever `window.formfeedFit()` is called: the paged preview after Paged.js,
6
+ * the design stage after a stylesheet change, the render-worker before it captures. Every run starts
7
+ * from the CSS size, so it is idempotent. Bundled by `engine:frames`; keep it self-contained.
8
+ */
9
+ export declare function fits(box: HTMLElement, text: HTMLElement, win: Window): boolean;
10
+ export declare function fitBox(box: HTMLElement, win: Window): number;
11
+ export declare function installFit(win: Window & {
12
+ formfeedFit?: () => void;
13
+ }): void;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Fit text to its box (plan 16 §4.3): an element with `data-ff-fit="shrink"` and a fixed size gets
3
+ * the largest font size between its own CSS size and `data-ff-fit-min` (px) at which its text fits.
4
+ * `assembleDocument` adds this script when a document contains the attribute. It runs once the fonts
5
+ * are loaded and again whenever `window.formfeedFit()` is called: the paged preview after Paged.js,
6
+ * the design stage after a stylesheet change, the render-worker before it captures. Every run starts
7
+ * from the CSS size, so it is idempotent. Bundled by `engine:frames`; keep it self-contained.
8
+ */
9
+ export declare function fits(box: HTMLElement, text: HTMLElement, win: Window): boolean;
10
+ export declare function fitBox(box: HTMLElement, win: Window): number;
11
+ export declare function installFit(win: Window & {
12
+ formfeedFit?: () => void;
13
+ }): void;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The runtime of the design stage's frame (plan 16 §4.6). The frame shows the emitted template and
3
+ * takes no pointer events: the editor draws selection and handles in an overlay and talks to the
4
+ * frame by message. Bundled by `engine:frames`; keep it self-contained.
5
+ *
6
+ * - `formfeed:ready` (frame → editor), once the fonts are loaded and text is fitted, and again after
7
+ * every stylesheet patch: each layer's laid-out size and whether its text overflows its box.
8
+ * - `formfeed:layer-style` (editor → frame): position, size and rotation of one layer during a drag,
9
+ * applied inline; `formfeed:layer-style-clear` drops them.
10
+ * - `formfeed:css`: the template's stylesheet replaced in place, without a reload.
11
+ * - The edit session of `text-edit.ts`, addressed by layer, for typing in place.
12
+ */
13
+ export interface StageLayerBox {
14
+ id: string;
15
+ width: number;
16
+ height: number;
17
+ overflow: boolean;
18
+ }
19
+ export declare function measureLayers(doc: Document, win: Window): StageLayerBox[];
20
+ export declare function installStage(win: Window & {
21
+ formfeedFit?: () => void;
22
+ }): void;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The runtime of the design stage's frame (plan 16 §4.6). The frame shows the emitted template and
3
+ * takes no pointer events: the editor draws selection and handles in an overlay and talks to the
4
+ * frame by message. Bundled by `engine:frames`; keep it self-contained.
5
+ *
6
+ * - `formfeed:ready` (frame → editor), once the fonts are loaded and text is fitted, and again after
7
+ * every stylesheet patch: each layer's laid-out size and whether its text overflows its box.
8
+ * - `formfeed:layer-style` (editor → frame): position, size and rotation of one layer during a drag,
9
+ * applied inline; `formfeed:layer-style-clear` drops them.
10
+ * - `formfeed:css`: the template's stylesheet replaced in place, without a reload.
11
+ * - The edit session of `text-edit.ts`, addressed by layer, for typing in place.
12
+ */
13
+ export interface StageLayerBox {
14
+ id: string;
15
+ width: number;
16
+ height: number;
17
+ overflow: boolean;
18
+ }
19
+ export declare function measureLayers(doc: Document, win: Window): StageLayerBox[];
20
+ export declare function installStage(win: Window & {
21
+ formfeedFit?: () => void;
22
+ }): void;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,75 @@
1
+ /**
2
+ * The edit session inside a preview frame (plan 16 §3.3). Bundled by `engine:frames` into
3
+ * `lib/generated/frames.ts` and injected into the flow and paged previews while the editor's edit
4
+ * mode is on, so it must stay self-contained: no imports but types, nothing from module scope that a
5
+ * bundler would not inline.
6
+ *
7
+ * A click on an element marked `data-ff-edit` asks the editor (`formfeed:edit-request`); the editor
8
+ * answers with the items to show (`formfeed:edit-begin`) or a refusal. While editing, text is typed
9
+ * in place, chips are atomic, and Enter, Tab or leaving the element commit
10
+ * (`formfeed:edit-commit`), Escape cancels. The frame never writes the template: it only sends what
11
+ * the user typed. Ctrl+B, Ctrl+I and Ctrl+U format nothing here; on the design stage they are passed
12
+ * on (`formfeed:edit-style`), where they switch the style of the whole layer.
13
+ */
14
+ /** An item as the frame shows it: chips carry the text to display. */
15
+ export type FrameItem = {
16
+ kind: 'text';
17
+ text: string;
18
+ } | {
19
+ kind: 'chip';
20
+ index: number;
21
+ text: string;
22
+ title?: string;
23
+ } | {
24
+ kind: 'break';
25
+ };
26
+ /** What the frame sends back: chips by index only. */
27
+ export type FrameEditItem = {
28
+ kind: 'text';
29
+ text: string;
30
+ } | {
31
+ kind: 'chip';
32
+ index: number;
33
+ } | {
34
+ kind: 'break';
35
+ };
36
+ export interface EditBegin {
37
+ type: 'formfeed:edit-begin';
38
+ token: string;
39
+ src: string;
40
+ /** A design layer instead of a source position: its `.ff-text` is edited (the canvas, plan 16 §4.6). */
41
+ layer?: string;
42
+ /**
43
+ * Where the caret goes, in this document's viewport px. The canvas takes its clicks on an overlay
44
+ * outside the frame, so it says where the click was; without it the caret goes to the end.
45
+ */
46
+ at?: {
47
+ x: number;
48
+ y: number;
49
+ };
50
+ /** Text to type first: the key that started the session on the canvas (select a text, then type). */
51
+ insert?: string;
52
+ /** Starts with the whole text selected, so typing replaces it: a text added a moment ago holds a placeholder. */
53
+ select?: 'all';
54
+ items: FrameItem[];
55
+ allowBreaks: boolean;
56
+ /** Shown beside the element while editing ("Changes all 12"). */
57
+ note?: string;
58
+ label?: string;
59
+ }
60
+ export interface TextEditOptions {
61
+ /**
62
+ * The preview's edit mode: a click on marked text asks the editor, and undo keys are forwarded.
63
+ * The design stage starts sessions itself (its frame takes no pointer events), so it turns this off.
64
+ */
65
+ clicks?: boolean;
66
+ /**
67
+ * The design stage: report the items on every change (`formfeed:edit-input`), so what was typed
68
+ * survives a frame that goes away before its session commits (the stage is rebuilt when the editor
69
+ * switches panels, and the commit would reach no one).
70
+ */
71
+ live?: boolean;
72
+ }
73
+ export declare function installTextEdit(win: Window, options?: TextEditOptions): void;
74
+ /** The element's content as items: text, chips by index, breaks; anything the browser added is flattened. */
75
+ export declare function serialize(element: Element): FrameEditItem[];
@@ -0,0 +1,75 @@
1
+ /**
2
+ * The edit session inside a preview frame (plan 16 §3.3). Bundled by `engine:frames` into
3
+ * `lib/generated/frames.ts` and injected into the flow and paged previews while the editor's edit
4
+ * mode is on, so it must stay self-contained: no imports but types, nothing from module scope that a
5
+ * bundler would not inline.
6
+ *
7
+ * A click on an element marked `data-ff-edit` asks the editor (`formfeed:edit-request`); the editor
8
+ * answers with the items to show (`formfeed:edit-begin`) or a refusal. While editing, text is typed
9
+ * in place, chips are atomic, and Enter, Tab or leaving the element commit
10
+ * (`formfeed:edit-commit`), Escape cancels. The frame never writes the template: it only sends what
11
+ * the user typed. Ctrl+B, Ctrl+I and Ctrl+U format nothing here; on the design stage they are passed
12
+ * on (`formfeed:edit-style`), where they switch the style of the whole layer.
13
+ */
14
+ /** An item as the frame shows it: chips carry the text to display. */
15
+ export type FrameItem = {
16
+ kind: 'text';
17
+ text: string;
18
+ } | {
19
+ kind: 'chip';
20
+ index: number;
21
+ text: string;
22
+ title?: string;
23
+ } | {
24
+ kind: 'break';
25
+ };
26
+ /** What the frame sends back: chips by index only. */
27
+ export type FrameEditItem = {
28
+ kind: 'text';
29
+ text: string;
30
+ } | {
31
+ kind: 'chip';
32
+ index: number;
33
+ } | {
34
+ kind: 'break';
35
+ };
36
+ export interface EditBegin {
37
+ type: 'formfeed:edit-begin';
38
+ token: string;
39
+ src: string;
40
+ /** A design layer instead of a source position: its `.ff-text` is edited (the canvas, plan 16 §4.6). */
41
+ layer?: string;
42
+ /**
43
+ * Where the caret goes, in this document's viewport px. The canvas takes its clicks on an overlay
44
+ * outside the frame, so it says where the click was; without it the caret goes to the end.
45
+ */
46
+ at?: {
47
+ x: number;
48
+ y: number;
49
+ };
50
+ /** Text to type first: the key that started the session on the canvas (select a text, then type). */
51
+ insert?: string;
52
+ /** Starts with the whole text selected, so typing replaces it: a text added a moment ago holds a placeholder. */
53
+ select?: 'all';
54
+ items: FrameItem[];
55
+ allowBreaks: boolean;
56
+ /** Shown beside the element while editing ("Changes all 12"). */
57
+ note?: string;
58
+ label?: string;
59
+ }
60
+ export interface TextEditOptions {
61
+ /**
62
+ * The preview's edit mode: a click on marked text asks the editor, and undo keys are forwarded.
63
+ * The design stage starts sessions itself (its frame takes no pointer events), so it turns this off.
64
+ */
65
+ clicks?: boolean;
66
+ /**
67
+ * The design stage: report the items on every change (`formfeed:edit-input`), so what was typed
68
+ * survives a frame that goes away before its session commits (the stage is rebuilt when the editor
69
+ * switches panels, and the commit would reach no one).
70
+ */
71
+ live?: boolean;
72
+ }
73
+ export declare function installTextEdit(win: Window, options?: TextEditOptions): void;
74
+ /** The element's content as items: text, chips by index, breaks; anything the browser added is flattened. */
75
+ export declare function serialize(element: Element): FrameEditItem[];
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/types/index.d.cts CHANGED
@@ -2,33 +2,40 @@ export * from './lib/types.cjs';
2
2
  export { EngineSyntaxError, RenderError, RenderLimitError } from './lib/errors.cjs';
3
3
  export { defaultLimits, depthGuard, enforceLimits } from './lib/limits.cjs';
4
4
  export { DefaultHelperRegistry, EPC_MAX_BYTES, builtinHelpers, chartMarkup, chartPayload, createHelperRegistry, defaultHelpers, epcPayload, escapeHtml, helperDocs, ibanChecksum, imageMarkup, normaliseIban, qrSvg, svgDataUri, toDate, toNumber, validateEpc, } from './lib/helpers/index.cjs';
5
- export type { EpcInput, EpcPayment, EpcProblem, QrOptions } from './lib/helpers/index.cjs';
5
+ export type { EpcInput, EpcPayment, EpcProblem, QrOptions, } from './lib/helpers/index.cjs';
6
6
  export { analyzeHandlebars, analyzeJinja2, analyzeLiquid, engineIds, engines, getEngine, handlebarsEngine, jinja2Engine, liquidEngine, liquidBuiltinFilters, nunjucksBuiltinFilters, } from './lib/engines/index.cjs';
7
- export { diffSchemas, inferSchema, inferSchemaFromDataSets, schemaPaths } from './lib/schema.cjs';
7
+ export { diffSchemas, inferSchema, inferSchemaFromDataSets, schemaPaths, } from './lib/schema.cjs';
8
8
  export { defaultOutput, imageOutput, isOfficeKind, isOutputFormat, officeKinds, outputFormats, outputsForKind, type OfficeKind, type OutputFormat, } from './lib/output.cjs';
9
- export { brandCss, emptyBrand, layeredPartials, normalisePartialName } from './lib/brand.cjs';
9
+ export { brandCss, emptyBrand, layeredPartials, normalisePartialName, } from './lib/brand.cjs';
10
10
  export type { BrandContext, SharedPartial } from './lib/brand.cjs';
11
11
  export { mergeSampleData, mergeSnippetCss, mergeSnippetI18n, partialInclude, snippets, snippetsFor, snippetText, } from './lib/snippets.cjs';
12
12
  export { apitemplateRegions, importApitemplate, importApitemplateFromApi, isApitemplateHtmlTemplate, isApitemplateRegion, slugFromName, splitApitemplateCss, } from './lib/import/apitemplate.cjs';
13
- export type { ApitemplateApiTemplate, ApitemplateExport, ApitemplateListItem, ApitemplateRegion } from './lib/import/apitemplate.cjs';
14
- export type { ImportNote, ImportResult, ImportSource } from './lib/import/common.cjs';
13
+ export type { ApitemplateApiTemplate, ApitemplateExport, ApitemplateListItem, ApitemplateRegion, } from './lib/import/apitemplate.cjs';
14
+ export type { ImportNote, ImportResult, ImportSource, } from './lib/import/common.cjs';
15
15
  export { importPdfmonkey, strftimeToDateFns } from './lib/import/pdfmonkey.cjs';
16
- export type { PdfmonkeyImportOptions, PdfmonkeySettings, PdfmonkeyTemplate } from './lib/import/pdfmonkey.cjs';
17
- export { importJsreport, jsreportTemplates, readJsreportExport } from './lib/import/jsreport.cjs';
18
- export type { JsreportBundle, JsreportImportOptions, JsreportTemplate } from './lib/import/jsreport.cjs';
16
+ export type { PdfmonkeyImportOptions, PdfmonkeySettings, PdfmonkeyTemplate, } from './lib/import/pdfmonkey.cjs';
17
+ export { importJsreport, jsreportTemplates, readJsreportExport, } from './lib/import/jsreport.cjs';
18
+ export type { JsreportBundle, JsreportImportOptions, JsreportTemplate, } from './lib/import/jsreport.cjs';
19
19
  export { convertScss, isScss } from './lib/import/scss.cjs';
20
20
  export type { Snippet, SnippetGroup } from './lib/snippets.cjs';
21
- export type { JsonSchema, SchemaChange, SchemaChangeKind, SchemaDiff } from './lib/schema.cjs';
21
+ export type { JsonSchema, SchemaChange, SchemaChangeKind, SchemaDiff, } from './lib/schema.cjs';
22
22
  export { DEFAULT_CHROME_PADDING, assembleDocument, chartInitScript, defaultSettings, fontFaceCss, mergeSettings, pageSize, printReset, renderVersion, } from './lib/assemble.cjs';
23
23
  export type { ChartSpec, ImageOptions } from './lib/helpers/index.cjs';
24
- export { flowDocument, pagedDocument, pageNumberSpans, paperOf, zoomGestureScript } from './lib/preview.cjs';
25
- export type { PagedOptions, PreviewOverflow, RenderedDraft } from './lib/preview.cjs';
26
- export { annotateSourcePositions, parseSourceAttribute, sourceAttribute, } from './lib/source-positions.cjs';
27
- export type { SourceFile, SourceLocation } from './lib/source-positions.cjs';
24
+ export { canvasDocument, flowDocument, pagedDocument, pageNumberSpans, paperOf, zoomGestureScript, } from './lib/preview.cjs';
25
+ export type { PagedOptions, PreviewOptions, PreviewOverflow, RenderedDraft, } from './lib/preview.cjs';
26
+ export { annotateSourcePositions, editAttribute, parseSourceAttribute, sourceAttribute, } from './lib/source-positions.cjs';
27
+ export type { AnnotateOptions, SourceFile, SourceLocation, } from './lib/source-positions.cjs';
28
+ export { applyRegionEdit, chipValues, editableRegion, editableRegionAt, findRegionAgain, regionChips, regionItems, translationItems, translationText, } from './lib/source-edit.cjs';
29
+ export type { ApplyResult, ChipKind, EditableRegion, EditItem, RegionChip, RegionLookup, RegionPart, RegionRefusal, } from './lib/source-edit.cjs';
30
+ export { resolveTranslation, translationTarget } from './lib/translation.cjs';
31
+ export { DESIGN_LIMITS, DESIGN_VERSION, dataPathPattern, defaultLayer, designBytes, designOutputHash, designStarters, emitDesign, emptyDesign, genericFamily, googleFont, googleFonts, googleFontsUrl, imageIsEmpty, layerIdPattern, nearestWeight, nextLayerId, parseDesign, } from './lib/design/index.cjs';
32
+ export type { BarcodeLayer, BarcodeSymbology, Binding, CanvasSize, DesignDocument, DesignLayer, DesignStarter, EmittedDesign, FontChoice, GoogleFont, ImageLayer, ImageSource, LayerBase, LayerType, Paint, ParsedDesign, QrLayer, Shadow, ShapeLayer, Stroke, TextFormat, TextItem, TextLayer, TextStyle, } from './lib/design/index.cjs';
33
+ export { encodeTemplateText } from './lib/source-edit.cjs';
34
+ export type { Dictionaries } from './lib/translation.cjs';
28
35
  export type { AssembleExtras, AssembleInput, AssembleVendor, FontFace, HeaderFooterSettings, RenderedDocument, TemplateKind, TemplateSettings, VersionSource, } from './lib/assemble.cjs';
29
36
  export { resolvePath, scanBlocks, jinjaTags, liquidTags, } from './lib/analysis/tags.cjs';
30
37
  export { OFFICE_FILLED_MAX_BYTES, OfficeTemplateError, analyzeOffice, officeTextParts, renderOffice, type OfficeAnalysis, type OfficeAnalysisDiagnostic, type OfficeRenderOptions, type OfficeRenderResult, } from './lib/office/render.cjs';
31
38
  export type { OfficeTag } from './lib/office/tags.cjs';
32
39
  export { starterDocument } from './lib/office/starter.cjs';
33
40
  export { starterPresentation } from './lib/office/starter-pptx.cjs';
34
- export { officeDrawingLimits, type OfficeImageHost } from './lib/office/drawings.cjs';
41
+ export { officeDrawingLimits, type OfficeImageHost, } from './lib/office/drawings.cjs';
package/types/index.d.ts CHANGED
@@ -2,33 +2,40 @@ export * from './lib/types.js';
2
2
  export { EngineSyntaxError, RenderError, RenderLimitError } from './lib/errors.js';
3
3
  export { defaultLimits, depthGuard, enforceLimits } from './lib/limits.js';
4
4
  export { DefaultHelperRegistry, EPC_MAX_BYTES, builtinHelpers, chartMarkup, chartPayload, createHelperRegistry, defaultHelpers, epcPayload, escapeHtml, helperDocs, ibanChecksum, imageMarkup, normaliseIban, qrSvg, svgDataUri, toDate, toNumber, validateEpc, } from './lib/helpers/index.js';
5
- export type { EpcInput, EpcPayment, EpcProblem, QrOptions } from './lib/helpers/index.js';
5
+ export type { EpcInput, EpcPayment, EpcProblem, QrOptions, } from './lib/helpers/index.js';
6
6
  export { analyzeHandlebars, analyzeJinja2, analyzeLiquid, engineIds, engines, getEngine, handlebarsEngine, jinja2Engine, liquidEngine, liquidBuiltinFilters, nunjucksBuiltinFilters, } from './lib/engines/index.js';
7
- export { diffSchemas, inferSchema, inferSchemaFromDataSets, schemaPaths } from './lib/schema.js';
7
+ export { diffSchemas, inferSchema, inferSchemaFromDataSets, schemaPaths, } from './lib/schema.js';
8
8
  export { defaultOutput, imageOutput, isOfficeKind, isOutputFormat, officeKinds, outputFormats, outputsForKind, type OfficeKind, type OutputFormat, } from './lib/output.js';
9
- export { brandCss, emptyBrand, layeredPartials, normalisePartialName } from './lib/brand.js';
9
+ export { brandCss, emptyBrand, layeredPartials, normalisePartialName, } from './lib/brand.js';
10
10
  export type { BrandContext, SharedPartial } from './lib/brand.js';
11
11
  export { mergeSampleData, mergeSnippetCss, mergeSnippetI18n, partialInclude, snippets, snippetsFor, snippetText, } from './lib/snippets.js';
12
12
  export { apitemplateRegions, importApitemplate, importApitemplateFromApi, isApitemplateHtmlTemplate, isApitemplateRegion, slugFromName, splitApitemplateCss, } from './lib/import/apitemplate.js';
13
- export type { ApitemplateApiTemplate, ApitemplateExport, ApitemplateListItem, ApitemplateRegion } from './lib/import/apitemplate.js';
14
- export type { ImportNote, ImportResult, ImportSource } from './lib/import/common.js';
13
+ export type { ApitemplateApiTemplate, ApitemplateExport, ApitemplateListItem, ApitemplateRegion, } from './lib/import/apitemplate.js';
14
+ export type { ImportNote, ImportResult, ImportSource, } from './lib/import/common.js';
15
15
  export { importPdfmonkey, strftimeToDateFns } from './lib/import/pdfmonkey.js';
16
- export type { PdfmonkeyImportOptions, PdfmonkeySettings, PdfmonkeyTemplate } from './lib/import/pdfmonkey.js';
17
- export { importJsreport, jsreportTemplates, readJsreportExport } from './lib/import/jsreport.js';
18
- export type { JsreportBundle, JsreportImportOptions, JsreportTemplate } from './lib/import/jsreport.js';
16
+ export type { PdfmonkeyImportOptions, PdfmonkeySettings, PdfmonkeyTemplate, } from './lib/import/pdfmonkey.js';
17
+ export { importJsreport, jsreportTemplates, readJsreportExport, } from './lib/import/jsreport.js';
18
+ export type { JsreportBundle, JsreportImportOptions, JsreportTemplate, } from './lib/import/jsreport.js';
19
19
  export { convertScss, isScss } from './lib/import/scss.js';
20
20
  export type { Snippet, SnippetGroup } from './lib/snippets.js';
21
- export type { JsonSchema, SchemaChange, SchemaChangeKind, SchemaDiff } from './lib/schema.js';
21
+ export type { JsonSchema, SchemaChange, SchemaChangeKind, SchemaDiff, } from './lib/schema.js';
22
22
  export { DEFAULT_CHROME_PADDING, assembleDocument, chartInitScript, defaultSettings, fontFaceCss, mergeSettings, pageSize, printReset, renderVersion, } from './lib/assemble.js';
23
23
  export type { ChartSpec, ImageOptions } from './lib/helpers/index.js';
24
- export { flowDocument, pagedDocument, pageNumberSpans, paperOf, zoomGestureScript } from './lib/preview.js';
25
- export type { PagedOptions, PreviewOverflow, RenderedDraft } from './lib/preview.js';
26
- export { annotateSourcePositions, parseSourceAttribute, sourceAttribute, } from './lib/source-positions.js';
27
- export type { SourceFile, SourceLocation } from './lib/source-positions.js';
24
+ export { canvasDocument, flowDocument, pagedDocument, pageNumberSpans, paperOf, zoomGestureScript, } from './lib/preview.js';
25
+ export type { PagedOptions, PreviewOptions, PreviewOverflow, RenderedDraft, } from './lib/preview.js';
26
+ export { annotateSourcePositions, editAttribute, parseSourceAttribute, sourceAttribute, } from './lib/source-positions.js';
27
+ export type { AnnotateOptions, SourceFile, SourceLocation, } from './lib/source-positions.js';
28
+ export { applyRegionEdit, chipValues, editableRegion, editableRegionAt, findRegionAgain, regionChips, regionItems, translationItems, translationText, } from './lib/source-edit.js';
29
+ export type { ApplyResult, ChipKind, EditableRegion, EditItem, RegionChip, RegionLookup, RegionPart, RegionRefusal, } from './lib/source-edit.js';
30
+ export { resolveTranslation, translationTarget } from './lib/translation.js';
31
+ export { DESIGN_LIMITS, DESIGN_VERSION, dataPathPattern, defaultLayer, designBytes, designOutputHash, designStarters, emitDesign, emptyDesign, genericFamily, googleFont, googleFonts, googleFontsUrl, imageIsEmpty, layerIdPattern, nearestWeight, nextLayerId, parseDesign, } from './lib/design/index.js';
32
+ export type { BarcodeLayer, BarcodeSymbology, Binding, CanvasSize, DesignDocument, DesignLayer, DesignStarter, EmittedDesign, FontChoice, GoogleFont, ImageLayer, ImageSource, LayerBase, LayerType, Paint, ParsedDesign, QrLayer, Shadow, ShapeLayer, Stroke, TextFormat, TextItem, TextLayer, TextStyle, } from './lib/design/index.js';
33
+ export { encodeTemplateText } from './lib/source-edit.js';
34
+ export type { Dictionaries } from './lib/translation.js';
28
35
  export type { AssembleExtras, AssembleInput, AssembleVendor, FontFace, HeaderFooterSettings, RenderedDocument, TemplateKind, TemplateSettings, VersionSource, } from './lib/assemble.js';
29
36
  export { resolvePath, scanBlocks, jinjaTags, liquidTags, } from './lib/analysis/tags.js';
30
37
  export { OFFICE_FILLED_MAX_BYTES, OfficeTemplateError, analyzeOffice, officeTextParts, renderOffice, type OfficeAnalysis, type OfficeAnalysisDiagnostic, type OfficeRenderOptions, type OfficeRenderResult, } from './lib/office/render.js';
31
38
  export type { OfficeTag } from './lib/office/tags.js';
32
39
  export { starterDocument } from './lib/office/starter.js';
33
40
  export { starterPresentation } from './lib/office/starter-pptx.js';
34
- export { officeDrawingLimits, type OfficeImageHost } from './lib/office/drawings.js';
41
+ export { officeDrawingLimits, type OfficeImageHost, } from './lib/office/drawings.js';
@@ -70,6 +70,11 @@ export interface TemplateSettings {
70
70
  text?: string;
71
71
  opacity?: number;
72
72
  } | null;
73
+ /**
74
+ * The visual editor's document (plan 16 §4.1, `DesignDocument` once `parseDesign` accepted it). It
75
+ * is authoring data: nothing renders it, the version's HTML and CSS are what it emitted.
76
+ */
77
+ design?: unknown;
73
78
  }
74
79
  export type TemplateKind = 'pdf' | 'image';
75
80
  export declare function defaultSettings(): Required<Pick<TemplateSettings, 'paper' | 'margin' | 'printBackground' | 'scale' | 'preferCssPageSize' | 'locale' | 'timezone' | 'currency'>> & TemplateSettings;
@@ -70,6 +70,11 @@ export interface TemplateSettings {
70
70
  text?: string;
71
71
  opacity?: number;
72
72
  } | null;
73
+ /**
74
+ * The visual editor's document (plan 16 §4.1, `DesignDocument` once `parseDesign` accepted it). It
75
+ * is authoring data: nothing renders it, the version's HTML and CSS are what it emitted.
76
+ */
77
+ design?: unknown;
73
78
  }
74
79
  export type TemplateKind = 'pdf' | 'image';
75
80
  export declare function defaultSettings(): Required<Pick<TemplateSettings, 'paper' | 'margin' | 'printBackground' | 'scale' | 'preferCssPageSize' | 'locale' | 'timezone' | 'currency'>> & TemplateSettings;
@@ -0,0 +1,20 @@
1
+ import type { EngineId } from '../types.cjs';
2
+ import type { CanvasSize, DesignDocument } from './types.cjs';
3
+ /**
4
+ * A design as the template it stands for (plan 16 §4.2): the body and the CSS in the template's
5
+ * engine, deterministic, so the output hashes and diffs stably. Structure goes into the HTML (one
6
+ * line per layer) and presentation into the CSS, so moving or restyling a layer changes only the
7
+ * stylesheet. Values that reach CSS were checked by `parseDesign` and are checked again here.
8
+ */
9
+ export interface EmittedDesign {
10
+ html: string;
11
+ css: string;
12
+ /** Each layer's line range (1-based, inclusive) in `html`, to show a diagnostic on its layer. */
13
+ map: Record<string, {
14
+ start: number;
15
+ end: number;
16
+ }>;
17
+ /** `designOutputHash(html, css)`: what the design records as `output`. */
18
+ output: string;
19
+ }
20
+ export declare function emitDesign(design: DesignDocument, engine: EngineId, size: CanvasSize): EmittedDesign;
@@ -0,0 +1,20 @@
1
+ import type { EngineId } from '../types.js';
2
+ import type { CanvasSize, DesignDocument } from './types.js';
3
+ /**
4
+ * A design as the template it stands for (plan 16 §4.2): the body and the CSS in the template's
5
+ * engine, deterministic, so the output hashes and diffs stably. Structure goes into the HTML (one
6
+ * line per layer) and presentation into the CSS, so moving or restyling a layer changes only the
7
+ * stylesheet. Values that reach CSS were checked by `parseDesign` and are checked again here.
8
+ */
9
+ export interface EmittedDesign {
10
+ html: string;
11
+ css: string;
12
+ /** Each layer's line range (1-based, inclusive) in `html`, to show a diagnostic on its layer. */
13
+ map: Record<string, {
14
+ start: number;
15
+ end: number;
16
+ }>;
17
+ /** `designOutputHash(html, css)`: what the design records as `output`. */
18
+ output: string;
19
+ }
20
+ export declare function emitDesign(design: DesignDocument, engine: EngineId, size: CanvasSize): EmittedDesign;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The Google Fonts a design can pick (plan 16 §4.2, §9): a curated list, so the one `@import` the
3
+ * emitter writes only ever names families and weights Google serves — an unknown family or a weight
4
+ * a family lacks makes Google answer 400, and every font of the design would be missing. The
5
+ * render-worker's asset cache serves the stylesheet and the files like any other Google Fonts request.
6
+ */
7
+ export interface GoogleFont {
8
+ family: string;
9
+ category: 'sans-serif' | 'serif' | 'display' | 'monospace' | 'handwriting';
10
+ weights: number[];
11
+ italic: boolean;
12
+ }
13
+ export declare const googleFonts: GoogleFont[];
14
+ export declare function googleFont(family: string): GoogleFont | undefined;
15
+ /** The generic family a font falls back to in CSS. */
16
+ export declare function genericFamily(font: GoogleFont | undefined): string;
17
+ /** The weight a family serves that is closest to the one asked for (heavier on a tie). */
18
+ export declare function nearestWeight(font: GoogleFont, weight: number): number;
19
+ /**
20
+ * One stylesheet URL for every family, weight and style a design uses, or null when it uses none.
21
+ * `display=block`, so a capture never shows a fallback font.
22
+ */
23
+ export declare function googleFontsUrl(uses: Array<{
24
+ family: string;
25
+ weight: number;
26
+ italic: boolean;
27
+ }>): string | null;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The Google Fonts a design can pick (plan 16 §4.2, §9): a curated list, so the one `@import` the
3
+ * emitter writes only ever names families and weights Google serves — an unknown family or a weight
4
+ * a family lacks makes Google answer 400, and every font of the design would be missing. The
5
+ * render-worker's asset cache serves the stylesheet and the files like any other Google Fonts request.
6
+ */
7
+ export interface GoogleFont {
8
+ family: string;
9
+ category: 'sans-serif' | 'serif' | 'display' | 'monospace' | 'handwriting';
10
+ weights: number[];
11
+ italic: boolean;
12
+ }
13
+ export declare const googleFonts: GoogleFont[];
14
+ export declare function googleFont(family: string): GoogleFont | undefined;
15
+ /** The generic family a font falls back to in CSS. */
16
+ export declare function genericFamily(font: GoogleFont | undefined): string;
17
+ /** The weight a family serves that is closest to the one asked for (heavier on a tie). */
18
+ export declare function nearestWeight(font: GoogleFont, weight: number): number;
19
+ /**
20
+ * One stylesheet URL for every family, weight and style a design uses, or null when it uses none.
21
+ * `display=block`, so a capture never shows a fallback font.
22
+ */
23
+ export declare function googleFontsUrl(uses: Array<{
24
+ family: string;
25
+ weight: number;
26
+ italic: boolean;
27
+ }>): string | null;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * The hash a design keeps of the body and CSS the emitter wrote (plan 16 §4.5): equal means the design
3
+ * still owns the code, different means someone edited it. It detects edits and defends nothing, so a
4
+ * fast non-cryptographic hash does: two FNV-1a passes with different offsets, 64 bits as hex.
5
+ */
6
+ export declare function designOutputHash(html: string, css: string): string;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * The hash a design keeps of the body and CSS the emitter wrote (plan 16 §4.5): equal means the design
3
+ * still owns the code, different means someone edited it. It detects edits and defends nothing, so a
4
+ * fast non-cryptographic hash does: two FNV-1a passes with different offsets, 64 bits as hex.
5
+ */
6
+ export declare function designOutputHash(html: string, css: string): string;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * `@formfeed/engine/design`: visual designs without the template engines (plan 16 §4), for hosts that
3
+ * read or write designs but never render — the MCP server, the gateway's checks, tools. Free of
4
+ * Nunjucks, LiquidJS, Handlebars, bwip-js and date-fns; the main entry exports the same.
5
+ */
6
+ export * from './types.cjs';
7
+ export { DESIGN_LIMITS, dataPathPattern, designBytes, layerIdPattern, parseDesign, type ParsedDesign, } from './parse.cjs';
8
+ export { emitDesign, type EmittedDesign } from './emit.cjs';
9
+ export { designOutputHash } from './hash.cjs';
10
+ export { genericFamily, googleFont, googleFonts, googleFontsUrl, nearestWeight, type GoogleFont, } from './fonts.cjs';
11
+ export { defaultLayer, emptyDesign, imageIsEmpty, nextLayerId } from './layers.cjs';
12
+ export { designStarters, type DesignStarter } from './starters.cjs';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * `@formfeed/engine/design`: visual designs without the template engines (plan 16 §4), for hosts that
3
+ * read or write designs but never render — the MCP server, the gateway's checks, tools. Free of
4
+ * Nunjucks, LiquidJS, Handlebars, bwip-js and date-fns; the main entry exports the same.
5
+ */
6
+ export * from './types.js';
7
+ export { DESIGN_LIMITS, dataPathPattern, designBytes, layerIdPattern, parseDesign, type ParsedDesign, } from './parse.js';
8
+ export { emitDesign, type EmittedDesign } from './emit.js';
9
+ export { designOutputHash } from './hash.js';
10
+ export { genericFamily, googleFont, googleFonts, googleFontsUrl, nearestWeight, type GoogleFont, } from './fonts.js';
11
+ export { defaultLayer, emptyDesign, imageIsEmpty, nextLayerId } from './layers.js';
12
+ export { designStarters, type DesignStarter } from './starters.js';
@@ -0,0 +1,12 @@
1
+ import { type CanvasSize, type DesignDocument, type DesignLayer, type ImageSource, type LayerType } from './types.cjs';
2
+ /**
3
+ * An image layer whose image is not chosen yet: an empty file name, URL or data path. A new layer
4
+ * starts that way; the emitter writes an empty box for it and the editor asks for an image.
5
+ */
6
+ export declare function imageIsEmpty(source: ImageSource): boolean;
7
+ /** A design with nothing on it but a white canvas. */
8
+ export declare function emptyDesign(): DesignDocument;
9
+ /** The next free id for a layer of `type`: `text-1`, `text-2`, … */
10
+ export declare function nextLayerId(design: DesignDocument, type: LayerType): string;
11
+ /** A new layer of `type` in the middle of the canvas, sized for it. */
12
+ export declare function defaultLayer(type: LayerType, id: string, name: string, canvas: CanvasSize): DesignLayer;
@@ -0,0 +1,12 @@
1
+ import { type CanvasSize, type DesignDocument, type DesignLayer, type ImageSource, type LayerType } from './types.js';
2
+ /**
3
+ * An image layer whose image is not chosen yet: an empty file name, URL or data path. A new layer
4
+ * starts that way; the emitter writes an empty box for it and the editor asks for an image.
5
+ */
6
+ export declare function imageIsEmpty(source: ImageSource): boolean;
7
+ /** A design with nothing on it but a white canvas. */
8
+ export declare function emptyDesign(): DesignDocument;
9
+ /** The next free id for a layer of `type`: `text-1`, `text-2`, … */
10
+ export declare function nextLayerId(design: DesignDocument, type: LayerType): string;
11
+ /** A new layer of `type` in the middle of the canvas, sized for it. */
12
+ export declare function defaultLayer(type: LayerType, id: string, name: string, canvas: CanvasSize): DesignLayer;
@@ -0,0 +1,25 @@
1
+ import { type DesignDocument } from './types.cjs';
2
+ /**
3
+ * Reads a design as it arrives from `settings.design`: from the editor, but also from the API or a
4
+ * pushed `design.json`, so nothing is trusted. Every value is checked, numbers are clamped to sane
5
+ * ranges, and a problem names where it is; a design with problems is not half loaded (the editor opens
6
+ * the template as code and says so).
7
+ */
8
+ export declare const DESIGN_LIMITS: {
9
+ readonly layers: 200;
10
+ readonly textPerLayer: 5000;
11
+ readonly bytes: number;
12
+ };
13
+ export type ParsedDesign = {
14
+ design: DesignDocument;
15
+ problems: [];
16
+ } | {
17
+ design: null;
18
+ problems: string[];
19
+ };
20
+ export declare const layerIdPattern: RegExp;
21
+ /** A data path the emitter writes as is in every engine: dotted identifiers. */
22
+ export declare const dataPathPattern: RegExp;
23
+ /** A design's size as the gateway bounds it: the UTF-8 bytes of its JSON. */
24
+ export declare function designBytes(value: unknown): number;
25
+ export declare function parseDesign(value: unknown): ParsedDesign;
@@ -0,0 +1,25 @@
1
+ import { type DesignDocument } from './types.js';
2
+ /**
3
+ * Reads a design as it arrives from `settings.design`: from the editor, but also from the API or a
4
+ * pushed `design.json`, so nothing is trusted. Every value is checked, numbers are clamped to sane
5
+ * ranges, and a problem names where it is; a design with problems is not half loaded (the editor opens
6
+ * the template as code and says so).
7
+ */
8
+ export declare const DESIGN_LIMITS: {
9
+ readonly layers: 200;
10
+ readonly textPerLayer: 5000;
11
+ readonly bytes: number;
12
+ };
13
+ export type ParsedDesign = {
14
+ design: DesignDocument;
15
+ problems: [];
16
+ } | {
17
+ design: null;
18
+ problems: string[];
19
+ };
20
+ export declare const layerIdPattern: RegExp;
21
+ /** A data path the emitter writes as is in every engine: dotted identifiers. */
22
+ export declare const dataPathPattern: RegExp;
23
+ /** A design's size as the gateway bounds it: the UTF-8 bytes of its JSON. */
24
+ export declare function designBytes(value: unknown): number;
25
+ export declare function parseDesign(value: unknown): ParsedDesign;