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