Skip to content

Commit

Permalink
Allow custom web component tags in HSX. Fixes #607
Browse files Browse the repository at this point in the history
  • Loading branch information
mpscholten committed Dec 27, 2020
1 parent e7c2768 commit e8056fd
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 15 deletions.
28 changes: 15 additions & 13 deletions IHP/HtmlSupport/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ module IHP.HtmlSupport.Parser
, Node (..)
, Attribute (..)
, AttributeValue (..)
, attributes
, parents
, leafs
) where

import CorePrelude
Expand All @@ -23,6 +20,8 @@ import qualified Language.Haskell.Meta as Haskell
import qualified Language.Haskell.TH.Syntax as Haskell
import qualified "template-haskell" Language.Haskell.TH as TH
import qualified "template-haskell" Language.Haskell.TH.Syntax as TH
import qualified Data.Set as Set
import Data.Set (Set)

data AttributeValue = TextValue !Text | ExpressionValue !Haskell.Exp deriving (Eq, Show)

Expand Down Expand Up @@ -73,7 +72,7 @@ manyHsxElement = do
hsxSelfClosingElement = do
_ <- char '<'
name <- hsxElementName
let isLeaf = name `List.elem` leafs
let isLeaf = name `Set.member` leafs
attributes <-
if isLeaf
then hsxNodeAttributes (string ">" <|> string "/>")
Expand Down Expand Up @@ -176,7 +175,7 @@ hsxAttributeName = do
|| "aria-" `Text.isPrefixOf` name
|| "hx-" `Text.isPrefixOf` name
|| "hx-" `Text.isPrefixOf` name
|| name `List.elem` attributes
|| name `Set.member` attributes

rawAttribute = takeWhile1P Nothing (\c -> Char.isAlphaNum c || c == '-')

Expand Down Expand Up @@ -240,7 +239,10 @@ hsxSplicedNode = do
hsxElementName :: Parser Text
hsxElementName = do
name <- takeWhile1P (Just "identifier") (\c -> Char.isAlphaNum c || c == '_' || c == '-')
unless (name `List.elem` parents || name `List.elem` leafs) (fail $ "Invalid tag name: " <> cs name)
let isValidParent = name `Set.member` parents
let isValidLeaf = name `Set.member` leafs
let isValidCustomWebComponent = "-" `Text.isInfixOf` name
unless (isValidParent || isValidLeaf || isValidCustomWebComponent) (fail $ "Invalid tag name: " <> cs name)
space
pure name

Expand All @@ -251,8 +253,8 @@ hsxIdentifier = do
pure name


attributes :: [Text]
attributes =
attributes :: Set Text
attributes = Set.fromList
[ "accept", "accept-charset", "accesskey", "action", "alt", "async"
, "autocomplete", "autofocus", "autoplay", "challenge", "charset"
, "checked", "cite", "class", "cols", "colspan", "content"
Expand Down Expand Up @@ -340,11 +342,11 @@ attributes =
, "stop-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap"
, "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width"
, "stroke", "text-anchor", "text-decoration", "text-rendering", "unicode-bidi"
, "visibility", "word-spacing", "writing-mode"
, "visibility", "word-spacing", "writing-mode", "is"
]

parents :: [Text]
parents =
parents :: Set Text
parents = Set.fromList
[ "a", "abbr", "address", "article", "aside", "audio", "b"
, "bdo", "blockquote", "body", "button", "canvas", "caption", "cite"
, "code", "colgroup", "command", "datalist", "dd", "del", "details"
Expand All @@ -361,8 +363,8 @@ parents =
, "loading"
]

leafs :: [Text]
leafs =
leafs :: Set Text
leafs = Set.fromList
[ "area", "br", "col", "hr", "link", "img", "input", "meta", "param"
]

Expand Down
4 changes: 2 additions & 2 deletions Test/HtmlSupport/ParserSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ tests = do
let position = Megaparsec.SourcePos "" (Megaparsec.mkPos 0) (Megaparsec.mkPos 0)
describe "HSX Parser" do
it "should fail on invalid html tags" do
let errorText = "1:15:\n |\n1 | <my-invalid-el>\n | ^\nInvalid tag name: my-invalid-el\n"
let (Left error) = parseHsx position "<my-invalid-el>"
let errorText = "1:13:\n |\n1 | <myinvalidel>\n | ^\nInvalid tag name: myinvalidel\n"
let (Left error) = parseHsx position "<myinvalidel>"
(Megaparsec.errorBundlePretty error) `shouldBe` errorText

it "should fail on invalid attribute names" do
Expand Down
5 changes: 5 additions & 0 deletions Test/HtmlSupport/QQSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ tests = do
let variableContent :: Text = "<script>alert(1);</script>"
[hsx|{variableContent}|] `shouldBeHtml` "&lt;script&gt;alert(1);&lt;/script&gt;"

it "should parse custom web component tags" do
[hsx|<confetti-effect></confetti-effect>|] `shouldBeHtml` "<confetti-effect></confetti-effect>"
[hsx|<confetti-effect/>|] `shouldBeHtml` "<confetti-effect></confetti-effect>" -- Currently we cannot deal with self closing tags as expected
[hsx|<div is="confetti-effect"></div>|] `shouldBeHtml` "<div is=\"confetti-effect\"></div>"

data Project = Project { name :: Text }

shouldBeHtml hsx expectedHtml = (Blaze.renderMarkup hsx) `shouldBe` expectedHtml

0 comments on commit e8056fd

Please sign in to comment.