# Rationale & operations for built-in \`HTML\` type

**URL:** <https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585>\
**Category:** General Usage\
**Created:** [November 22, 2020, 4:05pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585 "2020-11-22T16:05:11Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![cce](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cce/32/460_2.png) [@cce](https://discourse.julialang.org/u/cce)\
**Post date:** [November 22, 2020, 4:05pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/1 "2020-11-22T16:05:12Z")

</div>

I’m curious about the scope of the built-in `HTML` type. It’s nice that something like this exists, to indicate that a given string value is intended to be valid HTML. However, it doesn’t seem that general operations on this type have been implemented. Some standard operations give you an error, others give you quite unexpected results.

```julia
julia> html"A" * html"B"
ERROR: MethodError: no method matching *(::HTML{String}, ::HTML{String})
julia> join([html"A", html"B"])
"HTML{String}(\"A\")HTML{String}(\"B\")"

```

Is there an articulated design rationale for the `HTML` data type?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 23, 2020, 12:02pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/2 "2020-11-23T12:02:39Z")

</div>

> [@cce](#):
>
> design rationale for the `HTML` data type?

My understanding is that it is just a thin wrapper for stuff that is already HTML, eg for [this `show` method](https://github.com/JuliaLang/julia/blob/5b7699217267cec91d5b2b3d1ce1d47fd53f6068/base/docs/utils.jl#L34).

If you want to construct HTML output from Julia, look at the various packages that do that (depending on what you want to do — perhaps provide specifics).

---

<div class="post-metadata">

**Author:** ![cce](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cce/32/460_2.png) [@cce](https://discourse.julialang.org/u/cce)\
**Post date:** [November 23, 2020, 2:10pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/3 "2020-11-23T14:10:53Z")

</div>

> [@Tamas\_Papp](#):
>
> If you want to construct HTML output from Julia

That’s not my concern. My concern is about the behavior of `HTML` objects once they are constructed. What operations are valid on them, etc. For example, the constructor doesn’t recognize even its own type. For strings, nesting of strings in the constructor has relatively intuitive behavior…

```julia
julia> string("X", " ", string("Y"))
"X Y"

```

I’m not sure why `HTML` behaves this way, but it’s not parallel (the [source](https://github.com/JuliaLang/julia/blob/5b7699217267cec91d5b2b3d1ce1d47fd53f6068/base/docs/utils.jl#L26) for the construct shows it’s not self-aware), as the constructor for the `string` type is.

```julia
julia> display("text/html", HTML("X", " ", HTML("Y")))
X HTML{String}("Y")

```

My guess is that this type was declared in a moment, but never really explored and developed. If we want interoperability among tools that construct HTML, then we should probably provide reasonable semantics for HTML objects. As Julia becomes more used outside of core number crunching for web application development (or even notebooks, like `Pluto.jl`), working smartly with hypertext data seems important.

Importantly, what is the stomach and path to providing better semantics for HTML data type? Or, given how undeveloped it is, should it even be part of the core system? I mean, `HTML` is active with no other action when I start Julia… it’s a built-in. Not using it when rendering to HTML seems anti-social, yet, as noted, even basic operations simply don’t work as you’d expect.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 23, 2020, 2:22pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/4 "2020-11-23T14:22:54Z")

</div>

> [@cce](#):
>
> What operations are valid on them, etc.

Pretty much `show`, I guess (as documented, BTW).

```julia
julia> methodswith(HTML)
[1] show(io::IO, ::MIME{Symbol("text/html")}, h::HTML) in Base.Docs at docs/utils.jl:34

```

> [@cce](#):
>
> tools that construct HTML

I think that those should be in packages, not `Base`. Also, I am not sure what kind of interoperability you are after.

> [@cce](#):
>
> what is the stomach and path to providing better semantics for HTML data type?

Sorry, I could not parse that (English is not my native language).

> [@cce](#):
>
> Not using it when rendering to HTML seems anti-social, yet, as noted, even basic operations simply don’t work as you’d expect.

Maybe just use it for emitting a final HTML that is rendered as is — for _constructing_ HTML, use one of the existing packages or just build up from strings.

---

<div class="post-metadata">

**Author:** ![cce](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cce/32/460_2.png) [@cce](https://discourse.julialang.org/u/cce)\
**Post date:** [November 23, 2020, 2:32pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/5 "2020-11-23T14:32:01Z")

</div>

@Tamas_Papp I’m not suggesting that tools the construct HTML should be in base. However, if one wishes tools that construct HTML to be composable (e.g. a plurality of libraries and not a singular framework), they need a unit of composition.

In my opinion, the `HTML` type should support basic operations that are supported by `string` (construction, concatenation, and join) or `HTML` shouldn’t be in `Base`. What is the path way to providing sane support for basic operations? This could be done in an package, and then, after a while, Julia could incorporate those improvements? Even so, the constructor is a problem, how could a library fix that?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 23, 2020, 2:36pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/6 "2020-11-23T14:36:25Z")

</div>

> [@cce](#):
>
> the `HTML` type should support basic operations that are supported by `string` (construction, concatenation, and join) or `HTML` shouldn’t be in `Base`

I disagree — again, it is just a _wrapper_ type. You construct HTML code any way you prefer, and then _wrap_ it in `HTML`. From that point on, `show` knows that to do with it — that’s the sole purpose of this type.

IMO constructing HTML as strings is not ideal for nontrivial output, but if you insist, you can use strings and then just wrap the end result.

> [@cce](#):
>
> tools that construct HTML to be composable

Tools that actually construct HTML usually use their own structural representation — I am not sure how you want them to be composable. That’s an interesting question (that could benefit from an example), but possibly orthogonal to the one in this topic.

---

<div class="post-metadata">

**Author:** ![cce](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cce/32/460_2.png) [@cce](https://discourse.julialang.org/u/cce)\
**Post date:** [November 23, 2020, 2:37pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/7 "2020-11-23T14:37:44Z")

</div>

> [@Tamas\_Papp](#):
>
> I disagree — again, it is just a _wrapper_ type.

Then the `HTML` constructor should only accept a single `String` and not have intelligence built in.

> [@Tamas\_Papp](#):
>
> Tools that actually construct HTML usually use their own structural representation — I am not sure how you want them to be composable.

So, when mixing libraries from various sources, we may wish each component to be able to produce an `HTML` representation, and using `HTML` for this purpose seems reasonable (since it’s obvious and it’s a built-in).

The `HTML` constructor takes any number of objects for its argument, but it doesn’t ask those objects to render themselves for `text/html` (this would be smart), instead, it renders them without a MIME type. As a result, it doesn’t even handle itself, let alone any object that supports HTML rendering. The constructor should have only accepted `String`, or, objects that can be rendered as `text/html`… taking the `repr` of an object and treating it as its hypertext representation is misconceived.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 23, 2020, 2:51pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/8 "2020-11-23T14:51:27Z")

</div>

> [@cce](#):
>
> Then the `HTML` constructor should only accept a single `String` and not have intelligence built in.

If you read the docs, you will see that the `HTML(xs...)` constructor is just for convenience. Similar examples exist in `Base`.

> [@cce](#):
>
> The `HTML` constructor is simply wrong, it doesn’t even properly handle itself.

I am not sure I see the motivation for that — a `HTML` value should be something that is the end result (to be `show`n), not further input to something else.

> [@cce](#):
>
> The constructor should have only accepted `String` , or, objects that can be rendered as `text/html` … taking the `repr` of an object and treating it as its hypertext representation is misconceived.

Possibly (then it should be `AbstractString` though, not only `String`). Personally, I find it innocuous — callers should be responsible for providing valid HTML to `HTML`. User-facing methods to `show` will just error anyway if HTML output is not defined for `show` for a particular type, so this is not really harmful.

---

<div class="post-metadata">

**Author:** ![cce](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cce/32/460_2.png) [@cce](https://discourse.julialang.org/u/cce)\
**Post date:** [November 23, 2020, 3:31pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/9 "2020-11-23T15:31:17Z")

</div>

Thank you @Tamas_Papp. I’ve made a ticket, [#38540](https://github.com/JuliaLang/julia/issues/38540), for the suggestion to limit the constructor to an AbstractString. I’d prefer a higher-level discussion of what it means to be an `HTML` object, rather than having it being defined by its implementation.

> [@Tamas\_Papp](#):
>
> I am not sure I see the motivation for that — a `HTML` value should be something that is the end result (to be `show` n), not further input to something else.

The “final” output of one program is often the input for another. Having ways to compose libraries that produce hypertext fragments without having to know about each other seems important. It also seems that the `HTML` datatype should answer this casting call.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 23, 2020, 3:38pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/10 "2020-11-23T15:38:40Z")

</div>

> [@cce](#):
>
> The “final” output of one program is often the input for another.

Not really for `show`, though.

> [@cce](#):
>
> Having ways to compose libraries that produce hypertext fragments without having to know about each other seems important.

In the abstract, yes. But (again) a concrete example would really help this discussion.

---

<div class="post-metadata">

**Author:** ![cce](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cce/32/460_2.png) [@cce](https://discourse.julialang.org/u/cce)\
**Post date:** [November 23, 2020, 3:59pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/11 "2020-11-23T15:59:35Z")

</div>

> [@Tamas\_Papp](#):
>
> In the abstract, yes. But (again) a concrete example would really help this discussion.

Ok. So, I’m using [DataKnots.jl](https://github.com/rbt-lang/DataKnots.jl) to build cohort and other clinical queries within an application that emulates [OHDI ATLAS](https://github.com/OHDSI/Atlas) only written in Julia, and not SQL+Java+Javascript+R. This application will probably build on top of [Pluto.jl](https://github.com/fonsp/Pluto.jl). Critically, we’re trying to do this as a set of bottom-up libraries and conventions, rather than as a top-down framework. As a result, I need a way for various approaches to compose hypertext fragments to work together. Some of of these presentation fragments may be generated by [Hyperscript.jl](https://github.com/yurivish/Hyperscript.jl) or [HAML.jl](https://github.com/tkluck/HAML.jl) or really any other tooling. Moreover, those fragments would be combined as leaf nodes within a query, so that the query itself is composing the page. As a result, I need a _unit of composition_ that these libraries could support without having to know about my applications. That is, if I have a query with results rendered using HAML, I need them to also mix with fragments produced by Hyperscript. In this regard, `HTML` data type seems a lovely “unit of composition”. The problem with using the `HTML` type as a unit of composition is that page composition shouldn’t care what hypertext generation library was used, so long as the inputs are all `HTML` fragments. Yet, even naive use of `HTML` fragments breaks. I’ve given simple examples above that show the usage problems, with the constructor, with join, and the like. These all have equivalent manifestations at higher levels when attempting to use `HTML` as the wrapper that signals content is “ready for display in a browser”.

Pointedly, `HTML` seems to lack any intent / definition other than its implementation. If `HTML` is meant to mean that “the content is ready for presentation to a browser”, one would expect this invariant – for any `x` if `isa(HTML, x)` then `HTML(x)` should produce `x`. It’s also problematic to take any arbitrary value `x` and make it “ready for presentation for the browser” by printing it without specifying the `text/html` mimetype; that seems fundamentally unwise. The current constructor seems as if it was a stop-gap, undoubtely a useful one at some point in Julia’s history. However, to move the ecosystem forward, we need a unit of composition for HTML fragments.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 23, 2020, 4:11pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/12 "2020-11-23T16:11:50Z")

</div>

> [@cce](#):
>
> As a result, I need a _unit of composition_ that these libraries could support without having to know about my applications. That is, if I have a query with results rendered using HAML, I need them to also mix with fragments produced by Hyperscript. In this regard, `HTML` data type seems a lovely “unit of composition”.

I think you just need to define your API (type?) that does what you want, perhaps in a barebones package that can then be built on by packages that extend your ecosystem. I don’t think that `Base.HTML` was meant for this, and because of this I don’t think that punning on for your project it is a good idea.

---

<div class="post-metadata">

**Author:** ![cce](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cce/32/460_2.png) [@cce](https://discourse.julialang.org/u/cce)\
**Post date:** [December 15, 2020, 2:39pm UTC](https://discourse.julialang.org/t/rationale-operations-for-built-in-html-type/50585/13 "2020-12-15T14:39:31Z")

</div>

So. I understand `HTML` better now. I also think it could be improved. Currently, it doesn’t nest. With two `print` methods, it could be made to nest nicely.

```julia
print(io::IO, h::HTML) = print(io, h.content)
print(io::IO, h::HTML{<:Function}) = h.content(io)

```

[https://github.com/JuliaLang/julia/issues/38889](https://github.com/JuliaLang/julia/issues/38889)

With this change, you get…

```julia
julia> display("text/html", HTML(HTML("<tag/>")))
<tag/>

julia> display("text/html", HTML("<div>", HTML("<span>text</span>"), "</div>"))
<div><span>text</span></div>

julia> display("text/html", HTML(HTML("<span>", "text", "</span>")))
<span>text</span>

julia> display("text/html", HTML("<div>", HTML("<span>", "text", "</span>"), "</div>"))
<div><span>text</span></div>

```
