docx-kit 0.1.0 → 0.3.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.js DELETED
@@ -1,683 +0,0 @@
1
- import { n as ERROR_CODES, t as DocxKitError } from "./errors-c9CC63Ti.js";
2
- import { n as dataUrlToUint8Array, t as createImageRun } from "./image-6yS25Ggr.js";
3
- import { Paragraph } from "docx";
4
- //#region src/types/style.ts
5
- /**
6
- * Define a type-safe stylesheet.
7
- *
8
- * `fontSize` defaults to pt when passed as a bare number.
9
- *
10
- * @param styles - — The stylesheet object
11
- * @returns The same stylesheet with `const` type inference
12
- *
13
- * @example
14
- * ```ts
15
- * const styles = defineStyles({
16
- * title: { fontSize: 28, fontWeight: 'bold' },
17
- * body: { fontSize: 12, lineHeight: 1.5 },
18
- * })
19
- * ```
20
- */
21
- function defineStyles(styles) {
22
- return styles;
23
- }
24
- //#endregion
25
- //#region src/types/plugin.ts
26
- /**
27
- * Define a type-safe plugin with full inference.
28
- *
29
- * @param plugin - — The plugin definition object
30
- * @returns The same plugin with `const` type inference
31
- *
32
- * @example
33
- * ```ts
34
- * const myPlugin = definePlugin<'badge', { text: string }>({
35
- * name: 'badge',
36
- * render: async (opts, ctx) => {
37
- * // ... render logic
38
- * return new Paragraph({ text: opts.text })
39
- * },
40
- * })
41
- * ```
42
- */
43
- function definePlugin(plugin) {
44
- return plugin;
45
- }
46
- //#endregion
47
- //#region src/builder/DocxBuilder.ts
48
- /**
49
- * Fluent document builder.
50
- *
51
- * Use `createDocx()` to instantiate, then chain `.h1()`, `.p()`, `.table()`,
52
- * etc. to build content. Call `.save()`, `.toBlob()`, `.toBuffer()`, or
53
- * `.toBase64()` to export the document.
54
- *
55
- * @template TStyles — Inferred stylesheet type from `config.styles`
56
- * @template TPlugins — Accumulated plugin registry (built via `.use()`)
57
- */
58
- var DocxBuilder = class {
59
- config;
60
- nodes = [];
61
- pendingSetups = [];
62
- pluginMap = /* @__PURE__ */ new Map();
63
- constructor(config = {}) {
64
- this.config = config;
65
- }
66
- /**
67
- * Add a raw DSL node to the document.
68
- *
69
- * @param node - — Any block-level node
70
- * @returns The builder (for chaining)
71
- *
72
- * @example
73
- * ```ts
74
- * doc.add({ type: 'heading', level: 2, text: 'Section' })
75
- * doc.add({ type: 'pageBreak' })
76
- * ```
77
- */
78
- add(node) {
79
- this.nodes.push(node);
80
- return this;
81
- }
82
- /**
83
- * Add a level-1 heading.
84
- *
85
- * @param text - — Heading text
86
- * @param options - — Optional style overrides (className, id, style)
87
- * @returns The builder (for chaining)
88
- *
89
- * @example
90
- * ```ts
91
- * doc.h1('Introduction', { className: 'title' })
92
- * ```
93
- */
94
- h1(text, options = {}) {
95
- return this.add({
96
- level: 1,
97
- text,
98
- type: "heading",
99
- ...options
100
- });
101
- }
102
- /**
103
- * Add a level-2 heading.
104
- *
105
- * @param text - — Heading text
106
- * @param options - — Optional style overrides
107
- * @returns The builder (for chaining)
108
- */
109
- h2(text, options = {}) {
110
- return this.add({
111
- level: 2,
112
- text,
113
- type: "heading",
114
- ...options
115
- });
116
- }
117
- /**
118
- * Add a level-3 heading.
119
- *
120
- * @param text - — Heading text
121
- * @param options - — Optional style overrides
122
- * @returns The builder (for chaining)
123
- */
124
- h3(text, options = {}) {
125
- return this.add({
126
- level: 3,
127
- text,
128
- type: "heading",
129
- ...options
130
- });
131
- }
132
- /**
133
- * Add a level-4 heading.
134
- *
135
- * @param text - — Heading text
136
- * @param options - — Optional style overrides
137
- * @returns The builder (for chaining)
138
- */
139
- h4(text, options = {}) {
140
- return this.add({
141
- level: 4,
142
- text,
143
- type: "heading",
144
- ...options
145
- });
146
- }
147
- /**
148
- * Add a level-5 heading.
149
- *
150
- * @param text - — Heading text
151
- * @param options - — Optional style overrides
152
- * @returns The builder (for chaining)
153
- */
154
- h5(text, options = {}) {
155
- return this.add({
156
- level: 5,
157
- text,
158
- type: "heading",
159
- ...options
160
- });
161
- }
162
- /**
163
- * Add a level-6 heading.
164
- *
165
- * @param text - — Heading text
166
- * @param options - — Optional style overrides
167
- * @returns The builder (for chaining)
168
- */
169
- h6(text, options = {}) {
170
- return this.add({
171
- level: 6,
172
- text,
173
- type: "heading",
174
- ...options
175
- });
176
- }
177
- /**
178
- * Add an image node.
179
- *
180
- * @param options - — Image node options (data, width, height, etc.)
181
- * @returns The builder (for chaining)
182
- *
183
- * @example
184
- * ```ts
185
- * doc.image({ data: imageBytes, width: 400, height: 300 })
186
- * ```
187
- */
188
- image(options) {
189
- return this.add({
190
- type: "image",
191
- ...options
192
- });
193
- }
194
- /**
195
- * Add a paragraph.
196
- *
197
- * @param text - — Paragraph text content
198
- * @param options - — Optional style overrides (className, id, style)
199
- * @returns The builder (for chaining)
200
- *
201
- * @example
202
- * ```ts
203
- * doc.p('Hello world', { className: 'body', style: { textAlign: 'center' } })
204
- * ```
205
- */
206
- p(text, options = {}) {
207
- return this.add({
208
- text,
209
- type: "paragraph",
210
- ...options
211
- });
212
- }
213
- /**
214
- * Add a forced page break.
215
- *
216
- * @returns The builder (for chaining)
217
- *
218
- * @example
219
- * ```ts
220
- * doc.h1('Chapter 1').pageBreak().h1('Chapter 2')
221
- * ```
222
- */
223
- pageBreak() {
224
- return this.add({ type: "pageBreak" });
225
- }
226
- /**
227
- * Invoke a registered plugin.
228
- *
229
- * @param name - — Plugin name (must match a previously registered plugin)
230
- * @param options - — Plugin-specific options
231
- * @param style - — Optional inline style for the plugin's container
232
- * @returns The builder (for chaining)
233
- *
234
- * @example
235
- * ```ts
236
- * doc.use(qrcodePlugin()).plugin('qrcode', { text: 'https://example.com' })
237
- * ```
238
- */
239
- plugin(name, options, style) {
240
- return this.add({
241
- name,
242
- options,
243
- style,
244
- type: "plugin"
245
- });
246
- }
247
- /**
248
- * Save the document to a file (Node.js only).
249
- *
250
- * **⚠️ Not available in browser environments.**
251
- * Use {@link toBlob} and trigger a download instead.
252
- *
253
- * @param filename - — Output file path (e.g. `"report.docx"`)
254
- *
255
- * @example
256
- * ```ts
257
- * await doc.save('output.docx')
258
- * ```
259
- */
260
- async save(filename) {
261
- const { saveDocument } = await import("./fs-DF8ug9Wi.js").then((n) => n.t);
262
- return saveDocument(await this.toDocument(), filename);
263
- }
264
- /**
265
- * Add a table.
266
- *
267
- * @param options - — Table node options (columns, data, style, etc.)
268
- * @returns The builder (for chaining)
269
- *
270
- * @example
271
- * ```ts
272
- * doc.table({
273
- * columns: [
274
- * { key: 'name', title: 'Name' },
275
- * { key: 'value', title: 'Value', align: 'right' },
276
- * ],
277
- * data: [{ name: 'Revenue', value: '$1.2M' }],
278
- * headerCellStyle: { fontWeight: 'bold' },
279
- * })
280
- * ```
281
- */
282
- table(options) {
283
- return this.add({
284
- type: "table",
285
- ...options
286
- });
287
- }
288
- /**
289
- * Export the document as a base64-encoded string.
290
- *
291
- * @returns Base64-encoded .docx data
292
- *
293
- * @example
294
- * ```ts
295
- * const b64 = await doc.toBase64()
296
- * // Send b64 over HTTP or store in a database
297
- * ```
298
- */
299
- async toBase64() {
300
- const { packToBase64String } = await import("./pack-0Jsv03Sk.js");
301
- return packToBase64String(await this.toDocument());
302
- }
303
- /**
304
- * Export the document as a `Blob` (browser-friendly).
305
- *
306
- * @returns A `Blob` containing the .docx binary
307
- *
308
- * @example
309
- * ```ts
310
- * const blob = await doc.toBlob()
311
- * const url = URL.createObjectURL(blob)
312
- * ```
313
- */
314
- async toBlob() {
315
- const { packToBlob } = await import("./pack-0Jsv03Sk.js");
316
- return packToBlob(await this.toDocument());
317
- }
318
- /**
319
- * Export the document as a `Uint8Array` (alias for {@link toUint8Array}).
320
- *
321
- * **Note:** Despite the name, this returns a standard `Uint8Array`,
322
- * not a Node.js `Buffer`. Prefer using {@link toUint8Array} for clarity.
323
- *
324
- * @returns Raw .docx bytes
325
- *
326
- * @example
327
- * ```ts
328
- * const bytes = await doc.toBuffer()
329
- * fs.writeFileSync('output.docx', bytes)
330
- * ```
331
- */
332
- async toBuffer() {
333
- return this.toUint8Array();
334
- }
335
- /**
336
- * Compile and return the internal `docx` {@link Document} instance.
337
- *
338
- * Useful if you need to further manipulate the document with the
339
- * raw `docx` library before packaging.
340
- *
341
- * @returns A `docx` `Document` object
342
- */
343
- async toDocument() {
344
- await Promise.all(this.pendingSetups);
345
- this.pendingSetups.length = 0;
346
- const { compileDocument } = await import("./compileDocument-BvuU28Yj.js");
347
- return compileDocument({
348
- config: this.config,
349
- nodes: this.nodes,
350
- plugins: this.pluginMap
351
- });
352
- }
353
- /**
354
- * Serialize the builder state to a JSON-friendly object.
355
- *
356
- * Useful for debugging, serialization, or AI-driven document generation.
357
- *
358
- * @returns The config + content node array as a plain object
359
- */
360
- toJSON() {
361
- return {
362
- ...this.config,
363
- content: this.nodes
364
- };
365
- }
366
- /**
367
- * Export the document as a `Uint8Array` (browser & Node.js).
368
- *
369
- * This is the preferred cross-platform export method.
370
- *
371
- * @returns Raw .docx bytes
372
- *
373
- * @example
374
- * ```ts
375
- * const bytes = await doc.toUint8Array()
376
- * // In Node.js: import { writeFileSync } from 'node:fs'
377
- * // In browser: trigger a download
378
- * ```
379
- */
380
- async toUint8Array() {
381
- const { packToBuffer } = await import("./pack-0Jsv03Sk.js");
382
- return packToBuffer(await this.toDocument());
383
- }
384
- /**
385
- * Register a plugin.
386
- *
387
- * The plugin's name and options type are accumulated into the builder's
388
- * type-level plugin registry, enabling type-safe `.plugin()` calls.
389
- *
390
- * @param plugin - — The plugin definition returned by `definePlugin()`
391
- * @returns The builder with the plugin type merged into `TPlugins`
392
- *
393
- * @example
394
- * ```ts
395
- * const doc = createDocx()
396
- * .use(qrcodePlugin())
397
- * .plugin('qrcode', { text: 'https://example.com' })
398
- * ```
399
- */
400
- use(plugin) {
401
- this.pluginMap.set(plugin.name, plugin);
402
- if (plugin.setup) this.pendingSetups.push(Promise.resolve(plugin.setup()));
403
- return this;
404
- }
405
- };
406
- //#endregion
407
- //#region src/plugins/qrcode/index.ts
408
- /**
409
- * QR Code plugin — embeds a QR code image in the document.
410
- *
411
- * Uses the `qrcode` package (peer dependency) to generate
412
- * a QR code PNG and renders it as an inline `ImageRun`.
413
- *
414
- * @module plugins/qrcode
415
- *
416
- * @example
417
- * ```ts
418
- * const doc = createDocx()
419
- * .use(qrcodePlugin())
420
- * .h1('Scan Me')
421
- * .plugin('qrcode', { text: 'https://example.com', caption: 'Visit us' })
422
- * .save('qrcode.docx')
423
- * ```
424
- */
425
- /**
426
- * Create a QRCode plugin instance.
427
- *
428
- * The plugin dynamically imports the `qrcode` package at render time,
429
- * keeping it an optional peer dependency of docx-kit core.
430
- *
431
- * @returns A configured DocxPlugin for `'qrcode'`
432
- *
433
- * @example
434
- * ```ts
435
- * import { createDocx, qrcodePlugin } from 'docx-kit'
436
- *
437
- * const doc = createDocx()
438
- * .use(qrcodePlugin())
439
- * .plugin('qrcode', {
440
- * text: 'https://example.com',
441
- * size: 256,
442
- * errorCorrectionLevel: 'H',
443
- * caption: 'Scan to visit',
444
- * })
445
- * ```
446
- */
447
- function qrcodePlugin() {
448
- return definePlugin({
449
- name: "qrcode",
450
- async render(options) {
451
- const QRCode = (await import("qrcode")).default ?? await import("qrcode");
452
- const size = options.size ?? 128;
453
- const paragraphs = [new Paragraph({ children: [createImageRun({
454
- data: await dataUrlToUint8Array(await QRCode.toDataURL(options.text, {
455
- errorCorrectionLevel: options.errorCorrectionLevel ?? "M",
456
- margin: options.margin ?? 1,
457
- width: size
458
- })),
459
- height: size,
460
- type: "png",
461
- width: size
462
- })] })];
463
- if (options.caption) paragraphs.push(new Paragraph({ text: options.caption }));
464
- return paragraphs;
465
- }
466
- });
467
- }
468
- //#endregion
469
- //#region src/plugins/echarts/index.ts
470
- /**
471
- * ECharts plugin — embeds interactive ECharts charts as static images.
472
- *
473
- * Renders charts in the browser via the DOM. For Node.js rendering,
474
- * a custom canvas/SVG implementation is needed (not built-in).
475
- *
476
- * @module plugins/echarts
477
- *
478
- * @example
479
- * ```ts
480
- * const doc = createDocx()
481
- * .use(echartsPlugin())
482
- * .h1('Sales Chart')
483
- * .plugin('echarts', {
484
- * option: {
485
- * title: { text: 'Monthly Sales' },
486
- * xAxis: { data: ['Jan', 'Feb', 'Mar'] },
487
- * yAxis: {},
488
- * series: [{ type: 'bar', data: [120, 200, 150] }],
489
- * },
490
- * width: 640,
491
- * height: 360,
492
- * caption: 'Figure 1: Monthly sales data',
493
- * })
494
- * .save('chart.docx')
495
- * ```
496
- */
497
- /**
498
- * Create an ECharts plugin instance.
499
- *
500
- * The plugin renders charts using the browser DOM. In Node.js
501
- * environments, it throws an error prompting the user to provide
502
- * a server-side canvas implementation.
503
- *
504
- * @returns A configured DocxPlugin for `'echarts'`
505
- *
506
- * @example
507
- * ```ts
508
- * import { createDocx, echartsPlugin } from 'docx-kit'
509
- *
510
- * const doc = createDocx()
511
- * .use(echartsPlugin())
512
- * .plugin('echarts', {
513
- * option: {
514
- * title: { text: 'Revenue' },
515
- * xAxis: { type: 'category', data: ['Q1', 'Q2', 'Q3', 'Q4'] },
516
- * yAxis: { type: 'value' },
517
- * series: [{ data: [820, 932, 901, 1347], type: 'line' }],
518
- * },
519
- * caption: 'Quarterly revenue trend',
520
- * })
521
- * ```
522
- */
523
- function echartsPlugin() {
524
- return definePlugin({
525
- name: "echarts",
526
- async render(options) {
527
- const width = options.width ?? 640;
528
- const height = options.height ?? 360;
529
- const imageType = options.imageType ?? "png";
530
- const renderer = options.renderer ?? "canvas";
531
- const image = await renderEChartsToImage(options.option, {
532
- height,
533
- imageType,
534
- renderer,
535
- width
536
- });
537
- const paragraphs = [new Paragraph({ children: [createImageRun({
538
- data: image.data,
539
- height,
540
- type: image.type,
541
- width
542
- })] })];
543
- if (options.caption) paragraphs.push(new Paragraph({ text: options.caption }));
544
- return paragraphs;
545
- }
546
- });
547
- }
548
- /**
549
- * Render an ECharts option to an image.
550
- *
551
- * Automatically selects browser or Node.js rendering based on
552
- * whether the `window` global is available.
553
- *
554
- * @param option - — Full ECharts option object
555
- * @param config - — Render dimensions and format
556
- * @returns Rendered image data and type
557
- */
558
- async function renderEChartsToImage(option, config) {
559
- if (typeof window !== "undefined") return renderInBrowser(option, config);
560
- return renderInNode(option, config);
561
- }
562
- /**
563
- * Browser-side ECharts rendering.
564
- *
565
- * Creates a hidden DOM container, renders the chart, and extracts
566
- * the image as a base64 data-URL.
567
- */
568
- async function renderInBrowser(option, config) {
569
- const echarts = await import("echarts");
570
- const container = document.createElement("div");
571
- container.style.cssText = `width:${config.width}px;height:${config.height}px;position:fixed;left:-99999px;`;
572
- document.body.append(container);
573
- const chart = echarts.init(container, void 0, {
574
- height: config.height,
575
- renderer: config.renderer,
576
- width: config.width
577
- });
578
- chart.setOption(option);
579
- const dataUrl = chart.getDataURL({
580
- backgroundColor: "#ffffff",
581
- pixelRatio: 2,
582
- type: config.imageType === "svg" ? "svg" : "png"
583
- });
584
- chart.dispose();
585
- container.remove();
586
- return {
587
- data: await dataUrlToUint8Array(dataUrl),
588
- type: config.imageType
589
- };
590
- }
591
- /**
592
- * Node.js-side ECharts rendering (not built-in).
593
- *
594
- * Requires a server-side canvas or SVG DOM implementation
595
- * (e.g. `node-canvas` + `echarts`). Throws an error prompting
596
- * the user to provide a custom render function when used
597
- * outside the browser.
598
- */
599
- async function renderInNode(_option, _config) {
600
- throw new DocxKitError(ERROR_CODES.PLUGIN_RENDER_FAILED, "ECharts Node renderer is not built-in. Use a server-side canvas implementation (e.g. node-canvas + echarts) and provide a custom render function. See https://github.com/ntnyq/docx-kit for alternatives.");
601
- }
602
- //#endregion
603
- //#region src/builder/createDocx.ts
604
- /**
605
- * Factory functions for creating `DocxBuilder` instances.
606
- *
607
- * Two entry points are provided:
608
- * - `createDocx()` — Fluent builder API with chaining
609
- * - `renderDocx()` — JSON-schema driven (AI-friendly / serializable)
610
- *
611
- * @module builder/createDocx
612
- */
613
- /**
614
- * Create a new DocxBuilder with optional configuration.
615
- *
616
- * This is the primary entry point for the fluent builder API.
617
- * Chain `.h1()`, `.p()`, `.table()`, etc. and call `.save()`
618
- * or `.toBlob()` to export.
619
- *
620
- * @param config - — Document configuration (page, styles, metadata, theme, defaults)
621
- * @returns A new `DocxBuilder` instance
622
- *
623
- * @example
624
- * ```ts
625
- * const styles = defineStyles({
626
- * title: { fontSize: 28, fontWeight: 'bold' },
627
- * body: { fontSize: 12, lineHeight: 1.5 },
628
- * })
629
- *
630
- * const doc = createDocx({
631
- * styles,
632
- * page: { size: 'A4', margin: '20mm' },
633
- * metadata: { title: 'Report', creator: 'docx-kit' },
634
- * })
635
- *
636
- * await doc
637
- * .h1('Annual Report', { className: 'title' })
638
- * .p('Lorem ipsum...', { className: 'body' })
639
- * .save('report.docx')
640
- * ```
641
- */
642
- function createDocx(config = {}) {
643
- return new DocxBuilder(config);
644
- }
645
- /**
646
- * Render a document from a JSON schema (AI-friendly / serializable DSL).
647
- *
648
- * Unlike `createDocx()`, this accepts a single JSON-serializable object
649
- * with `content` (node array), optional `styles`, and optional `page` config.
650
- * Ideal for AI-driven document generation or API integrations.
651
- *
652
- * @param schema - — The `DocxSchema` object
653
- * @returns A `DocxBuilder` instance (ready to export)
654
- *
655
- * @example
656
- * ```ts
657
- * const blob = await renderDocx({
658
- * page: { size: 'A4', margin: '20mm' },
659
- * styles: {
660
- * h1: { fontSize: 24, fontWeight: 'bold' },
661
- * p: { fontSize: 12 },
662
- * },
663
- * content: [
664
- * { type: 'heading', level: 1, text: 'Report', className: 'h1' },
665
- * { type: 'paragraph', text: 'This is a report generated via JSON DSL.', className: 'p' },
666
- * { type: 'pageBreak' },
667
- * {
668
- * type: 'table',
669
- * columns: [{ key: 'name', title: 'Name' }, { key: 'value', title: 'Value' }],
670
- * data: [{ name: 'Revenue', value: '$1.2M' }],
671
- * },
672
- * ],
673
- * }).toBlob()
674
- * ```
675
- */
676
- function renderDocx(schema) {
677
- const { content, ...config } = schema;
678
- const builder = new DocxBuilder(config);
679
- for (const node of content) builder.add(node);
680
- return builder;
681
- }
682
- //#endregion
683
- export { DocxBuilder, DocxKitError, ERROR_CODES, createDocx, dataUrlToUint8Array, definePlugin, defineStyles, echartsPlugin, qrcodePlugin, renderDocx };