我一直在研究一些快速增长的基于Haskell的Web应用程序,并且发现自己在这个问题上陷入困境。假设我有一些我在代码中早期定义的模板:
{-# LANGUAGE OverloadedStrings #-}
import Text.Blaze.Html5
import Text.Blaze.Html5.Attributes
import qualified Text.Blaze.Html5 as H
import qualified Text.Blaze.Html5.Attributes as A
foo = H.div ! class_ "foo"
以后,我决定使用foo
,但稍加非破坏性修正案:
bar = foo ! class_ "bar" -- this should add bar to the classes available, imo
但是,当我渲染html时,这是我得到的结果:
import Text.Blaze.Html.Renderer.String
λ: renderHtml $ bar "baz"
↪ "<div class=\"foo\" class=\"bar\"></div>"
毕竟这是 monad !有没有什么办法可以将这种逻辑整合到blaze-html中?或者这超出了模板框架的范围?有没有任何选择方法(比如jQuery),这样我就可以做一些......
bar' = do
classes <- classesOf foo
H.div ! class_ (classes ++ " bar")
有没有人找到解决方法? Haskell有没有任何类型辅助的Html工具?这真让我摸不着头脑,想出了可怕的想法......
答案 0 :(得分:1)
TL; DR :当前版本的blaze不支持monoidal属性操作。
Attribute
是一个新类型的包装器:
newtype Attribute = Attribute (forall a. MarkupM a -> MarkupM a)
大多数(X)HTML属性都是使用Text.Blaze.Internal.attribute
:
attribute :: Tag -- ^ Raw key
-> Tag -- ^ Shared key string for the HTML attribute.
-> AttributeValue -- ^ Value for the HTML attribute.
-> Attribute -- ^ Resulting HTML attribute.
attribute rawKey key value = Attribute $
AddAttribute (unTag rawKey) (unTag key) (unAttributeValue value)
其中AddAttribute
是MarkupM
's个构造函数之一:
data MarkupM a
= {- ... -}
-- | Add an attribute to the inner HTML. Raw key, key, value, HTML to
-- receive the attribute.
| AddAttribute StaticString StaticString ChoiceString (MarkupM a)
{- ... -}
现在,来自Attributable
的(!)
基本上会应用Attribute
。因此,如果属性foo
和属性bar
,则tag ! bar ! foo
与foo $ bar $ tag
相同。渲染器稍后展开AddAttribute
构造函数:
go attrs (AddAttribute _ key value h) =
go (B.copyByteString (getUtf8ByteString key)
`mappend` fromChoiceString value
`mappend` B.fromChar '"'
`mappend` attrs) h
为了实现所需的行为,您需要进一步推迟属性渲染并在中间数据结构中收集属性,例如Map ChoiceString AttributeValue
。
但是,请注意,如果您要创建自己的渲染器,此帖子中的所有类型都在Text.Blaze.Internal
。
毕竟这是一个单子!
不,不是,它不符合monad法律。
我们有什么方法可以将这种逻辑整合到blaze-html中吗?
见上文,但请记住,内部API可能会发生变化。
或者超出了模板框架的范围?
显然,它至少超出了大火的范围。此外,我不知道额外的Map
是否会引入性能问题,这可能会消除大火的“快速”部分。
有没有任何选择方法(比如jQuery),这样我就可以做一些......
见上文,MarkupM
不是真正的monad。您可以解开构造函数以获取正确的AddAttributes
,但同样,这是一个内部类型和构造函数。