Skip to content

Commit

Permalink
Add documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
kodeFant committed Nov 1, 2024
1 parent 0185bea commit 0864979
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 7 deletions.
87 changes: 87 additions & 0 deletions Guide/hsx.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,93 @@ The underlying HTML library blaze currently does not support an empty HTML attri

If you use HTML entities, such as ` ` for a non-breaking space, you will notice they appear exactly like that. To output directly (i.e. unescaped) use the method `preEscapedToMarkup` from `Text.Blaze.Html5`.

### 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 valid HTML, but it will accept any tag and attribute names.


```haskell
[uncheckedHsx|
<my-custom-element custom-attribute="value">
Content
</my-custom-element>
|]
```

While convenient for rapid development, use it with caution as you lose the benefits of compile-time guarantees for your markup.

#### 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.


To use `customHsx`, you need to create it in a separate module due to Template Haskell restrictions. Here's how to set it up:

1. First, create a new module for your custom HSX (e.g., `Application.Helper.CustomHsx`):

```haskell
module Application.Helper.CustomHsx where

import IHP.Prelude
import IHP.HSX.QQ (customHsx)
import IHP.HSX.Parser
import Language.Haskell.TH.Quote
import qualified Data.Set as Set

myHsx :: QuasiQuoter
myHsx = customHsx
(HsxSettings
{ checkMarkup = True
, additionalTagNames = Set.fromList ["book", "title", "name"]
, additionalAttributeNames = Set.fromList ["_", "custom-attribute"]
}
)
```

Configuration options for `HsxSettings`:
- `checkMarkup`: Boolean to enable/disable markup checking
- `additionalTagNames`: Set of additional allowed tag names
- `additionalAttributeNames`: Set of additional allowed attribute names

2. Make it available in your views by adding it to your view helpers module:

```haskell
module Application.Helper.View (
module Application.Helper.View,
module Application.Helper.CustomHsx -- Add this line
) where

import IHP.ViewPrelude
import Application.Helper.CustomHsx (myHsx) -- Add this line
```

3. Use it in your views:

```haskell
[myHsx|
<book>
<title custom-attribute="value">My Book</title>
<name>Author Name</name>
</book>
|]
```

The custom HSX will validate that tags and attributes are either in the default HSX whitelist or in your additional sets. This gives you the flexibility to use custom elements and attributes.

This approach is particularly useful for:
- Web Components with custom attribute names
- UI libraries with non-standard attributes
- Integration with third-party frameworks that extend HTML syntax

It's not usable for libraries with highly esoteric attributes, like Alpine.js. Even `uncheckedHsx` will throw an error because it doesn't recognize html attributes starting with `@` or has `:` in the attribute name.

## Common HSX Patterns

Expand Down
15 changes: 8 additions & 7 deletions ihp-hsx/IHP/HSX/QQ.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,16 @@ uncheckedHsx = customHsx
, additionalTagNames = Set.empty
, additionalAttributeNames = Set.empty
}
)
)

customHsx :: HsxSettings -> QuasiQuoter
customHsx settings = QuasiQuoter {
quoteExp = quoteHsxExpression settings,
quotePat = error "quotePat: not defined",
quoteDec = error "quoteDec: not defined",
quoteType = error "quoteType: not defined"
}
customHsx settings =
QuasiQuoter
{ quoteExp = quoteHsxExpression settings
, quotePat = error "quotePat: not defined"
, quoteDec = error "quoteDec: not defined"
, quoteType = error "quoteType: not defined"
}

quoteHsxExpression :: HsxSettings -> String -> TH.ExpQ
quoteHsxExpression settings code = do
Expand Down
87 changes: 87 additions & 0 deletions ihp-hsx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,93 @@ The underlying HTML library blaze currently does not support an empty HTML attri

If you use HTML entities, such as `&nbsp;` for a non-breaking space, you will notice they appear exactly like that. To output directly (i.e. unescaped) use the method `preEscapedToMarkup` from `Text.Blaze.Html5`.

### 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 valid HTML, but it will accept any tag and attribute names.


```haskell
[uncheckedHsx|
<my-custom-element custom-attribute="value">
Content
</my-custom-element>
|]
```

While convenient for rapid development, use it with caution as you lose the benefits of compile-time guarantees for your markup.

#### 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.


To use `customHsx`, you need to create it in a separate module due to Template Haskell restrictions. Here's how to set it up:

1. First, create a new module for your custom HSX (e.g., `Application.Helper.CustomHsx`):

```haskell
module Application.Helper.CustomHsx where

import IHP.Prelude
import IHP.HSX.QQ (customHsx)
import IHP.HSX.Parser
import Language.Haskell.TH.Quote
import qualified Data.Set as Set

myHsx :: QuasiQuoter
myHsx = customHsx
(HsxSettings
{ checkMarkup = True
, additionalTagNames = Set.fromList ["book", "title", "name"]
, additionalAttributeNames = Set.fromList ["_", "custom-attribute"]
}
)
```

Configuration options for `HsxSettings`:
- `checkMarkup`: Boolean to enable/disable markup checking
- `additionalTagNames`: Set of additional allowed tag names
- `additionalAttributeNames`: Set of additional allowed attribute names

2. Make it available in your views by adding it to your view helpers module:

```haskell
module Application.Helper.View (
module Application.Helper.View,
module Application.Helper.CustomHsx -- Add this line
) where

import IHP.ViewPrelude
import Application.Helper.CustomHsx (myHsx) -- Add this line
```

3. Use it in your views:

```haskell
[myHsx|
<book>
<title custom-attribute="value">My Book</title>
<name>Author Name</name>
</book>
|]
```

The custom HSX will validate that tags and attributes are either in the default HSX whitelist or in your additional sets. This gives you the flexibility to use custom elements and attributes.

This approach is particularly useful for:
- Web Components with custom attribute names
- UI libraries with non-standard attributes
- Integration with third-party frameworks that extend HTML syntax

It's not usable for libraries with highly esoteric attributes, like Alpine.js. Even `uncheckedHsx` will throw an error because it doesn't recognize html attributes starting with `@` or has `:` in the attribute name.

## Common HSX Patterns

Expand Down

0 comments on commit 0864979

Please sign in to comment.