expand input contract for `->html`

pull/102/head
Matthew Butterick 9 years ago
parent 2f85a1955f
commit 9d39494b4b

@ -15,12 +15,12 @@ This module also provides everything from @racketmodname[sugar/coerce].
@defproc[ @defproc[
(->html (->html
[xexpr xexpr?] [xexpr-or-xexprs (or/c xexpr? (listof xexpr?))]
[#:tag html-tag (or/c #f txexpr-tag?) #f] [#:tag html-tag (or/c #f txexpr-tag?) #f]
[#:attrs html-attrs (or/c #f txexpr-attrs?) #f] [#:attrs html-attrs (or/c #f txexpr-attrs?) #f]
[#:splice splice-html? boolean? #f]) [#:splice splice-html? boolean? #f])
string?] string?]
Convert @racket[_xexpr] to an HTML string. Similar to @racket[xexpr->string], but consistent with the HTML spec, text that appears within @code{script} or @code{style} blocks will not be escaped. Convert @racket[_xexpr-or-xexprs] to an HTML string. Similar to @racket[xexpr->string], but consistent with the HTML spec, text that appears within @code{script} or @code{style} blocks will not be escaped.
@examples[#:eval my-eval @examples[#:eval my-eval
(define tx '(root (script "3 > 2") "Why is 3 > 2?")) (define tx '(root (script "3 > 2") "Why is 3 > 2?"))
@ -28,7 +28,7 @@ Convert @racket[_xexpr] to an HTML string. Similar to @racket[xexpr->string], bu
(->html tx) (->html tx)
] ]
The optional keyword arguments @racket[_html-tag] and @racket[_html-attrs] let you set the outer tag and attributes for the generated HTML. If @racket[_xexpr] already has an outer tag or attributes, they will be replaced. The optional keyword arguments @racket[_html-tag] and @racket[_html-attrs] let you set the outer tag and attributes for the generated HTML. If @racket[_xexpr-or-xexprs] already has an outer tag or attributes, they will be replaced.
@examples[#:eval my-eval @examples[#:eval my-eval
(define tx '(root ((id "huff")) "Bunk beds")) (define tx '(root ((id "huff")) "Bunk beds"))
@ -38,7 +38,7 @@ The optional keyword arguments @racket[_html-tag] and @racket[_html-attrs] let y
(->html tx #:tag 'div #:attrs '((id "doback"))) (->html tx #:tag 'div #:attrs '((id "doback")))
] ]
Whereas if @racket[_xexpr] has no tag or attributes, they will be added. If you supply attributes without a tag, you'll get an error. Whereas if @racket[_xexpr-or-xexprs] has no tag or attributes, they will be added. If you supply attributes without a tag, you'll get an error.
@examples[#:eval my-eval @examples[#:eval my-eval
(define x "Drum kit") (define x "Drum kit")
@ -68,11 +68,22 @@ If the generated HTML has an outer tag, the @racket[_splice-html?] option will s
Be careful not to pass existing HTML strings into this function, because the angle brackets will be escaped. Fine if that's what you want, but you probably don't. Be careful not to pass existing HTML strings into this function, because the angle brackets will be escaped. Fine if that's what you want, but you probably don't.
@examples[#:eval my-eval @examples[#:eval my-eval
(define tx '(p "You did" (em "what?"))) (define tx '(p "You did " (em "what?")))
(->html tx) (->html tx)
(->html (->html tx)) (->html (->html tx))
] ]
As the input contract suggests, this function can take either a single @racket[xexpr?] or a list of @racket[xexpr?], with the expected results.
@examples[#:eval my-eval
(define tx '(p "You did " (em "what?")))
(->html tx)
(define txs '("You " "did " (em "what?")))
(->html txs)
(->html #:tag 'p txs)
]
@deftogether[( @deftogether[(
@defproc[ @defproc[

@ -105,11 +105,18 @@
(define paren-match (cadr matches)) (define paren-match (cadr matches))
paren-match) paren-match)
(define+provide/contract (->html x #:tag [tag #f] #:attrs [attrs #f] #:splice [splice? #f]) (define placeholder-tag (gensym))
((xexpr?) (#:tag (or/c #f txexpr-tag?) #:attrs (or/c #f txexpr-attrs?) #:splice boolean?) . ->* . string?)
(define+provide/contract (->html x-in #:tag [tag #f] #:attrs [attrs #f] #:splice [splice? #f])
(((or/c xexpr? (listof xexpr?))) (#:tag (or/c #f txexpr-tag?) #:attrs (or/c #f txexpr-attrs?) #:splice boolean?) . ->* . string?)
(define x (cond
[(txexpr? x-in) x-in]
[(list? x-in) (cons 'html x-in)]
[else x-in]))
(when (and (not (txexpr? x)) attrs (not tag)) (when (and (not (txexpr? x)) attrs (not tag))
(error '->html "can't use attribute list '~a without a #:tag argument" attrs)) (raise-argument-error '->html (format "can't use attribute list ~v without a #:tag argument" attrs)))
(if (or tag (txexpr? x)) (if (or tag (txexpr? x))
(let () (let ()
@ -117,7 +124,7 @@
(define html-attrs (or attrs (and (txexpr? x) (get-attrs x)) null)) (define html-attrs (or attrs (and (txexpr? x) (get-attrs x)) null))
(define html-elements (or (and (txexpr? x) (get-elements x)) (list x))) (define html-elements (or (and (txexpr? x) (get-elements x)) (list x)))
(define html (xexpr->html (make-txexpr html-tag html-attrs html-elements))) (define html (xexpr->html (make-txexpr html-tag html-attrs html-elements)))
(if splice? (if (or splice? (and (list? x-in) (not (txexpr? x-in)) (not tag)))
(trim-outer-tag html) (trim-outer-tag html)
html)) html))
(xexpr->html x))) (xexpr->html x)))
@ -136,7 +143,12 @@
(check-exn exn:fail? (λ() (->html #:attrs '((id "dale")) x) "hello")) ;; won't work without tag (check-exn exn:fail? (λ() (->html #:attrs '((id "dale")) x) "hello")) ;; won't work without tag
(check-equal? (->html #:splice #t x) "hello") (check-equal? (->html #:splice #t x) "hello")
(check-equal? (->html #:tag 'brennan #:attrs '((id "dale")) x) "<brennan id=\"dale\">hello</brennan>") (check-equal? (->html #:tag 'brennan #:attrs '((id "dale")) x) "<brennan id=\"dale\">hello</brennan>")
(check-equal? (->html #:tag 'brennan #:attrs '((id "dale")) #:splice #t x) "hello")) (check-equal? (->html #:tag 'brennan #:attrs '((id "dale")) #:splice #t x) "hello")
(define xs '("hello " (em "you") " " 42))
(check-equal? (->html xs) "hello <em>you</em> &#42;")
(check-equal? (->html #:splice #t xs) "hello <em>you</em> &#42;")
(check-equal? (->html #:tag 'div xs) "<div>hello <em>you</em> &#42;</div>"))
(provide when/block) (provide when/block)
(define-syntax (when/block stx) (define-syntax (when/block stx)

Loading…
Cancel
Save