Add Tailwind CSS toggle, Markdown/WASM modes, and npm import resolution
- Tailwind CSS: toolbar checkbox injects Play CDN into preview, persisted per-fiddle via new options JSON column - Markdown mode: uses marked.js CDN, renders markdown to HTML preview with CSS tab for custom styling - WASM mode: starter template with inline WebAssembly add function, supports top-level await via module detection - npm imports: auto-detect bare import specifiers in module code and inject importmap pointing to esm.sh CDN - Module auto-detection for html-css-js mode (import/export statements) - DB migration adds options column, server passes through all API endpoints - All features work across preview, export, and embed
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { loadFiddle } from './api.js';
|
||||
import { getFrameworkRuntime } from './js-preprocessors.js';
|
||||
import { extractBareImports, buildImportMapTag } from './import-map.js';
|
||||
|
||||
const MODE_MAP = {
|
||||
javascript: 'html-css-js',
|
||||
@@ -8,6 +9,8 @@ const MODE_MAP = {
|
||||
'react-ts': 'react-ts',
|
||||
vue: 'vue',
|
||||
svelte: 'svelte',
|
||||
markdown: 'markdown',
|
||||
wasm: 'wasm',
|
||||
};
|
||||
|
||||
async function init() {
|
||||
@@ -26,6 +29,7 @@ async function init() {
|
||||
const fiddle = await loadFiddle(match[1]);
|
||||
const mode = MODE_MAP[fiddle.js_type] || 'html-css-js';
|
||||
const runtime = getFrameworkRuntime(mode);
|
||||
const opts = JSON.parse(fiddle.options || '{}');
|
||||
|
||||
// For embed, we compile client-side using the same preprocessors
|
||||
const { compileCss } = await import('./preprocessors.js');
|
||||
@@ -36,32 +40,51 @@ async function init() {
|
||||
|
||||
const allCss = result.extraCss ? `${compiledCss}\n${result.extraCss}` : compiledCss;
|
||||
|
||||
const finalHtml = result.renderedHtml || fiddle.html;
|
||||
const finalJs = result.renderedHtml ? '' : result.js;
|
||||
|
||||
let bodyContent;
|
||||
if (mode === 'vue' || mode === 'svelte') {
|
||||
bodyContent = fiddle.html ? `${fiddle.html}\n${runtime.bodyHtml}` : runtime.bodyHtml;
|
||||
bodyContent = finalHtml ? `${finalHtml}\n${runtime.bodyHtml}` : runtime.bodyHtml;
|
||||
} else if (runtime.bodyHtml) {
|
||||
bodyContent = `${fiddle.html}\n${runtime.bodyHtml}`;
|
||||
bodyContent = `${finalHtml}\n${runtime.bodyHtml}`;
|
||||
} else {
|
||||
bodyContent = fiddle.html;
|
||||
bodyContent = finalHtml;
|
||||
}
|
||||
|
||||
const isModule = result.isModule || mode === 'svelte';
|
||||
|
||||
// Build importmap for module scripts with bare imports
|
||||
let importMapTag = '';
|
||||
if (isModule && finalJs) {
|
||||
const bareImports = extractBareImports(finalJs);
|
||||
if (bareImports.length) {
|
||||
importMapTag = buildImportMapTag(bareImports);
|
||||
}
|
||||
}
|
||||
|
||||
let scripts = '';
|
||||
if (result.js) {
|
||||
if (result.isModule) {
|
||||
scripts = `<script type="module">\n${escapeScriptClose(result.js)}\n<\/script>`;
|
||||
if (finalJs) {
|
||||
if (isModule) {
|
||||
scripts = `<script type="module">\n${escapeScriptClose(finalJs)}\n<\/script>`;
|
||||
} else {
|
||||
for (const url of runtime.scripts) {
|
||||
scripts += `<script src="${url}"><\/script>\n`;
|
||||
}
|
||||
scripts += `<script>\n${escapeScriptClose(result.js)}\n<\/script>`;
|
||||
scripts += `<script>\n${escapeScriptClose(finalJs)}\n<\/script>`;
|
||||
}
|
||||
}
|
||||
|
||||
const tailwindScript = opts.tailwind
|
||||
? `<script src="https://cdn.tailwindcss.com"><\/script>\n`
|
||||
: '';
|
||||
|
||||
const doc = `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<style>${allCss}</style>
|
||||
${tailwindScript}<style>${allCss}</style>
|
||||
${importMapTag}
|
||||
</head>
|
||||
<body>
|
||||
${bodyContent}
|
||||
|
||||
Reference in New Issue
Block a user