HS: remove bare @attr, set X @attr, JSON clean, FormEncoded, HTML join
- parser remove/set: accept bare @attr (not just [@attr]) - parser set: wrap tgt as (attr name tgt) when @attr follows target - runtime: hs-json-stringify walks sx-dict/list to emit plain JSON (strips _type key which leaked via JSON.stringify) - hs-coerce JSON / JSONString: use hs-json-stringify - hs-coerce FormEncoded: dict → k=v&... (list values repeat key) - hs-coerce HTML: join list elements; element → outerHTML +4 tests (button query in form, JSONString value, array→HTML, form | JSONString now fails only on key order). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -294,10 +294,13 @@
|
||||
hs-add-to!
|
||||
(fn
|
||||
(value target)
|
||||
(if
|
||||
(list? target)
|
||||
(append target (list value))
|
||||
(host-call target "push" value))))
|
||||
(cond
|
||||
((list? target)
|
||||
(if
|
||||
(some (fn (x) (= x value)) target)
|
||||
target
|
||||
(append target (list value))))
|
||||
(true (do (host-call target "push" value) target)))))
|
||||
|
||||
;; First/last within a specific scope.
|
||||
(define
|
||||
@@ -664,7 +667,11 @@
|
||||
(cond
|
||||
((nil? target) value)
|
||||
((string? target) (str target value))
|
||||
((list? target) (append target (list value)))
|
||||
((list? target)
|
||||
(if
|
||||
(some (fn (x) (= x value)) target)
|
||||
target
|
||||
(append target (list value))))
|
||||
((hs-element? target)
|
||||
(do
|
||||
(dom-insert-adjacent-html target "beforeend" (str value))
|
||||
@@ -688,6 +695,61 @@
|
||||
((fmt (cond ((nil? format) "text") ((or (= format "JSON") (= format "json") (= format "Object") (= format "object")) "json") ((or (= format "HTML") (= format "html")) "html") ((or (= format "Response") (= format "response")) "response") ((or (= format "Text") (= format "text")) "text") (true format))))
|
||||
(perform (list "io-fetch" url fmt)))))
|
||||
;; Array slicing (inclusive both ends)
|
||||
(define
|
||||
hs-json-escape
|
||||
(fn
|
||||
(s)
|
||||
(str
|
||||
"\""
|
||||
(let
|
||||
((out "") (i 0) (n (string-length s)))
|
||||
(define
|
||||
walk
|
||||
(fn
|
||||
()
|
||||
(when
|
||||
(< i n)
|
||||
(let
|
||||
((c (substring s i (+ i 1))))
|
||||
(set!
|
||||
out
|
||||
(cond
|
||||
((= c "\\") (str out "\\\\"))
|
||||
((= c "\"") (str out "\\\""))
|
||||
((= c "\n") (str out "\\n"))
|
||||
((= c "\r") (str out "\\r"))
|
||||
((= c "\t") (str out "\\t"))
|
||||
(true (str out c))))
|
||||
(set! i (+ i 1))
|
||||
(walk)))))
|
||||
(walk)
|
||||
out)
|
||||
"\"")))
|
||||
;; Collection: sorted by
|
||||
(define
|
||||
hs-json-stringify
|
||||
(fn
|
||||
(v)
|
||||
(cond
|
||||
((nil? v) "null")
|
||||
((= v true) "true")
|
||||
((= v false) "false")
|
||||
((number? v) (str v))
|
||||
((string? v) (hs-json-escape v))
|
||||
((list? v) (str "[" (join "," (map hs-json-stringify v)) "]"))
|
||||
((dict? v)
|
||||
(str
|
||||
"{"
|
||||
(join
|
||||
","
|
||||
(map
|
||||
(fn
|
||||
(k)
|
||||
(str (hs-json-escape k) ":" (hs-json-stringify (get v k))))
|
||||
(keys v)))
|
||||
"}"))
|
||||
(true (hs-json-escape (str v))))))
|
||||
;; Collection: sorted by descending
|
||||
(define
|
||||
hs-coerce
|
||||
(fn
|
||||
@@ -705,19 +767,39 @@
|
||||
((= type-name "Bool") (not (hs-falsy? value)))
|
||||
((= type-name "Boolean") (not (hs-falsy? value)))
|
||||
((= type-name "Array") (if (list? value) value (list value)))
|
||||
((= type-name "HTML") (str value))
|
||||
((= type-name "HTML")
|
||||
(cond
|
||||
((list? value) (join "" (map (fn (x) (str x)) value)))
|
||||
((hs-element? value) (host-get value "outerHTML"))
|
||||
(true (str value))))
|
||||
((= type-name "JSON")
|
||||
(cond
|
||||
((string? value) (guard (_e (true value)) (json-parse value)))
|
||||
((dict? value) (json-stringify value))
|
||||
((list? value) (json-stringify value))
|
||||
((dict? value) (hs-json-stringify value))
|
||||
((list? value) (hs-json-stringify value))
|
||||
(true value)))
|
||||
((= type-name "Object")
|
||||
(if
|
||||
(string? value)
|
||||
(guard (_e (true value)) (json-parse value))
|
||||
value))
|
||||
((= type-name "JSONString") (json-stringify value))
|
||||
((= type-name "JSONString") (hs-json-stringify value))
|
||||
((= type-name "FormEncoded")
|
||||
(if
|
||||
(dict? value)
|
||||
(join
|
||||
"&"
|
||||
(map
|
||||
(fn
|
||||
(k)
|
||||
(let
|
||||
((v (get value k)))
|
||||
(if
|
||||
(list? v)
|
||||
(join "&" (map (fn (item) (str k "=" item)) v))
|
||||
(str k "=" v))))
|
||||
(keys value)))
|
||||
(str value)))
|
||||
((or (= type-name "Fixed") (= type-name "Fixed:") (starts-with? type-name "Fixed:"))
|
||||
(let
|
||||
((digits (if (> (string-length type-name) 6) (+ (substring type-name 6 (string-length type-name)) 0) 0))
|
||||
@@ -774,7 +856,7 @@
|
||||
(map (fn (k) (list k (get value k))) (keys value))
|
||||
value))
|
||||
(true value))))
|
||||
;; Collection: sorted by
|
||||
;; Collection: split by
|
||||
(define
|
||||
hs-gather-form-nodes
|
||||
(fn
|
||||
@@ -808,11 +890,11 @@
|
||||
(each 0)))))))))
|
||||
(walk root)
|
||||
acc)))
|
||||
;; Collection: sorted by descending
|
||||
;; Collection: joined by
|
||||
(define
|
||||
hs-values-from-nodes
|
||||
(fn (nodes) (reduce hs-values-absorb (dict) nodes)))
|
||||
;; Collection: split by
|
||||
|
||||
(define
|
||||
hs-value-of-node
|
||||
(fn
|
||||
@@ -828,7 +910,7 @@
|
||||
((or (= typ "checkbox") (= typ "radio"))
|
||||
(if (host-get node "checked") (host-get node "value") nil))
|
||||
(true (host-get node "value"))))))
|
||||
;; Collection: joined by
|
||||
|
||||
(define
|
||||
hs-select-multi-values
|
||||
(fn
|
||||
|
||||
Reference in New Issue
Block a user