Podlite - a lightweight markup language







  • Notification blocks, :notify attribute for =nested blocks,

  • :folded attribute,

  • :folded-levels for =toc block,

  • Refactor Named custom blocks and markup custom codes, M<>,

  • embedding binary data into documents, =data, :filename, :encoding,

  • :mime-type attribute for =include and =data blocks,

  • introduce data: schema for use in =picture and =table,

  • render tables from CSV files, =table,

  • new markdown mode for parser,

  • M<> - extends inline markup features,

  • add :id, :caption, :lang attributes,

  • task lists, =item and :checked attribute,

  • intro Selectors,

  • table of contents, =toc,

  • include block, =include,

  • inserting pictures, =picture, P<>,

  • mathematical formulas, =formula, F<>,

  • Markdown support, =markdown,

  • mistake marking, O<>,

  • text positioning, J<>, H<>,

  • Emoji, E<>,

  • contextual backlinks, W<>,

  • advanced table format, =row,=cell blocks, :header, :rowspan, :colspan attributes.


  • Contextual aliases,

  • =finish,

  • markers in comments,

  • :margin attribute,

  • =encoding directive,

  • P<toc:> due to =toc block,

  • P<man:>, P<doc:> due to =include block,

  • P<> - placement links,

  • Declarator block,

  • :formatted attribute,

  • :like attribute.


Podlite is an easy-to-use markup language with a simple, consistent underlying document object model. Podlite can be used for writing language documentation, for documenting programs and modules, as well as for other types of document composition.

The Podlite is a purely descriptive mark-up notation, with no presentational components.

General syntactic structure

Podlite documents are specified using directives, which are used to declare configuration information and to delimit blocks of textual content.

Every directive starts either with an equals sign (=) followed immediately by an identifier.

An identifier composed of an alphabetical character followed by any combination of alphanumeric characters. Alphabetic and numeric definitions encompass relevant Unicode characters. The underscore is consistently treated as alphabetic. Additionally, an identifier can include isolated apostrophes or hyphens, given that the subsequent character is alphabetic.

Directives that start with = can be indented like the code they interleave, but their initial = must still be the first non-whitespace character on their line.

An indented Podlite block is considered to have a virtual left margin, determined by the indentation of its opening delimiter.

In other words, if a directive is indented from the left margin, the column at which the first character of its opening delimiter appears is thereafter considered the first column of the entire block's contents.

The virtual margin treats leading tabs as aligning to tabstops spaced every ($?TABSTOP // 8) characters.

Podlite blocks

The content of a document is specified within one or more blocks. Every Podlite block may be declared in any of three forms: delimited style, paragraph style, or abbreviated style. All of these forms are equivalent.

Anything in a document that is neither a Podlite directive nor contained within a Podlite block is treated as "ambient" material. Typically this would be the source code of the program that the Podlite is documenting. Podlite parsers still parse this text into the internal representation of the file, representing it as a "ambient" block. Renderers will usually ignore such blocks. This is the default mode of the parser.

All directives have a defined terminator and the Podlite parser always reverts to "ambient" at the end of each Podlite directive or block.

The =pod block puts the parser in "pod" mode, treating all text between blocks as implicit paragraph Podlite, even if it's not inside an explicit block.

To keep the parser in "pod" mode, enclose the desired Podlite region in a =pod block:

  =begin pod

  =head1 A heading

  This is Podlite too. Specifically, this is a simple C<para> block

      $this = pod('also');  # Specifically, a code block

  =end pod

The contents of files with the extensions .podlite and .pod6 are implicitly wrapped in a =pod directive.

For .md and .markdown files, the parser operates in "Markdown" mode for the entire file, treating all text as markdown even if it is not inside an =markdown block.

Any other file extension puts the parser in default mode. The =include block has a mechanism to override this behavior by using the :mime-type attribute for the included files.

Delimited blocks

Delimited blocks are bounded by =begin and =end markers, both of which are followed by a valid Podlite identifier, which is the typename of the block. Typenames that are entirely lowercase (for example: =begin head1) or entirely uppercase (for example: =begin SYNOPSIS) are reserved.

After the typename, the rest of the =begin marker line is treated as configuration information for the block. This information is used in different ways by different types of blocks, but is always specified using any of:

Configuration syntax options
Value is... Specify with... Or with... Or with...
Boolean (true) :key :key(1) key => 1
Boolean (false) :!key :key(0) key => 0
String :key<str> :key('str') key => 'str'
List :key<1 2 3> :key[1,2,3] key => [1,2,3]
Hash :key{a=>1, b=>2} key => {a=>1, b=>2}

All option keys and values must, of course, be constants since Podlite is a specification language, not a programming language. Specifically, option values cannot be closures.

The configuration section may be extended over subsequent lines by starting those lines with an = in the first (virtual) column followed by a whitespace character.

The lines following the opening delimiter and configuration are the data or contents of the block, which continue until the block's matching =end marker line. For most block types, these contents may be indented if you wish, without them being treated as code blocks. Indented text is only treated as code within =pod, =nested, =item, =code, and semantic blocks.

The general syntax is:

     =                  R<OPTIONAL EXTRA CONFIG INFO>
     =end R<BLOCK_TYPE>

For example:

     =begin table  :caption<Table of Contents>
         Constants           1

         Variables           10

         Subroutines         33

         Everything else     57
     =end table

        =begin Name  :required
        =            :width(50)
        The applicant's full name
        =end Name

        =begin Contact  :optional
            The applicant's contact details
        =end Contact

Note that no blank lines are required around the directives; blank lines within the contents are always treated as part of the contents. This is a universal feature of Podlite.

Note also that in the following specifications, a "blank line" is a line that is either empty or that contains only whitespace characters. That is, a blank line matches the following pattern: /^^ \h* $$/. Podlite uses blank lines as delimiters, rather than empty lines, to minimize unpleasant surprises when stray spaces or tabs mysteriously turn up in hitherto empty lines.

Paragraph blocks

Paragraph blocks are introduced by a =for marker and terminated by the next Podlite directive or the first blank line (which is not considered to be part of the block's contents). The =for marker is followed by the name of the block and optional configuration information. The general syntax is:

     =                R<OPTIONAL EXTRA CONFIG INFO>

For example:

     =for table  :caption<Table of Contents>
         Constants           1
         Variables           10
         Subroutines         33
         Everything else     57

        =for Name  :required
        =          :width(50)
        The applicant's full name

     =for Contact  :optional
        The applicant's contact details

Abbreviated blocks

Abbreviated blocks are introduced by an '=' sign in the first column, which is followed immediately by the typename of the block. The rest of the line is treated as block data, rather than as configuration. The content terminates at the next Podlite directive or the first blank line (which is not part of the block data). The general syntax is:


For example:

         Constants           1
         Variables           10
         Subroutines         33
         Everything else     57

        =Name  The applicant's full name
     =Contact  The applicant's contact details

Note that abbreviated blocks cannot specify configuration information. If configuration is required, use a =for or =begin/=end instead.

Block equivalence

The underlying documentation model treats all block specifications (delimited, paragraph, and abbreviated) the same way. It is possible to choose the form is most convenient for a particular documentation task. In the descriptions that follow, the abbreviated form will generally be used, but should be read as standing for all three forms equally.

For example, although #Headings shows only:

  =head1 Top Level Heading

this automatically implies that you could also write that block as:

  =for head1
  Top Level Heading


  =begin head1
  Top Level Heading
  =end head1

Standard configuration options

Podlite predefines a small number of standard configuration options that can be applied uniformly to any built-in block type. These include:

This option specifies that the block may be given an associated description or title using the :caption option.
Usually, this description uses for build table of contents.
This option allows to explicitly define identificator for blocks and use those IDs for linking, rather than relying on it content (see #Links).
This option specifies that the block is to be nested within its current context. For example, nesting might be applied to block quotes, to textual examples, or to commentaries. In addition the =code, =item, =input, and =output blocks all have implicit nesting.
Nesting of blocks is usually rendered by adding extra indentation to the block contents, but may also be indicated in other ways: by boxing the contents, by changing the font or size of the nested text, or even by folding the text (so long as a visible placeholder is provided).
Occasionally it is desirable to nest content by more than one level:
    =begin para :nested
    =begin para :nested
    =begin para :nested
    "We're going deep, deep, I<deep> undercover!"
    =end para
    =end para
    =end para
This can be simplified by giving the :nested option a positive integer value:
    =begin para :nested(3)
    "We're going deep, deep, I<deep> undercover!"
    =end para
You can also give the option a value of zero, to defeat any implicit nesting that might normally be applied to a paragraph. For example, to specify a block of code that should appear without its usual nesting:
    =comment Don't nest this code block in the usual way...
    =begin code :nested(0)

                 1         2         3         4         5         6
          line        instruction                comments
         number           code

    =end code
Note that :!nested could also be used for this purpose:
    =Z<>begin code :!nested
This option specifies that the block is to be numbered. The most common use of this option is to create numbered headings and ordered lists, but it can be applied to any block.
The numbering conventions for headings and lists are specified in those sections, but it is up to individual renderers to decide how to display any numbering associated with other types of blocks.
Note that numbering is never explicit; it is always implied by context.
This attribute indicates that a checkbox should be added to that block. It possible to apply a :checked attributes to any block. The most common use of this option is to create task lists.
For unchecked checkbox the :!checked is used.
The task list item marker (checkbox) is added to the output. In an HTML output, this would be represented as an <input type="checkbox"> element.
The specification does not define how these checkboxes are interacted with. Implementors are free to choose whether they render them as disabled, unchangeable elements, or handle dynamic interactions like checking and unchecking in the final rendered document.
This option specifies whether the block is foldable and, if specified, whether it should be collapsed or expanded by default. This feature is useful in managing the length of documents and focusing the reader's attention on certain sections as needed.
A :!folded or :folded(0) expands the callout by default, and a :folded or :folded(1) collapses it instead.
  =for table :folded :caption('Culinary Techniques for Sustainability')
    Sous-vide   Low energy consumption
    ----------  -------------------------
    Steaming    Preserves nutrients
    Baking      Efficient for batch cooking
When applied to a block element, such as a heading, the attribute typically affects all headings with lower-level content, creating a hierarchical folding effect.
For example:
  =for head2 :folded
  Green Energy Overview 
This option used to provide information about the programming language used in a specific code block. This helps in ensuring that the code is displayed and interpreted correctly by rendering engines or syntax highlighters.
Here's a table that lists a few programming languages along with their possible values for the :lang attribute:
Matching languages and lang attribute values
Programming language Possible :lang values
C++ cpp
CSS css
HTML html
Java java
JavaScript javascript
Python python
Raku raku
If the language is not specified, the default language is used based on the file extension or mime type of the current document.
This option expects a list of markup codes that are to be recognized within any V<> codes that appear in (or are implicitly applied to) the current block. The option is most often used on =code blocks to allow mark-up within those otherwise verbatim blocks, though it can be used in any block that contains verbatim text. See #Formatting within code blocks.


Selectors consist of patterns that help identify and filter specific blocks within documents. Each pattern contains optional source of blocks and block names.

The general syntax is:



  • EXTERNAL_SOURCE - optional source of blocks for filtering, default current document,

  • BLOCK_SELECTOR - list of block names, filter for

For example:

Selector Description
head1, head2, item1 all head1, head2 and item1 blocks from document
file:article.pod6 | head1, head2 all head1 and head2 blocks from article.pod6 file
file:./includes/*.pod6 | head1, head2 all head1 and head2 blocks from pod6 files placed in includes directory
doc:Data::Dumper | code all code blocks from a module documentation
file:/docs/**/*.md | head1 search headers with first level for all ".md" files
within the "docs" directory and its subdirectories.

Please note that while the Selector blocks provide a way to query and filter specific elements within Markdown files, Markdown itself doesn't have formal named blocks like the Podlite syntax. Instead, Markdown uses a lightweight markup to structure content. The above table provides a mapping between Podlite block names and their corresponding Markdown elements.

A table of correspondences for some Podlite blocks and markdown blocks
Podlite Markdown Describtion
=head1, =head2, ... #, ##, ... Heading level 1,2...
=nested ">" blockquote
=para block of text paragraph
N<> [^1]: footnote. footnote
=Html <span>text<span> HTML block
O<text> ~~text~~ Strikethrough, "O for Overstrike"
H<text> ^text^ Superscript, "H for High text"
J<text> ~text~ Subscript, "J for Junior text"
F<>, =formula $,$$, ```math Mathematical formulas

The most common use of Selectors is to create table of contents and in include block.

Block types

Podlite offers notations for specifying a wide range of standard block types...


Podlite provides an unlimited number of levels of heading, specified by the =headN block marker. For example:

  =head1 A Top Level Heading

    =head2 A Second Level Heading

      =head3 A third level heading

            =head86 A "Missed it by I<that> much!" heading

While Podlite parsers are required to recognize and distinguish all levels of heading, Podlite renderers are only required to provide distinct renderings of the first four levels of heading (though they may, of course, provide more than that). Headings at levels without distinct renderings would typically be rendered like the lowest distinctly rendered level.

Numbered headings

You can specify that a heading is numbered using the :numbered option. For example:

  =for head1 :numbered
  The Problem
  =for head1 :numbered
  The Solution
      =for head2 :numbered
          =for head3
          =for head3
      =for head2 :numbered
  =for head1 :numbered
  The Implementation

which would produce:

1. The Problem

2. The Solution

2.1. Analysis



2.2: Design

3. The Implementation

It is usually better to preset a numbering scheme for each heading level, in a series of configuration blocks:

  =config head1 :numbered
  =config head2 :numbered
  =config head3 :!numbered
  =head1 The Problem
  =head1 The Solution
  =head2   Analysis
  =head3     Overview
  =head3     Details
  =head2   Design
  =head1 The Implementation

Alternatively, as a short-hand, if the first whitespace-delimited word in a heading consists of a single literal # character, the # is removed and the heading is treated as if it had a :numbered option:

  =head1 # The Problem
  =head1 # The Solution
  =head2   # Analysis
  =head3       Overview
  =head3       Details
  =head2   # Design
  =head1 # The Implementation

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:

    =head6 # The Rescue of the Kobayashi Maru

should produce something like: The Rescue of the Kobayashi Maru

Ordinary paragraph blocks

Ordinary paragraph blocks consist 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 mark-up applied.

Ordinary paragraphs consist of one or more consecutive lines of text, each of which starts with a non-whitespace character at (virtual) column 1. The paragraph is terminated by the first blank line or block directive. For example:

  =head1 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

Within a =pod, =item, =defn, =nested, or semantic block, ordinary paragraphs do not require an explicit marker or delimiters, but there is also an explicit para marker (which may be used anywhere):

  This is an ordinary paragraph.
  Its text  will   be     squeezed     and
  short lines filled.

and likewise the longer =for and =begin/=end forms. For example:

  =begin para
    This is an ordinary paragraph.
    Its text  will   be     squeezed     and
    short lines filled.
    This is I<still> part of the same paragraph,
    which continues until an...
  =end para

As the previous example implies, when any form of explicit =para block is used, any whitespace at the start of each line is removed during rendering. In addition, within a delimited =begin para/=end para block, any blank lines are preserved.

Code blocks

Code blocks are used to specify pre-formatted text (typically source code), which should be rendered without rejustification, without whitespace-squeezing, and without recognizing any inline markup codes. Code blocks also have an implicit nesting associated with them. Typically these blocks are used to show examples of code, mark-up, or other textual specifications, and are 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. For example:

  This ordinary paragraph introduces a code block:

    $this = 1 * code('block');

Implicit code blocks may only be used within =pod, =item, =defn, =nested, or semantic blocks.

There is also an explicit =code block (which can be specified within any other block type, not just =pod, =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 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.

Formatting within code blocks

Although =code blocks automatically disregard all markup codes, occasionally you may still need to specify some formatting 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 markup codes 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 codes. Those codes will then remain active inside the code block. For example:

  =begin code :allow< B R >
  sub demo {
      B<say> 'Hello R<name>';
  =end code

would be rendered:

  sub demo {
      B<say> 'Hello R<name>';

Note that the use of the :allow option also makes it possible for verbatim markup codes (such as C<> and V<>) to contain other codes as well.

Assign programming language to code blocks

The :lang attribute will be used to provide information about the programming language used in a particular block of code. This helps in ensuring that the code is correctly rendered and interpreted by the renderers or syntax highlighting tools.

For example:

  =begin code :lang<raku>
  sub demo {
     say 'Hello R<name>';
  =end code

I/O blocks

Podlite also provides blocks for specifying the input and output of programs.

The =input block is used to specify pre-formatted keyboard input, which should be rendered without rejustification or squeezing of whitespace.

The =output block is used to specify pre-formatted terminal or file output which should also be rendered without rejustification or whitespace-squeezing.

Note that, like =code blocks, both =input and =output blocks have an implicit level of nesting. They are also like =code blocks in that they are typically rendered in a fixed-width font, though ideally all three blocks would be rendered in distinct font/weight combinations (for example: regular serifed for code, bold sans-serif for input, and regular sans-serif for output).

Unlike =code blocks, both =input and =output blocks honour any nested markup codes. This is particularly useful since a sample of input will often include prompts (which are, of course, output). Likewise a sample of output may contain the occasional interactive component. Podlite provides special markup codes (K<> and T<>) to indicate embedded input or output, so you can use the block type that indicates the overall purpose of the sample (i.e. is it demonstrating an input operation or an output sequence?) and then use the "contrasting" markup code within the block.

For example, to include a small amount of input in a sample of output you could use the K<> markup code:

  =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


Lists in Podlite are specified as a series of contiguous =item blocks. No special "container" directives or other delimiters are required to enclose the entire list. For example:

  The seven suspects are:
  =item  Happy
  =item  Dopey
  =item  Sleepy
  =item  Bashful
  =item  Sneezy
  =item  Grumpy
  =item  Keyser Soze

List items have one implicit level of nesting:

The seven suspects are:

  • Happy

  • Dopey

  • Sleepy

  • Bashful

  • Sneezy

  • Grumpy

  • Keyser Soze

Lists may be multi-level, with items at each level specified using the =item1, =item2, =item3, etc. blocks. Note that =item is just an abbreviation for =item1. For example:

  =item1  Animal
  =item2     Vertebrate
  =item2     Invertebrate
  =item1  Phase
  =item2     Solid
  =item2     Liquid
  =item2     Gas
  =item2     Chocolate

which would be rendered something like:









Podlite parsers must issue a warning if a "level-N+1" =item block (e.g. an =item2, =item3, etc.) appears anywhere except where there is a preceding "level-N" =item in the same surrounding block. That is, an =item3 should only be specified if an =item2 appears somewhere before it, and that =item2 should itself only appear if there is a preceding =item1.

Note that item blocks within the same list are not physically nested. That is, lower-level items should not be specified inside higher-level items:

    =comment WRONG...
    =begin item1          --------------
    The choices are:                    |
    =item2 Liberty        ==< Level 2   |==<  Level 1
    =item2 Death          ==< Level 2   |
    =item2 Beer           ==< Level 2   |
    =end item1            --------------
    =comment CORRECT...
    =begin item1          ---------------
    The choices are:                     |==< Level 1
    =end item1            ---------------
    =item2 Liberty        ==================< Level 2
    =item2 Death          ==================< Level 2
    =item2 Beer           ==================< Level 2

Ordered lists

An item is part of an ordered list if the item has a :numbered configuration option:

     =for item1 :numbered

     =for item2 :numbered

     =for item2 :numbered

     =for item2 :numbered

This would produce something like:

1. Visito

1.1. Veni

1.2. Vidi

1.3. Vici

although the numbering scheme is entirely at the discretion of the renderer, so it might equally well be rendered:

1. Visito

1a. Veni

1b. Vidi

1c. Vici

or even:

A: Visito

  (i) Veni

 (ii) Vidi

(iii) Vici

Alternatively, if the first word of the item consists of a single # character, the item is treated as having a :numbered option:

     =item1  # Visito
     =item2     # Veni
     =item2     # Vidi
     =item2     # Vici

To specify an unnumbered list item that starts with a literal #, either make the octothorpe verbatim:

    =item V<#> introduces a comment

or explicitly mark the item itself as being unnumbered:

    =for item :!numbered
    # introduces a comment

The numbering of successive =item1 list items increments automatically, but is reset to 1 whenever any other kind of non-ambient Podlite block appears between two =item1 blocks. For example:

    The options are:

    =item1 # Liberty
    =item1 # Death
    =item1 # Beer

    The tools are:

    =item1 # Revolution
    =item1 # Deep-fried peanut butter sandwich
    =item1 # Keg

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 (=item2, =item3, etc.) only resets (to 1) when the higher-level item's numbering either resets or increments.

To prevent a numbered =item1 from resetting after a non-item block, you can specify the :continued option:

     =for item1
     # Retreat to remote Himalayan monastery

     =for item1
     # Learn the hidden mysteries of space and time


     =for item1 :continued
     # Prophet!

which produces:

1. Retreat to remote Himalayan monastery

2. Learn the hidden mysteries of space and time


3. Prophet!

Task lists

In addition to the ordered list Podlite also supports task lists, which are commonly known as checklists or to-do lists.

To create a task list item just apply a :checked attribute to =item block.

 =for item :checked
 Buy groceries
 =for item :!checked
 Clean the garage

The rendered output looks like this:

[X] Buy groceries
 [ ] Clean the garage

Alternatively, if item content starts with brackets with space ([ ]) the item is treated as having a :!checked attribute. To select a checkbox, add an x in between the brackets ([x]). it eqvivalent of :checked attribute.

For example:

 =item [x] Buy groceries
 =itme [ ] Clean the garage 

It possiible to create multilevel to-do lists, which permits the inclusion of various task levels or sub-tasks. Here's an example:

 =item1 [ ] Work
   =item2 [ ] Prepare the presentation
   =item2 [x] Send emails
 =item1 [ ] Home
   =item2 [ ] Vacuum the living room
   =item2 [ ] Water the plants

Unordered lists

List items that are not :numbered or :checked are treated as defining unordered lists. Typically, such lists are rendered with bullets. For example:

    =item1 Reading
    =item2 Writing
    =item3 'Rithmetic

might be rendered:

•  Reading

—  Writing

¤  'Rithmetic

As with numbering styles, the bulletting strategy used for different levels within a nested list is entirely up to the renderer.

Multi-paragraph list items

Use the delimited form of the =item block to specify items that contain multiple paragraphs. For example:

     Let's consider two common proverbs:

     =begin item :numbered
     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 :numbered
     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.

which produces:

Let's consider two common proverbs:

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

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

As you can see, folk wisdom is often of dubious value.

Definition lists

To create term/definition lists, use a =defn block. This is similar in effect to an =item block, in that a series of =defn blocks implicitly defines a list (but which might then be rendered into HTML using <DL>...</DL> tags, rather than <UL>...</UL> tags)

The first non-blank line of content is treated as a term being defined, and the remaining content is treated as the definition for the term. For example:

    =defn  MAD
    Affected with a high degree of intellectual independence.

    =defn  MEEKNESS
    Uncommon patience in planning a revenge that is worth while.

    Conforming to a local and mutable standard of right.
    Having the quality of general expediency.

Like other kinds of list items, definitions can be numbered, using either an option or a leading #:

    =for defn :numbered
    Devoid of consideration for the selfishness of others.

    =defn # SUCCESS
    The one unpardonable sin against one's fellows.

Nesting blocks

Any block can be nested by specifying a :nested option on it:

    =begin para :nested
        We are all of us in the gutter,E<NL>
        but some of us are looking at the stars!
    =end para

However, qualifying each nested paragraph individually quickly becomes tedious if there are many in a sequence, or if multiple levels of nesting are required:

    =begin para :nested
        We are all of us in the gutter,E<NL>
        but some of us are looking at the stars!
    =end para
    =begin para :nested(2)
            -- Oscar Wilde
    =end para

So Podlite provides a =nested block that marks all its contents as being nested:

    =begin nested
    We are all of us in the gutter,E<NL>
    but some of us are looking at the stars!
        =begin nested
        -- Oscar Wilde
        =end nested
    =end nested

Nesting blocks can contain any other kind of block, including implicit paragraph and code blocks. Note that the relative physical indentation of the blocks plays no role in determining their ultimate nesting. The preceding example could equally have been specified:

    =begin nested
    We are all of us in the gutter,E<NL>
    but some of us are looking at the stars!
    =begin nested
    -- Oscar Wilde
    =end nested
    =end nested


Simple tables can be specified in Podlite using a =table block. The table may be given an associated description or title using the :caption option.

Columns are separated by two or more consecutive whitespace characters (double-space), 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 column separator type is allowed in a single line, but different lines are allowed to use different visible column separator types (that style is not recommended). Using a mixture of visible and non-visible column separator types in a 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 have the same number of cells.

This means you can create tables compactly, line-by-line:

        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

With header:

 =begin table

    Directive           Specifies
    _________           ____________________________________________________
    C<=begin>           Start of an explicitly terminated block
    C<=config>          Lexical modifications to a block or markup code
 =end table


 =begin table

    Energy Source                Benefit

    Solar power                  Reduces electricity bills
    Wind energy                  Clean power source
    Hydroelectric power          Highly efficient
    Geothermal energy            Low emissions
    Biomass                      Reduces waste

=end table

or line-by-line with multi-line headers:

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

        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

Advanced Table Format

Tables may construct using =row and =cell blocks. The =row blocks represent individual rows within the table.

The =cell blocks exist within rows and contain the actual content of the table. These cells can contain text, data, or other blocks.

  =begin table

  =begin row
    =cell Fruits
    =cell Bananas
    =cell Yellow and ripe
  =end row

  =begin row
    =cell Vegetables
    =cell Carrots
    =begin cell
     =para Crunchy and orange
    =end cell
  =end row

  =end table

Each =row block may have an optional :header attribute, designating it as a header row. Header rows typically contain labels or titles for columns and are visually distinct.

  =begin table

  =begin row :header
    =cell Category
    =cell Product
    =cell Description
  =end row

  =begin row
    =cell Fruits
    =cell Bananas
    =cell Yellow and ripe
  =end row

  =begin row
    =cell Vegetables
    =cell Carrots
    =cell Crunchy and orange
  =end row
  =end table

The =cell blocks can also have two important attributes:

This attribute specifies the number of columns a cell should span horizontally. It allows cells to merge and occupy multiple adjacent columns, creating a visually unified cell.
This attribute determines how many rows a cell should span vertically. Cells with :rowspan can cover multiple rows in a table, creating a vertical merge effect.

These example demonstrate how :colspan and :rowspan attributes can be used to create tables with merged cells, which is especially useful for complex data structures.

    =begin table

    =begin row :header
      =for cell :colspan(2)
      Item and Quantity 
      =cell Description
    =end row

    =begin row
      =cell Apples
      =cell 5
      =for cell :rowspan(2)
      Fruit for snacking
    =end row

    =begin row
      =cell Bananas
      =cell 3
    =end row

    =end table

It draw somethink like this:

    |         Item and Quantity        |     Description          |
    |   Apples     |      5            |                          |
    |--------------|-------------------|    Fruit for snacking    |
    |   Bananas    |      3            |                          |

Each =row block may only contain =cell blocks or blank lines as delimiters. All other types of blocks within the =row are implicitly wrapped by =cell blocks.

For example:

 =begin table

  =begin row :header
    =cell Diagram or Picture
    =cell Description
  =end row

  =begin row
    =picture spacecraft_in_orbit.jpg
    A vehicle designed for space travel
  =end row

  =begin row
       graph TD;
       A[Space Station] --> B[Mars Base]
   A space station connected to a Mars base
  =end row
 =end table

Table from CSV files or data blocks

It is possible to create tables from files or data blocks. To do this, use the file: or data: schema in the first non-blank line to specify the source of the table data. For example:

  =table file:recipe_ingredients.csv
  =for table :caption('Basic cake recipe ingredients')

  =begin data :key<recipe_ingredients> :mime-type<text/csv>
    baking powder,2,teaspoons
  =end data

Named or modular custom blocks

Blocks whose names contain at least one uppercase and one lowercase letter are assumed to be destined for specialized renderers or parser plug-ins. For example:

    =begin Xhtml
    <object type="video/quicktime" data="onion.mov">
    =end Xhtml


  =Image http://www.perlfoundation.org/images/perl_logo_32x104.png

Ideally, each named block should have a corresponding handler responsible for its rendering and processing.

In the absence of a handler for named block, the implementation should allow the content to degrade gracefully, ensuring that the core message or functionality remains accessible even if some advanced features cannot be rendered. As result, that blocks my be displayed as verbatim or placeholder content or even not rendered at all.

Alongside the verbatim or placeholder content, the renderer could provide an unobtrusive yet informative error message, explaining that the named block could not be processed.

Note that all block names consisting entirely of lowercase or entirely of uppercase letters are reserved. See #Semantic blocks.

To check custom markup codes, refer to #Custom markup codes.

Podlite comments

Podlite comments refers to Podlite blocks that should not be displayed by any renderer. However, they are still may be part of the internal Podlite representation. However, they can still be part of internal Podlite representation.

Comments are useful for meta-documentation (documenting the documentation):

    =comment Add more here about the algorithm

and for temporarily removing parts of a document:

  =item # Retreat to remote Himalayan monastery

  =item # Learn the hidden mysteries of space and time

  =item # Achieve enlightenment

  =begin comment
  =item # Prophet!
  =end comment

Data blocks

The =data block is used to embed various types of data directly into a document.

For example, to include a CSV file in a document, it is possible to use the following syntax:

  =begin data :key<sales_data> :mime-type<text/csv>
    John Doe,January,1000
    Jane Doe,February,1500
  =end data

Each =data block can be given a :key option, to name it. The contents of any =data block with a key are addressable via the data: schema. For example:

  =begin data :key<employee_data> :mime-type<text/csv>
    1,John Doe,Manager,Marketing
    2,Jane Smith,Developer,Engineering
    3,Bob Brown,Designer,Product
  =end data

  =table data:employee_data

Each =data block can include several attributes to provide additional information about the contained data:

This option specifies the original file name of the embedded data, which can be used to hint at the type of data contained if the :mime/type is not explicitly provided.
This option indicates the MIME type of the data, such as image/png for PNG images, which helps in determining how the data should be interpretered and processed.
Here is a list of few well-known mime types and their corresponding file extensions:
MIME Type File Extension
text/plain .txt
text/markdown .md, .markdown
text/podlite .podlite, .pod6
application/json .json
application/xml .xml
image/jpeg .jpg, .jpeg
image/png .png
application/pdf .pdf
application/zip .zip
audio/mpeg .mp3
video/mp4 .mp4
application/msword .doc, .docx
text/csv .csv
text/tab-separated-values .tsv, .tab
:access-time and :modify-time
This attributes record time for when the data was last accessed or edited.
This option specifies the encoding method used to store the data. For non-text data, such as images in the PNG format, the encoding method base64 is used.

Example of storing images in =data blocks:

  =begin data :key<Logo> :filename<Logo.png> :mime-type<image/png>
  = :access-time<2022-01-01T00:00:00Z>  :modify-time<2022-01-02T10:00:00Z>
  = :encoding<base64>
  =end data

  =picture data:Logo

In the example above, we have a =data block with :id Logo that stores the base64-encoded image data. We also specify the filename, mime type, access time, and edit time as attributes of the =data block.

The image can then be referenced using the `=picture` block with the scheme data: and the block name Logo.

The =data blocks are just regular Podlite blocks and may appear anywhere within a source file, and as many times as required.

Note that in Podlite, it is possible to specify =data blocks after the point in the source where their contents will be used.

=data blocks are never rendered by the standard Podlite renderers.

Semantic blocks

All uppercase block typenames are reserved for specifying standard documentation, publishing, source components, or meta-information of a compunit it needs to be able to be selected for loading.

Standard semantic blocks include:


The plural forms of each of these keywords are also reserved, and are aliases for the singular forms.

Most of these blocks would typically be used in their full delimited forms:

    =begin SYNOPSIS
        use Magic::Parser;

        my Magic::Parser $parser .= new();

        my $tree = $parser.parse($fh);
    =end SYNOPSIS

Semantic blocks can be considered to be variants of the =head1 block in most respects (and most renderers will treat them as such). The main difference is that, in a =head1 block, the heading is the contents of the block; whereas, in a semantic block, the heading is derived from the typename of the block itself and the block contents are instead treated as the =para or =code block(s) belonging to the heading.

The use of these special blocks is not required; you can still just write:

    =head1 SYNOPSIS
    =begin code :lang<raku>
        use Magic::Parser

        my Magic::Parser $parser .= new();

        my $tree = $parser.parse($fh);
    =end code

However, using the keywords adds semantic information to the documentation, which may assist various renderers, summarizers, coverage tools, document refactorers, and other utilities. This is because a semantic block encloses the text it controls (unlike a =head1, which merely precedes its corresponding text), so using semantic blocks produces a more explicitly structured document.

Note that there is no requirement that semantic blocks be rendered in a particular way (or at all). Specifically, it is not necessary to preserve the capitalization of the keyword. For example, the =SYNOPSIS block of the preceding example might be rendered like so:

3.  Synopsis

    use Raku::Magic::Parser;

    my $rep = Raku::Magic::Parser.parse($fh, :all_pod);

Table of contents

The =toc block is used to make an autogenerated table of contents (TOC) in a document. The TOC is an index of section titles within the document, and its structure is determined by the document's organization.

The first non-blank line of =toc content is treated as a selector

For example:

 =toc head1, head2, head3, item1, item2, table


  =toc  head1, head2, head3 

The TOC is, by default, displayed without a caption. However, the value assigned to the :caption attribute of the =toc block is used to generate a caption for the TOC.

For example:

  =for toc :caption('Table of contents')
  head1, head2, head3 

To build the entries in the TOC, the content of the :caption attribute within the block is used. If this attribute does not exist, then the text presentation of the block's content is utilized as the TOC entry.

The depth of the generated TOC is determined by the "Selector" argument. The selector processed, and headers or filtered blocks that allow levels are used to build the TOC levels. If a block does not have an associated level, it is rendered at a level one higher than the previous block with a level in the TOC.

Note also that all semantic blocks are treated as equivalent to head1 headings, and the =item1/=item equivalence is preserved.

The :folded-levels attribute indicates which level of the TOC should be folded.

 =for toc :folded-levels[2,3] :caption('Table of contents')
    head1, head2, item1

If the :folded-levels attribute is provided with a set of key-value pairs, it indicates the folding state of each specified level.

For example:

  =for toc  :folded-levels< 2=>1, 4 => 1, 3=>0 > 
    head1, head2, head3, item1, item2

The value 0 for to level 3 indicates that this level should remain unfolded. Levels 2 and 4 are folded.

This allows for a highly customized folding configuration within the TOC.

The TOC is inserted at the location of the =toc block.

To enable the autogenerated TOC, controlled and maintained by render, set the :toc document attribute for =pod block. In this case, the specific configuration and outcome of the TOC are influenced by the settings of the concrete render implementation.

Include block

The =include block is a powerful tool that allows to reuse specific parts of documents within project sources. This is particularly handy when dealing with complex documents that require to include certain sections from different files while keeping the overall context and structure intact.

The =include block is followed by an "Selector" that specifies the content to be included.

In this example, the content of the file chapter01.pod6 located in the ./includes directory is included:

=include file:./includes/chapter01.pod6

A wildcard "Selector" serves this purpose, enabling inclusion of content from all the Markdown files:

  =include file:./includes/*.md

It's possible to include blocks from the same document being worked on. This feature proves valuable when reusing parts of existing content.

For instance, a semantic block =VERSION can be included as demonstrated:

=include VERSION
=VERSION 1.0.0

or, equivalently:

=VERSION 1.0.0
=VERSION 1.0.0

Podlite detects type of the included file by its extension. For example, if the included file has a .md extension, it is treated as a Markdown file.

To override the type of the included file by extension, you can use the :mime-type attribute. This attribute allows you to specify the MIME type of the included file. For example:

  =for include :mime-type('text/podlite')

The :mime-type attribute is particularly useful when including files with extensions that do not match their actual MIME type.

It's crucial to think about security concerns, as adding content from external sources could potentially create vulnerabilities such as injecting harmful code or malicious material. Tools responsible for displaying and handling the content should be able to provide a warning in such situations.

Inserting pictures

Podlite allows to include images using a =picture block with an inline version represented as P<alternative text|source of the image>:

 =picture astronaut.png
 =para In the vast expanse of the cosmos, an intrepid P<astronaut|astronaut.png>
 floats weightlessly above the Earth.

The first non-blank line of content within the =picture block specifies the source of the image and the remaining content is treated as caption.

This source can be either local or remote, and it can be indicated using different schemas: https: for remote images, file: for local ones, or data for embedded images in to the document. If no schema is provided, it defaults to file:.

 =picture https://example.com/image.jpg
 =picture file:/local/image.png
 =picture /local/image.png
 =picture ../image.png
 =picture data:Logo

Following the source line, it possible to include an image caption.

 =picture astronaut.png
 In the vast expanse of the cosmos, an intrepid B<astronaut>
 floats weightlessly above the Earth.

in delimited form of =picture it possible to include as match texts as needed:

 =begin picture
 In the vast expanse of the cosmos, an intrepid B<astronaut>
 floats weightlessly above the Earth.

 This astronaut explores the vastness of space.
 =end picture

It possible to use all inline markup codes that are supported by ordinary paragraph blocks.

Alternatively, you can define the image caption using the :caption attribute.

 =for picture :caption<diagram>

Mathematical formulas

To include mathematical formulas, use a =formula block with an inline version represented as F<>.

To insert mathematical expressions, use LaTeX-style syntax, which is a commonly used format for writing mathematical equations.

  x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}

  In a right triangle, the length of the hypotenuse can be calculated 
  using the Pythagorean theorem: F<a^2 + b^2 = c^2>.

  Euler's identity, F<e^{i\pi} + 1 = 0>, is a fundamental equation in
  complex analysis.

It possible to define the formule caption using the :caption attribute.

  =formula  :caption<Quadratic Formula> 
  x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}

Markdown support

Podlite includes built-in support for Markdown, making it easy to include Markdown content within Podlite documents. This is achieved using the =markdown block.

  =begin markdown

  ## Markdown Example

  You can use all the standard Markdown syntax within this block. For example:

  - *Italic text* using asterisks or underscores: *italic* or _italic_.
  - **Bold text** using double asterisks or underscores: **bold** or __bold__.
  - [Links](https://example.com) with the `[text](url)` syntax.
  - Unordered lists using `-`, `*`, or `+`:

  - Item 1
  - Item 2

  - Ordered lists using numbers:

  1. First item
  2. Second item

  - Code blocks with backticks:

  def hello_world():
      print("Hello, World!")

  - Blockquotes with the `>` symbol:
    > This is a blockquote.

  =end markdown

This block allows to seamlessly combine Podlite's structured blocks with the flexibility of Markdown.

Markup codes

Markup codes enable inline markup within the text of (most) Podlite block types. They are a form of block that can contain only other markup codes. Specifically, markup codes can nest:

    B<I shall say this loudly
    Z<and repeatedly>
    and with emphasis.>

All Podlite markup codes consist of a single capital letter followed immediately by a set of angle brackets. The brackets contain the text or data to which the markup code applies. You can use a set of single angles (<...>), a set of double angles («...»), or multiple single-angles (<<<...>>>).

Within angle delimiters, you cannot use sequences of the same angle characters that are longer than the delimiters:

        These are errors...

    C< $foo<<bar>> >
    The Perl 5 heredoc syntax was: C< <<END_MARKER >

You can use sequences of angles that are the same length as the delimiters, but they must be balanced. For example:

C<  $foo<bar>   >
    C<< $foo<<bar>> >>

If you need an unbalanced angle, either use different delimiters:

    C«$foo < $bar»
    The Perl 5 heredoc syntax was: C« <<END_MARKER »

or delimiters with more consecutive angles than your text contains:

    C<<$foo < $bar>>
    The Perl 5 heredoc syntax was: C<<< <<END_MARKER >>>

A markup code ends at the matching closing angle bracket(s), or at the end of the enclosing block or markup code in which the opening angle bracket was specified, whichever comes first (this includes paragraph and abbreviated blocks, ending with blank a line). Podlite parsers are required to issue a warning whenever a markup code is terminated by the end of an outer block rather than by its own delimiter (unless the user explicitly disables the warning).

Significance indicators

Podlite provides three markup codes that flag their contents with increasing levels of significance:

  • The U<> markup code specifies that the contained text is unusual or distinctive; that it is of minor significance. Typically such content would be rendered in an underlined style.

  • The I<> markup code specifies that the contained text is important; that it is of major significance. Such content would typically be rendered in italics or in <em>...</em> tags

  • The B<> markup code specifies that the contained text is the basis or focus of the surrounding text; that it is of fundamental significance. Such content would typically be rendered in a bold style or in <strong>...</strong> tags.

Mistake marking

It possible strikethrough words using the code O<>, where 'O' stands for "Overstrike." This is a way to indicate that certain words are a mistake and should not be included in the document.

O<The sky is green.> Our planet's sky is usually blue.

Text positioning

Podlite provides two markup codes that allow positioning characters or words.

  • To create subscript text, you can use the J<> markup code, where 'J' represents "Junior text." Subscript positions one or more characters slightly below the normal line of type.


    This code renders as H<sub>2</sub>O, which signifies that the '2' is positioned slightly below the baseline, as is often seen in chemical formulas like H₂O (water).

  • To create superscript text, it possible to use the H<> markup code, where 'H' stands for "High text." Superscript positions one or more characters slightly above the normal line of type


    This code renders as X<sup>2</sup>, indicating that the '2' is positioned slightly above the baseline. This is commonly used for mathematical exponents, as in .


The D<> markup code indicates that the contained text is a definition, introducing a term that the adjacent text elucidates. It is the inline equivalent of a =defn block. 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.

A definition may be given synonyms, which are specified after a vertical bar and separated by semicolons:

    A D<markup code|markup codes;formatters> provides a way
    to add inline mark-up to a piece of text.

A definition would typically be rendered in italics or <dfn>...</dfn> tags and will often be used as a link target for subsequent instances of the term (or any of its specified synonyms) within a hypertext.

Example specifiers

Podlite provides markup codes for specifying inline examples of input, output, code, and metasyntax:

  • The T<> markup code specifies that the contained text is terminal output; that is: something that a program might print out. Such content would typically be rendered in a fixed-width font or with <samp>...</samp> tags. The contents of a T<> code are always space-preserved (as if they had an implicit S<...> around them). The T<> code is the inline equivalent of the =output block.

  • The K<> markup code specifies that the contained text is keyboard input; that is: something that a user might type in. Such content would typically be rendered in a fixed-width font (preferably a different font from that used for the T<> markup code) or with <kbd>...</kbd> tags. The contents of a K<> code are always space-preserved. The K<> code is the inline equivalent of the =input block.

  • The C<> markup code specifies that the contained text is code; that is, something that might appear in a program or specification. Such content would typically be rendered in a fixed-width font (preferably a different font from that used for the T<> or K<> markup codes) or with <code>...</code> tags. The contents of a C<> code are space-preserved and verbatim. The C<> code is the inline equivalent of the =code block.

    To include other markup codes in a C<> code, you can lexically reconfigure it:

      =begin para
      =config C< :allow<E I>>
      Raku makes extensive use of the C<E<laquo>> and C<E<raquo>>
      characters, for example, in a hash look-up:
      =end para

    To enable entities in every C<...> put a =config C<> :allow<E> at the top of the document

  • The R<> markup code 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>


      Then enter your details at the prompt:
      =for input
          Name: R<your surname>
            ID: R<your employee number>
          Pass: R<your 36-letter password>

    Typically replaceables would be rendered in fixed-width italics or with <var>...</var> tags. The font used should be the same as that used for the C<> code, unless the R<> is inside a K<> or T<> code (or the equivalent =input or =output blocks), in which case their respective fonts should be used.

Verbatim text

The V<> markup code treats its entire contents as being verbatim, disregarding every apparent markup code within it. For example:

The B<V< V<> >> markup code 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 codes surrounding the V<> code are still applied to its contents. For example the previous example is rendered:

The V<> markup code disarms other codes such as I<>, C<>, B<>, and M< >.

You can prespecify markup codes that remain active within a V<> code, using the :allow option.

Inline comments

The Z<> markup code indicates that its contents constitute a zero-width comment, which should not be rendered by any renderer. For example:

  The "exeunt" command Z<Think about renaming this command?> is used
  to quit all applications.

In certain scenarios, the Z<> code is used to break up text that would otherwise be considered mark-up:

  In certain scenarios, the ZZ<><> code is used to break up text that 
  would otherwise be considered mark-up.

That technique still works, but it's now easier to accomplish the same goal using a verbatim markup code:

  In certain scenarios, the V<V<Z<>>> code is used to break up text that 
  would otherwise be considered mark-up.

Moreover, the C<> code automatically treats its contents as being verbatim, which often eliminates the need for the V<> as well:

  In certain scenarios, the V<C<Z<>>> code was widely used to break up text
  that would otherwise be considered mark-up.

The Z<> markup code is the inline equivalent of a =comment block.

The L<> code is used to specify all kinds of links, filenames, citations, and cross-references (both internal and external).

A link specification consists of a scheme specifier terminated by a colon, followed by an external address (in the scheme's preferred syntax), followed by an internal address (again, in the scheme's syntax). All three components are optional, though at least one must be present in any link specification.

Usually, in schemes where an internal address makes sense, it will be separated from the preceding external address by a #, unless the particular addressing scheme requires some other syntax. When new addressing schemes are created specifically for Podlite it is strongly recommended that # be used to mark the start of internal addresses.

Standard schemes include:

http: and https:
A standard web URL. For example:
  This module needs the LAME library
  (available from L<http://www.mp3dev.org/mp3/>)
If the link does not start with // it is treated as being relative to the location of the current document:
  See also: L<http:tutorial/faq.html> and
A filename on the local system. For example:
  Next, edit the global config file (that is, either
  L<file:/usr/local/lib/.configrc> or L<file:~/.configrc>).
Filenames that don't begin with a / or a ~ are relative to the current document's location:
    Then, edit the local config file (that is, either
    L<file:.configrc> or L<file:CONFIG/.configrc>.
An email address. Typically, activating this type of link invokes a mailer. For example:
  Please forward bug reports to L<mailto:[email protected]>
A link to the system manpages. For example:
  This module implements the standard
  Unix L<man:find(1)> facilities.
A link to other documents by utilizing semantic blocks such as =TITLE or =NAME as anchor points for these links.
For example:
  =NAME Dumper
  You may wish to use L<doc:Dumper> to
  view the results.
Moreover, the doc: scheme allows the use of an :id attribute within the =TITLE or =NAME blocks to create unique identifiers for document linking. This ensures precision in navigation, as each identifier corresponds to a specific part of the document set. An example would be:
    =for TITLE :id<Specification>
    The Specification of Podlite
    Read the L<spec|doc:Specification>.
When Podlite processes a link, it can automatically use the document's title from the =TITLE or =NAME blocks as the display text for the hyperlink if no explicit text is provided. For example:
   =for TITLE :id<Specification>
       The Specification of Podlite

   Please read "L<doc:Specification>".

... will be rendered as:
 Please read "The Specification of Podlite".

A link to the block-form or inline definition of the specified term within the current document. For example:
  He was highly prone to D<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)
and later, to link back to the definition
To treat his chronic L<defn:lexiphania> the doctor prescribed an
immediate L<defn:glossoligation> or, if that proved ineffective,
a complete cephalectomy.
isbn: and issn:
The International Standard Book Number or International Standard Serial Number for a publication. For example:
  The Perl Journal was a registered
  serial publication (L<issn:1087-903X>)

To refer to a specific section within a webpage, manpage, or Podlite document, add the name of that section after the main link, separated by a #. For example:

  Also see: L<man:bash(1)#Compound Commands>,
  L<doc:perlsyn#For Loops>, and

To refer to a section of the current document, omit the external address:

  This mechanism is described under L<doc:#Special Features> below.

The scheme name may also be omitted in that case:

  This mechanism is described under L<#Special Features> below.

Podlite include the possibility of assigning a unique identifier to a block. These identifiers can be explicitly assigned to any blocks using the :id attribute. Later, these identifiers are utilized for adressing blocks and creating links.

  =for head1 :id<intro>
  =for para :id<id1>
  This is an introductory paragraph.
  For more information, see L<here|#intro> and L<here|#id1>

In this example, the link reference to the header block identified by "intro" rather than the name "Introduction" and to the paragrapth block with identifier "id1".

Normally a link is presented as some rendered version of the link specification itself. However, you can specify an alternate presentation by prefixing the link with the desired text and a vertical bar. Whitespace is not significant on either side of the bar. For example:

  This module needs the L<LAME library|http://www.mp3dev.org/mp3/>.

  You could also write the code
  L<in Latin | doc:Lingua::Romana::Perligata>

  His L<lexiphanic|defn:lexiphania>> tendencies were, alas, incurable.

Podlite introduces the concept of contextual backward links W<> (or contextual backlinks), enhancing the traditional linking mechanism by allowing to not only reference another location but also provide specific context around that reference. This context can take the form of opinions, additional information, or any relevant commentary that enhances the understanding of the referenced material.

For example:

  This text can reveal the meaning of W<glossoligation|defn:glossoligation>


  We discuss here about W<doc:perldata>.

Contextual backlinks on the destination page can be displayed in various ways. They may appear with surrounding text chunks, providing context within the flow of the content. Alternatively, they can be placed at the end of the text, in the margin of the page, or highlighted in other visually distinctive ways.

Like traditional links, contextual backlinks allows the use of all available link schemes, including https: and doc:, to link to external content.

Contextual backlinks might be visually distinguished from standard links through color coding.

Alias placements

The A<> code 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>.

See #Aliases for further details of the aliasing macro mechanism.

Space-preserving text

Any text enclosed in an S<> code is formatted normally, except that every whitespace character in itincluding any newlineis 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.


To include Unicode code points or HTML5 character references in a Podlite document, specify the required entity using the E<> code.

If the E<> contains a number, that number is treated as the decimal Unicode value for the desired code point. For example:

Podlite makes considerable use of E<171> and E<187>.

You can also use explicit binary, octal, decimal, or hexadecimal numbers:

Podlite makes considerable use of E<0b10101011> and E<0b10111011>.
    Podlite makes considerable use of E<0o253> and E<0o273>.
    Podlite makes considerable use of E<0d171> and E<0d187>.
    Podlite makes considerable use of E<0xAB> and E<0xBB>.

If the E<> contains anything that is not a number, the contents are interpreted as a Unicode character name (which is always uppercase), or else as an HTML5 named character reference. For example:

Podlite makes considerable use of E<LEFT DOUBLE ANGLE BRACKET>

or, equivalently:

Podlite makes considerable use of E<laquo> and E<raquo>.

To include emoji codes, you can use the E<> code along with the colon-prefixed and postfix emoji shortname:

Podlite uses emoji codes to express emotions and actions,
    such as E<:thumbsup:> for approval and E<:smile:> for happiness.

In this example, :smile: and :thumbsup: are emoji codes representing the respective emojis. You can use any valid emoji code in this format to include emojis in your Podlite document.

Note that the specific emoji codes and the emojis they represent may vary depending on the platform or system you are using.

Multiple consecutive entities (in any format) can be specified in a single E<> code, separated by semicolons:

Podlite makes considerable use of E<LEFT DOUBLE ANGLE BRACKET;hellip;0xBB;:smile:>.

Indexing terms

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 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 Manoeuvre"
  because you "OR" the "cache".


Anything enclosed in an N<> code is an inline note. For example:

  Space stations feature hydroponic gardens N<Plants grow without soil,
  using mineral nutrient solutions.>, a necessity for long-term missions.

Renderers may render such annotations in a variety of ways: as footnotes, as endnotes, as sidebars, as pop-ups, as tooltips, as expandable tags, etc. They are never, however, rendered as unmarked inline text. So the previous example might be rendered as:

Space stations feature hydroponic gardens , a necessity for long-term missions. and later:


Plants grow without soil, using mineral nutrient solutions.

Module-defined handler for extends markup features

The M<> code in Podlite extends the language's capabilities by allowing users to specify additional processing instructions within their documents. This is achieved by combining content text with a custom plug-in specifier, followed by optional configuration information that is passed to a handler function.

The structure of the M<> markup code as follows:


This syntax includes CONTENT-TEXT section, followed by a name specifier MODULE_NAME and then the OPTIONAL CONFIG INFO (see "Configuration syntax options"). The name specifier should follow the same rules as for named blocks.

The M<> formatting code is the inline equivalent of a named block.

An example of how this code might be used is :

    M< This text is highlighted in yellow |Marker :color('yellow') >.

In this example, the text "This text is highlighted in yellow" is subject to special handling specified by the Marker module and :color('yellow'), indicating that the text should be highlighted in yellow.

If the MODULE_NAME is unrecognized, the content text CONTENT-TEXT should be rendered as ordinary text. This ensures that documents remain readable even if specific processing instructions cannot be executed. The renderer could provide an unobtrusive yet informative error message, explaining that the custom markup block could not be processed.

Block pre-configuration

The =config directive allows you to prespecify standard configuration information that is applied to every block of a particular type.

  =config code     :lang<python> :allow<B>
  =config head1    :numbered
  =config head2    :folded

Here, two configurations are outlined. The first one sets the language for code blocks to python and allows bold markup. The second establishes that all level 1 headings will be numbered.

The general syntax for configuration directives is:

    =                   R<OPTIONAL EXTRA CONFIG OPTIONS>

A =config is a directive, not a block. Hence, there is no paragraph or delimited form of the =config directive. Each =config specification is lexically scoped to the surrounding block or file in which it is specified.

Note that, if a particular block later explicitly specifies a configuration option with the same key, that option overrides the pre-configured option. For example, given the code blocks configurations in the previous example, to specify another language for code block:

  =for code :lang<javascript>

Pre-configuring markup codes

You can also lexically preconfigure a markup code, by naming it with a pair of angles as a suffix. For example:

  =comment  Always allow E<> codes in any (implicit or explicit) V<> code...
  =config V<>  :allow<E>
  =comment  All inline code allows I<>
  =config C<>  :allow<I>

Note that, even though the markup code is named using single-angles, the preconfiguration applies regardless of the actual delimiters used on subsequent instances of the code.


The =alias directive provides a way to define lexically scoped synonyms for longer Podlite sequences, (meta)object declarators from the code, or even entire chunks of ambient source. These synonyms can then be inserted into subsequent Podlite using the A<> markup code.

Note that =alias is a fundamental Podlite directive, like =begin or =for; there are no equivalent paragraph or delimited forms.

Macro aliases are lexically scoped to the surrounding Podlite block.

The simplest form of alias takes two arguments. The first is an identifier (which is usually specified in uppercase, though this is certainly not mandatory). The second argument consists of one or more lines of replacement text.

This creates a lexically scoped Podlite macro that can be invoked during document generation by placing the identifier (i.e. the first argument of the alias) in an A<> markup code. This markup code is then replaced by the text returned by 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 addition 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:


would produce:

The use of Earl Irradiatem Evermore is subject to the terms and conditions laid out by 4D Kingdoms Inc, 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>

Notification blocks

These blocks, often referred to as admonitions, callouts, or alerts, serve to draw the reader's attention to different types of content, such as tips, warnings, or important notes.

To create specially formatted blocks to highlight information in Podlite the =nested block and :notice attribute are utilized.

For example:

    =begin nested :notify<tip>
    Remember to always use oven mitts when handling hot bakeware
    to prevent burns.
    =end nested

Below is a table that outlines the different types of notification blocks along with a brief description of each type.

Types of Notification blocks
Type Description
note Provides additional information and context without interrupting the flow of the main content
tip Offers advice for doing things better or more easily
important Signifies that the information is crucial for understanding or success
warning Indicates urgent information that requires immediate attention to avoid potential problems
caution Advises readers about potential negative outcomes or risks associated with certain actions

By default, the title of the notification block is its type identifier in title case. It is possible to customize the title of the block and control the visibility of the information using the :caption and :folded options.

  =begin nested :caption<"Astronaut's Reminder"> :notify<important> :folded
    Space missions require meticulous planning and adherence to safety protocols.
    Neglecting these can lead to mission failure or, worse, endanger lives.
  =end nested

It is possible to create title-only callouts by omitting the body.

  =for nested :notify<important> :folded :caption<"Title-only callout">

Notification blocks are displayed with distinctive colors and icons that indicate the significance of the content.



Directive Specifies
=begin Start of an explicitly terminated block
=config Lexical modifications to a block or markup code
=end Explicit termination of a =begin block
=for Start of an implicitly (blank-line) terminated block
=alias Define a Podlite macro


Block typename Specifies
=code Verbatim pre-formatted sample source code
=comment Content to be ignored by all renderers
=defn Definition of a term
=headN Nth-level heading
=input Pre-formatted sample input
=item First-level list item
=itemN Nth-level list item
=nested Nest block contents within the current context
=output Pre-formatted sample output
=para Ordinary paragraph
=pod No "ambient" blocks inside
=table Simple rectangular table
=data Data section
=toc Autogenerated table of contents
=include Include other blocks, documents
=picture Inserting pictures
=formula Mathematical formulas
=markdown Markdown support
=RESERVED Semantic blocks (=SYNOPSIS, =BUGS, etc.)
=Typename User-defined block

Inline markup codes

Formatting code Specifies
A<...> Replaced by contents of specified macro/object
B<...> Basis/focus of sentence (typically rendered bold)
C<...> Code (typically rendered fixed-width)
D<...|...;...> Definition (D<R<defined term>|R<synonym>;R<synonym>;...>)
E<...;...> Entity names or numeric codepoints (E<R<entity1>;R<entity2>;...>), emoji
F<...> Mathematical formula
G<...> reserved
H<...> Superscript
I<...> Important (typically rendered in italics)
J<...> Subscript
K<...> Keyboard input (typically rendered fixed-width)
L<...|...> Link (L<R<display text>|R<destination URI>>)
M<...:...> Module-defined code (M<R<scheme>:R<contents>>)
N<...> Note (not rendered inline)
O<...> Strikethrough
P<...> Inline eqivalent for =picture block
Q<> reserved
C<R><...> Replaceable component or metasyntax
S<...> Space characters to be preserved
T<...> Terminal output (typically rendered fixed-width)
U<...> Unusual (typically rendered with underlining)
V<V><...> Verbatim (internal markup codes ignored)
W<...|...> Contextual backlinks
Y<> reserved
X<...|..,..;...> Index entry (X<R<display text>|R<entry>,R<subentry>;...>)
Z<...> Zero-width comment (contents never rendered)


Artistic license 2.0