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,4 +1,5 @@
|
||||
import { getFrameworkRuntime } from './js-preprocessors.js';
|
||||
import { extractBareImports, buildImportMapTag } from './import-map.js';
|
||||
|
||||
const consoleInterceptor = `
|
||||
<script>
|
||||
@@ -56,26 +57,54 @@ function buildLoaderScript(runtimeUrls, userJs, isModule) {
|
||||
return parts;
|
||||
}
|
||||
|
||||
export function renderPreview(html, css, js, mode = 'html-css-js', extraCss = '') {
|
||||
/**
|
||||
* Render compiled code into the preview iframe.
|
||||
* @param {string} html - HTML content
|
||||
* @param {string} css - Compiled CSS
|
||||
* @param {string} js - Compiled JS
|
||||
* @param {string} mode - Framework mode
|
||||
* @param {string} extraCss - Extra CSS (e.g. from Vue/Svelte)
|
||||
* @param {object} options - { tailwind, isModule, renderedHtml }
|
||||
*/
|
||||
export function renderPreview(html, css, js, mode = 'html-css-js', extraCss = '', options = {}) {
|
||||
const frame = document.getElementById('preview-frame');
|
||||
const runtime = getFrameworkRuntime(mode);
|
||||
|
||||
// Combine CSS
|
||||
const allCss = extraCss ? `${css}\n${extraCss}` : css;
|
||||
|
||||
// If renderedHtml is provided (e.g. Markdown), use it as the body and skip JS
|
||||
const finalHtml = options.renderedHtml || html;
|
||||
const finalJs = options.renderedHtml ? '' : js;
|
||||
|
||||
// Determine body content
|
||||
let bodyContent;
|
||||
if (mode === 'vue' || mode === 'svelte') {
|
||||
bodyContent = html ? `${html}\n${runtime.bodyHtml}` : runtime.bodyHtml;
|
||||
bodyContent = finalHtml ? `${finalHtml}\n${runtime.bodyHtml}` : runtime.bodyHtml;
|
||||
} else if (runtime.bodyHtml) {
|
||||
bodyContent = `${html}\n${runtime.bodyHtml}`;
|
||||
bodyContent = `${finalHtml}\n${runtime.bodyHtml}`;
|
||||
} else {
|
||||
bodyContent = html;
|
||||
bodyContent = finalHtml;
|
||||
}
|
||||
|
||||
const isModule = mode === 'svelte';
|
||||
const loaderScript = js
|
||||
? buildLoaderScript(runtime.scripts, js, isModule)
|
||||
const isModule = options.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);
|
||||
}
|
||||
}
|
||||
|
||||
const loaderScript = finalJs
|
||||
? buildLoaderScript(runtime.scripts, finalJs, isModule)
|
||||
: '';
|
||||
|
||||
// Tailwind CDN injection
|
||||
const tailwindScript = options.tailwind
|
||||
? `<script src="https://cdn.tailwindcss.com"><\/script>\n`
|
||||
: '';
|
||||
|
||||
const doc = `<!DOCTYPE html>
|
||||
@@ -83,7 +112,8 @@ export function renderPreview(html, css, js, mode = 'html-css-js', extraCss = ''
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
${consoleInterceptor}
|
||||
<style>${allCss}</style>
|
||||
${tailwindScript}<style>${allCss}</style>
|
||||
${importMapTag}
|
||||
</head>
|
||||
<body>
|
||||
${bodyContent}
|
||||
|
||||
Reference in New Issue
Block a user