Customise your weave by creating a new pattern.


§1. Patterns versus formats. Every weave produces output in a "format". The formats are built in to Inweb, and adding new ones would mean contributing code to the project: currently we have HTML, ePub, Plain Text, PDF, DIV, and TeX.

There is no way to specify the format at the command line. That's because -weave-as P tells Inweb to weave with a given "pattern": a weave pattern combines a choice of format with other settings to produce a customised weave. Patterns can also be based on other patterns: one can, in effect, say "I want something like P but with some differences". For example, the Inweb manual at GitHub is woven with -weave-as GitHubPages, which is a pattern based heavily on a generic website-producing pattern called HTML.

The upshot of all this is that if you want a website, but one which looks and behaves differently from what -weave-as HTML would give, you should create a new pattern based on it, and work from there. But patterns are not just for websites.

§2. A pattern definition is a directory containing various files, which we'll get to in due course. Inweb looks for patterns in three places in turn:

For example, the command

    $ inweb/Tangled/inweb inweb/Examples/goldbach -weave-as Tapestry

didn't set a colony file, so (a) doesn't apply. Inweb first tries inweb/Examples/goldbach/Patterns/Tapestry and then inweb/Patterns/Tapestry. If it can't find either, Inweb issues an error.

§3. Basic settings. Patterns allow for extensive customisation of the woven output, especially through the use of plugins (see below). But they can also be extremely minimal. The one absolute requirement is to include a configuration file called pattern.txt, which consists of a series of simple one-line commands. In this file, blank lines, leading and trailing white space are all ignored, as is any file whose first character is #.

The first genuine line of the file should always give the pattern's name, and say what if anything it is based on. For example, this might be:

    name: Tapestry based on HTML

That is the only compulsory content; with that one line in one file, the Tapestry pattern is ready for use. (But of course it behaves identically to HTML in every respect, so it's not very useful yet.)

Do not get these into loops, with A based on B and B based on A.

For a pattern not based on an existing one, simply omit the "based on X" part. Thus, for example,

    name: HTML

§4. There are then a handful of other, optional, settings. The following are all inherited automatically from the pattern we are based on, unless we set them ourselves.

    format: F

sets the format. At present, this must be HTML, plain (plain text), ePub, TeX, or TestingInweb.

    number sections: yes
    number sections: no

causes the weaver to apply numbers to section headings: the first included will be number 1, and so on. Default is no.

    default range: R

tells the weaver to assume the range R, if the user tries to weave a multi-section web with this pattern. (For example, the standard HTML pattern sets this to sections, causing a swarm of individual HTML files to be produced.)

Lastly, there are commands to do with plugins, covered below, which are also inherited.

§5. Bibliographic data can also be set, but this applies only to the current pattern, and is not inherited from any patterns it is based on.

    bibliographic data: K = V

tells the weaver to override the bibliographic data on any web it weaves, setting the key K to the value V. For example:

    bibliographic data: Booklet Title = A formal grammar for Inform 7

§6. It can be useful to do some post-processing after each woven file is made. For an example, see the PDFTeX pattern, which simply uses the TeX pattern to make a TeX file, and then runs it through the pdftex command-line tool. This is done by giving the necessary commands in the pattern file:

    name: PDFTeX based on TeX
    initial extension: .tex
    command: pdftex -output-directory=WOVENPATH -interaction=scrollmode WOVEN.tex
    command: rm WOVEN.tex
    command: rm WOVEN.log

Here WOVEN expands to the filename of the file which has just been woven, but stripped of its filename extension.

Note also the "initial extension" setting. The point of this is that if the user calls Inweb setting -weave-to Whatever.pdf, this pattern setting causes Inweb first to weave Whatever.tex; the post-processing commands will then make Whatever.pdf as expected.

As soon as any command in the list fails, Inweb halts with an error. To see the exact shell commands being issued, run Inweb with -verbose.

§7. Plugins and assets. Plugins are named bundles of resources which are sometimes added to a weave, and sometimes not, depending on its needs; they are placed in the pattern's folder, and Inweb has access to the plugins not only for the current pattern, but also for any pattern(s) it is based on. Plugins were designed for HTML, but there's no reason they shouldn't also be useful for other formats.

A plugin is identified by name alone, case-insensitively, and that name should be a single alphanumeric word. For example, the HTML pattern file says

    plugin: Base

and this ensures that every file woven by this pattern, or any pattern based on it, will use Base. There can be multiple such commands, for multiple such plugins, and the ability isn't restricted to HTML alone.

In addition, the HTML format:

Two of these draw on other open-source projects:

But if you would like your pattern to use different plugins to handle mathematics and footnoting, provide lines like these in your pattern file, but with your preferred plugin names:

    mathematics plugin: MathJax3
    footnotes plugin: Bigfoot

Bigfoot may eventually need to be simplified and rewritten: its big feet presently tread on the MathJax3 plugin, so right now it's not possible to have mathematics in a footnote when Bigfoot is in use.

§8. So what's in a plugin? A plugin is simply a set of "assets", which are individual files stored in the plugin's directory. A typical asset might be a CSS file to help making web pages, or a file of TeX macros to help typeset a PDF.

Plugin inclusion happens like this:

§9. This means it's possible to supply your own version of any plugin you would like to tinker with. If you want Carousel to have rather different CSS effects, for example, make your own copy of Carousel (copying it from the one in the Inweb distribution at inweb/Patterns/HTML/Carousel) and place it in your own pattern. Files in your version will prevail over files in the built-in one.

As a simple example, suppose you want a pattern just like GitHubPages but which uses monospaced fonts throughout, for commentary as well as code. The pattern file can just be:

    name: MonoGitHub based on GitHubPages

Then create just one subdirectory of MonoGitHub, called Base, and create a single file in that called Fonts.css, reading:

    .code-font { font-family: monospace; }
    .commentary-font { font-family: monospace; }

And that should work nicely. What happens here is that when pages are woven with MonoGitHub, they use this custom Fonts.css instead of the one in the Base plugin from HTML. (MonoGitHub is based on GitHubPages, but that in turn is based on HTML.) All the other files of Base remain as they were, and there's no need to provide duplicates here.

§10. But wait, there's more. How is an asset actually "included"? The pattern gets to decide this, based on the file-type of the asset, as expressed by its filename extension. For example, the TeX pattern says:

    assets: .tex embed

This admittedly cryptic line tells Inweb that when it includes plugins for this pattern, any assets ending .tex should be "embedded", rather than copied. There are four things it can do:

§11. In addition, the pattern can specify that some text referring to the asset file should be put into the woven file. For example, an HTML pattern might say this:

    assets: .js copy
    assets: .js prefix = <script src="URL"></script>
    assets: .css copy
    assets: .css prefix = <link href="URL" rel="stylesheet" rev="stylesheet" type="text/css">
    assets: .css transform names

With that done, any Javascript or CSS files in its plugins will be copied over, but links to them will be placed into the header of the HTML file being woven. (The text URL, in a prefix or suffix, expands to the relative URL from the path being woven to the asset file.)

The unique command "transform names", which should be used only for CSS, enables the colour-scheme renaming business described below.

An alternative scheme would be to embed all CSS and Javascript, thus producing a stand-alone HTML file. This could be achieved by:

    assets: .js embed
    assets: .js prefix = <script>
    assets: .js suffix = </script>
    assets: .css embed
    assets: .css prefix = <style type="text/css">
    assets: .css suffix = </style>
    assets: .css transform names

§12. Embeddings. Patterns with the HTML format may also want to provide "embeddings". These are for embedded video/audio or other gadgets, and each different "service" — YouTube, SoundCloud, and such — is represented by an embedding file. Inweb looks for these in the pattern's Embedding subdirectory, if there is one; then it tries in the pattern we are based on, and so on until it gives up and throws an error.

The services in the standard Inweb installation, then, are in inweb/Patterns/HTML/Embeddings. It's easy to add new ones; for example, by creating a similar fragment in Tapestry/Embedding/WebTubeo.html you would provide for embedding videos from WebTubeo when using your pattern.

§13. Syntax colouring. No two people ever agree on the ideal colour scheme for syntax-colouring, so one prime reason to create a custom pattern is to change Inweb's defaults.

Suppose Inweb wants to weave an extract of code written in, say, C. It will use the programming language definition for C to make a syntax-colouring, but then use the weave pattern to decide the colour scheme. For example, it's up to the C language to say which text is a function name: but it's up to the pattern to say whether functions are red or green.

A pattern based on HTML may provide a subdirectory called Colouring. If it does, then the contents will be CSS files which provide colour schemes for different programming languages. The scheme Colours.css is the fallback, and is used for any language not providing a colour scheme; otherwise, a language called, say, Anaconda would be coloured by Anaconda-Colours.css. Inweb looks first in the Colouring directory of the current pattern, then tries the pattern it is based on, and so on.

The practical effect is that if you want a pattern to colour Anaconda programs in your own preferred way — let's call this hypothetical pattern SnakeSkin — then you need only write two files: SnakeSkin/pattern.txt, consisting of the single line

    name: SnakeSkin based on HTML

(or perhaps based on GitHubPages, if you want to host there); and then a colouring file in SnakeSkin/Colouring/Anaconda-Colours.css. You should make this by copying the default Colours.css and tinkering.

§14. Note that Inweb supports multiple languages in the same weave, each having their own colour schemes. To do this, it renames CSS spans on the fly in order to prevent namespace clashes. But you can forget this, because it's automatic.

§15. Templates. The final possible ingredient for a pattern is a "template"; this is a file like a pro-forma letter, into which just the details need to be entered. Inweb does this in two main circumstances:

In fact the same process, called "collation", is also used internally to produce navigation sidebars in HTML, and to inject HTML into headers for the sake of plugins. But the author of a pattern can't control that, whereas she can write her own template-body.html and/or template-index.html.

§16. For example, here is a template file for making an HTML page:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>[[Booklet Title]]</title>
        [[Plugins]]
    </head>
    <body>
[[Weave Content]]
    </body>
</html>

The weaver uses this to generate any HTML page of program taken from the web being woven. What you see is what you get, except for the placeholders in double square brackets:

§17. Other placeholders, not used in the example above, include:

§18. The template-index.html file has access to additional placeholders enabling it to generate contents pages:

    [[Complete Leafname]]  [[Complete Extent]]  [[Complete PDF Size]]
    [[Chapter Title]]  [[Chapter Purpose]]  [[Chapter Leafname]]
    [[Chapter Extent]]  [[Chapter PDF Size]]  [[Chapter Errors]]
    [[Section Title]]  [[Section Purpose]]  [[Section Leafname]]
    [[Section Extent]]  [[Section PDF Size]]  [[Section Errors]]
    [[Section Lines]]  [[Section Paragraphs]]  [[Section Mean]]
    [[Section Source]]

§19. [[Repeat Chapter]] and [[Repeat Section]] begin blocks of lines which are repeated for each chapter or section: the material to be repeated continues to the matching [[End Repeat] line. The "current chapter or section" mentioned above is the one selected in the current innermost loop of that description.

[[Repeat Module]], similarly, begins a repeat through the imported modules of the current web. (The main module, containing the actual material of the current web, does not count.) Within such a loop,

    [[Module Title]]  [[Module Purpose]]  [[Module Page]]

can all be used to refer to the current module. [[Module Page]] expands to the relative URL of the module's own woven HTML form, provided that the module is listed as a member of the current colony file.

[[Select ...]] and [[End Select] form a block which behaves like a repetition, but happens just once, for the named chapter or section.

For example, the following pattern:

    To take chapter 3 as an example, for instance, we find -
    [[Select 3]]
    [[Repeat Section]]
        Section [[Section Title]], [[Section Code]], [[Section Lines]] lines.
    [[End Repeat]]
    [[End Select]]

weaves a report somewhat like this:

    To take chapter 3 as an example, for instance, we find -
        Section Lexer, 3/lex, 1011 lines.
        Section Read Source Text, 3/read, 394 lines.
        Section Lexical Writing Back, 3/lwb, 376 lines.
        Section Lexical Services, 3/lexs, 606 lines.
        Section Vocabulary, 3/vocab, 338 lines.
        Section Built-In Words, 3/words, 1207 lines.

§20. Finally, there is very limited support for conditionals with [[If CONDITION]], an optional Else, and a compulsory Endif. Very few conditions are in fact allowed:

[[If Chapters]] tests whether the current web is divided into chapters, the alternative being that all the sections are in a notional chapter just called Sections.

[[If Modules]] tests whether the current web imports any modules.

[[If Chapter Purpose]], inside a [[Repeat Chapter]], tests whether the current chapter has a (non-empty) purpose text. Similarly for [[If Section Purpose]] and [[If Module Purpose]].

[[If Module Page]], inside a [[Repeat Module]], tests whether the module appears (under its own name, i.e., not by a different name) as a member in the colony file, if there is one. In effect, this can be used to test whether it is safe to make a link to the module's own woven pages using [[Module Page]].