Skip to content

Commit

Permalink
Finish till chapter 5
Browse files Browse the repository at this point in the history
  • Loading branch information
psibi committed Dec 20, 2024
1 parent 099d85c commit 2bc9be6
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 36 deletions.
32 changes: 16 additions & 16 deletions book/asciidoc/shakespearean-templates.asciidoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
== Shakespearean Templates

Yesod uses the Shakespearean family of template languages as its standard
approach to HTML, CSS and Javascript creation. This language family shares some
approach to HTML, CSS and JavaScript creation. This language family shares some
common syntax, as well as overarching principles:

* As little interference to the underlying language as possible, while
Expand All @@ -28,7 +28,7 @@ Julius is for Javascript, and Cassius and Lucius are both for CSS. Hamlet and
Cassius are both whitespace-sensitive formats, using indentation to denote
nesting. By contrast, Lucius is a superset of CSS, keeping CSS's braces for
denoting nesting. Julius is a simple passthrough language for producing
Javascript; the only added feature is variable interpolation.
JavaScript; the only added feature is variable interpolation.

NOTE: Cassius is in fact just an alternate syntax for Lucius. They both use the
same processing engine underneath, but Cassius files have indentation converted
Expand Down Expand Up @@ -84,7 +84,7 @@ section.blog
background-image: url(@{MyBackgroundR})
----

==== Julius (Javascript)
==== Julius (JavaScript)

String interpolation works slightly differently in Julius. This is important
from a security standpoint — all interpolated values are valid JSON by default
Expand Down Expand Up @@ -121,7 +121,7 @@ name. It might look like this:
<p>Hello, my name is #{name}
----


NOTE: +#{...}+ is how we do variable interpolation in Shakespeare.

What should happen to +name+, and what should its datatype be? A naive approach
Expand Down Expand Up @@ -189,11 +189,11 @@ _http://example.com/display/time_ displays the current time. And let's say we
want to link from the homepage to the time. I can think of three different ways
of constructing the URL:

. As a relative link: _../display/time_
. As a relative link: _../display/time_

. As an absolute link, without a domain: _/display/time_
. As an absolute link, without a domain: _/display/time_

. As an absolute link, with a domain: _http://example.com/display/time_
. As an absolute link, with a domain: _http://example.com/display/time_

There are problems with each approach: the first will break if either URL
changes. Also, it's not suitable for all use cases; RSS and Atom feeds, for
Expand Down Expand Up @@ -230,7 +230,7 @@ renderMyRoute :: MyRoute -> Text
renderMyRoute Home = "http://example.com/profile/home"
renderMyRoute Time = "http://example.com/display/time"
----

[NOTE]
====
URL rendering functions are actually a bit more complicated than this. They
Expand Down Expand Up @@ -273,7 +273,7 @@ this would translate roughly into the Haskell code:

All Shakespearean languages share the same interpolation syntax, and are able
to utilize type-safe URLs. They differ in the syntax specific for their target
language (HTML, CSS, or Javascript). Let's explore each language in turn.
language (HTML, CSS, or JavaScript). Let's explore each language in turn.

==== Hamlet Syntax

Expand Down Expand Up @@ -635,7 +635,7 @@ $doctype 5
<p>All done.
----


NOTE: There is an older and still supported syntax: three exclamation points
(+!!!+). You may still see this in code out there. We have no plans to remove
support for this, but in general find the +$doctype+ approach easier to read.
Expand All @@ -653,7 +653,7 @@ in a few more features.
* You can declare variables in your templates.

* A set of CSS properties can be created as a mixin, and reused in multiple
declarations.
declarations.

Starting with the second point: let's say you want to have some special styling
for some tags within your +article+. In plain ol' CSS, you'd have to write:
Expand Down Expand Up @@ -743,12 +743,12 @@ simple example:
==== Julius Syntax

Julius is the simplest of the languages discussed here. In fact, some might
even say it's really just Javascript. Julius allows the three forms of
even say it's really just JavaScript. Julius allows the three forms of
interpolation we've mentioned so far, and otherwise applies no transformations
to your content.

NOTE: If you use Julius with the scaffolded Yesod site, you may notice that
your Javascript is automatically minified. This is not a feature of Julius;
your JavaScript is automatically minified. This is not a feature of Julius;
instead, Yesod uses the hjsmin package to minify Julius output.

=== Calling Shakespeare
Expand Down Expand Up @@ -873,7 +873,7 @@ There are a few changes:

* We use a different set of functions, prefixed with an "s". So the quasiquoter
is +shamlet+ and the external file function is +shamletFile+. How we
pronounce those is still up for debate.
pronounce this is still up for debate.

* No URL interpolation is allowed. Doing so will result in a compile-time
error.
Expand Down Expand Up @@ -920,7 +920,7 @@ $doctype 5
<p>_{Apples count}
----



This kind of a template now needs some way to turn those values into HTML. So
just like type-safe URLs, we pass in a render function. To represent this, we
Expand Down Expand Up @@ -981,7 +981,7 @@ main = putStrLn $ renderHtml

=== Other Shakespeare

In addition to HTML, CSS and Javascript helpers, there is also some more
In addition to HTML, CSS and JavaScript helpers, there is also some more
general-purpose Shakespeare available. shakespeare-text provides a simple way
to create interpolated strings, much like people are accustomed to in scripting
languages like Ruby and Python. This package's utility is definitely not
Expand Down
38 changes: 18 additions & 20 deletions book/asciidoc/widgets.asciidoc
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
== Widgets

One of the challenges in web development is that we have to coordinate three
different client-side technologies: HTML, CSS and Javascript. Worse still, we
different client-side technologies: HTML, CSS and JavaScript. Worse still, we
have to place these components in different locations on the page: CSS in a
style tag in the head, Javascript in a script tag before the closing body tag, and HTML in the
body. And never mind if you want to put your CSS and Javascript in separate
style tag in the head, JavaScript in a script tag before the closing body tag, and HTML in the
body. And never mind if you want to put your CSS and JavaScript in separate
files!

In practice, this works out fairly nicely when building a single page, because
we can separate our structure (HTML), style (CSS) and logic (Javascript). But
we can separate our structure (HTML), style (CSS) and logic (JavaScript). But
when we want to build modular pieces of code that can be easily composed, it
can be a headache to coordinate all three pieces separately. Widgets are
Yesod's solution to the problem. They also help with the issue of including
Expand Down Expand Up @@ -118,7 +118,7 @@ page. In particular:
* External stylesheets
* External Javascript
* CSS declarations
* Javascript code
* JavaScript code
* Arbitrary +<head>+ content
* Arbitrary +<body>+ content

Expand Down Expand Up @@ -148,7 +148,7 @@ style code appear in a separate file. The scaffolded site provides this for you
automatically.

But what if you want to add some +<meta>+ tags, which need to appear in
the head? Or if you want some Javascript to appear in the body instead of the
the head? Or if you want some JavaScript to appear in the body instead of the
head? For these purposes, Yesod provides two additional type classes:
+ToWidgetHead+ and +ToWidgetBody+. These work exactly as they seem they should. One example use case for this is to have fine-grained control of where your +<script>+ tags end up getting inserted.

Expand Down Expand Up @@ -207,7 +207,7 @@ referring to files hosted on a CDN, like Google's jQuery.
=== Combining Widgets

The whole idea of widgets is to increase composability. You can take these
individual pieces of HTML, CSS and Javascript, combine them together into
individual pieces of HTML, CSS and JavaScript, combine them together into
something more complicated, and then combine these larger entities into
complete pages. This all works naturally through the +Monad+ instance of
+Widget+, meaning you can use do-notation to compose pieces together.
Expand Down Expand Up @@ -322,26 +322,24 @@ answer is that each widget is a value of type +Widget+. But if you look through
the Yesod libraries, you'll find no definition of the +Widget+ type. What
gives?

Yesod defines a very similar type: +data WidgetT site m a+. This data type is a
*monad transformer*. The last two arguments are the underlying monad and the
monadic value, respectively. The site parameter is the specific foundation
type for your individual application. Since this type varies for each and every
site, it's impossible for the libraries to define a single +Widget+ datatype
which would work for every application.
Yesod defines a very similar type: +data WidgetFor site a+. This data
type is a *monad transformer*. The last argument +a+ is the monadic
value. The site parameter is the specific foundation type for your
individual application. Since this type varies for each and every
site, it's impossible for the libraries to define a single +Widget+
datatype which would work for every application.

Instead, the +mkYesod+ Template Haskell function generates this type synonym
for you. Assuming your foundation data type is called +MyApp+, your +Widget+
synonym is defined as:

[source, haskell]
--------
type Widget = WidgetT MyApp IO ()
type Widget = WidgetFor MyApp ()
--------

We set the monadic value to be +()+, since a widget's value will ultimately be
thrown away. +IO+ is the standard base monad, and will be used in almost all
cases. The only exception is when writing a *subsite*. Subsites are a more
advanced topic, and will be covered later in their own chapter.
thrown away.

Once we know about our +Widget+ type synonym, it's easy to add signatures to
our previous code samples:
Expand Down Expand Up @@ -372,14 +370,14 @@ page =
----

When we start digging into handler functions some more, we'll encounter a
similar situation with the +HandlerT+ and +Handler+ types.
similar situation with the +HandlerFor+ and +Handler+ types.

=== Using Widgets

It's all well and good that we have these beautiful Widget datatypes, but how
exactly do we turn them into something the user can interact with? The most
commonly used function is +defaultLayout+, which essentially has the type
signature +Widget -> Handler Html+.
signature +WidgetFor -> HandlerFor Html+.

+defaultLayout+ is actually a typeclass method, which can be overridden for
each application. This is how Yesod apps are themed. So we're still left with
Expand Down Expand Up @@ -535,7 +533,7 @@ tricks which were previously employed.
=== Summary

The basic building block of each page is a widget. Individual snippets of HTML,
CSS, and Javascript can be turned into widgets via the polymorphic +toWidget+
CSS, and JavaScript can be turned into widgets via the polymorphic +toWidget+
function. Using do-notation, you can combine these individual widgets into
larger widgets, eventually containing all the content of your page.

Expand Down

0 comments on commit 2bc9be6

Please sign in to comment.