Pamflet 

Pamflet is a publishing application for short texts, particularly user documentation of open-source software. It is designed to be easy to write and read on any platform.

Like a Book 

Pamflet generates a linked sets of pages called “pamflets”. Although hierarchical organization of pages is supported, the primary means of navigation is linear and authors are encouraged to write pamflets that progress logically when read front to back.

The table of contents appears at the bottom of every page. The first page of a pamflet should be brief so that the generated contents listing will appear above the fold. Think of it as a title page, with a few sentences of description.

On the Big Screen 

On devices with large screens—typically, laptop and desktop computers—pamflet texts appear in a fixed-width center column. The margins are giant clickable regions for page flipping. The left and right keyboard arrows may also be used for the same purpose.

Going Mobile 

Since Pamflets are meant to be carried around, having a good mobile appearance and behavior is vital. When viewed on a phone, tablet, or other small-screen device, pamflets take the full screen width.

Radio Silent 

And because mobile devices aren’t always connected, an HTML5 cache manifest is generated for all pamflets. Add a bookmark for a pamflet to your home screen so you can read it anywhere.

Writing and Organizing 

Pamflet’s purpose is to make it so easy to write decent project documentation that everyone will do it. This section tells you everything there is to know about writing pamflets.

Filenames and Page Names 

Pamflet reads source files from the source directory and produces finished web files at the destination. Sources with a markdown or md extension correspond to one html output file.

Filenames are used only for ordering pages and sections; the display titles and page URLs are determined instead by the first heading element in the source of the page.

Naming Conventions 

It is suggested that you name your sources with a simple numeric or alphabetical prefix to control ordering; after that you can include some portion of the title, or nothing, and end with the markdown extension.

For example, the title page of a pamflet could be named 00.markdown to ensure that is the first source in the ordered list. The contents might look like this:

Pamflet
=======

*Pamflet* is a publishing application...

This tells the processor that “Pamflet” is the name of the page. If this source is indeed the first one in the ordered list, it is interpreted as the name of the entire pamflet.

Output Names 

The output html filenames are URL-encoded versions of the page names; the have no relationship to the input filenames. Page names must therefore be unique across the pamflet.

Shaping the Contents Tree 

As mentioned on the previous page, pages are ordered alphabetically by their source filenames. This ordering also affects the Contents listing that appears below every page.

Pamflet uses HTML ordered lists for Contents. In the default stylesheet, the top-level contents list is made of simple numbers. There is one quirk of the structure that may be surprising: The first markdown source found in a directory is not placed in the same list as the other sources. The title page described in the previous example would not appear with any number at all. Given the following directory:

docs/
  00.markdown
  01.markdown
  02.markdown

The Contents will appear in this manner, with the actual names and links derived from the first header found in each page:

<00.markdown>
1. <01.markdown>
2. <02.markdown>

For this reason, we consider the title page to be the zeroth page and typically name it as such.

Going Deep 

Even the simplest pamflet can often benefit from grouping related pages into sections—in fact, you’re reading a section right now.

Pamflet supports arbitrarily many nested sections, defined by directories beneath the primary source directory. These directories participate in the same name-based ordering as their adjacent markdown sources.

docs/
  00.markdown
  01/
    00.markdown
    a.markdown
    b.markdown
  02.markdown

Given valid sources containing page headings, the above structure will produce the following Contents listing:

<00.markdown>
1. <01/00.markdown>
  a. <01/a.markdown>
  b. <01/b.markdown>
2, <02.markdown>

Here you can see how the first ordered source in a directory, 00.markdown, always acts as a title page whether it is for a the entire pamflet or just one section. It is numbered and positioned according on the higher level numbering; at the top level, this is simply the absence of any number.

You can also see in this example that Pamflet’s second level numbering is lowercase letters. The third is lowercase roman numerals, and and after that it is back to the browser default. You can override these for any level using a custom stylesheet.

Note

Nesting is reflected only in the Contents listing. The pamflet page namespace is flat, with all output html under a single path.

Pamflet in a Project 

Although it can be applied for any purpose, Pamflet is tailored to produce open-source project documentation. This section explores the workflow from drafting to publication.

On the Command Line 

Pamflet is installed with conscript, a general installer and updater for Scala applications. Conscript is pretty easy to set up, so please do that and come back if you haven’t yet.

Once you have conscript setup, and assuming that ~/bin is on your executable search path, you can install Pamflet like so:

cs foundweekends/pamflet

That installs Pamflet’s pf command, which is used to both preview and publish pamflets.

Usage: pf [SRC] [DEST]

Preview 

Pamflet’s preview mode allows you to check the layout and text rendering as much as you like while editing project documentation.

When you call pf with no arguments, SRC is assumed to be “docs” under the working directory—typically, your project’s base directory. When you call pf with one argument, you are specifying the SRC directory. In both these cases where no DEST is specified, Pamflet goes into preview mode.

2011-07-15 09:29:38.033:INFO::jetty-7.2.2.v20101205
2011-07-15 09:29:38.066:INFO::Started SocketConnector@127.0.0.1:44449

Previewing `docs`. Press CTRL+C to stop.

Preview mode starts an Unfiltered web server bound to the loopback interface on some available port. It also requests that a local web browser open the relevant URL; this occurs in a background or foreground window depending on your platform and browser.

If a usable pamflet is found in the docs or other specified directory, you will see its title page in the browser. Linear navigation and the Contents listing will work exactly as in the published pamflet. But the best thing about preview is that any changes to the pamflet source are reflected immediately: just hit reload.

Publish 

To publish Pamflet sources into web sources, call the pf command with both SRC and DEST parameters. If SRC has Pamflet sources and DEST is some directory that the current user can write to, you’ll find all the output files written to it after the command completes.

Git Hooks 

Git hooks turn Pamflet from a cute toy into digital printing press. Set them up on a server under your control (you do have one, yes?) and have your published documentation updated every time you push.

Assuming your have a --bare git repository on your server, it should already have a hooks/ subdirectory. In hooks/, create or edit a file post-update that is similar to the following:

#!/bin/sh
HOME=/home/me
DOCB=$HOME/app/my_doc_build
PUB=$HOME/app/my_pub
cd $DOCB
env -i git pull
cd -
$HOME/bin/pf $DOCB/docs $PUB

DOCB is a clone of the same repo, but with a working tree. PUB is the directory where the finished html and other files will be placed. HOME is your home directory, because git runs the hook in a weird environment and it’s best to be explicit.

Set all that up, and make the hook script executable or it will not run and you’ll be very confused for a while. Also, make sure that ~/bin/pf runs normally on the server.

When you push to the bare repo from elsewhere, you’ll see the normal git output along with a success or error message from Pamflet. (And yes, this is some pretty lame scripting. Fork this pamflet, that’s what it’s here for.)

Apache Setup 

You probably know all this already, but to save the rest of us some time, Apache can be pointed to your pamflet directory like this:

<VirtualHost *:80>
        ServerName pamflet.databinder.net
        DocumentRoot /home/me/app/pamflet
        RewriteEngine On
        RewriteRule ^/$ /Pamflet.html [L,R=permanent]
</VirtualHost>
Note

You do need a root redirect if you want requests to the root path to resolve. The title page is assigned an output name like any other.

Fancy Techniques 

We’ve covered how to write and publish pamflets. This is how to write and publish even fancier pamflets.

Source Code Highlighting 

Pamflet hooks into the very slick prettify.js source code highlighter. To activate it, use github’s fenced code block syntax to enclose your source and specify a language name known to prettify.

```scala
// Some comment
case class Page(name: String) {
  def foo: Int = (1 to 10).reduceLeft{ _ + _ }
  val bar = "wat"
}
```

appears as

// Some comment
case class Page(name: String) {
  def foo: Int = (1 to 10).reduceLeft{ _ + _ }
  val bar = "wat"
}

Really clears things up, right?

Custom Stylesheets 

To give your project that special edge, you will surely want to set all headings to Copperplate MT or Bank Gothic.

Not to worry, Pamflet supports this. All files in the source directory with the extension css will be packaged with the pamflet. These will be loaded after all other stylesheets, so go crazy.

Template Properties 

Because you probably have a few current version numbers and things repeated throughout your documentation, Pamflet supports template properties through StringTemplate.

If a file template.properties is found in the pamflet source directory, all Markdown sources are passed through StringTemplate with the properties as read by java.util.Properties. This is an example template.properties:

version=0.3.4
vrsn=034
scala=2.8.1

Properties are referenced in sources by bracketing them with the dollar sign. In this example, occurrences of $version$ in the Markdown source would be replaced by 0.3.4 in the HTML output.

Properties Front Matter 

In addition, each page may add its own properties by including a properties front matter at the beginning of the page as follows:

---
version=0.2.5
dispatch=0.8.5
---

Properties in the front matter takes precedence over the ones in template.properties.

Note

Once activated by the presence of the .properties file, StringTemplate will be confused by any stray $ in your source. Always escape dollar signs that are not template properties with a backslash: \$

Special Properties 

While template properties exist generally for you to define and use as in your own markdown sources, Pamflet also checks for a special, optional property that links to a project’s GitHub repository, etc.

Fork Me on GitHub 

If you define a github property with the repo owner and name, Pamflet constructs a link to the repository. For example:

github=foundweekends/pamflet

This is the property that produces the link to GitHub from Pamflet’s own documentation. Note that there is only one slash.

I Want Out 

If you define an out property with a file name, Pamflet uses it to generate the file for the page. It is intended to be used in the properties front matter of the page:

---
out: index.html
---

Collapsible table of contents 

toc property may be used to control how the table of contents is displayed. The allowed values are left, bottom, hide, and collapse.

Disqus 

Defining disqus property with a disqus short name will add a comment section at the end of all your pages.

disqus=namehere

Twitter 

Defining twitter property with any value will pop up a twitter button when some text is selected on any page. The button will compose a tweet including the selected text, the property, and the URL. The value show would display the button, but will not be included in the tweet.

twitter=#pamflet

Google Analytics 

Defining google-analytics with a Google Analytics web property ID will insert tracking Javascript in the head of all your pages. For example:

google-analytics=UA-12345-6

Page path 

The property page.localPath is automatically set to the local path to the page’s markdown source, which allows, for instance, the construction of a direct-to-GitHub page edit URL in the header or footer, e.g:

<div class="container">
    <div class="row">
      <div class="span-16 prepend-1 append-1">
        <div class="span-16 nav">
          <p style="padding-top: 0.5em">
            <a href="https://github.com/foundweekends/pamflet/edit/master/docs/$page.localPath$">
            [Edit on GitHub]</a>
          </p>
        </div>
      </div>
  </div>
</div>

Scroll to the bottom of this page to see how this works.

Additional resources 

If you want your pamflet to carry your favorite image or any other resource, add it to a files directory just below docs. Then, link to it as if this directory were beside your pamflet page.

Supposing you drop a file named a.txt into docs/files/ then [some file](files/a.txt) becomes some file. Try it!

Embedding images 

Of course, the trick works great for images using usual markdown:

![some svg](files/an.svg)

Becomes

some svg

It’s worth a thousand words, give or take.

favicon 

To customize the favicon, place favicon.ico in the source directory.

Globalization 

If you want to translate your pamflet into multiple languages, there are special template properties that enable globalization.

Default Language 

language property is used to specify the language used at the root level. By default, it is set to en, which is ISO 639-1 code for English.

language=en

List of Languages 

languages property is used to specify the list of languages used in your pamflet. Use ISO 639-1 two-letter language codes or IETF language tags separated by comma:

languages=en,ja

Then place non-default language contents under the folder named after the language code.

docs/
  00.markdown
  01/
    00.markdown
    a.markdown
  ja/
    00.markdown
    01/
      00.markdown
      a.markdown

This will generate Japanese contents under ja/ folder.

Language Labels 

Contents are assumed to be a translation when the relative path is the same. When they are detected, the language links appears at the bottom of each page to link to all translations.

Pamflet is able to resolve some of the language codes, but you can provide custom language labels using lang- properties if it doesn’t or just to change it:

lang-pt-BR=Português (Brasil)

Changing the look 

You might want to read pamflets using a dark color scheme. That’s why Pamflet ships with three color schemes: github, monokai, and redmond.

Applying a color scheme 

To apply a dark color scheme, open your pamflet with query string ?color_scheme=monokai. This will store "monokai" to the HTML5 local storage, and apply the scheme to the pamflet.

Default color scheme 

The default scheme is github. To change it to something else, set color_scheme property:

color_scheme=monokai

Custom color scheme 

To create your own custom color scheme, for example named “zen”, create color_scheme-zen.css and declare css properties under body.color_scheme-zen:

body.color_scheme-zen {
    color: black;
    background: white;
}
body.color_scheme-zen code.prettyprint span.str {
  color: #dd1144
}

Custom header and footer 

To change the header to something else, set layout.header and layout.header.height property:

layout.header=header.md
layout.header.height=2em

Now drop a file named header.md into docs/layout/:

<div class="container">
  <div class="span-16 prepend-1 append-1">
    <div class="span-16 top nav">
      <div class="span-16 title">
        <span>$contents.title$</span>$if(page.title)$ —
         $page.title$ $endif$ (draft)
      </div>
    </div>
  </div>
</div>

This will add ”(draft)” at the end of the default header. The footer works the same way. Just use layout.footer and layout.footer.height instead.

For Your Perusal 

All techniques described in this pamflet are used to produce it. Take a look through Pamflet’s docs/ directory on github.

Who’s Using Pamflet? 

Are you using Pamflet? Add your project and send a pull request.

Fork me on GitHub