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 )