Add comprehensive TW test suite (627 tests), fix 4 bugs, add 9 features
Bugs fixed: - line-through: check full token not just head after hyphen split - gap-x-N/gap-y-N: compound 2-part spacing prefix handler in tw-layout - Negative values (-mt-4): replace ":" with ":-" instead of no-op - Class name doubling: chain replace calls instead of concatenating New features in tw-process-token: - !important modifier (!p-4 → padding:1rem !important) - dark: variant (class-based, .dark ancestor selector) - group-hover:/group-focus:/group-active: (parent state) - peer-focus:/peer-hover:/peer-checked:/peer-disabled: (sibling state) - @container queries (@md:flex → @container(min-width:448px)) - Colour opacity modifier (bg-sky-500/50 → hsl with alpha) - Ring colours (ring-sky-500 → --tw-ring-color) - Arbitrary values (w-[300px], grid-cols-[1fr_2fr], bg-[#ff0000]) - colour-with-alpha helper for HSL+alpha generation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -244,6 +244,20 @@ env["render-sx"] = function(source) {
|
||||
return parts.join("");
|
||||
};
|
||||
|
||||
// Mock request/state primitives for test-handlers.sx
|
||||
const _mockState = {};
|
||||
env["now"] = function(fmt) { return new Date().toISOString(); };
|
||||
env["state-get"] = function(key, dflt) { return key in _mockState ? _mockState[key] : (dflt !== undefined ? dflt : null); };
|
||||
env["state-set!"] = function(key, val) { _mockState[key] = val; return val; };
|
||||
env["state-clear!"] = function(key) { delete _mockState[key]; return null; };
|
||||
env["request-method"] = function() { return "GET"; };
|
||||
env["request-arg"] = function(name, dflt) { return dflt !== undefined ? dflt : null; };
|
||||
env["request-form"] = function(name, dflt) { return dflt !== undefined ? dflt : ""; };
|
||||
env["request-headers-all"] = function() { return {}; };
|
||||
env["request-form-all"] = function() { return {}; };
|
||||
env["request-args-all"] = function() { return {}; };
|
||||
env["request-content-type"] = function() { return "text/html"; };
|
||||
|
||||
// Platform test functions
|
||||
env["try-call"] = function(thunk) {
|
||||
try {
|
||||
@@ -315,6 +329,33 @@ if (fs.existsSync(canonicalPath)) {
|
||||
}
|
||||
}
|
||||
|
||||
// Load sx-swap.sx (needed by spec/tests/test-sx-swap.sx)
|
||||
const swapPath = path.join(projectDir, "lib", "sx-swap.sx");
|
||||
if (fs.existsSync(swapPath)) {
|
||||
const swapSrc = fs.readFileSync(swapPath, "utf8");
|
||||
const swapExprs = Sx.parse(swapSrc);
|
||||
for (const expr of swapExprs) {
|
||||
try { Sx.eval(expr, env); } catch (e) {
|
||||
console.error(`Error loading sx-swap.sx: ${e.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load tw system (needed by spec/tests/test-tw.sx)
|
||||
const twDir = path.join(projectDir, "shared", "sx", "templates");
|
||||
for (const twFile of ["tw-type.sx", "tw-layout.sx", "tw.sx"]) {
|
||||
const twPath = path.join(twDir, twFile);
|
||||
if (fs.existsSync(twPath)) {
|
||||
const twSrc = fs.readFileSync(twPath, "utf8");
|
||||
const twExprs = Sx.parse(twSrc);
|
||||
for (const expr of twExprs) {
|
||||
try { Sx.eval(expr, env); } catch (e) {
|
||||
console.error(`Error loading ${twFile}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load compiler + VM from lib/ when running full tests
|
||||
if (fullBuild) {
|
||||
const libDir = path.join(projectDir, "lib");
|
||||
|
||||
Reference in New Issue
Block a user