From 086497982b4f401aaee41b1e2e2788298431e569 Mon Sep 17 00:00:00 2001 From: lillo Date: Fri, 1 Nov 2024 23:52:14 +0700 Subject: [PATCH] Add documentation --- Guide/hsx.markdown | 87 +++++++++++++++++++++++++++++++++++++++++++ ihp-hsx/IHP/HSX/QQ.hs | 15 ++++---- ihp-hsx/README.md | 87 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+), 7 deletions(-) diff --git a/Guide/hsx.markdown b/Guide/hsx.markdown index f58a933d1..c96ee5a6e 100644 --- a/Guide/hsx.markdown +++ b/Guide/hsx.markdown @@ -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| + + Content + +|] +``` + +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| + + My Book + Author Name + +|] +``` + +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 diff --git a/ihp-hsx/IHP/HSX/QQ.hs b/ihp-hsx/IHP/HSX/QQ.hs index a8aefb5f4..4599c7ff2 100644 --- a/ihp-hsx/IHP/HSX/QQ.hs +++ b/ihp-hsx/IHP/HSX/QQ.hs @@ -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 diff --git a/ihp-hsx/README.md b/ihp-hsx/README.md index 20fcc3a4f..68b625766 100644 --- a/ihp-hsx/README.md +++ b/ihp-hsx/README.md @@ -274,6 +274,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| + + Content + +|] +``` + +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| + + My Book + Author Name + +|] +``` + +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