Markdown-Parser
view release on metacpan or search on metacpan
lib/Markdown/Parser.pm view on Meta::CPAN
## We save what we caught to put it back in case the abbreviation lookup failed
my $catch = substr( $data, $-[0], $+[0] - $-[0] );
if( defined( my $abbr = $self->document->get_abbreviation( $re->{abbr_name} ) ) )
{
my $id = $self->document->add_object( $abbr->clone );
"${PH_PREFIX}${id}${PH_SUFFIX}";
}
# Failed somehow
else
{
"$catch";
}
}xge;
}
$self->message_colour( 3, "{orange}", ( $top->tag_name eq 'top' ? 'Parsing' : 'Sub-parsing' ), " done.{/}" );
if( $top->tag_name eq 'top' )
{
# We need to separate parsing of footnotes' text in a second step, so we do this here
$top->footnotes->foreach(sub
{
$_->parse( $self );
});
}
# NOTE: ultra fast parsing
my $object_re = qr/\Q${PH_PREFIX}\E(?<object_id>\d+)\Q${PH_SUFFIX}\E/;
my $parts = [ split( m/${object_re}\n?/, $data ) ];
$self->message( 3, "Parts are: '", join( "', '", @$parts ), "'." );
my $objects = $self->document->objects;
for( my $n = 0; $n < scalar( @$parts ); $n++ )
{
# When $n is an even number, it means this is a text, otherwise it is an object id
# If this is a text, we create a text object and add it to the tree
if( $n % 2 )
{
my $id = $parts->[ $n ];
next if( !length( $id ) );
my $obj = $objects->get( $id );
if( ref( $obj ) )
{
$cb->( $obj );
$top->add_element( $obj );
}
else
{
$self->message_colour( 3, "{bold red}No object found for id \"", $id, "\"!{/}" );
}
}
else
{
my $obj = $top->create_text({
text => $parts->[ $n ],
});
$cb->( $obj );
$top->add_element( $obj );
}
}
# Depth-first expansion, repeat until no changes (handles cascades)
my $changed = 1;
my $walk;
$walk = sub
{
my( $node ) = @_;
# Recurse into container children first (depth-first)
if( $node->can( 'children' ) && $node->children->length )
{
# Children list may mutate while we insert; iterate by index
my $i = 0;
while( $i < $node->children->length )
{
my $child = $node->children->get( $i );
$walk->( $child );
# If structure changed, do not increment blindly
$i++;
}
}
# Only interested in Text nodes that might contain placeholders
return if( !$node->isa( 'Markdown::Parser::Text' ) );
my $txt = $node->text->scalar // '';
return if( $txt !~ /$object_re/ );
# Split into text / id / text / id / ... / text
my @parts = split( /$object_re/, $txt );
# First piece stays in current node
my $head = shift( @parts );
$node->text( $head );
my $cursor = $node;
while( @parts )
{
my $id = shift( @parts );
# may be undef at end
my $after = shift( @parts );
my $obj = $self->document->objects->get( $id );
if( $obj )
{
# Splice the referenced object right after the cursor
$node->parent->insert_after( $cursor, $obj );
$cursor = $obj;
$changed = 1;
}
else
{
# Unknown id: keep literal placeholder (safer than dropping)
my $lit = $node->parent->create_text({ text => "${PH_PREFIX}${id}${PH_SUFFIX}" });
$node->parent->insert_after( $cursor, $lit );
$cursor = $lit;
}
if( defined( $after ) && length( $after ) )
{
( run in 0.492 second using v1.01-cache-2.11-cpan-df04353d9ac )