@json-to-office/shared 1.2.0 → 1.4.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/dist/capabilities-DtPF3aBj.d.ts +253 -0
- package/dist/chunk-QLZNOXT5.js +734 -0
- package/dist/chunk-QLZNOXT5.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +13 -11
- package/dist/index.js.map +1 -1
- package/dist/rendering/index.d.ts +177 -181
- package/dist/rendering/index.js +31 -3
- package/dist/schemas/slide-content.d.ts +5 -1
- package/dist/schemas/slide-content.js +6 -1
- package/dist/schemas/slide-content.js.map +1 -1
- package/package.json +4 -4
- package/dist/chunk-JM5KTMNL.js +0 -240
- package/dist/chunk-JM5KTMNL.js.map +0 -1
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format-independent renderer contracts.
|
|
3
|
+
*
|
|
4
|
+
* This module deliberately knows nothing about DOCX or PPTX semantics. Each
|
|
5
|
+
* format owns its own intermediate representation (`DocxIR`, `PptxIR`) and its
|
|
6
|
+
* own feature union; the only thing shared between them is the shape of the
|
|
7
|
+
* contract a backend adapter must satisfy.
|
|
8
|
+
*
|
|
9
|
+
* Do not add format-specific feature names, IR nodes or units here.
|
|
10
|
+
*/
|
|
11
|
+
/** The Office formats this repository can produce. */
|
|
12
|
+
type OfficeFormat = 'docx' | 'pptx';
|
|
13
|
+
/**
|
|
14
|
+
* Options every renderer accepts.
|
|
15
|
+
*
|
|
16
|
+
* `deterministic` asks the adapter (and the packaging step after it) to make
|
|
17
|
+
* output byte-stable across runs: fixed zip entry timestamps, fixed core
|
|
18
|
+
* metadata timestamps, no random identifiers.
|
|
19
|
+
*
|
|
20
|
+
* `generatedAt` pins the timestamp written into package metadata. Callers that
|
|
21
|
+
* want reproducible bytes pass both.
|
|
22
|
+
*/
|
|
23
|
+
interface RenderOptions {
|
|
24
|
+
deterministic?: boolean;
|
|
25
|
+
generatedAt?: Date;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A backend that turns a format-specific IR into package bytes.
|
|
29
|
+
*
|
|
30
|
+
* @typeParam TIR - the format's intermediate representation (plain data)
|
|
31
|
+
* @typeParam TFeature - the format's feature union (see `capabilities.ts`)
|
|
32
|
+
* @typeParam TId - the string-literal union of renderer ids for the format
|
|
33
|
+
*/
|
|
34
|
+
interface OfficeRenderer<TIR, TFeature extends string, TId extends string> {
|
|
35
|
+
readonly id: TId;
|
|
36
|
+
readonly format: OfficeFormat;
|
|
37
|
+
readonly capabilities: ReadonlySet<TFeature>;
|
|
38
|
+
render(document: TIR, options?: RenderOptions): Promise<Uint8Array>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Exhaustiveness guard for discriminated-union switches.
|
|
42
|
+
*
|
|
43
|
+
* Reaching this at runtime means an IR node kind was added without a matching
|
|
44
|
+
* `case`, so it throws rather than silently dropping content.
|
|
45
|
+
*/
|
|
46
|
+
declare function assertNever(value: never, context?: string): never;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Diagnostics raised when an IR asks a renderer for something it cannot do.
|
|
50
|
+
*
|
|
51
|
+
* These are distinct from `GenerationWarning` (see `../types/warnings`), which
|
|
52
|
+
* describes authoring problems found while building the document. A renderer
|
|
53
|
+
* diagnostic describes a *backend* limitation: the document is fine, this
|
|
54
|
+
* particular adapter just cannot express part of it.
|
|
55
|
+
*/
|
|
56
|
+
type RendererDiagnosticSeverity = 'error' | 'warning';
|
|
57
|
+
/**
|
|
58
|
+
* One unsupported (or degraded) feature at one place in the IR.
|
|
59
|
+
*
|
|
60
|
+
* `path` is an IR path such as `slides[2].elements[0].fill` — not an author-JSON
|
|
61
|
+
* path — because the check runs against compiled IR. Compilers record the
|
|
62
|
+
* authoring path alongside where it is useful for the message text.
|
|
63
|
+
*/
|
|
64
|
+
interface RendererDiagnostic<TFeature extends string = string> {
|
|
65
|
+
feature: TFeature;
|
|
66
|
+
path: string;
|
|
67
|
+
severity: RendererDiagnosticSeverity;
|
|
68
|
+
message: string;
|
|
69
|
+
}
|
|
70
|
+
interface UnsupportedRendererFeatureErrorInit<TFeature extends string = string> {
|
|
71
|
+
format: OfficeFormat;
|
|
72
|
+
rendererId: string;
|
|
73
|
+
diagnostics: readonly RendererDiagnostic<TFeature>[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Aggregated failure thrown *before* rendering starts.
|
|
77
|
+
*
|
|
78
|
+
* One error carries every unsupported feature found in the IR so a caller sees
|
|
79
|
+
* the whole gap at once instead of fixing them one render at a time.
|
|
80
|
+
*/
|
|
81
|
+
declare class UnsupportedRendererFeatureError<TFeature extends string = string> extends Error {
|
|
82
|
+
readonly code = "UNSUPPORTED_RENDERER_FEATURE";
|
|
83
|
+
readonly format: OfficeFormat;
|
|
84
|
+
readonly rendererId: string;
|
|
85
|
+
/** Distinct unsupported features, in first-seen order. */
|
|
86
|
+
readonly features: readonly TFeature[];
|
|
87
|
+
/** Distinct IR paths that required them, in first-seen order. */
|
|
88
|
+
readonly paths: readonly string[];
|
|
89
|
+
/** Every error-severity diagnostic that produced this failure. */
|
|
90
|
+
readonly diagnostics: readonly RendererDiagnostic<TFeature>[];
|
|
91
|
+
constructor(init: UnsupportedRendererFeatureErrorInit<TFeature>);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* A renderer id that is not registered for the format asked for.
|
|
95
|
+
*
|
|
96
|
+
* Caller input, not an infrastructure failure — which is the whole reason it is
|
|
97
|
+
* a class with a `code` rather than a bare `Error`. A server matching on the
|
|
98
|
+
* message text could only answer `500`, so an unknown id looked like the
|
|
99
|
+
* service falling over, and a retry looked worth attempting (#263).
|
|
100
|
+
*/
|
|
101
|
+
declare class UnknownRendererError extends Error {
|
|
102
|
+
readonly code = "UNKNOWN_RENDERER";
|
|
103
|
+
readonly format: OfficeFormat;
|
|
104
|
+
/** What the caller asked for. */
|
|
105
|
+
readonly rendererId: string;
|
|
106
|
+
/** Every id registered for this format, in registration order. */
|
|
107
|
+
readonly availableIds: readonly string[];
|
|
108
|
+
constructor(format: OfficeFormat, rendererId: string, availableIds: readonly string[]);
|
|
109
|
+
}
|
|
110
|
+
/** Build a `RendererDiagnostic` with `severity: 'error'`. */
|
|
111
|
+
declare function rendererError<TFeature extends string>(feature: TFeature, path: string, message: string): RendererDiagnostic<TFeature>;
|
|
112
|
+
/** Build a `RendererDiagnostic` with `severity: 'warning'`. */
|
|
113
|
+
declare function rendererWarning<TFeature extends string>(feature: TFeature, path: string, message: string): RendererDiagnostic<TFeature>;
|
|
114
|
+
/** Split diagnostics into blocking errors and non-blocking warnings. */
|
|
115
|
+
declare function partitionDiagnostics<TFeature extends string>(diagnostics: readonly RendererDiagnostic<TFeature>[]): {
|
|
116
|
+
errors: RendererDiagnostic<TFeature>[];
|
|
117
|
+
warnings: RendererDiagnostic<TFeature>[];
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Capability checking: what an IR *requires* versus what an adapter *provides*.
|
|
122
|
+
*
|
|
123
|
+
* A compiler records one `FeatureRequirement` each time it emits an IR node that
|
|
124
|
+
* needs a backend capability. Before rendering, `assertRendererSupports` diffs
|
|
125
|
+
* those requirements against the adapter's `capabilities` set and throws a
|
|
126
|
+
* single aggregated `UnsupportedRendererFeatureError` if anything is missing.
|
|
127
|
+
*
|
|
128
|
+
* The point is that nothing is dropped silently: a feature either appears in the
|
|
129
|
+
* adapter's capability set and is rendered, or it fails loudly before bytes are
|
|
130
|
+
* produced.
|
|
131
|
+
*/
|
|
132
|
+
/** One capability an IR node needs, and where in the IR it was needed. */
|
|
133
|
+
interface FeatureRequirement<TFeature extends string = string> {
|
|
134
|
+
feature: TFeature;
|
|
135
|
+
/** IR path, e.g. `sections[0].children[3].image`. */
|
|
136
|
+
path: string;
|
|
137
|
+
/** Optional detail folded into the failure message. */
|
|
138
|
+
detail?: string;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Accumulates feature requirements during compilation.
|
|
142
|
+
*
|
|
143
|
+
* Deliberately per-compilation (never module-global) so concurrent generations
|
|
144
|
+
* never share state.
|
|
145
|
+
*/
|
|
146
|
+
declare class FeatureRequirementCollector<TFeature extends string> {
|
|
147
|
+
private readonly requirements;
|
|
148
|
+
private readonly seen;
|
|
149
|
+
/**
|
|
150
|
+
* Record that `feature` is needed at `path`.
|
|
151
|
+
*
|
|
152
|
+
* Duplicate (feature, path) pairs collapse, so a compiler can call this
|
|
153
|
+
* unconditionally inside a loop without inflating the diagnostics.
|
|
154
|
+
*/
|
|
155
|
+
require(feature: TFeature, path: string, detail?: string): void;
|
|
156
|
+
/** Every recorded requirement, in first-seen order. */
|
|
157
|
+
list(): readonly FeatureRequirement<TFeature>[];
|
|
158
|
+
/** Distinct required features, in first-seen order. */
|
|
159
|
+
features(): readonly TFeature[];
|
|
160
|
+
/** True when nothing has been required yet. */
|
|
161
|
+
isEmpty(): boolean;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Diff required features against a capability set.
|
|
165
|
+
*
|
|
166
|
+
* Returns one error-severity diagnostic per unsupported requirement. An empty
|
|
167
|
+
* array means the renderer can render the IR.
|
|
168
|
+
*/
|
|
169
|
+
declare function diagnoseUnsupportedFeatures<TFeature extends string>(required: readonly FeatureRequirement<TFeature>[], capabilities: ReadonlySet<TFeature>, rendererId: string): RendererDiagnostic<TFeature>[];
|
|
170
|
+
/**
|
|
171
|
+
* Throw one aggregated error if the renderer is missing any required feature.
|
|
172
|
+
*
|
|
173
|
+
* Call this after compiling to IR and before handing the IR to an adapter.
|
|
174
|
+
*/
|
|
175
|
+
declare function assertRendererSupports<TFeature extends string>(required: readonly FeatureRequirement<TFeature>[], renderer: Pick<OfficeRenderer<unknown, TFeature, string>, 'id' | 'format' | 'capabilities'>): void;
|
|
176
|
+
/**
|
|
177
|
+
* Whether a registered renderer can actually run on this host.
|
|
178
|
+
*
|
|
179
|
+
* Registration says a renderer exists; it says nothing about whether its
|
|
180
|
+
* backend is installed, because the factory is only invoked on selection. A
|
|
181
|
+
* discovery surface that reports the ids alone therefore advertises renderers
|
|
182
|
+
* that fail at the first render — which is what `jto_info` and `jto_discover`
|
|
183
|
+
* used to do for `office-open` on a host that never installed it.
|
|
184
|
+
*/
|
|
185
|
+
interface RendererStatus<TId extends string = string> {
|
|
186
|
+
id: TId;
|
|
187
|
+
/** The one used when a caller passes no id. */
|
|
188
|
+
default: boolean;
|
|
189
|
+
available: boolean;
|
|
190
|
+
/** Why not, when not — the message the load failure carried. */
|
|
191
|
+
reason?: string;
|
|
192
|
+
/** The command that would make it available. */
|
|
193
|
+
installHint?: string;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* A registry of renderers for a single format.
|
|
197
|
+
*
|
|
198
|
+
* Instances are created per format module, not per generation, and hold only
|
|
199
|
+
* immutable adapter descriptors — never per-document state.
|
|
200
|
+
*/
|
|
201
|
+
declare class RendererRegistry<TIR, TFeature extends string, TId extends string> {
|
|
202
|
+
private readonly format;
|
|
203
|
+
private readonly defaultId;
|
|
204
|
+
private readonly renderers;
|
|
205
|
+
constructor(format: OfficeFormat, defaultId: TId);
|
|
206
|
+
/**
|
|
207
|
+
* Register a lazily-constructed renderer.
|
|
208
|
+
*
|
|
209
|
+
* The factory is async and only invoked on selection, so choosing one
|
|
210
|
+
* renderer never imports another one's backend.
|
|
211
|
+
*/
|
|
212
|
+
register(id: TId, factory: () => Promise<OfficeRenderer<TIR, TFeature, TId>>): void;
|
|
213
|
+
/** Renderer ids registered for this format, in registration order. */
|
|
214
|
+
ids(): readonly TId[];
|
|
215
|
+
/** The id used when a caller does not pass one. */
|
|
216
|
+
getDefaultId(): TId;
|
|
217
|
+
has(id: string): id is TId;
|
|
218
|
+
/**
|
|
219
|
+
* Resolve a renderer, defaulting when `id` is omitted.
|
|
220
|
+
*
|
|
221
|
+
* An unknown id is `UnknownRendererError`, which carries the id asked for and
|
|
222
|
+
* the ones that exist, so a caller boundary can answer "bad request" rather
|
|
223
|
+
* than "the server broke". A backend that will not load is re-thrown with an
|
|
224
|
+
* actionable install hint.
|
|
225
|
+
*/
|
|
226
|
+
resolve(id?: TId): Promise<OfficeRenderer<TIR, TFeature, TId>>;
|
|
227
|
+
/**
|
|
228
|
+
* Every registered renderer, with whether it can actually be loaded here.
|
|
229
|
+
*
|
|
230
|
+
* Answers the question by loading each one, which is the only answer that
|
|
231
|
+
* cannot be wrong — a resolver check would still miss a backend that
|
|
232
|
+
* resolves and then throws on import.
|
|
233
|
+
*
|
|
234
|
+
* Memoized, and the promise rather than its value, so concurrent callers
|
|
235
|
+
* share one probe instead of racing several. Nothing installs a package into
|
|
236
|
+
* a running process, so the answer cannot go stale within one; without this
|
|
237
|
+
* `jto_validate` would pay a package import on every call, which is the tool
|
|
238
|
+
* an agent uses after every edit.
|
|
239
|
+
*/
|
|
240
|
+
statuses(): Promise<RendererStatus<TId>[]>;
|
|
241
|
+
private statusCache?;
|
|
242
|
+
private probeStatuses;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* `Error.name` marking a renderer whose optional backend is not installed.
|
|
246
|
+
*
|
|
247
|
+
* A name rather than a subclass: the error crosses a package boundary and an
|
|
248
|
+
* `instanceof` there would depend on both sides loading the same copy of this
|
|
249
|
+
* module, which under a workspace layout is not something to rely on.
|
|
250
|
+
*/
|
|
251
|
+
declare const RENDERER_DEPENDENCY_MISSING = "RendererDependencyMissingError";
|
|
252
|
+
|
|
253
|
+
export { type FeatureRequirement as F, type OfficeFormat as O, RENDERER_DEPENDENCY_MISSING as R, UnknownRendererError as U, FeatureRequirementCollector as a, type OfficeRenderer as b, type RenderOptions as c, type RendererDiagnostic as d, type RendererDiagnosticSeverity as e, RendererRegistry as f, type RendererStatus as g, UnsupportedRendererFeatureError as h, type UnsupportedRendererFeatureErrorInit as i, assertNever as j, assertRendererSupports as k, diagnoseUnsupportedFeatures as l, rendererWarning as m, partitionDiagnostics as p, rendererError as r };
|