Raku markup for documenting Raku software to aid development and use.
RakuDoc has a variety of components that allow for rich structured documents, provide markup hints to renderers without assuming an output format, extract information from compiled programs, provide information to programs, and enable custom developer extensions.
This document describes a revision of RakuDoc modifying the original speculation S26 that was implemented as Raku was developed. RakuDoc is intended to be backwards compatible with the POD6 markup language based on S26.
RakuDoc is extensible and renderers are free to provide extra functionality beyond the minimum set of instructions described here.
The markup language is called RakuDoc with the CamelCase spelling in order to highlight both the Raku and Doc parts for a newcomer. Some authors may prefer Rakudoc with Titlecase spelling, which is considered a possible but non-canonical variant.
The file extension for a file containing RakuDoc source is .rakudoc.
As it will become apparent, whitespace and indentation plays an important role in RakuDoc. There are quite a few horizontal whitespace characters; no equivalence is made between them by Rakudo. For example, tabs and spaces are treated as two separate horizontal whitespace characters, with no assumption that a single tab is equivalent to four (or two or eight) spaces.
Consequently, mixing spaces and tabs may appear to create the same visual margin in some editor, but they may be treated as different margins when parsing RakuDoc.
It is recommended that RakuDoc authors choose a single whitespace character (e.g. only tabs or only spaces) for margin alignment.
RakuDoc can be thought of as having components that are closely connected to a program or module that is being documented (code-oriented RakuDoc), and components that can be used for text-oriented documents, such as the source for a webpage or a book (text-oriented RakuDoc).
Code-oriented RakuDoc is expected to be "consumed" by users in an editor or Integrated Design Environment (IDE), while text-oriented RakuDoc is consumed in some rendered version, such as an HTML web page, a command-line manpage, or a chapter in an e-book.
When RakuDoc components are viewed in an editor or IDE to provide information about variables, methods, roles, classes and the like, the information could be made available in a pop-up whenever a documented term is selected in some way (e.g. hovering a mouse over it). In the editor context, RakuDoc blocks and markup should then be treated as a comment to the code. Editors are not expected to render the RakuDoc other than to show the RakuDoc components verbatim, but may do so if it seems expedient.
When RakuDoc components are viewed in a rendered version (for example, as HTML), components related to the executable aspects of the program should be ignored.
Within the body of a program there may be several sections of code, which is called the ambient context, interleaved between sections of RakuDoc.
Sections of code that are intended to be examples within the documentation (i.e. code that is not actual interleaved executable code) can be specified in =code blocks, which are treated as integral parts of the RakuDoc, not as source code in ambient context.
Consider a source file containing the definition of a class. When the file is edited in an IDE (e.g. the class is being developed or maintained) the code-oriented RakuDoc is useful to help the developer understand the internal structure and function of specific elements within the code.
Furthermore, when the class is imported into another Raku program the IDE will be able to access the information in declarator blocks attached to specific terms, without needing the source code to be available.
However, by including text-oriented RakuDoc in the same file, end-user documentation can be provided for the class within the same source file. By passing the source through a renderer, a documentation file (e.g. a README.md file for a github repo) can be generated.
This document describes the minimum version of RakuDoc that a renderer or editor must recognize, along with some expected rendering behaviours for text-oriented renderers. “Expected behaviours” means that a renderer should approximate the behaviour as far as possible given the limitations of the output format, and that the approximation should be a reasonable interpretation of the standard described here.
The RakuDoc design assumes certain types of customisability, such as the ability to define new blocks or markup instructions. In order to access blocks or functionality not described in this document, the file containing such RakuDoc instructions should contain a use statement that loads a module that provides the information needed to render the extensions. The information provided by this module may be renderer-specific.
Further exposition on this topic is available.
RakuDoc has four main types of components, which are distinguished by their scope and by effect they have on other components.
Directives define how blocks work. Directives have a similar syntax to regular blocks, but they actually operate on other blocks. New directives cannot be defined. Directives specify behaviours rather than content.
Blocks define complete text components, such as a new paragraph or a code sample or a table. New kinds of blocks can be defined. Blocks contain actual content which is to be directly rendered in some way.
These are the syntax forms for each directive. The = of each directive must be the first non-whitespace character on a given line.
The =alias directive specifies a text substitution available in subsequent A<...> markup instructions. The general syntax for an alias directive is:
=alias ALIAS_NAME Text for substitution
= Optional extra text
The =config directive specifies default options to be applied to specific types of blocks or markup instructions within the remainder of the current block-scope. These default options apply from immediately after the =config directive up to the end of the innermost surrounding block.
The general syntax for configuration directives is:
=config BLOCK_TYPE :CONFIG= :OPTIONAL<EXTRA CONFIG OPTIONS>
If the block-type is single uppercase character X, the =config directive applies the specified configuration options to the X markup instruction. For example:
=config C :allow<B I>
This configures the C<> markup instruction to recognize nested B<> and I<> markup instructions (both of which would otherwise be treated as verbatim within a C<> instruction).
To avoid ambiguities Naming rules are applied to blocks and markup instructions.
Note that since the =config directive applies to block types, =config item ... and =config numitem ... are equivalent. More information about block types can be found in the section on Block type, level and enumeration.
The =document directive specifies new default values for options applicable to the whole document. These values are applied when the final rendering is completed.
The syntax is:
=document :DOCUMENT= :OPTIONAL<EXTRA DOCUMENT OPTIONS>
A renderer may provide custom options not specified here. These should have mixed-case names, see Naming rules.
The =place directive specifies a source of information that is to be placed in the current block. The general syntax of =place is
=place URL :OPTIONS = :MORE:IF<NECESSARY>
The =counter directive reconfigures a named counter within the current lexical scope. The general syntax of =counter is
=counter COUNTER_NAME :OPTIONS = :MORE:IF<NECESSARY>
Even though visually similar in some contexts, a block is not a directive...nor vice versa.
Blocks may be specified in three ways...
A delimited block starts with the directive =begin as the first non-whitespace on a line, followed by a valid Raku identifier indicating the name of the block, followed optionally by metadata (see #Metadata syntax below), followed by content lines. A delimited block is only terminated by an =end directive followed by the same block name. A delimited block that is not terminated by an =end same-block-name instruction throws an error.
For example, to specify a para block in delimited form:
=begin para :meta<data>
This text is the content of the block.
The preceding blank line is also a part of the block,
as are these two non-blank lines.
=end para
The general syntax is:
=begin BLOCK_TYPE :OPTIONAL<CONFIG INFO> = :OPTIONAL<EXTRA CONFIG INFO> BLOCK CONTENTS =end BLOCK_TYPE
An extended block begins with the directive =for as the first non-whitespace on a line, followed by the name of the block, followed by optional metadata. The next non-blank lines after the metadata specify the content of the block, which is terminated either by the first entirely blank line after the content or by the first line that begins with a RakuDoc directive or block. For example, to specify a para block in extended format:
=for para :meta<data>
This text is the content of the block.
This text is NOT content of the block.
After a blank line, a new block is started.
The general syntax is:
=for BLOCK_TYPE :OPTIONAL<CONFIG INFO> = :OPTIONAL<EXTRA CONFIG INFO> BLOCK DATA
In an abbreviated block, the name of the block immediately follows an = sign, which must be the first non-whitespace character on the line. Everything after the block name (up to the first blank line or the start of the next directive or block) is considered the content of the block. For example, to specify a para block in abbreviated form:
=para This text is the content of the block.
This text is NOT content of the block.
After a blank line, a new block is started.
Note that abbreviated blocks cannot be specified with metadata. Any apparent metadata elements placed after an abbreviated block name are instead considered to be part of the block contents.
Where an extended or abbreviated block uses a blank line as the block terminator, the blank line is not included as part of the content of the block. All subsequent whitespace, whether horizontal or vertical (spaces, tabs, new lines), is ignored. Note that horizontal and vertical whitespace can be included inside a delimited block, and may be significant (e.g. in #Verbatim blocks).
Naturally, the contents of blocks may contain embedded RakuDoc markup codes, but not all blocks may contain other blocks. These rules are:
The general syntax of a markup instruction is
|
This is a single uppercase letter, or a unicode entity with the UPPER property
This is either one-or-more < characters or a single « character (i.e. The Unicode entity E<0x00AB>)
This is a string that does not contain the | character (i.e. Unicode entity E<0x007C>), unless that character is inside a nested markup instruction.
Is a list of strings separated by , or ;, depending on the semantics imposed by the <Instruction>
Is one-or-more > or a single » (i.e. Unicode entity E<0x00BB>). The closing marker must be symmetrical with the markup instruction’s opening marker. That is, it must consist of the same number of > or » as there were < or « in the opening marker.
For example:
This is U<unusual> text, and this is I<important>. And this is a L<link to the Raku Programming Language|https://raku.org>.
Which would be rendered as:
For example: This is unusual text, and this is important. And this is a link to the Raku Programming Language.
Metadata is specified using a Raku option pair, where the value portion is always parsed using Raku semantics. The following table contains some typical examples.
| Value is... | Specify with... |
|---|---|
| True | :key |
| False | :!key |
| Literal | :key<answer> |
| List | :key("foo", 42) |
| Hash | :key{ :note('Rosebud, they said'), :emphasize } |
Numerical values can be specified in any Raku-compatible format (42, 42.0, 42e0, 0x2a, 0d42, 0o52, 0b101010). Strings can either be specified using single or double quotes, or angle brackets ('foo', "bar", <baz>). Note that if a string with whitespace is specified in angle brackets, it is in fact a list of strings: <foo bar baz> is the same as ('foo','bar','baz').
Within the context of the parser of the Raku Programming Language, it is also possible to refer to any compile-time value inside the meta-data.
Requiring Raku semantics for the value component of a metadata option means that for compliance to this specification, RakuDoc markup is prohibited within a metadata option. For example, :bullet( E<BALLOT BOX WITH X> ) is prohibited. However, Raku has a syntax for Unicode characters, so :bullet«\c[BALLOT BOX WITH CHECK]» is possible. Note the use of «...» delimiters, which stringify their contents with interpolation, ensuring the \c[...] interpolator is correctly converted.
A renderer may provide a mechanism for allowing RakuDoc within a metadata option but the value part must still conform to Raku semantics, for example,
:caption('This is a heading with I<important markup> in it')
The outer single quotes ensures that the parser passes a plain string to the renderer, which may then post-process the string.
The metadata of an extended block or abbreviated block may extend beyond the first line declaring the block. Each subsequent line must start with an = in the first virtual column, meaning that it must vertically align with the = of the RakuDoc block declaration, and it must be followed by at least one horizontal whitespace character.
For example:
=for head1 :a-first-line-key<firstvalue> :another-first-line-key<xyz>
= :a-second-line-key(42)
= :a-third-line-key<third>
Content for the heading block
Directives are similar in form to abbreviated block instructions, but they do not have the extended or delimited forms. If a directive name is preceded by a =begin, =for or =end, then an error will be thrown.
Directives cannot be enumerated. If a directive is prefixed by num, then a warning will be generated and the prefix ignored.
The =alias directive provides a way to define block-scoped synonyms for longer RakuDoc sequences, (meta)object declarators from the code, or even entire chunks of ambient source. These synonyms can then be inserted into subsequent RakuDoc using the A<> formatting code.
An =alias is scoped from immediately after its declaration up to the end of the innermost surrounding RakuDoc block.
The alias directive takes two arguments. The first is an identifier (which is usually specified in uppercase, though this is not mandatory). The second argument consists of one or more lines of replacement text.
Each =alias directive creates a block-scoped RakuDoc macro that can be invoked during document generation by placing the identifier (i.e. the first argument of the alias) in an A<> formatting code. This formatting code is then replaced by the text returned by the new macro.
The replacement text returned by the alias macro begins at the first non-whitespace character after the alias’s identifier, and continues to the end of the line. You can extend the replacement text over multiple lines by starting the following line(s) with an = (at the same level of indentation as the =alias directive itself) followed by at least one whitespace. Each additional line of replacement text uses the original line’s (virtual) left margin, as specified by the indentation of the replacement text on the =alias line.
For example:
=alias PROGNAME Earl Irradiatem Evermore
=alias VENDOR 4D Kingdoms
=alias TERMS_URLS =item L<http://www.4dk.com/eie>
= =item L<http://www.4dk.co.uk/eie.io/>
= =item L<http://www.fordecay.ch/canttouchthis>
The use of A<PROGNAME> is subject to the terms and conditions
laid out by A<VENDOR>, as specified at:
A<TERMS_URLS>
This would produce:
The use of Earl Irradiatem Evermore is subject to the terms and conditions laid out by 4D Kingdoms, as specified at:
The advantage of using aliases is, obviously, that the same alias can be reused in multiple places in the documentation. Then, if the replacement text ever has to be changed, it need only be modified in a single place:
=alias PROGNAME Count Krunchem Constantly
=alias VENDOR Last Chance Receivers Intl
=alias TERMS_URLS L<http://www.c11.com/generic_conditions>
Alias placement codes may also specify a default display text, before the alias name and separated from it by a |. When a display is specified, it will be used if the requested alias cannot be found (and an "unknown alias" warning will be issued in that case):
The use of A<this program | SOFTWARE> is subject to the terms and conditions laid out by A<our company | COMPANY>, as specified at: A<(Please visit our website) | OURTERMS>
produces ...
The use of this program is subject to the terms and conditions laid out by our company , as specified at: (Please visit our website)
Furthermore, since none of the aliases were specified in this document, error messages will be produced by the renderer (perhaps at the end of the rendered page).
The =begin, =end, and =for directives all specify types of blocks. They have already been illustrated in multiple examples and will not be described further here.
All block forms can be associated with metadata options. Typically the metadata are specified for a block using the extended or delimited forms.
If the same option needs to be added to multiple blocks, this can be done using a config directive, and then the abbreviated block form can be used in the same block scope.
For example, suppose we want all =code blocks to be labelled with a :delta within some section of a document (More information on developer notes). Rather than add a :delta modifier to every individual =code, we could configure every =code block to be automatically given the same developer note, like so:
=config code :delta(v2.3.2+, 'oFun enhancements')
=code method droll { say 'what a cool operator' }
=code method drool { say 'what a slob' }
=code method drill { say 'keep up' }
Within the same block scope, e.g. between =begin section and =end section instructions, one or more =config directives can be specified to define the default behaviour of specific block types. Successive =config directives within the same scope are cumulative in effect. Because =config directives specify default behaviours, whenever a particular kind of metadata is explicitly specified for an instance of that block type, that option overrides the defaults set by any active =config blocks. For example:
=config item1 :bullet« \c[Earth Globe Europe-Africa] » =config item2 :bullet« \c[Hand with Index and Middle Fingers Crossed] » =comment In the following list, =item1 and =item2 will now have non-standard bullets The major sources of sustainable energy are: =item1 geothermal =item1 fusion =item2 (eventually) =begin section =config item1 :toc :headlevel(2) =comment The following items still have non-standard bullets but now they will also be added to the table of contents as if they were =head2 blocks Important items are: =item1 small scale fusion =item1 room temperature superconductors =end section =comment The following list items will NOT be added to the Table of Contents because the section containing that particular =config has now ended. They will still have the non-standard Earth bullets though, because those two =config directives are still in scope. =item1 matter-antimatter annihilation =item1 zero-point energy
There is more discussion of =config in the context of Formatting codes.
The =document directive allows the author to override the values of document-level options. It is required that all document-level options have suitable default values, some of which are specified in this document. Any defaults that are not specified here are left to the discretion of the developer of each renderer.
Unlike the =config and other directives, the =document directive is not lexically scoped. Hence, one or more =document directives may be specified anywhere in a RakuDoc document and their effects are cumulative. That is, the options passed to each successive =document directive are accumulated and concatenated to determine the final set of options. Hence, the two directives:
=document :!auto-toc :auto-index :citation-style<acm>
=document :auto-toc :!auto-index :citation-locale<en-US>
... are equivalent to the single directive:
=document :!auto-toc :auto-index :citation-locale<en-US> :auto-toc :!auto-index :citation-style<acm>
... which is equivalent to:
=document :citation-locale< en-US> :auto-toc :!auto-index :citation-style<acm>
... because the :auto-toc and :auto-index options in later =document directives override those in earlier directives (which is the usual RakuDoc behaviour).
The following document level options are specified:
|
Option name |
Default |
Description |
|---|---|---|
| :error |
True |
If True, warnings for any error conditions are rendered at the end of the document. |
| :auto-toc | False unless overridden by the presence of =head or semantic blocks. | Whether to automatically generate a Table of Contents, or mandate no automatic rendering of a Table of Contents, more in Table of Contents, Index, and Citations. |
| :auto-index | False unless overridden by the presence of X< ... > markup. | Whether to automatically generate an Index, or mandate no automatic rendering of an Index, more in Table of Contents, Index, and Citations. |
| :auto-citations | False unless overridden by the presence of Q< ... > markup. | Whether to automatically generate a Citations list, or mandate no automatic rendering of a Citations list, more in Table of Contents, Index, and Citations. |
| :lang |
en |
The language of the content of the document. |
| :citation-style |
ieee | The style used to format citations. More detail can be found in Citations. |
| :citation-locale |
en-GB | The locale used to format citation dates and numbers. More detail can be found in Citations. |
The =finish directive indicates the end of all RakuDoc source and all ambient contexts within the document. This means that the parser will treat all the remaining text in the file as a string.
Any text after the =finish block can be accessed as a string within the program (i.e. the ambient code) via the $=finish variable. This can be used to provide data to a program, such as a test.
use JSON::Fast; my %h = from-json( $=finish ); say %h.raku; # more lines of code =finish { "key1": "a string value", "key2": "another value" }
This will generate the following output:
{:key1("a string value"), :key2("another value")}
Note, however, that the =data block is the intended and preferred method of providing text data to ambient code, because it allows developers to specify multiple distinct text blocks, which can then be accessed either by name or by position.
The =row and =column instructions are directives, not blocks, and they are described in more detail in the section on the procedural =table block.
The =place instruction is a directive that tells the renderer to obtain text, information, or an object from another source.
The rendered version of the data placed in the text is considered to form its own block scope.
An in-line version of =place is P<...>, which is described in more detail in the section on markup codes.
The schema of the URL specified in a =place directive specifies where to look for the external content:
| Schema | Where to look for the resource |
|---|---|
| http(s): | Look on the web |
| file: | Look on the local filesystem |
| rakudoc: | Look in the usual places for Raku documentation |
| man: | Look via a local man(1) |
| defn: | Look in the current document |
Meanwhile, the kind of content being placed is inferred from the final extension of the URL. For example:
| Extension | How to treat the contents |
|---|---|
| .txt | Render the contents as plaintext |
| .rakudoc | Render the contents as RakuDoc |
| .html | Render the contents as XHTML |
| .md | Render the contents as Markdown |
| .json | Render the contents as JSON |
| .jpg | Render the contents as an image |
| .mp4 | Render the contents as a video |
Renderers are not required to render anything other than plaintext and RakuDoc, but may also support other formats if they wish.
In the case where a URL does not end in a recognized extension:
=place https://example.org/landingpage
=place rakudoc:App::Rak
=place file:/usr/share/legal/std_disclaimer
...then the type of content (and hence rendering) may be inferred from the schema:
| Schema | Inferred content type if no final extension |
|---|---|
| http(s): | XHTML |
| file: | plaintext |
| rakudoc: | RakuDoc |
A =place directive may be accompanied by metadata options to ensure that a reference can be made in the Table of Contents, or to provide an ALT text. For example:
=place https://raku.org/img/camelia-logo.png :!toc :caption<Raku’s mascot> :alt<A cheerful butterfly>
will produce ...
Use =place ... :toc :headlevel(3) to treat the :caption text as a =head3, and include it in the Table of Contents as a =head3 caption.
Note that when any of the toc:, index:, or citation: schemas is used, the automatic rendering of a full Tables of Contents, Index, or Citations list will be cancelled. See Table of Contents, Index, and Citations for more detail.
The =counter instruction is a directive that affects the behaviour of the counters used by numbered blocks.
Although each counter is named in the same way as a blocktype, the two are separate entities.
The directive is followed by the name of a counter (not the name of a block) and one or more of:
These options may not be used in a =config statement, nor may =config options appear in a =counter directive. In case of error, a warning message will be generated and the option will be ignored.
The directive is described in more detail in the section on enumerated blocks
The following RakuDoc components are primarily intended for use when editing Raku code within an editor. Standalone renderers may ignore them.
Declarator blocks differ from other blocks in that they do not have a specific type. Instead, they are attached to a particular element of the ambient source code.
Declarator blocks are introduced by a special comment: either #| or #=, which must be immediately followed by either a space or an opening bracket character, such as a curly brace {, ( or «. If followed by a space, the block is terminated by the end of line; if followed by one or more opening bracket characters, the block may extend over multiple lines and is terminated by the matching sequence of closing bracket characters.
RakuDoc markup instructions may be used inside declarator blocks.
Blocks starting with #| are attached to the code after them, and blocks starting with #= are attached to the code before them.
Since declarator blocks are attached to source code, they can be used to document classes, roles, subroutines and in general any statement or block.
The WHY method can be used on these classes, roles, subroutines, etc. to return the attached RakuDoc value.
For example:
#| Base class for magicians
class Magician {
has Int $.level;
has Str @.spells;
}
#| Fight mechanics
sub duel( #= Magicians only, no mortals.
Magician $a, #= first magician
Magician $b, #= second magician
) {
}
say Magician.WHY; # OUTPUT: «Base class for magicians»
say &duel.WHY.leading; # OUTPUT: «Fight mechanics»
say &duel.WHY.trailing; # OUTPUT: «Magicians only, no mortals.»
say &duel.signature.params[0].WHY; # OUTPUT: «first magician»
say &duel.signature.params[1].WHY; # OUTPUT: «second magician»
These declarations can extend to several lines. For example:
#|( This is an example of stringification:
* Numbers turn into strings
* Regexes operate on said strings
* C<with> topicalizes and places result into $_
)
sub search-in-seq
#=« Uses
* topic
* decont operator
»
( Int $end, Int $number ) {
with (^$end).grep( /^$number/ ) {
.say for $_<>;
}
}
A useful idiom is to place trailing declarator blocks on the parameters of the MAIN sub. These comments will be picked up automatically by USAGE.
sub MAIN(
Str $prefix, #= use this prefix on output lines
Int :$verbose, #= how many lines of output per result (0 = no output)
)
=data blocks are used to specify named and/or ordered chunks of data for the ambient code. They may appear anywhere within a source file, and as many times as required.
The corresponding variable, $=data holds an object that does both the Associative and Positional roles.
Each =data block can be given a :key option, to name it. The contents of any =data block with a key are accessible (as a single string) via the Associative aspect of $=data object. For example:
=begin data :key<Virtues>
Laziness
Impatience
Hubris
=end data
say 'The three virtues are:';
say $=data<Virtues>;
The contents of any =data block that does not have a :key are accessible (as a single string) via the Positional aspect of $=data. Unkeyed =data blocks are stored in the same order they appear in the file. For example:
say 'The second anti-virtue is: ', $=data[1];
=data Industry
=data Patience
=data Humility
Note that, as the preceding example illustrates, because RakuDoc is a compile-time phenomenon, it is possible to specify =data blocks after the point in the source where their contents will be used (provided they’re not being used in a BEGIN, of course).
When $=data itself is stringified, it returns the concatenation of all the unkeyed =data blocks the parser has seen.
=data blocks are never rendered by the text-oriented RakuDoc renderers.
The RakuDoc instructions in this section are primarily intended for text-oriented rendering. However, text-oriented and code-oriented RakuDoc can be freely intermixed with Raku code in a single file; this may help to create code that is well-documented.
When a Raku compiler parses a file, line contents are expected to be Raku code (ambient text). When a RakuDoc block is finished, the next line is assumed to revert to ambient text.
#start of file
my $text; # ambient code
=head this is some text
this line continues the heading
#this line is now ambient code and so must be specified as a comment
A rakudoc block reverses this assumption.
#start of file
my $text; # ambient code
=begin rakudoc
=head this is some text
this line continues the heading
this line is not ambient code and so
it will be treated as an ordinary paragraph
=end rakudoc
# this line is now ambient code
Files that are intended to contain text-oriented documentation alone should be entirely enclosed in a rakudoc block.
However, files whose filename ends in a .rakudoc extension are always presumed to contain only text-oriented documentation, and any renderer must always treat the file’s contents as being enclosed in an implicit =begin rakudoc...=end rakudoc, unless those contents are already explicitly enclosed in a rakudoc block.
Historically the name pod was used for this functionality. For compatibility it will still be possible to use the name pod instead of rakudoc in the foreseeable future. Note however that the Raku Programming Language may assign slightly different semantics to rakudoc at some time in the future.
A block type consists of a block base name, such as head, and a block level, which is an integer starting from 1. (A block type consisting of a block base without an integer implies the block level is 1). The following are all valid block types: head, head2, formula3, table2, para.
Any block type can be associated with an enumeration by prefixing the block name with num, e.g. numhead, numtable, numitem, numcode, numformula.
The effects of enumeration and level on head, defn, and item are illustrated in the sections on those block types because they have some special properties by default, namely:
The block bases rakudoc, section, nested, citation, and pod are considered to be container blocks, which act on their contents but do not have any separate rendered contents. Consequently, even if the prefix num and a level are attached to these bases, they have no effect.
More detail about how enumerations can be customized for all block types can be found in Enumerated blocks.
Headings can be defined using =headN, where N is greater than zero (e.g. =head1, =head2, =head3, etc.). =head is an alias for =head1.
=head A top-level heading
=head2 A second-level heading
=head3 A third-level heading
You can specify that a heading is numbered using the =numhead block (more detail can be found in Enumerated blocks). For example:
=numhead1 The Problem
=numhead1 The Solution
=numhead2 Analysis
=head3 Overview
=head3 Details
=numhead2 Design
=numhead1 The Implementation
which would produce:
1. The Problem
2. The Solution
2.1. Analysis
Overview
Details
2.2. Design
3. The Implementation
A document has an inherent numbering for every heading, but only the =numheadN block makes the numeration visible in the heading and in the Table of Contents.
Note that, even though renderers are not required to distinctly render more than the first four levels of heading, they are required to correctly honour arbitrarily nested numberings. That is:
=numhead6 The Rescue of the Kobayashi Maru
should produce something like:
2.3.8.6.1.9. The Rescue of the Kobayashi Maru
A block scope is important for the =config and =alias directives. In addition, some renderers may generate secondary pages from primary source files, for example, gathering together the same method names in multiple classes. It is desirable for all the relevant blocks to be gathered together.
The section block will typically only be used in the delimited form so that the document writer can define an explicit block scope. The =begin section declaration starts a new block scope, and the =end section returns the scope to the previous one. Unlike an =end rakudoc, an =end section does not always change the scope back to ambient code. It only does so when its corresponding =begin section changed the scope from ambient code. In contrast, an =end rakudoc always reverts to ambient code.
Sections may be embedded within other sections.
When a =begin section is not present, a renderer may apply the following heuristic to determine the block scope (assuming X, Y, and Z are digits such that 0 < X < Y < Z):
Note that a =begin section declaration overrides the heuristic, meaning that multiple =headX declarations can be placed within the same block scope.
A renderer is not expected to render blocks differently when they are embedded in a section block.
Providing metadata to a =begin section block definition is not the same as declaring metadata using a =config directive. Metadata in a config is provided to all matching blocks in the current block scope. Metadata in the =begin section declaration is only applied to the section itself, not to the blocks it contains.
Further exposition on this topic is available.
A RakuDoc document starts with the first RakuDoc block or directive supplied by the parser to the renderer from a file, either as an AST or $=pod structure, and ends with the last such directive or block. Once the document has ended, the document level options are evaluated and applied to render the document and create its output. Note that a RakuDoc document may be embedded within a Raku module or program using one or more rakudoc blocks.
A =begin rakudoc declaration (or equivalently a =begin pod) has the effect that the lines following it are consider RakuDoc text or blocks, and are not treated by the parser as Raku code.
An =end rakudoc (or =end pod) will signal a return to the ambient code.
A rakudoc block does not start a new block scope and continues the previous document scope.
rakudoc blocks may be nested, but do not create additional scopes. For example, if a RakuDoc source containing its own (possibly implied) =begin rakudoc statement is included in another RakuDoc source by means of a =place statement, then the embedded rakudoc block does not create a new block scope. This means that any =config statements in an embedded RakuDoc source will apply to the document or block scope in which the source is embedded.
Contrast this to a section block, which does create a new block scope.
The metadata that affect an entire document are tabulated in the syntax section. These options may changed at any point in a RakuDoc document with a =document directive. The option values are evaluated at the end of the document scope, so the last directives are the most significant.
RakuDoc allows for the customisable numbering of any block, not just headings and items. Moreover, the enumeration, which is generated automatically by the renderer, can be referred to later in the text using the A< ... > markup code. The automatic enumeration is controlled using a construct that is largely independent of blocks: counters.
The block level integer at the end of the name of a block type (e.g. head1, table2, formula3, etc.) is used to characterize numbering hierarchies, so that subordinate blocks are typically numbered with reference to their superordinate predecessors. For example, an instance of =numhead2 is subordinate to the last instance of =numhead (which is equivalent to =numhead1).
The block type may optionally be prefixed by the letters num, which signals that the block should be rendered with an enumeration. Every block has an enumeration, but only those blocks prefixed with num actually include that number in their rendering.
Note that directives (such as =for, =begin, =end, =config, =row, =column, =alias, etc.) are not blocks, and so cannot be prefixed by num.
The (possibly hierarchical) enumeration value for each block is provided by the counter to which the block is currently subscribed. By default, each block automatically subscribes to the counter with the same base name as itself. So, for example, enumeration values for head, head1, numhead and numhead1 blocks are supplied by the single counter named head1.
Every block, whether built-in or user-defined, automatically subscribes to a counter, even if the block is never explicitly specified in a document. Counters autovivify (with an initial individual value of 1) the first time they are referenced, either when a block subscribed to them is used in a document, or when the counter name itself is first used as the argument of some metaoption.
The counter to which a block is subscribed can be changed using the :counter metaoption, either applied to an single instance of a block:
=for head1 :counter<SomeOtherCounter>»
This Is A Specially Numbered Heading
or configured for all subsequent blocks in the same scope:
=config head1 :counter<SomeOtherCounter>
Two or more blocks may subscribe to the same counter, in which case every instance of any of those blocks causes the counter to increment (even instances without the num prefix). For example, to have every table and every formula use a single shared enumeration, you could either have the formula block subscribe to the table counter (as the table block already does by default):
=config formula1 :counter< table1 >
...or else have both block types subscribe to the same user-defined counter (which would be autogenerated as soon as it is first used):
=config table1 :counter< TablesAndFormulae >
=config formula1 :counter< TablesAndFormulae >
Note that the :counter option can also be used to create a unique numbering for only part of a document, by taking advantage of the lexical scoping of the =config directive. For example, to cause tables and formulae within a single subheading to be numbered separately (without affecting subsequent table/formula numbering later in the document):
=head3 Aside: Detailed derivation of the master equation
=begin section
=config table :counter< AsideNumbering >
=config formula :counter< AsideNumbering >
...
=end section
=head3 Table/formula numbering continues normally from here
It is also possible to capture the specific number with which a given block was rendered, by specifying that block with the :numalias<TAG> metaoption. If this option is applied to a specific block then, when the block is rendered, a new alias is automatically created. If that alias is later referred to (using the A<TAG> notation), the enumeration value for the originating numbered block is substituted into the rendered document at that point. For example:
=for numtable :caption<Complete list of ingredients> :numalias<IngredientsTable>
=comment And later...
First gather all the ingredients listed in A<IngredientsTable>.
This might be rendered something like...
Table 7. Complete list of ingredients # And later... =para First gather all the ingredients listed in Table 7.
By default, the format used for the substituted enumeration text will be %T %N (using the enumeration format string described elsewhere). However, the author may specify a different rendering for the alias, using an extended variant of the option: :numalias< FORMAT | TAG >, where FORMAT is a desired alternative format string. For example:
=for numitem :numalias< Article %N | HQ > :form<Article %N. %D>
Headquarters location.
=comment Text of document with many other numitems
=para The deadline is noon at the location of the main office, see A<HQ>.
This would be rendered as something like
Article 10. Headquarters location # Lots of text The deadline is noon at the location of the main office, see Article 10.
Since all block options may be preconfigured using the =config directive, it is also possible to create a parameterized :numalias as follows:
=config numitem :numalias< Article %N. | * > :form<Article %N. %D>
In this case, the * is replaced by the tag specified in each subsequent :numalias option applied to individual numitem blocks. For example, with the previous =config the following uses of :numalias:
=for numitem :numalias< HQ >
=for numitem :numalias< CCN >
=for numitem :numalias< WTF >
...are equivalent to:
=for numitem :numalias< Article %N. | HQ >
=for numitem :numalias< Article %N. | CCN >
=for numitem :numalias< Article %N. | WTF >
The precedence rule for options is that options specified directly on a block take priority over preconfigured options specified by a =config directive. Consequently, a :numalias with an explicit format will replace any preconfigured :numalias supplied by a preceding =config directive. For example:
=config numitem :numalias< Article %N. | * > :form<Article %N. %D>
=for numitem :numalias< HQ >
=for numitem :numalias< CCN >
=for numitem :numalias< The WTF Exception (%N) | WTF >
...are equivalent to:
=for numitem :numalias< Article %N. | HQ >
=for numitem :numalias< Article %N. | CCN >
=for numitem :numalias< The WTF Exception (%N) | WTF >
Moreover, if the explicit format is empty (i.e. :numalias<|TAG>) then the default format (i.e. %T %N) will be reinstated for that one particular block. Hence:
=for numitem :numalias< | WTF >
...is equivalent to:
=for numitem :numalias< %T %N | WTF >
The counters to which blocks can subscribe are independent constructs that are created and maintained for each RakuDoc document by every compliant renderer. Counters are entirely separate from the blocks they service, though the two constructs do interact in several ways that will be described hereafter.
Counters have a range of features useful for generating enumerations: an individual value, a hierarchical prefix, a restart status, and various possible restart triggers.
All these features have sensible defaults whenever a counter is auto-created. However, all of them may also be explicitly reconfigured within a given lexical scope using the =counter directive.
A counter’s individual value (a.k.a. its count) is a global scalar integer variable that is external to the counter itself, and which tracks the counter’s current enumeration value. The individual value of every counter starts (and restarts) at 1, and is incremented every time some block requests the next value from the counter.
Because a counter’s individual value is not itself lexically scoped, it does not revert to its earlier value at the end of a section. It is the single value that a counter manages, not a lexical property of the counter itself. Diagrammatically:
Block (has lexically scoped properties: counter, form, allow, etc.)
┆
[subscribes to]
┆
V
Counter (has lexically scoped properties: prefix, restart status, restart trigger)
┆
[manages]
┆
V
Count (a single global integer variable)
A counter’s hierarchical prefix is the name of some other counter which recursively supplies it with a hierarchical enumeration, such as is required by subordinate blocks such as head2, table3, etc.
Therefore, when a counter is asked to supply its current or next value to a block being rendered, the value returned is a list of integers consisting of the original counter’s own individual value, preceded by the current value of some other counter whose name is specified by the original counter’s hierarchical prefix.
By default, a given counter’s hierarchical prefix is its immediate superordinate counter. That is, the counter table3 has a default prefix of table2, and the table2 counter’s default prefix is table1. Top-level counters, such as table1 have no default hierarchical prefix.
So, for example, the complete hierarchical enumeration supplied by the table3 counter is: (t1, t2, t3), where tN is the current individual value of the tableN counter. Mathematically speaking:
hier-enum( CounterN ) → hier-enum( Counter(N-1) ), indiv-count( CounterN )
hier-enum( Counter1 ) → indiv-count( Counter1 )
You can change the hierarchical prefix value for a given counter using the =counter directive. For example, you might prefer that all top-level tables (which normally have no hierarchical prefix) should be prefixed by the current value of the head1 counter, to produce output like:
1. Concept
Table 1.1. List of requirements
Table 1.2. List of resources
Table 1.3. List of constraints
2. Implementation
Table 2.4. Implementation schedule
Table 2.5. Resource suppliers
Table 2.6. Costings vs actual expenditure
To ensure that every numbered table uses the current head1 value as a prefix in this way, you would configure the table counter as follows:
=counter table1 :prefix<head1>
(To have the individual counters of the tables automatically restart after each heading, see the :restart-after metaoption, which is described later.)
Note that the =counter directive is lexically scoped (i.e. it is effectively a =config for counters instead of blocks), so the preceding directive would need to be placed at the start of the document.
You can also explicitly remove any prefix from a counter, by specifying an “empty” prefix for it. For example, to change the usual t1.t2.t3. enumeration of the table3 counter to just t3., you could specify:
=counter table3 :prefix<>
Note that this directive would also indirectly affect the table4, table5, etc. counters, by “cutting off” their default hierarchical prefixes at table3. This is considered a feature, as it ensures consistency of representation across counter hierarchies.
A counter normally continues to increment its individual value every time any subscribing block requests the “next” value from the counter. However, this monotonic progression can be changed by altering the counter’s restart status.
Normally, a counter’s restart status has the value Nil, indicating no special restart behaviour. In that case the counter defaults to simply incrementing its individual value to obtain its next value.
But you can configure a counter’s restart status to ensure that its next value will be something other than a simple increment, using the =counter directive’s :restart option.
If the value passed in the :restart option is true: =counter head1 :restart then the counter’s restart status immediately becomes true and the counter will no longer increment its individual value when its next value is requested (i.e. when its next subscribing block is rendered). Instead the counter will restart its global count from 1 and return that as its next value.
If the value passed in the :restart option is false: =counter item1 :!restart then the counter’s restart status immediately becomes false and the counter will thereafter increment its individual value as usual when its next value is requested, even if an automatic restart trigger is subsequently encountered (see the following section).
If the value passed in the :restart option is an integer, such as: =counter head1 :restart(42) then the counter’s restart status becomes that integer and the counter will thereafter restart its individual value at the specified integer when a next value is requested, even if an automatic restart trigger is subsequently encountered.
Once a counter has used its restart status to determine what its next enumeration value should be, that restart status is always reset to Nil. In other words, the :restart option tells the counter how to calculate its next (and only its next) value.
By default, most counters are flagged for subsequent automatic restarting (from 1) whenever a block with the same base name but some superordinate level is encountered in the document. However, there is also a mechanism that permits other non-standard automatic restart triggers to be specified on a given counter.
Each custom trigger consists of a set of one or more basenames of specific trigger blocks that, when they are rendered, will automatically set the restart status of a counter to true, so that the counter will automatically restart whenever its next value is subsequently requested.
To specify that a particular counter should be automatically restarted after one or more blocks are rendered, configure that counter using the :restart-after metaoption, passing the names of the restart-triggering blocks as the metaoption’s argument. For example, to have the numbering of every table and formula restart after each head1, head2, or head3 block:
=counter table :restart-after< head1 head2 head3 >
=counter formula :restart-after< head1 head2 head3 >
Or to have the numbering of items restart only after each input block (i.e. instead of after any non-item block):
=counter item1 :restart-after< input >
=counter item2 :restart-after< input >
=counter item3 :restart-after< input >
=counter item4 :restart-after< input >
Note that, as the first example above indicates, having to specify all the “superordinate” trigger blocks for each automatic counter restart is rather tedious, so we define that specifying a particular trigger blockname in a :restart-after< blocknameN > implies “...restart after blocknameN or any superordinate block of the same base name.”
In other words, the previous table-and-formula example (though still perfectly valid) could be simplified to:
=counter table :restart-after< head3 >
=counter formula :restart-after< head3 >
which means “Automatically restart the counter after any head3 or superordinate head block”.
It is also possible to specify automatic restart behaviours “negatively”. That is, to specify that a particular counter restarts after any block, except the one or more that are explicitly excluded from the trigger. For example, having previously changed the reset behaviours of the counters item1 through item4, we could reinstate their default “restart after any non-item” behaviours, like so:
=counter item1 :restart-except-after< item1 item2 item3 item4 >
=counter item2 :restart-except-after< item2 item3 item4 >
=counter item3 :restart-except-after< item3 item4 >
=counter item4 :restart-except-after< item4 >
Or we coulld construct special counters for a set of user-defined item-like blocks, as follows:
=counter MyItem :restart-except-after< MyItem MySubItem MySubSubItem >
=counter MySubItem :restart-except-after< MySubItem MySubSubItem >
=counter MySubSubItem :restart-except-after< MySubSubItem >
In other words, the presence of an excluded blockname (such as BlockName) in a :restart-except-after implies that the counter being configured is to be automatically restarted after every block except BlockName. Multiple excluded blocknames can be specified in the same :restart-except-after, but specifying both a :restart-after and a :restart-except-after option on the same counter is redundant, because the :restart-except-after already implies “restart after everything else”, so any blocks explicitly listed in the :restart-after are already covered by that “...everything else”.
Therefore, where both :restart-after and :restart-except-after options are specified in a single =counter directive, the :restart-except-after trigger is installed and the :restart-after trigger is ignored (preferably with the renderer issuing a warning).
Note that having to specify hierarchical subordinate excluded subitems all the way down is also tedious, so we define that any excluded blockname in a :restart-except-after implies “...restart after any block except this block or any subordinate block of the same base name.”
Hence the previous example of reinstating normal item restarting behaviour could also be simplified to:
=counter item1 :restart-except-after< item1 >
=counter item2 :restart-except-after< item2 >
=counter item3 :restart-except-after< item3 >
=counter item4 :restart-except-after< item4 >
Every counter’s automatic restart trigger is rechecked immediately after each block in a document is rendered, and if a match is found then the counter’s restart status is changed from Nil to True, which means that the counter will be restarted next time it is asked for a value. However, if the counter’s restart status is already non-Nil (because it has already had an explicit :restart option applied to it) then that pre-existing non-Nil restart status is left unchanged by the trigger.
The effect of this is that any explicit :restart always overrides the effect of any automatic trigger, regardless of whether the :restart precedes or follows the triggering.
Further exposition on this topic is available.
The :form metaoption allows the author to modify the way in which enumerated blocks are rendered. It can be used to alter the position where the enumeration value appears, and to add extra text around the various components of a block.
All para-ish blocks have a default format of :form<%N. %D> (e.g. 1. Block data here). All head-ish blocks have a default format of :form<%T %A. %C> (e.g. Table 1. Caption here), except for =numhead, which has a default of :form<%N. %D> (e.g. 1. Heading here).
The value associated with a :form option is similar in concept to a sprintf or strftime format string. That is, it specifies a template into which various values related to the block are inserted, to produce a final rendering of the block. The :form option differs from sprintf and strftime in that it uses a more verbose (but far more readable) specification syntax.
Placeholders for components to be formatted into the format template are known as “fields”, and are specified by a % followed by a single letter character (i.e. a single codepoint that matches /<:Letter>/. This may also be followed (immediately and without any intervening whitespace) by one or more options in the usual :OPTION or :OPTION<VALUE> format. Any other character sequences between fields are rendered verbatim.
Renderers are not required to implement the :form metaoption, but if they do then a conformant renderer must support at least the following field types:
|
Field |
Insert next enumeration value as... |
| %N | the corresponding Indo-Arabic numerals: 1, 2, 3, etc. |
| %A | the corresponding ASCII capital alpha: A, B, C ... Z, AA, AB, AC, etc. |
| %T | the name of the block type in Titlecase without the leading num or trailing level number: Head, Item, Table, Formula, Defn, etc. |
| %C |
the caption of the block (if any) |
| %D | the data contained in the block (i.e. its contents) |
| %% | a literal % |
| %: | a literal : |
So, for example, the following enumerated elements:
=numhead1 PHYSICS
=numhead2 Newtonian
=numhead2 Relativistic
=begin numformula :caption<Mass-Energy Equivalence>
E = MC²
=end numformula
...would normally be rendered something like:
1. PHYSICS
1.1. Newtonian
1.2. Relativistic
E = MC²
Formula 1. Mass-Energy Equivalence
But the following pre-configurations:
=config numhead1 :form<TOPIC %A - %D>
=config numhead2 :form<%D [subtopic %A%N]>
=config numformula :form<Equation %N: %C>
...would cause the document to be rendered differently:
TOPIC A - PHYSICS
Newtonian [subtopic A1]
Relativistic [subtopic A2]
E = MC²
Equation 1: Mass-Energy Equivalence
Notice that in the =config numhead2 example in the previous section the :form option specifies two enumeration fields: %A and %N. This is because enumerated headings are hierarchical in their numbering. For example, the sequence of numbered headings:
=numhead1 The Plan
=numhead2 Plan design criteria
=numhead2 Plan design constraints
=numhead3 Time
=numhead3 Space
=numhead3 Energy
=numhead4 Available energy
=numhead4 Energy costs
...would be rendered something like:
1. The Plan
1.1. Plan design criteria
1.2. Plan design constraints
1.2.1. Time
1.2.2. Space
1.2.3. Energy
1.2.3.1. Available energy
1.2.3.2. Energy costs
So a :form for a second-level heading:
=config numhead2 :form<%D [subtopic %A%N]>
...requires two fields, because it expects to interpolate two enumeration values: the enumeration value of the current first-level heading, plus its own second-level enumeration value.
In that example, the first field (%A) would be replaced by the current numhead1 enumeration value, and the second field (%N) would be replaced by the current numhead2 value.
In general, a :form applied to a numheadX block may specify up to X enumeration fields, X-1 of which would be replaced (left-to-right) by the X-1 current enumeration values of the X-1 superordinate headings. The X-th field would, of course, be replaced by the block’s own enumeration value. For example:
=config numhead4 :form<%N(%A) %N.%N: %D>
...would be formatted by replacing the first %N with the current numhead1 enumeration value, then the single %A with the current numhead2 enumeration value, then the second %N with the current numhead3 enumeration value, then the third %N with the current numhead4 enumeration value.
If any of the superordinate headings is not enumerated (e.g. head3 instead of numhead3), then the corresponding enumeration field would be replaced by an empty string instead of a number.
If a :form option specifies fewer enumeration fields than the corresponding heading level:
=config numhead4 :form<%N.%N: %D>
...then only the final X most-subordinate enumeration values are inserted into the corresponding format. That is, the previous example would be rendered:
1. The Plan
1.1. Plan design criteria
1.2. Plan design constraints
1.2.1. Time
1.2.2. Space
1.2.3. Energy
3.1. Available energy
3.2. Energy costs
That is, because the :form for numhead4 specifies only two enumeration fields, only the two most-subordinate enumeration values (those for numhead3 and numhead4) are interpolated.
The same rules and behaviour apply to numitem1/numitem2/numitem3 blocks and to every other block that may be given a hierarchical enumeration.
The %N field normally interpolates the current enumeration value as a cardinal number (1, 2, 3, etc.), but the :ord option requests the field to interpolate an ordinal number instead (1st, 2nd, 3rd, etc.th). For example:
=config numitem1 :form<%N:ord Activity: %D>
=config numitem2 :form<%N:ord step: %D>
=numitem1 Deploy
=numitem2 Plan
=numitem2 Prepare
=numitem2 Execute
=numitem1 Review
=numitem2 Observe
=numitem2 Discuss
...would be rendered:
1st Activity: Deploy
1st step: Plan
2nd step: Prepare
3rd step: Execute
2nd Activity: Review
1st step: Observe
2nd step: Discuss
To change the underlying language of the ordinal system (e.g. 1er, 2e, 3e etc. or 第一, 第二, 第三, etc.) see the :lang option.
Some enumeration formats (e.g. alphabetic characters or Roman numerals) have uppercase and lowercase variants or close analogies thereto (e.g. “Business” vs “ordinary” notation in Chinese and Japanese numbers). Other fields may benefit from other casing strategies (e.g. Sentencecase, or ProperCase).
To select which case-variant a field uses, append one of the following options:
|
Option |
How the contents of the field are rendered |
| :uc | EVERYTHING IN UPPERCASE OR AS “FORMAL/BUSINESS” NUMERALS |
| :lc | everything in lowercase or as “ordinary/everyday” numerals |
| :tc | First character in titlecase but NO other change of case |
| :tclc | First character in titlecase, everything else in lowercase |
| :sc | Sentencecase: First character of each sentence in Titlecase, ABBREVS entirely in uppercase, everything else in lowercase |
| :pc | Propercase: First Character Of Every Word In Titlecase, ABBREVS Entirely In Uppercase, Everything Else In Lowercase |
For example, to specify that particular case(s) should be used for %A alphabetic field:
=config numitem1 :form<%A:uc. %D>
=config numitem2 :form<%A:uc(%A:lc) %D>
=numitem1 Task sequence
=numitem2 Plan
=numitem2 Prepare
=numitem2 Execute
...would be rendered:
A. Task sequence
A(a) Plan
A(b) Prepare
A(c) Execute
These options also specify how ordinal numbers are rendered:
=config numitem1 :form<%N:ord:uc ACTIVITY: %D>
=config numitem2 :form<%N:ord:lc step: %D>
=numitem1 DEPLOY
=numitem2 Plan
=numitem2 Prepare
=numitem2 Execute
=numitem1 REVIEW
=numitem2 Observe
=numitem2 Discuss
...would be rendered:
1ST ACTIVITY: DEPLOY
1st step: Plan
2nd step: Prepare
3rd step: Execute
2ND ACTIVITY: REVIEW
1st step: Observe
2nd step: Discuss
As a convenient shortcut for common cases, every defined field of the form %X must also provide a corresponding field of the form %x, which is exactly equivalent to %X:lc.
Note, however, that the uppercase version (%X) is not automatically equivalent to %X:uc. That is, a renderer is free to specify, for each field type, whether the default rendering is uppercase or lowercase (if that is even relevant to the field). To override the renderer’s default casing and insist on an uppercase/formal rendering, the user must explicitly specify %X:uc
Note that the :uc, :lc, :tc, and :tclc options all behave exactly like their Raku counterparts, whereas :sc and :pc will attempt to behave in a somewhat more “literary” fashion. Specifically, these last two both understand that words originally in ALLCAPS usually need to stay capitalized. If you think that you need :tclc on a caption or data field, you probably want :sc instead, because it understands slightly more about natural language formatting. For example, the caption:
=for numtable :caption<list of allowed ASCII characters. Namely, those i like.> :form<%N. %C:tclc>
...would be rendered:
Table 1. List of allowed ascii characters. Namely, those i like.
...whereas:
=for numtable :caption<list of allowed ASCII characters. Namely, those i like.> :form<%N. %C:sc>
...would be rendered:
Table 2. List of allowed ASCII characters. Namely, those I like.
Note too that it is an error to specify two or more of :lc, :uc, :tc, :tclc, :sc, or :pc on the same field, either explicitly (e.g. %N:uc:lc) or implicitly (e.g. %n:tc). In such cases, the case of the field specifier itself determines which case is actually used (e.g. %N:uc:lc means %N:uc; %n:tc means %n:lc). Renderers should issue a warning when they encounter these kinds of self-contradictory field specifications.
Specific casing may also be applied to non-enumerator fields such as %T, %C, or %D. For example:
=config numhead1 :form<TOPIC %A - %D:uc> =config numformula :form<[%T:lc %N: %C:sc]> =numhead1 Physics =begin numformula :caption<Mass-Energy Equivalence> E = mc² =end numformula
This would override the intrinsic mixed-casing of the block data and captions to produce something like:
TOPIC A - PHYSICS
E = mc²
[formula 1: Mass-energy equivalence]
In order to avoid undue complexity and ambiguity, explicit embedded RakuDoc components in the data or caption associated with a block will disable any case handling.
For example:
=config numformula :form<[%T:lc %N: %C:sc]>
=begin numformula :caption<B<Mass-Energy> Equivalence>
E = mc²
=end numformula
This would override the sentence-casing of the caption (only) to produce something like:
E = mc²
[formula 1: Mass-Energy Equivalence]
The :lang option specifies that a field should use the conventions of a specific language when inserting a numeric or ordinal value. The language to be used is specified using the language’s ISO 639-1 two-character language code.
For example to specify that, instead of using regular Indo-Arabic numerals, the items of a first-level enumerated list should use Roman (i.e. Latin) numerals:
=config numitem1 :form<%N:lang . %D>
...or that second-level list items should use French ordinals (1er, 2e, 3e, etc.):
=config numitem2 :form<N:ord:lang . %D>
Renderers are encouraged to support at least the following languages: English (:lang<en>, which is the default and represents the Indo-Arabic numeral system) Roman numerals (:lang<la>), Mandarin Chinese (:lang<zh>), Hindi (:lang<hi>), Bengali (:lang<bn>), and Japanese (:lang<ja>). Collectively these six languages cover the primary number systems used by a majority the world’s population.
Note, however, that renderers are not required to support any languages other than the default :lang<en>. If an unsupported language is requested, renderers may always fall back on :lang<en>.
If a renderer supports Roman numerals (I, II, III, IV, etc.) via %N:lang<la>, then it must also provide the equivalent field %R. If it also supports lowercase Roman numerals via %N:lang<la>:lc (i, ii, iii, iv, etc.), then it must also provide the equivalent field %r.
Likewise, if a renderer supports Mandarin Chinese numbers via %N:lang<zh> (which should generate formal/business 大寫 numerals), then it must also provide the equivalent fields %Z and %大. If it also supports %N:lang<zh>:lc (which should produce ordinary 小寫 numerals), then it must also provide the equivalent fields %z and %小.
Generated Chinese numbers should probably use traditional glyphs, rather than simplified glyphs, for maximum comprehensibility outside mainland China (though the expert opinions of native speakers regarding this choice should certainly be sought where possible).
If a renderer supports Japanese numerals, via %N:lang<ja>, then it must also provide the equivalent fields %J and %業 (formal/business numbers) as well as %j and %並 (everyday numbers). Note that %業 and %並 are still tentative, and perhaps not the most obvious choices. Unfortunately the most obvious choices – %大 and %小 – are already taken by %Z and %z (as Chinese arguably had the prior claim to them). Feedback on these names and suggestions for improvements – especially from native speakers of Japanese – would be greatly appreciated.
If a renderer supports Hindi numerals, via %N:lang<hi>, then it must also provide the equivalent fields %H and %ह. If a renderer supports Bengali numerals, via %N:lang<bn>, then it must also provide the equivalent fields %B and %ব.
Only these six languages (English, Mandarin Chinese, Hindi, Bengali, Japanese, and Latin) will ever have dedicated single-character field specifiers. If a renderer supports the number systems of any other languages (e.g. %N:lang<fr>, %N:lang<th>, or %N:lang<eo>), the renderer is not permitted to reserve any %X field for them.
Note that a renderer is permitted to support %N:lang<xx>, without supporting the corresponding %N:lang<xx>:ord, or vice versa (though implementers are strongly encouraged to implement both cardinal and ordinal modifiers – where relevant – for any language they support).
A numBlockname may have an associated :numalias< TAG > option. Later, in accordance with the rules described above for the Alias directive , the enumeration can substituted into text using A<TAG>.
By default, the format used for the substituted enumeration text will be %T %N, using the enumeration format string described above.
The author may specify the rendering of the alias using the option :numalias< FORMAT | TAG >, where FORMAT is a format string. For example:
=for numitem :numalias :formHeadquarters location. =comment Text of document with many numitems =para The deadline is noon at the location of the main office, see A<HQ>.
This would be rendered as something like
Article 10. Headquarters location
# Lots of text
The deadline is noon at the location of the main office, see Article 10.
Since all options may be set using the =config directive, it is possible to set :numalias as follows:
=config numitem :numalias< Article %N. | * > :form<Article %N. %D>
In this case, the * is replaced by the actual TAG specified in the :numalias option for the block. For example:
=for numitem :numalias<HQ>
The precedence rule for options is that options specified by a block take priority over options specified by a =config directive.
Consequently, :numalias<|TAG> will override any declaration given by a =config directive, and the default value of %T %N. will be used to render any A<TAG> reference.
An ordinary paragraph consists of text that is to be formatted into a document at the current level of nesting, with whitespace squeezed, lines filled, and any special inline markup applied.
Ordinary paragraphs consist of one or more consecutive lines of text, each of which starts with a non-whitespace character. The paragraph is terminated by the first blank line or directive.
For example:
=head This is a heading block
This is an ordinary paragraph.
Its text will be squeezed and
short lines filled. It is terminated by
the first blank line.
This is another ordinary paragraph.
Its text will also be squeezed and
short lines filled. It is terminated by
the trailing directive on the next line.
=head2 This is another heading block
This is yet another ordinary paragraph,
at the first virtual column set by the
previous directive
Ordinary paragraphs do not require an explicit block specifier or delimiters (within a rakudoc block).
Alternatively, there is also an explicit =para block specifier that can be used to explicitly mark a paragraph, which would be necessary outside a rakudoc block.
=para
This is an ordinary paragraph.
Its text will be squeezed and
short lines filled.
This is rendered as:
This is an ordinary paragraph. Its text will be squeezed and short lines filled.
In addition, the longer =begin para and =end para form can be used. For example:
=begin para
This is an ordinary paragraph.
Its text will be squeezed and
short lines filled.
This is still part of the same paragraph,
which continues until an...
=end para
As demonstrated by the previous example, within a delimited =begin para and =end para block, any blank lines are preserved.
RakuDoc provides a =nested block that marks all its contents as being nested:
=begin nested
S<We are all of us in the gutter,
but some of us are looking at the stars!>
=begin nested
– Oscar Wilde
=end nested
=end nested
...which would produce:
We are all of us in the gutter,
but some of us are looking at the stars!
– Oscar Wilde
A nested block is like a section block in that it defines a scope and can contain any other kind of block, including implicit paragraph and code blocks. Note that the relative physical indentation of the nested blocks in the document plays no role in determining the ultimate indentation of their contents in the final rendering.
Normally a writer does not want to consider the way text flows on a page. They want the end of each line to be treated the same as a space, and for extra spaces to be eliminated. However, the exact placing of whitespace sometimes is important, especially for code.
Code blocks are used to specify pre-formatted text (typically source code), which should be rendered without rejustification, without whitespace squeezing, and by default without recognizing any inline markup instructions. Code blocks also have an implicit nesting associated with them. Typically these blocks are used to show examples of code, markup, data formats, or other textual specifications. They are usually rendered using a fixed-width font.
A code block may be implicitly specified as one or more lines of text, each of which starts with a whitespace character at the block’s virtual left margin. The implicit code block is then terminated by a blank line or an explicit directive. For example:
This ordinary paragraph introduces a code block:
$this = 1 * code('block');
$which.is_specified(:by<indenting>);
Implicit code blocks may be used elsewhere with some caveats.
There is also an explicit =code block (which can be specified within most other block types, not just =rakudoc, =item, etc.):
The C<loud_update()> subroutine adds feedback:
=begin code
sub loud_update ($who, $status) {
say "$who -> $status";
silent_update($who, $status);
}
=end code
As the previous example demonstrates, within an explicit =code block the code does not have to be indented; it can start at the (virtual) left margin. Furthermore, lines that start with whitespace characters after that margin have subsequent whitespace preserved exactly (in addition to the implicit nesting of the code). Explicit =code blocks may also contain empty lines.
The code in a document is almost always related to a specific programming language, by default Raku. But examples of Ruby, C, RakuDoc, or other languages may also appear in the Raku documentation sources.
A renderer may apply language specific syntax highlighting to the contents of a code block according to the following rules:
By default, a renderer will not change the contents of a code block, but see the caveat when :allow is used.
RakuDoc provides blocks for specifying the input and output of programs. These are similar to code blocks in that they preserve whitespace and are rendered distinctly from regular text paragraphs.
The =input block is used to specify pre-formatted keyboard input, which should be rendered without re-justification or squeezing of whitespace.
The =output block is used to specify pre-formatted terminal or file output, which should also be rendered without re-justification or whitespace-squeezing.
Although they are rendered with verbatim whitespace, like a code block, input and output blocks differ from code blocks in that they do recognize any inline markup instructions within their text.
For example:
=begin output
Name: Baracus, B.A.
Rank: Sgt
Serial: 1PTDF007
Do you want additional personnel details? K<y>
Height: 180cm/5'11"
Weight: 104kg/230lb
Age: 49
Print? K<n>
=end output
In this example, the two embedded K<...> sequences would be recognized as inline markup and rendered appropriately (i.e. as keyboard input).
Although =code blocks automatically disregard all markup instructions, occasionally you may still need to specify some markup within a code block. For example, you may wish to emphasize a particular keyword in an example (using a B<> code). Or you may want to indicate that part of the example is metasyntactic (using the R<> code). Or you might need to insert a non-ASCII character (using the E<> code).
You can specify a list of display only markup instructions (B, C, H, I, J, K, N, O, R, S, T, U, V) that should still be recognized within a code block using the :allow option. The value of the :allow option must be a list of the (single-letter) names of one or more markup instructions. Those codes will then remain active inside the code block. For example:
=begin code :allow< B R > :lang<RakuDoc>
sub demo {
B<say> 'Hello R<name>';
I<note> 'The I format is not recognized';
}
=end code
This would be rendered:
sub demo {
say 'Hello name';
I<note> 'The I format is not recognized';
}
It should be noted that both :allow and :lang (if :syntax-highlighting is True) will affect the rendering of the content of the block. This is likely to cause conflicts in some cases. The renderer is free to choose how to resolve such conflicts, e.g. by disregarding the :allow metadata.
Lists in RakuDoc are specified as a series of contiguous =item blocks. No special "container" directives or other list delimiters are required to enclose the entire list.
Note that =item is just an abbreviation for =item1.
Lists in RakuDoc are by default unordered. For example:
The three suspects are:
=item Happy
=item Sleepy
=item Grumpy
This produces:
The three suspects are:
By default, a compliant renderer will provide a bullet for each item. RakuDoc also allows for custom bullets as discussed below.
Lists may be multi-level, with items at each level specified using the =item1, =item2, =item3, etc. blocks. (The indentation depends on the rendering engine and does not need to be included in the RakuDoc markup.) Up to four levels are normally differentiated.
For example:
=item1 Animal
=item2 Vertebrate
=item3 Mammals
=item4 Primates
=item2 Invertebrate
=item1 Phase
=item2 Solid
=item3 Crystalline
=item3 Amorphous
=item2 Liquid
=item2 Gas
This would produce:
Note, however, that item blocks within the same list are not physically nested. That is, subordinate items should not be specified inside superordinate items:
=comment THE WRONG WAY...
=begin item1 ───────────────┐
The choices are: │
=item2 Liberty ─── Level 2 ├─── Level 1
=item2 Death ─── Level 2 │
=item2 Beer ─── Level 2 │
=end item1 ───────────────┘
=comment THE CORRECT WAY...
=begin item1 ───────────────┐
The choices are: ├─── Level 1
=end item1 ───────────────┘
=item2 Liberty ─────────────────── Level 2
=item2 Death ─────────────────── Level 2
=item2 Beer ─────────────────── Level 2
Renderers are not required to parse nested list items, nor to produce a coherent rendering if they are able to parse them.
Using the delimited form of the =item block (=begin item and =end item), we can specify items that contain multiple paragraphs.
For example:
Let’s consider two common proverbs:
=begin item
I<The rain in Spain falls mainly on the plain.>
This is a common myth and an unconscionable slur on the Spanish people,
the majority of whom are extremely attractive.
=end item
=begin item
I<The early bird gets the worm.>
In deciding whether to become an early riser, it is worth considering
whether you would actually enjoy annelids for breakfast.
=end item
As you can see, folk wisdom is often of dubious value.
This renders as:
Let’s consider two common proverbs:
This is a common myth and an unconscionable slur on the Spanish people, the majority of whom are extremely attractive.
In deciding whether to become an early riser, it is worth considering whether you would actually enjoy annelids for breakfast.
As you can see, folk wisdom is often of dubious value.
When rendered, each =itemN will be preceded by a bullet and each level may have a different bullet. A compliant renderer will define a default bullet for at least the first four levels within a nested list, with the bulleting strategy for other levels being up to the renderer.
The default bullet can be overridden with a custom bullet for any =itemN. For example:
The project originally consisted of five phases, of which two are already complete and two have been abandoned: =for item :bullet« \c[BALLOT BOX WITH CHECK] » Investigate existing solutions =for item :bullet« \c[BALLOT BOX WITH CHECK] » Define a minimal initial feature set =for item :bullet« \c[BALLOT BOX] » Implement this minimal set of features =for item :bullet« \c[BALLOT BOX WITH X] » Secure 100 million in venture capital =for item :bullet« \c[BALLOT BOX WITH X] » Abscond to the Bahamas with the cash
... would produce something like a list with checkboxes, thus:
The project originally consisted of five phases, of which two are already complete and two have been abandoned:
However, more interesting bullets are possible, including multiple characters. For example:
=for item :bullet« \c[Heavy Check Mark] » Investigate existing solutions =for item :bullet« \c[Heavy Check Mark] » Define a minimal initial feature set =for item :bullet« \c[Anticlockwise Downwards And Upwards Open Circle Arrows] » Implement this minimal set of features =for item :bullet« \c[no entry sign] » Secure 100 million in venture capital =for item :bullet« \c[no entry sign, palm tree] » Abscond to the Bahamas with the cash
... to produce
By using the =config directive, it is also possible to change the default bullets for the duration of a section. For example,
=begin section =config item1 :bullet« \c[Earth Globe Europe-Africa] » =config item2 :bullet« \c[Hand with Index and Middle Fingers Crossed] » The major sources of sustainable energy are: =item1 wind =item1 hydroelectric =item1 solar =item1 geothermal =item1 fusion =item2 (eventually) =end section
...which would produce:
The major sources of sustainable energy are:
In the event that a custom bullet cannot be rendered (e.g. a specified Unicode glyph is unrecognized or unrenderable in the target format), a compliant renderer will fall back to its default bullet and generate an error message.
A =numitemN expresses the inherent numeration of a list:
=numitem1 Visito
=numitem2 Veni
=numitem2 Vidi
=numitem2 Vici
This would produce something like:
1. Visito
1.1. Veni
1.2. Vidi
1.3. Vici
The numbering scheme is at the discretion of the renderer. A renderer might, for example, provide a scheme similar to the examples here, and also provide an enhancement, such as an :html-ordered metaoption that might leverage the <ul type="A"> markup.
The numbering of successive =numitem1 list items increments automatically, but is reset to 1 whenever any other kind of non-ambient RakuDoc block appears between two =numitem1 blocks. For example:
The options are:
=numitem1 Liberty
=numitem1 Death
=numitem1 Beer
The tools are:
=numitem1 Revolution
=numitem1 Deep-fried peanut butter sandwich
=numitem1 Keg
This would produce:
The options are:
1. Liberty
2. Death
3. Beer
The tools are:
1. Revolution
2. Deep-fried peanut butter sandwich
3. Keg
The numbering of nested items (=numitem2, =numitem3, etc.) resets to 1 whenever the numbering of a superordinate item changes (either resets or increments).
To prevent a =numitemN from resetting after a non-item block, you can modify the block’s counter using the :!restart option:
=numitem1 Retreat to remote Himalayan monastery
=numitem1 Learn the hidden mysteries of space and time
I<????>
=counter numitem1 :!restart
=numitem1 Prophet!
This produces:
1. Retreat to remote Himalayan monastery
2. Learn the hidden mysteries of space and time
????
3. Prophet!
Normally, if two =numitemN blocks are separated by some other kind of block (for example, a =para, =code, or =table block), then the numbering of the second =numitemN block resets to 1.
However, if the numitemN counter is modified with a :!restart option (either before or after the intervening block) the numbering of the second numitemN block does not reset, but increments instead (i.e. as if there had been no intervening non-numbered block).
The :!restart option has no effect on the counters of any superordinate or subordinate =numitem blocks that are currently active in the same scope. That is: a =counter numitemN :!restart causes the counter of every active =numitemZ block (where Z > N) to reset to 1, and the counter of every active =numitemA block (where A < N) stays the same.
A =numitem is the same as a =numitem1, by analogy with =item and =head.
The underlying paradigm is that every sequence of list instructions (that is: every sequence of =itemN and/or =numitemN blocks) has a default counter that provides an inherent numeration. The =numitemN instructions express the numeration when rendered, while the =itemN instructions do not.
When a sequence of list instructions is terminated by another sort of block then, by default, a new list is created with its own inherent numeration. By specifying :!restart before the next list instruction, the previous inherent numeration is preserved and continued.
Lists that define terms or commands can be specified using the =defn block, which is equivalent to HTML <DL> lists.
A definition contains two parts: a term and a defining text. The term is the contents of the first line of the defn block (i.e. the text immediately after an abbreviated =defn, or the first line after a =for defn or =begin defn). The defining text is the remaining lines within the scope of the defn block. A renderer is expected to distinguish between the term and the defining text. For this reason, the term part is rendered verbatim, including any attempted markup codes.
For example:
=defn Admiration
Our polite recognition of another’s resemblance to ourselves.
=defn Misfortune
The kind of fortune that never misses.
...will be rendered as:
A renderer is expected to retain the information generated by a definition list, and the defining text may be targeted by a link markup instruction.
Definitions can be numbered in the same way as =item lists. That is a =numdefn instruction will express the inherent numeration of the definition list when it is rendered.
As with ordinary lists, if the counter of a =numdefn block is configured with a :!restart metadata option, then the preceding definition list’s inherent numeration is preserved and continued.
For example:
=numdefn Aardvark
A lexicographically pre-eminent animal
=numdefn Beaver
An architecturally pre-eminent animal
Et cetera, et cetera...
=numdefn Yak
A grammatically pre-eminent animal
=numdefn Zorilla
A lexicographically penultimate animal
...will yield something like:
Et cetera, et cetera...
In order to continue a list, an explicit :!restart must be specified for the block’s counter, such as:
=numdefn Aardvark
A lexicographically pre-eminent animal
=numdefn Beaver
An architecturally pre-eminent animal
Et cetera, et cetera...
=counter numdefn :!restart
=numdefn Yak
A grammatically pre-eminent animal
=numdefn Zorilla
A lexicographically penultimate animal
...will yield something like:
Et cetera, et cetera...
Suppose a writer needs every numbered definition to form a single monotonic sequence within some block scope (e.g. for every definition within a document section, or every definition throughout the entire document). This would seem to require that every =numdefn be preceded by a =counter numdefn :!restart option. Or the writer could simply pre-configure the auto-restart behaviour for every =numdefn within the scope so that the block’s counter never auto-restarts (i.e. restarts after no block whatsoever), as follows:
=counter numdefn :restart-after<>
Tables can be specified in RakuDoc using a =table block using either a visual definition, or a procedural definition. The visual semantics allow for a simple table to be quickly specified, but the simplicity imposes a number of constraints. The procedural semantics overcome those constraints by describing the contents of rows, columns, and cells.
A table may be given an associated description or title using the :caption option and may be included in the Table of Contents.
A procedural table may only be specified in the delimited form. As will become clear below, procedural semantics are assumed if the next RakuDoc instruction after a =begin table is one of =row, =column, or =cell.
In a visual table specification, columns are separated by two or more consecutive whitespace characters (e.g. double-space or twin-tabs), or by a vertical line (|) or a border intersection (+), either of which must be separated from any content by at least one whitespace character. Note that only one kind of column separator (i.e. only spaced or only |/+) is allowed in a single line, but different lines are allowed to use different visible column separator types. Using a mixture of visible and non-visible column separator types in a single table is an error.
Rows can be specified in one of two ways: either one row per line, with no separators; or multiple lines per row with explicit horizontal separators – whitespace, intersections (+), or horizontal lines (-, =, _) – between every row. Either style can also have an explicitly separated header row at the top. If rows are using the two-whitespace-character separator, the row cells should be carefully aligned to ensure the table is interpreted as the user intended.
Each individual table cell is separately formatted, as if it were a nested =para. Note that table rows are expected to all have the same number of cells.
This means you can create tables compactly, line-by-line:
=table
The Shoveller Eddie Stevens King Arthur’s singing shovel
Blue Raja Geoffrey Smith Master of cutlery
Mr Furious Roy Orson Ticking time bomb of fury
The Bowler Carol Pinnsler Haunted bowling ball
...or line-by-line with multi-line headers:
=table
Superhero | Secret |
| Identity | Superpower
==============|=================|================================
The Shoveller | Eddie Stevens | King Arthur’s singing shovel
Blue Raja | Geoffrey Smith | Master of cutlery
Mr Furious | Roy Orson | Ticking time bomb of fury
The Bowler | Carol Pinnsler | Haunted bowling ball
...or with multi-line headers and multi-line data:
=begin table :caption('The Other Guys')
Secret
Superhero Identity Superpower
============= =============== ===================
The Shoveller Eddie Stevens King Arthur’s
singing shovel
Blue Raja Geoffrey Smith Master of cutlery
Mr Furious Roy Orson Ticking time bomb
of fury
The Bowler Carol Pinnsler Haunted bowling ball
=end table
Visual-style tables can only have a single header row (namely: everything before the first ===== line). That single header may, however, span one or more initial lines of the visual table specification, as some of the preceding examples illustrate. However, regardless of how many lines a visual-style header spans, it is always treated as a single header row. Individual renderers are free to choose how they represent visual header contents that have line breaks in them: they may treat them as a single string to be reflowed and wrapped, or they may elect to preserve the original line breaks within each header cell. The only requirement is that the entire header of a visual-style table must be rendered as a single row of cells. If two or more header rows are required, use a procedural table instead.
Further exposition on this topic is available.
A visual table is useful for most purposes, but a procedural description is needed if one or more of the following are required:
Table semantics are procedural if the =table declarator is immediately followed by =cell, =row, or =column, otherwise visual semantics are assumed.
Only =cell, =row, =column, or =comment declarations are permitted within the immediate block scope of a procedural table. Note that both =cell and =comment introduce their own block scopes, so other RakuDoc blocks (including nested tables) may be included within their block scopes.
The fundamental idea is that a procedural =table sets up a semi-infinite 2D grid of cells, all of which are initially empty. The grid also tracks the fill position ($POS: the next empty cell to be filled), and the fill direction ($DIR: the direction to move $POS after filling; either across or down). Initially, $POS is set to the top left-most cell of the table, and $DIR is set to across.
Subsequent =cell blocks start filling in that grid, with any intervening =row and =column directives adjusting $POS and $DIR.
=cell blocks can be specified as spanning multiple rows and/or columns, using the :row-span(WIDTH), :column-span(HEIGHT), or :span(WIDTH, HEIGHT) annotations, in which case the block fills more than one grid cell (and merges them into a single logical cell), with the top-left corner of the fill starting at $POS.
A =cell block has the following effects:
A =row directive has the following effects:
A =column directive has the following effects:
In other words, =row searches the south-west quadrant from $POS to find the most north-westerly empty cell ... and moves $POS to that cell. And =column searches the north-east quadrant from $POS to find the most north-westerly empty cell ... and moves $POS to that cell.
In addition, =table and =cell blocks and =row and =column directives can be annotated with any of the following metadata, which subsequently act as defaults for any =cell in their scope:
For example:
=begin table :caption('The Other Guys')
=row :header
=cell Superhero
=cell Secret Identity
=cell Superpower
=row
=cell The Shoveller
=cell Eddie Stevens
=cell King Arthur’s singing shovel
=row
=cell Blue Raja
=cell Geoffrey Smith
=cell Master of cutlery
=row
=cell The Bowler
=cell Carol Pinnsler
=cell Haunted bowling ball
=end table
Or, if you prefer to specify the data in columns:
=begin table :caption('The Other Guys')
=row :header
=cell Superhero
=cell Secret Identity
=cell Superpower
=row
=column
=cell The Shoveller
=cell Blue Raja
=cell The Bowler
=column
=cell Eddie Stevens
=cell Geoffrey Smith
=cell Carol Pinnsler
=column
=cell King Arthur’s singing shovel
=cell Master of cutlery
=cell Haunted bowling ball
=end table
Either of which would produce:
|
Superhero |
Secret Identity |
Superpower |
|---|---|---|
|
The Shoveller |
Eddie Stevens |
King Arthur’s singing shovel |
|
Blue Raja |
Geoffrey Smith |
Master of cutlery |
|
The Bowler |
Carol Pinnsler |
Haunted bowling ball |
Further exposition on this topic is available.
RakuDoc provides a built-in block =formula and an inline markup code F<> to contain text that will be rendered as formulae.
There are several markup languages for expressing mathematical expressions, so the RakuDoc specification recommends the currently most widespread markup syntax for =formula and F<>, namely the LaTeX mathematical notation, including the extensions specified in the AMSMath package
This does not preclude the development of custom blocks to support other mathematical markup languages, e.g. a =MathML custom block to support another syntax.
Implementors of renderers are not required to render the contents of these instructions; it is acceptable for a renderer to render the contents of a =formula or F<> in some other way than as a fully realized mathematical equation.
Both =formula and F<> may take explicit ALT texts, so that the author can decide how their formula should be rendered in cases where the renderer cannot handle the specification.
That is, the =formula block accepts an :alt metaoption, and the syntax for the F<> instruction is either F< FORMULA > or F< ALT | FORMULA >.
Using the ALT text options, the document author can supply a suitable explicit alternative rendering to renderers that cannot handle the full formula syntax:
We will use the identity: F<∑ 1/n² = 𝜋²/6 | \sum \frac{1}{n^{2}} = \frac{\pi^{2}}{6}> ...where the value of pi can be inferred from Euler’s Identity: =for formula :alt< eH<iπ> + 1 = 0 > e^{i\pi}+1=0
An ALT text allows an author to rely on getting an “accurate” representation under those renderers that fully support formulas, and to be able to fall back on a range of reasonable alternatives under those renderers that don’t:
|
Fall back on |
Example |
|---|---|
|
Plaintext | F< Euler’s Identity | e^{i\pi}+1=0 > |
|
RakuDoc | F< eH<iπ> + 1 = 0 | e^{i\pi}+1=0 > |
|
Unicode | F< eⁱᐢ + 1 = 0 | e^{i\pi}+1=0 > |
|
Image | F< P<file:EulerID.jpg> | e^{i\pi}+1=0 > |
|
Link | F< L<https://en.wikipedia.org/wiki/Euler%27s_identity> | e^{i\pi}+1=0 > |
It is also possible to stack the fallback options. For example, one could try for an “accurate” rendering of a formula, but fall back on the placement of a pre-rendered image, or (failing to find that) fall back again to a RakuDoc representation with an outgoing link:
We will use: F<
P<
L< eH<iπ> + 1 = 0
| https://en.wikipedia.org/wiki/Euler%27s_identity
>
>
| e^{i\pi}+1=0
>
Implementors are free to delay – or reject – implementing LaTeX-based formulas, and implementations are considered compliant with the specification, so long as the ALT texts are rendered.
Further exposition on this topic is available.
RakuDoc comments are components that both RakuDoc renderers and ambient-code compilers ignore. Comments are useful for meta-documentation (documenting the documentation) and for communication between authors and readers of RakuDoc documents.
Single-line comments can use an abbreviated =comment block:
=comment Add more here about the algorithm
For multi-line comments, use a delimited comment block:
=begin comment
This comment is
multi-line.
=end comment
Note, however, that delimited comment blocks do not nest, so they are not a reliable method of “commenting out” sections of a RakuDoc (or Raku) source document. In particular, they will always produce an error if the section to be commented out already contains another delimited comment. To safely remove sections of RakuDoc source code from the renderer’s consideration see Ignoring RakuDoc source instead.
Where an output format, such as HTML, offers a comment syntax, a compliant renderer may render the comment contents as a native comment in the output.
During the development or maintenance of a document it is often necessary to temporarily exclude source from being rendered, while at the same time leaving the source in the file either for reference or to return to later.
The =ignore block does this. After a =begin ignore is encountered, everything thereafter is treated as not being rendererable RakuDoc, until the matching =end ignore line is encountered, where “matching” takes into account any number of (recursively) nested =begin ignore...=end ignore pairs.
Note: this implies that, whilst a delimited ignore block does not care about the correctness of the vast majority of any RakuDoc source contained within it, it does insist that any nested delimited ignore blocks within it must be properly balanced. That is, an unmatched inner =begin ignore or =end ignore within a balanced outer =begin ignore...=end ignore pair will produce an error when the document is rendered.
A renderer must never render the contents of an ignore block in any way.
Further exposition on this topic is available.
All uppercase block typenames are reserved for specifying standard documentation, publishing components, source constructs, or meta-information. The following must be recognized:
=NAME
=AUTHOR
=VERSION
=TITLE
=SUBTITLE
=LICENSE
=LICENCE
=SYNOPSIS
The block name of a semantic block is to be rendered as if it were =head BLOCKNAME, and the contents of the block are then to be rendered as one or more regular paragraphs. Consequently, if a semantic block has multiple lines, then its contents must be enclosed using the delimited form.
A semantic block may be defined, but omitted from the text in the place it is written. This is because sections about Authors, or Licensing, are sometimes required at the end, or at the beginning, or in the meta section of an HTML document.
A renderer is expected to gather the contents of a semantic block for it to be accessible by an external program.
If the metadata option :hidden is associated with a semantic block (by using a =config directive, or as a direct metadata option on the extended or delimited forms) then the renderer will not render the semantic block at the position it is located in the RakuDoc document. It will be placed in a data structure by the renderer and the contents can then be rendered at a place defined by a Placement instruction.
The block name of a rendered semantic block will be placed in the Table of Contents table in the position that it is rendered, unless the :!toc and or :caption options are set. A :hidden metadata option will also remove the block’s entry from the ToC. But if it is placed by a P<semantic:> instruction, the block entry will be placed at the appropriate point in the ToC.
RakuDoc provides a mechanism for citing external reference sources in the usual way: with a compact marker in the text and the full information for the source material listed elsewhere. Citations in RakuDoc are marked and listed in an appearance-neutral syntax that allows them to be rendered consistently in any standard citation style (e.g. ACM, APA, Chicago, IEEE, Harvard, MLA, etc.).
Individual citations of reference sources in the text are indicated with a Q<> formatting code. The value contained within each such formatting code must be a unique citation identifier associated with some cited reference work within the document (see below). For example:
=para We have now explored Q<rakudoc-evo-chapter> at some length whether it would be better to use JSON or XML Q< JsonVsXMLMeta > to specify citation data or whether it might be better to design a bespoke DSL Q«10.1109/MODELS50736.2021.00031» instead.
A single Q<> can contain multiple identifiers, which must be separated by semicolons. For example:
=para
The design of Raku commenced Q<Apocalypse1; P6&Parrot; ConwayKeynote2010> in late 2000...
Depending on the chosen bibliographic style in which the document is eventually rendered, multi-identifier Q<> codes may be rendered separately:
The design of Raku commenced [7] [9] [10] in late 2000...
...or aggregated into a single bibliographic marker:
The design of Raku commenced [7,9-10] in late 2000...
Each identifier can also optionally be followed by comma and an annotation, which may be used to refine the context of a given citation by specifying particular sections, chapters, pages, figures, tables, timestamps, etc. within the work being cited. For example:
=para We have now explored Q<rakudoc-evo-chapter, pp. 32-47> at some length whether it would be better to use JSON or XML Qtable 8b> to specify citation data or whether it might be better to design a bespoke DSL Q<10.1109/MODELS50736.2021.00031, sect. III> instead. =para The design of Raku commenced Q ch. 1; ConwayKeynote2010, ts=00:03:27> in late 2000...
Note that whether or not these annotations are included as part of the corresponding bibliographic markers, or are silently ignored, is determined entirely by the bibliographic style that is selected when the document is rendered.
The full citation dataset for each individual reference work is specified in a citation block, as structured textual data in any of the following notations: CSL-JSON, CSL-YAML, CSL-Raku, RIS, MODS, BiBLaTeX, BibTeX, BibTeXML, or Medline/PubMed (XML or NBIB). All of these formats are widely used citation-data-interchange standards, except for CSL-Raku, which is just CSL-JSON/CSL-YAML data transposed into the native Raku syntax for a list of hashes.
Each citation block may contain multiple entries (i.e. aggregated citation data for multiple reference works), but the data for every entry within a single block must be represented in the same data format (e.g. all in CSL-JSON, or all in BibTeX, etc.) A document may, however, contain multiple citation blocks, each of which may specify their contents in different data formats.
For example:
=comment This citation data in in CSL-JSON format
=begin citation
[
{
"id": "mercurio2025",
"type": "book",
"title": "The Morphological Beauty of Raku Grammars",
"author": [ {"family": "Mercurio", "given": "Silvia"} ],
"issued": {"date-parts": [[2025, 3, 14]]},
"publisher": "Butterfly Press",
"ISBN": "978-1-2345-6789-0"
}
]
=end citation
=comment This citation is in BibLaTeX format
=citation @article{zenraku2024,
author = {Wall, Larry},
title = {The Zen of Raku},
journaltitle = {Journal of Camel Studies},
date = {2024-05-12},
volume = {42},
number = {3},
pages = {101-115},
url = {https://example.org/raku},
urldate = {2026-01-23}
}
=comment This in RIS data
=begin citation
TY - JOUR
ID - thorne2023
AU - Thorne, Alistair
TI - Optimization Strategies for MoarVM Bytecode
JO - Journal of Virtual Machine Design
PY - 2023/08/21/
VL - 9
IS - 2
SP - 210
EP - 235
SN - 1234-5678
ER -
=end citation
Note that, for implementation (and perhaps source-highlighting) purposes, the actual species of notation for data contained in each citation block can be automatically inferred by examining just the first few non-blank characters in the block’s content (the “sniff” test), according to the following table:
|
First char(s) |
Inferred format |
Because character represents the start of a... |
| [ |
CSL-JSON |
JSON array of objects |
| - |
CSL-YAML |
YAML list of mappings |
| ( |
CSL-Raku |
Raku-native parenthesized list of hashes |
| { |
CSL-Raku |
Raku-native unparenthesized list of hashes |
| @ |
BibLaTeX |
sequence of standard BibLaTeX or legacy BibTeX entries |
| <bibtex |
BibTeXML |
sequence of XML-encoded BibTeX entries. |
| <mods |
MODS |
sequence of XML-encoded MODS entries. |
| <PubmedArticleSet |
PubMed/Medline XML |
sequence of XML-encoded PubMed/Medline entries. |
| PMID- |
PubMed/Medline NBIB |
sequence of modern PubMed NBIB KEY-VALUE datasets |
| UI - |
Medline NBIB |
sequence of legacy Medline NBIB KEY-VALUE datasets |
| TY - |
RIS |
sequence of RIS-format KEY-VALUE datasets |
Citation data can also be loaded from external sources via a URL, by using the :load metaoption:
=for citation :load< file:/users/jan/.citelists/working/citations.json >
=for citation :load< https:example.com/markup_design_references.bib >
In this variant, the block must not contain any extra data (and renderers should report an error if it does).
The suffix of the file determines the inferred format of the imported data:
|
Suffix |
Inferred format |
|---|---|
| .bib |
BibLaTeX (including legacy BibTeX) |
| .json |
CSL-JSON |
| .mods |
MODS |
| .nbib |
Medline/PubMed NBIB |
| .raku |
CSL-Raku |
| .ris |
RIS |
| .xml |
MODS or PubMed XML or BibTeXML (distinguished via “sniff” test) |
| .yaml |
CSL-YAML |
A document can include any number of citation blocks, in any order, located anywhere in the document. Some common approaches might be:
Every dataset included in any citation block must contain a citation identifier: a text string consisting of any sequence of one or more Unicode characters. Each citation identifier must be unique across all citation datasets within the document.
This identifier may be specified in the id field (of any of the CSL notations), the ID attribute (of MODS), the mandatory initial ID string (of BibLaTeX, BibTeX, and BibTeXML), the PMID or UI value (of PubMed/Medline), or the ID tag (an unofficial extra tag commonly used with RIS data).
If a dataset cannot furnish a suitable identifier, but its citation data includes a ISO-26324 Digital Object Identifier, then the DOI may be used instead.
Each citation identifier is used to associate a Q<> marker with its corresponding citation data in some citation block. For example:
Most programming languages use everyday words for their keywords, but some have taken that notion much further, basing their entire syntax on (subsets) of natural languages Q<Perligata> or on conlangs Q<tlhInganHol::yIghun>. =begin citation [ { "id": "tlhInganHol::yIghun", "type": "software", "title": "Lingua::tlhInganHol::yIghun: Perl code in the original Klingon", "author": [{ "family": "Conway", "given": "Damian" }], "issued": { "date-parts": [[2009, 6, 1 ]] }, "abstract": "Perl module that allows programs to written Klingon syntax and vocabulary.", "publisher": "MetaCPAN", "version": "20090601", "URL": "https://metacpan.org/pod/Lingua::tlhInganHol::yIghun", "accessed": { "date-parts": [[2025, 1, 25 ]] } }, { "id": "Perligata", "type": "paper-conference", "title": "Lingua::Romana::Perligata -- Perl for the XXI-imum Century", "author": [{ "family": "Conway", "given": "Damian" }], "event-title": "Proceedings of the Perl Conference 4.0", "event-place": "Monterey, CA, USA", "publisher": "O’Reilly and Associates", "publisher-place": "CA, USA", "issued": { "date-parts": [[2000, 7]] }, "page": "1-15", "ISBN": "0-596-00013-8" } ] =end citation
When used within a Q<>, a citation identifier cannot contain the characters '|', ';', ',', or '\', unless they are escaped with a leading '\'. Likewise, it cannot contain the Q’s own delimiters, unless they are either balanced or escaped.
Further exposition on this topic is available.
The eventual bibliographic list that a renderer generates from the data may be placed anywhere within a document, by using a =place directive with the citation: scheme. For example:
=head References
=place citation:*
This places a custom list-of-citations that is specially produced by the renderer, using every dataset from all of the document’s =citation blocks, and applying a user-selected citation style – specified either within the document via a :citation-style option (see below), or a style externally selected for the renderer in some way (e.g. via a command-line argument or environment variable).
To have the renderer include only particular citations, you can specify something more limited than “whatever” (i.e. *) in the placement:
=head References =comment Only list sources actually cited in at least one Q<> =place citation:cited =head Further Reading =comment Only list sources not cited in any Q<> =place citation:uncited
If a RakuDoc document does not contain any =place citation: directives, but includes one or more Q<> codes, then the renderer should behave as if there had been a single =place citation:cited at the very end of the document.
Individual citation blocks can also be declared to belong in one or more user-defined categories (whose names must – as usual for user-defined components – contain at least one uppercase and one lowercase letter).
These categories can then be used to select particular citation data for a given listing. Multiple citation blocks can be specified in the same category, and a given citation block can be specified as belonging to multiple categories. For example:
=for citation :category<SyntaxResearch>
=for citation :category<OtherImpls>
=for citation :category<SyntaxResearch Semantics>
=for citation :category<Semantics ImplIssues>
=comment And then...
=head1 Bibliography
=numhead2 Syntactic design
=place citation:SyntaxResearch
=numhead2 Semantic constraints
=place citation:Semantics
=numhead2 Implementation
=place citation:ImplIssues,OtherImpls
When a Q<> marker or =place citation: list is to be rendered, the renderer must determine the citation style in which the markers and the citations list are to be formatted (i.e. ACM, APA, Chicago, IEEE, Harvard, etc.)
The required styling information may be hard-coded directly into a document, by specifying the :citation-style option in the document scope. The :citation-style value may be specified either as a full URL for the corresponding CSL style file:
=document :citation-style< https://raw.githubusercontent.com/citation-style-language/styles/refs/heads/master/apa-numeric-superscript-brackets.csl >
...or as just the standard name of the CSL style (without its filepath prefix or extension suffix):
=document :citation-style< chicago-author-date >
In the absence of an explicit specification within a RakuDoc document, the default citation style is IEEE . That is, each document begins with an implicit =document :citation-style<ieee>.
A CSL locale is also required and may be hard-wired into a RakuDoc document, using the document level :citation-locale option, which takes an IETF BCP 47 language tag specifying the desired locale:
=document :citation-locale< de-CH >
The default locale for a RakuDoc source is en-GB . That is, each document begins with an implicit =document :citation-locale< en-GB >.
Note: the en-US locale was not chosen as the default because it overpunctuates abbreviations and because it uses the month-day-year date sequence.
The specification order of the original citation data within a RakuDoc document is entirely unrelated to its final rendering; the order is always determined by the specified citation style and locale.
When rendering to output formats that support intradocument linkages (such as HTML), renderers may wish to link each rendered bibliographic marker to the corresponding bibliographic reference in the rendered bibliographic list, and perhaps back-link the reference to the marker as well. This approach is encouraged, but not required.
If any Q<> contains a citation identifier that is not present anywhere in the document’s citation data, and if the author has explicitly requested a listing for that non-existent citation dataset (e.g. by specifying a =place citation:* or =place citation:cited), then the missing dataset must be listed in such a way that it is clearly marked as absent/unknown.
The missing listing must also still be associated with a suitable marker generated for the orphaned Q<> code when the citations are listed. For example, if a Q<Wall42> or Q<SapWho99> appears in the text, but there are no datasets in any citation block that contain those particular citation identifiers, then the markers must still be rendered appropriately in the text, as something like:
As discussed in Wall’s early treatise on language design[7,8], the apparent design tension between manipulexity and whipuptitude may only be an artefact of our fixation with linguistic minimalism.
...and the missing reference sources might be rendered like so (in IEEE style):
[7] R. Unknown, “NO SUCH CITATION ID: Wall42”, Did you misspell Wall42?, 0.
[8] R. Unknown, “NO SUCH CITATION ID: SapWho99”, Did you misspell SapWho99?, 1.
...or like so (MLA style):
Unknown, Reference. 0. "NO SUCH CITATION ID: Wall42." Did you misspell Wall42?
Unknown, Reference. 1. "NO SUCH CITATION ID: SapWho99." Did you misspell SapWho99?
That is, a RakuDoc renderer must autogenerate a pseudo-entry for each missing citation dataset, with the issue dates numbered sequentially from 1, as if the absent citation data had been:
=begin citation
[
{
"id": "Wall42",
"type": "article",
"title": "NO SUCH CITATION ID: Wall42",
"author": [{ "family": "Unknown", "given": "Reference" }],
"container-title": "Did you misspell Wall42?",
"issued": { "date-parts": [[0]] }
},
{
"id": "SapWho99",
"type": "article",
"title": "NO SUCH CITATION ID: SapWho99",
"author": [{ "family": "Unknown", "given": "Reference" }],
"container-title": "Did you misspell SapWho99?",
"issued": { "date-parts": [[1]] }
},
]
=end citation
When a block name contains both an uppercase and a lowercase character, as specified in the naming rules below, it is interpreted as a developer-defined block. The naming rules are to ensure that the names of built-in blocks, semantic blocks, and custom blocks never collide.
The way in which a renderer styles the contents of a custom block depends on the renderer, and each renderer may specify a procedure for using user-supplied templates or code.
If a renderer does not recognize a custom block, then the renderer should replace that block with the contents of the block’s :alt<...> option (if provided). If the document author did not include an :alt<...> option, then the renderer should treat the block name as the contents of a =head block, which can be overridden as described in Table of Contents and should render the contents of the unrecognized custom block verbatim, like a =code block. Any unrecognized custom block (with or without an :alt<...> option) should generate a warning message unless the custom block is passed the :!warn option.
Multi-paragraph contents should be enclosed using the delimited form of the block.
In order to avoid conflicts between built-in blocks, semantic blocks, custom blocks, and markup instructions, the following rules must be followed:
An example of implied code was given in the section on Code blocks. Implied code can be used in other blocks.
Each block creates a virtual margin (at the column before its leading =) and that virtual margin extends only to the end of the block (i.e. not to the start of the next named block). Thus:
┊=begin rakudoc
┊This is an implicit =para block
┊
┊ This is implicit =code block
┊
┊=begin nested
┊This is an implicit =para block
┊
┊ This is implicit =code block
┊
┊=begin nested
┊This is an implicit =para block
┊
┊ This is implicit =code block
┊
┊=end nested
┊
┊=for nested
┊This is an implicit =para block
┊over multiple lines
┊ending at this final non-blank line
┊
┊ This is implicit =code block (NOT a =para)
┊
┊=end nested
┊
┊This is an implicit =para block
┊
┊ This is implicit =code block
┊
┊=end rakudoc
Which means that, in the following example:
=begin rakudoc
=for Podcast
this is not code
this is code
=end rakudoc
...the final line is an implicit code block, because it is indented from the virtual margin of its containing =begin rakudoc/=end rakudoc block.
Whereas in:
=begin rakudoc
=for Podcast
this is not code
this is not code either
=end rakudoc
...the final content is an implicit para block, because it starts at the virtual margin of its containing =begin rakudoc/=end rakudoc block.
Indentation from the current virtual margin only implies a para or code block in blocks that don’t already explicitly specify otherwise. Hence, all the following “container blocks” should honour the indented means code and on-margin means para shortcuts: =cell, =defn, =item, =itemN, =nested, =rakudoc, =section, =pod.
None of the following blocks should infer para or code from indentation: =para, =code, =input, =output, =comment, =table, =formula, =data, =head, =headN, =SEMANTIC.
That’s because each block in this second group specifies explicitly what type of information their contents are supposed to be, so there’s no need to infer anything. In particular, =para and =code are specifically provided to circumvent inference from indentation.
A =config code directive will also apply to any implicit code block in the block scope.
Finally, user-defined custom blocks should always pass their contents verbatim to whatever appropriate user-defined handler is in scope, and it’s up to that handler to infer the meaning of any indentation.
Further exposition on this topic is available.
A powerful feature of RakuDoc is the ability to associate metadata with a block. Metadata can be used to change the way a block is rendered, or to allow a renderer to access data in the cloud, or receive data from a microservice.
Some metadata options are defined for certain blocks and a renderer must produce the behaviour described in this section (or in the section for the relevant block), to the extent possible for a given output format.
A renderer may ignore metadata options not specified in this document, or define other metadata options that it will recognize.
Further exposition on this topic is available.
Whenever a =head block such as:
=head Table of Contents, Index, and Citations
...is rendered, it is also associated with an anchor, so that when a link of the form L<link to an internal heading|#Table of Contents, Index, and Citations> is rendered, the renderer will place a link to the correct heading in the output format. The anchor will also be used in the Table of Contents.
Note that the text in the L<...> before the | is the display text, and the tag after the | is the content of the target =head block.
In order for a link to work correctly, the anchor must be unique. The renderer is free to chose the algorithm it uses for generating the internal anchor. This is because different outputs, such as Markdown and HTML, have different formats for anchors.
An author may want to shorten an internal link to a title, and also to place an anchor on every block. For this purpose, the :id<LABEL> metadata option can be attached to any block. For example:
=for head :idTable of Contents, Index, and Citations ...and later we can add: L<link to an internal heading|#ToCIaC>
The renderer is expected to create a link with that name to the start of the block. It is up to the author of the document to ensure that all :id links are unique.
A renderer may mangle the link name (e.g. the contents of a header) to create an anchor ID internally because different output formats may place restrictions on the characters that can be used in a link. However, a document author may not rely on a renderer’s ID generation algorithm.
Internal links (links to anchors within the same document) must be specified by a leading # followed by either:
Internal links cannot be specified by a # followed by:
That is, the in-document link target cannot be the mangled contents of a =head block or a :caption<...> metatag; it can only be the original contents.
For example:
=for head :idA sample heading =for table :id :caption A B C 1 2 3 This is a L<valid link (to an explicit block ID) | #h123 > This is a L<valid link (to an explicit block ID) | #t456 > This is a L<valid link (to a heading) | #A sample heading > This is a L<valid link (to a caption) | #Example table > This is L<NOT a valid link | #A_sample_heading > This is L<NOT a valid link | #Example_table >
When a renderer parses a file containing RakuDoc, information is collected about headings (from =headN and semantic block statements), as well as X<> and Q<> markup codes.
This information, if it exists, is expected to be rendered in an automatic Table of Contents, an Index, or a Citations list, and placed in a manner determined by the renderer (e.g. as a sidebar Table of Contents, or as a separate Index or Bibliography at the end of the main text).
The information may also be filtered and placed by the author using a P<> markup instruction.
To avoid duplication, if an author uses a =place statement to filter information that would usually be automatically rendered, the automated rendering is cancelled. In this way, the author can circumvent the automated rendering of information and take explicit control of their positioning and content.
Additionally, some authors may not want any Table of Contents, Index, or Citations list. The automated generation of these structures can be prevented via the appropriate document-level meta option:
=document :!auto-toc :!auto-index
Renderers will typically add default captions or titles for automatically generated content. These can also be changed using the various :auto-... meta options:
=document :auto-toc<Contents> :auto-index<Glossary> :auto-citations<List of References>
Setting :toc on a block will cause the complete contents of that block to be included in the Table of Contents. Including the entire block contents is usually not desirable, so the :caption<...> meta option can be used to provide a more appropriate text for the Table of Contents.
Setting :!toc will prevent a block’s information from being included in the Table of Contents.
When a built-in block, such as table, needs to be entered into the Table of Contents and styled like a =head2, then use =table2 instead of table.
Custom Tables of Contents can be created to group together tables, formulas, code examples, etc.. This is described in Custom tables of contents. Note that placing information gathered for custom Tables of Content will not cancel the automated generation of the default head Table of Contents.
The implicit heading level of a block in the Table of Contents (TOC) is always equal to its block level. Hence =head1 is implicitly level-1, while =formula3 is implicitly level-3.
The default TOC is created from =head and semantic blocks (e.g. =SYNOPSIS), which are defined to have the :toc option set to True. The semantic blocks =TITLE and =SUBTITLE are not typically included in a Table of Contents, and so are defined to have the :!toc option.
Other blocks may be added to the default Table of Contents. To add a single block (or an entire block type) to the default TOC (a.k.a. the head TOC), configure it with an explicit :toc option. For example, if you want all first-level formulas to be listed in the TOC, preconfigure =formula1 with :toc:
=config formula1 :toc
Then use =formula1 or =formula to specify each formula.
On the other hand, if you want only one particular table included as a third-level TOC entry, specify the :toc option on just that one block:
=for table3 :caption<XOR logic> :toc
| | 0 | 1 |
| 0 | 0 | 1 |
| 1 | 1 | 0 |
You can also specify that a particular block or block type belongs to one or more other TOCs, by specifying the TOC name(s) as an optional argument to :toc. For example:
=comment All =formula3 and =Chart2 blocks are (only) included in “Diagrams” TOC... =config formula3 :toc< Diagrams > =config Chart2 :toc< Diagrams > =comment This specific table is included in the default (head) TOC, as well as in the Diagrams and table TOCs... =begin table :toc< head Diagrams table > | NW | N | NE | | W | * | E | | SW | S | SE | =end table
To insert these other TOCs into a document, use a =place directive at the location where each custom table of contents is required. If you do not want your other TOCs to themselves be listed in the main TOC, add the :!toc option to the placements. For example:
=place toc:Diagrams :!toc :caption<List of Diagrams>
More detail about constraining the TOC levels can be found in the section on placements.
When a set of source files is related to a project with versions (such as the Raku language), documentation may get out of date, or may only apply to features of a future release.
A delta note can be attached to a block using the :delta metadata option, or specified inline with the Δ< ... > markup instruction. Both the metadata option and the markup instruction have two arguments: the first is the version specification, and the second is an optional text note.
Note: This is an example of a built-in markup code that uses a Unicode Upper character. The mnemonic is Delta, which is commonly used to indicate an incremental component.
The version specification is summarized as follows:
| Syntax | Meaning |
|---|---|
| '*' | Any version |
| v1.2.3 | specific version |
| v1.2.3+ | specific version or later |
| v1.2.3- | specific version or earlier |
| v1.2.3..v2.3.4 | inclusive range of versions |
| v1.2.3^..^v2.3.4 | exclusive range of versions |
| v1.2.3..^v2.3.4 or v1.2.3^..v2.3.4 | semi-inclusive range of versions |
The version specification (e.g. v1.2.3) shown here follows the rules of semantic versioning, which is the preferred form for Raku documentation, but is not mandatory. Note that the .. and ^ characters create Raku ranges.
With no extra information about which version should be displayed, a renderer should have a way to include both the string and the version specification.
Alternatively, if there is information about the version to be shown (e.g. from a command-line argument), a renderer should only show blocks that correspond to the version information. A block that does not have an explicit :delta is treated as if it has :delta<*>.
An example is given in the description of the section block
If the metadata option :alt associated with a block has a string value, and an error is encountered when rendering a block, then the value of :alt is rendered in place of the block.
Markup instructions provide a way to add inline markup to a piece of text.
All RakuDoc markup instructions consist of a single capital letter followed immediately by a set of single or double angle brackets; Unicode double angle brackets may be used.
Markup instructions may nest other markup instructions.
Some markup instructions only affect their contents and do not have any metadata associated with them. These are sometimes called formatting codes. Other markup instructions have side effects.
RakuDoc characterizes formatting codes semantically: markup tags indicate the purpose/function/status/meaning of the marked-up text and renderers may choose any appropriate visual representation to reflect the indicated significance. Thus the B<> formatting code does not indicate that the text must be Bold; it indicates that the text is highly significant: the Basis of a sentence. Although, when this highly significant basis text is rendered, it might very appropriately be rendered in a bold font.
The following markup codes should be made available in all renderers.
|
Inline markup |
Instruction |
Mnemonic |
HTML equivalent |
Markdown equivalent |
|---|---|---|---|---|
|
Basis | B<text> | “B for Basis” | <strong>text</strong> | **text** |
|
Important | I<text> | “I for Important” | <em>text</em> | *text* |
|
Unusual | U<text> | “U for Unusual” | <ins>text</ins> | <ins>text</ins> |
|
Weighty | W<text> | “W for Weighty” | <span style="font-variant: small-caps;">text</span> | <span style="font-variant: small-caps;">text</span> |
|
Struck out | O<text> | “O for Out” | <del>text</del> | ~~text~~ |
|
Superscript | H<text> | “H for High text” | <sup>text</sup> | <sup>text</sup> |
|
Subscript | J<text> | “J for Junior text” | <sub>text</sub> | <sub>text</sub> |
|
Code | C<text> | “C for Code” | <code>text</code> | `text` |
The table contains suggested HTML and Markdown equivalents, however a renderer is free to choose other representations.
This syntax does not provide a mechanism to associate metadata options with formatting codes explicitly. It is, however, possible to do this via a =config directive. For example, C<> markup by default does not allow for embedded format codes to be rendered, but an author might want B<> to be allowed. This can be achieved with:
=config C :allow<B>
This mechanism is explained further in the syntax section.
The following markup instructions, including all customisable instructions, will typically have associated metadata.
To create a link, enclose the target specification and any inline text in L< >. RakuDoc links are more general than the conventional HTML links.
The general syntax is L< LABEL | TARGET >
where the optional label is text that is rendered and the target may include a schema. If the label is omitted, then the target is used as the label. Whitespace on either side of the bar is not significant.
When the bar is present with whitespace as the label, then the renderer must supply a suitable text for the label. It is recommended that the renderer retrieves the description supplied by the URI target itself. Descriptions are common with modern internet protocols, such as HTTPS, but may not be available with older or poorly configured URIs. In such a case, the renderer may fallback to a text version of the URI itself. This can be summarised as follows:
|
Link specificiation |
Displayed text |
|---|---|
| L< https://example.com > |
The URI itself |
| L< some text | https://example.com> | The text before the | |
| L< | https://example.com> | The renderer is free to find a suitable display text, but must in all cases display something. The most "suitable display text" would be the title supplied by the URI target. |
When the schema in the URI is missing, then the https:// schema is implied, which means that if the website url is missing as well, the link is to the same host as the document.
The exact name of the resource to which a link is pointing must be used by the renderer. So L< For reference | README.md > or L< text reference | README >
must link to README.md and to README, with the renderer making no assumption about the file format.
However, a collection of RakuDoc source documents may be intended as the base for multiple output formats, such as .html, .md, or .pdf, and so links within the collection may not be able to provide fixed extensions within links. Instead, a group of interlinked RakuDoc documents may need to delegate the selection of an appropriate file format (and extension, if one is needed) to the renderer itself. This is accomplished explicitly using the .* pseudo extension. For example:
L< dealing with the filesystem | type/IO.Path.* >
or for a heading within another resource:
L< getting a directory listing | type/IO.Path.*#routine_dir >
When a .* (“whatever”) extension is encountered by the renderer, if the output format is Markdown, these links would be rendered with .md extensions replacing the .* pseudo-extensions:
[dealing with the filesystem](type/IO.Path.md) [getting a directory listing](type/IO.Path.md#routine_dir)
Or, if the output format is HTML, these links would be rendered with .html extensions instead:
<a href="type/IO.Path.html"> dealing with the filesystem .html#routine_dir"> getting a directory listing </a>
Several schemas are possible:
To refer to a specific section within a webpage, manpage, or RakuDoc document, add the name of that section after the main link, separated by a #. To refer to a section of the current document, omit the external address (i.e. start the target specifier with a #).
A renderer is expected to render a link with a schema as follows:
Renderers are not expected to handle all schemas beyond the minimum above. Renderers offering more sophisticated styling or operational links should provide ways to configure schemas, whilst offering reasonable defaults.
I<ACM Transactions on Programming Languages and Systems> is a registered serial publication (L<issn:0164-0925>) This module implements the standard Unix L<man:find(1)> facilities. Please forward bug reports to L<mailto:abyss@example.org> This module needs the L<LAME library|http://www.mp3dev.org/mp3/>. You could also write the code L<in gibberish|RakuDoc:Acme::Anguish> Also see: L<man:bash(1)#Compound Commands>, =defn lexiphania An unfortunate proclivity for employing grandiloquisms (for example, words such as "proclivity", "grandiloquism", and indeed "lexiphania"). =defn glossoligation Restraint of the tongue (voluntary or otherwise) To treat his chronic L<defn:lexiphania> the doctor prescribed an immediate L<defn:glossoligation> or, if that proved ineffective, a complete cephalectomy.
A second kind of link — the P<> or placement link — works in the opposite direction. Instead of directing focus out to another document, it allows you to assimilate the contents of another document into your own.
In other words, the P<> markup instruction takes a URI and (where possible) inserts the contents of the corresponding document inline in place of the code itself.
A URI meets the regex pattern \w+:\S+, where the word characters before : are called the schema. There may not be any explicit whitespace characters in a URI.
P<> markup is handy for breaking out standard elements of your documentation set into reusable components that can then be incorporated directly into multiple documents. For example:
=COPYRIGHT
P<file:/shared/docs/std_copyright.rakudoc>
=DISCLAIMER
P<http://www.MegaGigaTeraPetaCorp.com/std/disclaimer.txt>
might produce:
Copyright
This document is copyright (c) MegaGigaTeraPetaCorp, 2006. All rights reserved.
Disclaimer
ABSOLUTELY NO WARRANTY IS IMPLIED. NOT EVEN OF ANY KIND. WE HAVE SOLD YOU THIS SOFTWARE WITH NO HINT OF A SUGGESTION THAT IT IS EITHER USEFUL OR USABLE. AS FOR GUARANTEES OF CORRECTNESS...DON’T MAKE US LAUGH! AT SOME TIME IN THE FUTURE WE MIGHT DEIGN TO SELL YOU UPGRADES THAT PURPORT TO ADDRESS SOME OF THE APPLICATION’S MANY DEFICIENCIES, BUT NO PROMISES THERE EITHER. WE HAVE MORE LAWYERS ON STAFF THAN YOU HAVE TOTAL EMPLOYEES, SO DON’T EVEN *THINK* ABOUT SUING US. HAVE A NICE DAY.
The P<> markup code can also be specified with an optional display text, which will be rendered if the renderer cannot find or access the external data source for the placement link. For example:
=COPYRIGHT P<The document is copyright. | file:/shared/docs/std_copyright.rakudoc> =DISCLAIMER P<NO WARRANTY. NONE. NIL. NADA. | http://www.MegaGigaTeraPetaCorp.com/std/disclaimer.txt>
If the filesystem or internet is inaccessible, this might produce:
Copyright
This document is copyright.
Disclaimer
NO WARRANTY. NONE. NIL. NADA.
If a renderer cannot find or access the external data source for a placement link, and the placement link does not have an alternative display text, it must issue a warning and render the URI directly in some form, possibly as an outwards link. For example:
Copyright
See: file:/shared/docs/std_copyright.rakudoc
Disclaimer
You can use any of the following URI forms (see #Links) in a placement link:
The toc: form is a special pseudo-scheme that inserts a table of contents (TOC) in place of the P<> code. After the colon, there must be a string of one or more non-blank characters, called the specification.
There is at least one set of TOC data collected by the renderer from the =head and semantic blocks, but as described above, custom TOC names can be created.
The specification is used to select the TOC data set and to constrain how much data is rendered. When the specification is a *, a digit, or a range, then the default or head TOC is implied. For example, to place a table of contents listing only first- and second-level headings:
P<toc:1..2 >
To place a table of contents that lists the first four levels of headings:
P<toc:1..4 >
In order to include the whole default (or head) table of contents, use toc:*.
When toc: is followed by the name of TOC and optionally a comma, then *, number, or range, the level restrictions are applied to the named TOC.
Valid specs would be:
Invalid specs:
A document may have as many P<toc:...> placements as necessary.
The index:* form is a special pseudo-scheme that inserts an index table in place of the P<> code.
The semantic:NAME form places the NAME semantic block at the position of the P<> instruction.
A variation on the placement instruction is the A<> instruction, which is replaced by the contents of the named alias or object specified within its delimiters. For example:
=alias PROGNAME Earl Irradiatem Eventually
=alias VENDOR 4D Kingdoms
=alias TERMS_URL L<http://www.4dk.com/eie>
The use of A<PROGNAME> is subject to the terms and conditions
laid out by A<VENDOR>, as specified at A<TERMS_URL>.
Any Raku object available after the CHECK phase, such as an object that starts with a sigil, is available within an alias placement. Unless the object is already a string type, it is converted to a string during document-generation by implicitly calling .raku on it.
So, for example, a document can refer to its own filename (as A<$?FILE>), or to the subroutine inside which the specific RakuDoc is nested (as A<&?ROUTINE>), or to the current class (as A<$?CLASS>). Similarly, the value of any program constants defined with sigils can be easily reproduced in documentation:
# Actual code...
constant Num $GROWTH_RATE = 1.6;
=begin rakudoc
=head4 Standard Growth Rate
The standard growth rate is assumed to be A<$GROWTH_RATE>.
=end rakudoc
Non-mutating method calls on these objects are also allowed, so a document can reproduce the surrounding subroutine’s signature (A<&?ROUTINE.signature>) or the type of a constant (A<$GROWTH_RATE.WHAT>).
See Aliases for further details of the aliasing macro mechanism.
A D<> formatting code marks a piece of text as being the “inline definition” of a term. That is: it’s like a =defn block, but it’s not a list item; it’s just part of the regular text. Well-written documentation often includes sentences/paragraphs that introduce a new term, and define it. Typically we want to visually distinguish those newly defined terms, and to be able to link back to the paragraph where they’re defined.
For example:
There ensued a terrible moment of D<coyotus interruptus>: a brief
suspension of the effects of gravity, accompanied by a sudden
to-the-camera realization of imminent downwards acceleration.
The contents of the D<> represent the term being defined, the location of the D<> implies a link target location, and the paragraph containing the D<> suggests a suitable pop-up definition of the term (if a renderer supports such).
The definition term in a D<> is rendered distinctly (typically in bold italics), and the D<> sets up a link target to that term, and possibly a pop-up for the corresponding L<> link to display the entire paragraph in which the D<> appeared. For this reason, the term is rendered verbatim, including any attempted markup codes.
In other words, when rendered to HTML, a D<term being defined> would be translated to something like:
...a term being defined would be...
And a L<defn:term being defined> link would be translated to something like:
...a term being defined link would be...
A definition may be given synonyms, which are specified after a vertical bar and separated by semicolons:
A D<formatting code|formatting codes;formatters> provides a way
to add inline markup to a piece of text.
Any text enclosed in an S<> code is formatted normally, except that every whitespace character in it — including any newline — is preserved. These characters are also treated as being non-breaking (except for the newlines, of course). For example:
The emergency signal is: S<
dot dot dot dash dash dash dot dot dot>.
would be formatted like so:
The emergency signal is:
dot dot dot dash dash dash dot dot dot.
rather than:
The emergency signal is: dot dot dot dash dash dash dot dot dot.
A comment is text that is never rendered.
To create a comment enclose it in Z< >:
Raku is awesome Z<Of course it is!>
This would be rendered as:
Raku is awesome
Notes are ancillary information that may be rendered as footnotes or sidenotes or pop-up notes, depending on the renderer and environment.
To create a note, enclose it in N< >
Raku is multi-paradigmatic N<Supporting Procedural, Object Oriented, and Functional programming>
Which produces:
Raku is multi-paradigmatic [ 1 ]
To flag text as keyboard input enclose it in K< >
=output Enter your name: K<John Doe>
Which is rendered like so:
Enter your name: John Doe
The R<> markup instruction specifies that the contained text is a replaceable item, a placeholder, or a metasyntactic variable. It is used to indicate a component of a syntax or specification that should eventually be replaced by an actual value. For example:
The basic C<ln> command is: C<ln> R<source_file> R<target_file>
This is rendered like so:
The basic ln command is: ln source_file target_file
To flag text as terminal output enclose it in T< >
=input T<Enter your name:> John Doe
Which would be rendered:
Enter your name: John Doe
Unicode codepoint names or numbers may be included in a RakuDoc document by enclosing them in E< >. When E< > encloses a number, it is treated as the Unicode value for the code point using binary, octal, decimal, or hexadecimal numbers specified in the Raku notations for explicitly based numbers. Numbers without an explicit base, as per Raku convention, are decimal.
For example, each of the following:
Raku makes considerable use of the E<171> and E<187> characters.
Raku makes considerable use of the E<0b10101011> and E<0b10111011> characters.
Raku makes considerable use of the E<0o253> and E<0o273> characters.
Raku makes considerable use of the E<0d171> and E<0d187> characters.
Raku makes considerable use of the E<0xAB> and E<0xBB> characters.
will yield the same rendering:
Raku makes considerable use of the « and » characters.
It is also possible to specify Unicode codepoint names. Multiple codepoints separated by , will be considered as a single grapheme. So:
E<LEFT-POINTING DOUBLE ANGLE QUOTATION MARK>
E<REGIONAL INDICATOR SYMBOL LETTER U, REGIONAL INDICATOR SYMBOL LETTER A> Ukraine
E<RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK>
will be rendered as:
« 🇺🇦 Ukraine »
Since emojis are graphemes that can be described by Unicode, E< > will also generate emojis. For example:
E<WHITE SMILING FACE> Smiling face
will generate:
☺ Smiling face
Alternatively, HTML5 character references may be used. For example:
Raku makes considerable use of the E<laquo> and E<raquo> characters.
also yields: Raku makes considerable use of the « and » characters.
The E<> markup may be used for a list of characters separated by ;
Raku code often contains the E<0xff62;0xff63> bracketing characters to avoid using quotes.
This would yield: Raku code often contains the 「」 bracketing characters to avoid using quotes.
The E<> code can also be specified with an alternate display text (before the entity specification and separated from it by a |). When an alternate text is specified, it is used if the specified entity cannot be represented by the renderer (e.g. if the renderer only supports ASCII).
For example:
Raku makes considerable use of the E<left- |laquo> and E<right-double-angle |raquo> characters. Raku code often contains the E<left- and right-corner |0xff62; 0xff63> bracketing characters to avoid using quotes.
An ASCII-only renderer would then render those like so:
Raku makes considerable use of the left- and right-double-angle characters.
Raku code often contains the left- and right-corner bracketing characters to avoid using quotes.
The V<> markup instruction treats its entire contents as being verbatim, disregarding every apparent markup instruction within it. For example:
The B<V< V<> >> markup instruction disarms other codes
such as V< I<>, C<>, B<>, and M<> >.
Note, however that the V<> code only changes the way its contents are parsed, not the way they are rendered. That is, the contents are still wrapped and formatted like plain text, and the effects of any markup instructions surrounding the V<> code are still applied to its contents. For example the previous example is rendered as:
The V<> markup instruction disarms other codes such as I<>, C<>, B<>, and M<>.
Note that C<> also by default keeps its contents verbatim; the difference between C<> and V<> is that C<> always renders its contents to show that they are code (e.g. in a fixed-width font or a distinctive style), whilst V<> uses the default text presentation for the current block.
The default behaviors of both V<> and C<> can be changed using a =config directive. For example:
=config C :allow< B I U >
=config V :allow< N L X >
Anything enclosed in an X<> code is an index entry. The contents of the code are both formatted into the document and used as the (case-insensitive) index entry:
An X<array> is an ordered list of scalars indexed by number, starting with 0. A X<hash> is an unordered collection of scalar values indexed by their associated string key.
You can specify an index entry in which the indexed text and the index entry are different, by separating the two with a vertical bar:
An X<array|arrays> is an ordered list of scalars indexed by number, starting with 0. A X<hash|hashes> is an unordered collection of scalar values indexed by their associated string key.
In the two-part form, the presentation text comes before the bar, and the actual index entry comes after the bar and is case-sensitive.
You can specify hierarchical index entries by separating indexing levels with commas:
An X<array|arrays, definition of> is an ordered list of scalars indexed by number, starting with 0. A X<hash|hashes, definition of> is an unordered collection of scalar values indexed by their associated string key.
You can specify two or more entries for a single indexed text, by separating the entries with semicolons:
A X<hash|hashes, definition of; associative arrays>
is an unordered collection of scalar values indexed by their
associated string key.
The indexed text can be empty, creating a "zero-width" index entry:
X<|puns, deliberate>This is called the "Orcish Maneuver"
because you "OR" the "cache".
In order to allow for renderers to add customisable markup code, whilst at the same time abiding by the naming rules, the markup instruction M< visible text | list-of-strings > is defined as a built-in markup instruction.
The visible text is shown in the text, and may be blank.
The list-of-strings is specified in the same way as the X<> markup instruction for indexing. The semantics of the string is defined by the renderer. If a renderer does not recognize the list of strings, it is expected that the visible text will be rendered and marked in some way (such as with a border, or highlighted), and at least the first string will be made available in the same way as the D<> markup instruction. It is also recommended that the first string is used by the renderer to identify the functionality being provided.
For example, suppose a RakuDoc document is used to create part of a website in which a button is to be styled that accesses the API of a payment service (e.g. 'PayMe'). A developer can then create some functionality according to the rules of a RakuDoc renderer, and present it to the service point. In an HTML document, this might be coded as a <button class="PayMeApp" data-token="vendor-id" data-price="$0.99"> with a specific class and structure. The RakuDoc instruction might then be:
To sample this marvellous libation M<order now by PayMeApp|PayMeApp; vendor-id; $0.99>
An HTML renderer would the convert this to, for example,
<p>To sample this marvellous libation
<button class="PayMeApp" data-token="vendor-id" data-price="$0.99">
order now by PayMeApp
</button>
</p>
RakuDoc is intended to be a markup language for text oriented documentation, which will be rendered into output formats such as HTML or epub. It is expected that there may be several modules that will render RakuDoc.
In order for a renderer to be compliant with the specification, it must: