% @page_title = 'User guide' %> It is assumed that you have installed Rote already. If not, please consult the "README":<%= link_rel '/index.html' %> for installation instructions. <%= section 3, 'Conventions', false %> *Task names* - Rote's standard tasks are always referred to with the base-name _doc_ , e.g. @doc_pages@, @doc_clean@, and just plain @doc@. This is the prefix used by the built-in Rakefile, but since it can be changed when using Rote in your own Rake builds you should of course substitute whatever is appropriate if you have chosen to modify it. <%= section 3, 'Starting out with Rote' %> <%= section 4, 'Creating a project', false %> To get started quickly, we'll use the built-in project template, which provides a standard Rote directory tree with a single page, and Rakefile ready for customisation. The template gives a convenient way to get started on a new Rote project. To invoke it, just type:
rote create someproject
If all goes well, you should see a single line (@cp_r ...@) indicating that Rote copied the template to your specified directory (@someproject@ in this case). This directory will have the following layout:
someproject
|
|--> Rakefile
|
|--> doc
| |--> res
| | |--> images
| | |--> rote-tiny.png
| |
| |--> layouts
| | |--> normal.thtml
| |
| |--> pages
| |--> COMMON.rb
| |--> index.thtml
| |--> index.rb
Template sources under the 'pages' directory may have any extension (except @rb@), and will be rendered to the same base-name under the output directory, with their file extension supplied by the original, possible via an <%= section_link 'extension_mappings', 'extension mapping' %>
See the section on Layouts below for details on layout name resolution.
Ruby source is optional, and allows you to define instance variables and methods on a Page instance. COMMON.rb is applied to all pages in a given
directory. See <%= section_link 'creating templates', 'the section on templates' %> for more information on the specifics.
To build the sample page, simply type @rote@ or @rake@ from the top-level directory. This will start the default @doc@ task to transform all
modified pages / resources (everything, in this case).
The README included with the project template has further information about build options and available tasks, as well as pointers to possible
next steps.
<%= section 4, 'From the command-line' %>
If you are generating a standalone documentation set (i.e. not as part of some wider build) and you don't want to worry maintaining a @Rakefile@,
you can use the built-in build via the @rote@ command. This works with the standard directory layout above, and wraps invocation of @rake@ on a
built-in version of the standard Rakefile.
Given the above layout, you can generate the documentation set by running:
rote
from the top-level directory (@project@ in the example above), you should get a 'html' directory created with the (transformed) templates, and any
resources should be copied as necessary.
Being based on Rake, Rote supports last-modified checking, and provides an individual file task for each page in your doc set. For example, running
the 'rote' command again with no options will cause it to exit almost immediately, since all output is up to date. If you change a file, and run
rote again, then just that file will be updated. Even dependencies that are determined dynamically (such as layout files) can be tracked for incremental build purposes.
The file tasks are named for the target files, so for example to generate just the top-level index.html (regardless of whether it's been modified)
you'd run:
rote html/index.html
The @clobber@ task supports deleting all output files to start from scratch:
rote clobber
Of course, multiple file or task names (or a mixture) can be specified.
You can get a list of valid tasks in the current context with:
rote --tasks
Further command-line usage information is available with:
rote --usage
and Unix installations performed with @install.rb@ should also make a manpage available for the @rote@ command.
rake doc
If all goes well, you should see each command and transformation output to your console as Rote runs.
See the main Rote @Rakefile@ for an example of integrating Rote with your software project, including linking to Rdoc generation and so on. The
<%= section_link 'Rake task configuration' %> section has more information on the options supported by Rote's task library.
<%= section 3, 'Creating templates' %>
p=. *Wherever directories and files are mentioned, they refer to the appropriate path/name/etc supplied during <%= section_link 'rake task configuration' %>*.
*In all cases the default settings can be seen in the layout created by the @rote create foo@ command.*
<%= section 4, 'The Basics', false %>
As mentioned, templates are simply files in the specifed pages directory (@doc/pages@ by default) that match the supplied glob (default: all files,
though ruby source is implicitly excluded). The directory layout beneath the page root is retained when transforming pages, and is also used to provide hierarchical structure to the common page code.
The default behaviour is to transform all matched <%= section_link 'template code and erb', 'templates' %> pages with ERB, and optionally apply a second render pass with a <%= section_link 'layout' %>, before writing to the same base filename beneath the output directory. You can customise this behaviour by specifying <%= section_link 'extension mappings' %> for specific file extensions - see the <%= section_link 'Rake task configuration' %> section for details.
Each page and layout template used by Rote may have associated with it an optional Ruby source file, allowing variables to be defined for use in ERB code, and supporting interaction with Rote via the methods of the "@Rote::Page@":<%= link_rel '/rdoc/classes/Rote/Page.html' %> class. Page and layout code is loaded from a @rb@ file alongside the template itself.
Code can also be applied across multiple pages based on filesystem hierarchy by placing it in @COMMON.rb@ files in the *pages* tree. The order of evaluation of these files travels down from the most remote COMMON.rb to the page code itself, and this provides a simple yet fairly powerful way to apply various configuration options, filtering, and user variables across your pages.
See <%= section_link 'template code and erb' %> for more information on the search path and evaluation order for page code.
Rote additionally allows a variety of formatting and postprocessing options thanks to it's support for <%= section_link 'filters' %> - little bits of Ruby that perform some text transformation, macro expansion, or postprocessing during page rendering. Rote provides standard filters to support Textile and Markdown formatting, syntax highlighting, processing with HTMLTidy, and more.
<%= section 4, 'Template code and ERB' %>
All templates may contain embedded Ruby code (ERB), delimited by the standard <% ... %> (for executed code) and <%= ... %> (for output) tags. Any (valid) Ruby code may be placed in the templates, and variables may be defined to allow information to be passed into templates. There are four places where you might define such variables. The following is in order of evaluation:
* A block supplied to the <%= section_link 'extension mappings', 'extension mapping' %> that matched this page (if any).
* Any COMMON.rb files from the filesystem root down to this directory.
* This page's ruby code, _basename_.rb.
* In the template itself (via ERB).
When a @Page@ instance is created, Rote looks for these, and if found evaluates them, in order, in the same binding as the template is later rendered in (i.e. the @Page@ instance binding). Therefore, you can define instance variables to pass data around, or even helper methods if you wish.
Additionally, when <%= section_link 'layout' %> is used the following evaluation takes place *after rendering the template text* and can be used to make variables available for the layout pass(es):
* This layout's ruby code, _layout_basename_.rb.
* In the layout itself (again, with ERB).
Template code is used to support a great deal of flexibility in Rote, from selecting layouts to mixing in format helpers to controlling the filter chain. You can find details of the methods available in the "@Rote::Page@ RDoc":<%= link_rel '/rdoc/classes/Rote/Page.html' %>
<%= section 4, 'Plaintext Formatting' %>
If you are using Rote to generate HTML, you'll probably want to utilise some kind of _plain-text formatting_. Rote has out-of-the-box support for
Textile, Markdown, and RDoc formatting, which can be applied to any page using standard <%= section_link 'filters' %>.
These filters can be applied to any page directly from page or common code, and if you are using the built-in Rakefile (either using the @rote@ command to build, or with a @rake@ build created with the @rote create@ command) then the following extension mappings are defined by default, allowing the filters to be applied without resorting to page code:
.mhtml or .markdown => Markdown formatting, .html output
.thtml or .textile => Textile formatting, .html output
.rdhtml or .rdoc => RDoc formatting, .html output
Each of these filters is covered (along with further usage instructions) in the <%= section_link 'filters' %> section.
<%= section 4, 'Layout' %>
_Layouts_ allow common template to be applied across several pages. This is handled via multiple render passes, with each layout responsible
for including the previously rendered content (via ERB).
Layouts are stored under the @doc/layouts@ directory (by default). They may be organised into subdirectories, but this hierarchy is not connected to
the hierarchy in @pages@. To apply a layout to a page, simply call the @Rote::Page.layout@ method from code applied to that page, passing the
base-name (and path, relative to @layouts@, if used). If no extension is specified, then the same extension as the page itself is assumed. Examples:
* layout 'one'
* layout 'main/wide'
* layout 'dark.txt'
* <% layout 'my' %>
_*Note* the absence of the = sign in the ERB tag in the last example, indicating that this is code to be executed rather than code that should generate output._
With that done, Rote would first render the template text (including textile) and set the Page instance variable @\@content_for_layout@ before rendering the layout (in which textile is currently not supported). The layout is responsible for inserting the rendered template where appropriate, with e.g.:
* <%= @content_for_layout %>
This pattern shouldn't be unfamiliar. Again, note that Rote doesn't mandate HTML, despite the appearance from the ERB tags - any (textual) format can
be templated and laid out.
h5. Layout code
Like page templates, each layout may have associated with it some layout code, which is executed just prior to rendering the layout, in the same
way as the page code.
There is no equivalent of @COMMON.rb@ for layout templates, however.
h5. Nested layout
Layout code (see above) may call the @Page#layout@ method (i.e. to apply a layout). This will result in the result of the current rendering being
passed (via @content_for_layout
) to the specified layout in a further render pass. In all respects this is no different from the initial layout pass - layout code is executed, and rendering performed. Obviously, this may result in additional layouts being applied to the page.
@content_for_layout
where appropriate.
All layouts are rendered prior to post filtering.
<%= section 4, 'Filters' %>
As well as rendering ERB and applying layout (both universal features of @Page@), Rote provides the ability to apply custom _filters_ to a page or set of pages. Along with this ability, a number of filters are provided as standard:
For example If you're generating HTML, you'll probably want to use some plaintext formatting, rather than writing HTML by hand. Rote directly supports this (thanks to "RedCloth":http://whytheluckystiff.net/ruby/redcloth and "BlueCloth":http://www.deveiate.org/projects/BlueCloth) via _filters_, with Textile, RDoc and Markdown support out of the box (assuming those libraries are available on your machine). See the <%=section_link 'plaintext formatting' %> for more details on this.
h5. Filter chaining
In order to filter a given page, filter instances are added to that page's filter chain. There are actually two separate chains, for _page filtering_
and _post filtering_.
* *Page filtering* takes place on the page content itself, after any ERB is executed, but before the layout pass is applied. Most of the standard filters are pre-filters.
* *Post filtering* takes place on the final output of the render pass, after layout is applied. The @Filters::Tidy@ filter is a post filter.
Adding filters to a page's chain can be done anywhere you can call that page's filter-chain methods. This could be page code, COMMON.rb, or even inside the template itself. Filters can also be applied to all files with a matching extension by adding filters inside an <%= section_link 'extension mappings', 'extension mapping' %> block. Bear in mind that the order in which filters are added *is* important, since each filters output becomes input for the next. You must ensure that filters are applied in a compatible order - should you need to prepend filters or otherwise modify the chain prior to rendering you may do so by directly accessing the @page_filters@ and @post_filters@ array attributes.
See <%= section_link 'template code and erb', 'the section on template code' %> for more information on adding code to your pages.
h5. Standard filters
Rote supplies the following filters 'out of the box':
h6. *"Filters::BlueCloth":<%= link_rel '/rdoc/classes/Rote/Filters/RedCloth.html' %>* - Supports conversion of plain-text (Markdown) formatting to HTML.
This is a text filter, and should be applied in the _page filter chain_:
#:code#ruby#
# in page code or common.rb
page_filter Filters::BlueCloth.new
#:code#
h6. *"Filters::Exec":<%= link_rel '/rdoc/classes/Rote/Filters/Exec.html' %>* - Pipes the macro body to an external command, and replaces the macro with the output of that command.
This is a macro filter, and should be applied in the _page filter chain_:
#:code#ruby#
# in page code or common.rb
page_filter Filters::Exec.new
#:code#
Code can then be inserted in the page like:
#:code#
#:exec#python#
print "Hello, World"
#:exec#
#:code#
h6. *"Filters::Eval":<%= link_rel '/rdoc/classes/Rote/Filters/Eval.html' %>* - Evaluates the macro body as Ruby code, capturing standard output and using it as the macro replacement.
This is a macro filter, and should be applied in the _page filter chain_:
#:code#ruby#
# in page code or common.rb
page_filter Filters::Eval.new
#:code#
Code can then be inserted in the page like:
#:code#
#:eval#
puts "Hello, World"
#:eval#
#:code#
h6. *"Filters::RDoc":<%= link_rel '/rdoc/classes/Rote/Filters/RDoc.html' %>* - Supports RDoc formatting with optional custom markup, to any supported output format (defaults to HTML).
This is a text filter, and should be applied in the _page filter chain_:
#:code#ruby#
# in page code or common.rb
page_filter Filters::RDoc.new
#:code#
h6. *"Filters::RedCloth":<%= link_rel '/rdoc/classes/Rote/Filters/RedCloth.html' %>* - Supports conversion of plain-text (Textile) formatting to HTML.
This is a text filter, and should be applied in the _page filter chain_:
#:code#ruby#
# in page code or common.rb
page_filter Filters::RedCloth.new
#:code#
h6. *"Filters::Syntax":<%= link_rel '/rdoc/classes/Rote/Filters/Syntax.html' %>* - Supports @code@ <%= section_link 'macros' %> with pluggable syntax highlighting (via the "Syntax library":http://syntax.rubyforge.org/) and Ruby-code support out of the box.
This is a macro filter, and should be applied in the _page filter chain_:
#:code#ruby#
# in page code or common.rb
page_filter Filters::Syntax.new
#:code#
This filter uses the "Syntax":http://syntax.rubyforge.org/ library, passing the macro argument as the language ('ruby', 'xml' and 'yaml' are supported out of the box). The output is wrapped in <pre class='[language]'><code> ... </code></pre> for output, with highlighting handled by tags, allowing syntax colours and styles to be applied via CSS. You can find a full list of the Ruby highlight classes
in the "Syntax documentation":http://syntax.rubyforge.org/chapter-2.html but you will need to experiment with the highlighter to find the XML and YAML classes.
Code to be highlighted is inserted into pages like so:
#:code#
#:code#[language]#
def amethod
"some code"
end
#:code
#:code#
#{converter.convert(body,false)}
"
end
end
#:code#
As you can see, a macro filter simply inherits @Rote::Filters::MacroFilter@ and implements one or more @macro_XXXX@ methods, which is passed the arguments supplied to the macro (used here to indicate the code language) and the raw macro body.
If you want to implement a macro quickly, perhaps across a section or set of pages, you can use @MacroFilter@ itself, supplying a block:
#:code#ruby#
page.page_filter Rote::Filters::MacroFilter.new([:foomacro]) { |tag, args, body
"FooMacro Replacement!"
}
#:code#
This can be done from any page code, a COMMON.rb (see <%= section_link 'Template code and ERB' %>), or on a per-extension basis with <%= section_link 'extension mappings' %>.
*Note* that macro data is passed raw, and excluded from rendering by <%= section_link 'text filters' %>. The output, however, *will* be processed by any filters that follow the macro filter in the chain.
h5. Duck Filters
This being Ruby, you don't _have_ to inherit one of the above filters to create your own - a filter is just an object with a @filter(text,page)@ method.
The standard TOC filter takes this route.
<%= section 4, 'Rake Extensions' %>
Rote supplies a number of non-intrusive extensions a number of the Rake classes, in order to support dynamic dependency caching, caching dependency-based block memoize, and task reset for use in monitor mode. These features are very new, and only lightly documented at present. You are advised to see the "RDoc":<%= link_rel '/rdoc' %> and source if you want to find out more.
These extensions were almost exclusively contributed by Jonathan Paisley.
h5. Dynamic dependency caching
Since layout files are specified in Ruby code, and may be calculated dynamically, it's not possible to determine the layout files upon which a given page depends without running that page's code (including all COMMON.rb files that apply to it, extension mapping blocks, and so forth). This would have (or, had) an adverse impact on Rote's incremental build functionality, especially from the point of view of source monitoring.
This problem is addressed by a small Rake extension that adds the ability to dynamically register dependencies on the current task, and to have those dependencies cached when Rake exits. Internally, Rote automatically registers any layouts loaded by a page, and you can easily register additional dependencies from any Ruby code, by calling methods on the @Rake@ module.
*Note* that this extension is intended, and tested, for Rote - it is not designed to be a general extension (though one could easily be extracted from it). In particular it takes advantage of other extended functionality provided by Rote, and takes no account, for example, of parallel task execution.
By default, the cache is maintained in the project root, in a directory named @.rake_cache@. This is managed by Rote, so for the most part can be ignored, though you can of course supply an alternate path if you wish (via @Rake.cache_dir=@).
h6. Caching and clean builds
When performing a clean build, the cache will also be removed (as part of the @clobber@ task), and all dependencies will be re-evaluated and cached afresh. Caching exists only to allow accurate dependency resolution during incremental builds.
h6. Disabling the cache
There may be occasions when you want to disable use of the cache (for example when diagnosing unexpected dependency chains). This can be accomplished by setting an environment variable, NO_RAKE_CACHE prior to invoking Rote (or Rake). For a single invocation, the easiest way to do this is from the command-line:
rake clobber doc NO_RAKE_CACHE=true
Specifying this option (or setting the variable) will completely disable use of the cache, causing any existing cache to be ignored and all dependencies determined during the run to be discarded.
h5. Dependency-based block memoize
Somewhat related to dependency caching, Rote also provides the ability to memoize Ruby block results, caching them to disk, and only execute the block during incremental builds. This is handy if, for example, you want to incorporate information derived from external commands, for example, or index large files in your documentation.
The following (OSX-specific) example illustrates usage of this feature:
#:code#ruby#
def image_size(fn)
Rake::Task.memoize "image_size" => fn do
# This code only runs if the cache is out-of-date with
# respect to the file
puts "image_size for #{fn}"
# OSX-specific stuff here
s = `sips -g pixelWidth -g pixelHeight #{fn}`
[s[/pixelWidth: (\d+)/,1], s[/pixelHeight: (\d+)/,1]]
end
end
#:code#
<%= section 3, 'Final notes' %>
Rake is a *very* flexible tool, and supports a wide variety of configuration options and advanced features you can use to fit Rote to your needs. Such configuration is (far) beyond the scope of this manual - see "Rake's Documentation":http://rake.rubyforge.org/ for information on the features supported by Rake.
[<%= section_link 'Top' %>]