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

NAME

Text::Multi - Transform a file containing a mixture of markup types into HTML

SYNOPSIS

  use Text::Multi;
  my $parser = Text::Multi->new(
    default_type => 'Markdown',
    detailed     => 1,
  );
  print $multi->render;

DESCRIPTION

This module formats text files that contain a mixture of different types of text markup. This allows, for example, for you to write a blog entry in markdown, with sample code being formatted by an appropriate syntax-coloring system.

Text::Multi itself only uses a single type of tag which indicates a change in processor type. It usually looks like this:

  {{{ BlockType }}}

or like this:

  {{{ BlockType param=option }}}

The first word is the type of block, and indicates the subclass of Text::Multi::Block that should be used to process the following section of text. Any parameters following the blocktype are optional, and the options available depend on the processing module. There are some options common to all block processors, so check the documentation for Text::Multi::Block as well as for the individual subclasses.

You can also use a blank tag, like so:

  {{{ }}}

Any amount of whitespace in a blank tag is ignored. A blank tag indicates that the previous block is ending. While processing a document, new tags are kept on a stack so that as a block ends the previous block can continue.

An example would probably clarify that last paragraph.

  {{{ Markdown }}}
  
  Markdown text, describing the code that follows.
  
  {{{ Code lang=perl }}}
  #!/usr/bin/perl -w
  use strict;
  use warnings;
  # This is some dumb perl code
  print <<"END";
  {{{ Code lang=html }}}
  <html>
  <head>
  <title>HTML</title>
  </head>
  <body>
  This will be syntax-colored as HTML.
  </body>
  </html>
  {{{ }}}
  END
  # This is the end of the dumb perl code
  {{{ }}}

  This is more Markdown.

METHODS

new( %options );

Create a new Text::Multi object.

import( $class, @configuration );

Text::Multi defines an import() method that accepts additional configuration information both for itself and for the block types you intend to use. You can use it like this:

  use Text::Multi (
    { default_type => 'Code', detailed => 1 },
    'Code' => { starting_line_number => 1 },
  );

The configuration entries are processed according to these rules:

  1. If the first option is a hashref, it is shift()ed off the array, and the parameters it contains are used to configure Text::Multi itself.

  2. Each remaining element of the array is examined in turn. If the value is a scalar, it is assumed to contain a block type, and the corresponding class will be loaded. If the value is a hashref, it's parameters are used to configure the preceding block type.

For example, this use line:

  use Text::Multi (
    { default_type => 'Code', detailed => 1 },
    'Code' => { starting_line_number => 1 },
    qw( Pod Metadata Markdown ),
  );

Is roughly equivalent to this code:

  use Text::Multi;
  Text::Multi->default_type( 'Code' );
  Text::Multi->detailed( 1 );
  use Text::Multi::Block::Code;
  Text::Multi::Block::Code->starting_line_number( 1 );
  use Text::Multi::Block::Pod;
  use Text::Multi::Block::Metadata;
  use Text::Multi::Block::Markdown;

default_type( $type );

Get or set a default block type. This is used to determine what type of block should be used for rendering any content that appears before the first opening tag, or after the last closing tag. For example...

  This text would be rendered using whatever the default_type type of
  block is.
  
  {{{ Markdown }}}
  
  This would be rendered as Markdown.
  
  {{{ }}}
  
  This is the default_type again.

You can think of the default_type as adding an implicit block around the entire document. If not specified, the default type is 'Markdown'.

default_args( $hashref );

For any content that is rendered using the default_type, this option specifies any optional parameters to be used to configure the default object.

For example, this code would implicitly wrap the whole document in a default {{{ Code starting_line_number=1 }}} block.

  Text::Multi->default_type( 'Code' );
  Text::Multi->default_args( { starting_line_number => 1 } );

detailed( $value );

Get or set the value of the 'detailed' parameter. If this is true then the HTML output from render() will precede each rendered block with an HTML comment containing the original text. This is primarily a debugging feature.

process_file( $filename );

Process the text in the provided filename.

process_fh( $filehandle );

Read the text to be processed from the provided filehandle.

process_text( $text );

Process the text contained in the provided scalar variable.

render();

The render method collects all the blocks from the source provided by "process_file", "process_fh", or "process_text" and returns the formatted HTML.

css_inline();

Each Text::Multi::Block has the option to provide a CSS file to be used in conjunction with the rendered HTML. The css_inline method collects the contents of these files for each block type used in the source text, and returns them in a concatenated form, suitable for including in a <style> tag.

css_files();

Similar to "css_inline", this method returns the path to the css files for each block type.

find_blocks( %params );

This method takes a hash of parameters, and returns as a list all the blocks which have the parameters indicated. For example, if called as

  my @blocks = $tm->find_blocks( type => 'Markdown', section => 'summary' )

Would return any block with a tag like

  {{{ Markdown section=summary }}}

get_blocks();

Returns the block objects that make up the current file.

block_type_map();

The block_type_map provides a means of changing the names or processors for different block types. By default a block marked like this:

  {{{ Markdown }}}

would be rendered using the Text::Multi::Block::Markdown formatter. If you wanted to use a different formatter for Markdown syntax, you could remap the Markdown type like this:

  $tm->block_type_map( { Markdown => 'MyMarkdown' } );

Then the call to 'Markdown' would use a formatter called Text::Multi::Block::MyMarkdown instead.

If your block subclass does not live in the Text::Multi::Block namespace, you can prefix it's name with a +, then it won't have "Text::Multi::Block" prepended:

  $tm->block_type_map->{ 'Wiki' } = '+MyApp::Formatter::Text::Wiki';

INTERNAL METHODS

You generally don't need to do anything with these methods, they will be called at the appropriate times.

make_blocks();

Called automatically by "process_file", "process_fh", and "process_text". This method does the actual processing of the text and turns it into block objects.

block_class( $type );

Returns the class name for a given block type, ensuring that the class is laoded first.

make_meta( $text );

Processes the arguments given to a block start tag, and returns a hashref of the options. For example, given the start tag

  {{{ Markdown section=summary }}}

make_meta would return (after running through "dump" in Data::Dump).

  ( section => 'summary' )

SEE ALSO

Text::Multi::Block

http://www.jasonkohles.com/software/Text-Multi/

SUPPORT

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

    perldoc Text::Multi

You can also look for information at:

BUGS

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

KNOWN BUGS

  • There aren't really any tests yet.

AUTHOR

Jason Kohles, <email@jasonkohles.com>, http://www.jasonkohles.com/

COPYRIGHT AND LICENSE

Copyright (C) 2007-2008 Jason Kohles.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.