@maizzle/framework 6.1.0 → 6.1.2
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/build.js +2 -1
- package/dist/build.js.map +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/plugins/postcss/mergeMediaQueries.js +2 -1
- package/dist/plugins/postcss/mergeMediaQueries.js.map +1 -1
- package/dist/plugins/postcss/resolveMaizzleImports.js.map +1 -1
- package/dist/render/buildTemplate.js +4 -2
- package/dist/render/buildTemplate.js.map +1 -1
- package/dist/render/createRenderer.d.ts +7 -0
- package/dist/render/createRenderer.d.ts.map +1 -1
- package/dist/render/createRenderer.js +46 -3
- package/dist/render/createRenderer.js.map +1 -1
- package/dist/serve.js +19 -10
- package/dist/serve.js.map +1 -1
- package/dist/server/compatibility.js +2 -1
- package/dist/server/compatibility.js.map +1 -1
- package/dist/server/linter.js +2 -1
- package/dist/server/linter.js.map +1 -1
- package/dist/server/sfc-utils.js.map +1 -1
- package/dist/server/ui/.vite/deps/@lucide_vue.js +6845 -6285
- package/dist/server/ui/.vite/deps/@lucide_vue.js.map +1 -1
- package/dist/server/ui/.vite/deps/@vueuse_core.js +2 -6
- package/dist/server/ui/.vite/deps/@vueuse_core.js.map +1 -1
- package/dist/server/ui/.vite/deps/@vueuse_shared.js +1 -1
- package/dist/server/ui/.vite/deps/@vueuse_shared.js.map +1 -1
- package/dist/server/ui/.vite/deps/_metadata.json +15 -15
- package/dist/server/ui/.vite/deps/culori.js +8 -6
- package/dist/server/ui/.vite/deps/culori.js.map +1 -1
- package/dist/server/ui/.vite/deps/reka-ui.js +63 -73
- package/dist/server/ui/.vite/deps/reka-ui.js.map +1 -1
- package/dist/server/ui/.vite/deps/tailwind-merge.js.map +1 -1
- package/dist/server/ui/.vite/deps/vue-router.js +5 -13
- package/dist/server/ui/.vite/deps/vue-router.js.map +1 -1
- package/dist/server/ui/.vite/deps/vue.js +1 -1
- package/dist/server/ui/.vite/deps/{vue.runtime.esm-bundler-BHD3r-bP.js → vue.runtime.esm-bundler-S54atuNJ.js} +323 -259
- package/dist/server/ui/.vite/deps/{vue.runtime.esm-bundler-BHD3r-bP.js.map → vue.runtime.esm-bundler-S54atuNJ.js.map} +1 -1
- package/dist/transformers/format.js +2 -1
- package/dist/transformers/format.js.map +1 -1
- package/dist/transformers/index.d.ts +1 -1
- package/dist/transformers/index.d.ts.map +1 -1
- package/dist/transformers/index.js +4 -4
- package/dist/transformers/index.js.map +1 -1
- package/dist/transformers/inlineCss.js +3 -2
- package/dist/transformers/inlineCss.js.map +1 -1
- package/dist/transformers/inlineLink.js +2 -1
- package/dist/transformers/inlineLink.js.map +1 -1
- package/dist/transformers/minify.js +2 -1
- package/dist/transformers/minify.js.map +1 -1
- package/dist/transformers/tailwindComponent.d.ts +1 -1
- package/dist/transformers/tailwindComponent.d.ts.map +1 -1
- package/dist/transformers/tailwindComponent.js +26 -7
- package/dist/transformers/tailwindComponent.js.map +1 -1
- package/dist/transformers/tailwindcss.d.ts +10 -3
- package/dist/transformers/tailwindcss.d.ts.map +1 -1
- package/dist/transformers/tailwindcss.js +30 -14
- package/dist/transformers/tailwindcss.js.map +1 -1
- package/dist/transformers/urlQuery.js +2 -1
- package/dist/transformers/urlQuery.js.map +1 -1
- package/dist/types/config.d.ts +11 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/utils/cssBox.js +2 -6
- package/dist/utils/cssBox.js.map +1 -1
- package/package.json +2 -2
package/dist/serve.js
CHANGED
|
@@ -23,7 +23,8 @@ import { renderUnicodeCompact } from "uqr";
|
|
|
23
23
|
import tailwindcss from "@tailwindcss/vite";
|
|
24
24
|
import { createHighlighter } from "shiki";
|
|
25
25
|
//#region src/serve.ts
|
|
26
|
-
const
|
|
26
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
const devUIDir = resolve(__dirname, "server/ui");
|
|
27
28
|
const require = createRequire(import.meta.url);
|
|
28
29
|
const version = JSON.parse(readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), "../package.json"), "utf-8")).version;
|
|
29
30
|
const pkg = (name) => {
|
|
@@ -43,7 +44,8 @@ const pkg = (name) => {
|
|
|
43
44
|
const pkgEsmEntry = (name) => {
|
|
44
45
|
const dir = pkg(name);
|
|
45
46
|
const pj = JSON.parse(readFileSync(resolve(dir, "package.json"), "utf-8"));
|
|
46
|
-
|
|
47
|
+
const entry = pj.exports?.["."]?.import ?? pj.module ?? pj.main;
|
|
48
|
+
return resolve(dir, entry);
|
|
47
49
|
};
|
|
48
50
|
/**
|
|
49
51
|
* Start the Maizzle dev server.
|
|
@@ -320,7 +322,8 @@ async function serveDevUI(server, res, url, config) {
|
|
|
320
322
|
res.end(transformed);
|
|
321
323
|
}
|
|
322
324
|
async function serveTemplateList(config, res) {
|
|
323
|
-
const
|
|
325
|
+
const contentPatterns = config.content ?? ["emails/**/*.vue"];
|
|
326
|
+
const data = (await glob(contentPatterns)).map((t) => ({
|
|
324
327
|
name: basename(t).replace(/\.(vue|md)$/, ""),
|
|
325
328
|
path: t,
|
|
326
329
|
href: "/" + t.replace(/\.(vue|md)$/, "")
|
|
@@ -376,7 +379,7 @@ function getRendered(absolutePath, config, renderer, events) {
|
|
|
376
379
|
html: rendered.html
|
|
377
380
|
});
|
|
378
381
|
const doctype = rendered.doctype ?? templateConfig.doctype ?? "<!DOCTYPE html>";
|
|
379
|
-
if (templateConfig.useTransformers !== false) html = await runTransformers(html, templateConfig, absolutePath, doctype, rendered.tailwindBlocks);
|
|
382
|
+
if (templateConfig.useTransformers !== false) html = await runTransformers(html, templateConfig, absolutePath, doctype, rendered.tailwindBlocks, rendered.sourceFiles);
|
|
380
383
|
return {
|
|
381
384
|
rawHtml: await events.fireAfterTransform({
|
|
382
385
|
config: templateConfig,
|
|
@@ -401,7 +404,8 @@ function getRendered(absolutePath, config, renderer, events) {
|
|
|
401
404
|
*/
|
|
402
405
|
async function serveRenderedTemplate(url, config, renderer, events, res) {
|
|
403
406
|
const templateSlug = url.replace("/__maizzle/render/", "").replace(/\?.*$/, "");
|
|
404
|
-
const
|
|
407
|
+
const contentPatterns = config.content ?? ["emails/**/*.vue"];
|
|
408
|
+
const match = (await glob(contentPatterns)).find((t) => t.replace(/\.(vue|md)$/, "") === templateSlug);
|
|
405
409
|
if (!match) {
|
|
406
410
|
res.statusCode = 404;
|
|
407
411
|
res.end("Template not found");
|
|
@@ -429,7 +433,8 @@ async function getHighlighter() {
|
|
|
429
433
|
}
|
|
430
434
|
async function serveHighlightedSource(url, config, renderer, events, res) {
|
|
431
435
|
const templateSlug = url.replace("/__maizzle/source/", "").replace(/\?.*$/, "");
|
|
432
|
-
const
|
|
436
|
+
const contentPatterns = config.content ?? ["emails/**/*.vue"];
|
|
437
|
+
const match = (await glob(contentPatterns)).find((t) => t.replace(/\.(vue|md)$/, "") === templateSlug);
|
|
433
438
|
if (!match) {
|
|
434
439
|
res.statusCode = 404;
|
|
435
440
|
res.end("Template not found");
|
|
@@ -455,7 +460,8 @@ async function serveHighlightedSource(url, config, renderer, events, res) {
|
|
|
455
460
|
}
|
|
456
461
|
async function serveVueSource(url, config, res) {
|
|
457
462
|
const templateSlug = url.replace("/__maizzle/vue-source/", "").replace(/\?.*$/, "");
|
|
458
|
-
const
|
|
463
|
+
const contentPatterns = config.content ?? ["emails/**/*.vue"];
|
|
464
|
+
const match = (await glob(contentPatterns)).find((t) => t.replace(/\.(vue|md)$/, "") === templateSlug);
|
|
459
465
|
if (!match) {
|
|
460
466
|
res.statusCode = 404;
|
|
461
467
|
res.end("Template not found");
|
|
@@ -480,7 +486,8 @@ async function serveVueSource(url, config, res) {
|
|
|
480
486
|
}
|
|
481
487
|
async function servePlaintext(url, config, renderer, events, res) {
|
|
482
488
|
const templateSlug = url.replace("/__maizzle/plaintext/", "").replace(/\?.*$/, "");
|
|
483
|
-
const
|
|
489
|
+
const contentPatterns = config.content ?? ["emails/**/*.vue"];
|
|
490
|
+
const match = (await glob(contentPatterns)).find((t) => t.replace(/\.(vue|md)$/, "") === templateSlug);
|
|
484
491
|
if (!match) {
|
|
485
492
|
res.statusCode = 404;
|
|
486
493
|
res.end("Template not found");
|
|
@@ -520,7 +527,8 @@ function humanFileSize(bytes, si = false, dp = 2) {
|
|
|
520
527
|
}
|
|
521
528
|
async function serveStats(url, config, renderer, events, res) {
|
|
522
529
|
const templateSlug = url.replace("/__maizzle/stats/", "").replace(/\?.*$/, "");
|
|
523
|
-
const
|
|
530
|
+
const contentPatterns = config.content ?? ["emails/**/*.vue"];
|
|
531
|
+
const match = (await glob(contentPatterns)).find((t) => t.replace(/\.(vue|md)$/, "") === templateSlug);
|
|
524
532
|
if (!match) {
|
|
525
533
|
res.statusCode = 404;
|
|
526
534
|
res.end(JSON.stringify({ error: "Template not found" }));
|
|
@@ -549,7 +557,8 @@ async function serveStats(url, config, renderer, events, res) {
|
|
|
549
557
|
}
|
|
550
558
|
async function serveEmailEndpoint(url, req, res, config, renderer, events) {
|
|
551
559
|
const templateSlug = url.replace("/__maizzle/email/", "").replace(/\?.*$/, "");
|
|
552
|
-
const
|
|
560
|
+
const contentPatterns = config.content ?? ["emails/**/*.vue"];
|
|
561
|
+
const match = (await glob(contentPatterns)).find((t) => t.replace(/\.(vue|md)$/, "") === templateSlug);
|
|
553
562
|
if (!match) {
|
|
554
563
|
res.statusCode = 404;
|
|
555
564
|
res.end(JSON.stringify({
|
package/dist/serve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.js","names":["parsePath"],"sources":["../src/serve.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport { dirname, resolve, basename, parse as parsePath } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { createRequire } from 'node:module'\nimport { createServer, createLogger, type ViteDevServer } from 'vite'\nimport { renderUnicodeCompact } from 'uqr'\nimport vue from '@vitejs/plugin-vue'\nimport tailwindcss from '@tailwindcss/vite'\nimport { glob } from 'tinyglobby'\nimport { createHighlighter, type Highlighter } from 'shiki'\nimport { createPlaintext } from './plaintext.ts'\nimport { stripForHtml, stripForPlaintext } from './utils/output-markers.ts'\nimport { resolveConfig } from './config/index.ts'\nimport { runTransformers } from './transformers/index.ts'\nimport { EventManager } from './events/index.ts'\nimport { cloneConfig } from './utils/cloneConfig.ts'\nimport { createRenderer, type Renderer, type RenderedTemplate } from './render/createRenderer.ts'\nimport { _setCurrentTemplate } from './composables/useCurrentTemplate.ts'\nimport { setActiveRenderer } from './render/active.ts'\nimport { serveCompatibility } from './server/compatibility.ts'\nimport { serveLint } from './server/linter.ts'\nimport { sendEmail } from './server/email.ts'\nimport { normalizeComponentSources } from './utils/componentSources.ts'\nimport { createWatchedFileMatcher } from './utils/watchPaths.ts'\nimport type { MaizzleConfig } from './types/index.ts'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nconst devUIDir = resolve(__dirname, 'server/ui')\n\nconst require = createRequire(import.meta.url)\n\nconst version = JSON.parse(\n readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'), 'utf-8'),\n).version\n\nconst pkg = (name: string) => {\n const resolved = require.resolve(name).replace(/\\\\/g, '/')\n const marker = `node_modules/${name}`\n const idx = resolved.lastIndexOf(marker)\n\n return resolved.slice(0, idx + marker.length)\n}\n\n/**\n * Resolve a package's ESM entry via its `exports` map. Aliasing to the\n * package directory bypasses `exports` (it only keys off the bare name),\n * so directory resolution can fall back to a UMD/CJS bundle — which Vite 8\n * flags `needsInterop` and then default-imports, breaking ESM-only deps\n * like culori (named exports, no default). Point the alias at the real\n * ESM entry instead.\n */\nconst pkgEsmEntry = (name: string) => {\n const dir = pkg(name)\n const pj = JSON.parse(readFileSync(resolve(dir, 'package.json'), 'utf-8'))\n const entry = pj.exports?.['.']?.import ?? pj.module ?? pj.main\n return resolve(dir, entry)\n}\n\nexport interface ServeOptions {\n config?: Partial<MaizzleConfig> | string\n /** Override the dev server port (takes precedence over config.server.port) */\n port?: number\n /** Expose the server on the network (e.g. --host) */\n host?: boolean | string\n /** When true, suppresses the startup banner/URL output. */\n silent?: boolean\n}\n\n/**\n * Start the Maizzle dev server.\n *\n * Creates two things:\n * 1. A Vite dev server for the dev UI (sidebar + preview, with Vue + Tailwind for the UI itself)\n * 2. A Renderer instance for SSR rendering email templates\n *\n * Template rendering goes through the Renderer, not the Vite dev server.\n */\nexport async function serve(options: ServeOptions = {}) {\n const start = performance.now()\n\n let config = await resolveConfig(options.config)\n const port = options.port ?? config.server?.port ?? 3000\n const host = options.host ?? config.server?.host\n\n // Create a renderer for SSR rendering email templates (with dts for dev)\n let renderer = await createRenderer({ dts: true, markdown: config.markdown, root: config.root, componentDirs: normalizeComponentSources(config.components?.source, process.cwd()), vite: config.vite, customElements: config.vue?.customElements })\n\n /**\n * Register so user-land render() calls reuse this renderer instead of\n * spinning up another Vite SSR server (which collides when the host\n * app is itself a Vite dev process — e.g. TanStack Start).\n */\n setActiveRenderer(renderer)\n\n const events = new EventManager()\n events.registerConfig(config)\n await events.fireBeforeCreate({ config })\n\n const server = await createServer({\n configFile: false,\n plugins: [\n // Vue and Tailwind are only for the dev UI SPA, not for email templates\n vue(),\n tailwindcss(),\n maizzleDevPlugin(config, renderer, events, options.config),\n ],\n resolve: {\n dedupe: ['vue'],\n alias: [\n { find: '@', replacement: devUIDir },\n { find: 'vue', replacement: resolve(pkg('vue'), 'dist/vue.runtime.esm-bundler.js') },\n // culori is ESM-only — alias to its ESM entry, not the package dir (see pkgEsmEntry)\n { find: 'culori', replacement: pkgEsmEntry('culori') },\n ...['vue-router', 'reka-ui', '@vueuse/core', '@vueuse/shared', '@lucide/vue', 'class-variance-authority', 'clsx', 'tailwind-merge']\n .map(name => ({ find: name, replacement: pkg(name) })),\n ],\n },\n cacheDir: resolve(devUIDir, '.vite'),\n optimizeDeps: {\n noDiscovery: true,\n include: [\n 'vue',\n 'vue-router',\n '@lucide/vue',\n '@vueuse/core',\n '@vueuse/shared',\n 'reka-ui',\n 'class-variance-authority',\n 'clsx',\n 'tailwind-merge',\n 'culori',\n ],\n },\n server: {\n // Cherry-pick Vite's `server` options (e.g. watch.ignored) from the\n // user's `vite` config; Maizzle's required keys below take precedence.\n ...config.vite?.server,\n port,\n host,\n fs: {\n ...config.vite?.server?.fs,\n allow: [process.cwd(), config.root ?? process.cwd(), devUIDir, ...['vue', 'vue-router', 'reka-ui', '@vueuse/core', '@vueuse/shared', '@lucide/vue', 'class-variance-authority', 'clsx', 'tailwind-merge', 'culori'].map(pkg), ...(config.vite?.server?.fs?.allow ?? [])],\n },\n },\n customLogger: customLogger(),\n })\n\n // Store renderer ref on server for cleanup\n const originalClose = server.close.bind(server)\n server.close = async () => {\n setActiveRenderer(null)\n await renderer.close()\n return originalClose()\n }\n\n await server.listen()\n\n const startupTime = Math.round(performance.now() - start)\n\n if (!options.silent) {\n printBanner(server, startupTime)\n }\n\n // Expose startup time so the plugin can print it later\n ; (server as any)._maizzleStartupTime = startupTime\n\n return server\n}\n\n/**\n * Internal Vite plugin that adds Maizzle middleware and file watching to the dev UI server.\n */\nfunction maizzleDevPlugin(\n config: MaizzleConfig,\n renderer: Renderer,\n events: EventManager,\n configInput: Partial<MaizzleConfig> | string | undefined,\n) {\n return {\n name: 'maizzle:dev',\n enforce: 'pre' as const,\n\n hotUpdate: {\n order: 'pre' as const,\n handler({ file }: { file: string }) {\n /**\n * Prevent Tailwind/Vue from triggering a full reload for email template\n * files. Maizzle handles these via custom HMR events in the\n * watcher below.\n */\n if (isTemplateFile(file)) {\n return []\n }\n },\n },\n\n configureServer(server: ViteDevServer) {\n // File watching\n const defaultWatchPaths = [\n 'maizzle.config.js',\n 'maizzle.config.ts',\n 'tailwind.config.js',\n 'tailwind.config.ts',\n 'locales/**',\n ]\n\n const userWatchPaths = config.server?.watch ?? []\n const watchPaths = [...defaultWatchPaths, ...userWatchPaths]\n // Match against cwd, not config.root: the watched paths (maizzle/tailwind\n // configs, locales) are project-root relative, and `watcher.add` below\n // resolves them against cwd too. Using config.root would break matching\n // when root points at a subdirectory (e.g. the Vite-plugin setup).\n const isWatchedFile = createWatchedFileMatcher(watchPaths, process.cwd())\n\n for (const watchPath of watchPaths) {\n server.watcher.add(watchPath)\n }\n\n /**\n * Serialize watcher work onto one chain. The change handler closes and\n * recreates the renderer across awaits; without serialization a second\n * event firing mid-reload closes a stale renderer and leaks the new one.\n * Errors are caught so one failed task doesn't break the chain.\n */\n let watcherChain: Promise<void> = Promise.resolve()\n const enqueue = (task: () => Promise<void>): Promise<void> => {\n watcherChain = watcherChain.then(task).catch((err) => {\n console.error('[maizzle] watcher task failed:', err)\n })\n return watcherChain\n }\n\n server.watcher.on('add', file => enqueue(async () => {\n if (isTemplateFile(file)) {\n await renderer.invalidateAll()\n bumpGeneration()\n server.ws.send({ type: 'custom', event: 'maizzle:templates-changed' })\n }\n }))\n\n server.watcher.on('unlink', file => enqueue(async () => {\n if (isTemplateFile(file)) {\n await renderer.invalidateAll()\n bumpGeneration()\n server.ws.send({ type: 'custom', event: 'maizzle:templates-changed' })\n }\n }))\n\n server.watcher.on('change', file => enqueue(async () => {\n if (isWatchedFile(file)) {\n config = await resolveConfig(configInput)\n\n // Re-register event handlers against the reloaded config (the config\n // object is replaced wholesale, so old handlers would be stale).\n events.clear()\n events.registerConfig(config)\n\n // Recreate the renderer so config changes (e.g. markdown.shikiTheme) take effect\n await renderer.close()\n renderer = await createRenderer({ dts: true, markdown: config.markdown, root: config.root, componentDirs: normalizeComponentSources(config.components?.source, process.cwd()), vite: config.vite, customElements: config.vue?.customElements })\n\n // Re-register the new renderer so user-land render() calls don't keep\n // reusing the closed one (see setActiveRenderer above).\n setActiveRenderer(renderer)\n\n /**\n * Push UI-relevant config bits so the dev UI reacts to live edits\n * without a page reload. Uses the same shape as the initial\n * inject.\n */\n server.ws.send({ type: 'custom', event: 'maizzle:config-updated', data: buildUiConfig(config) })\n }\n\n /**\n * Invalidate all renderer modules so component and config changes\n * are picked up on the next render (Tailwind recompiles with\n * fresh content).\n */\n await renderer.invalidateAll()\n bumpGeneration()\n\n if (\n isTemplateFile(file)\n || isWatchedFile(file)\n ) {\n server.ws.send({ type: 'custom', event: 'maizzle:template-updated', data: { file } })\n }\n }))\n\n // API middleware (before Vite's middleware)\n server.middlewares.use(async (req: any, res: any, next: any) => {\n const url = req.url || '/'\n\n if (url === '/__maizzle/templates') {\n return serveTemplateList(config, res)\n }\n\n if (url.startsWith('/__maizzle/render/')) {\n return await serveRenderedTemplate(url, config, renderer, events, res)\n }\n\n if (url.startsWith('/__maizzle/source/')) {\n return await serveHighlightedSource(url, config, renderer, events, res)\n }\n\n if (url.startsWith('/__maizzle/compatibility/')) {\n return await serveCompatibility(url, res, config, normalizeComponentSources(config.components?.source, process.cwd()))\n }\n\n if (url.startsWith('/__maizzle/lint/')) {\n return await serveLint(url, res, config, normalizeComponentSources(config.components?.source, process.cwd()))\n }\n\n if (url.startsWith('/__maizzle/vue-source/')) {\n return await serveVueSource(url, config, res)\n }\n\n if (url.startsWith('/__maizzle/plaintext/')) {\n return await servePlaintext(url, config, renderer, events, res)\n }\n\n if (url.startsWith('/__maizzle/stats/')) {\n return await serveStats(url, config, renderer, events, res)\n }\n\n if (url.startsWith('/__maizzle/email/') && req.method === 'POST') {\n return await serveEmailEndpoint(url, req, res, config, renderer, events)\n }\n\n if (url === '/__maizzle/email-config') {\n return serveEmailConfig(config, res)\n }\n\n next()\n })\n\n // Dev UI fallback (after Vite's middleware)\n return () => {\n server.middlewares.use(async (req: any, res: any, next: any) => {\n if (isNavigationRequest(req)) {\n return await serveDevUI(server, res, req.url || '/', config)\n }\n\n next()\n })\n }\n },\n }\n}\n\nfunction isTemplateFile(file: string): boolean {\n return (file.endsWith('.vue') || file.endsWith('.md')) && !file.includes('server/ui')\n}\n\nfunction isNavigationRequest(req: any): boolean {\n const accept = req.headers?.accept || ''\n return req.method === 'GET' && accept.includes('text/html')\n}\n\n/**\n * Shape exposed to the dev UI both at initial HTML load (as\n * `window.__MAIZZLE_CONFIG__`) and on the `maizzle:config-updated` HMR event.\n * Add UI-visible config bits here; consumers on both ends pick up automatically.\n */\nfunction buildUiConfig(config: MaizzleConfig) {\n return {\n checks: config.server?.checks ?? true,\n }\n}\n\nasync function serveDevUI(server: ViteDevServer, res: any, url: string, config: MaizzleConfig) {\n let indexHtml = readFileSync(resolve(devUIDir, 'index.html'), 'utf-8')\n\n indexHtml = indexHtml.replace('./main.ts', `/@fs/${resolve(devUIDir, 'main.ts')}`)\n indexHtml = indexHtml.replace('./favicon.svg', `/@fs/${resolve(devUIDir, 'favicon.svg')}`)\n\n const configScript = `<script>window.__MAIZZLE_CONFIG__ = ${JSON.stringify(buildUiConfig(config))};</script>`\n indexHtml = indexHtml.replace('</head>', `${configScript}</head>`)\n\n const transformed = await server.transformIndexHtml(url, indexHtml)\n\n res.setHeader('Content-Type', 'text/html')\n res.end(transformed)\n}\n\nasync function serveTemplateList(config: MaizzleConfig, res: any) {\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n\n const data = templates.map(t => ({\n name: basename(t).replace(/\\.(vue|md)$/, ''),\n path: t,\n href: '/' + t.replace(/\\.(vue|md)$/, ''),\n }))\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify(data))\n}\n\ninterface DedupedRender {\n /** Transformer output — before doctype prepend / stripForHtml / stripForPlaintext. */\n rawHtml: string\n doctype: string\n templateConfig: MaizzleConfig\n rendered: RenderedTemplate\n}\n\n/**\n * Render-result memo for the dev server. A single template save makes the\n * browser fire several endpoint requests in parallel (render, source, stats,\n * plaintext, email) that each need the same SSR render + transformer output.\n * Keying the in-flight Promise by `${generation}:${path}` collapses those into\n * one render and dedupes concurrent requests. The watcher bumps the generation\n * (and clears the cache) on every file/config change, so results never go\n * stale. Each endpoint applies its own tail step (doctype prepend, strip,\n * highlight, …) on top of `rawHtml`, keeping output byte-identical.\n */\nlet renderGeneration = 0\nconst renderCache = new Map<string, Promise<DedupedRender>>()\n\nfunction bumpGeneration() {\n renderGeneration++\n renderCache.clear()\n}\n\nfunction getRendered(absolutePath: string, config: MaizzleConfig, renderer: Renderer, events: EventManager): Promise<DedupedRender> {\n const key = `${renderGeneration}:${absolutePath}`\n let promise = renderCache.get(key)\n if (!promise) {\n promise = (async () => {\n _setCurrentTemplate(parsePath(absolutePath))\n try {\n /**\n * Mirror the build's per-template event pipeline (see buildTemplate)\n * so dev preview fires the same beforeRender / afterRender /\n * afterTransform hooks and matches production output. Clone config so\n * beforeRender mutations stay scoped to this render.\n */\n const renderConfig = cloneConfig(config)\n const template = { source: readFileSync(absolutePath, 'utf-8'), path: parsePath(absolutePath) }\n const originalSource = template.source\n\n await events.fireBeforeRender({ config: renderConfig, template })\n\n const rendered = await renderer.render(\n absolutePath,\n renderConfig,\n template.source !== originalSource ? { source: template.source } : undefined,\n )\n\n for (const { name, handler } of rendered.sfcEventHandlers) {\n events.on(name, handler)\n }\n\n const templateConfig = rendered.templateConfig\n let html = await events.fireAfterRender({ config: templateConfig, template, html: rendered.html })\n const doctype = rendered.doctype ?? templateConfig.doctype ?? '<!DOCTYPE html>'\n\n if (templateConfig.useTransformers !== false) {\n html = await runTransformers(html, templateConfig, absolutePath, doctype, rendered.tailwindBlocks)\n }\n\n const rawHtml = await events.fireAfterTransform({ config: templateConfig, template, html })\n\n return { rawHtml, doctype, templateConfig, rendered }\n } finally {\n _setCurrentTemplate(undefined)\n events.clearSfcHandlers()\n }\n })()\n renderCache.set(key, promise)\n }\n return promise\n}\n\n/**\n * SSR render a .vue template using the Renderer (not the dev UI server).\n */\nasync function serveRenderedTemplate(url: string, config: MaizzleConfig, renderer: Renderer, events: EventManager, res: any) {\n const templateSlug = url.replace('/__maizzle/render/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n const absolutePath = resolve(match)\n\n try {\n const { rawHtml, doctype } = await getRendered(absolutePath, config, renderer, events)\n let html = rawHtml\n if (doctype) html = `${doctype}\\n${html}`\n\n res.setHeader('Content-Type', 'text/html')\n res.end(stripForHtml(html))\n } catch (error: any) {\n res.statusCode = 500\n res.end(`<pre>${error.stack || error.message}</pre>`)\n }\n}\n\nlet highlighter: Highlighter | null = null\n\nasync function getHighlighter() {\n if (!highlighter) {\n highlighter = await createHighlighter({\n themes: ['laserwave'],\n langs: ['html', 'vue'],\n })\n }\n return highlighter\n}\n\nasync function serveHighlightedSource(url: string, config: MaizzleConfig, renderer: Renderer, events: EventManager, res: any) {\n const templateSlug = url.replace('/__maizzle/source/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n const absolutePath = resolve(match)\n\n try {\n const { rawHtml, doctype } = await getRendered(absolutePath, config, renderer, events)\n const html = stripForHtml(doctype ? `${doctype}\\n${rawHtml}` : rawHtml)\n\n const hl = await getHighlighter()\n const highlighted = hl.codeToHtml(html, {\n lang: 'html',\n theme: 'laserwave',\n transformers: [{\n line(node, line) {\n node.properties['data-line'] = line\n },\n }],\n })\n\n res.setHeader('Content-Type', 'text/html')\n res.end(highlighted)\n } catch (error: any) {\n res.statusCode = 500\n res.end(`<pre>${error.stack || error.message}</pre>`)\n }\n}\n\nasync function serveVueSource(url: string, config: MaizzleConfig, res: any) {\n const templateSlug = url.replace('/__maizzle/vue-source/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n try {\n const source = readFileSync(resolve(match), 'utf-8')\n const lang = match.endsWith('.md') ? 'html' : 'vue'\n\n const hl = await getHighlighter()\n const highlighted = hl.codeToHtml(source, {\n lang,\n theme: 'laserwave',\n transformers: [{\n line(node, line) {\n node.properties['data-line'] = line\n },\n }],\n })\n\n res.setHeader('Content-Type', 'text/html')\n res.end(highlighted)\n } catch (error: any) {\n res.statusCode = 500\n res.end(`<pre>${error.stack || error.message}</pre>`)\n }\n}\n\nasync function servePlaintext(url: string, config: MaizzleConfig, renderer: Renderer, events: EventManager, res: any) {\n const templateSlug = url.replace('/__maizzle/plaintext/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n const absolutePath = resolve(match)\n\n try {\n const { rawHtml } = await getRendered(absolutePath, config, renderer, events)\n const plaintext = createPlaintext(stripForPlaintext(rawHtml))\n\n res.setHeader('Content-Type', 'text/plain')\n res.end(plaintext)\n } catch (error: any) {\n res.statusCode = 500\n res.end(error.message)\n }\n}\n\nfunction humanFileSize(bytes: number, si = false, dp = 2) {\n const threshold = si ? 1000 : 1024\n\n if (Math.abs(bytes) < threshold) {\n return bytes + ' B'\n }\n\n const units = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n let u = -1\n const r = 10 ** dp\n\n do {\n bytes /= threshold\n ++u\n } while (Math.round(Math.abs(bytes) * r) / r >= threshold && u < units.length - 1)\n\n return bytes.toFixed(dp) + ' ' + units[u]\n}\n\nasync function serveStats(url: string, config: MaizzleConfig, renderer: Renderer, events: EventManager, res: any) {\n const templateSlug = url.replace('/__maizzle/stats/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end(JSON.stringify({ error: 'Template not found' }))\n return\n }\n\n const absolutePath = resolve(match)\n\n try {\n const { rawHtml } = await getRendered(absolutePath, config, renderer, events)\n const html = stripForHtml(rawHtml)\n\n const sizeBytes = new TextEncoder().encode(html).length\n\n // Count images: <img> tags and CSS background images\n const imgTags = (html.match(/<img\\b[^>]*>/gi) || []).length\n const bgImages = (html.match(/url\\s*\\([^)]+\\)/gi) || []).length\n const totalImages = imgTags + bgImages\n\n // Count links\n const links = (html.match(/<a\\b[^>]*href\\s*=/gi) || []).length\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify({\n size: {\n bytes: sizeBytes,\n formatted: humanFileSize(sizeBytes),\n },\n images: totalImages,\n links,\n }))\n } catch (error: any) {\n res.statusCode = 500\n res.end(JSON.stringify({ error: error.message }))\n }\n}\n\nasync function serveEmailEndpoint(url: string, req: any, res: any, config: MaizzleConfig, renderer: Renderer, events: EventManager) {\n const templateSlug = url.replace('/__maizzle/email/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end(JSON.stringify({ success: false, message: 'Template not found' }))\n return\n }\n\n let body = ''\n for await (const chunk of req) body += chunk\n\n let payload: { to: string[]; subject: string }\n\n try {\n payload = JSON.parse(body)\n } catch {\n res.statusCode = 400\n res.end(JSON.stringify({ success: false, message: 'Invalid JSON' }))\n return\n }\n\n if (!payload.to?.length) {\n res.statusCode = 400\n res.end(JSON.stringify({ success: false, message: 'Missing recipients' }))\n return\n }\n\n const absolutePath = resolve(match)\n\n try {\n const { rawHtml, doctype, templateConfig } = await getRendered(absolutePath, config, renderer, events)\n let html = doctype ? `${doctype}\\n${rawHtml}` : rawHtml\n\n const text = createPlaintext(stripForPlaintext(html))\n html = stripForHtml(html)\n\n const result = await sendEmail(\n { to: payload.to, subject: payload.subject, html, text },\n config,\n templateConfig,\n )\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify(result))\n } catch (error: any) {\n res.statusCode = 500\n res.end(JSON.stringify({ success: false, message: error.message }))\n }\n}\n\nfunction serveEmailConfig(config: MaizzleConfig, res: any) {\n const emailConfig = config.server?.email\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify({\n to: emailConfig?.to ? (Array.isArray(emailConfig.to) ? emailConfig.to : [emailConfig.to]) : [],\n from: emailConfig?.from ?? '',\n subject: emailConfig?.subject ?? '',\n hasTransport: !!emailConfig?.transport,\n }))\n}\n\nexport function printBanner(server: ViteDevServer, startupTime?: number) {\n const info = server.config.logger.info\n const time = startupTime ?? (server as any)._maizzleStartupTime\n\n const networkUrl = server.resolvedUrls?.network[0]\n if (networkUrl) {\n const qr = renderUnicodeCompact(networkUrl, { border: 1 })\n info('')\n info(qr.split('\\n').map(line => ` ${line}`).join('\\n'))\n }\n\n info('')\n info(` \\x1b[32m\\x1b[1mMAIZZLE\\x1b[0m\\x1b[32m v${version}\\x1b[0m \\x1b[2mready in\\x1b[0m \\x1b[1m${time}\\x1b[0m ms`)\n info('')\n server.printUrls()\n info('')\n}\n\nfunction customLogger() {\n const logger = createLogger('info')\n const warn = logger.warn\n\n logger.warn = (message, options) => {\n if (typeof message === 'string' && message.includes('<tr> cannot be child of <table>')) {\n return\n }\n\n warn(message, options)\n }\n\n return logger\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"serve.js","names":["parsePath"],"sources":["../src/serve.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport { dirname, resolve, basename, parse as parsePath } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { createRequire } from 'node:module'\nimport { createServer, createLogger, type ViteDevServer } from 'vite'\nimport { renderUnicodeCompact } from 'uqr'\nimport vue from '@vitejs/plugin-vue'\nimport tailwindcss from '@tailwindcss/vite'\nimport { glob } from 'tinyglobby'\nimport { createHighlighter, type Highlighter } from 'shiki'\nimport { createPlaintext } from './plaintext.ts'\nimport { stripForHtml, stripForPlaintext } from './utils/output-markers.ts'\nimport { resolveConfig } from './config/index.ts'\nimport { runTransformers } from './transformers/index.ts'\nimport { EventManager } from './events/index.ts'\nimport { cloneConfig } from './utils/cloneConfig.ts'\nimport { createRenderer, type Renderer, type RenderedTemplate } from './render/createRenderer.ts'\nimport { _setCurrentTemplate } from './composables/useCurrentTemplate.ts'\nimport { setActiveRenderer } from './render/active.ts'\nimport { serveCompatibility } from './server/compatibility.ts'\nimport { serveLint } from './server/linter.ts'\nimport { sendEmail } from './server/email.ts'\nimport { normalizeComponentSources } from './utils/componentSources.ts'\nimport { createWatchedFileMatcher } from './utils/watchPaths.ts'\nimport type { MaizzleConfig } from './types/index.ts'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nconst devUIDir = resolve(__dirname, 'server/ui')\n\nconst require = createRequire(import.meta.url)\n\nconst version = JSON.parse(\n readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'), 'utf-8'),\n).version\n\nconst pkg = (name: string) => {\n const resolved = require.resolve(name).replace(/\\\\/g, '/')\n const marker = `node_modules/${name}`\n const idx = resolved.lastIndexOf(marker)\n\n return resolved.slice(0, idx + marker.length)\n}\n\n/**\n * Resolve a package's ESM entry via its `exports` map. Aliasing to the\n * package directory bypasses `exports` (it only keys off the bare name),\n * so directory resolution can fall back to a UMD/CJS bundle — which Vite 8\n * flags `needsInterop` and then default-imports, breaking ESM-only deps\n * like culori (named exports, no default). Point the alias at the real\n * ESM entry instead.\n */\nconst pkgEsmEntry = (name: string) => {\n const dir = pkg(name)\n const pj = JSON.parse(readFileSync(resolve(dir, 'package.json'), 'utf-8'))\n const entry = pj.exports?.['.']?.import ?? pj.module ?? pj.main\n return resolve(dir, entry)\n}\n\nexport interface ServeOptions {\n config?: Partial<MaizzleConfig> | string\n /** Override the dev server port (takes precedence over config.server.port) */\n port?: number\n /** Expose the server on the network (e.g. --host) */\n host?: boolean | string\n /** When true, suppresses the startup banner/URL output. */\n silent?: boolean\n}\n\n/**\n * Start the Maizzle dev server.\n *\n * Creates two things:\n * 1. A Vite dev server for the dev UI (sidebar + preview, with Vue + Tailwind for the UI itself)\n * 2. A Renderer instance for SSR rendering email templates\n *\n * Template rendering goes through the Renderer, not the Vite dev server.\n */\nexport async function serve(options: ServeOptions = {}) {\n const start = performance.now()\n\n let config = await resolveConfig(options.config)\n const port = options.port ?? config.server?.port ?? 3000\n const host = options.host ?? config.server?.host\n\n // Create a renderer for SSR rendering email templates (with dts for dev)\n let renderer = await createRenderer({ dts: true, markdown: config.markdown, root: config.root, componentDirs: normalizeComponentSources(config.components?.source, process.cwd()), vite: config.vite, customElements: config.vue?.customElements })\n\n /**\n * Register so user-land render() calls reuse this renderer instead of\n * spinning up another Vite SSR server (which collides when the host\n * app is itself a Vite dev process — e.g. TanStack Start).\n */\n setActiveRenderer(renderer)\n\n const events = new EventManager()\n events.registerConfig(config)\n await events.fireBeforeCreate({ config })\n\n const server = await createServer({\n configFile: false,\n plugins: [\n // Vue and Tailwind are only for the dev UI SPA, not for email templates\n vue(),\n tailwindcss(),\n maizzleDevPlugin(config, renderer, events, options.config),\n ],\n resolve: {\n dedupe: ['vue'],\n alias: [\n { find: '@', replacement: devUIDir },\n { find: 'vue', replacement: resolve(pkg('vue'), 'dist/vue.runtime.esm-bundler.js') },\n // culori is ESM-only — alias to its ESM entry, not the package dir (see pkgEsmEntry)\n { find: 'culori', replacement: pkgEsmEntry('culori') },\n ...['vue-router', 'reka-ui', '@vueuse/core', '@vueuse/shared', '@lucide/vue', 'class-variance-authority', 'clsx', 'tailwind-merge']\n .map(name => ({ find: name, replacement: pkg(name) })),\n ],\n },\n cacheDir: resolve(devUIDir, '.vite'),\n optimizeDeps: {\n noDiscovery: true,\n include: [\n 'vue',\n 'vue-router',\n '@lucide/vue',\n '@vueuse/core',\n '@vueuse/shared',\n 'reka-ui',\n 'class-variance-authority',\n 'clsx',\n 'tailwind-merge',\n 'culori',\n ],\n },\n server: {\n // Cherry-pick Vite's `server` options (e.g. watch.ignored) from the\n // user's `vite` config; Maizzle's required keys below take precedence.\n ...config.vite?.server,\n port,\n host,\n fs: {\n ...config.vite?.server?.fs,\n allow: [process.cwd(), config.root ?? process.cwd(), devUIDir, ...['vue', 'vue-router', 'reka-ui', '@vueuse/core', '@vueuse/shared', '@lucide/vue', 'class-variance-authority', 'clsx', 'tailwind-merge', 'culori'].map(pkg), ...(config.vite?.server?.fs?.allow ?? [])],\n },\n },\n customLogger: customLogger(),\n })\n\n // Store renderer ref on server for cleanup\n const originalClose = server.close.bind(server)\n server.close = async () => {\n setActiveRenderer(null)\n await renderer.close()\n return originalClose()\n }\n\n await server.listen()\n\n const startupTime = Math.round(performance.now() - start)\n\n if (!options.silent) {\n printBanner(server, startupTime)\n }\n\n // Expose startup time so the plugin can print it later\n ; (server as any)._maizzleStartupTime = startupTime\n\n return server\n}\n\n/**\n * Internal Vite plugin that adds Maizzle middleware and file watching to the dev UI server.\n */\nfunction maizzleDevPlugin(\n config: MaizzleConfig,\n renderer: Renderer,\n events: EventManager,\n configInput: Partial<MaizzleConfig> | string | undefined,\n) {\n return {\n name: 'maizzle:dev',\n enforce: 'pre' as const,\n\n hotUpdate: {\n order: 'pre' as const,\n handler({ file }: { file: string }) {\n /**\n * Prevent Tailwind/Vue from triggering a full reload for email template\n * files. Maizzle handles these via custom HMR events in the\n * watcher below.\n */\n if (isTemplateFile(file)) {\n return []\n }\n },\n },\n\n configureServer(server: ViteDevServer) {\n // File watching\n const defaultWatchPaths = [\n 'maizzle.config.js',\n 'maizzle.config.ts',\n 'tailwind.config.js',\n 'tailwind.config.ts',\n 'locales/**',\n ]\n\n const userWatchPaths = config.server?.watch ?? []\n const watchPaths = [...defaultWatchPaths, ...userWatchPaths]\n // Match against cwd, not config.root: the watched paths (maizzle/tailwind\n // configs, locales) are project-root relative, and `watcher.add` below\n // resolves them against cwd too. Using config.root would break matching\n // when root points at a subdirectory (e.g. the Vite-plugin setup).\n const isWatchedFile = createWatchedFileMatcher(watchPaths, process.cwd())\n\n for (const watchPath of watchPaths) {\n server.watcher.add(watchPath)\n }\n\n /**\n * Serialize watcher work onto one chain. The change handler closes and\n * recreates the renderer across awaits; without serialization a second\n * event firing mid-reload closes a stale renderer and leaks the new one.\n * Errors are caught so one failed task doesn't break the chain.\n */\n let watcherChain: Promise<void> = Promise.resolve()\n const enqueue = (task: () => Promise<void>): Promise<void> => {\n watcherChain = watcherChain.then(task).catch((err) => {\n console.error('[maizzle] watcher task failed:', err)\n })\n return watcherChain\n }\n\n server.watcher.on('add', file => enqueue(async () => {\n if (isTemplateFile(file)) {\n await renderer.invalidateAll()\n bumpGeneration()\n server.ws.send({ type: 'custom', event: 'maizzle:templates-changed' })\n }\n }))\n\n server.watcher.on('unlink', file => enqueue(async () => {\n if (isTemplateFile(file)) {\n await renderer.invalidateAll()\n bumpGeneration()\n server.ws.send({ type: 'custom', event: 'maizzle:templates-changed' })\n }\n }))\n\n server.watcher.on('change', file => enqueue(async () => {\n if (isWatchedFile(file)) {\n config = await resolveConfig(configInput)\n\n // Re-register event handlers against the reloaded config (the config\n // object is replaced wholesale, so old handlers would be stale).\n events.clear()\n events.registerConfig(config)\n\n // Recreate the renderer so config changes (e.g. markdown.shikiTheme) take effect\n await renderer.close()\n renderer = await createRenderer({ dts: true, markdown: config.markdown, root: config.root, componentDirs: normalizeComponentSources(config.components?.source, process.cwd()), vite: config.vite, customElements: config.vue?.customElements })\n\n // Re-register the new renderer so user-land render() calls don't keep\n // reusing the closed one (see setActiveRenderer above).\n setActiveRenderer(renderer)\n\n /**\n * Push UI-relevant config bits so the dev UI reacts to live edits\n * without a page reload. Uses the same shape as the initial\n * inject.\n */\n server.ws.send({ type: 'custom', event: 'maizzle:config-updated', data: buildUiConfig(config) })\n }\n\n /**\n * Invalidate all renderer modules so component and config changes\n * are picked up on the next render (Tailwind recompiles with\n * fresh content).\n */\n await renderer.invalidateAll()\n bumpGeneration()\n\n if (\n isTemplateFile(file)\n || isWatchedFile(file)\n ) {\n server.ws.send({ type: 'custom', event: 'maizzle:template-updated', data: { file } })\n }\n }))\n\n // API middleware (before Vite's middleware)\n server.middlewares.use(async (req: any, res: any, next: any) => {\n const url = req.url || '/'\n\n if (url === '/__maizzle/templates') {\n return serveTemplateList(config, res)\n }\n\n if (url.startsWith('/__maizzle/render/')) {\n return await serveRenderedTemplate(url, config, renderer, events, res)\n }\n\n if (url.startsWith('/__maizzle/source/')) {\n return await serveHighlightedSource(url, config, renderer, events, res)\n }\n\n if (url.startsWith('/__maizzle/compatibility/')) {\n return await serveCompatibility(url, res, config, normalizeComponentSources(config.components?.source, process.cwd()))\n }\n\n if (url.startsWith('/__maizzle/lint/')) {\n return await serveLint(url, res, config, normalizeComponentSources(config.components?.source, process.cwd()))\n }\n\n if (url.startsWith('/__maizzle/vue-source/')) {\n return await serveVueSource(url, config, res)\n }\n\n if (url.startsWith('/__maizzle/plaintext/')) {\n return await servePlaintext(url, config, renderer, events, res)\n }\n\n if (url.startsWith('/__maizzle/stats/')) {\n return await serveStats(url, config, renderer, events, res)\n }\n\n if (url.startsWith('/__maizzle/email/') && req.method === 'POST') {\n return await serveEmailEndpoint(url, req, res, config, renderer, events)\n }\n\n if (url === '/__maizzle/email-config') {\n return serveEmailConfig(config, res)\n }\n\n next()\n })\n\n // Dev UI fallback (after Vite's middleware)\n return () => {\n server.middlewares.use(async (req: any, res: any, next: any) => {\n if (isNavigationRequest(req)) {\n return await serveDevUI(server, res, req.url || '/', config)\n }\n\n next()\n })\n }\n },\n }\n}\n\nfunction isTemplateFile(file: string): boolean {\n return (file.endsWith('.vue') || file.endsWith('.md')) && !file.includes('server/ui')\n}\n\nfunction isNavigationRequest(req: any): boolean {\n const accept = req.headers?.accept || ''\n return req.method === 'GET' && accept.includes('text/html')\n}\n\n/**\n * Shape exposed to the dev UI both at initial HTML load (as\n * `window.__MAIZZLE_CONFIG__`) and on the `maizzle:config-updated` HMR event.\n * Add UI-visible config bits here; consumers on both ends pick up automatically.\n */\nfunction buildUiConfig(config: MaizzleConfig) {\n return {\n checks: config.server?.checks ?? true,\n }\n}\n\nasync function serveDevUI(server: ViteDevServer, res: any, url: string, config: MaizzleConfig) {\n let indexHtml = readFileSync(resolve(devUIDir, 'index.html'), 'utf-8')\n\n indexHtml = indexHtml.replace('./main.ts', `/@fs/${resolve(devUIDir, 'main.ts')}`)\n indexHtml = indexHtml.replace('./favicon.svg', `/@fs/${resolve(devUIDir, 'favicon.svg')}`)\n\n const configScript = `<script>window.__MAIZZLE_CONFIG__ = ${JSON.stringify(buildUiConfig(config))};</script>`\n indexHtml = indexHtml.replace('</head>', `${configScript}</head>`)\n\n const transformed = await server.transformIndexHtml(url, indexHtml)\n\n res.setHeader('Content-Type', 'text/html')\n res.end(transformed)\n}\n\nasync function serveTemplateList(config: MaizzleConfig, res: any) {\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n\n const data = templates.map(t => ({\n name: basename(t).replace(/\\.(vue|md)$/, ''),\n path: t,\n href: '/' + t.replace(/\\.(vue|md)$/, ''),\n }))\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify(data))\n}\n\ninterface DedupedRender {\n /** Transformer output — before doctype prepend / stripForHtml / stripForPlaintext. */\n rawHtml: string\n doctype: string\n templateConfig: MaizzleConfig\n rendered: RenderedTemplate\n}\n\n/**\n * Render-result memo for the dev server. A single template save makes the\n * browser fire several endpoint requests in parallel (render, source, stats,\n * plaintext, email) that each need the same SSR render + transformer output.\n * Keying the in-flight Promise by `${generation}:${path}` collapses those into\n * one render and dedupes concurrent requests. The watcher bumps the generation\n * (and clears the cache) on every file/config change, so results never go\n * stale. Each endpoint applies its own tail step (doctype prepend, strip,\n * highlight, …) on top of `rawHtml`, keeping output byte-identical.\n */\nlet renderGeneration = 0\nconst renderCache = new Map<string, Promise<DedupedRender>>()\n\nfunction bumpGeneration() {\n renderGeneration++\n renderCache.clear()\n}\n\nfunction getRendered(absolutePath: string, config: MaizzleConfig, renderer: Renderer, events: EventManager): Promise<DedupedRender> {\n const key = `${renderGeneration}:${absolutePath}`\n let promise = renderCache.get(key)\n if (!promise) {\n promise = (async () => {\n _setCurrentTemplate(parsePath(absolutePath))\n try {\n /**\n * Mirror the build's per-template event pipeline (see buildTemplate)\n * so dev preview fires the same beforeRender / afterRender /\n * afterTransform hooks and matches production output. Clone config so\n * beforeRender mutations stay scoped to this render.\n */\n const renderConfig = cloneConfig(config)\n const template = { source: readFileSync(absolutePath, 'utf-8'), path: parsePath(absolutePath) }\n const originalSource = template.source\n\n await events.fireBeforeRender({ config: renderConfig, template })\n\n const rendered = await renderer.render(\n absolutePath,\n renderConfig,\n template.source !== originalSource ? { source: template.source } : undefined,\n )\n\n for (const { name, handler } of rendered.sfcEventHandlers) {\n events.on(name, handler)\n }\n\n const templateConfig = rendered.templateConfig\n let html = await events.fireAfterRender({ config: templateConfig, template, html: rendered.html })\n const doctype = rendered.doctype ?? templateConfig.doctype ?? '<!DOCTYPE html>'\n\n if (templateConfig.useTransformers !== false) {\n html = await runTransformers(html, templateConfig, absolutePath, doctype, rendered.tailwindBlocks, rendered.sourceFiles)\n }\n\n const rawHtml = await events.fireAfterTransform({ config: templateConfig, template, html })\n\n return { rawHtml, doctype, templateConfig, rendered }\n } finally {\n _setCurrentTemplate(undefined)\n events.clearSfcHandlers()\n }\n })()\n renderCache.set(key, promise)\n }\n return promise\n}\n\n/**\n * SSR render a .vue template using the Renderer (not the dev UI server).\n */\nasync function serveRenderedTemplate(url: string, config: MaizzleConfig, renderer: Renderer, events: EventManager, res: any) {\n const templateSlug = url.replace('/__maizzle/render/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n const absolutePath = resolve(match)\n\n try {\n const { rawHtml, doctype } = await getRendered(absolutePath, config, renderer, events)\n let html = rawHtml\n if (doctype) html = `${doctype}\\n${html}`\n\n res.setHeader('Content-Type', 'text/html')\n res.end(stripForHtml(html))\n } catch (error: any) {\n res.statusCode = 500\n res.end(`<pre>${error.stack || error.message}</pre>`)\n }\n}\n\nlet highlighter: Highlighter | null = null\n\nasync function getHighlighter() {\n if (!highlighter) {\n highlighter = await createHighlighter({\n themes: ['laserwave'],\n langs: ['html', 'vue'],\n })\n }\n return highlighter\n}\n\nasync function serveHighlightedSource(url: string, config: MaizzleConfig, renderer: Renderer, events: EventManager, res: any) {\n const templateSlug = url.replace('/__maizzle/source/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n const absolutePath = resolve(match)\n\n try {\n const { rawHtml, doctype } = await getRendered(absolutePath, config, renderer, events)\n const html = stripForHtml(doctype ? `${doctype}\\n${rawHtml}` : rawHtml)\n\n const hl = await getHighlighter()\n const highlighted = hl.codeToHtml(html, {\n lang: 'html',\n theme: 'laserwave',\n transformers: [{\n line(node, line) {\n node.properties['data-line'] = line\n },\n }],\n })\n\n res.setHeader('Content-Type', 'text/html')\n res.end(highlighted)\n } catch (error: any) {\n res.statusCode = 500\n res.end(`<pre>${error.stack || error.message}</pre>`)\n }\n}\n\nasync function serveVueSource(url: string, config: MaizzleConfig, res: any) {\n const templateSlug = url.replace('/__maizzle/vue-source/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n try {\n const source = readFileSync(resolve(match), 'utf-8')\n const lang = match.endsWith('.md') ? 'html' : 'vue'\n\n const hl = await getHighlighter()\n const highlighted = hl.codeToHtml(source, {\n lang,\n theme: 'laserwave',\n transformers: [{\n line(node, line) {\n node.properties['data-line'] = line\n },\n }],\n })\n\n res.setHeader('Content-Type', 'text/html')\n res.end(highlighted)\n } catch (error: any) {\n res.statusCode = 500\n res.end(`<pre>${error.stack || error.message}</pre>`)\n }\n}\n\nasync function servePlaintext(url: string, config: MaizzleConfig, renderer: Renderer, events: EventManager, res: any) {\n const templateSlug = url.replace('/__maizzle/plaintext/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n const absolutePath = resolve(match)\n\n try {\n const { rawHtml } = await getRendered(absolutePath, config, renderer, events)\n const plaintext = createPlaintext(stripForPlaintext(rawHtml))\n\n res.setHeader('Content-Type', 'text/plain')\n res.end(plaintext)\n } catch (error: any) {\n res.statusCode = 500\n res.end(error.message)\n }\n}\n\nfunction humanFileSize(bytes: number, si = false, dp = 2) {\n const threshold = si ? 1000 : 1024\n\n if (Math.abs(bytes) < threshold) {\n return bytes + ' B'\n }\n\n const units = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n let u = -1\n const r = 10 ** dp\n\n do {\n bytes /= threshold\n ++u\n } while (Math.round(Math.abs(bytes) * r) / r >= threshold && u < units.length - 1)\n\n return bytes.toFixed(dp) + ' ' + units[u]\n}\n\nasync function serveStats(url: string, config: MaizzleConfig, renderer: Renderer, events: EventManager, res: any) {\n const templateSlug = url.replace('/__maizzle/stats/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end(JSON.stringify({ error: 'Template not found' }))\n return\n }\n\n const absolutePath = resolve(match)\n\n try {\n const { rawHtml } = await getRendered(absolutePath, config, renderer, events)\n const html = stripForHtml(rawHtml)\n\n const sizeBytes = new TextEncoder().encode(html).length\n\n // Count images: <img> tags and CSS background images\n const imgTags = (html.match(/<img\\b[^>]*>/gi) || []).length\n const bgImages = (html.match(/url\\s*\\([^)]+\\)/gi) || []).length\n const totalImages = imgTags + bgImages\n\n // Count links\n const links = (html.match(/<a\\b[^>]*href\\s*=/gi) || []).length\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify({\n size: {\n bytes: sizeBytes,\n formatted: humanFileSize(sizeBytes),\n },\n images: totalImages,\n links,\n }))\n } catch (error: any) {\n res.statusCode = 500\n res.end(JSON.stringify({ error: error.message }))\n }\n}\n\nasync function serveEmailEndpoint(url: string, req: any, res: any, config: MaizzleConfig, renderer: Renderer, events: EventManager) {\n const templateSlug = url.replace('/__maizzle/email/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end(JSON.stringify({ success: false, message: 'Template not found' }))\n return\n }\n\n let body = ''\n for await (const chunk of req) body += chunk\n\n let payload: { to: string[]; subject: string }\n\n try {\n payload = JSON.parse(body)\n } catch {\n res.statusCode = 400\n res.end(JSON.stringify({ success: false, message: 'Invalid JSON' }))\n return\n }\n\n if (!payload.to?.length) {\n res.statusCode = 400\n res.end(JSON.stringify({ success: false, message: 'Missing recipients' }))\n return\n }\n\n const absolutePath = resolve(match)\n\n try {\n const { rawHtml, doctype, templateConfig } = await getRendered(absolutePath, config, renderer, events)\n let html = doctype ? `${doctype}\\n${rawHtml}` : rawHtml\n\n const text = createPlaintext(stripForPlaintext(html))\n html = stripForHtml(html)\n\n const result = await sendEmail(\n { to: payload.to, subject: payload.subject, html, text },\n config,\n templateConfig,\n )\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify(result))\n } catch (error: any) {\n res.statusCode = 500\n res.end(JSON.stringify({ success: false, message: error.message }))\n }\n}\n\nfunction serveEmailConfig(config: MaizzleConfig, res: any) {\n const emailConfig = config.server?.email\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify({\n to: emailConfig?.to ? (Array.isArray(emailConfig.to) ? emailConfig.to : [emailConfig.to]) : [],\n from: emailConfig?.from ?? '',\n subject: emailConfig?.subject ?? '',\n hasTransport: !!emailConfig?.transport,\n }))\n}\n\nexport function printBanner(server: ViteDevServer, startupTime?: number) {\n const info = server.config.logger.info\n const time = startupTime ?? (server as any)._maizzleStartupTime\n\n const networkUrl = server.resolvedUrls?.network[0]\n if (networkUrl) {\n const qr = renderUnicodeCompact(networkUrl, { border: 1 })\n info('')\n info(qr.split('\\n').map(line => ` ${line}`).join('\\n'))\n }\n\n info('')\n info(` \\x1b[32m\\x1b[1mMAIZZLE\\x1b[0m\\x1b[32m v${version}\\x1b[0m \\x1b[2mready in\\x1b[0m \\x1b[1m${time}\\x1b[0m ms`)\n info('')\n server.printUrls()\n info('')\n}\n\nfunction customLogger() {\n const logger = createLogger('info')\n const warn = logger.warn\n\n logger.warn = (message, options) => {\n if (typeof message === 'string' && message.includes('<tr> cannot be child of <table>')) {\n return\n }\n\n warn(message, options)\n }\n\n return logger\n}\n"],"mappings":"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"}
|
|
@@ -767,7 +767,8 @@ function labelFor(idx, level) {
|
|
|
767
767
|
async function scan(rootFile, config, componentDirs, allowedClients) {
|
|
768
768
|
const idx = await initCompatibility();
|
|
769
769
|
if (!idx) return [];
|
|
770
|
-
const
|
|
770
|
+
const root = config.root ?? process.cwd();
|
|
771
|
+
const componentMap = await buildComponentMap(root, componentDirs);
|
|
771
772
|
const streams = [];
|
|
772
773
|
collectStreams(rootFile, componentMap, /* @__PURE__ */ new Set(), streams);
|
|
773
774
|
const issues = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compatibility.js","names":["compileWithPipeline"],"sources":["../../src/server/compatibility.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport postcss, { type Declaration, type AtRule, type Rule } from 'postcss'\nimport safeParser from 'postcss-safe-parser'\nimport valueParser from 'postcss-value-parser'\nimport { Parser } from 'htmlparser2'\nimport { DomHandler, type ChildNode, type Element } from 'domhandler'\nimport { parseSfcBlocks, findComponentTags, buildComponentMap, isFrameworkComponent, type SfcBlock } from './sfc-utils.ts'\nimport { scanLint } from './linter.ts'\nimport { tailwindcss as compileWithPipeline } from '../transformers/tailwindcss.ts'\nimport type { MaizzleConfig } from '../types/index.ts'\nimport type { NormalizedComponentSource } from '../utils/componentSources.ts'\n\nconst API_URL = 'https://www.caniemail.com/api/data.json'\nconst DEFAULT_CLIENTS = new Set(['gmail', 'apple-mail', 'outlook', 'yahoo'])\n\ntype SupportLevel = 'unsupported' | 'mitigated' | 'unknown'\n\ninterface Feature {\n slug: string\n title: string\n url: string\n category: string\n stats: any\n}\n\ninterface Issue {\n kind: 'compat' | 'lint'\n slug?: string\n title: string\n url?: string\n category: string\n line?: number\n file: string\n // compat-only\n supportLevel?: SupportLevel\n supportLabel?: string\n affectedClients?: string[]\n // lint-only\n severity?: 'error' | 'warning'\n message?: string\n}\n\ninterface Indexes {\n nicenames: { supported: string, mitigated: string, unsupported: string, unknown: string, mixed: string }\n familyNicenames: Record<string, string>\n cssProp: Map<string, Feature[]>\n cssPropValue: Map<string, Array<{ value: string, feature: Feature }>>\n cssAtRule: Map<string, Feature[]>\n cssMediaFeature: Map<string, Feature[]>\n cssPseudoClass: Map<string, Feature[]>\n cssPseudoElement: Map<string, Feature[]>\n cssFunction: Map<string, Feature[]>\n cssUnit: Map<string, Feature[]>\n cssImportant?: Feature\n cssVariables?: Feature\n cssNesting?: Feature\n cssComments?: Feature\n cssModernColor?: Feature\n htmlTag: Map<string, Feature[]>\n htmlAttr: Map<string, Feature[]>\n htmlInputType: Map<string, Feature[]>\n htmlButtonType: Map<string, Feature[]>\n htmlDoctype?: Feature\n htmlComments?: Feature\n htmlAnchorLinks?: Feature\n htmlMailtoLinks?: Feature\n htmlMetaColorScheme?: Feature\n htmlSemantics?: Feature\n htmlStyleInBody?: Feature\n imageExt: Map<string, Feature[]>\n /** All features by slug — unfiltered, used for URL lookups (e.g. by lint). */\n bySlug: Map<string, { title: string, url: string }>\n}\n\nlet indexes: Indexes | null = null\nlet initPromise: Promise<Indexes | null> | null = null\n\nfunction mpush<K, V>(m: Map<K, V[]>, k: K, v: V) {\n const arr = m.get(k)\n if (arr) arr.push(v)\n else m.set(k, [v])\n}\n\nfunction emptyIndexes(nicenames: any, familyNicenames: Record<string, string>): Indexes {\n return {\n nicenames,\n familyNicenames,\n cssProp: new Map(), cssPropValue: new Map(), cssAtRule: new Map(),\n cssMediaFeature: new Map(), cssPseudoClass: new Map(), cssPseudoElement: new Map(),\n cssFunction: new Map(), cssUnit: new Map(),\n htmlTag: new Map(), htmlAttr: new Map(), htmlInputType: new Map(), htmlButtonType: new Map(),\n imageExt: new Map(),\n bySlug: new Map(),\n }\n}\n\nfunction hasAnyNonY(stats: any): boolean {\n if (!stats) return false\n for (const family in stats) {\n for (const plat in stats[family]) {\n for (const ver in stats[family][plat]) {\n const v = stripNotes(String(stats[family][plat][ver]).trim())\n if (v && v !== 'y') return true\n }\n }\n }\n return false\n}\n\n/** Strip `#N` note markers — `\"y #1\"` → `\"y\"`. Notes document edge cases but\n * don't change support semantics, so treat `y #1` as fully supported. */\nfunction stripNotes(v: string): string {\n return v.split(/\\s+/).filter(t => t && !t.startsWith('#')).join(' ')\n}\n\nfunction computeSupport(stats: any, familyNicenames: Record<string, string>, allowedClients: Set<string> | 'all'): { level: SupportLevel, affected: string[] } | null {\n let nY = 0, nN = 0, nU = 0, nPartial = 0, total = 0\n const affectedFamilies = new Set<string>()\n for (const family in stats) {\n if (allowedClients !== 'all' && !allowedClients.has(family)) continue\n let familyHasNonY = false\n for (const plat in stats[family]) {\n /**\n * Only score the latest version per (family, platform) — legacy\n * versions (Outlook 2007, etc.) otherwise flag modern-widely\n * supported features as partial forever.\n */\n const versions = Object.keys(stats[family][plat]).sort()\n const latest = versions[versions.length - 1]\n if (!latest) continue\n total++\n const v = stripNotes(String(stats[family][plat][latest]).trim())\n if (v === 'y') nY++\n else if (v === 'n') { nN++; familyHasNonY = true }\n else if (v === 'u') { nU++; familyHasNonY = true }\n else { nPartial++; familyHasNonY = true }\n }\n if (familyHasNonY) affectedFamilies.add(family)\n }\n if (!total) return null\n if (nY === total) return null\n const affected = [...affectedFamilies].map(f => familyNicenames[f] ?? f).sort()\n if (nN === total) return { level: 'unsupported', affected }\n if (nU === total) return { level: 'unknown', affected }\n return { level: 'mitigated', affected }\n}\n\n/**\n * Slugs we never report. Fundamental HTML (every email uses these) plus\n * CSS noise that's not actionable (comments, !important usage).\n */\nconst IGNORED_SLUGS = new Set([\n // Required/unavoidable tags\n 'html-doctype', 'html-comments',\n 'html-html', 'html-head', 'html-body', 'html-title',\n 'html-meta', 'html-meta-color-scheme',\n 'html-style', 'html-link',\n 'html-div', 'html-span', 'html-br', 'html-p', 'html-a', 'html-img',\n 'html-table', 'html-tr', 'html-td', 'html-th',\n 'html-thead', 'html-tbody', 'html-tfoot',\n 'html-h1-h6', 'html-lists',\n 'html-strong', 'html-em', 'html-b', 'html-i', 'html-u',\n 'html-semantics',\n // Ubiquitous attributes — always present, caveats aren't actionable.\n 'html-role', 'html-hidden', 'html-width', 'html-height',\n // CSS noise\n 'css-comments', 'css-important',\n /**\n * CSS fundamentals — universally used with known minor caveats; flagging\n * them as \"partial\" is noise rather than signal.\n */\n 'css-margin', 'css-padding', 'css-border',\n 'css-font-size', 'css-font-weight', 'css-font', 'css-font-family',\n 'css-line-height', 'css-letter-spacing', 'css-text-align',\n 'css-text-decoration', 'css-text-transform', 'css-color',\n 'css-background', 'css-background-color',\n 'css-width', 'css-height',\n 'css-display',\n])\n\nfunction classify(f: Feature, idx: Indexes) {\n const slug = f.slug\n /**\n * Retain html-style feature for the body-only detector even though it's\n * blacklisted from the normal html-tag detection path. Title is\n * suffixed so the flag reads as a body-placement warning, not a\n * blanket `<style>`.\n */\n if (slug === 'html-style') {\n idx.htmlStyleInBody = { ...f, title: `${f.title} in <body>` }\n return\n }\n if (IGNORED_SLUGS.has(slug)) return\n\n if (f.category === 'css') return classifyCss(f, slug, idx)\n if (f.category === 'html') return classifyHtml(f, slug, idx)\n if (f.category === 'image') {\n const ext = slug.slice('image-'.length)\n if (ext === 'base64') return\n mpush(idx.imageExt, ext, f)\n }\n // 'others' (amp, bimi) intentionally skipped\n}\n\nfunction classifyCss(f: Feature, slug: string, idx: Indexes) {\n // Specials first\n switch (slug) {\n case 'css-important': idx.cssImportant = f; return\n case 'css-variables': idx.cssVariables = f; return\n case 'css-nesting': idx.cssNesting = f; return\n case 'css-comments': idx.cssComments = f; return\n case 'css-modern-color': idx.cssModernColor = f; return\n case 'css-display-flex': mpushPropValue(idx, 'display', 'flex', f); return\n case 'css-display-grid': mpushPropValue(idx, 'display', 'grid', f); return\n case 'css-display-none': mpushPropValue(idx, 'display', 'none', f); return\n case 'css-rgb': mpush(idx.cssFunction, 'rgb', f); return\n case 'css-rgba': mpush(idx.cssFunction, 'rgba', f); return\n case 'css-linear-gradient': mpush(idx.cssFunction, 'linear-gradient', f); return\n case 'css-radial-gradient': mpush(idx.cssFunction, 'radial-gradient', f); return\n case 'css-conic-gradient': mpush(idx.cssFunction, 'conic-gradient', f); return\n }\n\n if (slug.startsWith('css-at-media-') && slug !== 'css-at-media') {\n mpush(idx.cssMediaFeature, slug.slice('css-at-media-'.length), f)\n return\n }\n if (slug.startsWith('css-at-')) {\n mpush(idx.cssAtRule, slug.slice('css-at-'.length), f)\n return\n }\n if (slug.startsWith('css-pseudo-class-')) {\n mpush(idx.cssPseudoClass, slug.slice('css-pseudo-class-'.length), f)\n return\n }\n if (slug.startsWith('css-pseudo-element-')) {\n mpush(idx.cssPseudoElement, slug.slice('css-pseudo-element-'.length), f)\n return\n }\n if (slug.startsWith('css-unit-')) {\n const u = slug.slice('css-unit-'.length)\n if (u === 'calc') { mpush(idx.cssFunction, 'calc', f); return }\n if (u === 'initial') return // keyword detection is noisy; skip\n const unit = u === 'percent' ? '%' : u\n mpush(idx.cssUnit, unit, f)\n return\n }\n if (slug.startsWith('css-function-')) {\n mpush(idx.cssFunction, slug.slice('css-function-'.length), f)\n return\n }\n // css-selector-* — skip (too broad to detect meaningfully)\n if (slug.startsWith('css-selector-')) return\n\n // Fallback: treat as property name\n mpush(idx.cssProp, slug.slice('css-'.length), f)\n}\n\nfunction mpushPropValue(idx: Indexes, prop: string, value: string, f: Feature) {\n const arr = idx.cssPropValue.get(prop)\n if (arr) arr.push({ value, feature: f })\n else idx.cssPropValue.set(prop, [{ value, feature: f }])\n}\n\nconst HTML_ATTR_SLUGS = new Set([\n 'align', 'background', 'cellpadding', 'cellspacing', 'height', 'width',\n 'valign', 'target', 'srcset', 'lang', 'dir', 'role', 'required', 'hidden',\n])\n\nfunction classifyHtml(f: Feature, slug: string, idx: Indexes) {\n // Specials\n switch (slug) {\n case 'html-doctype': idx.htmlDoctype = f; return\n case 'html-comments': idx.htmlComments = f; return\n case 'html-anchor-links': idx.htmlAnchorLinks = f; return\n case 'html-mailto-links': idx.htmlMailtoLinks = f; return\n case 'html-meta-color-scheme': idx.htmlMetaColorScheme = f; return\n case 'html-semantics': idx.htmlSemantics = f; return\n case 'html-loading-attribute': mpush(idx.htmlAttr, 'loading', f); return\n case 'html-image-maps':\n mpush(idx.htmlTag, 'map', f); mpush(idx.htmlTag, 'area', f); mpush(idx.htmlAttr, 'usemap', f); return\n case 'html-lists':\n for (const t of ['ul', 'ol', 'li', 'dl', 'dt', 'dd']) mpush(idx.htmlTag, t, f)\n return\n case 'html-h1-h6':\n for (const t of ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']) mpush(idx.htmlTag, t, f)\n return\n }\n\n if (slug.startsWith('html-input-')) {\n mpush(idx.htmlInputType, slug.slice('html-input-'.length), f)\n return\n }\n if (slug.startsWith('html-button-')) {\n mpush(idx.htmlButtonType, slug.slice('html-button-'.length), f)\n return\n }\n if (slug.startsWith('html-aria-')) {\n mpush(idx.htmlAttr, slug.slice('html-'.length), f)\n return\n }\n const name = slug.slice('html-'.length)\n if (HTML_ATTR_SLUGS.has(name)) {\n mpush(idx.htmlAttr, name, f)\n return\n }\n mpush(idx.htmlTag, name, f)\n}\n\nexport async function initCompatibility(): Promise<Indexes | null> {\n if (indexes) return indexes\n if (initPromise) return initPromise\n initPromise = (async () => {\n try {\n const res = await fetch(API_URL)\n if (!res.ok) return null\n const data = await res.json()\n const idx = emptyIndexes(data.nicenames?.support ?? {}, data.nicenames?.family ?? {})\n for (const item of data.data ?? []) {\n /**\n * Record every slug's title/url so lint can look up caniemail\n * pages for issues that map to a known feature, even ignored.\n */\n if (item.slug && item.url) idx.bySlug.set(item.slug, { title: item.title, url: item.url })\n /**\n * Index the feature if any cell anywhere in the matrix is non-y.\n * Per-request aggregation (with the active client filter)\n * decides whether to actually surface the issue.\n */\n if (!hasAnyNonY(item.stats)) continue\n const f: Feature = {\n slug: item.slug,\n title: item.title,\n url: item.url,\n category: item.category,\n stats: item.stats,\n }\n classify(f, idx)\n }\n indexes = idx\n return idx\n } catch {\n return null\n }\n })()\n return initPromise\n}\n\n/**\n * Note: fetch of the caniemail dataset is lazy — it fires on the first\n * check request, not at module load, so `server.checks: false` pays\n * no network cost.\n */\n\ninterface FileStreams {\n path: string\n source: string\n template: SfcBlock | null\n styles: SfcBlock[]\n classes: Set<string>\n}\n\nfunction collectStreams(\n filePath: string,\n componentMap: Map<string, string>,\n visited: Set<string>,\n out: FileStreams[],\n) {\n if (visited.has(filePath)) return\n visited.add(filePath)\n\n let source: string\n try {\n source = readFileSync(filePath, 'utf-8')\n } catch { return }\n\n const { template, styles } = parseSfcBlocks(source)\n const classes = new Set<string>()\n if (template) extractClasses(template.content, classes)\n\n out.push({ path: filePath, source, template, styles, classes })\n\n if (template) {\n for (const tag of findComponentTags(template.content)) {\n const cp = componentMap.get(tag.toLowerCase())\n if (cp) collectStreams(cp, componentMap, visited, out)\n }\n }\n}\n\nfunction extractClasses(html: string, out: Set<string>) {\n const parser = new Parser({\n onopentag(_tag, attrs) {\n const c = attrs.class\n if (!c) return\n for (const t of c.split(/\\s+/)) if (t) out.add(t)\n },\n }, { decodeEntities: true })\n parser.write(html)\n parser.end()\n}\n\nfunction parseWithIndices(html: string): ChildNode[] {\n const handler = new DomHandler(undefined, { withStartIndices: true })\n const parser = new Parser(handler)\n parser.write(html)\n parser.end()\n return handler.dom\n}\n\nfunction findStyleNodes(nodes: ChildNode[], out: Element[] = []): Element[] {\n for (const n of nodes) {\n const el = n as Element\n if (el.name === 'style') out.push(el)\n if (el.children?.length) findStyleNodes(el.children as ChildNode[], out)\n }\n return out\n}\n\n/**\n * Parse each file's template, collect every `<style>` node with its source\n * line (via htmlparser2 start indices), then pass the combined DOM through\n * the framework's real Tailwind pipeline. The pipeline resolves imports\n * (@maizzle/tailwindcss), compiles utilities from class attrs, lowers modern\n * CSS via lightningcss, and resolves static calc() — so what we walk matches\n * what ships.\n */\nasync function compileViaPipeline(\n streams: FileStreams[],\n config: MaizzleConfig,\n rootFile: string,\n): Promise<Array<{ file: string, css: string, line: number }>> {\n const all: ChildNode[] = []\n const tracked: Array<{ node: Element, file: string, line: number }> = []\n\n for (const s of streams) {\n if (!s.template) continue\n const templateStart = s.source.indexOf(s.template.content)\n const nodes = parseWithIndices(s.template.content)\n for (const styleNode of findStyleNodes(nodes)) {\n const startIdx = (styleNode as any).startIndex ?? 0\n const line = offsetToLine(s.source, templateStart + startIdx)\n tracked.push({ node: styleNode, file: s.path, line })\n }\n for (const n of nodes) all.push(n)\n }\n\n if (!tracked.length) return []\n\n try {\n await compileWithPipeline(all, config, rootFile)\n } catch { return [] }\n\n return tracked\n .map(t => {\n const txt = t.node.children?.find(c => (c as any).type === 'text') as any\n return txt?.data ? { file: t.file, css: txt.data as string, line: t.line } : null\n })\n .filter((x): x is { file: string, css: string, line: number } => x !== null)\n}\n\n/**\n * Walk CSS AST with detectors. Calls onHit per feature hit.\n * `selector` is the containing rule's selector (undefined if no rule ancestor).\n */\nfunction walkCss(\n css: string,\n idx: Indexes,\n onHit: (feature: Feature, node: { line?: number, selector?: string }) => void,\n) {\n let root: postcss.Root\n try { root = safeParser(css) } catch { return }\n\n const containingSelector = (n: postcss.Node | undefined): string | undefined => {\n let p = n?.parent\n while (p && p.type !== 'root') {\n if (p.type === 'rule') return (p as Rule).selector\n p = p.parent\n }\n return undefined\n }\n\n if (idx.cssComments) {\n root.walkComments((c) => { onHit(idx.cssComments!, { line: c.source?.start?.line, selector: containingSelector(c) }) })\n }\n\n root.walkAtRules((atRule: AtRule) => {\n const line = atRule.source?.start?.line\n let sel = containingSelector(atRule)\n if (atRule.name === 'media' && !sel) {\n const innerSelectors: string[] = []\n atRule.walkRules((r) => { innerSelectors.push(r.selector) })\n if (innerSelectors.length) sel = innerSelectors.join(', ')\n }\n\n if (atRule.name === 'media') {\n /**\n * Pick the most specific media-feature match (prefers-color-scheme,\n * hover, orientation, …). If one matches, skip the generic\n * `css-at-media` to avoid duplicate rows on the same line.\n */\n const specific: Feature[] = []\n if (idx.cssMediaFeature.size) {\n for (const [feat, fs2] of idx.cssMediaFeature) {\n if (atRule.params.includes(`(${feat}`) || atRule.params.includes(feat)) {\n specific.push(...fs2)\n }\n }\n }\n if (specific.length) {\n for (const f of specific) onHit(f, { line, selector: sel })\n } else {\n const fs = idx.cssAtRule.get('media')\n if (fs) for (const f of fs) onHit(f, { line, selector: sel })\n }\n } else {\n const fs = idx.cssAtRule.get(atRule.name)\n if (fs) for (const f of fs) onHit(f, { line, selector: sel })\n }\n })\n\n root.walkRules((rule: Rule) => {\n const line = rule.source?.start?.line\n const sel = rule.selector\n if (idx.cssPseudoClass.size) {\n for (const [name, fs] of idx.cssPseudoClass) {\n const re = new RegExp(`(^|[^:]):${escapeRe(name)}(\\\\b|\\\\()`)\n if (re.test(sel)) for (const f of fs) onHit(f, { line, selector: sel })\n }\n }\n if (idx.cssPseudoElement.size) {\n for (const [name, fs] of idx.cssPseudoElement) {\n const re = new RegExp(`::${escapeRe(name)}\\\\b`)\n if (re.test(sel)) for (const f of fs) onHit(f, { line, selector: sel })\n }\n }\n })\n\n root.walkDecls((decl: Declaration) => {\n const line = decl.source?.start?.line\n const sel = containingSelector(decl)\n const prop = decl.prop\n\n if (idx.cssImportant && decl.important) onHit(idx.cssImportant, { line, selector: sel })\n if (idx.cssVariables && prop.startsWith('--')) onHit(idx.cssVariables, { line, selector: sel })\n\n const fs = idx.cssProp.get(prop)\n if (fs) for (const f of fs) onHit(f, { line, selector: sel })\n\n const pvs = idx.cssPropValue.get(prop)\n if (pvs) {\n const v = decl.value.trim().toLowerCase()\n for (const pv of pvs) if (v === pv.value) onHit(pv.feature, { line, selector: sel })\n }\n\n if (idx.cssFunction.size || idx.cssUnit.size || idx.cssVariables || idx.cssModernColor) {\n try {\n valueParser(decl.value).walk((n) => {\n if (n.type === 'function') {\n const fname = n.value.toLowerCase()\n const fs2 = idx.cssFunction.get(fname)\n if (fs2) for (const f of fs2) onHit(f, { line, selector: sel })\n if (idx.cssVariables && fname === 'var') onHit(idx.cssVariables, { line, selector: sel })\n if (idx.cssModernColor && MODERN_COLOR_FNS.has(fname)) onHit(idx.cssModernColor, { line, selector: sel })\n } else if (n.type === 'word') {\n const m = /^-?\\d*\\.?\\d+([a-z%]+)$/i.exec(n.value)\n if (m) {\n const unit = m[1].toLowerCase()\n const fs2 = idx.cssUnit.get(unit)\n if (fs2) for (const f of fs2) onHit(f, { line, selector: sel })\n }\n }\n })\n } catch {}\n }\n })\n}\n\nconst MODERN_COLOR_FNS = new Set(['oklch', 'oklab', 'lch', 'lab', 'color', 'color-mix', 'hwb'])\n\nfunction escapeRe(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nfunction offsetToLine(source: string, offset: number): number {\n let line = 1\n for (let i = 0; i < offset && i < source.length; i++) {\n if (source.charCodeAt(i) === 10) line++\n }\n return line\n}\n\nfunction walkTemplate(\n html: string,\n idx: Indexes,\n fileLineOffset: number,\n source: string,\n templateStartOffset: number,\n onHit: (feature: Feature, line: number) => void,\n) {\n const semanticTags = new Set(['article', 'aside', 'details', 'figcaption', 'figure',\n 'footer', 'header', 'main', 'mark', 'nav', 'section', 'time', 'summary'])\n\n /**\n * Stack of tags that opened a body-scope: a literal <body> or a\n * <Teleport to=\"body...\"> whose rendered contents land inside body.\n */\n const bodyScopeStack: string[] = []\n const parser = new Parser({\n onopentag(tag, attrs) {\n const startIdx = (parser as any).startIndex as number\n const line = offsetToLine(source, templateStartOffset + startIdx)\n\n const tagFs = idx.htmlTag.get(tag)\n if (tagFs) for (const f of tagFs) onHit(f, line)\n\n if (idx.htmlSemantics && semanticTags.has(tag)) onHit(idx.htmlSemantics, line)\n\n if (tag === 'style' && bodyScopeStack.length > 0 && idx.htmlStyleInBody) {\n onHit(idx.htmlStyleInBody, line)\n }\n if (tag === 'body') bodyScopeStack.push(tag)\n else if (tag === 'teleport' && /body/i.test(attrs.to ?? '')) bodyScopeStack.push(tag)\n\n for (const attr in attrs) {\n const attrFs = idx.htmlAttr.get(attr)\n if (attrFs) for (const f of attrFs) onHit(f, line)\n }\n\n if (tag === 'input' && attrs.type) {\n const fs = idx.htmlInputType.get(attrs.type.toLowerCase())\n if (fs) for (const f of fs) onHit(f, line)\n }\n if (tag === 'button' && attrs.type) {\n const fs = idx.htmlButtonType.get(attrs.type.toLowerCase())\n if (fs) for (const f of fs) onHit(f, line)\n }\n if (tag === 'a' && attrs.href) {\n const h = attrs.href.trim()\n if (idx.htmlMailtoLinks && /^mailto:/i.test(h)) onHit(idx.htmlMailtoLinks, line)\n else if (idx.htmlAnchorLinks && h.startsWith('#')) onHit(idx.htmlAnchorLinks, line)\n }\n if (tag === 'meta' && idx.htmlMetaColorScheme\n && attrs.name?.toLowerCase() === 'color-scheme') onHit(idx.htmlMetaColorScheme, line)\n\n // Image formats via src / srcset\n if (idx.imageExt.size && (attrs.src || attrs.srcset)) {\n const urls: string[] = []\n if (attrs.src) urls.push(attrs.src)\n if (attrs.srcset) for (const part of attrs.srcset.split(',')) urls.push(part.trim().split(/\\s+/)[0])\n for (const url of urls) {\n const m = /\\.([a-z0-9]+)(?:\\?|#|$)/i.exec(url)\n if (!m) continue\n const fs = idx.imageExt.get(m[1].toLowerCase())\n if (fs) for (const f of fs) onHit(f, line)\n }\n }\n\n // inline style attribute → scan as CSS decl list\n if (attrs.style) scanInlineStyle(attrs.style, idx, line, onHit)\n },\n onclosetag(tag) {\n const top = bodyScopeStack[bodyScopeStack.length - 1]\n if (top === tag) bodyScopeStack.pop()\n },\n onprocessinginstruction(name) {\n if (idx.htmlDoctype && name.toLowerCase() === '!doctype') {\n const startIdx = (parser as any).startIndex as number\n onHit(idx.htmlDoctype, offsetToLine(source, templateStartOffset + startIdx))\n }\n },\n oncomment() {\n if (idx.htmlComments) {\n const startIdx = (parser as any).startIndex as number\n onHit(idx.htmlComments, offsetToLine(source, templateStartOffset + startIdx))\n }\n },\n }, { decodeEntities: false, lowerCaseTags: true, lowerCaseAttributeNames: true })\n\n parser.write(html)\n parser.end()\n}\n\nfunction scanInlineStyle(\n style: string,\n idx: Indexes,\n line: number,\n onHit: (feature: Feature, line: number) => void,\n) {\n // Wrap in a rule so safeParser produces a Root with declarations\n const wrapped = `*{${style}}`\n try {\n const root = safeParser(wrapped)\n root.walkDecls((decl) => {\n if (idx.cssImportant && decl.important) onHit(idx.cssImportant, line)\n const fs = idx.cssProp.get(decl.prop)\n if (fs) for (const f of fs) onHit(f, line)\n if (idx.cssVariables && decl.prop.startsWith('--')) onHit(idx.cssVariables, line)\n const pvs = idx.cssPropValue.get(decl.prop)\n if (pvs) {\n const v = decl.value.trim().toLowerCase()\n for (const pv of pvs) if (v === pv.value) onHit(pv.feature, line)\n }\n if (idx.cssFunction.size || idx.cssUnit.size || idx.cssVariables || idx.cssModernColor) {\n try {\n valueParser(decl.value).walk((n) => {\n if (n.type === 'function') {\n const fname = n.value.toLowerCase()\n const fs2 = idx.cssFunction.get(fname)\n if (fs2) for (const f of fs2) onHit(f, line)\n if (idx.cssVariables && fname === 'var') onHit(idx.cssVariables, line)\n if (idx.cssModernColor && MODERN_COLOR_FNS.has(fname)) onHit(idx.cssModernColor, line)\n } else if (n.type === 'word') {\n const m = /^-?\\d*\\.?\\d+([a-z%]+)$/i.exec(n.value)\n if (m) {\n const fs2 = idx.cssUnit.get(m[1].toLowerCase())\n if (fs2) for (const f of fs2) onHit(f, line)\n }\n }\n })\n } catch {}\n }\n })\n } catch {}\n}\n\nfunction labelFor(idx: Indexes, level: SupportLevel): string {\n const n = idx.nicenames\n if (level === 'unsupported') return n.unsupported ?? 'Not supported'\n if (level === 'mitigated') return n.mitigated ?? 'Partially supported'\n return n.unknown ?? 'Support unknown'\n}\n\nasync function scan(\n rootFile: string,\n config: MaizzleConfig,\n componentDirs: NormalizedComponentSource[],\n allowedClients: Set<string> | 'all',\n): Promise<Issue[]> {\n const idx = await initCompatibility()\n if (!idx) return []\n\n const root = config.root ?? process.cwd()\n const componentMap = await buildComponentMap(root, componentDirs)\n const streams: FileStreams[] = []\n collectStreams(rootFile, componentMap, new Set(), streams)\n\n const issues: Issue[] = []\n const seen = new Set<string>()\n const resolvedCache = new Map<string, { level: SupportLevel, affected: string[] } | null>()\n const resolveSupport = (f: Feature) => {\n let cached = resolvedCache.get(f.slug)\n if (cached === undefined) {\n cached = computeSupport(f.stats, idx.familyNicenames, allowedClients)\n resolvedCache.set(f.slug, cached)\n }\n return cached\n }\n const add = (f: Feature, file: string, line?: number) => {\n const key = `${f.slug}|${file}|${line ?? 0}`\n if (seen.has(key)) return\n const support = resolveSupport(f)\n if (!support) return\n seen.add(key)\n issues.push({\n kind: 'compat',\n slug: f.slug, title: f.title, url: f.url, category: f.category,\n supportLevel: support.level, supportLabel: labelFor(idx, support.level),\n affectedClients: support.affected,\n line, file,\n })\n }\n\n /**\n * Stream A: compiled CSS from real pipeline — reflects shipped output\n * (Tailwind utilities resolved, @maizzle/tailwindcss imported, calc\n * resolved, modern CSS lowered). Filter hits whose containing\n * selector doesn't reference a user class — drops Tailwind\n * preflight noise. For hits without a class selector\n * (e.g. @media, user-written rules), attribute to the\n * file that owned the style block.\n */\n const compiledBlocks = await compileViaPipeline(streams, config, rootFile)\n for (const block of compiledBlocks) {\n walkCss(block.css, idx, (feature, node) => {\n const locations = classLocations(node.selector, streams)\n if (!locations.length) {\n add(feature, block.file, block.line)\n return\n }\n /**\n * @media features collapse to a single source line: the first use\n * of whatever class/variant triggered the wrapper. Other\n * features show up for every occurrence.\n */\n if (feature.slug.startsWith('css-at-media')) {\n add(feature, locations[0].file, locations[0].line)\n } else {\n for (const { file, line } of locations) add(feature, file, line)\n }\n })\n }\n\n // Stream C: source template per file\n for (const s of streams) {\n if (!s.template) continue\n walkTemplate(s.template.content, idx, s.template.offset, s.source,\n s.source.indexOf(s.template.content),\n (feature, line) => add(feature, s.path, line))\n }\n\n return issues\n}\n\n/**\n * Return every (file, line) where any class from the selector appears in a\n * template. Scans every stream so a shared utility class used in multiple\n * components surfaces once per occurrence.\n */\nfunction classLocations(\n selector: string | undefined,\n streams: FileStreams[],\n): Array<{ file: string, line: number }> {\n if (!selector) return []\n const classNames = extractSelectorClasses(selector)\n if (!classNames.length) return []\n const out: Array<{ file: string, line: number }> = []\n const seen = new Set<string>()\n for (const cn of classNames) {\n for (const s of streams) {\n if (!s.classes.has(cn) || !s.template) continue\n const tpl = s.template.content\n const tplStart = s.source.indexOf(tpl)\n let pos = 0\n while (true) {\n const i = tpl.indexOf(cn, pos)\n if (i < 0) break\n pos = i + cn.length\n // Whole-word boundary: adjacent char must be whitespace or quote\n const before = i > 0 ? tpl[i - 1] : ' '\n const after = i + cn.length < tpl.length ? tpl[i + cn.length] : ' '\n if (!isClassBoundary(before) || !isClassBoundary(after)) continue\n const line = offsetToLine(s.source, tplStart + i)\n const key = `${s.path}|${line}`\n if (seen.has(key)) continue\n seen.add(key)\n out.push({ file: s.path, line })\n }\n }\n }\n return out\n}\n\nfunction isClassBoundary(c: string): boolean {\n return c === ' ' || c === '\\t' || c === '\\n' || c === '\\r' || c === '\"' || c === \"'\"\n}\n\nfunction extractSelectorClasses(selector: string): string[] {\n const out: string[] = []\n const re = /\\.((?:\\\\.|[\\w-])+)/g\n let m\n while ((m = re.exec(selector)) !== null) {\n out.push(m[1].replace(/\\\\(.)/g, '$1'))\n }\n return out\n}\n\nconst CATEGORY_ORDER = ['css', 'html', 'image', 'others']\nconst LEVEL_ORDER: Record<string, number> = { error: 0, unsupported: 1, warning: 2, mitigated: 3, unknown: 4 }\n\nfunction orderKey(i: Issue): number {\n if (i.kind === 'lint') return LEVEL_ORDER[i.severity!] ?? 99\n return LEVEL_ORDER[i.supportLevel!] ?? 99\n}\n\nfunction resolveChecksConfig(config: MaizzleConfig) {\n const raw = (config as any).server?.checks\n if (raw === false) return null\n const clients: Set<string> | 'all' = raw?.clients === 'all'\n ? 'all'\n : Array.isArray(raw?.clients) && raw.clients.length\n ? new Set(raw.clients as string[])\n : DEFAULT_CLIENTS\n const level: 'error' | 'warning' | 'lint' | null = raw?.level ?? null\n return { clients, level }\n}\n\nfunction passesLevelFilter(issue: Issue, level: 'error' | 'warning' | 'lint' | null): boolean {\n if (!level) return true\n if (level === 'lint') return issue.kind === 'lint'\n if (issue.kind === 'lint') {\n return level === 'error' ? issue.severity === 'error' : issue.severity === 'warning'\n }\n // compat\n return level === 'error'\n ? issue.supportLevel === 'unsupported'\n : issue.supportLevel === 'mitigated' || issue.supportLevel === 'unknown'\n}\n\nexport async function serveCompatibility(\n url: string,\n res: any,\n config: MaizzleConfig,\n componentDirs: NormalizedComponentSource[],\n) {\n const filePath = url.replace('/__maizzle/compatibility/', '').replace(/\\?.*$/, '')\n const checksCfg = resolveChecksConfig(config)\n try {\n res.setHeader('Content-Type', 'application/json')\n if (!checksCfg) {\n /**\n * Defensive: UI hides the tab using window.__MAIZZLE_CONFIG__ so\n * it shouldn't reach this endpoint when disabled, but if\n * something else does, return an empty list.\n */\n res.end(JSON.stringify([]))\n return\n }\n const absolutePath = resolve(filePath)\n const [compatIssues, lintIssues] = await Promise.all([\n scan(absolutePath, config, componentDirs, checksCfg.clients),\n scanLint(absolutePath, config, componentDirs),\n ])\n\n const idx = await initCompatibility()\n const lintAsIssues: Issue[] = lintIssues.map((li) => {\n const info = li.slug ? idx?.bySlug.get(li.slug) : undefined\n return {\n kind: 'lint',\n slug: li.slug,\n title: li.title,\n url: info?.url,\n category: li.category,\n severity: li.type,\n message: li.message,\n line: li.line,\n file: li.file,\n }\n })\n\n let issues: Issue[] = [...compatIssues, ...lintAsIssues]\n issues = issues.filter((i) => !isFrameworkComponent(i.file))\n if (checksCfg.level) issues = issues.filter((i) => passesLevelFilter(i, checksCfg.level))\n issues.sort((a, b) => {\n const c = CATEGORY_ORDER.indexOf(a.category) - CATEGORY_ORDER.indexOf(b.category)\n if (c) return c\n const l = orderKey(a) - orderKey(b)\n if (l) return l\n return (a.slug ?? a.title).localeCompare(b.slug ?? b.title)\n })\n res.end(JSON.stringify(issues))\n } catch (error: any) {\n res.statusCode = 500\n res.end(JSON.stringify({ error: error.message }))\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compatibility.js","names":["compileWithPipeline"],"sources":["../../src/server/compatibility.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport postcss, { type Declaration, type AtRule, type Rule } from 'postcss'\nimport safeParser from 'postcss-safe-parser'\nimport valueParser from 'postcss-value-parser'\nimport { Parser } from 'htmlparser2'\nimport { DomHandler, type ChildNode, type Element } from 'domhandler'\nimport { parseSfcBlocks, findComponentTags, buildComponentMap, isFrameworkComponent, type SfcBlock } from './sfc-utils.ts'\nimport { scanLint } from './linter.ts'\nimport { tailwindcss as compileWithPipeline } from '../transformers/tailwindcss.ts'\nimport type { MaizzleConfig } from '../types/index.ts'\nimport type { NormalizedComponentSource } from '../utils/componentSources.ts'\n\nconst API_URL = 'https://www.caniemail.com/api/data.json'\nconst DEFAULT_CLIENTS = new Set(['gmail', 'apple-mail', 'outlook', 'yahoo'])\n\ntype SupportLevel = 'unsupported' | 'mitigated' | 'unknown'\n\ninterface Feature {\n slug: string\n title: string\n url: string\n category: string\n stats: any\n}\n\ninterface Issue {\n kind: 'compat' | 'lint'\n slug?: string\n title: string\n url?: string\n category: string\n line?: number\n file: string\n // compat-only\n supportLevel?: SupportLevel\n supportLabel?: string\n affectedClients?: string[]\n // lint-only\n severity?: 'error' | 'warning'\n message?: string\n}\n\ninterface Indexes {\n nicenames: { supported: string, mitigated: string, unsupported: string, unknown: string, mixed: string }\n familyNicenames: Record<string, string>\n cssProp: Map<string, Feature[]>\n cssPropValue: Map<string, Array<{ value: string, feature: Feature }>>\n cssAtRule: Map<string, Feature[]>\n cssMediaFeature: Map<string, Feature[]>\n cssPseudoClass: Map<string, Feature[]>\n cssPseudoElement: Map<string, Feature[]>\n cssFunction: Map<string, Feature[]>\n cssUnit: Map<string, Feature[]>\n cssImportant?: Feature\n cssVariables?: Feature\n cssNesting?: Feature\n cssComments?: Feature\n cssModernColor?: Feature\n htmlTag: Map<string, Feature[]>\n htmlAttr: Map<string, Feature[]>\n htmlInputType: Map<string, Feature[]>\n htmlButtonType: Map<string, Feature[]>\n htmlDoctype?: Feature\n htmlComments?: Feature\n htmlAnchorLinks?: Feature\n htmlMailtoLinks?: Feature\n htmlMetaColorScheme?: Feature\n htmlSemantics?: Feature\n htmlStyleInBody?: Feature\n imageExt: Map<string, Feature[]>\n /** All features by slug — unfiltered, used for URL lookups (e.g. by lint). */\n bySlug: Map<string, { title: string, url: string }>\n}\n\nlet indexes: Indexes | null = null\nlet initPromise: Promise<Indexes | null> | null = null\n\nfunction mpush<K, V>(m: Map<K, V[]>, k: K, v: V) {\n const arr = m.get(k)\n if (arr) arr.push(v)\n else m.set(k, [v])\n}\n\nfunction emptyIndexes(nicenames: any, familyNicenames: Record<string, string>): Indexes {\n return {\n nicenames,\n familyNicenames,\n cssProp: new Map(), cssPropValue: new Map(), cssAtRule: new Map(),\n cssMediaFeature: new Map(), cssPseudoClass: new Map(), cssPseudoElement: new Map(),\n cssFunction: new Map(), cssUnit: new Map(),\n htmlTag: new Map(), htmlAttr: new Map(), htmlInputType: new Map(), htmlButtonType: new Map(),\n imageExt: new Map(),\n bySlug: new Map(),\n }\n}\n\nfunction hasAnyNonY(stats: any): boolean {\n if (!stats) return false\n for (const family in stats) {\n for (const plat in stats[family]) {\n for (const ver in stats[family][plat]) {\n const v = stripNotes(String(stats[family][plat][ver]).trim())\n if (v && v !== 'y') return true\n }\n }\n }\n return false\n}\n\n/** Strip `#N` note markers — `\"y #1\"` → `\"y\"`. Notes document edge cases but\n * don't change support semantics, so treat `y #1` as fully supported. */\nfunction stripNotes(v: string): string {\n return v.split(/\\s+/).filter(t => t && !t.startsWith('#')).join(' ')\n}\n\nfunction computeSupport(stats: any, familyNicenames: Record<string, string>, allowedClients: Set<string> | 'all'): { level: SupportLevel, affected: string[] } | null {\n let nY = 0, nN = 0, nU = 0, nPartial = 0, total = 0\n const affectedFamilies = new Set<string>()\n for (const family in stats) {\n if (allowedClients !== 'all' && !allowedClients.has(family)) continue\n let familyHasNonY = false\n for (const plat in stats[family]) {\n /**\n * Only score the latest version per (family, platform) — legacy\n * versions (Outlook 2007, etc.) otherwise flag modern-widely\n * supported features as partial forever.\n */\n const versions = Object.keys(stats[family][plat]).sort()\n const latest = versions[versions.length - 1]\n if (!latest) continue\n total++\n const v = stripNotes(String(stats[family][plat][latest]).trim())\n if (v === 'y') nY++\n else if (v === 'n') { nN++; familyHasNonY = true }\n else if (v === 'u') { nU++; familyHasNonY = true }\n else { nPartial++; familyHasNonY = true }\n }\n if (familyHasNonY) affectedFamilies.add(family)\n }\n if (!total) return null\n if (nY === total) return null\n const affected = [...affectedFamilies].map(f => familyNicenames[f] ?? f).sort()\n if (nN === total) return { level: 'unsupported', affected }\n if (nU === total) return { level: 'unknown', affected }\n return { level: 'mitigated', affected }\n}\n\n/**\n * Slugs we never report. Fundamental HTML (every email uses these) plus\n * CSS noise that's not actionable (comments, !important usage).\n */\nconst IGNORED_SLUGS = new Set([\n // Required/unavoidable tags\n 'html-doctype', 'html-comments',\n 'html-html', 'html-head', 'html-body', 'html-title',\n 'html-meta', 'html-meta-color-scheme',\n 'html-style', 'html-link',\n 'html-div', 'html-span', 'html-br', 'html-p', 'html-a', 'html-img',\n 'html-table', 'html-tr', 'html-td', 'html-th',\n 'html-thead', 'html-tbody', 'html-tfoot',\n 'html-h1-h6', 'html-lists',\n 'html-strong', 'html-em', 'html-b', 'html-i', 'html-u',\n 'html-semantics',\n // Ubiquitous attributes — always present, caveats aren't actionable.\n 'html-role', 'html-hidden', 'html-width', 'html-height',\n // CSS noise\n 'css-comments', 'css-important',\n /**\n * CSS fundamentals — universally used with known minor caveats; flagging\n * them as \"partial\" is noise rather than signal.\n */\n 'css-margin', 'css-padding', 'css-border',\n 'css-font-size', 'css-font-weight', 'css-font', 'css-font-family',\n 'css-line-height', 'css-letter-spacing', 'css-text-align',\n 'css-text-decoration', 'css-text-transform', 'css-color',\n 'css-background', 'css-background-color',\n 'css-width', 'css-height',\n 'css-display',\n])\n\nfunction classify(f: Feature, idx: Indexes) {\n const slug = f.slug\n /**\n * Retain html-style feature for the body-only detector even though it's\n * blacklisted from the normal html-tag detection path. Title is\n * suffixed so the flag reads as a body-placement warning, not a\n * blanket `<style>`.\n */\n if (slug === 'html-style') {\n idx.htmlStyleInBody = { ...f, title: `${f.title} in <body>` }\n return\n }\n if (IGNORED_SLUGS.has(slug)) return\n\n if (f.category === 'css') return classifyCss(f, slug, idx)\n if (f.category === 'html') return classifyHtml(f, slug, idx)\n if (f.category === 'image') {\n const ext = slug.slice('image-'.length)\n if (ext === 'base64') return\n mpush(idx.imageExt, ext, f)\n }\n // 'others' (amp, bimi) intentionally skipped\n}\n\nfunction classifyCss(f: Feature, slug: string, idx: Indexes) {\n // Specials first\n switch (slug) {\n case 'css-important': idx.cssImportant = f; return\n case 'css-variables': idx.cssVariables = f; return\n case 'css-nesting': idx.cssNesting = f; return\n case 'css-comments': idx.cssComments = f; return\n case 'css-modern-color': idx.cssModernColor = f; return\n case 'css-display-flex': mpushPropValue(idx, 'display', 'flex', f); return\n case 'css-display-grid': mpushPropValue(idx, 'display', 'grid', f); return\n case 'css-display-none': mpushPropValue(idx, 'display', 'none', f); return\n case 'css-rgb': mpush(idx.cssFunction, 'rgb', f); return\n case 'css-rgba': mpush(idx.cssFunction, 'rgba', f); return\n case 'css-linear-gradient': mpush(idx.cssFunction, 'linear-gradient', f); return\n case 'css-radial-gradient': mpush(idx.cssFunction, 'radial-gradient', f); return\n case 'css-conic-gradient': mpush(idx.cssFunction, 'conic-gradient', f); return\n }\n\n if (slug.startsWith('css-at-media-') && slug !== 'css-at-media') {\n mpush(idx.cssMediaFeature, slug.slice('css-at-media-'.length), f)\n return\n }\n if (slug.startsWith('css-at-')) {\n mpush(idx.cssAtRule, slug.slice('css-at-'.length), f)\n return\n }\n if (slug.startsWith('css-pseudo-class-')) {\n mpush(idx.cssPseudoClass, slug.slice('css-pseudo-class-'.length), f)\n return\n }\n if (slug.startsWith('css-pseudo-element-')) {\n mpush(idx.cssPseudoElement, slug.slice('css-pseudo-element-'.length), f)\n return\n }\n if (slug.startsWith('css-unit-')) {\n const u = slug.slice('css-unit-'.length)\n if (u === 'calc') { mpush(idx.cssFunction, 'calc', f); return }\n if (u === 'initial') return // keyword detection is noisy; skip\n const unit = u === 'percent' ? '%' : u\n mpush(idx.cssUnit, unit, f)\n return\n }\n if (slug.startsWith('css-function-')) {\n mpush(idx.cssFunction, slug.slice('css-function-'.length), f)\n return\n }\n // css-selector-* — skip (too broad to detect meaningfully)\n if (slug.startsWith('css-selector-')) return\n\n // Fallback: treat as property name\n mpush(idx.cssProp, slug.slice('css-'.length), f)\n}\n\nfunction mpushPropValue(idx: Indexes, prop: string, value: string, f: Feature) {\n const arr = idx.cssPropValue.get(prop)\n if (arr) arr.push({ value, feature: f })\n else idx.cssPropValue.set(prop, [{ value, feature: f }])\n}\n\nconst HTML_ATTR_SLUGS = new Set([\n 'align', 'background', 'cellpadding', 'cellspacing', 'height', 'width',\n 'valign', 'target', 'srcset', 'lang', 'dir', 'role', 'required', 'hidden',\n])\n\nfunction classifyHtml(f: Feature, slug: string, idx: Indexes) {\n // Specials\n switch (slug) {\n case 'html-doctype': idx.htmlDoctype = f; return\n case 'html-comments': idx.htmlComments = f; return\n case 'html-anchor-links': idx.htmlAnchorLinks = f; return\n case 'html-mailto-links': idx.htmlMailtoLinks = f; return\n case 'html-meta-color-scheme': idx.htmlMetaColorScheme = f; return\n case 'html-semantics': idx.htmlSemantics = f; return\n case 'html-loading-attribute': mpush(idx.htmlAttr, 'loading', f); return\n case 'html-image-maps':\n mpush(idx.htmlTag, 'map', f); mpush(idx.htmlTag, 'area', f); mpush(idx.htmlAttr, 'usemap', f); return\n case 'html-lists':\n for (const t of ['ul', 'ol', 'li', 'dl', 'dt', 'dd']) mpush(idx.htmlTag, t, f)\n return\n case 'html-h1-h6':\n for (const t of ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']) mpush(idx.htmlTag, t, f)\n return\n }\n\n if (slug.startsWith('html-input-')) {\n mpush(idx.htmlInputType, slug.slice('html-input-'.length), f)\n return\n }\n if (slug.startsWith('html-button-')) {\n mpush(idx.htmlButtonType, slug.slice('html-button-'.length), f)\n return\n }\n if (slug.startsWith('html-aria-')) {\n mpush(idx.htmlAttr, slug.slice('html-'.length), f)\n return\n }\n const name = slug.slice('html-'.length)\n if (HTML_ATTR_SLUGS.has(name)) {\n mpush(idx.htmlAttr, name, f)\n return\n }\n mpush(idx.htmlTag, name, f)\n}\n\nexport async function initCompatibility(): Promise<Indexes | null> {\n if (indexes) return indexes\n if (initPromise) return initPromise\n initPromise = (async () => {\n try {\n const res = await fetch(API_URL)\n if (!res.ok) return null\n const data = await res.json()\n const idx = emptyIndexes(data.nicenames?.support ?? {}, data.nicenames?.family ?? {})\n for (const item of data.data ?? []) {\n /**\n * Record every slug's title/url so lint can look up caniemail\n * pages for issues that map to a known feature, even ignored.\n */\n if (item.slug && item.url) idx.bySlug.set(item.slug, { title: item.title, url: item.url })\n /**\n * Index the feature if any cell anywhere in the matrix is non-y.\n * Per-request aggregation (with the active client filter)\n * decides whether to actually surface the issue.\n */\n if (!hasAnyNonY(item.stats)) continue\n const f: Feature = {\n slug: item.slug,\n title: item.title,\n url: item.url,\n category: item.category,\n stats: item.stats,\n }\n classify(f, idx)\n }\n indexes = idx\n return idx\n } catch {\n return null\n }\n })()\n return initPromise\n}\n\n/**\n * Note: fetch of the caniemail dataset is lazy — it fires on the first\n * check request, not at module load, so `server.checks: false` pays\n * no network cost.\n */\n\ninterface FileStreams {\n path: string\n source: string\n template: SfcBlock | null\n styles: SfcBlock[]\n classes: Set<string>\n}\n\nfunction collectStreams(\n filePath: string,\n componentMap: Map<string, string>,\n visited: Set<string>,\n out: FileStreams[],\n) {\n if (visited.has(filePath)) return\n visited.add(filePath)\n\n let source: string\n try {\n source = readFileSync(filePath, 'utf-8')\n } catch { return }\n\n const { template, styles } = parseSfcBlocks(source)\n const classes = new Set<string>()\n if (template) extractClasses(template.content, classes)\n\n out.push({ path: filePath, source, template, styles, classes })\n\n if (template) {\n for (const tag of findComponentTags(template.content)) {\n const cp = componentMap.get(tag.toLowerCase())\n if (cp) collectStreams(cp, componentMap, visited, out)\n }\n }\n}\n\nfunction extractClasses(html: string, out: Set<string>) {\n const parser = new Parser({\n onopentag(_tag, attrs) {\n const c = attrs.class\n if (!c) return\n for (const t of c.split(/\\s+/)) if (t) out.add(t)\n },\n }, { decodeEntities: true })\n parser.write(html)\n parser.end()\n}\n\nfunction parseWithIndices(html: string): ChildNode[] {\n const handler = new DomHandler(undefined, { withStartIndices: true })\n const parser = new Parser(handler)\n parser.write(html)\n parser.end()\n return handler.dom\n}\n\nfunction findStyleNodes(nodes: ChildNode[], out: Element[] = []): Element[] {\n for (const n of nodes) {\n const el = n as Element\n if (el.name === 'style') out.push(el)\n if (el.children?.length) findStyleNodes(el.children as ChildNode[], out)\n }\n return out\n}\n\n/**\n * Parse each file's template, collect every `<style>` node with its source\n * line (via htmlparser2 start indices), then pass the combined DOM through\n * the framework's real Tailwind pipeline. The pipeline resolves imports\n * (@maizzle/tailwindcss), compiles utilities from class attrs, lowers modern\n * CSS via lightningcss, and resolves static calc() — so what we walk matches\n * what ships.\n */\nasync function compileViaPipeline(\n streams: FileStreams[],\n config: MaizzleConfig,\n rootFile: string,\n): Promise<Array<{ file: string, css: string, line: number }>> {\n const all: ChildNode[] = []\n const tracked: Array<{ node: Element, file: string, line: number }> = []\n\n for (const s of streams) {\n if (!s.template) continue\n const templateStart = s.source.indexOf(s.template.content)\n const nodes = parseWithIndices(s.template.content)\n for (const styleNode of findStyleNodes(nodes)) {\n const startIdx = (styleNode as any).startIndex ?? 0\n const line = offsetToLine(s.source, templateStart + startIdx)\n tracked.push({ node: styleNode, file: s.path, line })\n }\n for (const n of nodes) all.push(n)\n }\n\n if (!tracked.length) return []\n\n try {\n await compileWithPipeline(all, config, rootFile)\n } catch { return [] }\n\n return tracked\n .map(t => {\n const txt = t.node.children?.find(c => (c as any).type === 'text') as any\n return txt?.data ? { file: t.file, css: txt.data as string, line: t.line } : null\n })\n .filter((x): x is { file: string, css: string, line: number } => x !== null)\n}\n\n/**\n * Walk CSS AST with detectors. Calls onHit per feature hit.\n * `selector` is the containing rule's selector (undefined if no rule ancestor).\n */\nfunction walkCss(\n css: string,\n idx: Indexes,\n onHit: (feature: Feature, node: { line?: number, selector?: string }) => void,\n) {\n let root: postcss.Root\n try { root = safeParser(css) } catch { return }\n\n const containingSelector = (n: postcss.Node | undefined): string | undefined => {\n let p = n?.parent\n while (p && p.type !== 'root') {\n if (p.type === 'rule') return (p as Rule).selector\n p = p.parent\n }\n return undefined\n }\n\n if (idx.cssComments) {\n root.walkComments((c) => { onHit(idx.cssComments!, { line: c.source?.start?.line, selector: containingSelector(c) }) })\n }\n\n root.walkAtRules((atRule: AtRule) => {\n const line = atRule.source?.start?.line\n let sel = containingSelector(atRule)\n if (atRule.name === 'media' && !sel) {\n const innerSelectors: string[] = []\n atRule.walkRules((r) => { innerSelectors.push(r.selector) })\n if (innerSelectors.length) sel = innerSelectors.join(', ')\n }\n\n if (atRule.name === 'media') {\n /**\n * Pick the most specific media-feature match (prefers-color-scheme,\n * hover, orientation, …). If one matches, skip the generic\n * `css-at-media` to avoid duplicate rows on the same line.\n */\n const specific: Feature[] = []\n if (idx.cssMediaFeature.size) {\n for (const [feat, fs2] of idx.cssMediaFeature) {\n if (atRule.params.includes(`(${feat}`) || atRule.params.includes(feat)) {\n specific.push(...fs2)\n }\n }\n }\n if (specific.length) {\n for (const f of specific) onHit(f, { line, selector: sel })\n } else {\n const fs = idx.cssAtRule.get('media')\n if (fs) for (const f of fs) onHit(f, { line, selector: sel })\n }\n } else {\n const fs = idx.cssAtRule.get(atRule.name)\n if (fs) for (const f of fs) onHit(f, { line, selector: sel })\n }\n })\n\n root.walkRules((rule: Rule) => {\n const line = rule.source?.start?.line\n const sel = rule.selector\n if (idx.cssPseudoClass.size) {\n for (const [name, fs] of idx.cssPseudoClass) {\n const re = new RegExp(`(^|[^:]):${escapeRe(name)}(\\\\b|\\\\()`)\n if (re.test(sel)) for (const f of fs) onHit(f, { line, selector: sel })\n }\n }\n if (idx.cssPseudoElement.size) {\n for (const [name, fs] of idx.cssPseudoElement) {\n const re = new RegExp(`::${escapeRe(name)}\\\\b`)\n if (re.test(sel)) for (const f of fs) onHit(f, { line, selector: sel })\n }\n }\n })\n\n root.walkDecls((decl: Declaration) => {\n const line = decl.source?.start?.line\n const sel = containingSelector(decl)\n const prop = decl.prop\n\n if (idx.cssImportant && decl.important) onHit(idx.cssImportant, { line, selector: sel })\n if (idx.cssVariables && prop.startsWith('--')) onHit(idx.cssVariables, { line, selector: sel })\n\n const fs = idx.cssProp.get(prop)\n if (fs) for (const f of fs) onHit(f, { line, selector: sel })\n\n const pvs = idx.cssPropValue.get(prop)\n if (pvs) {\n const v = decl.value.trim().toLowerCase()\n for (const pv of pvs) if (v === pv.value) onHit(pv.feature, { line, selector: sel })\n }\n\n if (idx.cssFunction.size || idx.cssUnit.size || idx.cssVariables || idx.cssModernColor) {\n try {\n valueParser(decl.value).walk((n) => {\n if (n.type === 'function') {\n const fname = n.value.toLowerCase()\n const fs2 = idx.cssFunction.get(fname)\n if (fs2) for (const f of fs2) onHit(f, { line, selector: sel })\n if (idx.cssVariables && fname === 'var') onHit(idx.cssVariables, { line, selector: sel })\n if (idx.cssModernColor && MODERN_COLOR_FNS.has(fname)) onHit(idx.cssModernColor, { line, selector: sel })\n } else if (n.type === 'word') {\n const m = /^-?\\d*\\.?\\d+([a-z%]+)$/i.exec(n.value)\n if (m) {\n const unit = m[1].toLowerCase()\n const fs2 = idx.cssUnit.get(unit)\n if (fs2) for (const f of fs2) onHit(f, { line, selector: sel })\n }\n }\n })\n } catch {}\n }\n })\n}\n\nconst MODERN_COLOR_FNS = new Set(['oklch', 'oklab', 'lch', 'lab', 'color', 'color-mix', 'hwb'])\n\nfunction escapeRe(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nfunction offsetToLine(source: string, offset: number): number {\n let line = 1\n for (let i = 0; i < offset && i < source.length; i++) {\n if (source.charCodeAt(i) === 10) line++\n }\n return line\n}\n\nfunction walkTemplate(\n html: string,\n idx: Indexes,\n fileLineOffset: number,\n source: string,\n templateStartOffset: number,\n onHit: (feature: Feature, line: number) => void,\n) {\n const semanticTags = new Set(['article', 'aside', 'details', 'figcaption', 'figure',\n 'footer', 'header', 'main', 'mark', 'nav', 'section', 'time', 'summary'])\n\n /**\n * Stack of tags that opened a body-scope: a literal <body> or a\n * <Teleport to=\"body...\"> whose rendered contents land inside body.\n */\n const bodyScopeStack: string[] = []\n const parser = new Parser({\n onopentag(tag, attrs) {\n const startIdx = (parser as any).startIndex as number\n const line = offsetToLine(source, templateStartOffset + startIdx)\n\n const tagFs = idx.htmlTag.get(tag)\n if (tagFs) for (const f of tagFs) onHit(f, line)\n\n if (idx.htmlSemantics && semanticTags.has(tag)) onHit(idx.htmlSemantics, line)\n\n if (tag === 'style' && bodyScopeStack.length > 0 && idx.htmlStyleInBody) {\n onHit(idx.htmlStyleInBody, line)\n }\n if (tag === 'body') bodyScopeStack.push(tag)\n else if (tag === 'teleport' && /body/i.test(attrs.to ?? '')) bodyScopeStack.push(tag)\n\n for (const attr in attrs) {\n const attrFs = idx.htmlAttr.get(attr)\n if (attrFs) for (const f of attrFs) onHit(f, line)\n }\n\n if (tag === 'input' && attrs.type) {\n const fs = idx.htmlInputType.get(attrs.type.toLowerCase())\n if (fs) for (const f of fs) onHit(f, line)\n }\n if (tag === 'button' && attrs.type) {\n const fs = idx.htmlButtonType.get(attrs.type.toLowerCase())\n if (fs) for (const f of fs) onHit(f, line)\n }\n if (tag === 'a' && attrs.href) {\n const h = attrs.href.trim()\n if (idx.htmlMailtoLinks && /^mailto:/i.test(h)) onHit(idx.htmlMailtoLinks, line)\n else if (idx.htmlAnchorLinks && h.startsWith('#')) onHit(idx.htmlAnchorLinks, line)\n }\n if (tag === 'meta' && idx.htmlMetaColorScheme\n && attrs.name?.toLowerCase() === 'color-scheme') onHit(idx.htmlMetaColorScheme, line)\n\n // Image formats via src / srcset\n if (idx.imageExt.size && (attrs.src || attrs.srcset)) {\n const urls: string[] = []\n if (attrs.src) urls.push(attrs.src)\n if (attrs.srcset) for (const part of attrs.srcset.split(',')) urls.push(part.trim().split(/\\s+/)[0])\n for (const url of urls) {\n const m = /\\.([a-z0-9]+)(?:\\?|#|$)/i.exec(url)\n if (!m) continue\n const fs = idx.imageExt.get(m[1].toLowerCase())\n if (fs) for (const f of fs) onHit(f, line)\n }\n }\n\n // inline style attribute → scan as CSS decl list\n if (attrs.style) scanInlineStyle(attrs.style, idx, line, onHit)\n },\n onclosetag(tag) {\n const top = bodyScopeStack[bodyScopeStack.length - 1]\n if (top === tag) bodyScopeStack.pop()\n },\n onprocessinginstruction(name) {\n if (idx.htmlDoctype && name.toLowerCase() === '!doctype') {\n const startIdx = (parser as any).startIndex as number\n onHit(idx.htmlDoctype, offsetToLine(source, templateStartOffset + startIdx))\n }\n },\n oncomment() {\n if (idx.htmlComments) {\n const startIdx = (parser as any).startIndex as number\n onHit(idx.htmlComments, offsetToLine(source, templateStartOffset + startIdx))\n }\n },\n }, { decodeEntities: false, lowerCaseTags: true, lowerCaseAttributeNames: true })\n\n parser.write(html)\n parser.end()\n}\n\nfunction scanInlineStyle(\n style: string,\n idx: Indexes,\n line: number,\n onHit: (feature: Feature, line: number) => void,\n) {\n // Wrap in a rule so safeParser produces a Root with declarations\n const wrapped = `*{${style}}`\n try {\n const root = safeParser(wrapped)\n root.walkDecls((decl) => {\n if (idx.cssImportant && decl.important) onHit(idx.cssImportant, line)\n const fs = idx.cssProp.get(decl.prop)\n if (fs) for (const f of fs) onHit(f, line)\n if (idx.cssVariables && decl.prop.startsWith('--')) onHit(idx.cssVariables, line)\n const pvs = idx.cssPropValue.get(decl.prop)\n if (pvs) {\n const v = decl.value.trim().toLowerCase()\n for (const pv of pvs) if (v === pv.value) onHit(pv.feature, line)\n }\n if (idx.cssFunction.size || idx.cssUnit.size || idx.cssVariables || idx.cssModernColor) {\n try {\n valueParser(decl.value).walk((n) => {\n if (n.type === 'function') {\n const fname = n.value.toLowerCase()\n const fs2 = idx.cssFunction.get(fname)\n if (fs2) for (const f of fs2) onHit(f, line)\n if (idx.cssVariables && fname === 'var') onHit(idx.cssVariables, line)\n if (idx.cssModernColor && MODERN_COLOR_FNS.has(fname)) onHit(idx.cssModernColor, line)\n } else if (n.type === 'word') {\n const m = /^-?\\d*\\.?\\d+([a-z%]+)$/i.exec(n.value)\n if (m) {\n const fs2 = idx.cssUnit.get(m[1].toLowerCase())\n if (fs2) for (const f of fs2) onHit(f, line)\n }\n }\n })\n } catch {}\n }\n })\n } catch {}\n}\n\nfunction labelFor(idx: Indexes, level: SupportLevel): string {\n const n = idx.nicenames\n if (level === 'unsupported') return n.unsupported ?? 'Not supported'\n if (level === 'mitigated') return n.mitigated ?? 'Partially supported'\n return n.unknown ?? 'Support unknown'\n}\n\nasync function scan(\n rootFile: string,\n config: MaizzleConfig,\n componentDirs: NormalizedComponentSource[],\n allowedClients: Set<string> | 'all',\n): Promise<Issue[]> {\n const idx = await initCompatibility()\n if (!idx) return []\n\n const root = config.root ?? process.cwd()\n const componentMap = await buildComponentMap(root, componentDirs)\n const streams: FileStreams[] = []\n collectStreams(rootFile, componentMap, new Set(), streams)\n\n const issues: Issue[] = []\n const seen = new Set<string>()\n const resolvedCache = new Map<string, { level: SupportLevel, affected: string[] } | null>()\n const resolveSupport = (f: Feature) => {\n let cached = resolvedCache.get(f.slug)\n if (cached === undefined) {\n cached = computeSupport(f.stats, idx.familyNicenames, allowedClients)\n resolvedCache.set(f.slug, cached)\n }\n return cached\n }\n const add = (f: Feature, file: string, line?: number) => {\n const key = `${f.slug}|${file}|${line ?? 0}`\n if (seen.has(key)) return\n const support = resolveSupport(f)\n if (!support) return\n seen.add(key)\n issues.push({\n kind: 'compat',\n slug: f.slug, title: f.title, url: f.url, category: f.category,\n supportLevel: support.level, supportLabel: labelFor(idx, support.level),\n affectedClients: support.affected,\n line, file,\n })\n }\n\n /**\n * Stream A: compiled CSS from real pipeline — reflects shipped output\n * (Tailwind utilities resolved, @maizzle/tailwindcss imported, calc\n * resolved, modern CSS lowered). Filter hits whose containing\n * selector doesn't reference a user class — drops Tailwind\n * preflight noise. For hits without a class selector\n * (e.g. @media, user-written rules), attribute to the\n * file that owned the style block.\n */\n const compiledBlocks = await compileViaPipeline(streams, config, rootFile)\n for (const block of compiledBlocks) {\n walkCss(block.css, idx, (feature, node) => {\n const locations = classLocations(node.selector, streams)\n if (!locations.length) {\n add(feature, block.file, block.line)\n return\n }\n /**\n * @media features collapse to a single source line: the first use\n * of whatever class/variant triggered the wrapper. Other\n * features show up for every occurrence.\n */\n if (feature.slug.startsWith('css-at-media')) {\n add(feature, locations[0].file, locations[0].line)\n } else {\n for (const { file, line } of locations) add(feature, file, line)\n }\n })\n }\n\n // Stream C: source template per file\n for (const s of streams) {\n if (!s.template) continue\n walkTemplate(s.template.content, idx, s.template.offset, s.source,\n s.source.indexOf(s.template.content),\n (feature, line) => add(feature, s.path, line))\n }\n\n return issues\n}\n\n/**\n * Return every (file, line) where any class from the selector appears in a\n * template. Scans every stream so a shared utility class used in multiple\n * components surfaces once per occurrence.\n */\nfunction classLocations(\n selector: string | undefined,\n streams: FileStreams[],\n): Array<{ file: string, line: number }> {\n if (!selector) return []\n const classNames = extractSelectorClasses(selector)\n if (!classNames.length) return []\n const out: Array<{ file: string, line: number }> = []\n const seen = new Set<string>()\n for (const cn of classNames) {\n for (const s of streams) {\n if (!s.classes.has(cn) || !s.template) continue\n const tpl = s.template.content\n const tplStart = s.source.indexOf(tpl)\n let pos = 0\n while (true) {\n const i = tpl.indexOf(cn, pos)\n if (i < 0) break\n pos = i + cn.length\n // Whole-word boundary: adjacent char must be whitespace or quote\n const before = i > 0 ? tpl[i - 1] : ' '\n const after = i + cn.length < tpl.length ? tpl[i + cn.length] : ' '\n if (!isClassBoundary(before) || !isClassBoundary(after)) continue\n const line = offsetToLine(s.source, tplStart + i)\n const key = `${s.path}|${line}`\n if (seen.has(key)) continue\n seen.add(key)\n out.push({ file: s.path, line })\n }\n }\n }\n return out\n}\n\nfunction isClassBoundary(c: string): boolean {\n return c === ' ' || c === '\\t' || c === '\\n' || c === '\\r' || c === '\"' || c === \"'\"\n}\n\nfunction extractSelectorClasses(selector: string): string[] {\n const out: string[] = []\n const re = /\\.((?:\\\\.|[\\w-])+)/g\n let m\n while ((m = re.exec(selector)) !== null) {\n out.push(m[1].replace(/\\\\(.)/g, '$1'))\n }\n return out\n}\n\nconst CATEGORY_ORDER = ['css', 'html', 'image', 'others']\nconst LEVEL_ORDER: Record<string, number> = { error: 0, unsupported: 1, warning: 2, mitigated: 3, unknown: 4 }\n\nfunction orderKey(i: Issue): number {\n if (i.kind === 'lint') return LEVEL_ORDER[i.severity!] ?? 99\n return LEVEL_ORDER[i.supportLevel!] ?? 99\n}\n\nfunction resolveChecksConfig(config: MaizzleConfig) {\n const raw = (config as any).server?.checks\n if (raw === false) return null\n const clients: Set<string> | 'all' = raw?.clients === 'all'\n ? 'all'\n : Array.isArray(raw?.clients) && raw.clients.length\n ? new Set(raw.clients as string[])\n : DEFAULT_CLIENTS\n const level: 'error' | 'warning' | 'lint' | null = raw?.level ?? null\n return { clients, level }\n}\n\nfunction passesLevelFilter(issue: Issue, level: 'error' | 'warning' | 'lint' | null): boolean {\n if (!level) return true\n if (level === 'lint') return issue.kind === 'lint'\n if (issue.kind === 'lint') {\n return level === 'error' ? issue.severity === 'error' : issue.severity === 'warning'\n }\n // compat\n return level === 'error'\n ? issue.supportLevel === 'unsupported'\n : issue.supportLevel === 'mitigated' || issue.supportLevel === 'unknown'\n}\n\nexport async function serveCompatibility(\n url: string,\n res: any,\n config: MaizzleConfig,\n componentDirs: NormalizedComponentSource[],\n) {\n const filePath = url.replace('/__maizzle/compatibility/', '').replace(/\\?.*$/, '')\n const checksCfg = resolveChecksConfig(config)\n try {\n res.setHeader('Content-Type', 'application/json')\n if (!checksCfg) {\n /**\n * Defensive: UI hides the tab using window.__MAIZZLE_CONFIG__ so\n * it shouldn't reach this endpoint when disabled, but if\n * something else does, return an empty list.\n */\n res.end(JSON.stringify([]))\n return\n }\n const absolutePath = resolve(filePath)\n const [compatIssues, lintIssues] = await Promise.all([\n scan(absolutePath, config, componentDirs, checksCfg.clients),\n scanLint(absolutePath, config, componentDirs),\n ])\n\n const idx = await initCompatibility()\n const lintAsIssues: Issue[] = lintIssues.map((li) => {\n const info = li.slug ? idx?.bySlug.get(li.slug) : undefined\n return {\n kind: 'lint',\n slug: li.slug,\n title: li.title,\n url: info?.url,\n category: li.category,\n severity: li.type,\n message: li.message,\n line: li.line,\n file: li.file,\n }\n })\n\n let issues: Issue[] = [...compatIssues, ...lintAsIssues]\n issues = issues.filter((i) => !isFrameworkComponent(i.file))\n if (checksCfg.level) issues = issues.filter((i) => passesLevelFilter(i, checksCfg.level))\n issues.sort((a, b) => {\n const c = CATEGORY_ORDER.indexOf(a.category) - CATEGORY_ORDER.indexOf(b.category)\n if (c) return c\n const l = orderKey(a) - orderKey(b)\n if (l) return l\n return (a.slug ?? a.title).localeCompare(b.slug ?? b.title)\n })\n res.end(JSON.stringify(issues))\n } catch (error: any) {\n res.statusCode = 500\n res.end(JSON.stringify({ error: error.message }))\n }\n}\n"],"mappings":"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"}
|
package/dist/server/linter.js
CHANGED
|
@@ -23,7 +23,8 @@ function tableRoleAutoAdded(config) {
|
|
|
23
23
|
return true;
|
|
24
24
|
}
|
|
25
25
|
async function scanLint(rootFile, config, componentDirs) {
|
|
26
|
-
const
|
|
26
|
+
const root = config.root ?? process.cwd();
|
|
27
|
+
const componentMap = await buildComponentMap(root, componentDirs);
|
|
27
28
|
const visited = /* @__PURE__ */ new Set();
|
|
28
29
|
const presence = {
|
|
29
30
|
html: false,
|