@json-to-office/jto 0.26.0 → 0.28.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/cli.js +134 -77
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/{HomePage-CcmtpSuV.js → HomePage-BX2wX21e.js} +3 -3
- package/dist/client/assets/HomePage-BX2wX21e.js.map +1 -0
- package/dist/client/assets/{JsonEditorPage-RDa8GWDd.js → JsonEditorPage-DseCjMok.js} +3 -3
- package/dist/client/assets/{JsonEditorPage-RDa8GWDd.js.map → JsonEditorPage-DseCjMok.js.map} +1 -1
- package/dist/client/assets/{MonacoPluginProvider-DM63WAJx.js → MonacoPluginProvider-DvO7h20V.js} +3 -3
- package/dist/client/assets/{MonacoPluginProvider-DM63WAJx.js.map → MonacoPluginProvider-DvO7h20V.js.map} +1 -1
- package/dist/client/assets/{button-CyTe9rTl.js → button-DzgfrDEj.js} +2 -2
- package/dist/client/assets/{button-CyTe9rTl.js.map → button-DzgfrDEj.js.map} +1 -1
- package/dist/client/assets/{editor-DCtGYNz2.js → editor-BDi6QWgh.js} +2 -2
- package/dist/client/assets/{editor-DCtGYNz2.js.map → editor-BDi6QWgh.js.map} +1 -1
- package/dist/client/assets/{editor-monaco-json-CU9ciwPv.js → editor-monaco-json-CsQqBG2A.js} +2 -2
- package/dist/client/assets/{editor-monaco-json-CU9ciwPv.js.map → editor-monaco-json-CsQqBG2A.js.map} +1 -1
- package/dist/client/assets/{index-CHAIoQtG.js → index-Cxjik2Rg.js} +3 -3
- package/dist/client/assets/{index-CHAIoQtG.js.map → index-Cxjik2Rg.js.map} +1 -1
- package/dist/client/assets/preview-BOF6SWhK.js +3 -0
- package/dist/client/assets/preview-BOF6SWhK.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-CcmtpSuV.js.map +0 -1
- package/dist/client/assets/preview-oxnxMi4x.js +0 -3
- package/dist/client/assets/preview-oxnxMi4x.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -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, path7, 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
|
+
path7,
|
|
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(path7, "only HTTPS URLs are allowed");
|
|
1646
1656
|
}
|
|
1647
1657
|
if (url.username || url.password) {
|
|
1648
1658
|
throw new UnsafeOutboundSourceError(
|
|
1649
|
-
|
|
1659
|
+
path7,
|
|
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
|
+
path7,
|
|
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
|
+
path7,
|
|
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, path7, 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(path7, "active SVG content is disabled");
|
|
1683
1693
|
}
|
|
1684
1694
|
if (/<!\s*(?:DOCTYPE|ENTITY)\b/i.test(svg)) {
|
|
1685
1695
|
throw new UnsafeOutboundSourceError(
|
|
1686
|
-
|
|
1696
|
+
path7,
|
|
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, path7, 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, path7, allowedHosts);
|
|
1700
1710
|
}
|
|
1701
1711
|
}
|
|
1702
|
-
function assertSafeEncodedImage(source,
|
|
1712
|
+
function assertSafeEncodedImage(source, path7, 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(path7, "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(path7, "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(path7, "malformed SVG image data");
|
|
1726
1736
|
}
|
|
1727
1737
|
return;
|
|
1728
1738
|
}
|
|
1729
|
-
assertSafeSvg(candidate,
|
|
1739
|
+
assertSafeSvg(candidate, path7, allowedHosts);
|
|
1730
1740
|
}
|
|
1731
|
-
function assertSafeResources(resources,
|
|
1741
|
+
function assertSafeResources(resources, path7, allowedHosts) {
|
|
1732
1742
|
if (typeof resources.js === "string" && resources.js.trim()) {
|
|
1733
1743
|
throw new UnsafeOutboundSourceError(
|
|
1734
|
-
`${
|
|
1744
|
+
`${path7}.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, `${path7}.css`, allowedHosts);
|
|
1742
1752
|
}
|
|
1743
1753
|
}
|
|
1744
1754
|
if (Array.isArray(resources.files) && resources.files.length > 0) {
|
|
1745
1755
|
throw new UnsafeOutboundSourceError(
|
|
1746
|
-
`${
|
|
1756
|
+
`${path7}.files`,
|
|
1747
1757
|
"remote renderer JavaScript resources are disabled"
|
|
1748
1758
|
);
|
|
1749
1759
|
}
|
|
1750
1760
|
}
|
|
1751
|
-
function assertNoRemoteReferences(value,
|
|
1761
|
+
function assertNoRemoteReferences(value, path7, 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
|
+
path7,
|
|
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, path7, allowedHosts);
|
|
1765
1775
|
}
|
|
1766
1776
|
if (/^\/\//.test(value.trim())) {
|
|
1767
1777
|
throw new UnsafeOutboundSourceError(
|
|
1768
|
-
|
|
1778
|
+
path7,
|
|
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, `${path7}[${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, `${path7}.${key}`, allowedHosts, seen);
|
|
1784
1794
|
}
|
|
1785
1795
|
}
|
|
1786
|
-
function visit(value,
|
|
1796
|
+
function visit(value, path7, 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, `${path7}[${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
|
+
`${path7}.${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
|
+
`${path7}.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, `${path7}.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, `${path7}.props.path`, allowedHosts);
|
|
1829
|
+
assertSafeEncodedImage(props.path, `${path7}.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
|
+
`${path7}.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
|
+
`${path7}.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
|
+
`${path7}.props.resources`,
|
|
1840
1850
|
allowedHosts
|
|
1841
1851
|
);
|
|
1842
1852
|
}
|
|
1843
1853
|
assertNoRemoteReferences(
|
|
1844
1854
|
props.options,
|
|
1845
|
-
`${
|
|
1855
|
+
`${path7}.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, `${path7}.path`, allowedHosts);
|
|
1863
|
+
assertSafeEncodedImage(record.path, `${path7}.path`, allowedHosts);
|
|
1854
1864
|
}
|
|
1855
1865
|
if (typeof record.svg === "string") {
|
|
1856
|
-
assertSafeSvg(record.svg, `${
|
|
1866
|
+
assertSafeSvg(record.svg, `${path7}.svg`, allowedHosts);
|
|
1857
1867
|
}
|
|
1858
1868
|
if (containerKey === "resources") {
|
|
1859
|
-
assertSafeResources(record,
|
|
1869
|
+
assertSafeResources(record, path7, allowedHosts);
|
|
1860
1870
|
}
|
|
1861
1871
|
for (const [key, child] of Object.entries(record)) {
|
|
1862
|
-
visit(child, `${
|
|
1872
|
+
visit(child, `${path7}.${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(path7, reason) {
|
|
1894
|
+
super(`Unsafe outbound source at ${path7}: ${reason}`);
|
|
1895
|
+
this.path = path7;
|
|
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
|
);
|
|
@@ -1988,12 +2012,16 @@ var init_rasterize_route = __esm({
|
|
|
1988
2012
|
import { Hono as Hono2 } from "hono";
|
|
1989
2013
|
import { HTTPException as HTTPException4 } from "hono/http-exception";
|
|
1990
2014
|
import { bodyLimit as bodyLimit2 } from "hono/body-limit";
|
|
1991
|
-
import {
|
|
2015
|
+
import {
|
|
2016
|
+
PluginRegistry as PluginRegistry2,
|
|
2017
|
+
PluginDiscoveryService
|
|
2018
|
+
} from "@json-to-office/jto-cli";
|
|
2019
|
+
import { dirname } from "path";
|
|
1992
2020
|
function createFormatRouter(adapter) {
|
|
1993
2021
|
const router = new Hono2();
|
|
1994
|
-
const assertRequestSources = (value,
|
|
2022
|
+
const assertRequestSources = (value, path7) => {
|
|
1995
2023
|
try {
|
|
1996
|
-
assertSafeOutboundSources(value, config.outboundSources,
|
|
2024
|
+
assertSafeOutboundSources(value, config.outboundSources, path7);
|
|
1997
2025
|
} catch (error) {
|
|
1998
2026
|
if (error instanceof UnsafeOutboundSourceError) {
|
|
1999
2027
|
throw new HTTPException4(400, { message: error.message });
|
|
@@ -2001,6 +2029,26 @@ function createFormatRouter(adapter) {
|
|
|
2001
2029
|
throw error;
|
|
2002
2030
|
}
|
|
2003
2031
|
};
|
|
2032
|
+
const resolveSourceBaseDir = async (options) => {
|
|
2033
|
+
const sourceName = options?.sourceName;
|
|
2034
|
+
if (typeof sourceName !== "string" || sourceName.length === 0) {
|
|
2035
|
+
return void 0;
|
|
2036
|
+
}
|
|
2037
|
+
try {
|
|
2038
|
+
const discovery = new PluginDiscoveryService({
|
|
2039
|
+
maxDepth: 10,
|
|
2040
|
+
includeNodeModules: false,
|
|
2041
|
+
verbose: false
|
|
2042
|
+
});
|
|
2043
|
+
const documents = await discovery.discoverDocuments(
|
|
2044
|
+
adapter.name
|
|
2045
|
+
);
|
|
2046
|
+
const match = documents.find((doc) => doc.name === sourceName);
|
|
2047
|
+
return match ? dirname(match.path) : void 0;
|
|
2048
|
+
} catch {
|
|
2049
|
+
return void 0;
|
|
2050
|
+
}
|
|
2051
|
+
};
|
|
2004
2052
|
const contentTypeMw = async (c, next) => {
|
|
2005
2053
|
const contentType = c.req.header("content-type");
|
|
2006
2054
|
if (!contentType || !contentType.includes("application/json")) {
|
|
@@ -2036,12 +2084,16 @@ function createFormatRouter(adapter) {
|
|
|
2036
2084
|
} else if (rawFonts) {
|
|
2037
2085
|
sanitizedFonts = rawFonts;
|
|
2038
2086
|
}
|
|
2087
|
+
const baseDir = await resolveSourceBaseDir(options);
|
|
2088
|
+
const clientOptions = { ...options };
|
|
2089
|
+
delete clientOptions.baseDir;
|
|
2039
2090
|
const result = await generatorService.generate({
|
|
2040
2091
|
jsonDefinition,
|
|
2041
2092
|
customThemes,
|
|
2042
2093
|
options: {
|
|
2043
|
-
...
|
|
2094
|
+
...clientOptions,
|
|
2044
2095
|
...sanitizedFonts !== void 0 && { fonts: sanitizedFonts },
|
|
2096
|
+
...baseDir !== void 0 && { baseDir },
|
|
2045
2097
|
bypassCache
|
|
2046
2098
|
}
|
|
2047
2099
|
});
|
|
@@ -2298,14 +2350,19 @@ function createFormatRouter(adapter) {
|
|
|
2298
2350
|
const libreOfficeService = getContainer().get(
|
|
2299
2351
|
"libreOfficeConverterService"
|
|
2300
2352
|
);
|
|
2301
|
-
const { jsonDefinition, customThemes } = getValidated(c, "json");
|
|
2353
|
+
const { jsonDefinition, customThemes, options } = getValidated(c, "json");
|
|
2302
2354
|
try {
|
|
2303
2355
|
assertRequestSources(jsonDefinition, "jsonDefinition");
|
|
2304
2356
|
assertRequestSources(customThemes, "customThemes");
|
|
2357
|
+
assertRequestSources(options, "options");
|
|
2358
|
+
const baseDir = await resolveSourceBaseDir(options);
|
|
2305
2359
|
const generated = await generatorService.generate({
|
|
2306
2360
|
jsonDefinition,
|
|
2307
2361
|
customThemes,
|
|
2308
|
-
options: {
|
|
2362
|
+
options: {
|
|
2363
|
+
bypassCache: true,
|
|
2364
|
+
...baseDir !== void 0 && { baseDir }
|
|
2365
|
+
}
|
|
2309
2366
|
});
|
|
2310
2367
|
const pdfBuffer = await libreOfficeService.convertToPdf(
|
|
2311
2368
|
generated.buffer,
|
|
@@ -2479,7 +2536,7 @@ var init_format = __esm({
|
|
|
2479
2536
|
// src/server/routes/discovery.ts
|
|
2480
2537
|
import { Hono as Hono3 } from "hono";
|
|
2481
2538
|
import {
|
|
2482
|
-
PluginDiscoveryService,
|
|
2539
|
+
PluginDiscoveryService as PluginDiscoveryService2,
|
|
2483
2540
|
PluginRegistry as PluginRegistry3
|
|
2484
2541
|
} from "@json-to-office/jto-cli";
|
|
2485
2542
|
import { latestVersion } from "@json-to-office/shared";
|
|
@@ -2590,7 +2647,7 @@ var init_discovery = __esm({
|
|
|
2590
2647
|
discoveryRouter.get("/all", async (c) => {
|
|
2591
2648
|
try {
|
|
2592
2649
|
const format = Container.getAdapter().name;
|
|
2593
|
-
const discovery = new
|
|
2650
|
+
const discovery = new PluginDiscoveryService2({
|
|
2594
2651
|
maxDepth: 10,
|
|
2595
2652
|
includeNodeModules: false,
|
|
2596
2653
|
verbose: false
|
|
@@ -2620,7 +2677,7 @@ var init_discovery = __esm({
|
|
|
2620
2677
|
const includeSchemas = c.req.query("schemas") === "true";
|
|
2621
2678
|
const includeExamples = c.req.query("examples") === "true";
|
|
2622
2679
|
const format = Container.getAdapter().name;
|
|
2623
|
-
const discovery = new
|
|
2680
|
+
const discovery = new PluginDiscoveryService2({
|
|
2624
2681
|
maxDepth: 10,
|
|
2625
2682
|
includeNodeModules: false,
|
|
2626
2683
|
verbose: false
|
|
@@ -2644,7 +2701,7 @@ var init_discovery = __esm({
|
|
|
2644
2701
|
discoveryRouter.get("/documents", async (c) => {
|
|
2645
2702
|
try {
|
|
2646
2703
|
const format = Container.getAdapter().name;
|
|
2647
|
-
const discovery = new
|
|
2704
|
+
const discovery = new PluginDiscoveryService2({
|
|
2648
2705
|
maxDepth: 10,
|
|
2649
2706
|
includeNodeModules: false,
|
|
2650
2707
|
verbose: false
|
|
@@ -2659,7 +2716,7 @@ var init_discovery = __esm({
|
|
|
2659
2716
|
discoveryRouter.get("/themes", async (c) => {
|
|
2660
2717
|
try {
|
|
2661
2718
|
const format = Container.getAdapter().name;
|
|
2662
|
-
const discovery = new
|
|
2719
|
+
const discovery = new PluginDiscoveryService2({
|
|
2663
2720
|
maxDepth: 10,
|
|
2664
2721
|
includeNodeModules: false,
|
|
2665
2722
|
verbose: false
|
|
@@ -2675,7 +2732,7 @@ var init_discovery = __esm({
|
|
|
2675
2732
|
try {
|
|
2676
2733
|
const pluginName = c.req.param("name");
|
|
2677
2734
|
const format = Container.getAdapter().name;
|
|
2678
|
-
const discovery = new
|
|
2735
|
+
const discovery = new PluginDiscoveryService2({
|
|
2679
2736
|
maxDepth: 10,
|
|
2680
2737
|
includeNodeModules: false,
|
|
2681
2738
|
verbose: false
|
|
@@ -2711,7 +2768,7 @@ var init_discovery = __esm({
|
|
|
2711
2768
|
try {
|
|
2712
2769
|
const name = c.req.param("name");
|
|
2713
2770
|
const format = Container.getAdapter().name;
|
|
2714
|
-
const discovery = new
|
|
2771
|
+
const discovery = new PluginDiscoveryService2({
|
|
2715
2772
|
maxDepth: 10,
|
|
2716
2773
|
includeNodeModules: false,
|
|
2717
2774
|
verbose: false
|
|
@@ -2727,7 +2784,7 @@ var init_discovery = __esm({
|
|
|
2727
2784
|
try {
|
|
2728
2785
|
const name = c.req.param("name");
|
|
2729
2786
|
const format = Container.getAdapter().name;
|
|
2730
|
-
const discovery = new
|
|
2787
|
+
const discovery = new PluginDiscoveryService2({
|
|
2731
2788
|
maxDepth: 10,
|
|
2732
2789
|
includeNodeModules: false,
|
|
2733
2790
|
verbose: false
|
|
@@ -2850,7 +2907,7 @@ var init_ai_schema = __esm({
|
|
|
2850
2907
|
|
|
2851
2908
|
// src/server/services/prompt-loader.ts
|
|
2852
2909
|
import { readFileSync, existsSync } from "fs";
|
|
2853
|
-
import { join, dirname } from "path";
|
|
2910
|
+
import { join, dirname as dirname2 } from "path";
|
|
2854
2911
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2855
2912
|
function resolvePromptsDir() {
|
|
2856
2913
|
const candidates = [
|
|
@@ -2885,7 +2942,7 @@ var init_prompt_loader = __esm({
|
|
|
2885
2942
|
"src/server/services/prompt-loader.ts"() {
|
|
2886
2943
|
"use strict";
|
|
2887
2944
|
init_esm_shims();
|
|
2888
|
-
__dirname2 =
|
|
2945
|
+
__dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
2889
2946
|
PROMPTS_DIR = resolvePromptsDir();
|
|
2890
2947
|
cache = /* @__PURE__ */ new Map();
|
|
2891
2948
|
}
|
|
@@ -3760,7 +3817,7 @@ import { Hono as Hono7 } from "hono";
|
|
|
3760
3817
|
import { serve } from "@hono/node-server";
|
|
3761
3818
|
import { logger as logger2 } from "hono/logger";
|
|
3762
3819
|
import { compress } from "hono/compress";
|
|
3763
|
-
import { resolve, dirname as
|
|
3820
|
+
import { resolve, dirname as dirname3 } from "path";
|
|
3764
3821
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3765
3822
|
var __filename2, __dirname3, UnifiedServer;
|
|
3766
3823
|
var init_unified_server = __esm({
|
|
@@ -3770,7 +3827,7 @@ var init_unified_server = __esm({
|
|
|
3770
3827
|
init_app();
|
|
3771
3828
|
init_logger();
|
|
3772
3829
|
__filename2 = fileURLToPath3(import.meta.url);
|
|
3773
|
-
__dirname3 =
|
|
3830
|
+
__dirname3 = dirname3(__filename2);
|
|
3774
3831
|
UnifiedServer = class {
|
|
3775
3832
|
app;
|
|
3776
3833
|
config;
|
|
@@ -3806,9 +3863,9 @@ var init_unified_server = __esm({
|
|
|
3806
3863
|
return await apiApp.fetch(c.req.raw, c.env);
|
|
3807
3864
|
});
|
|
3808
3865
|
this.app.use("*", async (c, next) => {
|
|
3809
|
-
const
|
|
3810
|
-
if (
|
|
3811
|
-
if (/\.(ts|tsx|js|jsx|css|map)$/.test(
|
|
3866
|
+
const path7 = c.req.path;
|
|
3867
|
+
if (path7.startsWith("/api")) {
|
|
3868
|
+
if (/\.(ts|tsx|js|jsx|css|map)$/.test(path7)) {
|
|
3812
3869
|
return next();
|
|
3813
3870
|
}
|
|
3814
3871
|
const response = await apiApp.fetch(c.req.raw, c.env);
|
|
@@ -3911,8 +3968,8 @@ var init_unified_server = __esm({
|
|
|
3911
3968
|
}
|
|
3912
3969
|
if (this.viteServer) {
|
|
3913
3970
|
this.app.use("*", async (c, next) => {
|
|
3914
|
-
const
|
|
3915
|
-
if ((
|
|
3971
|
+
const path7 = c.req.path;
|
|
3972
|
+
if ((path7.startsWith("/api") || path7 === "/health") && !/\.(ts|tsx|js|jsx|css|map)$/.test(path7)) {
|
|
3916
3973
|
return next();
|
|
3917
3974
|
}
|
|
3918
3975
|
const env = c.env;
|
|
@@ -3939,7 +3996,7 @@ var init_unified_server = __esm({
|
|
|
3939
3996
|
"/assets/*",
|
|
3940
3997
|
serveStatic({
|
|
3941
3998
|
root: clientPath,
|
|
3942
|
-
rewriteRequestPath: (
|
|
3999
|
+
rewriteRequestPath: (path7) => path7.replace(/^\/assets/, "/assets")
|
|
3943
4000
|
})
|
|
3944
4001
|
);
|
|
3945
4002
|
this.app.use("/*", async (c, next) => {
|
|
@@ -4124,7 +4181,7 @@ function createDevCommand(adapter) {
|
|
|
4124
4181
|
}
|
|
4125
4182
|
|
|
4126
4183
|
// src/cli.ts
|
|
4127
|
-
var PACKAGE_VERSION = true ? "0.
|
|
4184
|
+
var PACKAGE_VERSION = true ? "0.28.0" : "dev-mode";
|
|
4128
4185
|
var program = new Command2();
|
|
4129
4186
|
program.name("jto").description("JSON to Office CLI - Generate .docx and .pptx from JSON").version(PACKAGE_VERSION);
|
|
4130
4187
|
registerCoreCommands(program, {
|