The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.


Text::PageLayout - Distribute paragraphs onto pages, with headers and footers.


    use 5.010;
    use Text::PageLayout;

    my @paragraphs = ("a\nb\nc\nd\n") x 6,

    # simple example
    my $layout = Text::PageLayout->new(
        page_size   => 20,      # number of lines per page
        header      => "head\n",
        footer      => "foot\n",
        paragraphs  => \@paragraphs,    # REQUIRED

    for my $p ( $layout->pages ) {
        say "Page No. ", $p->page_number;
        say $p;

    # more complex example:
    sub header {
        my %param = @_;
        if ($param{page_number} == 1) {
            return "header for first page\n";
        return "== page %d of %d == \n";
    sub process_template {
        my %param = @_;
        my $t = $param{template};
        if ($t =~ /%/) {
            return sprintf $t, $param{page_number}, $param{total_pages};
        else {
            return $t;
    sub split_paragraph {
        my %param = @_;
        my ($first, $rest) = split /\n\n/, $param{paragraph}, 2;
        return ("$first\n", $rest);

    $layout = Text::PageLayout->new(
        page_size           => 42,
        tolerance           => 2,
        paragraphs          => [ ... ],
        separator           => "\n\n",
        footer              => "\nCopyright (C) 2014 by M. Lenz\n",
        header              => \&header,
        process_template    => \&process_template,
        split_paragraph     => \&split_paragraph,


Text::PageLayout breaks up a list of paragraphs into pages. It supports headers and footers, possibly varying by page number.

It operates under the assumption that all text blocks that are passed to (header, footer, paragraphs, separator) are either the empty string, or terminated by a newline. It also assumes that all those text blocks are properly line-wrapped already.

The header and footer can either be strings, or subroutines that will be called, and must return the string that is then used as a header or a footer. In both cases, the string that is used as header or footer can be post-processed with a custom callback process_template.

The layout of a result page is always the header first, then as many paragraphs as fit on the page, separated by separator, followed by as many blank lines as necessary to fill the page (if fillup_pages is set, which it is by default), followed by the footer.

If the naive layouting algorithm (take as many paragraphs as fit) leaves more than tolerance empty fill lines, the split_paragraph callback is called, which can attempt to split the paragraph into small chunks, which are nicer to format.


Attributes should be set in the constructor (Text::PageLayout->new), but most of them can also be set later on, for example the page_size attribute with $layout->page_size(42).

Note that all callbacks receive named arguments, i.e. are called like this:

        page_number => 1,
        total_pages => 2,

Callbacks must accept additional named arguments (future versions of this module might pass more arguments).


Max. number of lines on a result page.

Default: 67


Number of empty lines to accept on a page before attempting to split paragraphs.

Default: 6 (subject to change)


An array reference of paragraphs (newline-terminated strings) that is to be split up in pages.

This attribute is required.

A string that is used as a per-page header (or header template, if process_template is set), or a callback that returns the header.

If used as a callback, it receives page_number as a named argument.

Default: empty string.

A string that is used as a per-page footer (or footer template, if process_template is set), or a callback that returns the footer.

If used as a callback, it receives page_number as a named argument.

Default: empty string.


If set to a true value, pages are filled up to their maximum length by adding newlines before the footer.

Default: 1.


A string that is used to separate multiple paragraphs on the same page.

Default: "\n" (newline)


A callback that can split a paragraph into smaller chunks to create nicer layouts. If paragraphs exist that exceed the number of free lines on a page that only contains header or footer, this callback must split such a paragraph into smaller chunks, the first of which must fit on a page.

The return value must be a list of paragraphs.

It receives the arguments paragraph, max_lines and page_number. max_lines is the maximal number of lines that fit on the current page.

The default split_paragraph simply splits off the first max_lines as a sparate chunk, without any consideration for its content.


A callback that turns a header or footer template into the actual header or footer. It receives the named arguments template, element (which can be header or footer), page_number and total_pages.

It must return a string with the same number of lines as the template.

The default template callback simply returns the template.



Creates a new Text::PageLayout object. Expects attributes as named arguments, with paragraphs being the only required attribute.


Returns a list of Text::PageLayout::Page objects (which you can use like strings, if you want to).


Moritz Lenz, <moritz at>


Please report any bugs or feature requests to bug-text-pagelayout at, or through the web interface at I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


You can find documentation for this module with the perldoc command.

    perldoc Text::PageLayout

You can also look for information at:


Thanks to noris network AG for letting the author develop and open-source this module.


Copyright 2014 Moritz Lenz. Written for noris network AG.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See for more information.


Development happens at github, see Pull requests welcome!