@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
|
@@ -828,7 +828,7 @@ function convertLineSpacing(lineSpacing) {
|
|
|
828
828
|
}
|
|
829
829
|
return { line, lineRule };
|
|
830
830
|
}
|
|
831
|
-
var TWIPS_PER_POINT, SINGLE_LINE_SPACING_POINTS, SINGLE_LINE_SPACING_TWIPS, DOUBLE_LINE_SPACING_TWIPS
|
|
831
|
+
var TWIPS_PER_POINT, SINGLE_LINE_SPACING_POINTS, SINGLE_LINE_SPACING_TWIPS, DOUBLE_LINE_SPACING_TWIPS;
|
|
832
832
|
var init_styleHelpers = __esm({
|
|
833
833
|
"src/styles/utils/styleHelpers.ts"() {
|
|
834
834
|
"use strict";
|
|
@@ -839,22 +839,6 @@ var init_styleHelpers = __esm({
|
|
|
839
839
|
SINGLE_LINE_SPACING_POINTS = 12;
|
|
840
840
|
SINGLE_LINE_SPACING_TWIPS = SINGLE_LINE_SPACING_POINTS * TWIPS_PER_POINT;
|
|
841
841
|
DOUBLE_LINE_SPACING_TWIPS = SINGLE_LINE_SPACING_TWIPS * 2;
|
|
842
|
-
getBodyTextStyle = (theme, themeName) => {
|
|
843
|
-
const themeConfig = resolveTheme(theme, themeName);
|
|
844
|
-
if (themeConfig) {
|
|
845
|
-
const normalStyle = getNormalStyle(themeConfig);
|
|
846
|
-
return {
|
|
847
|
-
size: (normalStyle.size || 11) * 2,
|
|
848
|
-
font: resolveFontFamily(themeConfig, normalStyle.font),
|
|
849
|
-
color: normalStyle.color ? resolveColor(normalStyle.color, themeConfig) : "000000"
|
|
850
|
-
};
|
|
851
|
-
}
|
|
852
|
-
return {
|
|
853
|
-
size: 20,
|
|
854
|
-
font: "Arial",
|
|
855
|
-
color: "000000"
|
|
856
|
-
};
|
|
857
|
-
};
|
|
858
842
|
}
|
|
859
843
|
});
|
|
860
844
|
|
|
@@ -1347,7 +1331,8 @@ __export(widthUtils_exports, {
|
|
|
1347
1331
|
getPageHeightTwips: () => getPageHeightTwips,
|
|
1348
1332
|
getPageWidthTwips: () => getPageWidthTwips,
|
|
1349
1333
|
parsePercentageStringToFraction: () => parsePercentageStringToFraction,
|
|
1350
|
-
relativeLengthToTwips: () => relativeLengthToTwips
|
|
1334
|
+
relativeLengthToTwips: () => relativeLengthToTwips,
|
|
1335
|
+
resolveOffsetTwips: () => resolveOffsetTwips
|
|
1351
1336
|
});
|
|
1352
1337
|
function getAvailableWidthTwips(theme, themeName) {
|
|
1353
1338
|
const page = getPageSetup(theme, themeName);
|
|
@@ -1378,6 +1363,17 @@ function parsePercentageStringToFraction(value) {
|
|
|
1378
1363
|
if (pct < 0 || pct > 100) return void 0;
|
|
1379
1364
|
return pct / 100;
|
|
1380
1365
|
}
|
|
1366
|
+
function resolveOffsetTwips(value, referenceTwips) {
|
|
1367
|
+
if (typeof value === "number") return value;
|
|
1368
|
+
const match = /^([0-9]+(?:\.[0-9]+)?)%$/.exec(value);
|
|
1369
|
+
if (!match) {
|
|
1370
|
+
console.warn(
|
|
1371
|
+
`resolveOffsetTwips: invalid percentage string "${value}", defaulting to 0`
|
|
1372
|
+
);
|
|
1373
|
+
return 0;
|
|
1374
|
+
}
|
|
1375
|
+
return Math.round(referenceTwips * parseFloat(match[1]) / 100);
|
|
1376
|
+
}
|
|
1381
1377
|
function relativeLengthToTwips(value, availableWidthTwips) {
|
|
1382
1378
|
if (typeof value === "number") {
|
|
1383
1379
|
return pointsToTwips(value);
|
|
@@ -1394,240 +1390,6 @@ var init_widthUtils = __esm({
|
|
|
1394
1390
|
}
|
|
1395
1391
|
});
|
|
1396
1392
|
|
|
1397
|
-
// src/utils/imageUtils.ts
|
|
1398
|
-
var imageUtils_exports = {};
|
|
1399
|
-
__export(imageUtils_exports, {
|
|
1400
|
-
calculateImageDimensions: () => calculateImageDimensions,
|
|
1401
|
-
calculateMissingDimension: () => calculateMissingDimension,
|
|
1402
|
-
decodeBase64Image: () => decodeBase64Image,
|
|
1403
|
-
detectImageType: () => detectImageType,
|
|
1404
|
-
detectImageTypeFromExtension: () => detectImageTypeFromExtension,
|
|
1405
|
-
detectImageTypeFromMimeType: () => detectImageTypeFromMimeType,
|
|
1406
|
-
downloadImageFromUrl: () => downloadImageFromUrl,
|
|
1407
|
-
extractMimeTypeFromDataUri: () => extractMimeTypeFromDataUri,
|
|
1408
|
-
getImageBuffer: () => getImageBuffer,
|
|
1409
|
-
getImageDimensions: () => getImageDimensions,
|
|
1410
|
-
isBase64Image: () => isBase64Image,
|
|
1411
|
-
isValidUrl: () => isValidUrl,
|
|
1412
|
-
parseDimensionValue: () => parseDimensionValue,
|
|
1413
|
-
parseWidthValue: () => parseWidthValue
|
|
1414
|
-
});
|
|
1415
|
-
import { readFileSync } from "fs";
|
|
1416
|
-
import probe from "probe-image-size";
|
|
1417
|
-
function parseWidthValue(width, availableWidthPx) {
|
|
1418
|
-
if (typeof width === "number") {
|
|
1419
|
-
return width;
|
|
1420
|
-
}
|
|
1421
|
-
const percentageMatch = width.match(/^(\d+(?:\.\d+)?)%$/);
|
|
1422
|
-
if (percentageMatch) {
|
|
1423
|
-
const pct = parseFloat(percentageMatch[1]);
|
|
1424
|
-
if (pct < 0 || pct > 100) {
|
|
1425
|
-
throw new Error(
|
|
1426
|
-
`Invalid percentage value: ${width}. Must be between 0% and 100%`
|
|
1427
|
-
);
|
|
1428
|
-
}
|
|
1429
|
-
const fraction = parsePercentageStringToFraction(width);
|
|
1430
|
-
if (fraction !== void 0) {
|
|
1431
|
-
return Math.round(availableWidthPx * fraction);
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
|
-
throw new Error(
|
|
1435
|
-
`Invalid width value: ${width}. Expected number (pixels) or percentage string (e.g., "90%")`
|
|
1436
|
-
);
|
|
1437
|
-
}
|
|
1438
|
-
function parseDimensionValue(value, availablePx) {
|
|
1439
|
-
if (typeof value === "number") return value;
|
|
1440
|
-
const percentageMatch = value.match(/^(\d+(?:\.\d+)?)%$/);
|
|
1441
|
-
if (percentageMatch) {
|
|
1442
|
-
const pct = parseFloat(percentageMatch[1]);
|
|
1443
|
-
if (pct < 0 || pct > 100) {
|
|
1444
|
-
throw new Error(
|
|
1445
|
-
`Invalid percentage value: ${value}. Must be between 0% and 100%`
|
|
1446
|
-
);
|
|
1447
|
-
}
|
|
1448
|
-
const fraction = parsePercentageStringToFraction(value);
|
|
1449
|
-
if (fraction !== void 0) return Math.round(availablePx * fraction);
|
|
1450
|
-
}
|
|
1451
|
-
throw new Error(
|
|
1452
|
-
`Invalid dimension value: ${value}. Expected number (pixels) or percentage string (e.g., "90%")`
|
|
1453
|
-
);
|
|
1454
|
-
}
|
|
1455
|
-
function isValidUrl(string) {
|
|
1456
|
-
try {
|
|
1457
|
-
const url = new URL(string);
|
|
1458
|
-
return url.protocol === "http:" || url.protocol === "https:";
|
|
1459
|
-
} catch {
|
|
1460
|
-
return false;
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
function isBase64Image(string) {
|
|
1464
|
-
return /^data:image\/[a-zA-Z+]+;base64,/.test(string);
|
|
1465
|
-
}
|
|
1466
|
-
function decodeBase64Image(dataUri) {
|
|
1467
|
-
try {
|
|
1468
|
-
const base64Data = dataUri.split(",")[1];
|
|
1469
|
-
if (!base64Data) {
|
|
1470
|
-
throw new Error("Invalid base64 data URI format");
|
|
1471
|
-
}
|
|
1472
|
-
return Buffer.from(base64Data, "base64");
|
|
1473
|
-
} catch (error) {
|
|
1474
|
-
throw new Error(
|
|
1475
|
-
`Failed to decode base64 image: ${error instanceof Error ? error.message : String(error)}`
|
|
1476
|
-
);
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
|
-
function extractMimeTypeFromDataUri(dataUri) {
|
|
1480
|
-
const match = dataUri.match(/^data:(image\/[a-zA-Z0-9+.-]+);base64,/);
|
|
1481
|
-
return match ? match[1] : void 0;
|
|
1482
|
-
}
|
|
1483
|
-
function detectImageTypeFromExtension(path3) {
|
|
1484
|
-
const extension = path3.toLowerCase().split(".").pop()?.split("?")[0];
|
|
1485
|
-
switch (extension) {
|
|
1486
|
-
case "jpg":
|
|
1487
|
-
case "jpeg":
|
|
1488
|
-
return "jpg";
|
|
1489
|
-
case "png":
|
|
1490
|
-
return "png";
|
|
1491
|
-
case "gif":
|
|
1492
|
-
return "gif";
|
|
1493
|
-
case "bmp":
|
|
1494
|
-
return "bmp";
|
|
1495
|
-
case "svg":
|
|
1496
|
-
return "svg";
|
|
1497
|
-
default:
|
|
1498
|
-
return void 0;
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1501
|
-
function detectImageTypeFromMimeType(mimeType) {
|
|
1502
|
-
const normalized = mimeType.toLowerCase();
|
|
1503
|
-
if (normalized.includes("svg")) return "svg";
|
|
1504
|
-
if (normalized.includes("jpeg") || normalized.includes("jpg")) return "jpg";
|
|
1505
|
-
if (normalized.includes("png")) return "png";
|
|
1506
|
-
if (normalized.includes("gif")) return "gif";
|
|
1507
|
-
if (normalized.includes("bmp")) return "bmp";
|
|
1508
|
-
return void 0;
|
|
1509
|
-
}
|
|
1510
|
-
function detectImageType(imagePath) {
|
|
1511
|
-
if (isBase64Image(imagePath)) {
|
|
1512
|
-
const mimeType = extractMimeTypeFromDataUri(imagePath);
|
|
1513
|
-
if (mimeType) {
|
|
1514
|
-
const typeFromMime = detectImageTypeFromMimeType(mimeType);
|
|
1515
|
-
if (typeFromMime) return typeFromMime;
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
const typeFromExtension = detectImageTypeFromExtension(imagePath);
|
|
1519
|
-
if (typeFromExtension) return typeFromExtension;
|
|
1520
|
-
return "png";
|
|
1521
|
-
}
|
|
1522
|
-
async function downloadImageFromUrl(url) {
|
|
1523
|
-
try {
|
|
1524
|
-
const controller = new AbortController();
|
|
1525
|
-
const timeoutId = setTimeout(() => controller.abort(), 1e4);
|
|
1526
|
-
const response = await fetch(url, {
|
|
1527
|
-
signal: controller.signal,
|
|
1528
|
-
headers: {
|
|
1529
|
-
"User-Agent": "Mozilla/5.0 (compatible; json-to-docx/1.0)"
|
|
1530
|
-
},
|
|
1531
|
-
redirect: "follow"
|
|
1532
|
-
// Automatically follow redirects (default behavior)
|
|
1533
|
-
});
|
|
1534
|
-
clearTimeout(timeoutId);
|
|
1535
|
-
if (!response.ok) {
|
|
1536
|
-
throw new Error(
|
|
1537
|
-
`Failed to download image: HTTP ${response.status} ${response.statusText}`
|
|
1538
|
-
);
|
|
1539
|
-
}
|
|
1540
|
-
const arrayBuffer = await response.arrayBuffer();
|
|
1541
|
-
return Buffer.from(arrayBuffer);
|
|
1542
|
-
} catch (error) {
|
|
1543
|
-
if (error instanceof Error) {
|
|
1544
|
-
if (error.name === "AbortError") {
|
|
1545
|
-
throw new Error(
|
|
1546
|
-
"Failed to download image: Request timeout after 10 seconds"
|
|
1547
|
-
);
|
|
1548
|
-
}
|
|
1549
|
-
throw new Error(`Failed to download image from ${url}: ${error.message}`);
|
|
1550
|
-
}
|
|
1551
|
-
throw new Error(`Failed to download image from ${url}: Unknown error`);
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
async function getImageBuffer(imagePath) {
|
|
1555
|
-
if (isBase64Image(imagePath)) {
|
|
1556
|
-
return decodeBase64Image(imagePath);
|
|
1557
|
-
}
|
|
1558
|
-
if (isValidUrl(imagePath)) {
|
|
1559
|
-
return await downloadImageFromUrl(imagePath);
|
|
1560
|
-
}
|
|
1561
|
-
return readFileSync(imagePath);
|
|
1562
|
-
}
|
|
1563
|
-
async function getImageDimensions(imagePath) {
|
|
1564
|
-
try {
|
|
1565
|
-
const imageBuffer = await getImageBuffer(imagePath);
|
|
1566
|
-
const result = probe.sync(imageBuffer);
|
|
1567
|
-
if (!result) {
|
|
1568
|
-
throw new Error(`Unable to determine dimensions for image: ${imagePath}`);
|
|
1569
|
-
}
|
|
1570
|
-
return {
|
|
1571
|
-
width: result.width,
|
|
1572
|
-
height: result.height
|
|
1573
|
-
};
|
|
1574
|
-
} catch (error) {
|
|
1575
|
-
throw new Error(
|
|
1576
|
-
`Error reading image dimensions from ${imagePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
1577
|
-
);
|
|
1578
|
-
}
|
|
1579
|
-
}
|
|
1580
|
-
function calculateMissingDimension(originalWidth, originalHeight, targetWidth, targetHeight) {
|
|
1581
|
-
if (targetWidth && targetHeight) {
|
|
1582
|
-
return { width: targetWidth, height: targetHeight };
|
|
1583
|
-
}
|
|
1584
|
-
const aspectRatio = originalWidth / originalHeight;
|
|
1585
|
-
if (targetWidth && !targetHeight) {
|
|
1586
|
-
return {
|
|
1587
|
-
width: targetWidth,
|
|
1588
|
-
height: Math.round(targetWidth / aspectRatio)
|
|
1589
|
-
};
|
|
1590
|
-
}
|
|
1591
|
-
if (!targetWidth && targetHeight) {
|
|
1592
|
-
return {
|
|
1593
|
-
width: Math.round(targetHeight * aspectRatio),
|
|
1594
|
-
height: targetHeight
|
|
1595
|
-
};
|
|
1596
|
-
}
|
|
1597
|
-
return { width: originalWidth, height: originalHeight };
|
|
1598
|
-
}
|
|
1599
|
-
async function calculateImageDimensions(imagePath, targetWidth, targetHeight, fallbackWidth = 300, fallbackHeight = 180) {
|
|
1600
|
-
try {
|
|
1601
|
-
const originalDimensions = await getImageDimensions(imagePath);
|
|
1602
|
-
return calculateMissingDimension(
|
|
1603
|
-
originalDimensions.width,
|
|
1604
|
-
originalDimensions.height,
|
|
1605
|
-
targetWidth,
|
|
1606
|
-
targetHeight
|
|
1607
|
-
);
|
|
1608
|
-
} catch (error) {
|
|
1609
|
-
if (targetWidth && targetHeight) {
|
|
1610
|
-
return { width: targetWidth, height: targetHeight };
|
|
1611
|
-
}
|
|
1612
|
-
if (targetWidth && !targetHeight) {
|
|
1613
|
-
return { width: targetWidth, height: Math.round(targetWidth * 9 / 16) };
|
|
1614
|
-
}
|
|
1615
|
-
if (!targetWidth && targetHeight) {
|
|
1616
|
-
return {
|
|
1617
|
-
width: Math.round(targetHeight * 16 / 9),
|
|
1618
|
-
height: targetHeight
|
|
1619
|
-
};
|
|
1620
|
-
}
|
|
1621
|
-
return { width: fallbackWidth, height: fallbackHeight };
|
|
1622
|
-
}
|
|
1623
|
-
}
|
|
1624
|
-
var init_imageUtils = __esm({
|
|
1625
|
-
"src/utils/imageUtils.ts"() {
|
|
1626
|
-
"use strict";
|
|
1627
|
-
init_widthUtils();
|
|
1628
|
-
}
|
|
1629
|
-
});
|
|
1630
|
-
|
|
1631
1393
|
// src/utils/docxImagePositioning.ts
|
|
1632
1394
|
var docxImagePositioning_exports = {};
|
|
1633
1395
|
__export(docxImagePositioning_exports, {
|
|
@@ -1736,13 +1498,17 @@ function mapWrapSide(side) {
|
|
|
1736
1498
|
return void 0;
|
|
1737
1499
|
}
|
|
1738
1500
|
}
|
|
1739
|
-
function mapFloatingOptions(floating) {
|
|
1501
|
+
function mapFloatingOptions(floating, theme, themeName) {
|
|
1740
1502
|
if (!floating) return void 0;
|
|
1741
1503
|
if (floating.wrap?.type === "tight") {
|
|
1742
1504
|
throw new Error(
|
|
1743
1505
|
"Image floating wrap.type 'tight' is not supported due to invalid OOXML emitted by docx. Use 'square', 'topAndBottom', or 'none'."
|
|
1744
1506
|
);
|
|
1745
1507
|
}
|
|
1508
|
+
const hRelative = floating.horizontalPosition?.relative;
|
|
1509
|
+
const vRelative = floating.verticalPosition?.relative;
|
|
1510
|
+
const hRef = hRelative && hRelative !== "page" ? getAvailableWidthTwips(theme, themeName) : getPageWidthTwips(theme, themeName);
|
|
1511
|
+
const vRef = vRelative && vRelative !== "page" ? getAvailableHeightTwips(theme, themeName) : getPageHeightTwips(theme, themeName);
|
|
1746
1512
|
const hasHorizontal = Boolean(floating.horizontalPosition);
|
|
1747
1513
|
const hasVertical = Boolean(floating.verticalPosition);
|
|
1748
1514
|
const horizontalPosition = floating.horizontalPosition ? {
|
|
@@ -1753,7 +1519,7 @@ function mapFloatingOptions(floating) {
|
|
|
1753
1519
|
align: mapHorizontalAlign(floating.horizontalPosition.align)
|
|
1754
1520
|
},
|
|
1755
1521
|
...floating.horizontalPosition.offset !== void 0 && {
|
|
1756
|
-
offset: floating.horizontalPosition.offset * TWIPS_TO_EMU
|
|
1522
|
+
offset: resolveOffsetTwips(floating.horizontalPosition.offset, hRef) * TWIPS_TO_EMU
|
|
1757
1523
|
}
|
|
1758
1524
|
} : hasVertical ? {
|
|
1759
1525
|
// Default horizontal: align left relative to margin
|
|
@@ -1768,7 +1534,7 @@ function mapFloatingOptions(floating) {
|
|
|
1768
1534
|
align: mapVerticalAlign(floating.verticalPosition.align)
|
|
1769
1535
|
},
|
|
1770
1536
|
...floating.verticalPosition.offset !== void 0 && {
|
|
1771
|
-
offset: floating.verticalPosition.offset * TWIPS_TO_EMU
|
|
1537
|
+
offset: resolveOffsetTwips(floating.verticalPosition.offset, vRef) * TWIPS_TO_EMU
|
|
1772
1538
|
}
|
|
1773
1539
|
} : hasHorizontal ? {
|
|
1774
1540
|
// Default vertical: align top relative to paragraph
|
|
@@ -1779,19 +1545,21 @@ function mapFloatingOptions(floating) {
|
|
|
1779
1545
|
...floating.wrap.type && { type: mapWrapType(floating.wrap.type) },
|
|
1780
1546
|
...floating.wrap.side && { side: mapWrapSide(floating.wrap.side) }
|
|
1781
1547
|
} : void 0;
|
|
1548
|
+
const pageW = getPageWidthTwips(theme, themeName);
|
|
1549
|
+
const pageH = getPageHeightTwips(theme, themeName);
|
|
1782
1550
|
const rawMargins = floating.wrap?.margins || floating.margins;
|
|
1783
1551
|
const margins = rawMargins ? {
|
|
1784
1552
|
...rawMargins.top !== void 0 && {
|
|
1785
|
-
top: rawMargins.top * TWIPS_TO_EMU
|
|
1553
|
+
top: resolveOffsetTwips(rawMargins.top, pageH) * TWIPS_TO_EMU
|
|
1786
1554
|
},
|
|
1787
1555
|
...rawMargins.bottom !== void 0 && {
|
|
1788
|
-
bottom: rawMargins.bottom * TWIPS_TO_EMU
|
|
1556
|
+
bottom: resolveOffsetTwips(rawMargins.bottom, pageH) * TWIPS_TO_EMU
|
|
1789
1557
|
},
|
|
1790
1558
|
...rawMargins.left !== void 0 && {
|
|
1791
|
-
left: rawMargins.left * TWIPS_TO_EMU
|
|
1559
|
+
left: resolveOffsetTwips(rawMargins.left, pageW) * TWIPS_TO_EMU
|
|
1792
1560
|
},
|
|
1793
1561
|
...rawMargins.right !== void 0 && {
|
|
1794
|
-
right: rawMargins.right * TWIPS_TO_EMU
|
|
1562
|
+
right: resolveOffsetTwips(rawMargins.right, pageW) * TWIPS_TO_EMU
|
|
1795
1563
|
}
|
|
1796
1564
|
} : void 0;
|
|
1797
1565
|
let zIndex = floating.zIndex !== void 0 ? floating.zIndex : 0;
|
|
@@ -1827,6 +1595,7 @@ var TWIPS_TO_EMU;
|
|
|
1827
1595
|
var init_docxImagePositioning = __esm({
|
|
1828
1596
|
"src/utils/docxImagePositioning.ts"() {
|
|
1829
1597
|
"use strict";
|
|
1598
|
+
init_widthUtils();
|
|
1830
1599
|
TWIPS_TO_EMU = 635;
|
|
1831
1600
|
}
|
|
1832
1601
|
});
|
|
@@ -2191,8 +1960,6 @@ import {
|
|
|
2191
1960
|
isTableComponent,
|
|
2192
1961
|
isListComponent,
|
|
2193
1962
|
isTocComponent,
|
|
2194
|
-
isHeaderComponent,
|
|
2195
|
-
isFooterComponent,
|
|
2196
1963
|
isHighchartsComponent
|
|
2197
1964
|
} from "@json-to-office/shared-docx";
|
|
2198
1965
|
|
|
@@ -2666,18 +2433,251 @@ Suggestion: ${suggestion}`
|
|
|
2666
2433
|
}
|
|
2667
2434
|
|
|
2668
2435
|
// src/core/render.ts
|
|
2669
|
-
init_imageUtils();
|
|
2670
|
-
init_defaults();
|
|
2671
2436
|
import {
|
|
2672
2437
|
Document,
|
|
2673
|
-
Paragraph as
|
|
2674
|
-
TextRun as
|
|
2675
|
-
|
|
2676
|
-
AlignmentType as AlignmentType6,
|
|
2438
|
+
Paragraph as Paragraph7,
|
|
2439
|
+
TextRun as TextRun5,
|
|
2440
|
+
AlignmentType as AlignmentType5,
|
|
2677
2441
|
BookmarkStart as BookmarkStart2,
|
|
2678
2442
|
BookmarkEnd as BookmarkEnd2
|
|
2679
2443
|
} from "docx";
|
|
2680
2444
|
|
|
2445
|
+
// src/utils/imageUtils.ts
|
|
2446
|
+
init_widthUtils();
|
|
2447
|
+
import { readFileSync } from "fs";
|
|
2448
|
+
import probe from "probe-image-size";
|
|
2449
|
+
import { ImageRun } from "docx";
|
|
2450
|
+
function parseWidthValue(width, availableWidthPx) {
|
|
2451
|
+
if (typeof width === "number") {
|
|
2452
|
+
return width;
|
|
2453
|
+
}
|
|
2454
|
+
const percentageMatch = width.match(/^(\d+(?:\.\d+)?)%$/);
|
|
2455
|
+
if (percentageMatch) {
|
|
2456
|
+
const pct = parseFloat(percentageMatch[1]);
|
|
2457
|
+
if (pct < 0 || pct > 100) {
|
|
2458
|
+
throw new Error(
|
|
2459
|
+
`Invalid percentage value: ${width}. Must be between 0% and 100%`
|
|
2460
|
+
);
|
|
2461
|
+
}
|
|
2462
|
+
const fraction = parsePercentageStringToFraction(width);
|
|
2463
|
+
if (fraction !== void 0) {
|
|
2464
|
+
return Math.round(availableWidthPx * fraction);
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
throw new Error(
|
|
2468
|
+
`Invalid width value: ${width}. Expected number (pixels) or percentage string (e.g., "90%")`
|
|
2469
|
+
);
|
|
2470
|
+
}
|
|
2471
|
+
function parseDimensionValue(value, availablePx) {
|
|
2472
|
+
if (typeof value === "number") return value;
|
|
2473
|
+
const percentageMatch = value.match(/^(\d+(?:\.\d+)?)%$/);
|
|
2474
|
+
if (percentageMatch) {
|
|
2475
|
+
const pct = parseFloat(percentageMatch[1]);
|
|
2476
|
+
if (pct < 0 || pct > 100) {
|
|
2477
|
+
throw new Error(
|
|
2478
|
+
`Invalid percentage value: ${value}. Must be between 0% and 100%`
|
|
2479
|
+
);
|
|
2480
|
+
}
|
|
2481
|
+
const fraction = parsePercentageStringToFraction(value);
|
|
2482
|
+
if (fraction !== void 0) return Math.round(availablePx * fraction);
|
|
2483
|
+
}
|
|
2484
|
+
throw new Error(
|
|
2485
|
+
`Invalid dimension value: ${value}. Expected number (pixels) or percentage string (e.g., "90%")`
|
|
2486
|
+
);
|
|
2487
|
+
}
|
|
2488
|
+
function isValidUrl(string) {
|
|
2489
|
+
try {
|
|
2490
|
+
const url = new URL(string);
|
|
2491
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
2492
|
+
} catch {
|
|
2493
|
+
return false;
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
function isBase64Image(string) {
|
|
2497
|
+
return /^data:image\/[a-zA-Z+]+;base64,/.test(string);
|
|
2498
|
+
}
|
|
2499
|
+
function decodeBase64Image(dataUri) {
|
|
2500
|
+
try {
|
|
2501
|
+
const base64Data = dataUri.split(",")[1];
|
|
2502
|
+
if (!base64Data) {
|
|
2503
|
+
throw new Error("Invalid base64 data URI format");
|
|
2504
|
+
}
|
|
2505
|
+
return Buffer.from(base64Data, "base64");
|
|
2506
|
+
} catch (error) {
|
|
2507
|
+
throw new Error(
|
|
2508
|
+
`Failed to decode base64 image: ${error instanceof Error ? error.message : String(error)}`
|
|
2509
|
+
);
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
function extractMimeTypeFromDataUri(dataUri) {
|
|
2513
|
+
const match = dataUri.match(/^data:(image\/[a-zA-Z0-9+.-]+);base64,/);
|
|
2514
|
+
return match ? match[1] : void 0;
|
|
2515
|
+
}
|
|
2516
|
+
function detectImageTypeFromExtension(path3) {
|
|
2517
|
+
const extension = path3.toLowerCase().split(".").pop()?.split("?")[0];
|
|
2518
|
+
switch (extension) {
|
|
2519
|
+
case "jpg":
|
|
2520
|
+
case "jpeg":
|
|
2521
|
+
return "jpg";
|
|
2522
|
+
case "png":
|
|
2523
|
+
return "png";
|
|
2524
|
+
case "gif":
|
|
2525
|
+
return "gif";
|
|
2526
|
+
case "bmp":
|
|
2527
|
+
return "bmp";
|
|
2528
|
+
case "svg":
|
|
2529
|
+
return "svg";
|
|
2530
|
+
default:
|
|
2531
|
+
return void 0;
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
function detectImageTypeFromMimeType(mimeType) {
|
|
2535
|
+
const normalized = mimeType.toLowerCase();
|
|
2536
|
+
if (normalized.includes("svg")) return "svg";
|
|
2537
|
+
if (normalized.includes("jpeg") || normalized.includes("jpg")) return "jpg";
|
|
2538
|
+
if (normalized.includes("png")) return "png";
|
|
2539
|
+
if (normalized.includes("gif")) return "gif";
|
|
2540
|
+
if (normalized.includes("bmp")) return "bmp";
|
|
2541
|
+
return void 0;
|
|
2542
|
+
}
|
|
2543
|
+
function detectImageType(imagePath, responseContentType) {
|
|
2544
|
+
if (responseContentType) {
|
|
2545
|
+
const typeFromResponse = detectImageTypeFromMimeType(responseContentType);
|
|
2546
|
+
if (typeFromResponse) return typeFromResponse;
|
|
2547
|
+
}
|
|
2548
|
+
if (isBase64Image(imagePath)) {
|
|
2549
|
+
const mimeType = extractMimeTypeFromDataUri(imagePath);
|
|
2550
|
+
if (mimeType) {
|
|
2551
|
+
const typeFromMime = detectImageTypeFromMimeType(mimeType);
|
|
2552
|
+
if (typeFromMime) return typeFromMime;
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
const typeFromExtension = detectImageTypeFromExtension(imagePath);
|
|
2556
|
+
if (typeFromExtension) return typeFromExtension;
|
|
2557
|
+
return "png";
|
|
2558
|
+
}
|
|
2559
|
+
function createTypedImageRun(opts) {
|
|
2560
|
+
const base = {
|
|
2561
|
+
data: opts.data,
|
|
2562
|
+
transformation: opts.transformation,
|
|
2563
|
+
...opts.floating && { floating: opts.floating }
|
|
2564
|
+
};
|
|
2565
|
+
if (opts.type === "svg") {
|
|
2566
|
+
return new ImageRun({
|
|
2567
|
+
type: "svg",
|
|
2568
|
+
...base,
|
|
2569
|
+
fallback: { type: "png", data: opts.data }
|
|
2570
|
+
});
|
|
2571
|
+
}
|
|
2572
|
+
return new ImageRun({ type: opts.type, ...base });
|
|
2573
|
+
}
|
|
2574
|
+
async function downloadImageFromUrl(url) {
|
|
2575
|
+
try {
|
|
2576
|
+
const controller = new AbortController();
|
|
2577
|
+
const timeoutId = setTimeout(() => controller.abort(), 1e4);
|
|
2578
|
+
const response = await fetch(url, {
|
|
2579
|
+
signal: controller.signal,
|
|
2580
|
+
headers: {
|
|
2581
|
+
"User-Agent": "Mozilla/5.0 (compatible; json-to-docx/1.0)"
|
|
2582
|
+
},
|
|
2583
|
+
redirect: "follow"
|
|
2584
|
+
// Automatically follow redirects (default behavior)
|
|
2585
|
+
});
|
|
2586
|
+
clearTimeout(timeoutId);
|
|
2587
|
+
if (!response.ok) {
|
|
2588
|
+
throw new Error(
|
|
2589
|
+
`Failed to download image: HTTP ${response.status} ${response.statusText}`
|
|
2590
|
+
);
|
|
2591
|
+
}
|
|
2592
|
+
const contentType = response.headers.get("content-type") || void 0;
|
|
2593
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
2594
|
+
return { buffer: Buffer.from(arrayBuffer), contentType };
|
|
2595
|
+
} catch (error) {
|
|
2596
|
+
if (error instanceof Error) {
|
|
2597
|
+
if (error.name === "AbortError") {
|
|
2598
|
+
throw new Error(
|
|
2599
|
+
"Failed to download image: Request timeout after 10 seconds"
|
|
2600
|
+
);
|
|
2601
|
+
}
|
|
2602
|
+
throw new Error(`Failed to download image from ${url}: ${error.message}`);
|
|
2603
|
+
}
|
|
2604
|
+
throw new Error(`Failed to download image from ${url}: Unknown error`);
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
async function getImageBuffer(imagePath) {
|
|
2608
|
+
if (isBase64Image(imagePath)) {
|
|
2609
|
+
return { buffer: decodeBase64Image(imagePath) };
|
|
2610
|
+
}
|
|
2611
|
+
if (isValidUrl(imagePath)) {
|
|
2612
|
+
return await downloadImageFromUrl(imagePath);
|
|
2613
|
+
}
|
|
2614
|
+
return { buffer: readFileSync(imagePath) };
|
|
2615
|
+
}
|
|
2616
|
+
async function getImageDimensions(imagePath) {
|
|
2617
|
+
try {
|
|
2618
|
+
const { buffer: imageBuffer } = await getImageBuffer(imagePath);
|
|
2619
|
+
const result = probe.sync(imageBuffer);
|
|
2620
|
+
if (!result) {
|
|
2621
|
+
throw new Error(`Unable to determine dimensions for image: ${imagePath}`);
|
|
2622
|
+
}
|
|
2623
|
+
return {
|
|
2624
|
+
width: result.width,
|
|
2625
|
+
height: result.height
|
|
2626
|
+
};
|
|
2627
|
+
} catch (error) {
|
|
2628
|
+
throw new Error(
|
|
2629
|
+
`Error reading image dimensions from ${imagePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
2630
|
+
);
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
function calculateMissingDimension(originalWidth, originalHeight, targetWidth, targetHeight) {
|
|
2634
|
+
if (targetWidth && targetHeight) {
|
|
2635
|
+
return { width: targetWidth, height: targetHeight };
|
|
2636
|
+
}
|
|
2637
|
+
const aspectRatio = originalWidth / originalHeight;
|
|
2638
|
+
if (targetWidth && !targetHeight) {
|
|
2639
|
+
return {
|
|
2640
|
+
width: targetWidth,
|
|
2641
|
+
height: Math.round(targetWidth / aspectRatio)
|
|
2642
|
+
};
|
|
2643
|
+
}
|
|
2644
|
+
if (!targetWidth && targetHeight) {
|
|
2645
|
+
return {
|
|
2646
|
+
width: Math.round(targetHeight * aspectRatio),
|
|
2647
|
+
height: targetHeight
|
|
2648
|
+
};
|
|
2649
|
+
}
|
|
2650
|
+
return { width: originalWidth, height: originalHeight };
|
|
2651
|
+
}
|
|
2652
|
+
async function calculateImageDimensions(imagePath, targetWidth, targetHeight, fallbackWidth = 300, fallbackHeight = 180) {
|
|
2653
|
+
try {
|
|
2654
|
+
const originalDimensions = await getImageDimensions(imagePath);
|
|
2655
|
+
return calculateMissingDimension(
|
|
2656
|
+
originalDimensions.width,
|
|
2657
|
+
originalDimensions.height,
|
|
2658
|
+
targetWidth,
|
|
2659
|
+
targetHeight
|
|
2660
|
+
);
|
|
2661
|
+
} catch (error) {
|
|
2662
|
+
if (targetWidth && targetHeight) {
|
|
2663
|
+
return { width: targetWidth, height: targetHeight };
|
|
2664
|
+
}
|
|
2665
|
+
if (targetWidth && !targetHeight) {
|
|
2666
|
+
return { width: targetWidth, height: Math.round(targetWidth * 9 / 16) };
|
|
2667
|
+
}
|
|
2668
|
+
if (!targetWidth && targetHeight) {
|
|
2669
|
+
return {
|
|
2670
|
+
width: Math.round(targetHeight * 16 / 9),
|
|
2671
|
+
height: targetHeight
|
|
2672
|
+
};
|
|
2673
|
+
}
|
|
2674
|
+
return { width: fallbackWidth, height: fallbackHeight };
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2678
|
+
// src/core/render.ts
|
|
2679
|
+
init_defaults();
|
|
2680
|
+
|
|
2681
2681
|
// src/styles/themeToDocxAdapter.ts
|
|
2682
2682
|
init_themes();
|
|
2683
2683
|
init_colorUtils();
|
|
@@ -3932,9 +3932,6 @@ function resolveListProps(props, theme) {
|
|
|
3932
3932
|
}
|
|
3933
3933
|
|
|
3934
3934
|
// src/core/content.ts
|
|
3935
|
-
init_imageUtils();
|
|
3936
|
-
init_styles();
|
|
3937
|
-
init_defaults();
|
|
3938
3935
|
import {
|
|
3939
3936
|
Paragraph,
|
|
3940
3937
|
TextRun as TextRun3,
|
|
@@ -3942,7 +3939,6 @@ import {
|
|
|
3942
3939
|
TableRow,
|
|
3943
3940
|
TableCell,
|
|
3944
3941
|
AlignmentType as AlignmentType2,
|
|
3945
|
-
ImageRun,
|
|
3946
3942
|
PageBreak,
|
|
3947
3943
|
WidthType,
|
|
3948
3944
|
BorderStyle as BorderStyle2,
|
|
@@ -3954,6 +3950,8 @@ import {
|
|
|
3954
3950
|
VerticalAlign,
|
|
3955
3951
|
Bookmark
|
|
3956
3952
|
} from "docx";
|
|
3953
|
+
init_styles();
|
|
3954
|
+
init_defaults();
|
|
3957
3955
|
|
|
3958
3956
|
// src/utils/bookmarkRegistry.ts
|
|
3959
3957
|
var BookmarkRegistry = class {
|
|
@@ -4028,7 +4026,8 @@ var globalBookmarkRegistry = new BookmarkRegistry();
|
|
|
4028
4026
|
init_styleHelpers();
|
|
4029
4027
|
init_colorUtils();
|
|
4030
4028
|
init_styleHelpers();
|
|
4031
|
-
|
|
4029
|
+
init_widthUtils();
|
|
4030
|
+
function createText(content, theme, themeName, options = {}) {
|
|
4032
4031
|
const normalizedContent = normalizeUnicodeText(content);
|
|
4033
4032
|
const style = options.style || "Normal";
|
|
4034
4033
|
const spacing = {};
|
|
@@ -4080,7 +4079,7 @@ function createText(content, theme, _themeName, options = {}) {
|
|
|
4080
4079
|
children.push(...textRuns);
|
|
4081
4080
|
}
|
|
4082
4081
|
const isFloating = !!options.floating;
|
|
4083
|
-
const frameOptions = isFloating && options.floating ? mapFrameOptions(options.floating) : void 0;
|
|
4082
|
+
const frameOptions = isFloating && options.floating ? mapFrameOptions(options.floating, theme, themeName) : void 0;
|
|
4084
4083
|
return new Paragraph({
|
|
4085
4084
|
children,
|
|
4086
4085
|
style,
|
|
@@ -4094,7 +4093,7 @@ function createText(content, theme, _themeName, options = {}) {
|
|
|
4094
4093
|
...options.keepLines !== void 0 && { keepLines: options.keepLines }
|
|
4095
4094
|
});
|
|
4096
4095
|
}
|
|
4097
|
-
function mapFrameOptions(floating) {
|
|
4096
|
+
function mapFrameOptions(floating, theme, themeName) {
|
|
4098
4097
|
const hasHorizontalOffset = floating.horizontalPosition?.offset !== void 0;
|
|
4099
4098
|
const hasVerticalOffset = floating.verticalPosition?.offset !== void 0;
|
|
4100
4099
|
const hasHorizontalAlign = floating.horizontalPosition?.align !== void 0;
|
|
@@ -4119,8 +4118,21 @@ function mapFrameOptions(floating) {
|
|
|
4119
4118
|
baseOptions.anchorLock = floating.anchorLock;
|
|
4120
4119
|
}
|
|
4121
4120
|
if (useAbsolute) {
|
|
4122
|
-
const
|
|
4123
|
-
const
|
|
4121
|
+
const rawX = floating.horizontalPosition?.offset ?? 0;
|
|
4122
|
+
const rawY = floating.verticalPosition?.offset ?? 0;
|
|
4123
|
+
let x;
|
|
4124
|
+
let y;
|
|
4125
|
+
if (typeof rawX === "string" || typeof rawY === "string") {
|
|
4126
|
+
const hRelative = floating.horizontalPosition?.relative;
|
|
4127
|
+
const vRelative = floating.verticalPosition?.relative;
|
|
4128
|
+
const hRef = hRelative && hRelative !== "page" ? getAvailableWidthTwips(theme, themeName) : getPageWidthTwips(theme, themeName);
|
|
4129
|
+
const vRef = vRelative && vRelative !== "page" ? getAvailableHeightTwips(theme, themeName) : getPageHeightTwips(theme, themeName);
|
|
4130
|
+
x = resolveOffsetTwips(rawX, hRef);
|
|
4131
|
+
y = resolveOffsetTwips(rawY, vRef);
|
|
4132
|
+
} else {
|
|
4133
|
+
x = rawX;
|
|
4134
|
+
y = rawY;
|
|
4135
|
+
}
|
|
4124
4136
|
return {
|
|
4125
4137
|
type: "absolute",
|
|
4126
4138
|
position: { x, y },
|
|
@@ -4218,14 +4230,17 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4218
4230
|
...options.keepLines !== void 0 && { keepLines: options.keepLines }
|
|
4219
4231
|
});
|
|
4220
4232
|
}
|
|
4221
|
-
async function createImage(path3, theme, options = {}) {
|
|
4233
|
+
async function createImage(path3, theme, themeName, options = {}) {
|
|
4222
4234
|
const elements = [];
|
|
4223
4235
|
const isFloating = !!options.floating;
|
|
4224
4236
|
const alignment = isFloating ? void 0 : getAlignment(options.alignment || "center");
|
|
4225
4237
|
let imagePath = path3;
|
|
4226
4238
|
let imageBuffer;
|
|
4239
|
+
let responseContentType;
|
|
4227
4240
|
try {
|
|
4228
|
-
|
|
4241
|
+
const imageResult = await getImageBuffer(imagePath);
|
|
4242
|
+
imageBuffer = imageResult.buffer;
|
|
4243
|
+
responseContentType = imageResult.contentType;
|
|
4229
4244
|
const {
|
|
4230
4245
|
getAvailableWidthTwips: getAvailableWidthTwips2,
|
|
4231
4246
|
getPageWidthTwips: getPageWidthTwips2,
|
|
@@ -4255,29 +4270,12 @@ async function createImage(path3, theme, options = {}) {
|
|
|
4255
4270
|
fallbackHeight
|
|
4256
4271
|
);
|
|
4257
4272
|
const { mapFloatingOptions: mapFloatingOptions2 } = await Promise.resolve().then(() => (init_docxImagePositioning(), docxImagePositioning_exports));
|
|
4258
|
-
const floating = isFloating ? mapFloatingOptions2(options.floating) : void 0;
|
|
4259
|
-
const
|
|
4260
|
-
const
|
|
4261
|
-
const imageRun = imageType === "svg" ? new ImageRun({
|
|
4262
|
-
type: "svg",
|
|
4263
|
-
data: imageBuffer,
|
|
4264
|
-
fallback: {
|
|
4265
|
-
type: "png",
|
|
4266
|
-
data: imageBuffer
|
|
4267
|
-
// Use the same buffer as fallback for now
|
|
4268
|
-
},
|
|
4269
|
-
transformation: {
|
|
4270
|
-
width: dimensions.width,
|
|
4271
|
-
height: dimensions.height
|
|
4272
|
-
},
|
|
4273
|
-
...floating && { floating }
|
|
4274
|
-
}) : new ImageRun({
|
|
4273
|
+
const floating = isFloating ? mapFloatingOptions2(options.floating, theme, themeName) : void 0;
|
|
4274
|
+
const imageType = detectImageType(imagePath, responseContentType);
|
|
4275
|
+
const imageRun = createTypedImageRun({
|
|
4275
4276
|
type: imageType,
|
|
4276
4277
|
data: imageBuffer,
|
|
4277
|
-
transformation: {
|
|
4278
|
-
width: dimensions.width,
|
|
4279
|
-
height: dimensions.height
|
|
4280
|
-
},
|
|
4278
|
+
transformation: { width: dimensions.width, height: dimensions.height },
|
|
4281
4279
|
...floating && { floating }
|
|
4282
4280
|
});
|
|
4283
4281
|
const spacing = {};
|
|
@@ -4401,7 +4399,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
4401
4399
|
const numRows = columns[0]?.cells?.length || 0;
|
|
4402
4400
|
const getDefaultCellDefaults = () => ({
|
|
4403
4401
|
color: "000000",
|
|
4404
|
-
backgroundColor: "
|
|
4402
|
+
backgroundColor: "transparent",
|
|
4405
4403
|
horizontalAlignment: "left",
|
|
4406
4404
|
verticalAlignment: "top",
|
|
4407
4405
|
font: {
|
|
@@ -4706,9 +4704,27 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
4706
4704
|
if (typeof cell === "object" && "name" in cell && "props" in cell) {
|
|
4707
4705
|
if (isParagraphComponent(cell)) {
|
|
4708
4706
|
const textComp = cell;
|
|
4707
|
+
const paragraphFont = textComp.props.font;
|
|
4708
|
+
const paragraphStyle = {
|
|
4709
|
+
...mergedStyle,
|
|
4710
|
+
...paragraphFont?.family && { font: paragraphFont.family },
|
|
4711
|
+
...paragraphFont?.size && { size: paragraphFont.size * 2 },
|
|
4712
|
+
...paragraphFont?.bold !== void 0 && {
|
|
4713
|
+
bold: paragraphFont.bold
|
|
4714
|
+
},
|
|
4715
|
+
...paragraphFont?.italic !== void 0 && {
|
|
4716
|
+
italics: paragraphFont.italic
|
|
4717
|
+
},
|
|
4718
|
+
...paragraphFont?.underline !== void 0 && {
|
|
4719
|
+
underline: paragraphFont.underline ? { type: "single" } : void 0
|
|
4720
|
+
},
|
|
4721
|
+
...paragraphFont?.color && {
|
|
4722
|
+
color: resolveColor(paragraphFont.color, theme)
|
|
4723
|
+
}
|
|
4724
|
+
};
|
|
4709
4725
|
cellChildren = parseTextWithDecorators(
|
|
4710
4726
|
textComp.props.text,
|
|
4711
|
-
|
|
4727
|
+
paragraphStyle,
|
|
4712
4728
|
{ enableHyperlinks: true }
|
|
4713
4729
|
);
|
|
4714
4730
|
} else if (isImageComponent(cell)) {
|
|
@@ -4720,7 +4736,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
4720
4736
|
'Image component requires either "path" or "base64" property'
|
|
4721
4737
|
);
|
|
4722
4738
|
}
|
|
4723
|
-
const
|
|
4739
|
+
const imageResult = await getImageBuffer(imageSource);
|
|
4724
4740
|
const parsedWidth = typeof imageComp.props.width === "string" ? parseWidthValue(imageComp.props.width, 300) : imageComp.props.width;
|
|
4725
4741
|
const parsedHeight = typeof imageComp.props.height === "string" ? parseWidthValue(imageComp.props.height, 200) : imageComp.props.height;
|
|
4726
4742
|
const dimensions = await calculateImageDimensions(
|
|
@@ -4732,9 +4748,10 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
4732
4748
|
20
|
|
4733
4749
|
// fallback height
|
|
4734
4750
|
);
|
|
4735
|
-
const
|
|
4736
|
-
|
|
4737
|
-
|
|
4751
|
+
const imgType = detectImageType(imageSource, imageResult.contentType);
|
|
4752
|
+
const imageRun = createTypedImageRun({
|
|
4753
|
+
type: imgType,
|
|
4754
|
+
data: imageResult.buffer,
|
|
4738
4755
|
transformation: {
|
|
4739
4756
|
width: dimensions.width,
|
|
4740
4757
|
height: dimensions.height
|
|
@@ -4838,8 +4855,10 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
4838
4855
|
})
|
|
4839
4856
|
],
|
|
4840
4857
|
verticalAlign: verticalAlignment,
|
|
4841
|
-
|
|
4842
|
-
|
|
4858
|
+
...mergedDefaults.backgroundColor !== "transparent" && {
|
|
4859
|
+
shading: {
|
|
4860
|
+
fill: mergedDefaults.backgroundColor
|
|
4861
|
+
}
|
|
4843
4862
|
},
|
|
4844
4863
|
margins: createMarginsFromPadding(mergedDefaults.padding),
|
|
4845
4864
|
borders: {
|
|
@@ -5005,8 +5024,10 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
5005
5024
|
})
|
|
5006
5025
|
],
|
|
5007
5026
|
verticalAlign: verticalAlignment,
|
|
5008
|
-
|
|
5009
|
-
|
|
5027
|
+
...mergedDefaults.backgroundColor !== "transparent" && {
|
|
5028
|
+
shading: {
|
|
5029
|
+
fill: mergedDefaults.backgroundColor
|
|
5030
|
+
}
|
|
5010
5031
|
},
|
|
5011
5032
|
margins: createMarginsFromPadding(mergedDefaults.padding),
|
|
5012
5033
|
borders: {
|
|
@@ -5410,7 +5431,7 @@ function renderListComponent(component, theme, themeName) {
|
|
|
5410
5431
|
}
|
|
5411
5432
|
|
|
5412
5433
|
// src/components/image.ts
|
|
5413
|
-
async function renderImageComponent(component, theme) {
|
|
5434
|
+
async function renderImageComponent(component, theme, themeName) {
|
|
5414
5435
|
if (!isImageComponent(component)) return [];
|
|
5415
5436
|
const resolvedConfig = resolveImageProps(component.props, theme);
|
|
5416
5437
|
const imageSource = resolvedConfig.base64 || resolvedConfig.path;
|
|
@@ -5419,7 +5440,7 @@ async function renderImageComponent(component, theme) {
|
|
|
5419
5440
|
'Image component requires either "path" or "base64" property'
|
|
5420
5441
|
);
|
|
5421
5442
|
}
|
|
5422
|
-
return await createImage(imageSource, theme, {
|
|
5443
|
+
return await createImage(imageSource, theme, themeName, {
|
|
5423
5444
|
caption: resolvedConfig.caption,
|
|
5424
5445
|
width: resolvedConfig.width,
|
|
5425
5446
|
height: resolvedConfig.height,
|
|
@@ -5520,15 +5541,20 @@ function buildCellOptions(children, styleCfg, theme) {
|
|
|
5520
5541
|
}
|
|
5521
5542
|
|
|
5522
5543
|
// src/components/text-box.ts
|
|
5523
|
-
|
|
5544
|
+
init_widthUtils();
|
|
5545
|
+
function mapTableFloatOptions(floating, theme, themeName) {
|
|
5524
5546
|
if (!floating) return void 0;
|
|
5525
5547
|
const opt = {};
|
|
5548
|
+
const hRelative = floating.horizontalPosition?.relative;
|
|
5549
|
+
const vRelative = floating.verticalPosition?.relative;
|
|
5550
|
+
const hRef = hRelative && hRelative !== "page" ? getAvailableWidthTwips(theme, themeName) : getPageWidthTwips(theme, themeName);
|
|
5551
|
+
const vRef = vRelative && vRelative !== "page" ? getAvailableHeightTwips(theme, themeName) : getPageHeightTwips(theme, themeName);
|
|
5526
5552
|
const hp = floating.horizontalPosition;
|
|
5527
5553
|
if (hp?.relative) {
|
|
5528
5554
|
opt.horizontalAnchor = hp.relative === "margin" ? TableAnchorType.MARGIN : hp.relative === "page" ? TableAnchorType.PAGE : TableAnchorType.TEXT;
|
|
5529
5555
|
}
|
|
5530
5556
|
if (hp?.offset !== void 0) {
|
|
5531
|
-
opt.absoluteHorizontalPosition = hp.offset;
|
|
5557
|
+
opt.absoluteHorizontalPosition = resolveOffsetTwips(hp.offset, hRef);
|
|
5532
5558
|
} else if (hp?.align) {
|
|
5533
5559
|
const map = {
|
|
5534
5560
|
left: RelativeHorizontalPosition.LEFT,
|
|
@@ -5544,7 +5570,7 @@ function mapTableFloatOptions(floating) {
|
|
|
5544
5570
|
opt.verticalAnchor = vp.relative === "margin" ? TableAnchorType.MARGIN : vp.relative === "page" ? TableAnchorType.PAGE : TableAnchorType.TEXT;
|
|
5545
5571
|
}
|
|
5546
5572
|
if (vp?.offset !== void 0) {
|
|
5547
|
-
opt.absoluteVerticalPosition = vp.offset;
|
|
5573
|
+
opt.absoluteVerticalPosition = resolveOffsetTwips(vp.offset, vRef);
|
|
5548
5574
|
} else if (vp?.align) {
|
|
5549
5575
|
const mapV = {
|
|
5550
5576
|
top: RelativeVerticalPosition.TOP,
|
|
@@ -5555,12 +5581,17 @@ function mapTableFloatOptions(floating) {
|
|
|
5555
5581
|
};
|
|
5556
5582
|
opt.relativeVerticalPosition = mapV[vp.align];
|
|
5557
5583
|
}
|
|
5584
|
+
const pageW = getPageWidthTwips(theme, themeName);
|
|
5585
|
+
const pageH = getPageHeightTwips(theme, themeName);
|
|
5558
5586
|
const m = floating.wrap?.margins;
|
|
5559
5587
|
if (m) {
|
|
5560
|
-
if (m.top !== void 0) opt.topFromText = m.top;
|
|
5561
|
-
if (m.right !== void 0)
|
|
5562
|
-
|
|
5563
|
-
if (m.
|
|
5588
|
+
if (m.top !== void 0) opt.topFromText = resolveOffsetTwips(m.top, pageH);
|
|
5589
|
+
if (m.right !== void 0)
|
|
5590
|
+
opt.rightFromText = resolveOffsetTwips(m.right, pageW);
|
|
5591
|
+
if (m.bottom !== void 0)
|
|
5592
|
+
opt.bottomFromText = resolveOffsetTwips(m.bottom, pageH);
|
|
5593
|
+
if (m.left !== void 0)
|
|
5594
|
+
opt.leftFromText = resolveOffsetTwips(m.left, pageW);
|
|
5564
5595
|
}
|
|
5565
5596
|
opt.overlap = OverlapType.OVERLAP;
|
|
5566
5597
|
return opt;
|
|
@@ -5616,7 +5647,7 @@ async function renderTextBoxComponent(component, theme, themeName, _context) {
|
|
|
5616
5647
|
const row = new TableRow2({
|
|
5617
5648
|
children: [new TableCell2(cellOpts)]
|
|
5618
5649
|
});
|
|
5619
|
-
const float = mapTableFloatOptions(tb.props.floating);
|
|
5650
|
+
const float = mapTableFloatOptions(tb.props.floating, theme, themeName);
|
|
5620
5651
|
const PIXELS_TO_TWIPS = 15;
|
|
5621
5652
|
const DEFAULT_WIDTH_TWIPS = 5e3;
|
|
5622
5653
|
const rawWidth = tb.props.width ?? tb.props.floating?.width;
|
|
@@ -5653,7 +5684,7 @@ async function renderTableComponent(component, theme, themeName) {
|
|
|
5653
5684
|
const rows = rawConfig.rows;
|
|
5654
5685
|
const defaultCellDefaults = {
|
|
5655
5686
|
color: "000000",
|
|
5656
|
-
backgroundColor: "
|
|
5687
|
+
backgroundColor: "transparent",
|
|
5657
5688
|
horizontalAlignment: "left",
|
|
5658
5689
|
verticalAlignment: "top",
|
|
5659
5690
|
font: {
|
|
@@ -5889,77 +5920,12 @@ function renderStatisticComponent(component, theme) {
|
|
|
5889
5920
|
);
|
|
5890
5921
|
}
|
|
5891
5922
|
|
|
5892
|
-
// src/components/header.ts
|
|
5893
|
-
import { Paragraph as Paragraph6, TextRun as TextRun4 } from "docx";
|
|
5894
|
-
init_styles();
|
|
5895
|
-
init_defaults();
|
|
5896
|
-
|
|
5897
|
-
// src/utils/alignmentUtils.ts
|
|
5898
|
-
import { AlignmentType as AlignmentType4 } from "docx";
|
|
5899
|
-
function getAlignment3(alignment) {
|
|
5900
|
-
switch (alignment) {
|
|
5901
|
-
case "center":
|
|
5902
|
-
return AlignmentType4.CENTER;
|
|
5903
|
-
case "right":
|
|
5904
|
-
return AlignmentType4.RIGHT;
|
|
5905
|
-
case "justify":
|
|
5906
|
-
return AlignmentType4.JUSTIFIED;
|
|
5907
|
-
default:
|
|
5908
|
-
return AlignmentType4.LEFT;
|
|
5909
|
-
}
|
|
5910
|
-
}
|
|
5911
|
-
|
|
5912
|
-
// src/components/header.ts
|
|
5913
|
-
function renderHeaderComponent(component, theme, themeName) {
|
|
5914
|
-
if (!isHeaderComponent(component)) return [];
|
|
5915
|
-
const headerComp = component;
|
|
5916
|
-
const bodyStyle = getBodyTextStyle(theme, themeName);
|
|
5917
|
-
return [
|
|
5918
|
-
new Paragraph6({
|
|
5919
|
-
children: [
|
|
5920
|
-
new TextRun4({
|
|
5921
|
-
text: `[Header: ${headerComp.props.alignment || "center"}]`,
|
|
5922
|
-
font: bodyStyle.font,
|
|
5923
|
-
size: bodyStyle.size,
|
|
5924
|
-
color: getThemeColors(theme).secondary
|
|
5925
|
-
})
|
|
5926
|
-
],
|
|
5927
|
-
alignment: getAlignment3(headerComp.props.alignment || "center"),
|
|
5928
|
-
style: "Normal"
|
|
5929
|
-
})
|
|
5930
|
-
];
|
|
5931
|
-
}
|
|
5932
|
-
|
|
5933
|
-
// src/components/footer.ts
|
|
5934
|
-
import { Paragraph as Paragraph7, TextRun as TextRun5 } from "docx";
|
|
5935
|
-
init_styles();
|
|
5936
|
-
init_defaults();
|
|
5937
|
-
function renderFooterComponent(component, theme, themeName) {
|
|
5938
|
-
if (!isFooterComponent(component)) return [];
|
|
5939
|
-
const footerComp = component;
|
|
5940
|
-
const bodyStyle = getBodyTextStyle(theme, themeName);
|
|
5941
|
-
return [
|
|
5942
|
-
new Paragraph7({
|
|
5943
|
-
children: [
|
|
5944
|
-
new TextRun5({
|
|
5945
|
-
text: `[Footer: ${footerComp.props.alignment || "center"}]`,
|
|
5946
|
-
font: bodyStyle.font,
|
|
5947
|
-
size: bodyStyle.size,
|
|
5948
|
-
color: getThemeColors(theme).secondary
|
|
5949
|
-
})
|
|
5950
|
-
],
|
|
5951
|
-
alignment: getAlignment3(footerComp.props.alignment || "center"),
|
|
5952
|
-
style: "Normal"
|
|
5953
|
-
})
|
|
5954
|
-
];
|
|
5955
|
-
}
|
|
5956
|
-
|
|
5957
5923
|
// src/components/toc/index.ts
|
|
5958
5924
|
import {
|
|
5959
|
-
Paragraph as
|
|
5925
|
+
Paragraph as Paragraph6,
|
|
5960
5926
|
TableOfContents,
|
|
5961
|
-
AlignmentType as
|
|
5962
|
-
TextRun as
|
|
5927
|
+
AlignmentType as AlignmentType4,
|
|
5928
|
+
TextRun as TextRun4,
|
|
5963
5929
|
StyleLevel
|
|
5964
5930
|
} from "docx";
|
|
5965
5931
|
function parseDepthRange(rawDepth, fieldName, defaultFrom = 1, defaultTo = 3) {
|
|
@@ -6012,9 +5978,9 @@ function renderTocComponent(component, theme, context) {
|
|
|
6012
5978
|
const paragraphs = [];
|
|
6013
5979
|
if (componentProps.title) {
|
|
6014
5980
|
paragraphs.push(
|
|
6015
|
-
new
|
|
5981
|
+
new Paragraph6({
|
|
6016
5982
|
children: [
|
|
6017
|
-
new
|
|
5983
|
+
new TextRun4({
|
|
6018
5984
|
text: componentProps.title,
|
|
6019
5985
|
bold: true,
|
|
6020
5986
|
size: 28
|
|
@@ -6027,7 +5993,7 @@ function renderTocComponent(component, theme, context) {
|
|
|
6027
5993
|
// 180 ~= 9pt, provides clearer separation by default
|
|
6028
5994
|
after: 180
|
|
6029
5995
|
},
|
|
6030
|
-
alignment:
|
|
5996
|
+
alignment: AlignmentType4.LEFT
|
|
6031
5997
|
})
|
|
6032
5998
|
);
|
|
6033
5999
|
}
|
|
@@ -6096,27 +6062,33 @@ function isNodeEnvironment() {
|
|
|
6096
6062
|
|
|
6097
6063
|
// src/components/highcharts.ts
|
|
6098
6064
|
var DEFAULT_EXPORT_SERVER_URL = "http://localhost:7801";
|
|
6099
|
-
function getExportServerUrl(propsUrl) {
|
|
6100
|
-
|
|
6065
|
+
function getExportServerUrl(propsUrl, servicesUrl) {
|
|
6066
|
+
const raw = propsUrl || servicesUrl || DEFAULT_EXPORT_SERVER_URL;
|
|
6067
|
+
return raw.startsWith("http") ? raw : `http://${raw}`;
|
|
6101
6068
|
}
|
|
6102
|
-
async function generateChart(config) {
|
|
6069
|
+
async function generateChart(config, servicesConfig) {
|
|
6103
6070
|
if (!isNodeEnvironment()) {
|
|
6104
6071
|
throw new Error(
|
|
6105
6072
|
"Highcharts export server requires a Node.js environment. Chart generation is not available in browser environments."
|
|
6106
6073
|
);
|
|
6107
6074
|
}
|
|
6108
|
-
const serverUrl = getExportServerUrl(
|
|
6075
|
+
const serverUrl = getExportServerUrl(
|
|
6076
|
+
config.serverUrl,
|
|
6077
|
+
servicesConfig?.serverUrl
|
|
6078
|
+
);
|
|
6109
6079
|
const requestBody = {
|
|
6110
6080
|
infile: config.options,
|
|
6111
6081
|
type: "png",
|
|
6112
6082
|
b64: true,
|
|
6113
6083
|
scale: config.scale
|
|
6114
6084
|
};
|
|
6085
|
+
const headers = {
|
|
6086
|
+
"Content-Type": "application/json",
|
|
6087
|
+
...servicesConfig?.headers
|
|
6088
|
+
};
|
|
6115
6089
|
const response = await fetch(`${serverUrl}/export`, {
|
|
6116
6090
|
method: "POST",
|
|
6117
|
-
headers
|
|
6118
|
-
"Content-Type": "application/json"
|
|
6119
|
-
},
|
|
6091
|
+
headers,
|
|
6120
6092
|
body: JSON.stringify(requestBody)
|
|
6121
6093
|
}).catch((error) => {
|
|
6122
6094
|
throw new Error(
|
|
@@ -6139,16 +6111,20 @@ Cause: ${error instanceof Error ? error.message : String(error)}`
|
|
|
6139
6111
|
height
|
|
6140
6112
|
};
|
|
6141
6113
|
}
|
|
6142
|
-
async function renderHighchartsComponent(component, theme,
|
|
6114
|
+
async function renderHighchartsComponent(component, theme, themeName, context) {
|
|
6143
6115
|
if (!isHighchartsComponent(component)) return [];
|
|
6144
6116
|
const config = component.props;
|
|
6145
|
-
const chartResult = await generateChart(
|
|
6117
|
+
const chartResult = await generateChart(
|
|
6118
|
+
config,
|
|
6119
|
+
context?.services?.highcharts
|
|
6120
|
+
);
|
|
6146
6121
|
const hasConfigDimensions = config.width !== void 0 || config.height !== void 0;
|
|
6147
6122
|
const renderWidth = hasConfigDimensions ? config.width : chartResult.width;
|
|
6148
6123
|
const renderHeight = hasConfigDimensions ? config.height : chartResult.height;
|
|
6149
6124
|
const imageParagraphs = await createImage(
|
|
6150
6125
|
chartResult.base64DataUri,
|
|
6151
6126
|
theme,
|
|
6127
|
+
themeName,
|
|
6152
6128
|
{
|
|
6153
6129
|
width: renderWidth,
|
|
6154
6130
|
height: renderHeight,
|
|
@@ -6211,16 +6187,16 @@ var textSpaceAfterComponent = createComponent({
|
|
|
6211
6187
|
|
|
6212
6188
|
// src/core/render.ts
|
|
6213
6189
|
init_docxImagePositioning();
|
|
6214
|
-
function
|
|
6190
|
+
function getAlignment3(alignment) {
|
|
6215
6191
|
switch (alignment) {
|
|
6216
6192
|
case "center":
|
|
6217
|
-
return
|
|
6193
|
+
return AlignmentType5.CENTER;
|
|
6218
6194
|
case "right":
|
|
6219
|
-
return
|
|
6195
|
+
return AlignmentType5.RIGHT;
|
|
6220
6196
|
case "justify":
|
|
6221
|
-
return
|
|
6197
|
+
return AlignmentType5.JUSTIFIED;
|
|
6222
6198
|
default:
|
|
6223
|
-
return
|
|
6199
|
+
return AlignmentType5.LEFT;
|
|
6224
6200
|
}
|
|
6225
6201
|
}
|
|
6226
6202
|
async function renderDocument(structure, layout, options) {
|
|
@@ -6237,6 +6213,7 @@ async function renderDocument(structure, layout, options) {
|
|
|
6237
6213
|
structure.theme,
|
|
6238
6214
|
structure.themeName
|
|
6239
6215
|
);
|
|
6216
|
+
context.services = options?.services;
|
|
6240
6217
|
let sectionBookmarkCounter = 0;
|
|
6241
6218
|
let previousHeader = void 0;
|
|
6242
6219
|
let previousFooter = void 0;
|
|
@@ -6311,7 +6288,7 @@ async function renderDocument(structure, layout, options) {
|
|
|
6311
6288
|
}
|
|
6312
6289
|
});
|
|
6313
6290
|
}
|
|
6314
|
-
async function renderHeaderFooterComponents(components, theme,
|
|
6291
|
+
async function renderHeaderFooterComponents(components, theme, themeName, _context) {
|
|
6315
6292
|
if (!components || components.length === 0) {
|
|
6316
6293
|
return [];
|
|
6317
6294
|
}
|
|
@@ -6333,9 +6310,9 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6333
6310
|
};
|
|
6334
6311
|
const textRuns = parseTextWithDecorators(textComp.props.text, textStyle);
|
|
6335
6312
|
elements.push(
|
|
6336
|
-
new
|
|
6313
|
+
new Paragraph7({
|
|
6337
6314
|
children: textRuns,
|
|
6338
|
-
alignment: textComp.props.alignment ?
|
|
6315
|
+
alignment: textComp.props.alignment ? getAlignment3(textComp.props.alignment) : void 0,
|
|
6339
6316
|
style: "Normal"
|
|
6340
6317
|
})
|
|
6341
6318
|
);
|
|
@@ -6344,9 +6321,9 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6344
6321
|
let imageSource = imageComp.props.base64 || imageComp.props.path;
|
|
6345
6322
|
if (!imageSource) {
|
|
6346
6323
|
elements.push(
|
|
6347
|
-
new
|
|
6324
|
+
new Paragraph7({
|
|
6348
6325
|
children: [
|
|
6349
|
-
new
|
|
6326
|
+
new TextRun5({
|
|
6350
6327
|
text: "[IMAGE: Missing path or base64 property]",
|
|
6351
6328
|
font: getThemeFonts(theme).body.family,
|
|
6352
6329
|
size: 20,
|
|
@@ -6354,15 +6331,18 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6354
6331
|
color: "#FF0000"
|
|
6355
6332
|
})
|
|
6356
6333
|
],
|
|
6357
|
-
alignment: imageComp.props.alignment ?
|
|
6334
|
+
alignment: imageComp.props.alignment ? getAlignment3(imageComp.props.alignment) : void 0,
|
|
6358
6335
|
style: "Normal"
|
|
6359
6336
|
})
|
|
6360
6337
|
);
|
|
6361
6338
|
continue;
|
|
6362
6339
|
}
|
|
6363
6340
|
let imageBuffer;
|
|
6341
|
+
let responseContentType;
|
|
6364
6342
|
try {
|
|
6365
|
-
|
|
6343
|
+
const imageResult = await getImageBuffer(imageSource);
|
|
6344
|
+
imageBuffer = imageResult.buffer;
|
|
6345
|
+
responseContentType = imageResult.contentType;
|
|
6366
6346
|
} catch (error) {
|
|
6367
6347
|
throw new Error(
|
|
6368
6348
|
`Failed to load image from ${imageSource.substring(0, 50)}`
|
|
@@ -6395,9 +6375,14 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6395
6375
|
referenceWidthPx,
|
|
6396
6376
|
fallbackHeight
|
|
6397
6377
|
);
|
|
6398
|
-
const floatingOptions = mapFloatingOptions(
|
|
6399
|
-
|
|
6400
|
-
|
|
6378
|
+
const floatingOptions = mapFloatingOptions(
|
|
6379
|
+
imageComp.props.floating,
|
|
6380
|
+
theme,
|
|
6381
|
+
themeName
|
|
6382
|
+
);
|
|
6383
|
+
const imageType = detectImageType(imageSource, responseContentType);
|
|
6384
|
+
const imageRun = createTypedImageRun({
|
|
6385
|
+
type: imageType,
|
|
6401
6386
|
data: imageBuffer,
|
|
6402
6387
|
transformation: {
|
|
6403
6388
|
width: dimensions.width,
|
|
@@ -6406,9 +6391,9 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6406
6391
|
...floatingOptions && { floating: floatingOptions }
|
|
6407
6392
|
});
|
|
6408
6393
|
elements.push(
|
|
6409
|
-
new
|
|
6394
|
+
new Paragraph7({
|
|
6410
6395
|
children: [imageRun],
|
|
6411
|
-
alignment: imageComp.props.alignment ?
|
|
6396
|
+
alignment: imageComp.props.alignment ? getAlignment3(imageComp.props.alignment) : void 0,
|
|
6412
6397
|
style: "Normal"
|
|
6413
6398
|
})
|
|
6414
6399
|
);
|
|
@@ -6418,9 +6403,9 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6418
6403
|
error instanceof Error ? error.message : error
|
|
6419
6404
|
);
|
|
6420
6405
|
elements.push(
|
|
6421
|
-
new
|
|
6406
|
+
new Paragraph7({
|
|
6422
6407
|
children: [
|
|
6423
|
-
new
|
|
6408
|
+
new TextRun5({
|
|
6424
6409
|
text: `[IMAGE: ${imageComp.props.path}]`,
|
|
6425
6410
|
font: getThemeFonts(theme).body.family,
|
|
6426
6411
|
size: 20,
|
|
@@ -6433,7 +6418,7 @@ async function renderHeaderFooterComponents(components, theme, _themeName, _cont
|
|
|
6433
6418
|
);
|
|
6434
6419
|
}
|
|
6435
6420
|
} else if (isTableComponent(component)) {
|
|
6436
|
-
const tables = await renderTableComponent(component, theme,
|
|
6421
|
+
const tables = await renderTableComponent(component, theme, themeName);
|
|
6437
6422
|
elements.push(...tables);
|
|
6438
6423
|
}
|
|
6439
6424
|
}
|
|
@@ -6458,7 +6443,7 @@ async function renderSection(section, theme, themeName, context, sectionOrdinal,
|
|
|
6458
6443
|
};
|
|
6459
6444
|
if (sectionBookmarkId && isFirstLayoutOfUserSection && sharedLinkId !== void 0) {
|
|
6460
6445
|
elements.push(
|
|
6461
|
-
new
|
|
6446
|
+
new Paragraph7({
|
|
6462
6447
|
children: [new BookmarkStart2(sectionBookmarkId, sharedLinkId)],
|
|
6463
6448
|
spacing: {
|
|
6464
6449
|
before: 0,
|
|
@@ -6484,7 +6469,7 @@ async function renderSection(section, theme, themeName, context, sectionOrdinal,
|
|
|
6484
6469
|
}
|
|
6485
6470
|
if (closeBookmark && sharedLinkId !== void 0) {
|
|
6486
6471
|
elements.push(
|
|
6487
|
-
new
|
|
6472
|
+
new Paragraph7({
|
|
6488
6473
|
children: [new BookmarkEnd2(sharedLinkId)]
|
|
6489
6474
|
})
|
|
6490
6475
|
);
|
|
@@ -6537,23 +6522,24 @@ async function renderComponent(component, theme, themeName, context) {
|
|
|
6537
6522
|
} else if (isColumnsComponent(component)) {
|
|
6538
6523
|
return await renderColumnsComponent(component, theme, themeName, context);
|
|
6539
6524
|
} else if (isImageComponent(component)) {
|
|
6540
|
-
return await renderImageComponent(component, theme);
|
|
6525
|
+
return await renderImageComponent(component, theme, themeName);
|
|
6541
6526
|
} else if (isTextBoxComponent(component)) {
|
|
6542
6527
|
return await renderTextBoxComponent(component, theme, themeName, context);
|
|
6543
6528
|
} else if (isStatisticComponent(component)) {
|
|
6544
6529
|
return renderStatisticComponent(component, theme);
|
|
6545
6530
|
} else if (isTableComponent(component)) {
|
|
6546
6531
|
return await renderTableComponent(component, theme, themeName);
|
|
6547
|
-
} else if (isHeaderComponent(component)) {
|
|
6548
|
-
return renderHeaderComponent(component, theme, themeName);
|
|
6549
|
-
} else if (isFooterComponent(component)) {
|
|
6550
|
-
return renderFooterComponent(component, theme, themeName);
|
|
6551
6532
|
} else if (isListComponent(component)) {
|
|
6552
6533
|
return renderListComponent(component, theme, themeName);
|
|
6553
6534
|
} else if (isTocComponent(component)) {
|
|
6554
6535
|
return renderTocComponent(component, theme, context);
|
|
6555
6536
|
} else if (isHighchartsComponent(component)) {
|
|
6556
|
-
return await renderHighchartsComponent(
|
|
6537
|
+
return await renderHighchartsComponent(
|
|
6538
|
+
component,
|
|
6539
|
+
theme,
|
|
6540
|
+
themeName,
|
|
6541
|
+
context
|
|
6542
|
+
);
|
|
6557
6543
|
} else if (isSectionComponent(component)) {
|
|
6558
6544
|
return await renderSectionComponent(component, theme, themeName, context);
|
|
6559
6545
|
}
|
|
@@ -6775,7 +6761,8 @@ function createBuilderImpl(state) {
|
|
|
6775
6761
|
theme: state.theme,
|
|
6776
6762
|
customThemes: state.customThemes,
|
|
6777
6763
|
debug: state.debug,
|
|
6778
|
-
enableCache: state.enableCache
|
|
6764
|
+
enableCache: state.enableCache,
|
|
6765
|
+
services: state.services
|
|
6779
6766
|
};
|
|
6780
6767
|
return createBuilderImpl(
|
|
6781
6768
|
newState
|
|
@@ -6807,7 +6794,9 @@ function createBuilderImpl(state) {
|
|
|
6807
6794
|
themeName
|
|
6808
6795
|
);
|
|
6809
6796
|
const layout = applyLayout(structure.sections, docTheme, themeName);
|
|
6810
|
-
const generatedDocument = await renderDocument(structure, layout
|
|
6797
|
+
const generatedDocument = await renderDocument(structure, layout, {
|
|
6798
|
+
services: state.services
|
|
6799
|
+
});
|
|
6811
6800
|
return {
|
|
6812
6801
|
document: generatedDocument,
|
|
6813
6802
|
warnings: warnings.length > 0 ? warnings : null
|
|
@@ -6922,7 +6911,8 @@ function createDocumentGenerator(options) {
|
|
|
6922
6911
|
theme: options.theme,
|
|
6923
6912
|
customThemes: options.customThemes,
|
|
6924
6913
|
debug: options.debug ?? false,
|
|
6925
|
-
enableCache: options.enableCache ?? false
|
|
6914
|
+
enableCache: options.enableCache ?? false,
|
|
6915
|
+
services: options.services
|
|
6926
6916
|
};
|
|
6927
6917
|
return createBuilderImpl(initialState);
|
|
6928
6918
|
}
|