sc-theme-builder/lib/sassCompile.js
2026-07-01 20:07:28 -05:00

41 lines
1.7 KiB
JavaScript

// Phase 2 dart-sass recompile (ARCHITECTURE.md 7.5). Lazy and defensive: the
// `sass` dependency and the vendored Bootstrap SCSS under ../scss are Phase-2
// only, so a missing dep or compile error degrades to the Phase-1 overlay
// rather than white-screening. Only ever reached for engine:"sass" themes.
const path = require("path");
const { sanitizeValue } = require("./sanitize"); // shared guard (folded fix)
function compileSass(tokens, opts = {}) {
const warnings = [];
try {
const sass = require("sass"); // lazy; Phase-2 dep
const flat = require("./compile").flattenTokens(tokens);
const varBlock = Object.entries(flat)
.filter(([k]) => /^[-a-zA-Z0-9_]{1,64}$/.test(k))
.map(([k, v]) => {
const sv = sanitizeValue(v, warnings);
return sv == null ? "" : `$${k}: ${sv};`;
})
.filter(Boolean)
.join("\n");
const scssDir = path.join(__dirname, "..", "scss");
// relative module id resolved via loadPaths; no absolute @import string.
const entry = `@use "bootstrap/bootstrap" with (\n${varBlock}\n);\n`;
const result = sass.compileString(entry, {
loadPaths: [scssDir],
style: "compressed",
logger: { warn: (m) => warnings.push(m), debug: () => {} },
});
return { css: result.css, warnings };
} catch (e) {
warnings.push("sass compile unavailable/failed: " + e.message);
// fall back to the overlay; never white-screen.
const overlay = require("./compile").emitOverlayCss(tokens);
return { css: overlay.css, warnings: warnings.concat(overlay.warnings || []) };
}
}
module.exports = { compileSass };