ANN: nice-html, an all-around "nice" html templating library, similar but different to lucid, blaze, type-of-html, etc.

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

ANN: nice-html, an all-around "nice" html templating library, similar but different to lucid, blaze, type-of-html, etc.

Mike Ledger
Hi Haskell-Cafe,

I've been working on and off on a HTML templating library that is slightly novel for a few months. 

Here's the good parts:
* it's faster than lucid and blaze
* it has a valid monad instance
* it has another valid monad instance, that is slightly different!
* it paramaterises templates by the data they require
* the HTML5 combinators don't rely on any highly overloaded/overlapping typeclasses; type errors in nice-html templates tend to be nice monomorphic type mismatches

To achieve this, it has a distinct compilation phase (at runtime) for templates. This means the actual rendering function does very little beyond concatenate Text and escape dynamic input. It also severely restricts usage to the built-in combinators available -- at least, for dynamic data -- and can make writing a nice-html template difficult, though littering _ throughout type signatures helps.

Check it out!

Benchmark results, a README, and an example: https://github.com/TransportEngineering/nice-html

The only thing on the roadmap right now is to have some nice :-) way to assign JavaScript event handlers to Markup. This is something that I really appreciate when using React.js, so my eventual aim is for nice-html to be like a (more) server-side version of React. Right now, you can keep track of element ids with `Text.Html.Writer.note`, but it's neither a very good nor very useful interface.

Cheers,
Mike

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: ANN: nice-html, an all-around "nice" html templating library, similar but different to lucid, blaze, type-of-html, etc.

Saurabh Nanda
Thank you for putting comparisons and benchmarks, upfront.

Do you mind explaining the invalid monad instance of Lucid and how it would impact a library user?

Also, I'm assuming one shouldn't call the `compile` function each time a page needs to be rendered, right? Should one put the results of the `compile` function in a top-level Map and use those to get the speed gains?

Side comment, the use of `dynamic` makes it look similar to reflex `dyn*` API.

-- Saurabh.

On Thu, Oct 26, 2017 at 4:15 PM, Mike Ledger <[hidden email]> wrote:
Hi Haskell-Cafe,

I've been working on and off on a HTML templating library that is slightly novel for a few months. 

Here's the good parts:
* it's faster than lucid and blaze
* it has a valid monad instance
* it has another valid monad instance, that is slightly different!
* it paramaterises templates by the data they require
* the HTML5 combinators don't rely on any highly overloaded/overlapping typeclasses; type errors in nice-html templates tend to be nice monomorphic type mismatches

To achieve this, it has a distinct compilation phase (at runtime) for templates. This means the actual rendering function does very little beyond concatenate Text and escape dynamic input. It also severely restricts usage to the built-in combinators available -- at least, for dynamic data -- and can make writing a nice-html template difficult, though littering _ throughout type signatures helps.

Check it out!

Benchmark results, a README, and an example: https://github.com/TransportEngineering/nice-html

The only thing on the roadmap right now is to have some nice :-) way to assign JavaScript event handlers to Markup. This is something that I really appreciate when using React.js, so my eventual aim is for nice-html to be like a (more) server-side version of React. Right now, you can keep track of element ids with `Text.Html.Writer.note`, but it's neither a very good nor very useful interface.

Cheers,
Mike

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.



--

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: ANN: nice-html, an all-around "nice" html templating library, similar but different to lucid, blaze, type-of-html, etc.

Mike Ledger
>Do you mind explaining the invalid monad instance of Lucid and how it would impact a library user?
To my knowledge lucid uses a monad instance that follow the monad laws (what I meant by "valid") fine.

It's blaze that's (somewhat) infamous for having an invalid monad instance. It used to be the case that (>>=) in blaze called 'error' -- the Monad instance was to just use (>>) = mappend. Looking now, the implementation has changed and my knowledge was out-of-date. I think it still violates the monad laws, but I don't know if as a user of blaze you'd ever be able to actually observe this, if that makes any sense.

For some fun discussions on this see:

How invalid monads can impact users is better explored in the SO question.

>Also, I'm assuming one shouldn't call the `compile` function each time a page needs to be rendered, right? Should one put the results of the `compile` function in a top-level Map and use those to get the speed gains?
The idea is to only compile a template once, ever. If you need to compile a template every time a page is rendered (though I can't actually think of a case where you would), you should probably just skip the middle-man, and use lucid (or blaze). It's not horribly slow, but you'd miss out on the benefits of nice-html by doing this.

Cheers

On Thu, Oct 26, 2017 at 11:51 PM, Saurabh Nanda <[hidden email]> wrote:
Thank you for putting comparisons and benchmarks, upfront.

Do you mind explaining the invalid monad instance of Lucid and how it would impact a library user?

Also, I'm assuming one shouldn't call the `compile` function each time a page needs to be rendered, right? Should one put the results of the `compile` function in a top-level Map and use those to get the speed gains?

Side comment, the use of `dynamic` makes it look similar to reflex `dyn*` API.

-- Saurabh.

On Thu, Oct 26, 2017 at 4:15 PM, Mike Ledger <[hidden email]> wrote:
Hi Haskell-Cafe,

I've been working on and off on a HTML templating library that is slightly novel for a few months. 

Here's the good parts:
* it's faster than lucid and blaze
* it has a valid monad instance
* it has another valid monad instance, that is slightly different!
* it paramaterises templates by the data they require
* the HTML5 combinators don't rely on any highly overloaded/overlapping typeclasses; type errors in nice-html templates tend to be nice monomorphic type mismatches

To achieve this, it has a distinct compilation phase (at runtime) for templates. This means the actual rendering function does very little beyond concatenate Text and escape dynamic input. It also severely restricts usage to the built-in combinators available -- at least, for dynamic data -- and can make writing a nice-html template difficult, though littering _ throughout type signatures helps.

Check it out!

Benchmark results, a README, and an example: https://github.com/TransportEngineering/nice-html

The only thing on the roadmap right now is to have some nice :-) way to assign JavaScript event handlers to Markup. This is something that I really appreciate when using React.js, so my eventual aim is for nice-html to be like a (more) server-side version of React. Right now, you can keep track of element ids with `Text.Html.Writer.note`, but it's neither a very good nor very useful interface.

Cheers,
Mike

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.



--


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: ANN: nice-html, an all-around "nice" html templating library, similar but different to lucid, blaze, type-of-html, etc.

Oleg Grenrus
Please, if you think blaze-markup violates the Monad laws, then report a
counterexample so it will get fixed.

The changelog for 0.8.0.0 [1] advertises: Make `MarkupM` finally adhere
to the Monad laws

http://hackage.haskell.org/package/blaze-markup-0.8.0.0/changelog

Cheers, Oleg.


On 26.10.2017 16:54, Mike Ledger wrote:

> >Do you mind explaining the invalid monad instance of Lucid and how it
> would impact a library user?
> To my knowledge lucid uses a monad instance that follow the monad laws
> (what I meant by "valid") fine.
>
> It's blaze that's (somewhat) infamous for having an invalid monad
> instance. It used to be the case that (>>=) in blaze called 'error' --
> the Monad instance was to just use (>>) = mappend. Looking now, the
> implementation has changed and my knowledge was out-of-date. I think
> it still violates the monad laws, but I don't know if as a user of
> blaze you'd ever be able to actually observe this, if that makes any
> sense.
>
> For some fun discussions on this see:
> -
> https://stackoverflow.com/questions/6399648/what-happens-to-you-if-you-break-the-monad-laws
> -
> https://www.reddit.com/r/haskell/comments/16iakr/what_happens_when_a_monad_violates_monadic_laws/
>
> How invalid monads /can/ impact users is better explored in the SO
> question.
>
> >Also, I'm assuming one shouldn't call the `compile` function each
> time a page needs to be rendered, right? Should one put the results of
> the `compile` function in a top-level Map and use those to get the
> speed gains?
> The idea is to only compile a template once, ever. If you need to
> compile a template every time a page is rendered (though I can't
> actually think of a case where you would), you should probably just
> skip the middle-man, and use lucid (or blaze). It's not horribly slow,
> but you'd miss out on the benefits of nice-html by doing this.
>
> Cheers
>
> On Thu, Oct 26, 2017 at 11:51 PM, Saurabh Nanda
> <[hidden email] <mailto:[hidden email]>> wrote:
>
>     Thank you for putting comparisons and benchmarks, upfront.
>
>     Do you mind explaining the invalid monad instance of Lucid and how
>     it would impact a library user?
>
>     Also, I'm assuming one shouldn't call the `compile` function each
>     time a page needs to be rendered, right? Should one put the
>     results of the `compile` function in a top-level Map and use those
>     to get the speed gains?
>
>     Side comment, the use of `dynamic` makes it look similar to reflex
>     `dyn*` API.
>
>     -- Saurabh.
>
>     On Thu, Oct 26, 2017 at 4:15 PM, Mike Ledger
>     <[hidden email] <mailto:[hidden email]>> wrote:
>
>         Hi Haskell-Cafe,
>
>         I've been working on and off on a HTML templating library that
>         is slightly novel for a few months. 
>
>         Here's the good parts:
>         * it's faster than lucid and blaze
>         * it has a valid monad instance
>         * it has another valid monad instance, that is slightly different!
>         * it paramaterises templates by the data they require
>         * the HTML5 combinators don't rely on any highly
>         overloaded/overlapping typeclasses; type errors in nice-html
>         templates tend to be nice monomorphic type mismatches
>
>         To achieve this, it has a distinct compilation phase (at
>         runtime) for templates. This means the actual rendering
>         function does very little beyond concatenate Text and escape
>         dynamic input. It also severely restricts usage to the
>         built-in combinators available -- at least, for dynamic data
>         -- and can make writing a nice-html template difficult, though
>         littering _ throughout type signatures helps.
>
>         Check it out!
>
>         Benchmark results, a README, and an example:
>         https://github.com/TransportEngineering/nice-html
>         <https://github.com/TransportEngineering/nice-html>
>         Hackage: https://hackage.haskell.org/package/nice-html
>         <https://hackage.haskell.org/package/nice-html>
>
>         The only thing on the roadmap right now is to have some nice
>         :-) way to assign JavaScript event handlers to Markup. This is
>         something that I really appreciate when using React.js, so my
>         eventual aim is for nice-html to be like a (more) server-side
>         version of React. Right now, you can keep track of element ids
>         with `Text.Html.Writer.note`, but it's neither a very good nor
>         very useful interface.
>
>         Cheers,
>         Mike
>
>         _______________________________________________
>         Haskell-Cafe mailing list
>         To (un)subscribe, modify options or view archives go to:
>         http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>         <http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe>
>         Only members subscribed via the mailman list are allowed to post.
>
>
>
>
>     --
>     http://www.saurabhnanda.com
>
>
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: ANN: nice-html, an all-around "nice" html templating library, similar but different to lucid, blaze, type-of-html, etc.

Mike Ledger
>The changelog for 0.8.0.0 [1] advertises: Make `MarkupM` finally adhere
>to the Monad laws
Nice. I searched the issue tracker on GitHub but ought to have just looked at the changelog.

>Please, if you think blaze-markup violates the Monad laws, then report a
>counterexample so it will get fixed.
Not really. Hence the caveat. But just to clarify, my thinking* was this:

return a >>= f 
= Empty a >>= f
= Append (Empty a) (f (markupValue (Empty a)))
= Append (Empty a) (f a)
≠ f a

BUT you can only observe this by importing Blaze.Text.Internal and pattern matching on MarkupM. Using renderMarkup you can't observe it. So long as a user can't observe the difference (or is at least discouraged by a scary-looking .Internal suffix), it's just an implementation detail that the data constructors don't exactly match. 

Cheers,
Mike

*: using = and ≠ to mean "exactly the same as", like a derived Eq instance, rather than e.g. https://github.com/jaspervdj/blaze-markup/blob/master/tests/Text/Blaze/Tests.hs#L179 which compares different Markup renderings.


On Fri, Oct 27, 2017 at 1:53 AM, Oleg Grenrus <[hidden email]> wrote:
Please, if you think blaze-markup violates the Monad laws, then report a
counterexample so it will get fixed.

The changelog for 0.8.0.0 [1] advertises: Make `MarkupM` finally adhere
to the Monad laws

http://hackage.haskell.org/package/blaze-markup-0.8.0.0/changelog

Cheers, Oleg.


On 26.10.2017 16:54, Mike Ledger wrote:
> >Do you mind explaining the invalid monad instance of Lucid and how it
> would impact a library user?
> To my knowledge lucid uses a monad instance that follow the monad laws
> (what I meant by "valid") fine.
>
> It's blaze that's (somewhat) infamous for having an invalid monad
> instance. It used to be the case that (>>=) in blaze called 'error' --
> the Monad instance was to just use (>>) = mappend. Looking now, the
> implementation has changed and my knowledge was out-of-date. I think
> it still violates the monad laws, but I don't know if as a user of
> blaze you'd ever be able to actually observe this, if that makes any
> sense.
>
> For some fun discussions on this see:
> -
> https://stackoverflow.com/questions/6399648/what-happens-to-you-if-you-break-the-monad-laws
> -
> https://www.reddit.com/r/haskell/comments/16iakr/what_happens_when_a_monad_violates_monadic_laws/
>
> How invalid monads /can/ impact users is better explored in the SO
> question.
>
> >Also, I'm assuming one shouldn't call the `compile` function each
> time a page needs to be rendered, right? Should one put the results of
> the `compile` function in a top-level Map and use those to get the
> speed gains?
> The idea is to only compile a template once, ever. If you need to
> compile a template every time a page is rendered (though I can't
> actually think of a case where you would), you should probably just
> skip the middle-man, and use lucid (or blaze). It's not horribly slow,
> but you'd miss out on the benefits of nice-html by doing this.
>
> Cheers
>
> On Thu, Oct 26, 2017 at 11:51 PM, Saurabh Nanda
> <[hidden email] <mailto:[hidden email]>> wrote:
>
>     Thank you for putting comparisons and benchmarks, upfront.
>
>     Do you mind explaining the invalid monad instance of Lucid and how
>     it would impact a library user?
>
>     Also, I'm assuming one shouldn't call the `compile` function each
>     time a page needs to be rendered, right? Should one put the
>     results of the `compile` function in a top-level Map and use those
>     to get the speed gains?
>
>     Side comment, the use of `dynamic` makes it look similar to reflex
>     `dyn*` API.
>
>     -- Saurabh.
>
>     On Thu, Oct 26, 2017 at 4:15 PM, Mike Ledger
>     <[hidden email] <mailto:[hidden email]>> wrote:
>
>         Hi Haskell-Cafe,
>
>         I've been working on and off on a HTML templating library that
>         is slightly novel for a few months. 
>
>         Here's the good parts:
>         * it's faster than lucid and blaze
>         * it has a valid monad instance
>         * it has another valid monad instance, that is slightly different!
>         * it paramaterises templates by the data they require
>         * the HTML5 combinators don't rely on any highly
>         overloaded/overlapping typeclasses; type errors in nice-html
>         templates tend to be nice monomorphic type mismatches
>
>         To achieve this, it has a distinct compilation phase (at
>         runtime) for templates. This means the actual rendering
>         function does very little beyond concatenate Text and escape
>         dynamic input. It also severely restricts usage to the
>         built-in combinators available -- at least, for dynamic data
>         -- and can make writing a nice-html template difficult, though
>         littering _ throughout type signatures helps.
>
>         Check it out!
>
>         Benchmark results, a README, and an example:
>         https://github.com/TransportEngineering/nice-html
>         <https://github.com/TransportEngineering/nice-html>
>         Hackage: https://hackage.haskell.org/package/nice-html
>         <https://hackage.haskell.org/package/nice-html>
>
>         The only thing on the roadmap right now is to have some nice
>         :-) way to assign JavaScript event handlers to Markup. This is
>         something that I really appreciate when using React.js, so my
>         eventual aim is for nice-html to be like a (more) server-side
>         version of React. Right now, you can keep track of element ids
>         with `Text.Html.Writer.note`, but it's neither a very good nor
>         very useful interface.
>
>         Cheers,
>         Mike
>
>         _______________________________________________
>         Haskell-Cafe mailing list
>         To (un)subscribe, modify options or view archives go to:
>         http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>         <http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe>
>         Only members subscribed via the mailman list are allowed to post.
>
>
>
>
>     --
>     http://www.saurabhnanda.com
>
>
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.




_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: ANN: nice-html, an all-around "nice" html templating library, similar but different to lucid, blaze, type-of-html, etc.

Saurabh Nanda
In reply to this post by Mike Ledger
>Do you mind explaining the invalid monad instance of Lucid and how it would impact a library user?
To my knowledge lucid uses a monad instance that follow the monad laws (what I meant by "valid") fine.


Sorry for causing the confusion. I misread that statement in your README.
 
>Also, I'm assuming one shouldn't call the `compile` function each time a page needs to be rendered, right? Should one put the results of the `compile` function in a top-level Map and use those to get the speed gains?
The idea is to only compile a template once, ever. If you need to compile a template every time a page is rendered (though I can't actually think of a case where you would), you should probably just skip the middle-man, and use lucid (or blaze). It's not horribly slow, but you'd miss out on the benefits of nice-html by doing this.


So, I guess my question was, how does one compile a template exactly once with `nice-html` ? If some content inside the template is conditional based on input values, will it work properly, as expected?

-- Saurabh.



_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.