@json-to-office/jto 0.27.0 → 0.28.1
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/cli.js +283 -96
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/{HomePage-Dm2fRH6p.js → HomePage-g8gOpx6G.js} +3 -3
- package/dist/client/assets/HomePage-g8gOpx6G.js.map +1 -0
- package/dist/client/assets/{JsonEditorPage-CeOvPs5I.js → JsonEditorPage-CzMTUrNe.js} +3 -3
- package/dist/client/assets/{JsonEditorPage-CeOvPs5I.js.map → JsonEditorPage-CzMTUrNe.js.map} +1 -1
- package/dist/client/assets/{MonacoPluginProvider-BDwUsxu4.js → MonacoPluginProvider-CmMAmp3u.js} +3 -3
- package/dist/client/assets/{MonacoPluginProvider-BDwUsxu4.js.map → MonacoPluginProvider-CmMAmp3u.js.map} +1 -1
- package/dist/client/assets/{button-DpH0SUBp.js → button-BEg2__r6.js} +2 -2
- package/dist/client/assets/{button-DpH0SUBp.js.map → button-BEg2__r6.js.map} +1 -1
- package/dist/client/assets/{editor-e3ONSdDx.js → editor-DPs_adn-.js} +2 -2
- package/dist/client/assets/{editor-e3ONSdDx.js.map → editor-DPs_adn-.js.map} +1 -1
- package/dist/client/assets/{editor-monaco-json-CFSP94ky.js → editor-monaco-json-xnoKHnLp.js} +2 -2
- package/dist/client/assets/{editor-monaco-json-CFSP94ky.js.map → editor-monaco-json-xnoKHnLp.js.map} +1 -1
- package/dist/client/assets/{index-D2uJMa4G.js → index-DgKS-gEZ.js} +3 -3
- package/dist/client/assets/{index-D2uJMa4G.js.map → index-DgKS-gEZ.js.map} +1 -1
- package/dist/client/assets/preview-RxIHvUjz.js +3 -0
- package/dist/client/assets/preview-RxIHvUjz.js.map +1 -0
- package/dist/client/index.html +1 -1
- package/dist/client/templates/management-plan.pptx.json +18 -18
- package/dist/client/templates/minimalist-pitch-deck.pptx.json +19 -19
- package/dist/client/templates/modern-annual-report-2.docx.json +12 -12
- package/dist/client/templates/modern-annual-report-3.docx.json +14 -14
- package/dist/client/templates/standard-annual-report.docx.json +2 -2
- package/dist/render-server.js +62 -48
- package/dist/render-server.js.map +1 -1
- package/package.json +7 -8
- package/dist/client/assets/HomePage-Dm2fRH6p.js.map +0 -1
- package/dist/client/assets/preview-_aGms4Sr.js +0 -3
- package/dist/client/assets/preview-_aGms4Sr.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -234,10 +234,10 @@ function collectReferencedNames(config2, customThemes, adapterName) {
|
|
|
234
234
|
}
|
|
235
235
|
function collectReferencedWeights(config2, customThemes) {
|
|
236
236
|
const weights = /* @__PURE__ */ new Set();
|
|
237
|
-
const
|
|
237
|
+
const visit3 = (node) => {
|
|
238
238
|
if (node == null) return;
|
|
239
239
|
if (Array.isArray(node)) {
|
|
240
|
-
for (const item of node)
|
|
240
|
+
for (const item of node) visit3(item);
|
|
241
241
|
return;
|
|
242
242
|
}
|
|
243
243
|
if (typeof node === "object") {
|
|
@@ -245,21 +245,21 @@ function collectReferencedWeights(config2, customThemes) {
|
|
|
245
245
|
if (k === "fontWeight" && typeof v === "number" && v >= 100 && v <= 900) {
|
|
246
246
|
weights.add(v);
|
|
247
247
|
} else {
|
|
248
|
-
|
|
248
|
+
visit3(v);
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
251
|
}
|
|
252
252
|
};
|
|
253
|
-
|
|
254
|
-
for (const theme of Object.values(customThemes ?? {}))
|
|
253
|
+
visit3(config2);
|
|
254
|
+
for (const theme of Object.values(customThemes ?? {})) visit3(theme);
|
|
255
255
|
return weights;
|
|
256
256
|
}
|
|
257
257
|
function collectReferencedItalic(config2, customThemes) {
|
|
258
258
|
let found = false;
|
|
259
|
-
const
|
|
259
|
+
const visit3 = (node) => {
|
|
260
260
|
if (found || node == null) return;
|
|
261
261
|
if (Array.isArray(node)) {
|
|
262
|
-
for (const item of node)
|
|
262
|
+
for (const item of node) visit3(item);
|
|
263
263
|
return;
|
|
264
264
|
}
|
|
265
265
|
if (typeof node === "object") {
|
|
@@ -268,14 +268,14 @@ function collectReferencedItalic(config2, customThemes) {
|
|
|
268
268
|
found = true;
|
|
269
269
|
return;
|
|
270
270
|
}
|
|
271
|
-
|
|
271
|
+
visit3(v);
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
274
|
};
|
|
275
|
-
|
|
275
|
+
visit3(config2);
|
|
276
276
|
if (!found) {
|
|
277
277
|
for (const theme of Object.values(customThemes ?? {})) {
|
|
278
|
-
|
|
278
|
+
visit3(theme);
|
|
279
279
|
if (found) break;
|
|
280
280
|
}
|
|
281
281
|
}
|
|
@@ -422,12 +422,15 @@ var init_generator = __esm({
|
|
|
422
422
|
}
|
|
423
423
|
}
|
|
424
424
|
const bypassCache = options?.bypassCache === true || extraEntries.length > 0;
|
|
425
|
+
const baseDir = typeof options?.baseDir === "string" ? options.baseDir : void 0;
|
|
425
426
|
const cacheKeyData = {
|
|
426
427
|
config: config2,
|
|
427
428
|
customThemes: customThemes && Object.keys(customThemes).length > 0 ? customThemes : null,
|
|
428
429
|
fontMode: fontMode ?? null,
|
|
429
430
|
fontSubstitution: fontSubstitution ?? null,
|
|
430
|
-
fontStrict: callerStrict ?? null
|
|
431
|
+
fontStrict: callerStrict ?? null,
|
|
432
|
+
// Same definition, different source directory → different local assets.
|
|
433
|
+
baseDir: baseDir ?? null
|
|
431
434
|
};
|
|
432
435
|
const cacheKey = this.cacheService.generateCacheKey(cacheKeyData);
|
|
433
436
|
const hasDynamicContent = this.cacheService.hasDynamicContent(config2);
|
|
@@ -464,13 +467,15 @@ var init_generator = __esm({
|
|
|
464
467
|
const plugins = registry.getPlugins();
|
|
465
468
|
const generator = await this.adapter.createGenerator(plugins, {
|
|
466
469
|
customThemes,
|
|
467
|
-
fonts: fontOpts
|
|
470
|
+
fonts: fontOpts,
|
|
471
|
+
baseDir
|
|
468
472
|
});
|
|
469
473
|
buffer = await generator.generateBuffer(config2);
|
|
470
474
|
} else {
|
|
471
475
|
buffer = await this.adapter.generateBuffer(config2, {
|
|
472
476
|
customThemes,
|
|
473
|
-
fonts: fontOpts
|
|
477
|
+
fonts: fontOpts,
|
|
478
|
+
baseDir
|
|
474
479
|
});
|
|
475
480
|
}
|
|
476
481
|
this.cacheService.set(cacheKey, buffer, config2, {
|
|
@@ -1413,7 +1418,12 @@ var init_loose = __esm({
|
|
|
1413
1418
|
{
|
|
1414
1419
|
bypassCache: Type.Optional(Type.Boolean()),
|
|
1415
1420
|
returnUrl: Type.Optional(Type.Boolean()),
|
|
1416
|
-
fonts: Type.Optional(FontOptionsSchema)
|
|
1421
|
+
fonts: Type.Optional(FontOptionsSchema),
|
|
1422
|
+
// Name of the discovered document this definition came from; the
|
|
1423
|
+
// server maps it to that document's directory so relative asset
|
|
1424
|
+
// paths resolve against it (#142). Names, never paths — a client
|
|
1425
|
+
// cannot point the server at an arbitrary directory.
|
|
1426
|
+
sourceName: Type.Optional(Type.String())
|
|
1417
1427
|
},
|
|
1418
1428
|
{ additionalProperties: true }
|
|
1419
1429
|
)
|
|
@@ -1630,36 +1640,36 @@ function isPrivateHost(host) {
|
|
|
1630
1640
|
const firstIpv6Group = Number.parseInt(normalized.split(":")[0] || "0", 16);
|
|
1631
1641
|
return firstIpv6Group >= 64512 && firstIpv6Group <= 65023 || firstIpv6Group >= 65152 && firstIpv6Group <= 65215;
|
|
1632
1642
|
}
|
|
1633
|
-
function assertAllowedUrl(source,
|
|
1643
|
+
function assertAllowedUrl(source, path8, allowedHosts) {
|
|
1634
1644
|
if (source.startsWith("data:")) return;
|
|
1635
1645
|
let url;
|
|
1636
1646
|
try {
|
|
1637
1647
|
url = new URL(source);
|
|
1638
1648
|
} catch {
|
|
1639
1649
|
throw new UnsafeOutboundSourceError(
|
|
1640
|
-
|
|
1650
|
+
path8,
|
|
1641
1651
|
"local and relative file paths are disabled for HTTP requests"
|
|
1642
1652
|
);
|
|
1643
1653
|
}
|
|
1644
1654
|
if (url.protocol !== "https:") {
|
|
1645
|
-
throw new UnsafeOutboundSourceError(
|
|
1655
|
+
throw new UnsafeOutboundSourceError(path8, "only HTTPS URLs are allowed");
|
|
1646
1656
|
}
|
|
1647
1657
|
if (url.username || url.password) {
|
|
1648
1658
|
throw new UnsafeOutboundSourceError(
|
|
1649
|
-
|
|
1659
|
+
path8,
|
|
1650
1660
|
"URLs containing credentials are not allowed"
|
|
1651
1661
|
);
|
|
1652
1662
|
}
|
|
1653
1663
|
const host = url.hostname.toLowerCase().replace(/\.$/, "");
|
|
1654
1664
|
if (isPrivateHost(host)) {
|
|
1655
1665
|
throw new UnsafeOutboundSourceError(
|
|
1656
|
-
|
|
1666
|
+
path8,
|
|
1657
1667
|
`private or local host "${host}" is not allowed`
|
|
1658
1668
|
);
|
|
1659
1669
|
}
|
|
1660
1670
|
if (!allowedHosts.some((pattern) => hostMatches(host, pattern))) {
|
|
1661
1671
|
throw new UnsafeOutboundSourceError(
|
|
1662
|
-
|
|
1672
|
+
path8,
|
|
1663
1673
|
`host "${host}" is not in OUTBOUND_HOST_ALLOWLIST`
|
|
1664
1674
|
);
|
|
1665
1675
|
}
|
|
@@ -1677,13 +1687,13 @@ function extractCssReferences(input) {
|
|
|
1677
1687
|
function extractAbsoluteUrls(input) {
|
|
1678
1688
|
return input.match(/(?:https?|file):\/\/[^\s'"<>)}\]]+/gi) ?? [];
|
|
1679
1689
|
}
|
|
1680
|
-
function assertSafeSvg(svg,
|
|
1690
|
+
function assertSafeSvg(svg, path8, allowedHosts) {
|
|
1681
1691
|
if (/<\s*script\b/i.test(svg) || /<\s*(?:foreignObject|iframe|object|embed)\b/i.test(svg) || /\bon[a-z]+\s*=/i.test(svg)) {
|
|
1682
|
-
throw new UnsafeOutboundSourceError(
|
|
1692
|
+
throw new UnsafeOutboundSourceError(path8, "active SVG content is disabled");
|
|
1683
1693
|
}
|
|
1684
1694
|
if (/<!\s*(?:DOCTYPE|ENTITY)\b/i.test(svg)) {
|
|
1685
1695
|
throw new UnsafeOutboundSourceError(
|
|
1686
|
-
|
|
1696
|
+
path8,
|
|
1687
1697
|
"SVG document types and entities are disabled"
|
|
1688
1698
|
);
|
|
1689
1699
|
}
|
|
@@ -1692,20 +1702,20 @@ function assertSafeSvg(svg, path6, allowedHosts) {
|
|
|
1692
1702
|
while (match = refPattern.exec(svg)) {
|
|
1693
1703
|
const ref = match[2].trim();
|
|
1694
1704
|
if (!ref || ref.startsWith("#") || ref.startsWith("data:")) continue;
|
|
1695
|
-
assertAllowedUrl(ref,
|
|
1705
|
+
assertAllowedUrl(ref, path8, allowedHosts);
|
|
1696
1706
|
}
|
|
1697
1707
|
for (const ref of extractCssReferences(svg)) {
|
|
1698
1708
|
if (ref.startsWith("#") || ref.startsWith("data:")) continue;
|
|
1699
|
-
assertAllowedUrl(ref,
|
|
1709
|
+
assertAllowedUrl(ref, path8, allowedHosts);
|
|
1700
1710
|
}
|
|
1701
1711
|
}
|
|
1702
|
-
function assertSafeEncodedImage(source,
|
|
1712
|
+
function assertSafeEncodedImage(source, path8, allowedHosts) {
|
|
1703
1713
|
let candidate = source.trim();
|
|
1704
1714
|
let declaredSvg = false;
|
|
1705
1715
|
if (candidate.startsWith("data:")) {
|
|
1706
1716
|
const comma = candidate.indexOf(",");
|
|
1707
1717
|
if (comma < 0) {
|
|
1708
|
-
throw new UnsafeOutboundSourceError(
|
|
1718
|
+
throw new UnsafeOutboundSourceError(path8, "malformed image data URL");
|
|
1709
1719
|
}
|
|
1710
1720
|
const metadata = candidate.slice(5, comma);
|
|
1711
1721
|
declaredSvg = metadata.split(";")[0].toLowerCase() === "image/svg+xml";
|
|
@@ -1714,7 +1724,7 @@ function assertSafeEncodedImage(source, path6, allowedHosts) {
|
|
|
1714
1724
|
try {
|
|
1715
1725
|
candidate = /(?:^|;)base64(?:;|$)/i.test(metadata) ? Buffer.from(payload, "base64").toString("utf8") : decodeURIComponent(payload);
|
|
1716
1726
|
} catch {
|
|
1717
|
-
throw new UnsafeOutboundSourceError(
|
|
1727
|
+
throw new UnsafeOutboundSourceError(path8, "malformed SVG data URL");
|
|
1718
1728
|
}
|
|
1719
1729
|
} else if (!/<\s*svg\b/i.test(candidate)) {
|
|
1720
1730
|
candidate = Buffer.from(candidate, "base64").toString("utf8");
|
|
@@ -1722,37 +1732,37 @@ function assertSafeEncodedImage(source, path6, allowedHosts) {
|
|
|
1722
1732
|
const svgStart = candidate.search(/<\s*svg\b/i);
|
|
1723
1733
|
if (svgStart < 0) {
|
|
1724
1734
|
if (declaredSvg) {
|
|
1725
|
-
throw new UnsafeOutboundSourceError(
|
|
1735
|
+
throw new UnsafeOutboundSourceError(path8, "malformed SVG image data");
|
|
1726
1736
|
}
|
|
1727
1737
|
return;
|
|
1728
1738
|
}
|
|
1729
|
-
assertSafeSvg(candidate,
|
|
1739
|
+
assertSafeSvg(candidate, path8, allowedHosts);
|
|
1730
1740
|
}
|
|
1731
|
-
function assertSafeResources(resources,
|
|
1741
|
+
function assertSafeResources(resources, path8, allowedHosts) {
|
|
1732
1742
|
if (typeof resources.js === "string" && resources.js.trim()) {
|
|
1733
1743
|
throw new UnsafeOutboundSourceError(
|
|
1734
|
-
`${
|
|
1744
|
+
`${path8}.js`,
|
|
1735
1745
|
"remote renderer JavaScript resources are disabled"
|
|
1736
1746
|
);
|
|
1737
1747
|
}
|
|
1738
1748
|
if (typeof resources.css === "string") {
|
|
1739
1749
|
for (const ref of extractCssReferences(resources.css)) {
|
|
1740
1750
|
if (ref.startsWith("data:")) continue;
|
|
1741
|
-
assertAllowedUrl(ref, `${
|
|
1751
|
+
assertAllowedUrl(ref, `${path8}.css`, allowedHosts);
|
|
1742
1752
|
}
|
|
1743
1753
|
}
|
|
1744
1754
|
if (Array.isArray(resources.files) && resources.files.length > 0) {
|
|
1745
1755
|
throw new UnsafeOutboundSourceError(
|
|
1746
|
-
`${
|
|
1756
|
+
`${path8}.files`,
|
|
1747
1757
|
"remote renderer JavaScript resources are disabled"
|
|
1748
1758
|
);
|
|
1749
1759
|
}
|
|
1750
1760
|
}
|
|
1751
|
-
function assertNoRemoteReferences(value,
|
|
1761
|
+
function assertNoRemoteReferences(value, path8, allowedHosts, seen) {
|
|
1752
1762
|
if (typeof value === "string") {
|
|
1753
1763
|
if (/\b(?:fetch|XMLHttpRequest|WebSocket|EventSource)\s*\(/i.test(value) || /\b(?:javascript|file):/i.test(value)) {
|
|
1754
1764
|
throw new UnsafeOutboundSourceError(
|
|
1755
|
-
|
|
1765
|
+
path8,
|
|
1756
1766
|
"network-capable JavaScript and file URLs are disabled"
|
|
1757
1767
|
);
|
|
1758
1768
|
}
|
|
@@ -1761,11 +1771,11 @@ function assertNoRemoteReferences(value, path6, allowedHosts, seen) {
|
|
|
1761
1771
|
...extractCssReferences(value)
|
|
1762
1772
|
]) {
|
|
1763
1773
|
if (url.startsWith("data:")) continue;
|
|
1764
|
-
assertAllowedUrl(url,
|
|
1774
|
+
assertAllowedUrl(url, path8, allowedHosts);
|
|
1765
1775
|
}
|
|
1766
1776
|
if (/^\/\//.test(value.trim())) {
|
|
1767
1777
|
throw new UnsafeOutboundSourceError(
|
|
1768
|
-
|
|
1778
|
+
path8,
|
|
1769
1779
|
"protocol-relative URLs are disabled"
|
|
1770
1780
|
);
|
|
1771
1781
|
}
|
|
@@ -1775,20 +1785,20 @@ function assertNoRemoteReferences(value, path6, allowedHosts, seen) {
|
|
|
1775
1785
|
seen.add(value);
|
|
1776
1786
|
if (Array.isArray(value)) {
|
|
1777
1787
|
value.forEach(
|
|
1778
|
-
(entry, index) => assertNoRemoteReferences(entry, `${
|
|
1788
|
+
(entry, index) => assertNoRemoteReferences(entry, `${path8}[${index}]`, allowedHosts, seen)
|
|
1779
1789
|
);
|
|
1780
1790
|
return;
|
|
1781
1791
|
}
|
|
1782
1792
|
for (const [key, child] of Object.entries(value)) {
|
|
1783
|
-
assertNoRemoteReferences(child, `${
|
|
1793
|
+
assertNoRemoteReferences(child, `${path8}.${key}`, allowedHosts, seen);
|
|
1784
1794
|
}
|
|
1785
1795
|
}
|
|
1786
|
-
function visit(value,
|
|
1796
|
+
function visit(value, path8, containerKey, allowedHosts, seen) {
|
|
1787
1797
|
if (!value || typeof value !== "object" || seen.has(value)) return;
|
|
1788
1798
|
seen.add(value);
|
|
1789
1799
|
if (Array.isArray(value)) {
|
|
1790
1800
|
value.forEach(
|
|
1791
|
-
(entry, index) => visit(entry, `${
|
|
1801
|
+
(entry, index) => visit(entry, `${path8}[${index}]`, containerKey, allowedHosts, seen)
|
|
1792
1802
|
);
|
|
1793
1803
|
return;
|
|
1794
1804
|
}
|
|
@@ -1796,7 +1806,7 @@ function visit(value, path6, containerKey, allowedHosts, seen) {
|
|
|
1796
1806
|
for (const key of Object.keys(record)) {
|
|
1797
1807
|
if (DANGEROUS_KEYS.has(key)) {
|
|
1798
1808
|
throw new UnsafeOutboundSourceError(
|
|
1799
|
-
`${
|
|
1809
|
+
`${path8}.${key}`,
|
|
1800
1810
|
"prototype mutation keys are disabled"
|
|
1801
1811
|
);
|
|
1802
1812
|
}
|
|
@@ -1804,31 +1814,31 @@ function visit(value, path6, containerKey, allowedHosts, seen) {
|
|
|
1804
1814
|
const kind = typeof record.kind === "string" ? record.kind : void 0;
|
|
1805
1815
|
if (kind === "file" && typeof record.path === "string") {
|
|
1806
1816
|
throw new UnsafeOutboundSourceError(
|
|
1807
|
-
`${
|
|
1817
|
+
`${path8}.path`,
|
|
1808
1818
|
"local file sources are disabled for HTTP requests"
|
|
1809
1819
|
);
|
|
1810
1820
|
}
|
|
1811
1821
|
if ((kind === "url" || kind === "variable") && typeof record.url === "string") {
|
|
1812
|
-
assertAllowedUrl(record.url, `${
|
|
1822
|
+
assertAllowedUrl(record.url, `${path8}.url`, allowedHosts);
|
|
1813
1823
|
}
|
|
1814
1824
|
const componentName = typeof record.name === "string" ? record.name.toLowerCase() : void 0;
|
|
1815
1825
|
const props = isRecord(record.props) ? record.props : void 0;
|
|
1816
1826
|
if (componentName && props) {
|
|
1817
1827
|
if (COMPONENT_SOURCE_NAMES.has(componentName) && typeof props.path === "string") {
|
|
1818
|
-
assertAllowedUrl(props.path, `${
|
|
1819
|
-
assertSafeEncodedImage(props.path, `${
|
|
1828
|
+
assertAllowedUrl(props.path, `${path8}.props.path`, allowedHosts);
|
|
1829
|
+
assertSafeEncodedImage(props.path, `${path8}.props.path`, allowedHosts);
|
|
1820
1830
|
}
|
|
1821
1831
|
if (COMPONENT_SOURCE_NAMES.has(componentName) && typeof props.base64 === "string") {
|
|
1822
1832
|
assertSafeEncodedImage(
|
|
1823
1833
|
props.base64,
|
|
1824
|
-
`${
|
|
1834
|
+
`${path8}.props.base64`,
|
|
1825
1835
|
allowedHosts
|
|
1826
1836
|
);
|
|
1827
1837
|
}
|
|
1828
1838
|
if ((componentName === "highcharts" || componentName === "visual") && typeof props.serverUrl === "string") {
|
|
1829
1839
|
assertAllowedUrl(
|
|
1830
1840
|
props.serverUrl,
|
|
1831
|
-
`${
|
|
1841
|
+
`${path8}.props.serverUrl`,
|
|
1832
1842
|
allowedHosts
|
|
1833
1843
|
);
|
|
1834
1844
|
}
|
|
@@ -1836,30 +1846,30 @@ function visit(value, path6, containerKey, allowedHosts, seen) {
|
|
|
1836
1846
|
if (isRecord(props.resources)) {
|
|
1837
1847
|
assertSafeResources(
|
|
1838
1848
|
props.resources,
|
|
1839
|
-
`${
|
|
1849
|
+
`${path8}.props.resources`,
|
|
1840
1850
|
allowedHosts
|
|
1841
1851
|
);
|
|
1842
1852
|
}
|
|
1843
1853
|
assertNoRemoteReferences(
|
|
1844
1854
|
props.options,
|
|
1845
|
-
`${
|
|
1855
|
+
`${path8}.props.options`,
|
|
1846
1856
|
allowedHosts,
|
|
1847
1857
|
/* @__PURE__ */ new WeakSet()
|
|
1848
1858
|
);
|
|
1849
1859
|
}
|
|
1850
1860
|
}
|
|
1851
1861
|
if (containerKey === "image" && typeof record.path === "string") {
|
|
1852
|
-
assertAllowedUrl(record.path, `${
|
|
1853
|
-
assertSafeEncodedImage(record.path, `${
|
|
1862
|
+
assertAllowedUrl(record.path, `${path8}.path`, allowedHosts);
|
|
1863
|
+
assertSafeEncodedImage(record.path, `${path8}.path`, allowedHosts);
|
|
1854
1864
|
}
|
|
1855
1865
|
if (typeof record.svg === "string") {
|
|
1856
|
-
assertSafeSvg(record.svg, `${
|
|
1866
|
+
assertSafeSvg(record.svg, `${path8}.svg`, allowedHosts);
|
|
1857
1867
|
}
|
|
1858
1868
|
if (containerKey === "resources") {
|
|
1859
|
-
assertSafeResources(record,
|
|
1869
|
+
assertSafeResources(record, path8, allowedHosts);
|
|
1860
1870
|
}
|
|
1861
1871
|
for (const [key, child] of Object.entries(record)) {
|
|
1862
|
-
visit(child, `${
|
|
1872
|
+
visit(child, `${path8}.${key}`, key, allowedHosts, seen);
|
|
1863
1873
|
}
|
|
1864
1874
|
}
|
|
1865
1875
|
function assertSafeOutboundSources(value, policy, rootPath = "request") {
|
|
@@ -1880,9 +1890,9 @@ var init_outbound_source_policy = __esm({
|
|
|
1880
1890
|
"use strict";
|
|
1881
1891
|
init_esm_shims();
|
|
1882
1892
|
UnsafeOutboundSourceError = class extends Error {
|
|
1883
|
-
constructor(
|
|
1884
|
-
super(`Unsafe outbound source at ${
|
|
1885
|
-
this.path =
|
|
1893
|
+
constructor(path8, reason) {
|
|
1894
|
+
super(`Unsafe outbound source at ${path8}: ${reason}`);
|
|
1895
|
+
this.path = path8;
|
|
1886
1896
|
this.name = "UnsafeOutboundSourceError";
|
|
1887
1897
|
}
|
|
1888
1898
|
};
|
|
@@ -1892,6 +1902,7 @@ var init_outbound_source_policy = __esm({
|
|
|
1892
1902
|
});
|
|
1893
1903
|
|
|
1894
1904
|
// src/server/rasterize-route.ts
|
|
1905
|
+
import path6 from "path";
|
|
1895
1906
|
import { Type as Type2 } from "@sinclair/typebox";
|
|
1896
1907
|
import { bodyLimit } from "hono/body-limit";
|
|
1897
1908
|
import { HTTPException as HTTPException3 } from "hono/http-exception";
|
|
@@ -1922,7 +1933,18 @@ function registerRasterizeRoute(router, options = {}) {
|
|
|
1922
1933
|
jsonOnly,
|
|
1923
1934
|
tbValidator(RasterizeRequestSchema),
|
|
1924
1935
|
async (c) => {
|
|
1925
|
-
const { presentation, dpi } = getValidated(c, "json");
|
|
1936
|
+
const { presentation, dpi, baseDir } = getValidated(c, "json");
|
|
1937
|
+
let safeBaseDir;
|
|
1938
|
+
if (baseDir !== void 0) {
|
|
1939
|
+
const resolved = path6.resolve(baseDir);
|
|
1940
|
+
const cwd = process.cwd();
|
|
1941
|
+
if (resolved !== cwd && !resolved.startsWith(cwd + path6.sep)) {
|
|
1942
|
+
throw new HTTPException3(400, {
|
|
1943
|
+
message: "baseDir must be inside the server working directory"
|
|
1944
|
+
});
|
|
1945
|
+
}
|
|
1946
|
+
safeBaseDir = resolved;
|
|
1947
|
+
}
|
|
1926
1948
|
try {
|
|
1927
1949
|
if (options.sourcePolicy) {
|
|
1928
1950
|
assertSafeOutboundSources(
|
|
@@ -1933,7 +1955,8 @@ function registerRasterizeRoute(router, options = {}) {
|
|
|
1933
1955
|
}
|
|
1934
1956
|
const result = await getRasterizer()({
|
|
1935
1957
|
presentation,
|
|
1936
|
-
dpi: clampVisualDpi(dpi ?? DEFAULT_VISUAL_DPI)
|
|
1958
|
+
dpi: clampVisualDpi(dpi ?? DEFAULT_VISUAL_DPI),
|
|
1959
|
+
baseDir: safeBaseDir
|
|
1937
1960
|
});
|
|
1938
1961
|
return c.json(result);
|
|
1939
1962
|
} catch (error) {
|
|
@@ -1968,7 +1991,8 @@ var init_rasterize_route = __esm({
|
|
|
1968
1991
|
presentation: Type2.Object({}, { additionalProperties: true }),
|
|
1969
1992
|
dpi: Type2.Optional(
|
|
1970
1993
|
Type2.Number({ minimum: MIN_VISUAL_DPI, maximum: MAX_VISUAL_DPI })
|
|
1971
|
-
)
|
|
1994
|
+
),
|
|
1995
|
+
baseDir: Type2.Optional(Type2.String())
|
|
1972
1996
|
},
|
|
1973
1997
|
{ additionalProperties: false }
|
|
1974
1998
|
);
|
|
@@ -1984,16 +2008,132 @@ var init_rasterize_route = __esm({
|
|
|
1984
2008
|
}
|
|
1985
2009
|
});
|
|
1986
2010
|
|
|
2011
|
+
// src/server/services/template-media-inliner.ts
|
|
2012
|
+
import { promises as fs5 } from "fs";
|
|
2013
|
+
import path7 from "path";
|
|
2014
|
+
function isRecord2(value) {
|
|
2015
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2016
|
+
}
|
|
2017
|
+
function isInlineCandidate(source) {
|
|
2018
|
+
if (!source || source.includes("\0")) return false;
|
|
2019
|
+
if (source.startsWith("data:")) return false;
|
|
2020
|
+
if (path7.isAbsolute(source)) return false;
|
|
2021
|
+
try {
|
|
2022
|
+
new URL(source);
|
|
2023
|
+
return false;
|
|
2024
|
+
} catch {
|
|
2025
|
+
return true;
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
async function toDataUrl(source, baseDir, state) {
|
|
2029
|
+
let cacheKey = source;
|
|
2030
|
+
let result = null;
|
|
2031
|
+
try {
|
|
2032
|
+
const resolved = await fs5.realpath(path7.resolve(baseDir, source));
|
|
2033
|
+
cacheKey = resolved;
|
|
2034
|
+
const cached2 = state.cache.get(cacheKey);
|
|
2035
|
+
if (cached2 !== void 0) return cached2;
|
|
2036
|
+
const contained = resolved === state.baseDirReal || resolved.startsWith(state.baseDirReal + path7.sep);
|
|
2037
|
+
if (contained) {
|
|
2038
|
+
const mime = MIME_BY_EXTENSION[path7.extname(resolved).toLowerCase()];
|
|
2039
|
+
if (mime) {
|
|
2040
|
+
const stat = await fs5.stat(resolved);
|
|
2041
|
+
if (stat.isFile() && stat.size <= state.maxFileBytes && stat.size <= state.totalBudget) {
|
|
2042
|
+
const buffer = await fs5.readFile(resolved);
|
|
2043
|
+
state.totalBudget -= buffer.length;
|
|
2044
|
+
result = `data:${mime};base64,${buffer.toString("base64")}`;
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
} catch {
|
|
2049
|
+
}
|
|
2050
|
+
state.cache.set(cacheKey, result);
|
|
2051
|
+
return result;
|
|
2052
|
+
}
|
|
2053
|
+
async function visit2(value, containerKey, baseDir, state, seen) {
|
|
2054
|
+
if (!value || typeof value !== "object" || seen.has(value)) return;
|
|
2055
|
+
seen.add(value);
|
|
2056
|
+
if (Array.isArray(value)) {
|
|
2057
|
+
for (const entry of value) {
|
|
2058
|
+
await visit2(entry, containerKey, baseDir, state, seen);
|
|
2059
|
+
}
|
|
2060
|
+
return;
|
|
2061
|
+
}
|
|
2062
|
+
const record = value;
|
|
2063
|
+
const componentName = typeof record.name === "string" ? record.name.toLowerCase() : void 0;
|
|
2064
|
+
const props = isRecord2(record.props) ? record.props : void 0;
|
|
2065
|
+
if (componentName === "image" && props && typeof props.path === "string" && isInlineCandidate(props.path)) {
|
|
2066
|
+
const inlined = await toDataUrl(props.path, baseDir, state);
|
|
2067
|
+
if (inlined !== null) props.path = inlined;
|
|
2068
|
+
}
|
|
2069
|
+
if (containerKey === "image" && typeof record.path === "string" && isInlineCandidate(record.path)) {
|
|
2070
|
+
const inlined = await toDataUrl(record.path, baseDir, state);
|
|
2071
|
+
if (inlined !== null) record.path = inlined;
|
|
2072
|
+
}
|
|
2073
|
+
for (const [key, child] of Object.entries(record)) {
|
|
2074
|
+
await visit2(child, key, baseDir, state, seen);
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
async function inlineTemplateMedia(jsonDefinition, baseDir, options = {}) {
|
|
2078
|
+
if (typeof jsonDefinition === "string") {
|
|
2079
|
+
try {
|
|
2080
|
+
jsonDefinition = JSON.parse(jsonDefinition);
|
|
2081
|
+
} catch {
|
|
2082
|
+
return jsonDefinition;
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
if (!jsonDefinition || typeof jsonDefinition !== "object") {
|
|
2086
|
+
return jsonDefinition;
|
|
2087
|
+
}
|
|
2088
|
+
let baseDirReal;
|
|
2089
|
+
try {
|
|
2090
|
+
baseDirReal = await fs5.realpath(baseDir);
|
|
2091
|
+
} catch {
|
|
2092
|
+
return jsonDefinition;
|
|
2093
|
+
}
|
|
2094
|
+
const clone = structuredClone(jsonDefinition);
|
|
2095
|
+
const state = {
|
|
2096
|
+
baseDirReal,
|
|
2097
|
+
maxFileBytes: options.maxFileBytes ?? 10 * 1024 * 1024,
|
|
2098
|
+
totalBudget: options.maxTotalBytes ?? 32 * 1024 * 1024,
|
|
2099
|
+
cache: /* @__PURE__ */ new Map()
|
|
2100
|
+
};
|
|
2101
|
+
await visit2(clone, void 0, baseDir, state, /* @__PURE__ */ new WeakSet());
|
|
2102
|
+
return clone;
|
|
2103
|
+
}
|
|
2104
|
+
var MIME_BY_EXTENSION;
|
|
2105
|
+
var init_template_media_inliner = __esm({
|
|
2106
|
+
"src/server/services/template-media-inliner.ts"() {
|
|
2107
|
+
"use strict";
|
|
2108
|
+
init_esm_shims();
|
|
2109
|
+
MIME_BY_EXTENSION = {
|
|
2110
|
+
".png": "image/png",
|
|
2111
|
+
".jpg": "image/jpeg",
|
|
2112
|
+
".jpeg": "image/jpeg",
|
|
2113
|
+
".gif": "image/gif",
|
|
2114
|
+
".svg": "image/svg+xml",
|
|
2115
|
+
".webp": "image/webp",
|
|
2116
|
+
".bmp": "image/bmp",
|
|
2117
|
+
".tiff": "image/tiff",
|
|
2118
|
+
".tif": "image/tiff"
|
|
2119
|
+
};
|
|
2120
|
+
}
|
|
2121
|
+
});
|
|
2122
|
+
|
|
1987
2123
|
// src/server/routes/format.ts
|
|
1988
2124
|
import { Hono as Hono2 } from "hono";
|
|
1989
2125
|
import { HTTPException as HTTPException4 } from "hono/http-exception";
|
|
1990
2126
|
import { bodyLimit as bodyLimit2 } from "hono/body-limit";
|
|
1991
|
-
import {
|
|
2127
|
+
import {
|
|
2128
|
+
PluginRegistry as PluginRegistry2,
|
|
2129
|
+
PluginDiscoveryService
|
|
2130
|
+
} from "@json-to-office/jto-cli";
|
|
2131
|
+
import { dirname } from "path";
|
|
1992
2132
|
function createFormatRouter(adapter) {
|
|
1993
2133
|
const router = new Hono2();
|
|
1994
|
-
const assertRequestSources = (value,
|
|
2134
|
+
const assertRequestSources = (value, path8) => {
|
|
1995
2135
|
try {
|
|
1996
|
-
assertSafeOutboundSources(value, config.outboundSources,
|
|
2136
|
+
assertSafeOutboundSources(value, config.outboundSources, path8);
|
|
1997
2137
|
} catch (error) {
|
|
1998
2138
|
if (error instanceof UnsafeOutboundSourceError) {
|
|
1999
2139
|
throw new HTTPException4(400, { message: error.message });
|
|
@@ -2001,6 +2141,35 @@ function createFormatRouter(adapter) {
|
|
|
2001
2141
|
throw error;
|
|
2002
2142
|
}
|
|
2003
2143
|
};
|
|
2144
|
+
const resolveSourceBaseDir = async (options) => {
|
|
2145
|
+
const sourceName = options?.sourceName;
|
|
2146
|
+
if (typeof sourceName !== "string" || sourceName.length === 0) {
|
|
2147
|
+
return void 0;
|
|
2148
|
+
}
|
|
2149
|
+
try {
|
|
2150
|
+
const discovery = new PluginDiscoveryService({
|
|
2151
|
+
maxDepth: 10,
|
|
2152
|
+
includeNodeModules: false,
|
|
2153
|
+
verbose: false
|
|
2154
|
+
});
|
|
2155
|
+
const documents = await discovery.discoverDocuments(
|
|
2156
|
+
adapter.name
|
|
2157
|
+
);
|
|
2158
|
+
const match = documents.find((doc) => doc.name === sourceName);
|
|
2159
|
+
return match ? dirname(match.path) : void 0;
|
|
2160
|
+
} catch {
|
|
2161
|
+
return void 0;
|
|
2162
|
+
}
|
|
2163
|
+
};
|
|
2164
|
+
const inlineDiscoveredMedia = async (jsonDefinition, baseDir) => {
|
|
2165
|
+
if (baseDir === void 0 || config.outboundSources.mode === "development") {
|
|
2166
|
+
return jsonDefinition;
|
|
2167
|
+
}
|
|
2168
|
+
return inlineTemplateMedia(jsonDefinition, baseDir, {
|
|
2169
|
+
maxFileBytes: config.requestLimits.maxFileSize,
|
|
2170
|
+
maxTotalBytes: config.requestLimits.maxBodySize
|
|
2171
|
+
});
|
|
2172
|
+
};
|
|
2004
2173
|
const contentTypeMw = async (c, next) => {
|
|
2005
2174
|
const contentType = c.req.header("content-type");
|
|
2006
2175
|
if (!contentType || !contentType.includes("application/json")) {
|
|
@@ -2024,7 +2193,12 @@ function createFormatRouter(adapter) {
|
|
|
2024
2193
|
const { jsonDefinition, customThemes, options } = getValidated(c, "json");
|
|
2025
2194
|
const requestId = c.get("requestId");
|
|
2026
2195
|
try {
|
|
2027
|
-
|
|
2196
|
+
const baseDir = await resolveSourceBaseDir(options);
|
|
2197
|
+
const effectiveDefinition = await inlineDiscoveredMedia(
|
|
2198
|
+
jsonDefinition,
|
|
2199
|
+
baseDir
|
|
2200
|
+
);
|
|
2201
|
+
assertRequestSources(effectiveDefinition, "jsonDefinition");
|
|
2028
2202
|
assertRequestSources(customThemes, "customThemes");
|
|
2029
2203
|
assertRequestSources(options, "options");
|
|
2030
2204
|
const bypassCache = c.req.header("X-Bypass-Cache") === "true" || c.req.query("bypass-cache") === "true" || options?.bypassCache === true;
|
|
@@ -2036,12 +2210,15 @@ function createFormatRouter(adapter) {
|
|
|
2036
2210
|
} else if (rawFonts) {
|
|
2037
2211
|
sanitizedFonts = rawFonts;
|
|
2038
2212
|
}
|
|
2213
|
+
const clientOptions = { ...options };
|
|
2214
|
+
delete clientOptions.baseDir;
|
|
2039
2215
|
const result = await generatorService.generate({
|
|
2040
|
-
jsonDefinition,
|
|
2216
|
+
jsonDefinition: effectiveDefinition,
|
|
2041
2217
|
customThemes,
|
|
2042
2218
|
options: {
|
|
2043
|
-
...
|
|
2219
|
+
...clientOptions,
|
|
2044
2220
|
...sanitizedFonts !== void 0 && { fonts: sanitizedFonts },
|
|
2221
|
+
...baseDir !== void 0 && { baseDir },
|
|
2045
2222
|
bypassCache
|
|
2046
2223
|
}
|
|
2047
2224
|
});
|
|
@@ -2298,14 +2475,23 @@ function createFormatRouter(adapter) {
|
|
|
2298
2475
|
const libreOfficeService = getContainer().get(
|
|
2299
2476
|
"libreOfficeConverterService"
|
|
2300
2477
|
);
|
|
2301
|
-
const { jsonDefinition, customThemes } = getValidated(c, "json");
|
|
2478
|
+
const { jsonDefinition, customThemes, options } = getValidated(c, "json");
|
|
2302
2479
|
try {
|
|
2303
|
-
|
|
2480
|
+
const baseDir = await resolveSourceBaseDir(options);
|
|
2481
|
+
const effectiveDefinition = await inlineDiscoveredMedia(
|
|
2482
|
+
jsonDefinition,
|
|
2483
|
+
baseDir
|
|
2484
|
+
);
|
|
2485
|
+
assertRequestSources(effectiveDefinition, "jsonDefinition");
|
|
2304
2486
|
assertRequestSources(customThemes, "customThemes");
|
|
2487
|
+
assertRequestSources(options, "options");
|
|
2305
2488
|
const generated = await generatorService.generate({
|
|
2306
|
-
jsonDefinition,
|
|
2489
|
+
jsonDefinition: effectiveDefinition,
|
|
2307
2490
|
customThemes,
|
|
2308
|
-
options: {
|
|
2491
|
+
options: {
|
|
2492
|
+
bypassCache: true,
|
|
2493
|
+
...baseDir !== void 0 && { baseDir }
|
|
2494
|
+
}
|
|
2309
2495
|
});
|
|
2310
2496
|
const pdfBuffer = await libreOfficeService.convertToPdf(
|
|
2311
2497
|
generated.buffer,
|
|
@@ -2473,13 +2659,14 @@ var init_format = __esm({
|
|
|
2473
2659
|
init_config();
|
|
2474
2660
|
init_outbound_source_policy();
|
|
2475
2661
|
init_libreoffice_converter();
|
|
2662
|
+
init_template_media_inliner();
|
|
2476
2663
|
}
|
|
2477
2664
|
});
|
|
2478
2665
|
|
|
2479
2666
|
// src/server/routes/discovery.ts
|
|
2480
2667
|
import { Hono as Hono3 } from "hono";
|
|
2481
2668
|
import {
|
|
2482
|
-
PluginDiscoveryService,
|
|
2669
|
+
PluginDiscoveryService as PluginDiscoveryService2,
|
|
2483
2670
|
PluginRegistry as PluginRegistry3
|
|
2484
2671
|
} from "@json-to-office/jto-cli";
|
|
2485
2672
|
import { latestVersion } from "@json-to-office/shared";
|
|
@@ -2590,7 +2777,7 @@ var init_discovery = __esm({
|
|
|
2590
2777
|
discoveryRouter.get("/all", async (c) => {
|
|
2591
2778
|
try {
|
|
2592
2779
|
const format = Container.getAdapter().name;
|
|
2593
|
-
const discovery = new
|
|
2780
|
+
const discovery = new PluginDiscoveryService2({
|
|
2594
2781
|
maxDepth: 10,
|
|
2595
2782
|
includeNodeModules: false,
|
|
2596
2783
|
verbose: false
|
|
@@ -2620,7 +2807,7 @@ var init_discovery = __esm({
|
|
|
2620
2807
|
const includeSchemas = c.req.query("schemas") === "true";
|
|
2621
2808
|
const includeExamples = c.req.query("examples") === "true";
|
|
2622
2809
|
const format = Container.getAdapter().name;
|
|
2623
|
-
const discovery = new
|
|
2810
|
+
const discovery = new PluginDiscoveryService2({
|
|
2624
2811
|
maxDepth: 10,
|
|
2625
2812
|
includeNodeModules: false,
|
|
2626
2813
|
verbose: false
|
|
@@ -2644,7 +2831,7 @@ var init_discovery = __esm({
|
|
|
2644
2831
|
discoveryRouter.get("/documents", async (c) => {
|
|
2645
2832
|
try {
|
|
2646
2833
|
const format = Container.getAdapter().name;
|
|
2647
|
-
const discovery = new
|
|
2834
|
+
const discovery = new PluginDiscoveryService2({
|
|
2648
2835
|
maxDepth: 10,
|
|
2649
2836
|
includeNodeModules: false,
|
|
2650
2837
|
verbose: false
|
|
@@ -2659,7 +2846,7 @@ var init_discovery = __esm({
|
|
|
2659
2846
|
discoveryRouter.get("/themes", async (c) => {
|
|
2660
2847
|
try {
|
|
2661
2848
|
const format = Container.getAdapter().name;
|
|
2662
|
-
const discovery = new
|
|
2849
|
+
const discovery = new PluginDiscoveryService2({
|
|
2663
2850
|
maxDepth: 10,
|
|
2664
2851
|
includeNodeModules: false,
|
|
2665
2852
|
verbose: false
|
|
@@ -2675,7 +2862,7 @@ var init_discovery = __esm({
|
|
|
2675
2862
|
try {
|
|
2676
2863
|
const pluginName = c.req.param("name");
|
|
2677
2864
|
const format = Container.getAdapter().name;
|
|
2678
|
-
const discovery = new
|
|
2865
|
+
const discovery = new PluginDiscoveryService2({
|
|
2679
2866
|
maxDepth: 10,
|
|
2680
2867
|
includeNodeModules: false,
|
|
2681
2868
|
verbose: false
|
|
@@ -2711,7 +2898,7 @@ var init_discovery = __esm({
|
|
|
2711
2898
|
try {
|
|
2712
2899
|
const name = c.req.param("name");
|
|
2713
2900
|
const format = Container.getAdapter().name;
|
|
2714
|
-
const discovery = new
|
|
2901
|
+
const discovery = new PluginDiscoveryService2({
|
|
2715
2902
|
maxDepth: 10,
|
|
2716
2903
|
includeNodeModules: false,
|
|
2717
2904
|
verbose: false
|
|
@@ -2727,7 +2914,7 @@ var init_discovery = __esm({
|
|
|
2727
2914
|
try {
|
|
2728
2915
|
const name = c.req.param("name");
|
|
2729
2916
|
const format = Container.getAdapter().name;
|
|
2730
|
-
const discovery = new
|
|
2917
|
+
const discovery = new PluginDiscoveryService2({
|
|
2731
2918
|
maxDepth: 10,
|
|
2732
2919
|
includeNodeModules: false,
|
|
2733
2920
|
verbose: false
|
|
@@ -2850,7 +3037,7 @@ var init_ai_schema = __esm({
|
|
|
2850
3037
|
|
|
2851
3038
|
// src/server/services/prompt-loader.ts
|
|
2852
3039
|
import { readFileSync, existsSync } from "fs";
|
|
2853
|
-
import { join, dirname } from "path";
|
|
3040
|
+
import { join, dirname as dirname2 } from "path";
|
|
2854
3041
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2855
3042
|
function resolvePromptsDir() {
|
|
2856
3043
|
const candidates = [
|
|
@@ -2885,7 +3072,7 @@ var init_prompt_loader = __esm({
|
|
|
2885
3072
|
"src/server/services/prompt-loader.ts"() {
|
|
2886
3073
|
"use strict";
|
|
2887
3074
|
init_esm_shims();
|
|
2888
|
-
__dirname2 =
|
|
3075
|
+
__dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
2889
3076
|
PROMPTS_DIR = resolvePromptsDir();
|
|
2890
3077
|
cache = /* @__PURE__ */ new Map();
|
|
2891
3078
|
}
|
|
@@ -3760,7 +3947,7 @@ import { Hono as Hono7 } from "hono";
|
|
|
3760
3947
|
import { serve } from "@hono/node-server";
|
|
3761
3948
|
import { logger as logger2 } from "hono/logger";
|
|
3762
3949
|
import { compress } from "hono/compress";
|
|
3763
|
-
import { resolve, dirname as
|
|
3950
|
+
import { resolve, dirname as dirname3 } from "path";
|
|
3764
3951
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3765
3952
|
var __filename2, __dirname3, UnifiedServer;
|
|
3766
3953
|
var init_unified_server = __esm({
|
|
@@ -3770,7 +3957,7 @@ var init_unified_server = __esm({
|
|
|
3770
3957
|
init_app();
|
|
3771
3958
|
init_logger();
|
|
3772
3959
|
__filename2 = fileURLToPath3(import.meta.url);
|
|
3773
|
-
__dirname3 =
|
|
3960
|
+
__dirname3 = dirname3(__filename2);
|
|
3774
3961
|
UnifiedServer = class {
|
|
3775
3962
|
app;
|
|
3776
3963
|
config;
|
|
@@ -3806,9 +3993,9 @@ var init_unified_server = __esm({
|
|
|
3806
3993
|
return await apiApp.fetch(c.req.raw, c.env);
|
|
3807
3994
|
});
|
|
3808
3995
|
this.app.use("*", async (c, next) => {
|
|
3809
|
-
const
|
|
3810
|
-
if (
|
|
3811
|
-
if (/\.(ts|tsx|js|jsx|css|map)$/.test(
|
|
3996
|
+
const path8 = c.req.path;
|
|
3997
|
+
if (path8.startsWith("/api")) {
|
|
3998
|
+
if (/\.(ts|tsx|js|jsx|css|map)$/.test(path8)) {
|
|
3812
3999
|
return next();
|
|
3813
4000
|
}
|
|
3814
4001
|
const response = await apiApp.fetch(c.req.raw, c.env);
|
|
@@ -3911,8 +4098,8 @@ var init_unified_server = __esm({
|
|
|
3911
4098
|
}
|
|
3912
4099
|
if (this.viteServer) {
|
|
3913
4100
|
this.app.use("*", async (c, next) => {
|
|
3914
|
-
const
|
|
3915
|
-
if ((
|
|
4101
|
+
const path8 = c.req.path;
|
|
4102
|
+
if ((path8.startsWith("/api") || path8 === "/health") && !/\.(ts|tsx|js|jsx|css|map)$/.test(path8)) {
|
|
3916
4103
|
return next();
|
|
3917
4104
|
}
|
|
3918
4105
|
const env = c.env;
|
|
@@ -3931,7 +4118,7 @@ var init_unified_server = __esm({
|
|
|
3931
4118
|
}
|
|
3932
4119
|
async setupBuiltClient(clientPath) {
|
|
3933
4120
|
const { serveStatic } = await import("@hono/node-server/serve-static");
|
|
3934
|
-
const
|
|
4121
|
+
const fs6 = await import("fs");
|
|
3935
4122
|
const { extname } = await import("path");
|
|
3936
4123
|
const mime = await import("mime-types");
|
|
3937
4124
|
const format = this.adapter.name.replace(/[^a-zA-Z0-9]/g, "");
|
|
@@ -3939,7 +4126,7 @@ var init_unified_server = __esm({
|
|
|
3939
4126
|
"/assets/*",
|
|
3940
4127
|
serveStatic({
|
|
3941
4128
|
root: clientPath,
|
|
3942
|
-
rewriteRequestPath: (
|
|
4129
|
+
rewriteRequestPath: (path8) => path8.replace(/^\/assets/, "/assets")
|
|
3943
4130
|
})
|
|
3944
4131
|
);
|
|
3945
4132
|
this.app.use("/*", async (c, next) => {
|
|
@@ -3948,9 +4135,9 @@ var init_unified_server = __esm({
|
|
|
3948
4135
|
const ext = extname(reqPath);
|
|
3949
4136
|
if (ext) {
|
|
3950
4137
|
const filePath = resolve(clientPath, reqPath.slice(1));
|
|
3951
|
-
if (
|
|
4138
|
+
if (fs6.existsSync(filePath)) {
|
|
3952
4139
|
const mimeType = mime.lookup(filePath) || "application/octet-stream";
|
|
3953
|
-
const content =
|
|
4140
|
+
const content = fs6.readFileSync(filePath);
|
|
3954
4141
|
c.header("Content-Type", mimeType);
|
|
3955
4142
|
return c.body(content);
|
|
3956
4143
|
}
|
|
@@ -3962,8 +4149,8 @@ var init_unified_server = __esm({
|
|
|
3962
4149
|
if (reqPath.startsWith("/api") || reqPath === "/health")
|
|
3963
4150
|
return c.notFound();
|
|
3964
4151
|
const indexPath = resolve(clientPath, "index.html");
|
|
3965
|
-
if (
|
|
3966
|
-
let html =
|
|
4152
|
+
if (fs6.existsSync(indexPath)) {
|
|
4153
|
+
let html = fs6.readFileSync(indexPath, "utf-8");
|
|
3967
4154
|
html = html.replace(
|
|
3968
4155
|
"</head>",
|
|
3969
4156
|
`<script>window.__JTO_FORMAT__ = '${format}';</script>
|
|
@@ -4124,7 +4311,7 @@ function createDevCommand(adapter) {
|
|
|
4124
4311
|
}
|
|
4125
4312
|
|
|
4126
4313
|
// src/cli.ts
|
|
4127
|
-
var PACKAGE_VERSION = true ? "0.
|
|
4314
|
+
var PACKAGE_VERSION = true ? "0.28.1" : "dev-mode";
|
|
4128
4315
|
var program = new Command2();
|
|
4129
4316
|
program.name("jto").description("JSON to Office CLI - Generate .docx and .pptx from JSON").version(PACKAGE_VERSION);
|
|
4130
4317
|
registerCoreCommands(program, {
|