@json-to-office/core-docx 0.5.0 → 0.6.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 CHANGED
@@ -834,7 +834,7 @@ function convertLineSpacing(lineSpacing) {
834
834
  }
835
835
  return { line, lineRule };
836
836
  }
837
- var TWIPS_PER_POINT, SINGLE_LINE_SPACING_POINTS, SINGLE_LINE_SPACING_TWIPS, DOUBLE_LINE_SPACING_TWIPS, getBodyTextStyle;
837
+ var TWIPS_PER_POINT, SINGLE_LINE_SPACING_POINTS, SINGLE_LINE_SPACING_TWIPS, DOUBLE_LINE_SPACING_TWIPS;
838
838
  var init_styleHelpers = __esm({
839
839
  "src/styles/utils/styleHelpers.ts"() {
840
840
  "use strict";
@@ -845,22 +845,6 @@ var init_styleHelpers = __esm({
845
845
  SINGLE_LINE_SPACING_POINTS = 12;
846
846
  SINGLE_LINE_SPACING_TWIPS = SINGLE_LINE_SPACING_POINTS * TWIPS_PER_POINT;
847
847
  DOUBLE_LINE_SPACING_TWIPS = SINGLE_LINE_SPACING_TWIPS * 2;
848
- getBodyTextStyle = (theme, themeName) => {
849
- const themeConfig = resolveTheme(theme, themeName);
850
- if (themeConfig) {
851
- const normalStyle = getNormalStyle(themeConfig);
852
- return {
853
- size: (normalStyle.size || 11) * 2,
854
- font: resolveFontFamily(themeConfig, normalStyle.font),
855
- color: normalStyle.color ? resolveColor(normalStyle.color, themeConfig) : "000000"
856
- };
857
- }
858
- return {
859
- size: 20,
860
- font: "Arial",
861
- color: "000000"
862
- };
863
- };
864
848
  }
865
849
  });
866
850
 
@@ -1426,7 +1410,8 @@ __export(widthUtils_exports, {
1426
1410
  getPageHeightTwips: () => getPageHeightTwips,
1427
1411
  getPageWidthTwips: () => getPageWidthTwips,
1428
1412
  parsePercentageStringToFraction: () => parsePercentageStringToFraction,
1429
- relativeLengthToTwips: () => relativeLengthToTwips
1413
+ relativeLengthToTwips: () => relativeLengthToTwips,
1414
+ resolveOffsetTwips: () => resolveOffsetTwips
1430
1415
  });
1431
1416
  function getAvailableWidthTwips(theme, themeName) {
1432
1417
  const page = getPageSetup(theme, themeName);
@@ -1457,6 +1442,17 @@ function parsePercentageStringToFraction(value) {
1457
1442
  if (pct < 0 || pct > 100) return void 0;
1458
1443
  return pct / 100;
1459
1444
  }
1445
+ function resolveOffsetTwips(value, referenceTwips) {
1446
+ if (typeof value === "number") return value;
1447
+ const match = /^([0-9]+(?:\.[0-9]+)?)%$/.exec(value);
1448
+ if (!match) {
1449
+ console.warn(
1450
+ `resolveOffsetTwips: invalid percentage string "${value}", defaulting to 0`
1451
+ );
1452
+ return 0;
1453
+ }
1454
+ return Math.round(referenceTwips * parseFloat(match[1]) / 100);
1455
+ }
1460
1456
  function relativeLengthToTwips(value, availableWidthTwips) {
1461
1457
  if (typeof value === "number") {
1462
1458
  return pointsToTwips(value);
@@ -1473,240 +1469,6 @@ var init_widthUtils = __esm({
1473
1469
  }
1474
1470
  });
1475
1471
 
1476
- // src/utils/imageUtils.ts
1477
- var imageUtils_exports = {};
1478
- __export(imageUtils_exports, {
1479
- calculateImageDimensions: () => calculateImageDimensions,
1480
- calculateMissingDimension: () => calculateMissingDimension,
1481
- decodeBase64Image: () => decodeBase64Image,
1482
- detectImageType: () => detectImageType,
1483
- detectImageTypeFromExtension: () => detectImageTypeFromExtension,
1484
- detectImageTypeFromMimeType: () => detectImageTypeFromMimeType,
1485
- downloadImageFromUrl: () => downloadImageFromUrl,
1486
- extractMimeTypeFromDataUri: () => extractMimeTypeFromDataUri,
1487
- getImageBuffer: () => getImageBuffer,
1488
- getImageDimensions: () => getImageDimensions,
1489
- isBase64Image: () => isBase64Image,
1490
- isValidUrl: () => isValidUrl,
1491
- parseDimensionValue: () => parseDimensionValue,
1492
- parseWidthValue: () => parseWidthValue
1493
- });
1494
- import { readFileSync } from "fs";
1495
- import probe from "probe-image-size";
1496
- function parseWidthValue(width, availableWidthPx) {
1497
- if (typeof width === "number") {
1498
- return width;
1499
- }
1500
- const percentageMatch = width.match(/^(\d+(?:\.\d+)?)%$/);
1501
- if (percentageMatch) {
1502
- const pct = parseFloat(percentageMatch[1]);
1503
- if (pct < 0 || pct > 100) {
1504
- throw new Error(
1505
- `Invalid percentage value: ${width}. Must be between 0% and 100%`
1506
- );
1507
- }
1508
- const fraction = parsePercentageStringToFraction(width);
1509
- if (fraction !== void 0) {
1510
- return Math.round(availableWidthPx * fraction);
1511
- }
1512
- }
1513
- throw new Error(
1514
- `Invalid width value: ${width}. Expected number (pixels) or percentage string (e.g., "90%")`
1515
- );
1516
- }
1517
- function parseDimensionValue(value, availablePx) {
1518
- if (typeof value === "number") return value;
1519
- const percentageMatch = value.match(/^(\d+(?:\.\d+)?)%$/);
1520
- if (percentageMatch) {
1521
- const pct = parseFloat(percentageMatch[1]);
1522
- if (pct < 0 || pct > 100) {
1523
- throw new Error(
1524
- `Invalid percentage value: ${value}. Must be between 0% and 100%`
1525
- );
1526
- }
1527
- const fraction = parsePercentageStringToFraction(value);
1528
- if (fraction !== void 0) return Math.round(availablePx * fraction);
1529
- }
1530
- throw new Error(
1531
- `Invalid dimension value: ${value}. Expected number (pixels) or percentage string (e.g., "90%")`
1532
- );
1533
- }
1534
- function isValidUrl(string) {
1535
- try {
1536
- const url = new URL(string);
1537
- return url.protocol === "http:" || url.protocol === "https:";
1538
- } catch {
1539
- return false;
1540
- }
1541
- }
1542
- function isBase64Image(string) {
1543
- return /^data:image\/[a-zA-Z+]+;base64,/.test(string);
1544
- }
1545
- function decodeBase64Image(dataUri) {
1546
- try {
1547
- const base64Data = dataUri.split(",")[1];
1548
- if (!base64Data) {
1549
- throw new Error("Invalid base64 data URI format");
1550
- }
1551
- return Buffer.from(base64Data, "base64");
1552
- } catch (error) {
1553
- throw new Error(
1554
- `Failed to decode base64 image: ${error instanceof Error ? error.message : String(error)}`
1555
- );
1556
- }
1557
- }
1558
- function extractMimeTypeFromDataUri(dataUri) {
1559
- const match = dataUri.match(/^data:(image\/[a-zA-Z0-9+.-]+);base64,/);
1560
- return match ? match[1] : void 0;
1561
- }
1562
- function detectImageTypeFromExtension(path4) {
1563
- const extension = path4.toLowerCase().split(".").pop()?.split("?")[0];
1564
- switch (extension) {
1565
- case "jpg":
1566
- case "jpeg":
1567
- return "jpg";
1568
- case "png":
1569
- return "png";
1570
- case "gif":
1571
- return "gif";
1572
- case "bmp":
1573
- return "bmp";
1574
- case "svg":
1575
- return "svg";
1576
- default:
1577
- return void 0;
1578
- }
1579
- }
1580
- function detectImageTypeFromMimeType(mimeType) {
1581
- const normalized = mimeType.toLowerCase();
1582
- if (normalized.includes("svg")) return "svg";
1583
- if (normalized.includes("jpeg") || normalized.includes("jpg")) return "jpg";
1584
- if (normalized.includes("png")) return "png";
1585
- if (normalized.includes("gif")) return "gif";
1586
- if (normalized.includes("bmp")) return "bmp";
1587
- return void 0;
1588
- }
1589
- function detectImageType(imagePath) {
1590
- if (isBase64Image(imagePath)) {
1591
- const mimeType = extractMimeTypeFromDataUri(imagePath);
1592
- if (mimeType) {
1593
- const typeFromMime = detectImageTypeFromMimeType(mimeType);
1594
- if (typeFromMime) return typeFromMime;
1595
- }
1596
- }
1597
- const typeFromExtension = detectImageTypeFromExtension(imagePath);
1598
- if (typeFromExtension) return typeFromExtension;
1599
- return "png";
1600
- }
1601
- async function downloadImageFromUrl(url) {
1602
- try {
1603
- const controller = new AbortController();
1604
- const timeoutId = setTimeout(() => controller.abort(), 1e4);
1605
- const response = await fetch(url, {
1606
- signal: controller.signal,
1607
- headers: {
1608
- "User-Agent": "Mozilla/5.0 (compatible; json-to-docx/1.0)"
1609
- },
1610
- redirect: "follow"
1611
- // Automatically follow redirects (default behavior)
1612
- });
1613
- clearTimeout(timeoutId);
1614
- if (!response.ok) {
1615
- throw new Error(
1616
- `Failed to download image: HTTP ${response.status} ${response.statusText}`
1617
- );
1618
- }
1619
- const arrayBuffer = await response.arrayBuffer();
1620
- return Buffer.from(arrayBuffer);
1621
- } catch (error) {
1622
- if (error instanceof Error) {
1623
- if (error.name === "AbortError") {
1624
- throw new Error(
1625
- "Failed to download image: Request timeout after 10 seconds"
1626
- );
1627
- }
1628
- throw new Error(`Failed to download image from ${url}: ${error.message}`);
1629
- }
1630
- throw new Error(`Failed to download image from ${url}: Unknown error`);
1631
- }
1632
- }
1633
- async function getImageBuffer(imagePath) {
1634
- if (isBase64Image(imagePath)) {
1635
- return decodeBase64Image(imagePath);
1636
- }
1637
- if (isValidUrl(imagePath)) {
1638
- return await downloadImageFromUrl(imagePath);
1639
- }
1640
- return readFileSync(imagePath);
1641
- }
1642
- async function getImageDimensions(imagePath) {
1643
- try {
1644
- const imageBuffer = await getImageBuffer(imagePath);
1645
- const result = probe.sync(imageBuffer);
1646
- if (!result) {
1647
- throw new Error(`Unable to determine dimensions for image: ${imagePath}`);
1648
- }
1649
- return {
1650
- width: result.width,
1651
- height: result.height
1652
- };
1653
- } catch (error) {
1654
- throw new Error(
1655
- `Error reading image dimensions from ${imagePath}: ${error instanceof Error ? error.message : String(error)}`
1656
- );
1657
- }
1658
- }
1659
- function calculateMissingDimension(originalWidth, originalHeight, targetWidth, targetHeight) {
1660
- if (targetWidth && targetHeight) {
1661
- return { width: targetWidth, height: targetHeight };
1662
- }
1663
- const aspectRatio = originalWidth / originalHeight;
1664
- if (targetWidth && !targetHeight) {
1665
- return {
1666
- width: targetWidth,
1667
- height: Math.round(targetWidth / aspectRatio)
1668
- };
1669
- }
1670
- if (!targetWidth && targetHeight) {
1671
- return {
1672
- width: Math.round(targetHeight * aspectRatio),
1673
- height: targetHeight
1674
- };
1675
- }
1676
- return { width: originalWidth, height: originalHeight };
1677
- }
1678
- async function calculateImageDimensions(imagePath, targetWidth, targetHeight, fallbackWidth = 300, fallbackHeight = 180) {
1679
- try {
1680
- const originalDimensions = await getImageDimensions(imagePath);
1681
- return calculateMissingDimension(
1682
- originalDimensions.width,
1683
- originalDimensions.height,
1684
- targetWidth,
1685
- targetHeight
1686
- );
1687
- } catch (error) {
1688
- if (targetWidth && targetHeight) {
1689
- return { width: targetWidth, height: targetHeight };
1690
- }
1691
- if (targetWidth && !targetHeight) {
1692
- return { width: targetWidth, height: Math.round(targetWidth * 9 / 16) };
1693
- }
1694
- if (!targetWidth && targetHeight) {
1695
- return {
1696
- width: Math.round(targetHeight * 16 / 9),
1697
- height: targetHeight
1698
- };
1699
- }
1700
- return { width: fallbackWidth, height: fallbackHeight };
1701
- }
1702
- }
1703
- var init_imageUtils = __esm({
1704
- "src/utils/imageUtils.ts"() {
1705
- "use strict";
1706
- init_widthUtils();
1707
- }
1708
- });
1709
-
1710
1472
  // src/utils/docxImagePositioning.ts
1711
1473
  var docxImagePositioning_exports = {};
1712
1474
  __export(docxImagePositioning_exports, {
@@ -1815,13 +1577,17 @@ function mapWrapSide(side) {
1815
1577
  return void 0;
1816
1578
  }
1817
1579
  }
1818
- function mapFloatingOptions(floating) {
1580
+ function mapFloatingOptions(floating, theme, themeName) {
1819
1581
  if (!floating) return void 0;
1820
1582
  if (floating.wrap?.type === "tight") {
1821
1583
  throw new Error(
1822
1584
  "Image floating wrap.type 'tight' is not supported due to invalid OOXML emitted by docx. Use 'square', 'topAndBottom', or 'none'."
1823
1585
  );
1824
1586
  }
1587
+ const hRelative = floating.horizontalPosition?.relative;
1588
+ const vRelative = floating.verticalPosition?.relative;
1589
+ const hRef = hRelative && hRelative !== "page" ? getAvailableWidthTwips(theme, themeName) : getPageWidthTwips(theme, themeName);
1590
+ const vRef = vRelative && vRelative !== "page" ? getAvailableHeightTwips(theme, themeName) : getPageHeightTwips(theme, themeName);
1825
1591
  const hasHorizontal = Boolean(floating.horizontalPosition);
1826
1592
  const hasVertical = Boolean(floating.verticalPosition);
1827
1593
  const horizontalPosition = floating.horizontalPosition ? {
@@ -1832,7 +1598,7 @@ function mapFloatingOptions(floating) {
1832
1598
  align: mapHorizontalAlign(floating.horizontalPosition.align)
1833
1599
  },
1834
1600
  ...floating.horizontalPosition.offset !== void 0 && {
1835
- offset: floating.horizontalPosition.offset * TWIPS_TO_EMU
1601
+ offset: resolveOffsetTwips(floating.horizontalPosition.offset, hRef) * TWIPS_TO_EMU
1836
1602
  }
1837
1603
  } : hasVertical ? {
1838
1604
  // Default horizontal: align left relative to margin
@@ -1847,7 +1613,7 @@ function mapFloatingOptions(floating) {
1847
1613
  align: mapVerticalAlign(floating.verticalPosition.align)
1848
1614
  },
1849
1615
  ...floating.verticalPosition.offset !== void 0 && {
1850
- offset: floating.verticalPosition.offset * TWIPS_TO_EMU
1616
+ offset: resolveOffsetTwips(floating.verticalPosition.offset, vRef) * TWIPS_TO_EMU
1851
1617
  }
1852
1618
  } : hasHorizontal ? {
1853
1619
  // Default vertical: align top relative to paragraph
@@ -1858,19 +1624,21 @@ function mapFloatingOptions(floating) {
1858
1624
  ...floating.wrap.type && { type: mapWrapType(floating.wrap.type) },
1859
1625
  ...floating.wrap.side && { side: mapWrapSide(floating.wrap.side) }
1860
1626
  } : void 0;
1627
+ const pageW = getPageWidthTwips(theme, themeName);
1628
+ const pageH = getPageHeightTwips(theme, themeName);
1861
1629
  const rawMargins = floating.wrap?.margins || floating.margins;
1862
1630
  const margins = rawMargins ? {
1863
1631
  ...rawMargins.top !== void 0 && {
1864
- top: rawMargins.top * TWIPS_TO_EMU
1632
+ top: resolveOffsetTwips(rawMargins.top, pageH) * TWIPS_TO_EMU
1865
1633
  },
1866
1634
  ...rawMargins.bottom !== void 0 && {
1867
- bottom: rawMargins.bottom * TWIPS_TO_EMU
1635
+ bottom: resolveOffsetTwips(rawMargins.bottom, pageH) * TWIPS_TO_EMU
1868
1636
  },
1869
1637
  ...rawMargins.left !== void 0 && {
1870
- left: rawMargins.left * TWIPS_TO_EMU
1638
+ left: resolveOffsetTwips(rawMargins.left, pageW) * TWIPS_TO_EMU
1871
1639
  },
1872
1640
  ...rawMargins.right !== void 0 && {
1873
- right: rawMargins.right * TWIPS_TO_EMU
1641
+ right: resolveOffsetTwips(rawMargins.right, pageW) * TWIPS_TO_EMU
1874
1642
  }
1875
1643
  } : void 0;
1876
1644
  let zIndex = floating.zIndex !== void 0 ? floating.zIndex : 0;
@@ -1906,6 +1674,7 @@ var TWIPS_TO_EMU;
1906
1674
  var init_docxImagePositioning = __esm({
1907
1675
  "src/utils/docxImagePositioning.ts"() {
1908
1676
  "use strict";
1677
+ init_widthUtils();
1909
1678
  TWIPS_TO_EMU = 635;
1910
1679
  }
1911
1680
  });
@@ -2172,8 +1941,6 @@ import {
2172
1941
  isTableComponent,
2173
1942
  isListComponent,
2174
1943
  isTocComponent,
2175
- isHeaderComponent,
2176
- isFooterComponent,
2177
1944
  isHighchartsComponent
2178
1945
  } from "@json-to-office/shared-docx";
2179
1946
 
@@ -2650,18 +2417,251 @@ Suggestion: ${suggestion}`
2650
2417
  }
2651
2418
 
2652
2419
  // src/core/render.ts
2653
- init_imageUtils();
2654
- init_defaults();
2655
2420
  import {
2656
2421
  Document,
2657
- Paragraph as Paragraph9,
2658
- TextRun as TextRun7,
2659
- ImageRun as ImageRun2,
2660
- AlignmentType as AlignmentType6,
2422
+ Paragraph as Paragraph7,
2423
+ TextRun as TextRun5,
2424
+ AlignmentType as AlignmentType5,
2661
2425
  BookmarkStart as BookmarkStart2,
2662
2426
  BookmarkEnd as BookmarkEnd2
2663
2427
  } from "docx";
2664
2428
 
2429
+ // src/utils/imageUtils.ts
2430
+ init_widthUtils();
2431
+ import { readFileSync } from "fs";
2432
+ import probe from "probe-image-size";
2433
+ import { ImageRun } from "docx";
2434
+ function parseWidthValue(width, availableWidthPx) {
2435
+ if (typeof width === "number") {
2436
+ return width;
2437
+ }
2438
+ const percentageMatch = width.match(/^(\d+(?:\.\d+)?)%$/);
2439
+ if (percentageMatch) {
2440
+ const pct = parseFloat(percentageMatch[1]);
2441
+ if (pct < 0 || pct > 100) {
2442
+ throw new Error(
2443
+ `Invalid percentage value: ${width}. Must be between 0% and 100%`
2444
+ );
2445
+ }
2446
+ const fraction = parsePercentageStringToFraction(width);
2447
+ if (fraction !== void 0) {
2448
+ return Math.round(availableWidthPx * fraction);
2449
+ }
2450
+ }
2451
+ throw new Error(
2452
+ `Invalid width value: ${width}. Expected number (pixels) or percentage string (e.g., "90%")`
2453
+ );
2454
+ }
2455
+ function parseDimensionValue(value, availablePx) {
2456
+ if (typeof value === "number") return value;
2457
+ const percentageMatch = value.match(/^(\d+(?:\.\d+)?)%$/);
2458
+ if (percentageMatch) {
2459
+ const pct = parseFloat(percentageMatch[1]);
2460
+ if (pct < 0 || pct > 100) {
2461
+ throw new Error(
2462
+ `Invalid percentage value: ${value}. Must be between 0% and 100%`
2463
+ );
2464
+ }
2465
+ const fraction = parsePercentageStringToFraction(value);
2466
+ if (fraction !== void 0) return Math.round(availablePx * fraction);
2467
+ }
2468
+ throw new Error(
2469
+ `Invalid dimension value: ${value}. Expected number (pixels) or percentage string (e.g., "90%")`
2470
+ );
2471
+ }
2472
+ function isValidUrl(string) {
2473
+ try {
2474
+ const url = new URL(string);
2475
+ return url.protocol === "http:" || url.protocol === "https:";
2476
+ } catch {
2477
+ return false;
2478
+ }
2479
+ }
2480
+ function isBase64Image(string) {
2481
+ return /^data:image\/[a-zA-Z+]+;base64,/.test(string);
2482
+ }
2483
+ function decodeBase64Image(dataUri) {
2484
+ try {
2485
+ const base64Data = dataUri.split(",")[1];
2486
+ if (!base64Data) {
2487
+ throw new Error("Invalid base64 data URI format");
2488
+ }
2489
+ return Buffer.from(base64Data, "base64");
2490
+ } catch (error) {
2491
+ throw new Error(
2492
+ `Failed to decode base64 image: ${error instanceof Error ? error.message : String(error)}`
2493
+ );
2494
+ }
2495
+ }
2496
+ function extractMimeTypeFromDataUri(dataUri) {
2497
+ const match = dataUri.match(/^data:(image\/[a-zA-Z0-9+.-]+);base64,/);
2498
+ return match ? match[1] : void 0;
2499
+ }
2500
+ function detectImageTypeFromExtension(path4) {
2501
+ const extension = path4.toLowerCase().split(".").pop()?.split("?")[0];
2502
+ switch (extension) {
2503
+ case "jpg":
2504
+ case "jpeg":
2505
+ return "jpg";
2506
+ case "png":
2507
+ return "png";
2508
+ case "gif":
2509
+ return "gif";
2510
+ case "bmp":
2511
+ return "bmp";
2512
+ case "svg":
2513
+ return "svg";
2514
+ default:
2515
+ return void 0;
2516
+ }
2517
+ }
2518
+ function detectImageTypeFromMimeType(mimeType) {
2519
+ const normalized = mimeType.toLowerCase();
2520
+ if (normalized.includes("svg")) return "svg";
2521
+ if (normalized.includes("jpeg") || normalized.includes("jpg")) return "jpg";
2522
+ if (normalized.includes("png")) return "png";
2523
+ if (normalized.includes("gif")) return "gif";
2524
+ if (normalized.includes("bmp")) return "bmp";
2525
+ return void 0;
2526
+ }
2527
+ function detectImageType(imagePath, responseContentType) {
2528
+ if (responseContentType) {
2529
+ const typeFromResponse = detectImageTypeFromMimeType(responseContentType);
2530
+ if (typeFromResponse) return typeFromResponse;
2531
+ }
2532
+ if (isBase64Image(imagePath)) {
2533
+ const mimeType = extractMimeTypeFromDataUri(imagePath);
2534
+ if (mimeType) {
2535
+ const typeFromMime = detectImageTypeFromMimeType(mimeType);
2536
+ if (typeFromMime) return typeFromMime;
2537
+ }
2538
+ }
2539
+ const typeFromExtension = detectImageTypeFromExtension(imagePath);
2540
+ if (typeFromExtension) return typeFromExtension;
2541
+ return "png";
2542
+ }
2543
+ function createTypedImageRun(opts) {
2544
+ const base = {
2545
+ data: opts.data,
2546
+ transformation: opts.transformation,
2547
+ ...opts.floating && { floating: opts.floating }
2548
+ };
2549
+ if (opts.type === "svg") {
2550
+ return new ImageRun({
2551
+ type: "svg",
2552
+ ...base,
2553
+ fallback: { type: "png", data: opts.data }
2554
+ });
2555
+ }
2556
+ return new ImageRun({ type: opts.type, ...base });
2557
+ }
2558
+ async function downloadImageFromUrl(url) {
2559
+ try {
2560
+ const controller = new AbortController();
2561
+ const timeoutId = setTimeout(() => controller.abort(), 1e4);
2562
+ const response = await fetch(url, {
2563
+ signal: controller.signal,
2564
+ headers: {
2565
+ "User-Agent": "Mozilla/5.0 (compatible; json-to-docx/1.0)"
2566
+ },
2567
+ redirect: "follow"
2568
+ // Automatically follow redirects (default behavior)
2569
+ });
2570
+ clearTimeout(timeoutId);
2571
+ if (!response.ok) {
2572
+ throw new Error(
2573
+ `Failed to download image: HTTP ${response.status} ${response.statusText}`
2574
+ );
2575
+ }
2576
+ const contentType = response.headers.get("content-type") || void 0;
2577
+ const arrayBuffer = await response.arrayBuffer();
2578
+ return { buffer: Buffer.from(arrayBuffer), contentType };
2579
+ } catch (error) {
2580
+ if (error instanceof Error) {
2581
+ if (error.name === "AbortError") {
2582
+ throw new Error(
2583
+ "Failed to download image: Request timeout after 10 seconds"
2584
+ );
2585
+ }
2586
+ throw new Error(`Failed to download image from ${url}: ${error.message}`);
2587
+ }
2588
+ throw new Error(`Failed to download image from ${url}: Unknown error`);
2589
+ }
2590
+ }
2591
+ async function getImageBuffer(imagePath) {
2592
+ if (isBase64Image(imagePath)) {
2593
+ return { buffer: decodeBase64Image(imagePath) };
2594
+ }
2595
+ if (isValidUrl(imagePath)) {
2596
+ return await downloadImageFromUrl(imagePath);
2597
+ }
2598
+ return { buffer: readFileSync(imagePath) };
2599
+ }
2600
+ async function getImageDimensions(imagePath) {
2601
+ try {
2602
+ const { buffer: imageBuffer } = await getImageBuffer(imagePath);
2603
+ const result = probe.sync(imageBuffer);
2604
+ if (!result) {
2605
+ throw new Error(`Unable to determine dimensions for image: ${imagePath}`);
2606
+ }
2607
+ return {
2608
+ width: result.width,
2609
+ height: result.height
2610
+ };
2611
+ } catch (error) {
2612
+ throw new Error(
2613
+ `Error reading image dimensions from ${imagePath}: ${error instanceof Error ? error.message : String(error)}`
2614
+ );
2615
+ }
2616
+ }
2617
+ function calculateMissingDimension(originalWidth, originalHeight, targetWidth, targetHeight) {
2618
+ if (targetWidth && targetHeight) {
2619
+ return { width: targetWidth, height: targetHeight };
2620
+ }
2621
+ const aspectRatio = originalWidth / originalHeight;
2622
+ if (targetWidth && !targetHeight) {
2623
+ return {
2624
+ width: targetWidth,
2625
+ height: Math.round(targetWidth / aspectRatio)
2626
+ };
2627
+ }
2628
+ if (!targetWidth && targetHeight) {
2629
+ return {
2630
+ width: Math.round(targetHeight * aspectRatio),
2631
+ height: targetHeight
2632
+ };
2633
+ }
2634
+ return { width: originalWidth, height: originalHeight };
2635
+ }
2636
+ async function calculateImageDimensions(imagePath, targetWidth, targetHeight, fallbackWidth = 300, fallbackHeight = 180) {
2637
+ try {
2638
+ const originalDimensions = await getImageDimensions(imagePath);
2639
+ return calculateMissingDimension(
2640
+ originalDimensions.width,
2641
+ originalDimensions.height,
2642
+ targetWidth,
2643
+ targetHeight
2644
+ );
2645
+ } catch (error) {
2646
+ if (targetWidth && targetHeight) {
2647
+ return { width: targetWidth, height: targetHeight };
2648
+ }
2649
+ if (targetWidth && !targetHeight) {
2650
+ return { width: targetWidth, height: Math.round(targetWidth * 9 / 16) };
2651
+ }
2652
+ if (!targetWidth && targetHeight) {
2653
+ return {
2654
+ width: Math.round(targetHeight * 16 / 9),
2655
+ height: targetHeight
2656
+ };
2657
+ }
2658
+ return { width: fallbackWidth, height: fallbackHeight };
2659
+ }
2660
+ }
2661
+
2662
+ // src/core/render.ts
2663
+ init_defaults();
2664
+
2665
2665
  // src/styles/themeToDocxAdapter.ts
2666
2666
  init_themes();
2667
2667
  init_colorUtils();
@@ -3941,9 +3941,6 @@ function resolveListProps(props, theme) {
3941
3941
  }
3942
3942
 
3943
3943
  // src/core/content.ts
3944
- init_imageUtils();
3945
- init_styles();
3946
- init_defaults();
3947
3944
  import {
3948
3945
  Paragraph,
3949
3946
  TextRun as TextRun3,
@@ -3951,7 +3948,6 @@ import {
3951
3948
  TableRow,
3952
3949
  TableCell,
3953
3950
  AlignmentType as AlignmentType2,
3954
- ImageRun,
3955
3951
  PageBreak,
3956
3952
  WidthType,
3957
3953
  BorderStyle as BorderStyle2,
@@ -3963,6 +3959,8 @@ import {
3963
3959
  VerticalAlign,
3964
3960
  Bookmark
3965
3961
  } from "docx";
3962
+ init_styles();
3963
+ init_defaults();
3966
3964
 
3967
3965
  // src/utils/bookmarkRegistry.ts
3968
3966
  var BookmarkRegistry = class {
@@ -4037,7 +4035,8 @@ var globalBookmarkRegistry = new BookmarkRegistry();
4037
4035
  init_styleHelpers();
4038
4036
  init_colorUtils();
4039
4037
  init_styleHelpers();
4040
- function createText(content, theme, _themeName, options = {}) {
4038
+ init_widthUtils();
4039
+ function createText(content, theme, themeName, options = {}) {
4041
4040
  const normalizedContent = normalizeUnicodeText(content);
4042
4041
  const style = options.style || "Normal";
4043
4042
  const spacing = {};
@@ -4089,7 +4088,7 @@ function createText(content, theme, _themeName, options = {}) {
4089
4088
  children.push(...textRuns);
4090
4089
  }
4091
4090
  const isFloating = !!options.floating;
4092
- const frameOptions = isFloating && options.floating ? mapFrameOptions(options.floating) : void 0;
4091
+ const frameOptions = isFloating && options.floating ? mapFrameOptions(options.floating, theme, themeName) : void 0;
4093
4092
  return new Paragraph({
4094
4093
  children,
4095
4094
  style,
@@ -4103,7 +4102,7 @@ function createText(content, theme, _themeName, options = {}) {
4103
4102
  ...options.keepLines !== void 0 && { keepLines: options.keepLines }
4104
4103
  });
4105
4104
  }
4106
- function mapFrameOptions(floating) {
4105
+ function mapFrameOptions(floating, theme, themeName) {
4107
4106
  const hasHorizontalOffset = floating.horizontalPosition?.offset !== void 0;
4108
4107
  const hasVerticalOffset = floating.verticalPosition?.offset !== void 0;
4109
4108
  const hasHorizontalAlign = floating.horizontalPosition?.align !== void 0;
@@ -4128,8 +4127,21 @@ function mapFrameOptions(floating) {
4128
4127
  baseOptions.anchorLock = floating.anchorLock;
4129
4128
  }
4130
4129
  if (useAbsolute) {
4131
- const x = floating.horizontalPosition?.offset ?? 0;
4132
- const y = floating.verticalPosition?.offset ?? 0;
4130
+ const rawX = floating.horizontalPosition?.offset ?? 0;
4131
+ const rawY = floating.verticalPosition?.offset ?? 0;
4132
+ let x;
4133
+ let y;
4134
+ if (typeof rawX === "string" || typeof rawY === "string") {
4135
+ const hRelative = floating.horizontalPosition?.relative;
4136
+ const vRelative = floating.verticalPosition?.relative;
4137
+ const hRef = hRelative && hRelative !== "page" ? getAvailableWidthTwips(theme, themeName) : getPageWidthTwips(theme, themeName);
4138
+ const vRef = vRelative && vRelative !== "page" ? getAvailableHeightTwips(theme, themeName) : getPageHeightTwips(theme, themeName);
4139
+ x = resolveOffsetTwips(rawX, hRef);
4140
+ y = resolveOffsetTwips(rawY, vRef);
4141
+ } else {
4142
+ x = rawX;
4143
+ y = rawY;
4144
+ }
4133
4145
  return {
4134
4146
  type: "absolute",
4135
4147
  position: { x, y },
@@ -4227,14 +4239,17 @@ function createHeading(text, level, theme, _themeName, options = {}) {
4227
4239
  ...options.keepLines !== void 0 && { keepLines: options.keepLines }
4228
4240
  });
4229
4241
  }
4230
- async function createImage(path4, theme, options = {}) {
4242
+ async function createImage(path4, theme, themeName, options = {}) {
4231
4243
  const elements = [];
4232
4244
  const isFloating = !!options.floating;
4233
4245
  const alignment = isFloating ? void 0 : getAlignment(options.alignment || "center");
4234
4246
  let imagePath = path4;
4235
4247
  let imageBuffer;
4248
+ let responseContentType;
4236
4249
  try {
4237
- imageBuffer = await getImageBuffer(imagePath);
4250
+ const imageResult = await getImageBuffer(imagePath);
4251
+ imageBuffer = imageResult.buffer;
4252
+ responseContentType = imageResult.contentType;
4238
4253
  const {
4239
4254
  getAvailableWidthTwips: getAvailableWidthTwips2,
4240
4255
  getPageWidthTwips: getPageWidthTwips2,
@@ -4264,29 +4279,12 @@ async function createImage(path4, theme, options = {}) {
4264
4279
  fallbackHeight
4265
4280
  );
4266
4281
  const { mapFloatingOptions: mapFloatingOptions2 } = await Promise.resolve().then(() => (init_docxImagePositioning(), docxImagePositioning_exports));
4267
- const floating = isFloating ? mapFloatingOptions2(options.floating) : void 0;
4268
- const { detectImageType: detectImageType2 } = await Promise.resolve().then(() => (init_imageUtils(), imageUtils_exports));
4269
- const imageType = detectImageType2(imagePath);
4270
- const imageRun = imageType === "svg" ? new ImageRun({
4271
- type: "svg",
4272
- data: imageBuffer,
4273
- fallback: {
4274
- type: "png",
4275
- data: imageBuffer
4276
- // Use the same buffer as fallback for now
4277
- },
4278
- transformation: {
4279
- width: dimensions.width,
4280
- height: dimensions.height
4281
- },
4282
- ...floating && { floating }
4283
- }) : new ImageRun({
4282
+ const floating = isFloating ? mapFloatingOptions2(options.floating, theme, themeName) : void 0;
4283
+ const imageType = detectImageType(imagePath, responseContentType);
4284
+ const imageRun = createTypedImageRun({
4284
4285
  type: imageType,
4285
4286
  data: imageBuffer,
4286
- transformation: {
4287
- width: dimensions.width,
4288
- height: dimensions.height
4289
- },
4287
+ transformation: { width: dimensions.width, height: dimensions.height },
4290
4288
  ...floating && { floating }
4291
4289
  });
4292
4290
  const spacing = {};
@@ -4410,7 +4408,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
4410
4408
  const numRows = columns[0]?.cells?.length || 0;
4411
4409
  const getDefaultCellDefaults = () => ({
4412
4410
  color: "000000",
4413
- backgroundColor: "FFFFFF",
4411
+ backgroundColor: "transparent",
4414
4412
  horizontalAlignment: "left",
4415
4413
  verticalAlignment: "top",
4416
4414
  font: {
@@ -4715,9 +4713,27 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
4715
4713
  if (typeof cell === "object" && "name" in cell && "props" in cell) {
4716
4714
  if (isParagraphComponent(cell)) {
4717
4715
  const textComp = cell;
4716
+ const paragraphFont = textComp.props.font;
4717
+ const paragraphStyle = {
4718
+ ...mergedStyle,
4719
+ ...paragraphFont?.family && { font: paragraphFont.family },
4720
+ ...paragraphFont?.size && { size: paragraphFont.size * 2 },
4721
+ ...paragraphFont?.bold !== void 0 && {
4722
+ bold: paragraphFont.bold
4723
+ },
4724
+ ...paragraphFont?.italic !== void 0 && {
4725
+ italics: paragraphFont.italic
4726
+ },
4727
+ ...paragraphFont?.underline !== void 0 && {
4728
+ underline: paragraphFont.underline ? { type: "single" } : void 0
4729
+ },
4730
+ ...paragraphFont?.color && {
4731
+ color: resolveColor(paragraphFont.color, theme)
4732
+ }
4733
+ };
4718
4734
  cellChildren = parseTextWithDecorators(
4719
4735
  textComp.props.text,
4720
- mergedStyle,
4736
+ paragraphStyle,
4721
4737
  { enableHyperlinks: true }
4722
4738
  );
4723
4739
  } else if (isImageComponent(cell)) {
@@ -4729,7 +4745,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
4729
4745
  'Image component requires either "path" or "base64" property'
4730
4746
  );
4731
4747
  }
4732
- const imageBuffer = await getImageBuffer(imageSource);
4748
+ const imageResult = await getImageBuffer(imageSource);
4733
4749
  const parsedWidth = typeof imageComp.props.width === "string" ? parseWidthValue(imageComp.props.width, 300) : imageComp.props.width;
4734
4750
  const parsedHeight = typeof imageComp.props.height === "string" ? parseWidthValue(imageComp.props.height, 200) : imageComp.props.height;
4735
4751
  const dimensions = await calculateImageDimensions(
@@ -4741,9 +4757,10 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
4741
4757
  20
4742
4758
  // fallback height
4743
4759
  );
4744
- const imageRun = new ImageRun({
4745
- type: "png",
4746
- data: imageBuffer,
4760
+ const imgType = detectImageType(imageSource, imageResult.contentType);
4761
+ const imageRun = createTypedImageRun({
4762
+ type: imgType,
4763
+ data: imageResult.buffer,
4747
4764
  transformation: {
4748
4765
  width: dimensions.width,
4749
4766
  height: dimensions.height
@@ -4847,8 +4864,10 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
4847
4864
  })
4848
4865
  ],
4849
4866
  verticalAlign: verticalAlignment,
4850
- shading: {
4851
- fill: mergedDefaults.backgroundColor || getThemeColors(theme).background
4867
+ ...mergedDefaults.backgroundColor !== "transparent" && {
4868
+ shading: {
4869
+ fill: mergedDefaults.backgroundColor
4870
+ }
4852
4871
  },
4853
4872
  margins: createMarginsFromPadding(mergedDefaults.padding),
4854
4873
  borders: {
@@ -5014,8 +5033,10 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
5014
5033
  })
5015
5034
  ],
5016
5035
  verticalAlign: verticalAlignment,
5017
- shading: {
5018
- fill: mergedDefaults.backgroundColor || getThemeColors(theme).background
5036
+ ...mergedDefaults.backgroundColor !== "transparent" && {
5037
+ shading: {
5038
+ fill: mergedDefaults.backgroundColor
5039
+ }
5019
5040
  },
5020
5041
  margins: createMarginsFromPadding(mergedDefaults.padding),
5021
5042
  borders: {
@@ -5419,7 +5440,7 @@ function renderListComponent(component, theme, themeName) {
5419
5440
  }
5420
5441
 
5421
5442
  // src/components/image.ts
5422
- async function renderImageComponent(component, theme) {
5443
+ async function renderImageComponent(component, theme, themeName) {
5423
5444
  if (!isImageComponent(component)) return [];
5424
5445
  const resolvedConfig = resolveImageProps(component.props, theme);
5425
5446
  const imageSource = resolvedConfig.base64 || resolvedConfig.path;
@@ -5428,7 +5449,7 @@ async function renderImageComponent(component, theme) {
5428
5449
  'Image component requires either "path" or "base64" property'
5429
5450
  );
5430
5451
  }
5431
- return await createImage(imageSource, theme, {
5452
+ return await createImage(imageSource, theme, themeName, {
5432
5453
  caption: resolvedConfig.caption,
5433
5454
  width: resolvedConfig.width,
5434
5455
  height: resolvedConfig.height,
@@ -5529,15 +5550,20 @@ function buildCellOptions(children, styleCfg, theme) {
5529
5550
  }
5530
5551
 
5531
5552
  // src/components/text-box.ts
5532
- function mapTableFloatOptions(floating) {
5553
+ init_widthUtils();
5554
+ function mapTableFloatOptions(floating, theme, themeName) {
5533
5555
  if (!floating) return void 0;
5534
5556
  const opt = {};
5557
+ const hRelative = floating.horizontalPosition?.relative;
5558
+ const vRelative = floating.verticalPosition?.relative;
5559
+ const hRef = hRelative && hRelative !== "page" ? getAvailableWidthTwips(theme, themeName) : getPageWidthTwips(theme, themeName);
5560
+ const vRef = vRelative && vRelative !== "page" ? getAvailableHeightTwips(theme, themeName) : getPageHeightTwips(theme, themeName);
5535
5561
  const hp = floating.horizontalPosition;
5536
5562
  if (hp?.relative) {
5537
5563
  opt.horizontalAnchor = hp.relative === "margin" ? TableAnchorType.MARGIN : hp.relative === "page" ? TableAnchorType.PAGE : TableAnchorType.TEXT;
5538
5564
  }
5539
5565
  if (hp?.offset !== void 0) {
5540
- opt.absoluteHorizontalPosition = hp.offset;
5566
+ opt.absoluteHorizontalPosition = resolveOffsetTwips(hp.offset, hRef);
5541
5567
  } else if (hp?.align) {
5542
5568
  const map = {
5543
5569
  left: RelativeHorizontalPosition.LEFT,
@@ -5553,7 +5579,7 @@ function mapTableFloatOptions(floating) {
5553
5579
  opt.verticalAnchor = vp.relative === "margin" ? TableAnchorType.MARGIN : vp.relative === "page" ? TableAnchorType.PAGE : TableAnchorType.TEXT;
5554
5580
  }
5555
5581
  if (vp?.offset !== void 0) {
5556
- opt.absoluteVerticalPosition = vp.offset;
5582
+ opt.absoluteVerticalPosition = resolveOffsetTwips(vp.offset, vRef);
5557
5583
  } else if (vp?.align) {
5558
5584
  const mapV = {
5559
5585
  top: RelativeVerticalPosition.TOP,
@@ -5564,12 +5590,17 @@ function mapTableFloatOptions(floating) {
5564
5590
  };
5565
5591
  opt.relativeVerticalPosition = mapV[vp.align];
5566
5592
  }
5593
+ const pageW = getPageWidthTwips(theme, themeName);
5594
+ const pageH = getPageHeightTwips(theme, themeName);
5567
5595
  const m = floating.wrap?.margins;
5568
5596
  if (m) {
5569
- if (m.top !== void 0) opt.topFromText = m.top;
5570
- if (m.right !== void 0) opt.rightFromText = m.right;
5571
- if (m.bottom !== void 0) opt.bottomFromText = m.bottom;
5572
- if (m.left !== void 0) opt.leftFromText = m.left;
5597
+ if (m.top !== void 0) opt.topFromText = resolveOffsetTwips(m.top, pageH);
5598
+ if (m.right !== void 0)
5599
+ opt.rightFromText = resolveOffsetTwips(m.right, pageW);
5600
+ if (m.bottom !== void 0)
5601
+ opt.bottomFromText = resolveOffsetTwips(m.bottom, pageH);
5602
+ if (m.left !== void 0)
5603
+ opt.leftFromText = resolveOffsetTwips(m.left, pageW);
5573
5604
  }
5574
5605
  opt.overlap = OverlapType.OVERLAP;
5575
5606
  return opt;
@@ -5625,7 +5656,7 @@ async function renderTextBoxComponent(component, theme, themeName, _context) {
5625
5656
  const row = new TableRow2({
5626
5657
  children: [new TableCell2(cellOpts)]
5627
5658
  });
5628
- const float = mapTableFloatOptions(tb.props.floating);
5659
+ const float = mapTableFloatOptions(tb.props.floating, theme, themeName);
5629
5660
  const PIXELS_TO_TWIPS = 15;
5630
5661
  const DEFAULT_WIDTH_TWIPS = 5e3;
5631
5662
  const rawWidth = tb.props.width ?? tb.props.floating?.width;
@@ -5662,7 +5693,7 @@ async function renderTableComponent(component, theme, themeName) {
5662
5693
  const rows = rawConfig.rows;
5663
5694
  const defaultCellDefaults = {
5664
5695
  color: "000000",
5665
- backgroundColor: "FFFFFF",
5696
+ backgroundColor: "transparent",
5666
5697
  horizontalAlignment: "left",
5667
5698
  verticalAlignment: "top",
5668
5699
  font: {
@@ -5898,77 +5929,12 @@ function renderStatisticComponent(component, theme) {
5898
5929
  );
5899
5930
  }
5900
5931
 
5901
- // src/components/header.ts
5902
- import { Paragraph as Paragraph6, TextRun as TextRun4 } from "docx";
5903
- init_styles();
5904
- init_defaults();
5905
-
5906
- // src/utils/alignmentUtils.ts
5907
- import { AlignmentType as AlignmentType4 } from "docx";
5908
- function getAlignment3(alignment) {
5909
- switch (alignment) {
5910
- case "center":
5911
- return AlignmentType4.CENTER;
5912
- case "right":
5913
- return AlignmentType4.RIGHT;
5914
- case "justify":
5915
- return AlignmentType4.JUSTIFIED;
5916
- default:
5917
- return AlignmentType4.LEFT;
5918
- }
5919
- }
5920
-
5921
- // src/components/header.ts
5922
- function renderHeaderComponent(component, theme, themeName) {
5923
- if (!isHeaderComponent(component)) return [];
5924
- const headerComp = component;
5925
- const bodyStyle = getBodyTextStyle(theme, themeName);
5926
- return [
5927
- new Paragraph6({
5928
- children: [
5929
- new TextRun4({
5930
- text: `[Header: ${headerComp.props.alignment || "center"}]`,
5931
- font: bodyStyle.font,
5932
- size: bodyStyle.size,
5933
- color: getThemeColors(theme).secondary
5934
- })
5935
- ],
5936
- alignment: getAlignment3(headerComp.props.alignment || "center"),
5937
- style: "Normal"
5938
- })
5939
- ];
5940
- }
5941
-
5942
- // src/components/footer.ts
5943
- import { Paragraph as Paragraph7, TextRun as TextRun5 } from "docx";
5944
- init_styles();
5945
- init_defaults();
5946
- function renderFooterComponent(component, theme, themeName) {
5947
- if (!isFooterComponent(component)) return [];
5948
- const footerComp = component;
5949
- const bodyStyle = getBodyTextStyle(theme, themeName);
5950
- return [
5951
- new Paragraph7({
5952
- children: [
5953
- new TextRun5({
5954
- text: `[Footer: ${footerComp.props.alignment || "center"}]`,
5955
- font: bodyStyle.font,
5956
- size: bodyStyle.size,
5957
- color: getThemeColors(theme).secondary
5958
- })
5959
- ],
5960
- alignment: getAlignment3(footerComp.props.alignment || "center"),
5961
- style: "Normal"
5962
- })
5963
- ];
5964
- }
5965
-
5966
5932
  // src/components/toc/index.ts
5967
5933
  import {
5968
- Paragraph as Paragraph8,
5934
+ Paragraph as Paragraph6,
5969
5935
  TableOfContents,
5970
- AlignmentType as AlignmentType5,
5971
- TextRun as TextRun6,
5936
+ AlignmentType as AlignmentType4,
5937
+ TextRun as TextRun4,
5972
5938
  StyleLevel
5973
5939
  } from "docx";
5974
5940
  function parseDepthRange(rawDepth, fieldName, defaultFrom = 1, defaultTo = 3) {
@@ -6021,9 +5987,9 @@ function renderTocComponent(component, theme, context) {
6021
5987
  const paragraphs = [];
6022
5988
  if (componentProps.title) {
6023
5989
  paragraphs.push(
6024
- new Paragraph8({
5990
+ new Paragraph6({
6025
5991
  children: [
6026
- new TextRun6({
5992
+ new TextRun4({
6027
5993
  text: componentProps.title,
6028
5994
  bold: true,
6029
5995
  size: 28
@@ -6036,7 +6002,7 @@ function renderTocComponent(component, theme, context) {
6036
6002
  // 180 ~= 9pt, provides clearer separation by default
6037
6003
  after: 180
6038
6004
  },
6039
- alignment: AlignmentType5.LEFT
6005
+ alignment: AlignmentType4.LEFT
6040
6006
  })
6041
6007
  );
6042
6008
  }
@@ -6155,7 +6121,7 @@ Cause: ${error instanceof Error ? error.message : String(error)}`
6155
6121
  height
6156
6122
  };
6157
6123
  }
6158
- async function renderHighchartsComponent(component, theme, _themeName) {
6124
+ async function renderHighchartsComponent(component, theme, themeName) {
6159
6125
  if (!isHighchartsComponent(component)) return [];
6160
6126
  const config = component.props;
6161
6127
  const chartResult = await generateChart(config);
@@ -6165,6 +6131,7 @@ async function renderHighchartsComponent(component, theme, _themeName) {
6165
6131
  const imageParagraphs = await createImage(
6166
6132
  chartResult.base64DataUri,
6167
6133
  theme,
6134
+ themeName,
6168
6135
  {
6169
6136
  width: renderWidth,
6170
6137
  height: renderHeight,
@@ -6227,16 +6194,16 @@ var textSpaceAfterComponent = createComponent({
6227
6194
 
6228
6195
  // src/core/render.ts
6229
6196
  init_docxImagePositioning();
6230
- function getAlignment4(alignment) {
6197
+ function getAlignment3(alignment) {
6231
6198
  switch (alignment) {
6232
6199
  case "center":
6233
- return AlignmentType6.CENTER;
6200
+ return AlignmentType5.CENTER;
6234
6201
  case "right":
6235
- return AlignmentType6.RIGHT;
6202
+ return AlignmentType5.RIGHT;
6236
6203
  case "justify":
6237
- return AlignmentType6.JUSTIFIED;
6204
+ return AlignmentType5.JUSTIFIED;
6238
6205
  default:
6239
- return AlignmentType6.LEFT;
6206
+ return AlignmentType5.LEFT;
6240
6207
  }
6241
6208
  }
6242
6209
  async function renderDocument(structure, layout, options) {
@@ -6327,7 +6294,7 @@ async function renderDocument(structure, layout, options) {
6327
6294
  }
6328
6295
  });
6329
6296
  }
6330
- async function renderHeaderFooterComponents(components, theme, _themeName, _context) {
6297
+ async function renderHeaderFooterComponents(components, theme, themeName, _context) {
6331
6298
  if (!components || components.length === 0) {
6332
6299
  return [];
6333
6300
  }
@@ -6349,9 +6316,9 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
6349
6316
  };
6350
6317
  const textRuns = parseTextWithDecorators(textComp.props.text, textStyle);
6351
6318
  elements.push(
6352
- new Paragraph9({
6319
+ new Paragraph7({
6353
6320
  children: textRuns,
6354
- alignment: textComp.props.alignment ? getAlignment4(textComp.props.alignment) : void 0,
6321
+ alignment: textComp.props.alignment ? getAlignment3(textComp.props.alignment) : void 0,
6355
6322
  style: "Normal"
6356
6323
  })
6357
6324
  );
@@ -6360,9 +6327,9 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
6360
6327
  let imageSource = imageComp.props.base64 || imageComp.props.path;
6361
6328
  if (!imageSource) {
6362
6329
  elements.push(
6363
- new Paragraph9({
6330
+ new Paragraph7({
6364
6331
  children: [
6365
- new TextRun7({
6332
+ new TextRun5({
6366
6333
  text: "[IMAGE: Missing path or base64 property]",
6367
6334
  font: getThemeFonts(theme).body.family,
6368
6335
  size: 20,
@@ -6370,15 +6337,18 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
6370
6337
  color: "#FF0000"
6371
6338
  })
6372
6339
  ],
6373
- alignment: imageComp.props.alignment ? getAlignment4(imageComp.props.alignment) : void 0,
6340
+ alignment: imageComp.props.alignment ? getAlignment3(imageComp.props.alignment) : void 0,
6374
6341
  style: "Normal"
6375
6342
  })
6376
6343
  );
6377
6344
  continue;
6378
6345
  }
6379
6346
  let imageBuffer;
6347
+ let responseContentType;
6380
6348
  try {
6381
- imageBuffer = await getImageBuffer(imageSource);
6349
+ const imageResult = await getImageBuffer(imageSource);
6350
+ imageBuffer = imageResult.buffer;
6351
+ responseContentType = imageResult.contentType;
6382
6352
  } catch (error) {
6383
6353
  throw new Error(
6384
6354
  `Failed to load image from ${imageSource.substring(0, 50)}`
@@ -6411,9 +6381,14 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
6411
6381
  referenceWidthPx,
6412
6382
  fallbackHeight
6413
6383
  );
6414
- const floatingOptions = mapFloatingOptions(imageComp.props.floating);
6415
- const imageRun = new ImageRun2({
6416
- type: "png",
6384
+ const floatingOptions = mapFloatingOptions(
6385
+ imageComp.props.floating,
6386
+ theme,
6387
+ themeName
6388
+ );
6389
+ const imageType = detectImageType(imageSource, responseContentType);
6390
+ const imageRun = createTypedImageRun({
6391
+ type: imageType,
6417
6392
  data: imageBuffer,
6418
6393
  transformation: {
6419
6394
  width: dimensions.width,
@@ -6422,9 +6397,9 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
6422
6397
  ...floatingOptions && { floating: floatingOptions }
6423
6398
  });
6424
6399
  elements.push(
6425
- new Paragraph9({
6400
+ new Paragraph7({
6426
6401
  children: [imageRun],
6427
- alignment: imageComp.props.alignment ? getAlignment4(imageComp.props.alignment) : void 0,
6402
+ alignment: imageComp.props.alignment ? getAlignment3(imageComp.props.alignment) : void 0,
6428
6403
  style: "Normal"
6429
6404
  })
6430
6405
  );
@@ -6434,9 +6409,9 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
6434
6409
  error instanceof Error ? error.message : error
6435
6410
  );
6436
6411
  elements.push(
6437
- new Paragraph9({
6412
+ new Paragraph7({
6438
6413
  children: [
6439
- new TextRun7({
6414
+ new TextRun5({
6440
6415
  text: `[IMAGE: ${imageComp.props.path}]`,
6441
6416
  font: getThemeFonts(theme).body.family,
6442
6417
  size: 20,
@@ -6449,7 +6424,7 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
6449
6424
  );
6450
6425
  }
6451
6426
  } else if (isTableComponent(component)) {
6452
- const tables = await renderTableComponent(component, theme, _themeName);
6427
+ const tables = await renderTableComponent(component, theme, themeName);
6453
6428
  elements.push(...tables);
6454
6429
  }
6455
6430
  }
@@ -6474,7 +6449,7 @@ async function renderSection(section, theme, themeName, context, sectionOrdinal,
6474
6449
  };
6475
6450
  if (sectionBookmarkId && isFirstLayoutOfUserSection && sharedLinkId !== void 0) {
6476
6451
  elements.push(
6477
- new Paragraph9({
6452
+ new Paragraph7({
6478
6453
  children: [new BookmarkStart2(sectionBookmarkId, sharedLinkId)],
6479
6454
  spacing: {
6480
6455
  before: 0,
@@ -6500,7 +6475,7 @@ async function renderSection(section, theme, themeName, context, sectionOrdinal,
6500
6475
  }
6501
6476
  if (closeBookmark && sharedLinkId !== void 0) {
6502
6477
  elements.push(
6503
- new Paragraph9({
6478
+ new Paragraph7({
6504
6479
  children: [new BookmarkEnd2(sharedLinkId)]
6505
6480
  })
6506
6481
  );
@@ -6553,17 +6528,13 @@ async function renderComponent(component, theme, themeName, context) {
6553
6528
  } else if (isColumnsComponent(component)) {
6554
6529
  return await renderColumnsComponent(component, theme, themeName, context);
6555
6530
  } else if (isImageComponent(component)) {
6556
- return await renderImageComponent(component, theme);
6531
+ return await renderImageComponent(component, theme, themeName);
6557
6532
  } else if (isTextBoxComponent(component)) {
6558
6533
  return await renderTextBoxComponent(component, theme, themeName, context);
6559
6534
  } else if (isStatisticComponent(component)) {
6560
6535
  return renderStatisticComponent(component, theme);
6561
6536
  } else if (isTableComponent(component)) {
6562
6537
  return await renderTableComponent(component, theme, themeName);
6563
- } else if (isHeaderComponent(component)) {
6564
- return renderHeaderComponent(component, theme, themeName);
6565
- } else if (isFooterComponent(component)) {
6566
- return renderFooterComponent(component, theme, themeName);
6567
6538
  } else if (isListComponent(component)) {
6568
6539
  return renderListComponent(component, theme, themeName);
6569
6540
  } else if (isTocComponent(component)) {
@@ -7638,8 +7609,6 @@ export {
7638
7609
  hasNodeBuiltins,
7639
7610
  initializeComponentCache,
7640
7611
  isColumnsComponent,
7641
- isFooterComponent,
7642
- isHeaderComponent,
7643
7612
  isHeadingComponent,
7644
7613
  isHighchartsComponent,
7645
7614
  isImageComponent,