Files
fiddle/public/js/import-map.js
root 77f64d2862 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
2026-02-26 15:15:53 -06:00

44 lines
1.6 KiB
JavaScript

/**
* Extract bare import specifiers from JS code.
* Matches `from 'pkg'`, `from "pkg"`, `import 'pkg'`, `import "pkg"`
* where the specifier doesn't start with `.`, `/`, `http:`, or `https:`.
*/
export function extractBareImports(jsCode) {
const imports = new Set();
const re = /(?:import\s+(?:[\s\S]*?\s+from\s+)?['"])([^'"\s][^'"]*?)(?=['"])/g;
let match;
while ((match = re.exec(jsCode)) !== null) {
const spec = match[1];
// Skip relative, absolute, and URL imports
if (spec.startsWith('.') || spec.startsWith('/') || spec.startsWith('http:') || spec.startsWith('https:')) {
continue;
}
// Skip svelte internal imports (already rewritten by the compiler)
if (spec.startsWith('svelte')) continue;
imports.add(spec);
}
return Array.from(imports);
}
/**
* Build an HTML <script type="importmap"> tag from bare import specifiers.
* Maps each bare import to its esm.sh URL.
*/
export function buildImportMapTag(bareImports) {
if (!bareImports.length) return '';
const imports = {};
for (const spec of bareImports) {
// Get the package name (handle scoped packages like @scope/pkg)
const parts = spec.split('/');
const pkgName = spec.startsWith('@') ? `${parts[0]}/${parts[1]}` : parts[0];
// Map the full specifier (e.g. 'lodash/fp' -> 'https://esm.sh/lodash/fp')
imports[spec] = `https://esm.sh/${spec}`;
// Also map the base package if it's different
if (spec !== pkgName) {
imports[pkgName] = `https://esm.sh/${pkgName}`;
}
}
const map = JSON.stringify({ imports }, null, 2);
return `<script type="importmap">\n${map}\n<\/script>`;
}