Fractional MIME types? what about style/class attribute values?

Hello. I’m finalizing the implementation of an HTML generation library, HypertextLiteral.jl based upon @mbostock’s Hypertext Literal (HTM). The goal of this is to provide server-side HTML generation, using Julia interpolation syntax. I’m wondering if I should be abusing the MIME type mechanism for style, onclick and other attributes.

Let’s start with some background. This library successfully uses showable("text/html", obj) to see if a user defined object can be serialized directly as HTML. If so, then I can directly call show(io, MIME("text/html"), obj). Else, I’m throwing an error asking that applications either: expressly convert the object to a string, or provide their own implementation of show for the text/html mimetype. I think this is a clean way to enable extensions… for not just this HTML generation library, but any other tool that needs a text/html representation of an object. This would, for example, let HTML objects be transparently treated without any dependencies.

Along these lines of thinking, for the <script> tag, which has its own (lack of) escaping, I think I’m going to follow the same approach, only using MIME("application/javascript"). Similarly, for the <style> tag, I could ask the user object to serialize to MIME("text/css"). I’m assuming any String value provided works… this is for custom objects that are not already converted to string values.

Now for my question. What do I do for references to objects that occur within a style attribute? I was thinking about using style = MIME{Tuple{Symbol("text/html"), Symbol("@style")}}. This convention would decouple the show dispatch from our code. Then, I could use showable(style, obj) and show(io, style, obj) to ask third party libraries to provide a customized adequate serialization to the “style” attribute. Thoughts?

Possibly not — that mechanism was introduced for show & friends.

I would just define my own functions in the API, which fall back to

show(io, MIME"text/html"(), obj)

unless the user defines a specific method. But there may be cases where the user would want different outputs for show and HTML generation. Eg similarly for PGFPlotsX.jl, we have a print_tex.

Rather than overload MIME, I think we’ll try something that mirrors how MIME works. I think with more work in the implementation, this could all be specified at macro expansion time so that the result is type stable and the resulting code is perhaps even fast.

import HypertextLiteral: HTLAttribute, htl_escape

struct Custom data::String end

Base.show(io::IO, at::HTLAttribute{Symbol("data-custom")}, value::Custom) =
    print(io, htl_escape(value.data))

@print @htl("<tag data-custom=$(Custom("a&b"))/>")
#-> <tag data-custom=a&#38;b/>

@print @htl("<tag $(:dataCustom => Custom("a&b"))/>")
#-> <tag data-custom=a&#38;b/>

The issue is that within an attribute, especially unquoted attributes, the escaping rules are different, it’s not really "text/html" anymore, it’s a horse of a different colour.