@asterdoc/render 0.0.0-stage → 0.9.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/LICENSE +25 -0
- package/README.md +264 -2
- package/dist/check-BA5xdYgi.d.ts +69 -0
- package/dist/chunk-4QVR6LUY.js +98 -0
- package/dist/chunk-ICQLU4FL.js +630 -0
- package/dist/chunk-PNYKTSIT.js +1267 -0
- package/dist/chunk-U7LF3GN4.js +34 -0
- package/dist/context-BmjDcc_j.d.ts +32 -0
- package/dist/docx.d.ts +37 -0
- package/dist/docx.js +38 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +69 -0
- package/dist/layer-bindings-CFXyN7SM.d.ts +94 -0
- package/dist/pdf.d.ts +620 -0
- package/dist/pdf.js +4638 -0
- package/dist/signatures-DPaL4gay.d.ts +20 -0
- package/dist/signatures-cS3V0yR3.d.ts +27 -0
- package/dist/text/field-formatter.d.ts +46 -0
- package/dist/text/field-formatter.js +21 -0
- package/dist/text.d.ts +44 -0
- package/dist/text.js +77 -0
- package/package.json +103 -3
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// src/render-data.ts
|
|
2
|
+
var SPREAD_ROOTS = {
|
|
3
|
+
parties: true,
|
|
4
|
+
signatories: true,
|
|
5
|
+
annexes: true,
|
|
6
|
+
defs: true
|
|
7
|
+
};
|
|
8
|
+
var RENDER_DATA_ROOTS = /* @__PURE__ */ new Set([
|
|
9
|
+
...Object.keys(SPREAD_ROOTS),
|
|
10
|
+
"_signers",
|
|
11
|
+
"_captures"
|
|
12
|
+
]);
|
|
13
|
+
function flattenRenderData(data) {
|
|
14
|
+
const { fields, signers, captures, ...rest } = data;
|
|
15
|
+
return {
|
|
16
|
+
fields,
|
|
17
|
+
...rest,
|
|
18
|
+
...signers ? { _signers: signers } : {},
|
|
19
|
+
...captures ? { _captures: captures } : {}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function requestRenderData(request) {
|
|
23
|
+
if (request.kind !== "form") return { data: {} };
|
|
24
|
+
const fields = request.data?.fields;
|
|
25
|
+
if (fields === null || typeof fields !== "object" || Array.isArray(fields)) {
|
|
26
|
+
throw new TypeError("A form render request needs FormData: its data must hold a `fields` record.");
|
|
27
|
+
}
|
|
28
|
+
return { data: flattenRenderData(request.data), form: request.artifact };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
RENDER_DATA_ROOTS,
|
|
33
|
+
requestRenderData
|
|
34
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { EvaluationContext, HostFunction, FnSignature } from '@asterdoc/expr';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The expression context a template reads, and where its paths sit in the
|
|
5
|
+
* render data.
|
|
6
|
+
*
|
|
7
|
+
* Roots are those of every other artifact expression: `fields`, computed
|
|
8
|
+
* values by name, `parties`, and `items` for a checklist. An artifact runtime
|
|
9
|
+
* hands over its own context; a direct render builds one from the data. A
|
|
10
|
+
* printed path may also name an attachment as `annexes.<slot>`.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* How a renderer is told what template expressions can read and call.
|
|
15
|
+
*
|
|
16
|
+
* Its `context` is the one a render request carries in `ctx.expressions`
|
|
17
|
+
* (`RendererExpressions` from `@asterdoc/types`); the functions and their
|
|
18
|
+
* signatures come from the renderer's own options.
|
|
19
|
+
*/
|
|
20
|
+
interface TemplateExpressionOptions {
|
|
21
|
+
/**
|
|
22
|
+
* The artifact's expression context. `@asterdoc/core` supplies it, so a
|
|
23
|
+
* template sees exactly what field logic sees.
|
|
24
|
+
*/
|
|
25
|
+
context?: EvaluationContext;
|
|
26
|
+
/** Host-configured functions, used when no context is supplied. */
|
|
27
|
+
functions?: Readonly<Record<string, HostFunction>>;
|
|
28
|
+
/** Signatures of the configured functions. A template cannot call a function it has no signature for. */
|
|
29
|
+
signatures?: readonly FnSignature[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type { TemplateExpressionOptions as T };
|
package/dist/docx.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Form, Formatter, AsterdocRenderer, RendererLayer } from '@asterdoc/types';
|
|
2
|
+
import { T as TemplateExpressionOptions } from './context-BmjDcc_j.js';
|
|
3
|
+
import { D as DocxSignatureOptions } from './signatures-DPaL4gay.js';
|
|
4
|
+
export { D as DocxCheckOptions, T as TemplateDiagnostic, a as TemplateError, b as TemplatePosition, c as checkDocxTemplate } from './check-BA5xdYgi.js';
|
|
5
|
+
import '@asterdoc/expr';
|
|
6
|
+
|
|
7
|
+
interface DocxRenderOptions {
|
|
8
|
+
cmdDelimiter?: [string, string];
|
|
9
|
+
processLineBreaks?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface RenderDocxOptions {
|
|
12
|
+
template: Uint8Array;
|
|
13
|
+
data: Record<string, unknown>;
|
|
14
|
+
form?: Form;
|
|
15
|
+
formatter?: Formatter;
|
|
16
|
+
signatureOptions?: DocxSignatureOptions;
|
|
17
|
+
options?: DocxRenderOptions;
|
|
18
|
+
/** The expression context and configured functions templates read. */
|
|
19
|
+
expressions?: TemplateExpressionOptions;
|
|
20
|
+
/** The layer key, named in template errors. */
|
|
21
|
+
layer?: string;
|
|
22
|
+
}
|
|
23
|
+
declare function renderDocx({ template, data, form, formatter, signatureOptions, options, expressions, layer, }: RenderDocxOptions): Promise<Uint8Array>;
|
|
24
|
+
|
|
25
|
+
interface DocxRendererOptions {
|
|
26
|
+
formatter?: Formatter;
|
|
27
|
+
signatureOptions?: DocxSignatureOptions;
|
|
28
|
+
/** Configured functions templates can call when no artifact context is supplied. */
|
|
29
|
+
expressions?: Pick<TemplateExpressionOptions, 'functions' | 'signatures'>;
|
|
30
|
+
}
|
|
31
|
+
type DocxLayer = RendererLayer & {
|
|
32
|
+
type: 'docx';
|
|
33
|
+
content: Uint8Array;
|
|
34
|
+
};
|
|
35
|
+
declare function docxRenderer(options?: DocxRendererOptions): AsterdocRenderer<DocxLayer, Uint8Array>;
|
|
36
|
+
|
|
37
|
+
export { type DocxRenderOptions, type DocxRendererOptions, DocxSignatureOptions, type RenderDocxOptions, docxRenderer, renderDocx };
|
package/dist/docx.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TemplateError,
|
|
3
|
+
checkDocxTemplate,
|
|
4
|
+
renderDocx,
|
|
5
|
+
requestExpressions
|
|
6
|
+
} from "./chunk-PNYKTSIT.js";
|
|
7
|
+
import {
|
|
8
|
+
requestRenderData
|
|
9
|
+
} from "./chunk-U7LF3GN4.js";
|
|
10
|
+
import "./chunk-ICQLU4FL.js";
|
|
11
|
+
import "./chunk-4QVR6LUY.js";
|
|
12
|
+
|
|
13
|
+
// src/docx/renderer.ts
|
|
14
|
+
import { defaultFormatter } from "@asterdoc/format";
|
|
15
|
+
function docxRenderer(options = {}) {
|
|
16
|
+
const formatter = options.formatter ?? defaultFormatter;
|
|
17
|
+
return {
|
|
18
|
+
id: "docx",
|
|
19
|
+
render(request) {
|
|
20
|
+
const { data, form } = requestRenderData(request);
|
|
21
|
+
return renderDocx({
|
|
22
|
+
template: request.template.content,
|
|
23
|
+
data,
|
|
24
|
+
form,
|
|
25
|
+
formatter: request.ctx?.formatter ?? formatter,
|
|
26
|
+
signatureOptions: options.signatureOptions,
|
|
27
|
+
expressions: requestExpressions(options.expressions, request.ctx?.expressions),
|
|
28
|
+
layer: request.template.key
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
TemplateError,
|
|
35
|
+
checkDocxTemplate,
|
|
36
|
+
docxRenderer,
|
|
37
|
+
renderDocx
|
|
38
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Formatter, FormatterProgressivePolicy, AsterdocRenderer, RendererLayer } from '@asterdoc/types';
|
|
2
|
+
import { D as DocxSignatureOptions } from './signatures-DPaL4gay.js';
|
|
3
|
+
import { P as PdfFont } from './layer-bindings-CFXyN7SM.js';
|
|
4
|
+
export { L as LayerBindingsSpec, a as PdfBindingKeyError, b as PdfBindingPart, c as PdfBindingSyntaxError, p as parseBinding, r as resolveLayerBindings } from './layer-bindings-CFXyN7SM.js';
|
|
5
|
+
import { T as TextSignatureOptions } from './signatures-cS3V0yR3.js';
|
|
6
|
+
import { T as TemplateExpressionOptions } from './context-BmjDcc_j.js';
|
|
7
|
+
import '@asterdoc/expr';
|
|
8
|
+
|
|
9
|
+
/** Parse Asterdoc paths with object dots and zero-based list brackets. */
|
|
10
|
+
declare function pathSegments(path: string): string[];
|
|
11
|
+
declare function getPath(value: unknown, path: string): unknown;
|
|
12
|
+
|
|
13
|
+
/** Options shared by the MIME-selected rendering engines. */
|
|
14
|
+
interface CreateLayerRendererOptions {
|
|
15
|
+
formatter?: Formatter;
|
|
16
|
+
progressive?: FormatterProgressivePolicy;
|
|
17
|
+
textSignatureOptions?: TextSignatureOptions;
|
|
18
|
+
/** A font the PDF engine tries first, before the font a PDF layer declares. */
|
|
19
|
+
pdfFont?: PdfFont;
|
|
20
|
+
docxSignatureOptions?: DocxSignatureOptions;
|
|
21
|
+
/** Host-configured functions text and DOCX templates can call, with their signatures. */
|
|
22
|
+
expressions?: Pick<TemplateExpressionOptions, 'functions' | 'signatures'>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Render a document layer with the engine selected from `template.mimeType`.
|
|
26
|
+
*
|
|
27
|
+
* The selected renderer is imported only when it is needed. Import a format
|
|
28
|
+
* subpath directly when an application needs format-specific operations.
|
|
29
|
+
*/
|
|
30
|
+
declare function createLayerRenderer(options?: CreateLayerRendererOptions): AsterdocRenderer<RendererLayer, string | Uint8Array>;
|
|
31
|
+
|
|
32
|
+
export { type CreateLayerRendererOptions, PdfFont, createLayerRenderer, getPath, pathSegments };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PdfBindingKeyError,
|
|
3
|
+
PdfBindingSyntaxError,
|
|
4
|
+
getPath,
|
|
5
|
+
parseBinding,
|
|
6
|
+
pathSegments,
|
|
7
|
+
resolveLayerBindings
|
|
8
|
+
} from "./chunk-4QVR6LUY.js";
|
|
9
|
+
|
|
10
|
+
// src/index.ts
|
|
11
|
+
var DOCX_MIME_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
12
|
+
function unsupportedMimeType(template) {
|
|
13
|
+
const mimeType = template.mimeType ?? "(missing)";
|
|
14
|
+
throw new Error(
|
|
15
|
+
`Unsupported render layer MIME type: ${mimeType}. Use @asterdoc/render/text, @asterdoc/render/pdf, or @asterdoc/render/docx for an explicit renderer.`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
function requireContent(template) {
|
|
19
|
+
if (template.content !== void 0) return;
|
|
20
|
+
const mimeType = template.mimeType ?? "(missing)";
|
|
21
|
+
throw new Error(
|
|
22
|
+
`Render layer of MIME type ${mimeType} carries no content. Layers that name their content instead of carrying it render through a renderer registered for their MIME type; pass one in the \`renderers\` option.`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
function createLayerRenderer(options = {}) {
|
|
26
|
+
return {
|
|
27
|
+
id: "render-layer",
|
|
28
|
+
async render(request) {
|
|
29
|
+
const mimeType = request.template.mimeType?.toLowerCase();
|
|
30
|
+
if (mimeType === "text/plain" || mimeType === "text/markdown" || mimeType === "text/html") {
|
|
31
|
+
requireContent(request.template);
|
|
32
|
+
const { textRenderer } = await import("./text.js");
|
|
33
|
+
return textRenderer({
|
|
34
|
+
formatter: options.formatter,
|
|
35
|
+
progressive: options.progressive,
|
|
36
|
+
signatureOptions: options.textSignatureOptions,
|
|
37
|
+
expressions: options.expressions
|
|
38
|
+
}).render(request);
|
|
39
|
+
}
|
|
40
|
+
if (mimeType === "application/pdf") {
|
|
41
|
+
requireContent(request.template);
|
|
42
|
+
const { pdfRenderer } = await import("./pdf.js");
|
|
43
|
+
return pdfRenderer({
|
|
44
|
+
formatter: options.formatter,
|
|
45
|
+
font: options.pdfFont
|
|
46
|
+
}).render(request);
|
|
47
|
+
}
|
|
48
|
+
if (mimeType === DOCX_MIME_TYPE) {
|
|
49
|
+
requireContent(request.template);
|
|
50
|
+
const { docxRenderer } = await import("./docx.js");
|
|
51
|
+
return docxRenderer({
|
|
52
|
+
formatter: options.formatter,
|
|
53
|
+
signatureOptions: options.docxSignatureOptions,
|
|
54
|
+
expressions: options.expressions
|
|
55
|
+
}).render(request);
|
|
56
|
+
}
|
|
57
|
+
return unsupportedMimeType(request.template);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
PdfBindingKeyError,
|
|
63
|
+
PdfBindingSyntaxError,
|
|
64
|
+
createLayerRenderer,
|
|
65
|
+
getPath,
|
|
66
|
+
parseBinding,
|
|
67
|
+
pathSegments,
|
|
68
|
+
resolveLayerBindings
|
|
69
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal reader for TrueType-outline font programs: enough to map
|
|
3
|
+
* characters to glyphs, measure them, decide whether a glyph really draws
|
|
4
|
+
* something, and describe the font to a PDF reader. Nothing is shaped.
|
|
5
|
+
*/
|
|
6
|
+
/** Why a font program could not be used. */
|
|
7
|
+
type FontProgramProblem = 'unreadable' | 'unsupported-format' | 'not-embeddable';
|
|
8
|
+
|
|
9
|
+
/** A font program supplied to the PDF renderer, and the name its errors use for it. */
|
|
10
|
+
interface PdfFont {
|
|
11
|
+
/** A TrueType-outline font program (.ttf, or .otf with TrueType outlines). */
|
|
12
|
+
bytes: Uint8Array;
|
|
13
|
+
/** Where the font came from, such as its path. Errors name the font by this. */
|
|
14
|
+
source: string;
|
|
15
|
+
}
|
|
16
|
+
/** Thrown when a supplied font cannot be used, naming its source. */
|
|
17
|
+
declare class PdfFontError extends Error {
|
|
18
|
+
readonly source: string;
|
|
19
|
+
readonly problem: FontProgramProblem;
|
|
20
|
+
constructor(source: string, problem: FontProgramProblem, detail: string);
|
|
21
|
+
}
|
|
22
|
+
/** Measures text in a supplied font, the way filling and overlays draw it. */
|
|
23
|
+
interface PdfFontMetrics {
|
|
24
|
+
/**
|
|
25
|
+
* True when filling or an overlay can draw every character of `text` in
|
|
26
|
+
* this font: each has a glyph that paints, and none is in a script that
|
|
27
|
+
* needs shaping.
|
|
28
|
+
*/
|
|
29
|
+
canDraw(text: string): boolean;
|
|
30
|
+
/** The width of `text` in points at `size`, ignoring line breaks. */
|
|
31
|
+
width(text: string, size: number): number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Metrics for a supplied font, so a caller can wrap or fall back before it
|
|
35
|
+
* draws overlay text with that font.
|
|
36
|
+
*
|
|
37
|
+
* @throws {PdfFontError} when the font cannot be used, naming its source.
|
|
38
|
+
*/
|
|
39
|
+
declare function pdfFontMetrics(font: PdfFont): PdfFontMetrics;
|
|
40
|
+
|
|
41
|
+
/** The part of a layer that decides which bindings it fills with. */
|
|
42
|
+
interface LayerBindingsSpec {
|
|
43
|
+
mimeType?: string;
|
|
44
|
+
bindings?: Record<string, string>;
|
|
45
|
+
bindingsFrom?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The bindings a layer fills with: its own, or else those of the sibling layer
|
|
49
|
+
* its `bindingsFrom` names. The reference is one hop: the sibling's own
|
|
50
|
+
* `bindings`, never its `bindingsFrom`. Only bindings carry over; a layer's
|
|
51
|
+
* `format` is always its own.
|
|
52
|
+
*
|
|
53
|
+
* Only PDF layers have bindings, which map AcroForm field names to Asterdoc
|
|
54
|
+
* paths; any other layer, or a source that is not a PDF layer, gives none.
|
|
55
|
+
*
|
|
56
|
+
* Throws when `bindingsFrom` names a layer that does not exist.
|
|
57
|
+
*/
|
|
58
|
+
declare function resolveLayerBindings(layers: Record<string, LayerBindingsSpec>, layer: LayerBindingsSpec): Record<string, string> | undefined;
|
|
59
|
+
/** One path a PDF binding value reads. */
|
|
60
|
+
interface PdfBindingPart {
|
|
61
|
+
/** The path as the binding writes it, trimmed: `fields.name`, `ssn`. */
|
|
62
|
+
source: string;
|
|
63
|
+
/** Where the path sits in fill data, historically without the `fields` root. */
|
|
64
|
+
path: string;
|
|
65
|
+
/** The text after `:`, trimmed: the option a checkbox tests, or the one-based part a split binding fills. */
|
|
66
|
+
qualifier?: string;
|
|
67
|
+
}
|
|
68
|
+
/** A PDF binding value whose syntax no fill, extraction, or check can read. */
|
|
69
|
+
declare class PdfBindingSyntaxError extends Error {
|
|
70
|
+
readonly binding: string;
|
|
71
|
+
constructor(binding: string, problem: string);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Parse a PDF binding value into the paths it reads. Fill, extraction, the fit
|
|
75
|
+
* check, and validation all read bindings through this one parser.
|
|
76
|
+
*
|
|
77
|
+
* - `name` or `fields.name` reads one path.
|
|
78
|
+
* - `status:married` tests an option; `ssn:2` fills the second hyphen-separated
|
|
79
|
+
* part. Space around the `:` is ignored.
|
|
80
|
+
* - `city, state, zip` joins several whole values with `, `. A part of a joined
|
|
81
|
+
* binding takes no qualifier.
|
|
82
|
+
*
|
|
83
|
+
* @throws {PdfBindingSyntaxError} for an empty part or qualifier, or a
|
|
84
|
+
* qualifier inside a joined binding.
|
|
85
|
+
*/
|
|
86
|
+
declare function parseBinding(binding: string): PdfBindingPart[];
|
|
87
|
+
/** A PDF binding key that names no form field of the template. */
|
|
88
|
+
declare class PdfBindingKeyError extends Error {
|
|
89
|
+
/** The binding keys the template has no field for. */
|
|
90
|
+
readonly keys: string[];
|
|
91
|
+
constructor(keys: string[], templateFields: string[]);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export { type FontProgramProblem as F, type LayerBindingsSpec as L, type PdfFont as P, PdfBindingKeyError as a, type PdfBindingPart as b, PdfBindingSyntaxError as c, PdfFontError as d, type PdfFontMetrics as e, pdfFontMetrics as f, parseBinding as p, resolveLayerBindings as r };
|