first commit
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @wrnexus/styles — global stylesheet pipeline + app config.
|
||||
*
|
||||
* Works for SSR and CSR: the bundled stylesheet is `<link>`ed into every page's
|
||||
* `<head>`, so it styles server-rendered markup and hydrated client islands
|
||||
* alike. Use any CSS framework via `@import` in global.css (npm) or via a CDN
|
||||
* link in `wrnexus.config.ts`'s `head` field.
|
||||
*/
|
||||
|
||||
export type {
|
||||
AppConfig,
|
||||
MobileConfig,
|
||||
PwaConfig,
|
||||
StylesConfig,
|
||||
StyleProcessContext,
|
||||
Mode,
|
||||
} from "./config.ts";
|
||||
export { loadAppConfig, loadRawConfig, headToString, resolveProfile, loadEnv } from "./config.ts";
|
||||
export { findStyleEntry, bundleCss } from "./styles.ts";
|
||||
export type { FontConfig, GoogleFont, LocalFontFace, FontDisplay } from "./fonts.ts";
|
||||
export { renderFontHead, fontCspSources } from "./fonts.ts";
|
||||
export type { ThemeConfig, ThemeTokens, ResolvedTheme } from "./theme.ts";
|
||||
export {
|
||||
DEFAULT_THEMES,
|
||||
THEME_COOKIE,
|
||||
THEME_CSS_HREF,
|
||||
THEME_JS_HREF,
|
||||
resolveThemeConfig,
|
||||
resolveThemeName,
|
||||
renderThemeCss,
|
||||
renderThemeRuntime,
|
||||
} from "./theme.ts";
|
||||
|
||||
import type { Mode, StyleProcessContext, StylesConfig } from "./config.ts";
|
||||
import { bundleCss } from "./styles.ts";
|
||||
|
||||
/**
|
||||
* Produce the final CSS for an entry: run the config's custom processor if one
|
||||
* is provided (Tailwind/PostCSS/Sass), otherwise use the built-in Bun bundler.
|
||||
*
|
||||
* If a custom processor throws (e.g. Tailwind can't resolve `tailwindcss`
|
||||
* because deps aren't installed), we DON'T crash every request — we log a clear,
|
||||
* actionable message and fall back to best-effort CSS so the app keeps serving.
|
||||
*/
|
||||
export async function renderStyles(
|
||||
ctx: StyleProcessContext,
|
||||
styles?: StylesConfig,
|
||||
): Promise<string> {
|
||||
if (!ctx.entryPath) return "";
|
||||
if (styles?.process) {
|
||||
try {
|
||||
return String(await styles.process(ctx));
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err);
|
||||
console.error(
|
||||
`\n[wrnexus] Stylesheet processing failed — serving un-processed CSS.\n` +
|
||||
` ${msg.split("\n")[0]}\n` +
|
||||
` If you use Tailwind, run \`bun install\` inside the app so \`tailwindcss\`\n` +
|
||||
` is available (an app created inside another project may not have it).\n`,
|
||||
);
|
||||
return await fallbackCss(ctx);
|
||||
}
|
||||
}
|
||||
return bundleCss(ctx.entryPath, ctx.mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Best-effort CSS when a custom processor fails: try the built-in bundler; if that
|
||||
* also fails (e.g. `@import "tailwindcss"` can't resolve), serve the raw entry with
|
||||
* the tool-only directives stripped so the page still renders.
|
||||
*/
|
||||
async function fallbackCss(ctx: StyleProcessContext): Promise<string> {
|
||||
try {
|
||||
return await bundleCss(ctx.entryPath!, ctx.mode);
|
||||
} catch {
|
||||
try {
|
||||
const raw = await Bun.file(ctx.entryPath!).text();
|
||||
return raw.replace(/@import\s+["']tailwindcss["'];?/g, "").replace(/@source[^;\n]*;?/g, "");
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type { Mode as StylesMode };
|
||||
Reference in New Issue
Block a user