@json-to-office/jto-ops 1.2.0 → 1.5.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/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { FontRuntimeOpts, GenerationWarning, PptxBatchRasterizer, PptxRasterizer, ResolvedFont } from '@json-to-office/shared';
1
+ import { FontRuntimeOpts, GenerationWarning, RendererStatus, PptxBatchRasterizer, PptxRasterizer, ResolvedFont } from '@json-to-office/shared';
2
+ import { QualityProfile, QualityPolicy, PreparedDocument, QualityAnalysis } from '@json-to-office/quality';
2
3
 
3
4
  type FormatName = 'docx' | 'pptx';
4
5
  interface GeneratorOptions {
@@ -37,6 +38,13 @@ interface GeneratorOptions {
37
38
  * `GeneratorResult` — allocate one array per logical request.
38
39
  */
39
40
  warnings?: GenerationWarning[];
41
+ /** Design profile and invocation-specific enforcement. */
42
+ quality?: {
43
+ profile?: QualityProfile;
44
+ policy?: QualityPolicy;
45
+ };
46
+ /** Opaque canonical prologue output shared by analysis and rendering. */
47
+ prepared?: PreparedDocument;
40
48
  }
41
49
  interface GeneratorResult {
42
50
  generateBuffer: (document: any) => Promise<Buffer>;
@@ -67,8 +75,14 @@ interface FormatAdapter {
67
75
  valid: boolean;
68
76
  errors?: any[];
69
77
  };
78
+ /** Analyze format-specific design quality with profiles, policy, and gate. */
79
+ analyzeQuality?(doc: unknown, options?: GeneratorOptions): Promise<QualityAnalysis>;
80
+ /** Prepare effective values and provenance once for official pipelines. */
81
+ prepareDocument?(doc: unknown, options?: GeneratorOptions): Promise<PreparedDocument>;
70
82
  generateSchema(options?: any): any;
71
83
  getBuiltinThemes(): Record<string, any>;
84
+ /** Full values for ESM hosts; falls back to `getBuiltinThemes` for plugins. */
85
+ getBuiltinThemeValues?(): Promise<Record<string, any>>;
72
86
  resolveTheme(options: GeneratorOptions): Promise<any>;
73
87
  loadCustomThemes(options: GeneratorOptions): Promise<Record<string, any> | undefined>;
74
88
  /**
@@ -78,6 +92,16 @@ interface FormatAdapter {
78
92
  * list is read from it rather than repeated here, so the two cannot drift.
79
93
  */
80
94
  rendererIds(): Promise<readonly string[]>;
95
+ /**
96
+ * The same renderers, each with whether its backend loads on this host.
97
+ *
98
+ * `rendererIds` answers "what is registered", which is not the same question:
99
+ * a factory only runs when its renderer is selected, so an id says nothing
100
+ * about whether the render behind it will work. Anything that *advertises*
101
+ * renderers should report this instead — otherwise a caller picks one, gets
102
+ * a green light from validation, and fails a call later.
103
+ */
104
+ rendererStatuses(): Promise<readonly RendererStatus[]>;
81
105
  /** Cumulative visual pre-pass dedupe counters (DOCX only) (#156). */
82
106
  getVisualPrepassStats?(): Promise<any>;
83
107
  /** Reset per-format cache observability counters (DOCX only). */
@@ -89,6 +113,7 @@ declare class DocxFormatAdapter implements FormatAdapter {
89
113
  label: string;
90
114
  defaultPort: number;
91
115
  rendererIds(): Promise<readonly string[]>;
116
+ rendererStatuses(): Promise<readonly RendererStatus[]>;
92
117
  generateBuffer(json: unknown, options: GeneratorOptions): Promise<Buffer>;
93
118
  createGenerator(plugins: any[], options: GeneratorOptions): Promise<GeneratorResult>;
94
119
  parseJson(input: string | object): unknown;
@@ -96,8 +121,13 @@ declare class DocxFormatAdapter implements FormatAdapter {
96
121
  valid: boolean;
97
122
  errors?: any[];
98
123
  };
124
+ analyzeQuality(doc: unknown, options?: GeneratorOptions): Promise<QualityAnalysis>;
125
+ prepareDocument(doc: unknown, options?: GeneratorOptions): Promise<PreparedDocument>;
126
+ /** Prepare into a caller-owned sink; `prepareDocument` owns the reporting. */
127
+ private prepareModel;
99
128
  generateSchema(_options?: any): any;
100
129
  getBuiltinThemes(): Record<string, any>;
130
+ getBuiltinThemeValues(): Promise<Record<string, any>>;
101
131
  resolveTheme(options: GeneratorOptions): Promise<any>;
102
132
  /**
103
133
  * Resolve `theme`/`themePath` once for a whole run: `themePath` is read a
@@ -115,6 +145,7 @@ declare class PptxFormatAdapter implements FormatAdapter {
115
145
  label: string;
116
146
  defaultPort: number;
117
147
  rendererIds(): Promise<readonly string[]>;
148
+ rendererStatuses(): Promise<readonly RendererStatus[]>;
118
149
  generateBuffer(json: unknown, options: GeneratorOptions): Promise<Buffer>;
119
150
  createGenerator(plugins: any[], options: GeneratorOptions): Promise<GeneratorResult>;
120
151
  parseJson(input: string | object): unknown;
@@ -122,8 +153,13 @@ declare class PptxFormatAdapter implements FormatAdapter {
122
153
  valid: boolean;
123
154
  errors?: any[];
124
155
  };
156
+ analyzeQuality(doc: unknown, options?: GeneratorOptions): Promise<QualityAnalysis>;
157
+ prepareDocument(doc: unknown, options?: GeneratorOptions): Promise<PreparedDocument>;
158
+ /** Prepare into a caller-owned sink; `prepareDocument` owns the reporting. */
159
+ private prepareModel;
125
160
  generateSchema(_options?: any): any;
126
161
  getBuiltinThemes(): Record<string, any>;
162
+ getBuiltinThemeValues(): Promise<Record<string, any>>;
127
163
  resolveTheme(options: GeneratorOptions): Promise<any>;
128
164
  /**
129
165
  * Resolve `theme`/`themePath` once for a whole run: `themePath` is read a
@@ -218,6 +254,55 @@ declare function createLibreOfficePptxBatchRasterizer(options?: {
218
254
  cacheDir?: string | null;
219
255
  }): PptxBatchRasterizer;
220
256
 
257
+ /**
258
+ * Text geometry from a rendered PDF — the ground truth the quality
259
+ * estimators are guessing at (#216 follow-up).
260
+ *
261
+ * The pptx preview pipeline already produces a PDF (soffice → pdftoppm) and
262
+ * uses it purely as a bitmap source. That PDF records the exact position of
263
+ * every glyph as laid out by LibreOffice — the same engine the quality rules
264
+ * try to predict. `pdftotext -bbox` (poppler, already a rasterizer
265
+ * dependency alongside pdftoppm) dumps per-word bounding boxes; this module
266
+ * parses them into slide-space points so callers can compare a rule's
267
+ * estimate against what the renderer actually did.
268
+ *
269
+ * Coordinates: PDF points (1/72 in), origin at the page's top-left corner,
270
+ * y increasing downward — the same frame as authored inches × 72. A PDF page
271
+ * rendered from a slide has the slide's dimensions, so word boxes compare
272
+ * directly against authored shape geometry with no transform.
273
+ *
274
+ * Consumers: the quality ground-truth harness (estimator calibration) today;
275
+ * a `rendered`-certainty analysis pass tomorrow.
276
+ */
277
+ /** One word as laid out on the page, in PDF points, top-left origin. */
278
+ interface PdfTextWord {
279
+ text: string;
280
+ xMin: number;
281
+ yMin: number;
282
+ xMax: number;
283
+ yMax: number;
284
+ }
285
+ /** One PDF page: its size in points plus every word poppler segmented. */
286
+ interface PdfTextPage {
287
+ widthPt: number;
288
+ heightPt: number;
289
+ words: PdfTextWord[];
290
+ }
291
+ /**
292
+ * Parse `pdftotext -bbox` output (XHTML with `<page>`/`<word>` elements).
293
+ * Pure — feed it a captured document for tests, or the runner's stdout.
294
+ */
295
+ declare function parsePdfTextBbox(bboxXml: string): PdfTextPage[];
296
+ /** True when a `pdftotext` binary is reachable — lets harnesses skip early. */
297
+ declare function pdftotextAvailable(): Promise<boolean>;
298
+ /**
299
+ * Extract per-word text geometry from a PDF on disk. One pdftotext spawn,
300
+ * output streamed through stdout — nothing else touches the filesystem.
301
+ */
302
+ declare function extractPdfTextGeometry(pdfPath: string, options?: {
303
+ timeoutMs?: number;
304
+ }): Promise<PdfTextPage[]>;
305
+
221
306
  /**
222
307
  * Make resolved fonts visible to the LibreOffice child process for the
223
308
  * duration of one PDF conversion, then clean up.
@@ -409,4 +494,4 @@ declare function emitDiagnostic(text: string, tone?: DiagnosticTone): void;
409
494
  */
410
495
  declare const stderrDiagnosticSink: DiagnosticSink;
411
496
 
412
- export { type DiagnosticSink, type DiagnosticTone, DocxFormatAdapter, type FontStageHandle, type FontStageOptions, type FontStager, FontconfigStager, type FormatAdapter, type FormatName, type GeneratorOptions, type GeneratorResult, MacOSCoreTextStager, NoopFontStager, PptxFormatAdapter, type RasterizerCacheStats, WindowsFontStager, clearRasterizerCache, createAdapter, createLibreOfficePptxBatchRasterizer, createLibreOfficePptxRasterizer, emitDiagnostic, getFontStager, getRasterizerCacheStats, runWithDiagnosticSink, stderrDiagnosticSink };
497
+ export { type DiagnosticSink, type DiagnosticTone, DocxFormatAdapter, type FontStageHandle, type FontStageOptions, type FontStager, FontconfigStager, type FormatAdapter, type FormatName, type GeneratorOptions, type GeneratorResult, MacOSCoreTextStager, NoopFontStager, type PdfTextPage, type PdfTextWord, PptxFormatAdapter, type RasterizerCacheStats, WindowsFontStager, clearRasterizerCache, createAdapter, createLibreOfficePptxBatchRasterizer, createLibreOfficePptxRasterizer, emitDiagnostic, extractPdfTextGeometry, getFontStager, getRasterizerCacheStats, parsePdfTextBbox, pdftotextAvailable, runWithDiagnosticSink, stderrDiagnosticSink };