Support for attributes with boolean values #3

Closed
opened 8 years ago by otherjoel · 5 comments
otherjoel commented 8 years ago (Migrated from github.com)

Currently only strings are valid attribute values for a tagged x-expression. Would it make sense to support non-serialized boolean values in attributes, given that boolean attributes are a thing in XML/HTML5?

I understand how to work around it for now. But serializing #t and #f into strings on my own, and remembering to omit "false" attributes from x-expressions destined for HTML output, feels like I'm doing something that belongs in the library.

Currently only strings are valid attribute values for a tagged x-expression. Would it make sense to support non-serialized boolean values in attributes, given that boolean attributes are a thing in XML/HTML5? I understand how to work around it for now. But serializing `#t` and `#f` into strings on my own, and remembering to omit "false" attributes from x-expressions destined for HTML output, feels like I'm doing something that belongs in the library.
mbutterick commented 8 years ago (Migrated from github.com)

The txexpr library relies on Racket’s existing X-expression grammar, which predates HTML5 and thus neither 1) prohibits "true" and "false" as attribute values, nor 2) permits attributes without values like <button checked>.

That grammar is a fixed target, so changing the current txexpr functions would make it incompatible with other Racket X-expression functions (and possibly existing code).

The right way to do what you suggest would be to introduce a txexpr/html5 submodule that refines the grammar to be consistent with the html5 spec. I’m not opposed to that in principle. But supporting a particular spec means implementing all of it, which is a bigger project (e.g., I would also have to do enumerated attributes and who knows what else).

Maybe I’m exaggerating the labor because I just assume anything with the W3C name on it will be a pain in the ass. I invite you to convince me otherwise 😧

The `txexpr` library relies on Racket’s existing [X-expression grammar](http://docs.racket-lang.org/txexpr/index.html?q=txexpr#%28part._what-is-a-txexpr%29), which predates HTML5 and thus neither 1) prohibits `"true"` and `"false"` as attribute values, nor 2) permits attributes without values like `<button checked>`. That grammar is a fixed target, so changing the current `txexpr` functions would make it incompatible with other Racket X-expression functions (and possibly existing code). The right way to do what you suggest would be to introduce a `txexpr/html5` submodule that refines the grammar to be consistent with the `html5` spec. I’m not opposed to that in principle. But supporting a particular spec means implementing all of it, which is a bigger project (e.g., I would also have to do [enumerated attributes](https://www.w3.org/TR/html5/infrastructure.html#keywords-and-enumerated-attributes) and who knows what else). Maybe I’m exaggerating the labor because I just assume anything with the W3C name on it will be a pain in the ass. I invite you to convince me otherwise 😧
otherjoel commented 8 years ago (Migrated from github.com)

Good points. I definitely am not thinking we need the whole spec done, and I share your opinion of the W3C.

I was mainly looking to understand why something like '(tag [[highlighted #t]] "Hello") is not considered a valid txexpr. That seems useful outside of any XML/HTML5 considerations, which perhaps I shouldn't have even brought up. For example, a Pollen tag function defined with (define-tag-function (tag attrs elems) (...)) could test boolean attribute values directly rather than using string=? or string-length and vary output accordingly—the attribute itself might not even be intended for inclusion in any HTML output.

Regarding the x-expression grammar being a fixed target, I don't know if this is relevant but with (require xml txexpr):

> (permissive-xexprs)
#f
> (define test '(div [[highlight #t]] "Hello"))
> (xexpr? test)
#f
> (permissive-xexprs #t)
> (xexpr? test)
#t
> (txexpr? test)
#f

Does this have any relevance for txexpr? I know (permissive-xexprs #t) allows you to put anything in an x-expression attribute, which could be bad.

Good points. I definitely am not thinking we need the whole spec done, and I share your opinion of the W3C. I was mainly looking to understand why something like `'(tag [[highlighted #t]] "Hello")` is not considered a valid txexpr. That seems useful outside of any XML/HTML5 considerations, which perhaps I shouldn't have even brought up. For example, a Pollen tag function defined with `(define-tag-function (tag attrs elems) (...))` could test boolean attribute values directly rather than using `string=?` or `string-length` and vary output accordingly—the attribute itself might not even be intended for inclusion in any HTML output. Regarding the x-expression grammar being a fixed target, I don't know if this is relevant but with `(require xml txexpr)`: ``` > (permissive-xexprs) #f > (define test '(div [[highlight #t]] "Hello")) > (xexpr? test) #f > (permissive-xexprs #t) > (xexpr? test) #t > (txexpr? test) #f ``` Does this have any relevance for `txexpr`? I know [`(permissive-xexprs #t)`](https://docs.racket-lang.org/xml/#%28def._%28%28lib._xml%2Fmain..rkt%29._permissive-xexprs%29%29) allows you to put _anything_ in an x-expression attribute, which could be bad.
mbutterick commented 8 years ago (Migrated from github.com)

Yes, permissive-xexprs essentially suspends the X-expression grammar. I’ve wondered whether txexpr should respond to that parameter, but decided against it (since keeping things consistent with the grammar is intrinsic to txexpr, and it would make the module more complex for no apparent benefit).

“No apparent benefit” because you never need to use txexpr to manipulate X-expressions. In general, Pollen doesn’t care what you put in your X-expressions, so you can use & test boolean attribute values like so:

#lang racket
(require pollen/tag rackunit)

(define-tag-function (foo attrs elems)
  (if (second (assq 'boo attrs))
      'yay
      'aw))

(check-equal? (foo #:boo #t "hoo") 'yay)
(check-equal? (foo #:boo #f "hoo") 'aw)

Or did you have something else in mind?

Yes, `permissive-xexprs` essentially suspends the X-expression grammar. I’ve wondered whether `txexpr` should respond to that parameter, but decided against it (since keeping things consistent with the grammar is intrinsic to `txexpr`, and it would make the module more complex for no apparent benefit). “No apparent benefit” because you never need to use `txexpr` to manipulate X-expressions. In general, Pollen doesn’t care what you put in your X-expressions, so you can use & test boolean attribute values like so: ``` racket #lang racket (require pollen/tag rackunit) (define-tag-function (foo attrs elems) (if (second (assq 'boo attrs)) 'yay 'aw)) (check-equal? (foo #:boo #t "hoo") 'yay) (check-equal? (foo #:boo #f "hoo") 'aw) ``` Or did you have something else in mind?
otherjoel commented 8 years ago (Migrated from github.com)

Ok I see better now. I am writing some macros around define-tag-function and using attr-set as part of a method (in a helper function, not in the macro) to specify default attribute values. It was attr-set that was throwing the error on booleans (“can’t convert to string”), and I had assumed that to be a good indication that passing around txexprs with boolean attribute values was just going to be Not Acceptable. So it seems as though if I just avoid using functions from txexpr anywhere I know those will be used, it will be possible to do what I want.

Ok I see better now. I am writing some macros around `define-tag-function` and using `attr-set` as part of a method (in a helper function, not in the macro) to specify default attribute values. It was `attr-set` that was throwing the error on booleans (“can’t convert to string”), and I had assumed that to be a good indication that passing around txexprs with boolean attribute values was just going to be Not Acceptable. So it seems as though if I just avoid using functions from `txexpr` anywhere I know those will be used, it will be possible to do what I want.
mbutterick commented 8 years ago (Migrated from github.com)

Right. IOW, txexpr provides the benefit of a higher-level interface, but at the cost of being more strict about input & output. But it is always optional: X-expressions are nice because they’re simple list-based structures, so they can be manipulated with any of the list functions in Racket.

Right. IOW, `txexpr` provides the benefit of a higher-level interface, but at the cost of being more strict about input & output. But it is always optional: X-expressions are nice because they’re simple list-based structures, so they can be manipulated with any of the list functions in Racket.
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: mbutterick/txexpr#3
Loading…
There is no content yet.