Introduction
HSX can be written pretty much like normal HTML. You can write an HSX expression inside your Haskell code by wrapping it with[hsx|YOUR HSX CODE|]. HSX expressions are just a syntax for BlazeHtml and thus are automatically escaped as described in the blaze documentation.
Because the HSX is parsed, you will get a syntax error when you type in invalid HTML.
Inline Haskell
HSX can access Haskell variables wrapped with{} like this:
show on it. You can add a custom ToHtml instance to customize rendering a data structure.
You can also write more complex code like:
{} expressions will be reported to you by the compiler.
Dynamic Attributes
The variable syntax can also be used in attribute values:Boolean Attribute Values
HSX has special handling for Boolean values to make it easy to deal with HTML Boolean attributes likedisabled, readonly, checked, etc.
- True
- False
You can write:as a short form for:
Boolean data attributes
This behavior of omitting a attribute when it’s set toFalse does not apply to data- attributes.
You can write:
False, the output HTML will keep the attribute and set it to "false":
Maybe Attribute Values / Optional Attributes
HSX has special handling for Maybe values to make it easy to deal with optional attributes. You can write:Nothing results in the target attribute not being in the output HTML:
Spread Values
For dynamic use cases you can use{...attributeList}:
<> concatenation operator.
Special Elements: <script> and <style>
For <script> and <style> tags HSX applies some special handling. This only applies to tags with inline scripts or styles:
{myHaskellExpr} without evaluating the Haskell expression itself. This is because JavaScript usually uses {} for object expressions like { a: "hello" }.
Instead use a data- attribute to solve this:
Syntax Rules
While most HTML is also valid HSX, there are some differences you need to be aware of:Closing Tags
Tags always need to have a closing tag or be self-closing: so instead of<br> you need to write <br/>.
JSX Differences
In JSX you have the restriction that you always have to have a single root tag. In HSX this restriction does not apply, so this is valid HSX (but not valid JSX):Comments
HTML Comments are supported and can be used like this:hsx, but without being rendered to HTML:
Empty Attributes
HSX allows you to write empty attributes like these:Common HSX Patterns
Dealing with Maybe Values
When dealing withMaybe values you sometimes want to conditionally render something. In HSX you usually write it like this:
User record already. Use emptyValueToNothing to transform an empty Just "" to Nothing before inserting it into the db:
country field will be set to Nothing instead of Just "".
Displaying HTML without Escaping
In HSX all variables and expressions are automatically escaped to avoid XSS. Let’s say we have variablemyVariable = "<script>alert(1)</script>". This is how the HSX will behave:
preEscapedToHtml to mark a text as already escaped:
Be careful when using
preEscapedToHtml as it can easily introduce security issues.preEscapedToHtml function can also be used to output HTML code that is not supported by HSX:
HTML Attributes without Escaping
Variable attributes are also escaped:& symbol has been replaced with it’s escaped form &:
& character not escaped. E.g. to use Tailwind Arbitrary Variants. In that case wrap the attribute value with a call to preEscapedTextValue:
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.Custom HSX and Unchecked HSX
HSX provides two additional QuasiQuoters beyond the standard[hsx|...|] for increased flexibility: uncheckedHsx and customHsx.
Using uncheckedHsx
uncheckedHsx provides a quick way to bypass HSX’s strict tag and attribute name checking.
It will still check for a valid HTML structure, but it will accept any tag and attribute names.
Using customHsx
customHsx allows you to extend the default HSX with additional whitelisted tag names and attribute names while maintaining the same strict compile-time checking of the default hsx.
This makes it easier to use custom elements that often also contain special attributes, and javascript libraries, for example _hyperscript, that use the _ as an attribute name.
Create a custom HSX module
First, create a new module for your custom HSX (e.g., Configuration options for
Application.Helper.CustomHsx):HsxSettings:checkMarkup: Boolean to enable/disable markup checkingadditionalTagNames: Set of additional allowed tag namesadditionalAttributeNames: Set of additional allowed attribute names
- Web Components with custom attribute names
- UI libraries with non-standard attributes
- Domain-specific XML markup languages
- Integration with third-party frameworks that extend HTML syntax
customHsx whitelisting and even uncheckedHsx does not entirely help for libraries with very unusual symbols in their attributes, like Alpine.js, because they don’t recognize html attributes starting with @ or has : in the attribute name. In these cases, the spread syntax {...attributeList} is likely your best bet.