reamkit 0.1.0-alpha.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 +21 -0
- package/README.md +95 -0
- package/dist/esm/bidi/algorithm.d.ts +9 -0
- package/dist/esm/bidi/algorithm.js +458 -0
- package/dist/esm/bidi/char-types.d.ts +2 -0
- package/dist/esm/bidi/char-types.js +439 -0
- package/dist/esm/bidi/index.d.ts +14 -0
- package/dist/esm/bidi/index.js +25 -0
- package/dist/esm/converter/docx-to-pdf.d.ts +15 -0
- package/dist/esm/converter/docx-to-pdf.js +227 -0
- package/dist/esm/converter/index.d.ts +4 -0
- package/dist/esm/converter/index.js +2 -0
- package/dist/esm/converter/xlsx-to-pdf.d.ts +13 -0
- package/dist/esm/converter/xlsx-to-pdf.js +515 -0
- package/dist/esm/crypto/asn1.d.ts +23 -0
- package/dist/esm/crypto/asn1.js +123 -0
- package/dist/esm/crypto/cms.d.ts +9 -0
- package/dist/esm/crypto/cms.js +34 -0
- package/dist/esm/crypto/index.d.ts +2 -0
- package/dist/esm/crypto/index.js +1 -0
- package/dist/esm/document-model/index.d.ts +1 -0
- package/dist/esm/document-model/index.js +0 -0
- package/dist/esm/document-model/types.d.ts +403 -0
- package/dist/esm/font/arabic-joining.d.ts +4 -0
- package/dist/esm/font/arabic-joining.js +97 -0
- package/dist/esm/font/binary-reader.d.ts +13 -0
- package/dist/esm/font/binary-reader.js +44 -0
- package/dist/esm/font/font-registry.d.ts +19 -0
- package/dist/esm/font/font-registry.js +39 -0
- package/dist/esm/font/index.d.ts +7 -0
- package/dist/esm/font/opentype-layout.d.ts +21 -0
- package/dist/esm/font/opentype-layout.js +329 -0
- package/dist/esm/font/ttf-parser.d.ts +29 -0
- package/dist/esm/font/ttf-parser.js +290 -0
- package/dist/esm/font/ttf-subset.d.ts +3 -0
- package/dist/esm/font/ttf-subset.js +201 -0
- package/dist/esm/fonts/index.d.ts +2 -0
- package/dist/esm/fonts/remote-fonts.d.ts +13 -0
- package/dist/esm/fonts/remote-fonts.js +94 -0
- package/dist/esm/hyphenation/index.d.ts +10 -0
- package/dist/esm/hyphenation/index.js +38 -0
- package/dist/esm/hyphenation/liang.d.ts +10 -0
- package/dist/esm/hyphenation/liang.js +79 -0
- package/dist/esm/hyphenation/patterns-en-us.d.ts +2 -0
- package/dist/esm/hyphenation/patterns-en-us.js +5 -0
- package/dist/esm/hyphenation/patterns-ru.d.ts +2 -0
- package/dist/esm/hyphenation/patterns-ru.js +5 -0
- package/dist/esm/index.d.ts +12 -0
- package/dist/esm/index.js +13 -0
- package/dist/esm/line-breaker/index.d.ts +2 -0
- package/dist/esm/line-breaker/knuth-plass.d.ts +30 -0
- package/dist/esm/line-breaker/knuth-plass.js +172 -0
- package/dist/esm/numbering/index.d.ts +1 -0
- package/dist/esm/numbering/state.d.ts +6 -0
- package/dist/esm/numbering/state.js +83 -0
- package/dist/esm/ooxml/drawingml/chart-parser.d.ts +3 -0
- package/dist/esm/ooxml/drawingml/chart-parser.js +218 -0
- package/dist/esm/ooxml/drawingml/colors.d.ts +17 -0
- package/dist/esm/ooxml/drawingml/colors.js +125 -0
- package/dist/esm/ooxml/drawingml/theme-parser.d.ts +1 -0
- package/dist/esm/ooxml/drawingml/theme-parser.js +55 -0
- package/dist/esm/ooxml/index.d.ts +1 -0
- package/dist/esm/ooxml/math/omml-parser.d.ts +4 -0
- package/dist/esm/ooxml/math/omml-parser.js +217 -0
- package/dist/esm/ooxml/spreadsheet/cell-reference.d.ts +6 -0
- package/dist/esm/ooxml/spreadsheet/cell-reference.js +26 -0
- package/dist/esm/ooxml/spreadsheet/defined-name-ref.d.ts +11 -0
- package/dist/esm/ooxml/spreadsheet/defined-name-ref.js +64 -0
- package/dist/esm/ooxml/spreadsheet/index.d.ts +12 -0
- package/dist/esm/ooxml/spreadsheet/index.js +7 -0
- package/dist/esm/ooxml/spreadsheet/number-format.d.ts +1 -0
- package/dist/esm/ooxml/spreadsheet/number-format.js +438 -0
- package/dist/esm/ooxml/spreadsheet/shared-strings-parser.d.ts +1 -0
- package/dist/esm/ooxml/spreadsheet/shared-strings-parser.js +47 -0
- package/dist/esm/ooxml/spreadsheet/styles-parser.d.ts +52 -0
- package/dist/esm/ooxml/spreadsheet/styles-parser.js +225 -0
- package/dist/esm/ooxml/spreadsheet/workbook-parser.d.ts +16 -0
- package/dist/esm/ooxml/spreadsheet/workbook-parser.js +90 -0
- package/dist/esm/ooxml/spreadsheet/worksheet-parser.d.ts +60 -0
- package/dist/esm/ooxml/spreadsheet/worksheet-parser.js +311 -0
- package/dist/esm/ooxml/wordproc/document-parser.d.ts +9 -0
- package/dist/esm/ooxml/wordproc/document-parser.js +274 -0
- package/dist/esm/ooxml/wordproc/drawing-parser.d.ts +33 -0
- package/dist/esm/ooxml/wordproc/drawing-parser.js +374 -0
- package/dist/esm/ooxml/wordproc/font-table.d.ts +15 -0
- package/dist/esm/ooxml/wordproc/font-table.js +82 -0
- package/dist/esm/ooxml/wordproc/index.d.ts +10 -0
- package/dist/esm/ooxml/wordproc/index.js +9 -0
- package/dist/esm/ooxml/wordproc/numbering-parser.d.ts +3 -0
- package/dist/esm/ooxml/wordproc/numbering-parser.js +89 -0
- package/dist/esm/ooxml/wordproc/paragraph-properties.d.ts +2 -0
- package/dist/esm/ooxml/wordproc/paragraph-properties.js +85 -0
- package/dist/esm/ooxml/wordproc/po-helpers.d.ts +14 -0
- package/dist/esm/ooxml/wordproc/po-helpers.js +76 -0
- package/dist/esm/ooxml/wordproc/po-to-flat.d.ts +2 -0
- package/dist/esm/ooxml/wordproc/po-to-flat.js +28 -0
- package/dist/esm/ooxml/wordproc/run-properties.d.ts +2 -0
- package/dist/esm/ooxml/wordproc/run-properties.js +82 -0
- package/dist/esm/ooxml/wordproc/settings-parser.d.ts +5 -0
- package/dist/esm/ooxml/wordproc/settings-parser.js +26 -0
- package/dist/esm/ooxml/wordproc/styles-parser.d.ts +3 -0
- package/dist/esm/ooxml/wordproc/styles-parser.js +67 -0
- package/dist/esm/ooxml/wordproc/table-parser.d.ts +3 -0
- package/dist/esm/ooxml/wordproc/table-parser.js +162 -0
- package/dist/esm/ooxml/wordproc/text-extractor.d.ts +1 -0
- package/dist/esm/ooxml/wordproc/text-extractor.js +1 -0
- package/dist/esm/ooxml/wordproc/xml-helpers.d.ts +9 -0
- package/dist/esm/ooxml/wordproc/xml-helpers.js +36 -0
- package/dist/esm/opc/core-properties.d.ts +11 -0
- package/dist/esm/opc/core-properties.js +51 -0
- package/dist/esm/opc/index.d.ts +5 -0
- package/dist/esm/opc/index.js +3 -0
- package/dist/esm/opc/package.d.ts +26 -0
- package/dist/esm/opc/package.js +113 -0
- package/dist/esm/opc/relationship-types.d.ts +3 -0
- package/dist/esm/opc/relationship-types.js +4 -0
- package/dist/esm/opc/relationships.d.ts +7 -0
- package/dist/esm/opc/relationships.js +28 -0
- package/dist/esm/pdf/arc-to-bezier.d.ts +5 -0
- package/dist/esm/pdf/arc-to-bezier.js +58 -0
- package/dist/esm/pdf/builtin-fonts.d.ts +2 -0
- package/dist/esm/pdf/chart-geometry.d.ts +64 -0
- package/dist/esm/pdf/chart-geometry.js +674 -0
- package/dist/esm/pdf/cid-font.d.ts +15 -0
- package/dist/esm/pdf/cid-font.js +174 -0
- package/dist/esm/pdf/embedded-file.d.ts +11 -0
- package/dist/esm/pdf/embedded-file.js +23 -0
- package/dist/esm/pdf/icc-profile.d.ts +1 -0
- package/dist/esm/pdf/icc-profile.js +166 -0
- package/dist/esm/pdf/image-xobject.d.ts +13 -0
- package/dist/esm/pdf/image-xobject.js +335 -0
- package/dist/esm/pdf/index.d.ts +11 -0
- package/dist/esm/pdf/index.js +5 -0
- package/dist/esm/pdf/math-layout.d.ts +45 -0
- package/dist/esm/pdf/math-layout.js +1138 -0
- package/dist/esm/pdf/objects.d.ts +32 -0
- package/dist/esm/pdf/objects.js +54 -0
- package/dist/esm/pdf/preset-geometry.d.ts +6 -0
- package/dist/esm/pdf/preset-geometry.js +199 -0
- package/dist/esm/pdf/serialize.d.ts +3 -0
- package/dist/esm/pdf/serialize.js +54 -0
- package/dist/esm/pdf/signature.d.ts +25 -0
- package/dist/esm/pdf/signature.js +126 -0
- package/dist/esm/pdf/struct-tree.d.ts +31 -0
- package/dist/esm/pdf/struct-tree.js +109 -0
- package/dist/esm/pdf/styled-page-renderer.d.ts +43 -0
- package/dist/esm/pdf/styled-page-renderer.js +2317 -0
- package/dist/esm/pdf/text-encoding.d.ts +2 -0
- package/dist/esm/pdf/text-page-renderer.d.ts +16 -0
- package/dist/esm/pdf/text-page-renderer.js +4 -0
- package/dist/esm/pdf/vector-graphics.d.ts +46 -0
- package/dist/esm/pdf/vector-graphics.js +103 -0
- package/dist/esm/pdf/writer.d.ts +10 -0
- package/dist/esm/pdf/writer.js +81 -0
- package/dist/esm/pdf/xmp.d.ts +13 -0
- package/dist/esm/pdf/xmp.js +38 -0
- package/dist/esm/style-cascade/index.d.ts +3 -0
- package/dist/esm/style-cascade/resolver.d.ts +4 -0
- package/dist/esm/style-cascade/resolver.js +96 -0
- package/dist/esm/style-cascade/types.d.ts +29 -0
- package/dist/esm/style-cascade/types.js +26 -0
- package/package.json +90 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ParsedTtf } from '../font/index.js';
|
|
2
|
+
export type FontInput = ParsedTtf | {
|
|
3
|
+
readonly bytes: Uint8Array;
|
|
4
|
+
};
|
|
5
|
+
export interface TextRenderOptions {
|
|
6
|
+
readonly font: FontInput;
|
|
7
|
+
readonly pageWidth?: number;
|
|
8
|
+
readonly pageHeight?: number;
|
|
9
|
+
readonly marginLeft?: number;
|
|
10
|
+
readonly marginRight?: number;
|
|
11
|
+
readonly marginTop?: number;
|
|
12
|
+
readonly marginBottom?: number;
|
|
13
|
+
readonly fontSize?: number;
|
|
14
|
+
readonly lineHeight?: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function renderPlainTextPdf(paragraphs: ReadonlyArray<string>, options: TextRenderOptions): Uint8Array;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type PathSegment = {
|
|
2
|
+
readonly op: 'move';
|
|
3
|
+
readonly x: number;
|
|
4
|
+
readonly y: number;
|
|
5
|
+
} | {
|
|
6
|
+
readonly op: 'line';
|
|
7
|
+
readonly x: number;
|
|
8
|
+
readonly y: number;
|
|
9
|
+
} | {
|
|
10
|
+
readonly op: 'cubic';
|
|
11
|
+
readonly x1: number;
|
|
12
|
+
readonly y1: number;
|
|
13
|
+
readonly x2: number;
|
|
14
|
+
readonly y2: number;
|
|
15
|
+
readonly x: number;
|
|
16
|
+
readonly y: number;
|
|
17
|
+
} | {
|
|
18
|
+
readonly op: 'close';
|
|
19
|
+
};
|
|
20
|
+
export interface VectorPath {
|
|
21
|
+
readonly segments: ReadonlyArray<PathSegment>;
|
|
22
|
+
readonly fillRule?: 'nonzero' | 'evenodd';
|
|
23
|
+
}
|
|
24
|
+
export interface StrokeStyle {
|
|
25
|
+
readonly colorHex: string;
|
|
26
|
+
readonly widthPt: number;
|
|
27
|
+
readonly cap?: 'butt' | 'round' | 'square';
|
|
28
|
+
readonly join?: 'miter' | 'round' | 'bevel';
|
|
29
|
+
readonly dash?: ReadonlyArray<number>;
|
|
30
|
+
}
|
|
31
|
+
export interface VectorShape {
|
|
32
|
+
readonly paths: ReadonlyArray<VectorPath>;
|
|
33
|
+
readonly fillColorHex?: string;
|
|
34
|
+
readonly stroke?: StrokeStyle;
|
|
35
|
+
readonly transform: readonly [number, number, number, number, number, number];
|
|
36
|
+
}
|
|
37
|
+
export declare class PathBuilder {
|
|
38
|
+
private readonly segments;
|
|
39
|
+
moveTo(x: number, y: number): this;
|
|
40
|
+
lineTo(x: number, y: number): this;
|
|
41
|
+
cubicTo(x1: number, y1: number, x2: number, y2: number, x: number, y: number): this;
|
|
42
|
+
append(segments: ReadonlyArray<PathSegment>): this;
|
|
43
|
+
close(): this;
|
|
44
|
+
build(fillRule?: 'nonzero' | 'evenodd'): VectorPath;
|
|
45
|
+
}
|
|
46
|
+
export declare function emitVectorShape(shape: VectorShape): Array<string>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
//#region src/pdf/vector-graphics.ts
|
|
2
|
+
var PathBuilder = class {
|
|
3
|
+
segments = [];
|
|
4
|
+
moveTo(x, y) {
|
|
5
|
+
this.segments.push({
|
|
6
|
+
op: "move",
|
|
7
|
+
x,
|
|
8
|
+
y
|
|
9
|
+
});
|
|
10
|
+
return this;
|
|
11
|
+
}
|
|
12
|
+
lineTo(x, y) {
|
|
13
|
+
this.segments.push({
|
|
14
|
+
op: "line",
|
|
15
|
+
x,
|
|
16
|
+
y
|
|
17
|
+
});
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
cubicTo(x1, y1, x2, y2, x, y) {
|
|
21
|
+
this.segments.push({
|
|
22
|
+
op: "cubic",
|
|
23
|
+
x1,
|
|
24
|
+
y1,
|
|
25
|
+
x2,
|
|
26
|
+
y2,
|
|
27
|
+
x,
|
|
28
|
+
y
|
|
29
|
+
});
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
append(segments) {
|
|
33
|
+
for (const s of segments) this.segments.push(s);
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
close() {
|
|
37
|
+
this.segments.push({ op: "close" });
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
build(fillRule) {
|
|
41
|
+
return {
|
|
42
|
+
segments: this.segments.slice(),
|
|
43
|
+
...fillRule ? { fillRule } : {}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
function emitVectorShape(shape) {
|
|
48
|
+
const out = [];
|
|
49
|
+
out.push("q");
|
|
50
|
+
const [a, b, c, d, e, f] = shape.transform;
|
|
51
|
+
out.push(`${num(a)} ${num(b)} ${num(c)} ${num(d)} ${num(e)} ${num(f)} cm`);
|
|
52
|
+
const stroke = shape.stroke;
|
|
53
|
+
if (stroke) {
|
|
54
|
+
out.push(`${num(stroke.widthPt)} w`);
|
|
55
|
+
if (stroke.cap !== void 0) out.push(`${capCode(stroke.cap)} J`);
|
|
56
|
+
if (stroke.join !== void 0) out.push(`${joinCode(stroke.join)} j`);
|
|
57
|
+
if (stroke.dash && stroke.dash.length > 0) out.push(`[${stroke.dash.map(num).join(" ")}] 0 d`);
|
|
58
|
+
const [r, g, bl] = hexToRgb01(stroke.colorHex);
|
|
59
|
+
out.push(`${num(r)} ${num(g)} ${num(bl)} RG`);
|
|
60
|
+
}
|
|
61
|
+
if (shape.fillColorHex) {
|
|
62
|
+
const [r, g, bl] = hexToRgb01(shape.fillColorHex);
|
|
63
|
+
out.push(`${num(r)} ${num(g)} ${num(bl)} rg`);
|
|
64
|
+
}
|
|
65
|
+
let evenodd = false;
|
|
66
|
+
for (const path of shape.paths) {
|
|
67
|
+
if (path.fillRule === "evenodd") evenodd = true;
|
|
68
|
+
for (const seg of path.segments) out.push(emitSegment(seg));
|
|
69
|
+
}
|
|
70
|
+
out.push(paintOp(shape.fillColorHex !== void 0, stroke !== void 0, evenodd));
|
|
71
|
+
out.push("Q");
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
function emitSegment(seg) {
|
|
75
|
+
switch (seg.op) {
|
|
76
|
+
case "move": return `${num(seg.x)} ${num(seg.y)} m`;
|
|
77
|
+
case "line": return `${num(seg.x)} ${num(seg.y)} l`;
|
|
78
|
+
case "cubic": return `${num(seg.x1)} ${num(seg.y1)} ${num(seg.x2)} ${num(seg.y2)} ${num(seg.x)} ${num(seg.y)} c`;
|
|
79
|
+
case "close": return "h";
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function paintOp(fill, stroke, evenodd) {
|
|
83
|
+
if (fill && stroke) return evenodd ? "B*" : "B";
|
|
84
|
+
if (fill) return evenodd ? "f*" : "f";
|
|
85
|
+
if (stroke) return "S";
|
|
86
|
+
return "n";
|
|
87
|
+
}
|
|
88
|
+
var capCode = (c) => c === "round" ? 1 : c === "square" ? 2 : 0;
|
|
89
|
+
var joinCode = (j) => j === "round" ? 1 : j === "bevel" ? 2 : 0;
|
|
90
|
+
function num(n) {
|
|
91
|
+
if (!Number.isFinite(n)) return "0";
|
|
92
|
+
if (Number.isInteger(n)) return String(n);
|
|
93
|
+
return n.toFixed(6).replace(/0+$/, "").replace(/\.$/, "");
|
|
94
|
+
}
|
|
95
|
+
function hexToRgb01(hex) {
|
|
96
|
+
return [
|
|
97
|
+
parseInt(hex.slice(0, 2), 16) / 255,
|
|
98
|
+
parseInt(hex.slice(2, 4), 16) / 255,
|
|
99
|
+
parseInt(hex.slice(4, 6), 16) / 255
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { PathBuilder, emitVectorShape };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PdfValue, PdfRef } from './objects.js';
|
|
2
|
+
export interface BuildOptions {
|
|
3
|
+
readonly version?: string;
|
|
4
|
+
readonly id?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare class PdfDocument {
|
|
7
|
+
private readonly objects;
|
|
8
|
+
add(value: PdfValue): PdfRef;
|
|
9
|
+
build(root: PdfRef, info?: PdfRef, options?: BuildOptions): Uint8Array;
|
|
10
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { PdfRef } from "./objects.js";
|
|
2
|
+
import { serializeIndirectObject } from "./serialize.js";
|
|
3
|
+
//#region src/pdf/writer.ts
|
|
4
|
+
var encoder = new TextEncoder();
|
|
5
|
+
var BINARY_MARKER = new Uint8Array([
|
|
6
|
+
37,
|
|
7
|
+
226,
|
|
8
|
+
227,
|
|
9
|
+
207,
|
|
10
|
+
211,
|
|
11
|
+
10
|
|
12
|
+
]);
|
|
13
|
+
var PdfDocument = class {
|
|
14
|
+
objects = [];
|
|
15
|
+
add(value) {
|
|
16
|
+
const id = this.objects.length + 1;
|
|
17
|
+
this.objects.push({
|
|
18
|
+
id,
|
|
19
|
+
value
|
|
20
|
+
});
|
|
21
|
+
return new PdfRef(id);
|
|
22
|
+
}
|
|
23
|
+
build(root, info, options = {}) {
|
|
24
|
+
const parts = [];
|
|
25
|
+
const offsets = new Array(this.objects.length + 1).fill(0);
|
|
26
|
+
let pos = 0;
|
|
27
|
+
const push = (bytes) => {
|
|
28
|
+
parts.push(bytes);
|
|
29
|
+
pos += bytes.length;
|
|
30
|
+
};
|
|
31
|
+
push(encoder.encode(`%PDF-${options.version ?? "1.7"}\n`));
|
|
32
|
+
push(BINARY_MARKER);
|
|
33
|
+
for (const obj of this.objects) {
|
|
34
|
+
offsets[obj.id] = pos;
|
|
35
|
+
push(serializeIndirectObject(obj.id, 0, obj.value));
|
|
36
|
+
}
|
|
37
|
+
const xrefOffset = pos;
|
|
38
|
+
const totalObjects = this.objects.length + 1;
|
|
39
|
+
let xref = `xref\n0 ${totalObjects}\n0000000000 65535 f \n`;
|
|
40
|
+
for (let i = 1; i < totalObjects; i++) {
|
|
41
|
+
const off = offsets[i].toString().padStart(10, "0");
|
|
42
|
+
xref += `${off} 00000 n \n`;
|
|
43
|
+
}
|
|
44
|
+
push(encoder.encode(xref));
|
|
45
|
+
const infoEntry = info ? ` /Info ${info.id} ${info.generation} R` : "";
|
|
46
|
+
let idEntry = "";
|
|
47
|
+
if (options.id) {
|
|
48
|
+
const hashHex = hash128Hex(parts);
|
|
49
|
+
idEntry = ` /ID [<${hashHex}> <${hashHex}>]`;
|
|
50
|
+
}
|
|
51
|
+
const trailer = `trailer\n<</Size ${totalObjects} /Root ${root.id} ${root.generation} R${infoEntry}${idEntry}>>\nstartxref\n${xrefOffset}\n%%EOF\n`;
|
|
52
|
+
push(encoder.encode(trailer));
|
|
53
|
+
const out = new Uint8Array(pos);
|
|
54
|
+
let off = 0;
|
|
55
|
+
for (const p of parts) {
|
|
56
|
+
out.set(p, off);
|
|
57
|
+
off += p.length;
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
function hash128Hex(parts) {
|
|
63
|
+
const acc = new Uint32Array([
|
|
64
|
+
2166136261,
|
|
65
|
+
16777619,
|
|
66
|
+
2654435769,
|
|
67
|
+
2246822507
|
|
68
|
+
]);
|
|
69
|
+
for (const part of parts) for (let i = 0; i < part.length; i++) {
|
|
70
|
+
const b = part[i];
|
|
71
|
+
for (let s = 0; s < 4; s++) {
|
|
72
|
+
acc[s] = (acc[s] ^ b) >>> 0;
|
|
73
|
+
acc[s] = Math.imul(acc[s], 16777619) >>> 0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
let hex = "";
|
|
77
|
+
for (let s = 0; s < 4; s++) hex += acc[s].toString(16).padStart(8, "0").toUpperCase();
|
|
78
|
+
return hex;
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { PdfDocument };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface XmpInput {
|
|
2
|
+
readonly title?: string;
|
|
3
|
+
readonly author?: string;
|
|
4
|
+
readonly subject?: string;
|
|
5
|
+
readonly keywords?: string;
|
|
6
|
+
readonly creator?: string;
|
|
7
|
+
readonly producer?: string;
|
|
8
|
+
readonly createDate?: Date;
|
|
9
|
+
readonly modifyDate?: Date;
|
|
10
|
+
readonly pdfaPart?: '1' | '2' | '3';
|
|
11
|
+
readonly pdfaConformance?: 'A' | 'B' | 'U';
|
|
12
|
+
}
|
|
13
|
+
export declare function buildXmpPacket(input: XmpInput): Uint8Array;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//#region src/pdf/xmp.ts
|
|
2
|
+
function escapeXml(s) {
|
|
3
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
4
|
+
}
|
|
5
|
+
function xmpDate(d) {
|
|
6
|
+
const pad = (n, w = 2) => String(n).padStart(w, "0");
|
|
7
|
+
return `${pad(d.getUTCFullYear(), 4)}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}T${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}Z`;
|
|
8
|
+
}
|
|
9
|
+
function buildXmpPacket(input) {
|
|
10
|
+
const props = [];
|
|
11
|
+
if (input.pdfaPart) props.push(` <rdf:Description rdf:about="" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/">`, ` <pdfaid:part>${input.pdfaPart}</pdfaid:part>`, ` <pdfaid:conformance>${input.pdfaConformance ?? "B"}</pdfaid:conformance>`, ` </rdf:Description>`);
|
|
12
|
+
const dc = [];
|
|
13
|
+
if (input.title) dc.push(` <dc:title><rdf:Alt><rdf:li xml:lang="x-default">${escapeXml(input.title)}</rdf:li></rdf:Alt></dc:title>`);
|
|
14
|
+
if (input.author) dc.push(` <dc:creator><rdf:Seq><rdf:li>${escapeXml(input.author)}</rdf:li></rdf:Seq></dc:creator>`);
|
|
15
|
+
if (input.subject) dc.push(` <dc:description><rdf:Alt><rdf:li xml:lang="x-default">${escapeXml(input.subject)}</rdf:li></rdf:Alt></dc:description>`);
|
|
16
|
+
if (dc.length > 0) props.push(` <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">`, ...dc, ` </rdf:Description>`);
|
|
17
|
+
const xmp = [];
|
|
18
|
+
if (input.creator) xmp.push(` <xmp:CreatorTool>${escapeXml(input.creator)}</xmp:CreatorTool>`);
|
|
19
|
+
if (input.createDate) xmp.push(` <xmp:CreateDate>${xmpDate(input.createDate)}</xmp:CreateDate>`);
|
|
20
|
+
if (input.modifyDate) xmp.push(` <xmp:ModifyDate>${xmpDate(input.modifyDate)}</xmp:ModifyDate>`);
|
|
21
|
+
if (xmp.length > 0) props.push(` <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">`, ...xmp, ` </rdf:Description>`);
|
|
22
|
+
const pdf = [];
|
|
23
|
+
if (input.producer) pdf.push(` <pdf:Producer>${escapeXml(input.producer)}</pdf:Producer>`);
|
|
24
|
+
if (input.keywords) pdf.push(` <pdf:Keywords>${escapeXml(input.keywords)}</pdf:Keywords>`);
|
|
25
|
+
if (pdf.length > 0) props.push(` <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">`, ...pdf, ` </rdf:Description>`);
|
|
26
|
+
const body = [
|
|
27
|
+
`<?xpacket begin="\uFEFF" id="W5M0MpCehiHzreSzNTczkc9d"?>`,
|
|
28
|
+
`<x:xmpmeta xmlns:x="adobe:ns:meta/">`,
|
|
29
|
+
` <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">`,
|
|
30
|
+
...props,
|
|
31
|
+
` </rdf:RDF>`,
|
|
32
|
+
`</x:xmpmeta>`,
|
|
33
|
+
`<?xpacket end="w"?>`
|
|
34
|
+
].join("\n");
|
|
35
|
+
return new TextEncoder().encode(body);
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { buildXmpPacket };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ParagraphProperties, RunProperties, StyleSheet } from '../document-model/index.js';
|
|
2
|
+
import { ResolvedParagraphProperties, ResolvedRunProperties } from './types.js';
|
|
3
|
+
export declare function resolveRunProperties(runDirect: RunProperties, paragraphDirect: ParagraphProperties, sheet: StyleSheet): ResolvedRunProperties;
|
|
4
|
+
export declare function resolveParagraphProperties(paragraphDirect: ParagraphProperties, sheet: StyleSheet): ResolvedParagraphProperties;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { DEFAULT_RESOLVED_PARAGRAPH, DEFAULT_RESOLVED_RUN } from "./types.js";
|
|
2
|
+
//#region src/style-cascade/resolver.ts
|
|
3
|
+
function resolveRunProperties(runDirect, paragraphDirect, sheet) {
|
|
4
|
+
let acc = mergeRun(DEFAULT_RESOLVED_RUN, sheet.defaultRunProperties);
|
|
5
|
+
if (paragraphDirect.styleId) {
|
|
6
|
+
const chain = resolveStyleChain(paragraphDirect.styleId, sheet);
|
|
7
|
+
acc = mergeRun(acc, chain.rPr);
|
|
8
|
+
}
|
|
9
|
+
if (runDirect.styleId) {
|
|
10
|
+
const chain = resolveStyleChain(runDirect.styleId, sheet);
|
|
11
|
+
acc = mergeRun(acc, chain.rPr);
|
|
12
|
+
}
|
|
13
|
+
return mergeRun(acc, runDirect);
|
|
14
|
+
}
|
|
15
|
+
function resolveParagraphProperties(paragraphDirect, sheet) {
|
|
16
|
+
let acc = mergePar(DEFAULT_RESOLVED_PARAGRAPH, sheet.defaultParagraphProperties);
|
|
17
|
+
if (paragraphDirect.styleId) {
|
|
18
|
+
const chain = resolveStyleChain(paragraphDirect.styleId, sheet);
|
|
19
|
+
acc = mergePar(acc, chain.pPr);
|
|
20
|
+
}
|
|
21
|
+
return mergePar(acc, paragraphDirect);
|
|
22
|
+
}
|
|
23
|
+
function resolveStyleChain(styleId, sheet) {
|
|
24
|
+
const chain = [];
|
|
25
|
+
const visited = /* @__PURE__ */ new Set();
|
|
26
|
+
let cursor = styleId;
|
|
27
|
+
while (cursor && !visited.has(cursor)) {
|
|
28
|
+
visited.add(cursor);
|
|
29
|
+
const style = sheet.styles.get(cursor);
|
|
30
|
+
if (!style) break;
|
|
31
|
+
chain.unshift({
|
|
32
|
+
rPr: style.runProperties,
|
|
33
|
+
pPr: style.paragraphProperties
|
|
34
|
+
});
|
|
35
|
+
cursor = style.basedOn;
|
|
36
|
+
}
|
|
37
|
+
let rPr = {};
|
|
38
|
+
let pPr = {};
|
|
39
|
+
for (const link of chain) {
|
|
40
|
+
rPr = mergeRunPartial(rPr, link.rPr);
|
|
41
|
+
pPr = mergeParPartial(pPr, link.pPr);
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
rPr,
|
|
45
|
+
pPr
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function mergeRun(base, override) {
|
|
49
|
+
const lang = override.lang ?? base.lang;
|
|
50
|
+
return {
|
|
51
|
+
bold: override.bold ?? base.bold,
|
|
52
|
+
italic: override.italic ?? base.italic,
|
|
53
|
+
underline: override.underline ?? base.underline,
|
|
54
|
+
strike: override.strike ?? base.strike,
|
|
55
|
+
fontSizeHalfPoints: override.fontSizeHalfPoints ?? base.fontSizeHalfPoints,
|
|
56
|
+
colorHex: override.colorHex ?? base.colorHex,
|
|
57
|
+
fontFamily: override.fontFamily ?? base.fontFamily,
|
|
58
|
+
verticalAlign: override.verticalAlign ?? base.verticalAlign,
|
|
59
|
+
rtl: override.rtl ?? base.rtl,
|
|
60
|
+
...lang !== void 0 ? { lang } : {}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function mergePar(base, override) {
|
|
64
|
+
const outlineLevel = override.outlineLevel ?? base.outlineLevel;
|
|
65
|
+
const styleId = override.styleId ?? base.styleId;
|
|
66
|
+
return {
|
|
67
|
+
alignment: override.alignment ?? base.alignment,
|
|
68
|
+
spacingBeforeTwips: override.spacingBeforeTwips ?? base.spacingBeforeTwips,
|
|
69
|
+
spacingAfterTwips: override.spacingAfterTwips ?? base.spacingAfterTwips,
|
|
70
|
+
spacingLineTwips: override.spacingLineTwips ?? base.spacingLineTwips,
|
|
71
|
+
spacingLineRule: override.spacingLineRule ?? base.spacingLineRule,
|
|
72
|
+
indentLeftTwips: override.indentLeftTwips ?? base.indentLeftTwips,
|
|
73
|
+
indentRightTwips: override.indentRightTwips ?? base.indentRightTwips,
|
|
74
|
+
indentFirstLineTwips: override.indentFirstLineTwips ?? base.indentFirstLineTwips,
|
|
75
|
+
pageBreakBefore: override.pageBreakBefore ?? base.pageBreakBefore,
|
|
76
|
+
bidi: override.bidi ?? base.bidi,
|
|
77
|
+
...outlineLevel !== void 0 ? { outlineLevel } : {},
|
|
78
|
+
...styleId !== void 0 ? { styleId } : {}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function mergeRunPartial(base, override) {
|
|
82
|
+
return copyDefined(base, override);
|
|
83
|
+
}
|
|
84
|
+
function mergeParPartial(base, override) {
|
|
85
|
+
return copyDefined(base, override);
|
|
86
|
+
}
|
|
87
|
+
function copyDefined(base, override) {
|
|
88
|
+
const out = { ...base };
|
|
89
|
+
for (const key of Object.keys(override)) {
|
|
90
|
+
const v = override[key];
|
|
91
|
+
if (v !== void 0) out[key] = v;
|
|
92
|
+
}
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { resolveParagraphProperties, resolveRunProperties };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Alignment, FontFamilyMap, UnderlineStyle, VerticalAlign } from '../document-model/index.js';
|
|
2
|
+
export interface ResolvedRunProperties {
|
|
3
|
+
readonly bold: boolean;
|
|
4
|
+
readonly italic: boolean;
|
|
5
|
+
readonly underline: UnderlineStyle;
|
|
6
|
+
readonly strike: boolean;
|
|
7
|
+
readonly fontSizeHalfPoints: number;
|
|
8
|
+
readonly colorHex: string;
|
|
9
|
+
readonly fontFamily: FontFamilyMap;
|
|
10
|
+
readonly verticalAlign: VerticalAlign;
|
|
11
|
+
readonly rtl: boolean;
|
|
12
|
+
readonly lang?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ResolvedParagraphProperties {
|
|
15
|
+
readonly alignment: Alignment;
|
|
16
|
+
readonly spacingBeforeTwips: number;
|
|
17
|
+
readonly spacingAfterTwips: number;
|
|
18
|
+
readonly spacingLineTwips: number;
|
|
19
|
+
readonly spacingLineRule: 'auto' | 'exact' | 'atLeast';
|
|
20
|
+
readonly indentLeftTwips: number;
|
|
21
|
+
readonly indentRightTwips: number;
|
|
22
|
+
readonly indentFirstLineTwips: number;
|
|
23
|
+
readonly pageBreakBefore: boolean;
|
|
24
|
+
readonly bidi: boolean;
|
|
25
|
+
readonly outlineLevel?: number;
|
|
26
|
+
readonly styleId?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare const DEFAULT_RESOLVED_RUN: ResolvedRunProperties;
|
|
29
|
+
export declare const DEFAULT_RESOLVED_PARAGRAPH: ResolvedParagraphProperties;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/style-cascade/types.ts
|
|
2
|
+
var DEFAULT_RESOLVED_RUN = {
|
|
3
|
+
bold: false,
|
|
4
|
+
italic: false,
|
|
5
|
+
underline: "none",
|
|
6
|
+
strike: false,
|
|
7
|
+
fontSizeHalfPoints: 22,
|
|
8
|
+
colorHex: "000000",
|
|
9
|
+
fontFamily: {},
|
|
10
|
+
verticalAlign: "baseline",
|
|
11
|
+
rtl: false
|
|
12
|
+
};
|
|
13
|
+
var DEFAULT_RESOLVED_PARAGRAPH = {
|
|
14
|
+
alignment: "left",
|
|
15
|
+
spacingBeforeTwips: 0,
|
|
16
|
+
spacingAfterTwips: 0,
|
|
17
|
+
spacingLineTwips: 240,
|
|
18
|
+
spacingLineRule: "auto",
|
|
19
|
+
indentLeftTwips: 0,
|
|
20
|
+
indentRightTwips: 0,
|
|
21
|
+
indentFirstLineTwips: 0,
|
|
22
|
+
pageBreakBefore: false,
|
|
23
|
+
bidi: false
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
26
|
+
export { DEFAULT_RESOLVED_PARAGRAPH, DEFAULT_RESOLVED_RUN };
|
package/package.json
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "reamkit",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Ream — DOCX/XLSX to PDF, built from scratch on the ECMA-376 and ISO 32000 specifications (alpha; more document formats to come)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Alex Krassavin",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/alex-krassavin/reamkit.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/alex-krassavin/reamkit#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/alex-krassavin/reamkit/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./dist/esm/index.js",
|
|
17
|
+
"types": "./dist/esm/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/esm/index.d.ts",
|
|
21
|
+
"import": "./dist/esm/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./document-model": {
|
|
24
|
+
"types": "./dist/esm/document-model/index.d.ts",
|
|
25
|
+
"import": "./dist/esm/document-model/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./package.json": "./package.json"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"README.md"
|
|
32
|
+
],
|
|
33
|
+
"sideEffects": false,
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public",
|
|
36
|
+
"provenance": true
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"docx",
|
|
40
|
+
"xlsx",
|
|
41
|
+
"pdf",
|
|
42
|
+
"ooxml",
|
|
43
|
+
"ecma-376",
|
|
44
|
+
"iso-32000",
|
|
45
|
+
"pdf/a",
|
|
46
|
+
"office",
|
|
47
|
+
"word",
|
|
48
|
+
"excel",
|
|
49
|
+
"converter"
|
|
50
|
+
],
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "vite build",
|
|
53
|
+
"prepack": "npm run build",
|
|
54
|
+
"prepublishOnly": "npm run build && npm run test:build",
|
|
55
|
+
"test": "vitest run",
|
|
56
|
+
"test:watch": "vitest",
|
|
57
|
+
"test:lib": "vitest run",
|
|
58
|
+
"test:types": "tsc -p tsconfig.json --noEmit",
|
|
59
|
+
"test:eslint": "eslint .",
|
|
60
|
+
"test:build": "publint --strict && attw --pack . --profile esm-only",
|
|
61
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
62
|
+
"lint": "eslint .",
|
|
63
|
+
"lint:fix": "eslint . --fix",
|
|
64
|
+
"format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.ts\"",
|
|
65
|
+
"format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\" \"scripts/**/*.ts\"",
|
|
66
|
+
"docs:api": "tsx scripts/docs/generate-api.ts",
|
|
67
|
+
"corpus:build": "tsx scripts/corpus/build-corpus.ts",
|
|
68
|
+
"corpus:fetch": "tsx scripts/corpus/fetch-corpus.ts",
|
|
69
|
+
"corpus:sandbox:build": "docker build -t docgen-losandbox:latest scripts/corpus/sandbox/",
|
|
70
|
+
"corpus": "tsx scripts/corpus/run.ts"
|
|
71
|
+
},
|
|
72
|
+
"dependencies": {
|
|
73
|
+
"fast-xml-parser": "5.7.0",
|
|
74
|
+
"fflate": "^0.8.2"
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@arethetypeswrong/cli": "^0.18.3",
|
|
78
|
+
"@tanstack/config": "^0.22.2",
|
|
79
|
+
"@types/node": "^22.10.0",
|
|
80
|
+
"prettier": "^3.8.3",
|
|
81
|
+
"publint": "^0.3.21",
|
|
82
|
+
"tsx": "^4.19.0",
|
|
83
|
+
"typescript": "^5.7.0",
|
|
84
|
+
"vite": "8.0.5",
|
|
85
|
+
"vitest": "^2.1.0"
|
|
86
|
+
},
|
|
87
|
+
"engines": {
|
|
88
|
+
"node": ">=20"
|
|
89
|
+
}
|
|
90
|
+
}
|