1# vim: set ts=2 sts=2 sw=2 expandtab smarttab: 2# 3# This file is part of Pod-Markdown 4# 5# This software is copyright (c) 2011 by Randy Stauner. 6# 7# This is free software; you can redistribute it and/or modify it under 8# the same terms as the Perl 5 programming language system itself. 9# 10use 5.008; 11use strict; 12use warnings; 13 14package Pod::Markdown; 15# git description: v3.200-4-gd31d626 16 17our $AUTHORITY = 'cpan:RWSTAUNER'; 18# ABSTRACT: Convert POD to Markdown 19$Pod::Markdown::VERSION = '3.300'; 20use Pod::Simple 3.27 (); # detected_encoding and keep_encoding bug fix 21use parent qw(Pod::Simple::Methody); 22use Encode (); 23use URI::Escape (); 24 25our %URL_PREFIXES = ( 26 sco => 'http://search.cpan.org/perldoc?', 27 metacpan => 'https://metacpan.org/pod/', 28 man => 'http://man.he.net/man', 29); 30$URL_PREFIXES{perldoc} = $URL_PREFIXES{metacpan}; 31 32our $LOCAL_MODULE_RE = qr/^(Local::|\w*?_\w*)/; 33 34## no critic 35#{ 36 our $HAS_HTML_ENTITIES; 37 38 # Stolen from Pod::Simple::XHTML 3.28. {{{ 39 40 BEGIN { 41 $HAS_HTML_ENTITIES = eval "require HTML::Entities; 1"; 42 } 43 44 my %entities = ( 45 q{>} => 'gt', 46 q{<} => 'lt', 47 q{'} => '#39', 48 q{"} => 'quot', 49 q{&} => 'amp', 50 ); 51 52 sub encode_entities { 53 my $self = shift; 54 my $ents = $self->html_encode_chars; 55 return HTML::Entities::encode_entities( $_[0], $ents ) if $HAS_HTML_ENTITIES; 56 if (defined $ents) { 57 $ents =~ s,(?<!\\)([]/]),\\$1,g; 58 $ents =~ s,(?<!\\)\\\z,\\\\,; 59 } else { 60 $ents = join '', keys %entities; 61 } 62 my $str = $_[0]; 63 $str =~ s/([$ents])/'&' . ($entities{$1} || sprintf '#x%X', ord $1) . ';'/ge; 64 return $str; 65 } 66 67 # }}} 68 69 # Add a few very common ones for consistency and readability 70 # (in case HTML::Entities isn't available). 71 %entities = ( 72 # Pod::Markdown has always required 5.8 so unicode_to_native will be available. 73 chr(utf8::unicode_to_native(0xA0)) => 'nbsp', 74 chr(utf8::unicode_to_native(0xA9)) => 'copy', 75 %entities 76 ); 77 78 sub __entity_encode_ord_he { 79 my $chr = chr $_[0]; 80 # Skip the encode_entities() logic and go straight for the substitution 81 # since we already have the char we know we want replaced. 82 # Both the hash and the function are documented as exportable (so should be reliable). 83 return $HTML::Entities::char2entity{ $chr } || HTML::Entities::num_entity( $chr ); 84 } 85 sub __entity_encode_ord_basic { 86 return '&' . ($entities{chr $_[0]} || sprintf '#x%X', $_[0]) . ';'; 87 } 88 89 # From HTML::Entities 3.69 90 my $DEFAULT_ENTITY_CHARS = '^\n\r\t !\#\$%\(-;=?-~'; 91 92#} 93## use critic 94 95# Use hash for simple "exists" check in `new` (much more accurate than `->can`). 96my %attributes = map { ($_ => 1) } 97 qw( 98 html_encode_chars 99 match_encoding 100 output_encoding 101 local_module_re 102 local_module_url_prefix 103 man_url_prefix 104 perldoc_url_prefix 105 perldoc_fragment_format 106 markdown_fragment_format 107 include_meta_tags 108 escape_url 109 ); 110 111 112sub new { 113 my $class = shift; 114 my %args = @_; 115 116 my $self = $class->SUPER::new(); 117 $self->preserve_whitespace(1); 118 $self->nbsp_for_S(1); 119 $self->accept_targets(qw( markdown html )); 120 $self->escape_url(1); 121 122 # Default to the global, but allow it to be overwritten in args. 123 $self->local_module_re($LOCAL_MODULE_RE); 124 125 for my $type ( qw( perldoc man ) ){ 126 my $attr = $type . '_url_prefix'; 127 # Initialize to the alias. 128 $self->$attr($type); 129 } 130 131 while( my ($attr, $val) = each %args ){ 132 # NOTE: Checking exists on a private var means we don't allow Pod::Simple 133 # attributes to be set this way. It's not very consistent, but I think 134 # I'm ok with that for now since there probably aren't many Pod::Simple attributes 135 # being changed besides `output_*` which feel like API rather than attributes. 136 # We'll see. 137 # This is currently backward-compatible as we previously just put the attribute 138 # into the private stash so anything unknown was silently ignored. 139 # We could open this up to `$self->can($attr)` in the future if that seems better 140 # but it tricked me when I was testing a misspelled attribute name 141 # which also happened to be a Pod::Simple method. 142 143 exists $attributes{ $attr } or 144 # Provide a more descriptive message than "Can't locate object method". 145 warn("Unknown argument to ${class}->new(): '$attr'"), next; 146 147 # Call setter. 148 $self->$attr($val); 149 } 150 151 # TODO: call from the setters. 152 $self->_prepare_fragment_formats; 153 154 if(defined $self->local_module_url_prefix && $self->local_module_url_prefix eq '' && !$self->escape_url) { 155 warn("turning escape_url with an empty local_module_url_prefix is not recommended as relative URLs could be confused for IPv6 addresses"); 156 } 157 158 return $self; 159} 160 161for my $type ( qw( local_module perldoc man ) ){ 162 my $attr = $type . '_url_prefix'; 163 no strict 'refs'; ## no critic 164 *$attr = sub { 165 my $self = shift; 166 if (@_) { 167 $self->{$attr} = $URL_PREFIXES{ $_[0] } || $_[0]; 168 } 169 else { 170 return $self->{$attr}; 171 } 172 } 173} 174 175## Attribute accessors ## 176 177 178sub html_encode_chars { 179 my $self = shift; 180 my $stash = $self->_private; 181 182 # Setter. 183 if( @_ ){ 184 # If false ('', 0, undef), disable. 185 if( !$_[0] ){ 186 delete $stash->{html_encode_chars}; 187 $stash->{encode_amp} = 1; 188 $stash->{encode_lt} = 1; 189 } 190 else { 191 # Special case boolean '1' to mean "all". 192 # If we have HTML::Entities, undef will use the default. 193 # Without it, we need to specify so that we use the same list (for consistency). 194 $stash->{html_encode_chars} = $_[0] eq '1' ? ($HAS_HTML_ENTITIES ? undef : $DEFAULT_ENTITY_CHARS) : $_[0]; 195 196 # If [char] doesn't get encoded, we need to do it ourselves. 197 $stash->{encode_amp} = ($self->encode_entities('&') eq '&'); 198 $stash->{encode_lt} = ($self->encode_entities('<') eq '<'); 199 } 200 return; 201 } 202 203 # Getter. 204 return $stash->{html_encode_chars}; 205} 206 207 208# I prefer ro-accessors (immutability!) but it can be confusing 209# to not support the same API as other Pod::Simple classes. 210 211# NOTE: Pod::Simple::_accessorize is not a documented public API. 212# Skip any that have already been defined. 213__PACKAGE__->_accessorize(grep { !__PACKAGE__->can($_) } keys %attributes); 214 215sub _prepare_fragment_formats { 216 my ($self) = @_; 217 218 foreach my $attr ( keys %attributes ){ 219 next unless $attr =~ /^(\w+)_fragment_format/; 220 my $type = $1; 221 my $format = $self->$attr; 222 223 # If one was provided. 224 if( $format ){ 225 # If the attribute is a coderef just use it. 226 next if ref($format) eq 'CODE'; 227 } 228 # Else determine a default. 229 else { 230 if( $type eq 'perldoc' ){ 231 # Choose a default that matches the destination url. 232 my $target = $self->perldoc_url_prefix; 233 foreach my $alias ( qw( metacpan sco ) ){ 234 if( $target eq $URL_PREFIXES{ $alias } ){ 235 $format = $alias; 236 } 237 } 238 # This seems like a reasonable fallback. 239 $format ||= 'pod_simple_xhtml'; 240 } 241 else { 242 $format = $type; 243 } 244 } 245 246 # The short name should become a method name with the prefix prepended. 247 my $prefix = 'format_fragment_'; 248 $format =~ s/^$prefix//; 249 die "Unknown fragment format '$format'" 250 unless $self->can($prefix . $format); 251 252 # Save it. 253 $self->$attr($format); 254 } 255 256 return; 257} 258 259## Backward compatible API ## 260 261# For backward compatibility (previously based on Pod::Parser): 262# While Pod::Simple provides a parse_from_file() method 263# it's primarily for Pod::Parser compatibility. 264# When called without an output handle it will print to STDOUT 265# but the old Pod::Markdown never printed to a handle 266# so we don't want to start now. 267sub parse_from_file { 268 my ($self, $file) = @_; 269 270 # TODO: Check that all dependent cpan modules use the Pod::Simple API 271 # then add a deprecation warning here to avoid confusion. 272 273 $self->output_string(\($self->{_as_markdown_})); 274 $self->parse_file($file); 275} 276 277# Likewise, though Pod::Simple doesn't define this method at all. 278sub parse_from_filehandle { shift->parse_from_file(@_) } 279 280 281## Document state ## 282 283sub _private { 284 my ($self) = @_; 285 $self->{_Pod_Markdown_} ||= { 286 indent => 0, 287 stacks => [], 288 states => [{}], 289 link => [], 290 encode_amp => 1, 291 encode_lt => 1, 292 }; 293} 294 295sub _increase_indent { 296 ++$_[0]->_private->{indent} >= 1 297 or die 'Invalid state: indent < 0'; 298} 299sub _decrease_indent { 300 --$_[0]->_private->{indent} >= 0 301 or die 'Invalid state: indent < 0'; 302} 303 304sub _new_stack { 305 push @{ $_[0]->_private->{stacks} }, []; 306 push @{ $_[0]->_private->{states} }, {}; 307} 308 309sub _last_string { 310 $_[0]->_private->{stacks}->[-1][-1]; 311} 312 313sub _pop_stack_text { 314 $_[0]->_private->{last_state} = pop @{ $_[0]->_private->{states} }; 315 join '', @{ pop @{ $_[0]->_private->{stacks} } }; 316} 317 318sub _stack_state { 319 $_[0]->_private->{states}->[-1]; 320} 321 322sub _save { 323 my ($self, $text) = @_; 324 push @{ $self->_private->{stacks}->[-1] }, $text; 325 # return $text; # DEBUG 326} 327 328sub _save_line { 329 my ($self, $text) = @_; 330 331 $text = $self->_process_escapes($text); 332 333 $self->_save($text . $/); 334} 335 336# For paragraphs, etc. 337sub _save_block { 338 my ($self, $text) = @_; 339 340 $self->_stack_state->{blocks}++; 341 342 $self->_save_line($self->_indent($text) . $/); 343} 344 345## Formatting ## 346 347sub _chomp_all { 348 my ($self, $text) = @_; 349 1 while chomp $text; 350 return $text; 351} 352 353sub _indent { 354 my ($self, $text) = @_; 355 my $level = $self->_private->{indent}; 356 357 if( $level ){ 358 my $indent = ' ' x ($level * 4); 359 360 # Capture text on the line so that we don't indent blank lines (/^\x20{4}$/). 361 $text =~ s/^(.+)/$indent$1/mg; 362 } 363 364 return $text; 365} 366 367# as_markdown() exists solely for backward compatibility 368# and requires having called parse_from_file() to be useful. 369 370 371sub as_markdown { 372 my ($parser, %args) = @_; 373 my @header; 374 # Don't add meta tags again if we've already done it. 375 if( $args{with_meta} && !$parser->include_meta_tags ){ 376 @header = $parser->_build_markdown_head; 377 } 378 return join("\n" x 2, @header, $parser->{_as_markdown_}); 379} 380 381sub _build_markdown_head { 382 my $parser = shift; 383 my $data = $parser->_private; 384 return join "\n", 385 map { qq![[meta \l$_="$data->{$_}"]]! } 386 grep { defined $data->{$_} } 387 qw( Title Author ); 388} 389 390## Escaping ## 391 392# http://daringfireball.net/projects/markdown/syntax#backslash 393# Markdown provides backslash escapes for the following characters: 394# 395# \ backslash 396# ` backtick 397# * asterisk 398# _ underscore 399# {} curly braces 400# [] square brackets 401# () parentheses 402# # hash mark 403# + plus sign 404# - minus sign (hyphen) 405# . dot 406# ! exclamation mark 407 408# However some of those only need to be escaped in certain places: 409# * Backslashes *do* need to be escaped or they may be swallowed by markdown. 410# * Word-surrounding characters (/[`*_]/) *do* need to be escaped mid-word 411# because the markdown spec explicitly allows mid-word em*pha*sis. 412# * I don't actually see anything that curly braces are used for. 413# * Escaping square brackets is enough to avoid accidentally 414# creating links and images (so we don't need to escape plain parentheses 415# or exclamation points as that would generate a lot of unnecesary noise). 416# Parentheses will be escaped in urls (&end_L) to avoid premature termination. 417# * We don't need a backslash for every hash mark or every hyphen found mid-word, 418# just the ones that start a line (likewise for plus and dot). 419# (Those will all be handled by _escape_paragraph_markdown). 420 421 422# Backslash escape markdown characters to avoid having them interpreted. 423sub _escape_inline_markdown { 424 local $_ = $_[1]; 425 426# s/([\\`*_{}\[\]()#+-.!])/\\$1/g; # See comments above. 427 s/([\\`*_\[\]])/\\$1/g; 428 429 return $_; 430} 431 432# Escape markdown characters that would be interpreted 433# at the start of a line. 434sub _escape_paragraph_markdown { 435 local $_ = $_[1]; 436 437 # Escape headings, horizontal rules, (unordered) lists, and blockquotes. 438 s/^([-+#>])/\\$1/mg; 439 440 # Markdown doesn't support backslash escapes for equal signs 441 # even though they can be used to underline a header. 442 # So use html to escape them to avoid having them interpreted. 443 s/^([=])/sprintf '&#x%x;', ord($1)/mge; 444 445 # Escape the dots that would wrongfully create numbered lists. 446 s/^( (?:>\s+)? \d+ ) (\.\x20)/$1\\$2/xgm; 447 448 return $_; 449} 450 451 452# Additionally Markdown allows inline html so we need to escape things that look like it. 453# While _some_ Markdown processors handle backslash-escaped html, 454# [Daring Fireball](http://daringfireball.net/projects/markdown/syntax) states distinctly: 455# > In HTML, there are two characters that demand special treatment: < and &... 456# > If you want to use them as literal characters, you must escape them as entities, e.g. <, and &. 457 458# It goes on to say: 459# > Markdown allows you to use these characters naturally, 460# > taking care of all the necessary escaping for you. 461# > If you use an ampersand as part of an HTML entity, 462# > it remains unchanged; otherwise it will be translated into &. 463# > Similarly, because Markdown supports inline HTML, 464# > if you use angle brackets as delimiters for HTML tags, Markdown will treat them as such. 465 466# In order to only encode the occurrences that require it (something that 467# could be interpreted as an entity) we escape them all so that we can do the 468# suffix test later after the string is complete (since we don't know what 469# strings might come after this one). 470 471my %_escape = 472 map { 473 my ($k, $v) = split /:/; 474 # Put the "code" marker before the char instead of after so that it doesn't 475 # get confused as the $2 (which is what requires us to entity-encode it). 476 # ( "XsX", "XcsX", "X(c?)sX" ) 477 my ($s, $code, $re) = map { "\0$_$v\0" } '', map { ($_, '('.$_.'?)') } 'c'; 478 479 ( 480 $k => $s, 481 $k.'_code' => $code, 482 $k.'_re' => qr/$re/, 483 ) 484 } 485 qw( amp:& lt:< ); 486 487# Make the values of this private var available to the tests. 488sub __escape_sequences { %_escape } 489 490 491# HTML-entity encode any characters configured by the user. 492# If that doesn't include [&<] then we escape those chars so we can decide 493# later if we will entity-encode them or put them back verbatim. 494sub _encode_or_escape_entities { 495 my $self = $_[0]; 496 my $stash = $self->_private; 497 local $_ = $_[1]; 498 499 if( $stash->{encode_amp} ){ 500 if( exists($stash->{html_encode_chars}) ){ 501 # Escape all amps for later processing. 502 # Pass intermediate strings to entity encoder so that it doesn't 503 # process any of the characters of our escape sequences. 504 # Use -1 to get "as many fields as possible" so that we keep leading and 505 # trailing (possibly empty) fields. 506 $_ = join $_escape{amp}, map { $self->encode_entities($_) } split /&/, $_, -1; 507 } 508 else { 509 s/&/$_escape{amp}/g; 510 } 511 } 512 elsif( exists($stash->{html_encode_chars}) ){ 513 $_ = $self->encode_entities($_); 514 } 515 516 s/</$_escape{lt}/g 517 if $stash->{encode_lt}; 518 519 return $_; 520} 521 522# From Markdown.pl version 1.0.1 line 1172 (_DoAutoLinks). 523my $EMAIL_MARKER = qr{ 524# < # Opening token is in parent regexp. 525 (?:mailto:)? 526 ( 527 [-.\w]+ 528 \@ 529 [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+ 530 ) 531 > 532}x; 533 534# Process any escapes we put in the text earlier, 535# now that the text is complete (end of a block). 536sub _process_escapes { 537 my $self = $_[0]; 538 my $stash = $self->_private; 539 local $_ = $_[1]; 540 541 # The patterns below are taken from Markdown.pl 1.0.1 _EncodeAmpsAndAngles(). 542 # In this case we only want to encode the ones that Markdown won't. 543 # This is overkill but produces nicer looking text (less escaped entities). 544 # If it proves insufficent then we'll just encode them all. 545 546 # $1: If the escape was in a code sequence, simply replace the original. 547 # $2: If the unescaped value would be followed by characters 548 # that could be interpreted as html, entity-encode it. 549 # else: The character is safe to leave bare. 550 551 # Neither currently allows $2 to contain '0' so bool tests are sufficient. 552 553 if( $stash->{encode_amp} ){ 554 # Encode & if succeeded by chars that look like an html entity. 555 s,$_escape{amp_re}((?:#?[xX]?(?:[0-9a-fA-F]+|\w+);)?), 556 $1 ? '&'.$2 : $2 ? '&'.$2 : '&',egos; 557 } 558 559 if( $stash->{encode_lt} ){ 560 # Encode < if succeeded by chars that look like an html tag. 561 # Leave email addresses (<foo@bar.com>) for Markdown to process. 562 s,$_escape{lt_re}((?=$EMAIL_MARKER)|(?:[a-z/?\$!])?), 563 $1 ? '<'.$2 : $2 ? '<'.$2 : '<',egos; 564 } 565 566 return $_; 567} 568 569 570## Parsing ## 571 572sub handle_text { 573 my $self = $_[0]; 574 my $stash = $self->_private; 575 local $_ = $_[1]; 576 577 # Unless we're in a code span, verbatim block, or formatted region. 578 unless( $stash->{no_escape} ){ 579 580 # We could, in theory, alter what gets escaped according to context 581 # (for example, escape square brackets (but not parens) inside link text). 582 # The markdown produced might look slightly nicer but either way you're 583 # at the whim of the markdown processor to interpret things correctly. 584 # For now just escape everything. 585 586 # Don't let literal characters be interpreted as markdown. 587 $_ = $self->_escape_inline_markdown($_); 588 589 # Entity-encode (or escape for later processing) necessary/desired chars. 590 $_ = $self->_encode_or_escape_entities($_); 591 592 } 593 # If this _is_ a code section, do limited/specific handling. 594 else { 595 # Always escaping these chars ensures that we won't mangle the text 596 # in the unlikely event that a sequence matching our escape occurred in the 597 # input stream (since we're going to escape it and then unescape it). 598 s/&/$_escape{amp_code}/gos if $stash->{encode_amp}; 599 s/</$_escape{lt_code}/gos if $stash->{encode_lt}; 600 } 601 602 $self->_save($_); 603} 604 605sub start_Document { 606 my ($self) = @_; 607 $self->_new_stack; 608} 609 610sub end_Document { 611 my ($self) = @_; 612 $self->_check_search_header; 613 my $end = pop @{ $self->_private->{stacks} }; 614 615 @{ $self->_private->{stacks} } == 0 616 or die 'Document ended with stacks remaining'; 617 618 my @doc = $self->_chomp_all(join('', @$end)) . $/; 619 620 if( $self->include_meta_tags ){ 621 unshift @doc, $self->_build_markdown_head, ($/ x 2); 622 } 623 624 if( my $encoding = $self->_get_output_encoding ){ 625 # Do the check outside the loop(s) for efficiency. 626 my $ents = $HAS_HTML_ENTITIES ? \&__entity_encode_ord_he : \&__entity_encode_ord_basic; 627 # Iterate indices to avoid copying large strings. 628 for my $i ( 0 .. $#doc ){ 629 print { $self->{output_fh} } Encode::encode($encoding, $doc[$i], $ents); 630 } 631 } 632 else { 633 print { $self->{output_fh} } @doc; 634 } 635} 636 637sub _get_output_encoding { 638 my ($self) = @_; 639 640 # If 'match_encoding' is set we need to return an encoding. 641 # If pod has no =encoding, Pod::Simple will guess if it sees a high-bit char. 642 # If there are no high-bit chars, encoding is undef. 643 # Use detected_encoding() rather than encoding() because if Pod::Simple 644 # can't use whatever encoding was specified, we probably can't either. 645 # Fallback to 'o_e' if no match is found. This gives the user the choice, 646 # since otherwise there would be no reason to specify 'o_e' *and* 'm_e'. 647 # Fallback to UTF-8 since it is a reasonable default these days. 648 649 return $self->detected_encoding || $self->output_encoding || 'UTF-8' 650 if $self->match_encoding; 651 652 # If output encoding wasn't specified, return false. 653 return $self->output_encoding; 654} 655 656## Blocks ## 657 658sub start_Verbatim { 659 my ($self) = @_; 660 $self->_new_stack; 661 $self->_private->{no_escape} = 1; 662} 663 664sub end_Verbatim { 665 my ($self) = @_; 666 667 my $text = $self->_pop_stack_text; 668 669 $text = $self->_indent_verbatim($text); 670 671 $self->_private->{no_escape} = 0; 672 673 # Verbatim blocks do not generate a separate "Para" event. 674 $self->_save_block($text); 675} 676 677sub _indent_verbatim { 678 my ($self, $paragraph) = @_; 679 680 # NOTE: Pod::Simple expands the tabs for us (as suggested by perlpodspec). 681 # Pod::Simple also has a 'strip_verbatim_indent' attribute 682 # but it doesn't sound like it gains us anything over this method. 683 684 # POD verbatim can start with any number of spaces (or tabs) 685 # markdown should be 4 spaces (or a tab) 686 # so indent any paragraphs so that all lines start with at least 4 spaces 687 my @lines = split /\n/, $paragraph; 688 my $indent = ' ' x 4; 689 foreach my $line ( @lines ){ 690 next unless $line =~ m/^( +)/; 691 # find the smallest indentation 692 $indent = $1 if length($1) < length($indent); 693 } 694 if( (my $smallest = length($indent)) < 4 ){ 695 # invert to get what needs to be prepended 696 $indent = ' ' x (4 - $smallest); 697 698 # Prepend indent to each line. 699 # We could check /\S/ to only indent non-blank lines, 700 # but it's backward compatible to respect the whitespace. 701 # Additionally, both pod and markdown say they ignore blank lines 702 # so it shouldn't hurt to leave them in. 703 $paragraph = join "\n", map { length($_) ? $indent . $_ : '' } @lines; 704 } 705 706 return $paragraph; 707} 708 709sub start_Para { 710 $_[0]->_new_stack; 711} 712 713sub end_Para { 714 my ($self) = @_; 715 my $text = $self->_pop_stack_text; 716 717 $text = $self->_escape_paragraph_markdown($text); 718 719 $self->_save_block($text); 720} 721 722 723## Headings ## 724 725sub start_head1 { $_[0]->_start_head(1) } 726sub end_head1 { $_[0]->_end_head(1) } 727sub start_head2 { $_[0]->_start_head(2) } 728sub end_head2 { $_[0]->_end_head(2) } 729sub start_head3 { $_[0]->_start_head(3) } 730sub end_head3 { $_[0]->_end_head(3) } 731sub start_head4 { $_[0]->_start_head(4) } 732sub end_head4 { $_[0]->_end_head(4) } 733 734sub _check_search_header { 735 my ($self) = @_; 736 # Save the text since the last heading if we want it for metadata. 737 if( my $last = $self->_private->{search_header} ){ 738 for( $self->_private->{$last} = $self->_last_string ){ 739 s/\A\s+//; 740 s/\s+\z//; 741 } 742 } 743} 744sub _start_head { 745 my ($self) = @_; 746 $self->_check_search_header; 747 $self->_new_stack; 748} 749 750sub _end_head { 751 my ($self, $num) = @_; 752 my $h = '#' x $num; 753 754 my $text = $self->_pop_stack_text; 755 $self->_private->{search_header} = 756 $text =~ /NAME/ ? 'Title' 757 : $text =~ /AUTHOR/ ? 'Author' 758 : undef; 759 760 # TODO: option for $h suffix 761 # TODO: put a name="" if $self->{embed_anchor_tags}; ? 762 # https://rt.cpan.org/Ticket/Display.html?id=57776 763 $self->_save_block(join(' ', $h, $text)); 764} 765 766## Lists ## 767 768# With Pod::Simple->parse_empty_lists(1) there could be an over_empty event, 769# but what would you do with that? 770 771sub _start_list { 772 my ($self) = @_; 773 $self->_new_stack; 774 775 # Nest again b/c start_item will pop this to look for preceding content. 776 $self->_increase_indent; 777 $self->_new_stack; 778} 779 780sub _end_list { 781 my ($self) = @_; 782 $self->_handle_between_item_content; 783 784 # Finish the list. 785 786 # All the child elements should be blocks, 787 # but don't end with a double newline. 788 my $text = $self->_chomp_all($self->_pop_stack_text); 789 790 $_[0]->_save_line($text . $/); 791} 792 793sub _handle_between_item_content { 794 my ($self) = @_; 795 796 # This might be empty (if the list item had no additional content). 797 if( my $text = $self->_pop_stack_text ){ 798 # Else it's a sub-document. 799 # If there are blocks we need to separate with blank lines. 800 if( $self->_private->{last_state}->{blocks} ){ 801 $text = $/ . $text; 802 } 803 # If not, we can condense the text. 804 # In this module's history there was a patch contributed to specifically 805 # produce "huddled" lists so we'll try to maintain that functionality. 806 else { 807 $text = $self->_chomp_all($text) . $/; 808 } 809 $self->_save($text) 810 } 811 812 $self->_decrease_indent; 813} 814 815sub _start_item { 816 my ($self) = @_; 817 $self->_handle_between_item_content; 818 $self->_new_stack; 819} 820 821sub _end_item { 822 my ($self, $marker) = @_; 823 my $text = $self->_pop_stack_text; 824 $self->_save_line($self->_indent($marker . 825 # Add a space only if there is text after the marker. 826 (defined($text) && length($text) ? ' ' . $text : '') 827 )); 828 829 # Store any possible contents in a new stack (like a sub-document). 830 $self->_increase_indent; 831 $self->_new_stack; 832} 833 834sub start_over_bullet { $_[0]->_start_list } 835sub end_over_bullet { $_[0]->_end_list } 836 837sub start_item_bullet { $_[0]->_start_item } 838sub end_item_bullet { $_[0]->_end_item('-') } 839 840sub start_over_number { $_[0]->_start_list } 841sub end_over_number { $_[0]->_end_list } 842 843sub start_item_number { 844 $_[0]->_start_item; 845 # It seems like this should be a stack, 846 # but from testing it appears that the corresponding 'end' event 847 # comes right after the text (it doesn't surround any embedded content). 848 # See t/nested.t which shows start-item, text, end-item, para, start-item.... 849 $_[0]->_private->{item_number} = $_[1]->{number}; 850} 851 852sub end_item_number { 853 my ($self) = @_; 854 $self->_end_item($self->_private->{item_number} . '.'); 855} 856 857# Markdown doesn't support definition lists 858# so do regular (unordered) lists with indented paragraphs. 859sub start_over_text { $_[0]->_start_list } 860sub end_over_text { $_[0]->_end_list } 861 862sub start_item_text { $_[0]->_start_item } 863sub end_item_text { $_[0]->_end_item('-')} 864 865 866# perlpodspec equates an over/back region with no items to a blockquote. 867sub start_over_block { 868 # NOTE: We don't actually need to indent for a blockquote. 869 $_[0]->_new_stack; 870} 871 872sub end_over_block { 873 my ($self) = @_; 874 875 # Chomp first to avoid prefixing a blank line with a `>`. 876 my $text = $self->_chomp_all($self->_pop_stack_text); 877 878 # NOTE: Paragraphs will already be escaped. 879 880 # I don't really like either of these implementations 881 # but the join/map/split seems a little better and benches a little faster. 882 # You would lose the last newline but we've already chomped. 883 #$text =~ s{^(.)?}{'>' . (defined($1) && length($1) ? (' ' . $1) : '')}mge; 884 $text = join $/, map { length($_) ? '> ' . $_ : '>' } split qr-$/-, $text; 885 886 $self->_save_block($text); 887} 888 889## Custom Formats ## 890 891sub start_for { 892 my ($self, $attr) = @_; 893 $self->_new_stack; 894 895 if( $attr->{target} eq 'html' ){ 896 # Use another stack so we can indent 897 # (not syntactily necessary but seems appropriate). 898 $self->_new_stack; 899 $self->_increase_indent; 900 $self->_private->{no_escape} = 1; 901 # Mark this so we know to undo it. 902 $self->_stack_state->{for_html} = 1; 903 } 904} 905 906sub end_for { 907 my ($self) = @_; 908 # Data gets saved as a block (which will handle indents), 909 # but if there was html we'll alter this, so chomp and save a block again. 910 my $text = $self->_chomp_all($self->_pop_stack_text); 911 912 if( $self->_private->{last_state}->{for_html} ){ 913 $self->_private->{no_escape} = 0; 914 # Save it to the next stack up so we can pop it again (we made two stacks). 915 $self->_save($text); 916 $self->_decrease_indent; 917 $text = join "\n", '<div>', $self->_chomp_all($self->_pop_stack_text), '</div>'; 918 } 919 920 $self->_save_block($text); 921} 922 923# Data events will be emitted for any formatted regions that have been enabled 924# (by default, `markdown` and `html`). 925 926sub start_Data { 927 my ($self) = @_; 928 # TODO: limit this to what's in attr? 929 $self->_private->{no_escape}++; 930 $self->_new_stack; 931} 932 933sub end_Data { 934 my ($self) = @_; 935 my $text = $self->_pop_stack_text; 936 $self->_private->{no_escape}--; 937 $self->_save_block($text); 938} 939 940## Codes ## 941 942sub start_B { $_[0]->_save('**') } 943sub end_B { $_[0]->start_B() } 944 945sub start_I { $_[0]->_save('_') } 946sub end_I { $_[0]->start_I() } 947 948sub start_C { 949 my ($self) = @_; 950 $self->_new_stack; 951 $self->_private->{no_escape}++; 952} 953 954sub end_C { 955 my ($self) = @_; 956 $self->_private->{no_escape}--; 957 $self->_save( $self->_wrap_code_span($self->_pop_stack_text) ); 958} 959 960# Use code spans for F<>. 961sub start_F { shift->start_C(@_); } 962sub end_F { shift ->end_C(@_); } 963 964sub start_L { 965 my ($self, $flags) = @_; 966 $self->_new_stack; 967 push @{ $self->_private->{link} }, $flags; 968} 969 970sub end_L { 971 my ($self) = @_; 972 my $flags = pop @{ $self->_private->{link} } 973 or die 'Invalid state: link end with no link start'; 974 975 my ($type, $to, $section) = @{$flags}{qw( type to section )}; 976 977 my $url = ( 978 $type eq 'url' ? $to 979 : $type eq 'man' ? $self->format_man_url($to, $section) 980 : $type eq 'pod' ? $self->format_perldoc_url($to, $section) 981 : undef 982 ); 983 984 my $text = $self->_pop_stack_text; 985 986 # NOTE: I don't think the perlpodspec says what to do with L<|blah> 987 # but it seems like a blank link text just doesn't make sense 988 if( !length($text) ){ 989 $text = 990 $section ? 991 $to ? sprintf('"%s" in %s', $section, $to) 992 : ('"' . $section . '"') 993 : $to; 994 } 995 996 # FIXME: What does Pod::Simple::X?HTML do for this? 997 # if we don't know how to handle the url just print the pod back out 998 if (!$url) { 999 $self->_save(sprintf 'L<%s>', $flags->{raw}); 1000 return; 1001 } 1002 1003 # In the url we need to escape quotes and parentheses lest markdown 1004 # break the url (cut it short and/or wrongfully interpret a title). 1005 1006 # Backslash escapes do not work for the space and quotes. 1007 # URL-encoding the space is not sufficient 1008 # (the quotes confuse some parsers and produce invalid html). 1009 # I've arbitratily chosen HTML encoding to hide them from markdown 1010 # while mangling the url as litle as possible. 1011 $url =~ s/([ '"])/sprintf '&#x%x;', ord($1)/ge; 1012 1013 # We also need to double any backslashes that may be present 1014 # (lest they be swallowed up) and stop parens from breaking the url. 1015 $url =~ s/([\\()])/\\$1/g; 1016 1017 # TODO: put section name in title if not the same as $text 1018 $self->_save('[' . $text . '](' . $url . ')'); 1019} 1020 1021sub start_X { 1022 $_[0]->_new_stack; 1023} 1024 1025sub end_X { 1026 my ($self) = @_; 1027 my $text = $self->_pop_stack_text; 1028 # TODO: mangle $text? 1029 # TODO: put <a name="$text"> if configured 1030} 1031 1032# A code span can be delimited by multiple backticks (and a space) 1033# similar to pod codes (C<< code >>), so ensure we use a big enough 1034# delimiter to not have it broken by embedded backticks. 1035sub _wrap_code_span { 1036 my ($self, $arg) = @_; 1037 my $longest = 0; 1038 while( $arg =~ /([`]+)/g ){ 1039 my $len = length($1); 1040 $longest = $len if $longest < $len; 1041 } 1042 my $delim = '`' x ($longest + 1); 1043 my $pad = $longest > 0 ? ' ' : ''; 1044 return $delim . $pad . $arg . $pad . $delim; 1045} 1046 1047## Link Formatting (TODO: Move this to another module) ## 1048 1049 1050sub format_man_url { 1051 my ($self, $to) = @_; 1052 my ($page, $part) = ($to =~ /^ ([^(]+) (?: \( (\S+) \) )? /x); 1053 return $self->man_url_prefix . ($part || 1) . '/' . ($page || $to); 1054} 1055 1056 1057sub format_perldoc_url { 1058 my ($self, $name, $section) = @_; 1059 1060 my $url_prefix = $self->perldoc_url_prefix; 1061 if ( 1062 defined($name) 1063 && $self->is_local_module($name) 1064 && defined($self->local_module_url_prefix) 1065 ) { 1066 $url_prefix = $self->local_module_url_prefix; 1067 } 1068 1069 my $url = ''; 1070 1071 # If the link is to another module (external link). 1072 if ($name) { 1073 $url = $url_prefix . ($self->escape_url ? URI::Escape::uri_escape($name) : $name); 1074 } 1075 1076 # See https://rt.cpan.org/Ticket/Display.html?id=57776 1077 # for a discussion on the need to mangle the section. 1078 if ($section){ 1079 1080 my $method = $url 1081 # If we already have a prefix on the url it's external. 1082 ? $self->perldoc_fragment_format 1083 # Else an internal link points to this markdown doc. 1084 : $self->markdown_fragment_format; 1085 1086 $method = 'format_fragment_' . $method 1087 unless ref($method); 1088 1089 { 1090 # Set topic to enable code refs to be simple. 1091 local $_ = $section; 1092 $section = $self->$method($section); 1093 } 1094 1095 $url .= '#' . $section; 1096 } 1097 1098 return $url; 1099} 1100 1101 1102# TODO: simple, pandoc, etc? 1103 1104sub format_fragment_markdown { 1105 my ($self, $section) = @_; 1106 1107 # If this is an internal link (to another section in this doc) 1108 # we can't be sure what the heading id's will look like 1109 # (it depends on what is rendering the markdown to html) 1110 # but we can try to follow popular conventions. 1111 1112 # http://johnmacfarlane.net/pandoc/demo/example9/pandocs-markdown.html#header-identifiers-in-html-latex-and-context 1113 #$section =~ s/(?![-_.])[[:punct:]]//g; 1114 #$section =~ s/\s+/-/g; 1115 $section =~ s/\W+/-/g; 1116 $section =~ s/-+$//; 1117 $section =~ s/^-+//; 1118 $section = lc $section; 1119 #$section =~ s/^[^a-z]+//; 1120 $section ||= 'section'; 1121 1122 return $section; 1123} 1124 1125 1126{ 1127 # From Pod::Simple::XHTML 3.28. 1128 # The strings gets passed through encode_entities() before idify(). 1129 # If we don't do it here the substitutions below won't operate consistently. 1130 1131 sub format_fragment_pod_simple_xhtml { 1132 my ($self, $t) = @_; 1133 1134 # encode_entities { 1135 # We need to use the defaults in case html_encode_chars has been customized 1136 # (since the purpose is to match what external sources are doing). 1137 1138 local $self->_private->{html_encode_chars}; 1139 $t = $self->encode_entities($t); 1140 # } 1141 1142 # idify { 1143 for ($t) { 1144 s/<[^>]+>//g; # Strip HTML. 1145 s/&[^;]+;//g; # Strip entities. 1146 s/^\s+//; s/\s+$//; # Strip white space. 1147 s/^([^a-zA-Z]+)$/pod$1/; # Prepend "pod" if no valid chars. 1148 s/^[^a-zA-Z]+//; # First char must be a letter. 1149 s/[^-a-zA-Z0-9_:.]+/-/g; # All other chars must be valid. 1150 s/[-:.]+$//; # Strip trailing punctuation. 1151 } 1152 # } 1153 1154 return $t; 1155 } 1156} 1157 1158 1159sub format_fragment_pod_simple_html { 1160 my ($self, $section) = @_; 1161 1162 # From Pod::Simple::HTML 3.28. 1163 1164 # section_name_tidy { 1165 $section =~ s/^\s+//; 1166 $section =~ s/\s+$//; 1167 $section =~ tr/ /_/; 1168 $section =~ tr/\x00-\x1F\x80-\x9F//d if 'A' eq chr(65); # drop crazy characters 1169 1170 #$section = $self->unicode_escape_url($section); 1171 # unicode_escape_url { 1172 $section =~ s/([^\x00-\xFF])/'('.ord($1).')'/eg; 1173 # Turn char 1234 into "(1234)" 1174 # } 1175 1176 $section = '_' unless length $section; 1177 return $section; 1178 # } 1179} 1180 1181 1182sub format_fragment_metacpan { shift->format_fragment_pod_simple_xhtml(@_); } 1183sub format_fragment_sco { shift->format_fragment_pod_simple_html(@_); } 1184 1185 1186sub is_local_module { 1187 my ($self, $name) = @_; 1188 1189 return ($name =~ $self->local_module_re); 1190} 1191 11921; 1193 1194__END__ 1195 1196=pod 1197 1198=encoding UTF-8 1199 1200=for :stopwords Marcel Gruenauer Victor Moral Ryan C. Thompson <rct at thompsonclan d0t 1201org> Aristotle Pagaltzis Randy Stauner ACKNOWLEDGEMENTS html cpan 1202testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto 1203metadata placeholders metacpan 1204 1205=head1 NAME 1206 1207Pod::Markdown - Convert POD to Markdown 1208 1209=head1 VERSION 1210 1211version 3.300 1212 1213=for test_synopsis my ($pod_string); 1214 1215=head1 SYNOPSIS 1216 1217 # Pod::Simple API is supported. 1218 1219 # Command line usage: Parse a pod file and print to STDOUT: 1220 # $ perl -MPod::Markdown -e 'Pod::Markdown->new->filter(@ARGV)' path/to/POD/file > README.md 1221 1222 # Work with strings: 1223 my $markdown; 1224 my $parser = Pod::Markdown->new; 1225 $parser->output_string(\$markdown); 1226 $parser->parse_string_document($pod_string); 1227 1228 # See Pod::Simple docs for more. 1229 1230=head1 DESCRIPTION 1231 1232This module uses L<Pod::Simple> to convert POD to Markdown. 1233 1234Literal characters in Pod that are special in Markdown 1235(like *asterisks*) are backslash-escaped when appropriate. 1236 1237By default C<markdown> and C<html> formatted regions are accepted. 1238Regions of C<markdown> will be passed through unchanged. 1239Regions of C<html> will be placed inside a C<< E<lt>divE<gt> >> tag 1240so that markdown characters won't be processed. 1241Regions of C<:markdown> or C<:html> will be processed as POD and included. 1242To change which regions are accepted use the L<Pod::Simple> API: 1243 1244 my $parser = Pod::Markdown->new; 1245 $parser->unaccept_targets(qw( markdown html )); 1246 1247=head2 A note on encoding and escaping 1248 1249The common L<Pod::Simple> API returns a character string. 1250If you want Pod::Markdown to return encoded octets, there are two attributes 1251to assist: L</match_encoding> and L</output_encoding>. 1252 1253When an output encoding is requested any characters that are not valid 1254for that encoding will be escaped as HTML entities. 1255 1256This is not 100% safe, however. 1257 1258Markdown escapes all ampersands inside of code spans, so escaping a character 1259as an HTML entity inside of a code span will not be correct. 1260However, with pod's C<S> and C<E> sequences it is possible 1261to end up with high-bit characters inside of code spans. 1262 1263So, while C<< output_encoding => 'ascii' >> can work, it is not recommended. 1264For these reasons (and more), C<UTF-8> is the default, fallback encoding (when one is required). 1265 1266If you prefer HTML entities over literal characters you can use 1267L</html_encode_chars> which will only operate outside of code spans (where it is safe). 1268 1269=head1 METHODS 1270 1271=head2 new 1272 1273 Pod::Markdown->new(%options); 1274 1275The constructor accepts the following named arguments: 1276 1277=over 4 1278 1279=item * 1280 1281C<local_module_url_prefix> 1282 1283Alters the perldoc urls that are created from C<< LE<lt>E<gt> >> codes 1284when the module is a "local" module (C<"Local::*"> or C<"Foo_Corp::*"> (see L<perlmodlib>)). 1285 1286The default is to use C<perldoc_url_prefix>. 1287 1288=item * 1289 1290C<local_module_re> 1291 1292Alternate regular expression for determining "local" modules. 1293Default is C<< our $LOCAL_MODULE_RE = qr/^(Local::|\w*?_\w*)/ >>. 1294 1295=item * 1296 1297C<man_url_prefix> 1298 1299Alters the man page urls that are created from C<< LE<lt>E<gt> >> codes. 1300 1301The default is C<http://man.he.net/man>. 1302 1303=item * 1304 1305C<perldoc_url_prefix> 1306 1307Alters the perldoc urls that are created from C<< LE<lt>E<gt> >> codes. 1308Can be: 1309 1310=over 4 1311 1312=item * 1313 1314C<metacpan> (shortcut for C<https://metacpan.org/pod/>) 1315 1316=item * 1317 1318C<sco> (shortcut for C<http://search.cpan.org/perldoc?>) 1319 1320=item * 1321 1322any url 1323 1324=back 1325 1326The default is C<metacpan>. 1327 1328 Pod::Markdown->new(perldoc_url_prefix => 'http://localhost/perl/pod'); 1329 1330=item * 1331 1332C<perldoc_fragment_format> 1333 1334Alters the format of the url fragment for any C<< LE<lt>E<gt> >> links 1335that point to a section of an external document (C<< L<name/section> >>). 1336The default will be chosen according to the destination L</perldoc_url_prefix>. 1337Alternatively you can specify one of the following: 1338 1339=over 4 1340 1341=item * 1342 1343C<metacpan> 1344 1345=item * 1346 1347C<sco> 1348 1349=item * 1350 1351C<pod_simple_xhtml> 1352 1353=item * 1354 1355C<pod_simple_html> 1356 1357=item * 1358 1359A code ref 1360 1361=back 1362 1363The code ref can expect to receive two arguments: 1364the parser object (C<$self>) and the section text. 1365For convenience the topic variable (C<$_>) is also set to the section text: 1366 1367 perldoc_fragment_format => sub { s/\W+/-/g; } 1368 1369=item * 1370 1371C<markdown_fragment_format> 1372 1373Alters the format of the url fragment for any C<< LE<lt>E<gt> >> links 1374that point to an internal section of this document (C<< L</section> >>). 1375 1376Unfortunately the format of the id attributes produced 1377by whatever system translates the markdown into html is unknown at the time 1378the markdown is generated so we do some simple clean up. 1379 1380B<Note:> C<markdown_fragment_format> and C<perldoc_fragment_format> accept 1381the same values: a (shortcut to a) method name or a code ref. 1382 1383=item * 1384 1385C<include_meta_tags> 1386 1387Specifies whether or not to print author/title meta tags at the top of the document. 1388Default is false. 1389 1390=item * 1391 1392C<escape_url> 1393 1394Specifies whether or not to escape URLs. Default is true. It is not recommended 1395to turn this off with an empty local_module_url_prefix, as the resulting local 1396module URLs can be confused with IPv6 addresses by web browsers. 1397 1398=back 1399 1400=head2 html_encode_chars 1401 1402A string of characters to encode as html entities 1403(using L<HTML::Entities/encode_entities> if available, falling back to numeric entities if not). 1404 1405Possible values: 1406 1407=over 4 1408 1409=item * 1410 1411A value of C<1> will use the default set of characters from L<HTML::Entities> (control chars, high-bit chars, and C<< <&>"' >>). 1412 1413=item * 1414 1415A false value will disable. 1416 1417=item * 1418 1419Any other value is used as a string of characters (like a regular expression character class). 1420 1421=back 1422 1423By default this is disabled and literal characters will be in the output stream. 1424If you specify a desired L</output_encoding> any characters not valid for that encoding will be HTML entity encoded. 1425 1426B<Note> that Markdown requires ampersands (C<< & >>) and left angle brackets (C<< < >>) 1427to be entity-encoded if they could otherwise be interpreted as html entities. 1428If this attribute is configured to encode those characters, they will always be encoded. 1429If not, the module will make an effort to only encode the ones required, 1430so there will be less html noise in the output. 1431 1432=head2 match_encoding 1433 1434Boolean: If true, use the C<< =encoding >> of the input pod 1435as the encoding for the output. 1436 1437If no encoding is specified, L<Pod::Simple> will guess the encoding 1438if it sees a high-bit character. 1439 1440If no encoding is guessed (or the specified encoding is unusable), 1441L</output_encoding> will be used if it was specified. 1442Otherwise C<UTF-8> will be used. 1443 1444This attribute is not recommended 1445but is provided for consistency with other pod converters. 1446 1447Defaults to false. 1448 1449=head2 output_encoding 1450 1451The encoding to use when writing to the output file handle. 1452 1453If neither this nor L</match_encoding> are specified, 1454a character string will be returned in whatever L<Pod::Simple> output method you specified. 1455 1456=head2 local_module_re 1457 1458Returns the regular expression used to determine local modules. 1459 1460=head2 local_module_url_prefix 1461 1462Returns the url prefix in use for local modules. 1463 1464=head2 man_url_prefix 1465 1466Returns the url prefix in use for man pages. 1467 1468=head2 perldoc_url_prefix 1469 1470Returns the url prefix in use (after resolving shortcuts to urls). 1471 1472=head2 perldoc_fragment_format 1473 1474Returns the coderef or format name used to format a url fragment 1475to a section in an external document. 1476 1477=head2 markdown_fragment_format 1478 1479Returns the coderef or format name used to format a url fragment 1480to an internal section in this document. 1481 1482=head2 include_meta_tags 1483 1484Returns the boolean value indicating 1485whether or not meta tags will be printed. 1486 1487=head2 escape_url 1488 1489Returns the boolean value indicating 1490whether or not URLs should be escaped. 1491 1492=head2 format_man_url 1493 1494Used internally to create a url (using L</man_url_prefix>) 1495from a string like C<man(1)>. 1496 1497=head2 format_perldoc_url 1498 1499 # With $name and section being the two parts of L<name/section>. 1500 my $url = $parser->format_perldoc_url($name, $section); 1501 1502Used internally to create a url from 1503the name (of a module or script) 1504and a possible section (heading). 1505 1506The format of the url fragment (when pointing to a section in a document) 1507varies depending on the destination url 1508so L</perldoc_fragment_format> is used (which can be customized). 1509 1510If the module name portion of the link is blank 1511then the section is treated as an internal fragment link 1512(to a section of the generated markdown document) 1513and L</markdown_fragment_format> is used (which can be customized). 1514 1515=head2 format_fragment_markdown 1516 1517Format url fragment for an internal link 1518by replacing non-word characters with dashes. 1519 1520=head2 format_fragment_pod_simple_xhtml 1521 1522Format url fragment like L<Pod::Simple::XHTML/idify>. 1523 1524=head2 format_fragment_pod_simple_html 1525 1526Format url fragment like L<Pod::Simple::HTML/section_name_tidy>. 1527 1528=head2 format_fragment_metacpan 1529 1530Format fragment for L<metacpan.org> 1531(uses L</format_fragment_pod_simple_xhtml>). 1532 1533=head2 format_fragment_sco 1534 1535Format fragment for L<search.cpan.org> 1536(uses L</format_fragment_pod_simple_html>). 1537 1538=head2 is_local_module 1539 1540Uses C<local_module_re> to determine if passed module is a "local" module. 1541 1542=for Pod::Coverage parse_from_file 1543parse_from_filehandle 1544 1545=for Pod::Coverage as_markdown 1546 1547=for Pod::Coverage handle_text 1548end_.+ 1549start_.+ 1550encode_entities 1551 1552=head1 SEE ALSO 1553 1554=over 4 1555 1556=item * 1557 1558L<pod2markdown> - script included for command line usage 1559 1560=item * 1561 1562L<Pod::Simple> - Super class that handles Pod parsing 1563 1564=item * 1565 1566L<perlpod> - For writing POD 1567 1568=item * 1569 1570L<perlpodspec> - For parsing POD 1571 1572=item * 1573 1574L<http://daringfireball.net/projects/markdown/syntax> - Markdown spec 1575 1576=back 1577 1578=head1 SUPPORT 1579 1580=head2 Perldoc 1581 1582You can find documentation for this module with the perldoc command. 1583 1584 perldoc Pod::Markdown 1585 1586=head2 Websites 1587 1588The following websites have more information about this module, and may be of help to you. As always, 1589in addition to those websites please use your favorite search engine to discover more resources. 1590 1591=over 4 1592 1593=item * 1594 1595MetaCPAN 1596 1597A modern, open-source CPAN search engine, useful to view POD in HTML format. 1598 1599L<https://metacpan.org/release/Pod-Markdown> 1600 1601=back 1602 1603=head2 Bugs / Feature Requests 1604 1605Please report any bugs or feature requests by email to C<bug-pod-markdown at rt.cpan.org>, or through 1606the web interface at L<https://rt.cpan.org/Public/Bug/Report.html?Queue=Pod-Markdown>. You will be automatically notified of any 1607progress on the request by the system. 1608 1609=head2 Source Code 1610 1611 1612L<https://github.com/rwstauner/Pod-Markdown> 1613 1614 git clone https://github.com/rwstauner/Pod-Markdown.git 1615 1616=head1 AUTHORS 1617 1618=over 4 1619 1620=item * 1621 1622Marcel Gruenauer <marcel@cpan.org> 1623 1624=item * 1625 1626Victor Moral <victor@taquiones.net> 1627 1628=item * 1629 1630Ryan C. Thompson <rct at thompsonclan d0t org> 1631 1632=item * 1633 1634Aristotle Pagaltzis <pagaltzis@gmx.de> 1635 1636=item * 1637 1638Randy Stauner <rwstauner@cpan.org> 1639 1640=back 1641 1642=head1 CONTRIBUTORS 1643 1644=for stopwords Aristotle Pagaltzis Cindy Wang (CindyLinz) Graham Ollis Mike Covington motemen moznion Peter Vereshagin Ryan C. Thompson Yasutaka ATARASHI 1645 1646=over 4 1647 1648=item * 1649 1650Aristotle Pagaltzis <aristotle@cpan.org> 1651 1652=item * 1653 1654Cindy Wang (CindyLinz) <cindylinz@gmail.com> 1655 1656=item * 1657 1658Graham Ollis <plicease@cpan.org> 1659 1660=item * 1661 1662Mike Covington <mfcovington@gmail.com> 1663 1664=item * 1665 1666motemen <motemen@cpan.org> 1667 1668=item * 1669 1670moznion <moznion@cpan.org> 1671 1672=item * 1673 1674Peter Vereshagin <veresc@cpan.org> 1675 1676=item * 1677 1678Ryan C. Thompson <rthompson@cpan.org> 1679 1680=item * 1681 1682Yasutaka ATARASHI <yakex@cpan.org> 1683 1684=back 1685 1686=head1 COPYRIGHT AND LICENSE 1687 1688This software is copyright (c) 2011 by Randy Stauner. 1689 1690This is free software; you can redistribute it and/or modify it under 1691the same terms as the Perl 5 programming language system itself. 1692 1693=cut 1694