@design.estate/dees-document 5.6.0 → 6.1.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_bundle/bundle.js +289 -284
- package/dist_bundle/bundle.js.map +1 -1
- package/dist_bundle/bundle.js.third-party-notices.json +57 -70
- package/dist_bundle/bundle.js.third-party-notices.txt +82 -119
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.pdfservice.js +5 -2
- package/dist_ts/paths.js +1 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/contentinvoice.js +1 -1
- package/dist_ts_web/elements/document.d.ts +11 -1
- package/dist_ts_web/elements/document.js +64 -7
- package/dist_ts_web/elements/viewer.d.ts +2 -1
- package/dist_ts_web/elements/viewer.js +1 -1
- package/package.json +13 -13
- package/readme.md +4 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.pdfservice.ts +4 -3
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/document.ts +77 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@design.estate/dees-document",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A sophisticated framework for dynamically generating and rendering business documents like invoices with modern web technologies, featuring PDF creation, templating, and automation.",
|
|
6
6
|
"main": "dist_ts_web/index.js",
|
|
@@ -15,31 +15,31 @@
|
|
|
15
15
|
"author": "Lossless GmbH",
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@design.estate/dees-domtools": "^
|
|
19
|
-
"@design.estate/dees-element": "^
|
|
18
|
+
"@design.estate/dees-domtools": "^5.0.0",
|
|
19
|
+
"@design.estate/dees-element": "^4.0.1",
|
|
20
20
|
"@fin.cx/calculation": "^1.4.0",
|
|
21
21
|
"@push.rocks/smartfile": "^13.1.3",
|
|
22
22
|
"@push.rocks/smartfs": "^1.7.0",
|
|
23
23
|
"@push.rocks/smartjson": "^6.0.2",
|
|
24
24
|
"@push.rocks/smartpath": "^6.0.0",
|
|
25
|
-
"@push.rocks/smartpdf": "^6.0
|
|
25
|
+
"@push.rocks/smartpdf": "^6.5.0",
|
|
26
26
|
"@push.rocks/smarttime": "^4.2.3",
|
|
27
27
|
"@tsclass/tsclass": "^10.2.0",
|
|
28
28
|
"@types/qrcode": "^1.5.6",
|
|
29
29
|
"qrcode": "^1.5.4"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@design.estate/dees-catalog": "^
|
|
32
|
+
"@design.estate/dees-catalog": "^21.0.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@design.estate/dees-catalog": "^
|
|
36
|
-
"@design.estate/dees-wcctools": "^
|
|
37
|
-
"@git.zone/tsbuild": "^
|
|
38
|
-
"@git.zone/tsbundle": "^3.1
|
|
39
|
-
"@git.zone/tsrun": "^3.0.
|
|
40
|
-
"@git.zone/tstest": "^7.
|
|
41
|
-
"@git.zone/tswatch": "^
|
|
42
|
-
"@types/node": "^26.6.
|
|
35
|
+
"@design.estate/dees-catalog": "^21.0.0",
|
|
36
|
+
"@design.estate/dees-wcctools": "^5.0.0",
|
|
37
|
+
"@git.zone/tsbuild": "^6.0.2",
|
|
38
|
+
"@git.zone/tsbundle": "^3.2.1",
|
|
39
|
+
"@git.zone/tsrun": "^3.0.3",
|
|
40
|
+
"@git.zone/tstest": "^7.2.0",
|
|
41
|
+
"@git.zone/tswatch": "^7.1.1",
|
|
42
|
+
"@types/node": "^26.6.4"
|
|
43
43
|
},
|
|
44
44
|
"files": [
|
|
45
45
|
"ts/**/*",
|
package/readme.md
CHANGED
|
@@ -12,7 +12,7 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
|
|
|
12
12
|
pnpm install @design.estate/dees-document @design.estate/dees-catalog
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
`@design.estate/dees-catalog` is a peer dependency (
|
|
15
|
+
`@design.estate/dees-catalog` is a peer dependency (21.x, the catalog on `@design.estate/dees-element` 4): the web components (`@design.estate/dees-document/web`) render the catalog's `dees-icon` and use the catalog copy your application installs. Custom elements are registered globally, so an application must hold one catalog copy, and a component library that brought its own would register each catalog element a second time. pnpm and npm 7+ install a missing peer automatically; Yarn reports it as missing, so list it yourself. The web components run on `@design.estate/dees-element` 4 and `@design.estate/dees-domtools` 5; an application that depends on either itself needs those majors too, or its bundle carries a second copy. The server side (`@design.estate/dees-document`, `/node`) and `/shared` do not load the catalog at runtime: `PdfService` renders with the bundle built into the package.
|
|
16
16
|
|
|
17
17
|
## Features
|
|
18
18
|
|
|
@@ -142,7 +142,7 @@ await fs.file('./invoice.pdf').write(Buffer.from(pdfResult.buffer));
|
|
|
142
142
|
await pdfService.stop();
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
-
`createPdfFromLetterObject()` returns the `IPdf` of `@push.rocks/smartpdf` 6: the PDF in `buffer`, and in `metadata.textExtraction` its text as PDF.js reads it, a line break where a printed line ends and a blank line (`PDF_TEXT_PAGE_SEPARATOR` of smartpdf) between pages. PDF generation needs Node.js 22.13 or newer.
|
|
145
|
+
`createPdfFromLetterObject()` returns the `IPdf` of `@push.rocks/smartpdf` 6: the PDF in `buffer`, and in `metadata.textExtraction` its text as PDF.js reads it, a line break where a printed line ends and a blank line (`PDF_TEXT_PAGE_SEPARATOR` of smartpdf) between pages. The page is printed once the document is laid out (it has the attribute `rendered`, see [Web Component Usage](#web-component-usage)); a document that is not within 30 seconds rejects with an error naming the selector it waited for and the errors the page threw. PDF generation needs Node.js 22.13 or newer.
|
|
146
146
|
|
|
147
147
|
### Document Settings
|
|
148
148
|
|
|
@@ -214,6 +214,8 @@ html`
|
|
|
214
214
|
`;
|
|
215
215
|
```
|
|
216
216
|
|
|
217
|
+
`<dedocument-dedocument>` lays the letter out on pages after it updates. Once the pages show the current letter and settings, with their images loaded (or failed) and the fonts ready, the element has the attribute `rendered`; a change to the letter or the settings takes it away until the pages show the change. Whatever prints or captures the element waits for `dedocument-dedocument[rendered]`, as `PdfService` does.
|
|
218
|
+
|
|
217
219
|
### Translation System
|
|
218
220
|
|
|
219
221
|
The package includes a translation system for multi-language document generation:
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@design.estate/dees-document',
|
|
6
|
-
version: '
|
|
6
|
+
version: '6.1.0',
|
|
7
7
|
description: 'A sophisticated framework for dynamically generating and rendering business documents like invoices with modern web technologies, featuring PDF creation, templating, and automation.'
|
|
8
8
|
}
|
package/ts/classes.pdfservice.ts
CHANGED
|
@@ -66,9 +66,10 @@ export class PdfService {
|
|
|
66
66
|
)}"></dedocument-dedocument>
|
|
67
67
|
`;
|
|
68
68
|
// console.log(html);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
// the page is printed once the document's pages are done, with their images and fonts
|
|
70
|
+
const pdfResult = await this.smartpdfInstance.getA4PdfResultForHtmlString(html, {
|
|
71
|
+
readySelector: "dedocument-dedocument[rendered]",
|
|
72
|
+
});
|
|
72
73
|
return pdfResult;
|
|
73
74
|
}
|
|
74
75
|
}
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@design.estate/dees-document',
|
|
6
|
-
version: '
|
|
6
|
+
version: '6.1.0',
|
|
7
7
|
description: 'A sophisticated framework for dynamically generating and rendering business documents like invoices with modern web technologies, featuring PDF creation, templating, and automation.'
|
|
8
8
|
}
|
|
@@ -38,6 +38,42 @@ declare global {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/** the elements under a node, those in shadow roots included */
|
|
42
|
+
const elementsUnder = (rootArg: ParentNode): Element[] => {
|
|
43
|
+
const found: Element[] = [];
|
|
44
|
+
for (const element of Array.from(rootArg.querySelectorAll("*"))) {
|
|
45
|
+
found.push(element);
|
|
46
|
+
if (element.shadowRoot) {
|
|
47
|
+
found.push(...elementsUnder(element.shadowRoot));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return found;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Resolves once the pages under a node show what they are given: no element
|
|
55
|
+
* under it has an update pending, its images have loaded or failed, and the
|
|
56
|
+
* fonts are ready.
|
|
57
|
+
*/
|
|
58
|
+
const settleRendering = async (rootArg: ParentNode): Promise<void> => {
|
|
59
|
+
for (;;) {
|
|
60
|
+
const pending = elementsUnder(rootArg).filter(
|
|
61
|
+
(element): element is DeesElement =>
|
|
62
|
+
element instanceof DeesElement && element.isUpdatePending
|
|
63
|
+
);
|
|
64
|
+
if (pending.length === 0) {
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
await Promise.all(pending.map((element) => element.updateComplete));
|
|
68
|
+
}
|
|
69
|
+
const images = elementsUnder(rootArg).filter(
|
|
70
|
+
(element): element is HTMLImageElement => element instanceof HTMLImageElement
|
|
71
|
+
);
|
|
72
|
+
// an image that fails is shown as the browser shows it: it settles all the same
|
|
73
|
+
await Promise.all(images.map((image) => image.decode().catch(() => {})));
|
|
74
|
+
await document.fonts.ready;
|
|
75
|
+
};
|
|
76
|
+
|
|
41
77
|
@customElement("dedocument-dedocument")
|
|
42
78
|
export class DeDocument extends DeesElement {
|
|
43
79
|
public static demo = demoFunc;
|
|
@@ -121,15 +157,23 @@ export class DeDocument extends DeesElement {
|
|
|
121
157
|
return html` <div class="documentContainer"></div> `;
|
|
122
158
|
}
|
|
123
159
|
|
|
124
|
-
public
|
|
125
|
-
|
|
126
|
-
) {
|
|
127
|
-
|
|
160
|
+
public willUpdate(
|
|
161
|
+
changedProperties: Map<string | number | symbol, unknown>
|
|
162
|
+
): void {
|
|
163
|
+
super.willUpdate(changedProperties);
|
|
164
|
+
// the settings the document is first given are completed with the
|
|
165
|
+
// defaults before its first update, so it renders once, with them
|
|
166
|
+
if (!this.hasUpdated) {
|
|
128
167
|
this.documentSettings = {
|
|
129
168
|
...defaultDocumentSettings,
|
|
130
169
|
...this.documentSettings,
|
|
131
170
|
};
|
|
132
|
-
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
public async firstUpdated(
|
|
175
|
+
_changedProperties: Map<string | number | symbol, unknown>
|
|
176
|
+
) {
|
|
133
177
|
const resizeObserver = new ResizeObserver((entries) => {
|
|
134
178
|
for (const entry of entries) {
|
|
135
179
|
const width = entry.contentRect.width;
|
|
@@ -149,8 +193,19 @@ export class DeDocument extends DeesElement {
|
|
|
149
193
|
public latestRenderedLetterData: plugins.tsclass.business.TLetter | null = null;
|
|
150
194
|
public cleanupStore: HTMLElement[] = [];
|
|
151
195
|
public paginationInfo: IPagePaginationInfo[] = [];
|
|
196
|
+
/** the renders begun; a render a later one superseded leaves the document to it */
|
|
197
|
+
private renderGeneration = 0;
|
|
152
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Lays the letter out on pages. Once the pages show the current letter and
|
|
201
|
+
* settings, with their images loaded and the fonts ready, the element has
|
|
202
|
+
* the attribute `rendered` (what a print of it can wait for); a render begun
|
|
203
|
+
* since takes it away until that render is done.
|
|
204
|
+
*/
|
|
153
205
|
public async renderDocument() {
|
|
206
|
+
const generation = ++this.renderGeneration;
|
|
207
|
+
const isCurrent = () => generation === this.renderGeneration;
|
|
208
|
+
this.removeAttribute("rendered");
|
|
154
209
|
// a document whose advance payments do not add up to its paid amount, or
|
|
155
210
|
// whose accent colour is no hex colour, is refused: no page of it, and none
|
|
156
211
|
// of the letter before it, stays on screen. The accent is checked here,
|
|
@@ -168,7 +223,7 @@ export class DeDocument extends DeesElement {
|
|
|
168
223
|
}
|
|
169
224
|
this.latestDocumentSettings = this.documentSettings;
|
|
170
225
|
this.latestRenderedLetterData = this.letterData;
|
|
171
|
-
|
|
226
|
+
const paginationInfo: IPagePaginationInfo[] = [];
|
|
172
227
|
|
|
173
228
|
const cleanUpStoreCurrentRender: HTMLElement[] = [];
|
|
174
229
|
const cleanUpStoreNextRender: HTMLElement[] = [];
|
|
@@ -189,7 +244,7 @@ export class DeDocument extends DeesElement {
|
|
|
189
244
|
content.documentSettings = this.documentSettings;
|
|
190
245
|
document.body.appendChild(content);
|
|
191
246
|
|
|
192
|
-
await domtools.convenience.
|
|
247
|
+
await domtools.convenience.smartpromise.delayFor(0);
|
|
193
248
|
let overallContentOffset: number = 0;
|
|
194
249
|
let currentContentOffset: number;
|
|
195
250
|
let trimmed: number;
|
|
@@ -224,7 +279,7 @@ export class DeDocument extends DeesElement {
|
|
|
224
279
|
overallContentOffset = overallContentOffset + currentContentOffset;
|
|
225
280
|
|
|
226
281
|
// Track pagination info for this page
|
|
227
|
-
|
|
282
|
+
paginationInfo.push({
|
|
228
283
|
pageNumber: pageCounter,
|
|
229
284
|
startOffset: pageStartOffset,
|
|
230
285
|
contentLength: currentContentOffset,
|
|
@@ -235,6 +290,15 @@ export class DeDocument extends DeesElement {
|
|
|
235
290
|
}
|
|
236
291
|
}
|
|
237
292
|
|
|
293
|
+
if (!isCurrent()) {
|
|
294
|
+
// a later render shows the document: this one's pages are dropped
|
|
295
|
+
for (const cleanUp of [...cleanUpStoreCurrentRender, ...cleanUpStoreNextRender]) {
|
|
296
|
+
cleanUp.remove();
|
|
297
|
+
}
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
this.paginationInfo = paginationInfo;
|
|
301
|
+
|
|
238
302
|
for (const cleanUp of this.cleanupStore) {
|
|
239
303
|
cleanUp.remove();
|
|
240
304
|
}
|
|
@@ -275,6 +339,11 @@ export class DeDocument extends DeesElement {
|
|
|
275
339
|
bubbles: true,
|
|
276
340
|
composed: true,
|
|
277
341
|
}));
|
|
342
|
+
|
|
343
|
+
await settleRendering(documentContainer);
|
|
344
|
+
if (isCurrent()) {
|
|
345
|
+
this.toggleAttribute("rendered", true);
|
|
346
|
+
}
|
|
278
347
|
}
|
|
279
348
|
|
|
280
349
|
async updated(
|