Skip to content

Commit

Permalink
Improved support for preEscapedTextValue
Browse files Browse the repository at this point in the history
  • Loading branch information
mpscholten committed Sep 17, 2022
1 parent 20bc0c2 commit 928516c
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 2 deletions.
41 changes: 41 additions & 0 deletions Guide/hsx.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,47 @@ The [`preEscapedToHtml`](https://ihp.digitallyinduced.com/api-docs/IHP-ViewPrelu
{"<!--[if IE]> Internet Explorer Conditional Comments <![endif]-->" |> preEscapedToHtml}
```

#### HTML Attributes without Escaping

Variable attributes are also escaped:

```haskell
html = [hsx|
<div class={style}>
Hello World
</div>
|]
where
style = "someClassName&" :: Text
```

The above code will generate the following HTML, where the `&` symbol has been replaced with it's escpaed form `&amp;`:

```html
<div class="someClassName&amp;">Hello World</div>
```

You might want to have this `&` character not escaped. E.g. to use [Tailwind Arbitrary Variants](https://tailwindcss.com/blog/tailwindcss-v3-1#arbitrary-values-but-for-variants). In that case wrap the attribute value with a call to `preEscapedTextValue`:


```haskell
html = [hsx|
<div class={style}>
Hello World
</div>
|]
where
style = preEscapedTextValue "someClassName&"
```

The HTML will now render without escaping the attribute:

```html
<div class="someClassName&">Hello World</div>
```

Keep in mind that you're now responsible for making sure that there's no bad input inside the string passed to `preEscapedTextValue`. You might accidentally open the door for XSS.

## Example: HSX and the equivalent BlazeHtml

The following code using HSX:
Expand Down
3 changes: 2 additions & 1 deletion IHP/ViewPrelude.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module IHP.ViewPrelude (
hsx,
toHtml,
preEscapedToHtml,
preEscapedTextValue,
module IHP.ValidationSupport,
pathTo,
urlTo,
Expand Down Expand Up @@ -41,7 +42,7 @@ import IHP.Prelude
import IHP.ViewErrorMessages ()
import IHP.ViewSupport
import Text.Blaze (preEscapedText, stringValue, text, (!))
import Text.Blaze.Html5 (preEscapedToHtml)
import Text.Blaze.Html5 (preEscapedToHtml, preEscapedTextValue)
import IHP.View.Form
import IHP.HSX.QQ (hsx)
import IHP.HSX.ToHtml
Expand Down
7 changes: 7 additions & 0 deletions Test/HSX/QQSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Test.Hspec
import IHP.Prelude
import IHP.HSX.QQ
import qualified Text.Blaze.Renderer.Text as Blaze
import Text.Blaze (preEscapedTextValue)

tests = do
describe "HSX" do
Expand Down Expand Up @@ -163,6 +164,12 @@ tests = do
-- See https://github.com/digitallyinduced/ihp/issues/1226

[hsx|<div {...[ ("data-hoge" :: Text, "Hello World!" :: Text) ]}></div>|] `shouldBeHtml` "<div data-hoge=\"Hello World!\"></div>"

it "should support pre escaped class names" do
-- See https://github.com/digitallyinduced/ihp/issues/1527

let className = preEscapedTextValue "a&"
[hsx|<div class={className}></div>|] `shouldBeHtml` "<div class=\"a&\"></div>"

data Project = Project { name :: Text }

Expand Down
6 changes: 5 additions & 1 deletion ihp-hsx/IHP/HSX/ConvertibleStrings.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ instance ConvertibleStrings LBS.ByteString Html5.AttributeValue where

instance ConvertibleStrings Text Html5.Html where
{-# INLINE convertString #-}
convertString = Html5.text
convertString = Html5.text

instance ConvertibleStrings Html5.AttributeValue Html5.AttributeValue where
{-# INLINE convertString #-}
convertString value = value

0 comments on commit 928516c

Please sign in to comment.