Pod-Confluence

 view release on metacpan or  search on metacpan

lib/Pod/Confluence.pm  view on Meta::CPAN

    );

    return join( '',
        "<ac:structured-macro ac:name='$name' ac:schema-version='$self->{confluence_schema_version}'",
        ( $options{self_close} ? ' /' : '' ), ">", @optional_elements );
}

sub end_B {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('</strong>');
}

sub end_C {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('</code>');
}

sub end_F {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('</em>');
}

sub end_head1 {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('</h1>');
    pop( @{ $self->{element_stack} } );
}

sub end_head2 {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('</h2>');
    pop( @{ $self->{element_stack} } );
}

sub end_head3 {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('</h3>');
    pop( @{ $self->{element_stack} } );
}

sub end_head4 {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('</h4>');
    pop( @{ $self->{element_stack} } );
}

sub end_I {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('</em>');
}

sub end_item_text {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('</strong>');
    $self->end_Para();
}

sub end_L {
    my ( $self, $attribute_hash ) = @_;
    if ( $self->{link_type} eq 'pod' ) {
        $self->{in_cdata} = 0;
        $self->_print( ']]></ac:plain-text-link-body>' . '</ac:link>' );
    }
    elsif ( $self->{link_type} eq 'url' ) {
        $self->_print('</a>');
    }
    delete( $self->{link_type} );
}

sub end_over_text {
    my ( $self, $attribute_hash ) = @_;
    $self->{indent} -= 2;
}

sub end_Para {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('</p>');
    pop( @{ $self->{element_stack} } );
}

sub end_S {
    my ( $self, $attribute_hash ) = @_;
    $self->{in_non_breaking} = 0;
}

sub end_Verbatim {
    my ( $self, $attribute_hash ) = @_;
    $self->{in_cdata} = 0;
    $self->_print( $self->_confluence_macro_end( has_text => 1 ) );
    pop( @{ $self->{element_stack} } );
}

sub _handle_element_end {
    $logger->tracef( '_handle_element_end(%s,%s)', $_[1], $_[2] );
    Pod::Simple::Methody::_handle_element_end(@_);
}

sub _handle_element_start {
    $logger->tracef( '_handle_element_start(%s,%s)', $_[1], $_[2] );
    Pod::Simple::Methody::_handle_element_start(@_);
}

sub handle_text {
    my ( $self, $text ) = @_;

    $text = encode_entities($text) unless ( $self->{in_cdata} );
    $text =~ s/[ \t]/&nbsp;/g if ( $self->{in_non_breaking} );

    $logger->tracef( 'handle_text(%s)', $text );
    $self->_print($text);
}

sub _init {
    my ( $self, %options ) = @_;

    $self->{space_key} = $options{space_key};
    $self->{packages_in_space} =
        { map { $_ => 1 } @{ $options{packages_in_space} } };
    $self->{confluence_schema_version} = $options{confluence_schema_version} || 1;

    $self->{element_stack} = [];
    $self->{indent}        = 0;

    return $self;
}

sub _print {
    my ( $self, $text ) = @_;
    print( { $self->{output_fh} } $text );
}

sub start_B {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('<strong>');
}

sub start_C {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('<code>');
}

sub start_F {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('<em>');
}

sub start_Document {
    my ( $self, $attribute_hash ) = @_;
    $self->_print( '<p>' . $self->_confluence_macro_start( 'toc', self_close => 1 ) . '</p>' );
}

sub start_head1 {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('<h1>');
    $self->{indent} = 0;
}

sub start_head2 {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('<h2>');
    $self->{indent} = 0;
}

sub start_head3 {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('<h3>');
    $self->{indent} = 0;
}

sub start_head4 {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('<h4>');
    $self->{indent} = 0;
}

sub start_I {
    my ( $self, $attribute_hash ) = @_;
    $self->_print('<em>');
}

sub start_item_text {
    my ( $self, $attribute_hash ) = @_;
    $self->{indent} -= 1;
    $self->start_Para();
    $self->{indent} += 1;
    $self->_print('<strong>');
}

sub start_L {
    my ( $self, $attribute_hash ) = @_;
    $self->{link_type} = $attribute_hash->{type};
    if ( $attribute_hash->{type} eq 'pod' ) {
        my $to = $attribute_hash->{to};
        if ( !$to || $self->{packages_in_space}{"$to"} ) {
            $self->{link_type} = 'pod';
            $self->_print(
                (   $attribute_hash->{section}
                    ? "<ac:link ac:anchor='$attribute_hash->{section}'>"
                    : '<ac:link>'
                )
                . ( $to ? "<ri:page ri:content-title='$to' ri:space-key='$self->{space_key}'/>"
                    : ''
                    )
                    . '<ac:plain-text-link-body><![CDATA['
            );
            $self->{in_cdata} = 1;
        }
        else {
            my $url = $to ? "https://metacpan.org/pod/$to" : '';
            my $section = $attribute_hash->{section};
            if ($section) {
                $section =~ s/[^a-zA-Z0-9]+/-/g;
                $section =~ s/-$//g;
                $url .= "#$section";
            }
            $self->{link_type} = 'url';
            $self->_print("<a href='$url'>");
        }
    }
    elsif ( $attribute_hash->{type} eq 'url' ) {
        $self->{link_type} = 'url';
        $self->_print("<a href='$attribute_hash->{to}'>");
    }
}

sub start_over_text {
    my ( $self, $attribute_hash ) = @_;
    $self->{indent} += 2;
}

sub start_Para {
    my ( $self, $attribute_hash ) = @_;
    my $style;
    if ( $self->{indent} ) {
        $style = 'style="margin-left: ' . ( $self->{indent} * 30 ) . 'px;"';
    }
    $self->_print( $style ? "<p $style>" : '<p>' );
}

sub start_S {
    my ( $self, $attribute_hash ) = @_;
    $self->{in_non_breaking} = 1;
}

sub start_Verbatim {
    my ( $self, $attribute_hash ) = @_;
    $self->_print(
        $self->_confluence_macro_start(
            'code',
            has_text   => 1,
            parameters => { language => 'perl' }
        )
    );
    $self->{in_cdata} = 1;
}

1;

__END__

=pod

=head1 NAME

Pod::Confluence - Converts pod to confluence flavored markdown

=head1 VERSION

version 1.01

=head1 SYNOPSIS

    my $parser = Pod::Confluence->new(
        space_key => 'FooPod',
        packages_in_space => [
            'Foo',
            'Foo::Bar',
            'Foo::Baz',
        ]);

    my $structured_storage_markdown;
    $parser->output_string(\$structured_storage_markdown);
    $parser->parse_file('/path/to/Foo.pm');

=head1 DESCRIPTION

This module uses L<Pod::Simple> to convert POD to Confluence structured 
storage format.  The output can be cut/paste into the source view of a page,
or you can use the Confluence API to push directly to the server.

=head1 CONSTRUCTORS

=head2 new(%options)

Creates a new parser to process POD into markdown.  Available options are:

=over 4

=item space_key

The C<spaceKey> from the Confluence space this page will be added to.  This
is necessary to ensure all the links between pages are properly generated.

=item packages_in_space

This is a list of all the packages that will be in this space.  When a POD 
link is encountered, this list will be checked.  If the package is in the
list, a local link will be generated.  Otherwise, the link will point to
metacpan.

=back

=head1 AUTHOR



( run in 2.279 seconds using v1.01-cache-2.11-cpan-6aa56a78535 )