Podlite - a lightweight markup language
- Unreleased
- v2.0
- v1.0
- Podlite
- General syntactic structure
- Podlite blocks
- Delimited blocks
- Paragraph blocks
- Abbreviated blocks
- Block equivalence
- Standard configuration options
- Selectors
- Internal addresses
- Predicates
- Universal pattern
- Empty and absent values
- Membership
- Operations in parentheses
- Combining conditions
- Non-matching conditions
- Block types
- Headings
- Ordinary paragraph blocks
- Code blocks
- I/O blocks
- Lists
- Nesting blocks
- Tables
- Named or modular custom blocks
- Data-table blocks
- Podlite comments
- Data blocks
- Semantic blocks
- Table of contents
- Include directive
- Section boundaries
- Test blocks
- Inserting pictures
- Mathematical formulas
- Markdown support
- Markup codes
- Significance indicators
- Mistake marking
- Text positioning
- Definitions
- Example specifiers
- Verbatim text
- Inline comments
- Content masking
- Links
- Contextual backlinks
- Link configuration attributes
- Alias placements
- Space-preserving text
- Entities
- Indexing terms
- Annotations
- Module-defined handler for extends markup features
- Block pre-configuration
- Block attribute assignment with =set
- Aliases
- Notification blocks
- Directives
- Blocks
- Inline markup codes
AUTHORS
Damian Conway <damian@conway.org>
Aliaksandr Zahatski <zag@cpan.org>
VERSION
2.0
CHANGES
Unreleased
Added:
Described operations written in parentheses, the rule telling an operation from a value, and the
inoperator with its operands.Described internal addresses: the three parts of their reading, their bounds in a selector and in a link, and the naming of a
data:column.Described
=testblocks with selector assertions, and their=fixture,=assertand=resourcechildren.Described predicates in selectors: the operators, the outcome for empty and absent values, membership, and the combination of conditions.
Described the universal pattern, which matches a block of any name.
Added tests for the block frame, kept in files under
t/and included after the rules they check: the three forms of a block, where a block ends, the virtual margin, and indentation as code.Added tests for block configuration, kept in files under
t/and included after the rules they check: the notations of a value, empty values, continuation lines, the:nestedand:langoptions, and the language of a Markdown fence.Added tests for configuration precedence and for
=config,=setand selectors across=include.Added tests for
=settargeting, predicates over configuration, relative paths in selector sources, and tests brought in by=include.Added tests for heading levels, the
:numberedoption, input and output blocks, semantic blocks, pictures and formulas.Added tests for test blocks: the blocks a test contains, their options, and the document an assertion is resolved against.
Added tests for selectors: internal addresses, predicate operators, the universal pattern, empty and absent values, membership, operations in parentheses, combined and non-matching conditions, and wildcard sources of
=include.Added a list of the tests at the end of the specification.
Described a
=podblock nested in another as a group.
Changed:
Described how blocks and tests brought in by
=includebelong to the including document.Described a selector pattern as a block name or the universal
*followed by an optional predicate.Aligned the introduction to selectors with their grammar: the source of a selector is not part of its patterns.
Named the kind of a value in the block configuration table.
Distinguished the two hash notations by the keys each admits.
Stated that the separators of an index entry describe one structure.
Reworked the forms of an attribute value.
Allowed a value in parentheses or braces to span configuration lines.
Described the empty forms of a value.
Stated where a relative path resolves from in selector sources, images and links, and that including the document elsewhere does not change it.
Removed the claim that an internal address is written in the syntax of its scheme.
Stated that a predicate tests the configuration in effect for a block.
Stated configuration precedence and made
=setassignments in an included file override those accumulated before=include.Made
=configreach blocks brought in by=include, which changes the reading of documents written under the earlier rule, with no transition period.Stated that the default language of a code block comes from its source file.
Allowed a
:mime-typewritten on=data-tableto override the format of adata:source.Stated that a test obtained under different configurations is run under each.
Stated that the rule governs if a test of this specification differs from it.
Stated which content counts as external for the warning about included content.
Stated which blocks give a document its name for the
doc:scheme, and that a name two documents carry does not resolve.Stated that text on the directive line of an abbreviated
=itemis an ordinary paragraph of the item.Stated that the first line of an implicit paragraph or code block decides it, regardless of later indentation.
Stated that a virtual margin ends with its block, which changes the reading of text indented under an ended block.
Stated that a line left of the virtual margin stays in its block, and a warning may be issued.
Stated that indented text in the abbreviated and paragraph forms of
=itemand=defnis not code.Stated that a delimited
=defnholds implicit code blocks, as the rule on code blocks already did.Stated that the implicit
=podof a file is not a block a selector reaches.Stated that the body of a
=fixtureis read as a.podlitefile.Stated that an included block brings all its content and that a block found inside another found block is included once.
Stated that a predicate tests the block itself and that a selected block keeps its content, with an example of a negated condition.
Stated that the selector of a table of contents is applied to the document the block is in.
Stated that a
=tocblock brought in by=includeapplies its selector to the including document.Stated that the
=includedirective is not a block a selector reaches, whether or not it resolves.Stated where
=setassignments before an=includego when it brings no block or fails to resolve.Stated that an
=aliasis scoped to its file and reaches blocks placed there by=include.Fixed the notification attribute name to
:noticewhere it differed from the rule.
v2.0
Added:
Attributes on Markdown fenced code blocks,
Per-link configuration attributes for
L<>markup code,Error recovery rules for
=tableblock,=boundarydirective for marking structural section boundaries,G<>markup code (Guarded) and:maskedblock attribute for content masking,=setdirective for per-block attribute assignment with multiline values and inline markup support,Extended
:mime-typeattribute syntax to accept MIME parameters per RFC 6838, withheader=present|absentrecognised for CSV/TSV header indication per RFC 4180 §3,=data-tableblock for rendering CSV and TSV data, with:src,:columns,:renameattributes.
Changed:
Reclassified
=includeas directive,Refined
:foldeddefinition,Fixed attribute name inconsistencies in examples.
Removed:
Outdated string attribute syntax formats.
v1.0
Added:
Notification blocks,
:noticeattribute for=nestedblocks,:foldedattribute,:folded-levelsfor=tocblock,embedding binary data into documents,
=data,:filename,:encoding,:mime-typeattribute for=includeand=datablocks,introduce
data:schema for use in=pictureand=table,render tables from CSV files,
=table,new markdown mode for parser,
M<>- extends inline markup features,add
:id,:caption,:langattributes,task lists,
=itemand:checkedattribute,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,=cellblocks,:header,:rowspan,:colspanattributes.
Changed:
refactor Named custom blocks and markup custom codes,
M<>.
Removed:
Contextual aliases,
=finish,markers in comments,
:marginattribute,=encodingdirective,P<toc:>due to=tocblock,P<man:>,P<doc:>due to=includedirective,P<>- placement links,Declarator block,
:formattedattribute,:likeattribute.
Podlite
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 considered the first column of the entire block's contents until the block ends, when the virtual margin of the enclosing block applies again.
test an indented directive sets the first column of its block
=begin pod
=begin nested :v<1>
Text at the column of the directive.
=end nested
=end pod
nested[ :v<1> ]
must find a block: the indented directive is recognisedcode
must find no block: text at the virtual margin is not indented and forms no code block=begin pod
=begin nested :v<2>
Text indented past the column of the directive.
=end nested
=end pod
code
must find a block: text indented past the virtual margin is a code blocktest the virtual margin of a block ends with it, and the margin of the enclosing block applies again
=begin pod
=head2 Shifted heading
Text indented to the column of the heading.
=end pod
code
must find a block: the heading has ended, so the indented text is a code block=begin pod
=head2 Shifted heading
Text at the margin of the enclosing block.
=end pod
para
must find a block: text at the margin of the enclosing block is a paragraphcode
must find no block: and no code block arisesA non-blank line other than a directive that starts left of its block's virtual margin is read as starting at that margin; Podlite parsers may issue a warning.
test a line left of the virtual margin stays in its block and is read as if at the margin
=begin pod
=begin nested
=config para :v<1>
Text at the margin of the nested block,
continued two columns to the left of it.
=end nested
=end pod
para[ :v<1> ]
must find a block: the paragraph stays in the nested block and gets its configurationpara[ :!?v ]
must find no block: no paragraph arises outside the nested blockcode
must find no block: the line left of the margin does not start a code block=begin pod
=begin nested
=config para :v<1>
Text that starts two columns to the left of the margin.
=end nested
=end pod
para[ :v<1> ]
must find a block: a first line left of the margin is a paragraph of the nested blockpara[ :!?v ]
must find no block: no paragraph arises outside the nested blockcode
must find no block: and no code block arisesThe 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 the mode of the enclosing block, or to "ambient" outside any block, 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
A =pod block nested in another groups the blocks it contains: the parser
stays in "pod" mode, the group has its own virtual margin and scope, and it adds
no formatting.
test a =pod block nested in another is a group with its own margin and scope
=begin pod
=config para :x<1>
Text inside the group.
=end pod
Text after the group.
pod
must find a block: the group is a block that a selector reachespara[ :x<1> ]
must find a block: the configuration inside the group reaches its paragraphpara[ :!?x ]
must find a block: after the group the configuration no longer applies=begin pod
=begin pod
Text at the margin of the group.
=end pod
=end pod
para
must find a block: the group has its own margin, so text at it is a paragraphcode
must find no block: and not a code block=begin pod
=begin pod
Text at the margin of the group.
=end pod
Text indented after the group.
=end pod
code
must find a block: after the group the margin of the enclosing block applies again, so the indented text is a code blockThe contents of files with the extensions .podlite and .pod6 are
implicitly wrapped in a =pod directive.
The implicit wrapper establishes the mode of parsing and is not a block that a
selector reaches. A selector applied to such a file finds only the blocks written
in it, so file:./part.podlite | pod selects nothing when the file contains no
explicit =pod block. A =pod block written in the file is reached like any
other block.
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.
test a file with the .md extension is read in Markdown mode
# Title
Some text.
=include file:./doc.md
head1
must find a block: a Markdown heading becomes a heading blockpara
must find a block: Markdown text becomes a paragraph# Title
head1
must find no block: in pod mode the same line is not a headingAny other file extension puts the parser in default mode. The =include
directive provides a mechanism to override this behavior
by using the :mime-type attribute for the included files.
test a file with another extension is read in default mode
Text outside any block.
=head1 Heading
=include file:./doc.txt
head1
must find a block: a directive is recognisedambient
must find a block: text outside a block is kept as an ambient blockpara
must find no block: and is not a paragraphtest a :mime-type on =include decides the mode instead of the extension
# Title
=include file:./doc.txt :mime-type('text/markdown')
head1
must find a block: read in Markdown mode, the line is a heading=include file:./doc.txt
head1
must find no block: read by its extension, in default mode, the line is not a headingDelimited 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:
| Value | Written as | Also accepted |
|---|---|---|
| Boolean | :key :!key | :key(True) :key(False) |
| Number | :key(42) | :key(2.3) |
| String | :key<str> | :key('str') :key"str" :key'str' :key「str」 |
| String with spaces | :key('str with spaces') | :key("str with spaces") :key'str with spaces' :key「str with spaces」 |
| List | :key<a b> | :key('a','b') |
| Hash, identifier keys | :key{:a<x>, :b(42), :c} | :key{a=>1, b=>'str', c=>True} |
| Hash, other keys | :key{1=>'x', 2=>'y'} |
test whitespace inside angle brackets separates the elements of a list
=for para :k<a b>
text
para[ :k~<a b> ]
must find a block: both elements are values of the attributepara[ :k<'a b'> ]
must find no block: the value is not one string holding the spaceThe first column of the table names the kind of the value. A rule that refers to the kind of a value refers to these names.
All option keys and values are constants: Podlite is a specification language, not a programming language. An option value cannot be a closure.
Whitespace surrounding a value is not significant and is removed. The delimiters that enclose a value determine how it is read.
A single word enclosed in angle brackets is not converted to another type. A
comma is retained as part of the value, so :key<a,b> is read as the
string a,b. Quotation marks delimit a string and suppress separation by
whitespace, which makes :key<'a b'> a string. Guillemets are not
quotation marks and are retained as part of the value.
test a comma inside angle brackets is part of the value
=for para :k<a,b>
text
para[ :k<a,b> ]
must find a block: the value is the string a,bpara[ :k~<a> ]
must find no block: the comma does not separate elementstest quotation marks inside angle brackets make one string
=for para :k<'a b'>
text
para[ :k('a b') ]
must find a block: the value is the string a bpara[ :k~<a> ]
must find no block: the space does not separate elementsA delimiter with nothing inside it carries the empty value of its kind, so
:key<> and :key() are an empty list and :key{} is an empty hash.
An empty string is written with quotation marks, as :key('').
test an empty delimiter carries the empty value of its kind
=for para :l<> :p() :h{} :s('')
text
para[ :?l :?p :?h :?s ]
must find a block: each empty value existspara[ :l ], para[ :p ], para[ :h ], para[ :s ]
must find no block: an empty value fails the test for a value neither empty nor falsepara[ :!l ], para[ :!p ], para[ :!h ], para[ :!s ]
must find no block: an empty value is not the value falseApart from True and False, an unquoted word is not a valid element of a
parenthesised list or value of a hash entry. Inside braces an option is read
as on the marker line: with no value it denotes the boolean true, and negated
it denotes the boolean false. The key of an option is an identifier.
A value that cannot be read is discarded together with its attribute, and parsing of the block continues. Podlite parsers issue a warning that identifies the position of the discarded value.
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. A value in parentheses or braces may continue on
such a line. A value in angle brackets or in quotation marks ends with its
line.
test configuration continues on a line that starts with = and whitespace
=begin para :one<a>
= :two<b>
text
=end para
para[ :one<a> :two<b> ]
must find a blocktest a value in parentheses continues on the next configuration line
=begin para :nums(1, 2,
= 3, 4)
text
=end para
para[ :nums(in 4) ]
must find a block: an element written on the continuation line belongs to the valuetest a value in angle brackets ends with its line
=begin para :k<a
= :ok<b>
text
=end para
para[ :ok<b> ]
must find a block: reading of the configuration continues after the unclosed valuepara[ :?k ]
must find no block: the unclosed value is discarded with its attributeThe 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,
=defn, =code,
and semantic blocks.
test indented contents of a =para block are not treated as code
=begin para :x<1>
indented body
=end para
para[ :x<1> ]
must find a block: the block is read with its configurationcode
must find no block: no code block arises inside ittest indented text after a blank line in a delimited =defn is a code block
=begin defn
virtual margin
indented body
=end defn
code
must find a block: the indented text is a code block=begin defn
virtual margin
not indented
=end defn
para
must find a block: without indentation the text is a paragraphcode
must find no block: and no code block arisesThe general syntax is:
=begin BLOCK_TYPE OPTIONAL CONFIG INFO
= OPTIONAL EXTRA CONFIG INFO
BLOCK CONTENTS
=end 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.
test a blank line ends a block introduced by =for
=begin pod
=for head2
Title
Text after the blank line.
=end pod
para
must find a block: the blank line ends the heading; the text after it lies between blocks and is a para block=begin pod
=for head2
Title
Text on the next line.
=end pod
para
must find no block: without the blank line the text is part of the contents of the heading and no para block arisestest a =for marker carries configuration for its block
=for para :x<1>
text
para[ :x<1> ]
must find a blockThe general syntax is:
=for BLOCK_TYPE OPTIONAL CONFIG INFO
= OPTIONAL EXTRA CONFIG INFO
BLOCK DATA
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).
test a blank line ends an abbreviated block
=begin pod
=head2 Title
Text after the blank line.
=end pod
para
must find a block: the blank line ends the heading; the text after it lies between blocks and is a para block=begin pod
=head2 Title
Text on the next line.
=end pod
para
must find no block: without the blank line the text is part of the contents of the heading and no para block arisesThe general syntax is:
=BLOCK_TYPE BLOCK DATA
MORE BLOCK DATA
For example:
=table
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.
test the rest of an abbreviated line is data, not configuration
=para :x<1> text
para
must find a block: the block is recognisedpara[ :?x ]
must find no block: no configuration is read from the lineBlock 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.
test each of the three forms yields a head2 block; the test does not tell the forms apart
=begin head2
Title
=end head2
head2
must find a block=for head2
Title
head2
must find a block=head2 Title
head2
must find a blockFor 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
or:
=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:
:caption- This option assigns a title to the given block, which is typically used to create a table of contents.
:id- This option enables the explicit definition of identifiers for blocks and use those IDs for linking purposes (see #Links).
:nested- 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:
- This can be simplified by giving the
:nestedoption a positive integer value: - 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:
- Note that
:!nestedcould also be used for this purpose:
=begin para :nested
=begin para :nested
=begin para :nested
"We're going deep, deep, deep undercover!"
=end para
=end para
=end para
=begin para :nested(3)
"We're going deep, deep, deep undercover!"
=end para
=comment Don't nest this code block in the usual way...
=begin code :nested(0)
1 2 3 4 5 6
123456789012345678901234567890123456789012345678901234567890
|------|-----------------------|---------------------------|
line instruction comments
number code
=end code
=Z<>begin code :!nested
test the value of :nested is read as a level or as false; only the value is checked
=begin para :nested(3)
text
=end para
para[ :nested(3) ]
must find a block: the attribute has the value 3=begin code :!nested
text
=end code
code[ :!nested ]
must find a block: the negated form gives the value false:numbered- 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. For a
block placed by
=include, the context is the document it is placed in.
:checked- This attribute indicates that a checkbox should be added to that block.
It is possible to apply a
:checkedattributes to any block. The most common use of this option is to create task lists. - For an unchecked checkbox the
:!checkedis used. - The task list item marker (checkbox) is added to the output.
In 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.
:folded- This option specifies that the block content is not presented
immediately but is available on demand. The attribute controls the
initial state:
:foldedor:folded(1)indicates the content is concealed by default;:!foldedor:folded(0)indicates it is revealed by default. - When applied to a heading block, the attribute governs the heading and all associated lower-level content, forming a hierarchical structure.
- In non-interactive contexts, the distinction may be expressed through visual means such as sidebar placement or reduced emphasis.
=for table :folded :caption('Culinary Techniques for Sustainability')
Sous-vide Low energy consumption
---------- -------------------------
Steaming Preserves nutrients
Baking Efficient for batch cooking
=for head2 :folded
Green Energy Overview
:lang- This option is used to provide information about the programming language used in a specific code block. This helps ensure 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
:langattribute: - If the language is not specified, the default language is used based on the file extension or MIME type of the file in which the block is written.
| Programming language | Possible :lang values |
|---|---|
| C++ | cpp |
| CSS | css |
| HTML | html |
| Java | java |
| JavaScript | javascript |
| Python | python |
| Raku | raku |
:allow- 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=codeblocks 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
A selector specifies a source, a list of block patterns, or both. A pattern
matches a block by name or by the universal *, optionally subject to a predicate.
The general syntax is:
EXTERNAL_SOURCE
or
[ EXTERNAL_SOURCE | ] BLOCKS_SELECTOR
...where
EXTERNAL_SOURCE - optional source of blocks for filtering, default current document,
BLOCK_SELECTOR - list of patterns; a pattern is a block name or the universal
*, optionally followed by a predicate
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.
| 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 the include directive.
A relative path in a file: source of a selector resolves against the file in
which that source is written, not the parent including document. This also
applies to a selector used as an operand of in. Within tests, the rules in
#Test blocks also apply.
test a relative path resolves against the file it is written in
=include file:./part.podlite
=head2 Inner
=head3 Wrong
=include file:./includes/guide.podlite
head2
must find a block: the file beside the including file is reachedhead3
must find no block: the file beside the parent is notA selector whose source is another file is applied without the configuration in effect in the document containing the selector.
test a selector on =include reads its source without the configuration of the including document
=para Plain.
=config para :v<1>
=include file:./part.podlite | para[ :v<1> ]
=for para :src<own>
After.
para[ :src<own> ]
must find a block: the paragraph of the including document is presentpara[ :!?src ]
must find no block: the source paragraph without a value for :v is not includedtest a selector reads a source whose own includes and configuration are resolved
=para Leaf.
=config para :v<part>
=include file:./leaf.podlite
=config para :v<book>
=include file:./part.podlite | para[ :v<part> ]
para[ :v<part> ]
must find a block: the nested included paragraph is selected with the value partpara[ :v<book> ]
must find no block: the value book from the including document does not replace the value partInternal addresses
An internal address follows a #, or the separator a scheme requires in its
place. It names a section or block in a document, a column in a table, or a
position or range in audio or video. Three parts of the reading are separate:
the syntax separates the address at the
#, and reads no further;the scheme resolves the source into content;
the format of that content reads the address.
A scheme may define the structure of its own address, and must then state so in its own description. If no such definition is given, the format reads the address.
Within a selector operand the separator is the #. The address is bounded by
whitespace, carries none of the characters that structure a selection, and is
never empty. A path containing a # cannot be written there, and no escape is
provided.
test an internal address in a selector operand ends at whitespace
=for para :id<first>
First.
=for para :id<second>
Second.
=include file:./part.podlite#second | para
para[ :id<second> ]
must find a block: the address is read up to the whitespace before the selectionpara[ :id<first> ]
must find no block: the other block of the file is not brought inIf the scheme is omitted, it is read as file:. The vertical bar required
before a selection is then what tells a source from a block name:
=include file:./guide.podlite#Overview
=include article.podlite | head1
test a source written without a scheme is read as file:
=head2 Part
=include part.podlite | head2
head2
must find a block: the file is readWithin a link markup code the address is bounded by what ends the code. Three rules bound it, and they apply in this order:
the vertical bar separates the link text;
the first whitespace immediately followed by
:begins the configuration;the matching closing angle bracket or brackets end the code.
What remains is the address: in L<the introduction|#intro :new> it is #intro.
An address the format does not recognise does not resolve, and the outcome is told from two others:
| What happened | What is reported |
|---|---|
| the source did not resolve | an error of resolution |
| the format is unknown | an error of format |
| no such address for that format | the address does not resolve |
None of the three yields an empty result. A condition carrying a selector reports a match or a non-match only if resolution, column selection and decoding all succeed.
If a data: source reads one column, the address names it by the heading its
MIME type declares present. If none is declared, no column has a name. Such an
address is read only if the content is tabular: data: reaches content of any
kind, and against an image it does not resolve. For example, a column addressed
by a declared heading:
=begin data :key<statuses> :mime-type('text/tab-separated-values; header=present')
value label
draft Draft
=end data
| Invoice[ :status(in data:statuses#value) ]
test a column of a data source is addressed by its declared heading
=begin data :key<statuses> :mime-type('text/tab-separated-values; header=present')
value label
draft Draft
=end data
=for Invoice :id<a> :status<draft>
A.
=for Invoice :id<b> :status<Draft>
B.
Invoice[ :id<a> :status(in data:statuses#value) ]
must find a block: a value in the addressed column selects the blockInvoice[ :id<b> :status(in data:statuses#value) ]
must find no block: a value only in another column does notInvoice[ :id<b> :status(in data:statuses#label) ]
must find a block: the other column, addressed by its heading, holds itPredicates
A pattern may carry a predicate. The predicate is written in square brackets
after the block name. It tests the configuration in effect for a block,
including options supplied by =config and =set, and does not distinguish
them from options written on the block. A block is
selected when its name matches the pattern and every condition of the
predicate holds.
test the selection of an include sees =set of the file it reads
=set :v<1>
=para Assigned.
=head1 Other
=include file:./part.podlite | *[ :v<1> ]
para
must find a block: the assigned paragraph is selectedhead1
must find no block: the block without the assignment is notConditions are written in the syntax of the block configuration table, so an operator means the same thing in a declaration and in a predicate.
| Written as | Holds when |
|---|---|
[ :attr ] | the attribute exists and its value is neither empty nor false |
[ :!attr ] | the value is false |
[ :?attr ] | the attribute exists, whatever its value |
[ :!?attr ] | the attribute does not exist |
[ :attr<value> ] | the value equals the operand |
[ :!attr<value> ] | the attribute exists and its value does not equal the operand |
[ :attr~<element> ] | the operand occurs among the values |
[ :attr(in V,W) ] | a value of the attribute is any of the operands |
test equality, negated equality, membership and in follow the operator table
=for para :id<p1> :v<one> :t<a b>
One.
=for para :id<p2> :v<two>
Two.
para[ :id<p1> :v<one> ]
must find a block: :attr<value> holds for an equal valuepara[ :id<p2> :v<one> ]
must find no block: and not for anotherpara[ :id<p2> :!v<one> ]
must find a block: :!attr<value> holds for a different valuepara[ :id<p1> :!v<one> ]
must find no block: an equal value does not satisfy negated equalitypara[ :id<p2> :!f<x> ]
must find no block: :!attr<value> does not hold when the attribute does not existpara[ :id<p1> :t~<b> ]
must find a block: ~<> holds for an element among the valuespara[ :id<p2> :v(in 'one','two') ]
must find a block: in holds for any operandPredicates are case-sensitive. No adjustment to case is provided.
test predicates are case-sensitive
=for para :v<Draft>
Text.
para[ :v<Draft> ]
must find a block: the value as written matchespara[ :v<draft> ]
must find no block: another case does notA predicate tests the block it is applied to, not the blocks within it. A
selected block keeps all of its content, and a negated condition does not remove
the blocks within it that fail the condition. In the following file, the
=pod block has no :draft option and is selected by *[ :!?draft ], and
the draft paragraph is brought in with it:
=begin pod
=for para :draft
Unfinished text.
=para Finished text.
=end pod
=include file:./part.podlite | *[ :!?draft ]
test a negated predicate does not remove blocks within a selected block
=begin pod
=for para :draft
Unfinished text.
=para Finished text.
=end pod
=include file:./part.podlite | *[ :!?draft ]
para[ :?draft ]
must find a block: the draft paragraph comes with the block that holds it=include file:./part.podlite | para[ :!?draft ]
para
must find a block: a paragraph without the option is selectedpara[ :?draft ]
must find no block: a paragraph tested by the predicate itself is left outA value containing whitespace is written in quotation marks, as it is in a declaration:
=include file:./guide.podlite | para[ :author('John Doe') ]
Universal pattern
The character * forms a universal pattern, which matches a block of any
name and stands in the position of a block name. It is used when the selection
is by configuration rather than by name:
=include file:./guide.podlite | *[ :platform<arm> ]
test the universal pattern selects blocks of any name by configuration
=for head1 :platform<arm>
Head.
=for para :platform<arm>
Para.
=for para :platform<x86>
Other.
=include file:./part.podlite | *[ :platform<arm> ]
head1
must find a block: a heading is selectedpara[ :platform<arm> ]
must find a block: a paragraph is selectedpara[ :platform<x86> ]
must find no block: a block failing the predicate is not* is not a valid identifier start, so a pattern and a block name cannot be
confused.
A universal pattern without a predicate selects every block and filters nothing.
test a universal pattern without a predicate selects every block
=head1 Title
=para Text.
=code x
=include file:./part.podlite | *
head1
must find a block: the heading is selectedpara
must find a block: the paragraph is selectedcode
must find a block: the code block is selectedWithin a single selection, one attribute may be encountered as several kinds of value, because a universal pattern matches blocks of every name. Every predicate is defined for every kind of value. The selection is not interrupted by a kind it does not expect.
Empty and absent values
An attribute that exists with an empty value is distinct from an attribute that does not exist and from one whose value is false. The following table states the outcome for each predicate:
| Declared as | [ :attr ] | [ :!attr ] | [ :?attr ] | [ :!?attr ] |
|---|---|---|---|---|
:attr<value> | true | false | true | false |
:attr(False) | false | true | true | false |
:attr<> | false | false | true | false |
:attr() | false | false | true | false |
:attr('') | false | false | true | false |
| not declared | false | false | false | true |
test a value, false, an empty value and no declaration give the outcomes the table states
=for para :id<value> :a<v>
.
=for para :id<false> :a(False)
.
=for para :id<empty> :a<>
.
=for para :id<empty-parens> :a()
.
=for para :id<empty-string> :a('')
.
=for para :id<none>
.
para[ :id<value> :a ]
must find a block: :attr holds for a valuepara[ :id<false> :a ], para[ :id<none> :a ]
must find no block: and not for false or no declarationpara[ :id<false> :!a ]
must find a block: :!attr holds for falsepara[ :id<value> :!a ], para[ :id<none> :!a ]
must find no block: and not for a value or no declarationpara[ :id<value> :?a ]
must find a block: :?attr holds for a valuepara[ :id<false> :?a ]
must find a block: and for falsepara[ :id<none> :?a ]
must find no block: and not for no declarationpara[ :id<none> :!?a ]
must find a block: :!?attr holds only for no declarationpara[ :id<value> :!?a ], para[ :id<false> :!?a ], para[ :id<empty> :!?a ], para[ :id<empty-parens> :!?a ], para[ :id<empty-string> :!?a ]
must find no block: and not for a value, false or an empty value of any notationNo predicate distinguishes an empty list from an empty string. An empty list holds no values. An empty string is one value of zero length. Both are false and both satisfy the tests above in the same way. The distinction is preserved in the document tree.
Membership
[ :attr~<V> ] holds when every element of V occurs among the values of
the attribute. Values present in the attribute and absent from the operand do
not affect the outcome. The condition states what is required to be present.
The condition says nothing about what is required to be absent.
The operand of ~<> is read by the
rule that governs any value. Whitespace inside the
operand separates a list. A single word is a string. Quotation marks produce
one element that may contain whitespace.
=for para :id<A> :tags<draft review>
=for para :id<B> :tags<draft review urgent>
=for para :id<C> :tags<draft>
=for para :id<D> :tags<'draft review'>
| para[ :tags~<draft> ] # A, B, C
| para[ :tags~<draft review> ] # A, B
| para[ :tags~<'draft review'> ] # D
An empty operand is an error and is reported when the selector is read. An empty list occurs among any set of values, so the condition would hold for every block and would test nothing.
Membership is not a test for a substring. [ :tags~<spec> ] does not hold for
:tags<specification>, and ~<> never falls back to comparing parts of a
value.
Addressing the keys of a hash is not defined. Applied to a hash, ~<> yields
no match.
test membership holds when every element of the operand is among the values
=for para :id<A> :tags<draft review>
.
=for para :id<B> :tags<draft review urgent>
.
=for para :id<C> :tags<draft>
.
=for para :id<D> :tags<'draft review'>
.
=for para :id<E> :tags<specification>
.
=for para :id<F> :h{draft => 1}
.
para[ :id<A> :tags~<draft review> ]
must find a block: both elements are among the valuespara[ :id<B> :tags~<draft review> ]
must find a block: a further value does not affect the outcomepara[ :id<C> :tags~<draft review> ], para[ :id<D> :tags~<draft review> ]
must find no block: one element alone, or one string holding both words, does not sufficepara[ :id<D> :tags~<'draft review'> ]
must find a block: quotation marks make the operand one elementpara[ :id<A> :tags~<'draft review'> ]
must find no block: two separate values are not that elementpara[ :tags~<spec> ]
must find no block: not a substringpara[ :tags~<specification> ]
must find a block: the whole value is an elementpara[ :h~<draft> ]
must find no block: a hash yields no matchpara[ :?h ]
must find a block: the hash attribute existsOperations in parentheses
The operation is named, and its operands follow the name inside parentheses:
| Invoice[ :author('John Doe') ] # a value
| Invoice[ :status(in 'draft','issued') ] # an operation
What follows the opening parenthesis is read as a value when it is one of the forms of the block configuration table. Every other name is the name of an operation. A name in that position which this specification does not define is an error and is reported when the selector is read.
| Written as | Holds when |
|---|---|
[ :attr(in V,W) ] | a value of the attribute is any of the operands |
in is written with one or more operands. An absent operand and an empty
operand are both errors and are reported when the selector is read.
Literal operands are separated by commas, as the block configuration table writes a list. Angle brackets instead separate values with whitespace.
The condition holds when at least one value of the attribute equals an operand. Other values do not affect the outcome, as in:
=for note :tags<approved secret>
| note[ :tags(in 'approved') ] # holds
test in holds when a value of the attribute equals an operand
=for para :id<a> :tags<approved secret>
A.
=for para :id<b> :tags<draft>
B.
para[ :id<a> :tags(in 'approved') ]
must find a block: other values of the attribute do not affect the outcomepara[ :id<b> :tags(in 'issued','draft') ]
must find a block: any of several operands sufficespara[ :id<b> :tags(in 'approved') ]
must find no block: no value equals an operandA literal operand is a number or a value in quotation marks. Alternatively, a selector supplies the values and is the sole operand. If the operand is a selector, the condition holds when a value of the attribute is one the selector yields:
=include file:./guide.podlite | Invoice[ :type(in file:./vocabulary.podlite | defn) ]
The term is taken from a definition, as definition lists state. Nothing is taken from a block whose kind defines no single value.
test a selector operand of in supplies the values
=defn draft
A draft.
=defn issued
Issued.
=para paid
=for Invoice :id<a> :type<draft>
A.
=for Invoice :id<b> :type<paid>
B.
=include file:./invoices.podlite | Invoice[ :type(in file:./vocabulary.podlite | defn, para) ]
Invoice[ :id<a> ]
must find a block: a value among the terms is selectedInvoice[ :id<b> ]
must find no block: a value outside them, written only in a block with no single value, is notA source is resolved and read before a condition carrying a selector reports a match or a non-match. Failure to resolve a source is an error; the source is not treated as empty. Such a failure establishes neither a match nor a non-match.
The rules for an internal address within an operand are stated in #Internal addresses.
Combining conditions
Whitespace separates one condition from the next. A block is selected only when every condition holds. Whitespace enclosed by brackets, by parentheses or by quotation marks belongs to the condition it appears in.
code[ :lang<python> :numbered ]
test a block is selected only when every condition holds
=for code :id<both> :lang<python> :numbered
x
=for code :id<one> :lang<python>
y
code[ :id<both> :lang<python> :numbered ]
must find a block: both conditions holdcode[ :id<one> :lang<python> :numbered ]
must find no block: one condition does not sufficeA comma separates whole patterns, and a block is selected when it matches any of them:
head1, head2, code[ :lang<python> ]
test a block is selected when it matches any of the patterns
=head1 Title
=for code :lang<python>
x
=for code :lang<perl>
y
=para Text.
=include file:./part.podlite | head1, code[ :lang<python> ]
head1
must find a block: the first pattern selectscode[ :lang<python> ]
must find a block: the second pattern selectscode[ :lang<perl> ], para
must find no block: a block matching neither is not selectedThe result is a set in document order. A block that matches more than one pattern appears once.
Non-matching conditions
A condition naming an attribute that no block declares holds for no block. No diagnostic is required.
test a condition naming an attribute no block declares holds for no block
=para Text.
para
must find a block: the paragraph is therepara[ :nosuch ], para[ :?nosuch ]
must find no block: a condition on an undeclared attribute selects nothingA value whose kind does not admit the test is reported as a non-match. The selection is not interrupted, which the universal pattern requires. Under it, values of unexpected kinds are encountered by construction.
test a value of a kind the test does not admit is a non-match and the selection goes on
=for para :id<hash> :v{a => 1}
Hash.
=for para :id<list> :v(1,2)
List.
=for para :id<string> :v<x>
String.
=include file:./part.podlite | *[ :v<x> ]
para[ :id<string> ]
must find a block: the block after the hash and the list is selectedpara[ :id<hash> ], para[ :id<list> ]
must find no block: the hash and the list are non-matchesBlock types
Podlite offers notations for specifying a wide range of standard block types...
Headings
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.
test every level of heading is recognized and kept apart from the others
=head2 Second level
head2
must find a block: the second-level heading is recognizedhead86, head1
must find no block: it is not taken for a heading of the first or the eighty-sixth level=head86 Eighty-sixth level
head86
must find a block: a heading at a level beyond the first four is recognizedhead2, head1
must find no block: it is not taken for a heading of the first or the second levelNumbered 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
Analysis
=for head3
Overview
=for head3
Details
=for head2 :numbered
Design
=for head1 :numbered
The Implementation
which would produce:
1. The Problem
2. The Solution
2.1. Analysis
Overview
Details
2.2: Design
3. The Implementation
test a heading written with :numbered carries the option
=for head1 :numbered
The Problem
head1[ :numbered ]
must find a block: the heading written with :numbered is selected by the optionIt 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:
2.3.8.6.1.9. 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, the first of which starts with a non-whitespace character at (virtual) column 1. The paragraph is terminated by the first blank line or Podlite 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 virtual margin of the enclosing block
The heading block ends at the blank line, and its virtual margin with it (see general syntactic structure).
test the first line decides an ordinary paragraph, and an indented line continues it
Plain text of a paragraph
continued on an indented line.
para
must find a block: the text is a paragraphcode
must find no block: the indented line does not start a code blockWithin 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):
=para
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.
In an abbreviated =item, text that begins on the directive line, together
with the lines that continue it, is an ordinary paragraph of that item.
test the text of an item is a para block in each of the three forms
=config para :x<1>
=item Abbreviated item text
para[ :x<1> ]
must find a block: the text on the directive line of an abbreviated item is a para block and gets the value 1 from =config=config para :x<1>
=item Abbreviated item text
continued abbreviated item text
para[ :x<1> ]
must find a block: the text of the abbreviated item with a continuation line is a para block and gets the value 1 from =config=config para :x<1>
=for item
For item text
continued for item text
para[ :x<1> ]
must find a block: the text of the =for item is a para block and gets the value 1 from =config=config para :x<1>
=begin item
Delimited item text
continued delimited item text
=end item
para[ :x<1> ]
must find a block: the text of the delimited item is a para block and gets the value 1 from =configtest an indented line under an abbreviated item continues its text
=item Happy
and glad
code
must find no block: the indented line does not start a code blockpara
must find a block: the text of the abbreviated item is a para block=begin item
Happy
and glad
=end item
code
must find a block: in a delimited item an indented line after a blank line is a code blockCode 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, the first of which starts with a whitespace character at the block's virtual left margin. The implicit code block is then terminated by a blank line or Podlite directive. For example:
This ordinary paragraph introduces a code block:
$this = 1 * code('block');
$which.is_specified(:by<indenting>);
Implicit code blocks may only be used within =pod, =item, =defn,
=nested, or semantic blocks. In the abbreviated and
paragraph forms of =item and =defn, unlike the delimited form, indented
text does not start an implicit code block.
test indented text inside =nested is a code block; the fixture has no =code, so only the implicit block can match
=begin nested
indented text
=end nested
code
must find a blocktest the first line decides an implicit code block, and a line at the margin continues it
my $x = 1;
say $x;
code
must find a block: the text is a code blockpara
must find no block: the line at the margin does not start a paragraphtest indented text in the abbreviated and paragraph forms of =item and =defn is text
=for item
Install the package first.
para
must find a block: the text of =for item is a paragraphcode
must find no block: and not a code block=item
Install the package first.
para
must find a block: the text of a bare =item is a paragraphcode
must find no block: and not a code block=defn virtual margin
The column at which a block's directive starts.
para
must find a block: the definition is a paragraphcode
must find no block: and not a code blockThere 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 {
say 'Hello 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.
test the :lang option carries the language of a code block
=begin code :lang<raku>
say 1;
=end code
code[ :lang<raku> ]
must find a blockFor 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.
test =input and =output are blocks of their own names
=begin input
ls -l
=end input
=begin output
total 0
=end output
input
must find a block: the input block is recognizedoutput
must find a block: the output block is recognizedNote 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
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:
• Animal
– Vertebrate
– Invertebrate
• Phase
– Solid
– Liquid
– Gas
– Chocolate
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
Visito
=for item2 :numbered
Veni
=for item2 :numbered
Vidi
=for item2 :numbered
Vici
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
I<????>
=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.
=defn
MORAL
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
SELFISH
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
Tables
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:
=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
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
Or:
=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:
=table
Superhero | Secret |
| Identity | Superpower
==============|=================|================================
The Shoveller | Eddie Stevens | King Arthur's singing shovel
Blue Raja | Geoffrey Smith | Master of cutlery
Mr Furious | Roy Orson | Ticking time bomb of fury
The Bowler | Carol Pinnsler | Haunted bowling ball
or with multi-line headers and multi-line data:
=begin table :caption('The Other Guys')
Secret
Superhero Identity Superpower
============= =============== ===================
The Shoveller Eddie Stevens King Arthur's
singing shovel
Blue Raja Geoffrey Smith Master of cutlery
Mr Furious Roy Orson Ticking time bomb
of fury
The Bowler Carol Pinnsler Haunted bowling ball
=end table
Advanced Table Format
Tables may be constructed 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:
:colspan- 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.
:rowspan- This attribute determines how many rows a cell should span vertically.
Cells with
:rowspancan cover multiple rows in a table, creating a vertical merge effect.
The following examples demonstrate how :colspan and :rowspan attributes
are used to create tables with merged cells, which is particularly 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
The resulting table is rendered as follows:
---------------------------------------------------------------
| 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
=para
A vehicle designed for space travel
=end row
=begin row
=Mermaid
graph TD;
A[Space Station] --> B[Mars Base]
A space station connected to a Mars base
=end row
=end table
Cell spanning attributes and nested block content within cells are semantic properties of the table document model and are preserved in the document tree.
For loading external CSV or TSV data into tables, use =data-table
(#Data-table blocks).
Error Recovery
The column separator type is determined per line. If visible separators
(| or +) are present, they are used; otherwise, sequences of two
or more consecutive whitespace characters serve as separators. Mixed
separator types across lines produce a warning; the table is not
rejected.
The expected cell count is established from the header row or, in its absence, the row with the most cells. Rows with fewer cells are padded with empty cells; rows with excess cells are truncated. In both cases, a warning is issued.
For =row/=cell tables, separator recovery does not apply, but
mismatched cell counts produce a warning.
For tables sourced from file: or data: references, three levels
of error are defined. If the source cannot be resolved, an error is
issued and the table is rendered as an empty block. If the source
cannot be interpreted as CSV, the content is rendered as a =code
block. If the CSV contains rows with unequal field counts, parsing
proceeds with padding for missing fields, and a warning is issued.
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
or:
=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.
Data-table blocks
The =data-table block renders CSV and TSV tables. It accepts
data in three forms: inline body, an external file via :src, or
a referenced =data block. :columns declares column projection;
:rename declares display name overrides.
The inline body form embeds the source data:
=begin data-table :mime-type('text/csv; header=present')
name,age,city
Alice,30,London
Bob,25,Paris
=end data-table
The external file form references a CSV or TSV file via the :src
option, as in:
=for data-table :src<file:./planets.csv>
= :columns<name radius_km>
= :caption('Inner planets')
The reference form refers to a named =data block:
=begin data :key<sales> :mime-type('text/csv; header=present')
quarter,region,revenue
Q1,EU,120
=end data
=for data-table :src<data:sales> :columns<quarter revenue>
The body is verbatim and is parsed per :mime-type using RFC 4180
for text/csv or RFC 4180 §3 for text/tab-separated-values.
The standard :allow option enables markup codes within each cell;
listed codes are interpreted after the cell is parsed from CSV or
TSV. Without :allow, cell content is plain text.
The :mime-type option declares the format. With :src<data:X>,
the format is taken from the referenced block unless a :mime-type
written on =data-table overrides it. A :mime-type supplied by
=config does not override the referenced format.
With :src<file:X.ext>, :mime-type may be omitted and is inferred
from the file extension. With :src<http:> or :src<https:>,
:mime-type may be omitted and is inferred from the HTTP
Content-Type response header. For inline body, :mime-type is
required.
Error recovery follows =table rules (#Error Recovery).
Each =data-table block can include the following attributes:
:src- This option declares the source URI. Accepted schemes are
file:for local files,data:for references to=datablocks by key,http:andhttps:for remote resources, anddoc:for cross-document references. When the scheme is omitted,file:is the default. For example: - Relative paths in
file:URIs resolve against the file declaring the directive, not the parent including document. For a URI supplied by=config, this is the file declaring that=config. - The
:srcoption and inline body content are mutually exclusive; declaring both produces an error at parse time.
:src<file:./planets.csv>
:src<data:sales>
:src<https://example.com/data.csv>
:columns- This option declares ordered column projection: which source columns appear in the output and in what order. Numeric indices refer to column position (1-based) in the source, not row position. For example:
- Output order matches list order; columns absent from the list are excluded. Omitting the option renders all source columns in their source order.
- An empty value for
:columnsproduces an error; omit the option to render all columns. Out-of-range indices produce an error.
:columns<product revenue>
:columns(1,3,5)
:columns<revenue product>
:rename- This option declares display name overrides for projected columns. The value is a hash mapping source identifiers, either names or indices, to display strings. For example:
- Only columns appearing as hash keys receive overrides; other columns
retain their source name when
header=presentor numeric index whenheader=absent. - Hash keys referring to columns absent from
:columns(or from the source when:columnsis omitted) produce an error.
:rename{revenue=>'USD'}
:rename{1=>'Time', 2=>'Action'}
:rename{product=>'Product name'}
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.
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>
name,month,amount
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>
id,name,position,department
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:
:filename- 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-typeis not explicitly provided.
:mime-type- This option indicates the MIME type of the data, such as
image/pngfor PNG images, which helps determine how the data should be interpreted and processed. - The
headerMIME parameter (per RFC 4180 §3) is recognised on:mime-typefor CSV and TSV content. It acceptspresentorabsent, with defaultabsent. Whenheader=present, the renderer treats the first row as column labels in=table data:X: - For
=data-tableblocks, the:mime-typeoption may be omitted when the format can be inferred from the source. With:src<file:X.ext>, the format is inferred from the file extension via the MIME extension table below; matching is case-insensitive and multi-dot filenames use the last extension component. With:src<http:>or:src<https:>, the format is inferred from the HTTPContent-Typeresponse header. For adata:source, see #Data-table blocks. - For inline body and for sources where inference fails (unknown file
extension, missing or generic HTTP
Content-Type, absent file extension),:mime-typeis required and its omission produces an error. An explicit:mime-typealways overrides inference. - Here is a list of common MIME types and their corresponding file extensions:
=begin data :key<planets> :mime-type('text/csv; header=present')
name,radius_km,moons
Mercury,2440,0
Venus,6052,0
Earth,6371,1
Mars,3390,2
=end data
=for table :caption('Inner planets')
data:planets
| 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 | |
| application/zip | .zip |
| audio/mpeg | .mp3 |
| video/mp4 | .mp4 |
| application/msword | .doc, .docx |
| text/csv | .csv |
| text/tab-separated-values | .tsv, .tab |
:access-timeand:modify-time- These attributes record the times when the data was last accessed or edited.
:encoding- This option specifies the encoding method used to store the data.
For non-text data, such as images in PNG format,
the encoding method
base64is 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>
iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAS0lEQVR4AWPOPfjpvWZSW4db
ZLk+kwTHP24HUQYGfi4WTiZVAcYfDtIMDCJc/38xK6TWth37wcrw7cufF8yeeWUGrL8Z33Ey
/t0HAMBnF2nt5sNRAAAAAElFTkSuQmCC
=end data
=picture data:Logo
In the example above, we have a =data block with :key 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, or source components.
Standard semantic blocks include:
=NAME
=AUTHOR
=VERSION
=SYNOPSIS
=DESCRIPTION
=USAGE
=INTERFACE
=METHOD
=SUBROUTINE
=OPTION
=DIAGNOSTIC
=ERROR
=WARNING
=DEPENDENCY
=BUG
=SEE-ALSO
=ACKNOWLEDGEMENT
=COPYRIGHT
=DISCLAIMER
=LICENCE
=LICENSE
=TITLE
=SECTION
=CHAPTER
=APPENDIX
=TOC
=INDEX
=FOREWORD
=SUMMARY
test a semantic block is a block of its uppercase name, in either form
=AUTHOR Jane Doe
=begin DESCRIPTION
What the module does.
=end DESCRIPTION
AUTHOR
must find a block: the abbreviated semantic block is recognizedDESCRIPTION
must find a block: the delimited semantic block is recognizedThe plural forms of each of these keywords are also reserved, and are aliases for the singular forms.
Most of these blocks are typically 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 creates 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.
The selector is applied to the document the block is in; a selector naming a source lists nothing.
A =toc block brought in by =include applies its selector to the
including document, not to the file in which it is written.
For example:
=toc head1, head2, head3, item1, item2, table
or:
=toc head1, head2, head3
The TOC displays without a caption by default.
However, a caption can be specified using the :caption
attribute of the =toc block.
For example:
=for toc :caption('Table of contents')
head1, head2, head3
The TOC entries are built using the :caption attribute content
within the block. If this attribute is not present, the text
presentation of the block's content serves as the TOC entry.
The depth of the generated TOC is determined by the "Selector" argument. The selector is processed, and headers or filtered blocks that allow levels are used to build the TOC levels. If a block lacks an associated level, it is rendered at a level one higher than the previous block with a level in the TOC.
Note that all semantic blocks are treated as equivalent
to head1 headings, and the =item1/=item equivalence is preserved.
The :folded-levels attribute indicates which levels 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 level 3 indicates that this level should
remain unfolded. Levels 2 and 4 are folded.
This configuration enables customized folding within the TOC.
The TOC is inserted at the location of the =toc block.
To enable the autogenerated TOC controlled by the renderer, set the :toc
document attribute for the =pod block. In this case, the specific configuration
and outcome of the TOC are determined by the renderer implementation.
Include directive
The =include directive enables reuse of specific parts of documents within
project sources. It is useful for complex documents that combine sections
from different files while maintaining overall context and structure.
The =include construct is classified as a directive, consistent with
=config and =alias. As a directive, =include references external
content rather than containing it directly.
The =include directive is followed by a "Selector" that specifies the
content to be included.
The blocks that the =include directive resolves to take the place of the
directive in the document that contains it, and selectors applied to that
document, including the selector of a table of contents, reach them.
The directive itself is not a block, and no selector reaches it, whether or
not it resolves.
test the =include directive is not a block, and no selector reaches it
=for para :v<included>
Included.
=include file:./part.podlite :mime-type('text/podlite')
=for para :v<own>
Own.
para[ :v<included> ]
must find a block: the block the include resolves to is reachedinclude
must find no block: the directive is not reached by its name when it resolves to blocks*[ :v<included> ]
must find a block: the universal pattern reaches the included block*[ :?mime-type ]
must find no block: the universal pattern does not reach the directive, which alone carries :mime-type=include file:./part.podlite | head1
=for para :v<own>
Own.
para[ :v<own> ]
must find a block: the block after an include that resolves to no block is reachedinclude
must find no block: the directive is not reached when it resolves to no blocktest a test brought by an include is a block of the document
=begin test :id<inner>
=for assert
para
=end test
=include file:./cases.podlite
test[ :id<inner> ]
must find a block: the included test is reached by a selectorA found block brings its content with it, whether or not the blocks within it match the selector. A block contained in another found block is not placed a second time: the included content consists of the found blocks that no other found block contains, in document order.
Relative file: sources follow the resolution rule in #Selectors.
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" enables inclusion of content from all the Markdown files:
=include file:./includes/*.md
test a wildcard source reads every matching file
# A
## B
=include file:./includes/*.md
head1
must find a block: the heading of the first file is brought inhead2
must find a block: the heading of the second file is brought inIt is possible to include blocks from the same document. 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 the 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, the :mime-type attribute
is placed on the directive line after the source URI. For example:
=include file:./includes/text.txt :mime-type('text/podlite')
The :mime-type attribute lets the parser handle files whose extension
does not match their actual type.
External content can introduce vulnerabilities such as code injection. Tools displaying included content should provide warnings. For this warning, content is external when it comes from a remote source or from a file outside the root directory the tool specifies. Blocks of the same document are not external. The warning names the source.
=set directives accumulated before =include apply to the first
block of the resolved included content (resolution-time targeting).
The =include directive itself does not receive =set attributes.
Full discipline: Block attribute assignment with =set.
Section boundaries
The =boundary directive marks a structural transition between major
document sections such as chapters, parts, or topics. The transition
is semantic, not presentational.
A =boundary is a directive, not a block. Hence, there is no
paragraph or delimited form of the =boundary directive. It accepts
an optional :caption attribute that describes the transition:
=boundary
=boundary :caption<BOUNDARY_DESCRIPTION>
Boundaries are placed between blocks, not within them, at the same structural level as the blocks they separate:
=head1 Chapter One
Content of chapter one.
=boundary
=head1 Chapter Two
Content of chapter two.
Rendering is format-specific. Renderers may use page breaks
(paginated output), thematic breaks (web), or separator lines (plain
text), and may ignore the directive when boundaries are not supported.
The :caption attribute is descriptive metadata; renderers may
surface it as a header, navigation entry, or omit it.
Test blocks
=test- A block stating a piece of source and one or more statements that must hold of what a parser makes of it.
The statements are written with selectors. A test contains one or
more =assert blocks. It may contain =fixture blocks, each a document an
assertion of it may be resolved against under the rule stated below. It may
contain =resource blocks if the subject of the test is the resolution of a
path:
=begin test :id<heading-carries-its-level>
=begin fixture
=head2 Overview
=end fixture
=for assert :caption('a second-level heading is recognised as such')
head2
=end test
test a test and the blocks it contains are blocks of the document they are written in
=begin test :id<inner>
=for resource :name<part.podlite>
Part text.
=begin fixture
=include file:./part.podlite
=end fixture
=for assert
para
=end test
=include file:./cases.podlite
test[ :id<inner> ]
must find a block: the test is a blockfixture
must find a block: its fixture is a blockassert
must find a block: its assertion is a blockresource[ :name<part.podlite> ]
must find a block: its resource is a blockA test containing no =assert does not pass. An implementation that does not
recognise a child of =test reports the test as skipped rather than failed; one
it recognises but cannot satisfy is a failure.
If a test of this specification differs from the rule it checks, the rule governs.
The blocks a test contains
=fixture- A verbatim block whose body is a document in its own right, carried as Podlite
source and read as a
.podlitefile.
The body of a =fixture is not processed by the document that holds it:
nothing in it is read as that document's markup and nothing in it is resolved.
It is still passed to the parser verbatim if an assertion is resolved
against the fixture. Anything a test requires besides the body is declared as
=resource and is not written into the body.
test the body of a fixture is not markup of the document holding it
=for head2 :v<outside>
Outside.
=begin test :id<inner>
=begin fixture
=for head2 :v<inside>
Inside.
=end fixture
=for assert
head2
=end test
=include file:./cases.podlite
head2[ :v<outside> ]
must find a block: a heading outside the fixture body is a blockfixture
must find a block: the fixture is a blockhead2[ :v<inside> ]
must find no block: a heading inside the fixture body is notTo test another mode from a fixture, the document is declared as a
=resource and brought in by =include; its mode follows the extension of
the resource name or a :mime-type on the =include.
test the body of a fixture is read as a .podlite file, in pod mode
Plain text.
para
must find a block: text between blocks is a paragraph# Title
head1
must find no block: a Markdown heading line is not a heading in pod modepara
must find a block: it is a paragraph=head1 Heading
head1
must find a block: the block written in the body is reachedpod
must find no block: the implicit wrapper is not a block a selector reachesA test may contain more than one =fixture. Only another =fixture ends the
reach of one, and whatever else stands between, child of the test or not, leaves
it unchanged.
test an assertion reads the nearest fixture before it until another fixture
=head1 First
head1
must find a block: the first fixture is readhead1
must find a block: a comment between leaves the first fixture read=head2 Second
head2
must find a block: the next fixture is readhead1
must find no block: the first fixture is no longer read=assert- A verbatim block carrying a selector expression.
An assertion holds according to whether it carries :absent:
Without
:absent, the assertion holds when the selector matches at least one block, and fails when it matches none.With
:absent, the assertion holds when the selector matches no block, and fails when it matches one or more.
If a test contains several =assert blocks, it passes when every assertion
holds. Their order among themselves carries no meaning; position relative to a
=fixture decides which document an assertion takes.
An assertion states that something is present somewhere in the document, not
that it holds for every block. A statement of that kind is written with
:absent over the opposite condition. That every invoice carries the attribute
:number is stated by requiring that none lacks it:
=for assert :absent
Invoice[ :!?number ]
test that every block meets a condition is stated with :absent over the opposite condition
=for Invoice :number<1>
First.
=for Invoice :number<2>
Second.
Invoice[ :?number ]
must find a block: the invoices are thereInvoice[ :!?number ]
must find no block: none lacks a number=for Invoice :number<1>
First.
=for Invoice
Second.
Invoice[ :!?number ]
must find a block: one lacking a number is found=resource- A verbatim block carrying content the test requires to be reachable by a path.
Two properties are fixed of a declared resource:
The name is reachable only while the body of a
=fixtureof the same test is read. A reference in that body, or inside a resource reached from it, obtains only what the test declares.How the content is made reachable is not fixed here, and an implementation that cannot write to a filesystem is not excluded.
test a fixture obtains the resource its own test declares under a name
=for para :v<first>
First test.
=include file:./part.podlite
para[ :v<first> ]
must find a block: the resource of this test is readpara[ :v<second> ]
must find no block: the resource of the same name in another test is nottest a resource declared under the same name by another test is not obtained
=for para :v<second>
Second test.
=include file:./part.podlite
para[ :v<second> ]
must find a block: the resource of this test is readpara[ :v<first> ]
must find no block: the resource of the same name in another test is notA resource is reached from the body of a fixture by the path it declares:
=begin test :id<include-reaches-resource>
=begin resource :name<includes/guide.podlite>
=head1 Guide
=end resource
=begin fixture
=include file:./includes/guide.podlite
=end fixture
=for assert
head1
=end test
A declared name is given relative to the body of the =fixture an assertion is
resolved against. A directive or markup code in that body resolves its relative
paths against the file declaring it, and not the parent including document.
Options
:id and :caption are the standard options
of those names. :id names a test; :caption records what a test, or a single
assertion, is for.
=begin test :id<value-comma-stays> :caption('a comma inside a value stays part of it')
=begin fixture
=for para :one<a,b>
text
=end fixture
=for assert :caption('the value is one string')
para[ :one<a,b> ]
=end test
:name- The path under which the content of a
=resourceis made reachable. Its form is the form of the reference that resolves it.
:absent- Written on an
=assert, gives the assertion its negative sense.
test the options of a test and of its blocks are their configuration
=begin test :id<inner> :caption('what the test is for')
=for resource :name<includes/part.podlite>
Part text.
=begin fixture
=include file:./includes/part.podlite
=end fixture
=for assert :caption('the paragraph is reached')
para
=for assert :absent :caption('what the assertion is for')
head1
=end test
=include file:./cases.podlite
test[ :id<inner> :caption('what the test is for') ]
must find a block: :id and :caption on a testassert[ :absent :caption('what the assertion is for') ]
must find a block: :absent and :caption on an assertionresource[ :name<includes/part.podlite> ]
must find a block: :name on a resourceThe document an assertion is resolved against
An assertion that names a source is resolved against that source. An assertion that names none is resolved against the document the implementation has made current.
Which document that is follows three cases in order:
a document supplied to the implementation from outside;
if none is supplied, the body of the
=fixturenearest preceding the assertion;if neither is present, the document in which the test sits.
test an assertion with no fixture before it reads the document holding the test
test[ :id<assertion-before-any-fixture-reads-the-holding-document> ]
must find a block: before any fixture, the document holding the test is read=head1 Body
head1
must find a block: after a fixture, its body is readtest
must find no block: and the document holding the test is notIf a document is supplied from outside, the bodies of =fixture are not
read as the input of the test. That a supplied document happens to be the one
containing the test does not change this.
The file the tests are taken from is not a supplied document. A document is supplied only if the implementation is told to examine it, separately from being told where to find the tests.
A failure against a =fixture is about the implementation: the text is fixed
and its reading is not. A failure against a supplied document is about the
document.
A relative path in the source of an assertion is resolved against the file the test is written in, and not among the declared resources of the test.
test a relative path in the source of an assertion resolves against the file the test is written in
=head3 Declared
=head1 Body
file:./test-blocks.podlite | test[ :id<assertion-source-resolves-against-the-test-file> ]
must find a block: the named source is read, not the fixture before the assertionfile:./test-blocks.podlite | head3
must find no block: the declared resource of the same name is not readAn assertion whose named source cannot be obtained does not hold, whether or not
it carries :absent. A missing source is not a document in which nothing
matched.
A document containing tests
If the document an assertion is resolved against is the one containing the
test, the =test blocks of that document are part of it and a selector reaches
them: an assertion written over every block of a document matches the tests
written in it.
test the tests of a document are blocks of it
*[ :id<tests-are-blocks-of-their-document> ]
must find a block: the universal pattern reaches the testWhen an implementation is given a file from which to obtain tests, the =test
blocks of that file are obtained after its =include directives are resolved.
A =test block obtained more than once, from different files given for a single
execution of the tests, is run once, if each time it is obtained each of its
assertions is resolved against a =fixture or against a source it names. Blocks
so obtained are one block if they originate from the same =test block in the
file in which it is written, under the same configuration in effect.
Different configurations give distinct blocks, and the test is run under each.
Walking a document does not run the tests found in it. An implementation
resolves the assertions of the test it was given, and a =test block met while
walking is not a test to obtain.
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
specified using different schemas: https: for remote images, file: for
local ones, or data: for embedded images in the document.
If no schema is provided, file: is used as default. For example:
=picture https://example.com/image.jpg
=picture file:/local/image.png
=picture /local/image.png
=picture data:Logo
In =picture and P<>, a relative file: path resolves against the file
in which the image reference is written, not the parent including document:
=picture ../image.png
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 the delimited form of =picture, multiple text blocks can be included:
=begin picture
astronaut.png
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
All inline markup codes supported by ordinary paragraph blocks can be used within picture captions.
A caption can also be defined using the :caption attribute:
=for picture :caption<diagram>
diag01.png
test =picture is a block, and :caption on it is an option of the block
=picture astronaut.png
picture
must find a block: the abbreviated picture block is recognized=for picture :caption<diagram>
diag01.png
picture[ :caption<diagram> ]
must find a block: the caption written as an attribute is an option of the picture blockMathematical 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.
=formula
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.
The formula caption can be defined using the :caption attribute:
=for formula :caption('Quadratic Formula')
x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
test =formula is a block, and :caption on it is an option of the block
=for formula :caption('Quadratic Formula')
x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
formula[ :caption('Quadratic Formula') ]
must find a block: the formula block carries its captionMarkdown 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:
```python
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.
Fenced code block attributes
Within markdown content, fenced code blocks may include Podlite configuration
attributes following the language identifier. The language identifier on the
opening fence line maps directly to the :lang attribute of the native
=code block.
test the language on an opening fence becomes the :lang of a code block
=begin markdown
```python
print(1)
```
=end markdown
code[ :lang<python> ]
must find a block ```python
def hello():
print("Hello")
```
This fenced code block is semantically equivalent to:
=begin code :lang<python>
def hello():
print("Hello")
=end code
Both backtick (```) and tilde (~~~) fence delimiters are supported.
The two forms are semantically identical.
test a tilde fence is read as a backtick fence is
=begin markdown
~~~rust
fn main() {}
~~~
=end markdown
code[ :lang<rust> ]
must find a blockExtended attributes may be specified after the language identifier using standard Podlite configuration syntax:
```python :line-numbers :highlight<2,5-7> :caption<Example>
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
```
This is equivalent to:
=begin code :lang<python> :line-numbers :highlight<2,5-7> :caption<Example>
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
=end code
All attributes defined for =code blocks in this specification are available
on fenced code blocks. The complete attribute syntax is described in the
block configuration table.
Implementation of extended attributes beyond the language identifier is optional. Parsers not supporting extended attributes parse the language identifier and either ignore trailing content or emit a warning, continuing processing in accordance with the graceful degradation principle.
| Markdown fence | Podlite equivalent |
|---|---|
```python | =code :lang<python> |
```javascript | =code :lang<javascript> |
``` | =code |
~~~rust | =code :lang<rust> |
Common attribute patterns found in various markdown implementations may be mapped to Podlite notation as follows:
| Function | Common pattern | Podlite equivalent |
|---|---|---|
| Line numbers | showLineNumbers | :line-numbers |
| Line numbers | .numberLines | :line-numbers |
| Start line | startFrom="N" | :start-line<N> |
| Highlight | {1,3-5} | :highlight<1,3-5> |
| Title | title="text" | :caption<text> |
| Element ID | #identifier | :id<identifier> |
| CSS class | .classname | :class<classname> |
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. A set of single
angles (<...>), a set of double angles («...»), or multiple
single-angles (<<<...>>>) can be used.
Within angle delimiters, you cannot use sequences of the same angle characters that are longer than the delimiters:
=comment
These are errors...
C< $foo<<bar>> >
The Perl 5 heredoc syntax was: C< <<END_MARKER >
Sequences of angles that are the same length as the delimiters can be used, but they must be balanced. For example:
C< $foo<bar> >
C<< $foo<<bar>> >>
If an unbalanced angle is needed, either use different delimiters:
C«$foo < $bar»
The Perl 5 heredoc syntax was: C« <<END_MARKER »
or delimiters with more consecutive angles than the 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
The code O<> can be used for strikethrough text, where 'O' stands
for "Overstrike." This indicates 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 for positioning characters or words.
To create subscript text, use the
J<>markup code, where 'J' represents "Junior text." Subscript positions one or more characters slightly below the normal line of type.HJ<2>OThis 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 likeH₂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 typeXH<2>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 inX².
Definitions
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 aT<>code are always space-preserved (as if they had an implicitS<...>around them). TheT<>code is the inline equivalent of the=outputblock.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 theT<>markup code) or with<kbd>...</kbd>tags. The contents of aK<>code are always space-preserved. TheK<>code is the inline equivalent of the=inputblock.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 afixed-width font(preferably a different font from that used for theT<>orK<>markup codes) or with<code>...</code>tags. The contents of aC<>code are space-preserved and verbatim. TheC<>code is the inline equivalent of the=codeblock.To include other markup codes in a
C<>code, the code can be lexically reconfigured:=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: C<%hashI<E<laquo>>keyI<E<raquo>>> =end paraTo enable entities in every
C<...>, place a=config C<> :allow<E>at the top of the document.The
R<>markup code specifies that the contained text is a replaceable item, placeholder, or 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>or:
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 theC<>code, unless theR<>is inside aK<>orT<>code (or the equivalent=inputor=outputblocks), 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 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.
Content masking
The G<> markup code marks an inline text fragment, and the
:masked attribute marks an entire block, as guarded. The original
content is preserved in the document model; only the rendered output is
concealed.
The mechanism provides presentation-layer concealment for sensitive content (API tokens, credentials, personally identifiable information, age-restricted material). It complements other security layers such as source file access controls and authenticated build pipelines.
The password is G<>hunter2 and must not be exposed.
=for BLOCKTYPE :masked
The mask character is determined by the renderer; the recommended default is U+2588 (█ FULL BLOCK). Whitespace structure is preserved in the masked output.
Two render modes are defined:
production mode (default): guarded content is concealed;
draft mode: guarded content is rendered visibly for editing and review.
Selection between modes is implementation-defined (renderer-controlled through command-line, environment, or interactive interface).
When G<> appears within a block marked :masked, both the inline and
surrounding content are concealed; the masking operation is idempotent.
Guard is a property of content, not of location. Content marked
with G<> or carrying :masked renders concealed wherever it
appears in rendered output. The rule applies when content is
reached through links, inclusion,
aliases, or data references.
The G<> code is not processed inside code blocks by default. To enable
masking in code blocks, the :allow<G> attribute is required on the
=code block (see :allow).
=begin code :lang<python> :allow<G>
api_key = "G<sk-12345>"
=end code
The G<> code marks content for concealment at render time but
does not protect it. The original text remains in plain form in
source files, document model, version control, and any consumer
that does not invoke the renderer. For cryptographic security or
access control, complementary mechanisms (file permissions,
encryption, authenticated access) are required.
Links
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. All three components are optional, though at least one must be present in any link specification.
When new addressing schemes are created specifically for Podlite, it is
strongly recommended that # be used to mark the start of internal
addresses.
The rules for the internal address and the outcomes of reading it are stated in #Internal addresses.
Standard schemes include:
http:andhttps:- A standard web URL. For example:
- If the link does not start with
//it is treated as being relative to the location of the document in which it is written, not the parent including document:
This module needs the LAME library
(available from L<http://www.mp3dev.org/mp3/>)
See also: L<http:tutorial/faq.html> and
L<http:../examples/index.html>
file:- A filename on the local system. For example:
- Filenames that don't begin with a
/or a~are relative to the location of the file in which the link is written, not the parent including document:
Next, edit the global config file (that is, either
L<file:/usr/local/lib/.configrc> or L<file:~/.configrc>).
Then, edit the local config file (that is, either
L<file:.configrc> or L<file:CONFIG/.configrc>.
mailto:- An email address. Typically, activating this type of link invokes a mailer. For example:
Please forward bug reports to L<mailto:devnull@rt.cpan.org>
man:- A link to the system manpages. For example:
This module implements the standard
Unix L<man:find(1)> facilities.
doc:- A link to other documents by utilizing semantic blocks
such as
=TITLEor=NAMEas anchor points for these links. - For example:
- Moreover, the
doc:scheme allows the use of an:idattribute within the=TITLEor=NAMEblocks 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: - Only a
=TITLEor=NAMEblock written in the document itself, at any depth, names it; one brought in by=includedoes not. A name that two documents carry does not resolve, and the error of resolution names the documents. - When Podlite processes a link, it can automatically use the document's title
from the
=TITLEor=NAMEblocks as the display text for the hyperlink if no explicit text is provided. For example: - ... will be rendered as:
=NAME Dumper
You may wish to use L<doc:Dumper> to
view the results.
=for TITLE :id<Specification>
The Specification of Podlite
...
Read the L<spec|doc:Specification>.
...
=for TITLE :id<Specification>
The Specification of Podlite
=para
Please read "L<doc:Specification>".
Please read "The Specification of Podlite".
defn:- A link to the block-form or inline definition of the specified term within the current document. For example:
- and later, to link back to the definition:
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)
To treat his chronic L<defn:lexiphania> the doctor prescribed an
immediate L<defn:glossoligation> or, if that proved ineffective,
a complete cephalectomy.
isbn:andissn:- 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
L<http://dev.perl.org/perl6/syn/S04.html#The_for_statement>
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 includes 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 addressing blocks
and creating links. An identifier that occurs twice in a document is an error.
=for head1 :id<intro>
Introduction
=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".
test an internal address in an include source names a block by its :id
=for para :id<first>
First.
=for para :id<second>
Second.
=include file:./part.podlite#second
para[ :id<second> ]
must find a block: the addressed block is brought inpara[ :id<first> ]
must find no block: the other block of the file is notNormally 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.
Contextual backlinks
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>
or:
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.
Link configuration attributes
The L<> and W<> markup codes may be extended with optional
configuration attributes following the link specification. These attributes
are specified using the standard Podlite configuration syntax.
The general form is:
L<[text|]linkspec [:attr1 :attr2<value> ...]>
W<[text|]linkspec [:attr1 :attr2<value> ...]>
The configuration portion begins at the first whitespace character that
is immediately followed by a colon (:). The substring preceding this
boundary constitutes the link specification. This boundary rule is
unambiguous because URL schemes begin with a letter character, not a colon,
and standard URLs do not contain space-colon sequences.
For example:
L<https://example.com :new>
In this example, the boundary occurs at the space before :new.
The following attributes are defined:
| Attribute | Type | Semantics |
|---|---|---|
| :new | Boolean | Resource is opened in a new navigation context |
| :title | String | Advisory information about the resource |
| :lang | String | Primary language of the linked resource |
| :download | Boolean/String | Resource is downloaded; string suggests filename |
For example:
L<API Reference|https://api.example.com :new :title('Official documentation')>
L<Download SDK|https://example.com/sdk.tar.gz :download<sdk-v2.tar.gz>>
L<French Guide|https://example.fr/guide :lang<fr>>
W<related term|defn:glossary :title('See definition')>
When the same attribute is specified both in =config L<> and in an
inline L<> instance, the inline value takes precedence:
=config L<> :new
=comment inherits :new
L<External|https://example.com>
=comment overrides to false
L<Internal|file:local.html :!new>
Link specifications containing literal spaces are required to be quoted.
The file: scheme commonly requires this treatment:
=comment correct
L<file:'my document.txt' :download>
Colons within URLs (such as port numbers or path parameters) are not preceded by whitespace and therefore do not trigger attribute parsing:
=comment :8080 is port
L<http://localhost:8080/api :new>
=comment :id is path
L<https://api.example.com/users/:id :title('User profile')>
Parsers that do not implement this extension treat the entire content
of L<> as a link specification. The link remains functional; only
metadata is lost. Renderers that encounter unknown attributes are
required to ignore them without error.
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 it—including any newline—is
preserved. These characters are also treated as being non-breaking
(except for the newlines, of course). For example:
The emergency signal is: S<
dot dot dot dash dash dash dot dot dot>.
would be formatted like so:
The emergency signal is: dot dot dot dash dash dash dot dot dot.
rather than:
The emergency signal is: dot dot dot dash dash dash dot dot dot.
Entities
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>
and E<RIGHT 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.
An index entry where the indexed text and the index entry differ can be specified 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.
Hierarchical index entries can be specified 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.
Multiple entries for a single indexed text can be specified 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.
Both notations describe one structure: a list of entries, each of which is a list of levels. The order of entries and the order of levels are significant. Whitespace adjacent to either separator is not part of a value.
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".
Annotations
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 present such annotations in various ways: as footnotes, endnotes, sidebars, pop-ups, tooltips, or expandable tags. They are never rendered as unmarked inline text. The previous example might be rendered as:
Space stations feature hydroponic gardens †, a necessity for long-term missions. and later:
Footnotes
† 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:
M< CONTENT-TEXT| R<MODULE_NAME> R<OPTIONAL CONFIG INFO>>
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<> markup 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:
=config BLOCK_TYPE CONFIG OPTIONS
= 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. It applies to the blocks of its type
that follow it within that scope, including blocks placed there by
=include.
test configuration in an included file does not reach the including file
=config para :v<1>
=para Included.
=include file:./part.podlite
=for para :src<parent>
After.
para[ :v<1> ]
must find a block: the included paragraph gets the value 1 from its own filepara[ :src<parent> ]
must find a block: the paragraph of the including document is presentpara[ :src<parent> :v<1> ]
must find no block: the paragraph of the including document does not get the value 1 from the included filetest only following blocks receive the =config value
=para Guest.
=include file:./guest.podlite
=config para :v<1>
=for para :src<own>
Own.
para[ :!?src ]
must find a block: the included paragraph is presentpara[ :!?src :v<1> ]
must find no block: the included paragraph does not get the value 1 from the following =configpara[ :src<own> :v<1> ]
must find a block: the paragraph after =config gets the value 1A block placed by =include is read with the configuration at the
directive, including :allow and the preconfiguration of markup codes.
An option takes its value from the first of these that sets it: an option
written on the block, a =set assignment, a =config setting, the default
of the option.
Among settings of one kind, the one nearest to the block takes precedence.
A =config in the block's file takes precedence over one in an including
file, and a nearer including file over a more distant one. The value taken
replaces any other for that option as a whole.
For example, a code block can override a preconfigured language:
=for code :lang<javascript>
print(JSON.stringify([1,2]]));
test =config applies to included blocks
=for para :src<plain>
Included.
=for para :src<own> :v<2>
Own.
=config para :v<1>
=include file:./part.podlite
para[ :!?v ]
must find no block: every included paragraph has a value for :vpara[ :src<plain> :v<1> ]
must find a block: the included paragraph without its own value gets the value 1 from the including =configpara[ :src<own> :v<2> ]
must find a block: the included paragraph keeps the value 2 written on ittest block attributes outrank =set, and =set outranks =config
=config para :v<config>
=set :v<set>
=for para :src<block> :v<block>
Written.
=set :v<set>
=for para :src<set>
Assigned.
=for para :src<config>
Configured.
para[ :src<block> :v<block> ]
must find a block: the block keeps the value block rather than the =set valuepara[ :src<set> :v<set> ]
must find a block: the =set value outranks the =config valuepara[ :src<config> :v<config> ]
must find a block: the =config value is used when neither the block nor =set specifies the optiontest an attribute written on an included block outranks =set before the include
=for head1 :v<own>
Included
=set :v<set>
=include file:./part.podlite
head1[ :v<own> ]
must find a block: the written value stayshead1[ :v<set> ]
must find no block: the assignment does not replace ittest =set before =include overrides =config of the included file
=config head1 :v<config>
=head1 Included
=set :v<set>
=include file:./part.podlite
head1[ :v<set> ]
must find a block: the assignment winshead1[ :v<config> ]
must find no block: the default of the included file yieldstest =config applies to included Markdown blocks and supplies the language of a code fence
Text.
```
x
```
=config para :v<outer>
=config code :lang<python>
=include file:./part.md
para[ :v<outer> ]
must find a block: the included Markdown paragraph gets the value outer from the including filepara[ :!?v ]
must find no block: every included Markdown paragraph has a value for :vcode[ :lang<python> ]
must find a block: the included code fence gets the value python for :lang from =configtest configuration in an included file outranks configuration in the including file
=config para :v<own>
=para Included.
=config para :v<book> :w<book>
=include file:./part.podlite
para[ :v<own> ]
must find a block: the included paragraph gets the value own for the shared keypara[ :v<book> ]
must find no block: the included paragraph does not get the value book from the including filepara[ :w<book> ]
must find a block: the included paragraph receives the value book for the key set only by the including filetest nearer including configuration outranks more distant configuration
=para Leaf.
=config para :v<part>
=include file:./chapter.podlite
=config para :v<book>
=include file:./part.podlite
para[ :v<part> ]
must find a block: the nested included paragraph gets the value part from the nearer including filepara[ :v<book> ]
must find no block: the nested included paragraph does not get the value book from the more distant including filetest the included value replaces the including value as a whole
=config para :v<c d>
=para Included.
=config para :v<a b>
=include file:./part.podlite
para[ :v~<c d> ]
must find a block: the included paragraph has both the values c and dpara[ :v~<a> ]
must find no block: the including value a is not retained in the included paragraphpara[ :v~<b> ]
must find no block: the including value b is not retained in the included paragraphPre-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.
For per-block attribute assignment that targets a single block instance rather than setting type-wide defaults, see Block attribute assignment with =set.
Block attribute assignment with =set
The =set directive assigns attribute values to the next block in
the same lexical scope. Like =config, it sets attributes for a
block; unlike =config, it targets a single block instance rather
than all blocks of a type. Attribute values may include multiline
content with inline markup codes.
test =set carried past an empty include does not leave the containing block
=para Only.
=begin nested
=set :v<1>
=include file:./part.podlite | head1
=end nested
=para After.
para
must find a block: the block after the container is therepara[ :v<1> ], nested[ :v<1> ]
must find no block: it does not receive the assignmentThe directive has two syntax variants. Configuration syntax uses standard delimited attribute values, for example:
=set :caption('Product comparison') :id<table-1>
=set :lang<en> :numbered
=begin table
...
=end table
Alias syntax permits multiline values with inline markup codes, for example:
=set :caption Selected chemical elements with their
= L<atomic numbers|#elements> and symbols
=begin table
Element Symbol Atomic Number
========= ====== =============
Hydrogen H 1
Carbon C 6
Oxygen O 8
=end table
Continuation lines (= followed by whitespace) extend multiline
alias values until the next non-continuation directive or a blank
line. Lines join into the final value before markup processing.
Both syntax variants may be mixed across continuation lines, as in
the following example combining configuration-syntax continuation
(= :folded<true>) with alias-syntax continuation:
=set :id<special-table>
= :folded<true>
=set :caption Product Performance Metrics
= with detailed analysis
=begin table
...
=end table
The table receives all three attributes (:id, :folded, :caption).
When multiple =set directives assign the same attribute key, the last
assignment wins, regardless of syntax variant.
test a =set after an empty include overrides the carried one
=para Only.
=set :v<1>
=include file:./part.podlite | head1
=set :v<2>
=head2 After
head2[ :v<2> ]
must find a block: the later value winshead2[ :v<1> ]
must find no block: the carried value is overriddenDirectives (=set, =config, =alias, =include, =boundary)
and =comment blocks are transparent to =set targeting and do not
consume the assignment, except an =include directive that fails to
resolve. For example:
=set :caption Renewable energy sources
=config table :width<100%>
=alias COMPANY Acme Corp
=comment Approved
=begin table
Source Type
========= ==========
Solar photovoltaic
Wind turbine
=end table
The =table block receives the :caption attribute despite the
intervening directives and =comment.
test directives and comments between =set and a block do not take the assignment
=set :caption Renewable energy sources
=config table :width<100%>
=alias COMPANY Acme Corp
=comment Approved
=begin table
Source Type
========= ==========
Solar photovoltaic
Wind turbine
=end table
table[ :?caption ]
must find a block: the table receives the captionFor =include, attributes apply to the first block of the resolved
included content, under the same rules of transparency. If there is no such
block, they pass on to the next block after the =include directive.
test =set before =include goes to the first included block that is not transparent
=comment note
=head1 Included
=head2 Second
=set :v<1>
=include file:./part.podlite
=para After.
head1[ :v<1> ]
must find a block: the included heading receives the assignmenthead2
must find a block: the second included block is presenthead2[ :v<1> ]
must find no block: the second included block does not receive the assignmentpara
must find a block: the block after the include is therepara[ :v<1> ]
must find no block: the next block does not receive ittest an include that resolves to nothing passes =set on to the next block
=para Only.
=set :v<1>
=include file:./part.podlite | head1
=head2 After
head2[ :v<1> ]
must find a block: the next block receives the assignmenttest an included file holding only comments passes =set on
=comment first
=comment second
=set :v<1>
=include file:./notes.podlite
=head2 After
head2[ :v<1> ]
must find a block: the next block receives the assignmentIf the =include directive fails to resolve, for any reason, the attributes are not applied.
Their non-application is reported with that failure, instead of a warning that
the =set directive has no target.
=set directives inside an included file are lexically scoped to that file
and do not leak to the parent file. On the first included block, assignments
from that file override those accumulated before =include for the same key.
test assignments in an included file outrank earlier assignments for the same key
=set :v<inner> :w<inner>
=head1 Included
=set :v<outer> :x<outer>
=include file:./part.podlite
head1[ :v<inner> ]
must find a block: the included heading gets the value inner from the nearer assignmenthead1[ :v<outer> ]
must find no block: the included heading does not get the value outer for the shared keyhead1[ :w<inner> ]
must find a block: the included heading keeps the value inner for the key set only insidehead1[ :x<outer> ]
must find a block: the included heading receives the value outer for the key set before =includetest =set at the end of an included file does not reach the parent
=head1 Included
=set :v<1>
=include file:./part.podlite
=para After.
para
must find a block: the block after the include is therepara[ :v<1> ]
must find no block: it does not receive the assignmentIf no block follows before the end of the containing block or file,
parsers issue a warning that the =set directive has no target.
Aliases
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 or file,
including blocks placed there by =include.
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. The replacement text can extend over multiple
lines by starting each following line with an = (at the same level
of indentation as the =alias directive itself) followed by at least
one whitespace. Each additional line uses the original
line's (virtual) left margin, as specified by the indentation of the
replacement text on the =alias line.
For example:
=alias PROGNAME Earl Irradiatem Evermore
=alias VENDOR 4D Kingdoms
=alias TERMS_URLS =item L<http://www.4dk.com/eie>
= =item L<http://www.4dk.co.uk/eie.io/>
= =item L<http://www.fordecay.ch/canttouchthis>
The use of A<PROGNAME> is subject to the terms and conditions
laid out by A<VENDOR>, as specified at:
A<TERMS_URLS>
This would produce:
The use of Earl Irradiatem Evermore is subject to the terms and conditions laid out by 4D Kingdoms Inc, as specified at:
The advantage of using aliases is that the same alias can be reused in multiple places in the documentation. If the replacement text needs to be changed, it requires modification in only 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 attention to different types of content, such as tips, warnings, or important notes.
To create specially formatted blocks highlighting information in Podlite,
the =nested block and :notice attribute are used.
For example:
=begin nested :notice<tip>
Remember to always use oven mitts when handling hot bakeware
to prevent burns.
=end nested
test the :notice attribute of a =nested block carries the notification type
=begin nested :notice<tip>
Text.
=end nested
nested[ :notice<tip> ]
must find a block: the block written with :notice is selected by its notification typeBelow is a table outlining the different types of notification blocks along with a brief description of each type.
| 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.
The title of the block and visibility of the information can be customized
using the :caption and :folded options.
=begin nested :caption("Astronaut's Reminder") :notice<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
Title-only callouts can be created by omitting the body.
=for nested :notice<important> :folded :caption("Title-only callout")
Notification blocks are displayed with distinctive colors and icons that indicate the significance of the content.
SUMMARY
Directives
| Directive | Specifies |
|---|---|
=begin | Start of an explicitly terminated block |
=config | Pre-configuration of following blocks of a type, or of a markup code |
=set | Attribute assignment to the next block |
=end | Explicit termination of a =begin block |
=for | Start of an implicitly (blank-line) terminated block |
=alias | Define a Podlite macro |
=include | Include content from other sources |
=boundary | Marker for a structural section boundary |
Blocks
| 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 | Nested block contents within the current context |
=output | Pre-formatted sample output |
=para | Ordinary paragraph |
=pod | No "ambient" blocks inside |
=table | Simple rectangular table |
=row | Row in advanced table format |
=cell | Cell within a =row block |
=data | Data section |
=data-table | Tabular rendering of CSV or TSV data |
=toc | Autogenerated table of contents |
=picture | Insert pictures |
=formula | Mathematical formulas |
=markdown | Markdown support |
=test | Statements required to hold of a piece of source |
=fixture | Source supplied to a test |
=assert | Condition a test requires of a document |
=resource | Content a test requires to be reachable by a path |
=RESERVED | Semantic blocks (=SYNOPSIS, =BUGS, etc.) |
=Typename | User-defined block |
Inline markup codes
| Markup 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<defined term|synonym;synonym;...>) |
E<...;...> | Entity names or numeric codepoints (E<entity1;entity2;...>), emoji |
F<...> | Mathematical formula |
G<...> | Guard inline content (concealed in published output) |
H<...> | Superscript |
I<...> | Important (typically rendered in italics) |
J<...> | Subscript |
K<...> | Keyboard input (typically rendered fixed-width) |
L<...|...> | Link (L<display text|destination URI>) |
M<...:...> | Module-defined code (M<scheme:contents>) |
N<...> | Note (not rendered inline) |
O<...> | Strikethrough |
P<...> | Inline eqivalent for =picture block |
Q<> | reserved |
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<...> | Verbatim (internal markup codes ignored) |
W<...|...> | Contextual backlinks |
X<...|..,..;...> | Index entry (X<display text|entry,subentry;...>) |
Y<> | Reserved |
Z<...> | Zero-width comment (contents never rendered) |
- an indented directive sets the first column of its block
- the virtual margin of a block ends with it, and the margin of the enclosing block applies again
- a line left of the virtual margin stays in its block and is read as if at the margin
- a =pod block nested in another is a group with its own margin and scope
- a file with the .md extension is read in Markdown mode
- a file with another extension is read in default mode
- a :mime-type on =include decides the mode instead of the extension
- whitespace inside angle brackets separates the elements of a list
- a comma inside angle brackets is part of the value
- quotation marks inside angle brackets make one string
- an empty delimiter carries the empty value of its kind
- configuration continues on a line that starts with = and whitespace
- a value in parentheses continues on the next configuration line
- a value in angle brackets ends with its line
- indented contents of a =para block are not treated as code
- indented text after a blank line in a delimited =defn is a code block
- a blank line ends a block introduced by =for
- a =for marker carries configuration for its block
- a blank line ends an abbreviated block
- the rest of an abbreviated line is data, not configuration
- each of the three forms yields a head2 block; the test does not tell the forms apart
- the value of :nested is read as a level or as false; only the value is checked
- a relative path resolves against the file it is written in
- a selector on =include reads its source without the configuration of the including document
- a selector reads a source whose own includes and configuration are resolved
- an internal address in a selector operand ends at whitespace
- a source written without a scheme is read as file:
- a column of a data source is addressed by its declared heading
- the selection of an include sees =set of the file it reads
- equality, negated equality, membership and in follow the operator table
- predicates are case-sensitive
- a negated predicate does not remove blocks within a selected block
- the universal pattern selects blocks of any name by configuration
- a universal pattern without a predicate selects every block
- a value, false, an empty value and no declaration give the outcomes the table states
- membership holds when every element of the operand is among the values
- in holds when a value of the attribute equals an operand
- a selector operand of in supplies the values
- a block is selected only when every condition holds
- a block is selected when it matches any of the patterns
- a condition naming an attribute no block declares holds for no block
- a value of a kind the test does not admit is a non-match and the selection goes on
- every level of heading is recognized and kept apart from the others
- a heading written with :numbered carries the option
- the first line decides an ordinary paragraph, and an indented line continues it
- the text of an item is a para block in each of the three forms
- an indented line under an abbreviated item continues its text
- indented text inside =nested is a code block; the fixture has no =code, so only the implicit block can match
- the first line decides an implicit code block, and a line at the margin continues it
- indented text in the abbreviated and paragraph forms of =item and =defn is text
- the :lang option carries the language of a code block
- =input and =output are blocks of their own names
- a semantic block is a block of its uppercase name, in either form
- the =include directive is not a block, and no selector reaches it
- a test brought by an include is a block of the document
- a wildcard source reads every matching file
- a test and the blocks it contains are blocks of the document they are written in
- the body of a fixture is not markup of the document holding it
- the body of a fixture is read as a .podlite file, in pod mode
- an assertion reads the nearest fixture before it until another fixture
- that every block meets a condition is stated with :absent over the opposite condition
- a fixture obtains the resource its own test declares under a name
- a resource declared under the same name by another test is not obtained
- the options of a test and of its blocks are their configuration
- an assertion with no fixture before it reads the document holding the test
- a relative path in the source of an assertion resolves against the file the test is written in
- the tests of a document are blocks of it
- =picture is a block, and :caption on it is an option of the block
- =formula is a block, and :caption on it is an option of the block
- the language on an opening fence becomes the :lang of a code block
- a tilde fence is read as a backtick fence is
- an internal address in an include source names a block by its :id
- configuration in an included file does not reach the including file
- only following blocks receive the =config value
- =config applies to included blocks
- block attributes outrank =set, and =set outranks =config
- an attribute written on an included block outranks =set before the include
- =set before =include overrides =config of the included file
- =config applies to included Markdown blocks and supplies the language of a code fence
- configuration in an included file outranks configuration in the including file
- nearer including configuration outranks more distant configuration
- the included value replaces the including value as a whole
- =set carried past an empty include does not leave the containing block
- a =set after an empty include overrides the carried one
- directives and comments between =set and a block do not take the assignment
- =set before =include goes to the first included block that is not transparent
- an include that resolves to nothing passes =set on to the next block
- an included file holding only comments passes =set on
- assignments in an included file outrank earlier assignments for the same key
- =set at the end of an included file does not reach the parent
- the :notice attribute of a =nested block carries the notification type
LICENSE
Artistic license 2.0