Files
rose-ash/shared/static/scripts/sx-browser.js
giles 917a487195 Add deps and engine test specs, bootstrap engine to Python
New test specs (test-deps.sx: 33 tests, test-engine.sx: 37 tests) covering
component dependency analysis and engine pure functions. All 6 spec modules
now have formal SX tests: eval (81), parser (39), router (18), render (23),
deps (33), engine (37) = 231 total.

- Add engine as spec module in bootstrap_py.py (alongside deps)
- Add primitive aliases (trim, replace, parse_int, upper) for engine functions
- Fix parse-int to match JS parseInt semantics (strip trailing non-digits)
- Regenerate sx_ref.py with --spec-modules deps,engine
- Update all three test runners (run.js, run.py, sx-test-runner.js)
- Add Dependencies and Engine nav items and testing page entries
- Wire deps-source/engine-source through testing overview UI

Node.js: 231/231 pass. Python: 226/231 (5 pre-existing parser/router gaps).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:01:33 +00:00

4770 lines
211 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* sx-ref.js — Generated from reference SX evaluator specification.
*
* Bootstrap-compiled from shared/sx/ref/{eval,render,primitives}.sx
* Compare against hand-written sx.js for correctness verification.
*
* DO NOT EDIT — regenerate with: python bootstrap_js.py
*/
;(function(global) {
"use strict";
// =========================================================================
// Types
// =========================================================================
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
var SX_VERSION = "2026-03-07T17:50:50Z";
function isNil(x) { return x === NIL || x === null || x === undefined; }
function isSxTruthy(x) { return x !== false && !isNil(x); }
function Symbol(name) { this.name = name; }
Symbol.prototype.toString = function() { return this.name; };
Symbol.prototype._sym = true;
function Keyword(name) { this.name = name; }
Keyword.prototype.toString = function() { return ":" + this.name; };
Keyword.prototype._kw = true;
function Lambda(params, body, closure, name) {
this.params = params;
this.body = body;
this.closure = closure || {};
this.name = name || null;
}
Lambda.prototype._lambda = true;
function Component(name, params, hasChildren, body, closure) {
this.name = name;
this.params = params;
this.hasChildren = hasChildren;
this.body = body;
this.closure = closure || {};
}
Component.prototype._component = true;
function Macro(params, restParam, body, closure, name) {
this.params = params;
this.restParam = restParam;
this.body = body;
this.closure = closure || {};
this.name = name || null;
}
Macro.prototype._macro = true;
function Thunk(expr, env) { this.expr = expr; this.env = env; }
Thunk.prototype._thunk = true;
function RawHTML(html) { this.html = html; }
RawHTML.prototype._raw = true;
function StyleValue(className, declarations, mediaRules, pseudoRules, keyframes) {
this.className = className;
this.declarations = declarations || "";
this.mediaRules = mediaRules || [];
this.pseudoRules = pseudoRules || [];
this.keyframes = keyframes || [];
}
StyleValue.prototype._styleValue = true;
function isSym(x) { return x != null && x._sym === true; }
function isKw(x) { return x != null && x._kw === true; }
function merge() {
var out = {};
for (var i = 0; i < arguments.length; i++) {
var d = arguments[i];
if (d) for (var k in d) out[k] = d[k];
}
return out;
}
function sxOr() {
for (var i = 0; i < arguments.length; i++) {
if (isSxTruthy(arguments[i])) return arguments[i];
}
return arguments.length ? arguments[arguments.length - 1] : false;
}
// =========================================================================
// Platform interface — JS implementation
// =========================================================================
function typeOf(x) {
if (isNil(x)) return "nil";
if (typeof x === "number") return "number";
if (typeof x === "string") return "string";
if (typeof x === "boolean") return "boolean";
if (x._sym) return "symbol";
if (x._kw) return "keyword";
if (x._thunk) return "thunk";
if (x._lambda) return "lambda";
if (x._component) return "component";
if (x._macro) return "macro";
if (x._raw) return "raw-html";
if (x._styleValue) return "style-value";
if (typeof Node !== "undefined" && x instanceof Node) return "dom-node";
if (Array.isArray(x)) return "list";
if (typeof x === "object") return "dict";
return "unknown";
}
function symbolName(s) { return s.name; }
function keywordName(k) { return k.name; }
function makeSymbol(n) { return new Symbol(n); }
function makeKeyword(n) { return new Keyword(n); }
function makeLambda(params, body, env) { return new Lambda(params, body, merge(env)); }
function makeComponent(name, params, hasChildren, body, env) {
return new Component(name, params, hasChildren, body, merge(env));
}
function makeMacro(params, restParam, body, env, name) {
return new Macro(params, restParam, body, merge(env), name);
}
function makeThunk(expr, env) { return new Thunk(expr, env); }
function lambdaParams(f) { return f.params; }
function lambdaBody(f) { return f.body; }
function lambdaClosure(f) { return f.closure; }
function lambdaName(f) { return f.name; }
function setLambdaName(f, n) { f.name = n; }
function componentParams(c) { return c.params; }
function componentBody(c) { return c.body; }
function componentClosure(c) { return c.closure; }
function componentHasChildren(c) { return c.hasChildren; }
function componentName(c) { return c.name; }
function macroParams(m) { return m.params; }
function macroRestParam(m) { return m.restParam; }
function macroBody(m) { return m.body; }
function macroClosure(m) { return m.closure; }
function isThunk(x) { return x != null && x._thunk === true; }
function thunkExpr(t) { return t.expr; }
function thunkEnv(t) { return t.env; }
function isCallable(x) { return typeof x === "function" || (x != null && x._lambda === true); }
function isLambda(x) { return x != null && x._lambda === true; }
function isComponent(x) { return x != null && x._component === true; }
function isMacro(x) { return x != null && x._macro === true; }
function isStyleValue(x) { return x != null && x._styleValue === true; }
function styleValueClass(x) { return x.className; }
function styleValue_p(x) { return x != null && x._styleValue === true; }
function buildKeyframes(kfName, steps, env) {
// Platform implementation of defkeyframes
var parts = [];
for (var i = 0; i < steps.length; i++) {
var step = steps[i];
var selector = isSym(step[0]) ? step[0].name : String(step[0]);
var body = trampoline(evalExpr(step[1], env));
var decls = isStyleValue(body) ? body.declarations : String(body);
parts.push(selector + "{" + decls + "}");
}
var kfRule = "@keyframes " + kfName + "{" + parts.join("") + "}";
var cn = "sx-ref-kf-" + kfName;
var sv = new StyleValue(cn, "animation-name:" + kfName, [], [], [[kfName, kfRule]]);
env[kfName] = sv;
return sv;
}
function envHas(env, name) { return name in env; }
function envGet(env, name) { return env[name]; }
function envSet(env, name, val) { env[name] = val; }
function envExtend(env) { return Object.create(env); }
function envMerge(base, overlay) {
var child = Object.create(base);
if (overlay) for (var k in overlay) if (overlay.hasOwnProperty(k)) child[k] = overlay[k];
return child;
}
function dictSet(d, k, v) { d[k] = v; return v; }
function dictGet(d, k) { var v = d[k]; return v !== undefined ? v : NIL; }
// Render-expression detection — lets the evaluator delegate to the active adapter.
// Matches HTML tags, SVG tags, <>, raw!, ~components, html: prefix, custom elements.
function isRenderExpr(expr) {
if (!Array.isArray(expr) || !expr.length) return false;
var h = expr[0];
if (!h || !h._sym) return false;
var n = h.name;
return !!(n === "<>" || n === "raw!" ||
n.charAt(0) === "~" || n.indexOf("html:") === 0 ||
(typeof HTML_TAGS !== "undefined" && HTML_TAGS.indexOf(n) >= 0) ||
(typeof SVG_TAGS !== "undefined" && SVG_TAGS.indexOf(n) >= 0) ||
(n.indexOf("-") > 0 && expr.length > 1 && expr[1] && expr[1]._kw));
}
// Render dispatch — call the active adapter's render function.
// Set by each adapter when loaded; defaults to identity (no rendering).
var _renderExprFn = null;
function renderExpr(expr, env) {
if (_renderExprFn) return _renderExprFn(expr, env);
// No adapter loaded — just return the expression as-is
return expr;
}
function stripPrefix(s, prefix) {
return s.indexOf(prefix) === 0 ? s.slice(prefix.length) : s;
}
function error(msg) { throw new Error(msg); }
function inspect(x) { return JSON.stringify(x); }
// =========================================================================
// Primitives
// =========================================================================
var PRIMITIVES = {};
// core.arithmetic
PRIMITIVES["+"] = function() { var s = 0; for (var i = 0; i < arguments.length; i++) s += arguments[i]; return s; };
PRIMITIVES["-"] = function(a, b) { return arguments.length === 1 ? -a : a - b; };
PRIMITIVES["*"] = function() { var s = 1; for (var i = 0; i < arguments.length; i++) s *= arguments[i]; return s; };
PRIMITIVES["/"] = function(a, b) { return a / b; };
PRIMITIVES["mod"] = function(a, b) { return a % b; };
PRIMITIVES["inc"] = function(n) { return n + 1; };
PRIMITIVES["dec"] = function(n) { return n - 1; };
PRIMITIVES["abs"] = Math.abs;
PRIMITIVES["floor"] = Math.floor;
PRIMITIVES["ceil"] = Math.ceil;
PRIMITIVES["round"] = function(x, n) {
if (n === undefined || n === 0) return Math.round(x);
var f = Math.pow(10, n); return Math.round(x * f) / f;
};
PRIMITIVES["min"] = Math.min;
PRIMITIVES["max"] = Math.max;
PRIMITIVES["sqrt"] = Math.sqrt;
PRIMITIVES["pow"] = Math.pow;
PRIMITIVES["clamp"] = function(x, lo, hi) { return Math.max(lo, Math.min(hi, x)); };
// core.comparison
PRIMITIVES["="] = function(a, b) { return a === b; };
PRIMITIVES["!="] = function(a, b) { return a !== b; };
PRIMITIVES["<"] = function(a, b) { return a < b; };
PRIMITIVES[">"] = function(a, b) { return a > b; };
PRIMITIVES["<="] = function(a, b) { return a <= b; };
PRIMITIVES[">="] = function(a, b) { return a >= b; };
// core.logic
PRIMITIVES["not"] = function(x) { return !isSxTruthy(x); };
// core.predicates
PRIMITIVES["nil?"] = isNil;
PRIMITIVES["number?"] = function(x) { return typeof x === "number"; };
PRIMITIVES["string?"] = function(x) { return typeof x === "string"; };
PRIMITIVES["list?"] = Array.isArray;
PRIMITIVES["dict?"] = function(x) { return x !== null && typeof x === "object" && !Array.isArray(x) && !x._sym && !x._kw; };
PRIMITIVES["empty?"] = function(c) { return isNil(c) || (Array.isArray(c) ? c.length === 0 : typeof c === "string" ? c.length === 0 : Object.keys(c).length === 0); };
PRIMITIVES["contains?"] = function(c, k) {
if (typeof c === "string") return c.indexOf(String(k)) !== -1;
if (Array.isArray(c)) return c.indexOf(k) !== -1;
return k in c;
};
PRIMITIVES["odd?"] = function(n) { return n % 2 !== 0; };
PRIMITIVES["even?"] = function(n) { return n % 2 === 0; };
PRIMITIVES["zero?"] = function(n) { return n === 0; };
// core.strings
PRIMITIVES["str"] = function() {
var p = [];
for (var i = 0; i < arguments.length; i++) {
var v = arguments[i]; if (isNil(v)) continue; p.push(String(v));
}
return p.join("");
};
PRIMITIVES["upper"] = function(s) { return String(s).toUpperCase(); };
PRIMITIVES["lower"] = function(s) { return String(s).toLowerCase(); };
PRIMITIVES["trim"] = function(s) { return String(s).trim(); };
PRIMITIVES["split"] = function(s, sep) { return String(s).split(sep || " "); };
PRIMITIVES["join"] = function(sep, coll) { return coll.join(sep); };
PRIMITIVES["replace"] = function(s, old, nw) { return s.split(old).join(nw); };
PRIMITIVES["index-of"] = function(s, needle, from) { return String(s).indexOf(needle, from || 0); };
PRIMITIVES["starts-with?"] = function(s, p) { return String(s).indexOf(p) === 0; };
PRIMITIVES["ends-with?"] = function(s, p) { var str = String(s); return str.indexOf(p, str.length - p.length) !== -1; };
PRIMITIVES["slice"] = function(c, a, b) { return b !== undefined ? c.slice(a, b) : c.slice(a); };
PRIMITIVES["concat"] = function() {
var out = [];
for (var i = 0; i < arguments.length; i++) if (!isNil(arguments[i])) out = out.concat(arguments[i]);
return out;
};
// core.collections
PRIMITIVES["list"] = function() { return Array.prototype.slice.call(arguments); };
PRIMITIVES["dict"] = function() {
var d = {};
for (var i = 0; i < arguments.length - 1; i += 2) d[arguments[i]] = arguments[i + 1];
return d;
};
PRIMITIVES["range"] = function(a, b, step) {
var r = []; step = step || 1;
for (var i = a; step > 0 ? i < b : i > b; i += step) r.push(i);
return r;
};
PRIMITIVES["get"] = function(c, k, def) { var v = (c && c[k]); return v !== undefined ? v : (def !== undefined ? def : NIL); };
PRIMITIVES["len"] = function(c) { return Array.isArray(c) ? c.length : typeof c === "string" ? c.length : Object.keys(c).length; };
PRIMITIVES["first"] = function(c) { return c && c.length > 0 ? c[0] : NIL; };
PRIMITIVES["last"] = function(c) { return c && c.length > 0 ? c[c.length - 1] : NIL; };
PRIMITIVES["rest"] = function(c) { return c ? c.slice(1) : []; };
PRIMITIVES["nth"] = function(c, n) { return c && n >= 0 && n < c.length ? c[n] : NIL; };
PRIMITIVES["cons"] = function(x, c) { return [x].concat(c || []); };
PRIMITIVES["append"] = function(c, x) { return (c || []).concat([x]); };
PRIMITIVES["append!"] = function(arr, x) { arr.push(x); return arr; };
PRIMITIVES["chunk-every"] = function(c, n) {
var r = []; for (var i = 0; i < c.length; i += n) r.push(c.slice(i, i + n)); return r;
};
PRIMITIVES["zip-pairs"] = function(c) {
var r = []; for (var i = 0; i < c.length - 1; i++) r.push([c[i], c[i + 1]]); return r;
};
// core.dict
PRIMITIVES["keys"] = function(d) { return Object.keys(d || {}); };
PRIMITIVES["vals"] = function(d) { var r = []; for (var k in d) r.push(d[k]); return r; };
PRIMITIVES["merge"] = function() {
var out = {};
for (var i = 0; i < arguments.length; i++) { var d = arguments[i]; if (d && !isNil(d)) for (var k in d) out[k] = d[k]; }
return out;
};
PRIMITIVES["assoc"] = function(d) {
var out = {}; if (d && !isNil(d)) for (var k in d) out[k] = d[k];
for (var i = 1; i < arguments.length - 1; i += 2) out[arguments[i]] = arguments[i + 1];
return out;
};
PRIMITIVES["dissoc"] = function(d) {
var out = {}; for (var k in d) out[k] = d[k];
for (var i = 1; i < arguments.length; i++) delete out[arguments[i]];
return out;
};
PRIMITIVES["dict-set!"] = function(d, k, v) { d[k] = v; return v; };
PRIMITIVES["into"] = function(target, coll) {
if (Array.isArray(target)) return Array.isArray(coll) ? coll.slice() : Object.entries(coll);
var r = {}; for (var i = 0; i < coll.length; i++) { var p = coll[i]; if (Array.isArray(p) && p.length >= 2) r[p[0]] = p[1]; }
return r;
};
// stdlib.format
PRIMITIVES["format-decimal"] = function(v, p) { return Number(v).toFixed(p || 2); };
PRIMITIVES["parse-int"] = function(v, d) { var n = parseInt(v, 10); return isNaN(n) ? (d || 0) : n; };
PRIMITIVES["format-date"] = function(s, fmt) {
if (!s) return "";
try {
var d = new Date(s);
if (isNaN(d.getTime())) return String(s);
var months = ["January","February","March","April","May","June","July","August","September","October","November","December"];
var short_months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
return fmt.replace(/%-d/g, d.getDate()).replace(/%d/g, ("0"+d.getDate()).slice(-2))
.replace(/%B/g, months[d.getMonth()]).replace(/%b/g, short_months[d.getMonth()])
.replace(/%Y/g, d.getFullYear()).replace(/%m/g, ("0"+(d.getMonth()+1)).slice(-2))
.replace(/%H/g, ("0"+d.getHours()).slice(-2)).replace(/%M/g, ("0"+d.getMinutes()).slice(-2));
} catch (e) { return String(s); }
};
PRIMITIVES["parse-datetime"] = function(s) { return s ? String(s) : NIL; };
// stdlib.text
PRIMITIVES["pluralize"] = function(n, s, p) {
if (s || (p && p !== "s")) return n == 1 ? (s || "") : (p || "s");
return n == 1 ? "" : "s";
};
PRIMITIVES["escape"] = function(s) {
return String(s).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;");
};
PRIMITIVES["strip-tags"] = function(s) { return String(s).replace(/<[^>]+>/g, ""); };
// stdlib.style
PRIMITIVES["css"] = function() {
var atoms = [];
for (var i = 0; i < arguments.length; i++) {
var a = arguments[i];
if (isNil(a) || a === false) continue;
atoms.push(isKw(a) ? a.name : String(a));
}
if (!atoms.length) return NIL;
return new StyleValue("sx-" + atoms.join("-"), atoms.join(";"), [], [], []);
};
PRIMITIVES["merge-styles"] = function() {
var valid = [];
for (var i = 0; i < arguments.length; i++) {
if (isStyleValue(arguments[i])) valid.push(arguments[i]);
}
if (!valid.length) return NIL;
if (valid.length === 1) return valid[0];
var allDecls = valid.map(function(v) { return v.declarations; }).join(";");
return new StyleValue("sx-merged", allDecls, [], [], []);
};
// stdlib.debug
PRIMITIVES["assert"] = function(cond, msg) {
if (!isSxTruthy(cond)) throw new Error("Assertion error: " + (msg || "Assertion failed"));
return true;
};
function isPrimitive(name) { return name in PRIMITIVES; }
function getPrimitive(name) { return PRIMITIVES[name]; }
// Higher-order helpers used by the transpiled code
function map(fn, coll) { return coll.map(fn); }
function mapIndexed(fn, coll) { return coll.map(function(item, i) { return fn(i, item); }); }
function filter(fn, coll) { return coll.filter(function(x) { return isSxTruthy(fn(x)); }); }
function reduce(fn, init, coll) {
var acc = init;
for (var i = 0; i < coll.length; i++) acc = fn(acc, coll[i]);
return acc;
}
function some(fn, coll) {
for (var i = 0; i < coll.length; i++) { var r = fn(coll[i]); if (isSxTruthy(r)) return r; }
return NIL;
}
function forEach(fn, coll) { for (var i = 0; i < coll.length; i++) fn(coll[i]); return NIL; }
function isEvery(fn, coll) {
for (var i = 0; i < coll.length; i++) { if (!isSxTruthy(fn(coll[i]))) return false; }
return true;
}
function mapDict(fn, d) { var r = {}; for (var k in d) r[k] = fn(k, d[k]); return r; }
// List primitives used directly by transpiled code
var len = PRIMITIVES["len"];
var first = PRIMITIVES["first"];
var last = PRIMITIVES["last"];
var rest = PRIMITIVES["rest"];
var nth = PRIMITIVES["nth"];
var cons = PRIMITIVES["cons"];
var append = PRIMITIVES["append"];
var isEmpty = PRIMITIVES["empty?"];
var contains = PRIMITIVES["contains?"];
var startsWith = PRIMITIVES["starts-with?"];
var slice = PRIMITIVES["slice"];
var concat = PRIMITIVES["concat"];
var str = PRIMITIVES["str"];
var join = PRIMITIVES["join"];
var keys = PRIMITIVES["keys"];
var get = PRIMITIVES["get"];
var assoc = PRIMITIVES["assoc"];
var range = PRIMITIVES["range"];
function zip(a, b) { var r = []; for (var i = 0; i < Math.min(a.length, b.length); i++) r.push([a[i], b[i]]); return r; }
function append_b(arr, x) { arr.push(x); return arr; }
var apply = function(f, args) { return f.apply(null, args); };
// Additional primitive aliases used by adapter/engine transpiled code
var split = PRIMITIVES["split"];
var trim = PRIMITIVES["trim"];
var upper = PRIMITIVES["upper"];
var lower = PRIMITIVES["lower"];
var replace_ = function(s, old, nw) { return s.split(old).join(nw); };
var endsWith = PRIMITIVES["ends-with?"];
var parseInt_ = PRIMITIVES["parse-int"];
var dict_fn = PRIMITIVES["dict"];
// HTML rendering helpers
function escapeHtml(s) {
return String(s).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");
}
function escapeAttr(s) { return escapeHtml(s); }
function rawHtmlContent(r) { return r.html; }
function makeRawHtml(s) { return { _raw: true, html: s }; }
// Serializer
function serialize(val) {
if (isNil(val)) return "nil";
if (typeof val === "boolean") return val ? "true" : "false";
if (typeof val === "number") return String(val);
if (typeof val === "string") return '"' + val.replace(/\\/g, "\\\\").replace(/"/g, '\\"') + '"';
if (isSym(val)) return val.name;
if (isKw(val)) return ":" + val.name;
if (Array.isArray(val)) return "(" + val.map(serialize).join(" ") + ")";
return String(val);
}
function isSpecialForm(n) { return n in {
"if":1,"when":1,"cond":1,"case":1,"and":1,"or":1,"let":1,"let*":1,
"lambda":1,"fn":1,"define":1,"defcomp":1,"defmacro":1,"defstyle":1,
"defkeyframes":1,"defhandler":1,"begin":1,"do":1,
"quote":1,"quasiquote":1,"->":1,"set!":1
}; }
function isHoForm(n) { return n in {
"map":1,"map-indexed":1,"filter":1,"reduce":1,"some":1,"every?":1,"for-each":1
}; }
// processBindings and evalCond — now specced in render.sx, bootstrapped above
function isDefinitionForm(name) {
return name === "define" || name === "defcomp" || name === "defmacro" ||
name === "defstyle" || name === "defkeyframes" || name === "defhandler";
}
function indexOf_(s, ch) {
return typeof s === "string" ? s.indexOf(ch) : -1;
}
function dictHas(d, k) { return d != null && k in d; }
function dictDelete(d, k) { delete d[k]; }
function forEachIndexed(fn, coll) {
for (var i = 0; i < coll.length; i++) fn(i, coll[i]);
return NIL;
}
// =========================================================================
// Performance overrides — evaluator hot path
// =========================================================================
// Override parseKeywordArgs: imperative loop instead of reduce+assoc
parseKeywordArgs = function(rawArgs, env) {
var kwargs = {};
var children = [];
for (var i = 0; i < rawArgs.length; i++) {
var arg = rawArgs[i];
if (arg && arg._kw && (i + 1) < rawArgs.length) {
kwargs[arg.name] = trampoline(evalExpr(rawArgs[i + 1], env));
i++;
} else {
children.push(trampoline(evalExpr(arg, env)));
}
}
return [kwargs, children];
};
// Override callComponent: use prototype chain env, imperative kwarg binding
callComponent = function(comp, rawArgs, env) {
var kwargs = {};
var children = [];
for (var i = 0; i < rawArgs.length; i++) {
var arg = rawArgs[i];
if (arg && arg._kw && (i + 1) < rawArgs.length) {
kwargs[arg.name] = trampoline(evalExpr(rawArgs[i + 1], env));
i++;
} else {
children.push(trampoline(evalExpr(arg, env)));
}
}
var local = Object.create(componentClosure(comp));
for (var k in env) if (env.hasOwnProperty(k)) local[k] = env[k];
var params = componentParams(comp);
for (var j = 0; j < params.length; j++) {
var p = params[j];
local[p] = p in kwargs ? kwargs[p] : NIL;
}
if (componentHasChildren(comp)) {
local["children"] = children;
}
return makeThunk(componentBody(comp), local);
};
// =========================================================================
// Platform: deps module — component dependency analysis
// =========================================================================
function componentDeps(c) {
return c.deps ? c.deps.slice() : [];
}
function componentSetDeps(c, deps) {
c.deps = deps;
}
function componentCssClasses(c) {
return c.cssClasses ? c.cssClasses.slice() : [];
}
function envComponents(env) {
var names = [];
for (var k in env) {
var v = env[k];
if (v && (v._component || v._macro)) names.push(k);
}
return names;
}
function regexFindAll(pattern, source) {
var re = new RegExp(pattern, "g");
var results = [];
var m;
while ((m = re.exec(source)) !== null) {
if (m[1] !== undefined) results.push(m[1]);
else results.push(m[0]);
}
return results;
}
function scanCssClasses(source) {
var classes = {};
var result = [];
var m;
var re1 = /:class\s+"([^"]*)"/g;
while ((m = re1.exec(source)) !== null) {
var parts = m[1].split(/\s+/);
for (var i = 0; i < parts.length; i++) {
if (parts[i] && !classes[parts[i]]) {
classes[parts[i]] = true;
result.push(parts[i]);
}
}
}
var re2 = /:class\s+\(str\s+((?:"[^"]*"\s*)+)\)/g;
while ((m = re2.exec(source)) !== null) {
var re3 = /"([^"]*)"/g;
var m2;
while ((m2 = re3.exec(m[1])) !== null) {
var parts2 = m2[1].split(/\s+/);
for (var j = 0; j < parts2.length; j++) {
if (parts2[j] && !classes[parts2[j]]) {
classes[parts2[j]] = true;
result.push(parts2[j]);
}
}
}
}
var re4 = /;;\s*@css\s+(.+)/g;
while ((m = re4.exec(source)) !== null) {
var parts3 = m[1].split(/\s+/);
for (var k = 0; k < parts3.length; k++) {
if (parts3[k] && !classes[parts3[k]]) {
classes[parts3[k]] = true;
result.push(parts3[k]);
}
}
}
return result;
}
function componentIoRefs(c) {
return c.ioRefs ? c.ioRefs.slice() : [];
}
function componentSetIoRefs(c, refs) {
c.ioRefs = refs;
}
// =========================================================================
// Platform interface — Parser
// =========================================================================
// Character classification derived from the grammar:
// ident-start → [a-zA-Z_~*+\-><=/!?&]
// ident-char → ident-start + [0-9.:\/\[\]#,]
var _identStartRe = /[a-zA-Z_~*+\-><=/!?&]/;
var _identCharRe = /[a-zA-Z0-9_~*+\-><=/!?.:&/\[\]#,]/;
function isIdentStart(ch) { return _identStartRe.test(ch); }
function isIdentChar(ch) { return _identCharRe.test(ch); }
function parseNumber(s) { return Number(s); }
function escapeString(s) {
return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\t/g, "\\t");
}
function sxExprSource(e) { return typeof e === "string" ? e : String(e); }
// === Transpiled from eval ===
// trampoline
var trampoline = function(val) { return (function() {
var result = val;
return (isSxTruthy(isThunk(result)) ? trampoline(evalExpr(thunkExpr(result), thunkEnv(result))) : result);
})(); };
// eval-expr
var evalExpr = function(expr, env) { return (function() { var _m = typeOf(expr); if (_m == "number") return expr; if (_m == "string") return expr; if (_m == "boolean") return expr; if (_m == "nil") return NIL; if (_m == "symbol") return (function() {
var name = symbolName(expr);
return (isSxTruthy(envHas(env, name)) ? envGet(env, name) : (isSxTruthy(isPrimitive(name)) ? getPrimitive(name) : (isSxTruthy((name == "true")) ? true : (isSxTruthy((name == "false")) ? false : (isSxTruthy((name == "nil")) ? NIL : error((String("Undefined symbol: ") + String(name))))))));
})(); if (_m == "keyword") return keywordName(expr); if (_m == "dict") return mapDict(function(k, v) { return trampoline(evalExpr(v, env)); }, expr); if (_m == "list") return (isSxTruthy(isEmpty(expr)) ? [] : evalList(expr, env)); return expr; })(); };
// eval-list
var evalList = function(expr, env) { return (function() {
var head = first(expr);
var args = rest(expr);
return (isSxTruthy(!isSxTruthy(sxOr((typeOf(head) == "symbol"), (typeOf(head) == "lambda"), (typeOf(head) == "list")))) ? map(function(x) { return trampoline(evalExpr(x, env)); }, expr) : (isSxTruthy((typeOf(head) == "symbol")) ? (function() {
var name = symbolName(head);
return (isSxTruthy((name == "if")) ? sfIf(args, env) : (isSxTruthy((name == "when")) ? sfWhen(args, env) : (isSxTruthy((name == "cond")) ? sfCond(args, env) : (isSxTruthy((name == "case")) ? sfCase(args, env) : (isSxTruthy((name == "and")) ? sfAnd(args, env) : (isSxTruthy((name == "or")) ? sfOr(args, env) : (isSxTruthy((name == "let")) ? sfLet(args, env) : (isSxTruthy((name == "let*")) ? sfLet(args, env) : (isSxTruthy((name == "letrec")) ? sfLetrec(args, env) : (isSxTruthy((name == "lambda")) ? sfLambda(args, env) : (isSxTruthy((name == "fn")) ? sfLambda(args, env) : (isSxTruthy((name == "define")) ? sfDefine(args, env) : (isSxTruthy((name == "defcomp")) ? sfDefcomp(args, env) : (isSxTruthy((name == "defmacro")) ? sfDefmacro(args, env) : (isSxTruthy((name == "defstyle")) ? sfDefstyle(args, env) : (isSxTruthy((name == "defkeyframes")) ? sfDefkeyframes(args, env) : (isSxTruthy((name == "defhandler")) ? sfDefhandler(args, env) : (isSxTruthy((name == "defpage")) ? sfDefpage(args, env) : (isSxTruthy((name == "defquery")) ? sfDefquery(args, env) : (isSxTruthy((name == "defaction")) ? sfDefaction(args, env) : (isSxTruthy((name == "begin")) ? sfBegin(args, env) : (isSxTruthy((name == "do")) ? sfBegin(args, env) : (isSxTruthy((name == "quote")) ? sfQuote(args, env) : (isSxTruthy((name == "quasiquote")) ? sfQuasiquote(args, env) : (isSxTruthy((name == "->")) ? sfThreadFirst(args, env) : (isSxTruthy((name == "set!")) ? sfSetBang(args, env) : (isSxTruthy((name == "reset")) ? sfReset(args, env) : (isSxTruthy((name == "shift")) ? sfShift(args, env) : (isSxTruthy((name == "dynamic-wind")) ? sfDynamicWind(args, env) : (isSxTruthy((name == "map")) ? hoMap(args, env) : (isSxTruthy((name == "map-indexed")) ? hoMapIndexed(args, env) : (isSxTruthy((name == "filter")) ? hoFilter(args, env) : (isSxTruthy((name == "reduce")) ? hoReduce(args, env) : (isSxTruthy((name == "some")) ? hoSome(args, env) : (isSxTruthy((name == "every?")) ? hoEvery(args, env) : (isSxTruthy((name == "for-each")) ? hoForEach(args, env) : (isSxTruthy((isSxTruthy(envHas(env, name)) && isMacro(envGet(env, name)))) ? (function() {
var mac = envGet(env, name);
return makeThunk(expandMacro(mac, args, env), env);
})() : (isSxTruthy(isRenderExpr(expr)) ? renderExpr(expr, env) : evalCall(head, args, env)))))))))))))))))))))))))))))))))))))));
})() : evalCall(head, args, env)));
})(); };
// eval-call
var evalCall = function(head, args, env) { return (function() {
var f = trampoline(evalExpr(head, env));
var evaluatedArgs = map(function(a) { return trampoline(evalExpr(a, env)); }, args);
return (isSxTruthy((isSxTruthy(isCallable(f)) && isSxTruthy(!isSxTruthy(isLambda(f))) && !isSxTruthy(isComponent(f)))) ? apply(f, evaluatedArgs) : (isSxTruthy(isLambda(f)) ? callLambda(f, evaluatedArgs, env) : (isSxTruthy(isComponent(f)) ? callComponent(f, args, env) : error((String("Not callable: ") + String(inspect(f)))))));
})(); };
// call-lambda
var callLambda = function(f, args, callerEnv) { return (function() {
var params = lambdaParams(f);
var local = envMerge(lambdaClosure(f), callerEnv);
return (isSxTruthy((len(args) != len(params))) ? error((String(sxOr(lambdaName(f), "lambda")) + String(" expects ") + String(len(params)) + String(" args, got ") + String(len(args)))) : (forEach(function(pair) { return envSet(local, first(pair), nth(pair, 1)); }, zip(params, args)), makeThunk(lambdaBody(f), local)));
})(); };
// call-component
var callComponent = function(comp, rawArgs, env) { return (function() {
var parsed = parseKeywordArgs(rawArgs, env);
var kwargs = first(parsed);
var children = nth(parsed, 1);
var local = envMerge(componentClosure(comp), env);
{ var _c = componentParams(comp); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; local[p] = sxOr(dictGet(kwargs, p), NIL); } }
if (isSxTruthy(componentHasChildren(comp))) {
local["children"] = children;
}
return makeThunk(componentBody(comp), local);
})(); };
// parse-keyword-args
var parseKeywordArgs = function(rawArgs, env) { return (function() {
var kwargs = {};
var children = [];
var i = 0;
reduce(function(state, arg) { return (function() {
var idx = get(state, "i");
var skip = get(state, "skip");
return (isSxTruthy(skip) ? assoc(state, "skip", false, "i", (idx + 1)) : (isSxTruthy((isSxTruthy((typeOf(arg) == "keyword")) && ((idx + 1) < len(rawArgs)))) ? (dictSet(kwargs, keywordName(arg), trampoline(evalExpr(nth(rawArgs, (idx + 1)), env))), assoc(state, "skip", true, "i", (idx + 1))) : (append_b(children, trampoline(evalExpr(arg, env))), assoc(state, "i", (idx + 1)))));
})(); }, {["i"]: 0, ["skip"]: false}, rawArgs);
return [kwargs, children];
})(); };
// sf-if
var sfIf = function(args, env) { return (function() {
var condition = trampoline(evalExpr(first(args), env));
return (isSxTruthy((isSxTruthy(condition) && !isSxTruthy(isNil(condition)))) ? makeThunk(nth(args, 1), env) : (isSxTruthy((len(args) > 2)) ? makeThunk(nth(args, 2), env) : NIL));
})(); };
// sf-when
var sfWhen = function(args, env) { return (function() {
var condition = trampoline(evalExpr(first(args), env));
return (isSxTruthy((isSxTruthy(condition) && !isSxTruthy(isNil(condition)))) ? (forEach(function(e) { return trampoline(evalExpr(e, env)); }, slice(args, 1, (len(args) - 1))), makeThunk(last(args), env)) : NIL);
})(); };
// sf-cond
var sfCond = function(args, env) { return (isSxTruthy((isSxTruthy((typeOf(first(args)) == "list")) && (len(first(args)) == 2))) ? sfCondScheme(args, env) : sfCondClojure(args, env)); };
// sf-cond-scheme
var sfCondScheme = function(clauses, env) { return (isSxTruthy(isEmpty(clauses)) ? NIL : (function() {
var clause = first(clauses);
var test = first(clause);
var body = nth(clause, 1);
return (isSxTruthy(sxOr((isSxTruthy((typeOf(test) == "symbol")) && sxOr((symbolName(test) == "else"), (symbolName(test) == ":else"))), (isSxTruthy((typeOf(test) == "keyword")) && (keywordName(test) == "else")))) ? makeThunk(body, env) : (isSxTruthy(trampoline(evalExpr(test, env))) ? makeThunk(body, env) : sfCondScheme(rest(clauses), env)));
})()); };
// sf-cond-clojure
var sfCondClojure = function(clauses, env) { return (isSxTruthy((len(clauses) < 2)) ? NIL : (function() {
var test = first(clauses);
var body = nth(clauses, 1);
return (isSxTruthy(sxOr((isSxTruthy((typeOf(test) == "keyword")) && (keywordName(test) == "else")), (isSxTruthy((typeOf(test) == "symbol")) && sxOr((symbolName(test) == "else"), (symbolName(test) == ":else"))))) ? makeThunk(body, env) : (isSxTruthy(trampoline(evalExpr(test, env))) ? makeThunk(body, env) : sfCondClojure(slice(clauses, 2), env)));
})()); };
// sf-case
var sfCase = function(args, env) { return (function() {
var matchVal = trampoline(evalExpr(first(args), env));
var clauses = rest(args);
return sfCaseLoop(matchVal, clauses, env);
})(); };
// sf-case-loop
var sfCaseLoop = function(matchVal, clauses, env) { return (isSxTruthy((len(clauses) < 2)) ? NIL : (function() {
var test = first(clauses);
var body = nth(clauses, 1);
return (isSxTruthy(sxOr((isSxTruthy((typeOf(test) == "keyword")) && (keywordName(test) == "else")), (isSxTruthy((typeOf(test) == "symbol")) && sxOr((symbolName(test) == "else"), (symbolName(test) == ":else"))))) ? makeThunk(body, env) : (isSxTruthy((matchVal == trampoline(evalExpr(test, env)))) ? makeThunk(body, env) : sfCaseLoop(matchVal, slice(clauses, 2), env)));
})()); };
// sf-and
var sfAnd = function(args, env) { return (isSxTruthy(isEmpty(args)) ? true : (function() {
var val = trampoline(evalExpr(first(args), env));
return (isSxTruthy(!isSxTruthy(val)) ? val : (isSxTruthy((len(args) == 1)) ? val : sfAnd(rest(args), env)));
})()); };
// sf-or
var sfOr = function(args, env) { return (isSxTruthy(isEmpty(args)) ? false : (function() {
var val = trampoline(evalExpr(first(args), env));
return (isSxTruthy(val) ? val : sfOr(rest(args), env));
})()); };
// sf-let
var sfLet = function(args, env) { return (isSxTruthy((typeOf(first(args)) == "symbol")) ? sfNamedLet(args, env) : (function() {
var bindings = first(args);
var body = rest(args);
var local = envExtend(env);
(isSxTruthy((isSxTruthy((typeOf(first(bindings)) == "list")) && (len(first(bindings)) == 2))) ? forEach(function(binding) { return (function() {
var vname = (isSxTruthy((typeOf(first(binding)) == "symbol")) ? symbolName(first(binding)) : first(binding));
return envSet(local, vname, trampoline(evalExpr(nth(binding, 1), local)));
})(); }, bindings) : (function() {
var i = 0;
return reduce(function(acc, pairIdx) { return (function() {
var vname = (isSxTruthy((typeOf(nth(bindings, (pairIdx * 2))) == "symbol")) ? symbolName(nth(bindings, (pairIdx * 2))) : nth(bindings, (pairIdx * 2)));
var valExpr = nth(bindings, ((pairIdx * 2) + 1));
return envSet(local, vname, trampoline(evalExpr(valExpr, local)));
})(); }, NIL, range(0, (len(bindings) / 2)));
})());
{ var _c = slice(body, 0, (len(body) - 1)); for (var _i = 0; _i < _c.length; _i++) { var e = _c[_i]; trampoline(evalExpr(e, local)); } }
return makeThunk(last(body), local);
})()); };
// sf-named-let
var sfNamedLet = function(args, env) { return (function() {
var loopName = symbolName(first(args));
var bindings = nth(args, 1);
var body = slice(args, 2);
var params = [];
var inits = [];
(isSxTruthy((isSxTruthy((typeOf(first(bindings)) == "list")) && (len(first(bindings)) == 2))) ? forEach(function(binding) { params.push((isSxTruthy((typeOf(first(binding)) == "symbol")) ? symbolName(first(binding)) : first(binding)));
return append_b(inits, nth(binding, 1)); }, bindings) : reduce(function(acc, pairIdx) { return (append_b(params, (isSxTruthy((typeOf(nth(bindings, (pairIdx * 2))) == "symbol")) ? symbolName(nth(bindings, (pairIdx * 2))) : nth(bindings, (pairIdx * 2)))), append_b(inits, nth(bindings, ((pairIdx * 2) + 1)))); }, NIL, range(0, (len(bindings) / 2))));
return (function() {
var loopBody = (isSxTruthy((len(body) == 1)) ? first(body) : cons(makeSymbol("begin"), body));
var loopFn = makeLambda(params, loopBody, env);
loopFn.name = loopName;
lambdaClosure(loopFn)[loopName] = loopFn;
return (function() {
var initVals = map(function(e) { return trampoline(evalExpr(e, env)); }, inits);
return callLambda(loopFn, initVals, env);
})();
})();
})(); };
// sf-lambda
var sfLambda = function(args, env) { return (function() {
var paramsExpr = first(args);
var body = nth(args, 1);
var paramNames = map(function(p) { return (isSxTruthy((typeOf(p) == "symbol")) ? symbolName(p) : p); }, paramsExpr);
return makeLambda(paramNames, body, env);
})(); };
// sf-define
var sfDefine = function(args, env) { return (function() {
var nameSym = first(args);
var value = trampoline(evalExpr(nth(args, 1), env));
if (isSxTruthy((isSxTruthy(isLambda(value)) && isNil(lambdaName(value))))) {
value.name = symbolName(nameSym);
}
env[symbolName(nameSym)] = value;
return value;
})(); };
// sf-defcomp
var sfDefcomp = function(args, env) { return (function() {
var nameSym = first(args);
var paramsRaw = nth(args, 1);
var body = nth(args, 2);
var compName = stripPrefix(symbolName(nameSym), "~");
var parsed = parseCompParams(paramsRaw);
var params = first(parsed);
var hasChildren = nth(parsed, 1);
return (function() {
var comp = makeComponent(compName, params, hasChildren, body, env);
env[symbolName(nameSym)] = comp;
return comp;
})();
})(); };
// parse-comp-params
var parseCompParams = function(paramsExpr) { return (function() {
var params = [];
var hasChildren = false;
var inKey = false;
{ var _c = paramsExpr; for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; if (isSxTruthy((typeOf(p) == "symbol"))) {
(function() {
var name = symbolName(p);
return (isSxTruthy((name == "&key")) ? (inKey = true) : (isSxTruthy((name == "&rest")) ? (hasChildren = true) : (isSxTruthy((name == "&children")) ? (hasChildren = true) : (isSxTruthy(hasChildren) ? NIL : (isSxTruthy(inKey) ? append_b(params, name) : append_b(params, name))))));
})();
} } }
return [params, hasChildren];
})(); };
// sf-defmacro
var sfDefmacro = function(args, env) { return (function() {
var nameSym = first(args);
var paramsRaw = nth(args, 1);
var body = nth(args, 2);
var parsed = parseMacroParams(paramsRaw);
var params = first(parsed);
var restParam = nth(parsed, 1);
return (function() {
var mac = makeMacro(params, restParam, body, env, symbolName(nameSym));
env[symbolName(nameSym)] = mac;
return mac;
})();
})(); };
// parse-macro-params
var parseMacroParams = function(paramsExpr) { return (function() {
var params = [];
var restParam = NIL;
reduce(function(state, p) { return (isSxTruthy((isSxTruthy((typeOf(p) == "symbol")) && (symbolName(p) == "&rest"))) ? assoc(state, "in-rest", true) : (isSxTruthy(get(state, "in-rest")) ? ((restParam = (isSxTruthy((typeOf(p) == "symbol")) ? symbolName(p) : p)), state) : (append_b(params, (isSxTruthy((typeOf(p) == "symbol")) ? symbolName(p) : p)), state))); }, {["in-rest"]: false}, paramsExpr);
return [params, restParam];
})(); };
// sf-defstyle
var sfDefstyle = function(args, env) { return (function() {
var nameSym = first(args);
var value = trampoline(evalExpr(nth(args, 1), env));
env[symbolName(nameSym)] = value;
return value;
})(); };
// sf-defkeyframes
var sfDefkeyframes = function(args, env) { return (function() {
var kfName = symbolName(first(args));
var steps = rest(args);
return buildKeyframes(kfName, steps, env);
})(); };
// sf-begin
var sfBegin = function(args, env) { return (isSxTruthy(isEmpty(args)) ? NIL : (forEach(function(e) { return trampoline(evalExpr(e, env)); }, slice(args, 0, (len(args) - 1))), makeThunk(last(args), env))); };
// sf-quote
var sfQuote = function(args, env) { return (isSxTruthy(isEmpty(args)) ? NIL : first(args)); };
// sf-quasiquote
var sfQuasiquote = function(args, env) { return qqExpand(first(args), env); };
// qq-expand
var qqExpand = function(template, env) { return (isSxTruthy(!isSxTruthy((typeOf(template) == "list"))) ? template : (isSxTruthy(isEmpty(template)) ? [] : (function() {
var head = first(template);
return (isSxTruthy((isSxTruthy((typeOf(head) == "symbol")) && (symbolName(head) == "unquote"))) ? trampoline(evalExpr(nth(template, 1), env)) : reduce(function(result, item) { return (isSxTruthy((isSxTruthy((typeOf(item) == "list")) && isSxTruthy((len(item) == 2)) && isSxTruthy((typeOf(first(item)) == "symbol")) && (symbolName(first(item)) == "splice-unquote"))) ? (function() {
var spliced = trampoline(evalExpr(nth(item, 1), env));
return (isSxTruthy((typeOf(spliced) == "list")) ? concat(result, spliced) : (isSxTruthy(isNil(spliced)) ? result : append(result, spliced)));
})() : append(result, qqExpand(item, env))); }, [], template));
})())); };
// sf-thread-first
var sfThreadFirst = function(args, env) { return (function() {
var val = trampoline(evalExpr(first(args), env));
return reduce(function(result, form) { return (isSxTruthy((typeOf(form) == "list")) ? (function() {
var f = trampoline(evalExpr(first(form), env));
var restArgs = map(function(a) { return trampoline(evalExpr(a, env)); }, rest(form));
var allArgs = cons(result, restArgs);
return (isSxTruthy((isSxTruthy(isCallable(f)) && !isSxTruthy(isLambda(f)))) ? apply(f, allArgs) : (isSxTruthy(isLambda(f)) ? trampoline(callLambda(f, allArgs, env)) : error((String("-> form not callable: ") + String(inspect(f))))));
})() : (function() {
var f = trampoline(evalExpr(form, env));
return (isSxTruthy((isSxTruthy(isCallable(f)) && !isSxTruthy(isLambda(f)))) ? f(result) : (isSxTruthy(isLambda(f)) ? trampoline(callLambda(f, [result], env)) : error((String("-> form not callable: ") + String(inspect(f))))));
})()); }, val, rest(args));
})(); };
// sf-set!
var sfSetBang = function(args, env) { return (function() {
var name = symbolName(first(args));
var value = trampoline(evalExpr(nth(args, 1), env));
env[name] = value;
return value;
})(); };
// sf-letrec
var sfLetrec = function(args, env) { return (function() {
var bindings = first(args);
var body = rest(args);
var local = envExtend(env);
var names = [];
var valExprs = [];
(isSxTruthy((isSxTruthy((typeOf(first(bindings)) == "list")) && (len(first(bindings)) == 2))) ? forEach(function(binding) { return (function() {
var vname = (isSxTruthy((typeOf(first(binding)) == "symbol")) ? symbolName(first(binding)) : first(binding));
names.push(vname);
valExprs.push(nth(binding, 1));
return envSet(local, vname, NIL);
})(); }, bindings) : reduce(function(acc, pairIdx) { return (function() {
var vname = (isSxTruthy((typeOf(nth(bindings, (pairIdx * 2))) == "symbol")) ? symbolName(nth(bindings, (pairIdx * 2))) : nth(bindings, (pairIdx * 2)));
var valExpr = nth(bindings, ((pairIdx * 2) + 1));
names.push(vname);
valExprs.push(valExpr);
return envSet(local, vname, NIL);
})(); }, NIL, range(0, (len(bindings) / 2))));
(function() {
var values = map(function(e) { return trampoline(evalExpr(e, local)); }, valExprs);
{ var _c = zip(names, values); for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; local[first(pair)] = nth(pair, 1); } }
return forEach(function(val) { return (isSxTruthy(isLambda(val)) ? forEach(function(n) { return envSet(lambdaClosure(val), n, envGet(local, n)); }, names) : NIL); }, values);
})();
{ var _c = slice(body, 0, (len(body) - 1)); for (var _i = 0; _i < _c.length; _i++) { var e = _c[_i]; trampoline(evalExpr(e, local)); } }
return makeThunk(last(body), local);
})(); };
// sf-dynamic-wind
var sfDynamicWind = function(args, env) { return (function() {
var before = trampoline(evalExpr(first(args), env));
var body = trampoline(evalExpr(nth(args, 1), env));
var after = trampoline(evalExpr(nth(args, 2), env));
callThunk(before, env);
pushWind(before, after);
return (function() {
var result = callThunk(body, env);
popWind();
callThunk(after, env);
return result;
})();
})(); };
// expand-macro
var expandMacro = function(mac, rawArgs, env) { return (function() {
var local = envMerge(macroClosure(mac), env);
{ var _c = mapIndexed(function(i, p) { return [p, i]; }, macroParams(mac)); for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; local[first(pair)] = (isSxTruthy((nth(pair, 1) < len(rawArgs))) ? nth(rawArgs, nth(pair, 1)) : NIL); } }
if (isSxTruthy(macroRestParam(mac))) {
local[macroRestParam(mac)] = slice(rawArgs, len(macroParams(mac)));
}
return trampoline(evalExpr(macroBody(mac), local));
})(); };
// call-fn
var callFn = function(f, args, env) { return (isSxTruthy(isLambda(f)) ? trampoline(callLambda(f, args, env)) : (isSxTruthy(isCallable(f)) ? apply(f, args) : error((String("Not callable in HO form: ") + String(inspect(f)))))); };
// ho-map
var hoMap = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var coll = trampoline(evalExpr(nth(args, 1), env));
return map(function(item) { return callFn(f, [item], env); }, coll);
})(); };
// ho-map-indexed
var hoMapIndexed = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var coll = trampoline(evalExpr(nth(args, 1), env));
return mapIndexed(function(i, item) { return callFn(f, [i, item], env); }, coll);
})(); };
// ho-filter
var hoFilter = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var coll = trampoline(evalExpr(nth(args, 1), env));
return filter(function(item) { return callFn(f, [item], env); }, coll);
})(); };
// ho-reduce
var hoReduce = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var init = trampoline(evalExpr(nth(args, 1), env));
var coll = trampoline(evalExpr(nth(args, 2), env));
return reduce(function(acc, item) { return callFn(f, [acc, item], env); }, init, coll);
})(); };
// ho-some
var hoSome = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var coll = trampoline(evalExpr(nth(args, 1), env));
return some(function(item) { return callFn(f, [item], env); }, coll);
})(); };
// ho-every
var hoEvery = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var coll = trampoline(evalExpr(nth(args, 1), env));
return isEvery(function(item) { return callFn(f, [item], env); }, coll);
})(); };
// ho-for-each
var hoForEach = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var coll = trampoline(evalExpr(nth(args, 1), env));
return forEach(function(item) { return callFn(f, [item], env); }, coll);
})(); };
// === Transpiled from render (core) ===
// HTML_TAGS
var HTML_TAGS = ["html", "head", "body", "title", "meta", "link", "script", "style", "noscript", "header", "nav", "main", "section", "article", "aside", "footer", "h1", "h2", "h3", "h4", "h5", "h6", "hgroup", "div", "p", "blockquote", "pre", "figure", "figcaption", "address", "details", "summary", "a", "span", "em", "strong", "small", "b", "i", "u", "s", "mark", "sub", "sup", "abbr", "cite", "code", "time", "br", "wbr", "hr", "ul", "ol", "li", "dl", "dt", "dd", "table", "thead", "tbody", "tfoot", "tr", "th", "td", "caption", "colgroup", "col", "form", "input", "textarea", "select", "option", "optgroup", "button", "label", "fieldset", "legend", "output", "datalist", "img", "video", "audio", "source", "picture", "canvas", "iframe", "svg", "math", "path", "circle", "ellipse", "rect", "line", "polyline", "polygon", "text", "tspan", "g", "defs", "use", "clipPath", "mask", "pattern", "linearGradient", "radialGradient", "stop", "filter", "feGaussianBlur", "feOffset", "feBlend", "feColorMatrix", "feComposite", "feMerge", "feMergeNode", "feTurbulence", "feComponentTransfer", "feFuncR", "feFuncG", "feFuncB", "feFuncA", "feDisplacementMap", "feFlood", "feImage", "feMorphology", "feSpecularLighting", "feDiffuseLighting", "fePointLight", "feSpotLight", "feDistantLight", "animate", "animateTransform", "foreignObject", "template", "slot", "dialog", "menu"];
// VOID_ELEMENTS
var VOID_ELEMENTS = ["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"];
// BOOLEAN_ATTRS
var BOOLEAN_ATTRS = ["async", "autofocus", "autoplay", "checked", "controls", "default", "defer", "disabled", "formnovalidate", "hidden", "inert", "ismap", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "selected"];
// definition-form?
var isDefinitionForm = function(name) { return sxOr((name == "define"), (name == "defcomp"), (name == "defmacro"), (name == "defstyle"), (name == "defkeyframes"), (name == "defhandler")); };
// parse-element-args
var parseElementArgs = function(args, env) { return (function() {
var attrs = {};
var children = [];
reduce(function(state, arg) { return (function() {
var skip = get(state, "skip");
return (isSxTruthy(skip) ? assoc(state, "skip", false, "i", (get(state, "i") + 1)) : (isSxTruthy((isSxTruthy((typeOf(arg) == "keyword")) && ((get(state, "i") + 1) < len(args)))) ? (function() {
var val = trampoline(evalExpr(nth(args, (get(state, "i") + 1)), env));
attrs[keywordName(arg)] = val;
return assoc(state, "skip", true, "i", (get(state, "i") + 1));
})() : (append_b(children, arg), assoc(state, "i", (get(state, "i") + 1)))));
})(); }, {["i"]: 0, ["skip"]: false}, args);
return [attrs, children];
})(); };
// render-attrs
var renderAttrs = function(attrs) { return join("", map(function(key) { return (function() {
var val = dictGet(attrs, key);
return (isSxTruthy((isSxTruthy(contains(BOOLEAN_ATTRS, key)) && val)) ? (String(" ") + String(key)) : (isSxTruthy((isSxTruthy(contains(BOOLEAN_ATTRS, key)) && !isSxTruthy(val))) ? "" : (isSxTruthy(isNil(val)) ? "" : (isSxTruthy((isSxTruthy((key == "style")) && isStyleValue(val))) ? (String(" class=\"") + String(styleValueClass(val)) + String("\"")) : (String(" ") + String(key) + String("=\"") + String(escapeAttr((String(val)))) + String("\""))))));
})(); }, keys(attrs))); };
// eval-cond
var evalCond = function(clauses, env) { return (isSxTruthy((isSxTruthy(!isSxTruthy(isEmpty(clauses))) && isSxTruthy((typeOf(first(clauses)) == "list")) && (len(first(clauses)) == 2))) ? evalCondScheme(clauses, env) : evalCondClojure(clauses, env)); };
// eval-cond-scheme
var evalCondScheme = function(clauses, env) { return (isSxTruthy(isEmpty(clauses)) ? NIL : (function() {
var clause = first(clauses);
var test = first(clause);
var body = nth(clause, 1);
return (isSxTruthy(sxOr((isSxTruthy((typeOf(test) == "symbol")) && sxOr((symbolName(test) == "else"), (symbolName(test) == ":else"))), (isSxTruthy((typeOf(test) == "keyword")) && (keywordName(test) == "else")))) ? body : (isSxTruthy(trampoline(evalExpr(test, env))) ? body : evalCondScheme(rest(clauses), env)));
})()); };
// eval-cond-clojure
var evalCondClojure = function(clauses, env) { return (isSxTruthy((len(clauses) < 2)) ? NIL : (function() {
var test = first(clauses);
var body = nth(clauses, 1);
return (isSxTruthy(sxOr((isSxTruthy((typeOf(test) == "keyword")) && (keywordName(test) == "else")), (isSxTruthy((typeOf(test) == "symbol")) && sxOr((symbolName(test) == "else"), (symbolName(test) == ":else"))))) ? body : (isSxTruthy(trampoline(evalExpr(test, env))) ? body : evalCondClojure(slice(clauses, 2), env)));
})()); };
// process-bindings
var processBindings = function(bindings, env) { return (function() {
var local = merge(env);
{ var _c = bindings; for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; if (isSxTruthy((isSxTruthy((typeOf(pair) == "list")) && (len(pair) >= 2)))) {
(function() {
var name = (isSxTruthy((typeOf(first(pair)) == "symbol")) ? symbolName(first(pair)) : (String(first(pair))));
return envSet(local, name, trampoline(evalExpr(nth(pair, 1), local)));
})();
} } }
return local;
})(); };
// === Transpiled from parser ===
// sx-parse
var sxParse = function(source) { return (function() {
var pos = 0;
var lenSrc = len(source);
var skipComment = function() { while(true) { if (isSxTruthy((isSxTruthy((pos < lenSrc)) && !isSxTruthy((nth(source, pos) == "\n"))))) { pos = (pos + 1);
continue; } else { return NIL; } } };
var skipWs = function() { while(true) { if (isSxTruthy((pos < lenSrc))) { { var ch = nth(source, pos);
if (isSxTruthy(sxOr((ch == " "), (ch == "\t"), (ch == "\n"), (ch == "\\r")))) { pos = (pos + 1);
continue; } else if (isSxTruthy((ch == ";"))) { pos = (pos + 1);
skipComment();
continue; } else { return NIL; } } } else { return NIL; } } };
var readString = function() { pos = (pos + 1);
return (function() {
var buf = "";
var readStrLoop = function() { while(true) { if (isSxTruthy((pos >= lenSrc))) { return error("Unterminated string"); } else { { var ch = nth(source, pos);
if (isSxTruthy((ch == "\""))) { pos = (pos + 1);
return NIL; } else if (isSxTruthy((ch == "\\"))) { pos = (pos + 1);
{ var esc = nth(source, pos);
buf = (String(buf) + String((isSxTruthy((esc == "n")) ? "\n" : (isSxTruthy((esc == "t")) ? "\t" : (isSxTruthy((esc == "r")) ? "\\r" : esc)))));
pos = (pos + 1);
continue; } } else { buf = (String(buf) + String(ch));
pos = (pos + 1);
continue; } } } } };
readStrLoop();
return buf;
})(); };
var readIdent = function() { return (function() {
var start = pos;
var readIdentLoop = function() { while(true) { if (isSxTruthy((isSxTruthy((pos < lenSrc)) && isIdentChar(nth(source, pos))))) { pos = (pos + 1);
continue; } else { return NIL; } } };
readIdentLoop();
return slice(source, start, pos);
})(); };
var readKeyword = function() { pos = (pos + 1);
return makeKeyword(readIdent()); };
var readNumber = function() { return (function() {
var start = pos;
if (isSxTruthy((isSxTruthy((pos < lenSrc)) && (nth(source, pos) == "-")))) {
pos = (pos + 1);
}
var readDigits = function() { while(true) { if (isSxTruthy((isSxTruthy((pos < lenSrc)) && (function() {
var c = nth(source, pos);
return (isSxTruthy((c >= "0")) && (c <= "9"));
})()))) { pos = (pos + 1);
continue; } else { return NIL; } } };
readDigits();
if (isSxTruthy((isSxTruthy((pos < lenSrc)) && (nth(source, pos) == ".")))) {
pos = (pos + 1);
readDigits();
}
if (isSxTruthy((isSxTruthy((pos < lenSrc)) && sxOr((nth(source, pos) == "e"), (nth(source, pos) == "E"))))) {
pos = (pos + 1);
if (isSxTruthy((isSxTruthy((pos < lenSrc)) && sxOr((nth(source, pos) == "+"), (nth(source, pos) == "-"))))) {
pos = (pos + 1);
}
readDigits();
}
return parseNumber(slice(source, start, pos));
})(); };
var readSymbol = function() { return (function() {
var name = readIdent();
return (isSxTruthy((name == "true")) ? true : (isSxTruthy((name == "false")) ? false : (isSxTruthy((name == "nil")) ? NIL : makeSymbol(name))));
})(); };
var readList = function(closeCh) { return (function() {
var items = [];
var readListLoop = function() { while(true) { skipWs();
if (isSxTruthy((pos >= lenSrc))) { return error("Unterminated list"); } else { if (isSxTruthy((nth(source, pos) == closeCh))) { pos = (pos + 1);
return NIL; } else { items.push(readExpr());
continue; } } } };
readListLoop();
return items;
})(); };
var readMap = function() { return (function() {
var result = {};
var readMapLoop = function() { while(true) { skipWs();
if (isSxTruthy((pos >= lenSrc))) { return error("Unterminated map"); } else { if (isSxTruthy((nth(source, pos) == "}"))) { pos = (pos + 1);
return NIL; } else { { var keyExpr = readExpr();
var keyStr = (isSxTruthy((typeOf(keyExpr) == "keyword")) ? keywordName(keyExpr) : (String(keyExpr)));
var valExpr = readExpr();
result[keyStr] = valExpr;
continue; } } } } };
readMapLoop();
return result;
})(); };
var readExpr = function() { skipWs();
return (isSxTruthy((pos >= lenSrc)) ? error("Unexpected end of input") : (function() {
var ch = nth(source, pos);
return (isSxTruthy((ch == "(")) ? ((pos = (pos + 1)), readList(")")) : (isSxTruthy((ch == "[")) ? ((pos = (pos + 1)), readList("]")) : (isSxTruthy((ch == "{")) ? ((pos = (pos + 1)), readMap()) : (isSxTruthy((ch == "\"")) ? readString() : (isSxTruthy((ch == ":")) ? readKeyword() : (isSxTruthy((ch == "`")) ? ((pos = (pos + 1)), [makeSymbol("quasiquote"), readExpr()]) : (isSxTruthy((ch == ",")) ? ((pos = (pos + 1)), (isSxTruthy((isSxTruthy((pos < lenSrc)) && (nth(source, pos) == "@"))) ? ((pos = (pos + 1)), [makeSymbol("splice-unquote"), readExpr()]) : [makeSymbol("unquote"), readExpr()])) : (isSxTruthy(sxOr((isSxTruthy((ch >= "0")) && (ch <= "9")), (isSxTruthy((ch == "-")) && isSxTruthy(((pos + 1) < lenSrc)) && (function() {
var nextCh = nth(source, (pos + 1));
return (isSxTruthy((nextCh >= "0")) && (nextCh <= "9"));
})()))) ? readNumber() : (isSxTruthy((isSxTruthy((ch == ".")) && isSxTruthy(((pos + 2) < lenSrc)) && isSxTruthy((nth(source, (pos + 1)) == ".")) && (nth(source, (pos + 2)) == "."))) ? ((pos = (pos + 3)), makeSymbol("...")) : (isSxTruthy(isIdentStart(ch)) ? readSymbol() : error((String("Unexpected character: ") + String(ch)))))))))))));
})()); };
return (function() {
var exprs = [];
var parseLoop = function() { while(true) { skipWs();
if (isSxTruthy((pos < lenSrc))) { exprs.push(readExpr());
continue; } else { return NIL; } } };
parseLoop();
return exprs;
})();
})(); };
// sx-serialize
var sxSerialize = function(val) { return (function() { var _m = typeOf(val); if (_m == "nil") return "nil"; if (_m == "boolean") return (isSxTruthy(val) ? "true" : "false"); if (_m == "number") return (String(val)); if (_m == "string") return (String("\"") + String(escapeString(val)) + String("\"")); if (_m == "symbol") return symbolName(val); if (_m == "keyword") return (String(":") + String(keywordName(val))); if (_m == "list") return (String("(") + String(join(" ", map(sxSerialize, val))) + String(")")); if (_m == "dict") return sxSerializeDict(val); if (_m == "sx-expr") return sxExprSource(val); return (String(val)); })(); };
// sx-serialize-dict
var sxSerializeDict = function(d) { return (String("{") + String(join(" ", reduce(function(acc, key) { return concat(acc, [(String(":") + String(key)), sxSerialize(dictGet(d, key))]); }, [], keys(d)))) + String("}")); };
// === Transpiled from adapter-html ===
// render-to-html
var renderToHtml = function(expr, env) { return (function() { var _m = typeOf(expr); if (_m == "nil") return ""; if (_m == "string") return escapeHtml(expr); if (_m == "number") return (String(expr)); if (_m == "boolean") return (isSxTruthy(expr) ? "true" : "false"); if (_m == "list") return (isSxTruthy(isEmpty(expr)) ? "" : renderListToHtml(expr, env)); if (_m == "symbol") return renderValueToHtml(trampoline(evalExpr(expr, env)), env); if (_m == "keyword") return escapeHtml(keywordName(expr)); if (_m == "raw-html") return rawHtmlContent(expr); return renderValueToHtml(trampoline(evalExpr(expr, env)), env); })(); };
// render-value-to-html
var renderValueToHtml = function(val, env) { return (function() { var _m = typeOf(val); if (_m == "nil") return ""; if (_m == "string") return escapeHtml(val); if (_m == "number") return (String(val)); if (_m == "boolean") return (isSxTruthy(val) ? "true" : "false"); if (_m == "list") return renderListToHtml(val, env); if (_m == "raw-html") return rawHtmlContent(val); if (_m == "style-value") return styleValueClass(val); return escapeHtml((String(val))); })(); };
// RENDER_HTML_FORMS
var RENDER_HTML_FORMS = ["if", "when", "cond", "case", "let", "let*", "begin", "do", "define", "defcomp", "defmacro", "defstyle", "defkeyframes", "defhandler", "map", "map-indexed", "filter", "for-each"];
// render-html-form?
var isRenderHtmlForm = function(name) { return contains(RENDER_HTML_FORMS, name); };
// render-list-to-html
var renderListToHtml = function(expr, env) { return (isSxTruthy(isEmpty(expr)) ? "" : (function() {
var head = first(expr);
return (isSxTruthy(!isSxTruthy((typeOf(head) == "symbol"))) ? join("", map(function(x) { return renderValueToHtml(x, env); }, expr)) : (function() {
var name = symbolName(head);
var args = rest(expr);
return (isSxTruthy((name == "<>")) ? join("", map(function(x) { return renderToHtml(x, env); }, args)) : (isSxTruthy((name == "raw!")) ? join("", map(function(x) { return (String(trampoline(evalExpr(x, env)))); }, args)) : (isSxTruthy(contains(HTML_TAGS, name)) ? renderHtmlElement(name, args, env) : (isSxTruthy(startsWith(name, "~")) ? (function() {
var val = envGet(env, name);
return (isSxTruthy(isComponent(val)) ? renderHtmlComponent(val, args, env) : (isSxTruthy(isMacro(val)) ? renderToHtml(expandMacro(val, args, env), env) : error((String("Unknown component: ") + String(name)))));
})() : (isSxTruthy(isRenderHtmlForm(name)) ? dispatchHtmlForm(name, expr, env) : (isSxTruthy((isSxTruthy(envHas(env, name)) && isMacro(envGet(env, name)))) ? renderToHtml(expandMacro(envGet(env, name), args, env), env) : renderValueToHtml(trampoline(evalExpr(expr, env)), env)))))));
})());
})()); };
// dispatch-html-form
var dispatchHtmlForm = function(name, expr, env) { return (isSxTruthy((name == "if")) ? (function() {
var condVal = trampoline(evalExpr(nth(expr, 1), env));
return (isSxTruthy(condVal) ? renderToHtml(nth(expr, 2), env) : (isSxTruthy((len(expr) > 3)) ? renderToHtml(nth(expr, 3), env) : ""));
})() : (isSxTruthy((name == "when")) ? (isSxTruthy(!isSxTruthy(trampoline(evalExpr(nth(expr, 1), env)))) ? "" : join("", map(function(i) { return renderToHtml(nth(expr, i), env); }, range(2, len(expr))))) : (isSxTruthy((name == "cond")) ? (function() {
var branch = evalCond(rest(expr), env);
return (isSxTruthy(branch) ? renderToHtml(branch, env) : "");
})() : (isSxTruthy((name == "case")) ? renderToHtml(trampoline(evalExpr(expr, env)), env) : (isSxTruthy(sxOr((name == "let"), (name == "let*"))) ? (function() {
var local = processBindings(nth(expr, 1), env);
return join("", map(function(i) { return renderToHtml(nth(expr, i), local); }, range(2, len(expr))));
})() : (isSxTruthy(sxOr((name == "begin"), (name == "do"))) ? join("", map(function(i) { return renderToHtml(nth(expr, i), env); }, range(1, len(expr)))) : (isSxTruthy(isDefinitionForm(name)) ? (trampoline(evalExpr(expr, env)), "") : (isSxTruthy((name == "map")) ? (function() {
var f = trampoline(evalExpr(nth(expr, 1), env));
var coll = trampoline(evalExpr(nth(expr, 2), env));
return join("", map(function(item) { return (isSxTruthy(isLambda(f)) ? renderLambdaHtml(f, [item], env) : renderToHtml(apply(f, [item]), env)); }, coll));
})() : (isSxTruthy((name == "map-indexed")) ? (function() {
var f = trampoline(evalExpr(nth(expr, 1), env));
var coll = trampoline(evalExpr(nth(expr, 2), env));
return join("", mapIndexed(function(i, item) { return (isSxTruthy(isLambda(f)) ? renderLambdaHtml(f, [i, item], env) : renderToHtml(apply(f, [i, item]), env)); }, coll));
})() : (isSxTruthy((name == "filter")) ? renderToHtml(trampoline(evalExpr(expr, env)), env) : (isSxTruthy((name == "for-each")) ? (function() {
var f = trampoline(evalExpr(nth(expr, 1), env));
var coll = trampoline(evalExpr(nth(expr, 2), env));
return join("", map(function(item) { return (isSxTruthy(isLambda(f)) ? renderLambdaHtml(f, [item], env) : renderToHtml(apply(f, [item]), env)); }, coll));
})() : renderValueToHtml(trampoline(evalExpr(expr, env)), env)))))))))))); };
// render-lambda-html
var renderLambdaHtml = function(f, args, env) { return (function() {
var local = envMerge(lambdaClosure(f), env);
forEachIndexed(function(i, p) { return envSet(local, p, nth(args, i)); }, lambdaParams(f));
return renderToHtml(lambdaBody(f), local);
})(); };
// render-html-component
var renderHtmlComponent = function(comp, args, env) { return (function() {
var kwargs = {};
var children = [];
reduce(function(state, arg) { return (function() {
var skip = get(state, "skip");
return (isSxTruthy(skip) ? assoc(state, "skip", false, "i", (get(state, "i") + 1)) : (isSxTruthy((isSxTruthy((typeOf(arg) == "keyword")) && ((get(state, "i") + 1) < len(args)))) ? (function() {
var val = trampoline(evalExpr(nth(args, (get(state, "i") + 1)), env));
kwargs[keywordName(arg)] = val;
return assoc(state, "skip", true, "i", (get(state, "i") + 1));
})() : (append_b(children, arg), assoc(state, "i", (get(state, "i") + 1)))));
})(); }, {["i"]: 0, ["skip"]: false}, args);
return (function() {
var local = envMerge(componentClosure(comp), env);
{ var _c = componentParams(comp); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; local[p] = (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL); } }
if (isSxTruthy(componentHasChildren(comp))) {
local["children"] = makeRawHtml(join("", map(function(c) { return renderToHtml(c, env); }, children)));
}
return renderToHtml(componentBody(comp), local);
})();
})(); };
// render-html-element
var renderHtmlElement = function(tag, args, env) { return (function() {
var parsed = parseElementArgs(args, env);
var attrs = first(parsed);
var children = nth(parsed, 1);
var isVoid = contains(VOID_ELEMENTS, tag);
return (String("<") + String(tag) + String(renderAttrs(attrs)) + String((isSxTruthy(isVoid) ? " />" : (String(">") + String(join("", map(function(c) { return renderToHtml(c, env); }, children))) + String("</") + String(tag) + String(">")))));
})(); };
// === Transpiled from adapter-sx ===
// render-to-sx
var renderToSx = function(expr, env) { return (function() {
var result = aser(expr, env);
return (isSxTruthy((typeOf(result) == "string")) ? result : serialize(result));
})(); };
// aser
var aser = function(expr, env) { return (function() { var _m = typeOf(expr); if (_m == "number") return expr; if (_m == "string") return expr; if (_m == "boolean") return expr; if (_m == "nil") return NIL; if (_m == "symbol") return (function() {
var name = symbolName(expr);
return (isSxTruthy(envHas(env, name)) ? envGet(env, name) : (isSxTruthy(isPrimitive(name)) ? getPrimitive(name) : (isSxTruthy((name == "true")) ? true : (isSxTruthy((name == "false")) ? false : (isSxTruthy((name == "nil")) ? NIL : error((String("Undefined symbol: ") + String(name))))))));
})(); if (_m == "keyword") return keywordName(expr); if (_m == "list") return (isSxTruthy(isEmpty(expr)) ? [] : aserList(expr, env)); return expr; })(); };
// aser-list
var aserList = function(expr, env) { return (function() {
var head = first(expr);
var args = rest(expr);
return (isSxTruthy(!isSxTruthy((typeOf(head) == "symbol"))) ? map(function(x) { return aser(x, env); }, expr) : (function() {
var name = symbolName(head);
return (isSxTruthy((name == "<>")) ? aserFragment(args, env) : (isSxTruthy(startsWith(name, "~")) ? aserCall(name, args, env) : (isSxTruthy(contains(HTML_TAGS, name)) ? aserCall(name, args, env) : (isSxTruthy(sxOr(isSpecialForm(name), isHoForm(name))) ? aserSpecial(name, expr, env) : (isSxTruthy((isSxTruthy(envHas(env, name)) && isMacro(envGet(env, name)))) ? aser(expandMacro(envGet(env, name), args, env), env) : (function() {
var f = trampoline(evalExpr(head, env));
var evaledArgs = map(function(a) { return trampoline(evalExpr(a, env)); }, args);
return (isSxTruthy((isSxTruthy(isCallable(f)) && isSxTruthy(!isSxTruthy(isLambda(f))) && !isSxTruthy(isComponent(f)))) ? apply(f, evaledArgs) : (isSxTruthy(isLambda(f)) ? trampoline(callLambda(f, evaledArgs, env)) : (isSxTruthy(isComponent(f)) ? aserCall((String("~") + String(componentName(f))), args, env) : error((String("Not callable: ") + String(inspect(f)))))));
})())))));
})());
})(); };
// aser-fragment
var aserFragment = function(children, env) { return (function() {
var parts = filter(function(x) { return !isSxTruthy(isNil(x)); }, map(function(c) { return aser(c, env); }, children));
return (isSxTruthy(isEmpty(parts)) ? "" : (String("(<> ") + String(join(" ", map(serialize, parts))) + String(")")));
})(); };
// aser-call
var aserCall = function(name, args, env) { return (function() {
var parts = [name];
reduce(function(state, arg) { return (function() {
var skip = get(state, "skip");
return (isSxTruthy(skip) ? assoc(state, "skip", false, "i", (get(state, "i") + 1)) : (isSxTruthy((isSxTruthy((typeOf(arg) == "keyword")) && ((get(state, "i") + 1) < len(args)))) ? (function() {
var val = aser(nth(args, (get(state, "i") + 1)), env);
if (isSxTruthy(!isSxTruthy(isNil(val)))) {
parts.push((String(":") + String(keywordName(arg))));
parts.push(serialize(val));
}
return assoc(state, "skip", true, "i", (get(state, "i") + 1));
})() : (function() {
var val = aser(arg, env);
if (isSxTruthy(!isSxTruthy(isNil(val)))) {
parts.push(serialize(val));
}
return assoc(state, "i", (get(state, "i") + 1));
})()));
})(); }, {["i"]: 0, ["skip"]: false}, args);
return (String("(") + String(join(" ", parts)) + String(")"));
})(); };
// === Transpiled from adapter-dom ===
// SVG_NS
var SVG_NS = "http://www.w3.org/2000/svg";
// MATH_NS
var MATH_NS = "http://www.w3.org/1998/Math/MathML";
// render-to-dom
var renderToDom = function(expr, env, ns) { return (function() { var _m = typeOf(expr); if (_m == "nil") return createFragment(); if (_m == "boolean") return createFragment(); if (_m == "raw-html") return domParseHtml(rawHtmlContent(expr)); if (_m == "string") return createTextNode(expr); if (_m == "number") return createTextNode((String(expr))); if (_m == "symbol") return renderToDom(trampoline(evalExpr(expr, env)), env, ns); if (_m == "keyword") return createTextNode(keywordName(expr)); if (_m == "dom-node") return expr; if (_m == "dict") return createFragment(); if (_m == "list") return (isSxTruthy(isEmpty(expr)) ? createFragment() : renderDomList(expr, env, ns)); if (_m == "style-value") return createTextNode(styleValueClass(expr)); return createTextNode((String(expr))); })(); };
// render-dom-list
var renderDomList = function(expr, env, ns) { return (function() {
var head = first(expr);
return (isSxTruthy((typeOf(head) == "symbol")) ? (function() {
var name = symbolName(head);
var args = rest(expr);
return (isSxTruthy((name == "raw!")) ? renderDomRaw(args, env) : (isSxTruthy((name == "<>")) ? renderDomFragment(args, env, ns) : (isSxTruthy(startsWith(name, "html:")) ? renderDomElement(slice(name, 5), args, env, ns) : (isSxTruthy(isRenderDomForm(name)) ? (isSxTruthy((isSxTruthy(contains(HTML_TAGS, name)) && sxOr((isSxTruthy((len(args) > 0)) && (typeOf(first(args)) == "keyword")), ns))) ? renderDomElement(name, args, env, ns) : dispatchRenderForm(name, expr, env, ns)) : (isSxTruthy((isSxTruthy(envHas(env, name)) && isMacro(envGet(env, name)))) ? renderToDom(expandMacro(envGet(env, name), args, env), env, ns) : (isSxTruthy(contains(HTML_TAGS, name)) ? renderDomElement(name, args, env, ns) : (isSxTruthy(startsWith(name, "~")) ? (function() {
var comp = envGet(env, name);
return (isSxTruthy(isComponent(comp)) ? renderDomComponent(comp, args, env, ns) : renderDomUnknownComponent(name));
})() : (isSxTruthy((isSxTruthy((indexOf_(name, "-") > 0)) && isSxTruthy((len(args) > 0)) && (typeOf(first(args)) == "keyword"))) ? renderDomElement(name, args, env, ns) : (isSxTruthy(ns) ? renderDomElement(name, args, env, ns) : renderToDom(trampoline(evalExpr(expr, env)), env, ns))))))))));
})() : (isSxTruthy(sxOr(isLambda(head), (typeOf(head) == "list"))) ? renderToDom(trampoline(evalExpr(expr, env)), env, ns) : (function() {
var frag = createFragment();
{ var _c = expr; for (var _i = 0; _i < _c.length; _i++) { var x = _c[_i]; domAppend(frag, renderToDom(x, env, ns)); } }
return frag;
})()));
})(); };
// render-dom-element
var renderDomElement = function(tag, args, env, ns) { return (function() {
var newNs = (isSxTruthy((tag == "svg")) ? SVG_NS : (isSxTruthy((tag == "math")) ? MATH_NS : ns));
var el = domCreateElement(tag, newNs);
var extraClass = NIL;
reduce(function(state, arg) { return (function() {
var skip = get(state, "skip");
return (isSxTruthy(skip) ? assoc(state, "skip", false, "i", (get(state, "i") + 1)) : (isSxTruthy((isSxTruthy((typeOf(arg) == "keyword")) && ((get(state, "i") + 1) < len(args)))) ? (function() {
var attrName = keywordName(arg);
var attrVal = trampoline(evalExpr(nth(args, (get(state, "i") + 1)), env));
(isSxTruthy(sxOr(isNil(attrVal), (attrVal == false))) ? NIL : (isSxTruthy((isSxTruthy((attrName == "style")) && isStyleValue(attrVal))) ? (extraClass = styleValueClass(attrVal)) : (isSxTruthy(contains(BOOLEAN_ATTRS, attrName)) ? (isSxTruthy(attrVal) ? domSetAttr(el, attrName, "") : NIL) : (isSxTruthy((attrVal == true)) ? domSetAttr(el, attrName, "") : domSetAttr(el, attrName, (String(attrVal)))))));
return assoc(state, "skip", true, "i", (get(state, "i") + 1));
})() : ((isSxTruthy(!isSxTruthy(contains(VOID_ELEMENTS, tag))) ? domAppend(el, renderToDom(arg, env, newNs)) : NIL), assoc(state, "i", (get(state, "i") + 1)))));
})(); }, {["i"]: 0, ["skip"]: false}, args);
if (isSxTruthy(extraClass)) {
(function() {
var existing = domGetAttr(el, "class");
return domSetAttr(el, "class", (isSxTruthy(existing) ? (String(existing) + String(" ") + String(extraClass)) : extraClass));
})();
}
return el;
})(); };
// render-dom-component
var renderDomComponent = function(comp, args, env, ns) { return (function() {
var kwargs = {};
var children = [];
reduce(function(state, arg) { return (function() {
var skip = get(state, "skip");
return (isSxTruthy(skip) ? assoc(state, "skip", false, "i", (get(state, "i") + 1)) : (isSxTruthy((isSxTruthy((typeOf(arg) == "keyword")) && ((get(state, "i") + 1) < len(args)))) ? (function() {
var val = trampoline(evalExpr(nth(args, (get(state, "i") + 1)), env));
kwargs[keywordName(arg)] = val;
return assoc(state, "skip", true, "i", (get(state, "i") + 1));
})() : (append_b(children, arg), assoc(state, "i", (get(state, "i") + 1)))));
})(); }, {["i"]: 0, ["skip"]: false}, args);
return (function() {
var local = envMerge(componentClosure(comp), env);
{ var _c = componentParams(comp); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; local[p] = (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL); } }
if (isSxTruthy(componentHasChildren(comp))) {
(function() {
var childFrag = createFragment();
{ var _c = children; for (var _i = 0; _i < _c.length; _i++) { var c = _c[_i]; domAppend(childFrag, renderToDom(c, env, ns)); } }
return envSet(local, "children", childFrag);
})();
}
return renderToDom(componentBody(comp), local, ns);
})();
})(); };
// render-dom-fragment
var renderDomFragment = function(args, env, ns) { return (function() {
var frag = createFragment();
{ var _c = args; for (var _i = 0; _i < _c.length; _i++) { var x = _c[_i]; domAppend(frag, renderToDom(x, env, ns)); } }
return frag;
})(); };
// render-dom-raw
var renderDomRaw = function(args, env) { return (function() {
var frag = createFragment();
{ var _c = args; for (var _i = 0; _i < _c.length; _i++) { var arg = _c[_i]; (function() {
var val = trampoline(evalExpr(arg, env));
return (isSxTruthy((typeOf(val) == "string")) ? domAppend(frag, domParseHtml(val)) : (isSxTruthy((typeOf(val) == "dom-node")) ? domAppend(frag, domClone(val)) : (isSxTruthy(!isSxTruthy(isNil(val))) ? domAppend(frag, createTextNode((String(val)))) : NIL)));
})(); } }
return frag;
})(); };
// render-dom-unknown-component
var renderDomUnknownComponent = function(name) { return error((String("Unknown component: ") + String(name))); };
// RENDER_DOM_FORMS
var RENDER_DOM_FORMS = ["if", "when", "cond", "case", "let", "let*", "begin", "do", "define", "defcomp", "defmacro", "defstyle", "defkeyframes", "defhandler", "map", "map-indexed", "filter", "for-each"];
// render-dom-form?
var isRenderDomForm = function(name) { return contains(RENDER_DOM_FORMS, name); };
// dispatch-render-form
var dispatchRenderForm = function(name, expr, env, ns) { return (isSxTruthy((name == "if")) ? (function() {
var condVal = trampoline(evalExpr(nth(expr, 1), env));
return (isSxTruthy(condVal) ? renderToDom(nth(expr, 2), env, ns) : (isSxTruthy((len(expr) > 3)) ? renderToDom(nth(expr, 3), env, ns) : createFragment()));
})() : (isSxTruthy((name == "when")) ? (isSxTruthy(!isSxTruthy(trampoline(evalExpr(nth(expr, 1), env)))) ? createFragment() : (function() {
var frag = createFragment();
{ var _c = range(2, len(expr)); for (var _i = 0; _i < _c.length; _i++) { var i = _c[_i]; domAppend(frag, renderToDom(nth(expr, i), env, ns)); } }
return frag;
})()) : (isSxTruthy((name == "cond")) ? (function() {
var branch = evalCond(rest(expr), env);
return (isSxTruthy(branch) ? renderToDom(branch, env, ns) : createFragment());
})() : (isSxTruthy((name == "case")) ? renderToDom(trampoline(evalExpr(expr, env)), env, ns) : (isSxTruthy(sxOr((name == "let"), (name == "let*"))) ? (function() {
var local = processBindings(nth(expr, 1), env);
var frag = createFragment();
{ var _c = range(2, len(expr)); for (var _i = 0; _i < _c.length; _i++) { var i = _c[_i]; domAppend(frag, renderToDom(nth(expr, i), local, ns)); } }
return frag;
})() : (isSxTruthy(sxOr((name == "begin"), (name == "do"))) ? (function() {
var frag = createFragment();
{ var _c = range(1, len(expr)); for (var _i = 0; _i < _c.length; _i++) { var i = _c[_i]; domAppend(frag, renderToDom(nth(expr, i), env, ns)); } }
return frag;
})() : (isSxTruthy(isDefinitionForm(name)) ? (trampoline(evalExpr(expr, env)), createFragment()) : (isSxTruthy((name == "map")) ? (function() {
var f = trampoline(evalExpr(nth(expr, 1), env));
var coll = trampoline(evalExpr(nth(expr, 2), env));
var frag = createFragment();
{ var _c = coll; for (var _i = 0; _i < _c.length; _i++) { var item = _c[_i]; (function() {
var val = (isSxTruthy(isLambda(f)) ? renderLambdaDom(f, [item], env, ns) : renderToDom(apply(f, [item]), env, ns));
return domAppend(frag, val);
})(); } }
return frag;
})() : (isSxTruthy((name == "map-indexed")) ? (function() {
var f = trampoline(evalExpr(nth(expr, 1), env));
var coll = trampoline(evalExpr(nth(expr, 2), env));
var frag = createFragment();
forEachIndexed(function(i, item) { return (function() {
var val = (isSxTruthy(isLambda(f)) ? renderLambdaDom(f, [i, item], env, ns) : renderToDom(apply(f, [i, item]), env, ns));
return domAppend(frag, val);
})(); }, coll);
return frag;
})() : (isSxTruthy((name == "filter")) ? renderToDom(trampoline(evalExpr(expr, env)), env, ns) : (isSxTruthy((name == "for-each")) ? (function() {
var f = trampoline(evalExpr(nth(expr, 1), env));
var coll = trampoline(evalExpr(nth(expr, 2), env));
var frag = createFragment();
{ var _c = coll; for (var _i = 0; _i < _c.length; _i++) { var item = _c[_i]; (function() {
var val = (isSxTruthy(isLambda(f)) ? renderLambdaDom(f, [item], env, ns) : renderToDom(apply(f, [item]), env, ns));
return domAppend(frag, val);
})(); } }
return frag;
})() : renderToDom(trampoline(evalExpr(expr, env)), env, ns)))))))))))); };
// render-lambda-dom
var renderLambdaDom = function(f, args, env, ns) { return (function() {
var local = envMerge(lambdaClosure(f), env);
forEachIndexed(function(i, p) { return envSet(local, p, nth(args, i)); }, lambdaParams(f));
return renderToDom(lambdaBody(f), local, ns);
})(); };
// === Transpiled from engine ===
// ENGINE_VERBS
var ENGINE_VERBS = ["get", "post", "put", "delete", "patch"];
// DEFAULT_SWAP
var DEFAULT_SWAP = "outerHTML";
// parse-time
var parseTime = function(s) { return (isSxTruthy(isNil(s)) ? 0 : (isSxTruthy(endsWith(s, "ms")) ? parseInt_(s, 0) : (isSxTruthy(endsWith(s, "s")) ? (parseInt_(replace_(s, "s", ""), 0) * 1000) : parseInt_(s, 0)))); };
// parse-trigger-spec
var parseTriggerSpec = function(spec) { return (isSxTruthy(isNil(spec)) ? NIL : (function() {
var rawParts = split(spec, ",");
return filter(function(x) { return !isSxTruthy(isNil(x)); }, map(function(part) { return (function() {
var tokens = split(trim(part), " ");
return (isSxTruthy(isEmpty(tokens)) ? NIL : (isSxTruthy((isSxTruthy((first(tokens) == "every")) && (len(tokens) >= 2))) ? {["event"]: "every", ["modifiers"]: {["interval"]: parseTime(nth(tokens, 1))}} : (function() {
var mods = {};
{ var _c = rest(tokens); for (var _i = 0; _i < _c.length; _i++) { var tok = _c[_i]; (isSxTruthy((tok == "once")) ? dictSet(mods, "once", true) : (isSxTruthy((tok == "changed")) ? dictSet(mods, "changed", true) : (isSxTruthy(startsWith(tok, "delay:")) ? dictSet(mods, "delay", parseTime(slice(tok, 6))) : (isSxTruthy(startsWith(tok, "from:")) ? dictSet(mods, "from", slice(tok, 5)) : NIL)))); } }
return {["event"]: first(tokens), ["modifiers"]: mods};
})()));
})(); }, rawParts));
})()); };
// default-trigger
var defaultTrigger = function(tagName) { return (isSxTruthy((tagName == "FORM")) ? [{["event"]: "submit", ["modifiers"]: {}}] : (isSxTruthy(sxOr((tagName == "INPUT"), (tagName == "SELECT"), (tagName == "TEXTAREA"))) ? [{["event"]: "change", ["modifiers"]: {}}] : [{["event"]: "click", ["modifiers"]: {}}])); };
// get-verb-info
var getVerbInfo = function(el) { return some(function(verb) { return (function() {
var url = domGetAttr(el, (String("sx-") + String(verb)));
return (isSxTruthy(url) ? {["method"]: upper(verb), ["url"]: url} : NIL);
})(); }, ENGINE_VERBS); };
// build-request-headers
var buildRequestHeaders = function(el, loadedComponents, cssHash) { return (function() {
var headers = {["SX-Request"]: "true", ["SX-Current-URL"]: browserLocationHref()};
(function() {
var targetSel = domGetAttr(el, "sx-target");
return (isSxTruthy(targetSel) ? dictSet(headers, "SX-Target", targetSel) : NIL);
})();
if (isSxTruthy(!isSxTruthy(isEmpty(loadedComponents)))) {
headers["SX-Components"] = join(",", loadedComponents);
}
if (isSxTruthy(cssHash)) {
headers["SX-Css"] = cssHash;
}
(function() {
var extraH = domGetAttr(el, "sx-headers");
return (isSxTruthy(extraH) ? (function() {
var parsed = parseHeaderValue(extraH);
return (isSxTruthy(parsed) ? forEach(function(key) { return dictSet(headers, key, (String(get(parsed, key)))); }, keys(parsed)) : NIL);
})() : NIL);
})();
return headers;
})(); };
// process-response-headers
var processResponseHeaders = function(getHeader) { return {["redirect"]: getHeader("SX-Redirect"), ["refresh"]: getHeader("SX-Refresh"), ["trigger"]: getHeader("SX-Trigger"), ["retarget"]: getHeader("SX-Retarget"), ["reswap"]: getHeader("SX-Reswap"), ["location"]: getHeader("SX-Location"), ["replace-url"]: getHeader("SX-Replace-Url"), ["css-hash"]: getHeader("SX-Css-Hash"), ["trigger-swap"]: getHeader("SX-Trigger-After-Swap"), ["trigger-settle"]: getHeader("SX-Trigger-After-Settle"), ["content-type"]: getHeader("Content-Type")}; };
// parse-swap-spec
var parseSwapSpec = function(rawSwap, globalTransitions_p) { return (function() {
var parts = split(sxOr(rawSwap, DEFAULT_SWAP), " ");
var style = first(parts);
var useTransition = globalTransitions_p;
{ var _c = rest(parts); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; (isSxTruthy((p == "transition:true")) ? (useTransition = true) : (isSxTruthy((p == "transition:false")) ? (useTransition = false) : NIL)); } }
return {["style"]: style, ["transition"]: useTransition};
})(); };
// parse-retry-spec
var parseRetrySpec = function(retryAttr) { return (isSxTruthy(isNil(retryAttr)) ? NIL : (function() {
var parts = split(retryAttr, ":");
return {["strategy"]: first(parts), ["start-ms"]: parseInt_(nth(parts, 1), 1000), ["cap-ms"]: parseInt_(nth(parts, 2), 30000)};
})()); };
// next-retry-ms
var nextRetryMs = function(currentMs, capMs) { return min((currentMs * 2), capMs); };
// filter-params
var filterParams = function(paramsSpec, allParams) { return (isSxTruthy(isNil(paramsSpec)) ? allParams : (isSxTruthy((paramsSpec == "none")) ? [] : (isSxTruthy((paramsSpec == "*")) ? allParams : (isSxTruthy(startsWith(paramsSpec, "not ")) ? (function() {
var excluded = map(trim, split(slice(paramsSpec, 4), ","));
return filter(function(p) { return !isSxTruthy(contains(excluded, first(p))); }, allParams);
})() : (function() {
var allowed = map(trim, split(paramsSpec, ","));
return filter(function(p) { return contains(allowed, first(p)); }, allParams);
})())))); };
// resolve-target
var resolveTarget = function(el) { return (function() {
var sel = domGetAttr(el, "sx-target");
return (isSxTruthy(sxOr(isNil(sel), (sel == "this"))) ? el : (isSxTruthy((sel == "closest")) ? domParent(el) : domQuery(sel)));
})(); };
// apply-optimistic
var applyOptimistic = function(el) { return (function() {
var directive = domGetAttr(el, "sx-optimistic");
return (isSxTruthy(isNil(directive)) ? NIL : (function() {
var target = sxOr(resolveTarget(el), el);
var state = {["target"]: target, ["directive"]: directive};
(isSxTruthy((directive == "remove")) ? (dictSet(state, "opacity", domGetStyle(target, "opacity")), domSetStyle(target, "opacity", "0"), domSetStyle(target, "pointer-events", "none")) : (isSxTruthy((directive == "disable")) ? (dictSet(state, "disabled", domGetProp(target, "disabled")), domSetProp(target, "disabled", true)) : (isSxTruthy(startsWith(directive, "add-class:")) ? (function() {
var cls = slice(directive, 10);
state["add-class"] = cls;
return domAddClass(target, cls);
})() : NIL)));
return state;
})());
})(); };
// revert-optimistic
var revertOptimistic = function(state) { return (isSxTruthy(state) ? (function() {
var target = get(state, "target");
var directive = get(state, "directive");
return (isSxTruthy((directive == "remove")) ? (domSetStyle(target, "opacity", sxOr(get(state, "opacity"), "")), domSetStyle(target, "pointer-events", "")) : (isSxTruthy((directive == "disable")) ? domSetProp(target, "disabled", sxOr(get(state, "disabled"), false)) : (isSxTruthy(get(state, "add-class")) ? domRemoveClass(target, get(state, "add-class")) : NIL)));
})() : NIL); };
// find-oob-swaps
var findOobSwaps = function(container) { return (function() {
var results = [];
{ var _c = ["sx-swap-oob", "hx-swap-oob"]; for (var _i = 0; _i < _c.length; _i++) { var attr = _c[_i]; (function() {
var oobEls = domQueryAll(container, (String("[") + String(attr) + String("]")));
return forEach(function(oob) { return (function() {
var swapType = sxOr(domGetAttr(oob, attr), "outerHTML");
var targetId = domId(oob);
domRemoveAttr(oob, attr);
return (isSxTruthy(targetId) ? append_b(results, {["element"]: oob, ["swap-type"]: swapType, ["target-id"]: targetId}) : NIL);
})(); }, oobEls);
})(); } }
return results;
})(); };
// morph-node
var morphNode = function(oldNode, newNode) { return (isSxTruthy(sxOr(domHasAttr(oldNode, "sx-preserve"), domHasAttr(oldNode, "sx-ignore"))) ? NIL : (isSxTruthy(sxOr(!isSxTruthy((domNodeType(oldNode) == domNodeType(newNode))), !isSxTruthy((domNodeName(oldNode) == domNodeName(newNode))))) ? domReplaceChild(domParent(oldNode), domClone(newNode), oldNode) : (isSxTruthy(sxOr((domNodeType(oldNode) == 3), (domNodeType(oldNode) == 8))) ? (isSxTruthy(!isSxTruthy((domTextContent(oldNode) == domTextContent(newNode)))) ? domSetTextContent(oldNode, domTextContent(newNode)) : NIL) : (isSxTruthy((domNodeType(oldNode) == 1)) ? (syncAttrs(oldNode, newNode), (isSxTruthy(!isSxTruthy((isSxTruthy(domIsActiveElement(oldNode)) && domIsInputElement(oldNode)))) ? morphChildren(oldNode, newNode) : NIL)) : NIL)))); };
// sync-attrs
var syncAttrs = function(oldEl, newEl) { { var _c = domAttrList(newEl); for (var _i = 0; _i < _c.length; _i++) { var attr = _c[_i]; (function() {
var name = first(attr);
var val = nth(attr, 1);
return (isSxTruthy(!isSxTruthy((domGetAttr(oldEl, name) == val))) ? domSetAttr(oldEl, name, val) : NIL);
})(); } }
return forEach(function(attr) { return (isSxTruthy(!isSxTruthy(domHasAttr(newEl, first(attr)))) ? domRemoveAttr(oldEl, first(attr)) : NIL); }, domAttrList(oldEl)); };
// morph-children
var morphChildren = function(oldParent, newParent) { return (function() {
var oldKids = domChildList(oldParent);
var newKids = domChildList(newParent);
var oldById = reduce(function(acc, kid) { return (function() {
var id = domId(kid);
return (isSxTruthy(id) ? (dictSet(acc, id, kid), acc) : acc);
})(); }, {}, oldKids);
var oi = 0;
{ var _c = newKids; for (var _i = 0; _i < _c.length; _i++) { var newChild = _c[_i]; (function() {
var matchId = domId(newChild);
var matchById = (isSxTruthy(matchId) ? dictGet(oldById, matchId) : NIL);
return (isSxTruthy((isSxTruthy(matchById) && !isSxTruthy(isNil(matchById)))) ? ((isSxTruthy((isSxTruthy((oi < len(oldKids))) && !isSxTruthy((matchById == nth(oldKids, oi))))) ? domInsertBefore(oldParent, matchById, (isSxTruthy((oi < len(oldKids))) ? nth(oldKids, oi) : NIL)) : NIL), morphNode(matchById, newChild), (oi = (oi + 1))) : (isSxTruthy((oi < len(oldKids))) ? (function() {
var oldChild = nth(oldKids, oi);
return (isSxTruthy((isSxTruthy(domId(oldChild)) && !isSxTruthy(matchId))) ? domInsertBefore(oldParent, domClone(newChild), oldChild) : (morphNode(oldChild, newChild), (oi = (oi + 1))));
})() : domAppend(oldParent, domClone(newChild))));
})(); } }
return forEach(function(i) { return (isSxTruthy((i >= oi)) ? (function() {
var leftover = nth(oldKids, i);
return (isSxTruthy((isSxTruthy(domIsChildOf(leftover, oldParent)) && isSxTruthy(!isSxTruthy(domHasAttr(leftover, "sx-preserve"))) && !isSxTruthy(domHasAttr(leftover, "sx-ignore")))) ? domRemoveChild(oldParent, leftover) : NIL);
})() : NIL); }, range(oi, len(oldKids)));
})(); };
// swap-dom-nodes
var swapDomNodes = function(target, newNodes, strategy) { return (function() { var _m = strategy; if (_m == "innerHTML") return (isSxTruthy(domIsFragment(newNodes)) ? morphChildren(target, newNodes) : (function() {
var wrapper = domCreateElement("div", NIL);
domAppend(wrapper, newNodes);
return morphChildren(target, wrapper);
})()); if (_m == "outerHTML") return (function() {
var parent = domParent(target);
(isSxTruthy(domIsFragment(newNodes)) ? (function() {
var fc = domFirstChild(newNodes);
return (isSxTruthy(fc) ? (morphNode(target, fc), (function() {
var sib = domNextSibling(fc);
return insertRemainingSiblings(parent, target, sib);
})()) : domRemoveChild(parent, target));
})() : morphNode(target, newNodes));
return parent;
})(); if (_m == "afterend") return domInsertAfter(target, newNodes); if (_m == "beforeend") return domAppend(target, newNodes); if (_m == "afterbegin") return domPrepend(target, newNodes); if (_m == "beforebegin") return domInsertBefore(domParent(target), newNodes, target); if (_m == "delete") return domRemoveChild(domParent(target), target); if (_m == "none") return NIL; return (isSxTruthy(domIsFragment(newNodes)) ? morphChildren(target, newNodes) : (function() {
var wrapper = domCreateElement("div", NIL);
domAppend(wrapper, newNodes);
return morphChildren(target, wrapper);
})()); })(); };
// insert-remaining-siblings
var insertRemainingSiblings = function(parent, refNode, sib) { return (isSxTruthy(sib) ? (function() {
var next = domNextSibling(sib);
domInsertAfter(refNode, sib);
return insertRemainingSiblings(parent, sib, next);
})() : NIL); };
// swap-html-string
var swapHtmlString = function(target, html, strategy) { return (function() { var _m = strategy; if (_m == "innerHTML") return domSetInnerHtml(target, html); if (_m == "outerHTML") return (function() {
var parent = domParent(target);
domInsertAdjacentHtml(target, "afterend", html);
domRemoveChild(parent, target);
return parent;
})(); if (_m == "afterend") return domInsertAdjacentHtml(target, "afterend", html); if (_m == "beforeend") return domInsertAdjacentHtml(target, "beforeend", html); if (_m == "afterbegin") return domInsertAdjacentHtml(target, "afterbegin", html); if (_m == "beforebegin") return domInsertAdjacentHtml(target, "beforebegin", html); if (_m == "delete") return domRemoveChild(domParent(target), target); if (_m == "none") return NIL; return domSetInnerHtml(target, html); })(); };
// handle-history
var handleHistory = function(el, url, respHeaders) { return (function() {
var pushUrl = domGetAttr(el, "sx-push-url");
var replaceUrl = domGetAttr(el, "sx-replace-url");
var hdrReplace = get(respHeaders, "replace-url");
return (isSxTruthy(hdrReplace) ? browserReplaceState(hdrReplace) : (isSxTruthy((isSxTruthy(pushUrl) && !isSxTruthy((pushUrl == "false")))) ? browserPushState((isSxTruthy((pushUrl == "true")) ? url : pushUrl)) : (isSxTruthy((isSxTruthy(replaceUrl) && !isSxTruthy((replaceUrl == "false")))) ? browserReplaceState((isSxTruthy((replaceUrl == "true")) ? url : replaceUrl)) : NIL)));
})(); };
// PRELOAD_TTL
var PRELOAD_TTL = 30000;
// preload-cache-get
var preloadCacheGet = function(cache, url) { return (function() {
var entry = dictGet(cache, url);
return (isSxTruthy(isNil(entry)) ? NIL : (isSxTruthy(((nowMs() - get(entry, "timestamp")) > PRELOAD_TTL)) ? (dictDelete(cache, url), NIL) : (dictDelete(cache, url), entry)));
})(); };
// preload-cache-set
var preloadCacheSet = function(cache, url, text, contentType) { return dictSet(cache, url, {["text"]: text, ["content-type"]: contentType, ["timestamp"]: nowMs()}); };
// classify-trigger
var classifyTrigger = function(trigger) { return (function() {
var event = get(trigger, "event");
return (isSxTruthy((event == "every")) ? "poll" : (isSxTruthy((event == "intersect")) ? "intersect" : (isSxTruthy((event == "load")) ? "load" : (isSxTruthy((event == "revealed")) ? "revealed" : "event"))));
})(); };
// should-boost-link?
var shouldBoostLink = function(link) { return (function() {
var href = domGetAttr(link, "href");
return (isSxTruthy(href) && isSxTruthy(!isSxTruthy(startsWith(href, "#"))) && isSxTruthy(!isSxTruthy(startsWith(href, "javascript:"))) && isSxTruthy(!isSxTruthy(startsWith(href, "mailto:"))) && isSxTruthy(browserSameOrigin(href)) && isSxTruthy(!isSxTruthy(domHasAttr(link, "sx-get"))) && isSxTruthy(!isSxTruthy(domHasAttr(link, "sx-post"))) && !isSxTruthy(domHasAttr(link, "sx-disable")));
})(); };
// should-boost-form?
var shouldBoostForm = function(form) { return (isSxTruthy(!isSxTruthy(domHasAttr(form, "sx-get"))) && isSxTruthy(!isSxTruthy(domHasAttr(form, "sx-post"))) && !isSxTruthy(domHasAttr(form, "sx-disable"))); };
// parse-sse-swap
var parseSseSwap = function(el) { return sxOr(domGetAttr(el, "sx-sse-swap"), "message"); };
// === Transpiled from orchestration ===
// _preload-cache
var _preloadCache = {};
// _css-hash
var _cssHash = NIL;
// dispatch-trigger-events
var dispatchTriggerEvents = function(el, headerVal) { return (isSxTruthy(headerVal) ? (function() {
var parsed = tryParseJson(headerVal);
return (isSxTruthy(parsed) ? forEach(function(key) { return domDispatch(el, key, get(parsed, key)); }, keys(parsed)) : forEach(function(name) { return (function() {
var trimmed = trim(name);
return (isSxTruthy(!isSxTruthy(isEmpty(trimmed))) ? domDispatch(el, trimmed, {}) : NIL);
})(); }, split(headerVal, ",")));
})() : NIL); };
// init-css-tracking
var initCssTracking = function() { return (function() {
var meta = domQuery("meta[name=\"sx-css-classes\"]");
return (isSxTruthy(meta) ? (function() {
var content = domGetAttr(meta, "content");
return (isSxTruthy(content) ? (_cssHash = content) : NIL);
})() : NIL);
})(); };
// execute-request
var executeRequest = function(el, verbInfo, extraParams) { return (function() {
var info = sxOr(getVerbInfo(el), verbInfo);
return (isSxTruthy(isNil(info)) ? promiseResolve(NIL) : (function() {
var verb = get(info, "method");
var url = get(info, "url");
return (isSxTruthy((function() {
var media = domGetAttr(el, "sx-media");
return (isSxTruthy(media) && !isSxTruthy(browserMediaMatches(media)));
})()) ? promiseResolve(NIL) : (isSxTruthy((function() {
var confirmMsg = domGetAttr(el, "sx-confirm");
return (isSxTruthy(confirmMsg) && !isSxTruthy(browserConfirm(confirmMsg)));
})()) ? promiseResolve(NIL) : (function() {
var promptMsg = domGetAttr(el, "sx-prompt");
var promptVal = (isSxTruthy(promptMsg) ? browserPrompt(promptMsg) : NIL);
return (isSxTruthy((isSxTruthy(promptMsg) && isNil(promptVal))) ? promiseResolve(NIL) : (isSxTruthy(!isSxTruthy(validateForRequest(el))) ? promiseResolve(NIL) : doFetch(el, verb, verb, url, (isSxTruthy(promptVal) ? assoc(sxOr(extraParams, {}), "SX-Prompt", promptVal) : extraParams))));
})()));
})());
})(); };
// do-fetch
var doFetch = function(el, verb, method, url, extraParams) { return (function() {
var sync = domGetAttr(el, "sx-sync");
if (isSxTruthy((sync == "replace"))) {
abortPrevious(el);
}
return (function() {
var ctrl = newAbortController();
trackController(el, ctrl);
return (function() {
var bodyInfo = buildRequestBody(el, method, url);
var finalUrl = get(bodyInfo, "url");
var body = get(bodyInfo, "body");
var ct = get(bodyInfo, "content-type");
var headers = buildRequestHeaders(el, loadedComponentNames(), _cssHash);
var csrf = csrfToken();
if (isSxTruthy(extraParams)) {
{ var _c = keys(extraParams); for (var _i = 0; _i < _c.length; _i++) { var k = _c[_i]; headers[k] = get(extraParams, k); } }
}
if (isSxTruthy(ct)) {
headers["Content-Type"] = ct;
}
if (isSxTruthy(csrf)) {
headers["X-CSRFToken"] = csrf;
}
return (function() {
var cached = preloadCacheGet(_preloadCache, finalUrl);
var optimisticState = applyOptimistic(el);
var indicator = showIndicator(el);
var disabledElts = disableElements(el);
domAddClass(el, "sx-request");
domSetAttr(el, "aria-busy", "true");
domDispatch(el, "sx:beforeRequest", {["url"]: finalUrl, ["method"]: method});
return fetchRequest({["url"]: finalUrl, ["method"]: method, ["headers"]: headers, ["body"]: body, ["signal"]: controllerSignal(ctrl), ["cross-origin"]: isCrossOrigin(finalUrl), ["preloaded"]: cached}, function(respOk, status, getHeader, text) { return (clearLoadingState(el, indicator, disabledElts), revertOptimistic(optimisticState), (isSxTruthy(!isSxTruthy(respOk)) ? (domDispatch(el, "sx:responseError", {["status"]: status, ["text"]: text}), handleRetry(el, verb, method, finalUrl, extraParams)) : (domDispatch(el, "sx:afterRequest", {["status"]: status}), handleFetchSuccess(el, finalUrl, verb, extraParams, getHeader, text)))); }, function(err) { return (clearLoadingState(el, indicator, disabledElts), revertOptimistic(optimisticState), (isSxTruthy(!isSxTruthy(isAbortError(err))) ? domDispatch(el, "sx:requestError", {["error"]: err}) : NIL)); });
})();
})();
})();
})(); };
// handle-fetch-success
var handleFetchSuccess = function(el, url, verb, extraParams, getHeader, text) { return (function() {
var respHeaders = processResponseHeaders(getHeader);
(function() {
var newHash = get(respHeaders, "css-hash");
return (isSxTruthy(newHash) ? (_cssHash = newHash) : NIL);
})();
dispatchTriggerEvents(el, get(respHeaders, "trigger"));
return (isSxTruthy(get(respHeaders, "redirect")) ? browserNavigate(get(respHeaders, "redirect")) : (isSxTruthy(get(respHeaders, "refresh")) ? browserReload() : (isSxTruthy(get(respHeaders, "location")) ? fetchLocation(get(respHeaders, "location")) : (function() {
var targetEl = (isSxTruthy(get(respHeaders, "retarget")) ? domQuery(get(respHeaders, "retarget")) : resolveTarget(el));
var swapSpec = parseSwapSpec(sxOr(get(respHeaders, "reswap"), domGetAttr(el, "sx-swap")), domHasClass(domBody(), "sx-transitions"));
var swapStyle = get(swapSpec, "style");
var useTransition = get(swapSpec, "transition");
var ct = sxOr(get(respHeaders, "content-type"), "");
(isSxTruthy(contains(ct, "text/sx")) ? handleSxResponse(el, targetEl, text, swapStyle, useTransition) : handleHtmlResponse(el, targetEl, text, swapStyle, useTransition));
dispatchTriggerEvents(el, get(respHeaders, "trigger-swap"));
handleHistory(el, url, respHeaders);
if (isSxTruthy(get(respHeaders, "trigger-settle"))) {
setTimeout_(function() { return dispatchTriggerEvents(el, get(respHeaders, "trigger-settle")); }, 20);
}
return domDispatch(el, "sx:afterSwap", {["target"]: targetEl, ["swap"]: swapStyle});
})())));
})(); };
// handle-sx-response
var handleSxResponse = function(el, target, text, swapStyle, useTransition) { return (function() {
var cleaned = stripComponentScripts(text);
return (function() {
var final = extractResponseCss(cleaned);
return (function() {
var trimmed = trim(final);
return (isSxTruthy(!isSxTruthy(isEmpty(trimmed))) ? (function() {
var rendered = sxRender(trimmed);
var container = domCreateElement("div", NIL);
domAppend(container, rendered);
processOobSwaps(container, function(t, oob, s) { swapDomNodes(t, oob, s);
sxHydrate(t);
return processElements(t); });
return (function() {
var selectSel = domGetAttr(el, "sx-select");
var content = (isSxTruthy(selectSel) ? selectFromContainer(container, selectSel) : childrenToFragment(container));
return withTransition(useTransition, function() { swapDomNodes(target, content, swapStyle);
return postSwap(target); });
})();
})() : NIL);
})();
})();
})(); };
// handle-html-response
var handleHtmlResponse = function(el, target, text, swapStyle, useTransition) { return (function() {
var doc = domParseHtmlDocument(text);
return (isSxTruthy(doc) ? (function() {
var selectSel = domGetAttr(el, "sx-select");
return (isSxTruthy(selectSel) ? (function() {
var html = selectHtmlFromDoc(doc, selectSel);
return withTransition(useTransition, function() { swapHtmlString(target, html, swapStyle);
return postSwap(target); });
})() : (function() {
var container = domCreateElement("div", NIL);
domSetInnerHtml(container, domBodyInnerHtml(doc));
processOobSwaps(container, function(t, oob, s) { swapDomNodes(t, oob, s);
return postSwap(t); });
hoistHeadElements(container);
return withTransition(useTransition, function() { swapDomNodes(target, childrenToFragment(container), swapStyle);
return postSwap(target); });
})());
})() : NIL);
})(); };
// handle-retry
var handleRetry = function(el, verb, method, url, extraParams) { return (function() {
var retryAttr = domGetAttr(el, "sx-retry");
var spec = parseRetrySpec(retryAttr);
return (isSxTruthy(spec) ? (function() {
var currentMs = sxOr(domGetAttr(el, "data-sx-retry-ms"), get(spec, "start-ms"));
return (function() {
var ms = parseInt_(currentMs, get(spec, "start-ms"));
domSetAttr(el, "data-sx-retry-ms", (String(nextRetryMs(ms, get(spec, "cap-ms")))));
return setTimeout_(function() { return doFetch(el, verb, method, url, extraParams); }, ms);
})();
})() : NIL);
})(); };
// bind-triggers
var bindTriggers = function(el, verbInfo) { return (function() {
var triggers = sxOr(parseTriggerSpec(domGetAttr(el, "sx-trigger")), defaultTrigger(domTagName(el)));
return forEach(function(trigger) { return (function() {
var kind = classifyTrigger(trigger);
var mods = get(trigger, "modifiers");
return (isSxTruthy((kind == "poll")) ? setInterval_(function() { return executeRequest(el, NIL, NIL); }, get(mods, "interval")) : (isSxTruthy((kind == "intersect")) ? observeIntersection(el, function() { return executeRequest(el, NIL, NIL); }, false, get(mods, "delay")) : (isSxTruthy((kind == "load")) ? setTimeout_(function() { return executeRequest(el, NIL, NIL); }, sxOr(get(mods, "delay"), 0)) : (isSxTruthy((kind == "revealed")) ? observeIntersection(el, function() { return executeRequest(el, NIL, NIL); }, true, get(mods, "delay")) : (isSxTruthy((kind == "event")) ? bindEvent(el, get(trigger, "event"), mods, verbInfo) : NIL)))));
})(); }, triggers);
})(); };
// bind-event
var bindEvent = function(el, eventName, mods, verbInfo) { return (function() {
var timer = NIL;
var lastVal = NIL;
var listenTarget = (isSxTruthy(get(mods, "from")) ? domQuery(get(mods, "from")) : el);
return (isSxTruthy(listenTarget) ? domAddListener(listenTarget, eventName, function(e) { return (function() {
var shouldFire = true;
if (isSxTruthy(get(mods, "changed"))) {
(function() {
var val = elementValue(el);
return (isSxTruthy((val == lastVal)) ? (shouldFire = false) : (lastVal = val));
})();
}
return (isSxTruthy(shouldFire) ? ((isSxTruthy(sxOr((eventName == "submit"), (isSxTruthy((eventName == "click")) && domHasAttr(el, "href")))) ? preventDefault_(e) : NIL), (function() {
var liveInfo = sxOr(getVerbInfo(el), verbInfo);
var isGetLink = (isSxTruthy((eventName == "click")) && isSxTruthy((get(liveInfo, "method") == "GET")) && isSxTruthy(domHasAttr(el, "href")) && !isSxTruthy(get(mods, "delay")));
var clientRouted = false;
if (isSxTruthy(isGetLink)) {
clientRouted = tryClientRoute(urlPathname(get(liveInfo, "url")), domGetAttr(el, "sx-target"));
}
return (isSxTruthy(clientRouted) ? (browserPushState(get(liveInfo, "url")), browserScrollTo(0, 0)) : ((isSxTruthy(isGetLink) ? logInfo((String("sx:route server fetch ") + String(get(liveInfo, "url")))) : NIL), (isSxTruthy(get(mods, "delay")) ? (clearTimeout_(timer), (timer = setTimeout_(function() { return executeRequest(el, NIL, NIL); }, get(mods, "delay")))) : executeRequest(el, NIL, NIL))));
})()) : NIL);
})(); }, (isSxTruthy(get(mods, "once")) ? {["once"]: true} : NIL)) : NIL);
})(); };
// post-swap
var postSwap = function(root) { activateScripts(root);
sxProcessScripts(root);
sxHydrate(root);
return processElements(root); };
// activate-scripts
var activateScripts = function(root) { return (isSxTruthy(root) ? (function() {
var scripts = domQueryAll(root, "script");
return forEach(function(dead) { return (isSxTruthy((isSxTruthy(!isSxTruthy(domHasAttr(dead, "data-components"))) && !isSxTruthy(domHasAttr(dead, "data-sx-activated")))) ? (function() {
var live = createScriptClone(dead);
domSetAttr(live, "data-sx-activated", "true");
return domReplaceChild(domParent(dead), live, dead);
})() : NIL); }, scripts);
})() : NIL); };
// process-oob-swaps
var processOobSwaps = function(container, swapFn) { return (function() {
var oobs = findOobSwaps(container);
return forEach(function(oob) { return (function() {
var targetId = get(oob, "target-id");
var target = domQueryById(targetId);
var oobEl = get(oob, "element");
var swapType = get(oob, "swap-type");
if (isSxTruthy(domParent(oobEl))) {
domRemoveChild(domParent(oobEl), oobEl);
}
return (isSxTruthy(target) ? swapFn(target, oobEl, swapType) : NIL);
})(); }, oobs);
})(); };
// hoist-head-elements
var hoistHeadElements = function(container) { { var _c = domQueryAll(container, "style[data-sx-css]"); for (var _i = 0; _i < _c.length; _i++) { var style = _c[_i]; if (isSxTruthy(domParent(style))) {
domRemoveChild(domParent(style), style);
}
domAppendToHead(style); } }
return forEach(function(link) { if (isSxTruthy(domParent(link))) {
domRemoveChild(domParent(link), link);
}
return domAppendToHead(link); }, domQueryAll(container, "link[rel=\"stylesheet\"]")); };
// process-boosted
var processBoosted = function(root) { return forEach(function(container) { return boostDescendants(container); }, domQueryAll(sxOr(root, domBody()), "[sx-boost]")); };
// boost-descendants
var boostDescendants = function(container) { return (function() {
var boostTarget = domGetAttr(container, "sx-boost");
{ var _c = domQueryAll(container, "a[href]"); for (var _i = 0; _i < _c.length; _i++) { var link = _c[_i]; if (isSxTruthy((isSxTruthy(!isSxTruthy(isProcessed(link, "boost"))) && shouldBoostLink(link)))) {
markProcessed(link, "boost");
if (isSxTruthy((isSxTruthy(!isSxTruthy(domHasAttr(link, "sx-target"))) && isSxTruthy(boostTarget) && !isSxTruthy((boostTarget == "true"))))) {
domSetAttr(link, "sx-target", boostTarget);
}
if (isSxTruthy(!isSxTruthy(domHasAttr(link, "sx-swap")))) {
domSetAttr(link, "sx-swap", "innerHTML");
}
if (isSxTruthy(!isSxTruthy(domHasAttr(link, "sx-push-url")))) {
domSetAttr(link, "sx-push-url", "true");
}
bindClientRouteLink(link, domGetAttr(link, "href"));
} } }
return forEach(function(form) { return (isSxTruthy((isSxTruthy(!isSxTruthy(isProcessed(form, "boost"))) && shouldBoostForm(form))) ? (markProcessed(form, "boost"), (function() {
var method = upper(sxOr(domGetAttr(form, "method"), "GET"));
var action = sxOr(domGetAttr(form, "action"), browserLocationHref());
if (isSxTruthy((isSxTruthy(!isSxTruthy(domHasAttr(form, "sx-target"))) && isSxTruthy(boostTarget) && !isSxTruthy((boostTarget == "true"))))) {
domSetAttr(form, "sx-target", boostTarget);
}
if (isSxTruthy(!isSxTruthy(domHasAttr(form, "sx-swap")))) {
domSetAttr(form, "sx-swap", "innerHTML");
}
return bindBoostForm(form, method, action);
})()) : NIL); }, domQueryAll(container, "form"));
})(); };
// _page-data-cache
var _pageDataCache = {};
// _page-data-cache-ttl
var _pageDataCacheTtl = 30000;
// page-data-cache-key
var pageDataCacheKey = function(pageName, params) { return (function() {
var base = pageName;
return (isSxTruthy(sxOr(isNil(params), isEmpty(keys(params)))) ? base : (function() {
var parts = [];
{ var _c = keys(params); for (var _i = 0; _i < _c.length; _i++) { var k = _c[_i]; parts.push((String(k) + String("=") + String(get(params, k)))); } }
return (String(base) + String(":") + String(join("&", parts)));
})());
})(); };
// page-data-cache-get
var pageDataCacheGet = function(cacheKey) { return (function() {
var entry = get(_pageDataCache, cacheKey);
return (isSxTruthy(isNil(entry)) ? NIL : (isSxTruthy(((nowMs() - get(entry, "ts")) > _pageDataCacheTtl)) ? (dictSet(_pageDataCache, cacheKey, NIL), NIL) : get(entry, "data")));
})(); };
// page-data-cache-set
var pageDataCacheSet = function(cacheKey, data) { return dictSet(_pageDataCache, cacheKey, {"data": data, "ts": nowMs()}); };
// swap-rendered-content
var swapRenderedContent = function(target, rendered, pathname) { return (domSetTextContent(target, ""), domAppend(target, rendered), hoistHeadElementsFull(target), processElements(target), sxHydrateElements(target), domDispatch(target, "sx:clientRoute", {["pathname"]: pathname}), logInfo((String("sx:route client ") + String(pathname)))); };
// resolve-route-target
var resolveRouteTarget = function(targetSel) { return (isSxTruthy((isSxTruthy(targetSel) && !isSxTruthy((targetSel == "true")))) ? domQuery(targetSel) : NIL); };
// deps-satisfied?
var depsSatisfied_p = function(match) { return (function() {
var deps = get(match, "deps");
var loaded = loadedComponentNames();
return (isSxTruthy(sxOr(isNil(deps), isEmpty(deps))) ? true : isEvery(function(dep) { return contains(loaded, dep); }, deps));
})(); };
// try-client-route
var tryClientRoute = function(pathname, targetSel) { return (function() {
var match = findMatchingRoute(pathname, _pageRoutes);
return (isSxTruthy(isNil(match)) ? (logInfo((String("sx:route no match (") + String(len(_pageRoutes)) + String(" routes) ") + String(pathname))), false) : (function() {
var contentSrc = get(match, "content");
var closure = sxOr(get(match, "closure"), {});
var params = get(match, "params");
var pageName = get(match, "name");
return (isSxTruthy(sxOr(isNil(contentSrc), isEmpty(contentSrc))) ? (logWarn((String("sx:route no content for ") + String(pathname))), false) : (function() {
var target = resolveRouteTarget(targetSel);
return (isSxTruthy(isNil(target)) ? (logWarn((String("sx:route target not found: ") + String(targetSel))), false) : (isSxTruthy(!isSxTruthy(depsSatisfied_p(match))) ? (logInfo((String("sx:route deps miss for ") + String(pageName))), false) : (function() {
var ioDeps = get(match, "io-deps");
var hasIo = (isSxTruthy(ioDeps) && !isSxTruthy(isEmpty(ioDeps)));
if (isSxTruthy(hasIo)) {
registerIoDeps(ioDeps);
}
return (isSxTruthy(get(match, "has-data")) ? (function() {
var cacheKey = pageDataCacheKey(pageName, params);
var cached = pageDataCacheGet(cacheKey);
return (isSxTruthy(cached) ? (function() {
var env = merge(closure, params, cached);
return (isSxTruthy(hasIo) ? (logInfo((String("sx:route client+cache+async ") + String(pathname))), tryAsyncEvalContent(contentSrc, env, function(rendered) { return (isSxTruthy(isNil(rendered)) ? logWarn((String("sx:route async eval failed for ") + String(pathname))) : swapRenderedContent(target, rendered, pathname)); }), true) : (function() {
var rendered = tryEvalContent(contentSrc, env);
return (isSxTruthy(isNil(rendered)) ? (logWarn((String("sx:route cached eval failed for ") + String(pathname))), false) : (logInfo((String("sx:route client+cache ") + String(pathname))), swapRenderedContent(target, rendered, pathname), true));
})());
})() : (logInfo((String("sx:route client+data ") + String(pathname))), resolvePageData(pageName, params, function(data) { pageDataCacheSet(cacheKey, data);
return (function() {
var env = merge(closure, params, data);
return (isSxTruthy(hasIo) ? tryAsyncEvalContent(contentSrc, env, function(rendered) { return (isSxTruthy(isNil(rendered)) ? logWarn((String("sx:route data+async eval failed for ") + String(pathname))) : swapRenderedContent(target, rendered, pathname)); }) : (function() {
var rendered = tryEvalContent(contentSrc, env);
return (isSxTruthy(isNil(rendered)) ? logWarn((String("sx:route data eval failed for ") + String(pathname))) : swapRenderedContent(target, rendered, pathname));
})());
})(); }), true));
})() : (isSxTruthy(hasIo) ? (logInfo((String("sx:route client+async ") + String(pathname))), tryAsyncEvalContent(contentSrc, merge(closure, params), function(rendered) { return (isSxTruthy(isNil(rendered)) ? logWarn((String("sx:route async eval failed for ") + String(pathname))) : swapRenderedContent(target, rendered, pathname)); }), true) : (function() {
var env = merge(closure, params);
var rendered = tryEvalContent(contentSrc, env);
return (isSxTruthy(isNil(rendered)) ? (logInfo((String("sx:route server (eval failed) ") + String(pathname))), false) : (swapRenderedContent(target, rendered, pathname), true));
})()));
})()));
})());
})());
})(); };
// bind-client-route-link
var bindClientRouteLink = function(link, href) { return bindClientRouteClick(link, href, function() { return bindBoostLink(link, href); }); };
// process-sse
var processSse = function(root) { return forEach(function(el) { return (isSxTruthy(!isSxTruthy(isProcessed(el, "sse"))) ? (markProcessed(el, "sse"), bindSse(el)) : NIL); }, domQueryAll(sxOr(root, domBody()), "[sx-sse]")); };
// bind-sse
var bindSse = function(el) { return (function() {
var url = domGetAttr(el, "sx-sse");
return (isSxTruthy(url) ? (function() {
var source = eventSourceConnect(url, el);
var eventName = parseSseSwap(el);
return eventSourceListen(source, eventName, function(data) { return bindSseSwap(el, data); });
})() : NIL);
})(); };
// bind-sse-swap
var bindSseSwap = function(el, data) { return (function() {
var target = resolveTarget(el);
var swapSpec = parseSwapSpec(domGetAttr(el, "sx-swap"), domHasClass(domBody(), "sx-transitions"));
var swapStyle = get(swapSpec, "style");
var useTransition = get(swapSpec, "transition");
var trimmed = trim(data);
return (isSxTruthy(!isSxTruthy(isEmpty(trimmed))) ? (isSxTruthy(startsWith(trimmed, "(")) ? (function() {
var rendered = sxRender(trimmed);
var container = domCreateElement("div", NIL);
domAppend(container, rendered);
return withTransition(useTransition, function() { swapDomNodes(target, childrenToFragment(container), swapStyle);
return postSwap(target); });
})() : withTransition(useTransition, function() { swapHtmlString(target, trimmed, swapStyle);
return postSwap(target); })) : NIL);
})(); };
// bind-inline-handlers
var bindInlineHandlers = function(root) { return forEach(function(el) { return forEach(function(attr) { return (function() {
var name = first(attr);
var body = nth(attr, 1);
return (isSxTruthy(startsWith(name, "sx-on:")) ? (function() {
var eventName = slice(name, 6);
return (isSxTruthy(!isSxTruthy(isProcessed(el, (String("on:") + String(eventName))))) ? (markProcessed(el, (String("on:") + String(eventName))), bindInlineHandler(el, eventName, body)) : NIL);
})() : NIL);
})(); }, domAttrList(el)); }, domQueryAll(sxOr(root, domBody()), "[sx-on\\:beforeRequest],[sx-on\\:afterRequest],[sx-on\\:afterSwap],[sx-on\\:afterSettle],[sx-on\\:load]")); };
// bind-preload-for
var bindPreloadFor = function(el) { return (function() {
var preloadAttr = domGetAttr(el, "sx-preload");
return (isSxTruthy(preloadAttr) ? (function() {
var events = (isSxTruthy((preloadAttr == "mousedown")) ? ["mousedown", "touchstart"] : ["mouseover"]);
var debounceMs = (isSxTruthy((preloadAttr == "mousedown")) ? 0 : 100);
return bindPreload(el, events, debounceMs, function() { return (function() {
var info = getVerbInfo(el);
return (isSxTruthy(info) ? doPreload(get(info, "url"), buildRequestHeaders(el, loadedComponentNames(), _cssHash)) : NIL);
})(); });
})() : NIL);
})(); };
// do-preload
var doPreload = function(url, headers) { return (isSxTruthy(isNil(preloadCacheGet(_preloadCache, url))) ? fetchPreload(url, headers, _preloadCache) : NIL); };
// VERB_SELECTOR
var VERB_SELECTOR = (String("[sx-get],[sx-post],[sx-put],[sx-delete],[sx-patch]"));
// process-elements
var processElements = function(root) { (function() {
var els = domQueryAll(sxOr(root, domBody()), VERB_SELECTOR);
return forEach(function(el) { return (isSxTruthy(!isSxTruthy(isProcessed(el, "verb"))) ? (markProcessed(el, "verb"), processOne(el)) : NIL); }, els);
})();
processBoosted(root);
processSse(root);
return bindInlineHandlers(root); };
// process-one
var processOne = function(el) { return (function() {
var verbInfo = getVerbInfo(el);
return (isSxTruthy(verbInfo) ? (isSxTruthy(!isSxTruthy(domHasAttr(el, "sx-disable"))) ? (bindTriggers(el, verbInfo), bindPreloadFor(el)) : NIL) : NIL);
})(); };
// handle-popstate
var handlePopstate = function(scrollY) { return (function() {
var url = browserLocationHref();
var boostEl = domQuery("[sx-boost]");
var targetSel = (isSxTruthy(boostEl) ? (function() {
var attr = domGetAttr(boostEl, "sx-boost");
return (isSxTruthy((isSxTruthy(attr) && !isSxTruthy((attr == "true")))) ? attr : NIL);
})() : NIL);
var targetSel = sxOr(targetSel, "#main-panel");
var target = domQuery(targetSel);
var pathname = urlPathname(url);
return (isSxTruthy(target) ? (isSxTruthy(tryClientRoute(pathname, targetSel)) ? browserScrollTo(0, scrollY) : (function() {
var headers = buildRequestHeaders(target, loadedComponentNames(), _cssHash);
return fetchAndRestore(target, url, headers, scrollY);
})()) : NIL);
})(); };
// engine-init
var engineInit = function() { return (initCssTracking(), sxProcessScripts(NIL), sxHydrate(NIL), processElements(NIL)); };
// === Transpiled from cssx ===
// _style-atoms
var _styleAtoms = {};
// _pseudo-variants
var _pseudoVariants = {};
// _responsive-breakpoints
var _responsiveBreakpoints = {};
// _style-keyframes
var _styleKeyframes = {};
// _arbitrary-patterns
var _arbitraryPatterns = [];
// _child-selector-prefixes
var _childSelectorPrefixes = [];
// _style-cache
var _styleCache = {};
// _injected-styles
var _injectedStyles = {};
// load-style-dict
var loadStyleDict = function(data) { _styleAtoms = sxOr(get(data, "a"), {});
_pseudoVariants = sxOr(get(data, "v"), {});
_responsiveBreakpoints = sxOr(get(data, "b"), {});
_styleKeyframes = sxOr(get(data, "k"), {});
_childSelectorPrefixes = sxOr(get(data, "c"), []);
_arbitraryPatterns = map(function(pair) { return {["re"]: compileRegex((String("^") + String(first(pair)) + String("$"))), ["tmpl"]: nth(pair, 1)}; }, sxOr(get(data, "p"), []));
return (_styleCache = {}); };
// split-variant
var splitVariant = function(atom) { return (function() {
var result = NIL;
{ var _c = keys(_responsiveBreakpoints); for (var _i = 0; _i < _c.length; _i++) { var bp = _c[_i]; if (isSxTruthy(isNil(result))) {
(function() {
var prefix = (String(bp) + String(":"));
return (isSxTruthy(startsWith(atom, prefix)) ? (function() {
var restAtom = slice(atom, len(prefix));
return (function() {
var innerMatch = NIL;
{ var _c = keys(_pseudoVariants); for (var _i = 0; _i < _c.length; _i++) { var pv = _c[_i]; if (isSxTruthy(isNil(innerMatch))) {
(function() {
var innerPrefix = (String(pv) + String(":"));
return (isSxTruthy(startsWith(restAtom, innerPrefix)) ? (innerMatch = [(String(bp) + String(":") + String(pv)), slice(restAtom, len(innerPrefix))]) : NIL);
})();
} } }
return (result = sxOr(innerMatch, [bp, restAtom]));
})();
})() : NIL);
})();
} } }
if (isSxTruthy(isNil(result))) {
{ var _c = keys(_pseudoVariants); for (var _i = 0; _i < _c.length; _i++) { var pv = _c[_i]; if (isSxTruthy(isNil(result))) {
(function() {
var prefix = (String(pv) + String(":"));
return (isSxTruthy(startsWith(atom, prefix)) ? (result = [pv, slice(atom, len(prefix))]) : NIL);
})();
} } }
}
return sxOr(result, [NIL, atom]);
})(); };
// resolve-atom
var resolveAtom = function(atom) { return (function() {
var decls = dictGet(_styleAtoms, atom);
return (isSxTruthy(!isSxTruthy(isNil(decls))) ? decls : (isSxTruthy(startsWith(atom, "animate-")) ? (function() {
var kfName = slice(atom, 8);
return (isSxTruthy(dictHas(_styleKeyframes, kfName)) ? (String("animation-name:") + String(kfName)) : NIL);
})() : (function() {
var matchResult = NIL;
{ var _c = _arbitraryPatterns; for (var _i = 0; _i < _c.length; _i++) { var pat = _c[_i]; if (isSxTruthy(isNil(matchResult))) {
(function() {
var m = regexMatch(get(pat, "re"), atom);
return (isSxTruthy(m) ? (matchResult = regexReplaceGroups(get(pat, "tmpl"), m)) : NIL);
})();
} } }
return matchResult;
})()));
})(); };
// is-child-selector-atom?
var isChildSelectorAtom = function(atom) { return some(function(prefix) { return startsWith(atom, prefix); }, _childSelectorPrefixes); };
// hash-style
var hashStyle = function(input) { return fnv1aHash(input); };
// resolve-style
var resolveStyle = function(atoms) { return (function() {
var key = join("\\0", atoms);
return (function() {
var cached = dictGet(_styleCache, key);
return (isSxTruthy(!isSxTruthy(isNil(cached))) ? cached : (function() {
var baseDecls = [];
var mediaRules = [];
var pseudoRules = [];
var kfNeeded = [];
{ var _c = atoms; for (var _i = 0; _i < _c.length; _i++) { var a = _c[_i]; if (isSxTruthy(a)) {
(function() {
var clean = (isSxTruthy(startsWith(a, ":")) ? slice(a, 1) : a);
return (function() {
var parts = splitVariant(clean);
return (function() {
var variant = first(parts);
var base = nth(parts, 1);
var decls = resolveAtom(base);
return (isSxTruthy(decls) ? ((isSxTruthy(startsWith(base, "animate-")) ? (function() {
var kfName = slice(base, 8);
return (isSxTruthy(dictHas(_styleKeyframes, kfName)) ? append_b(kfNeeded, [kfName, dictGet(_styleKeyframes, kfName)]) : NIL);
})() : NIL), (isSxTruthy(isNil(variant)) ? (isSxTruthy(isChildSelectorAtom(base)) ? append_b(pseudoRules, [">:not(:first-child)", decls]) : append_b(baseDecls, decls)) : (isSxTruthy(dictHas(_responsiveBreakpoints, variant)) ? append_b(mediaRules, [dictGet(_responsiveBreakpoints, variant), decls]) : (isSxTruthy(dictHas(_pseudoVariants, variant)) ? append_b(pseudoRules, [dictGet(_pseudoVariants, variant), decls]) : (function() {
var vparts = split(variant, ":");
var mediaPart = NIL;
var pseudoPart = NIL;
{ var _c = vparts; for (var _i = 0; _i < _c.length; _i++) { var vp = _c[_i]; (isSxTruthy(dictHas(_responsiveBreakpoints, vp)) ? (mediaPart = dictGet(_responsiveBreakpoints, vp)) : (isSxTruthy(dictHas(_pseudoVariants, vp)) ? (pseudoPart = dictGet(_pseudoVariants, vp)) : NIL)); } }
if (isSxTruthy(mediaPart)) {
mediaRules.push([mediaPart, decls]);
}
if (isSxTruthy(pseudoPart)) {
pseudoRules.push([pseudoPart, decls]);
}
return (isSxTruthy((isSxTruthy(isNil(mediaPart)) && isNil(pseudoPart))) ? append_b(baseDecls, decls) : NIL);
})())))) : NIL);
})();
})();
})();
} } }
return (function() {
var hashInput = join(";", baseDecls);
{ var _c = mediaRules; for (var _i = 0; _i < _c.length; _i++) { var mr = _c[_i]; hashInput = (String(hashInput) + String("@") + String(first(mr)) + String("{") + String(nth(mr, 1)) + String("}")); } }
{ var _c = pseudoRules; for (var _i = 0; _i < _c.length; _i++) { var pr = _c[_i]; hashInput = (String(hashInput) + String(first(pr)) + String("{") + String(nth(pr, 1)) + String("}")); } }
{ var _c = kfNeeded; for (var _i = 0; _i < _c.length; _i++) { var kf = _c[_i]; hashInput = (String(hashInput) + String(nth(kf, 1))); } }
return (function() {
var cn = (String("sx-") + String(hashStyle(hashInput)));
var sv = makeStyleValue_(cn, join(";", baseDecls), mediaRules, pseudoRules, kfNeeded);
_styleCache[key] = sv;
injectStyleValue(sv, atoms);
return sv;
})();
})();
})());
})();
})(); };
// merge-style-values
var mergeStyleValues = function(styles) { return (isSxTruthy((len(styles) == 1)) ? first(styles) : (function() {
var allDecls = [];
var allMedia = [];
var allPseudo = [];
var allKf = [];
{ var _c = styles; for (var _i = 0; _i < _c.length; _i++) { var sv = _c[_i]; if (isSxTruthy(styleValueDeclarations(sv))) {
allDecls.push(styleValueDeclarations(sv));
}
allMedia = concat(allMedia, styleValueMediaRules(sv));
allPseudo = concat(allPseudo, styleValuePseudoRules(sv));
allKf = concat(allKf, styleValueKeyframes_(sv)); } }
return (function() {
var hashInput = join(";", allDecls);
{ var _c = allMedia; for (var _i = 0; _i < _c.length; _i++) { var mr = _c[_i]; hashInput = (String(hashInput) + String("@") + String(first(mr)) + String("{") + String(nth(mr, 1)) + String("}")); } }
{ var _c = allPseudo; for (var _i = 0; _i < _c.length; _i++) { var pr = _c[_i]; hashInput = (String(hashInput) + String(first(pr)) + String("{") + String(nth(pr, 1)) + String("}")); } }
{ var _c = allKf; for (var _i = 0; _i < _c.length; _i++) { var kf = _c[_i]; hashInput = (String(hashInput) + String(nth(kf, 1))); } }
return (function() {
var cn = (String("sx-") + String(hashStyle(hashInput)));
var merged = makeStyleValue_(cn, join(";", allDecls), allMedia, allPseudo, allKf);
injectStyleValue(merged, []);
return merged;
})();
})();
})()); };
// === Transpiled from boot ===
// HEAD_HOIST_SELECTOR
var HEAD_HOIST_SELECTOR = "meta, title, link[rel='canonical'], script[type='application/ld+json']";
// hoist-head-elements-full
var hoistHeadElementsFull = function(root) { return (function() {
var els = domQueryAll(root, HEAD_HOIST_SELECTOR);
return forEach(function(el) { return (function() {
var tag = lower(domTagName(el));
return (isSxTruthy((tag == "title")) ? (setDocumentTitle(domTextContent(el)), domRemoveChild(domParent(el), el)) : (isSxTruthy((tag == "meta")) ? ((function() {
var name = domGetAttr(el, "name");
var prop = domGetAttr(el, "property");
if (isSxTruthy(name)) {
removeHeadElement((String("meta[name=\"") + String(name) + String("\"]")));
}
return (isSxTruthy(prop) ? removeHeadElement((String("meta[property=\"") + String(prop) + String("\"]"))) : NIL);
})(), domRemoveChild(domParent(el), el), domAppendToHead(el)) : (isSxTruthy((isSxTruthy((tag == "link")) && (domGetAttr(el, "rel") == "canonical"))) ? (removeHeadElement("link[rel=\"canonical\"]"), domRemoveChild(domParent(el), el), domAppendToHead(el)) : (domRemoveChild(domParent(el), el), domAppendToHead(el)))));
})(); }, els);
})(); };
// sx-mount
var sxMount = function(target, source, extraEnv) { return (function() {
var el = resolveMountTarget(target);
return (isSxTruthy(el) ? (function() {
var node = sxRenderWithEnv(source, extraEnv);
domSetTextContent(el, "");
domAppend(el, node);
hoistHeadElementsFull(el);
processElements(el);
return sxHydrateElements(el);
})() : NIL);
})(); };
// resolve-suspense
var resolveSuspense = function(id, sx) { return (function() {
var el = domQuery((String("[data-suspense=\"") + String(id) + String("\"]")));
return (isSxTruthy(el) ? (function() {
var ast = parse(sx);
var env = getRenderEnv(NIL);
var node = renderToDom(ast, env, NIL);
domSetTextContent(el, "");
domAppend(el, node);
processElements(el);
sxHydrateElements(el);
return domDispatch(el, "sx:resolved", {"id": id});
})() : logWarn((String("resolveSuspense: no element for id=") + String(id))));
})(); };
// sx-hydrate-elements
var sxHydrateElements = function(root) { return (function() {
var els = domQueryAll(sxOr(root, domBody()), "[data-sx]");
return forEach(function(el) { return (isSxTruthy(!isSxTruthy(isProcessed(el, "hydrated"))) ? (markProcessed(el, "hydrated"), sxUpdateElement(el, NIL)) : NIL); }, els);
})(); };
// sx-update-element
var sxUpdateElement = function(el, newEnv) { return (function() {
var target = resolveMountTarget(el);
return (isSxTruthy(target) ? (function() {
var source = domGetAttr(target, "data-sx");
return (isSxTruthy(source) ? (function() {
var baseEnv = parseEnvAttr(target);
var env = mergeEnvs(baseEnv, newEnv);
return (function() {
var node = sxRenderWithEnv(source, env);
domSetTextContent(target, "");
domAppend(target, node);
return (isSxTruthy(newEnv) ? storeEnvAttr(target, baseEnv, newEnv) : NIL);
})();
})() : NIL);
})() : NIL);
})(); };
// sx-render-component
var sxRenderComponent = function(name, kwargs, extraEnv) { return (function() {
var fullName = (isSxTruthy(startsWith(name, "~")) ? name : (String("~") + String(name)));
return (function() {
var env = getRenderEnv(extraEnv);
var comp = envGet(env, fullName);
return (isSxTruthy(!isSxTruthy(isComponent(comp))) ? error((String("Unknown component: ") + String(fullName))) : (function() {
var callExpr = [makeSymbol(fullName)];
{ var _c = keys(kwargs); for (var _i = 0; _i < _c.length; _i++) { var k = _c[_i]; callExpr.push(makeKeyword(toKebab(k)));
callExpr.push(dictGet(kwargs, k)); } }
return renderToDom(callExpr, env, NIL);
})());
})();
})(); };
// process-sx-scripts
var processSxScripts = function(root) { return (function() {
var scripts = querySxScripts(root);
return forEach(function(s) { return (isSxTruthy(!isSxTruthy(isProcessed(s, "script"))) ? (markProcessed(s, "script"), (function() {
var text = domTextContent(s);
return (isSxTruthy(domHasAttr(s, "data-components")) ? processComponentScript(s, text) : (isSxTruthy(sxOr(isNil(text), isEmpty(trim(text)))) ? NIL : (isSxTruthy(domHasAttr(s, "data-mount")) ? (function() {
var mountSel = domGetAttr(s, "data-mount");
var target = domQuery(mountSel);
return (isSxTruthy(target) ? sxMount(target, text, NIL) : NIL);
})() : sxLoadComponents(text))));
})()) : NIL); }, scripts);
})(); };
// process-component-script
var processComponentScript = function(script, text) { return (function() {
var hash = domGetAttr(script, "data-hash");
return (isSxTruthy(isNil(hash)) ? (isSxTruthy((isSxTruthy(text) && !isSxTruthy(isEmpty(trim(text))))) ? sxLoadComponents(text) : NIL) : (function() {
var hasInline = (isSxTruthy(text) && !isSxTruthy(isEmpty(trim(text))));
(function() {
var cachedHash = localStorageGet("sx-components-hash");
return (isSxTruthy((cachedHash == hash)) ? (isSxTruthy(hasInline) ? (localStorageSet("sx-components-hash", hash), localStorageSet("sx-components-src", text), sxLoadComponents(text), logInfo("components: downloaded (cookie stale)")) : (function() {
var cached = localStorageGet("sx-components-src");
return (isSxTruthy(cached) ? (sxLoadComponents(cached), logInfo((String("components: cached (") + String(hash) + String(")")))) : (clearSxCompCookie(), browserReload()));
})()) : (isSxTruthy(hasInline) ? (localStorageSet("sx-components-hash", hash), localStorageSet("sx-components-src", text), sxLoadComponents(text), logInfo((String("components: downloaded (") + String(hash) + String(")")))) : (localStorageRemove("sx-components-hash"), localStorageRemove("sx-components-src"), clearSxCompCookie(), browserReload())));
})();
return setSxCompCookie(hash);
})());
})(); };
// init-style-dict
var initStyleDict = function() { return (function() {
var scripts = queryStyleScripts();
return forEach(function(s) { return (isSxTruthy(!isSxTruthy(isProcessed(s, "styles"))) ? (markProcessed(s, "styles"), (function() {
var text = domTextContent(s);
var hash = domGetAttr(s, "data-hash");
return (isSxTruthy(isNil(hash)) ? (isSxTruthy((isSxTruthy(text) && !isSxTruthy(isEmpty(trim(text))))) ? parseAndLoadStyleDict(text) : NIL) : (function() {
var hasInline = (isSxTruthy(text) && !isSxTruthy(isEmpty(trim(text))));
(function() {
var cachedHash = localStorageGet("sx-styles-hash");
return (isSxTruthy((cachedHash == hash)) ? (isSxTruthy(hasInline) ? (localStorageSet("sx-styles-src", text), parseAndLoadStyleDict(text), logInfo("styles: downloaded (cookie stale)")) : (function() {
var cached = localStorageGet("sx-styles-src");
return (isSxTruthy(cached) ? (parseAndLoadStyleDict(cached), logInfo((String("styles: cached (") + String(hash) + String(")")))) : (clearSxStylesCookie(), browserReload()));
})()) : (isSxTruthy(hasInline) ? (localStorageSet("sx-styles-hash", hash), localStorageSet("sx-styles-src", text), parseAndLoadStyleDict(text), logInfo((String("styles: downloaded (") + String(hash) + String(")")))) : (localStorageRemove("sx-styles-hash"), localStorageRemove("sx-styles-src"), clearSxStylesCookie(), browserReload())));
})();
return setSxStylesCookie(hash);
})());
})()) : NIL); }, scripts);
})(); };
// _page-routes
var _pageRoutes = [];
// process-page-scripts
var processPageScripts = function() { return (function() {
var scripts = queryPageScripts();
logInfo((String("pages: found ") + String(len(scripts)) + String(" script tags")));
{ var _c = scripts; for (var _i = 0; _i < _c.length; _i++) { var s = _c[_i]; if (isSxTruthy(!isSxTruthy(isProcessed(s, "pages")))) {
markProcessed(s, "pages");
(function() {
var text = domTextContent(s);
logInfo((String("pages: script text length=") + String((isSxTruthy(text) ? len(text) : 0))));
return (isSxTruthy((isSxTruthy(text) && !isSxTruthy(isEmpty(trim(text))))) ? (function() {
var pages = parse(text);
logInfo((String("pages: parsed ") + String(len(pages)) + String(" entries")));
return forEach(function(page) { return append_b(_pageRoutes, merge(page, {"parsed": parseRoutePattern(get(page, "path"))})); }, pages);
})() : logWarn("pages: script tag is empty"));
})();
} } }
return logInfo((String("pages: ") + String(len(_pageRoutes)) + String(" routes loaded")));
})(); };
// boot-init
var bootInit = function() { return (logInfo((String("sx-browser ") + String(SX_VERSION))), initCssTracking(), initStyleDict(), processPageScripts(), processSxScripts(NIL), sxHydrateElements(NIL), processElements(NIL)); };
// === Transpiled from deps (component dependency analysis) ===
// scan-refs
var scanRefs = function(node) { return (function() {
var refs = [];
scanRefsWalk(node, refs);
return refs;
})(); };
// scan-refs-walk
var scanRefsWalk = function(node, refs) { return (isSxTruthy((typeOf(node) == "symbol")) ? (function() {
var name = symbolName(node);
return (isSxTruthy(startsWith(name, "~")) ? (isSxTruthy(!isSxTruthy(contains(refs, name))) ? append_b(refs, name) : NIL) : NIL);
})() : (isSxTruthy((typeOf(node) == "list")) ? forEach(function(item) { return scanRefsWalk(item, refs); }, node) : (isSxTruthy((typeOf(node) == "dict")) ? forEach(function(key) { return scanRefsWalk(dictGet(node, key), refs); }, keys(node)) : NIL))); };
// transitive-deps-walk
var transitiveDepsWalk = function(n, seen, env) { return (isSxTruthy(!isSxTruthy(contains(seen, n))) ? (append_b(seen, n), (function() {
var val = envGet(env, n);
return (isSxTruthy((typeOf(val) == "component")) ? forEach(function(ref) { return transitiveDepsWalk(ref, seen, env); }, scanRefs(componentBody(val))) : (isSxTruthy((typeOf(val) == "macro")) ? forEach(function(ref) { return transitiveDepsWalk(ref, seen, env); }, scanRefs(macroBody(val))) : NIL));
})()) : NIL); };
// transitive-deps
var transitiveDeps = function(name, env) { return (function() {
var seen = [];
var key = (isSxTruthy(startsWith(name, "~")) ? name : (String("~") + String(name)));
transitiveDepsWalk(key, seen, env);
return filter(function(x) { return !isSxTruthy((x == key)); }, seen);
})(); };
// compute-all-deps
var computeAllDeps = function(env) { return forEach(function(name) { return (function() {
var val = envGet(env, name);
return (isSxTruthy((typeOf(val) == "component")) ? componentSetDeps(val, transitiveDeps(name, env)) : NIL);
})(); }, envComponents(env)); };
// scan-components-from-source
var scanComponentsFromSource = function(source) { return (function() {
var matches = regexFindAll("\\(~([a-zA-Z_][a-zA-Z0-9_\\-]*)", source);
return map(function(m) { return (String("~") + String(m)); }, matches);
})(); };
// components-needed
var componentsNeeded = function(pageSource, env) { return (function() {
var direct = scanComponentsFromSource(pageSource);
var allNeeded = [];
{ var _c = direct; for (var _i = 0; _i < _c.length; _i++) { var name = _c[_i]; if (isSxTruthy(!isSxTruthy(contains(allNeeded, name)))) {
allNeeded.push(name);
}
(function() {
var val = envGet(env, name);
return (function() {
var deps = (isSxTruthy((isSxTruthy((typeOf(val) == "component")) && !isSxTruthy(isEmpty(componentDeps(val))))) ? componentDeps(val) : transitiveDeps(name, env));
return forEach(function(dep) { return (isSxTruthy(!isSxTruthy(contains(allNeeded, dep))) ? append_b(allNeeded, dep) : NIL); }, deps);
})();
})(); } }
return allNeeded;
})(); };
// page-component-bundle
var pageComponentBundle = function(pageSource, env) { return componentsNeeded(pageSource, env); };
// page-css-classes
var pageCssClasses = function(pageSource, env) { return (function() {
var needed = componentsNeeded(pageSource, env);
var classes = [];
{ var _c = needed; for (var _i = 0; _i < _c.length; _i++) { var name = _c[_i]; (function() {
var val = envGet(env, name);
return (isSxTruthy((typeOf(val) == "component")) ? forEach(function(cls) { return (isSxTruthy(!isSxTruthy(contains(classes, cls))) ? append_b(classes, cls) : NIL); }, componentCssClasses(val)) : NIL);
})(); } }
{ var _c = scanCssClasses(pageSource); for (var _i = 0; _i < _c.length; _i++) { var cls = _c[_i]; if (isSxTruthy(!isSxTruthy(contains(classes, cls)))) {
classes.push(cls);
} } }
return classes;
})(); };
// scan-io-refs-walk
var scanIoRefsWalk = function(node, ioNames, refs) { return (isSxTruthy((typeOf(node) == "symbol")) ? (function() {
var name = symbolName(node);
return (isSxTruthy(contains(ioNames, name)) ? (isSxTruthy(!isSxTruthy(contains(refs, name))) ? append_b(refs, name) : NIL) : NIL);
})() : (isSxTruthy((typeOf(node) == "list")) ? forEach(function(item) { return scanIoRefsWalk(item, ioNames, refs); }, node) : (isSxTruthy((typeOf(node) == "dict")) ? forEach(function(key) { return scanIoRefsWalk(dictGet(node, key), ioNames, refs); }, keys(node)) : NIL))); };
// scan-io-refs
var scanIoRefs = function(node, ioNames) { return (function() {
var refs = [];
scanIoRefsWalk(node, ioNames, refs);
return refs;
})(); };
// transitive-io-refs-walk
var transitiveIoRefsWalk = function(n, seen, allRefs, env, ioNames) { return (isSxTruthy(!isSxTruthy(contains(seen, n))) ? (append_b(seen, n), (function() {
var val = envGet(env, n);
return (isSxTruthy((typeOf(val) == "component")) ? (forEach(function(ref) { return (isSxTruthy(!isSxTruthy(contains(allRefs, ref))) ? append_b(allRefs, ref) : NIL); }, scanIoRefs(componentBody(val), ioNames)), forEach(function(dep) { return transitiveIoRefsWalk(dep, seen, allRefs, env, ioNames); }, scanRefs(componentBody(val)))) : (isSxTruthy((typeOf(val) == "macro")) ? (forEach(function(ref) { return (isSxTruthy(!isSxTruthy(contains(allRefs, ref))) ? append_b(allRefs, ref) : NIL); }, scanIoRefs(macroBody(val), ioNames)), forEach(function(dep) { return transitiveIoRefsWalk(dep, seen, allRefs, env, ioNames); }, scanRefs(macroBody(val)))) : NIL));
})()) : NIL); };
// transitive-io-refs
var transitiveIoRefs = function(name, env, ioNames) { return (function() {
var allRefs = [];
var seen = [];
var key = (isSxTruthy(startsWith(name, "~")) ? name : (String("~") + String(name)));
transitiveIoRefsWalk(key, seen, allRefs, env, ioNames);
return allRefs;
})(); };
// compute-all-io-refs
var computeAllIoRefs = function(env, ioNames) { return forEach(function(name) { return (function() {
var val = envGet(env, name);
return (isSxTruthy((typeOf(val) == "component")) ? componentSetIoRefs(val, transitiveIoRefs(name, env, ioNames)) : NIL);
})(); }, envComponents(env)); };
// component-pure?
var componentPure_p = function(name, env, ioNames) { return isEmpty(transitiveIoRefs(name, env, ioNames)); };
// === Transpiled from router (client-side route matching) ===
// split-path-segments
var splitPathSegments = function(path) { return (function() {
var trimmed = (isSxTruthy(startsWith(path, "/")) ? slice(path, 1) : path);
return (function() {
var trimmed2 = (isSxTruthy((isSxTruthy(!isSxTruthy(isEmpty(trimmed))) && endsWith(trimmed, "/"))) ? slice(trimmed, 0, (len(trimmed) - 1)) : trimmed);
return (isSxTruthy(isEmpty(trimmed2)) ? [] : split(trimmed2, "/"));
})();
})(); };
// make-route-segment
var makeRouteSegment = function(seg) { return (isSxTruthy((isSxTruthy(startsWith(seg, "<")) && endsWith(seg, ">"))) ? (function() {
var paramName = slice(seg, 1, (len(seg) - 1));
return (function() {
var d = {};
d["type"] = "param";
d["value"] = paramName;
return d;
})();
})() : (function() {
var d = {};
d["type"] = "literal";
d["value"] = seg;
return d;
})()); };
// parse-route-pattern
var parseRoutePattern = function(pattern) { return (function() {
var segments = splitPathSegments(pattern);
return map(makeRouteSegment, segments);
})(); };
// match-route-segments
var matchRouteSegments = function(pathSegs, parsedSegs) { return (isSxTruthy(!isSxTruthy((len(pathSegs) == len(parsedSegs)))) ? NIL : (function() {
var params = {};
var matched = true;
forEachIndexed(function(i, parsedSeg) { return (isSxTruthy(matched) ? (function() {
var pathSeg = nth(pathSegs, i);
var segType = get(parsedSeg, "type");
return (isSxTruthy((segType == "literal")) ? (isSxTruthy(!isSxTruthy((pathSeg == get(parsedSeg, "value")))) ? (matched = false) : NIL) : (isSxTruthy((segType == "param")) ? dictSet(params, get(parsedSeg, "value"), pathSeg) : (matched = false)));
})() : NIL); }, parsedSegs);
return (isSxTruthy(matched) ? params : NIL);
})()); };
// match-route
var matchRoute = function(path, pattern) { return (function() {
var pathSegs = splitPathSegments(path);
var parsedSegs = parseRoutePattern(pattern);
return matchRouteSegments(pathSegs, parsedSegs);
})(); };
// find-matching-route
var findMatchingRoute = function(path, routes) { return (function() {
var pathSegs = splitPathSegments(path);
var result = NIL;
{ var _c = routes; for (var _i = 0; _i < _c.length; _i++) { var route = _c[_i]; if (isSxTruthy(isNil(result))) {
(function() {
var params = matchRouteSegments(pathSegs, get(route, "parsed"));
return (isSxTruthy(!isSxTruthy(isNil(params))) ? (function() {
var matched = merge(route, {});
matched["params"] = params;
return (result = matched);
})() : NIL);
})();
} } }
return result;
})(); };
// =========================================================================
// Platform interface — DOM adapter (browser-only)
// =========================================================================
var _hasDom = typeof document !== "undefined";
// Register DOM adapter as the render dispatch target for the evaluator.
_renderExprFn = function(expr, env) { return renderToDom(expr, env, null); };
var SVG_NS = "http://www.w3.org/2000/svg";
var MATH_NS = "http://www.w3.org/1998/Math/MathML";
function domCreateElement(tag, ns) {
if (!_hasDom) return null;
if (ns) return document.createElementNS(ns, tag);
return document.createElement(tag);
}
function createTextNode(s) {
return _hasDom ? document.createTextNode(s) : null;
}
function createFragment() {
return _hasDom ? document.createDocumentFragment() : null;
}
function domAppend(parent, child) {
if (parent && child) parent.appendChild(child);
}
function domPrepend(parent, child) {
if (parent && child) parent.insertBefore(child, parent.firstChild);
}
function domSetAttr(el, name, val) {
if (el && el.setAttribute) el.setAttribute(name, val);
}
function domGetAttr(el, name) {
if (!el || !el.getAttribute) return NIL;
var v = el.getAttribute(name);
return v === null ? NIL : v;
}
function domRemoveAttr(el, name) {
if (el && el.removeAttribute) el.removeAttribute(name);
}
function domHasAttr(el, name) {
return !!(el && el.hasAttribute && el.hasAttribute(name));
}
function domParseHtml(html) {
if (!_hasDom) return null;
var tpl = document.createElement("template");
tpl.innerHTML = html;
return tpl.content;
}
function domClone(node) {
return node && node.cloneNode ? node.cloneNode(true) : node;
}
function domParent(el) { return el ? el.parentNode : null; }
function domId(el) { return el && el.id ? el.id : NIL; }
function domNodeType(el) { return el ? el.nodeType : 0; }
function domNodeName(el) { return el ? el.nodeName : ""; }
function domTextContent(el) { return el ? el.textContent || el.nodeValue || "" : ""; }
function domSetTextContent(el, s) { if (el) { if (el.nodeType === 3 || el.nodeType === 8) el.nodeValue = s; else el.textContent = s; } }
function domIsFragment(el) { return el ? el.nodeType === 11 : false; }
function domIsChildOf(child, parent) { return !!(parent && child && child.parentNode === parent); }
function domIsActiveElement(el) { return _hasDom && el === document.activeElement; }
function domIsInputElement(el) {
if (!el || !el.tagName) return false;
var t = el.tagName;
return t === "INPUT" || t === "TEXTAREA" || t === "SELECT";
}
function domFirstChild(el) { return el ? el.firstChild : null; }
function domNextSibling(el) { return el ? el.nextSibling : null; }
function domChildList(el) {
if (!el || !el.childNodes) return [];
return Array.prototype.slice.call(el.childNodes);
}
function domAttrList(el) {
if (!el || !el.attributes) return [];
var r = [];
for (var i = 0; i < el.attributes.length; i++) {
r.push([el.attributes[i].name, el.attributes[i].value]);
}
return r;
}
function domInsertBefore(parent, node, ref) {
if (parent && node) parent.insertBefore(node, ref || null);
}
function domInsertAfter(ref, node) {
if (ref && ref.parentNode && node) {
ref.parentNode.insertBefore(node, ref.nextSibling);
}
}
function domRemoveChild(parent, child) {
if (parent && child && child.parentNode === parent) parent.removeChild(child);
}
function domReplaceChild(parent, newChild, oldChild) {
if (parent && newChild && oldChild) parent.replaceChild(newChild, oldChild);
}
function domSetInnerHtml(el, html) {
if (el) el.innerHTML = html;
}
function domInsertAdjacentHtml(el, pos, html) {
if (el && el.insertAdjacentHTML) el.insertAdjacentHTML(pos, html);
}
function domGetStyle(el, prop) {
return el && el.style ? el.style[prop] || "" : "";
}
function domSetStyle(el, prop, val) {
if (el && el.style) el.style[prop] = val;
}
function domGetProp(el, name) { return el ? el[name] : NIL; }
function domSetProp(el, name, val) { if (el) el[name] = val; }
function domAddClass(el, cls) {
if (el && el.classList) el.classList.add(cls);
}
function domRemoveClass(el, cls) {
if (el && el.classList) el.classList.remove(cls);
}
function domDispatch(el, name, detail) {
if (!_hasDom || !el) return false;
var evt = new CustomEvent(name, { bubbles: true, cancelable: true, detail: detail || {} });
return el.dispatchEvent(evt);
}
function domQuery(sel) {
return _hasDom ? document.querySelector(sel) : null;
}
function domQueryAll(root, sel) {
if (!root || !root.querySelectorAll) return [];
return Array.prototype.slice.call(root.querySelectorAll(sel));
}
function domTagName(el) { return el && el.tagName ? el.tagName : ""; }
// =========================================================================
// Performance overrides — replace transpiled spec with imperative JS
// =========================================================================
// Override renderDomComponent: imperative kwarg parsing, no reduce/assoc
renderDomComponent = function(comp, args, env, ns) {
// Parse keyword args imperatively
var kwargs = {};
var children = [];
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (arg && arg._kw && (i + 1) < args.length) {
kwargs[arg.name] = trampoline(evalExpr(args[i + 1], env));
i++; // skip value
} else {
children.push(arg);
}
}
// Build local env via prototype chain
var local = Object.create(componentClosure(comp));
// Copy caller env own properties
for (var k in env) if (env.hasOwnProperty(k)) local[k] = env[k];
// Bind params
var params = componentParams(comp);
for (var j = 0; j < params.length; j++) {
var p = params[j];
local[p] = p in kwargs ? kwargs[p] : NIL;
}
// Bind children
if (componentHasChildren(comp)) {
var childFrag = document.createDocumentFragment();
for (var c = 0; c < children.length; c++) {
var rendered = renderToDom(children[c], env, ns);
if (rendered) childFrag.appendChild(rendered);
}
local["children"] = childFrag;
}
return renderToDom(componentBody(comp), local, ns);
};
// Override renderDomElement: imperative attr parsing, no reduce/assoc
renderDomElement = function(tag, args, env, ns) {
var newNs = tag === "svg" ? SVG_NS : tag === "math" ? MATH_NS : ns;
var el = domCreateElement(tag, newNs);
var extraClasses = [];
var isVoid = contains(VOID_ELEMENTS, tag);
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (arg && arg._kw && (i + 1) < args.length) {
var attrName = arg.name;
var attrVal = trampoline(evalExpr(args[i + 1], env));
i++; // skip value
if (isNil(attrVal) || attrVal === false) continue;
if (attrName === "class" && attrVal && attrVal._styleValue) {
extraClasses.push(attrVal.className);
} else if (attrName === "style" && attrVal && attrVal._styleValue) {
extraClasses.push(attrVal.className);
} else if (contains(BOOLEAN_ATTRS, attrName)) {
if (isSxTruthy(attrVal)) el.setAttribute(attrName, "");
} else if (attrVal === true) {
el.setAttribute(attrName, "");
} else {
el.setAttribute(attrName, String(attrVal));
}
} else {
if (!isVoid) {
var child = renderToDom(arg, env, newNs);
if (child) el.appendChild(child);
}
}
}
if (extraClasses.length) {
var existing = el.getAttribute("class") || "";
el.setAttribute("class", (existing ? existing + " " : "") + extraClasses.join(" "));
}
return el;
};
// =========================================================================
// Platform interface — Engine pure logic (browser + node compatible)
// =========================================================================
function browserLocationHref() {
return typeof location !== "undefined" ? location.href : "";
}
function browserSameOrigin(url) {
try { return new URL(url, location.href).origin === location.origin; }
catch (e) { return true; }
}
function browserPushState(url) {
if (typeof history !== "undefined") {
try { history.pushState({ sxUrl: url, scrollY: typeof window !== "undefined" ? window.scrollY : 0 }, "", url); }
catch (e) {}
}
}
function browserReplaceState(url) {
if (typeof history !== "undefined") {
try { history.replaceState({ sxUrl: url, scrollY: typeof window !== "undefined" ? window.scrollY : 0 }, "", url); }
catch (e) {}
}
}
function nowMs() { return Date.now(); }
function parseHeaderValue(s) {
if (!s) return null;
try {
if (s.charAt(0) === "{" && s.charAt(1) === ":") return parse(s);
return JSON.parse(s);
} catch (e) { return null; }
}
// =========================================================================
// Platform interface — Orchestration (browser-only)
// =========================================================================
// --- Browser/Network ---
function browserNavigate(url) {
if (typeof location !== "undefined") location.assign(url);
}
function browserReload() {
if (typeof location !== "undefined") location.reload();
}
function browserScrollTo(x, y) {
if (typeof window !== "undefined") window.scrollTo(x, y);
}
function browserMediaMatches(query) {
if (typeof window === "undefined") return false;
return window.matchMedia(query).matches;
}
function browserConfirm(msg) {
if (typeof window === "undefined") return false;
return window.confirm(msg);
}
function browserPrompt(msg) {
if (typeof window === "undefined") return NIL;
var r = window.prompt(msg);
return r === null ? NIL : r;
}
function csrfToken() {
if (!_hasDom) return NIL;
var m = document.querySelector('meta[name="csrf-token"]');
return m ? m.getAttribute("content") : NIL;
}
function isCrossOrigin(url) {
try {
var h = new URL(url, location.href).hostname;
return h !== location.hostname &&
(h.indexOf(".rose-ash.com") >= 0 || h.indexOf(".localhost") >= 0);
} catch (e) { return false; }
}
// --- Promises ---
function promiseResolve(val) { return Promise.resolve(val); }
function promiseCatch(p, fn) { return p && p.catch ? p.catch(fn) : p; }
// --- Abort controllers ---
var _controllers = typeof WeakMap !== "undefined" ? new WeakMap() : null;
function abortPrevious(el) {
if (_controllers) {
var prev = _controllers.get(el);
if (prev) prev.abort();
}
}
function trackController(el, ctrl) {
if (_controllers) _controllers.set(el, ctrl);
}
function newAbortController() {
return typeof AbortController !== "undefined" ? new AbortController() : { signal: null, abort: function() {} };
}
function controllerSignal(ctrl) { return ctrl ? ctrl.signal : null; }
function isAbortError(err) { return err && err.name === "AbortError"; }
// --- Timers ---
function setTimeout_(fn, ms) { return setTimeout(fn, ms || 0); }
function setInterval_(fn, ms) { return setInterval(fn, ms || 1000); }
function clearTimeout_(id) { clearTimeout(id); }
function requestAnimationFrame_(fn) {
if (typeof requestAnimationFrame !== "undefined") requestAnimationFrame(fn);
else setTimeout(fn, 16);
}
// --- Fetch ---
function fetchRequest(config, successFn, errorFn) {
var opts = { method: config.method, headers: config.headers };
if (config.signal) opts.signal = config.signal;
if (config.body && config.method !== "GET") opts.body = config.body;
if (config["cross-origin"]) opts.credentials = "include";
var p = (config.preloaded && config.preloaded !== NIL)
? Promise.resolve({
ok: true, status: 200,
headers: new Headers({ "Content-Type": config.preloaded["content-type"] || "" }),
text: function() { return Promise.resolve(config.preloaded.text); }
})
: fetch(config.url, opts);
return p.then(function(resp) {
return resp.text().then(function(text) {
var getHeader = function(name) {
var v = resp.headers.get(name);
return v === null ? NIL : v;
};
return successFn(resp.ok, resp.status, getHeader, text);
});
}).catch(function(err) {
return errorFn(err);
});
}
function fetchLocation(headerVal) {
if (!_hasDom) return;
var locUrl = headerVal;
try { var obj = JSON.parse(headerVal); locUrl = obj.path || obj; } catch (e) {}
fetch(locUrl, { headers: { "SX-Request": "true" } }).then(function(r) {
return r.text().then(function(t) {
var main = document.getElementById("main-panel");
if (main) {
main.innerHTML = t;
postSwap(main);
try { history.pushState({ sxUrl: locUrl }, "", locUrl); } catch (e) {}
}
});
});
}
function fetchAndRestore(main, url, headers, scrollY) {
var opts = { headers: headers };
try {
var h = new URL(url, location.href).hostname;
if (h !== location.hostname &&
(h.indexOf(".rose-ash.com") >= 0 || h.indexOf(".localhost") >= 0)) {
opts.credentials = "include";
}
} catch (e) {}
fetch(url, opts).then(function(resp) {
return resp.text().then(function(text) {
text = stripComponentScripts(text);
text = extractResponseCss(text);
text = text.trim();
if (text.charAt(0) === "(") {
try {
var dom = sxRender(text);
var container = document.createElement("div");
container.appendChild(dom);
processOobSwaps(container, function(t, oob, s) {
swapDomNodes(t, oob, s);
sxHydrate(t);
processElements(t);
});
var newMain = container.querySelector("#main-panel");
morphChildren(main, newMain || container);
postSwap(main);
if (typeof window !== "undefined") window.scrollTo(0, scrollY || 0);
} catch (err) {
console.error("sx-ref popstate error:", err);
location.reload();
}
} else {
var parser = new DOMParser();
var doc = parser.parseFromString(text, "text/html");
var newMain = doc.getElementById("main-panel");
if (newMain) {
morphChildren(main, newMain);
postSwap(main);
if (typeof window !== "undefined") window.scrollTo(0, scrollY || 0);
} else {
location.reload();
}
}
});
}).catch(function() { location.reload(); });
}
function fetchPreload(url, headers, cache) {
fetch(url, { headers: headers }).then(function(resp) {
if (!resp.ok) return;
var ct = resp.headers.get("Content-Type") || "";
return resp.text().then(function(text) {
preloadCacheSet(cache, url, text, ct);
});
}).catch(function() { /* ignore */ });
}
// --- Request body building ---
function buildRequestBody(el, method, url) {
if (!_hasDom) return { body: null, url: url, "content-type": NIL };
var body = null;
var ct = NIL;
var finalUrl = url;
var isJson = el.getAttribute("sx-encoding") === "json";
if (method !== "GET") {
var form = el.closest("form") || (el.tagName === "FORM" ? el : null);
if (form) {
if (isJson) {
var fd = new FormData(form);
var obj = {};
fd.forEach(function(v, k) {
if (obj[k] !== undefined) {
if (!Array.isArray(obj[k])) obj[k] = [obj[k]];
obj[k].push(v);
} else { obj[k] = v; }
});
body = JSON.stringify(obj);
ct = "application/json";
} else {
body = new URLSearchParams(new FormData(form));
ct = "application/x-www-form-urlencoded";
}
}
}
// sx-params
var paramsSpec = el.getAttribute("sx-params");
if (paramsSpec && body instanceof URLSearchParams) {
if (paramsSpec === "none") {
body = new URLSearchParams();
} else if (paramsSpec.indexOf("not ") === 0) {
paramsSpec.substring(4).split(",").forEach(function(k) { body.delete(k.trim()); });
} else if (paramsSpec !== "*") {
var allowed = paramsSpec.split(",").map(function(s) { return s.trim(); });
var filtered = new URLSearchParams();
allowed.forEach(function(k) {
body.getAll(k).forEach(function(v) { filtered.append(k, v); });
});
body = filtered;
}
}
// sx-include
var includeSel = el.getAttribute("sx-include");
if (includeSel && method !== "GET") {
if (!body) body = new URLSearchParams();
document.querySelectorAll(includeSel).forEach(function(inp) {
if (inp.name) body.append(inp.name, inp.value);
});
}
// sx-vals
var valsAttr = el.getAttribute("sx-vals");
if (valsAttr) {
try {
var vals = valsAttr.charAt(0) === "{" && valsAttr.charAt(1) === ":" ? parse(valsAttr) : JSON.parse(valsAttr);
if (method === "GET") {
for (var vk in vals) finalUrl += (finalUrl.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(vk) + "=" + encodeURIComponent(vals[vk]);
} else if (body instanceof URLSearchParams) {
for (var vk2 in vals) body.append(vk2, vals[vk2]);
} else if (!body) {
body = new URLSearchParams();
for (var vk3 in vals) body.append(vk3, vals[vk3]);
ct = "application/x-www-form-urlencoded";
}
} catch (e) {}
}
// GET form data → URL
if (method === "GET") {
var form2 = el.closest("form") || (el.tagName === "FORM" ? el : null);
if (form2) {
var qs = new URLSearchParams(new FormData(form2)).toString();
if (qs) finalUrl += (finalUrl.indexOf("?") >= 0 ? "&" : "?") + qs;
}
if ((el.tagName === "INPUT" || el.tagName === "SELECT" || el.tagName === "TEXTAREA") && el.name) {
finalUrl += (finalUrl.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(el.name) + "=" + encodeURIComponent(el.value);
}
}
return { body: body, url: finalUrl, "content-type": ct };
}
// --- Loading state ---
function showIndicator(el) {
if (!_hasDom) return NIL;
var sel = el.getAttribute("sx-indicator");
var ind = sel ? (document.querySelector(sel) || el.closest(sel)) : null;
if (ind) { ind.classList.add("sx-request"); ind.style.display = ""; }
return ind || NIL;
}
function disableElements(el) {
if (!_hasDom) return [];
var sel = el.getAttribute("sx-disabled-elt");
if (!sel) return [];
var elts = Array.prototype.slice.call(document.querySelectorAll(sel));
elts.forEach(function(e) { e.disabled = true; });
return elts;
}
function clearLoadingState(el, indicator, disabledElts) {
el.classList.remove("sx-request");
el.removeAttribute("aria-busy");
if (indicator && !isNil(indicator)) {
indicator.classList.remove("sx-request");
indicator.style.display = "none";
}
if (disabledElts) {
for (var i = 0; i < disabledElts.length; i++) disabledElts[i].disabled = false;
}
}
// --- DOM extras ---
function domQueryById(id) {
return _hasDom ? document.getElementById(id) : null;
}
function domMatches(el, sel) {
return el && el.matches ? el.matches(sel) : false;
}
function domClosest(el, sel) {
return el && el.closest ? el.closest(sel) : null;
}
function domBody() {
return _hasDom ? document.body : null;
}
function domHasClass(el, cls) {
return el && el.classList ? el.classList.contains(cls) : false;
}
function domAppendToHead(el) {
if (_hasDom && document.head) document.head.appendChild(el);
}
function domParseHtmlDocument(text) {
if (!_hasDom) return null;
return new DOMParser().parseFromString(text, "text/html");
}
function domOuterHtml(el) {
return el ? el.outerHTML : "";
}
function domBodyInnerHtml(doc) {
return doc && doc.body ? doc.body.innerHTML : "";
}
// --- Events ---
function preventDefault_(e) { if (e && e.preventDefault) e.preventDefault(); }
function elementValue(el) { return el && el.value !== undefined ? el.value : NIL; }
function domAddListener(el, event, fn, opts) {
if (!el || !el.addEventListener) return;
var o = {};
if (opts && !isNil(opts)) {
if (opts.once || opts["once"]) o.once = true;
}
el.addEventListener(event, function(e) {
try { fn(e); } catch (err) { logInfo("EVENT ERROR: " + event + " " + (err && err.message ? err.message : err)); console.error("[sx-ref] event handler error:", event, err); }
}, o);
}
// --- Validation ---
function validateForRequest(el) {
if (!_hasDom) return true;
var attr = el.getAttribute("sx-validate");
if (attr === null) {
var vForm = el.closest("[sx-validate]");
if (vForm) attr = vForm.getAttribute("sx-validate");
}
if (attr === null) return true; // no validation configured
var form = el.tagName === "FORM" ? el : el.closest("form");
if (form && !form.reportValidity()) return false;
if (attr && attr !== "true" && attr !== "") {
var fn = window[attr];
if (typeof fn === "function" && !fn(el)) return false;
}
return true;
}
// --- View Transitions ---
function withTransition(enabled, fn) {
if (enabled && _hasDom && document.startViewTransition) {
document.startViewTransition(fn);
} else {
fn();
}
}
// --- IntersectionObserver ---
function observeIntersection(el, fn, once, delay) {
if (!_hasDom || !("IntersectionObserver" in window)) { fn(); return; }
var fired = false;
var d = isNil(delay) ? 0 : delay;
var obs = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (!entry.isIntersecting) return;
if (once && fired) return;
fired = true;
if (once) obs.unobserve(el);
if (d) setTimeout(fn, d); else fn();
});
});
obs.observe(el);
}
// --- EventSource ---
function eventSourceConnect(url, el) {
var source = new EventSource(url);
source.addEventListener("error", function() { domDispatch(el, "sx:sseError", {}); });
source.addEventListener("open", function() { domDispatch(el, "sx:sseOpen", {}); });
if (typeof MutationObserver !== "undefined") {
var obs = new MutationObserver(function() {
if (!document.body.contains(el)) { source.close(); obs.disconnect(); }
});
obs.observe(document.body, { childList: true, subtree: true });
}
return source;
}
function eventSourceListen(source, event, fn) {
source.addEventListener(event, function(e) { fn(e.data); });
}
// --- Boost bindings ---
function bindBoostLink(el, _href) {
el.addEventListener("click", function(e) {
e.preventDefault();
// Re-read href from element at click time (not closed-over value)
var liveHref = el.getAttribute("href") || _href;
executeRequest(el, { method: "GET", url: liveHref }).then(function() {
try { history.pushState({ sxUrl: liveHref, scrollY: window.scrollY }, "", liveHref); } catch (err) {}
});
});
}
function bindBoostForm(form, _method, _action) {
form.addEventListener("submit", function(e) {
e.preventDefault();
// Re-read from element at submit time
var liveMethod = (form.getAttribute("method") || _method || "GET").toUpperCase();
var liveAction = form.getAttribute("action") || _action || location.href;
executeRequest(form, { method: liveMethod, url: liveAction }).then(function() {
try { history.pushState({ sxUrl: liveAction, scrollY: window.scrollY }, "", liveAction); } catch (err) {}
});
});
}
// --- Client-side route bindings ---
function bindClientRouteClick(link, _href, fallbackFn) {
link.addEventListener("click", function(e) {
e.preventDefault();
// Re-read href from element at click time (not closed-over value)
var liveHref = link.getAttribute("href") || _href;
var pathname = urlPathname(liveHref);
// Find target selector: sx-boost ancestor, explicit sx-target, or #main-panel
var boostEl = link.closest("[sx-boost]");
var targetSel = boostEl ? boostEl.getAttribute("sx-boost") : null;
if (!targetSel || targetSel === "true") {
targetSel = link.getAttribute("sx-target") || "#main-panel";
}
if (tryClientRoute(pathname, targetSel)) {
try { history.pushState({ sxUrl: liveHref, scrollY: window.scrollY }, "", liveHref); } catch (err) {}
if (typeof window !== "undefined") window.scrollTo(0, 0);
} else {
logInfo("sx:route server " + pathname);
executeRequest(link, { method: "GET", url: liveHref }).then(function() {
try { history.pushState({ sxUrl: liveHref, scrollY: window.scrollY }, "", liveHref); } catch (err) {}
});
}
});
}
function tryEvalContent(source, env) {
try {
var merged = merge(componentEnv);
if (env && !isNil(env)) {
var ks = Object.keys(env);
for (var i = 0; i < ks.length; i++) merged[ks[i]] = env[ks[i]];
}
return sxRenderWithEnv(source, merged);
} catch (e) {
logInfo("sx:route eval miss: " + (e && e.message ? e.message : e));
return NIL;
}
}
// Async eval with callback — used for pages with IO deps.
// Calls callback(rendered) when done, callback(null) on failure.
function tryAsyncEvalContent(source, env, callback) {
var merged = merge(componentEnv);
if (env && !isNil(env)) {
var ks = Object.keys(env);
for (var i = 0; i < ks.length; i++) merged[ks[i]] = env[ks[i]];
}
try {
var result = asyncSxRenderWithEnv(source, merged);
if (isPromise(result)) {
result.then(function(rendered) {
callback(rendered);
}).catch(function(e) {
logWarn("sx:async eval miss: " + (e && e.message ? e.message : e));
callback(null);
});
} else {
callback(result);
}
} catch (e) {
logInfo("sx:async eval miss: " + (e && e.message ? e.message : e));
callback(null);
}
}
function resolvePageData(pageName, params, callback) {
// Platform implementation: fetch page data via HTTP from /sx/data/ endpoint.
// The spec only knows about resolve-page-data(name, params, callback) —
// this function provides the concrete transport.
var url = "/sx/data/" + encodeURIComponent(pageName);
if (params && !isNil(params)) {
var qs = [];
var ks = Object.keys(params);
for (var i = 0; i < ks.length; i++) {
var v = params[ks[i]];
if (v !== null && v !== undefined && v !== NIL) {
qs.push(encodeURIComponent(ks[i]) + "=" + encodeURIComponent(v));
}
}
if (qs.length) url += "?" + qs.join("&");
}
var headers = { "SX-Request": "true" };
fetch(url, { headers: headers }).then(function(resp) {
if (!resp.ok) {
logWarn("sx:data resolve failed " + resp.status + " for " + pageName);
return;
}
return resp.text().then(function(text) {
try {
var exprs = parse(text);
var data = exprs.length === 1 ? exprs[0] : {};
callback(data || {});
} catch (e) {
logWarn("sx:data parse error for " + pageName + ": " + (e && e.message ? e.message : e));
}
});
}).catch(function(err) {
logWarn("sx:data resolve error for " + pageName + ": " + (err && err.message ? err.message : err));
});
}
function urlPathname(href) {
try {
return new URL(href, location.href).pathname;
} catch (e) {
// Fallback: strip query/hash
var idx = href.indexOf("?");
if (idx >= 0) href = href.substring(0, idx);
idx = href.indexOf("#");
if (idx >= 0) href = href.substring(0, idx);
return href;
}
}
// --- Inline handlers ---
function bindInlineHandler(el, eventName, body) {
el.addEventListener(eventName, new Function("event", body));
}
// --- Preload binding ---
function bindPreload(el, events, debounceMs, fn) {
var timer = null;
events.forEach(function(evt) {
el.addEventListener(evt, function() {
if (debounceMs) {
clearTimeout(timer);
timer = setTimeout(fn, debounceMs);
} else {
fn();
}
});
});
}
// --- Processing markers ---
var PROCESSED = "_sxBound";
function markProcessed(el, key) { el[PROCESSED + key] = true; }
function isProcessed(el, key) { return !!el[PROCESSED + key]; }
// --- Script cloning ---
function createScriptClone(dead) {
var live = document.createElement("script");
for (var i = 0; i < dead.attributes.length; i++)
live.setAttribute(dead.attributes[i].name, dead.attributes[i].value);
live.textContent = dead.textContent;
return live;
}
// --- SX API references ---
function sxRender(source) {
var SxObj = typeof Sx !== "undefined" ? Sx : null;
if (SxObj && SxObj.render) return SxObj.render(source);
throw new Error("No SX renderer available");
}
function sxProcessScripts(root) {
var SxObj = typeof Sx !== "undefined" ? Sx : null;
var r = (root && root !== NIL) ? root : undefined;
if (SxObj && SxObj.processScripts) SxObj.processScripts(r);
}
function sxHydrate(root) {
var SxObj = typeof Sx !== "undefined" ? Sx : null;
var r = (root && root !== NIL) ? root : undefined;
if (SxObj && SxObj.hydrate) SxObj.hydrate(r);
}
function loadedComponentNames() {
var SxObj = typeof Sx !== "undefined" ? Sx : null;
if (!SxObj) return [];
var env = SxObj.componentEnv || (SxObj.getEnv ? SxObj.getEnv() : {});
return Object.keys(env).filter(function(k) { return k.charAt(0) === "~"; });
}
// --- Response processing ---
function stripComponentScripts(text) {
var SxObj = typeof Sx !== "undefined" ? Sx : null;
return text.replace(/<script[^>]*type="text\/sx"[^>]*data-components[^>]*>([\s\S]*?)<\/script>/gi,
function(_, defs) { if (SxObj && SxObj.loadComponents) SxObj.loadComponents(defs); return ""; });
}
function extractResponseCss(text) {
if (!_hasDom) return text;
var target = document.getElementById("sx-css");
if (!target) return text;
return text.replace(/<style[^>]*data-sx-css[^>]*>([\s\S]*?)<\/style>/gi,
function(_, css) { target.textContent += css; return ""; });
}
function selectFromContainer(container, sel) {
var frag = document.createDocumentFragment();
sel.split(",").forEach(function(s) {
container.querySelectorAll(s.trim()).forEach(function(m) { frag.appendChild(m); });
});
return frag;
}
function childrenToFragment(container) {
var frag = document.createDocumentFragment();
while (container.firstChild) frag.appendChild(container.firstChild);
return frag;
}
function selectHtmlFromDoc(doc, sel) {
var parts = sel.split(",").map(function(s) { return s.trim(); });
var frags = [];
parts.forEach(function(s) {
doc.querySelectorAll(s).forEach(function(m) { frags.push(m.outerHTML); });
});
return frags.join("");
}
// --- Parsing ---
function tryParseJson(s) {
if (!s) return NIL;
try { return JSON.parse(s); } catch (e) { return NIL; }
}
// =========================================================================
// Platform interface — CSSX (style dictionary)
// =========================================================================
function fnv1aHash(input) {
var h = 0x811c9dc5;
for (var i = 0; i < input.length; i++) {
h ^= input.charCodeAt(i);
h = (h * 0x01000193) >>> 0;
}
return h.toString(16).padStart(8, "0").substring(0, 6);
}
function compileRegex(pattern) {
try { return new RegExp(pattern); } catch (e) { return null; }
}
function regexMatch(re, s) {
if (!re) return NIL;
var m = s.match(re);
return m ? Array.prototype.slice.call(m) : NIL;
}
function regexReplaceGroups(tmpl, match) {
var result = tmpl;
for (var j = 1; j < match.length; j++) {
result = result.split("{" + (j - 1) + "}").join(match[j]);
}
return result;
}
function makeStyleValue_(cn, decls, media, pseudo, kf) {
return new StyleValue(cn, decls || "", media || [], pseudo || [], kf || []);
}
function styleValueDeclarations(sv) { return sv.declarations; }
function styleValueMediaRules(sv) { return sv.mediaRules; }
function styleValuePseudoRules(sv) { return sv.pseudoRules; }
function styleValueKeyframes_(sv) { return sv.keyframes; }
function injectStyleValue(sv, atoms) {
if (_injectedStyles[sv.className]) return;
_injectedStyles[sv.className] = true;
if (!_hasDom) return;
var cssTarget = document.getElementById("sx-css");
if (!cssTarget) return;
var rules = [];
// Child-selector atoms are now routed to pseudoRules by the resolver
// with selector ">:not(:first-child)", so base declarations are always
// applied directly to the class.
if (sv.declarations) {
rules.push("." + sv.className + "{" + sv.declarations + "}");
}
for (var pi = 0; pi < sv.pseudoRules.length; pi++) {
var sel = sv.pseudoRules[pi][0], decls = sv.pseudoRules[pi][1];
if (sel.indexOf("&") >= 0) {
rules.push(sel.replace(/&/g, "." + sv.className) + "{" + decls + "}");
} else {
rules.push("." + sv.className + sel + "{" + decls + "}");
}
}
for (var mi = 0; mi < sv.mediaRules.length; mi++) {
rules.push("@media " + sv.mediaRules[mi][0] + "{." + sv.className + "{" + sv.mediaRules[mi][1] + "}}");
}
for (var ki = 0; ki < sv.keyframes.length; ki++) {
rules.push(sv.keyframes[ki][1]);
}
cssTarget.textContent += rules.join("");
}
// Replace stub css primitive with real CSSX implementation
PRIMITIVES["css"] = function() {
var atoms = [];
for (var i = 0; i < arguments.length; i++) {
var a = arguments[i];
if (isNil(a) || a === false) continue;
atoms.push(isKw(a) ? a.name : String(a));
}
if (!atoms.length) return NIL;
return resolveStyle(atoms);
};
PRIMITIVES["merge-styles"] = function() {
var valid = [];
for (var i = 0; i < arguments.length; i++) {
if (isStyleValue(arguments[i])) valid.push(arguments[i]);
}
if (!valid.length) return NIL;
if (valid.length === 1) return valid[0];
return mergeStyleValues(valid);
};
// =========================================================================
// Platform interface — Boot (mount, hydrate, scripts, cookies)
// =========================================================================
function resolveMountTarget(target) {
if (typeof target === "string") return _hasDom ? document.querySelector(target) : null;
return target;
}
function sxRenderWithEnv(source, extraEnv) {
var env = extraEnv ? merge(componentEnv, extraEnv) : componentEnv;
var exprs = parse(source);
if (!_hasDom) return null;
var frag = document.createDocumentFragment();
for (var i = 0; i < exprs.length; i++) {
var node = renderToDom(exprs[i], env, null);
if (node) frag.appendChild(node);
}
return frag;
}
function getRenderEnv(extraEnv) {
return extraEnv ? merge(componentEnv, extraEnv) : componentEnv;
}
function mergeEnvs(base, newEnv) {
return newEnv ? merge(componentEnv, base, newEnv) : merge(componentEnv, base);
}
function sxLoadComponents(text) {
try {
var exprs = parse(text);
for (var i = 0; i < exprs.length; i++) trampoline(evalExpr(exprs[i], componentEnv));
} catch (err) {
logParseError("loadComponents", text, err);
throw err;
}
}
function setDocumentTitle(s) {
if (_hasDom) document.title = s || "";
}
function removeHeadElement(sel) {
if (!_hasDom) return;
var old = document.head.querySelector(sel);
if (old) old.parentNode.removeChild(old);
}
function querySxScripts(root) {
if (!_hasDom) return [];
var r = (root && root !== NIL) ? root : document;
return Array.prototype.slice.call(
r.querySelectorAll('script[type="text/sx"]'));
}
function queryStyleScripts() {
if (!_hasDom) return [];
return Array.prototype.slice.call(
document.querySelectorAll('script[type="text/sx-styles"]'));
}
function queryPageScripts() {
if (!_hasDom) return [];
return Array.prototype.slice.call(
document.querySelectorAll('script[type="text/sx-pages"]'));
}
// --- localStorage ---
function localStorageGet(key) {
try { var v = localStorage.getItem(key); return v === null ? NIL : v; }
catch (e) { return NIL; }
}
function localStorageSet(key, val) {
try { localStorage.setItem(key, val); } catch (e) {}
}
function localStorageRemove(key) {
try { localStorage.removeItem(key); } catch (e) {}
}
// --- Cookies ---
function setSxCompCookie(hash) {
if (_hasDom) document.cookie = "sx-comp-hash=" + hash + ";path=/;max-age=31536000;SameSite=Lax";
}
function clearSxCompCookie() {
if (_hasDom) document.cookie = "sx-comp-hash=;path=/;max-age=0;SameSite=Lax";
}
function setSxStylesCookie(hash) {
if (_hasDom) document.cookie = "sx-styles-hash=" + hash + ";path=/;max-age=31536000;SameSite=Lax";
}
function clearSxStylesCookie() {
if (_hasDom) document.cookie = "sx-styles-hash=;path=/;max-age=0;SameSite=Lax";
}
// --- Env helpers ---
function parseEnvAttr(el) {
var attr = el && el.getAttribute ? el.getAttribute("data-sx-env") : null;
if (!attr) return {};
try { return JSON.parse(attr); } catch (e) { return {}; }
}
function storeEnvAttr(el, base, newEnv) {
var merged = merge(base, newEnv);
if (el && el.setAttribute) el.setAttribute("data-sx-env", JSON.stringify(merged));
}
function toKebab(s) { return s.replace(/_/g, "-"); }
// --- Logging ---
function logInfo(msg) {
if (typeof console !== "undefined") console.log("[sx-ref] " + msg);
}
function logWarn(msg) {
if (typeof console !== "undefined") console.warn("[sx-ref] " + msg);
}
function logParseError(label, text, err) {
if (typeof console === "undefined") return;
var msg = err && err.message ? err.message : String(err);
var colMatch = msg.match(/col (\d+)/);
var lineMatch = msg.match(/line (\d+)/);
if (colMatch && text) {
var errLine = lineMatch ? parseInt(lineMatch[1]) : 1;
var errCol = parseInt(colMatch[1]);
var lines = text.split("\n");
var pos = 0;
for (var i = 0; i < errLine - 1 && i < lines.length; i++) pos += lines[i].length + 1;
pos += errCol;
var ws = 80;
var start = Math.max(0, pos - ws);
var end = Math.min(text.length, pos + ws);
console.error("[sx-ref] " + label + ":", msg,
"\n around error (pos ~" + pos + "):",
"\n \u00ab" + text.substring(start, pos) + "\u26d4" + text.substring(pos, end) + "\u00bb");
} else {
console.error("[sx-ref] " + label + ":", msg);
}
}
function parseAndLoadStyleDict(text) {
try { loadStyleDict(JSON.parse(text)); }
catch (e) { if (typeof console !== "undefined") console.warn("[sx-ref] style dict parse error", e); }
}
// =========================================================================
// Post-transpilation fixups
// =========================================================================
// The reference spec's call-lambda only handles Lambda objects, but HO forms
// (map, reduce, etc.) may receive native primitives. Wrap to handle both.
var _rawCallLambda = callLambda;
callLambda = function(f, args, callerEnv) {
if (typeof f === "function") return f.apply(null, args);
return _rawCallLambda(f, args, callerEnv);
};
// Expose render functions as primitives so SX code can call them
if (typeof renderToHtml === "function") PRIMITIVES["render-to-html"] = renderToHtml;
if (typeof renderToSx === "function") PRIMITIVES["render-to-sx"] = renderToSx;
if (typeof aser === "function") PRIMITIVES["aser"] = aser;
if (typeof renderToDom === "function") PRIMITIVES["render-to-dom"] = renderToDom;
// =========================================================================
// Async IO: Promise-aware rendering for client-side IO primitives
// =========================================================================
//
// IO primitives (query, current-user, etc.) return Promises on the client.
// asyncRenderToDom walks the component tree; when it encounters an IO
// primitive, it awaits the Promise and continues rendering.
//
// The sync evaluator/renderer is untouched. This is a separate async path
// used only when a page's component tree contains IO references.
var IO_PRIMITIVES = {};
function registerIoPrimitive(name, fn) {
IO_PRIMITIVES[name] = fn;
}
function isPromise(x) {
return x != null && typeof x === "object" && typeof x.then === "function";
}
// Async trampoline: resolves thunks, awaits Promises
function asyncTrampoline(val) {
if (isPromise(val)) return val.then(asyncTrampoline);
if (isThunk(val)) return asyncTrampoline(evalExpr(thunkExpr(val), thunkEnv(val)));
return val;
}
// Async eval: like trampoline(evalExpr(...)) but handles IO primitives
function asyncEval(expr, env) {
// Intercept IO primitive calls at the AST level
if (Array.isArray(expr) && expr.length > 0) {
var head = expr[0];
if (head && head._sym) {
var name = head.name;
if (IO_PRIMITIVES[name]) {
// Evaluate args, then call the IO primitive
return asyncEvalIoCall(name, expr.slice(1), env);
}
}
}
// Non-IO: use sync eval, but result might be a thunk
var result = evalExpr(expr, env);
return asyncTrampoline(result);
}
function asyncEvalIoCall(name, rawArgs, env) {
// Parse keyword args and positional args, evaluating each (may be async)
var kwargs = {};
var args = [];
var promises = [];
var i = 0;
while (i < rawArgs.length) {
var arg = rawArgs[i];
if (arg && arg._kw && (i + 1) < rawArgs.length) {
var kName = arg.name;
var kVal = asyncEval(rawArgs[i + 1], env);
if (isPromise(kVal)) {
(function(k) { promises.push(kVal.then(function(v) { kwargs[k] = v; })); })(kName);
} else {
kwargs[kName] = kVal;
}
i += 2;
} else {
var aVal = asyncEval(arg, env);
if (isPromise(aVal)) {
(function(idx) { promises.push(aVal.then(function(v) { args[idx] = v; })); })(args.length);
args.push(null); // placeholder
} else {
args.push(aVal);
}
i++;
}
}
var ioFn = IO_PRIMITIVES[name];
if (promises.length > 0) {
return Promise.all(promises).then(function() { return ioFn(args, kwargs); });
}
return ioFn(args, kwargs);
}
// Async render-to-dom: returns Promise<Node> or Node
function asyncRenderToDom(expr, env, ns) {
// Literals
if (expr === NIL || expr === null || expr === undefined) return null;
if (expr === true || expr === false) return null;
if (typeof expr === "string") return document.createTextNode(expr);
if (typeof expr === "number") return document.createTextNode(String(expr));
// Symbol -> async eval then render
if (expr && expr._sym) {
var val = asyncEval(expr, env);
if (isPromise(val)) return val.then(function(v) { return asyncRenderToDom(v, env, ns); });
return asyncRenderToDom(val, env, ns);
}
// Keyword
if (expr && expr._kw) return document.createTextNode(expr.name);
// DocumentFragment / DOM nodes pass through
if (expr instanceof DocumentFragment || (expr && expr.nodeType)) return expr;
// Dict -> skip
if (expr && typeof expr === "object" && !Array.isArray(expr)) return null;
// List
if (!Array.isArray(expr) || expr.length === 0) return null;
var head = expr[0];
if (!head) return null;
// Symbol head
if (head._sym) {
var hname = head.name;
// IO primitive
if (IO_PRIMITIVES[hname]) {
var ioResult = asyncEval(expr, env);
if (isPromise(ioResult)) return ioResult.then(function(v) { return asyncRenderToDom(v, env, ns); });
return asyncRenderToDom(ioResult, env, ns);
}
// Fragment
if (hname === "<>") return asyncRenderChildren(expr.slice(1), env, ns);
// raw!
if (hname === "raw!") {
return asyncEvalRaw(expr.slice(1), env);
}
// Special forms that need async handling
if (hname === "if") return asyncRenderIf(expr, env, ns);
if (hname === "when") return asyncRenderWhen(expr, env, ns);
if (hname === "cond") return asyncRenderCond(expr, env, ns);
if (hname === "case") return asyncRenderCase(expr, env, ns);
if (hname === "let" || hname === "let*") return asyncRenderLet(expr, env, ns);
if (hname === "begin" || hname === "do") return asyncRenderChildren(expr.slice(1), env, ns);
if (hname === "map") return asyncRenderMap(expr, env, ns);
if (hname === "map-indexed") return asyncRenderMapIndexed(expr, env, ns);
if (hname === "for-each") return asyncRenderMap(expr, env, ns);
// define/defcomp/defmacro — eval for side effects
if (hname === "define" || hname === "defcomp" || hname === "defmacro" ||
hname === "defstyle" || hname === "defkeyframes" || hname === "defhandler") {
trampoline(evalExpr(expr, env));
return null;
}
// quote
if (hname === "quote") return null;
// lambda/fn
if (hname === "lambda" || hname === "fn") {
trampoline(evalExpr(expr, env));
return null;
}
// and/or — eval and render result
if (hname === "and" || hname === "or" || hname === "->") {
var aoResult = asyncEval(expr, env);
if (isPromise(aoResult)) return aoResult.then(function(v) { return asyncRenderToDom(v, env, ns); });
return asyncRenderToDom(aoResult, env, ns);
}
// set!
if (hname === "set!") {
asyncEval(expr, env);
return null;
}
// Component
if (hname.charAt(0) === "~") {
var comp = env[hname];
if (comp && comp._component) return asyncRenderComponent(comp, expr.slice(1), env, ns);
if (comp && comp._macro) {
var expanded = trampoline(expandMacro(comp, expr.slice(1), env));
return asyncRenderToDom(expanded, env, ns);
}
}
// Macro
if (env[hname] && env[hname]._macro) {
var mac = env[hname];
var expanded = trampoline(expandMacro(mac, expr.slice(1), env));
return asyncRenderToDom(expanded, env, ns);
}
// HTML tag
if (typeof renderDomElement === "function" && contains(HTML_TAGS, hname)) {
return asyncRenderElement(hname, expr.slice(1), env, ns);
}
// html: prefix
if (hname.indexOf("html:") === 0) {
return asyncRenderElement(hname.slice(5), expr.slice(1), env, ns);
}
// Custom element
if (hname.indexOf("-") >= 0 && expr.length > 1 && expr[1] && expr[1]._kw) {
return asyncRenderElement(hname, expr.slice(1), env, ns);
}
// SVG context
if (ns) return asyncRenderElement(hname, expr.slice(1), env, ns);
// Fallback: eval and render
var fResult = asyncEval(expr, env);
if (isPromise(fResult)) return fResult.then(function(v) { return asyncRenderToDom(v, env, ns); });
return asyncRenderToDom(fResult, env, ns);
}
// Non-symbol head: eval call
var cResult = asyncEval(expr, env);
if (isPromise(cResult)) return cResult.then(function(v) { return asyncRenderToDom(v, env, ns); });
return asyncRenderToDom(cResult, env, ns);
}
function asyncRenderChildren(exprs, env, ns) {
var frag = document.createDocumentFragment();
var pending = [];
for (var i = 0; i < exprs.length; i++) {
var result = asyncRenderToDom(exprs[i], env, ns);
if (isPromise(result)) {
// Insert placeholder, replace when resolved
var placeholder = document.createComment("async");
frag.appendChild(placeholder);
(function(ph) {
pending.push(result.then(function(node) {
if (node) ph.parentNode.replaceChild(node, ph);
else ph.parentNode.removeChild(ph);
}));
})(placeholder);
} else if (result) {
frag.appendChild(result);
}
}
if (pending.length > 0) {
return Promise.all(pending).then(function() { return frag; });
}
return frag;
}
function asyncRenderElement(tag, args, env, ns) {
var newNs = tag === "svg" ? SVG_NS : tag === "math" ? MATH_NS : ns;
var el = domCreateElement(tag, newNs);
var pending = [];
var isVoid = contains(VOID_ELEMENTS, tag);
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (arg && arg._kw && (i + 1) < args.length) {
var attrName = arg.name;
var attrVal = asyncEval(args[i + 1], env);
i++;
if (isPromise(attrVal)) {
(function(an, av) {
pending.push(av.then(function(v) {
if (!isNil(v) && v !== false) {
if (contains(BOOLEAN_ATTRS, an)) { if (isSxTruthy(v)) el.setAttribute(an, ""); }
else if (v === true) el.setAttribute(an, "");
else el.setAttribute(an, String(v));
}
}));
})(attrName, attrVal);
} else {
if (!isNil(attrVal) && attrVal !== false) {
if (attrName === "class" && attrVal && attrVal._styleValue) {
el.setAttribute("class", (el.getAttribute("class") || "") + " " + attrVal.className);
} else if (attrName === "style" && attrVal && attrVal._styleValue) {
el.setAttribute("class", (el.getAttribute("class") || "") + " " + attrVal.className);
} else if (contains(BOOLEAN_ATTRS, attrName)) {
if (isSxTruthy(attrVal)) el.setAttribute(attrName, "");
} else if (attrVal === true) {
el.setAttribute(attrName, "");
} else {
el.setAttribute(attrName, String(attrVal));
}
}
}
} else if (!isVoid) {
var child = asyncRenderToDom(arg, env, newNs);
if (isPromise(child)) {
var placeholder = document.createComment("async");
el.appendChild(placeholder);
(function(ph) {
pending.push(child.then(function(node) {
if (node) ph.parentNode.replaceChild(node, ph);
else ph.parentNode.removeChild(ph);
}));
})(placeholder);
} else if (child) {
el.appendChild(child);
}
}
}
if (pending.length > 0) return Promise.all(pending).then(function() { return el; });
return el;
}
function asyncRenderComponent(comp, args, env, ns) {
var kwargs = {};
var children = [];
var pending = [];
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (arg && arg._kw && (i + 1) < args.length) {
var kName = arg.name;
var kVal = asyncEval(args[i + 1], env);
if (isPromise(kVal)) {
(function(k) { pending.push(kVal.then(function(v) { kwargs[k] = v; })); })(kName);
} else {
kwargs[kName] = kVal;
}
i++;
} else {
children.push(arg);
}
}
function doRender() {
var local = Object.create(componentClosure(comp));
for (var k in env) if (env.hasOwnProperty(k)) local[k] = env[k];
var params = componentParams(comp);
for (var j = 0; j < params.length; j++) {
local[params[j]] = params[j] in kwargs ? kwargs[params[j]] : NIL;
}
if (componentHasChildren(comp)) {
var childResult = asyncRenderChildren(children, env, ns);
if (isPromise(childResult)) {
return childResult.then(function(childFrag) {
local["children"] = childFrag;
return asyncRenderToDom(componentBody(comp), local, ns);
});
}
local["children"] = childResult;
}
return asyncRenderToDom(componentBody(comp), local, ns);
}
if (pending.length > 0) return Promise.all(pending).then(doRender);
return doRender();
}
function asyncRenderIf(expr, env, ns) {
var cond = asyncEval(expr[1], env);
if (isPromise(cond)) {
return cond.then(function(v) {
return isSxTruthy(v)
? asyncRenderToDom(expr[2], env, ns)
: (expr.length > 3 ? asyncRenderToDom(expr[3], env, ns) : null);
});
}
return isSxTruthy(cond)
? asyncRenderToDom(expr[2], env, ns)
: (expr.length > 3 ? asyncRenderToDom(expr[3], env, ns) : null);
}
function asyncRenderWhen(expr, env, ns) {
var cond = asyncEval(expr[1], env);
if (isPromise(cond)) {
return cond.then(function(v) {
return isSxTruthy(v) ? asyncRenderChildren(expr.slice(2), env, ns) : null;
});
}
return isSxTruthy(cond) ? asyncRenderChildren(expr.slice(2), env, ns) : null;
}
function asyncRenderCond(expr, env, ns) {
var clauses = expr.slice(1);
function step(idx) {
if (idx >= clauses.length) return null;
var clause = clauses[idx];
if (!Array.isArray(clause) || clause.length < 2) return step(idx + 1);
var test = clause[0];
if ((test && test._sym && (test.name === "else" || test.name === ":else")) ||
(test && test._kw && test.name === "else")) {
return asyncRenderToDom(clause[1], env, ns);
}
var v = asyncEval(test, env);
if (isPromise(v)) return v.then(function(r) { return isSxTruthy(r) ? asyncRenderToDom(clause[1], env, ns) : step(idx + 1); });
return isSxTruthy(v) ? asyncRenderToDom(clause[1], env, ns) : step(idx + 1);
}
return step(0);
}
function asyncRenderCase(expr, env, ns) {
var matchVal = asyncEval(expr[1], env);
function doCase(mv) {
var clauses = expr.slice(2);
for (var i = 0; i < clauses.length - 1; i += 2) {
var test = clauses[i];
if ((test && test._kw && test.name === "else") ||
(test && test._sym && (test.name === "else" || test.name === ":else"))) {
return asyncRenderToDom(clauses[i + 1], env, ns);
}
var tv = trampoline(evalExpr(test, env));
if (mv === tv || (typeof mv === "string" && typeof tv === "string" && mv === tv)) {
return asyncRenderToDom(clauses[i + 1], env, ns);
}
}
return null;
}
if (isPromise(matchVal)) return matchVal.then(doCase);
return doCase(matchVal);
}
function asyncRenderLet(expr, env, ns) {
var bindings = expr[1];
var local = Object.create(env);
for (var k in env) if (env.hasOwnProperty(k)) local[k] = env[k];
function bindStep(idx) {
if (!Array.isArray(bindings)) return asyncRenderChildren(expr.slice(2), local, ns);
// Nested pairs: ((a 1) (b 2))
if (bindings.length > 0 && Array.isArray(bindings[0])) {
if (idx >= bindings.length) return asyncRenderChildren(expr.slice(2), local, ns);
var b = bindings[idx];
var vname = b[0]._sym ? b[0].name : String(b[0]);
var val = asyncEval(b[1], local);
if (isPromise(val)) return val.then(function(v) { local[vname] = v; return bindStep(idx + 1); });
local[vname] = val;
return bindStep(idx + 1);
}
// Flat pairs: (a 1 b 2)
if (idx >= bindings.length) return asyncRenderChildren(expr.slice(2), local, ns);
var vn = bindings[idx]._sym ? bindings[idx].name : String(bindings[idx]);
var vv = asyncEval(bindings[idx + 1], local);
if (isPromise(vv)) return vv.then(function(v) { local[vn] = v; return bindStep(idx + 2); });
local[vn] = vv;
return bindStep(idx + 2);
}
return bindStep(0);
}
function asyncRenderMap(expr, env, ns) {
var fn = asyncEval(expr[1], env);
var coll = asyncEval(expr[2], env);
function doMap(f, c) {
if (!Array.isArray(c)) return null;
var frag = document.createDocumentFragment();
var pending = [];
for (var i = 0; i < c.length; i++) {
var item = c[i];
var result;
if (f && f._lambda) {
var lenv = Object.create(f.closure || env);
for (var k in env) if (env.hasOwnProperty(k)) lenv[k] = env[k];
lenv[f.params[0]] = item;
result = asyncRenderToDom(f.body, lenv, null);
} else if (typeof f === "function") {
var r = f(item);
result = isPromise(r) ? r.then(function(v) { return asyncRenderToDom(v, env, null); }) : asyncRenderToDom(r, env, null);
} else {
result = asyncRenderToDom(item, env, null);
}
if (isPromise(result)) {
var ph = document.createComment("async");
frag.appendChild(ph);
(function(p) { pending.push(result.then(function(n) { if (n) p.parentNode.replaceChild(n, p); else p.parentNode.removeChild(p); })); })(ph);
} else if (result) {
frag.appendChild(result);
}
}
if (pending.length) return Promise.all(pending).then(function() { return frag; });
return frag;
}
if (isPromise(fn) || isPromise(coll)) {
return Promise.all([isPromise(fn) ? fn : Promise.resolve(fn), isPromise(coll) ? coll : Promise.resolve(coll)])
.then(function(r) { return doMap(r[0], r[1]); });
}
return doMap(fn, coll);
}
function asyncRenderMapIndexed(expr, env, ns) {
var fn = asyncEval(expr[1], env);
var coll = asyncEval(expr[2], env);
function doMap(f, c) {
if (!Array.isArray(c)) return null;
var frag = document.createDocumentFragment();
var pending = [];
for (var i = 0; i < c.length; i++) {
var item = c[i];
var result;
if (f && f._lambda) {
var lenv = Object.create(f.closure || env);
for (var k in env) if (env.hasOwnProperty(k)) lenv[k] = env[k];
lenv[f.params[0]] = i;
lenv[f.params[1]] = item;
result = asyncRenderToDom(f.body, lenv, null);
} else if (typeof f === "function") {
var r = f(i, item);
result = isPromise(r) ? r.then(function(v) { return asyncRenderToDom(v, env, null); }) : asyncRenderToDom(r, env, null);
} else {
result = asyncRenderToDom(item, env, null);
}
if (isPromise(result)) {
var ph = document.createComment("async");
frag.appendChild(ph);
(function(p) { pending.push(result.then(function(n) { if (n) p.parentNode.replaceChild(n, p); else p.parentNode.removeChild(p); })); })(ph);
} else if (result) {
frag.appendChild(result);
}
}
if (pending.length) return Promise.all(pending).then(function() { return frag; });
return frag;
}
if (isPromise(fn) || isPromise(coll)) {
return Promise.all([isPromise(fn) ? fn : Promise.resolve(fn), isPromise(coll) ? coll : Promise.resolve(coll)])
.then(function(r) { return doMap(r[0], r[1]); });
}
return doMap(fn, coll);
}
function asyncEvalRaw(args, env) {
var parts = [];
var pending = [];
for (var i = 0; i < args.length; i++) {
var val = asyncEval(args[i], env);
if (isPromise(val)) {
(function(idx) {
pending.push(val.then(function(v) { parts[idx] = v; }));
})(parts.length);
parts.push(null);
} else {
parts.push(val);
}
}
function assemble() {
var html = "";
for (var j = 0; j < parts.length; j++) {
var p = parts[j];
if (p && p._rawHtml) html += p.html;
else if (typeof p === "string") html += p;
else if (p != null && !isNil(p)) html += String(p);
}
var el = document.createElement("span");
el.innerHTML = html;
var frag = document.createDocumentFragment();
while (el.firstChild) frag.appendChild(el.firstChild);
return frag;
}
if (pending.length) return Promise.all(pending).then(assemble);
return assemble();
}
// Async version of sxRenderWithEnv — returns Promise<DocumentFragment>
function asyncSxRenderWithEnv(source, extraEnv) {
var env = extraEnv ? merge(componentEnv, extraEnv) : componentEnv;
var exprs = parse(source);
if (!_hasDom) return Promise.resolve(null);
return asyncRenderChildren(exprs, env, null);
}
// IO proxy cache: key → { value, expires }
var _ioCache = {};
var IO_CACHE_TTL = 300000; // 5 minutes
// Register a server-proxied IO primitive: fetches from /sx/io/<name>
// Uses GET for short args, POST for long payloads (URL length safety).
// Results are cached client-side by (name + args) with a TTL.
function registerProxiedIo(name) {
registerIoPrimitive(name, function(args, kwargs) {
// Cache key: name + serialized args
var cacheKey = name;
for (var ci = 0; ci < args.length; ci++) cacheKey += "" + String(args[ci]);
for (var ck in kwargs) {
if (kwargs.hasOwnProperty(ck)) cacheKey += "" + ck + "=" + String(kwargs[ck]);
}
var cached = _ioCache[cacheKey];
if (cached && cached.expires > Date.now()) return cached.value;
var url = "/sx/io/" + encodeURIComponent(name);
var qs = [];
for (var i = 0; i < args.length; i++) {
qs.push("_arg" + i + "=" + encodeURIComponent(String(args[i])));
}
for (var k in kwargs) {
if (kwargs.hasOwnProperty(k)) {
qs.push(encodeURIComponent(k) + "=" + encodeURIComponent(String(kwargs[k])));
}
}
var queryStr = qs.join("&");
var fetchOpts;
if (queryStr.length > 1500) {
// POST with JSON body for long payloads
var sArgs = [];
for (var j = 0; j < args.length; j++) sArgs.push(String(args[j]));
var sKwargs = {};
for (var kk in kwargs) {
if (kwargs.hasOwnProperty(kk)) sKwargs[kk] = String(kwargs[kk]);
}
var postHeaders = { "SX-Request": "true", "Content-Type": "application/json" };
var csrf = csrfToken();
if (csrf && csrf !== NIL) postHeaders["X-CSRFToken"] = csrf;
fetchOpts = {
method: "POST",
headers: postHeaders,
body: JSON.stringify({ args: sArgs, kwargs: sKwargs })
};
} else {
if (queryStr) url += "?" + queryStr;
fetchOpts = { headers: { "SX-Request": "true" } };
}
var result = fetch(url, fetchOpts)
.then(function(resp) {
if (!resp.ok) {
logWarn("sx:io " + name + " failed " + resp.status);
return NIL;
}
return resp.text();
})
.then(function(text) {
if (!text || text === "nil") return NIL;
try {
var exprs = parse(text);
var val = exprs.length === 1 ? exprs[0] : exprs;
_ioCache[cacheKey] = { value: val, expires: Date.now() + IO_CACHE_TTL };
return val;
} catch (e) {
logWarn("sx:io " + name + " parse error: " + (e && e.message ? e.message : e));
return NIL;
}
})
.catch(function(e) {
logWarn("sx:io " + name + " network error: " + (e && e.message ? e.message : e));
return NIL;
});
// Cache the in-flight promise too (dedup concurrent calls for same args)
_ioCache[cacheKey] = { value: result, expires: Date.now() + IO_CACHE_TTL };
return result;
});
}
// Register IO deps as proxied primitives (idempotent, called per-page)
function registerIoDeps(names) {
if (!names || !names.length) return;
var registered = 0;
for (var i = 0; i < names.length; i++) {
var name = names[i];
if (!IO_PRIMITIVES[name]) {
registerProxiedIo(name);
registered++;
}
}
if (registered > 0) {
logInfo("sx:io registered " + registered + " proxied primitives: " + names.join(", "));
}
}
// Parser — compiled from parser.sx (see PLATFORM_PARSER_JS for ident char classes)
var parse = sxParse;
// =========================================================================
// Public API
// =========================================================================
var componentEnv = {};
function loadComponents(source) {
var exprs = parse(source);
for (var i = 0; i < exprs.length; i++) {
trampoline(evalExpr(exprs[i], componentEnv));
}
}
function render(source) {
if (!_hasDom) {
var exprs = parse(source);
var parts = [];
for (var i = 0; i < exprs.length; i++) parts.push(renderToHtml(exprs[i], merge(componentEnv)));
return parts.join("");
}
var exprs = parse(source);
var frag = document.createDocumentFragment();
for (var i = 0; i < exprs.length; i++) frag.appendChild(renderToDom(exprs[i], merge(componentEnv), null));
return frag;
}
function renderToString(source) {
var exprs = parse(source);
var parts = [];
for (var i = 0; i < exprs.length; i++) parts.push(renderToHtml(exprs[i], merge(componentEnv)));
return parts.join("");
}
var Sx = {
VERSION: "ref-2.0",
parse: parse,
parseAll: parse,
eval: function(expr, env) { return trampoline(evalExpr(expr, env || merge(componentEnv))); },
loadComponents: loadComponents,
render: render,
renderToString: renderToString,
serialize: serialize,
NIL: NIL,
Symbol: Symbol,
Keyword: Keyword,
isTruthy: isSxTruthy,
isNil: isNil,
componentEnv: componentEnv,
renderToHtml: function(expr, env) { return renderToHtml(expr, env || merge(componentEnv)); },
renderToSx: function(expr, env) { return renderToSx(expr, env || merge(componentEnv)); },
renderToDom: _hasDom ? function(expr, env, ns) { return renderToDom(expr, env || merge(componentEnv), ns || null); } : null,
parseTriggerSpec: typeof parseTriggerSpec === "function" ? parseTriggerSpec : null,
parseTime: typeof parseTime === "function" ? parseTime : null,
defaultTrigger: typeof defaultTrigger === "function" ? defaultTrigger : null,
parseSwapSpec: typeof parseSwapSpec === "function" ? parseSwapSpec : null,
parseRetrySpec: typeof parseRetrySpec === "function" ? parseRetrySpec : null,
nextRetryMs: typeof nextRetryMs === "function" ? nextRetryMs : null,
filterParams: typeof filterParams === "function" ? filterParams : null,
morphNode: typeof morphNode === "function" ? morphNode : null,
morphChildren: typeof morphChildren === "function" ? morphChildren : null,
swapDomNodes: typeof swapDomNodes === "function" ? swapDomNodes : null,
process: typeof processElements === "function" ? processElements : null,
executeRequest: typeof executeRequest === "function" ? executeRequest : null,
postSwap: typeof postSwap === "function" ? postSwap : null,
processScripts: typeof processSxScripts === "function" ? processSxScripts : null,
mount: typeof sxMount === "function" ? sxMount : null,
hydrate: typeof sxHydrateElements === "function" ? sxHydrateElements : null,
update: typeof sxUpdateElement === "function" ? sxUpdateElement : null,
renderComponent: typeof sxRenderComponent === "function" ? sxRenderComponent : null,
getEnv: function() { return componentEnv; },
resolveSuspense: typeof resolveSuspense === "function" ? resolveSuspense : null,
init: typeof bootInit === "function" ? bootInit : null,
scanRefs: scanRefs,
scanComponentsFromSource: scanComponentsFromSource,
transitiveDeps: transitiveDeps,
computeAllDeps: computeAllDeps,
componentsNeeded: componentsNeeded,
pageComponentBundle: pageComponentBundle,
pageCssClasses: pageCssClasses,
scanIoRefs: scanIoRefs,
transitiveIoRefs: transitiveIoRefs,
computeAllIoRefs: computeAllIoRefs,
componentPure_p: componentPure_p,
splitPathSegments: splitPathSegments,
parseRoutePattern: parseRoutePattern,
matchRoute: matchRoute,
findMatchingRoute: findMatchingRoute,
registerIo: typeof registerIoPrimitive === "function" ? registerIoPrimitive : null,
registerIoDeps: typeof registerIoDeps === "function" ? registerIoDeps : null,
asyncRender: typeof asyncSxRenderWithEnv === "function" ? asyncSxRenderWithEnv : null,
asyncRenderToDom: typeof asyncRenderToDom === "function" ? asyncRenderToDom : null,
_version: "ref-2.0 (boot+cssx+dom+engine+html+orchestration+parser+sx, bootstrap-compiled)"
};
// --- Popstate listener ---
if (typeof window !== "undefined") {
window.addEventListener("popstate", function(e) {
handlePopstate(e && e.state ? e.state.scrollY || 0 : 0);
});
}
// --- Auto-init ---
if (typeof document !== "undefined") {
var _sxInit = function() {
bootInit();
// Process any suspense resolutions that arrived before init
if (global.__sxPending) {
for (var pi = 0; pi < global.__sxPending.length; pi++) {
resolveSuspense(global.__sxPending[pi].id, global.__sxPending[pi].sx);
}
global.__sxPending = null;
}
// Set up direct resolution for future chunks
global.__sxResolve = function(id, sx) { resolveSuspense(id, sx); };
};
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", _sxInit);
} else {
_sxInit();
}
}
if (typeof module !== "undefined" && module.exports) module.exports = Sx;
else global.Sx = Sx;
})(typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : this);