BrowserREPL-button-tip-on BrowserREPL-button-tip-off

EditButtonTip 2026-08-10

RakuDoc Exposition

Additional notes and examples for the RakuDoc specification

VERSION    2.21.0§

Documenting code vs documenting software§

[This section elaborates the corresponding entry in the RakuDoc specification]

RakuDoc is a markup language with simple instructions for simple tasks and more complex structures to suit larger projects. There is a clear distinction between documentation intended to help maintain and develop the software, and the visual presentation of information needed by a newcomer to understand how to use software.

Consider the two ways in which documentation is used...

Case 1: You are writing internal documentation to aid software design§

    unit class Beginners;

    #| a variable to hold number of people
    has $.participants;

    #| data that is initially provided by default, but will be overwritten
    has $.new-participant = $=finish;

    ... # code

    =finish
    default data string for a new participant
Code

A RakuDoc compliant editor or Integrated Design Environment will pick up the text following #| and put it into a pop-up menu whenever you select (e.g. hover over) a use of $.participants.

The =finish statement marks the last piece of code. Everything after it is treated as a string and placed in the $=finish variable.

Case 2: You are writing external documentation to accompany some software§

Consider the following short description:

    =begin rakudoc
=TITLE Tutorial about Flavorizing
=SUBTITLE
A short tutorial on Flavorizing your quarks

=head Starting out

In the section you will learn about how to add flavors to quarks produced
by the
I<Imagiton>.
It goes without saying that these techniques should
B<NOT> be carried out
without a precocious child nearby; they will strain the imagination of
an ossified adult.

=head2 What is a flavour

It is well-known (see the
L<Wikipedia article|https://en.wikipedia.org/wiki/Flavour_(particle_physics)>
that quarks
N<a quark is a constituent of a hadron> come in six flavors, for example:
=item Up
=item Bottom
=item Charm

Z< Lots more text >
=end rakudoc
Code

To indicate that all of the markup above is not Raku code, it is enclosed in a block labelled rakudoc. This is an example of the delimited form of the rakudoc block (so named because it is specified between =begin and =end directives).

The =TITLE, =SUBTITLE, and =SYNOPSIS are semantic blocks containing standard information that can be searched by other tools. For all other purposes, they can be considered to the same as =head blocks.

A =head block begins a top-level heading. The =head2 is a second level heading. These are examples of the abbreviated form of RakuDoc blocks. Any non-empty text lines following a heading specifier are collectively treated as the text of the heading.

The =item components are abbreviated blocks containing text entries that constitute the items of a list. There is no need to start or stop a list explicitly; the renderer will place each consecutive =item in a single list. The first non-=item paragraph or block will end the list.

Within the text there are several examples of inline markup instructions, which have the form Upper Unicode character < > . In the example above, we used: I<...>, B<...>, N<...>, L<...>, and Z<...>. These are for Important, Basis, Note (a footnote), Link, and Zero (a comment) markup.

Text-oriented RakuDoc§

Block scope§

Sections§

[This section elaborates the corresponding entry in the RakuDoc specification]

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.

For example, suppose the following RakuDoc text was included in a source file

    =begin section :delta(v2.3.2-, "removed due to conflict with chancellor's role")
=head2 role Fool

This role is especially important in authoritarian kingdoms to remind kings of their humanity.

=end section
Code

which might render as:

2.3.2- removed due to conflict with chancellor's role

role Fool§

This role is especially important in authoritarian kingdoms to remind kings of their humanity.

If a user indicates to a renderer that they wish to view documentation valid in (for example) v3.1.1 then, because v3.1.1 is after v2.3.2, the section above – including the nested =head2 block and the following plain paragraph – would not be rendered.

If however, a user indicates they wish to view documentation for v2, the renderer would render the section above, including an indication the section will be removed after v2.3.2.

Counts and counters§

Each counter has a restart status§

[This section elaborates the corresponding entry in the RakuDoc specification]

A :restart is useful to restart a specific counter that would otherwise continue. For example, to cause a specially prefixed series of tables to reset after a heading:

1. Concept
    Table 1.1. List of requirements
    Table 1.2. List of resources
    Table 1.3. List of constraints

2. Implementation
    Table 2.1. Implementation schedule
    Table 2.2. Resource suppliers
    Table 2.3. Costings vs actual expenditure
Code

To manually reset the second series of tables, you could specify them like so:

=counter table1 :prefix<head1>

=numhead Concept
    =for numtable :caption< List of requirements >
    =for numtable :caption< List of resources >
    =for numtable :caption< List of constraints >

=numhead Implementation
    =counter table :restart
    =for numtable :caption< Implementation schedule >
    =for numtable :caption< Resource suppliers >
    =for numtable :caption< Costings vs actual expenditure >
Code

Note that, because a counter’s restart status persists until the next time it generates an enumeration, that :restart could be placed anywhere before the specific table whose numbering is to be restarted. For example, it could instead be specified immediately after the final table under the first heading:

=numhead Concept
    =for numtable :caption< List of requirements >
    =for numtable :caption< List of resources >
    =for numtable :caption< List of constraints >
    =counter table :restart

=numhead Implementation
    =for numtable :caption< Implementation schedule >
    =for numtable :caption< Resource suppliers >
    =for numtable :caption< Costings vs actual expenditure >
Code

The :!restart variant is useful to allow “list-like” numbered blocks, such as numitem or numdefn to preserve their enumeration sequences despite intervening blocks that would normally restart those sequences. For example, to allow an aside to be placed in the middle of a numbered list of items, without breaking the numbered sequence:

My nefarious plan is:

    1. Kidnap every being who knows the secret recipe for Nuka-Cola

    2. Demand a ransom of ONE MILLION DOLLARS

    (Note: need to work out how to get away cleanly from the exchange location)

    3. Profit!
Code

You could achieve this with something like:

=para My nefarious plan is:

=item Kidnap every being who knows the secret recipe for Nuka-Cola

=item Demand a ransom of ONE MILLION DOLLARS

=para (Note: need to work out how to get away cleanly from the exchange location)

=counter item :!restart
=item Profit!
Code

The :restart(INTEGER) form of the metaoption is useful for specialized numbering schemes, such as starting from zero instead of 1:

=counter head1 :restart(0)
Code

...or to enumerate blocks in a non-monotonically increasing sequence for some reason:

The values that can be ORed together in the bitset are:

=counter item :restart(1)
=numitem Read flag

=counter item :restart(2)
=numitem Write flag

=counter item :restart(4)
=numitem Execute flag

=counter item :restart(8)
=numitem Self-destruct flag (be careful with this one!)
Code

A note about using :counter and :restart-after/restart-except-after together§

It should be remembered, whereas a =config NAME directive changes the behaviour for the block named NAME, a =counter NAME directive changes the behaviour for the counter named NAME, not for the block named NAME.

Usually this distinction does not matter because, by default, blocks use the counter with their own name. But it can lead to seemingly non-obvious behaviours when blocks and counters with the same name are both configured at the same time.

For example, consider the following:

=config  table2 :counter< head2 >
=counter table2 :restart-after< table1 >
Code

After this configuration, one might expect table2 blocks to restart at 1 after each table1 block. But they do not. Instead, they restart after each head1 block.

This is because the table2 block is now using the counter named head2, and that counter (by default) is restarted after every head1 block. Or, to put it another way, it is true that the table2 counter will be restarted after every table1 block, but that will not matter because the table2 block is no longer using the table2 counter at all.

This kind of apparent violation of expectation usually indicates design confusion on the part of the document’s author. For example, the author seems to indicate that they want each table2 block to be numbered as if it were a head2 (Intent A), but they also want the numbering for table2 blocks to be restarted after every table1 block (Intent B).

However, restarting after every table1 block is not how the numbering of head2 blocks works, so if that did happen then each table2 block would not be being numbered as if it were a head2 block. So Intent B intrinsically contradicts Intent A.

Fortunately, this kind of logical contradiction does not blow up the RakuDoc parser (or the entire universe!) because =config and =counter configure different elements (i.e. blocks and counters respectively), even when those elements happen to share the same name.

Tables§

Visual description of simple tables§

Valid tables§

[This section elaborates the corresponding entry in the RakuDoc specification]

Following are examples of valid tables...

=begin 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
=end table
Code
=table
Constants 1
Variables 10
Subroutines 33
Everything else 57
Code
=for table
mouse | mice
horse | horses
elephant | elephants
Code
=table
Animal | Legs | Eats
=======================
Zebra + 4 + Cookies
Human + 2 + Pizza
Shark + 0 + Fish
Code
=table
Superhero | Secret |
| Identity | Superpower
==============|=================|================================
The Shoveller | Eddie Stevens | King Arthur's singing shovel
Code
=begin table

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
Code
=table
X | O |
---+---+---
| X | O
---+---+---
| | X
Code
=table
X O
===========
X O
===========
X
Code
=begin table

foo
bar

=end table
Code

Invalid tables§

Following are examples of invalid tables, and they should trigger an unhandled exception during parsing.

  • Using two or more different column separators in the same row is not allowed:
=begin table
r0c0  +  r0c1  |  r0c3
=end table
Code
  • Using both visual and whitespace column separators in the same table is not allowed:
=begin table
r0c0 +  r0c1 | r0c3
r1c0    r0c1   r0c3
=end table
Code
  • Specifying consecutive interior row separators without an intervening row is not allowed:
=begin table
r0c0 |  r0c1
============
============
r1c0 |  r1c1
=end table
Code

Unexpected tables§

Following are examples of valid tables that are probably intended to be two columns. However, the columns in these examples are not aligned well, so each will parse as a single-column table.

  • Unaligned columns with WS column separators:

    Notice the second row has the two words separated by only one WS character, while it takes at least two adjacent WS characters to define a column separation. This is a valid table but will be parsed as a single-column table.

=begin table
r0c0 r0c1
r1c0 r0c1
=end table
Code
  • Unaligned columns with visual column separators:

    Notice the second row has the two words separated by a visible character ('|') but the character is not recognized as a column separator because it doesn't have an adjacent WS character on both sides of it. Although this is a legal table, the result will not be what the user intended because the first row has two columns while the second row has only one column, and it will thus have an empty second column.

=begin table
r0c0 | r0c1
r1c0 |r0c1
=end table
Code

Procedural description of tables§

[This section elaborates the corresponding entry in the RakuDoc specification]

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).

Let’s see how it works...

The following RakuDoc specification:

=begin table :caption<Experimental data>
=row :header
=for cell :row-span(2)
Date
=for cell :column-span(3)
Samples
=for cell :row-span(2)
Mean
=row :header
=cell
I<Sample 1>
=cell
I<Sample 2>
=cell
I<Sample 3>
=row
=column
=cell 2023-03-08
=cell 2023-04-14
=cell 2023-06-23
=column
=cell 0.4
=cell 0.8
=cell 0.2
=column
=cell 0.1
=cell 0.6
=cell 0.9
=column
=cell 0.3
=cell 0.5
=cell 0.0
=column
=cell 0.26667
=cell 0.63333
=cell 0.36667
=row
=for cell :label
Mean:
=cell 0.46667
=cell 0.53333
=cell 0.26667
=cell 0.42222
=end table
code
produces the following table:
in table :!toc :caption<Experimental data>
=row :header
=for cell :row-span(2)
Date
=for cell :column-span(3)
Samples
=for cell :row-span(2)
Mean
=row :header
=cell
I<Sample 1>
=cell
I<Sample 2>
=cell
I<Sample 3>
=row
=column
=cell 2023-03-08
=cell 2023-04-14
=cell 2023-06-23
=column
=cell 0.4
=cell 0.8
=cell 0.2
=column
=cell 0.1
=cell 0.6
=cell 0.9
=column
=cell 0.3
=cell 0.5
=cell 0.0
=column
=cell 0.26667
=cell 0.63333
=cell 0.36667
=row
=for cell :label
Mean:
=cell 0.46667
=cell 0.53333
=cell 0.26667
=cell 0.42222
=end table

Let’s examine how that specification creates that layout, step by step.
Note that, in the following diagram, the various symbols have these meanings:
=begin code :lang<text>
┌───┐
│ │ : An empty table cell
└───┘
┌───┐
│ → │ : The empty cell at $POS; $DIR is currently "across"
└───┘
┌───┐
│ ↓ │ : The empty cell at $POS; $DIR is currently "down"
└───┘
┌───┐
│+++│ : The most recently filled cell
└───┘
┌───┐
│###│ : A previously filled cell
└───┘
Code

And now the step-by-step explanation:

    =begin table                   ┌───┬───┬───┬───┬───┬───┬┈┈
                                   │ → │   │   │   │   │   │
    (Create a new table grid       ├───┼───┼───┼───┼───┼───┼┈┈
     Default $POS is [0,0]         │   │   │   │   │   │   │
     Default $DIR is across)       ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =row :header                   ┌───┬───┬───┬───┬───┬───┬┈┈
                                   │ → │   │   │   │   │   │
    (Previous action was not =cell ├───┼───┼───┼───┼───┼───┼┈┈
     So set $DIR to "across"       │   │   │   │   │   │   │
     and don't change $POS)        ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊



    =for cell :row-span(2)         ┌───┬───┬───┬───┬───┬───┬┈┈
    Date                           │+++│ → │   │   │   │   │
                                   │+++│───┼───┼───┼───┼───┼┈┈
    (Fill in 1x2 cells             │+++│   │   │   │   │   │
     starting from $POS            ├───┼───┼───┼───┼───┼───┼┈┈
     Then move $POS to             │   │   │   │   │   │   │
     first empty cell              ├───┼───┼───┼───┼───┼───┼┈┈
     in $DIR direction)            │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊



    =for cell :column-span(3)      ┌───┬───────────┬───┬───┬┈┈
    Samples                        │###│+++++++++++│ → │   │
                                   │###├───┬───┬───┼───┼───┼┈┈
    (Fill in 3x1 cells             │###│   │   │   │   │   │
     starting from $POS            ├───┼───┼───┼───┼───┼───┼┈┈
     Then move $POS to             │   │   │   │   │   │   │
     first empty cell              ├───┼───┼───┼───┼───┼───┼┈┈
     in $DIR direction)            │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =for cell :row-span(2)         ┌───┬───────────┬───┬───┬┈┈
    Mean                           │###│###########│+++│ → │
                                   │###├───┬───┬───┤+++│───┼┈┈
    (Fill in 1x2 cells             │###│   │   │   │+++│   │
     starting from $POS            ├───┼───┼───┼───┼───┼───┼┈┈
     Then move $POS to             │   │   │   │   │   │   │
     first empty cell              ├───┼───┼───┼───┼───┼───┼┈┈
     in $DIR direction)            │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =row :header                   ┌───┬───────────┬───┬───┬┈┈
                                   │###│###########│###│   │
    (Find the next row at or       │###├───┬───┬───┤###│───┼┈┈
     below the current $POS        │###│ → │   │   │###│   │
     that has an empty cell        ├───┼───┼───┼───┼───┼───┼┈┈
     to the left of $POS, then     │   │   │   │   │   │   │
     move $POS to the leftmost     ├───┼───┼───┼───┼───┼───┼┈┈
     cell on that row, and set     │   │   │   │   │   │   │
     $DIR to "across")             ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =cell Sample 1                 ┌───┬───────────┬───┬───┬┈┈
                                   │###│###########│###│   │
    (Fill in 1x1 cell at $POS      │###├───┬───┬───┤###│───┼┈┈
     then move $POS to             │###│+++│ → │   │###│   │
     the first empty cell          ├───┼───┼───┼───┼───┼───┼┈┈
     in $DIR direction)            │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =cell Sample 2                 ┌───┬───────────┬───┬───┬┈┈
                                   │###│###########│###│   │
    (Fill in 1x1 cell at $POS      │###├───┬───┬───┤###│───┼┈┈
     then move $POS to             │###│###│+++│ → │###│   │
     the first empty cell          ├───┼───┼───┼───┼───┼───┼┈┈
     in $DIR direction)            │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =cell Sample 3                 ┌───┬───────────┬───┬───┬┈┈
                                   │###│###########│###│   │
    (Fill in 1x1 cell at $POS      │###├───┬───┬───┤###│───┼┈┈
     then move $POS to             │###│###│###│+++│###│ → │
     the first empty cell          ├───┼───┼───┼───┼───┼───┼┈┈
     in $DIR direction)            │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =row                           ┌───┬───────────┬───┬───┬┈┈
                                   │###│###########│###│   │
    (Move $POS down to the         │###├───┬───┬───┤###│───┼┈┈
     next row with an empty cell   │###│###│###│###│###│   │
     that's to the left of $POS    ├───┼───┼───┼───┼───┼───┼┈┈
     and to left-most empty cell   │ → │   │   │   │   │   │
     on that row)                  ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =column                        ┌───┬───────────┬───┬───┬┈┈
                                   │###│###########│###│   │
    (Previous action was not a     │###├───┬───┬───┤###│───┼┈┈
     =cell so set $DIR to "down",  │###│###│###│###│###│   │
     with no other effect)         ├───┼───┼───┼───┼───┼───┼┈┈
                                   │ ↓ │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =cell 2023-03-08               ┌───┬───────────┬───┬───┬┈┈
    =cell 2023-04-14               │###│###########│###│   │
    =cell 2023-06-23               │###├───┬───┬───┤###│───┼┈┈
                                   │###│###│###│###│###│   │
    (Each =cell block              ├───┼───┼───┼───┼───┼───┼┈┈
     fills in a 1x1 cell           │+++│   │   │   │   │   │
     at $POS, then moves           ├───┼───┼───┼───┼───┼───┼┈┈
     $POS to the first empty       │+++│   │   │   │   │   │
     cell in $DIR direction)       ├───┼───┼───┼───┼───┼───┼┈┈
                                   │+++│   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │ ↓ │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊



    =column                        ┌───┬───────────┬───┬───┬┈┈
                                   │###│###########│###│   │
    (Previous action was           │###├───┬───┬───┤###│───┼┈┈
     a =cell, so move $POS         │###│###│###│###│###│   │
     to the uppermost empty        ├───┼───┼───┼───┼───┼───┼┈┈
     cell in the first non-full    │###│ ↓ │   │   │   │   │
     column to the right,          ├───┼───┼───┼───┼───┼───┼┈┈
     and set $DIR to "down")       │###│   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │###│   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =cell 0.4                      ┌───┬───────────┬───┬───┬┈┈
    =cell 0.8                      │###│###########│###│   │
    =cell 0.2                      │###├───┬───┬───┤###│───┼┈┈
                                   │###│###│###│###│###│   │
    (Each =cell block              ├───┼───┼───┼───┼───┼───┼┈┈
     fills in a 1x1 cell           │###│+++│   │   │   │   │
     at $POS, then moves           ├───┼───┼───┼───┼───┼───┼┈┈
     $POS to the first empty       │###│+++│   │   │   │   │
     cell in $DIR direction)       ├───┼───┼───┼───┼───┼───┼┈┈
                                   │###│+++│   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │   │ ↓ │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊



    =column                        ┌───┬───────────┬───┬───┬┈┈
    =cell 0.1                      │###│###########│###│   │
    =cell 0.6                      │###├───┬───┬───┤###│───┼┈┈
    =cell 0.9                      │###│###│###│###│###│   │
    =column                        ├───┼───┼───┼───┼───┼───┼┈┈
    =cell 0.3                      │###│###│+++│+++│+++│   │
    =cell 0.5                      ├───┼───┼───┼───┼───┼───┼┈┈
    =cell 0.0                      │###│###│+++│+++│+++│   │
    =column                        ├───┼───┼───┼───┼───┼───┼┈┈
    =cell 0.26667                  │###│###│+++│+++│+++│   │
    =cell 0.63333                  ├───┼───┼───┼───┼───┼───┼┈┈
    =cell 0.36667                  │   │   │   │   │ ↓ │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
    (Rinse and repeat)             ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =row                           ┌───┬───────────┬───┬───┬┈┈
                                   │###│###########│###│   │
    ($POS row is entirely empty    │###├───┬───┬───┤###│───┼┈┈
     so it's the first row with    │###│###│###│###│###│   │
     an empty cell to the left     ├───┼───┼───┼───┼───┼───┼┈┈
     of $POS, so stay on current   │###│###│###│###│###│   │
     row and move $POS to the      ├───┼───┼───┼───┼───┼───┼┈┈
     left-most empty cell in row;  │###│###│###│###│###│   │
     change $DIR to "across")      ├───┼───┼───┼───┼───┼───┼┈┈
                                   │###│###│###│###│###│   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   │ → │   │   │   │   │   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =for cell :label               ┌───┬───────────┬───┬───┬┈┈
    Mean:                          │###│###########│###│   │
    =cell 0.46667                  │###├───┬───┬───┤###│───┼┈┈
    =cell 0.53333                  │###│###│###│###│###│   │
    =cell 0.26667                  ├───┼───┼───┼───┼───┼───┼┈┈
    =cell 0.42222                  │###│###│###│###│###│   │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
    (Fill in 1x1 cells,            │###│###│###│###│###│   │
     moving $POS each time         ├───┼───┼───┼───┼───┼───┼┈┈
     in the direction              │###│###│###│###│###│   │
     specified by $DIR)            ├───┼───┼───┼───┼───┼───┼┈┈
                                   │+++│+++│+++│+++│+++│ → │
                                   ├───┼───┼───┼───┼───┼───┼┈┈
                                   ┊   ┊   ┊   ┊   ┊   ┊   ┊


    =end table                     ┌───┬───────────┬───┐
                                   │###│###########│###│
    (Terminate grid-filling        │###├───┬───┬───┤###│
     then trim the table to        │###│###│###│###│###│
     the bounding box around       ├───┼───┼───┼───┼───┤
     all filled cells)             │###│###│###│###│###│
                                   ├───┼───┼───┼───┼───┤
                                   │###│###│###│###│###│
                                   ├───┼───┼───┼───┼───┤
                                   │###│###│###│###│###│
                                   ├───┼───┼───┼───┼───┤
                                   │###│###│###│###│###│
                                   └───┴───┴───┴───┴───┘
Code

Formulae§

[This section elaborates the corresponding entry in the RakuDoc specification]

Implementors of renderers are not required to render the instructions (e.g. the LaTeX code) in a formula; 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.

For example, the following two formulae:

We will use the identity: F<\sum \frac{1}{n^{2}} = \frac{\pi^{2}}{6}>

...where the value of pi can be inferred from Euler’s Identity:

=formula e^{i\pi}+1=0
Code

...may either be rendered “accurately”:

We will use the identity:

...where the value of pi can be inferred from Euler’s Identity:

... or may be converted to a suitable Unicode approximation:

We will use the identity: ∑ 1/n² = 𝜋²/6

...where the value of pi can be inferred from Euler’s Identity:

eiπ + 1 = 0

... or may even left as raw LaTeX (perhaps with some kind of visual marker indicating that it is unprocessed):

We will use the identity: \sum \frac{1}{n^{2}} = \frac{\pi^{2}}{6}

... where the value of pi can be inferred from Euler’s Identity:

e^{i\pi}+1=0

Commenting vs Ignoring§

[This section elaborates the corresponding entry in the RakuDoc specification]

RakuDoc provides several constructs that mark content as not contributing to the rendered form of the surrounding document. The following table summarizes their similarities, differences, and intended uses.

Element

=comment block=ignore block=finish directive=data block

Purpose

To insert documentation, explanations, to-do reminders, and other meaningful metacommentary

To hide (possibly invalid) RakuDoc source or ambient code from the parser

To hide the remainder of the document/file from the parser

To provide in-file data to ambient Raku code

Intended use

To allow authors to record and communicate information about a RakuDoc document

To facilitate incremental development and debugging of RakuDoc (and Raku) documents

To specify that the remainder of the document contains no RakuDoc or ambient components

To specify large blocks of text that a Raku program can access via its $=data object

Closing delimiter

Delimited form is terminated by the first =end comment encounteredDelimited form is terminated by the matching unnested =end ignore

Effect of directive is terminated by end-of-file

Delimited form is terminated by the first =end data encountered

Nesting

Does not allow nested =begin comment...=end comment blocksAllows nested =begin ignore...=end ignore blocks; does not allow single unbalanced =begin ignore or =end ignore delimitersAllows nested =finish directives (although they have no meaning nor any additional effect)Does not allow nested =begin data...=end data blocks
Table

In summary:

  • A =comment block cannot be nested, and is used to include (unrenderable) information about the document.
  • An =ignore block can be nested, and is used to hide (possibly invalid) parts of a document from the parser.
  • A =finish directive is equivalent to a =begin ignore with an implicit matching =end ignore at the end of the document, and also provides its content to ambient code via the $=finish object.
  • A =data block cannot be nested, and is used to provide its content to ambient code via the $=data object.

Citations§

Citation blocks§

[This section elaborates the corresponding entry in the RakuDoc specification]

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.

For example:

=comment  Citation source data specified in CSL-Raku
=begin citation
    {
        note            => "Fields can be specified as key => value pairs"
        id              => "rakudoc-evo-chapter",
        type            => "chapter",
        title           => "The Evolution of RakuDoc",
        author          => [ { family => "Hainsworth", given => "Richard"   },
                             { family => "Mattijsen",  given => "Elizabeth" },
                             { family => "Conway",     given => "Damian"    },
                           ],
        editor          => [ { family => "Smith", given => "Jane" } ],
        container-title => "Modern Markup Systems",
        publisher       => "Butterfly Press",
        publisher-place => "Amsterdam",
        page            => "42-65",
        issued          => { date-parts => [[2024, 5, 12]] },
        ISBN            => "978-3-16-148410-0",
    },
    {
                   :note< Fields can also be specified as adverbial pairs >
                     :id< json-vs-xml-meta >
                   :type< article-journal >
                  :title< A Performance Analysis of JSON vs XML in Academic Metadata >
                 :author[ { family => "Doe", given => "John", ORCID => "0000-0001-2345-6789" } ]
        :container-title< Journal of Digital Humanities >
                 :volume( 12 )
                  :issue( 3 )
                   :page< 101-115 >
                    :DO 10.1000/jdh.2024.03.01 
                 :issued{ date-parts => [[2024]] }
    }
=end citation
Code
=comment  This citation data is 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
Code
=comment  This citation data is CSL-YAML
=for citation
    - id:    starlight2024
      type:  article-journal
      title: "Asynchronous Concurrency: A Journey Through Raku Supplies"
      author:
          - family: Starlight
            given:  Orion
      container-title: "The Reactive Programmer's Quarterly"
      issued:
          date-parts: [[2024, 11]]
      volume: 12
      issue:  4
      page:   45-60
Code
=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}
           }
Code
=comment  This citation is in BibTeXML format
=begin citation
    <bibtex:file xmlns:bibtex="http://bibtexml.sf.net/">
      <bibtex:entry id="mercurio2025">
        <bibtex:book>
          <bibtex:author>Silvia Mercurio</bibtex:author>
          <bibtex:title>The Morphological Beauty of Raku Grammars</bibtex:title>
          <bibtex:publisher>Butterfly Press</bibtex:publisher>
          <bibtex:year>2025</bibtex:year>
          <bibtex:month>March</bibtex:month>
          <bibtex:isbn>978-1-2345-6789-0</bibtex:isbn>
        </bibtex:book>
      </bibtex:entry>
    </bibtex:file>
=end citation
Code
=comment  This is 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
Code
=comment  This is MODS
=begin citation
    <mods xmlns="http://www.loc.gov/mods/v3" ID="Vasiliev26">
        <titleInfo>
            <title>Functional Purity in a Multi-Paradigm World</title>
        </titleInfo>
        <name type="personal">
            <namePart type="given">Elena</namePart>
            <namePart type="family">Vasiliev</namePart>
            <role>
                <roleTerm type="text">author</roleTerm>
            </role>
        </name>
        <originInfo>
            <publisher>Deep Space Coding Collective</publisher>
            <dateIssued>2026</dateIssued>
        </originInfo>
        <typeOfResource>text</typeOfResource>
        <genre>technical report</genre>
    </mods>
=end citation
Code
=comment This citation is in PubMed/Medline NBIB format
=citation
    PMID- 39876543
    STAT- Publisher
    DA  - 2025/08/15
    TI  - The Semantic Elegance of Raku Grammars.
    BTI - The Semantic Elegance of Raku Grammars
    AU  - Mercurio S
    LA  - eng
    PT  - Book
    PB  - Butterfly Press
    SN  - 978-1-2345-9876-0
Code
=comment This citation is in PubMed/Medline XML format
=citation
   <PubmedArticleSet>
     <PubmedArticle>
       <MedlineCitation Status="Publisher">
         <PMID Version="1">98765432</PMID>
         <Article PubModel="Print">
           <Journal>
             <ISSN IssnType="Print">1234-567X</ISSN>
             <JournalIssue>
               <Volume>14</Volume>
               <Issue>1</Issue>
               <PubDate>
                 <Year>2026</Year>
                 <Month>Jan</Month>
                 <Day>30</Day>
               </PubDate>
             </JournalIssue>
             <Title>International Journal of Perl and Raku</Title>
           </Journal>
           <ArticleTitle>Concurrent Processing in RakuDoc: A Performance Analysis.</ArticleTitle>
           <Pagination>
             <MedlinePgn>102-115</MedlinePgn>
           </Pagination>
           <AuthorList CompleteYN="Y">
             <Author ValidYN="Y">
               <LastName>Generic</LastName>
               <ForeName>A</ForeName>
             </Author>
             <Author ValidYN="Y">
               <LastName>Researcher</LastName>
               <ForeName>B</ForeName>
             </Author>
           </AuthorList>
           <Language>eng</Language>
           <PublicationTypeList>
             <PublicationType>Journal Article</PublicationType>
           </PublicationTypeList>
         </Article>
       </MedlineCitation>
     </PubmedArticle>
   </PubmedArticleSet>
Code

Implied code and indentation§

[This section elaborates the corresponding entry in the RakuDoc specification]

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).

Care must be taken with abbreviated and extended blocks where the block ends at the next blank line.

=begin rakudoc
This is an ordinary paragraph

While this is not an ordinary paragraph;
it is a code block.

=head Mumble mumble

Surprisingly, this is a code block
(with fancy indentation too)

This is just an ordinary paragraph.

=end rakudoc
Code

The Surprisingly... paragraph is a code block because each block only sets the virtual margin within that block, and the =head block terminates at the blank line immediately after the =head line, and before the apparent code block begins. At which point, the virtual margin reverts to the previous virtual margin set by the surrounding =begin rakudoc...=end rakudoc block.

The current virtual margin terminates at the end of the block whose opener set it, and not at the start of the next block that sets a virtual margin. In other words, the virtual margin is a local feature of each individual block, not a collective feature of the entire document, and therefore a block’s virtual margin always ends at the end of the block itself (and reverts at that point to the virtual margin of the surrounding block, if any).

Which means:

=begin rakudoc
This is an ordinary paragraph

While this is not
This is a code block

=head Mumble mumble

This IS also a code block
because the preceding =head's virtual margin ended
at the end of the preceding =head block, which was
at the preceding blank line. So the virtual margin for
this implicit block is the virtual margin of the surrounding
C<=begin rakudoc ... =end rakudoc> block. This block is indented
relative to that
C<=rakudoc block>'s virtual margin, so it's
a code block.

This is a para block
(with fancy indentation too, because the indentation of first line alone
determines whether an implicit block is a
C<=para> or a C<=code> block,
and all subsequent lines, regardless of their indentation, become part
of that block ... until the end of the implicit block, which occurs at
the next blank line or the next explicit RakuDoc block or directive.)

=end rakudoc
Code

And if, instead, you wanted the block straight after the =head to be an implicit paragraph block (i.e. not an implicit code block), you'd write it:

=begin rakudoc
This is an ordinary paragraph

    While this is not
    This is a code block

    =begin section

    =head Mumble mumble

    This is a para block, NOT a code block
       because the virtual margin for this implicit block
       is the virtual margin of the surrounding
       =begin section ... =end section block.
       The first line of this implicit block is NOT indented
       relative to that =section block's virtual margin,
       so it's a para block.

    =end section

This is a para block too...because its first line is not indented
   relative to the virtual margin of the current =begin rakudoc ... =end rakudoc block.

=end rakudoc
Code

Metadata§

Instructions with side effects§

Display and metadata§

[This section elaborates the corresponding entry in the RakuDoc specification]

Markup codes may contain only display text or may contain a mix of display and meta information. This section clarifies these groups.

If a markup code may contain both display text and meta information, the character | is used to delimit the two components. In order to use | inside a display text, it must be escaped (\|) or specified as an entity (E<VERTICAL LINE>).

Display only codes§

The following codes may only contain display text:

B< DISPLAY-TEXT  >
C< DISPLAY-TEXT  >
H< DISPLAY-TEXT  >
I< DISPLAY-TEXT  >
J< DISPLAY-TEXT  >
K< DISPLAY-TEXT  >
N< DISPLAY-TEXT  >
O< DISPLAY-TEXT  >
R< DISPLAY-TEXT  >
S< DISPLAY-TEXT  >
T< DISPLAY-TEXT  >
U< DISPLAY-TEXT  >
V< DISPLAY-TEXT  >
W< DISPLAY-TEXT  >
Code

Metadata and (optional) display text§

The following codes may (and, in some cases, must) contain both a display text and some kind of metadata.

A< DISPLAY-TEXT   | METADATA=ALIAS-NAME            >
D< DISPLAY-TEXT   | METADATA=SYNONYMS              >
Δ< DISPLAY-TEXT   | METADATA=VERSION-ETC           >
E< DISPLAY-TEXT   | METADATA=HTML/UNICODE-ENTITIES >
F< DISPLAY-TEXT   | METADATA=LATEX-FORM            >
L< DISPLAY-TEXT   | METADATA=TARGET-URI            >
M< DISPLAY-TEXT   | METADATA=WHATEVER              >
P< DISPLAY-TEXT   | METADATA=REPLACEMENT-URI       >
X< DISPLAY-TEXT   | METADATA=INDEX-ENTRY           >
Code

The markup codes A, E, F, L, and P may be specified without a display text, in which case the specification permits the renderer to provide an automatic rendering if the metadata component fails to produce a renderable result. If an explicit display text is provided (i.e. to the left of a |), that text overrides the default alternate rendering.

Metadata only§

Q< METADATA=CITATION REFERENCES >
Z< METADATA=COMMENT >
Code

The quotation code Q<> has a semicolon list akin to a metadata list, which is replaced in the rendered text with properly styled citations.

The comment code Z<> is intended not to have a display text so the contents of a comment can be considered as pure metadata.

Summary of RakuDoc syntax§

Directive

Specifies

=alias

Define a RakuDoc macro

=begin

Start of an explicitly terminated block

=column

Start a new column in a procedural table

=config

Block-scoped modifications to a block or markup instruction

=counter

Block-scoped reconfiguration of a counter

=document

Change the default for document level options

=endExplicit termination of a =begin block
=finish

No RakuDoc or ambient blocks after this point

=for

Start of an implicitly (blank-line) terminated block

=place

Place into the document some text loaded from, or generated by, a URI

=row

Start a new row in a procedural table

Directives

Block typename

Specifies

=cell

Contents of a table cell, only valid in a procedural table context

=citation

Specify a list of citation datasets in one of several standard citation markup languages

=code

Verbatim pre-formatted sample source code

=input

Pre-formatted sample input

=output

Pre-formatted sample output

=comment

Content to be ignored by all renderers (unless it can be passed through as a native comment in the output format)

=head

First-level heading

=headN

Nth-level heading

=defn

Definition of a term

=ignore

Ignore completely all text in the block scope

=item

First-level list item

=itemN

Nth-level list item

=nested

Nest block contents within the current context

=para

Ordinary paragraph

=rakudoc

No "ambient" blocks inside

=section

Defines a lexical scope within the document

=podLegacy equivalent to =rakudoc (use is deprecated)
=table

Visual or procedural table

=formula

Render content as a LaTeX formula

=data

Raku data section

=NAMEDSemantic blocks (=SYNOPSIS, =TITLE, etc.)
=CustomName

User-defined block (must have mixed-case name)

Blocks

Metadata option

Blocks applied to

Description

:allow=code

Allow specific mark-up codes in otherwise verbatim blocks

=input
=output
=table
:id

all blocks

Specify the anchor for a block

:toc=para

Include content or caption in the Table of Contents

=nested
=code
=input
=output
=table
=formula
=place
:!toc

SEMANTIC block

Do not include content or caption in the Table of Contents

Custom block

=headN
=numheadN
:headlevel

All blocks

Override the automatic level of the block type within a Table of Contents

(but typically for para-ish blocks)

:caption

SEMANTIC block

Caption to be associated with a block in the Table of Contents

Custom block

=nested
=code
=input
=output
=table
=formula
=place
:hidden

SEMANTIC block

Remove block from rendered text and from Table of Contents (use P<semantic: ...> to inject elsewhere)
:header=table (procedural semantics only)

Specify rows, columns, or cells to be rendered as column headers in a table

=cell
=row directive
=column directive
:label=table (procedural semantics only)

Specify rows, columns, or cells to be rendered as labels (row headers) in a table

=cell
=row directive
=column directive
:align<ALIGNMENTS>=table (procedural semantics only)

Specify how cell contents are to be vertically and/or horizontally aligned

=cell
=row directive
=column directive
:row-span(HEIGHT)=cell

Specify how many rows a single cell should span in a procedural table

:column-span(WIDTH)=cell

Specify how many columns a single cell should span in a procedural table

:span(WIDTH, HEIGHT)=cellA shorthand for :column-span(WIDTH) :row-span(HEIGHT)
:delta=table

Developer information associated with a block

=formula
=nested
=code
=input
=output
=headN
=numheadN

SEMANTIC block

Custom block

:bullet<CHAR>=itemReplace the default bullet with one or more characters, or entities specified with E< >
=itemN
Metadata options

Markup instruction

Specifies

A<...|...>Alias to be replaced by contents of the specified =alias directive (A<alt text | aliasname>)
B<...>

Basis/focus of sentence (typically rendered bold)

C<...>

Code (typically rendered fixed-width)

D<...>Definition inline (D<term being defined | synonym1; synonym2>)
Δ<...|...;...>Delta note (Δ<visible text | version; notification text>)
E<...|...;...>Entity (HTML or Unicode) description (E<entity1; entity2; multi,glyph;...>)
F<...|...>Inline content for a formula (F<alt text | LaTeX notation>)
G<...>(This markup code is not yet defined, but is reserved for future use)
H<...>

High text (typically rendered superscript)

I<...>

Important content (typically rendered in italics)

J<...>

Junior text (typically rendered subscript)

K<...>

Keyboard input (typically rendered fixed-width)

L<...|...>Link (L<display text | destination URI>)
M<...|..,..;...>Markup extra (M<display text | functionality; param,sub-type;...>)
N<...>Note (not rendered inline, but made visible in some way: footnote, sidenote, pop-up, etc.))
O<...>

Struck-out content

P<...|...>Placement link (P< alt text | source URI >)
Q<...>Marker citing one or more bibliographic datasets via identifiers with possible text annotations (Q< ID1 ; ID2, text; etc. >)
R<...>

Replaceable component or metasyntax

S<...>

Space characters to be preserved

T<...>

Terminal output (typically rendered fixed-width)

U<...>

Unusual content (typically rendered with underlining)

V<...>

Verbatim (internal markup instructions ignored)

W<...>

Weighty content (typically rendered with small caps)

X<...|..,..;...>Index entry (X< display text | entry,subentry ; ...>)
Y<...>(This markup code is not yet defined, but is reserved for future use)
Z<...>

Zero-width comment (contents never rendered)

Markup instructions

Field

Meaning

:lc or informal shortcut
%A

enumeration value as an ASCII capital alpha

%a
%B or %বenumeration value in Bengali numerals (if supported)%b (no effect)
%Ccaption (if any)%c
%D

block’s data

%d
%H or %हenumeration value in Hindu numerals (if supported)%h (no effect)
%J or %業enumeration value in Japanese numerals (if supported)%j or %並
%N

enumeration value as a cardinal number

%n
%Renumeration value in Roman numerals (if supported)%r
%Tthe name of the block’s num-less type in Titlecase%t
%Z or %大enumeration value in Chinese numerals (if supported)%z or %小
%%a literal % (only required if literal % is followed by a letter)
%:a literal : (only required if literal : is followed by a letter)
:form components

Field option

Meaning

:orduse ordinal instead of cardinal number (if available in requested language)
:lcuse lowercase or informal notation (if any)
:ucuse uppercase or formal notation (if any)
:tcuse titlecase (uppercase first character only)
:tclc

use titlecase for first character, lowercase for the rest

:sc

use titlecase for first character of each sentence, preserve ALLCAPS words, lowercase for the rest

:pc

use titlecase for first character of each word, preserve ALLCAPS words, lowercase for the rest

:lang<xx>use numbering and/or ordinal system for ISO 639-1 language xx (if supported)
Options for form fields

Licence§

Artistic-2.0

Credits§

  • Damian Conway (@thoughtstream)
  • Richard Hainsworth (@finanalyst)
  • Elizabeth Mattijen (@lizmat)
  • Aliaksandr Zahatski (@zag)