chrisdone / lucid Goto Github PK
View Code? Open in Web Editor NEWClear to write, read and edit DSL for writing HTML
Clear to write, read and edit DSL for writing HTML
I have the situation where I want to factor out a pattern of two elements (which bootstrap dictates):
spanElem :: Term arg result => Text -> arg -> result
spanElem = elemWithClass "span"
inputGroupBtn_ :: Term arg result => arg -> result
inputGroupBtn_ arg =
spanElem "input-group-btn"
$ termWith "button" [ class_ " btn ", type_ "button" ] arg
Since termWith "foo" []
is :: arg -> result
and spanElem "bar"
is :: arg -> result
as well, I’d expect it to work, but the following error is thrown:
ootstrap.hs:134:51: error:
• Could not deduce (Term arg arg) arising from a use of ‘termWith’
from the context: Term arg result
bound by the type signature for:
inputGroupBtn_ :: Term arg result => arg -> result
at bootstrap.hs:133:1-50
Possible fix:
add (Term arg arg) to the context of
the type signature for:
inputGroupBtn_ :: Term arg result => arg -> result
• In the second argument of ‘($)’, namely
‘termWith "button" [class_ " btn ", type_ "button"] arg’
In the expression:
spanElem "input-group-btn"
$ termWith "button" [class_ " btn ", type_ "button"] arg
In an equation for ‘inputGroupBtn_’:
inputGroupBtn_ arg
= spanElem "input-group-btn"
$ termWith "button" [class_ " btn ", type_ "button"] arg
Here's what I was trying to do. Depending on whether row ^. R.clientDomain
evaluated to Maybe x
or Nothing
include or exclude the small_
tag from the HTML output.
Here's the best that I could do, and I'm still looking for a shorter way to get this done. (Btw, this solution isn't even 100% correct. If row ^. clientDomain
is Nothing
this still includes an empty <small></small>
tag in the HTML)
instance (ToHtml a) => ToHtml (Maybe a) where
toHtml (Just x) = toHtml x
toHtml Nothing = mempty
with td_ [class_ "client-name"] $ do
div_ (toHtml $ row ^. R.clientName)
-- TODO: this shouldn't be there if the domain is NULL
small_ (toHtml $ row ^. R.clientDomain)
Given html string output lucid code for it.
I have the following code that is causing some strange behavior when the actual html is generated.
a_ [href_ "polimorphic.com", style_ "display:block"] $ do div_ [class_ "...", style_ "..."] $ do ....
However when the html is generated it doesnt nest the div inside the a and instead the a tag gets propagated through the div tag in multiple spots.
It looks something like this
div_ [class_ "the containing div"] a_ [href="https://www.polimorphic.com"] div_ [style="some div"] a_ [href="https://www.polimorphic.com"] div_ [style="some other div"] a_ [href="https://www.polimorphic.com"]
Is there a way to turn an Html a
directly into a pretty printed/shown Text
?
I'm wondering if there is better/shorter way to get the conditional checked_
attribute:
makeCheckbox label name value = with div_ [class_ "checkbox"] $ label_ $ do
input_ $ [type_ "checkbox", name_ name] ++ (if value then [checked_] else [])
(toHtml label)
OG meta tags utilize the property
attribute on meta
tags, this attribute is currently not supported by Lucid, requiring the use of makeAttribute
instead.
See: http://ogp.me/
The poster attribute is missing
poster_ = mkAttribute "poster"
I have some code which looks like..
[class_ "blc", class_ (select correct)]
this then generates HTML which looks like
<td class="correctblc">B</td>
Is there a way to combine attributes without concatenating strings?
I started noticing some severe performance drop when combining Scotty's ActionT
with Lucid's HtmlT
. A little benchmarking produced the following: https://github.com/vacationlabs/monad-transformer-benchmark which seems to suggest that the underlying problem may be with HtmlT IO a
, which takes more than 2x the time required for HtmlT Reader
or HtmlT Identity
benchmarking renderText
time 32.04 ms (31.14 ms .. 32.54 ms)
0.997 R² (0.994 R² .. 1.000 R²)
mean 31.73 ms (31.25 ms .. 32.21 ms)
std dev 1.049 ms (785.1 μs .. 1.321 ms)
variance introduced by outliers: 11% (moderately inflated)
benchmarking renderTextT Identity
time 31.37 ms (30.17 ms .. 32.47 ms)
0.995 R² (0.989 R² .. 0.998 R²)
mean 32.90 ms (32.23 ms .. 33.53 ms)
std dev 1.359 ms (1.064 ms .. 1.839 ms)
variance introduced by outliers: 11% (moderately inflated)
benchmarking renderTextT Reader
time 33.45 ms (32.94 ms .. 33.94 ms)
0.999 R² (0.998 R² .. 1.000 R²)
mean 34.38 ms (33.95 ms .. 35.18 ms)
std dev 1.177 ms (647.7 μs .. 1.982 ms)
variance introduced by outliers: 11% (moderately inflated)
benchmarking renderTextT IO
time 74.52 ms (73.08 ms .. 75.69 ms)
0.999 R² (0.998 R² .. 1.000 R²)
mean 75.17 ms (74.51 ms .. 76.00 ms)
std dev 1.247 ms (880.2 μs .. 1.742 ms)
Haskell-cafe discussion: https://mail.haskell.org/pipermail/haskell-cafe/2017-January/126141.html
Reddit discussion: https://www.reddit.com/r/haskell/comments/5qpi15/expected_performance_drop_while_using_monad/
I do not see there is a way to print html in a human readable formatted fashion.
HTML5.2 is now a W3C Recommendation (14 December 2017), therefore it would
be good idea to update Html5
module to include things in the spec.
I suggest to add both spec, and MDN links as follows, so lucid
haddocks
could act as a good summary of what's in HTML5.2:
-- | The @poster@ attribute
-- [W3C REC](https://www.w3.org/TR/html5/semantics-embedded-content.html#element-attrdef-video-poster)
-- [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#attr-poster)
poster_ :: Text -> Attribute
poster_ = mkAttribute "poster
HTML5.2 Changes and
HTML5.1 Changes would
help to spot missing things. However, I'd prefer a complete spec scan anyway.
Currently it's TermRaw
I've found
termRawWith "script" [src_ "js/youtube.js"] ""
but not sure whether it's good
If I have two versions of the following snippet:
storefrontAngularApp :: Html ()
storefrontAngularApp = div_ $ do
script_ [type_ "text/javascript", src_ "inline.bundle.js"] ("" :: Text)
vs
storefrontAngularApp :: Html ()
storefrontAngularApp = div_ $ do
script_ [type_ "text/javascript", src_ "inline.bundle.js"] ("" :: BSL.ByteString)
...and I call renderBS storefrontAngularApp
on both of them -- it works. How is Lucid handling Text/ByteString internally? Is this going to have any perf impact? Is one preferred over the other? Is it possible at all to use hard-coded strings without having to annotate their types and letting the render*
function figure out which type to use?
Possibly related to #44
lucid-2.9.10 has a version constraint on base
that prevents building with ghc-8.6.1, but when that constraint is removed the build succeeds and seemingly works fine. So I wonder why that constraint was added in revision 1 by @phadej?
I have tried to use lucid for creating xhtml (html5 + xhtml ie.),
use <br/>
instead of <br>
eg.,
<img.../>
instead of <img ...>
,
<link>...</link>
so far my approach was to introduce new tags myself:
closingLink_ :: Term arg result => arg -> result
closingLink_ = term "link"
xmlBr_ :: Monad m => [Attribute] -> HtmlT m ()
xmlBr_ = with (makeXmlElementNoEnd "br")
xmlHr_ :: Monad m => [Attribute] -> HtmlT m ()
xmlHr_ = with (makeXmlElementNoEnd "hr")
-- and then in my pages:
closingLink_ [rel_ "stylesheet",type_ "text/css",href_ "screen.css"] ""
xmlBr_ []
xmlHr_ []
I would have thought that this is a more common thing to do
(xhtml can still be used even in the age of html5, and one may
argue that it is a good thing to do so)
obviously it's kind of tiresome to introduce all these
xhtml tags by hand, would it be possible
Thanks in advance.
Now, the type of Lucid.Base.class_
is Text -> Attribute
.
However, class attribute is used with multiple params usually.
I suggest to change the type of Lucid.Base.class_
to [Text] -> Attribute
and the logic to such as:
class_ :: [Data.Text.Text] -> Attribute
class_ cs = makeAttribute "class" $ Data.Text.intercalate " " cs
I see this used a lot in Bootstrap at least, so might be nice to have
role_ :: Text -> Attribute
role_ = makeAttribute "role"
since that seems to exist for most attributes.
I can write textarea_ [] ""
, but I can't write textarea_ []
or textarea_
. Is it possible for textarea_
not to require an argument?
How do I make this work so that it emits ×
and not &times;
?
with button_ [class_ "close", data_ "dismiss" "modal"] $ span_ "×"
Would you accept a contribution in the spirit of https://github.com/ggreif/leleka/blob/master/Lucid/MathML.hs?
(of course with a license corresponding to lucid...)
lts 3.10
λ> renderText $ p_ [colspan_ "2"] "xD"
"<p colspan=\"2\">xD</p>"
Is there any property checking provided? Or planned?
Would it be possible to drop the blaze-builder
dependency in favor of using only ByteString.Builder
in bytestring
?
I'm after toHtmlRaw for L.ByteString. If this is something that won't be added to lucid what's my best and most efficient alternative to toHtmlRaw in my application (since 'build' isn't exposed)? In my application I'm generating 100MB HTML files so memory usage is an important consideration.
Is it possible to make br_ which will work like br_ [](maybe same about hr_ etc..)
I have quite a few newtypes in my core app for greater type safety, eg:
newtype Tag = Tag T.Text deriving (Show, Eq, Ord)
For the purpose of ToHtml
it would be alright to treat them at-part with Text
. Is it possible to auto-derive a boilerplate ToHtml
instance for such cases?
svg_ :: Term arg result => arg -> result
svg_ = term "svg"
Hi
I'm getting some compilation errors with ghc when using Lucid which go away when I add a type signature to the function. I can understand that in some situations ghc just can't infer the type and that's to be expected. I was just wondering if someone could explain me how I can understand these errors and more importantly how I can predict them, i.e. I would like to know that if I do x then I get the type error. For instance in one case if I had a one html tag x it would compile but if I would do sequence_ [x, x] it would not compile, which to me seems very mysterious. Also I'm completely incapable of deciphering the type error I get, so that just leaves me with adding type signatures to functions randomly until the error goes away. If someone could explain me how to deal with this errors in a consistent way I would appreciate it.
example of error:
--withPaste :: Paste -> HtmlT Identity ()
withPaste (Paste n t _) = h1_ $ do
h1_ $ toHtml n
pre_ $ toHtml t
this is the error I get when I comment out the type signature:
https://gist.github.com/miguel-negrao/dd924cf34efce5afd507
full source:
https://gist.github.com/miguel-negrao/319cbe65044f3bdee392
I believe that having a MonadHtml
analogous to MonadReader
would make it possible to create neat single-purpose HTML widgets with controlled access to the application data model (without direct access to IO, for example).
Is such a large API change worth considering or would it be better to create a fork?
Is there any ongoing work to support embedding comments in html?
Yes, you read that right. Here is the context: we are trying to internationalize our application, and instead of manually verifying that there are no hard-coded strings in the HTML, we'd like the type-system to help us.
Is there any way to force HtmlT to force the programmer to use IText instead of Text, where newtype IText = IText Text
and the the only way the create an IText is via I18n.t someTranslationKey
It seems I can't get such HTML, because data_
is not exactly what I need:
<object data="movie.swf"
type="application/x-shockwave-flash"></object>
Existing data_
takes two arguments and yields data-foo="bar"
.
Please advise :) Maybe raw HTML is an option.
Or use makeAttribute
for a custom attribute?
I'm working with a monad transformer stack involving HtmlT
that looks like this:
type M = HtmlT (StateT Int Identity)
And there's a place in my code where I'd like to be able to write a function:
seed :: Int -> M a -> Svg a
And I can't write this if I don't have access to the data constructor. One obvious solution would be to flip the ordering of the stack like so:
type M = StateT Int (HtmlT Identity)
But lucid doesn't have an mtl-style interface so I would need to call lift
almost everywhere since HtmlT
is the monad transformer I use way more often. (Note: I'm totally fine with the lack of an mtl-style typeclass. I don't even like using mtl to begin with.)
What do you think about an identity instance for ToHtml?
instance a ~ () => ToHtml (HtmlT m a) where
toHtml = id
toHtmlRaw = id
This is useful in the scenario that you have a function that is polymorphic over anything that is ToHtml
, but when you end up in the situtation that you want to call this function on data where there isn't an instance available (and defining it is impossible without orphan instances) - the only option is to have the user cast ToHtml
and then having the function use the toHtml = id
implementation.
It would be nice to use HtmlT
with exceptions' mtl-style typeclass headers. I'll try to implement it myself and submit a PR.
While brain-storming MathML for lucid, I came across operator precedence issues. There is <mfenced>
for bracketing, maybe we shoud be generate that by means of a new class
ToHtmlPrec
which provides a showsPrec
-like mechanism for parenthesised output.
Or possibly toHtmlPrec
could go into class ToHtml
, even.
Sorry, wrong repo!
Hi,
I submitted an issue to scotty scotty-web/scotty#193 but on my latest test it appears a "HtmlT (S.State ()) ()" also leaks GBs of memory. So far I have only been able to reproduce this when the HtmlT is 3 levels (or more) deep. Is there anything in Lucid that may cause this?
{-# LANGUAGE OverloadedStrings, ExtendedDefaultRules #-}
import Web.Scotty
import Web.Scotty.Internal.Types
import Lucid.Base
import Lucid.Html5
import Control.Monad
import qualified Data.ByteString.Lazy as BL
import qualified Control.Monad.State.Lazy as SL
import qualified Control.Monad.State.Strict as S
import Data.Default.Class (def)
import Data.Functor.Identity
main = do
BL.putStr $ SL.evalState (runS $ renderBST (myhtml :: HtmlT (ScottyM) ())) def --bad
BL.putStr $ runIdentity $ renderBST (myhtml :: HtmlT Identity ()) --good
BL.putStr $ runIdentity $ evalHtmlT $ renderBST (myhtml :: HtmlT (HtmlT Identity) ()) --good
BL.putStr $ S.evalState (renderBST (myhtml :: HtmlT (S.State ()) ())) () --bad
myhtml :: Monad m => HtmlT m ()
myhtml = replicateM_ 2 $ div_ $ do
replicateM_ 1000 $ div_ $ do
replicateM_ 10000 $ div_ "test"
edit: opps, fixed bad copy/paste
lucid-from-html converts html into the lucid DSL, but is an experimental program. Once it is stable, it may be worth integrating into lucid itself, as discussed in #16 .
If this is desirable, this issue should track requirements for that program to be merged into lucid.
As far as I can see, align_
is not supported.
something alike termRawWith "script" [src_ "js/youtube.js"] ""
but without first argument, just raw html/template code without quotes escaping
As I see from code HTML5 terms are hard coded with postfix _
. I want to have functionality to use terms with prefix/postfix defined by user beside standard option, something like 'body
or body'
.
I found it less distracting, especially with big chunks of code. I think Template Haskell will be suitable for this task.
What is best option to achieve this?
Is this change to code structure useful and I should submit pull request, or just keep it in my fork?
At the moment you have to use toHtml
when using Text
variable which is bit noisy. For example you can do
myBody = title_ "my title"
but
myBody title = title_ title :: Text -> Html ()
doesn't work. You have to do
myBody title = title_ (toHtml title)
It perfectly makes sense, but it took me a while to understand why the first version worked but not the second. I didn't realize that Html overloaded strings and thought "my title" was a Text.
Hi Chirs,
Hope I'm not becoming a pest. I need an instance of Hashable
for Attribute
in
diagrams-svg, but the constructor of Attribute
is not exposed. Would you mind
either exposing the constructor or providing a Hashable
instance.
thanks
jeff
I found the docs at https://hackage.haskell.org/package/lucid-2.9.6/docs/Lucid.html difficult (well, impossible) to follow, due to eliding some things that are probably clear to an experienced Haskeller but non-obvious otherwise. I think it's just the following 3 lines, without which the examples provided won't run in ghci:
:import Lucid
:import Data.Monoid ((<>))
:set -XOverloadedStrings
(I realise that OverloadedStrings is mentioned, but the current phrasing "is written" doesn't make it explicit that you have to do something in order for them to be written like that...)
If that kind of change is something that would be generally welcome, I'm happy to draft a PR if that'd be helpful.
Hey there,
I've found myself leveraging HtmlT
quite often for its monadic state - I'll encode some crazy constraints in m
like MonadBaseControl IO
, so I can perform application-related effects when I render a view, where the read-only state of that view is represented by a data type which implements this typeclass.
I'm wondering if the exposure of the m
type variable could help with effect-stack specific rendering instances, rather than forcing a view to be pure:
toHtml :: (ToHtml a, Monad m) => a -> HtmlT m ()
would become
toHtml :: (ToHtml m a, Monad m) => a -> HtmlT m ()
and instances, originally looking like
instance ToHtml State where
toHtml State{foo,bar} = do
p_ "something forcibly pure, due to this html working forall m"
could become
data Env = Env
{hostname :: String, databaseQuery :: Query -> IO [Result], ...}
type AppM = ReaderT Env IO
instance ToHtml AppM State where
toHtml State{foo,bar} = do
Env{hostname,databaseQuery,etc} <- lift ask
p_ $ "The hostname: " <> T.pack hostname
Personally I think this would be a major advantage for server-side rendering, as it could model something similar to Elm or Thermite.
I'm trying to do something like..
container_ :: Term arg result => arg -> result
container_ arg = table_ [align_ "center", class_ " container "] $ do
tbody_ $ do
tr_ $ do
td_ arg
... which can be used like:
div_ $ do
container_ $ do
strong_ "wil this work"
container_ [class_ "extra-classes"] $ do
strong_ "what about this?
... but I can't get the definition of container_
to type-check. The best that I could get to compile is:
container_ :: (Monad m) => HtmlT m () -> HtmlT m ()
container_ arg = table_ [align_ "center", class_ " container "] $ do
tbody_ $ do
tr_ $ do
td_ arg
How can I use <html ng-app>
except toHtmlRaw
renderText (p_ [class_ "foo", style_ "attrib"] (do { style_ ""; style_ ""}))
can evaluate either to <p style="attrib" class="foo"><style></style><style></style></p>
or to <p class="foo" style="attrib"><style></style><style></style></p>
depending on the relative hash values of "style"
and "class"
. The "mixed"
test from testAttributes
accepts only the former, but on 32-bit platforms, which use a different string hash function than 64-bit platofrms to, it gets the latter and fails. testAttributesWith
has the same problem.
I'm sure I'm missing something very obvious, but I'm struggling with the following:
td_ (1::Int)
<interactive>:58:1: error:
• Non type-variable argument in the constraint: Term Int result
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall result. Term Int result => result
� :set -XFlexibleContexts
� td_ (1::Int)
<interactive>:60:1: error:
• No instance for (Term Int a0) arising from a use of ‘it’
• In a stmt of an interactive GHCi command: print it
� td_ (show 1::Int)
<interactive>:61:6: error:
• Couldn't match type ‘[Char]’ with ‘Int’
Expected type: Int
Actual type: String
• In the first argument of ‘td_’, namely ‘(show 1 :: Int)’
In the expression: td_ (show 1 :: Int)
In an equation for ‘it’: it = td_ (show 1 :: Int)
� td_ (Data.Text.pack $ show 1::Int)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.