docgen-utils 1.0.14 → 1.0.16

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.
@@ -1,342 +1,270 @@
1
1
  /**
2
2
  * Export docs command - converts HTML to DOCX
3
3
  *
4
- * Handles images in a general way:
5
- * - External <img> tags: fetched via HTTP and embedded
6
- * - SVG charts: rendered to PNG using Playwright's browser canvas
7
- * - Data URLs: passed through directly
4
+ * Uses Playwright to:
5
+ * - Fetch external images via browser canvas (accurate naturalWidth/naturalHeight)
6
+ * - Render SVG charts by screenshotting live DOM elements (preserves CSS context)
8
7
  */
9
8
  import * as fs from "node:fs";
10
9
  import * as path from "node:path";
11
10
  import { chromium } from "playwright";
12
11
  import { createDocxBuffer } from "../../docs/create-document";
13
12
  import { parseHtmlContent } from "../../docs/parse";
13
+ // Maximum content width in DOCX (6.5 inches at 96 DPI = 624 pixels)
14
+ // docx library ImageRun uses pixels: width * 9525 EMU/px
15
+ const MAX_IMAGE_WIDTH = 624;
14
16
  /**
15
- * Recursively find all image elements from parsed elements.
16
- * Searches top-level elements and also nested structures like blockquotes and two-column layouts.
17
+ * Fetch external images from the HTML page using Playwright browser canvas.
18
+ * Opens the actual HTML file so images load naturally, then extracts pixel data
19
+ * via canvas with accurate naturalWidth/naturalHeight dimensions.
17
20
  */
18
- function findAllImageElements(elements) {
19
- const images = [];
20
- for (const el of elements) {
21
- if (el.type === "image") {
22
- images.push(el);
23
- }
24
- // Recursively search blockquote/callout content
25
- if (el.type === "blockquote" && el.content) {
26
- images.push(...findAllImageElements(el.content));
27
- }
28
- // Recursively search two-column-layout content
29
- if (el.type === "two-column-layout") {
30
- images.push(...findAllImageElements(el.sidebar.content));
31
- images.push(...findAllImageElements(el.main.content));
32
- }
33
- }
34
- return images;
35
- }
36
- /**
37
- * Fetch external images from parsed elements and convert to image data.
38
- * Uses Node.js native fetch API to download images.
39
- * Returns a Map of image src URL to ChartImageData.
40
- */
41
- async function fetchExternalImages(elements) {
21
+ async function fetchExternalImages(browser, htmlPath) {
42
22
  const imageMap = new Map();
43
- // Find all image elements (including nested ones)
44
- const imageElements = findAllImageElements(elements);
45
- // Filter to only external HTTP/HTTPS images (skip data URLs)
46
- const externalImages = imageElements.filter((el) => el.src.startsWith("http://") || el.src.startsWith("https://"));
47
- if (externalImages.length === 0) {
23
+ const absoluteHtmlPath = path.resolve(htmlPath);
24
+ if (!fs.existsSync(absoluteHtmlPath)) {
25
+ return imageMap;
26
+ }
27
+ const page = await browser.newPage({
28
+ viewport: { width: 1200, height: 800 },
29
+ });
30
+ // Navigate to the HTML page to have proper context for relative URLs
31
+ await page.goto(`file://${absoluteHtmlPath}`, {
32
+ waitUntil: "networkidle",
33
+ });
34
+ // Wait for images to load
35
+ await page.waitForTimeout(1000);
36
+ // Find all unique image URLs in the page
37
+ const uniqueSrcs = await page.evaluate(() => {
38
+ const images = Array.from(document.querySelectorAll("img"));
39
+ const srcs = images.map(img => img.src).filter(src => src && !src.startsWith("data:"));
40
+ return [...new Set(srcs)];
41
+ });
42
+ if (uniqueSrcs.length === 0) {
43
+ await page.close();
48
44
  return imageMap;
49
45
  }
50
- console.log(`Fetching ${externalImages.length} external image(s)...`);
51
- // Maximum content width in DOCX (6.5 inches at 96 DPI = 624 pixels, but we use 468 for some margin)
52
- const maxWidth = 468;
53
- for (const imgEl of externalImages) {
46
+ console.log(`Fetching ${uniqueSrcs.length} external image(s)...`);
47
+ for (const src of uniqueSrcs) {
54
48
  try {
55
- const src = imgEl.src;
56
- // Fetch the image
57
- const response = await fetch(src, {
58
- headers: {
59
- // Some servers require a User-Agent
60
- "User-Agent": "Mozilla/5.0 (compatible; DocxExporter/1.0)",
61
- },
62
- });
63
- if (!response.ok) {
64
- console.warn(`Failed to fetch image: ${src} (${response.status})`);
65
- continue;
66
- }
67
- const arrayBuffer = await response.arrayBuffer();
68
- const data = Buffer.from(arrayBuffer);
69
- // Determine image dimensions
70
- // For now, use a reasonable default size that fits the document
71
- // The actual image will be scaled by the DOCX renderer
72
- let width = imgEl.width || 468;
73
- let height = imgEl.height || 300;
74
- // Try to get actual dimensions from the image data
75
- const dimensions = getImageDimensions(data);
76
- if (dimensions) {
77
- width = dimensions.width;
78
- height = dimensions.height;
49
+ // Use Playwright to fetch and render the image via browser canvas
50
+ // This handles CORS and gives accurate naturalWidth/naturalHeight
51
+ const imageData = await page.evaluate(async ({ src, maxWidth }) => {
52
+ return new Promise((resolve) => {
53
+ const img = new Image();
54
+ img.crossOrigin = "anonymous";
55
+ img.onload = () => {
56
+ try {
57
+ // Scale to fit within document width
58
+ let width = img.naturalWidth;
59
+ let height = img.naturalHeight;
60
+ if (width > maxWidth) {
61
+ const scale = maxWidth / width;
62
+ width = maxWidth;
63
+ height = Math.round(height * scale);
64
+ }
65
+ // Draw to canvas and get PNG data
66
+ const canvas = document.createElement("canvas");
67
+ canvas.width = width;
68
+ canvas.height = height;
69
+ const ctx = canvas.getContext("2d");
70
+ if (!ctx) {
71
+ resolve(null);
72
+ return;
73
+ }
74
+ ctx.drawImage(img, 0, 0, width, height);
75
+ // Get image data as base64
76
+ const dataUrl = canvas.toDataURL("image/png");
77
+ const base64 = dataUrl.split(",")[1];
78
+ if (!base64) {
79
+ resolve(null);
80
+ return;
81
+ }
82
+ // Convert base64 to byte array
83
+ const binaryString = atob(base64);
84
+ const bytes = new Array(binaryString.length);
85
+ for (let i = 0; i < binaryString.length; i++) {
86
+ bytes[i] = binaryString.charCodeAt(i);
87
+ }
88
+ resolve({ data: bytes, width, height });
89
+ }
90
+ catch (err) {
91
+ console.warn("Error processing image:", err);
92
+ resolve(null);
93
+ }
94
+ };
95
+ img.onerror = () => {
96
+ console.warn("Failed to load image:", src);
97
+ resolve(null);
98
+ };
99
+ // Set timeout for slow images
100
+ setTimeout(() => {
101
+ console.warn("Image load timeout:", src);
102
+ resolve(null);
103
+ }, 10000);
104
+ img.src = src;
105
+ });
106
+ }, { src, maxWidth: MAX_IMAGE_WIDTH });
107
+ if (imageData) {
108
+ imageMap.set(src, {
109
+ data: Buffer.from(imageData.data),
110
+ width: imageData.width,
111
+ height: imageData.height,
112
+ });
79
113
  }
80
- // Scale to fit within document width
81
- if (width > maxWidth) {
82
- const scale = maxWidth / width;
83
- height = Math.round(height * scale);
84
- width = maxWidth;
85
- }
86
- imageMap.set(src, { data, width, height });
87
114
  }
88
115
  catch (err) {
89
- console.warn(`Error fetching image ${imgEl.src}:`, err);
116
+ console.warn(`Failed to fetch image ${src}:`, err);
90
117
  continue;
91
118
  }
92
119
  }
120
+ await page.close();
93
121
  return imageMap;
94
122
  }
95
123
  /**
96
- * Extract image dimensions from binary data.
97
- * Supports PNG, JPEG, GIF, and WebP formats.
124
+ * Render SVG chart elements to PNG by screenshotting them from the live HTML page.
125
+ *
126
+ * Opens the actual HTML file in Playwright, locates SVG elements using multiple
127
+ * matching criteria (viewBox, gradient/pattern IDs, aria-labels), and screenshots
128
+ * each matched element directly. This preserves full CSS context, fonts, and styling
129
+ * that would be lost when rendering SVG strings in isolation.
98
130
  */
99
- function getImageDimensions(data) {
100
- // PNG: Check for PNG signature and read IHDR chunk
101
- if (data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4E && data[3] === 0x47) {
102
- // PNG signature found, IHDR chunk starts at byte 8
103
- // Width is at bytes 16-19, Height at bytes 20-23 (big-endian)
104
- const width = data.readUInt32BE(16);
105
- const height = data.readUInt32BE(20);
106
- return { width, height };
131
+ async function renderChartImages(browser, htmlPath) {
132
+ const chartImages = new Map();
133
+ const absoluteHtmlPath = path.resolve(htmlPath);
134
+ if (!fs.existsSync(absoluteHtmlPath)) {
135
+ return chartImages;
107
136
  }
108
- // JPEG: Look for SOF0 marker (0xFF 0xC0) or SOF2 (0xFF 0xC2)
109
- if (data[0] === 0xFF && data[1] === 0xD8) {
110
- let offset = 2;
111
- while (offset < data.length - 8) {
112
- if (data[offset] !== 0xFF) {
113
- offset++;
114
- continue;
137
+ // Parse the HTML using the library to get svg-chart elements
138
+ const htmlContent = fs.readFileSync(absoluteHtmlPath, "utf-8");
139
+ const elements = parseHtmlContent(htmlContent);
140
+ // Get svg-chart elements the library found, including those nested inside blockquotes and layouts
141
+ const svgChartElements = [];
142
+ function collectSvgCharts(els) {
143
+ for (const el of els) {
144
+ if (el.type === "svg-chart") {
145
+ svgChartElements.push(el);
115
146
  }
116
- const marker = data[offset + 1];
117
- // SOF0, SOF1, SOF2 markers contain dimensions
118
- if (marker >= 0xC0 && marker <= 0xC2) {
119
- const height = data.readUInt16BE(offset + 5);
120
- const width = data.readUInt16BE(offset + 7);
121
- return { width, height };
147
+ else if (el.type === "blockquote" && el.content) {
148
+ collectSvgCharts(el.content);
149
+ }
150
+ else if (el.type === "two-column-layout") {
151
+ collectSvgCharts(el.sidebar.content);
152
+ collectSvgCharts(el.main.content);
122
153
  }
123
- // Skip to next marker
124
- const length = data.readUInt16BE(offset + 2);
125
- offset += 2 + length;
126
- }
127
- }
128
- // GIF: Check for GIF87a or GIF89a signature
129
- if (data[0] === 0x47 && data[1] === 0x49 && data[2] === 0x46) {
130
- const width = data.readUInt16LE(6);
131
- const height = data.readUInt16LE(8);
132
- return { width, height };
133
- }
134
- // WebP: Check for RIFF....WEBP signature
135
- if (data[0] === 0x52 && data[1] === 0x49 && data[2] === 0x46 && data[3] === 0x46 &&
136
- data[8] === 0x57 && data[9] === 0x45 && data[10] === 0x42 && data[11] === 0x50) {
137
- // VP8 format (lossy)
138
- if (data[12] === 0x56 && data[13] === 0x50 && data[14] === 0x38 && data[15] === 0x20) {
139
- const width = data.readUInt16LE(26) & 0x3FFF;
140
- const height = data.readUInt16LE(28) & 0x3FFF;
141
- return { width, height };
142
- }
143
- // VP8L format (lossless)
144
- if (data[12] === 0x56 && data[13] === 0x50 && data[14] === 0x38 && data[15] === 0x4C) {
145
- const bits = data.readUInt32LE(21);
146
- const width = (bits & 0x3FFF) + 1;
147
- const height = ((bits >> 14) & 0x3FFF) + 1;
148
- return { width, height };
149
154
  }
150
155
  }
151
- return null;
152
- }
153
- /**
154
- * Render SVG chart elements to PNG images using Playwright browser canvas.
155
- * This allows Node.js CLI to render SVGs the same way the browser export does.
156
- */
157
- async function renderSvgChartsWithPlaywright(elements) {
158
- const chartImages = new Map();
159
- // Find all svg-chart elements
160
- const svgCharts = elements.filter((el) => el.type === "svg-chart");
161
- if (svgCharts.length === 0) {
156
+ collectSvgCharts(elements);
157
+ if (svgChartElements.length === 0) {
162
158
  return chartImages;
163
159
  }
164
- // Launch browser
165
- const launchOptions = { headless: true };
166
- const proxyServer = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
167
- if (proxyServer) {
168
- launchOptions.proxy = { server: proxyServer };
169
- }
170
- const browser = await chromium.launch(launchOptions);
171
- try {
172
- const context = await browser.newContext({
173
- bypassCSP: true,
174
- viewport: { width: 1280, height: 800 },
175
- });
176
- const page = await context.newPage();
177
- // Process each SVG chart
178
- let svgIndex = 0;
179
- for (const chart of svgCharts) {
180
- try {
181
- const imageData = await renderSvgInBrowser(page, chart.svgContent, chart.width, chart.height, chart.backgroundColor);
182
- if (imageData) {
183
- chartImages.set(`svg-chart-${svgIndex}`, imageData);
160
+ console.log(`Rendering ${svgChartElements.length} SVG chart(s)...`);
161
+ const page = await browser.newPage({
162
+ viewport: { width: 1200, height: 800 },
163
+ });
164
+ await page.goto(`file://${absoluteHtmlPath}`, {
165
+ waitUntil: "networkidle",
166
+ });
167
+ // Wait for fonts/styles to settle
168
+ await page.waitForTimeout(500);
169
+ // For each svg-chart element from the library, find the matching SVG in the DOM
170
+ // by extracting unique identifiers from the svgContent
171
+ for (let i = 0; i < svgChartElements.length; i++) {
172
+ const svgChartEl = svgChartElements[i];
173
+ const svgContent = svgChartEl.svgContent;
174
+ // Extract multiple identifiers for robust matching
175
+ const viewBoxMatch = svgContent.match(/viewBox\s*=\s*["']([^"']+)["']/);
176
+ const viewBox = viewBoxMatch ? viewBoxMatch[1] : null;
177
+ // Extract first gradient/pattern ID as a unique identifier
178
+ const gradientIdMatch = svgContent.match(/id\s*=\s*["']([^"']+)["']/);
179
+ const firstId = gradientIdMatch ? gradientIdMatch[1] : null;
180
+ // Extract aria-label as another identifier
181
+ // Use separate patterns for double-quoted and single-quoted values to handle
182
+ // aria-labels that contain the other quote character (e.g., "Korea's cat culture")
183
+ const ariaLabelMatch = svgContent.match(/aria-label\s*=\s*"([^"]+)"/) || svgContent.match(/aria-label\s*=\s*'([^']+)'/);
184
+ const ariaLabel = ariaLabelMatch ? ariaLabelMatch[1] : null;
185
+ // Find the SVG with matching identifiers and mark IT directly (not its parent)
186
+ // This ensures we only screenshot the SVG, not surrounding DOM elements
187
+ const found = await page.evaluate(({ viewBox, firstId, ariaLabel, index }) => {
188
+ const svgs = Array.from(document.querySelectorAll("svg"));
189
+ for (const svg of svgs) {
190
+ // Skip already marked SVGs
191
+ if (svg.hasAttribute("data-svg-chart-index"))
192
+ continue;
193
+ // Match by multiple criteria for robustness
194
+ const svgViewBox = svg.getAttribute("viewBox");
195
+ const svgAriaLabel = svg.getAttribute("aria-label");
196
+ // Check for first ID match (gradient/pattern IDs are often unique per SVG)
197
+ let hasMatchingId = false;
198
+ if (firstId) {
199
+ const idEl = svg.querySelector(`#${CSS.escape(firstId)}`);
200
+ hasMatchingId = !!idEl;
201
+ }
202
+ // Match: viewBox + (firstId OR ariaLabel)
203
+ if (viewBox && svgViewBox === viewBox) {
204
+ if (hasMatchingId || (ariaLabel && svgAriaLabel === ariaLabel) || (!firstId && !ariaLabel)) {
205
+ svg.setAttribute("data-svg-chart-index", String(index));
206
+ return true;
207
+ }
184
208
  }
185
209
  }
186
- catch (err) {
187
- console.warn(`Failed to render SVG chart ${svgIndex}:`, err);
210
+ return false;
211
+ }, { viewBox, firstId, ariaLabel, index: i });
212
+ if (!found) {
213
+ // Fallback: try to match by width/height if viewBox matching failed
214
+ const widthMatch = svgContent.match(/width\s*=\s*["']([^"']+)["']/);
215
+ const heightMatch = svgContent.match(/height\s*=\s*["']([^"']+)["']/);
216
+ const svgWidth = widthMatch ? widthMatch[1] : null;
217
+ const svgHeight = heightMatch ? heightMatch[1] : null;
218
+ if (svgWidth && svgHeight) {
219
+ await page.evaluate(({ w, h, firstId, index }) => {
220
+ const svgs = Array.from(document.querySelectorAll("svg"));
221
+ for (const svg of svgs) {
222
+ if (svg.getAttribute("width") === w && svg.getAttribute("height") === h) {
223
+ if (!svg.hasAttribute("data-svg-chart-index")) {
224
+ // Additional check: if we have firstId, verify it exists in this SVG
225
+ if (firstId) {
226
+ const idEl = svg.querySelector(`#${CSS.escape(firstId)}`);
227
+ if (!idEl)
228
+ continue;
229
+ }
230
+ svg.setAttribute("data-svg-chart-index", String(index));
231
+ return true;
232
+ }
233
+ }
234
+ }
235
+ return false;
236
+ }, { w: svgWidth, h: svgHeight, firstId, index: i });
188
237
  }
189
- svgIndex++;
190
238
  }
191
- await page.close();
192
- await context.close();
193
239
  }
194
- finally {
195
- await browser.close();
196
- }
197
- return chartImages;
198
- }
199
- /**
200
- * Render a single SVG to PNG in the browser using Canvas.
201
- */
202
- async function renderSvgInBrowser(page, svgContent, width, height, backgroundColor) {
203
- // Create HTML page with the SVG rendering logic
204
- const renderPage = `<!DOCTYPE html>
205
- <html>
206
- <head>
207
- <style>
208
- body { margin: 0; padding: 0; }
209
- #svg-container { display: inline-block; }
210
- </style>
211
- </head>
212
- <body>
213
- <div id="svg-container"></div>
214
- <canvas id="canvas"></canvas>
215
- <script>
216
- window.renderSvgToPng = async function(svgContent, width, height, backgroundColor) {
217
- // Parse SVG to get dimensions if not provided
218
- const parser = new DOMParser();
219
- const svgDoc = parser.parseFromString(svgContent, "image/svg+xml");
220
- const svgElement = svgDoc.querySelector("svg");
221
-
222
- if (!svgElement) {
223
- return null;
224
- }
225
-
226
- // Get dimensions from SVG
227
- let svgWidth = width;
228
- let svgHeight = height;
229
-
230
- if (!svgWidth || !svgHeight) {
231
- const viewBox = svgElement.getAttribute("viewBox");
232
- if (viewBox) {
233
- const parts = viewBox.split(/\\s+/).map(Number);
234
- if (parts.length >= 4) {
235
- svgWidth = svgWidth || parts[2];
236
- svgHeight = svgHeight || parts[3];
237
- }
238
- }
239
- if (!svgWidth) {
240
- const widthAttr = svgElement.getAttribute("width");
241
- if (widthAttr && !widthAttr.includes("%")) {
242
- svgWidth = parseFloat(widthAttr);
243
- }
240
+ // Screenshot each marked SVG element directly
241
+ for (let i = 0; i < svgChartElements.length; i++) {
242
+ const svgEl = await page.$(`svg[data-svg-chart-index="${i}"]`);
243
+ if (!svgEl) {
244
+ continue;
244
245
  }
245
- if (!svgHeight) {
246
- const heightAttr = svgElement.getAttribute("height");
247
- if (heightAttr && !heightAttr.includes("%")) {
248
- svgHeight = parseFloat(heightAttr);
249
- }
246
+ // Get bounding box
247
+ const box = await svgEl.boundingBox();
248
+ if (!box) {
249
+ continue;
250
250
  }
251
- }
252
-
253
- // Default dimensions if still not found
254
- svgWidth = svgWidth || 624;
255
- svgHeight = svgHeight || 468;
256
-
257
- // Ensure SVG has explicit dimensions
258
- svgElement.setAttribute("width", String(svgWidth));
259
- svgElement.setAttribute("height", String(svgHeight));
260
-
261
- // Ensure SVG has proper XML namespace
262
- if (!svgElement.getAttribute("xmlns")) {
263
- svgElement.setAttribute("xmlns", "http://www.w3.org/2000/svg");
264
- }
265
-
266
- // Serialize the modified SVG
267
- const serializer = new XMLSerializer();
268
- const svgString = serializer.serializeToString(svgElement);
269
-
270
- // Create a blob URL for the SVG
271
- const svgBlob = new Blob([svgString], { type: "image/svg+xml;charset=utf-8" });
272
- const svgUrl = URL.createObjectURL(svgBlob);
273
-
274
- try {
275
- // Create an image from the SVG
276
- const img = new Image();
277
- await new Promise((resolve, reject) => {
278
- img.onload = resolve;
279
- img.onerror = reject;
280
- img.src = svgUrl;
251
+ // Take screenshot of just this SVG element
252
+ const screenshot = await svgEl.screenshot({
253
+ type: "png",
254
+ });
255
+ // Scale to fit within document content width
256
+ const scale = box.width > MAX_IMAGE_WIDTH ? MAX_IMAGE_WIDTH / box.width : 1;
257
+ const width = Math.round(box.width * scale);
258
+ const height = Math.round(box.height * scale);
259
+ // Use svg-chart-{index} as the key to match the library's indexing
260
+ chartImages.set(`svg-chart-${i}`, {
261
+ data: screenshot,
262
+ width,
263
+ height,
281
264
  });
282
-
283
- // Create canvas
284
- const scale = window.devicePixelRatio || 1;
285
- const canvas = document.getElementById("canvas");
286
- canvas.width = svgWidth * scale;
287
- canvas.height = svgHeight * scale;
288
-
289
- const ctx = canvas.getContext("2d");
290
- if (!ctx) return null;
291
-
292
- // Fill with background color
293
- ctx.fillStyle = backgroundColor ? "#" + backgroundColor : "white";
294
- ctx.fillRect(0, 0, canvas.width, canvas.height);
295
-
296
- // Scale for device pixel ratio
297
- ctx.scale(scale, scale);
298
-
299
- // Draw the SVG
300
- ctx.drawImage(img, 0, 0, svgWidth, svgHeight);
301
-
302
- // Convert to PNG data URL
303
- const dataUrl = canvas.toDataURL("image/png");
304
-
305
- // Scale dimensions to fit within DOCX content width
306
- const maxWidth = 624;
307
- const aspectRatio = svgHeight / svgWidth;
308
- const finalWidth = Math.min(svgWidth, maxWidth);
309
- const finalHeight = finalWidth * aspectRatio;
310
-
311
- return {
312
- dataUrl,
313
- width: Math.round(finalWidth),
314
- height: Math.round(finalHeight),
315
- };
316
- } finally {
317
- URL.revokeObjectURL(svgUrl);
318
- }
319
- };
320
- </script>
321
- </body>
322
- </html>`;
323
- await page.setContent(renderPage, { waitUntil: "domcontentloaded" });
324
- // Call the rendering function in the browser
325
- const result = await page.evaluate(async ({ svgContent, width, height, backgroundColor }) => {
326
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
327
- return window.renderSvgToPng(svgContent, width, height, backgroundColor);
328
- }, { svgContent, width, height, backgroundColor });
329
- if (!result || !result.dataUrl) {
330
- return null;
331
265
  }
332
- // Convert data URL to Buffer
333
- const base64Data = result.dataUrl.replace(/^data:image\/png;base64,/, "");
334
- const data = Buffer.from(base64Data, "base64");
335
- return {
336
- data,
337
- width: result.width,
338
- height: result.height,
339
- };
266
+ await page.close();
267
+ return chartImages;
340
268
  }
341
269
  export async function exportDocs(filePath, outDir, options = {}) {
342
270
  const { name: outputName, pageless } = options;
@@ -349,12 +277,26 @@ export async function exportDocs(filePath, outDir, options = {}) {
349
277
  const html = fs.readFileSync(absolutePath, "utf-8");
350
278
  // Get filename for title - use provided name or derive from input file
351
279
  const baseName = outputName || path.basename(filePath, ".html");
352
- // Parse HTML to get elements
280
+ // Launch browser for image fetching and SVG rendering
281
+ const launchOptions = { headless: true };
282
+ const proxyServer = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
283
+ if (proxyServer) {
284
+ launchOptions.proxy = { server: proxyServer };
285
+ }
286
+ const browser = await chromium.launch(launchOptions);
287
+ let imageMap;
288
+ let chartImages;
289
+ try {
290
+ // Fetch external images using browser canvas (accurate dimensions via naturalWidth/naturalHeight)
291
+ imageMap = await fetchExternalImages(browser, absolutePath);
292
+ // Render SVG charts by screenshotting live DOM elements (preserves CSS context)
293
+ chartImages = await renderChartImages(browser, absolutePath);
294
+ }
295
+ finally {
296
+ await browser.close();
297
+ }
298
+ // Parse HTML to get elements (pass pre-parsed to avoid double-parsing in createDocxBuffer)
353
299
  const elements = parseHtmlContent(html);
354
- // Fetch external images (for <img> tags with HTTP URLs)
355
- const imageMap = await fetchExternalImages(elements);
356
- // Render SVG charts to PNG using Playwright browser canvas
357
- const chartImages = await renderSvgChartsWithPlaywright(elements);
358
300
  // Create DOCX buffer with pre-parsed elements, external images, and rendered charts
359
301
  const buffer = await createDocxBuffer(html, {
360
302
  title: baseName,
@@ -1 +1 @@
1
- {"version":3,"file":"export-docs.js","sourceRoot":"","sources":["../../../../packages/cli/commands/export-docs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"export-docs.js","sourceRoot":"","sources":["../../../../packages/cli/commands/export-docs.ts"],"names":[],"mappings":"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"}