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:
2026-04-23 20:14:03 +00:00
parent 8984520f05
commit 6b0334affe
6 changed files with 466 additions and 82 deletions

View File

@@ -18,7 +18,17 @@
(target value)
(if
(not (list? target))
(list (quote set!) target value)
(if
(= target (quote the-result))
(list
(quote let)
(list (list (quote __hs-r) value))
(list
(quote begin)
(list (quote set!) (quote the-result) (quote __hs-r))
(list (quote set!) (quote it) (quote __hs-r))
(quote __hs-r)))
(list (quote set!) target value))
(let
((th (first target)))
(cond
@@ -1169,15 +1179,71 @@
(let
((tgt-expr (cond ((and (list? raw-tgt) (= (first raw-tgt) (quote query))) (list (quote hs-query-all) (nth raw-tgt 1))) ((and (list? raw-tgt) (= (first raw-tgt) (quote in?)) (list? (nth raw-tgt 1)) (= (first (nth raw-tgt 1)) (quote query))) (list (quote host-call) (hs-to-sx (nth raw-tgt 2)) "querySelectorAll" (nth (nth raw-tgt 1) 1))) (true (hs-to-sx raw-tgt)))))
(list
(quote for-each)
(quote let)
(list
(quote fn)
(list (quote it))
(list
(quote when)
(hs-to-sx when-cond)
(list (quote dom-add-class) (quote it) cls)))
tgt-expr))))
(quote __hs-matched)
(list
(quote filter)
(list
(quote fn)
(list (quote it))
(hs-to-sx when-cond))
tgt-expr)))
(list
(quote begin)
(list
(quote set!)
(quote the-result)
(quote __hs-matched))
(list (quote set!) (quote it) (quote __hs-matched))
(list
(quote for-each)
(list
(quote fn)
(list (quote it))
(list (quote dom-add-class) (quote it) cls))
(quote __hs-matched))
(quote __hs-matched))))))
((= head (quote add-attr-when))
(let
((attr-name (nth ast 1))
(attr-val (hs-to-sx (nth ast 2)))
(raw-tgt (nth ast 3))
(when-cond (nth ast 4)))
(let
((tgt-expr (cond ((and (list? raw-tgt) (= (first raw-tgt) (quote query))) (list (quote hs-query-all) (nth raw-tgt 1))) (true (hs-to-sx raw-tgt)))))
(list
(quote let)
(list
(list
(quote __hs-matched)
(list
(quote filter)
(list
(quote fn)
(list (quote it))
(hs-to-sx when-cond))
tgt-expr)))
(list
(quote begin)
(list
(quote set!)
(quote the-result)
(quote __hs-matched))
(list (quote set!) (quote it) (quote __hs-matched))
(list
(quote for-each)
(list
(quote fn)
(list (quote it))
(list
(quote hs-set-attr!)
(quote it)
attr-name
attr-val))
(quote __hs-matched))
(quote __hs-matched))))))
((= head (quote multi-remove-class))
(let
((target (hs-to-sx (nth ast 1)))
@@ -1598,11 +1664,17 @@
((= head (quote append!))
(let
((tgt (hs-to-sx (nth ast 2)))
(val (hs-to-sx (nth ast 1))))
(if
(symbol? tgt)
(list (quote set!) tgt (list (quote hs-append) tgt val))
(list (quote hs-append!) val tgt))))
(val (hs-to-sx (nth ast 1)))
(raw-tgt (nth ast 2)))
(cond
((symbol? tgt)
(list
(quote set!)
tgt
(list (quote hs-append) tgt val)))
((and (list? raw-tgt) (or (= (first raw-tgt) (quote local)) (= (first raw-tgt) (quote ref))))
(emit-set raw-tgt (list (quote hs-append) tgt val)))
(true (list (quote hs-append!) val tgt)))))
((= head (quote tell))
(let
((tgt (hs-to-sx (nth ast 1))))