Phase 4: Client-side routing for SX expression URLs
Add sx-url-to-path to router.sx that converts SX expression URLs to old-style slash paths for route matching. find-matching-route now transparently handles both formats — the browser URL stays as the SX expression while matching uses the equivalent old-style path. /(language.(doc.introduction)) → /language/docs/introduction for matching but pushState keeps the SX URL in the browser bar. - router.sx: add _fn-to-segment (doc→docs, etc.), sx-url-to-path - router.sx: modify find-matching-route to convert SX URLs before matching - Rebootstrap sx-browser.js and sx_ref.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
// =========================================================================
|
||||
|
||||
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
|
||||
var SX_VERSION = "2026-03-11T23:22:03Z";
|
||||
var SX_VERSION = "2026-03-12T10:26:23Z";
|
||||
|
||||
function isNil(x) { return x === NIL || x === null || x === undefined; }
|
||||
function isSxTruthy(x) { return x !== false && !isNil(x); }
|
||||
@@ -3706,7 +3706,9 @@ callExpr.push(dictGet(kwargs, k)); } }
|
||||
|
||||
// find-matching-route
|
||||
var findMatchingRoute = function(path, routes) { return (function() {
|
||||
var pathSegs = splitPathSegments(path);
|
||||
var matchPath = (isSxTruthy(startsWith(path, "/(")) ? sxOr(sxUrlToPath(path), path) : path);
|
||||
return (function() {
|
||||
var pathSegs = splitPathSegments(matchPath);
|
||||
var result = NIL;
|
||||
{ var _c = routes; for (var _i = 0; _i < _c.length; _i++) { var route = _c[_i]; if (isSxTruthy(isNil(result))) {
|
||||
(function() {
|
||||
@@ -3719,8 +3721,24 @@ callExpr.push(dictGet(kwargs, k)); } }
|
||||
})();
|
||||
} } }
|
||||
return result;
|
||||
})();
|
||||
})(); };
|
||||
|
||||
// _fn-to-segment
|
||||
var _fnToSegment = function(name) { return (function() { var _m = name; if (_m == "doc") return "docs"; if (_m == "spec") return "specs"; if (_m == "bootstrapper") return "bootstrappers"; if (_m == "test") return "testing"; if (_m == "example") return "examples"; if (_m == "protocol") return "protocols"; if (_m == "essay") return "essays"; if (_m == "plan") return "plans"; if (_m == "reference-detail") return "reference"; return name; })(); };
|
||||
|
||||
// sx-url-to-path
|
||||
var sxUrlToPath = function(url) { return (isSxTruthy(!isSxTruthy((isSxTruthy(startsWith(url, "/(")) && endsWith(url, ")")))) ? NIL : (function() {
|
||||
var inner = slice(url, 2, (len(url) - 1));
|
||||
return (function() {
|
||||
var s = replace_(replace_(replace_(inner, ".", "/"), "(", ""), ")", "");
|
||||
return (function() {
|
||||
var segs = filter(function(s) { return !isSxTruthy(isEmpty(s)); }, split(s, "/"));
|
||||
return (String("/") + String(join("/", map(_fnToSegment, segs))));
|
||||
})();
|
||||
})();
|
||||
})()); };
|
||||
|
||||
|
||||
// === Transpiled from signals (reactive signal runtime) ===
|
||||
|
||||
@@ -4058,12 +4076,20 @@ return (isSxTruthy((_batchDepth == 0)) ? (function() {
|
||||
function domCallMethod() {
|
||||
var obj = arguments[0], method = arguments[1];
|
||||
var args = Array.prototype.slice.call(arguments, 2);
|
||||
console.log("[sx] dom-call-method:", obj, method, args);
|
||||
if (obj && typeof obj[method] === 'function') {
|
||||
try { return obj[method].apply(obj, args); }
|
||||
catch(e) { console.error("[sx] dom-call-method error:", e); return NIL; }
|
||||
}
|
||||
console.warn("[sx] dom-call-method: method not found or obj null", obj, method);
|
||||
return NIL;
|
||||
}
|
||||
// Post a message to an iframe's contentWindow without exposing the cross-origin
|
||||
// Window object to the SX evaluator (which would trigger _thunk access errors).
|
||||
function domPostMessage(iframe, msg, origin) {
|
||||
try {
|
||||
if (iframe && iframe.contentWindow) {
|
||||
iframe.contentWindow.postMessage(msg, origin || '*');
|
||||
}
|
||||
} catch(e) { console.error("[sx] domPostMessage error:", e); }
|
||||
return NIL;
|
||||
}
|
||||
|
||||
@@ -5272,6 +5298,7 @@ return (isSxTruthy((_batchDepth == 0)) ? (function() {
|
||||
PRIMITIVES["dom-get-prop"] = domGetProp;
|
||||
PRIMITIVES["dom-set-prop"] = domSetProp;
|
||||
PRIMITIVES["dom-call-method"] = domCallMethod;
|
||||
PRIMITIVES["dom-post-message"] = domPostMessage;
|
||||
PRIMITIVES["stop-propagation"] = stopPropagation_;
|
||||
PRIMITIVES["error-message"] = errorMessage;
|
||||
PRIMITIVES["schedule-idle"] = scheduleIdle;
|
||||
|
||||
Reference in New Issue
Block a user