You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pollen/doc/second-tutorial.html

10 lines
84 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
10 years ago
<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"/><title>6&nbsp;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"/><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,&quot;tocview_0&quot;);">&#9660;</a></td><td></td><td><a href="index.html" class="tocviewlink" data-pltdoc="x">Pollen:<span class="mywbr"> &nbsp;</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&nbsp;</td><td><a href="Installation.html" class="tocviewlink" data-pltdoc="x">Installation</a></td></tr><tr><td align="right">2&nbsp;</td><td><a href="quick-tour.html" class="tocviewlink" data-pltdoc="x">Quick tour</a></td></tr><tr><td align="right">3&nbsp;</td><td><a href="Backstory.html" class="tocviewlink" data-pltdoc="x">Backstory</a></td></tr><tr><td align="right">4&nbsp;</td><td><a href="big-picture.html" class="tocviewlink" data-pltdoc="x">The big picture</a></td></tr><tr><td align="right">5&nbsp;</td><td><a href="first-tutorial.html" class="tocviewlink" data-pltdoc="x">First tutorial</a></td></tr><tr><td align="right">6&nbsp;</td><td><a href="second-tutorial.html" class="tocviewselflink" data-pltdoc="x">Second tutorial</a></td></tr><tr><td align="right">7&nbsp;</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">8&nbsp;</td><td><a href="File_formats.html" class="tocviewlink" data-pltdoc="x">File formats</a></td></tr><tr><td align="right">9&nbsp;</td><td><a href="reader.html" class="tocviewlink" data-pltdoc="x">&#9674; command overview</a></td></tr><tr><td align="right">10&nbsp;</td><td><a href="Module_reference.html" class="tocviewlink" data-pltdoc="x">Module reference</a></td></tr><tr><td align="right">11&nbsp;</td><td><a href="Acknowledgments.html" class="tocviewlink" data-pltdoc="x">Acknowledgments</a></td></tr><tr><td align="right">12&nbsp;</td><td><a href="License___source_code.html" class="tocviewlink" data-pltdoc="x">License &amp; 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,&quot;tocview_1&quot;);">&#9658;</a></td><td>6&nbsp;</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&nbsp;</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&nbsp;</td><td><a href="second-tutorial.html#%28part._.Prelude__my_principled_objection_to_.Markdown%29" class="tocviewlink" data-pltdoc="x">Prelude:<span class="mywbr"> &nbsp;</span> my principled objection to Markdown</a></td></tr><tr><td align="right">6.3&nbsp;</td><td><a href="second-tutorial.html#%28part._.Markdown_in_.Pollen__two_options%29" class="tocviewlink" data-pltdoc="x">Markdo
<br/>(strong () "so") " happy to be writing this."))</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="RktVal">()</span> after <span class="RktVal">p</span> and <span class="RktVal">strong</span> signal that the tag&rsquo;s attributes are empty. When you write an X-expression without attributes, these parentheses are optional &#8212; <span class="RktVal">(tag () "text")</span> and <span class="RktVal">(tag "text")</span> are equivalent &#8212; 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="SCodeFlow"><p><span class="RktVal">&lt;root&gt;&lt;h1 id="my-article"&gt;Deep Thought&lt;/h1&gt;&lt;p&gt;I am <br/>&lt;strong&gt;so&lt;/strong&gt; happy to be writing this.&lt;/p&gt;&lt;/root&gt;</span></p></blockquote><p>&ldquo;But what&rsquo;s this <span class="stt">root</span> tag? That&rsquo;s not HTML.&rdquo; 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&rsquo;t need it, you can discard it. But it also creates a useful hook for further processing, as we&rsquo;ll see later.</p><p>By the way, as review, let&rsquo;s remind ourselves how this is different from preprocessor mode. Let&rsquo;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><blockquote class="Rfilebox"><p class="Rfiletitle"><span class="Rfilename"><span class="stt">"article.md.pp"</span></span></p><blockquote class="Rfilecontent"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">#lang pollen</span></p></td></tr><tr><td><p><span class="stt"></span><span class="hspace">&nbsp;</span></p></td></tr><tr><td><p><span class="stt">Deep Thought</span></p></td></tr><tr><td><p><span class="stt">============</span></p></td></tr><tr><td><p><span class="stt"></span><span class="hspace">&nbsp;</span></p></td></tr><tr><td><p><span class="stt">I am **so** happy to be writing this.</span></p></td></tr></table></blockquote></blockquote><p>When you run this file in DrRacket, you&rsquo;ll see:</p><blockquote class="SCodeFlow"><p><span class="RktVal">Deep Thought<br/>============<br/><br/>I am **so** happy to be writing this.</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>&nbsp;</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&rsquo;ve used other web-publishing systems, templates are probably a familiar idea. Templates in Pollen are in some ways similar to the ones you&rsquo;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
<br/>&lt;root&gt;&lt;h1 id="my-article"&gt;Deep Thought&lt;/h1&gt;&lt;p&gt;I am
<br/>&lt;strong&gt;so&lt;/strong&gt; happy to be writing this.&lt;/p&gt;&lt;/root&gt;
<br/>&lt;/body&gt;&lt;/html&gt;</span></p></blockquote><p>But wait &#8212; 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&rsquo;s used as a last resort. Under ordinary circumstances, seeing the fallback template usually signals a problem (e.g., Pollen couldn&rsquo;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>&nbsp;</tt><a name="(part._tutorial-2._.The_-_html_function_and_the_doc_variable)"></a>The <span class="stt">-&gt;html</span> function and the <span class="stt">doc</span> variable</h5><p>This is the fallback template that Pollen uses.</p><blockquote class="Rfilebox"><p class="Rfiletitle"><span class="Rfilename"><span class="stt">"fallback.html"</span></span></p><blockquote class="Rfilecontent"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">&#9674;(-&gt;html (html (head (meta 'charset: "UTF-8")) (body doc)))</span></p></td></tr></table></blockquote></blockquote><p>It has three key ingredients.</p><p>First, there&rsquo;s an X-expression that represents a basic HTML page:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">(html (head (meta 'charset: "UTF-8")) (body))</span></p></td></tr></table></blockquote><p>This is equivalent to the HTML:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">&lt;html&gt;&lt;head&gt;&lt;meta charset="UTF-8"&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;</span></p></td></tr></table></blockquote><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"><span class="nobreak">-&gt;</span>html</span>:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">&#9674;(-&gt;html (html (head (meta 'charset: "UTF-8")) (body)))</span></p></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"><tr><td><p><span class="stt">&#9674;(-&gt;html (html (head (meta 'charset: "UTF-8")) (body doc)))</span></p></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&rsquo;t defined. But when you run it in the context of another source file, it picks up the <span class="stt">doc</span> that&rsquo;s defined by that file.</p><p>Caution &#8212; 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&rsquo;s not actually written in HTML.</p><p>It could be,
<br/>(strong () "so") " happy to be writing this."))</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&rsquo;m going to omit the <span class="stt">style</span> tag in these examples, but it&rsquo;s fine to leave it in):</p><blockquote class="Rfilebox"><p class="Rfiletitle"><span class="Rfilename"><span class="stt">"template.html"</span></span></p><blockquote class="Rfilecontent"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">&lt;html&gt;</span></p></td></tr><tr><td><p><span class="stt">&lt;head&gt;&lt;meta charset="UTF-8"&gt;</span></p></td></tr><tr><td><p><span class="stt">&lt;title&gt;&#9674;(select 'h1 doc)&lt;/title&gt;&lt;/head&gt;</span></p></td></tr><tr><td><p><span class="stt">&lt;body&gt;&#9674;(-&gt;html doc)&lt;/body&gt;</span></p></td></tr><tr><td><p><span class="stt">&lt;/html&gt;</span></p></td></tr></table></blockquote></blockquote><p>When you refresh the page in the project server, the page title will now appear as &ldquo;Deep Thought.&rdquo; Of course, you can also combine static and dynamic elements in your template, like so:</p><blockquote class="Rfilebox"><p class="Rfiletitle"><span class="Rfilename"><span class="stt">"template.html"</span></span></p><blockquote class="Rfilecontent"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">&lt;html&gt;</span></p></td></tr><tr><td><p><span class="stt">&lt;head&gt;&lt;meta charset="UTF-8"&gt;</span></p></td></tr><tr><td><p><span class="stt">&lt;title&gt;&#9674;(select 'h1 doc), by MB&lt;/title&gt;&lt;/head&gt;</span></p></td></tr><tr><td><p><span class="stt">&lt;body&gt;&#9674;(-&gt;html doc)&lt;/body&gt;</span></p></td></tr><tr><td><p><span class="stt">&lt;/html&gt;</span></p></td></tr></table></blockquote></blockquote><p>The page title will now be &ldquo;Deep Thought, by MB&rdquo;.</p><p>A couple notes on command syntax. We inserted the <span class="RktSym">select</span> and <span class="RktSym"><span class="nobreak">-&gt;</span>html</span> commands using Racket-mode syntax. We could also use text-mode syntax and write the commands this way:</p><blockquote class="Rfilebox"><p class="Rfiletitle"><span class="Rfilename"><span class="stt">"template.html"</span></span></p><blockquote class="Rfilecontent"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">&lt;html&gt;</span></p></td></tr><tr><td><p><span class="stt">&lt;head&gt;&lt;meta charset="UTF-8"&gt;</span></p></td></tr><tr><td><p><span class="stt">&lt;title&gt;&#9674;select['h1 doc], by MB&lt;/title&gt;&lt;/head&gt;</span></p></td></tr><tr><td><p><span class="stt">&lt;body&gt;&#9674;-&gt;html[doc]&lt;/body&gt;</span></p></td></tr><tr><td><p><span class="stt">&lt;/html&gt;</span></p></td></tr></table></blockquote></blockquote><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">select</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&rsquo;t use a quote mark when you&rsquo;re referring to the name of an existing function or variable (like <span class="RktSym">select</span> or <span class="stt">doc</span>). But you do need a quote mark when you&rsquo;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
<br/>Can you mix dynamic and static style sheets? Yes.
<br/>Can you add a dynamic JavaScript file? Yes.
<br/>You&rsquo;re getting the general idea, right? So let&rsquo;s move on.</p><h4>6.5<tt>&nbsp;</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 &#8212; a source file and a template &#8212; 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>&nbsp;</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 &#8212;&#160;for instance, a book-length project can be organized into chapters, the chapters into sections, and so on. The pagetree doesn&rsquo;t impose any semantics on the organization of your project. It&rsquo;s just a tree, and it&rsquo;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&rsquo;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&rsquo;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>&nbsp;</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&rsquo;ll expand our sample article from one page to three, and see how to create &ldquo;previous page&rdquo; and &ldquo;next page&rdquo; links in our template that are dynamically generated relative to the current page.</p><h5>6.6.2<tt>&nbsp;</tt><a name="(part._tutorial-2._.Using_the_automatic_pagetree)"></a>Using the automatic pagetree</h5><p>You&rsquo;ve actually already been exposed to pagetrees (though I didn&rsquo;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><blockquote class="Rfilebox"><p class="Rfiletitle"><span class="Rfilename"><span class="stt">"article.html.pmd"</span></span></p><blockquote class="Rfilecontent"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt">#lang pollen</span></p></td></tr><tr><td><p><span class="stt"></span><span class="hspace">&nbsp;</span></p></td></tr><tr><td><p><span class="stt">Deep Thought</span></p></td></tr><tr><td><p><span class="stt">============</span></p></td></tr><tr><td><p><span class="stt"></span><span class="hspace">&nbsp;</span></p></td></tr><tr><td><p><span class="stt">I am **so** happy to be writing this.</span></p></td></tr></table></blockquote></blockquote><p>Let&rsquo;s supplement this source file by