@nxgt/material-core 0.1.1 → 0.2.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/README.md +70 -4
- package/dist/lib/format-file-size.d.ts +10 -0
- package/dist/lib/format-file-size.d.ts.map +1 -0
- package/dist/lib/format-file-size.js +17 -0
- package/dist/lib/format-file-size.js.map +10 -0
- package/dist/pdfkit-fonts/index.d.ts +61 -0
- package/dist/pdfkit-fonts/index.d.ts.map +1 -0
- package/dist/pdfkit-fonts/index.js +80 -0
- package/dist/pdfkit-fonts/index.js.map +10 -0
- package/docs/roadmap.md +5 -0
- package/docs/troubleshooting.md +65 -0
- package/package.json +15 -3
package/README.md
CHANGED
|
@@ -5,13 +5,16 @@ The framework-free core that [`@nxgt/material`](https://www.npmjs.com/package/@n
|
|
|
5
5
|
(Vue) share, as one copy: the PDF document model and its react-pdf renderer,
|
|
6
6
|
the print formatters, the PDF file helpers, the PDF viewer's framework-free
|
|
7
7
|
half (page geometry, scroll spy, text search), the currency field's decimals,
|
|
8
|
-
the fields' blur rule
|
|
9
|
-
fonts
|
|
8
|
+
the file-size formatter, the fields' blur rule, the Vite plugin that bundles
|
|
9
|
+
pdfkit's standard fonts, and the Node-only resolution of those fonts that the
|
|
10
|
+
Next.js helper and the Nuxt module run at build time.
|
|
10
11
|
|
|
11
12
|
**You usually do not install it yourself.** Both libraries depend on it and
|
|
12
13
|
re-export what they always exported, at the same subpaths:
|
|
13
14
|
`@nxgt/material/print`, `@nxgt/material-vue/pdf`, `/lib` and `/vite` read
|
|
14
|
-
from here, and so do their `PdfReader`, `CurrencyField
|
|
15
|
+
from here, and so do their `PdfReader`, `CurrencyField`, form fields, file
|
|
16
|
+
list and upload field (`formatFileSize`), `@nxgt/material/next` and
|
|
17
|
+
`@nxgt/material-vue/nuxt`. Import it directly when you want the model or a formatter without
|
|
15
18
|
a UI library.
|
|
16
19
|
|
|
17
20
|
```ts
|
|
@@ -42,7 +45,10 @@ files are plain ES modules and also load in Node without a bundler.
|
|
|
42
45
|
| `vite@^6 \|\| ^7 \|\| ^8` | `@nxgt/material-core/vite` — its declarations name Vite's `Plugin` type (types only); the plugin itself runs in your Vite config |
|
|
43
46
|
|
|
44
47
|
Every other subpath imports none of them, and is safe to import on a server
|
|
45
|
-
with no DOM.
|
|
48
|
+
with no DOM. One subpath is **Node only**: `/pdfkit-fonts` imports `node:module`
|
|
49
|
+
and `node:path`, for a framework's config at build time — never import it
|
|
50
|
+
from code a browser bundle can reach. No other subpath imports a `node:`
|
|
51
|
+
built-in.
|
|
46
52
|
|
|
47
53
|
## Subpaths
|
|
48
54
|
|
|
@@ -64,7 +70,9 @@ with no DOM.
|
|
|
64
70
|
| `/pdf-viewer` | The PDF viewer's pure half: page geometry and fit (`readerFitScale`, `placeholderSize`, `rotatedSize`, `PdfPageSize`, `FitMode`), page sizes (`readPageSizes`, `createPageSizesLoader`), the scroll spy (`createScrollSpy`, `revealHit`), text search (`pageTextFromItems`, `findTextMatches`, `searchDocument`), `escapeHtml`, `mapPdfOutline` |
|
|
65
71
|
| `/currency-digits` | `currencyFractionDigits` — the decimals `CurrencyField` shows |
|
|
66
72
|
| `/field-blur-layers` | `layerOf`, `openerOf`, `FieldLayers` — whose overlay a layer of the page is, for a field's blur |
|
|
73
|
+
| `/format-file-size` | `formatFileSize` — a byte count as `'1.5 KB'` |
|
|
67
74
|
| `/vite` | `pdfkitStandardFonts()` — see below |
|
|
75
|
+
| `/pdfkit-fonts` | **Node only.** `pdfkitStandardFontDirs`, `pdfkitStandardFontFiles`, `PDFKIT_STANDARD_FONTS`, the types `PdfkitStandardFont` and `PdfkitFontsWarn` — where the app's pdfkit keeps its standard fonts, for a server tracer |
|
|
68
76
|
|
|
69
77
|
## Usage
|
|
70
78
|
|
|
@@ -279,6 +287,23 @@ currencyFractionDigits('KWD'); // 3
|
|
|
279
287
|
currencyFractionDigits('EUR', 0); // 0 — an explicit value wins, as in formatAmount
|
|
280
288
|
```
|
|
281
289
|
|
|
290
|
+
### A file's size: `/format-file-size`
|
|
291
|
+
|
|
292
|
+
1024-based, one decimal above bytes, capped at GB, locale-free: a server and
|
|
293
|
+
a browser print the same string. What both libraries' `FileList`,
|
|
294
|
+
`NetworkUploadField` (and its size limit message), `FileCard` and chat
|
|
295
|
+
attachments show; both re-export it as `formatFileSize`.
|
|
296
|
+
|
|
297
|
+
```ts
|
|
298
|
+
import { formatFileSize } from '@nxgt/material-core/format-file-size';
|
|
299
|
+
|
|
300
|
+
formatFileSize(0); // '0 B'
|
|
301
|
+
formatFileSize(512); // '512 B'
|
|
302
|
+
formatFileSize(1536); // '1.5 KB'
|
|
303
|
+
formatFileSize(5 * 1024 ** 2); // '5.0 MB'
|
|
304
|
+
formatFileSize(-1); // '' — as for NaN and Infinity
|
|
305
|
+
```
|
|
306
|
+
|
|
282
307
|
### A field's blur across overlays: `/field-blur-layers`
|
|
283
308
|
|
|
284
309
|
A field whose popover, listbox or dialog renders into `<body>` must not count
|
|
@@ -317,12 +342,53 @@ export default defineConfig({ plugins: [pdfkitStandardFonts()] });
|
|
|
317
342
|
function. The doc comment on `pdfkitStandardFonts` explains when you need it
|
|
318
343
|
and when keeping the library external is the lighter answer.
|
|
319
344
|
|
|
345
|
+
### Tracing pdfkit's fonts: `/pdfkit-fonts` (Node only)
|
|
346
|
+
|
|
347
|
+
A server that keeps `node_modules` but copies only what a tracer finds
|
|
348
|
+
(`next build` with `output: 'standalone'`, Nitro's `.output/server`) gets
|
|
349
|
+
pdfkit without its fonts: pdfkit loads them with a runtime
|
|
350
|
+
`require('#standard-fonts/<Name>')` no tracer follows, and every PDF then
|
|
351
|
+
fails with `Cannot find module '…/pdfkit/js/standard-fonts/Helvetica.cjs'`.
|
|
352
|
+
These functions find the real files, as the app at a project directory
|
|
353
|
+
loads them — through `@react-pdf/renderer` and through `@react-pdf/font`,
|
|
354
|
+
each of which may nest its own pdfkit — for you to hand to the tracer.
|
|
355
|
+
|
|
356
|
+
```ts
|
|
357
|
+
// A build script or a framework config: Node code.
|
|
358
|
+
import { pdfkitStandardFontDirs, pdfkitStandardFontFiles } from '@nxgt/material-core/pdfkit-fonts';
|
|
359
|
+
|
|
360
|
+
const warn = (message: string) => console.warn(`[my-build] ${message}`);
|
|
361
|
+
|
|
362
|
+
pdfkitStandardFontDirs(process.cwd(), warn);
|
|
363
|
+
// ['/app/node_modules/pdfkit/js/standard-fonts'] — one per distinct pdfkit;
|
|
364
|
+
// each also holds the chunks/ the fonts require
|
|
365
|
+
|
|
366
|
+
pdfkitStandardFontFiles(process.cwd(), warn);
|
|
367
|
+
// ['/app/node_modules/pdfkit/js/standard-fonts/Courier.cjs', … 14 per pdfkit]
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
- **Without `@react-pdf/renderer`** (an optional peer: the app does not
|
|
371
|
+
print), both return `[]` and never call `warn`.
|
|
372
|
+
- **Otherwise, whatever fails** (`@react-pdf/font` or pdfkit not
|
|
373
|
+
resolvable, a font missing) reaches `warn` **once per call**, every problem
|
|
374
|
+
in one line (each error's first line, without Node's `Require stack:`),
|
|
375
|
+
and the rest is still returned. Prefix it with your
|
|
376
|
+
tool's name; a font that cannot be traced is a PDF route that fails in
|
|
377
|
+
production.
|
|
378
|
+
- A relative project directory is taken from the working directory. The
|
|
379
|
+
paths are real paths (symlinks resolved), as pnpm and bun lay them out.
|
|
380
|
+
|
|
381
|
+
You rarely call it yourself: `withNxgtPrint` (`@nxgt/material/next`) turns
|
|
382
|
+
the directories into `outputFileTracingIncludes` globs, and the Nuxt module
|
|
383
|
+
of `@nxgt/material-vue` adds the files to `nitro.externals.traceInclude`.
|
|
384
|
+
|
|
320
385
|
## Traps
|
|
321
386
|
|
|
322
387
|
| Symptom | Fix |
|
|
323
388
|
| --- | --- |
|
|
324
389
|
| `Cannot find package '@react-pdf/renderer'` (or `'react'`) when importing `/pdf` or `/pdf/render` | `bun add react @react-pdf/renderer@^4.9` — or import from `/pdf/model` where you only build documents |
|
|
325
390
|
| `Cannot find module '#standard-fonts/Helvetica'` on every request of a bundled server | `pdfkitStandardFonts()` from `/vite`, or keep the renderer external |
|
|
391
|
+
| `Cannot find module '…/pdfkit/js/standard-fonts/Helvetica.cjs'` from a traced server output | add `pdfkitStandardFontFiles()` (or the directories' `**/*.cjs`) to the tracer's includes — `withNxgtPrint` and the Nuxt module do |
|
|
326
392
|
|
|
327
393
|
Every message, with its cause, is in [troubleshooting](https://cdn.jsdelivr.net/npm/@nxgt/material-core@0/docs/troubleshooting.md).
|
|
328
394
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A byte count as people read it: `'512 B'`, `'1.5 KB'`, `'2.0 MB'`,
|
|
3
|
+
* `'1.0 GB'` (1024-based, one decimal above bytes, capped at GB), and `''`
|
|
4
|
+
* for a negative, `NaN` or infinite size. Locale-free, so a server and a
|
|
5
|
+
* browser print the same thing. The file list, the upload field and its
|
|
6
|
+
* constraints, the file card and the chat attachment chip of both libraries
|
|
7
|
+
* use it.
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatFileSize(bytes: number): string;
|
|
10
|
+
//# sourceMappingURL=format-file-size.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-file-size.d.ts","sourceRoot":"","sources":["../../src/lib/format-file-size.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUpD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/lib/format-file-size.ts
|
|
2
|
+
function formatFileSize(bytes) {
|
|
3
|
+
if (bytes < 0 || !Number.isFinite(bytes))
|
|
4
|
+
return "";
|
|
5
|
+
if (bytes === 0)
|
|
6
|
+
return "0 B";
|
|
7
|
+
const units = ["B", "KB", "MB", "GB"];
|
|
8
|
+
const exponent = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
|
|
9
|
+
const value = bytes / 1024 ** exponent;
|
|
10
|
+
return `${exponent === 0 ? value : value.toFixed(1)} ${units[exponent]}`;
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
formatFileSize
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
//# debugId=5CC787DB991D0F4A64756E2164756E21
|
|
17
|
+
//# sourceMappingURL=format-file-size.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/lib/format-file-size.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * A byte count as people read it: `'512 B'`, `'1.5 KB'`, `'2.0 MB'`,\n * `'1.0 GB'` (1024-based, one decimal above bytes, capped at GB), and `''`\n * for a negative, `NaN` or infinite size. Locale-free, so a server and a\n * browser print the same thing. The file list, the upload field and its\n * constraints, the file card and the chat attachment chip of both libraries\n * use it.\n */\nexport function formatFileSize(bytes: number): string {\n\tif (bytes < 0 || !Number.isFinite(bytes)) return '';\n\tif (bytes === 0) return '0 B';\n\tconst units = ['B', 'KB', 'MB', 'GB'];\n\tconst exponent = Math.min(\n\t\tMath.floor(Math.log(bytes) / Math.log(1024)),\n\t\tunits.length - 1,\n\t);\n\tconst value = bytes / 1024 ** exponent;\n\treturn `${exponent === 0 ? value : value.toFixed(1)} ${units[exponent]}`;\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";AAQO,SAAS,cAAc,CAAC,OAAuB;AAAA,EACrD,IAAI,QAAQ,KAAK,CAAC,OAAO,SAAS,KAAK;AAAA,IAAG,OAAO;AAAA,EACjD,IAAI,UAAU;AAAA,IAAG,OAAO;AAAA,EACxB,MAAM,QAAQ,CAAC,KAAK,MAAM,MAAM,IAAI;AAAA,EACpC,MAAM,WAAW,KAAK,IACrB,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC,GAC3C,MAAM,SAAS,CAChB;AAAA,EACA,MAAM,QAAQ,QAAQ,QAAQ;AAAA,EAC9B,OAAO,GAAG,aAAa,IAAI,QAAQ,MAAM,QAAQ,CAAC,KAAK,MAAM;AAAA;",
|
|
8
|
+
"debugId": "5CC787DB991D0F4A64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where an app's pdfkit keeps its fourteen standard fonts, resolved the way
|
|
3
|
+
* that app loads them. Build-time code for a framework's config: the Next.js
|
|
4
|
+
* helper of `@nxgt/material` (`@nxgt/material/next`, which turns the
|
|
5
|
+
* directories into `outputFileTracingIncludes` globs) and the Nuxt module of
|
|
6
|
+
* `@nxgt/material-vue` (which adds the files to Nitro's `traceInclude`).
|
|
7
|
+
*
|
|
8
|
+
* **Node only.** This is the one subpath of `@nxgt/material-core` that
|
|
9
|
+
* imports `node:*` built-ins (`node:module`, `node:path`); `verify:ssr` fails
|
|
10
|
+
* the build if any other reaches one. Never import it from code that can end
|
|
11
|
+
* up in a browser bundle.
|
|
12
|
+
*
|
|
13
|
+
* Why it exists: pdfkit registers its fonts with a runtime
|
|
14
|
+
* `require('#standard-fonts/<Name>')`, a package-`imports` specifier private
|
|
15
|
+
* to pdfkit. A server tracer (Next.js's, Nitro's) does not follow a runtime
|
|
16
|
+
* `require`, so a traced server output has pdfkit but not its `.cjs` fonts,
|
|
17
|
+
* and every PDF rendered there fails with
|
|
18
|
+
* `Cannot find module '…/pdfkit/js/standard-fonts/Helvetica.cjs'`.
|
|
19
|
+
*
|
|
20
|
+
* pdfkit is found through `@react-pdf/renderer` and through
|
|
21
|
+
* `@react-pdf/font` (resolved from the renderer), since each can nest a
|
|
22
|
+
* pdfkit of its own. Resolving `pdfkit/standard-fonts/<Name>` from them
|
|
23
|
+
* under the `require` condition lands on the `.cjs` file pdfkit's runtime
|
|
24
|
+
* `require` reads, as a real path, under npm, pnpm and bun alike.
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { pdfkitStandardFontDirs } from '@nxgt/material-core/pdfkit-fonts';
|
|
28
|
+
*
|
|
29
|
+
* pdfkitStandardFontDirs(process.cwd(), (message) => console.warn(message));
|
|
30
|
+
* // ['/app/node_modules/pdfkit/js/standard-fonts']
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
/** The fourteen standard PDF fonts, as pdfkit exports them. */
|
|
34
|
+
export declare const PDFKIT_STANDARD_FONTS: readonly ["Courier", "CourierBold", "CourierBoldOblique", "CourierOblique", "Helvetica", "HelveticaBold", "HelveticaBoldOblique", "HelveticaOblique", "Symbol", "TimesBold", "TimesBoldItalic", "TimesItalic", "TimesRoman", "ZapfDingbats"];
|
|
35
|
+
export type PdfkitStandardFont = (typeof PDFKIT_STANDARD_FONTS)[number];
|
|
36
|
+
/** Receives the one warning a call can give. */
|
|
37
|
+
export type PdfkitFontsWarn = (message: string) => void;
|
|
38
|
+
/**
|
|
39
|
+
* pdfkit's `js/standard-fonts` directories, real paths, as the app at
|
|
40
|
+
* `projectDir` loads them: the one of the pdfkit `@react-pdf/renderer`
|
|
41
|
+
* depends on and the one of `@react-pdf/font`'s, without duplicates (one
|
|
42
|
+
* directory when both share a pdfkit, as they usually do). Each directory
|
|
43
|
+
* also holds the `chunks/` the fonts `require`.
|
|
44
|
+
*
|
|
45
|
+
* `[]`, silently, when `@react-pdf/renderer` is not installed. Anything else
|
|
46
|
+
* that fails is passed to `warn`, once per call: a font that cannot be traced
|
|
47
|
+
* is a PDF route that fails in production.
|
|
48
|
+
*/
|
|
49
|
+
export declare function pdfkitStandardFontDirs(projectDir: string, warn?: PdfkitFontsWarn): string[];
|
|
50
|
+
/**
|
|
51
|
+
* pdfkit's fourteen standard-font modules (`.cjs`, real paths), as the app
|
|
52
|
+
* at `projectDir` loads them: through pdfkit's own `standard-fonts/<Name>`
|
|
53
|
+
* exports under the `require` condition, for the pdfkit
|
|
54
|
+
* `@react-pdf/renderer` depends on and the one `@react-pdf/font` depends on,
|
|
55
|
+
* without duplicates.
|
|
56
|
+
*
|
|
57
|
+
* `[]`, silently, when `@react-pdf/renderer` is not installed. Anything else
|
|
58
|
+
* that fails is passed to `warn`, once per call.
|
|
59
|
+
*/
|
|
60
|
+
export declare function pdfkitStandardFontFiles(projectDir: string, warn?: PdfkitFontsWarn): string[];
|
|
61
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pdfkit-fonts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,+DAA+D;AAC/D,eAAO,MAAM,qBAAqB,8OAexB,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,gDAAgD;AAChD,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAyDxD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACrC,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,eAA0B,GAC9B,MAAM,EAAE,CAYV;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACtC,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,eAA0B,GAC9B,MAAM,EAAE,CAcV"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// src/pdfkit-fonts/index.ts
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
var PDFKIT_STANDARD_FONTS = [
|
|
5
|
+
"Courier",
|
|
6
|
+
"CourierBold",
|
|
7
|
+
"CourierBoldOblique",
|
|
8
|
+
"CourierOblique",
|
|
9
|
+
"Helvetica",
|
|
10
|
+
"HelveticaBold",
|
|
11
|
+
"HelveticaBoldOblique",
|
|
12
|
+
"HelveticaOblique",
|
|
13
|
+
"Symbol",
|
|
14
|
+
"TimesBold",
|
|
15
|
+
"TimesBoldItalic",
|
|
16
|
+
"TimesItalic",
|
|
17
|
+
"TimesRoman",
|
|
18
|
+
"ZapfDingbats"
|
|
19
|
+
];
|
|
20
|
+
var isNotFound = (error) => error?.code === "MODULE_NOT_FOUND";
|
|
21
|
+
var firstLine = (error) => String(error).split(`
|
|
22
|
+
`, 1)[0] ?? "";
|
|
23
|
+
function fromEachPdfkit(projectDir, warn, collect) {
|
|
24
|
+
const problems = [];
|
|
25
|
+
let renderer;
|
|
26
|
+
try {
|
|
27
|
+
renderer = createRequire(join(resolve(projectDir), "package.json")).resolve("@react-pdf/renderer");
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (!isNotFound(error)) {
|
|
30
|
+
warn(`could not resolve @react-pdf/renderer: ${firstLine(error)}`);
|
|
31
|
+
}
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const fromRenderer = createRequire(renderer);
|
|
35
|
+
const owners = [["@react-pdf/renderer", fromRenderer]];
|
|
36
|
+
try {
|
|
37
|
+
owners.push([
|
|
38
|
+
"@react-pdf/font",
|
|
39
|
+
createRequire(fromRenderer.resolve("@react-pdf/font"))
|
|
40
|
+
]);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
problems.push(`could not resolve @react-pdf/font: ${firstLine(error)}`);
|
|
43
|
+
}
|
|
44
|
+
for (const [owner, from] of owners)
|
|
45
|
+
collect(owner, from, problems);
|
|
46
|
+
if (problems.length > 0)
|
|
47
|
+
warn(problems.join("; "));
|
|
48
|
+
}
|
|
49
|
+
function pdfkitStandardFontDirs(projectDir, warn = () => {}) {
|
|
50
|
+
const dirs = new Set;
|
|
51
|
+
fromEachPdfkit(projectDir, warn, (owner, from, problems) => {
|
|
52
|
+
try {
|
|
53
|
+
dirs.add(dirname(from.resolve("pdfkit/standard-fonts/Helvetica")));
|
|
54
|
+
} catch (error) {
|
|
55
|
+
problems.push(`could not resolve pdfkit's fonts for ${owner}: ${firstLine(error)}`);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return [...dirs];
|
|
59
|
+
}
|
|
60
|
+
function pdfkitStandardFontFiles(projectDir, warn = () => {}) {
|
|
61
|
+
const files = new Set;
|
|
62
|
+
fromEachPdfkit(projectDir, warn, (owner, from, problems) => {
|
|
63
|
+
for (const font of PDFKIT_STANDARD_FONTS) {
|
|
64
|
+
try {
|
|
65
|
+
files.add(from.resolve(`pdfkit/standard-fonts/${font}`));
|
|
66
|
+
} catch (error) {
|
|
67
|
+
problems.push(`could not resolve pdfkit's ${font} font for ${owner}: ${firstLine(error)}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return [...files];
|
|
72
|
+
}
|
|
73
|
+
export {
|
|
74
|
+
PDFKIT_STANDARD_FONTS,
|
|
75
|
+
pdfkitStandardFontDirs,
|
|
76
|
+
pdfkitStandardFontFiles
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
//# debugId=D12CCCD8FE08400864756E2164756E21
|
|
80
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/pdfkit-fonts/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Where an app's pdfkit keeps its fourteen standard fonts, resolved the way\n * that app loads them. Build-time code for a framework's config: the Next.js\n * helper of `@nxgt/material` (`@nxgt/material/next`, which turns the\n * directories into `outputFileTracingIncludes` globs) and the Nuxt module of\n * `@nxgt/material-vue` (which adds the files to Nitro's `traceInclude`).\n *\n * **Node only.** This is the one subpath of `@nxgt/material-core` that\n * imports `node:*` built-ins (`node:module`, `node:path`); `verify:ssr` fails\n * the build if any other reaches one. Never import it from code that can end\n * up in a browser bundle.\n *\n * Why it exists: pdfkit registers its fonts with a runtime\n * `require('#standard-fonts/<Name>')`, a package-`imports` specifier private\n * to pdfkit. A server tracer (Next.js's, Nitro's) does not follow a runtime\n * `require`, so a traced server output has pdfkit but not its `.cjs` fonts,\n * and every PDF rendered there fails with\n * `Cannot find module '…/pdfkit/js/standard-fonts/Helvetica.cjs'`.\n *\n * pdfkit is found through `@react-pdf/renderer` and through\n * `@react-pdf/font` (resolved from the renderer), since each can nest a\n * pdfkit of its own. Resolving `pdfkit/standard-fonts/<Name>` from them\n * under the `require` condition lands on the `.cjs` file pdfkit's runtime\n * `require` reads, as a real path, under npm, pnpm and bun alike.\n *\n * ```ts\n * import { pdfkitStandardFontDirs } from '@nxgt/material-core/pdfkit-fonts';\n *\n * pdfkitStandardFontDirs(process.cwd(), (message) => console.warn(message));\n * // ['/app/node_modules/pdfkit/js/standard-fonts']\n * ```\n */\n\nimport { createRequire } from 'node:module';\nimport { dirname, join, resolve } from 'node:path';\n\n/** The fourteen standard PDF fonts, as pdfkit exports them. */\nexport const PDFKIT_STANDARD_FONTS = [\n\t'Courier',\n\t'CourierBold',\n\t'CourierBoldOblique',\n\t'CourierOblique',\n\t'Helvetica',\n\t'HelveticaBold',\n\t'HelveticaBoldOblique',\n\t'HelveticaOblique',\n\t'Symbol',\n\t'TimesBold',\n\t'TimesBoldItalic',\n\t'TimesItalic',\n\t'TimesRoman',\n\t'ZapfDingbats',\n] as const;\n\nexport type PdfkitStandardFont = (typeof PDFKIT_STANDARD_FONTS)[number];\n\n/** Receives the one warning a call can give. */\nexport type PdfkitFontsWarn = (message: string) => void;\n\ntype Require = ReturnType<typeof createRequire>;\n\nconst isNotFound = (error: unknown) =>\n\t(error as { code?: string } | null)?.code === 'MODULE_NOT_FOUND';\n\n/**\n * An error as one line: its text up to the first newline. Node's\n * `Cannot find module` error appends a multi-line `Require stack:`, and the\n * warning joins every problem into ONE line: kept whole, a single failure\n * buried the others under a dozen stack paths.\n */\nconst firstLine = (error: unknown): string =>\n\tString(error).split('\\n', 1)[0] ?? '';\n\n/**\n * Runs `collect` with the `require` of each package that depends on pdfkit\n * (`@react-pdf/renderer`, then `@react-pdf/font`), and hands every problem\n * met on the way to `warn` as ONE message, joined by `; `, each error cut\n * to its first line (`firstLine`). None, silently,\n * when the app does not install `@react-pdf/renderer`: it is an optional\n * peer, and an app that does not print has no fonts to find.\n */\nfunction fromEachPdfkit(\n\tprojectDir: string,\n\twarn: PdfkitFontsWarn,\n\tcollect: (owner: string, from: Require, problems: string[]) => void,\n): void {\n\tconst problems: string[] = [];\n\tlet renderer: string;\n\ttry {\n\t\t// createRequire takes an absolute path only: a relative `projectDir`\n\t\t// is taken from the working directory.\n\t\trenderer = createRequire(join(resolve(projectDir), 'package.json')).resolve(\n\t\t\t'@react-pdf/renderer',\n\t\t);\n\t} catch (error) {\n\t\tif (!isNotFound(error)) {\n\t\t\twarn(`could not resolve @react-pdf/renderer: ${firstLine(error)}`);\n\t\t}\n\t\treturn;\n\t}\n\tconst fromRenderer = createRequire(renderer);\n\tconst owners: [string, Require][] = [['@react-pdf/renderer', fromRenderer]];\n\ttry {\n\t\towners.push([\n\t\t\t'@react-pdf/font',\n\t\t\tcreateRequire(fromRenderer.resolve('@react-pdf/font')),\n\t\t]);\n\t} catch (error) {\n\t\tproblems.push(`could not resolve @react-pdf/font: ${firstLine(error)}`);\n\t}\n\tfor (const [owner, from] of owners) collect(owner, from, problems);\n\tif (problems.length > 0) warn(problems.join('; '));\n}\n\n/**\n * pdfkit's `js/standard-fonts` directories, real paths, as the app at\n * `projectDir` loads them: the one of the pdfkit `@react-pdf/renderer`\n * depends on and the one of `@react-pdf/font`'s, without duplicates (one\n * directory when both share a pdfkit, as they usually do). Each directory\n * also holds the `chunks/` the fonts `require`.\n *\n * `[]`, silently, when `@react-pdf/renderer` is not installed. Anything else\n * that fails is passed to `warn`, once per call: a font that cannot be traced\n * is a PDF route that fails in production.\n */\nexport function pdfkitStandardFontDirs(\n\tprojectDir: string,\n\twarn: PdfkitFontsWarn = () => {},\n): string[] {\n\tconst dirs = new Set<string>();\n\tfromEachPdfkit(projectDir, warn, (owner, from, problems) => {\n\t\ttry {\n\t\t\tdirs.add(dirname(from.resolve('pdfkit/standard-fonts/Helvetica')));\n\t\t} catch (error) {\n\t\t\tproblems.push(\n\t\t\t\t`could not resolve pdfkit's fonts for ${owner}: ${firstLine(error)}`,\n\t\t\t);\n\t\t}\n\t});\n\treturn [...dirs];\n}\n\n/**\n * pdfkit's fourteen standard-font modules (`.cjs`, real paths), as the app\n * at `projectDir` loads them: through pdfkit's own `standard-fonts/<Name>`\n * exports under the `require` condition, for the pdfkit\n * `@react-pdf/renderer` depends on and the one `@react-pdf/font` depends on,\n * without duplicates.\n *\n * `[]`, silently, when `@react-pdf/renderer` is not installed. Anything else\n * that fails is passed to `warn`, once per call.\n */\nexport function pdfkitStandardFontFiles(\n\tprojectDir: string,\n\twarn: PdfkitFontsWarn = () => {},\n): string[] {\n\tconst files = new Set<string>();\n\tfromEachPdfkit(projectDir, warn, (owner, from, problems) => {\n\t\tfor (const font of PDFKIT_STANDARD_FONTS) {\n\t\t\ttry {\n\t\t\t\tfiles.add(from.resolve(`pdfkit/standard-fonts/${font}`));\n\t\t\t} catch (error) {\n\t\t\t\tproblems.push(\n\t\t\t\t\t`could not resolve pdfkit's ${font} font for ${owner}: ${firstLine(error)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t});\n\treturn [...files];\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";AAiCA;AACA;AAGO,IAAM,wBAAwB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AASA,IAAM,aAAa,CAAC,UAClB,OAAoC,SAAS;AAQ/C,IAAM,YAAY,CAAC,UAClB,OAAO,KAAK,EAAE,MAAM;AAAA,GAAM,CAAC,EAAE,MAAM;AAUpC,SAAS,cAAc,CACtB,YACA,MACA,SACO;AAAA,EACP,MAAM,WAAqB,CAAC;AAAA,EAC5B,IAAI;AAAA,EACJ,IAAI;AAAA,IAGH,WAAW,cAAc,KAAK,QAAQ,UAAU,GAAG,cAAc,CAAC,EAAE,QACnE,qBACD;AAAA,IACC,OAAO,OAAO;AAAA,IACf,IAAI,CAAC,WAAW,KAAK,GAAG;AAAA,MACvB,KAAK,0CAA0C,UAAU,KAAK,GAAG;AAAA,IAClE;AAAA,IACA;AAAA;AAAA,EAED,MAAM,eAAe,cAAc,QAAQ;AAAA,EAC3C,MAAM,SAA8B,CAAC,CAAC,uBAAuB,YAAY,CAAC;AAAA,EAC1E,IAAI;AAAA,IACH,OAAO,KAAK;AAAA,MACX;AAAA,MACA,cAAc,aAAa,QAAQ,iBAAiB,CAAC;AAAA,IACtD,CAAC;AAAA,IACA,OAAO,OAAO;AAAA,IACf,SAAS,KAAK,sCAAsC,UAAU,KAAK,GAAG;AAAA;AAAA,EAEvE,YAAY,OAAO,SAAS;AAAA,IAAQ,QAAQ,OAAO,MAAM,QAAQ;AAAA,EACjE,IAAI,SAAS,SAAS;AAAA,IAAG,KAAK,SAAS,KAAK,IAAI,CAAC;AAAA;AAc3C,SAAS,sBAAsB,CACrC,YACA,OAAwB,MAAM,IACnB;AAAA,EACX,MAAM,OAAO,IAAI;AAAA,EACjB,eAAe,YAAY,MAAM,CAAC,OAAO,MAAM,aAAa;AAAA,IAC3D,IAAI;AAAA,MACH,KAAK,IAAI,QAAQ,KAAK,QAAQ,iCAAiC,CAAC,CAAC;AAAA,MAChE,OAAO,OAAO;AAAA,MACf,SAAS,KACR,wCAAwC,UAAU,UAAU,KAAK,GAClE;AAAA;AAAA,GAED;AAAA,EACD,OAAO,CAAC,GAAG,IAAI;AAAA;AAaT,SAAS,uBAAuB,CACtC,YACA,OAAwB,MAAM,IACnB;AAAA,EACX,MAAM,QAAQ,IAAI;AAAA,EAClB,eAAe,YAAY,MAAM,CAAC,OAAO,MAAM,aAAa;AAAA,IAC3D,WAAW,QAAQ,uBAAuB;AAAA,MACzC,IAAI;AAAA,QACH,MAAM,IAAI,KAAK,QAAQ,yBAAyB,MAAM,CAAC;AAAA,QACtD,OAAO,OAAO;AAAA,QACf,SAAS,KACR,8BAA8B,iBAAiB,UAAU,UAAU,KAAK,GACzE;AAAA;AAAA,IAEF;AAAA,GACA;AAAA,EACD,OAAO,CAAC,GAAG,KAAK;AAAA;",
|
|
8
|
+
"debugId": "D12CCCD8FE08400864756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
package/docs/roadmap.md
CHANGED
|
@@ -37,3 +37,8 @@ Nothing in progress right now; see Next.
|
|
|
37
37
|
digits, the fields' blur layers and the fonts plugin, which
|
|
38
38
|
`@nxgt/material` and `@nxgt/material-vue` shared file by file, are this one
|
|
39
39
|
package, and both libraries depend on it. 0.1.0.
|
|
40
|
+
- **`formatFileSize` and the pdfkit fonts resolution** — the byte-count
|
|
41
|
+
formatter both libraries' file list and upload field use
|
|
42
|
+
(`/format-file-size`), and the Node-only resolution of pdfkit's standard
|
|
43
|
+
fonts behind `@nxgt/material/next` and `@nxgt/material-vue`'s Nuxt module
|
|
44
|
+
(`/pdfkit-fonts`), each kept once instead of in both libraries. 0.2.0.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -21,6 +21,9 @@ file) is an example — search for the words around it.
|
|
|
21
21
|
|
|
22
22
|
- [`… still references '#standard-fonts/' after the transform — …`](#-still-references-standard-fonts-after-the-transform--)
|
|
23
23
|
- [`Cannot find module '#standard-fonts/Helvetica' from '…'`](#cannot-find-module-standard-fontshelvetica-from-)
|
|
24
|
+
- [`Cannot find module '…/pdfkit/js/standard-fonts/Helvetica.cjs'`](#cannot-find-module-pdfkitjsstandard-fontshelveticacjs)
|
|
25
|
+
- [`could not resolve …` (`@react-pdf/renderer`, `@react-pdf/font`, pdfkit's fonts)](#could-not-resolve-)
|
|
26
|
+
- [`Module "node:module" has been externalized for browser compatibility`](#module-nodemodule-has-been-externalized-for-browser-compatibility)
|
|
24
27
|
|
|
25
28
|
## Install
|
|
26
29
|
|
|
@@ -103,3 +106,65 @@ rather than the server at its first request. Pin the previous
|
|
|
103
106
|
A server bundle that contains pdfkit, run without `node_modules`. Add
|
|
104
107
|
`pdfkitStandardFonts()` to that build (see the README's `/vite` section), or
|
|
105
108
|
keep the library external so pdfkit loads from `node_modules`.
|
|
109
|
+
|
|
110
|
+
### `Cannot find module '…/pdfkit/js/standard-fonts/Helvetica.cjs'`
|
|
111
|
+
|
|
112
|
+
**When:** on every PDF a traced server output renders — `.next/standalone`
|
|
113
|
+
(`output: 'standalone'`), Nitro's `.output/server` — while the dev server
|
|
114
|
+
renders fine. The path points into the output's own `node_modules/pdfkit/`.
|
|
115
|
+
**Why:** the tracer copies pdfkit, but pdfkit loads its fonts with a runtime
|
|
116
|
+
`require('#standard-fonts/<Name>')` it never follows, so the `.cjs` fonts
|
|
117
|
+
(and the `chunks/` they `require`) are left behind.
|
|
118
|
+
**Fix:** hand the tracer the files. With `@nxgt/material`, wrap the Next.js
|
|
119
|
+
config in `withNxgtPrint` (`@nxgt/material/next`); with
|
|
120
|
+
`@nxgt/material-vue`, use its Nuxt module. Anything else calls
|
|
121
|
+
`/pdfkit-fonts` in its config:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
import { pdfkitStandardFontDirs } from '@nxgt/material-core/pdfkit-fonts';
|
|
125
|
+
|
|
126
|
+
// every .cjs under each directory, chunks/ included
|
|
127
|
+
const include = pdfkitStandardFontDirs(process.cwd(), console.warn).map(
|
|
128
|
+
(dir) => `${dir}/**/*.cjs`,
|
|
129
|
+
);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### `could not resolve …`
|
|
133
|
+
|
|
134
|
+
**When:** at build, from `pdfkitStandardFontDirs` or
|
|
135
|
+
`pdfkitStandardFontFiles` — through `withNxgtPrint`
|
|
136
|
+
(`[@nxgt/material/next] …`), the Nuxt module (`pdf fonts: …`) or your own
|
|
137
|
+
`warn`. Every problem goes into one line, joined by `; `, each error cut to
|
|
138
|
+
its first line (Node's `Require stack:` is left out):
|
|
139
|
+
`could not resolve @react-pdf/renderer: …`,
|
|
140
|
+
`could not resolve @react-pdf/font: …`,
|
|
141
|
+
`could not resolve pdfkit's fonts for @react-pdf/renderer: …`,
|
|
142
|
+
`could not resolve pdfkit's Courier font for …`.
|
|
143
|
+
Without `@react-pdf/renderer` installed at all, nothing is printed.
|
|
144
|
+
**Why:** `@react-pdf/renderer` is installed, but resolving it, the
|
|
145
|
+
`@react-pdf/font` it uses or the pdfkit either depends on fails: a broken or
|
|
146
|
+
partial install, or a layout that hides them from the renderer.
|
|
147
|
+
**Fix:** reinstall (`rm -rf node_modules && <your package manager> install`),
|
|
148
|
+
and check that `node -e "require.resolve('pdfkit/standard-fonts/Helvetica', { paths: [require.resolve('@react-pdf/renderer')] })"`
|
|
149
|
+
prints a `.cjs` path. What could be resolved is still returned: the warning
|
|
150
|
+
names only what a PDF route will miss.
|
|
151
|
+
|
|
152
|
+
### `Module "node:module" has been externalized for browser compatibility`
|
|
153
|
+
|
|
154
|
+
**When:** Vite (or a similar bundler) prints this, or a browser console shows
|
|
155
|
+
`createRequire is not a function`, in an app that imports
|
|
156
|
+
`@nxgt/material-core/pdfkit-fonts`.
|
|
157
|
+
**Why:** `/pdfkit-fonts` is Node-only: it resolves files on disk with
|
|
158
|
+
`node:module` and `node:path`. Imported from code that reaches the browser, the
|
|
159
|
+
bundler swaps those built-ins for empty shims.
|
|
160
|
+
**Fix:** import it only from build-time Node code — `next.config.ts`, a Nuxt
|
|
161
|
+
module, a Vite config, a script. In a Next.js app use `withNxgtPrint` from
|
|
162
|
+
`@nxgt/material/next`; in Nuxt the `@nxgt/material-vue` module already calls
|
|
163
|
+
it.
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
// next.config.ts: runs in Node, never in the browser
|
|
167
|
+
import { withNxgtPrint } from '@nxgt/material/next';
|
|
168
|
+
|
|
169
|
+
export default withNxgtPrint({ output: 'standalone' });
|
|
170
|
+
```
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/material-core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "The framework-free core of @nxgt/material and @nxgt/material-vue: the PDF document model and its react-pdf renderer, print formatters, PDF file helpers, the PDF viewer's pure modules, the currency digits, the field-blur layers and the pdfkit fonts
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "The framework-free core of @nxgt/material and @nxgt/material-vue: the PDF document model and its react-pdf renderer, print formatters, PDF file helpers, the PDF viewer's pure modules, the currency digits, the file-size formatter, the field-blur layers, the pdfkit fonts Vite plugin and the Node-only pdfkit fonts resolution for Next.js and Nuxt builds",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"email": "stevegires@gmail.com"
|
|
@@ -92,6 +92,11 @@
|
|
|
92
92
|
"import": "./dist/lib/field-blur-layers.js",
|
|
93
93
|
"default": "./dist/lib/field-blur-layers.js"
|
|
94
94
|
},
|
|
95
|
+
"./format-file-size": {
|
|
96
|
+
"types": "./dist/lib/format-file-size.d.ts",
|
|
97
|
+
"import": "./dist/lib/format-file-size.js",
|
|
98
|
+
"default": "./dist/lib/format-file-size.js"
|
|
99
|
+
},
|
|
95
100
|
"./pdf-viewer": {
|
|
96
101
|
"types": "./dist/pdf-viewer/index.d.ts",
|
|
97
102
|
"import": "./dist/pdf-viewer/index.js",
|
|
@@ -102,6 +107,11 @@
|
|
|
102
107
|
"import": "./dist/vite/index.js",
|
|
103
108
|
"default": "./dist/vite/index.js"
|
|
104
109
|
},
|
|
110
|
+
"./pdfkit-fonts": {
|
|
111
|
+
"types": "./dist/pdfkit-fonts/index.d.ts",
|
|
112
|
+
"import": "./dist/pdfkit-fonts/index.js",
|
|
113
|
+
"default": "./dist/pdfkit-fonts/index.js"
|
|
114
|
+
},
|
|
105
115
|
"./package.json": "./package.json"
|
|
106
116
|
},
|
|
107
117
|
"sideEffects": false,
|
|
@@ -146,8 +156,10 @@
|
|
|
146
156
|
"src/lib/pdf-download.ts",
|
|
147
157
|
"src/lib/currency-digits.ts",
|
|
148
158
|
"src/lib/field-blur-layers.ts",
|
|
159
|
+
"src/lib/format-file-size.ts",
|
|
149
160
|
"src/pdf-viewer/index.ts",
|
|
150
|
-
"src/vite/index.ts"
|
|
161
|
+
"src/vite/index.ts",
|
|
162
|
+
"src/pdfkit-fonts/index.ts"
|
|
151
163
|
]
|
|
152
164
|
},
|
|
153
165
|
"dependencies": {
|