@json-to-office/jto-ops 4.1.0 → 4.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/index.d.ts +192 -10
- package/dist/index.js +703 -57
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FontRuntimeOpts, ServicesConfig, GenerationWarning, RendererStatus, PptxBatchRasterizer, PptxRasterizer, ResolvedFont } from '@json-to-office/shared';
|
|
2
|
-
import { QualityProfile, QualityPolicy, PreparedDocument, QualityAnalysis, QualityDiagnostic } from '@json-to-office/quality';
|
|
1
|
+
import { FontRuntimeOpts, ServicesConfig, GenerationWarning, RendererStatus, PptxBatchRasterizer, PptxRasterizer, JsonBlockDefinition, BlockSlot, ResolvedFont } from '@json-to-office/shared';
|
|
2
|
+
import { QualityProfile, QualityPolicy, PreparedDocument, QualityAnalysis, QualityRulePack, QualityDiagnostic, QualityAnalyzeOptions } from '@json-to-office/quality';
|
|
3
3
|
|
|
4
4
|
type FormatName = 'docx' | 'pptx';
|
|
5
5
|
interface GeneratorOptions {
|
|
@@ -401,6 +401,20 @@ declare function extractPdfFonts(pdfPath: string, options?: {
|
|
|
401
401
|
timeoutMs?: number;
|
|
402
402
|
}): Promise<PdfFontInfo[]>;
|
|
403
403
|
|
|
404
|
+
/**
|
|
405
|
+
* The rendered pass as a quality rule pack (#344).
|
|
406
|
+
*
|
|
407
|
+
* `draftRenderedFindings` measures; these rules are how the measurement
|
|
408
|
+
* enters the quality contract. Each rule owns one code, one description the
|
|
409
|
+
* design guide prints, and the defaults a profile or policy can move. All of
|
|
410
|
+
* them read a single `rendered/geometry` fact — the PDF's word boxes, its
|
|
411
|
+
* embedded fonts and the document's text inventory — and share one matching
|
|
412
|
+
* pass over it, memoised per fact, so eight rules cost one search.
|
|
413
|
+
*/
|
|
414
|
+
|
|
415
|
+
type RenderedRuleId = 'rendered/clip' | 'rendered/spill' | 'rendered/overlap' | 'rendered/text-missing' | 'rendered/font-substituted' | 'rendered/empty-page' | 'rendered/heading-stranded' | 'rendered/paragraph-split';
|
|
416
|
+
declare const RENDERED_QUALITY_RULES: QualityRulePack;
|
|
417
|
+
|
|
404
418
|
/**
|
|
405
419
|
* Locate authored text in rendered PDF geometry.
|
|
406
420
|
*
|
|
@@ -456,12 +470,34 @@ interface TextOccurrence {
|
|
|
456
470
|
endPageIndex: number;
|
|
457
471
|
parts: OccurrencePart[];
|
|
458
472
|
}
|
|
473
|
+
/**
|
|
474
|
+
* Word indices in the order a reader takes them, decided from geometry
|
|
475
|
+
* rather than from the order poppler emitted them: poppler 24 lists a table
|
|
476
|
+
* row line by line across every cell, poppler 26 lists it cell by cell, and
|
|
477
|
+
* an authored string in a wrapped cell only survives the second.
|
|
478
|
+
*
|
|
479
|
+
* Rows are grouped by vertical overlap and split into fragments at gaps
|
|
480
|
+
* wider than half the line is tall. A row of two or more fragments opens a
|
|
481
|
+
* column block; the rows under it belong to the block while each of their
|
|
482
|
+
* fragments sits inside one column (a right-aligned cell's second line
|
|
483
|
+
* starts further right; a wrapped label's later lines are the only
|
|
484
|
+
* fragment of their row) and the rows stay a line apart. A block reads
|
|
485
|
+
* column by column, so a cell's lines come out together; a row of one
|
|
486
|
+
* fragment outside any block — prose — reads as it lies.
|
|
487
|
+
*/
|
|
488
|
+
declare function readingOrder(words: readonly PdfTextWord[]): number[];
|
|
459
489
|
/** What an inventory entry needs to be matched: its text, in reading order. */
|
|
460
490
|
interface InventoryEntry {
|
|
461
491
|
path: string;
|
|
462
492
|
text: string;
|
|
463
493
|
/** Header/footer text repeats per page: every occurrence is legitimate. */
|
|
464
494
|
repeats?: boolean;
|
|
495
|
+
/**
|
|
496
|
+
* Painted by the renderer from other authored text — a contents entry —
|
|
497
|
+
* so it claims its occurrence when there is one and is `skipped`, never
|
|
498
|
+
* `missing`, when there is not.
|
|
499
|
+
*/
|
|
500
|
+
optional?: boolean;
|
|
465
501
|
}
|
|
466
502
|
type MappingStatus = 'mapped' | 'ambiguous' | 'missing' | 'skipped';
|
|
467
503
|
interface InventoryMatch<T extends InventoryEntry = InventoryEntry> {
|
|
@@ -493,8 +529,8 @@ interface InventoryAssignment<T extends InventoryEntry> {
|
|
|
493
529
|
* stream without those words; each claims the first unclaimed occurrence at
|
|
494
530
|
* or after the previous claim, which is how "Total" in the second table
|
|
495
531
|
* finds the second "Total". An entry with no occurrence is `missing` —
|
|
496
|
-
* fully clipped, or never set — and one whose every
|
|
497
|
-
* claimed is `ambiguous`.
|
|
532
|
+
* fully clipped, or never set — unless it is optional, and one whose every
|
|
533
|
+
* occurrence was already claimed is `ambiguous`.
|
|
498
534
|
*/
|
|
499
535
|
declare function assignInventory<T extends InventoryEntry>(pages: readonly PdfTextPage[], inventory: readonly T[]): InventoryAssignment<T>;
|
|
500
536
|
|
|
@@ -518,11 +554,17 @@ declare function assignInventory<T extends InventoryEntry>(pages: readonly PdfTe
|
|
|
518
554
|
* Pure: geometry and fonts are extracted by the caller (see
|
|
519
555
|
* `extractPdfTextGeometry`, `extractPdfFonts`), so every rule here is
|
|
520
556
|
* testable from captured fixtures with no converter on the host.
|
|
557
|
+
*
|
|
558
|
+
* The checks draft findings; the quality engine turns them into
|
|
559
|
+
* diagnostics. Each check is one rule of `RENDERED_QUALITY_RULES`, so a
|
|
560
|
+
* profile can switch one off or move its severity, a policy can suppress
|
|
561
|
+
* one at a pointer and a gate can make one blocking — the same levers every
|
|
562
|
+
* static rule answers to, applied to the pass that measures.
|
|
521
563
|
*/
|
|
522
564
|
|
|
523
565
|
/** One authored string the pass can match rendered words back to. */
|
|
524
566
|
interface RenderedTextEntry extends InventoryEntry {
|
|
525
|
-
role: 'heading' | 'body' | 'list-item' | 'table-header' | 'table-cell' | 'statistic' | 'caption' | 'chrome' | 'slide-text';
|
|
567
|
+
role: 'heading' | 'body' | 'list-item' | 'table-header' | 'table-cell' | 'statistic' | 'caption' | 'toc-entry' | 'chrome' | 'slide-text';
|
|
526
568
|
level?: number;
|
|
527
569
|
/** A declared box the text must fit: a docx frame, a pptx text box. */
|
|
528
570
|
box?: {
|
|
@@ -544,6 +586,8 @@ interface RequestedFont {
|
|
|
544
586
|
}
|
|
545
587
|
interface RenderedAnalysisInput {
|
|
546
588
|
format: 'docx' | 'pptx';
|
|
589
|
+
/** Renderer identity, for a profile that declares renderer targets. */
|
|
590
|
+
renderer?: string;
|
|
547
591
|
pages: readonly PdfTextPage[];
|
|
548
592
|
inventory: readonly RenderedTextEntry[];
|
|
549
593
|
/** Fonts the PDF carries; `undefined` when the host could not inspect them. */
|
|
@@ -557,21 +601,159 @@ interface RenderedAnalysisSummary {
|
|
|
557
601
|
words: number;
|
|
558
602
|
/** Inventory entries by mapping outcome. */
|
|
559
603
|
inventory: Record<MappingStatus, number>;
|
|
560
|
-
/** Findings by mapping outcome. */
|
|
604
|
+
/** Findings by mapping outcome, after suppressions. */
|
|
561
605
|
findings: Record<RenderedMapping, number>;
|
|
562
606
|
fonts?: {
|
|
563
607
|
requested: number;
|
|
564
608
|
substituted: number;
|
|
565
609
|
};
|
|
610
|
+
/** Findings a policy suppression removed. */
|
|
611
|
+
suppressed: number;
|
|
612
|
+
/** Whether a policy gate made any finding blocking. */
|
|
613
|
+
blocked: boolean;
|
|
614
|
+
/** Whether a policy `maxDiagnostics` budget cut the findings returned. */
|
|
615
|
+
truncated: boolean;
|
|
616
|
+
/** The quality profile the pass ran under, when one applied. */
|
|
617
|
+
profileId?: string;
|
|
566
618
|
}
|
|
567
619
|
interface RenderedAnalysis {
|
|
568
|
-
|
|
620
|
+
/** The pass's diagnostics, as the quality engine finalised them. */
|
|
621
|
+
findings: readonly QualityDiagnostic[];
|
|
569
622
|
summary: RenderedAnalysisSummary;
|
|
623
|
+
/** The engine's own account: evaluated rules, rule errors, truncation. */
|
|
624
|
+
analysis: QualityAnalysis;
|
|
570
625
|
}
|
|
571
626
|
/** Spill below this is sub-visual: renderer rounding, descender fuzz. */
|
|
572
627
|
declare const VISIBLE_SPILL_PT = 2;
|
|
573
|
-
/**
|
|
574
|
-
|
|
628
|
+
/**
|
|
629
|
+
* Run the pass. Geometry, fonts and inventory become one `rendered/geometry`
|
|
630
|
+
* fact; the rendered rule pack reads it under the caller's profile and
|
|
631
|
+
* policy, so the findings come back suppressed, re-severed and gated the
|
|
632
|
+
* way `jto_validate`'s would.
|
|
633
|
+
*/
|
|
634
|
+
declare function analyzeRenderedDocument(input: RenderedAnalysisInput, options?: QualityAnalyzeOptions): RenderedAnalysis;
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* The block boundary matrix (#343, report portion): every JSON block
|
|
638
|
+
* definition a playground template embeds, invoked at the edges of its own
|
|
639
|
+
* slot schema — minimum and maximum cardinality, every string at its word
|
|
640
|
+
* budget, every figure at its widest — on each bundled theme, with the
|
|
641
|
+
* design fonts and with the fallback faces LibreOffice substitutes when a
|
|
642
|
+
* host lacks them, on A4 and on Letter.
|
|
643
|
+
*
|
|
644
|
+
* The generator is pure and reads nothing but the template it is handed:
|
|
645
|
+
* a definition gains coverage by being embedded, never by being listed here.
|
|
646
|
+
* What the suites do with a case — the static rules under the archetype's
|
|
647
|
+
* profile, the rendered pass over the LibreOffice PDF — is theirs; this
|
|
648
|
+
* module only says what a boundary document is.
|
|
649
|
+
*
|
|
650
|
+
* Two shapes come out. A *block case* is a small report — cover, running
|
|
651
|
+
* head, section opener — with one block at an edge in the body, so a
|
|
652
|
+
* finding names the block that caused it. A *report case* is the template's
|
|
653
|
+
* own document with every invocation at that edge, so the blocks meet each
|
|
654
|
+
* other the way they do in a real report. Both carry their definitions and
|
|
655
|
+
* dependencies inline, so nothing is resolved at render time.
|
|
656
|
+
*/
|
|
657
|
+
|
|
658
|
+
type Rec = Record<string, unknown>;
|
|
659
|
+
type MatrixEdge = 'min' | 'max';
|
|
660
|
+
type MatrixFont = 'design' | 'fallback';
|
|
661
|
+
type MatrixCanvas = 'A4' | 'LETTER';
|
|
662
|
+
interface BlockMatrixDefinition {
|
|
663
|
+
name: string;
|
|
664
|
+
/** The template the definition is embedded in, as the catalog names it. */
|
|
665
|
+
template: string;
|
|
666
|
+
/** Where inside that template: `/props/blocks/<name>`. */
|
|
667
|
+
pointer: string;
|
|
668
|
+
definition: JsonBlockDefinition;
|
|
669
|
+
/** The template's own first invocation, when it has one: the nominal fill. */
|
|
670
|
+
example?: Rec;
|
|
671
|
+
}
|
|
672
|
+
interface BlockMatrixCase {
|
|
673
|
+
id: string;
|
|
674
|
+
/** The block at its edge, or `report` for the whole template at that edge. */
|
|
675
|
+
block: string;
|
|
676
|
+
edge: MatrixEdge;
|
|
677
|
+
theme: string;
|
|
678
|
+
font: MatrixFont;
|
|
679
|
+
canvas: MatrixCanvas;
|
|
680
|
+
document: Rec;
|
|
681
|
+
}
|
|
682
|
+
interface BlockMatrixOptions {
|
|
683
|
+
themes: readonly string[];
|
|
684
|
+
fonts?: readonly MatrixFont[];
|
|
685
|
+
edges?: readonly MatrixEdge[];
|
|
686
|
+
canvases?: readonly MatrixCanvas[];
|
|
687
|
+
/** Whether the whole-template report cases are generated. Default true. */
|
|
688
|
+
report?: boolean;
|
|
689
|
+
/** Whether the per-block cases are generated. Default true. */
|
|
690
|
+
blocks?: boolean;
|
|
691
|
+
/**
|
|
692
|
+
* Slot roles the profile under test requires present, so `min` keeps them:
|
|
693
|
+
* the client-report profile's `takeaway` and `source`.
|
|
694
|
+
*/
|
|
695
|
+
requiredRoles?: readonly string[];
|
|
696
|
+
}
|
|
697
|
+
interface CaseConditions {
|
|
698
|
+
font?: MatrixFont;
|
|
699
|
+
canvas?: MatrixCanvas;
|
|
700
|
+
requiredRoles?: readonly string[];
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* The face every LibreOffice ships with, bundled inside the application on
|
|
704
|
+
* each platform: what a design font degrades to when the host lacks it, and
|
|
705
|
+
* wider than Arial or Calibri, so a fit at these metrics is a fit anywhere.
|
|
706
|
+
* Only the roles a report paints are overridden: a family declared for a
|
|
707
|
+
* role nothing uses is never embedded, and the rendered pass would report
|
|
708
|
+
* it as substituted.
|
|
709
|
+
*/
|
|
710
|
+
declare const FALLBACK_FONTS: {
|
|
711
|
+
readonly heading: {
|
|
712
|
+
readonly family: "DejaVu Sans";
|
|
713
|
+
};
|
|
714
|
+
readonly body: {
|
|
715
|
+
readonly family: "DejaVu Sans";
|
|
716
|
+
};
|
|
717
|
+
};
|
|
718
|
+
/** A 4x2 PNG: an image with an aspect ratio, and no bytes outside the process. */
|
|
719
|
+
declare const MATRIX_IMAGE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAABytg0kAAAAFElEQVR42mNk+M9QzwAFjDAGACPuA/8fMSCgAAAAAElFTkSuQmCC";
|
|
720
|
+
/**
|
|
721
|
+
* The widest number of a given length: a true minus, thousands separators
|
|
722
|
+
* and one decimal, every glyph at tabular width. `−1,234,567.0` for 12.
|
|
723
|
+
*/
|
|
724
|
+
declare function widestNumber(length: number, seed?: number): string;
|
|
725
|
+
/** A slot's value at an edge; `undefined` means "leave it out". */
|
|
726
|
+
declare function boundarySlotValue(slot: BlockSlot, name: string, edge: MatrixEdge, seed?: number): unknown;
|
|
727
|
+
/**
|
|
728
|
+
* One invocation of a definition with every slot at the edge: optional slots
|
|
729
|
+
* left out at `min` (so defaults are what renders), every slot at `max`.
|
|
730
|
+
* A slot whose role the profile requires — a source under every figure —
|
|
731
|
+
* is never optional to that profile, so `requiredRoles` keeps it at `min`.
|
|
732
|
+
* Columns whose cells must count the rows do; nothing else knows a block.
|
|
733
|
+
*/
|
|
734
|
+
declare function boundaryInvocation(name: string, definition: JsonBlockDefinition, edge: MatrixEdge, seed?: number, requiredRoles?: readonly string[]): Rec;
|
|
735
|
+
/**
|
|
736
|
+
* The same invocation one past the edge: the first budgeted string a word
|
|
737
|
+
* over, or the first bounded array an item over. What a slot violation
|
|
738
|
+
* looks like, so a suite can prove it is reported at the authored pointer.
|
|
739
|
+
*/
|
|
740
|
+
declare function overBudgetInvocation(name: string, definition: JsonBlockDefinition, seed?: number): {
|
|
741
|
+
invocation: Rec;
|
|
742
|
+
slot: string;
|
|
743
|
+
kind: 'words' | 'items';
|
|
744
|
+
} | undefined;
|
|
745
|
+
/** Every definition a template embeds, with the template's own example of it. */
|
|
746
|
+
declare function enumerateBlockDefinitions(template: unknown, templateName: string): BlockMatrixDefinition[];
|
|
747
|
+
/**
|
|
748
|
+
* A small report with one block at its edge: the chrome at the template's
|
|
749
|
+
* nominal values (or at the edge, when the chrome block is the one under
|
|
750
|
+
* test), the block in the first body section, body copy after it.
|
|
751
|
+
*/
|
|
752
|
+
declare function blockCaseDocument(entries: readonly BlockMatrixDefinition[], name: string, edge: MatrixEdge, theme: string, { font, canvas, requiredRoles }?: CaseConditions): Rec;
|
|
753
|
+
/** The whole template with every invocation at the edge. */
|
|
754
|
+
declare function reportCaseDocument(template: unknown, edge: MatrixEdge, theme: string, { font, canvas, requiredRoles }?: CaseConditions): Rec;
|
|
755
|
+
/** Every case the options span, in a stable order. */
|
|
756
|
+
declare function generateBlockMatrix(template: unknown, templateName: string, options: BlockMatrixOptions): BlockMatrixCase[];
|
|
575
757
|
|
|
576
758
|
/**
|
|
577
759
|
* Make resolved fonts visible to the LibreOffice child process for the
|
|
@@ -764,4 +946,4 @@ declare function emitDiagnostic(text: string, tone?: DiagnosticTone): void;
|
|
|
764
946
|
*/
|
|
765
947
|
declare const stderrDiagnosticSink: DiagnosticSink;
|
|
766
948
|
|
|
767
|
-
export { type DiagnosticSink, type DiagnosticTone, DocxFormatAdapter, type FontStageHandle, type FontStageOptions, type FontStager, FontconfigStager, type FormatAdapter, type FormatName, type GeneratorOptions, type GeneratorResult, type InventoryEntry, type InventoryMatch, MacOSCoreTextStager, type MappingStatus, NoopFontStager, type PdfFontInfo, type PdfTextLine, type PdfTextPage, type PdfTextWord, PptxFormatAdapter, type RasterizerCacheStats, type RenderedAnalysis, type RenderedAnalysisInput, type RenderedAnalysisSummary, type RenderedMapping, type RenderedTextEntry, type RequestedFont, type TextOccurrence, VISIBLE_SPILL_PT, WindowsFontStager, analyzeRenderedDocument, assignInventory, authoredTextForMatch, clearRasterizerCache, createAdapter, createLibreOfficePptxBatchRasterizer, createLibreOfficePptxRasterizer, emitDiagnostic, extractPdfFonts, extractPdfTextGeometry, familyRendered, getFontStager, getRasterizerCacheStats, normalizeForMatch, parsePdfFonts, parsePdfTextBbox, pdffontsAvailable, pdftotextAvailable, runWithDiagnosticSink, stderrDiagnosticSink };
|
|
949
|
+
export { type BlockMatrixCase, type BlockMatrixDefinition, type BlockMatrixOptions, type CaseConditions, type DiagnosticSink, type DiagnosticTone, DocxFormatAdapter, FALLBACK_FONTS, type FontStageHandle, type FontStageOptions, type FontStager, FontconfigStager, type FormatAdapter, type FormatName, type GeneratorOptions, type GeneratorResult, type InventoryEntry, type InventoryMatch, MATRIX_IMAGE, MacOSCoreTextStager, type MappingStatus, type MatrixCanvas, type MatrixEdge, type MatrixFont, NoopFontStager, type PdfFontInfo, type PdfTextLine, type PdfTextPage, type PdfTextWord, PptxFormatAdapter, RENDERED_QUALITY_RULES, type RasterizerCacheStats, type RenderedAnalysis, type RenderedAnalysisInput, type RenderedAnalysisSummary, type RenderedMapping, type RenderedRuleId, type RenderedTextEntry, type RequestedFont, type TextOccurrence, VISIBLE_SPILL_PT, WindowsFontStager, analyzeRenderedDocument, assignInventory, authoredTextForMatch, blockCaseDocument, boundaryInvocation, boundarySlotValue, clearRasterizerCache, createAdapter, createLibreOfficePptxBatchRasterizer, createLibreOfficePptxRasterizer, emitDiagnostic, enumerateBlockDefinitions, extractPdfFonts, extractPdfTextGeometry, familyRendered, generateBlockMatrix, getFontStager, getRasterizerCacheStats, normalizeForMatch, overBudgetInvocation, parsePdfFonts, parsePdfTextBbox, pdffontsAvailable, pdftotextAvailable, readingOrder, reportCaseDocument, runWithDiagnosticSink, stderrDiagnosticSink, widestNumber };
|