Goal: It would be nice to place arbitrary Elm values in a Markdown document. This is a plan to enable this in a way that is type-safe, efficient, and at compile-time.
Overview: I would introduce two syntactic constructs to markdown blocks {{ 4 + 5 }} for non-signals and {~ Mouse.position ~} for signals. Both can hold arbitrary expressions. For example:
main = [markdown|
The factorial of 5 is {{ product [1..5] }}.
The mouse is currently at {~ Mouse.position ~}.
|]
A markdown block that only uses the {{ }} construct would itself be a non-signal. If a {~ ~} is used, the block becomes a signal as well.
Implementation and Types: The program above desugars to the following declaration:
main = customMarkdown (product [1..5]) Mouse.position
with the constraint that:
customMarkdown : a -> Signal b -> Signal Element
The number and type of arguments can be deduced during parsing because of the two kinds of quotations, so type inference still works out.
The actual customMarkdown function is generated by the compiler. It would replace interpolated expressions with <span> elements. When an Elm value needs to be displayed, you would use something very similar to the JS FFI to fill in a particular <span>. This would work for updates as well.
This means that the markdown can still be fully parsed and turned into HTML at compile time, no need for reparsing on the client-side.
Specifics of rendering: it seems reasonable to treat certain types specially to make things more convenient.
- Element: display the element inline
- Text: display the styled-escaped text inline
- everything else: convert to a string with show and display the monospace escaped version.
This imposes nearly no implementation overhead and makes things generally nicer to use (no need to remember a whole family of type-specific quotes).
This means you'd need to say {{ plainText "hello" }} to get a string to display without the monospace font. This will surely catch some people, but I think it makes sense to only special case Text and Element because they really are about display.
Related Work: Tangle.js, AngularJS, templating languages in general. With this feature, I think it could be reasonable to argue that Elm is a more principled super-set of these projects.
Feedback Please!