diorama-js 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +156 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +156 -15
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +159 -16
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +10 -0
- package/dist/react.d.ts +10 -0
- package/dist/react.js +159 -16
- package/dist/react.js.map +1 -1
- package/dist/svelte.cjs +157 -15
- package/dist/svelte.cjs.map +1 -1
- package/dist/svelte.d.cts +10 -0
- package/dist/svelte.d.ts +10 -0
- package/dist/svelte.js +157 -15
- package/dist/svelte.js.map +1 -1
- package/dist/vue.cjs +159 -16
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +8 -0
- package/dist/vue.d.ts +8 -0
- package/dist/vue.js +159 -16
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
package/dist/react.cjs
CHANGED
|
@@ -626,6 +626,7 @@ function analyzeProject(project, overrideType, overrideEntry) {
|
|
|
626
626
|
hasBareImports: hasBareImports(files),
|
|
627
627
|
isVite
|
|
628
628
|
});
|
|
629
|
+
const usesTailwind = usesTailwindCSS(files);
|
|
629
630
|
return {
|
|
630
631
|
type,
|
|
631
632
|
entryPoint: htmlEntry,
|
|
@@ -634,7 +635,8 @@ function analyzeProject(project, overrideType, overrideEntry) {
|
|
|
634
635
|
hasJSX,
|
|
635
636
|
hasTypeScript,
|
|
636
637
|
jsEntryPoint: jsEntry,
|
|
637
|
-
isVite
|
|
638
|
+
isVite,
|
|
639
|
+
usesTailwind
|
|
638
640
|
};
|
|
639
641
|
}
|
|
640
642
|
function detectProjectType(input) {
|
|
@@ -656,6 +658,17 @@ function hasBareImports(files) {
|
|
|
656
658
|
}
|
|
657
659
|
return false;
|
|
658
660
|
}
|
|
661
|
+
function usesTailwindCSS(files) {
|
|
662
|
+
for (const [path, content] of files) {
|
|
663
|
+
if (/(?:^|\/)tailwind\.config\.(?:js|cjs|mjs|ts)$/.test(path)) {
|
|
664
|
+
return true;
|
|
665
|
+
}
|
|
666
|
+
if (path.endsWith(".css") && /@tailwind\b|@apply\b/.test(content)) {
|
|
667
|
+
return true;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
return false;
|
|
671
|
+
}
|
|
659
672
|
|
|
660
673
|
// src/core/sandbox.ts
|
|
661
674
|
function buildErrorHTML(message) {
|
|
@@ -1510,6 +1523,18 @@ function getCDNProvider(name) {
|
|
|
1510
1523
|
return esmShProvider;
|
|
1511
1524
|
}
|
|
1512
1525
|
}
|
|
1526
|
+
function buildCSSURL(specifier, options = {}) {
|
|
1527
|
+
const { dependencies = {}, cdnProvider = "esm.sh" } = options;
|
|
1528
|
+
const clean = specifier.replace(/[?#].*$/, "");
|
|
1529
|
+
const { packageName, subpath } = parseSpecifier(clean);
|
|
1530
|
+
const version = dependencies[packageName];
|
|
1531
|
+
const ver = version ? `@${version}` : "";
|
|
1532
|
+
const sub = subpath ? `/${subpath}` : "";
|
|
1533
|
+
if (cdnProvider === "unpkg") {
|
|
1534
|
+
return `https://unpkg.com/${packageName}${ver}${sub}`;
|
|
1535
|
+
}
|
|
1536
|
+
return `https://esm.sh/${packageName}${ver}${sub}`;
|
|
1537
|
+
}
|
|
1513
1538
|
function rewriteImports(source, options = {}) {
|
|
1514
1539
|
const {
|
|
1515
1540
|
dependencies = {},
|
|
@@ -1523,6 +1548,9 @@ function rewriteImports(source, options = {}) {
|
|
|
1523
1548
|
if (raw.startsWith(".") || raw.startsWith("/") || /^https?:\/\//.test(raw)) {
|
|
1524
1549
|
return raw;
|
|
1525
1550
|
}
|
|
1551
|
+
if (/\.css(?:[?#]|$)/.test(raw)) {
|
|
1552
|
+
return raw;
|
|
1553
|
+
}
|
|
1526
1554
|
const { packageName, subpath } = parseSpecifier(raw);
|
|
1527
1555
|
if (NODE_BUILTINS.has(packageName) || NODE_BUILTINS.has(packageName.replace("node:", ""))) {
|
|
1528
1556
|
throw new NodeBuiltinError(packageName);
|
|
@@ -1725,20 +1753,25 @@ var ASSET_IMPORT_EXTENSIONS = {
|
|
|
1725
1753
|
".otf": "font/otf"
|
|
1726
1754
|
};
|
|
1727
1755
|
function assembleHTML(options) {
|
|
1728
|
-
const { project, config, transformedFiles } = options;
|
|
1756
|
+
const { project, config, transformedFiles, cdnProvider, tailwind = "auto" } = options;
|
|
1729
1757
|
const files = transformedFiles ?? project.files;
|
|
1758
|
+
let result;
|
|
1730
1759
|
switch (config.type) {
|
|
1731
1760
|
case "static":
|
|
1732
|
-
|
|
1761
|
+
result = assembleStatic(files, project, config);
|
|
1762
|
+
break;
|
|
1733
1763
|
case "static-esm":
|
|
1734
1764
|
case "jsx":
|
|
1735
1765
|
case "typescript":
|
|
1736
1766
|
case "jsx-typescript":
|
|
1737
1767
|
case "vite":
|
|
1738
|
-
|
|
1768
|
+
result = assembleESM(files, project, config, cdnProvider);
|
|
1769
|
+
break;
|
|
1739
1770
|
default:
|
|
1740
1771
|
throw new AssemblyError(`Unsupported project type: ${config.type}`);
|
|
1741
1772
|
}
|
|
1773
|
+
result.html = applyTailwindRuntime(result.html, project, config, tailwind);
|
|
1774
|
+
return result;
|
|
1742
1775
|
}
|
|
1743
1776
|
function assembleStatic(files, project, config) {
|
|
1744
1777
|
let html = files.get(config.entryPoint);
|
|
@@ -1752,10 +1785,13 @@ function assembleStatic(files, project, config) {
|
|
|
1752
1785
|
html = inlineAssets(html, project, config.entryPoint);
|
|
1753
1786
|
return { html, usesESM: false };
|
|
1754
1787
|
}
|
|
1755
|
-
function assembleESM(files, project, config) {
|
|
1788
|
+
function assembleESM(files, project, config, cdnProvider) {
|
|
1756
1789
|
const isGenerated = config.entryPoint === "__generated__/index.html";
|
|
1757
1790
|
rewriteAssetImports(files, project);
|
|
1758
|
-
const cssFromJS = extractCSSImports(files
|
|
1791
|
+
const { css: cssFromJS, links: cssLinks } = extractCSSImports(files, {
|
|
1792
|
+
dependencies: config.dependencies,
|
|
1793
|
+
cdnProvider
|
|
1794
|
+
});
|
|
1759
1795
|
if (config.isVite) {
|
|
1760
1796
|
injectImportMetaEnv(files);
|
|
1761
1797
|
}
|
|
@@ -1774,6 +1810,9 @@ function assembleESM(files, project, config) {
|
|
|
1774
1810
|
html = rewriteScriptSrcsToImportMap(html, config.entryPoint);
|
|
1775
1811
|
html = inlineAssets(html, project, config.entryPoint);
|
|
1776
1812
|
}
|
|
1813
|
+
for (const href of cssLinks) {
|
|
1814
|
+
html = injectIntoHead(html, `<link rel="stylesheet" href="${href}">`);
|
|
1815
|
+
}
|
|
1777
1816
|
if (cssFromJS) {
|
|
1778
1817
|
html = injectIntoHead(html, `<style>
|
|
1779
1818
|
${cssFromJS}
|
|
@@ -2023,20 +2062,32 @@ function rewriteAssetImports(files, project) {
|
|
|
2023
2062
|
}
|
|
2024
2063
|
}
|
|
2025
2064
|
}
|
|
2026
|
-
function extractCSSImports(files) {
|
|
2065
|
+
function extractCSSImports(files, options = {}) {
|
|
2027
2066
|
const cssChunks = [];
|
|
2028
|
-
const
|
|
2067
|
+
const links = [];
|
|
2068
|
+
const seenLinks = /* @__PURE__ */ new Set();
|
|
2069
|
+
const cssImportRe = /import\s+['"]([^'"]+\.css(?:[?#][^'"]*)?)['"]\s*;?/g;
|
|
2029
2070
|
for (const [path, content] of files) {
|
|
2030
2071
|
if (!/\.(js|ts|jsx|tsx|mjs)$/.test(path)) continue;
|
|
2031
2072
|
let modified = content;
|
|
2032
2073
|
let match;
|
|
2074
|
+
cssImportRe.lastIndex = 0;
|
|
2033
2075
|
while ((match = cssImportRe.exec(content)) !== null) {
|
|
2034
|
-
const
|
|
2035
|
-
const
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2076
|
+
const specifier = match[1];
|
|
2077
|
+
const bare = specifier.replace(/[?#].*$/, "");
|
|
2078
|
+
if (bare.startsWith(".") || bare.startsWith("/")) {
|
|
2079
|
+
const resolved = resolvePath(directoryOf(path), bare);
|
|
2080
|
+
const css = files.get(resolved);
|
|
2081
|
+
if (css) {
|
|
2082
|
+
cssChunks.push(`/* ${resolved} */
|
|
2039
2083
|
${css}`);
|
|
2084
|
+
}
|
|
2085
|
+
} else {
|
|
2086
|
+
const href = /^https?:\/\//.test(bare) ? bare : buildCSSURL(bare, options);
|
|
2087
|
+
if (!seenLinks.has(href)) {
|
|
2088
|
+
seenLinks.add(href);
|
|
2089
|
+
links.push(href);
|
|
2090
|
+
}
|
|
2040
2091
|
}
|
|
2041
2092
|
modified = modified.replace(match[0], "");
|
|
2042
2093
|
}
|
|
@@ -2044,7 +2095,95 @@ ${css}`);
|
|
|
2044
2095
|
files.set(path, modified);
|
|
2045
2096
|
}
|
|
2046
2097
|
}
|
|
2047
|
-
return cssChunks.join("\n\n");
|
|
2098
|
+
return { css: cssChunks.join("\n\n"), links };
|
|
2099
|
+
}
|
|
2100
|
+
var TAILWIND_DIRECTIVE_RE = /@tailwind\b|@apply\b/;
|
|
2101
|
+
var TAILWIND_CDN_URL = "https://cdn.tailwindcss.com";
|
|
2102
|
+
function hasTailwindDirectives(css) {
|
|
2103
|
+
return TAILWIND_DIRECTIVE_RE.test(css);
|
|
2104
|
+
}
|
|
2105
|
+
function applyTailwindRuntime(html, project, config, tailwind) {
|
|
2106
|
+
const enabled = tailwind === true || tailwind === "auto" && (config.usesTailwind ?? usesTailwindCSS(project.files));
|
|
2107
|
+
if (!enabled) return html;
|
|
2108
|
+
html = html.replace(
|
|
2109
|
+
/<style>([\s\S]*?)<\/style>/g,
|
|
2110
|
+
(match, css) => hasTailwindDirectives(css) ? `<style type="text/tailwindcss">${css}</style>` : match
|
|
2111
|
+
);
|
|
2112
|
+
let injection = `<script src="${TAILWIND_CDN_URL}"></script>`;
|
|
2113
|
+
const configObject = extractTailwindConfig(project.files);
|
|
2114
|
+
if (configObject) {
|
|
2115
|
+
injection += `
|
|
2116
|
+
<script>tailwind.config = ${configObject};</script>`;
|
|
2117
|
+
}
|
|
2118
|
+
return injectIntoHead(html, injection);
|
|
2119
|
+
}
|
|
2120
|
+
function extractTailwindConfig(files) {
|
|
2121
|
+
let source;
|
|
2122
|
+
for (const [path, content] of files) {
|
|
2123
|
+
if (/(?:^|\/)tailwind\.config\.(?:js|cjs|mjs|ts)$/.test(path)) {
|
|
2124
|
+
source = content;
|
|
2125
|
+
break;
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
if (!source) return null;
|
|
2129
|
+
const object = extractBalancedObject(source);
|
|
2130
|
+
if (!object || !isSafeConfigObject(object)) return null;
|
|
2131
|
+
return object;
|
|
2132
|
+
}
|
|
2133
|
+
function extractBalancedObject(source) {
|
|
2134
|
+
const opener = source.match(/(?:export\s+default|module\.exports\s*=)\s*\{/);
|
|
2135
|
+
if (!opener || opener.index === void 0) return null;
|
|
2136
|
+
const start = opener.index + opener[0].length - 1;
|
|
2137
|
+
let depth = 0;
|
|
2138
|
+
let str = null;
|
|
2139
|
+
let lineComment = false;
|
|
2140
|
+
let blockComment = false;
|
|
2141
|
+
for (let i = start; i < source.length; i++) {
|
|
2142
|
+
const c = source[i];
|
|
2143
|
+
const n = source[i + 1];
|
|
2144
|
+
if (lineComment) {
|
|
2145
|
+
if (c === "\n") lineComment = false;
|
|
2146
|
+
continue;
|
|
2147
|
+
}
|
|
2148
|
+
if (blockComment) {
|
|
2149
|
+
if (c === "*" && n === "/") {
|
|
2150
|
+
blockComment = false;
|
|
2151
|
+
i++;
|
|
2152
|
+
}
|
|
2153
|
+
continue;
|
|
2154
|
+
}
|
|
2155
|
+
if (str) {
|
|
2156
|
+
if (c === "\\") {
|
|
2157
|
+
i++;
|
|
2158
|
+
continue;
|
|
2159
|
+
}
|
|
2160
|
+
if (c === str) str = null;
|
|
2161
|
+
continue;
|
|
2162
|
+
}
|
|
2163
|
+
if (c === "/" && n === "/") {
|
|
2164
|
+
lineComment = true;
|
|
2165
|
+
i++;
|
|
2166
|
+
continue;
|
|
2167
|
+
}
|
|
2168
|
+
if (c === "/" && n === "*") {
|
|
2169
|
+
blockComment = true;
|
|
2170
|
+
i++;
|
|
2171
|
+
continue;
|
|
2172
|
+
}
|
|
2173
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
2174
|
+
str = c;
|
|
2175
|
+
continue;
|
|
2176
|
+
}
|
|
2177
|
+
if (c === "{") depth++;
|
|
2178
|
+
else if (c === "}") {
|
|
2179
|
+
depth--;
|
|
2180
|
+
if (depth === 0) return source.slice(start, i + 1);
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
return null;
|
|
2184
|
+
}
|
|
2185
|
+
function isSafeConfigObject(object) {
|
|
2186
|
+
return !(/\brequire\s*\(/.test(object) || /\bimport\b/.test(object) || /=>/.test(object) || /\bfunction\b/.test(object) || /`/.test(object) || /\bprocess\b/.test(object) || /\b__dirname\b|\b__filename\b/.test(object));
|
|
2048
2187
|
}
|
|
2049
2188
|
function injectImportMetaEnv(files) {
|
|
2050
2189
|
const shim = `if(!import.meta.env){Object.defineProperty(import.meta,'env',{value:{MODE:'production',BASE_URL:'/',PROD:true,DEV:false,SSR:false}});}`;
|
|
@@ -2155,7 +2294,9 @@ var Diorama = class {
|
|
|
2155
2294
|
const { html: html2, usesESM: usesESM2 } = assembleHTML({
|
|
2156
2295
|
project,
|
|
2157
2296
|
config,
|
|
2158
|
-
transformedFiles: files
|
|
2297
|
+
transformedFiles: files,
|
|
2298
|
+
cdnProvider: this.options.cdnProvider,
|
|
2299
|
+
tailwind: options.tailwind ?? "auto"
|
|
2159
2300
|
});
|
|
2160
2301
|
return { html: html2, usesESM: usesESM2, repoName: repoName2 };
|
|
2161
2302
|
};
|
|
@@ -2268,6 +2409,7 @@ var DioramaPreview = react.forwardRef(
|
|
|
2268
2409
|
height = "500px",
|
|
2269
2410
|
frame,
|
|
2270
2411
|
expand,
|
|
2412
|
+
tailwind,
|
|
2271
2413
|
onLoad,
|
|
2272
2414
|
onError,
|
|
2273
2415
|
options,
|
|
@@ -2294,6 +2436,7 @@ var DioramaPreview = react.forwardRef(
|
|
|
2294
2436
|
height,
|
|
2295
2437
|
frame,
|
|
2296
2438
|
expand,
|
|
2439
|
+
tailwind,
|
|
2297
2440
|
onLoad,
|
|
2298
2441
|
onError: (err) => {
|
|
2299
2442
|
onError?.(err);
|
|
@@ -2314,7 +2457,7 @@ var DioramaPreview = react.forwardRef(
|
|
|
2314
2457
|
instanceRef.current?.destroy();
|
|
2315
2458
|
instanceRef.current = null;
|
|
2316
2459
|
};
|
|
2317
|
-
}, [repo, branch, subdirectory, loading, placeholder, height, frame, expand]);
|
|
2460
|
+
}, [repo, branch, subdirectory, loading, placeholder, height, frame, expand, tailwind]);
|
|
2318
2461
|
const containerStyle = {
|
|
2319
2462
|
width: "100%",
|
|
2320
2463
|
minHeight: height,
|