Dont escape html string

Hello together,

I’m trying to put some html I got in a String into my DOM
I already searched through the Html package documentation for a while but couldnt find the function.

Try taking a look at this issue on GitHub. It explains why there isn’t a function for inserting HTML from a String and how to work around that limitation with ports and JavaScript.

The basic idea is to put the HTML string in a data attribute and have JavaScript triggered by a port grab the attribute content and set the innerHTML of the element.

You can also do a similar trick with WebComponents.

Be aware this opens you up to XSS vulnrabilities.

1 Like

It’s also possible to use the elm-explorations/markdown package with sanitze = False.

1 Like

The least ceremonious way to do this is by extending HTMLElement in JS and using a custom prop in Elm, see Print unescaped HTML - #5 by jreusch

TLDR:

Object.defineProperty(HTMLElement.prototype, "dangerouslySetInnerHTML", {
    get () {
        return this.innerHTML
    },
    set (value) {
        this.innerHTML = value
    }
})

And in your Elm code:

dangerouslySetInnerHTML: String -> Attribute msg
dangerouslySetInnerHTML= Json.Encode.string >> Html.Attributes.property "dangerouslySetInnerHTML"

view =
    div [ dangerouslySetInnerHTML "<b>Hi!</b> I'll probably end up exposed to XSS!" ] []

I did the ports way in a project and it is quite complex to understand for people new to the project.

6 Likes

as far as I can see on the documentation you can just parse markdown to html, not just indert html.
Or am I missing something?

It is just one part of the app (below all other parts) that needs to get html from a string, so I made that part seperate from elm and set it independantly via a port.
I Think thats the simplest solution for me for that project.

But thank you all anyways :slight_smile: might need another solution in some future project

Just try it. The sanitize = False option means that it will do exactly what you’re asking not escape the HTML:

myOptions : Options
myOptions =
    { githubFlavored = Just { tables = True, breaks = False }
    , defaultHighlighting = Nothing
    , sanitize = False -- The important part.
    , smartypants = False
    }

htmlExample : Html msg
htmlExample =
    """I am <b>HTML</b> featuring some <i>tags</i>, look they are <span style="color:green">not escaped</span>."""
         |> Markdown.toHtmlWith myOptions []
2 Likes

I’ve used this library in the past, with it you can take any html string and render it using elm’s virtual dom.

https://package.elm-lang.org/packages/hecrj/html-parser/latest/