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