diff --git a/shared/static/scripts/sx-browser.js b/shared/static/scripts/sx-browser.js index 71b452e..5990986 100644 --- a/shared/static/scripts/sx-browser.js +++ b/shared/static/scripts/sx-browser.js @@ -14,7 +14,7 @@ // ========================================================================= var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } }); - var SX_VERSION = "2026-03-06T21:35:37Z"; + var SX_VERSION = "2026-03-06T21:37:32Z"; function isNil(x) { return x === NIL || x === null || x === undefined; } function isSxTruthy(x) { return x !== false && !isNil(x); } @@ -2360,6 +2360,76 @@ callExpr.push(dictGet(kwargs, k)); } } var bootInit = function() { return (logInfo((String("sx-browser ") + String(SX_VERSION))), initCssTracking(), initStyleDict(), processPageScripts(), processSxScripts(NIL), sxHydrateElements(NIL), processElements(NIL)); }; + // === 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(!isEmpty(trimmed)) && endsWith(trimmed, "/"))) ? slice(trimmed, 0, (length(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, (length(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(!(length(pathSegs) == length(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(!(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(!isNil(params)) ? (function() { + var matched = merge(route, {}); + matched["params"] = params; + return (result = matched); +})() : NIL); +})(); +} } } + return result; +})(); }; + + // ========================================================================= // Platform interface — DOM adapter (browser-only) // ========================================================================= @@ -3497,6 +3567,10 @@ callExpr.push(dictGet(kwargs, k)); } } renderComponent: typeof sxRenderComponent === "function" ? sxRenderComponent : null, getEnv: function() { return componentEnv; }, init: typeof bootInit === "function" ? bootInit : null, + splitPathSegments: splitPathSegments, + parseRoutePattern: parseRoutePattern, + matchRoute: matchRoute, + findMatchingRoute: findMatchingRoute, _version: "ref-2.0 (boot+cssx+dom+engine+html+orchestration+parser+sx, bootstrap-compiled)" };