) for Markdown to process.
+ s,$_escape{lt_re}((?=$EMAIL_MARKER)|(?:[a-z/?\$!])?),
+ $1 ? '<'.$2 : $2 ? '<'.$2 : '<',egos;
+ }
+
+ return $_;
+}
+
+
+## Parsing ##
+
+sub handle_text {
+ my $self = $_[0];
+ my $stash = $self->_private;
+ local $_ = $_[1];
+
+ # Unless we're in a code span, verbatim block, or formatted region.
+ unless( $stash->{no_escape} ){
+
+ # We could, in theory, alter what gets escaped according to context
+ # (for example, escape square brackets (but not parens) inside link text).
+ # The markdown produced might look slightly nicer but either way you're
+ # at the whim of the markdown processor to interpret things correctly.
+ # For now just escape everything.
+
+ # Don't let literal characters be interpreted as markdown.
+ $_ = $self->_escape_inline_markdown($_);
+
+ # Entity-encode (or escape for later processing) necessary/desired chars.
+ $_ = $self->_encode_or_escape_entities($_);
+
+ }
+ # If this _is_ a code section, do limited/specific handling.
+ else {
+ # Always escaping these chars ensures that we won't mangle the text
+ # in the unlikely event that a sequence matching our escape occurred in the
+ # input stream (since we're going to escape it and then unescape it).
+ s/&/$_escape{amp_code}/gos if $stash->{encode_amp};
+ s/$_escape{lt_code}/gos if $stash->{encode_lt};
+ }
+
+ $self->_save($_);
+}
+
+sub start_Document {
+ my ($self) = @_;
+ $self->_new_stack;
+}
+
+sub end_Document {
+ my ($self) = @_;
+ $self->_check_search_header;
+ my $end = pop @{ $self->_private->{stacks} };
+
+ @{ $self->_private->{stacks} } == 0
+ or die 'Document ended with stacks remaining';
+
+ my @doc = $self->_chomp_all(join('', @$end)) . $/;
+
+ if( $self->include_meta_tags ){
+ unshift @doc, $self->_build_markdown_head, ($/ x 2);
+ }
+
+ if( my $encoding = $self->_get_output_encoding ){
+ # Do the check outside the loop(s) for efficiency.
+ my $ents = $HAS_HTML_ENTITIES ? \&__entity_encode_ord_he : \&__entity_encode_ord_basic;
+ # Iterate indices to avoid copying large strings.
+ for my $i ( 0 .. $#doc ){
+ print { $self->{output_fh} } Encode::encode($encoding, $doc[$i], $ents);
+ }
+ }
+ else {
+ print { $self->{output_fh} } @doc;
+ }
+}
+
+sub _get_output_encoding {
+ my ($self) = @_;
+
+ # If 'match_encoding' is set we need to return an encoding.
+ # If pod has no =encoding, Pod::Simple will guess if it sees a high-bit char.
+ # If there are no high-bit chars, encoding is undef.
+ # Use detected_encoding() rather than encoding() because if Pod::Simple
+ # can't use whatever encoding was specified, we probably can't either.
+ # Fallback to 'o_e' if no match is found. This gives the user the choice,
+ # since otherwise there would be no reason to specify 'o_e' *and* 'm_e'.
+ # Fallback to UTF-8 since it is a reasonable default these days.
+
+ return $self->detected_encoding || $self->output_encoding || 'UTF-8'
+ if $self->match_encoding;
+
+ # If output encoding wasn't specified, return false.
+ return $self->output_encoding;
+}
+
+## Blocks ##
+
+sub start_Verbatim {
+ my ($self) = @_;
+ $self->_new_stack;
+ $self->_private->{no_escape} = 1;
+}
+
+sub end_Verbatim {
+ my ($self) = @_;
+
+ my $text = $self->_pop_stack_text;
+
+ $text = $self->_indent_verbatim($text);
+
+ $self->_private->{no_escape} = 0;
+
+ # Verbatim blocks do not generate a separate "Para" event.
+ $self->_save_block($text);
+}
+
+sub _indent_verbatim {
+ my ($self, $paragraph) = @_;
+
+ # NOTE: Pod::Simple expands the tabs for us (as suggested by perlpodspec).
+ # Pod::Simple also has a 'strip_verbatim_indent' attribute
+ # but it doesn't sound like it gains us anything over this method.
+
+ # 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);
+
+ # Prepend indent to each line.
+ # We could check /\S/ to only indent non-blank lines,
+ # but it's backward compatible to respect the whitespace.
+ # Additionally, both pod and markdown say they ignore blank lines
+ # so it shouldn't hurt to leave them in.
+ $paragraph = join "\n", map { length($_) ? $indent . $_ : '' } @lines;
+ }
+
+ return $paragraph;
+}
+
+sub start_Para {
+ $_[0]->_new_stack;
+}
+
+sub end_Para {
+ my ($self) = @_;
+ my $text = $self->_pop_stack_text;
+
+ $text = $self->_escape_paragraph_markdown($text);
+
+ $self->_save_block($text);
+}
+
+
+## Headings ##
+
+sub start_head1 { $_[0]->_start_head(1) }
+sub end_head1 { $_[0]->_end_head(1) }
+sub start_head2 { $_[0]->_start_head(2) }
+sub end_head2 { $_[0]->_end_head(2) }
+sub start_head3 { $_[0]->_start_head(3) }
+sub end_head3 { $_[0]->_end_head(3) }
+sub start_head4 { $_[0]->_start_head(4) }
+sub end_head4 { $_[0]->_end_head(4) }
+
+sub _check_search_header {
+ my ($self) = @_;
+ # Save the text since the last heading if we want it for metadata.
+ if( my $last = $self->_private->{search_header} ){
+ for( $self->_private->{$last} = $self->_last_string ){
+ s/\A\s+//;
+ s/\s+\z//;
+ }
+ }
+}
+sub _start_head {
+ my ($self) = @_;
+ $self->_check_search_header;
+ $self->_new_stack;
+}
+
+sub _end_head {
+ my ($self, $num) = @_;
+ my $h = '#' x $num;
+
+ my $text = $self->_pop_stack_text;
+ $self->_private->{search_header} =
+ $text =~ /NAME/ ? 'Title'
+ : $text =~ /AUTHOR/ ? 'Author'
+ : undef;
+
+ # TODO: option for $h suffix
+ # TODO: put a name="" if $self->{embed_anchor_tags}; ?
+ # https://rt.cpan.org/Ticket/Display.html?id=57776
+ $self->_save_block(join(' ', $h, $text));
+}
+
+## Lists ##
+
+# With Pod::Simple->parse_empty_lists(1) there could be an over_empty event,
+# but what would you do with that?
+
+sub _start_list {
+ my ($self) = @_;
+ $self->_new_stack;
+
+ # Nest again b/c start_item will pop this to look for preceding content.
+ $self->_increase_indent;
+ $self->_new_stack;
+}
+
+sub _end_list {
+ my ($self) = @_;
+ $self->_handle_between_item_content;
+
+ # Finish the list.
+
+ # All the child elements should be blocks,
+ # but don't end with a double newline.
+ my $text = $self->_chomp_all($self->_pop_stack_text);
+
+ $_[0]->_save_line($text . $/);
+}
+
+sub _handle_between_item_content {
+ my ($self) = @_;
+
+ # This might be empty (if the list item had no additional content).
+ if( my $text = $self->_pop_stack_text ){
+ # Else it's a sub-document.
+ # If there are blocks we need to separate with blank lines.
+ if( $self->_private->{last_state}->{blocks} ){
+ $text = $/ . $text;
+ }
+ # If not, we can condense the text.
+ # In this module's history there was a patch contributed to specifically
+ # produce "huddled" lists so we'll try to maintain that functionality.
+ else {
+ $text = $self->_chomp_all($text) . $/;
+ }
+ $self->_save($text)
+ }
+
+ $self->_decrease_indent;
+}
+
+sub _start_item {
+ my ($self) = @_;
+ $self->_handle_between_item_content;
+ $self->_new_stack;
+}
+
+sub _end_item {
+ my ($self, $marker) = @_;
+ my $text = $self->_pop_stack_text;
+ $self->_save_line($self->_indent($marker .
+ # Add a space only if there is text after the marker.
+ (defined($text) && length($text) ? ' ' . $text : '')
+ ));
+
+ # Store any possible contents in a new stack (like a sub-document).
+ $self->_increase_indent;
+ $self->_new_stack;
+}
+
+sub start_over_bullet { $_[0]->_start_list }
+sub end_over_bullet { $_[0]->_end_list }
+
+sub start_item_bullet { $_[0]->_start_item }
+sub end_item_bullet { $_[0]->_end_item('-') }
+
+sub start_over_number { $_[0]->_start_list }
+sub end_over_number { $_[0]->_end_list }
+
+sub start_item_number {
+ $_[0]->_start_item;
+ # It seems like this should be a stack,
+ # but from testing it appears that the corresponding 'end' event
+ # comes right after the text (it doesn't surround any embedded content).
+ # See t/nested.t which shows start-item, text, end-item, para, start-item....
+ $_[0]->_private->{item_number} = $_[1]->{number};
+}
+
+sub end_item_number {
+ my ($self) = @_;
+ $self->_end_item($self->_private->{item_number} . '.');
+}
+
+# Markdown doesn't support definition lists
+# so do regular (unordered) lists with indented paragraphs.
+sub start_over_text { $_[0]->_start_list }
+sub end_over_text { $_[0]->_end_list }
+
+sub start_item_text { $_[0]->_start_item }
+sub end_item_text { $_[0]->_end_item('-')}
+
+
+# perlpodspec equates an over/back region with no items to a blockquote.
+sub start_over_block {
+ # NOTE: We don't actually need to indent for a blockquote.
+ $_[0]->_new_stack;
+}
+
+sub end_over_block {
+ my ($self) = @_;
+
+ # Chomp first to avoid prefixing a blank line with a `>`.
+ my $text = $self->_chomp_all($self->_pop_stack_text);
+
+ # NOTE: Paragraphs will already be escaped.
+
+ # I don't really like either of these implementations
+ # but the join/map/split seems a little better and benches a little faster.
+ # You would lose the last newline but we've already chomped.
+ #$text =~ s{^(.)?}{'>' . (defined($1) && length($1) ? (' ' . $1) : '')}mge;
+ $text = join $/, map { length($_) ? '> ' . $_ : '>' } split qr-$/-, $text;
+
+ $self->_save_block($text);
+}
+
+## Custom Formats ##
+
+sub start_for {
+ my ($self, $attr) = @_;
+ $self->_new_stack;
+
+ if( $attr->{target} eq 'html' ){
+ # Use another stack so we can indent
+ # (not syntactily necessary but seems appropriate).
+ $self->_new_stack;
+ $self->_increase_indent;
+ $self->_private->{no_escape} = 1;
+ # Mark this so we know to undo it.
+ $self->_stack_state->{for_html} = 1;
+ }
+}
+
+sub end_for {
+ my ($self) = @_;
+ # Data gets saved as a block (which will handle indents),
+ # but if there was html we'll alter this, so chomp and save a block again.
+ my $text = $self->_chomp_all($self->_pop_stack_text);
+
+ if( $self->_private->{last_state}->{for_html} ){
+ $self->_private->{no_escape} = 0;
+ # Save it to the next stack up so we can pop it again (we made two stacks).
+ $self->_save($text);
+ $self->_decrease_indent;
+ $text = join "\n", '', $self->_chomp_all($self->_pop_stack_text), '
';
+ }
+
+ $self->_save_block($text);
+}
+
+# Data events will be emitted for any formatted regions that have been enabled
+# (by default, `markdown` and `html`).
+
+sub start_Data {
+ my ($self) = @_;
+ # TODO: limit this to what's in attr?
+ $self->_private->{no_escape}++;
+ $self->_new_stack;
+}
+
+sub end_Data {
+ my ($self) = @_;
+ my $text = $self->_pop_stack_text;
+ $self->_private->{no_escape}--;
+ $self->_save_block($text);
+}
+
+## Codes ##
+
+sub start_B { $_[0]->_save('**') }
+sub end_B { $_[0]->start_B() }
+
+sub start_I { $_[0]->_save('_') }
+sub end_I { $_[0]->start_I() }
+
+sub start_C {
+ my ($self) = @_;
+ $self->_new_stack;
+ $self->_private->{no_escape}++;
+}
+
+sub end_C {
+ my ($self) = @_;
+ $self->_private->{no_escape}--;
+ $self->_save( $self->_wrap_code_span($self->_pop_stack_text) );
+}
+
+# Use code spans for F<>.
+sub start_F { shift->start_C(@_); }
+sub end_F { shift ->end_C(@_); }
+
+sub start_L {
+ my ($self, $flags) = @_;
+ $self->_new_stack;
+ push @{ $self->_private->{link} }, $flags;
+}
+
+sub end_L {
+ my ($self) = @_;
+ my $flags = pop @{ $self->_private->{link} }
+ or die 'Invalid state: link end with no link start';
+
+ my ($type, $to, $section) = @{$flags}{qw( type to section )};
+
+ my $url = (
+ $type eq 'url' ? $to
+ : $type eq 'man' ? $self->format_man_url($to, $section)
+ : $type eq 'pod' ? $self->format_perldoc_url($to, $section)
+ : undef
+ );
+
+ my $text = $self->_pop_stack_text;
+
+ # NOTE: I don't think the perlpodspec says what to do with L<|blah>
+ # but it seems like a blank link text just doesn't make sense
+ if( !length($text) ){
+ $text =
+ $section ?
+ $to ? sprintf('"%s" in %s', $section, $to)
+ : ('"' . $section . '"')
+ : $to;
+ }
+
+ # FIXME: What does Pod::Simple::X?HTML do for this?
+ # if we don't know how to handle the url just print the pod back out
+ if (!$url) {
+ $self->_save(sprintf 'L<%s>', $flags->{raw});
+ return;
+ }
+
+ # In the url we need to escape quotes and parentheses lest markdown
+ # break the url (cut it short and/or wrongfully interpret a title).
+
+ # Backslash escapes do not work for the space and quotes.
+ # URL-encoding the space is not sufficient
+ # (the quotes confuse some parsers and produce invalid html).
+ # I've arbitratily chosen HTML encoding to hide them from markdown
+ # while mangling the url as litle as possible.
+ $url =~ s/([ '"])/sprintf '%x;', ord($1)/ge;
+
+ # We also need to double any backslashes that may be present
+ # (lest they be swallowed up) and stop parens from breaking the url.
+ $url =~ s/([\\()])/\\$1/g;
+
+ # TODO: put section name in title if not the same as $text
+ $self->_save('[' . $text . '](' . $url . ')');
+}
+
+sub start_X {
+ $_[0]->_new_stack;
+}
+
+sub end_X {
+ my ($self) = @_;
+ my $text = $self->_pop_stack_text;
+ # TODO: mangle $text?
+ # TODO: put if configured
+}
+
+# A code span can be delimited by multiple backticks (and a space)
+# similar to pod codes (C<< code >>), so ensure we use a big enough
+# delimiter to not have it broken by embedded backticks.
+sub _wrap_code_span {
+ my ($self, $arg) = @_;
+ my $longest = 0;
+ while( $arg =~ /([`]+)/g ){
+ my $len = length($1);
+ $longest = $len if $longest < $len;
+ }
+ my $delim = '`' x ($longest + 1);
+ my $pad = $longest > 0 ? ' ' : '';
+ return $delim . $pad . $arg . $pad . $delim;
+}
+
+## Link Formatting (TODO: Move this to another module) ##
+
+
+sub format_man_url {
+ my ($self, $to) = @_;
+ my ($page, $part) = ($to =~ /^ ([^(]+) (?: \( (\S+) \) )? /x);
+ return $self->man_url_prefix . ($part || 1) . '/' . ($page || $to);
+}
+
+
+sub format_perldoc_url {
+ my ($self, $name, $section) = @_;
+
+ my $url_prefix = $self->perldoc_url_prefix;
+ if (
+ defined($name)
+ && $self->is_local_module($name)
+ && defined($self->local_module_url_prefix)
+ ) {
+ $url_prefix = $self->local_module_url_prefix;
+ }
+
+ my $url = '';
+
+ # If the link is to another module (external link).
+ if ($name) {
+ $url = $url_prefix . ($self->escape_url ? URI::Escape::uri_escape($name) : $name);
+ }
+
+ # See https://rt.cpan.org/Ticket/Display.html?id=57776
+ # for a discussion on the need to mangle the section.
+ if ($section){
+
+ my $method = $url
+ # If we already have a prefix on the url it's external.
+ ? $self->perldoc_fragment_format
+ # Else an internal link points to this markdown doc.
+ : $self->markdown_fragment_format;
+
+ $method = 'format_fragment_' . $method
+ unless ref($method);
+
+ {
+ # Set topic to enable code refs to be simple.
+ local $_ = $section;
+ $section = $self->$method($section);
+ }
+
+ $url .= '#' . $section;
+ }
+
+ return $url;
+}
+
+
+# TODO: simple, pandoc, etc?
+
+sub format_fragment_markdown {
+ my ($self, $section) = @_;
+
+ # If this is an internal link (to another section in this doc)
+ # we can't be sure what the heading id's will look like
+ # (it depends on what is rendering the markdown to html)
+ # but we can try to follow popular conventions.
+
+ # http://johnmacfarlane.net/pandoc/demo/example9/pandocs-markdown.html#header-identifiers-in-html-latex-and-context
+ #$section =~ s/(?![-_.])[[:punct:]]//g;
+ #$section =~ s/\s+/-/g;
+ $section =~ s/\W+/-/g;
+ $section =~ s/-+$//;
+ $section =~ s/^-+//;
+ $section = lc $section;
+ #$section =~ s/^[^a-z]+//;
+ $section ||= 'section';
+
+ return $section;
+}
+
+
+{
+ # From Pod::Simple::XHTML 3.28.
+ # The strings gets passed through encode_entities() before idify().
+ # If we don't do it here the substitutions below won't operate consistently.
+
+ sub format_fragment_pod_simple_xhtml {
+ my ($self, $t) = @_;
+
+ # encode_entities {
+ # We need to use the defaults in case html_encode_chars has been customized
+ # (since the purpose is to match what external sources are doing).
+
+ local $self->_private->{html_encode_chars};
+ $t = $self->encode_entities($t);
+ # }
+
+ # idify {
+ for ($t) {
+ s/<[^>]+>//g; # Strip HTML.
+ s/&[^;]+;//g; # Strip entities.
+ s/^\s+//; s/\s+$//; # Strip white space.
+ s/^([^a-zA-Z]+)$/pod$1/; # Prepend "pod" if no valid chars.
+ s/^[^a-zA-Z]+//; # First char must be a letter.
+ s/[^-a-zA-Z0-9_:.]+/-/g; # All other chars must be valid.
+ s/[-:.]+$//; # Strip trailing punctuation.
+ }
+ # }
+
+ return $t;
+ }
+}
+
+
+sub format_fragment_pod_simple_html {
+ my ($self, $section) = @_;
+
+ # From Pod::Simple::HTML 3.28.
+
+ # section_name_tidy {
+ $section =~ s/^\s+//;
+ $section =~ s/\s+$//;
+ $section =~ tr/ /_/;
+ $section =~ tr/\x00-\x1F\x80-\x9F//d if 'A' eq chr(65); # drop crazy characters
+
+ #$section = $self->unicode_escape_url($section);
+ # unicode_escape_url {
+ $section =~ s/([^\x00-\xFF])/'('.ord($1).')'/eg;
+ # Turn char 1234 into "(1234)"
+ # }
+
+ $section = '_' unless length $section;
+ return $section;
+ # }
+}
+
+
+sub format_fragment_metacpan { shift->format_fragment_pod_simple_xhtml(@_); }
+sub format_fragment_sco { shift->format_fragment_pod_simple_html(@_); }
+
+
+sub is_local_module {
+ my ($self, $name) = @_;
+
+ return ($name =~ $self->local_module_re);
+}
+
+1;
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=for :stopwords Marcel Gruenauer Victor Moral Ryan C. Thompson Aristotle Pagaltzis Randy Stauner ACKNOWLEDGEMENTS html cpan
+testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata
+placeholders metacpan
+
+=head1 NAME
+
+Pod::Markdown - Convert POD to Markdown
+
+=head1 VERSION
+
+version 3.400
+
+=for test_synopsis my ($pod_string);
+
+=head1 SYNOPSIS
+
+ # Pod::Simple API is supported.
+
+ # Command line usage: Parse a pod file and print to STDOUT:
+ # $ perl -MPod::Markdown -e 'Pod::Markdown->new->filter(@ARGV)' path/to/POD/file > README.md
+
+ # Work with strings:
+ my $markdown;
+ my $parser = Pod::Markdown->new;
+ $parser->output_string(\$markdown);
+ $parser->parse_string_document($pod_string);
+
+ # See Pod::Simple docs for more.
+
+=head1 DESCRIPTION
+
+This module uses L to convert POD to Markdown.
+
+Literal characters in Pod that are special in Markdown
+(like *asterisks*) are backslash-escaped when appropriate.
+
+By default C and C formatted regions are accepted.
+Regions of C will be passed through unchanged.
+Regions of C will be placed inside a C<< EdivE >> tag
+so that markdown characters won't be processed.
+Regions of C<:markdown> or C<:html> will be processed as POD and included.
+To change which regions are accepted use the L API:
+
+ my $parser = Pod::Markdown->new;
+ $parser->unaccept_targets(qw( markdown html ));
+
+=head2 A note on encoding and escaping
+
+The common L API returns a character string.
+If you want Pod::Markdown to return encoded octets, there are two attributes
+to assist: L and L.
+
+When an output encoding is requested any characters that are not valid
+for that encoding will be escaped as HTML entities.
+
+This is not 100% safe, however.
+
+Markdown escapes all ampersands inside of code spans, so escaping a character
+as an HTML entity inside of a code span will not be correct.
+However, with pod's C and C sequences it is possible
+to end up with high-bit characters inside of code spans.
+
+So, while C<< output_encoding => 'ascii' >> can work, it is not recommended.
+For these reasons (and more), C is the default, fallback encoding (when one is required).
+
+If you prefer HTML entities over literal characters you can use
+L which will only operate outside of code spans (where it is safe).
+
+=head1 METHODS
+
+=head2 new
+
+ Pod::Markdown->new(%options);
+
+The constructor accepts the following named arguments:
+
+=over 4
+
+=item *
+
+C
+
+Alters the perldoc urls that are created from C<< LEE >> codes
+when the module is a "local" module (C<"Local::*"> or C<"Foo_Corp::*"> (see L)).
+
+The default is to use C.
+
+=item *
+
+C
+
+Alternate regular expression for determining "local" modules.
+Default is C<< our $LOCAL_MODULE_RE = qr/^(Local::|\w*?_\w*)/ >>.
+
+=item *
+
+C
+
+Alters the man page urls that are created from C<< LEE >> codes.
+
+The default is C.
+
+=item *
+
+C
+
+Alters the perldoc urls that are created from C<< LEE >> codes.
+Can be:
+
+=over 4
+
+=item *
+
+C (shortcut for C)
+
+=item *
+
+C (shortcut for C)
+
+=item *
+
+any url
+
+=back
+
+The default is C.
+
+ Pod::Markdown->new(perldoc_url_prefix => 'http://localhost/perl/pod');
+
+=item *
+
+C
+
+Alters the format of the url fragment for any C<< LEE >> links
+that point to a section of an external document (C<< L >>).
+The default will be chosen according to the destination L.
+Alternatively you can specify one of the following:
+
+=over 4
+
+=item *
+
+C
+
+=item *
+
+C
+
+=item *
+
+C
+
+=item *
+
+C
+
+=item *
+
+A code ref
+
+=back
+
+The code ref can expect to receive two arguments:
+the parser object (C<$self>) and the section text.
+For convenience the topic variable (C<$_>) is also set to the section text:
+
+ perldoc_fragment_format => sub { s/\W+/-/g; }
+
+=item *
+
+C
+
+Alters the format of the url fragment for any C<< LEE >> links
+that point to an internal section of this document (C<< L >>).
+
+Unfortunately the format of the id attributes produced
+by whatever system translates the markdown into html is unknown at the time
+the markdown is generated so we do some simple clean up.
+
+B C and C accept
+the same values: a (shortcut to a) method name or a code ref.
+
+=item *
+
+C
+
+Specifies whether or not to print author/title meta tags at the top of the document.
+Default is false.
+
+=item *
+
+C
+
+Specifies whether or not to escape URLs. Default is true. It is not recommended
+to turn this off with an empty local_module_url_prefix, as the resulting local
+module URLs can be confused with IPv6 addresses by web browsers.
+
+=back
+
+=head2 html_encode_chars
+
+A string of characters to encode as html entities
+(using L if available, falling back to numeric entities if not).
+
+Possible values:
+
+=over 4
+
+=item *
+
+A value of C<1> will use the default set of characters from L (control chars, high-bit chars, and C<< <&>"' >>).
+
+=item *
+
+A false value will disable.
+
+=item *
+
+Any other value is used as a string of characters (like a regular expression character class).
+
+=back
+
+By default this is disabled and literal characters will be in the output stream.
+If you specify a desired L any characters not valid for that encoding will be HTML entity encoded.
+
+B that Markdown requires ampersands (C<< & >>) and left angle brackets (C<< < >>)
+to be entity-encoded if they could otherwise be interpreted as html entities.
+If this attribute is configured to encode those characters, they will always be encoded.
+If not, the module will make an effort to only encode the ones required,
+so there will be less html noise in the output.
+
+=head2 match_encoding
+
+Boolean: If true, use the C<< =encoding >> of the input pod
+as the encoding for the output.
+
+If no encoding is specified, L will guess the encoding
+if it sees a high-bit character.
+
+If no encoding is guessed (or the specified encoding is unusable),
+L will be used if it was specified.
+Otherwise C will be used.
+
+This attribute is not recommended
+but is provided for consistency with other pod converters.
+
+Defaults to false.
+
+=head2 output_encoding
+
+The encoding to use when writing to the output file handle.
+
+If neither this nor L are specified,
+a character string will be returned in whatever L output method you specified.
+
+=head2 local_module_re
+
+Returns the regular expression used to determine local modules.
+
+=head2 local_module_url_prefix
+
+Returns the url prefix in use for local modules.
+
+=head2 man_url_prefix
+
+Returns the url prefix in use for man pages.
+
+=head2 perldoc_url_prefix
+
+Returns the url prefix in use (after resolving shortcuts to urls).
+
+=head2 perldoc_fragment_format
+
+Returns the coderef or format name used to format a url fragment
+to a section in an external document.
+
+=head2 markdown_fragment_format
+
+Returns the coderef or format name used to format a url fragment
+to an internal section in this document.
+
+=head2 include_meta_tags
+
+Returns the boolean value indicating
+whether or not meta tags will be printed.
+
+=head2 escape_url
+
+Returns the boolean value indicating
+whether or not URLs should be escaped.
+
+=head2 format_man_url
+
+Used internally to create a url (using L)
+from a string like C.
+
+=head2 format_perldoc_url
+
+ # With $name and section being the two parts of L.
+ my $url = $parser->format_perldoc_url($name, $section);
+
+Used internally to create a url from
+the name (of a module or script)
+and a possible section (heading).
+
+The format of the url fragment (when pointing to a section in a document)
+varies depending on the destination url
+so L is used (which can be customized).
+
+If the module name portion of the link is blank
+then the section is treated as an internal fragment link
+(to a section of the generated markdown document)
+and L is used (which can be customized).
+
+=head2 format_fragment_markdown
+
+Format url fragment for an internal link
+by replacing non-word characters with dashes.
+
+=head2 format_fragment_pod_simple_xhtml
+
+Format url fragment like L.
+
+=head2 format_fragment_pod_simple_html
+
+Format url fragment like L.
+
+=head2 format_fragment_metacpan
+
+Format fragment for L
+(uses L).
+
+=head2 format_fragment_sco
+
+Format fragment for L
+(uses L).
+
+=head2 is_local_module
+
+Uses C to determine if passed module is a "local" module.
+
+=for Pod::Coverage parse_from_file
+parse_from_filehandle
+
+=for Pod::Coverage as_markdown
+
+=for Pod::Coverage handle_text
+end_.+
+start_.+
+encode_entities
+
+=head1 SEE ALSO
+
+=over 4
+
+=item *
+
+L - script included for command line usage
+
+=item *
+
+L - Super class that handles Pod parsing
+
+=item *
+
+L - For writing POD
+
+=item *
+
+L - For parsing POD
+
+=item *
+
+L - Markdown spec
+
+=back
+
+=head1 SUPPORT
+
+=head2 Perldoc
+
+You can find documentation for this module with the perldoc command.
+
+ perldoc Pod::Markdown
+
+=head2 Websites
+
+The following websites have more information about this module, and may be of help to you. As always,
+in addition to those websites please use your favorite search engine to discover more resources.
+
+=over 4
+
+=item *
+
+MetaCPAN
+
+A modern, open-source CPAN search engine, useful to view POD in HTML format.
+
+L
+
+=back
+
+=head2 Bugs / Feature Requests
+
+Please report any bugs or feature requests by email to C, or through
+the web interface at L. You will be automatically notified of any
+progress on the request by the system.
+
+=head2 Source Code
+
+
+L
+
+ git clone https://github.com/rwstauner/Pod-Markdown.git
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Marcel Gruenauer
+
+=item *
+
+Victor Moral
+
+=item *
+
+Ryan C. Thompson
+
+=item *
+
+Aristotle Pagaltzis
+
+=item *
+
+Randy Stauner
+
+=back
+
+=head1 CONTRIBUTORS
+
+=for stopwords Aristotle Pagaltzis Cindy Wang (CindyLinz) Graham Ollis Johannes Schauer Marin Rodrigues Mike Covington motemen moznion Peter Vereshagin Ryan C. Thompson Yasutaka ATARASHI
+
+=over 4
+
+=item *
+
+Aristotle Pagaltzis
+
+=item *
+
+Cindy Wang (CindyLinz)
+
+=item *
+
+Graham Ollis
+
+=item *
+
+Johannes Schauer Marin Rodrigues
+
+=item *
+
+Mike Covington
+
+=item *
+
+motemen
+
+=item *
+
+moznion
+
+=item *
+
+Peter Vereshagin
+
+=item *
+
+Ryan C. Thompson
+
+=item *
+
+Yasutaka ATARASHI
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2011 by Randy Stauner.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
diff --git a/src/tools/URI/Escape.pm b/src/tools/URI/Escape.pm
new file mode 100644
index 000000000..f5082a2dc
--- /dev/null
+++ b/src/tools/URI/Escape.pm
@@ -0,0 +1,249 @@
+package URI::Escape;
+
+use strict;
+use warnings;
+
+=head1 NAME
+
+URI::Escape - Percent-encode and percent-decode unsafe characters
+
+=head1 SYNOPSIS
+
+ use URI::Escape;
+ $safe = uri_escape("10% is enough\n");
+ $verysafe = uri_escape("foo", "\0-\377");
+ $str = uri_unescape($safe);
+
+=head1 DESCRIPTION
+
+This module provides functions to percent-encode and percent-decode URI strings as
+defined by RFC 3986. Percent-encoding URI's is informally called "URI escaping".
+This is the terminology used by this module, which predates the formalization of the
+terms by the RFC by several years.
+
+A URI consists of a restricted set of characters. The restricted set
+of characters consists of digits, letters, and a few graphic symbols
+chosen from those common to most of the character encodings and input
+facilities available to Internet users. They are made up of the
+"unreserved" and "reserved" character sets as defined in RFC 3986.
+
+ unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ reserved = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+ "!" / "$" / "&" / "'" / "(" / ")"
+ / "*" / "+" / "," / ";" / "="
+
+In addition, any byte (octet) can be represented in a URI by an escape
+sequence: a triplet consisting of the character "%" followed by two
+hexadecimal digits. A byte can also be represented directly by a
+character, using the US-ASCII character for that octet.
+
+Some of the characters are I for use as delimiters or as
+part of certain URI components. These must be escaped if they are to
+be treated as ordinary data. Read RFC 3986 for further details.
+
+The functions provided (and exported by default) from this module are:
+
+=over 4
+
+=item uri_escape( $string )
+
+=item uri_escape( $string, $unsafe )
+
+Replaces each unsafe character in the $string with the corresponding
+escape sequence and returns the result. The $string argument should
+be a string of bytes. The uri_escape() function will croak if given a
+characters with code above 255. Use uri_escape_utf8() if you know you
+have such chars or/and want chars in the 128 .. 255 range treated as
+UTF-8.
+
+The uri_escape() function takes an optional second argument that
+overrides the set of characters that are to be escaped. The set is
+specified as a string that can be used in a regular expression
+character class (between [ ]). E.g.:
+
+ "\x00-\x1f\x7f-\xff" # all control and hi-bit characters
+ "a-z" # all lower case characters
+ "^A-Za-z" # everything not a letter
+
+The default set of characters to be escaped is all those which are
+I part of the C character class shown above as well
+as the reserved characters. I.e. the default is:
+
+ "^A-Za-z0-9\-\._~"
+
+The second argument can also be specified as a regular expression object:
+
+ qr/[^A-Za-z]/
+
+Any strings matched by this regular expression will have all of their
+characters escaped.
+
+=item uri_escape_utf8( $string )
+
+=item uri_escape_utf8( $string, $unsafe )
+
+Works like uri_escape(), but will encode chars as UTF-8 before
+escaping them. This makes this function able to deal with characters
+with code above 255 in $string. Note that chars in the 128 .. 255
+range will be escaped differently by this function compared to what
+uri_escape() would. For chars in the 0 .. 127 range there is no
+difference.
+
+Equivalent to:
+
+ utf8::encode($string);
+ my $uri = uri_escape($string);
+
+Note: JavaScript has a function called escape() that produces the
+sequence "%uXXXX" for chars in the 256 .. 65535 range. This function
+has really nothing to do with URI escaping but some folks got confused
+since it "does the right thing" in the 0 .. 255 range. Because of
+this you sometimes see "URIs" with these kind of escapes. The
+JavaScript encodeURIComponent() function is similar to uri_escape_utf8().
+
+=item uri_unescape($string,...)
+
+Returns a string with each %XX sequence replaced with the actual byte
+(octet).
+
+This does the same as:
+
+ $string =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+
+but does not modify the string in-place as this RE would. Using the
+uri_unescape() function instead of the RE might make the code look
+cleaner and is a few characters less to type.
+
+In a simple benchmark test I did,
+calling the function (instead of the inline RE above) if a few chars
+were unescaped was something like 40% slower, and something like 700% slower if none were. If
+you are going to unescape a lot of times it might be a good idea to
+inline the RE.
+
+If the uri_unescape() function is passed multiple strings, then each
+one is returned unescaped.
+
+=back
+
+The module can also export the C<%escapes> hash, which contains the
+mapping from all 256 bytes to the corresponding escape codes. Lookup
+in this hash is faster than evaluating C
+each time.
+
+=head1 SEE ALSO
+
+L
+
+
+=head1 COPYRIGHT
+
+Copyright 1995-2004 Gisle Aas.
+
+This program is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+SPDX-License-Identifier: Artistic-2.0
+=cut
+
+use Exporter 5.57 'import';
+our %escapes;
+our @EXPORT = qw(uri_escape uri_unescape uri_escape_utf8);
+our @EXPORT_OK = qw(%escapes);
+our $VERSION = '5.28';
+
+use Carp ();
+
+# Build a char->hex map
+for (0..255) {
+ $escapes{chr($_)} = sprintf("%%%02X", $_);
+}
+
+my %subst; # compiled patterns
+
+my %Unsafe = (
+ RFC2732 => qr/[^A-Za-z0-9\-_.!~*'()]/,
+ RFC3986 => qr/[^A-Za-z0-9\-\._~]/,
+);
+
+sub uri_escape {
+ my($text, $patn) = @_;
+ return undef unless defined $text;
+ my $re;
+ if (defined $patn){
+ if (ref $patn eq 'Regexp') {
+ $text =~ s{($patn)}{
+ join('', map +($escapes{$_} || _fail_hi($_)), split //, "$1")
+ }ge;
+ return $text;
+ }
+ $re = $subst{$patn};
+ if (!defined $re) {
+ $re = $patn;
+ # we need to escape the [] characters, except for those used in
+ # posix classes. if they are prefixed by a backslash, allow them
+ # through unmodified.
+ $re =~ s{(\[:\w+:\])|(\\)?([\[\]]|\\\z)}{
+ defined $1 ? $1 : defined $2 ? "$2$3" : "\\$3"
+ }ge;
+ eval {
+ # disable the warnings here, since they will trigger later
+ # when used, and we only want them to appear once per call,
+ # but every time the same pattern is used.
+ no warnings 'regexp';
+ $re = $subst{$patn} = qr{[$re]};
+ 1;
+ } or Carp::croak("uri_escape: $@");
+ }
+ }
+ else {
+ $re = $Unsafe{RFC3986};
+ }
+ $text =~ s/($re)/$escapes{$1} || _fail_hi($1)/ge;
+ $text;
+}
+
+sub _fail_hi {
+ my $chr = shift;
+ Carp::croak(sprintf "Can't escape \\x{%04X}, try uri_escape_utf8() instead", ord($chr));
+}
+
+sub uri_escape_utf8 {
+ my $text = shift;
+ return undef unless defined $text;
+ utf8::encode($text);
+ return uri_escape($text, @_);
+}
+
+sub uri_unescape {
+ # Note from RFC1630: "Sequences which start with a percent sign
+ # but are not followed by two hexadecimal characters are reserved
+ # for future extension"
+ my $str = shift;
+ if (@_ && wantarray) {
+ # not executed for the common case of a single argument
+ my @str = ($str, @_); # need to copy
+ for (@str) {
+ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+ }
+ return @str;
+ }
+ $str =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg if defined $str;
+ $str;
+}
+
+# XXX FIXME escape_char is buggy as it assigns meaning to the string's storage format.
+sub escape_char {
+ # Old versions of utf8::is_utf8() didn't properly handle magical vars (e.g. $1).
+ # The following forces a fetch to occur beforehand.
+ my $dummy = substr($_[0], 0, 0);
+
+ if (utf8::is_utf8($_[0])) {
+ my $s = shift;
+ utf8::encode($s);
+ unshift(@_, $s);
+ }
+
+ return join '', @URI::Escape::escapes{split //, $_[0]};
+}
+
+1;