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:
@@ -102,25 +102,64 @@
|
||||
|
||||
(define find-matching-route :effects []
|
||||
(fn ((path :as string) (routes :as list))
|
||||
(let ((path-segs (split-path-segments path))
|
||||
(result nil))
|
||||
(for-each
|
||||
(fn ((route :as dict))
|
||||
(when (nil? result)
|
||||
(let ((params (match-route-segments path-segs (get route "parsed"))))
|
||||
(when (not (nil? params))
|
||||
(let ((matched (merge route {})))
|
||||
(dict-set! matched "params" params)
|
||||
(set! result matched))))))
|
||||
routes)
|
||||
result)))
|
||||
;; If path is an SX expression URL, convert to old-style for matching.
|
||||
(let ((match-path (if (starts-with? path "/(")
|
||||
(or (sx-url-to-path path) path)
|
||||
path)))
|
||||
(let ((path-segs (split-path-segments match-path))
|
||||
(result nil))
|
||||
(for-each
|
||||
(fn ((route :as dict))
|
||||
(when (nil? result)
|
||||
(let ((params (match-route-segments path-segs (get route "parsed"))))
|
||||
(when (not (nil? params))
|
||||
(let ((matched (merge route {})))
|
||||
(dict-set! matched "params" params)
|
||||
(set! result matched))))))
|
||||
routes)
|
||||
result))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; 6. SX expression URL → old-style path conversion
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Converts /(language.(doc.introduction)) → /language/docs/introduction
|
||||
;; so client-side routing can match SX URLs against Flask-style patterns.
|
||||
|
||||
(define _fn-to-segment :effects []
|
||||
(fn ((name :as string))
|
||||
(case name
|
||||
"doc" "docs"
|
||||
"spec" "specs"
|
||||
"bootstrapper" "bootstrappers"
|
||||
"test" "testing"
|
||||
"example" "examples"
|
||||
"protocol" "protocols"
|
||||
"essay" "essays"
|
||||
"plan" "plans"
|
||||
"reference-detail" "reference"
|
||||
:else name)))
|
||||
|
||||
(define sx-url-to-path :effects []
|
||||
(fn ((url :as string))
|
||||
;; Convert an SX expression URL to an old-style slash path.
|
||||
;; "/(language.(doc.introduction))" → "/language/docs/introduction"
|
||||
;; Returns nil for non-SX URLs (those not starting with "/(" ).
|
||||
(if (not (and (starts-with? url "/(") (ends-with? url ")")))
|
||||
nil
|
||||
(let ((inner (slice url 2 (- (len url) 1))))
|
||||
;; "language.(doc.introduction)" → dots to slashes, strip parens
|
||||
(let ((s (replace (replace (replace inner "." "/") "(" "") ")" "")))
|
||||
;; "language/doc/introduction" → split, map names, rejoin
|
||||
(let ((segs (filter (fn (s) (not (empty? s))) (split s "/"))))
|
||||
(str "/" (join "/" (map _fn-to-segment segs)))))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Platform interface — none required
|
||||
;; --------------------------------------------------------------------------
|
||||
;; All functions use only pure primitives:
|
||||
;; split, slice, starts-with?, ends-with?, len, empty?,
|
||||
;; map, for-each, for-each-indexed, nth, get, dict-set!, merge,
|
||||
;; list, nil?, not, =
|
||||
;; split, slice, starts-with?, ends-with?, len, empty?, replace,
|
||||
;; map, filter, for-each, for-each-indexed, nth, get, dict-set!, merge,
|
||||
;; list, nil?, not, =, case, join, str
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
@@ -3973,4 +3973,4 @@ def render(expr, env=None):
|
||||
|
||||
def make_env(**kwargs):
|
||||
"""Create an environment with initial bindings."""
|
||||
return _Env(dict(kwargs))
|
||||
return _Env(dict(kwargs))
|
||||
|
||||
Reference in New Issue
Block a user