5 lines
141 KiB
HTML
5 lines
141 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"/><title>6 Second tutorial</title><link rel="stylesheet" type="text/css" href="scribble.css" title="default"/><link rel="stylesheet" type="text/css" href="racket.css" title="default"/><link rel="stylesheet" type="text/css" href="manual-style.css" title="default"/><link rel="stylesheet" type="text/css" href="manual-racket.css" title="default"/><link rel="stylesheet" type="text/css" href="mb.css" title="default"/><script type="text/javascript" src="scribble-common.js"></script><script type="text/javascript" src="manual-racket.js"></script><!--[if IE 6]><style type="text/css">.SIEHidden { overflow: hidden; }</style><![endif]--></head><body id="scribble-racket-lang-org"><div class="tocset"><div class="tocview"><div class="tocviewlist tocviewlisttopspace"><div class="tocviewtitle"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,"tocview_0");">▼</a></td><td></td><td><a href="index.html" class="tocviewlink" data-pltdoc="x">Pollen:<span class="mywbr"> </span> the book is a program</a></td></tr></table></div><div class="tocviewsublisttop" style="display: block;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right">1 </td><td><a href="Installation.html" class="tocviewlink" data-pltdoc="x">Installation</a></td></tr><tr><td align="right">2 </td><td><a href="quick-tour.html" class="tocviewlink" data-pltdoc="x">Quick tour</a></td></tr><tr><td align="right">3 </td><td><a href="Backstory.html" class="tocviewlink" data-pltdoc="x">Backstory</a></td></tr><tr><td align="right">4 </td><td><a href="big-picture.html" class="tocviewlink" data-pltdoc="x">The big picture</a></td></tr><tr><td align="right">5 </td><td><a href="first-tutorial.html" class="tocviewlink" data-pltdoc="x">First tutorial</a></td></tr><tr><td align="right">6 </td><td><a href="second-tutorial.html" class="tocviewselflink" data-pltdoc="x">Second tutorial</a></td></tr><tr><td align="right">7 </td><td><a href="third-tutorial.html" class="tocviewlink" data-pltdoc="x">Third tutorial</a></td></tr><tr><td align="right">8 </td><td><a href="raco-pollen.html" class="tocviewlink" data-pltdoc="x">Using <span class="stt">raco pollen</span></a></td></tr><tr><td align="right">9 </td><td><a href="File_formats.html" class="tocviewlink" data-pltdoc="x">File formats</a></td></tr><tr><td align="right">10 </td><td><a href="reader.html" class="tocviewlink" data-pltdoc="x">◊ command overview</a></td></tr><tr><td align="right">11 </td><td><a href="Module_reference.html" class="tocviewlink" data-pltdoc="x">Module reference</a></td></tr><tr><td align="right">12 </td><td><a href="Acknowledgments.html" class="tocviewlink" data-pltdoc="x">Acknowledgments</a></td></tr><tr><td align="right">13 </td><td><a href="License___source_code.html" class="tocviewlink" data-pltdoc="x">License & source code</a></td></tr><tr><td align="right"></td><td><a href="doc-index.html" class="tocviewlink" data-pltdoc="x">Index</a></td></tr></table></div></div><div class="tocviewlist"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,"tocview_1");">►</a></td><td>6 </td><td><a href="second-tutorial.html" class="tocviewselflink" data-pltdoc="x">Second tutorial</a></td></tr></table><div class="tocviewsublistbottom" style="display: none;" id="tocview_1"><table cellspacing="0" cellpadding="0"><tr><td align="right">6.1 </td><td><a href="second-tutorial.html#%28part._tutorial-2._.Prerequisites%29" class="tocviewlink" data-pltdoc="x">Prerequisites</a></td></tr><tr><td align="right">6.2 </td><td><a href="second-tutorial.html#%28part._.Prelude__my_principled_objection_to_.Markdown%29" class="tocviewlink" data-pltdoc="x">Prelude:<span class="mywbr"> </span> my principled objection to Markdown</a></td></tr><tr><td align="right">6.3 </td><td><a href="second-tutorial.html#%28part._.Markdown_in_.Pollen__two_options%29" class="tocviewlink" data-pltdoc="x">Markdown in Pollen:<span class="mywbr"> </span> two options</a></td></tr><tr><td align="right">6.4 </td><td><a href="second-tutorial.html#%28part._tutorial-2._.Templates%29" class="tocviewlink" data-pltdoc="x">Templates</a></td></tr><tr><td align="right">6.5 </td><td><a href="second-tutorial.html#%28part._tutorial-2._.Intermission%29" class="tocviewlink" data-pltdoc="x">Intermission</a></td></tr><tr><td align="right">6.6 </td><td><a href="second-tutorial.html#%28part._tutorial-2._.Pagetrees%29" class="tocviewlink" data-pltdoc="x">Pagetrees</a></td></tr><tr><td align="right">6.7 </td><td><a href="second-tutorial.html#%28part._.Second_tutorial_complete%29" class="tocviewlink" data-pltdoc="x">Second tutorial complete</a></td></tr></table></div></div></div><div class="tocsub"><div class="tocsubtitle">On this page:</div><table class="tocsublist" cellspacing="0"><tr><td><span class="tocsublinknumber">6.1<tt> </tt></span><a href="#%28part._tutorial-2._.Prerequisites%29" class="tocsubseclink" data-pltdoc="x">Prerequisites</a></td></tr><tr><td><span class="tocsublinknumber">6.2<tt> </tt></span><a href="#%28part._.Prelude__my_principled_objection_to_.Markdown%29" class="tocsubseclink" data-pltdoc="x">Prelude:<span class="mywbr"> </span> my principled objection to Markdown</a></td></tr><tr><td><span class="tocsublinknumber">6.3<tt> </tt></span><a href="#%28part._.Markdown_in_.Pollen__two_options%29" class="tocsubseclink" data-pltdoc="x">Markdown in Pollen:<span class="mywbr"> </span> two options</a></td></tr><tr><td><span class="tocsublinknumber">6.3.1<tt> </tt></span><a href="#%28part._.Using_.Markdown_with_the_preprocessor%29" class="tocsubseclink" data-pltdoc="x">Using Markdown with the preprocessor</a></td></tr><tr><td><span class="tocsublinknumber">6.3.2<tt> </tt></span><a href="#%28part._.Authoring_mode%29" class="tocsubseclink" data-pltdoc="x">Authoring mode</a></td></tr><tr><td><span class="tocsublinknumber">6.3.3<tt> </tt></span><a href="#%28part._.X-expressions%29" class="tocsubseclink" data-pltdoc="x">X-<wbr></wbr>expressions</a></td></tr><tr><td><span class="tocsublinknumber">6.3.4<tt> </tt></span><a href="#%28part._.Markdown_authoring_mode%29" class="tocsubseclink" data-pltdoc="x">Markdown authoring mode</a></td></tr><tr><td><span class="tocsublinknumber">6.4<tt> </tt></span><a href="#%28part._tutorial-2._.Templates%29" class="tocsubseclink" data-pltdoc="x">Templates</a></td></tr><tr><td><span class="tocsublinknumber">6.4.1<tt> </tt></span><a href="#%28part._tutorial-2._.The_-_html_function_and_the_doc_variable%29" class="tocsubseclink" data-pltdoc="x">The <span class="stt">-<wbr></wbr>>html</span> function and the <span class="stt">doc</span> variable</a></td></tr><tr><td><span class="tocsublinknumber">6.4.2<tt> </tt></span><a href="#%28part._tutorial-2._.Making_a_custom_template%29" class="tocsubseclink" data-pltdoc="x">Making a custom template</a></td></tr><tr><td><span class="tocsublinknumber">6.4.3<tt> </tt></span><a href="#%28part._tutorial-2._.Inserting_specific_source_data_into_templates%29" class="tocsubseclink" data-pltdoc="x">Inserting specific source data into templates</a></td></tr><tr><td><span class="tocsublinknumber">6.4.4<tt> </tt></span><a href="#%28part._tutorial-2._.Linking_to_an_external_.C.S.S_file%29" class="tocsubseclink" data-pltdoc="x">Linking to an external CSS file</a></td></tr><tr><td><span class="tocsublinknumber">6.5<tt> </tt></span><a href="#%28part._tutorial-2._.Intermission%29" class="tocsubseclink" data-pltdoc="x">Intermission</a></td></tr><tr><td><span class="tocsublinknumber">6.6<tt> </tt></span><a href="#%28part._tutorial-2._.Pagetrees%29" class="tocsubseclink" data-pltdoc="x">Pagetrees</a></td></tr><tr><td><span class="tocsublinknumber">6.6.1<tt> </tt></span><a href="#%28part._tutorial-2._.Pagetree_navigation%29" class="tocsubseclink" data-pltdoc="x">Pagetree navigation</a></td></tr><tr><td><span class="tocsublinknumber">6.6.2<tt> </tt></span><a href="#%28part._tutorial-2._.Using_the_automatic_pagetree%29" class="tocsubseclink" data-pltdoc="x">Using the automatic pagetree</a></td></tr><tr><td><span class="tocsublinknumber">6.6.3<tt> </tt></span><a href="#%28part._tutorial-2._.Adding_navigation_links_to_the_template_with_here%29" class="tocsubseclink" data-pltdoc="x">Adding navigation links to the template with <span class="stt">here</span></a></td></tr><tr><td><span class="tocsublinknumber">6.6.4<tt> </tt></span><a href="#%28part._tutorial-2._.Handling_navigation_boundaries_with_conditionals%29" class="tocsubseclink" data-pltdoc="x">Handling navigation boundaries with conditionals</a></td></tr><tr><td><span class="tocsublinknumber">6.6.5<tt> </tt></span><a href="#%28part._tutorial-2._.Making_a_pagetree_source_file%29" class="tocsubseclink" data-pltdoc="x">Making a pagetree source file</a></td></tr><tr><td><span class="tocsublinknumber">6.6.6<tt> </tt></span><a href="#%28part._tutorial-2._index_ptree___the_project_server%29" class="tocsubseclink" data-pltdoc="x"><span class="stt">index.ptree</span> & the project server</a></td></tr><tr><td><span class="tocsublinknumber">6.7<tt> </tt></span><a href="#%28part._.Second_tutorial_complete%29" class="tocsubseclink" data-pltdoc="x">Second tutorial complete</a></td></tr></table></div></div><div class="maincolumn"><div class="main"><div class="versionbox"><span class="version">6.1.0.8</span></div><div class="navsettop"><span class="navleft"><div class="nosearchform"></div> </span><span class="navright"> <a href="first-tutorial.html" title="backward to "5 First tutorial"" data-pltdoc="x">← prev</a> <a href="index.html" title="up to "Pollen: the book is a program"" data-pltdoc="x">up</a> <a href="third-tutorial.html" title="forward to "7 Third tutorial"" data-pltdoc="x">next →</a></span> </div><h3>6<tt> </tt><a name="(part._second-tutorial)"></a>Second tutorial</h3><p>In this tutorial, you’ll use Pollen to publish a multiple-page article written in Markdown. You’ll learn about:</p><ul><li><p>Using Markdown files with the preprocessor</p></li><li><p>X-expressions</p></li><li><p>Markdown authoring mode</p></li><li><p>Templates</p></li><li><p>Pagetrees</p></li></ul><p>If you want the shortest possible introduction to Pollen, try the <a href="quick-tour.html" data-pltdoc="x">Quick tour</a>.</p><h4>6.1<tt> </tt><a name="(part._tutorial-2._.Prerequisites)"></a>Prerequisites</h4><p>I’ll assume you’ve completed the <a href="first-tutorial.html" data-pltdoc="x">First tutorial</a> and you understand how to create source files in DrRacket and view them in the project server. I will not be spelling out those tasks as I did before.</p><h4>6.2<tt> </tt><a name="(part._.Prelude__my_principled_objection_to_.Markdown)"></a>Prelude: my principled objection to Markdown</h4><p>I recognize that people like Markdown. I want people to like Pollen too, so that’s why Markdown support exists in Pollen. But just to be clear about my own views —</p><p>I’m mystified by the popularity of Markdown among writers. I can agree that it’s a clever and readable way of notating basic HTML. And sure, that makes it great for things like web comments, where speed and simplicity are primary virtues.</p><p>In longer-form writing, however, its shortcomings become evident. Like programming languages, the best writing tools maximize expressive possibilities, and minimize constraints. But Markdown is hugely constrained. First and worst, Markdown isn’t semantic. It only knows about formatting, and in that regard, isn’t that much of an improvement on tools like Microsoft Word. Second, even as a formatting-notation tool, it’s limited to a small subset of the already-small set of formatting tags permitted in HTML. Third, it can’t be extended by an author.</p><p>An animating principle of Pollen, as explained in the <a href="Backstory.html" data-pltdoc="x">Backstory</a>, is that after 20 years, we ought to move beyond thinking of HTML as a source format. Since Markdown is just well-disguised HTML, a vote for Markdown is really a vote to continue the status quo (albeit with fewer angle brackets). For me, that’s not good enough. I’m ready for the tools to expand to fit my ideas; I don’t want to keep cutting down my ideas to fit the tools.</p><p>All that said, if you genuinely prefer Markdown, I’m not looking to pry it from your fingers. Pollen has excellent Markdown support (due entirely to Greg Hendershott’s excellent <a href="https://github.com/greghendershott/markdown/">Markdown parser</a> for Racket). It makes Markdown more useful.</p><p>But let’s make a deal, Markdown fans. Having met you more than halfway, will you at least consider that <a href="third-tutorial.html#%28part._.Pollen_markup_vs__.X.M.L%29" data-pltdoc="x">Pollen markup</a> might be a better option for you than Markdown? Because it can notate anything that’s in your brain, not just a subset of HTML? And if <a href="big-picture.html#%28part._the-book-is-a-program%29" data-pltdoc="x">The book is a program</a>, the source for that book should look more like your brain, and less like HTML?</p><p>That’s all I ask.</p><h4>6.3<tt> </tt><a name="(part._.Markdown_in_.Pollen__two_options)"></a>Markdown in Pollen: two options</h4><p>There are two ways to use Markdown within Pollen: you can either send Markdown files through the preprocessor, or use Markdown authoring mode.</p><p>The preprocessor approach is better if you want to end up with a set of Markdown files that can be passed along to a HTML converter (or other Markdown-to-______ converter) elsewhere.</p><p>The authoring-mode approach is better if you want to end up with something other than Markdown, e.g., finished HTML files.</p><h5>6.3.1<tt> </tt><a name="(part._.Using_.Markdown_with_the_preprocessor)"></a>Using Markdown with the preprocessor</h5><p>Because Markdown is a text-based format, you can use the Pollen preprocessor to add programmatic features to existing Markdown files. (See <a href="first-tutorial.html#%28part._.Working_with_the_preprocessor%29" data-pltdoc="x">Working with the preprocessor</a> in the <a href="first-tutorial.html" data-pltdoc="x">First tutorial</a> if you need a refresher.)</p><p>Suppose we have a Markdown file called <span class="stt">brennan.md</span> that we want to use with the preprocessor. Create this file in DrRacket, save it, and start the project server in that directory.</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"brennan.md"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">My</span><span class="hspace"> </span><span class="RktMeta">name</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta">_Brennan_</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">and</span><span class="hspace"> </span><span class="RktMeta">I</span><span class="hspace"> </span><span class="RktMeta">enjoy:</span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">+</span><span class="hspace"> </span><span class="RktMeta">boring</span><span class="hspace"> </span><span class="RktMeta">sauce</span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">+</span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">24</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">fish</span><span class="hspace"> </span><span class="RktMeta">nuggets</span></td></tr></table></blockquote></div></div></div></div><p>You’ll be able to see this file in the project server, but for now, it’s just a static file. Pollen isn’t doing anything to it.</p><p>Let’s change that. Consistent with the usual preprocessor practice, we add <span class="stt">#lang pollen</span> as the first line, and append the <span class="stt">.pp</span> file extension, so our new preprocessor-ready file looks like this:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"brennan.md.pp"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">#lang</span><span class="hspace"> </span><span class="RktMeta"></span><a href="index.html" class="RktModLink" data-pltdoc="x"><span class="RktSym">pollen</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">My</span><span class="hspace"> </span><span class="RktMeta">name</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta">_Brennan_</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">and</span><span class="hspace"> </span><span class="RktMeta">I</span><span class="hspace"> </span><span class="RktMeta">enjoy:</span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">+</span><span class="hspace"> </span><span class="RktMeta">boring</span><span class="hspace"> </span><span class="RktMeta">sauce</span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">+</span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">24</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">fish</span><span class="hspace"> </span><span class="RktMeta">nuggets</span></td></tr></table></blockquote></div></div></div></div><p>Go back to the project server and you’ll see the new filename. When you click on it, Pollen will render a new <span class="stt">markdown.md</span> file, but it will look the same as the one you had before.</p><p>Now we’ll change some of the values using Pollen commands:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"brennan.md.pp"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">#lang</span><span class="hspace"> </span><span class="RktMeta"></span><a href="index.html" class="RktModLink" data-pltdoc="x"><span class="RktSym">pollen</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">sauce-type</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"fancy"</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">nugget-type</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"chicken"</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">nugget-quantity</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/generic-numbers.html#%28def._%28%28quote._~23~25kernel%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">2</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">2</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">My</span><span class="hspace"> </span><span class="RktMeta">name</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta">_Brennan_</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">and</span><span class="hspace"> </span><span class="RktMeta">I</span><span class="hspace"> </span><span class="RktMeta">enjoy:</span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">+</span><span class="hspace"> </span><span class="RktMeta">◊</span><span class="RktSym">sauce-type</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">sauce</span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">+</span><span class="hspace"> </span><span class="RktMeta">◊</span><span class="RktSym">nugget-quantity</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">◊</span><span class="RktSym">nugget-type</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">nuggets</span></td></tr></table></blockquote></div></div></div></div><p>When you reload this file in the project server, <span class="stt">brennan.md</span> will be regenerated, and will now look like this:</p><div class="terminal"><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">My name is _Brennan_, and I enjoy:</span></p></td></tr><tr><td><p><span class="stt"></span><span class="hspace"> </span></p></td></tr><tr><td><p><span class="stt">+ fancy sauce</span></p></td></tr><tr><td><p><span class="stt"></span><span class="hspace"> </span></p></td></tr><tr><td><p><span class="stt">+ 12 chicken nuggets</span></p></td></tr></table></div></div><p>Instead of running Markdown files through the preprocessor, you can also use Markdown authoring mode within Pollen. This is the better choice if you want to end up with rendered HTML files.</p><p>But first, let’s pause to clarify the general concept of an authoring mode.</p><h5>6.3.2<tt> </tt><a name="(part._.Authoring_mode)"></a>Authoring mode</h5><p>Though the preprocessor is useful, it limits you to inserting chunks of text at various positions into an existing file.</p><p>Pollen’s <span style="font-style: italic">authoring mode</span>, by contrast, parses the whole source file into a special data structure called an <span style="font-style: italic">X-expression</span>. You can then process the whole X-expression any way you like, and output to any format you like — or multiple formats — using a <span style="font-style: italic">template</span>.</p><p>Compared to the preprocessor, authoring mode offers more abstraction and flexibility. Of course, it’s also a bit more effort to set up.</p><p>Pollen offers two variants of authoring mode: one that uses Markdown syntax (which we’ll cover later in this tutorial) and the other that uses a free-form markup syntax (which we’ll cover in the next tutorial). In both cases, the basic idea is the same: parse the source into an X-expression, and then output it using a template.</p><h5>6.3.3<tt> </tt><a name="(part._.X-expressions)"></a>X-expressions</h5><div class="noskip"><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>Don’t skip this section! It explains a concept that’s essential to understanding how Pollen works.</p></blockquote></blockquote></blockquote></div><p>I avoid nerdy jargon whenever possible. But in this case, the thing is called an <span style="font-style: italic">X-expression</span> throughout the Racket documentation, for good reasons. So I use the term too. Better to acclimate you now.</p><p>An X-expression is a way of representing markup-based data in code. X-expressions are indigenous to Lisp-based languages like Pollen and Racket. They don’t exist in Python or JavaScript or Ruby.</p><p>Let’s start with the part you’re familiar with. By “markup-based data,” I mean things like HTML and XML and SVG. The idea is that you have text-based data surrounded by <span style="font-style: italic">tags</span>. Each tag can also have its own <span style="font-style: italic">attributes</span> that are made of keys and values. Tags can contain other tags, thus creating a tree-like structure. Right? You know what I mean:</p><div class="terminal"><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt"><body><h1>Hello world</h1><p class="first">Nice to <i>see</i> you.</p></body></span></p></td></tr></table></div></div><p>An X-expression is just a simplified, generalized method of notation for these data structures — much like Markdown is a simplified method of notation for HTML. To see the relationship, we’ll convert one into the other.</p><p>First, we change the angle brackets to parentheses, and only use them on the outside of tags:</p><div class="terminal"><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">(body (h1 Hello world /h1) (p class="first" Nice to (i see /i) you. /p) /body)</span></p></td></tr></table></div></div><p>Then we get rid of the closing tags, which are superfluous, since each closing parenthesis adequately marks the end of the tag:</p><div class="terminal"><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">(body (h1 Hello world) (p class="first" Nice to (i see) you.))</span></p></td></tr></table></div></div><p>However, this creates ambiguity between the name of the tag and the content. So we’ll put the content within double quotes:</p><div class="terminal"><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">(body (h1 "Hello world") (p class="first" "Nice to" (i "see") "you."))</span></p></td></tr></table></div></div><p>As for the <span class="stt">class</span> attribute, we need to distinguish it from both the markup tags and the content, so we’ll move it between double parentheses:</p><div class="terminal"><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">(body (h1 "Hello world") (p ((class "first")) "Nice to" (i "see") "you."))</span></p></td></tr></table></div></div><p>Net of a few boring details, that’s basically all there is to it.</p><p>So why is it called an X-expression? Lisp languages are built out of units called S-expressions, which look like this:</p><div class="terminal"><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">(and (txexpr? x) (member (get-tag x) (project-block-tags)) #t))</span></p></td></tr></table></div></div><p>S-expressions use prefix notation, where each pair of parentheses contains a list. The first element in the list names a function, and the other elements are the arguments to that function. (This is a review of <a href="first-tutorial.html#%28part._.Racket_basics__if_you_re_not_familiar_%29" data-pltdoc="x">Racket basics (if you’re not familiar)</a>.) X-expressions are just a minor adaptation of S-expression notation to represent markup, hence the name (the <span style="font-style: italic">X</span> is short for <span style="font-style: italic">XML-like</span>).</p><p>For handling markup-based data, X-expressions have some useful advantages compared to other methods:</p><ul><li><p><span style="font-weight: bold">Readability.</span> X-expressions retain all the semantics of markup-based data while dispensing with the infamous verbosity.</p></li><li><p><span style="font-weight: bold">A hybrid between a tree and a string.</span> Most programming languages represent markup-based data either as a string or as an XML tree. Neither is a good choice. The string captures none of the internal structure of the data. An XML tree captures the structure, but conceals the sequential nature of the data elements. The X-expression gets both.</p></li><li><p><span style="font-weight: bold">An ideal match for an expression-based programming language.</span> Aside from some notational details, X-expressions are just a subset of S-expressions generally, which are the building block of Racket. Processing X-expressions in Racket maximizes flexibility and minimizes <a href="http://programmers.stackexchange.com/questions/34775/correct-definition-of-the-term-yak-shaving">yak-shaving</a>.</p></li></ul><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>Given the close kinship between XML-ish data structures and Lisp-ish programming languages, I have no explanation why, during the Internet era, they have not been paired more often.</p></blockquote></blockquote></blockquote><p>In Pollen’s authoring modes, your source file is parsed into an X-expression, which can then be processed further before being injected into a template & converted to output. As a first example, we’ll look at Markdown authoring mode.</p><h5>6.3.4<tt> </tt><a name="(part._.Markdown_authoring_mode)"></a>Markdown authoring mode</h5><p>Let’s start putting together our article. For simplicity, I’m going to use unrealistically short sample texts. But you can use whatever Markdown content you want.</p><p>We want to use Markdown authoring mode to make a file that will ultimately be HTML. So consistent with Pollen file-naming conventions (see <a href="first-tutorial.html#%28part._.Saving___naming_your_source_file%29" data-pltdoc="x">Saving & naming your source file</a>), we’ll start with our desired output filename, <span class="stt">article.html</span>, and then append the Markdown authoring suffix, <span class="stt">.pmd</span>. So in DrRacket, start a new file called <span class="stt">article.html.pmd</span> and put some Markdown in it:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"article.html.pmd"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">#lang</span><span class="hspace"> </span><span class="RktMeta"></span><a href="index.html" class="RktModLink" data-pltdoc="x"><span class="RktSym">pollen</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">Deep</span><span class="hspace"> </span><span class="RktMeta">Thought</span></td></tr><tr><td><span class="RktMeta">============</span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">I</span><span class="hspace"> </span><span class="RktMeta">am</span><span class="hspace"> </span><span class="RktMeta">**so**</span><span class="hspace"> </span><span class="RktMeta">happy</span><span class="hspace"> </span><span class="RktMeta">to</span><span class="hspace"> </span><span class="RktMeta">be</span><span class="hspace"> </span><span class="RktMeta">writing</span><span class="hspace"> </span><span class="RktMeta">this.</span></td></tr></table></blockquote></div></div></div></div><p>Before you preview this file in the project server, click the <span class="ssansserif">Run</span> button in DrRacket just to see what the file produces. You’ll see something like this:</p><blockquote class="SubFlow"><p><span class="RktVal"><span class="stt">'(root (h1 ((id "my-article")) "Deep Thought") (p () "I am "<br/>(strong () "so") " happy to be writing this."))</span></span></p></blockquote><p>You should now be able to recognize this as an X-expression. In authoring mode, Pollen parses your Markdown into the corresponding HTML entities, but then provides the data as an X-expression rather than finished HTML.</p><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>The empty parentheses <span class="stt">()</span> after <span class="stt">p</span> and <span class="stt">strong</span> signal that the tag’s attributes are empty. When you write an X-expression without attributes, these parentheses are optional — <span class="stt">(tag () "text")</span> and <span class="stt">(tag "text")</span> are equivalent — but Pollen will always print X-expressions this way.</p></blockquote></blockquote></blockquote><p>From what you learned in the last section, it should be evident that this X-expression corresponds to HTML that looks like this:</p><blockquote class="SubFlow"><p><span class="RktVal"><span class="stt"><root><h1 id="my-article">Deep Thought</h1><p>I am <br/><strong>so</strong> happy to be writing this.</p></root></span></span></p></blockquote><p>“But what’s this <span class="stt">root</span> tag? That’s not HTML.” An X-expression must have a root tag, so in the spirit of obviousness, every X-expression produced by a source file in authoring mode will start with <span class="stt">root</span>. If you don’t need it, you can discard it. But it also creates a useful hook for further processing, as we’ll see later.</p><p>By the way, as review, let’s remind ourselves how this is different from preprocessor mode. Let’s take the same Markdown content, but this time put it into a preprocessor source file called <span class="stt">article.md.pp</span>.</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"article.md.pp"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">#lang</span><span class="hspace"> </span><span class="RktMeta"></span><a href="index.html" class="RktModLink" data-pltdoc="x"><span class="RktSym">pollen</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">Deep</span><span class="hspace"> </span><span class="RktMeta">Thought</span></td></tr><tr><td><span class="RktMeta">============</span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">I</span><span class="hspace"> </span><span class="RktMeta">am</span><span class="hspace"> </span><span class="RktMeta">**so**</span><span class="hspace"> </span><span class="RktMeta">happy</span><span class="hspace"> </span><span class="RktMeta">to</span><span class="hspace"> </span><span class="RktMeta">be</span><span class="hspace"> </span><span class="RktMeta">writing</span><span class="hspace"> </span><span class="RktMeta">this.</span></td></tr></table></blockquote></div></div></div></div><p>When you run this file in DrRacket, you’ll see:</p><blockquote class="SubFlow"><p><span class="RktVal"><span class="stt">Deep Thought<br/>============<br/><br/>I am **so** happy to be writing this.</span></span></p></blockquote><p>Hopefully, this result makes sense to you: when you run Markdown source in preprocessor mode, you get Markdown. When you run Markdown source in authoring mode, you get an X-expression.</p><h4>6.4<tt> </tt><a name="(part._tutorial-2._.Templates)"></a>Templates</h4><p>So how do you convert an X-expression into a finished file? You use a Pollen <span style="font-style: italic">template</span>, which takes data from an X-expression and converts it to the target format.</p><p>If you’ve used other web-publishing systems, templates are probably a familiar idea. Templates in Pollen are in some ways similar to the ones you’ve seen before, but in other ways different.</p><p>First, the similarities. At its simplest, a template holds boilerplate material that you want to reuse across multiple pages. For instance, in a set of HTML pages, you might have layout and navigation elements that stay the same, while the content changes. In that case, you could put the layout and navigation in the template, and keep the content in your Pollen source files. When you want to add a new page, you can make a new source file and just use it with the existing template. Moreover, if you want to change the layout and navigation globally, you can just change the template, rather than changing the source files.</p><p>Pollen templates, like others, can also have conditional features — meaning, you can embed simple code in your templates that allows them to change based on the content in the page. For instance, a template could show or hide “previous page” and “next page” links depending on whether there’s actually a previous or next page.</p><p>The major difference with Pollen templates is that there’s no special “template language” you need to learn, with magic delimiters and whatnot. Instead, you can use all the same Pollen commands in a template that you can in authoring mode or preprocessor mode.</p><p>To see a template in action, let’s return to the source file we started in the last section:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"article.html.pmd"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">#lang</span><span class="hspace"> </span><span class="RktMeta"></span><a href="index.html" class="RktModLink" data-pltdoc="x"><span class="RktSym">pollen</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">Deep</span><span class="hspace"> </span><span class="RktMeta">Thought</span></td></tr><tr><td><span class="RktMeta">============</span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">I</span><span class="hspace"> </span><span class="RktMeta">am</span><span class="hspace"> </span><span class="RktMeta">**so**</span><span class="hspace"> </span><span class="RktMeta">happy</span><span class="hspace"> </span><span class="RktMeta">to</span><span class="hspace"> </span><span class="RktMeta">be</span><span class="hspace"> </span><span class="RktMeta">writing</span><span class="hspace"> </span><span class="RktMeta">this.</span></td></tr></table></blockquote></div></div></div></div><p>Last time, I had you run this file in DrRacket to see the X-expression it produced. This time, load it in the project server. You’ll see something like this:</p><div class="browser"><div class="SIntrapara"><span style="font-weight: bold"><span class="Larger">Deep Thought</span></span><br/><br/>I am <span style="font-weight: bold">so</span> happy to be writing this.</div></div><p>Here, you’re seeing the X-expression from your source combined with an HTML template, which adds the necessary boilerplate for the finished HTML:</p><blockquote class="SubFlow"><p><span class="RktVal"><span class="stt"><html><head><meta charset="UTF-8" /></head><body><br/><root><h1 id="my-article">Deep Thought</h1><p>I am<br/><strong>so</strong> happy to be writing this.</p></root><br/></body></html></span></span></p></blockquote><p>But wait — where did the template come from? When you view an authoring-mode source file in the project server without specifying a template, Pollen helps you out and uses its <span style="font-style: italic">fallback template</span>. The fallback template is just a minimal template that’s used as a last resort. Under ordinary circumstances, seeing the fallback template usually signals a problem (e.g., Pollen couldn’t find the template you asked for).</p><p>But we can learn a few things from the fallback template about how to make an HTML template.</p><h5>6.4.1<tt> </tt><a name="(part._tutorial-2._.The_-_html_function_and_the_doc_variable)"></a>The <span class="stt">->html</span> function and the <span class="stt">doc</span> variable</h5><p>This is the fallback template that Pollen uses.</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"fallback.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">◊</span><span class="RktPn">(</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">html</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">head</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">meta</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">charset:</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"UTF-8"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">body</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr></table></blockquote></div></div></div></div><p>It has three key ingredients.</p><p>First, there’s an X-expression that represents a basic HTML page:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktMeta">html</span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktMeta">head</span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktMeta">meta</span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">'</span><span class="RktMeta">charset:</span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"UTF-8"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktMeta">body</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr></table></blockquote><p>This is equivalent to the HTML:</p><div class="terminal"><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt"><html><head><meta charset="UTF-8"></head><body></body></html></span></p></td></tr></table></div></div><p>But within a template, we need to explicitly convert from X-expression to HTML. So we wrap this X-expression with our second key ingredient, the Pollen command <span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">◊</span><span class="RktPn">(</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">html</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">head</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">meta</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">charset:</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"UTF-8"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">body</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr></table></blockquote><p>Third, we need to include the content from our source file. We do this by putting the variable <span class="stt">doc</span> inside the <span class="stt">body</span> tag.</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">◊</span><span class="RktPn">(</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">html</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">head</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">meta</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">charset:</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"UTF-8"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym">body</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr></table></blockquote><p>By convention, every Pollen source file makes its output available through the variable <span class="stt">doc</span>. A source file in preprocessor mode puts its text result in <span class="stt">doc</span>. And a source file in authoring mode puts its X-expression result in <span class="stt">doc</span>.</p><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>You can change the name to something other than <span class="stt">doc</span> by changing <span class="RktSym"><a href="World.html#%28def._%28%28lib._pollen%2Fworld..rkt%29._world~3amain-pollen-export%29%29" class="RktValLink" data-pltdoc="x">world:main-pollen-export</a></span>.</p></blockquote></blockquote></blockquote><p>Under the hood, a template is just a partial program that relies on a set of variables defined by another source file (fancy name: <span style="font-style: italic">lexical context</span>). So if you ran this template on its own, nothing would happen, because <span class="stt">doc</span> isn’t defined. But when you run it in the context of another source file, it picks up the <span class="stt">doc</span> that’s defined by that file.</p><p>Caution — despite the name, a Pollen template is not necessarily a file of the type suggested by its extension. For instance, <span class="stt">fallback.html</span> is a file that ultimately produces HTML, but it’s not actually written in HTML.</p><p>It could be, however. Here’s an equivalent way of writing <span class="stt">fallback.html</span> that inserts <span class="stt">doc</span> into actual HTML, rather than making the whole thing an X-expression.</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"fallback.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html><head><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktPn">(</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">)</span><span class="RktMeta"></body></html></span></td></tr></table></blockquote></div></div></div></div><p>Notice that we still need to use the <span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span> function, but this time, instead of surrounding a larger X-expression, it just goes around <span class="stt">doc</span>.</p><p>Truly, there is no difference between these two methods. Use whichever works best for you. I often prefer the second method because I like to build & test HTML layouts by hand using placeholder content to make sure all the fiddly bits work. Then it’s easy to replace the placeholder content with <span class="RktPn">(</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="stt"> </span><span class="RktSym">doc</span><span class="RktPn">)</span>, and it becomes a template.</p><h5>6.4.2<tt> </tt><a name="(part._tutorial-2._.Making_a_custom_template)"></a>Making a custom template</h5><p>We’ll use these three ingredients to make our own template for <span class="stt">article.html.pmd</span>.</p><p>In general, template files can have any name you want. But by default, Pollen will first look for a file in your project directory called <span class="stt">template.ext</span>, where <span class="stt">ext</span> matches the output-file extension of the source file. So if your source file is <span class="stt">database.xml.pmd</span>, Pollen will look for <span class="stt">template.xml</span>. And for <span class="stt">article.html.pmd</span>, Pollen will look for <span class="stt">template.html</span>.</p><p>Therefore, to set up a custom template, all we need to do is create a file called <span class="stt">template.html</span> in our project directory, and make sure it has the three key ingredients we saw in the fallback template. Pollen will automatically apply it to <span class="stt">article.html.pmd</span> when we view it in the project server.</p><p>But don’t take my word for it. In your project directory, create a new file called <span class="stt">template.html</span>:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>Custom</span><span class="hspace"> </span><span class="RktMeta">template</title></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktPn">(</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">)</span><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>Recall from the last section that this is the same as the fallback template, but written out in HTML, and with a <span class="stt">title</span> element added. In fact, you can now refresh <span class="stt">article.html</span> in the project server. Does it look different? No — it won’t, because the resulting template is the same. You should notice, however, that the title of the browser window is now “Custom template,” because Pollen is relying on your new template file, rather than the fallback template.</p><p>Let’s change our custom template by adding a <span class="stt">style</span> block:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>Custom</span><span class="hspace"> </span><span class="RktMeta">template</title></span></td></tr><tr><td><span class="RktMeta"><style</span><span class="hspace"> </span><span class="RktMeta">type=</span><span class="RktVal">"text/css"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta">body</span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">{</span><span class="RktMeta">padding:</span><span class="hspace"> </span><span class="RktMeta">3em</span><span class="RktCmt">;</span><span class="hspace"> </span><span class="RktCmt">font-size:</span><span class="hspace"> </span><span class="RktCmt">20px;}</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">h1</span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">{</span><span class="RktMeta">background:</span><span class="hspace"> </span><span class="RktMeta">gray</span><span class="RktCmt">;</span><span class="hspace"> </span><span class="RktCmt">color:</span><span class="hspace"> </span><span class="RktCmt">white;}</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">strong</span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">{</span><span class="RktMeta">color:</span><span class="hspace"> </span><span class="RktMeta">red</span><span class="RktCmt">;}</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></style></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktPn">(</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">)</span><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>When you refresh <span class="stt">article.html</span> in the project server, you’ll see that the heading now has a gray background, and one word in the text is red.</p><p>Feel free to add other settings to <span class="stt">template.html</span>, or update the text in <span class="stt">article.html</span>, and see how the page changes. As you’d expect, the project server keeps an eye on both your source files and your template files, and if one changes, it will refresh the output file automatically.</p><h5>6.4.3<tt> </tt><a name="(part._tutorial-2._.Inserting_specific_source_data_into_templates)"></a>Inserting specific source data into templates</h5><p>In the last example, we used <span class="stt">doc</span> to insert the entire content of the source file — as an X-expression — into the template.</p><p>But what if you want to only insert part of your source file into the template? For instance, you’ll look like a dork if the title on each page is “Custom template.” So let’s fix that.</p><p>When you’re working in a template, Pollen provides a <span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span> function that lets you extract the content of a specific tag, like so: <span class="stt">◊(select </span><span class="stt">’</span><span class="stt"></span><span class="RktVar">tag-name</span><span class="stt"> doc)</span>, which means “get the content of <span class="RktVar">tag-name</span> out of <span class="stt">doc</span> and put it here.”</p><p>Let’s suppose that we’d rather use the name of the article — <span style="font-style: italic">Deep Thought</span> — as the page title. We’re going to put a <span class="stt">◊(select ...)</span> command inside the <span class="stt"><title></span> tag.</p><p>Beyond that, we just need to know the tag name that contains the title. If we have a little Markdown expertise, we might already know that this part of our Markdown source:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">Deep</span><span class="hspace"> </span><span class="RktMeta">Thought</span></td></tr><tr><td><span class="RktMeta">============</span></td></tr></table></blockquote><p>is going to produce a tag named <span class="stt">h1</span>.</p><p>What if we don’t have all the Markdown conversions memorized? No problem. We can still figure out the tag name by running the <span class="stt">article.html.pmd</span> source file in DrRacket and looking at the X-expression that results:</p><blockquote class="SubFlow"><p><span class="RktVal"><span class="stt">'(root (h1 ((id "my-article")) "Deep Thought") (p () "I am "<br/>(strong () "so") " happy to be writing this."))</span></span></p></blockquote><p>Either way, now we know that the text <span style="font-style: italic">Deep Thought</span> lives in the <span class="stt">h1</span> tag. So we update our template accordingly (for brevity, I’m going to omit the <span class="stt">style</span> tag in these examples, but it’s fine to leave it in):</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>◊</span><span class="RktPn">(</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">h1</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">)</span><span class="RktMeta"></title></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktPn">(</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">)</span><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>When you refresh the page in the project server, the page title will now appear as “Deep Thought.” Of course, you can also combine static and dynamic elements in your template, like so:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>◊</span><span class="RktPn">(</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">h1</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">)</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">by</span><span class="hspace"> </span><span class="RktMeta">MB</title></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktPn">(</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">)</span><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>The page title will now be “Deep Thought, by MB”.</p><p>A couple notes on command syntax. We inserted the <span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span> and <span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span> commands using Racket-mode syntax. We could also use text-mode syntax and write the commands this way:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span><span class="RktPn">[</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">h1</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">by</span><span class="hspace"> </span><span class="RktMeta">MB</title></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktPn">[</span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>This is exactly equivalent to the previous example. Skeptics are welcome to confirm this by checking the result in the project server.</p><p>Finally, notice that in the <span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span> command, the tag name <span class="RktVal">'</span><span class="RktVal">h1</span> is written with a quote mark, whereas <span class="stt">doc</span> is not. This is an easy place to get tripped up, but the rule is simple: you don’t use a quote mark when you’re referring to the name of an existing function or variable (like <span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span> or <span class="stt">doc</span>). But you do need a quote mark when you’re using the text as a literal value.</p><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>Racket (and hence Pollen) makes a distinction between <a href="http://docs.racket-lang.org/guide/symbols.html" data-pltdoc="x">Symbols</a> (e.g. <span class="RktVal">'</span><span class="RktVal">h1</span>) and <a href="http://docs.racket-lang.org/reference/strings.html" data-pltdoc="x">Strings</a> (e.g. <span class="RktVal">"h1"</span>). Without getting into the weeds, just note for now that the tag of an X-expression is always a symbol, not a string. But if you write <span class="stt">◊(<span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span> "h1" doc)</span>, the command will still work, because Pollen will treat it as <span class="stt">◊(<span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span> 'h1 doc)</span>, consistent with a general policy of not being persnickety about input types when the intention is clear.</p></blockquote></blockquote></blockquote><h5>6.4.4<tt> </tt><a name="(part._tutorial-2._.Linking_to_an_external_.C.S.S_file)"></a>Linking to an external CSS file</h5><p>If you’re a super web hotshot, you probably don’t put your CSS selectors in the <span class="stt"><head></span> tag. Instead, you link to an external CSS file. So it will not surprise you that in Pollen, you can do this by adding the usual <span class="stt"><link></span> tag to your HTML template, in this case a file called <span class="stt">styles.css</span>:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head></span></td></tr><tr><td><span class="RktMeta"><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span><span class="RktPn">[</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">h1</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">by</span><span class="hspace"> </span><span class="RktMeta">MB</title></span></td></tr><tr><td><span class="RktMeta"><link</span><span class="hspace"> </span><span class="RktMeta">rel=</span><span class="RktVal">"stylesheet"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">type=</span><span class="RktVal">"text/css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">media=</span><span class="RktVal">"all"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"styles.css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">/></span></td></tr><tr><td><span class="RktMeta"></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktPn">[</span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>Fans of hand-coded CSS, I trust you to take it from here: make your <span class="stt">styles.css</span> file, and enjoy the results.</p><p>But folks who paid attention during the <a href="first-tutorial.html" data-pltdoc="x">First tutorial</a> might be wondering “Can we link to a dynamically generated <span class="stt">styles.css.pp</span> file?”</p><p>Yes, of course. Here’s the rule of thumb: when you’re making links between files — whether CSS, or HTML, or anything else — Pollen doesn’t care whether the file is static or dynamic. You just refer to it by its ultimate name, in this case <span class="stt">styles.css</span>. If a static <span class="stt">styles.css</span> file exists, Pollen will use that. If it doesn’t, Pollen will look for a source file it can use to make <span class="stt">styles.css</span>, and generate it on the spot. (You can also start with a static file, and change it to be dynamic later, and Pollen will do the right thing.)</p><p>So to use a dynamic CSS file, we don’t need to make any changes to <span class="stt">template.html</span>. We just need to add <span class="stt">styles.css.pp</span> to the project directory:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"styles.css.pp"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">#lang</span><span class="hspace"> </span><span class="RktMeta"></span><a href="index.html" class="RktModLink" data-pltdoc="x"><span class="RktSym">pollen</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">h1-color</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"blue"</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">strong-color</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"green"</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">body</span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">{</span><span class="RktMeta">padding:</span><span class="hspace"> </span><span class="RktMeta">3em</span><span class="RktCmt">;</span><span class="hspace"> </span><span class="RktCmt">font-size:</span><span class="hspace"> </span><span class="RktCmt">20px;}</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">h1</span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">{</span><span class="RktMeta">background:</span><span class="hspace"> </span><span class="RktMeta">◊|</span><span class="RktSym">h1-color</span><span class="RktMeta">|</span><span class="RktCmt">;</span><span class="hspace"> </span><span class="RktCmt">color:</span><span class="hspace"> </span><span class="RktCmt">white;}</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">strong</span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">{</span><span class="RktMeta">color:</span><span class="hspace"> </span><span class="RktMeta">◊|</span><span class="RktSym">strong-color</span><span class="RktMeta">|</span><span class="RktCmt">;}</span><span class="RktMeta"></span></td></tr></table></blockquote></div></div></div></div><p>Now, when you refresh <span class="stt">article.html</span> in the project server, Pollen will generate the <span class="stt">styles.css</span> file it needs, and you’ll see the new colors in the page. As before, if you update <span class="stt">styles.css.pp</span>, Pollen will notice and regenerate the CSS file when you refresh the page.</p><p>Can you add multiple dynamic style sheets? Yes.
|
|
<br/>Can you mix dynamic and static style sheets? Yes.
|
|
<br/>Can you add a dynamic JavaScript file? Yes.
|
|
<br/>You’re getting the general idea, right? So let’s move on.</p><h4>6.5<tt> </tt><a name="(part._tutorial-2._.Intermission)"></a>Intermission</h4><p>If you only need one page for your article, you can stop here. You now know everything necessary to publish a single-page article using authoring mode. You know how to create the mandatory ingredients — a source file and a template — and you also know how to link to an optional CSS file, which can be dynamically generated.</p><p>If you want to create a multi-page article, however, you need to get through one more big idea. This might be a good time to take a break.</p><h4>6.6<tt> </tt><a name="(part._tutorial-2._.Pagetrees)"></a>Pagetrees</h4><p>A <span style="font-style: italic">pagetree</span> is a hierarchical list of Pollen pages. When you have multiple pages in your project, the pagetree establishes relationships among those pages. At its most basic, a pagetree establishes a linear sequence for the pages. But pagetrees can also establish hierarchical relationships — for instance, a book-length project can be organized into chapters, the chapters into sections, and so on. The pagetree doesn’t impose any semantics on the organization of your project. It’s just a tree, and it’s up to you how many layers to establish, what those layers mean, and so on.</p><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p><span style="font-style: italic">Pagemap</span> might’ve been an equally good name, and perhaps more consistent with similar concepts in other web-publishing systems. But I avoided it out of deference to Racket’s <span class="RktSym"><a href="http://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Fprivate%2Fmap..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span> function, which means something completely different.</p></blockquote></blockquote></blockquote><h5>6.6.1<tt> </tt><a name="(part._tutorial-2._.Pagetree_navigation)"></a>Pagetree navigation</h5><p>Pagetrees are used in various ways throughout Pollen. But the most obvious use for a pagetree is to add navigational links to your pages. Obviously, in a multi-page article, readers need a way of getting from one page to the next. In this part of the tutorial, we’ll expand our sample article from one page to three, and see how to create “previous page” and “next page” links in our template that are dynamically generated relative to the current page.</p><h5>6.6.2<tt> </tt><a name="(part._tutorial-2._.Using_the_automatic_pagetree)"></a>Using the automatic pagetree</h5><p>You’ve actually already been exposed to pagetrees (though I didn’t tell you about it at the time). Recall that the dashboard of the project server is located at <span class="stt">http://localhost:8080/index.ptree</span>. The list of files you see in the dashboard is a pagetree that Pollen creates by reading the files in the current directory and arranging them in alphabetical order.</p><p>If the multiple pages in your project are already ordered by filename, then you can rely on this automatic pagetree.</p><p>From earlier in the tutorial, you have a Markdown source file called <span class="stt">article.html.pmd</span> that looks like this:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"article.html.pmd"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">#lang</span><span class="hspace"> </span><span class="RktMeta"></span><a href="index.html" class="RktModLink" data-pltdoc="x"><span class="RktSym">pollen</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">Deep</span><span class="hspace"> </span><span class="RktMeta">Thought</span></td></tr><tr><td><span class="RktMeta">============</span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">I</span><span class="hspace"> </span><span class="RktMeta">am</span><span class="hspace"> </span><span class="RktMeta">**so**</span><span class="hspace"> </span><span class="RktMeta">happy</span><span class="hspace"> </span><span class="RktMeta">to</span><span class="hspace"> </span><span class="RktMeta">be</span><span class="hspace"> </span><span class="RktMeta">writing</span><span class="hspace"> </span><span class="RktMeta">this.</span></td></tr></table></blockquote></div></div></div></div><p>Let’s supplement this source file by creating two others for the project:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"barticle.html.pmd"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">#lang</span><span class="hspace"> </span><span class="RktMeta"></span><a href="index.html" class="RktModLink" data-pltdoc="x"><span class="RktSym">pollen</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">Barticle</span><span class="hspace"> </span><span class="RktMeta">Title</span></td></tr><tr><td><span class="RktMeta">==============</span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">wonderful</span><span class="hspace"> </span><span class="RktMeta">second</span><span class="hspace"> </span><span class="RktMeta">part</span><span class="hspace"> </span><span class="RktMeta">of</span><span class="hspace"> </span><span class="RktMeta">the</span><span class="hspace"> </span><span class="RktMeta">article.</span></td></tr></table></blockquote></div></div></div></div><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"carticle.html.pmd"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">#lang</span><span class="hspace"> </span><span class="RktMeta"></span><a href="index.html" class="RktModLink" data-pltdoc="x"><span class="RktSym">pollen</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">Carticle</span><span class="hspace"> </span><span class="RktMeta">Title</span></td></tr><tr><td><span class="RktMeta">==============</span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">terrific</span><span class="hspace"> </span><span class="RktMeta">third</span><span class="hspace"> </span><span class="RktMeta">part.</span></td></tr></table></blockquote></div></div></div></div><p>As before, you can fill these source files with any sample Markdown content you like. Moreover, you don’t have to use the filenames <span class="stt">barticle.html.pmd</span> and <span class="stt">carticle.html.pmd</span> — the point is that the intended sequence needs to match the alphabetic sorting of the filenames.</p><p>We’ll reuse the <span class="stt">template.html</span> and <span class="stt">styles.css</span> files from earlier in the tutorial. Move or delete the other tutorial files so that your dashboard in the project server shows only these five files:</p><ul><li><p><span class="stt">article.html.pmd</span></p></li><li><p><span class="stt">barticle.html.pmd</span></p></li><li><p><span class="stt">carticle.html.pmd</span></p></li><li><p><span class="stt">styles.css</span> (or <span class="stt">styles.css.pp</span>)</p></li><li><p><span class="stt">template.html</span></p></li></ul><p>If you click on any of the three Markdown sources, you will see it converted into HTML using <span class="stt">template.html</span>, with styles appiled from <span class="stt">styles.css</span>.</p><p>The automatic pagetree for this project is exactly what you see in the dashboard: a list of the three article files, followed by <span class="stt">styles.css</span> and <span class="stt">template.html</span>.</p><h5>6.6.3<tt> </tt><a name="(part._tutorial-2._.Adding_navigation_links_to_the_template_with_here)"></a>Adding navigation links to the template with <span class="stt">here</span></h5><p>Recall from earlier in the tutorial that the content of your source file is made available in the template through the special variable <span class="stt">doc</span>. Likewise, the name of the current source file is made available through the special variable <span class="stt">here</span>.</p><p>To make any navigation link — up, down, sideways — the general idea is that we use <span class="stt">here</span> as input to a pagetree-navigation function, which then looks up the answer in the current pagetree.</p><p>First, let’s just see <span class="stt">here</span> on its own. Update your template as follows:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head></span></td></tr><tr><td><span class="RktMeta"><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span><span class="RktPn">[</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">h1</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">by</span><span class="hspace"> </span><span class="RktMeta">MB</title></span></td></tr><tr><td><span class="RktMeta"><link</span><span class="hspace"> </span><span class="RktMeta">rel=</span><span class="RktVal">"stylesheet"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">type=</span><span class="RktVal">"text/css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">media=</span><span class="RktVal">"all"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"styles.css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">/></span></td></tr><tr><td><span class="RktMeta"></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktPn">[</span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">current</span><span class="hspace"> </span><span class="RktMeta">page</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta">called</span><span class="hspace"> </span><span class="RktMeta">◊|</span><span class="RktSym">here</span><span class="RktMeta">|.</span></td></tr><tr><td><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>If you refresh <span class="stt">article.html</span>, you will now see the line “The current page is called article.html.” Switch to <span class="stt">barticle.html</span>, and you’ll see “The current page is called barticle.html.” Makes sense, right?</p><p>Now let’s use pagetree functions to show the names of the previous and next pages. Consistent with the usual policy of obviousness, these functions are called <span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._previous%29%29" class="RktValLink" data-pltdoc="x">previous</a></span> and <span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._next%29%29" class="RktValLink" data-pltdoc="x">next</a></span>:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head></span></td></tr><tr><td><span class="RktMeta"><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span><span class="RktPn">[</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">h1</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">by</span><span class="hspace"> </span><span class="RktMeta">MB</title></span></td></tr><tr><td><span class="RktMeta"><link</span><span class="hspace"> </span><span class="RktMeta">rel=</span><span class="RktVal">"stylesheet"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">type=</span><span class="RktVal">"text/css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">media=</span><span class="RktVal">"all"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"styles.css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">/></span></td></tr><tr><td><span class="RktMeta"></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktPn">[</span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">current</span><span class="hspace"> </span><span class="RktMeta">page</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta">called</span><span class="hspace"> </span><span class="RktMeta">◊|</span><span class="RktSym">here</span><span class="RktMeta">|.</span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">previous</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta">◊|(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._previous%29%29" class="RktValLink" data-pltdoc="x">previous</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktMeta">)|.</span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">next</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta">◊|(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._next%29%29" class="RktValLink" data-pltdoc="x">next</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktMeta">)|.</span></td></tr><tr><td><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>Refresh <span class="stt">barticle.html</span>. You’ll now see that “The current page is called barticle.html. The previous is article.html. The next is carticle.html.” So far, so good: we’re correctly deriving the previous and next pages from the automatic pagetree.</p><p>All that’s left is to add hyperlinks, which is easy:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head></span></td></tr><tr><td><span class="RktMeta"><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span><span class="RktPn">[</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">h1</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">by</span><span class="hspace"> </span><span class="RktMeta">MB</title></span></td></tr><tr><td><span class="RktMeta"><link</span><span class="hspace"> </span><span class="RktMeta">rel=</span><span class="RktVal">"stylesheet"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">type=</span><span class="RktVal">"text/css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">media=</span><span class="RktVal">"all"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"styles.css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">/></span></td></tr><tr><td><span class="RktMeta"></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktPn">[</span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">current</span><span class="hspace"> </span><span class="RktMeta">page</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta">called</span><span class="hspace"> </span><span class="RktMeta">◊|</span><span class="RktSym">here</span><span class="RktMeta">|.</span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">previous</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta"><a</span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"◊|(previous</span><span class="hspace"> </span><span class="RktVal">here)|"</span><span class="RktMeta">>◊|(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._previous%29%29" class="RktValLink" data-pltdoc="x">previous</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktMeta">)|</a>.</span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">next</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta"><a</span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"◊|(next</span><span class="hspace"> </span><span class="RktVal">here)|"</span><span class="RktMeta">>◊|(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._next%29%29" class="RktValLink" data-pltdoc="x">next</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktMeta">)|</a>.</span></td></tr><tr><td><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>Refresh <span class="stt">barticle.html</span>, and you’ll see that the names of the previous and next pages are now hyperlinks to those pages. Click through and convince yourself that it works.</p><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>The documentation for pagetree <a href="Pagetree.html#%28part._.Navigation%29" data-pltdoc="x">Navigation</a> will tell you about the other functions available for generating navigation links.</p></blockquote></blockquote></blockquote><h5>6.6.4<tt> </tt><a name="(part._tutorial-2._.Handling_navigation_boundaries_with_conditionals)"></a>Handling navigation boundaries with conditionals</h5><p>If you clicked through to <span class="stt">article.html</span> or <span class="stt">carticle.html</span>, you might’ve noticed a couple problems. Because <span class="stt">article.html</span> is the first page in the automatic pagetree, it doesn’t have any previous page it can link to. And the next-page link for <span class="stt">carticle.html</span> is <span class="stt">styles.css</span>, which is strictly correct — it is, in fact, the next file in the automatic pagetree — but it’s not part of our article, so we’d rather stop the navigation there.</p><p>One way to fix the problem would be to have three separate template files — the standard one with both previous- and next-page links, one with only a next-page link, and one with only a previous-page link.</p><p>But since we have a whole programming language available in Pollen, that’s a dull-witted way to solve the problem. The better way is to add <span style="font-style: italic">conditionals</span> to the template to selectively change the navigation. That keeps things simple, because we’ll still have only one <span class="stt">template.html</span> to deal with.</p><p>To handle <span class="stt">article.html</span>, we want to hide the previous-page navigation link when there’s no previous page. As it turns out, if the <span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._previous%29%29" class="RktValLink" data-pltdoc="x">previous</a></span> function can’t find a previous page, it will return false. So we just need to wrap our previous-page navigation in the <span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._when%2Fblock%29%29" class="RktValLink" data-pltdoc="x">when/block</a></span> command like so:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head></span></td></tr><tr><td><span class="RktMeta"><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span><span class="RktPn">[</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">h1</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">by</span><span class="hspace"> </span><span class="RktMeta">MB</title></span></td></tr><tr><td><span class="RktMeta"><link</span><span class="hspace"> </span><span class="RktMeta">rel=</span><span class="RktVal">"stylesheet"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">type=</span><span class="RktVal">"text/css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">media=</span><span class="RktVal">"all"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"styles.css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">/></span></td></tr><tr><td><span class="RktMeta"></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktPn">[</span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">current</span><span class="hspace"> </span><span class="RktMeta">page</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta">called</span><span class="hspace"> </span><span class="RktMeta">◊|</span><span class="RktSym">here</span><span class="RktMeta">|.</span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._when%2Fblock%29%29" class="RktValLink" data-pltdoc="x">when/block</a></span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._previous%29%29" class="RktValLink" data-pltdoc="x">previous</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">{</span><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">previous</span><span class="hspace"> </span><span class="RktMeta">is</span></td></tr><tr><td><span class="RktMeta"><a</span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"◊|(previous</span><span class="hspace"> </span><span class="RktVal">here)|"</span><span class="RktMeta">>◊|(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._previous%29%29" class="RktValLink" data-pltdoc="x">previous</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktMeta">)|</a>.</span><span class="RktPn">}</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">next</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta"><a</span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"◊|(next</span><span class="hspace"> </span><span class="RktVal">here)|"</span><span class="RktMeta">>◊|(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._next%29%29" class="RktValLink" data-pltdoc="x">next</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktMeta">)|</a>.</span></td></tr><tr><td><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>The basic structure of <span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._when%2Fblock%29%29" class="RktValLink" data-pltdoc="x">when/block</a></span> is <span class="stt">◊when/block[</span><span class="RktVar">condition</span><span class="stt">]{</span><span class="RktVar">insert-this-text</span><span class="stt">}.</span> Note the square braces around the <span class="RktVar">condition</span>, and the curly braces around the <span class="RktVar">text</span>. Using <span class="RktPn">(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._previous%29%29" class="RktValLink" data-pltdoc="x">previous</a></span><span class="stt"> </span><span class="RktSym">here</span><span class="RktPn">)</span> as the condition is shorthand for “when <span class="RktVal">"(previous here)"</span> does not return false...”</p><p>Programmers in the audience might be getting anxious about the repeated use of <span class="RktPn">(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._previous%29%29" class="RktValLink" data-pltdoc="x">previous</a></span><span class="stt"> </span><span class="RktSym">here</span><span class="RktPn">)</span> — you’re welcome to store that value in a variable, and everything will work the same way:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head></span></td></tr><tr><td><span class="RktMeta"><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span><span class="RktPn">[</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">h1</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">by</span><span class="hspace"> </span><span class="RktMeta">MB</title></span></td></tr><tr><td><span class="RktMeta"><link</span><span class="hspace"> </span><span class="RktMeta">rel=</span><span class="RktVal">"stylesheet"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">type=</span><span class="RktVal">"text/css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">media=</span><span class="RktVal">"all"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"styles.css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">/></span></td></tr><tr><td><span class="RktMeta"></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktPn">[</span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">current</span><span class="hspace"> </span><span class="RktMeta">page</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta">called</span><span class="hspace"> </span><span class="RktMeta">◊|</span><span class="RktSym">here</span><span class="RktMeta">|.</span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">prev-page</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._previous%29%29" class="RktValLink" data-pltdoc="x">previous</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._when%2Fblock%29%29" class="RktValLink" data-pltdoc="x">when/block</a></span><span class="RktPn">[</span><span class="RktSym">prev-page</span><span class="RktPn">]</span><span class="RktPn">{</span><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">previous</span><span class="hspace"> </span><span class="RktMeta">is</span></td></tr><tr><td><span class="RktMeta"><a</span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"◊|prev-page|"</span><span class="RktMeta">>◊|</span><span class="RktSym">prev-page</span><span class="RktMeta">|</a>.</span><span class="RktPn">}</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">next</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta"><a</span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"◊|(next</span><span class="hspace"> </span><span class="RktVal">here)|"</span><span class="RktMeta">>◊|(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._next%29%29" class="RktValLink" data-pltdoc="x">next</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktMeta">)|</a>.</span></td></tr><tr><td><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>We need a different technique for handling the end of the next-page navigation, because we’re not reaching the actual end of the pagetree. We’re just reaching the end of the pages we care about navigating through.</p><p>What condition will help us detect this? Here, we can notice that the names of our article pages all contain the string <span class="stt">article</span>. While you’d probably want a more robust condition for a real project, in this tutorial, what we’ll do is hide the next-page navigation if the name of the next page doesn’t contain “<span class="stt">article</span>”. As we did before, we wrap our navigation line in the <span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._when%2Fblock%29%29" class="RktValLink" data-pltdoc="x">when/block</a></span> function:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head></span></td></tr><tr><td><span class="RktMeta"><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span><span class="RktPn">[</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">h1</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">by</span><span class="hspace"> </span><span class="RktMeta">MB</title></span></td></tr><tr><td><span class="RktMeta"><link</span><span class="hspace"> </span><span class="RktMeta">rel=</span><span class="RktVal">"stylesheet"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">type=</span><span class="RktVal">"text/css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">media=</span><span class="RktVal">"all"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"styles.css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">/></span></td></tr><tr><td><span class="RktMeta"></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktPn">[</span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">current</span><span class="hspace"> </span><span class="RktMeta">page</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta">called</span><span class="hspace"> </span><span class="RktMeta">◊|</span><span class="RktSym">here</span><span class="RktMeta">|.</span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">prev-page</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._previous%29%29" class="RktValLink" data-pltdoc="x">previous</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._when%2Fblock%29%29" class="RktValLink" data-pltdoc="x">when/block</a></span><span class="RktPn">[</span><span class="RktSym">prev-page</span><span class="RktPn">]</span><span class="RktPn">{</span><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">previous</span><span class="hspace"> </span><span class="RktMeta">is</span></td></tr><tr><td><span class="RktMeta"><a</span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"◊|prev-page|"</span><span class="RktMeta">>◊|</span><span class="RktSym">prev-page</span><span class="RktMeta">|</a>.</span><span class="RktPn">}</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._when%2Fblock%29%29" class="RktValLink" data-pltdoc="x">when/block</a></span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/regexp.html#%28def._%28%28quote._~23~25kernel%29._regexp-match%29%29" class="RktValLink" data-pltdoc="x">regexp-match</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktVal">"article"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><span class="badlink"><span class="RktValLink">->string</span></span></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._next%29%29" class="RktValLink" data-pltdoc="x">next</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">{</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">next</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta"><a</span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"◊|(next</span><span class="hspace"> </span><span class="RktVal">here)|"</span><span class="RktMeta">>◊|(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._next%29%29" class="RktValLink" data-pltdoc="x">next</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktMeta">)|</a>.</span><span class="RktPn">}</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>This time, the condition is <span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/regexp.html#%28def._%28%28quote._~23~25kernel%29._regexp-match%29%29" class="RktValLink" data-pltdoc="x">regexp-match</a></span><span class="stt"> </span><span class="RktVal">"article"</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><span class="badlink"><span class="RktValLink">->string</span></span></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._next%29%29" class="RktValLink" data-pltdoc="x">next</a></span><span class="stt"> </span><span class="RktSym">here</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span>. How were you supposed to know this? You weren’t. That’s why this is a tutorial. Without going on a lengthy detour, the <span class="RktSym"><a href="http://docs.racket-lang.org/reference/regexp.html#%28def._%28%28quote._~23~25kernel%29._regexp-match%29%29" class="RktValLink" data-pltdoc="x">regexp-match</a></span> function returns true if the first string (in this case, <span class="RktVal">"article"</span>) is found inside the second string (in this case, we convert <span class="RktPn">(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._next%29%29" class="RktValLink" data-pltdoc="x">next</a></span><span class="stt"> </span><span class="RktSym">here</span><span class="RktPn">)</span> to a string by wrapping it in <span class="RktSym"><span class="badlink"><span class="RktValLink">->string</span></span></span>).</p><p>In any case, even if some of the programmy bits went over your head just now, relax and paste the code into your template. What you’ll see when you refresh <span class="stt">carticle.html</span> is that the next-page link is gone. So now our template lets us navigate among the pages of our article, and the conditionals handle the end pages correctly.</p><h5>6.6.5<tt> </tt><a name="(part._tutorial-2._.Making_a_pagetree_source_file)"></a>Making a pagetree source file</h5><p>I didn’t want to dwell on programming complications in the last conditional. Why? The extra programming was necessary only because we made life somewhat difficult for ourselves by relying on the automatic pagetree. A better way to solve the problem is to avoid it altogether by making a pagetree file.</p><p>Pagetree source files have a different syntax and status than other Pollen source files, so they are parsed using their own Pollen dialect. To invoke this dialect, you just start the file with <span class="stt">#lang pollen</span> and name the file with the <span class="stt">ptree</span> extension, for instance <span class="stt">my-project.ptree</span>. While you can have as many pagetrees in your project as you want, Pollen will accord primary status to the one named <span class="stt">index.ptree</span>.</p><p>So let’s make an <span class="stt">index.ptree</span> file. At its simplest, a pagetree file can just be a list of files in the intended order. In DrRacket, create a new file in your project directory as follows:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"index.ptree"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">#lang</span><span class="hspace"> </span><span class="RktMeta"></span><a href="index.html" class="RktModLink" data-pltdoc="x"><span class="RktSym">pollen</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">carticle.html</span></td></tr><tr><td><span class="RktMeta">article.html</span></td></tr><tr><td><span class="RktMeta">barticle.html</span></td></tr></table></blockquote></div></div></div></div><p>Now run the file. The result will be:</p><blockquote class="SubFlow"><p><span class="RktVal"><span class="stt">'(pagetree-root carticle.html article.html barticle.html)</span></span></p></blockquote><p>Pretty boring, I know. But behind the scenes, Pollen’s pagetree parser is making sure your tree is valid (e.g., no duplicate or malformed names). Today it’s boring, but on the day you have a long and complicated pagetree, you will be grateful.</p><p>Notice that the names in this pagetree are the names of <span style="font-style: italic">output</span> files, not source files. This is deliberate, so that neither you nor Pollen has to care which files are static vs. dynamic. This next pagetree wouldn’t be wrong in the sense of bad syntax — the pagetree parser won’t complain — but it would be wrong in the sense of not-what-you-want, because it refers to source names rather than output names:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"bad-index.ptree"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta">#lang</span><span class="hspace"> </span><span class="RktMeta"></span><a href="index.html" class="RktModLink" data-pltdoc="x"><span class="RktSym">pollen</span></a><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"> </span></td></tr><tr><td><span class="RktMeta">carticle.html.pmd</span></td></tr><tr><td><span class="RktMeta">article.html.pmd</span></td></tr><tr><td><span class="RktMeta">barticle.html.pmd</span></td></tr></table></blockquote></div></div></div></div><p>You also probably noticed that the files are in a different order than they were in the automatic pagetree: <span class="stt">carticle.html</span> is first, followed by <span class="stt">article.html</span> and then <span class="stt">barticle.html</span>. This too is deliberate, so we can see what happens with a differently ordered pagetree.</p><p>Pagetrees don’t change nearly as often as other source files, so as a performance optimization, the project server does <span style="font-style: italic">not</span> dynamically reflect changes to pagetrees. To see the effect of this new pagetree on our project, you’ll need to go to your terminal window and stop the project server with ctrl+C, and then restart it. Which will take all of three seconds.</p><p>Now refresh <span class="stt">carticle.html</span>. You’ll notice that the navigation links are different. You won’t see a previous-page link — because <span class="stt">carticle.html</span> is now the first page in the pagetree — and the next page will show up as <span class="stt">article.html</span>. Click through to <span class="stt">article.html</span>, and you’ll see the navigation likewise updated. Click through to <span class="stt">barticle.html</span>, and you’ll see ...</p><p>BAM! An error page with a yellow box that says <span class="stt">Can’t convert #f to string</span>. What happened? We switched to using our own pagetree file but we didn’t update our template conditionals. Once you reach <span class="stt">barticle.html</span>, the value of <span class="RktPn">(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._next%29%29" class="RktValLink" data-pltdoc="x">next</a></span><span class="stt"> </span><span class="RktSym">here</span><span class="RktPn">)</span> is false, which means the <span class="RktPn">(</span><span class="RktSym"><span class="badlink"><span class="RktValLink">->string</span></span></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._next%29%29" class="RktValLink" data-pltdoc="x">next</a></span><span class="stt"> </span><span class="RktSym">here</span><span class="RktPn">)</span><span class="RktPn">)</span> command in the template conditional is trying to convert false into a string. Hence the error.</p><p>So let’s go back and fix that. Because we don’t have extraneous files in our pagetree anymore, we can change the second conditional in the template to work the same way as the first:</p><div class="fileblock"><div class="SIntrapara"><div class="fileblock_filetitle"><span class="fileblock_filename"><span class="stt">"template.html"</span></span></div></div><div class="SIntrapara"><div class="fileblock_filecontent"><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktMeta"><html></span></td></tr><tr><td><span class="RktMeta"><head></span></td></tr><tr><td><span class="RktMeta"><meta</span><span class="hspace"> </span><span class="RktMeta">charset=</span><span class="RktVal">"UTF-8"</span><span class="RktMeta">></span></td></tr><tr><td><span class="RktMeta"><title>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._select%29%29" class="RktValLink" data-pltdoc="x">select</a></span><span class="RktPn">[</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/quote.html#%28form._%28%28quote._~23~25kernel%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym">h1</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta">,</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">by</span><span class="hspace"> </span><span class="RktMeta">MB</title></span></td></tr><tr><td><span class="RktMeta"><link</span><span class="hspace"> </span><span class="RktMeta">rel=</span><span class="RktVal">"stylesheet"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">type=</span><span class="RktVal">"text/css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">media=</span><span class="RktVal">"all"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"styles.css"</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta">/></span></td></tr><tr><td><span class="RktMeta"></head></span></td></tr><tr><td><span class="RktMeta"><body>◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._-~3ehtml%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-></span>html</a></span><span class="RktPn">[</span><span class="RktSym">doc</span><span class="RktPn">]</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">current</span><span class="hspace"> </span><span class="RktMeta">page</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta">called</span><span class="hspace"> </span><span class="RktMeta">◊|</span><span class="RktSym">here</span><span class="RktMeta">|.</span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">prev-page</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._previous%29%29" class="RktValLink" data-pltdoc="x">previous</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._when%2Fblock%29%29" class="RktValLink" data-pltdoc="x">when/block</a></span><span class="RktPn">[</span><span class="RktSym">prev-page</span><span class="RktPn">]</span><span class="RktPn">{</span><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">previous</span><span class="hspace"> </span><span class="RktMeta">is</span></td></tr><tr><td><span class="RktMeta"><a</span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"◊|prev-page|"</span><span class="RktMeta">>◊|</span><span class="RktSym">prev-page</span><span class="RktMeta">|</a>.</span><span class="RktPn">}</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktPn">(</span><span class="RktSym"><a href="http://docs.racket-lang.org/reference/define.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">next-page</span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktPn">(</span><span class="RktSym"><a href="Pagetree.html#%28def._%28%28lib._pollen%2Fpagetree..rkt%29._next%29%29" class="RktValLink" data-pltdoc="x">next</a></span><span class="RktMeta"></span><span class="hspace"> </span><span class="RktMeta"></span><span class="RktSym">here</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">◊</span><span class="RktSym"><a href="Template.html#%28def._%28%28lib._pollen%2Ftemplate..rkt%29._when%2Fblock%29%29" class="RktValLink" data-pltdoc="x">when/block</a></span><span class="RktPn">[</span><span class="RktSym">next-page</span><span class="RktPn">]</span><span class="RktPn">{</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta">The</span><span class="hspace"> </span><span class="RktMeta">next</span><span class="hspace"> </span><span class="RktMeta">is</span><span class="hspace"> </span><span class="RktMeta"><a</span><span class="hspace"> </span><span class="RktMeta">href=</span><span class="RktVal">"◊|next-page|"</span><span class="RktMeta">>◊|</span><span class="RktSym">next-page</span><span class="RktMeta">|</a>.</span><span class="RktPn">}</span><span class="RktMeta"></span></td></tr><tr><td><span class="RktMeta"></body></span></td></tr><tr><td><span class="RktMeta"></html></span></td></tr></table></blockquote></div></div></div></div><p>Refresh <span class="stt">barticle.html</span> — because you’re updating the template, you don’t need to restart the project server — and you’ll see the right result. The previous-page link goes to <span class="stt">article.html</span>, and the next-page link is hidden.</p><h5>6.6.6<tt> </tt><a name="(part._tutorial-2._index_ptree___the_project_server)"></a><span class="stt">index.ptree</span> & the project server</h5><p>One more thing to show you before we wrap up this tutorial. Remember that the dashboard of the project server is at <span class="stt">http://localhost:8080/index.ptree</span>? By default, the project server will synthesize a pagetree from an alphbetical directory listing.</p><p>But if you put your own <span class="stt">index.ptree</span> file in the directory, the project server will use that for the dashboard instead. In fact, visit <a href="http://localhost:8080/index.ptree"><span class="stt">http://localhost:8080/index.ptree</span></a> now and you’ll see what I mean. Consistent with the <span class="stt">index.ptree</span> you made, you’ll now see <span class="stt">carticle.html</span>, <span class="stt">article.html</span>, and <span class="stt">barticle.html</span>, but not <span class="stt">template.html</span> nor <span class="stt">styles.css</span> (even though they’re still in the project directory).</p><h4>6.7<tt> </tt><a name="(part._.Second_tutorial_complete)"></a>Second tutorial complete</h4><p>That was a big tutorial. I commend you for your tenacity and patience. But in this tutorial, you made a giant leap forward. Despite the silly examples, you now know everything you need to make multi-page articles — books, even — using Markdown authoring mode in Pollen. If this is all you ever use Pollen for, it’ll be a big improvement over ordinary Markdown.</p><p>But there’s more. We haven’t even gotten into the more elaborate automation that’s possible with Pollen, nor Pollen’s own markup language. We’ll cover that in the third tutorial.</p><div class="navsetbottom"><span class="navleft"><div class="nosearchform"></div> </span><span class="navright"> <a href="first-tutorial.html" title="backward to "5 First tutorial"" data-pltdoc="x">← prev</a> <a href="index.html" title="up to "Pollen: the book is a program"" data-pltdoc="x">up</a> <a href="third-tutorial.html" title="forward to "7 Third tutorial"" data-pltdoc="x">next →</a></span> </div></div></div><div id="contextindicator"> </div></body></html> |