@json-to-office/core-docx 0.5.0 → 0.7.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/components/highcharts.d.ts +2 -2
- package/dist/components/highcharts.d.ts.map +1 -1
- package/dist/components/image.d.ts +1 -1
- package/dist/components/image.d.ts.map +1 -1
- package/dist/components/index.d.ts +0 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/text-box.d.ts.map +1 -1
- package/dist/core/content.d.ts +10 -10
- package/dist/core/content.d.ts.map +1 -1
- package/dist/core/generator.d.ts +2 -0
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/core/render.d.ts +2 -0
- package/dist/core/render.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +426 -437
- package/dist/index.js.map +1 -1
- package/dist/plugin/createDocumentGenerator.d.ts +3 -0
- package/dist/plugin/createDocumentGenerator.d.ts.map +1 -1
- package/dist/plugin/example/index.js +421 -431
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/templates/documents/proposal.docx.json +3 -4
- package/dist/templates/documents/technical-guide.docx.json +3 -4
- package/dist/templates/themes/index.d.ts +32 -32
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +5 -7
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/docxImagePositioning.d.ts +2 -1
- package/dist/utils/docxImagePositioning.d.ts.map +1 -1
- package/dist/utils/imageUtils.d.ts +24 -4
- package/dist/utils/imageUtils.d.ts.map +1 -1
- package/dist/utils/widthUtils.d.ts +5 -0
- package/dist/utils/widthUtils.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/components/footer.d.ts +0 -12
- package/dist/components/footer.d.ts.map +0 -1
- package/dist/components/header.d.ts +0 -12
- package/dist/components/header.d.ts.map +0 -1
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
|
|
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
|
|
2658
|
-
TextRun as
|
|
2659
|
-
|
|
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
|
-
|
|
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
|
|
4132
|
-
const
|
|
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
|
-
|
|
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
|
|
4269
|
-
const
|
|
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: "
|
|
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
|
-
|
|
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
|
|
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
|
|
4745
|
-
|
|
4746
|
-
|
|
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
|
-
|
|
4851
|
-
|
|
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
|
-
|
|
5018
|
-
|
|
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
|
-
|
|
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)
|
|
5571
|
-
|
|
5572
|
-
if (m.
|
|
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: "
|
|
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
|
|
5934
|
+
Paragraph as Paragraph6,
|
|
5969
5935
|
TableOfContents,
|
|
5970
|
-
AlignmentType as
|
|
5971
|
-
TextRun as
|
|
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
|
|
5990
|
+
new Paragraph6({
|
|
6025
5991
|
children: [
|
|
6026
|
-
new
|
|
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:
|
|
6005
|
+
alignment: AlignmentType4.LEFT
|
|
6040
6006
|
})
|
|
6041
6007
|
);
|
|
6042
6008
|
}
|
|
@@ -6112,27 +6078,33 @@ function hasNodeBuiltins() {
|
|
|
6112
6078
|
|
|
6113
6079
|
// src/components/highcharts.ts
|
|
6114
6080
|
var DEFAULT_EXPORT_SERVER_URL = "http://localhost:7801";
|
|
6115
|
-
function getExportServerUrl(propsUrl) {
|
|
6116
|
-
|
|
6081
|
+
function getExportServerUrl(propsUrl, servicesUrl) {
|
|
6082
|
+
const raw = propsUrl || servicesUrl || DEFAULT_EXPORT_SERVER_URL;
|
|
6083
|
+
return raw.startsWith("http") ? raw : `http://${raw}`;
|
|
6117
6084
|
}
|
|
6118
|
-
async function generateChart(config) {
|
|
6085
|
+
async function generateChart(config, servicesConfig) {
|
|
6119
6086
|
if (!isNodeEnvironment()) {
|
|
6120
6087
|
throw new Error(
|
|
6121
6088
|
"Highcharts export server requires a Node.js environment. Chart generation is not available in browser environments."
|
|
6122
6089
|
);
|
|
6123
6090
|
}
|
|
6124
|
-
const serverUrl = getExportServerUrl(
|
|
6091
|
+
const serverUrl = getExportServerUrl(
|
|
6092
|
+
config.serverUrl,
|
|
6093
|
+
servicesConfig?.serverUrl
|
|
6094
|
+
);
|
|
6125
6095
|
const requestBody = {
|
|
6126
6096
|
infile: config.options,
|
|
6127
6097
|
type: "png",
|
|
6128
6098
|
b64: true,
|
|
6129
6099
|
scale: config.scale
|
|
6130
6100
|
};
|
|
6101
|
+
const headers = {
|
|
6102
|
+
"Content-Type": "application/json",
|
|
6103
|
+
...servicesConfig?.headers
|
|
6104
|
+
};
|
|
6131
6105
|
const response = await fetch(`${serverUrl}/export`, {
|
|
6132
6106
|
method: "POST",
|
|
6133
|
-
headers
|
|
6134
|
-
"Content-Type": "application/json"
|
|
6135
|
-
},
|
|
6107
|
+
headers,
|
|
6136
6108
|
body: JSON.stringify(requestBody)
|
|
6137
6109
|
}).catch((error) => {
|
|
6138
6110
|
throw new Error(
|
|
@@ -6155,16 +6127,20 @@ Cause: ${error instanceof Error ? error.message : String(error)}`
|
|
|
6155
6127
|
height
|
|
6156
6128
|
};
|
|
6157
6129
|
}
|
|
6158
|
-
async function renderHighchartsComponent(component, theme,
|
|
6130
|
+
async function renderHighchartsComponent(component, theme, themeName, context) {
|
|
6159
6131
|
if (!isHighchartsComponent(component)) return [];
|
|
6160
6132
|
const config = component.props;
|
|
6161
|
-
const chartResult = await generateChart(
|
|
6133
|
+
const chartResult = await generateChart(
|
|
6134
|
+
config,
|
|
6135
|
+
context?.services?.highcharts
|
|
6136
|
+
);
|
|
6162
6137
|
const hasConfigDimensions = config.width !== void 0 || config.height !== void 0;
|
|
6163
6138
|
const renderWidth = hasConfigDimensions ? config.width : chartResult.width;
|
|
6164
6139
|
const renderHeight = hasConfigDimensions ? config.height : chartResult.height;
|
|
6165
6140
|
const imageParagraphs = await createImage(
|
|
6166
6141
|
chartResult.base64DataUri,
|
|
6167
6142
|
theme,
|
|
6143
|
+
themeName,
|
|
6168
6144
|
{
|
|
6169
6145
|
width: renderWidth,
|
|
6170
6146
|
height: renderHeight,
|
|
@@ -6227,16 +6203,16 @@ var textSpaceAfterComponent = createComponent({
|
|
|
6227
6203
|
|
|
6228
6204
|
// src/core/render.ts
|
|
6229
6205
|
init_docxImagePositioning();
|
|
6230
|
-
function
|
|
6206
|
+
function getAlignment3(alignment) {
|
|
6231
6207
|
switch (alignment) {
|
|
6232
6208
|
case "center":
|
|
6233
|
-
return
|
|
6209
|
+
return AlignmentType5.CENTER;
|
|
6234
6210
|
case "right":
|
|
6235
|
-
return
|
|
6211
|
+
return AlignmentType5.RIGHT;
|
|
6236
6212
|
case "justify":
|
|
6237
|
-
return
|
|
6213
|
+
return AlignmentType5.JUSTIFIED;
|
|
6238
6214
|
default:
|
|
6239
|
-
return
|
|
6215
|
+
return AlignmentType5.LEFT;
|
|
6240
6216
|
}
|
|
6241
6217
|
}
|
|
6242
6218
|
async function renderDocument(structure, layout, options) {
|
|
@@ -6253,6 +6229,7 @@ async function renderDocument(structure, layout, options) {
|
|
|
6253
6229
|
structure.theme,
|
|
6254
6230
|
structure.themeName
|
|
6255
6231
|
);
|
|
6232
|
+
context.services = options?.services;
|
|
6256
6233
|
let sectionBookmarkCounter = 0;
|
|
6257
6234
|
let previousHeader = void 0;
|
|
6258
6235
|
let previousFooter = void 0;
|
|
@@ -6327,7 +6304,7 @@ async function renderDocument(structure, layout, options) {
|
|
|
6327
6304
|
}
|
|
6328
6305
|
});
|
|
6329
6306
|
}
|
|
6330
|
-
async function renderHeaderFooterComponents(components, theme,
|
|
6307
|
+
async function renderHeaderFooterComponents(components, theme, themeName, _context) {
|
|
6331
6308
|
if (!components || components.length === 0) {
|
|
6332
6309
|
return [];
|
|
6333
6310
|
}
|
|
@@ -6349,9 +6326,9 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6349
6326
|
};
|
|
6350
6327
|
const textRuns = parseTextWithDecorators(textComp.props.text, textStyle);
|
|
6351
6328
|
elements.push(
|
|
6352
|
-
new
|
|
6329
|
+
new Paragraph7({
|
|
6353
6330
|
children: textRuns,
|
|
6354
|
-
alignment: textComp.props.alignment ?
|
|
6331
|
+
alignment: textComp.props.alignment ? getAlignment3(textComp.props.alignment) : void 0,
|
|
6355
6332
|
style: "Normal"
|
|
6356
6333
|
})
|
|
6357
6334
|
);
|
|
@@ -6360,9 +6337,9 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6360
6337
|
let imageSource = imageComp.props.base64 || imageComp.props.path;
|
|
6361
6338
|
if (!imageSource) {
|
|
6362
6339
|
elements.push(
|
|
6363
|
-
new
|
|
6340
|
+
new Paragraph7({
|
|
6364
6341
|
children: [
|
|
6365
|
-
new
|
|
6342
|
+
new TextRun5({
|
|
6366
6343
|
text: "[IMAGE: Missing path or base64 property]",
|
|
6367
6344
|
font: getThemeFonts(theme).body.family,
|
|
6368
6345
|
size: 20,
|
|
@@ -6370,15 +6347,18 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6370
6347
|
color: "#FF0000"
|
|
6371
6348
|
})
|
|
6372
6349
|
],
|
|
6373
|
-
alignment: imageComp.props.alignment ?
|
|
6350
|
+
alignment: imageComp.props.alignment ? getAlignment3(imageComp.props.alignment) : void 0,
|
|
6374
6351
|
style: "Normal"
|
|
6375
6352
|
})
|
|
6376
6353
|
);
|
|
6377
6354
|
continue;
|
|
6378
6355
|
}
|
|
6379
6356
|
let imageBuffer;
|
|
6357
|
+
let responseContentType;
|
|
6380
6358
|
try {
|
|
6381
|
-
|
|
6359
|
+
const imageResult = await getImageBuffer(imageSource);
|
|
6360
|
+
imageBuffer = imageResult.buffer;
|
|
6361
|
+
responseContentType = imageResult.contentType;
|
|
6382
6362
|
} catch (error) {
|
|
6383
6363
|
throw new Error(
|
|
6384
6364
|
`Failed to load image from ${imageSource.substring(0, 50)}`
|
|
@@ -6411,9 +6391,14 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6411
6391
|
referenceWidthPx,
|
|
6412
6392
|
fallbackHeight
|
|
6413
6393
|
);
|
|
6414
|
-
const floatingOptions = mapFloatingOptions(
|
|
6415
|
-
|
|
6416
|
-
|
|
6394
|
+
const floatingOptions = mapFloatingOptions(
|
|
6395
|
+
imageComp.props.floating,
|
|
6396
|
+
theme,
|
|
6397
|
+
themeName
|
|
6398
|
+
);
|
|
6399
|
+
const imageType = detectImageType(imageSource, responseContentType);
|
|
6400
|
+
const imageRun = createTypedImageRun({
|
|
6401
|
+
type: imageType,
|
|
6417
6402
|
data: imageBuffer,
|
|
6418
6403
|
transformation: {
|
|
6419
6404
|
width: dimensions.width,
|
|
@@ -6422,9 +6407,9 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6422
6407
|
...floatingOptions && { floating: floatingOptions }
|
|
6423
6408
|
});
|
|
6424
6409
|
elements.push(
|
|
6425
|
-
new
|
|
6410
|
+
new Paragraph7({
|
|
6426
6411
|
children: [imageRun],
|
|
6427
|
-
alignment: imageComp.props.alignment ?
|
|
6412
|
+
alignment: imageComp.props.alignment ? getAlignment3(imageComp.props.alignment) : void 0,
|
|
6428
6413
|
style: "Normal"
|
|
6429
6414
|
})
|
|
6430
6415
|
);
|
|
@@ -6434,9 +6419,9 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6434
6419
|
error instanceof Error ? error.message : error
|
|
6435
6420
|
);
|
|
6436
6421
|
elements.push(
|
|
6437
|
-
new
|
|
6422
|
+
new Paragraph7({
|
|
6438
6423
|
children: [
|
|
6439
|
-
new
|
|
6424
|
+
new TextRun5({
|
|
6440
6425
|
text: `[IMAGE: ${imageComp.props.path}]`,
|
|
6441
6426
|
font: getThemeFonts(theme).body.family,
|
|
6442
6427
|
size: 20,
|
|
@@ -6449,7 +6434,7 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6449
6434
|
);
|
|
6450
6435
|
}
|
|
6451
6436
|
} else if (isTableComponent(component)) {
|
|
6452
|
-
const tables = await renderTableComponent(component, theme,
|
|
6437
|
+
const tables = await renderTableComponent(component, theme, themeName);
|
|
6453
6438
|
elements.push(...tables);
|
|
6454
6439
|
}
|
|
6455
6440
|
}
|
|
@@ -6474,7 +6459,7 @@ async function renderSection(section, theme, themeName, context, sectionOrdinal,
|
|
|
6474
6459
|
};
|
|
6475
6460
|
if (sectionBookmarkId && isFirstLayoutOfUserSection && sharedLinkId !== void 0) {
|
|
6476
6461
|
elements.push(
|
|
6477
|
-
new
|
|
6462
|
+
new Paragraph7({
|
|
6478
6463
|
children: [new BookmarkStart2(sectionBookmarkId, sharedLinkId)],
|
|
6479
6464
|
spacing: {
|
|
6480
6465
|
before: 0,
|
|
@@ -6500,7 +6485,7 @@ async function renderSection(section, theme, themeName, context, sectionOrdinal,
|
|
|
6500
6485
|
}
|
|
6501
6486
|
if (closeBookmark && sharedLinkId !== void 0) {
|
|
6502
6487
|
elements.push(
|
|
6503
|
-
new
|
|
6488
|
+
new Paragraph7({
|
|
6504
6489
|
children: [new BookmarkEnd2(sharedLinkId)]
|
|
6505
6490
|
})
|
|
6506
6491
|
);
|
|
@@ -6553,23 +6538,24 @@ async function renderComponent(component, theme, themeName, context) {
|
|
|
6553
6538
|
} else if (isColumnsComponent(component)) {
|
|
6554
6539
|
return await renderColumnsComponent(component, theme, themeName, context);
|
|
6555
6540
|
} else if (isImageComponent(component)) {
|
|
6556
|
-
return await renderImageComponent(component, theme);
|
|
6541
|
+
return await renderImageComponent(component, theme, themeName);
|
|
6557
6542
|
} else if (isTextBoxComponent(component)) {
|
|
6558
6543
|
return await renderTextBoxComponent(component, theme, themeName, context);
|
|
6559
6544
|
} else if (isStatisticComponent(component)) {
|
|
6560
6545
|
return renderStatisticComponent(component, theme);
|
|
6561
6546
|
} else if (isTableComponent(component)) {
|
|
6562
6547
|
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
6548
|
} else if (isListComponent(component)) {
|
|
6568
6549
|
return renderListComponent(component, theme, themeName);
|
|
6569
6550
|
} else if (isTocComponent(component)) {
|
|
6570
6551
|
return renderTocComponent(component, theme, context);
|
|
6571
6552
|
} else if (isHighchartsComponent(component)) {
|
|
6572
|
-
return await renderHighchartsComponent(
|
|
6553
|
+
return await renderHighchartsComponent(
|
|
6554
|
+
component,
|
|
6555
|
+
theme,
|
|
6556
|
+
themeName,
|
|
6557
|
+
context
|
|
6558
|
+
);
|
|
6573
6559
|
} else if (isSectionComponent(component)) {
|
|
6574
6560
|
return await renderSectionComponent(component, theme, themeName, context);
|
|
6575
6561
|
}
|
|
@@ -6762,7 +6748,7 @@ async function generateFromConfig(props, components) {
|
|
|
6762
6748
|
};
|
|
6763
6749
|
return await generateDocument(reportComponent);
|
|
6764
6750
|
}
|
|
6765
|
-
async function generateDocumentWithCustomThemes(document, customThemes) {
|
|
6751
|
+
async function generateDocumentWithCustomThemes(document, customThemes, services) {
|
|
6766
6752
|
const themeName = document.props.theme || "minimal";
|
|
6767
6753
|
let theme;
|
|
6768
6754
|
if (customThemes) {
|
|
@@ -6785,8 +6771,8 @@ async function generateDocumentWithCustomThemes(document, customThemes) {
|
|
|
6785
6771
|
const structure = await processDocument(document, theme, themeName);
|
|
6786
6772
|
const layout = applyLayout(structure.sections, theme, themeName);
|
|
6787
6773
|
const renderedDocument = await renderDocument(structure, layout, {
|
|
6788
|
-
bypassCache: false
|
|
6789
|
-
|
|
6774
|
+
bypassCache: false,
|
|
6775
|
+
services
|
|
6790
6776
|
});
|
|
6791
6777
|
return renderedDocument;
|
|
6792
6778
|
}
|
|
@@ -6804,7 +6790,8 @@ async function generateDocumentFromJson(jsonConfig, options) {
|
|
|
6804
6790
|
const [reportComponent] = normalizeDocument(componentToConvert);
|
|
6805
6791
|
return await generateDocumentWithCustomThemes(
|
|
6806
6792
|
reportComponent,
|
|
6807
|
-
options?.customThemes
|
|
6793
|
+
options?.customThemes,
|
|
6794
|
+
options?.services
|
|
6808
6795
|
);
|
|
6809
6796
|
}
|
|
6810
6797
|
function validateJsonSchema(jsonConfig) {
|
|
@@ -7434,7 +7421,8 @@ function createBuilderImpl(state) {
|
|
|
7434
7421
|
theme: state.theme,
|
|
7435
7422
|
customThemes: state.customThemes,
|
|
7436
7423
|
debug: state.debug,
|
|
7437
|
-
enableCache: state.enableCache
|
|
7424
|
+
enableCache: state.enableCache,
|
|
7425
|
+
services: state.services
|
|
7438
7426
|
};
|
|
7439
7427
|
return createBuilderImpl(
|
|
7440
7428
|
newState
|
|
@@ -7466,7 +7454,9 @@ function createBuilderImpl(state) {
|
|
|
7466
7454
|
themeName
|
|
7467
7455
|
);
|
|
7468
7456
|
const layout = applyLayout(structure.sections, docTheme, themeName);
|
|
7469
|
-
const generatedDocument = await renderDocument(structure, layout
|
|
7457
|
+
const generatedDocument = await renderDocument(structure, layout, {
|
|
7458
|
+
services: state.services
|
|
7459
|
+
});
|
|
7470
7460
|
return {
|
|
7471
7461
|
document: generatedDocument,
|
|
7472
7462
|
warnings: warnings.length > 0 ? warnings : null
|
|
@@ -7581,7 +7571,8 @@ function createDocumentGenerator(options) {
|
|
|
7581
7571
|
theme: options.theme,
|
|
7582
7572
|
customThemes: options.customThemes,
|
|
7583
7573
|
debug: options.debug ?? false,
|
|
7584
|
-
enableCache: options.enableCache ?? false
|
|
7574
|
+
enableCache: options.enableCache ?? false,
|
|
7575
|
+
services: options.services
|
|
7585
7576
|
};
|
|
7586
7577
|
return createBuilderImpl(initialState);
|
|
7587
7578
|
}
|
|
@@ -7638,8 +7629,6 @@ export {
|
|
|
7638
7629
|
hasNodeBuiltins,
|
|
7639
7630
|
initializeComponentCache,
|
|
7640
7631
|
isColumnsComponent,
|
|
7641
|
-
isFooterComponent,
|
|
7642
|
-
isHeaderComponent,
|
|
7643
7632
|
isHeadingComponent,
|
|
7644
7633
|
isHighchartsComponent,
|
|
7645
7634
|
isImageComponent,
|