@link["http://download.racket-lang.org/"]{Install Racket}, which includes DrRacket.
@section{Prerequisites}
Linux and Mac users: update your @envvar{PATH} to include @filepath{/path-to-new-racket-directory/bin/}. Then you'll have access to @exec{raco} (see @other-doc['(lib "scribblings/raco/raco.scrbl")]).
Pollen will run on OS X, Linux, or Windows.
Mac users who haven't done this before: @link["http://architectryan.com/2012/10/02/add-to-the-path-on-mac-os-x-mountain-lion/"]{these instructions} are simple and accurate.
Pollen is not a self-contained GUI program like Adobe InDesign. It's a software package that runs atop the Racket language environment (also a free download).
Windows users, I'll trust you to convert @exec{raco} into the appropriate command for your system — assuming defaults, it's likely to be @filepath{C:\Program Files\Racket\raco} (include the surrounding quotes in the command).
Your three main tools in Pollen will be a text editor (for those starting out, I recommend @other-doc['(lib "scribblings/drracket/drracket.scrbl")]), a terminal window, and a web browser. The terminal commands you'll be using are simple, but if you haven't used your terminal window before, this is the moment to learn where it is.
Then, from the command line, install Pollen:
After the initial download, Pollen does not require a network connection.
@section{How to install}
@itemlist[
@item{@link["http://download.racket-lang.org/"]{Download and install Racket}, which includes DrRacket. (Of course, you're welcome to use your preferred text editor, but the tutorials will assume you're using DrRacket.)}
@item{Linux and OSX users: update your system @envvar{PATH} to include @filepath{/path-to-racket-installation/bin/}. Then, from the terminal, you'll be able to run @exec{racket} and @exec{raco} (see @other-doc['(lib "scribblings/raco/raco.scrbl")]).
@margin-note{OSX users who haven't altered your @envvar{PATH} before: don't panic. @link["http://architectryan.com/2012/10/02/add-to-the-path-on-mac-os-x-mountain-lion/"]{These instructions} are simple and accurate.}
To check that you did it correctly, try typing @exec{racket} on your command line, and you should see something like this:
@terminal{~ : racket
Welcome to Racket v.@(version).
>
}
Type @exec{ctrl+D} to exit.
}
@item{Windows users, when you see instructions that reference @exec{raco} —like the one below — I'll trust you to convert into the appropriate command for your system — assuming defaults, it's likely to be @filepath{C:\Program Files\Racket\raco} (include the surrounding quotes in the command).}
@item{Then, from the command line, install Pollen:
@commandline{raco pkg install pollen}
@commandline{raco pkg install pollen}
After that, you can update the package from the command line:
To check that it worked, try typing @exec{raco pollen version} on the command line, and you should see something like this:
Updating is optional. Major updates may have backward-incompatible changes, so you might want to consult the current @secref["version-notes"] before plunging in. The documentation for the newest version of Pollen is @link["http://pkg-build.racket-lang.org/doc/pollen/"]{available online} and refreshed daily.
}
]
@section{Beyond that}
Pollen doesn't install anything on your machine other than the Racket packages it relies on. It does not gather any information about you or your project. Your data belongs to you. I won't know that you're using Pollen unless you tell me.
#:doc '(lib "pollen/scribblings/pollen.scrbl")]{project web server} is a real web server, however. Be mindful if you're using it on a machine visible on a public network.
This project server is primarily a development & previewing tool. You do not need it to deploy Pollen projects (which generally compile down to a set of static files).
In general, I subscribe to the view that software should let you do what you want, not enroll you in a nanny state. Pollen is, in part, a programming language. Like all programming languages, it will let you do things that are incredibly clever. And also miserably stupid. But that is how we learn.
I've been using Pollen daily for several years (and will continue to do so, because my main work is writing). I've made Pollen available because a) I'm certain that others have had the same frustrations that I have, and b) feature suggestions and bug reports make it more useful for everyone.
I hope you enjoy using it. If you get stuck on something not covered here, see @secref["Getting_more_help" #:doc '(lib "pollen/scribblings/pollen.scrbl")].
Pollen is a publishing system that helps authors create functional and beautiful digital books.
Pollen is a publishing system that helps authors create beautiful and functional web-based books. Pollen includes tools for writing, designing, programming, testing, and publishing.
I created Pollen so I could make my web-based books @link["http://practicaltypography.com"]{@italic{Butterick's Practical Typography}} and @link["http://typographyforlawyers.com"]{@italic{Typography for Lawyers}}. Sure, go take a look. Are they better than the last digital books you encountered? Yes they are. Would you like your next digital book to look like that? If so, keep reading.
I used Pollen to create my books @link["http://practicaltypography.com"]{@italic{Butterick's Practical Typography}} and @link["http://typographyforlawyers.com"]{@italic{Typography for Lawyers}}. Sure, go take a look. Are they better than the last digital book you encountered? Yes they are. Would you like your book to look like that? If so, keep reading.
At the core of Pollen is an argument:
The core idea of Pollen is an argument:
@itemlist[#:style 'unordered
@itemlist[#:style 'ordered
@item{First, that digital books should be the best books we've ever had. So far, they're not even close.}
@item{Digital books should be the best books we've ever had. So far, they're not even close.}
@item{Second, that because digital books are software, an author shouldn't think of a book as merely data. @bold{The book is a program.}}
@item{Because digital books are software, an author shouldn't think of a book as merely data. @bold{The book is a program.}}
@item{Third, that the way we make digital books better than their predecessors is by exploiting this programmability.}]
@item{The way we make digital books better than their predecessors is by exploiting this programmability.}]
That's what Pollen is for.
That's what Pollen is for.
Not that you need to be a programmer to use Pollen. On the contrary, the Pollen language is markup-based, so you can write & edit text naturally. But when you want to automate repetitive tasks, add cross-references, or pull in data from other sources, you can access a full programming language from within the text.
Not that you need to be a programmer to start using Pollen. On the contrary, the Pollen language is markup-based, so you can write & edit text naturally. But when you want to automate repetitive tasks, add cross-references, or pull in data from other sources, you can access a full programming language from within the text.
That language is Racket. I chose Racket because while the idea for Pollen had been with me for several years, it simply wasn't possible to build it with other languages. So if it's unfamiliar to you, don't panic. It was unfamiliar to me. Once you see what you can do with Pollen & Racket, you may be persuaded. I was.
That language is @link["http://racket-lang.org"]{Racket}. I chose Racket because it has some unique features that made Pollen possible. So if it's unfamiliar to you, don't panic. It was unfamiliar to me. Once you see what you can do with Racket & Pollen, you may be persuaded. I was.
Or, if you can find a better digital-publishing tool, use that. But I'm never going back to the way I used to work.
Or, if you can find a better digital-publishing tool, use that. But I'm never going back to the way I used to work.
@local-table-of-contents[]
@local-table-of-contents[]
@ -57,5 +49,6 @@ Or, if you can find a better digital-publishing tool, use that. But I'm never go
@ -31,7 +31,7 @@ Click the @onscreen{Run} button. In the interactions window, you'll see the resu
@repl-output{Hello world}
@repl-output{Hello world}
Not bad. I think Pollenjust won the @link["http://en.wikipedia.org/wiki/List_of_Hello_world_program_examples"]{Hello World Tournament}.
Not bad. I think Pollenjust won the @link["http://helloworldcollection.de"]{Hello World Tournament}.
You can work with Pollen source files in any text editor, including Emacs or Sublime Text. The key advantage of DrRacket is that you can preview the results by running the file.
You can work with Pollen source files in any text editor, including Emacs or Sublime Text. The key advantage of DrRacket is that you can preview the results by running the file.
@ -67,11 +67,9 @@ Save this file as @filepath{hello.txt.pp} in any convenient directory. The deskt
Open a terminal window and issue two commands:
Open a terminal window and issue two commands:
@terminal{
@terminal{
> cd [directory containing your file]
> cd /directory/containing/your/hello-file
> raco pollen render hello.txt.pp}
> raco pollen render hello.txt.pp}
@margin-note{Windows users, I'll trust you to convert @exec{raco} into the appropriate command for your system — assuming defaults, it's likely to be @filepath{C:\Program Files\Racket\raco} (include the surrounding quotes in the command).}
After a moment, a new file will appear called @filepath{hello.txt}. Let's see what's in it:
After a moment, a new file will appear called @filepath{hello.txt}. Let's see what's in it:
@terminal{
@terminal{
@ -81,6 +79,8 @@ Breakfast in America
Take the Long Way Home
Take the Long Way Home
}
}
@margin-note{If @exec{raco} doesn't work, it's probably because the @envvar{PATH} wasn't set up correctly during @secref["Installation"].}
You've just learned three things:
You've just learned three things:
@itemlist[
@itemlist[
@ -92,10 +92,14 @@ You've just learned three things:
@item{The name of the output file is the same as the source file, minus the Pollen source extension. So @filepath{hello.txt.pp} is rendered to a file called @filepath{hello.txt}.}
@item{The name of the output file is the same as the source file, minus the Pollen source extension. So @filepath{hello.txt.pp} is rendered to a file called @filepath{hello.txt}.}
]
]
Try editing the text in @filepath{hello.txt.pp} and running @commandline{raco pollen render hello.txt.pp} again. The old @filepath{hello.txt} will be replaced with a new one showing your changes. Thus, now you've learned a fourth thing:
Try editing the text in @filepath{hello.txt.pp} and running the command again:
@commandline{raco pollen render hello.txt.pp}
The old @filepath{hello.txt} will be replaced with a new one showing your changes. So now you've learned a fourth thing:
@itemlist[
@itemlist[
@item{Pollen works by rendering output files from source files. Output files can be overwritten. Therefore, you should only make edits to your source files.}
@item{Pollen works by rendering output files from source files. Output files can be overwritten. Therefore, you should only edit your source files.}
]
]
@ -106,19 +110,19 @@ You just saw two ways to view the output of a Pollen source file —first, you
Now here's a third: the Pollen project server. To start the project server, return to your terminal and issue two commands:
Now here's a third: the Pollen project server. To start the project server, return to your terminal and issue two commands:
@terminal{
@terminal{
> cd [directory containing your hello.txt.pp file]
> cd /directory/containing/your/hello-file
> raco pollen start}
> raco pollen start}
After a moment, you'll see the startup message:
After a moment, you'll see the startup message:
@terminal{
@terminal{
Welcome to Pollen 0.001 (Racket @(version))
Welcome to Pollen @|pollen:version| (Racket @(version))
Project root is /path/to/your/directory
Project root is /path/to/your/directory
Project server is http://localhost:8080 (Ctrl-C to exit)
Project server is http://localhost:8080 (Ctrl-C to exit)
Project dashboard is http://localhost:8080/index.ptree
Project dashboard is http://localhost:8080/index.ptree
Ready to rock}
Ready to rock}
Open a web browser and point it at @link-tt{http://localhost:8080/index.ptree}. The top line of the window will say @tt{Project root} and show the name of the starting directory. Below that will be a listing of the files in the directory.
Open a web browser and point it at the project dashboard, which by default is @link-tt{http://localhost:8080/index.ptree}. The top line of the window will say @tt{Project root} and show the name of the starting directory. Below that will be a listing of the files in the directory.
Among them will be @filepath{hello.txt}, with a greyed-out @filepath{.pp} extension. Click on it, and you'll be taken to @link-tt{http://localhost:8080/hello.txt}, where you'll see:
Among them will be @filepath{hello.txt}, with a greyed-out @filepath{.pp} extension. Click on it, and you'll be taken to @link-tt{http://localhost:8080/hello.txt}, where you'll see:
@ -145,14 +149,14 @@ Mean Street
Panama
Panama
Hear About It Later}
Hear About It Later}
Notice what happened —the Pollen project server dynamically regenerated the output file (@filepath{hello.txt}) from the source file (@filepath{hello.txt.pp}) after you edited the source. If you like, try making some more changes to @filepath{hello.txt.pp}, and reloading the browser to see the updates in @filepath{hello.txt}.
Notice what happened —the Pollen project server dynamically regenerated the output file (@filepath{hello.txt}) from the source file (@filepath{hello.txt.pp}) after you edited the source. If you like, try making some more changes to @filepath{hello.txt.pp}, and reloading the browser to see the updates in @filepath{hello.txt}. The project server will regenerate the file whenever it changes.
@section{Intermission}
@section{Intermission}
That covers input & output. Now let's circle back and look at what else you can do with Pollen (beyond the epic achievement of displaying plain textin a web browser).
That covers input & output. Now let's circle back and look at what else you can do with Pollen (beyond the epic achievement of displaying plain textin a web browser).
For the rest of this tutorial, I recommend keeping two windows on screen: a web-browser window pointed at your project server (the main URL is @link-tt{http://localhost:8080/index.ptree}) and the DrRacket editing window.
For the rest of this tutorial, I recommend keeping two windows on screen: a web-browser window pointed at your @link["http://localhost:8080/index.ptree"]{project dashboard}, and the DrRacket editing window.
@section{Pollen as a preprocessor}
@section{Pollen as a preprocessor}
@ -170,14 +174,14 @@ For instance, HTML. In DrRacket, create a new file called @filepath{margin.html.
The @filepath{.pp} file extension — which you saw before, with @filepath{hello.txt.pp} — stands for ``Pollen preprocessor.'' You can use the Pollen preprocessor with any text-based file by inserting @code{#lang pollen} as the first line, and adding the @filepath{.pp} file extension.
The @filepath{.pp} file extension — which you saw before, with @filepath{hello.txt.pp} — stands for ``Pollen preprocessor.'' You can use the Pollen preprocessor with any text-based file by inserting @code{#lang pollen} as the first line, and adding the @filepath{.pp} file extension.
But for now, go to your @link["http://localhost:8080/index.ptree"]{project dashboard} and click @link["http://localhost:8080/margin.html"]{@filepath{margin.html}}. You should see a black box containing the text ``5em is the inset.''
But for now, go to your @link["http://localhost:8080/index.ptree"]{project dashboard} and click @link["http://localhost:8080/margin.html"]{@filepath{margin.html}}. You should see a black box containing the text ``@tt{5em is the inset.}''
Suppose you want to change the inset to 30%. Without a preprocessor, you'd have to search & replace each value. But with a preprocessor, you can move the inset value into a variable, and update it from that one location. So first, introduce a variable called @code{my-inset} by using the @racket[define] command:
Suppose you want to change the inset to 30%. Without a preprocessor, you'd have to search & replace each value. But with a preprocessor, you can move the inset value into a variable, and update it from that one location. So first, introduce a variable called @code{my-inset} by using the @racket[define] command:
@ -185,28 +189,22 @@ Suppose you want to change the inset to 30%. Without a preprocessor, you'd have
The @code{◊} character is called a @italic{lozenge}. In Pollen, the lozenge is a special character used to denote anything that Pollen should interpret as a command (rather than plain text).
The @code{◊} character is called a @italic{lozenge}. In Pollen, the lozenge is a special character used to denote anything that Pollen should interpret as a command (rather than plain text).
@margin-note{How to type a lozenge:
If you're using DrRacket, you can insert a lozenge by clicking the @onscreen{Insert command char ◊} button at the top of your source window. (If you're not using DrRacket, see @seclink["The_lozenge_glyph____"]{these instructions}.)
If you're using DrRacket, click the @onscreen{Insert command char} button on the toolbar to insert a lozenge in your code.
If you're not:
@(linebreak)@bold{Mac}: option + shift + V
@(linebreak)@bold{Windows}: holding down alt, type 9674 on the num pad
@(linebreak)@bold{Ubuntu}: ctrl + shift + U, then 25CA}
Thus, the command @code{◊define[my-inset]{30%}} means ``create a variable called @code{my-inset} and give it the value @code{30%}.''
Thus, the command @code{◊(define my-inset "30%")} means ``create the variable @code{my-inset} and assign it the value @racket{30%}.''
Now you can insert the variable into the HTML like so, this time using the ◊ character with the variable name in the two places the value needs to appear:
Now you can insert the variable into the HTML, this time using the special ◊ character with the variable name in the two places the value needs to appear:
Now reload @link["http://localhost:8080/margin.html"]{@filepath{margin.html}}. You'll see that the size of the margin has changed (because of the change to the @code{style} attribute) and so has the text of the HTML. If you like, try editing @code{my-inset} with different values and reloading the page. You can also try using @racket[define] to create another variable (for instance, to change the color of the box border).
In your web browesr, reload @link["http://localhost:8080/margin.html"]{@filepath{margin.html}}. You'll see that the size of the margin has changed (because of the change to the @code{style} attribute) and so has the text of the HTML. If you like, try editing @code{my-inset} with different values and reloading the page. You can also try using @racket[define] to create another variable (for instance, to change the color of the box border).
Still, this is the tiniest tip of the iceberg. The Pollen preprocessor gives you access to everything in the Racket programming language —including string manipulation, math functions, and so on.
Still, this is the tiniest tip of the iceberg. The Pollen preprocessor gives you access to everything in the Racket programming language —including string manipulation, math functions, and so on.
@ -214,7 +212,7 @@ Still, this is the tiniest tip of the iceberg. The Pollen preprocessor gives you
When used as a preprocessor, Pollen's rule is that what you write is what you get. But if you're targeting HTML, who wants to type out all those @code{<tedious>tags</tedious>}? You can make Pollen do the heavy lifting by using an @defterm{authoring mode}.
When used as a preprocessor, Pollen's rule is that what you write is what you get. But if you're targeting HTML, who wants to type out all those @code{<tedious>tags</tedious>}? You can make Pollen do the heavy lifting by using an @defterm{authoring mode}.
For instance, Markdown authoring mode. Markdown is a simplified @link["https://daringfireball.net/projects/markdown/"]{notation system} for HTML. You can use Markdown authoring mode in Pollen by inserting @tt{#lang pollen} as the first line, and adding the @filepath{.pmd} file extension.
For instance, Markdown authoring mode. Markdown is a simplified @link["https://daringfireball.net/projects/markdown/"]{notation system} for HTML. You can use Markdown authoring mode in Pollen by inserting @code{#lang pollen} as the first line, and adding the @filepath{.pmd} file extension.
Try it. In DrRacket, create a file with the following lines and save it as @filepath{downtown.html.pmd}:
Try it. In DrRacket, create a file with the following lines and save it as @filepath{downtown.html.pmd}:
@ -230,7 +228,7 @@ Pollen + Markdown
+ [search for Racket](https://google.com/search?q=racket)
+ [search for Racket](https://google.com/search?q=racket)
}]
}]
As before, go to the @link["http://localhost:8080/index.ptree"]{dashboard} for the project server. This time, click the link for @link["http://localhost:8080/downtown.html"]{@filepath{downtown.html}}. You'll see something like this:
As before, go to the @link["http://localhost:8080/index.ptree"]{project dashboard}. This time, click the link for @link["http://localhost:8080/downtown.html"]{@filepath{downtown.html}}. You'll see something like this:
@browser{
@browser{
@ -249,7 +247,7 @@ In Markdown authoring mode, you can still embed Pollen commands within the sourc
@fileblock["downtown.html.pmd"
@fileblock["downtown.html.pmd"
@codeblock{
@codeblock{
#lang pollen
#lang pollen
◊define[metal]{Plutonium}
◊(define metal "Plutonium")
Pollen + ◊metal
Pollen + ◊metal
---------------
---------------
@ -270,19 +268,19 @@ Refresh @link["http://localhost:8080/downtown.html"]{@filepath{downtown.html}} i
}
}
Pollen is handling two tasks here: interpreting the commands in the source, and then converting the Markdown to HTML. (For more, see @secref["Markdown_authoring_mode"
Pollen is handling three tasks here: interpreting the commands in the source, converting the source to Markdown, and then to HTML. (For more, see @secref["Markdown_authoring_mode"
#:doc '(lib "pollen/scribblings/pollen.scrbl")].)
#:doc '(lib "pollen/scribblings/pollen.scrbl")].)
But what if you wanted to use Pollen as a preprocessor that outputs a Markdown file? No problem —just change the source name from @filepath{downtown.html.pmd} to @filepath{downtown.md.pp}. Changing the extension from @filepath{.pmd} to @filepath{.pp} switches Pollen from Markdown mode back to preprocessor mode. And changing the base name from @filepath{downtown.html} to @filepath{downtown.md} updates the name of the output file.
But what if you wanted to use Pollen as a preprocessor that outputs a Markdown file? No problem —just change the source name from @filepath{downtown.html.pmd} to @filepath{downtown.md.pp}. Changing the extension from @filepath{.pmd} to @filepath{.pp} switches Pollen from Markdown mode back to preprocessor mode. And changing the base name from @filepath{downtown.html} to @filepath{downtown.md} updates the name of the output file (and thereby skips the HTML conversion).
@section{Pollen markup}
@section{Pollen markup}
If all you need to do is produce basic HTML, Markdown is great. But if you need to do semantic markup or other kinds of custom markup, it's not flexible enough.
If all you need to do is produce basic HTML, Markdown is fine. But if you need to do semantic markup or other kinds of custom markup, it's @seclink["The_case_against_Markdown"]{not flexible enough}.
In that case, you can use another Pollen authoring mode, called @defterm{Pollen markup}. To use Pollen markup, insert @code{#lang pollen} as the first line of your source file, and add a @filepath{.pm} file extension.
In that case, you can use a different authoring mode, called @defterm{Pollen markup}. To use Pollen markup, insert @code{#lang pollen} as the first line of your source as usual, but this time add a @filepath{.pm} file extension.
Compared to Markdown authoring mode, Pollen markup is wide open. Markdown authoring mode limits you to the formatting commands supported by Markdown. With Pollen markup, by contrast, you can use any tags you want. Markdown mode decodes the source in a fixed way (i.e., with the Markdown decoder). But Pollen markup lets you build any decoder you want.
Compared to Markdown authoring mode, Pollen markup is wide open. Markdown authoring mode limits you to the formatting commands supported by Markdown. With Pollen markup, by contrast, you can use any tags you want. Markdown mode interprets the source in a fixed way (i.e., according to Markdown rules). But Pollen markup lets you attach any behavior you want to your tags.
To see how this works, let's convert our Markdown example into Pollen markup. Marking up content is simple: insert the lozenge character (@code{◊}) followed by the name of the tag (@code{◊tag}), followed by the content of the tag in curly braces (@code{◊tag{content}}). In DrRacket, create a new file called @filepath{uptown.html.pm} as follows:
To see how this works, let's convert our Markdown example into Pollen markup. Marking up content is simple: insert the lozenge character (@code{◊}) followed by the name of the tag (@code{◊tag}), followed by the content of the tag in curly braces (@code{◊tag{content}}). In DrRacket, create a new file called @filepath{uptown.html.pm} as follows:
@ -314,13 +312,12 @@ For that, we'll make a special file called @filepath{pollen.rkt}. This is a file
@fileblock["pollen.rkt"
@fileblock["pollen.rkt"
@codeblock{
@codeblock{
#lang racket/base
#lang racket/base
(require pollen/tag)
(require pollen/tag)
(provide (all-defined-out))
(provide (all-defined-out))
(define headline (default-tag-function 'h2))
(define headline (default-tag-function 'h2))
(define items (default-tag-function 'ul))
(define items (default-tag-function 'ul))
(define item (default-tag-function 'li 'p))
(define item (default-tag-function 'li 'p))
(define (link url text) `(a [[href ,url]] ,text))
(define (link url text) `(a ((href ,url)) ,text))
}]
}]
Return to the @link["http://localhost:8080/index.ptree"]{project dashboard} and click on @link["http://localhost:8080/uptown.html"]{@filepath{uptown.html}}. Now you'll get the right result:
Return to the @link["http://localhost:8080/index.ptree"]{project dashboard} and click on @link["http://localhost:8080/uptown.html"]{@filepath{uptown.html}}. Now you'll get the right result:
@ -333,7 +330,7 @@ Return to the @link["http://localhost:8080/index.ptree"]{project dashboard} and
• @link["https://google.com/search?q=racket"]{search for Racket}
• @link["https://google.com/search?q=racket"]{search for Racket}
}
}
Pollen markup takes a little more effort to set up. But it also allows you more flexibility. If you want to do semantic markup, or convert your source into multiple output formats, or handle complex page layouts —it's the way to go. (For more, see @seclink["Writing_with_Pollen_markup"
Pollen markup takes a little more effort to set up. But it also allows you more flexibility. If you want to do semantic markup, or convert your source into @seclink["fourth-tutorial"]{multiple output formats}, or handle complex page layouts —it's the way to go. (For more, see @seclink["Writing_with_Pollen_markup"
#:doc '(lib "pollen/scribblings/pollen.scrbl")].)
#:doc '(lib "pollen/scribblings/pollen.scrbl")].)
@section{Templates}
@section{Templates}
@ -354,11 +351,11 @@ So let's create @filepath{template.html}. Make a new file that with the followin
This is a simple HTML file that should look familiar, except for the two template variables. The first, @code{here}, contains the name of the current source file. As before, the lozenge character marks it as a Pollen command rather than text, so you write it as @code{◊here}. The other command, @code{◊->html{◊doc}}, takes the content from the source file, which is contained in a variable called @code{doc}, and converts it to HTML with a Pollen function called @racket[->html].
This is a simple HTML file that should look familiar, except for the two template variables. The first, @code{here}, contains the name of the current source file. As before, the lozenge character marks it as a Pollen command rather than text, so you write it as @code{◊here}. The other command, @code{◊(->html ◊doc)}, takes the content from the source file, which is contained in a variable called @code{doc}, and converts it to HTML with @racket[->html].
Return to your web browser and reload @link["http://localhost:8080/uptown.html"]{@filepath{uptown.html}}. (Or @link["http://localhost:8080/downtown.html"]{@filepath{downtown.html}} —both will work.) The page will be rendered with the new @filepath{template.html}. As before, you can edit the template or the source and the project server will dynamically update the output file.
Return to your web browser and reload @link["http://localhost:8080/uptown.html"]{@filepath{uptown.html}}. (Or @link["http://localhost:8080/downtown.html"]{@filepath{downtown.html}} —both will work.) The page will be rendered with the new @filepath{template.html}. As before, you can edit the template or the source and the project server will dynamically update the output file.
@ -367,7 +364,7 @@ Return to your web browser and reload @link["http://localhost:8080/uptown.html"]
Pollen can also be used as a dynamic preview server for Scribble files. From your terminal, do the following:
Pollen can also be used as a dynamic preview server for Scribble files. From your terminal, do the following:
@terminal{
@terminal{
> cd [directory containing your Scribble files]
> cd /path/to/scribble/sources
> raco pollen start}
> raco pollen start}
On the @link["http://localhost:8080/index.ptree"]{project dashboard}, you'll see your @filepath{filename.scrbl} files listed as @filepath{filename.html}. By clicking on these names, you can get a preview rendering of the Scribble source file. This may not represent the ultimate structure of your Scribble project —you may end up combining multiple Scribble source files into one HTML file, or making multiple HTML files from one Scribble source — but it's handy for checking your work as you go.
On the @link["http://localhost:8080/index.ptree"]{project dashboard}, you'll see your @filepath{filename.scrbl} files listed as @filepath{filename.html}. By clicking on these names, you can get a preview rendering of the Scribble source file. This may not represent the ultimate structure of your Scribble project —you may end up combining multiple Scribble source files into one HTML file, or making multiple HTML files from one Scribble source — but it's handy for checking your work as you go.
@ -380,20 +377,21 @@ Now you've seen the key features of Pollen. What do you think?
@itemlist[
@itemlist[
@item{@italic{``So it's like WordPress, but harder to use?''} I was a happy WordPress user for several years. If you need a blog, it's great. But the farther you get from blogs, the more it becomes like teaching an elephant to pirouette. And for those who like to solve problems with programming, PHP is, um, limited.}
@item{@italic{``So it's like WordPress, but harder to use?''} I was once a happy WordPress user. If you need a blog, it's great. But the farther you get from blogs, the more it becomes like teaching a hippo to fly. And for those who like to solve problems with programming, PHP is, um, @link["http://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/"]{limited}.}
@item{@italic{``What about pairing a Python template system and Python web server?''} Good idea. I even tried it. But Python template systems don't offer you Python —they offer you limited dialects that aren't very Pythonic. Also, Python's handing of XML-ish data is cumbersome.}
@item{@italic{``What about pairing a Python template system and Python web server?''} Good idea. I even tried it. But Python template systems don't offer you Python —they offer you limited dialects that aren't very Pythonic. Also, Python's handing of XML-ish data is cumbersome.}
@item{@italic{``Haven't you heard of Jekyll?''} Yes. If everything you need to write is expressible in Markdown, it's great. If you need more than that, you're stuck. (See also @seclink["The_case_against_Markdown"]{my objections to Markdown for books}.)}
@item{@italic{``Haven't you heard of Jekyll?''} Yes. If everything you need to write is expressible in Markdown, it's great. If you need more than that, you're stuck. (See also @seclink["The_case_against_Markdown"]{my objections to Markdown for books}.)}
@item{@italic{``Sounds a lot like LaTeX. Why not use that?''} Also a good idea. LaTeX gets a lot of things right. But it wasn't designed for web publishing.}
@item{@italic{``Sounds a lot like LaTeX. Why not use that?''} Also a good idea. LaTeX gets a lot of things right. But it's also missing a lot — for instance,Unicode and web publishing.}
@item{@italic{``Does the world really need another static site generator?''} Agreed —if you want a system that does the heavy lifting, you have plenty of good options. But if you want a system that's fully programmable and @seclink["Adding_support_for_PDF_output"]{doesn't limit you} to websites — well,let me know @link["http://lmgtfy.com/?q=programmable+document+generator"]{what you find}.}
@item{@italic{``Eh, there are plenty of adequate options. Why should I learn a system written in Racket, which I've never used?''} A salient objection. It's also the question I asked myself before I committed to Racket. But publishing systems that are author- or designer-friendly tend to be programmer-hostile, and vice versa. Racket is the only language I found that could meet my requirements. (For more about the benefits of Racket, see @link["http://practicaltypography.com/why-racket-why-lisp.html"]{Why Racket? Why Lisp?})}
@item{@italic{``Why should I try a system written in Racket, which I've never used?''} I respect your skepticism. I had never used it either. But Pollen isn't built on Racket merely so I can enhance my indie cred. Rather, it's because XML and Lisps have a @link["http://www.defmacro.org/ramblings/lisp.html"]{close kinship}, and the Racket developershad already figured out how to @seclink["reader" #:doc '(lib "scribblings/scribble/scribble.scrbl")]{embed code in text}. (For more about the benefits of Racket, see @link["http://practicaltypography.com/why-racket-why-lisp.html"]{Why Racket? Why Lisp?})}
]
]
But don't take my word for it. The rest of this documentation will show you the useful and sophisticated things you can do with Pollen. If there's another tool that suits you better, great. Keep in mind that I didn't make Pollen because I'm a programmer. I'm a writer who wants to make electronic books that are better than the ones we have now. And for that, I needed a better tool.
But don't take my word for it. The rest of this documentation will show you the useful and sophisticated things you can do with Pollen. If there's another tool that suits you better, great. Keep in mind that I didn't make Pollen because I'm a programmer. I'm a writer who wants to make electronic books that are better than the ones we have now. And for that, I needed a better tool.
Consistent with Racket's @seclink["Package_Concepts" #:doc '(lib "pkg/scribblings/pkg.scrbl")]{version-numbering system}, the first digit reflects major updates to Pollen that break backward compatibility. The second digit reflects feature updates that don't affect existing features.
Inconsistent with this system, Pollen's version also appends a build number, which is the age of the software in days and seconds. (The official version reported in Pollen's @filepath{info.rkt} is just the major + minor digits.)
@section{Source code}
Pollen's source code is @link["http://github.com/mbutterick/pollen"]{available from this Git repo}. The @tt{MASTER} branch of the repo will always contain the most recent stable version.
Racket's @link["http://pkg.racket-lang.org"]{package catalog} relies on this branch, so if you get your updates with @tt{raco pkg update pollen}, you'll get the most recent updates from this branch.
I will add Git tags to commits where the major or minor version changed, so if you need to rebuild an earlier version, you can.
@section{Development policy}
Beyond keeping the commit history available, I make no promise to maintain the public interface in its current state. I will avoid unnecessary upheaval, of course. But my goal is to make the system more capable and stable, not to permanently burden it with my current level of ignorance.
@section{Changelog}
@subsection{Version 1.0}
@bold{New features}
@racketmodname[pollen/cache]: @racket[cached-doc] and @racket[cached-metas] are the preferred way to retrieve data from a Pollen source file.
The @racketmodname[pollen/core] module has been added, the new home for functions that once lived in @racketmodname[pollen/template]. Also new splicing tag @racket[\@] and @racket[when/splice] macro.
@racketmodname[pollen/setup] replaces @racketfont{pollen/world}. @racketmodname[pollen/setup] values can be overridden with a @racket[setup] submodule. Parameter names are no longer prefixed.
@bold{Backward incompatibilities}
@racketmodname[pollen/cache]: @racketfont{cached-require} is deprecated. Use @racket[cached-doc] or @racket[cached-metas].
@racketmodname[pollen/template]: functions like @racket[get-doc], @racket[get-metas], and the @racket[select] functions have been moved to @racketmodname[pollen/core]. @racketfont{when/block} is deprecated in favor of @racket[when/splice].
@racketmodname[pollen/template]: @racketfont{detect-paragraphs} and @racketfont{detect-linebreaks} have been renamed @racket[decode-paragraphs] and @racket[decode-linebreaks]. Typography functions like @racket[smart-quotes] and @racket[smart-dashes] have been moved to @racketmodname[pollen/unstable/typography]. @racket[register-block-tags] is gone —override @racket[default-block-tags] instead.
@racketmodname[pollen/file]: refined to a more carefully curated set of functions.
@racketmodname[pollen/template]: Pollen now supports any output formats, so this module has been broken into format-specific versions. For now, the only submodule is @racketmodname[pollen/template/html], the home of @racket[->html].
@racketfont{pollen/world}: superseded by @racketmodname[pollen/setup] (see above). The @racket[config] submodule in a @filepath{pollen.rkt} will no longer work.