App-Ikachan
view release on metacpan or search on metacpan
inc/Pod/Markdown.pm view on Meta::CPAN
#line 1
# vim: set ts=4 sts=4 sw=4 expandtab smarttab:
#
# This file is part of Pod-Markdown
#
# This software is copyright (c) 2004 by Marcel Gruenauer.
#
# This is free software; you can redistribute it and/or modify it under
# the same terms as the Perl 5 programming language system itself.
#
use 5.008;
use strict;
use warnings;
package Pod::Markdown;
{
$Pod::Markdown::VERSION = '1.322';
}
# git description: v1.321-4-geed8814
BEGIN {
$Pod::Markdown::AUTHORITY = 'cpan:RWSTAUNER';
}
# ABSTRACT: Convert POD to Markdown
use parent qw(Pod::Parser);
use Pod::ParseLink (); # core
sub initialize {
my $self = shift;
$self->SUPER::initialize(@_);
$self->_private;
$self;
}
sub _private {
my $self = shift;
$self->{_MyParser} ||= {
Text => [], # final text
Indent => 0, # list indent levels counter
ListType => '-', # character on every item
searching => '' , # what are we searching for? (title, author etc.)
sstack => [] , # Stack for searching, needed for nested list
Title => undef, # page title
Author => undef, # page author
};
}
sub as_markdown {
my ($parser, %args) = @_;
my $data = $parser->_private;
my $lines = $data->{Text};
my @header;
if ($args{with_meta}) {
@header = $parser->_build_markdown_head;
}
join("\n" x 2, @header, @{$lines}) . "\n";
}
sub _build_markdown_head {
my $parser = shift;
my $data = $parser->_private;
return join "\n",
inc/Pod/Markdown.pm view on Meta::CPAN
# the headers never are indented
$parser->_save($parser->format_header($level, $paragraph));
if ($level == 1) {
if ($paragraph =~ m{NAME}xmsi) {
$data->{searching} = 'title';
} elsif ($paragraph =~ m{AUTHOR}xmsi) {
$data->{searching} = 'author';
} else {
$data->{searching} = '';
}
}
}
# opening a list ?
elsif ($command =~ m{over}xms) {
# update indent level
$data->{Indent}++;
push @{$data->{sstack}}, $data->{searching};
# closing a list ?
} elsif ($command =~ m{back}xms) {
# decrement indent level
$data->{Indent}--;
$data->{searching} = pop @{$data->{sstack}};
} elsif ($command =~ m{item}xms) {
# this strips the POD list head; the searching=listhead will insert markdown's
# FIXME: this does not account for named lists
# Assuming that POD is correctly wrtitten, we just use POD list head as markdown's
$data->{ListType} = '-'; # Default
if($paragraph =~ m{^[ \t]* \* [ \t]*}xms) {
$paragraph =~ s{^[ \t]* \* [ \t]*}{}xms;
} elsif($paragraph =~ m{^[ \t]* (\d+\.) [ \t]*}xms) {
$data->{ListType} = $1; # For numbered list only
$paragraph =~ s{^[ \t]* \d+\. [ \t]*}{}xms;
}
if ($data->{searching} eq 'listpara') {
$data->{searching} = 'listheadhuddled';
}
else {
$data->{searching} = 'listhead';
}
if (length $paragraph) {
$parser->textblock($paragraph, $line_num);
}
}
# ignore other commands
return;
}
sub verbatim {
my ($parser, $paragraph) = @_;
# NOTE: perlpodspec says parsers should expand tabs by default
# NOTE: Apparently Pod::Parser does not. should we?
# NOTE: this might be s/^\t/" " x 8/e, but what about tabs inside the para?
# POD verbatim can start with any number of spaces (or tabs)
# markdown should be 4 spaces (or a tab)
# so indent any paragraphs so that all lines start with at least 4 spaces
my @lines = split /\n/, $paragraph;
my $indent = ' ' x 4;
foreach my $line ( @lines ){
next unless $line =~ m/^( +)/;
# find the smallest indentation
$indent = $1 if length($1) < length($indent);
}
if( (my $smallest = length($indent)) < 4 ){
# invert to get what needs to be prepended
$indent = ' ' x (4 - $smallest);
# leave tabs alone
$paragraph = join "\n", map { /^\t/ ? $_ : $indent . $_ } @lines;
}
$parser->_save($paragraph);
}
sub _escape_and_interpolate {
my ($parser, $paragraph, $line_num) = @_;
# escape markdown characters in text sequences except for inline code
$paragraph = join '', $parser->parse_text(
{ -expand_text => '_escape_non_code' },
$paragraph, $line_num
)->raw_text;
# interpolate the paragraph for embedded sequences
$paragraph = $parser->interpolate($paragraph, $line_num);
return $paragraph;
}
sub _escape_non_code {
my ($parser, $text, $ptree) = @_;
$text = $parser->_escape($text)
unless $ptree->isa('Pod::InteriorSequence') && $ptree->cmd_name eq 'C';
return $text;
}
sub textblock {
my ($parser, $paragraph, $line_num) = @_;
my $data = $parser->_private;
my $prelisthead;
$paragraph = $parser->_escape_and_interpolate($paragraph, $line_num);
# clean the empty lines
$paragraph = $parser->_clean_text($paragraph);
# searching ?
if ($data->{searching} =~ m{title|author}xms) {
$data->{ ucfirst $data->{searching} } = $paragraph;
$data->{searching} = '';
} elsif ($data->{searching} =~ m{listhead(huddled)?$}xms) {
my $is_huddled = $1;
$paragraph = sprintf '%s %s', $data->{ListType}, $paragraph;
if ($is_huddled) {
# To compress into an item in order to avoid "\n\n" insertion.
$prelisthead = $parser->_unsave();
} else {
$prelisthead = '';
}
$data->{searching} = 'listpara';
} elsif ($data->{searching} eq 'listpara') {
$data->{searching} = '';
}
# save the text
$parser->_save($paragraph, $prelisthead);
}
sub interior_sequence {
my ($self, $seq_command, $seq_argument, $pod_seq) = @_;
# nested links are not allowed
return sprintf '%s<%s>', $seq_command, $seq_argument
if $seq_command eq 'L' && $self->_private->{InsideLink};
my $i = 2;
my %interiors = (
'I' => sub { return '_' . $_[$i] . '_' }, # italic
'B' => sub { return '__' . $_[$i] . '__' }, # bold
'C' => sub { return '`' . $_[$i] . '`' }, # monospace
( run in 0.321 second using v1.01-cache-2.11-cpan-96521ef73a4 )