, and L should work in headers
I, B, C, and L should work in body text.
POD
< Quote some poetry
> or say something special.
MKDN
'over/back becomes block quote';
convert_ok
< C<< E >> codes
POD
< C<< E >> codes
MKDN
'';
done_testing;
META.yml 100644 001750 001751 51473 14517525267 16674 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400 ---
abstract: 'Convert POD to Markdown'
author:
- 'Marcel Gruenauer '
- 'Victor Moral '
- 'Ryan C. Thompson '
- 'Aristotle Pagaltzis '
- 'Randy Stauner '
build_requires:
Exporter: '0'
ExtUtils::MakeMaker: '0'
File::Spec: '0'
File::Spec::Functions: '0'
File::Temp: '0'
IO::Handle: '0'
IPC::Open3: '0'
Symbol: '0'
Test::Differences: '0'
Test::More: '0.88'
lib: '0'
perl: '5.008'
utf8: '0'
configure_requires:
ExtUtils::MakeMaker: '0'
perl: '5.008'
dynamic_config: 0
generated_by: 'Dist::Zilla version 6.024, CPAN::Meta::Converter version 2.150010'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: '1.4'
name: Pod-Markdown
no_index:
directory:
- corpus
- examples
- fatlib
- inc
- local
- perl5
- share
- t
- xt
namespace:
- Local
- t::lib
package:
- DB
provides:
Pod::Markdown:
file: lib/Pod/Markdown.pm
version: '3.400'
Pod::Perldoc::ToMarkdown:
file: lib/Pod/Perldoc/ToMarkdown.pm
version: '3.400'
recommends:
HTML::Entities: '0'
requires:
Encode: '0'
Getopt::Long: '0'
Pod::Simple: '3.27'
Pod::Simple::Methody: '0'
Pod::Usage: '0'
URI::Escape: '0'
parent: '0'
perl: '5.008'
strict: '0'
warnings: '0'
resources:
bugtracker: https://rt.cpan.org/Public/Dist/Display.html?Name=Pod-Markdown
homepage: https://github.com/rwstauner/Pod-Markdown
repository: https://github.com/rwstauner/Pod-Markdown.git
version: '3.400'
x_Dist_Zilla:
perl:
version: '5.034000'
plugins:
-
class: Dist::Zilla::Plugin::Git::NextVersion
config:
Dist::Zilla::Plugin::Git::NextVersion:
first_version: '0.001'
version_by_branch: 0
version_regexp: (?^:^v(.+)$)
Dist::Zilla::Role::Git::Repo:
git_version: 2.42.0
repo_root: .
name: '@Author::RWSTAUNER/Git::NextVersion'
version: '2.048'
-
class: Dist::Zilla::Plugin::GenerateFile
name: '@Author::RWSTAUNER/GenerateManifestSkip'
version: '6.024'
-
class: Dist::Zilla::Plugin::GatherDir
config:
Dist::Zilla::Plugin::GatherDir:
exclude_filename:
- LICENSE
exclude_match: []
follow_symlinks: 0
include_dotfiles: 0
prefix: ''
prune_directory: []
root: .
name: '@Author::RWSTAUNER/GatherDir'
version: '6.024'
-
class: Dist::Zilla::Plugin::PruneCruft
name: '@Author::RWSTAUNER/PruneCruft'
version: '6.024'
-
class: Dist::Zilla::Plugin::ManifestSkip
name: '@Author::RWSTAUNER/ManifestSkip'
version: '6.024'
-
class: Dist::Zilla::Plugin::PruneFiles
name: '@Author::RWSTAUNER/PruneDevelCoverDatabase'
version: '6.024'
-
class: Dist::Zilla::Plugin::PruneFiles
name: '@Author::RWSTAUNER/PruneCodeStatCollection'
version: '6.024'
-
class: Dist::Zilla::Plugin::PruneFiles
name: '@Author::RWSTAUNER/PruneTags'
version: '6.024'
-
class: Dist::Zilla::Plugin::PkgVersion
name: '@Author::RWSTAUNER/PkgVersion'
version: '6.024'
-
class: Dist::Zilla::Plugin::Authority
name: '@Author::RWSTAUNER/Authority'
version: '1.009'
-
class: Dist::Zilla::Plugin::NextRelease
name: '@Author::RWSTAUNER/NextRelease'
version: '6.024'
-
class: Dist::Zilla::Plugin::Git::Describe
name: '@Author::RWSTAUNER/Git::Describe'
version: '0.007'
-
class: Dist::Zilla::Plugin::Prepender
name: '@Author::RWSTAUNER/Prepender'
version: '2.004'
-
class: Dist::Zilla::Plugin::PodWeaver
config:
Dist::Zilla::Plugin::PodWeaver:
config_plugins:
- '@Author::RWSTAUNER'
finder:
- ':InstallModules'
- ':ExecFiles'
plugins:
-
class: Pod::Weaver::Plugin::SingleEncoding
name: '@Author::RWSTAUNER/SingleEncoding'
version: '4.018'
-
class: Pod::Weaver::Plugin::WikiDoc
name: '@Author::RWSTAUNER/WikiDoc'
version: '0.093004'
-
class: Pod::Weaver::Plugin::EnsurePod5
name: '@CorePrep/EnsurePod5'
version: '4.018'
-
class: Pod::Weaver::Plugin::H1Nester
name: '@CorePrep/H1Nester'
version: '4.018'
-
class: Pod::Weaver::Section::Name
name: '@Author::RWSTAUNER/Name'
version: '4.018'
-
class: Pod::Weaver::Section::Version
name: '@Author::RWSTAUNER/Version'
version: '4.018'
-
class: Pod::Weaver::Section::Region
name: '@Author::RWSTAUNER/Prelude'
version: '4.018'
-
class: Pod::Weaver::Section::Region
name: '@Author::RWSTAUNER/test_synopsis'
version: '4.018'
-
class: Pod::Weaver::Section::Generic
name: '@Author::RWSTAUNER/Synopsis'
version: '4.018'
-
class: Pod::Weaver::Section::Generic
name: '@Author::RWSTAUNER/Description'
version: '4.018'
-
class: Pod::Weaver::Section::Generic
name: '@Author::RWSTAUNER/Overview'
version: '4.018'
-
class: Pod::Weaver::Section::Generic
name: '@Author::RWSTAUNER/Usage'
version: '4.018'
-
class: Pod::Weaver::Section::Collect
name: '@Author::RWSTAUNER/Class Methods'
version: '4.018'
-
class: Pod::Weaver::Section::Collect
name: '@Author::RWSTAUNER/Attributes'
version: '4.018'
-
class: Pod::Weaver::Section::Collect
name: '@Author::RWSTAUNER/Methods'
version: '4.018'
-
class: Pod::Weaver::Section::Collect
name: '@Author::RWSTAUNER/Functions'
version: '4.018'
-
class: Pod::Weaver::Section::Leftovers
name: '@Author::RWSTAUNER/Leftovers'
version: '4.018'
-
class: Pod::Weaver::Section::Region
name: '@Author::RWSTAUNER/Postlude'
version: '4.018'
-
class: Pod::Weaver::Section::Support
name: '@Author::RWSTAUNER/Support'
version: '1.013'
-
class: Pod::Weaver::Section::Generic
name: '@Author::RWSTAUNER/Acknowledgements'
version: '4.018'
-
class: Pod::Weaver::Section::Authors
name: '@Author::RWSTAUNER/Authors'
version: '4.018'
-
class: Pod::Weaver::Section::Contributors
name: '@Author::RWSTAUNER/Contributors'
version: '0.009'
-
class: Pod::Weaver::Section::Legal
name: '@Author::RWSTAUNER/Legal'
version: '4.018'
-
class: Pod::Weaver::Plugin::Transformer
name: '@Author::RWSTAUNER/List'
version: '4.018'
-
class: Pod::Weaver::Plugin::StopWords
name: '@Author::RWSTAUNER/StopWords'
version: '1.010'
name: '@Author::RWSTAUNER/PodWeaver'
version: '4.009'
-
class: Dist::Zilla::Plugin::License
name: '@Author::RWSTAUNER/License'
version: '6.024'
-
class: Dist::Zilla::Plugin::Readme
name: '@Author::RWSTAUNER/Readme'
version: '6.024'
-
class: Dist::Zilla::Plugin::ReadmeAnyFromPod
config:
Dist::Zilla::Role::FileWatcher:
version: '0.006'
name: '@Author::RWSTAUNER/ReadmeAnyFromPod'
version: '0.163250'
-
class: Dist::Zilla::Plugin::GitHubREADME::Badge
name: '@Author::RWSTAUNER/GitHubREADME::Badge'
version: '0.33'
-
class: Dist::Zilla::Plugin::CopyFilesFromRelease
config:
Dist::Zilla::Plugin::CopyFilesFromRelease:
filename:
- LICENSE
match: []
name: '@Author::RWSTAUNER/CopyFilesFromRelease'
version: '0.007'
-
class: Dist::Zilla::Plugin::AutoMetaResources
name: '@Author::RWSTAUNER/AutoMetaResources'
version: '1.21'
-
class: Dist::Zilla::Plugin::GithubMeta
name: '@Author::RWSTAUNER/GithubMeta'
version: '0.58'
-
class: Dist::Zilla::Plugin::Git::Contributors
config:
Dist::Zilla::Plugin::Git::Contributors:
git_version: 2.42.0
include_authors: 0
include_releaser: 1
order_by: name
paths: []
name: '@Author::RWSTAUNER/Git::Contributors'
version: '0.036'
-
class: Dist::Zilla::Plugin::AutoPrereqs
name: '@Author::RWSTAUNER/AutoPrereqs'
version: '6.024'
-
class: Dist::Zilla::Plugin::MetaNoIndex
name: '@Author::RWSTAUNER/MetaNoIndex'
version: '6.024'
-
class: Dist::Zilla::Plugin::MetaProvides::Package
config:
Dist::Zilla::Plugin::MetaProvides::Package:
finder_objects:
-
class: Dist::Zilla::Plugin::FinderCode
name: '@Author::RWSTAUNER/MetaProvides::Package/AUTOVIV/:InstallModulesPM'
version: '6.024'
include_underscores: 0
Dist::Zilla::Role::MetaProvider::Provider:
$Dist::Zilla::Role::MetaProvider::Provider::VERSION: '2.002004'
inherit_missing: '1'
inherit_version: '1'
meta_noindex: '1'
Dist::Zilla::Role::ModuleMetadata:
Module::Metadata: '1.000037'
version: '0.006'
name: '@Author::RWSTAUNER/MetaProvides::Package'
version: '2.004003'
-
class: Dist::Zilla::Plugin::MinimumPerl
name: '@Author::RWSTAUNER/MinimumPerl'
version: '1.006'
-
class: Dist::Zilla::Plugin::MetaConfig
name: '@Author::RWSTAUNER/MetaConfig'
version: '6.024'
-
class: Dist::Zilla::Plugin::MetaYAML
name: '@Author::RWSTAUNER/MetaYAML'
version: '6.024'
-
class: Dist::Zilla::Plugin::MetaJSON
name: '@Author::RWSTAUNER/MetaJSON'
version: '6.024'
-
class: Dist::Zilla::Plugin::ExecDir
name: '@Author::RWSTAUNER/ExecDir'
version: '6.024'
-
class: Dist::Zilla::Plugin::ShareDir
name: '@Author::RWSTAUNER/ShareDir'
version: '6.024'
-
class: Dist::Zilla::Plugin::MakeMaker
config:
Dist::Zilla::Role::TestRunner:
default_jobs: 1
name: '@Author::RWSTAUNER/MakeMaker'
version: '6.024'
-
class: Dist::Zilla::Plugin::Test::ReportPrereqs
name: '@Author::RWSTAUNER/Test::ReportPrereqs'
version: '0.028'
-
class: Dist::Zilla::Plugin::Test::PodSpelling
config:
Dist::Zilla::Plugin::Test::PodSpelling:
directories:
- bin
- lib
spell_cmd: ''
stopwords: []
wordlist: Pod::Wordlist
name: '@Author::RWSTAUNER/Test::PodSpelling'
version: '2.007005'
-
class: Dist::Zilla::Plugin::Test::EOL
config:
Dist::Zilla::Plugin::Test::EOL:
filename: xt/author/eol.t
finder:
- ':ExecFiles'
- ':InstallModules'
- ':TestFiles'
trailing_whitespace: 0
name: '@Author::RWSTAUNER/@TestingMania/Test::EOL'
version: '0.19'
-
class: Dist::Zilla::Plugin::PodCoverageTests
name: '@Author::RWSTAUNER/@TestingMania/PodCoverageTests'
version: '6.024'
-
class: Dist::Zilla::Plugin::Test::CPAN::Changes
config:
Dist::Zilla::Plugin::Test::CPAN::Changes:
changelog: Changes
name: '@Author::RWSTAUNER/@TestingMania/Test::CPAN::Changes'
version: '0.012'
-
class: Dist::Zilla::Plugin::Test::CPAN::Meta::JSON
name: '@Author::RWSTAUNER/@TestingMania/Test::CPAN::Meta::JSON'
version: '0.004'
-
class: Dist::Zilla::Plugin::Test::Portability
config:
Dist::Zilla::Plugin::Test::Portability:
options: ''
name: '@Author::RWSTAUNER/@TestingMania/Test::Portability'
version: '2.001000'
-
class: Dist::Zilla::Plugin::Test::Perl::Critic
name: '@Author::RWSTAUNER/@TestingMania/Test::Perl::Critic'
version: '3.001'
-
class: Dist::Zilla::Plugin::Test::DistManifest
name: '@Author::RWSTAUNER/@TestingMania/Test::DistManifest'
version: '2.000005'
-
class: Dist::Zilla::Plugin::MojibakeTests
name: '@Author::RWSTAUNER/@TestingMania/MojibakeTests'
version: '0.8'
-
class: Dist::Zilla::Plugin::PodSyntaxTests
name: '@Author::RWSTAUNER/@TestingMania/PodSyntaxTests'
version: '6.024'
-
class: Dist::Zilla::Plugin::MetaTests
name: '@Author::RWSTAUNER/@TestingMania/MetaTests'
version: '6.024'
-
class: Dist::Zilla::Plugin::Test::Synopsis
name: '@Author::RWSTAUNER/@TestingMania/Test::Synopsis'
version: '2.000007'
-
class: Dist::Zilla::Plugin::Test::MinimumVersion
config:
Dist::Zilla::Plugin::Test::MinimumVersion:
max_target_perl: '5.008'
name: '@Author::RWSTAUNER/@TestingMania/Test::MinimumVersion'
version: '2.000010'
-
class: Dist::Zilla::Plugin::Test::Kwalitee
config:
Dist::Zilla::Plugin::Test::Kwalitee:
filename: xt/release/kwalitee.t
skiptest: []
name: '@Author::RWSTAUNER/@TestingMania/Test::Kwalitee'
version: '2.12'
-
class: Dist::Zilla::Plugin::Test::Version
name: '@Author::RWSTAUNER/@TestingMania/Test::Version'
version: '1.09'
-
class: Dist::Zilla::Plugin::Test::NoTabs
config:
Dist::Zilla::Plugin::Test::NoTabs:
filename: xt/author/no-tabs.t
finder:
- ':InstallModules'
- ':ExecFiles'
- ':TestFiles'
name: '@Author::RWSTAUNER/@TestingMania/Test::NoTabs'
version: '0.15'
-
class: Dist::Zilla::Plugin::Test::Compile
config:
Dist::Zilla::Plugin::Test::Compile:
bail_out_on_fail: '0'
fail_on_warning: author
fake_home: 1
filename: t/00-compile.t
module_finder:
- ':InstallModules'
needs_display: 0
phase: test
script_finder:
- ':PerlExecFiles'
skips: []
switch: []
name: '@Author::RWSTAUNER/@TestingMania/Test::Compile'
version: '2.058'
-
class: Dist::Zilla::Plugin::Manifest
name: '@Author::RWSTAUNER/Manifest'
version: '6.024'
-
class: Dist::Zilla::Plugin::CheckExtraTests
name: '@Author::RWSTAUNER/CheckExtraTests'
version: '0.029'
-
class: Dist::Zilla::Plugin::CheckChangesHasContent
name: '@Author::RWSTAUNER/CheckChangesHasContent'
version: '0.011'
-
class: Dist::Zilla::Plugin::CheckMetaResources
name: '@Author::RWSTAUNER/CheckMetaResources'
version: '0.001'
-
class: Dist::Zilla::Plugin::CheckPrereqsIndexed
name: '@Author::RWSTAUNER/CheckPrereqsIndexed'
version: '0.021'
-
class: Dist::Zilla::Plugin::TestRelease
name: '@Author::RWSTAUNER/TestRelease'
version: '6.024'
-
class: Dist::Zilla::Plugin::Git::Check
config:
Dist::Zilla::Plugin::Git::Check:
untracked_files: die
Dist::Zilla::Role::Git::DirtyFiles:
allow_dirty:
- Changes
- LICENSE
- README.mkdn
- README.pod
allow_dirty_match: []
changelog: Changes
Dist::Zilla::Role::Git::Repo:
git_version: 2.42.0
repo_root: .
name: '@Author::RWSTAUNER/@Git/Check'
version: '2.048'
-
class: Dist::Zilla::Plugin::Git::Commit
config:
Dist::Zilla::Plugin::Git::Commit:
add_files_in: []
commit_msg: v%v%t%n%n%c
signoff: '0'
Dist::Zilla::Role::Git::DirtyFiles:
allow_dirty:
- Changes
- LICENSE
- README.mkdn
- README.pod
allow_dirty_match: []
changelog: Changes
Dist::Zilla::Role::Git::Repo:
git_version: 2.42.0
repo_root: .
Dist::Zilla::Role::Git::StringFormatter:
time_zone: local
name: '@Author::RWSTAUNER/@Git/Commit'
version: '2.048'
-
class: Dist::Zilla::Plugin::Git::Tag
config:
Dist::Zilla::Plugin::Git::Tag:
branch: ~
changelog: Changes
signed: 0
tag: v3.400
tag_format: v%V
tag_message: v%V
Dist::Zilla::Role::Git::Repo:
git_version: 2.42.0
repo_root: .
Dist::Zilla::Role::Git::StringFormatter:
time_zone: local
name: '@Author::RWSTAUNER/@Git/Tag'
version: '2.048'
-
class: Dist::Zilla::Plugin::Git::Push
config:
Dist::Zilla::Plugin::Git::Push:
push_to:
- origin
remotes_must_exist: 1
Dist::Zilla::Role::Git::Repo:
git_version: 2.42.0
repo_root: .
name: '@Author::RWSTAUNER/@Git/Push'
version: '2.048'
-
class: Dist::Zilla::Plugin::ConfirmRelease
name: '@Author::RWSTAUNER/ConfirmRelease'
version: '6.024'
-
class: Dist::Zilla::Plugin::UploadToCPAN
name: '@Author::RWSTAUNER/UploadToCPAN'
version: '6.024'
-
class: Dist::Zilla::Plugin::InstallRelease
name: '@Author::RWSTAUNER/InstallRelease'
version: '0.008'
-
class: Dist::Zilla::Plugin::Encoding
name: CP1252
version: '6.024'
-
class: Dist::Zilla::Plugin::Prereqs
config:
Dist::Zilla::Plugin::Prereqs:
phase: runtime
type: requires
name: RuntimeRequires
version: '6.024'
-
class: Dist::Zilla::Plugin::Prereqs
config:
Dist::Zilla::Plugin::Prereqs:
phase: runtime
type: recommends
name: RuntimeRecommends
version: '6.024'
-
class: Dist::Zilla::Plugin::Prereqs
config:
Dist::Zilla::Plugin::Prereqs:
phase: develop
type: recommends
name: DevelopRecommends
version: '6.024'
-
class: Dist::Zilla::Plugin::Run::AfterRelease
config:
Dist::Zilla::Plugin::Run::Role::Runner:
fatal_errors: 1
quiet: 0
run:
- "perl -i -pe '$orig = q[2009-2011 by Marcel Gruenauer.]; /\\Q$orig\\E/ and $already=1; $already or s/^(#?)(\\s*This software is copyright \\(c\\))( \\d+ by Randy Stauner\\.)/$1$2 $orig\\n$1\\n$1$2$3/' %d/lib/Pod/Markdown.pm %d/bin/pod2markdown %d/README* %d/LICENSE README*"
version: '0.048'
name: Run::AfterRelease
version: '0.048'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':InstallModules'
version: '6.024'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':IncModules'
version: '6.024'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':TestFiles'
version: '6.024'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':ExtraTestFiles'
version: '6.024'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':ExecFiles'
version: '6.024'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':PerlExecFiles'
version: '6.024'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':ShareFiles'
version: '6.024'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':MainModule'
version: '6.024'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':AllFiles'
version: '6.024'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':NoFiles'
version: '6.024'
-
class: Dist::Zilla::Plugin::FinderCode
name: '@Author::RWSTAUNER/MetaProvides::Package/AUTOVIV/:InstallModulesPM'
version: '6.024'
zilla:
class: Dist::Zilla::Dist::Builder
config:
is_trial: '0'
version: '6.024'
x_authority: cpan:RWSTAUNER
x_contributors:
- 'Aristotle Pagaltzis '
- 'Cindy Wang (CindyLinz) '
- 'Graham Ollis '
- 'Johannes Schauer Marin Rodrigues '
- 'Mike Covington '
- 'motemen '
- 'moznion '
- 'Peter Vereshagin '
- 'Ryan C. Thompson '
- 'Yasutaka ATARASHI '
x_generated_by_perl: v5.34.0
x_serialization_backend: 'YAML::Tiny version 1.73'
x_spdx_expression: 'Artistic-1.0-Perl OR GPL-1.0-or-later'
MANIFEST 100644 001750 001751 1763 14517525267 16531 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400 # This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.024.
Changes
LICENSE
MANIFEST
MANIFEST.SKIP
META.json
META.yml
Makefile.PL
README
bin/pod2markdown
corpus/copy-enc.pod
corpus/copy.pod
corpus/lit-cp1252-enc.pod
corpus/lit-cp1252.pod
corpus/lit-utf8-enc.pod
corpus/lit-utf8.pod
corpus/tinypod.txt
dist.ini
lib/Pod/Markdown.pm
lib/Pod/Perldoc/ToMarkdown.pm
t/00-compile.t
t/00-report-prereqs.dd
t/00-report-prereqs.t
t/back-compat.t
t/basic.t
t/codes.t
t/encoding.t
t/entities.t
t/escape.t
t/formats.t
t/lib/MarkdownTests.pm
t/links.t
t/lists.t
t/meta.t
t/misc.t
t/nested.t
t/new.t
t/perldoc.t
t/pod2markdown.t
t/verbatim.t
xt/author/critic.t
xt/author/distmeta.t
xt/author/eol.t
xt/author/minimum-version.t
xt/author/mojibake.t
xt/author/no-tabs.t
xt/author/pod-coverage.t
xt/author/pod-spell.t
xt/author/pod-syntax.t
xt/author/portability.t
xt/author/synopsis.t
xt/author/test-version.t
xt/release/cpan-changes.t
xt/release/dist-manifest.t
xt/release/kwalitee.t
xt/release/meta-json.t
codes.t 100644 001750 001751 6043 14517525267 17121 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use utf8;
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests;
my $pod_prefix = test_parser()->perldoc_url_prefix;
sub code {
my ($pod, $exp, %opts) = @_;
my $desc = delete $opts{desc} || $pod;
my %args = (
init => delete($opts{init}),
);
convert_code_ok($pod, $exp, $desc, {}, %args);
if( my $ents = delete $opts{entities} ){
# Use the same value for both if only one is specified.
$ents->[1] = $ents->[0] if @$ents == 1;
with_and_without_entities {
my $e = $ents->[ $_[0] ? 0 : 1 ];
convert_code_ok($pod, $e, $desc, {
html_encode_chars => '^\x20-\x7e', # most chars
}, %args);
};
}
if( my $utf8 = delete $opts{utf8} ){
convert_code_ok($pod, $utf8, $desc, { output_encoding => 'UTF-8' }, %args);
}
die "Invalid args: %opts" if keys %opts;
}
sub convert_code_ok {
my ($pod, $exp, $desc, $attr, %opts) = @_;
convert_ok($pod, $exp, $desc, %opts, attr => $attr, verbose => 1,
# Prefix line to avoid escaping beginning-of-line characters (like `>`).
prefix => 'Code: ',
);
}
code 'I', '_italic_';
code 'B', '**bold**';
code 'C', '`code`';
code 'C', '`c*de`';
# Links tested extensively in t/links.t.
code 'L', "[link](${pod_prefix}link)";
code 'L', "[star\\*](${pod_prefix}star%2A)";
# Pod::Simple handles the E<> entirely (Pod::Markdown never sees them).
code 'E', '<';
code 'E', '>';
code 'E', '|';
code 'E', '/';
code 'E', '©', entities => ['©'], utf8 => "\xc2\xa9";
code 'E', 'é', entities => ['é', 'é'], utf8 => "\xc3\xa9";
code 'E<0x201E>', '„', entities => ['„', '„'], desc => 'E hex';
code 'E<075>', '=', desc => 'E octal';
code 'E<0241>', '¡', entities => ['¡', '¡'], utf8 => "\xc2\xa1", desc => 'E octal';
code 'E<181>', 'µ', entities => ['µ', 'µ'], desc => 'E decimal';
# Legacy charnames specifically mentioned by perlpodspec.
code 'E', '«', entities => ['«', '«'], utf8 => "\xc2\xab";
code 'E', '»', entities => ['»', '»'], utf8 => "\xc2\xbb";
# Translate F<> as code spans.
code 'F', '`file.ext`';
code 'F', '`file_path.ext`';
code 'F', '`` /weird/file`path` ``';
# S<> for non-breaking spaces.
code 'S<$x ? $y : $z>', '$x ? $y : $z', # Literal NBSP chars.
# Entity-encode nbsp (whether we have HTML::Entities or not).
entities => ['$x ? $y : $z'];
code 'S>', '`$x & $y`', # Literal NBSP chars.
# Amps inside code spans will get escaped, so leave nsbp bare.
entities => ['`$x & $y`'];
code 'S<$x C<& $y>>', '$x `& $y`', # Just spaces.
entities => ['$x `& $y`'],
init => sub { $_[0]->nbsp_for_S(0) };
# Zero-width entries.
code 'X', '';
code 'Z<>', '';
# Pod::Simple swallows unknown codes.
#code 'Q', 'Q', desc => 'uknown code (Q<>)';
done_testing;
lists.t 100644 001750 001751 5172 14517525267 17164 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests tests => 1;
my $parser = Pod::Markdown->new(
perldoc_url_prefix => 'pod:',
);
$parser->output_string(\my $markdown);
$parser->parse_file(\*DATA);
# TODO: Verify this list behavior in html and perlpod(spec).
my $expect = <<'EOMARKDOWN';
# Lists
## Unordered
- This
- is
- a
basic
- bulleted
item
- list
- test
- and _Italics_, **Bold**, `Code`, and [Links](pod:Links) should work in list item
and _in_ **paragraph** `after` [item](pod:item)
- verbatim paragraphs
need double-indent inside lists
## Unordered nested list
**Note:** Markdown does not support definition lists (word => text), just bullets or numbers
- Head1
Paragraph should be indented.
\* And escaped.
- Head2
Paragraph should be indented.
- Head1
Paragraph should be indented.
## Unordered nested huddled list
- This is a list head.
- This is a list head, too.
- Again, this is a list head.
- Finally, this is also a list head.
And
- A list item
\\with a line that starts with a markdown char.
- item 2
## Ordered
1. B
2. D
## Ordered without dot
1. B
2. D
## No text after number
1.
verbatim item
EOMARKDOWN
# check out Pod::IkiWiki (or something like that)...
# the code looks very similar to some of the code in this module
# but it appears to have some list processing methods...
{
eq_or_diff $markdown, $expect, "this file's POD as markdown";
}
__DATA__
=head1 Lists
=head2 Unordered
=over 4
=item *
This
=item * is
=item * a
basic
=item *
bulleted
item
=item *
list
=item * test
=item * and I, B, C, and L should work in list item
and I B C L-
=item * verbatim paragraphs
need double-indent inside lists
=back
=head2 Unordered nested list
B
Markdown does not support definition lists (word => text), just bullets or numbers
=over 4
=item Head1
Paragraph should be indented.
* And escaped.
=over 4
=item Head2
Paragraph should be indented.
=back
=item Head1
Paragraph should be indented.
=back
=head2 Unordered nested huddled list
=over 4
=item *
This is a list head.
=item *
This is a list head, too.
=over 4
=item *
Again, this is a list head.
=back
=item *
Finally, this is also a list head.
=back
And
=over
=item *
A list item
\with a line that starts with a markdown char.
=item *
item 2
=back
=head2 Ordered
=over
=item 1.
B
=item 2.
D
=back
=head2 Ordered without dot
=over
=item 1
B
=item 2
D
=back
=head2 No text after number
=over
=item 1
verbatim item
=back
=cut
basic.t 100644 001750 001751 1434 14517525267 17104 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests tests => 1;
# Test a small, easy section of pod just to show when the parser
# is working. We'll test more of the details in other scripts.
my $parser = Pod::Markdown->new(
);
$parser->output_string(\my $markdown);
$parser->parse_file(\*DATA);
my $expect = <
B
I
=cut
links.t 100644 001750 001751 31001 14517525267 17154 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests;
# Test url aliases.
local $Pod::Markdown::URL_PREFIXES{manny} = 'http://manny.local/page/';
my %defaults = (
# We'll test the various formats later
# so for the first set just pass them through.
perldoc_fragment_format => sub { $_ },
markdown_fragment_format => sub { $_ },
);
my ($pod_prefix, $man_prefix) =
map { ($_->perldoc_url_prefix, $_->man_url_prefix) }
Pod::Markdown->new;
my $alt_text_for_urls = 1; # Assume we have a sufficient Pod::Simple version.
my ($space, $quot) =
map { sprintf '%x;', ord }
q[ ], q["];
my @tests = (
# in order of L<> examples in perlpod:
['name', q, qq^[name](${pod_prefix}name)^],
['other module', q, qq^[Other::Pod](${pod_prefix}Other%3A%3APod)^],
['other module, empty text', q<|Other::Pod>, qq^[Other::Pod](${pod_prefix}Other%3A%3APod)^],
['other module/sec, empty text', q<|Other::Pod/sec>, qq^["sec" in Other::Pod](${pod_prefix}Other%3A%3APod#sec)^],
['section in other module', q, qq^["sec" in Other::Pod](${pod_prefix}Other%3A%3APod#sec)^],
['quoted section in other doc', q, qq^["For Loops" in perlsyn](${pod_prefix}perlsyn#For${space}Loops)^],
['section in this doc', q, qq^["sec"](#sec)^],
['quoted section in this doc', q"sec">, qq^["sec"](#sec)^],
['/sec, empty text', q<|/sec>, qq^["sec"](#sec)^],
['other module, alternate text', q, qq^[other-pod](${pod_prefix}Other%3A%3APod)^],
['sec in other mod, alt text', q, qq^[x-sec](${pod_prefix}Other%3A%3APod#sec)^],
['"sec" in other mod, alt text', q, qq^[x-sec](${pod_prefix}Other%3A%3APod#sec)^],
['/"sec" in this doc, alt text', q, qq^[other-sec](#sec)^],
['/sec in this doc, alt text', q, qq^[other-sec](#sec)^],
['"sec" in this doc, alt text', q, qq^[other-sec](#sec)^],
['external ftp', q, qq^[ftp://server](ftp://server)^],
['external http', q, qq^[http://website](http://website)^],
['http, alt text (perl 5.12)', q, qq^[web](http://website)^],
['embedded codes', q^the docs on C<$.>|perlvar/"$."^, qq^[the docs on `\$.`](${pod_prefix}perlvar#\$.)^],
["don't expand nested L's", q^perlpodspec/"About LE...E Codes"^, qq^["About L<...> Codes" in perlpodspec](${pod_prefix}perlpodspec#About${space}L<...>${space}Codes)^],
# perlpodspec examples:
['name', q, qq^[Foo::Bar](${pod_prefix}Foo%3A%3ABar)^],
['alt|pod/sec', q, qq^[Perlport's section on NL's](${pod_prefix}perlport#Newlines)^],
['pod/sec', q, qq^["Newlines" in perlport](${pod_prefix}perlport#Newlines)^],
['man/sec', q, qq^["DESCRIPTION" in crontab(5)](${man_prefix}5/crontab)^],
['/section name', q, qq^["Object Attributes"](#Object${space}Attributes)^],
['http', q , qq^[http://www.perl.org/](http://www.perl.org/)^],
['text|http', q , qq^[Perl.org](http://www.perl.org/)^],
# man pages
['man(1)', q, qq^[crontab(1)](${man_prefix}1/crontab)^],
['man(5)', q, qq^[crontab(5)](${man_prefix}5/crontab)^],
# how should these be handled? these are unlikely/contrived occurrences and are mostly here for test coverage
#['man()', q, qq^[crontab()](${man_prefix}1/crontab)^],
#['man(X)', q, qq^[crontab(X)](${man_prefix}X/crontab)^],
#['man(2)-page', q, qq^[crontab(2)-page](${man_prefix}2/crontab)^],
#['(X)man', q<(X)foo>, qq^[(X)foo](${man_prefix}1/(X)foo)^],
#['()', q<()>, qq^[()](${man_prefix}1/())^],
# varies according to pod-to-html formatter:
['other/section name', q, qq^["Section Name" in Other](${pod_prefix}Other#Section${space}Name)^],
# Insert backslashes (to escape markdown).
['_underscore_', q<_underscore_>, qq^[\\_underscore\\_](${pod_prefix}_underscore_)^],
['*asterisk*', q<*asterisk*>, qq^[\\*asterisk\\*](${pod_prefix}%2Aasterisk%2A)^],
['section with quotes', q, qq^[whiskey](#Say${space}${quot}Cheese${quot})^],
# is there something better to do?
# These seem so useless I don't think I care what they do.
#['no url: empty', q<>, qq^L<>^], # FIXME: Error
# These work on 3.28 but not on 3.16:
#['no url: pipe', q<|>, qq^L<|>^],
#['no url: slash', q>, qq^L>^],
#['no url: quotes', q<"">, qq^L<"">^],
['empty text: |url', q<|http://foo>, qq^[http://foo](http://foo)^],
['false text: 0|url', q<0|http://foo>, qq^[0](http://foo)^],
# Alternate parser options:
['man url', q, qq^[crontab(1)](file:///docs/man1/crontab)^, man_url_prefix => 'file:///docs/man'],
['man alias: manny', q, qq^[crontab(1)](http://manny.local/page/1/crontab)^, man_url_prefix => 'manny'],
['man alias: man', q, qq^[crontab(1)](http://man.he.net/man1/crontab)^, man_url_prefix => 'man'],
['pod url', q, qq^[Foo::Bar](http://localhost/pod/Foo%3A%3ABar)^, perldoc_url_prefix => 'http://localhost/pod/'],
['pod alias: sco', q, qq^[Foo::Bar](http://search.cpan.org/perldoc?Foo%3A%3ABar)^, perldoc_url_prefix => 'sco'],
['pod alias: metacpan', q, qq^[Foo::Bar](https://metacpan.org/pod/Foo%3A%3ABar)^, perldoc_url_prefix => 'metacpan'],
['pod alias: perldoc', q, qq^[Foo::Bar](https://metacpan.org/pod/Foo%3A%3ABar)^, perldoc_url_prefix => 'perldoc'],
);
# Local Module URLs
{
my $p = {};
#'<,'>perldo if (s/^\[|\],$//g){ $a = [map { s/^\s+|\s+$//gr } split /,/, $_, 4]; @$a > 2 and $_ = " test_link({$a->[3]}, $a->[1], $a->[2], $a->[0]);" }
test_link($p, q, qq^[Local::Foo](${pod_prefix}Local%3A%3AFoo)^,
'Local::* defaults to perldoc');
test_link($p, q, qq^[Foo\\_Corp::Bar](${pod_prefix}Foo_Corp%3A%3ABar)^,
'Foo_Corp::* defaults to perldoc');
$p->{perldoc_url_prefix} = 'perldoc://';
test_link($p, q, qq^[Local::Foo](perldoc://Local%3A%3AFoo)^,
'local module without custom url respects perldoc_url_prefix');
$p->{local_module_url_prefix} = 'local://';
test_link($p, q, qq^[Local::Foo](local://Local%3A%3AFoo)^,
'Local::* custom url');
test_link($p, q, qq^[Foo\\_Corp::Bar](local://Foo_Corp%3A%3ABar)^,
'Foo_Corp::* custom url');
test_link($p, q, qq^[Normal::Foo](perldoc://Normal%3A%3AFoo)^,
'non local module');
$p->{local_module_re} = qr/Normal/;
test_link($p, q, qq^[Normal::Foo](local://Normal%3A%3AFoo)^,
'Normal::* with custom RE');
test_link($p, q, qq^[NonLocal::Foo](perldoc://NonLocal%3A%3AFoo)^,
'NonLocal* with custom RE');
test_link($p, q, qq^[Local::Foo](perldoc://Local%3A%3AFoo)^,
'even Local::* uses perldoc when custom re does not match');
$p = {local_module_url_prefix => ''};
test_link($p, q, qq^[Local::Foo::Bar](Local%3A%3AFoo%3A%3ABar)^,
'local module with empty prefix');
$p = {local_module_url_prefix => 'http://foo/', escape_url => 0};
test_link($p, q, qq^[Local::Foo::Bar](http://foo/Local::Foo::Bar)^,
'local module with empty prefix');
}
# Most of these examples were internal links
# so we add the perldoc name to make testing easier.
test_fragments(
q^perlvar/$.^,
{
# It's unfortunate that Pod::Simple::XHTML can't do links to just symbols:
# https://rt.cpan.org/Ticket/Display.html?id=90207
metacpan => q^["$." in perlvar](:perlvar#pod)^,
sco => q^["$." in perlvar](:perlvar#$.)^,
},
'section with only symbols',
);
test_fragments(
q^perlop/"IEO Operators"^,
{
metacpan => q^["I/O Operators" in perlop](:perlop#I-O-Operators)^,
sco => q^["I/O Operators" in perlop](:perlop#I/O_Operators)^,
},
'perlvar.pod: external section with symbols',
);
test_fragments(
q^perlpodspec/"About LE...E Codes"^,
{
metacpan => q^["About L<...> Codes" in perlpodspec](:perlpodspec#About-L...-Codes)^,
sco => q^["About L<...> Codes" in perlpodspec](:perlpodspec#About_L<...>_Codes)^,
markdown => q^["About L<...> Codes" in perlpodspec](:perlpodspec#about-l-codes)^,
},
'section with pod escapes',
);
test_fragments(
q^perlpodspec/About Data Paragraphs and "=beginE=end" Regions^,
{
metacpan => q^["About Data Paragraphs and "=begin/=end" Regions" in perlpodspec](:perlpodspec#About-Data-Paragraphs-and-begin-end-Regions)^,
sco => qq^["About Data Paragraphs and "=begin/=end" Regions" in perlpodspec](:perlpodspec#About_Data_Paragraphs_and_${quot}=begin/=end${quot}_Regions)^,
},
'section with pod commands',
);
test_fragments(
q^detach|Catalyst/"$c->detach( $action [, \@arguments ] )"^,
{
metacpan => q^[detach](:Catalyst#c-detach-action-arguments)^,
sco => q^[detach](:Catalyst#$c->detach\(_$action_[,_\\\\@arguments_]_\))^,
},
'section with sigils and syntax',
);
test_fragments(
q^perlpod/"Formatting Codes"^,
{
metacpan => q^["Formatting Codes" in perlpod](:perlpod#Formatting-Codes)^,
sco => q^["Formatting Codes" in perlpod](:perlpod#Formatting_Codes)^,
},
'quoted section in other doc',
);
test_fragments(
q,
{
markdown => q^["Some, OTHER Section!"](#some-other-section)^,
},
'complicated section',
);
test_fragments(
q"If you have a setup working, share your 'definition' with me. That would be fun!">,
{
markdown => qq^["If you have a setup working, share your 'definition' with me. That would be fun!"](#if-you-have-a-setup-working-share-your-definition-with-me-that-would-be-fun)^,
},
'extra long real life example complicated section',
);
test_fragments(
q,
{
metacpan => q^[A \\[charclass\\] is \\\\\\* bad](:page#section-with-Parens-and-Escapes-star)^,
sco => qq^[A \\[charclass\\] is \\\\\\* bad](:page#section_with_\\(Parens\\)_and_\\\\Escapes_*star*)^,
},
'extra long real life example complicated section',
);
with_and_without_entities {
my $ents = shift;
my $exp = $ents ? '101' : 'x65';
test_fragments(
q,
{
metacpan => qq^["s${exp};ction" in pag${exp};](:page#section)^,
sco => qq^["s${exp};ction" in pag${exp};](:page#section)^,
},
"respect html_encode_chars in code link text but not in fragment (HTML::Entites $ents)",
html_encode_chars => 'e',
);
};
foreach my $test ( @tests ){
my ($desc, $pod, $mkdn, %opts) = @$test;
%opts = %defaults unless %opts;
test_link(
\%opts,
$pod, $mkdn, $desc,
);
}
sub test_link {
my ($opts, $pod, $mkdn, $desc) = @_;
my $parser = Pod::Markdown->new(%$opts);
SKIP: {
skip 'alt text with schemes/absolute URLs not supported until perl 5.12 / Pod::ParseLink 1.10', 1
if !$alt_text_for_urls && $pod =~ m/\|\w+:[^:\s]\S*\z/; # /alt text \| url (not perl module)/ (regexp from perlpodspec)
$parser->output_string(\(my $got));
$parser->parse_string_document("=pod\n\nL<<< $pod >>>");
chomp($got);
is $got, $mkdn, $desc . ' (interpolate)';
}
}
sub test_fragments {
my ($pod, $tests, $desc, %opts) = @_;
foreach my $format ( sort keys %$tests ){
test_link(
# Only some combinations of these will normally make sense
# but it makes the function reusable.
{
perldoc_fragment_format => $format,
perldoc_url_prefix => ':', # easier
markdown_fragment_format => $format,
%opts,
},
$pod,
$tests->{$format},
"$desc: $format",
);
}
}
done_testing;
META.json 100644 001750 001751 77675 14517525267 17060 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400 {
"abstract" : "Convert POD to Markdown",
"author" : [
"Marcel Gruenauer ",
"Victor Moral ",
"Ryan C. Thompson ",
"Aristotle Pagaltzis ",
"Randy Stauner "
],
"dynamic_config" : 0,
"generated_by" : "Dist::Zilla version 6.024, CPAN::Meta::Converter version 2.150010",
"license" : [
"perl_5"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
"version" : 2
},
"name" : "Pod-Markdown",
"no_index" : {
"directory" : [
"corpus",
"examples",
"fatlib",
"inc",
"local",
"perl5",
"share",
"t",
"xt"
],
"namespace" : [
"Local",
"t::lib"
],
"package" : [
"DB"
]
},
"prereqs" : {
"configure" : {
"requires" : {
"ExtUtils::MakeMaker" : "0",
"perl" : "5.008"
}
},
"develop" : {
"recommends" : {
"IO::Scalar" : "0"
},
"requires" : {
"Pod::Coverage::TrustPod" : "0",
"Pod::Wordlist" : "0",
"Test::CPAN::Changes" : "0.19",
"Test::CPAN::Meta" : "0",
"Test::CPAN::Meta::JSON" : "0.16",
"Test::EOL" : "0",
"Test::Kwalitee" : "1.21",
"Test::MinimumVersion" : "0",
"Test::Mojibake" : "0",
"Test::More" : "0.96",
"Test::NoTabs" : "0",
"Test::Perl::Critic" : "0",
"Test::Pod" : "1.41",
"Test::Pod::Coverage" : "1.08",
"Test::Portability::Files" : "0",
"Test::Spelling" : "0.12",
"Test::Synopsis" : "0",
"Test::Version" : "1"
}
},
"runtime" : {
"recommends" : {
"HTML::Entities" : "0"
},
"requires" : {
"Encode" : "0",
"Getopt::Long" : "0",
"Pod::Simple" : "3.27",
"Pod::Simple::Methody" : "0",
"Pod::Usage" : "0",
"URI::Escape" : "0",
"parent" : "0",
"perl" : "5.008",
"strict" : "0",
"warnings" : "0"
}
},
"test" : {
"recommends" : {
"CPAN::Meta" : "2.120900"
},
"requires" : {
"Exporter" : "0",
"ExtUtils::MakeMaker" : "0",
"File::Spec" : "0",
"File::Spec::Functions" : "0",
"File::Temp" : "0",
"IO::Handle" : "0",
"IPC::Open3" : "0",
"Symbol" : "0",
"Test::Differences" : "0",
"Test::More" : "0.88",
"lib" : "0",
"perl" : "5.008",
"utf8" : "0"
}
}
},
"provides" : {
"Pod::Markdown" : {
"file" : "lib/Pod/Markdown.pm",
"version" : "3.400"
},
"Pod::Perldoc::ToMarkdown" : {
"file" : "lib/Pod/Perldoc/ToMarkdown.pm",
"version" : "3.400"
}
},
"release_status" : "stable",
"resources" : {
"bugtracker" : {
"mailto" : "bug-Pod-Markdown@rt.cpan.org",
"web" : "https://rt.cpan.org/Public/Dist/Display.html?Name=Pod-Markdown"
},
"homepage" : "https://github.com/rwstauner/Pod-Markdown",
"repository" : {
"type" : "git",
"url" : "https://github.com/rwstauner/Pod-Markdown.git",
"web" : "https://github.com/rwstauner/Pod-Markdown"
}
},
"version" : "3.400",
"x_Dist_Zilla" : {
"perl" : {
"version" : "5.034000"
},
"plugins" : [
{
"class" : "Dist::Zilla::Plugin::Git::NextVersion",
"config" : {
"Dist::Zilla::Plugin::Git::NextVersion" : {
"first_version" : "0.001",
"version_by_branch" : 0,
"version_regexp" : "(?^:^v(.+)$)"
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.42.0",
"repo_root" : "."
}
},
"name" : "@Author::RWSTAUNER/Git::NextVersion",
"version" : "2.048"
},
{
"class" : "Dist::Zilla::Plugin::GenerateFile",
"name" : "@Author::RWSTAUNER/GenerateManifestSkip",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::GatherDir",
"config" : {
"Dist::Zilla::Plugin::GatherDir" : {
"exclude_filename" : [
"LICENSE"
],
"exclude_match" : [],
"follow_symlinks" : 0,
"include_dotfiles" : 0,
"prefix" : "",
"prune_directory" : [],
"root" : "."
}
},
"name" : "@Author::RWSTAUNER/GatherDir",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::PruneCruft",
"name" : "@Author::RWSTAUNER/PruneCruft",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::ManifestSkip",
"name" : "@Author::RWSTAUNER/ManifestSkip",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::PruneFiles",
"name" : "@Author::RWSTAUNER/PruneDevelCoverDatabase",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::PruneFiles",
"name" : "@Author::RWSTAUNER/PruneCodeStatCollection",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::PruneFiles",
"name" : "@Author::RWSTAUNER/PruneTags",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::PkgVersion",
"name" : "@Author::RWSTAUNER/PkgVersion",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::Authority",
"name" : "@Author::RWSTAUNER/Authority",
"version" : "1.009"
},
{
"class" : "Dist::Zilla::Plugin::NextRelease",
"name" : "@Author::RWSTAUNER/NextRelease",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::Git::Describe",
"name" : "@Author::RWSTAUNER/Git::Describe",
"version" : "0.007"
},
{
"class" : "Dist::Zilla::Plugin::Prepender",
"name" : "@Author::RWSTAUNER/Prepender",
"version" : "2.004"
},
{
"class" : "Dist::Zilla::Plugin::PodWeaver",
"config" : {
"Dist::Zilla::Plugin::PodWeaver" : {
"config_plugins" : [
"@Author::RWSTAUNER"
],
"finder" : [
":InstallModules",
":ExecFiles"
],
"plugins" : [
{
"class" : "Pod::Weaver::Plugin::SingleEncoding",
"name" : "@Author::RWSTAUNER/SingleEncoding",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Plugin::WikiDoc",
"name" : "@Author::RWSTAUNER/WikiDoc",
"version" : "0.093004"
},
{
"class" : "Pod::Weaver::Plugin::EnsurePod5",
"name" : "@CorePrep/EnsurePod5",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Plugin::H1Nester",
"name" : "@CorePrep/H1Nester",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Name",
"name" : "@Author::RWSTAUNER/Name",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Version",
"name" : "@Author::RWSTAUNER/Version",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Region",
"name" : "@Author::RWSTAUNER/Prelude",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Region",
"name" : "@Author::RWSTAUNER/test_synopsis",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Generic",
"name" : "@Author::RWSTAUNER/Synopsis",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Generic",
"name" : "@Author::RWSTAUNER/Description",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Generic",
"name" : "@Author::RWSTAUNER/Overview",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Generic",
"name" : "@Author::RWSTAUNER/Usage",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Collect",
"name" : "@Author::RWSTAUNER/Class Methods",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Collect",
"name" : "@Author::RWSTAUNER/Attributes",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Collect",
"name" : "@Author::RWSTAUNER/Methods",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Collect",
"name" : "@Author::RWSTAUNER/Functions",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Leftovers",
"name" : "@Author::RWSTAUNER/Leftovers",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Region",
"name" : "@Author::RWSTAUNER/Postlude",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Support",
"name" : "@Author::RWSTAUNER/Support",
"version" : "1.013"
},
{
"class" : "Pod::Weaver::Section::Generic",
"name" : "@Author::RWSTAUNER/Acknowledgements",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Authors",
"name" : "@Author::RWSTAUNER/Authors",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Section::Contributors",
"name" : "@Author::RWSTAUNER/Contributors",
"version" : "0.009"
},
{
"class" : "Pod::Weaver::Section::Legal",
"name" : "@Author::RWSTAUNER/Legal",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Plugin::Transformer",
"name" : "@Author::RWSTAUNER/List",
"version" : "4.018"
},
{
"class" : "Pod::Weaver::Plugin::StopWords",
"name" : "@Author::RWSTAUNER/StopWords",
"version" : "1.010"
}
]
}
},
"name" : "@Author::RWSTAUNER/PodWeaver",
"version" : "4.009"
},
{
"class" : "Dist::Zilla::Plugin::License",
"name" : "@Author::RWSTAUNER/License",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::Readme",
"name" : "@Author::RWSTAUNER/Readme",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod",
"config" : {
"Dist::Zilla::Role::FileWatcher" : {
"version" : "0.006"
}
},
"name" : "@Author::RWSTAUNER/ReadmeAnyFromPod",
"version" : "0.163250"
},
{
"class" : "Dist::Zilla::Plugin::GitHubREADME::Badge",
"name" : "@Author::RWSTAUNER/GitHubREADME::Badge",
"version" : "0.33"
},
{
"class" : "Dist::Zilla::Plugin::CopyFilesFromRelease",
"config" : {
"Dist::Zilla::Plugin::CopyFilesFromRelease" : {
"filename" : [
"LICENSE"
],
"match" : []
}
},
"name" : "@Author::RWSTAUNER/CopyFilesFromRelease",
"version" : "0.007"
},
{
"class" : "Dist::Zilla::Plugin::AutoMetaResources",
"name" : "@Author::RWSTAUNER/AutoMetaResources",
"version" : "1.21"
},
{
"class" : "Dist::Zilla::Plugin::GithubMeta",
"name" : "@Author::RWSTAUNER/GithubMeta",
"version" : "0.58"
},
{
"class" : "Dist::Zilla::Plugin::Git::Contributors",
"config" : {
"Dist::Zilla::Plugin::Git::Contributors" : {
"git_version" : "2.42.0",
"include_authors" : 0,
"include_releaser" : 1,
"order_by" : "name",
"paths" : []
}
},
"name" : "@Author::RWSTAUNER/Git::Contributors",
"version" : "0.036"
},
{
"class" : "Dist::Zilla::Plugin::AutoPrereqs",
"name" : "@Author::RWSTAUNER/AutoPrereqs",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::MetaNoIndex",
"name" : "@Author::RWSTAUNER/MetaNoIndex",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::MetaProvides::Package",
"config" : {
"Dist::Zilla::Plugin::MetaProvides::Package" : {
"finder_objects" : [
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : "@Author::RWSTAUNER/MetaProvides::Package/AUTOVIV/:InstallModulesPM",
"version" : "6.024"
}
],
"include_underscores" : 0
},
"Dist::Zilla::Role::MetaProvider::Provider" : {
"$Dist::Zilla::Role::MetaProvider::Provider::VERSION" : "2.002004",
"inherit_missing" : 1,
"inherit_version" : 1,
"meta_noindex" : 1
},
"Dist::Zilla::Role::ModuleMetadata" : {
"Module::Metadata" : "1.000037",
"version" : "0.006"
}
},
"name" : "@Author::RWSTAUNER/MetaProvides::Package",
"version" : "2.004003"
},
{
"class" : "Dist::Zilla::Plugin::MinimumPerl",
"name" : "@Author::RWSTAUNER/MinimumPerl",
"version" : "1.006"
},
{
"class" : "Dist::Zilla::Plugin::MetaConfig",
"name" : "@Author::RWSTAUNER/MetaConfig",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::MetaYAML",
"name" : "@Author::RWSTAUNER/MetaYAML",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::MetaJSON",
"name" : "@Author::RWSTAUNER/MetaJSON",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::ExecDir",
"name" : "@Author::RWSTAUNER/ExecDir",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::ShareDir",
"name" : "@Author::RWSTAUNER/ShareDir",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::MakeMaker",
"config" : {
"Dist::Zilla::Role::TestRunner" : {
"default_jobs" : 1
}
},
"name" : "@Author::RWSTAUNER/MakeMaker",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::Test::ReportPrereqs",
"name" : "@Author::RWSTAUNER/Test::ReportPrereqs",
"version" : "0.028"
},
{
"class" : "Dist::Zilla::Plugin::Test::PodSpelling",
"config" : {
"Dist::Zilla::Plugin::Test::PodSpelling" : {
"directories" : [
"bin",
"lib"
],
"spell_cmd" : "",
"stopwords" : [],
"wordlist" : "Pod::Wordlist"
}
},
"name" : "@Author::RWSTAUNER/Test::PodSpelling",
"version" : "2.007005"
},
{
"class" : "Dist::Zilla::Plugin::Test::EOL",
"config" : {
"Dist::Zilla::Plugin::Test::EOL" : {
"filename" : "xt/author/eol.t",
"finder" : [
":ExecFiles",
":InstallModules",
":TestFiles"
],
"trailing_whitespace" : 0
}
},
"name" : "@Author::RWSTAUNER/@TestingMania/Test::EOL",
"version" : "0.19"
},
{
"class" : "Dist::Zilla::Plugin::PodCoverageTests",
"name" : "@Author::RWSTAUNER/@TestingMania/PodCoverageTests",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::Test::CPAN::Changes",
"config" : {
"Dist::Zilla::Plugin::Test::CPAN::Changes" : {
"changelog" : "Changes"
}
},
"name" : "@Author::RWSTAUNER/@TestingMania/Test::CPAN::Changes",
"version" : "0.012"
},
{
"class" : "Dist::Zilla::Plugin::Test::CPAN::Meta::JSON",
"name" : "@Author::RWSTAUNER/@TestingMania/Test::CPAN::Meta::JSON",
"version" : "0.004"
},
{
"class" : "Dist::Zilla::Plugin::Test::Portability",
"config" : {
"Dist::Zilla::Plugin::Test::Portability" : {
"options" : ""
}
},
"name" : "@Author::RWSTAUNER/@TestingMania/Test::Portability",
"version" : "2.001000"
},
{
"class" : "Dist::Zilla::Plugin::Test::Perl::Critic",
"name" : "@Author::RWSTAUNER/@TestingMania/Test::Perl::Critic",
"version" : "3.001"
},
{
"class" : "Dist::Zilla::Plugin::Test::DistManifest",
"name" : "@Author::RWSTAUNER/@TestingMania/Test::DistManifest",
"version" : "2.000005"
},
{
"class" : "Dist::Zilla::Plugin::MojibakeTests",
"name" : "@Author::RWSTAUNER/@TestingMania/MojibakeTests",
"version" : "0.8"
},
{
"class" : "Dist::Zilla::Plugin::PodSyntaxTests",
"name" : "@Author::RWSTAUNER/@TestingMania/PodSyntaxTests",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::MetaTests",
"name" : "@Author::RWSTAUNER/@TestingMania/MetaTests",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::Test::Synopsis",
"name" : "@Author::RWSTAUNER/@TestingMania/Test::Synopsis",
"version" : "2.000007"
},
{
"class" : "Dist::Zilla::Plugin::Test::MinimumVersion",
"config" : {
"Dist::Zilla::Plugin::Test::MinimumVersion" : {
"max_target_perl" : "5.008"
}
},
"name" : "@Author::RWSTAUNER/@TestingMania/Test::MinimumVersion",
"version" : "2.000010"
},
{
"class" : "Dist::Zilla::Plugin::Test::Kwalitee",
"config" : {
"Dist::Zilla::Plugin::Test::Kwalitee" : {
"filename" : "xt/release/kwalitee.t",
"skiptest" : []
}
},
"name" : "@Author::RWSTAUNER/@TestingMania/Test::Kwalitee",
"version" : "2.12"
},
{
"class" : "Dist::Zilla::Plugin::Test::Version",
"name" : "@Author::RWSTAUNER/@TestingMania/Test::Version",
"version" : "1.09"
},
{
"class" : "Dist::Zilla::Plugin::Test::NoTabs",
"config" : {
"Dist::Zilla::Plugin::Test::NoTabs" : {
"filename" : "xt/author/no-tabs.t",
"finder" : [
":InstallModules",
":ExecFiles",
":TestFiles"
]
}
},
"name" : "@Author::RWSTAUNER/@TestingMania/Test::NoTabs",
"version" : "0.15"
},
{
"class" : "Dist::Zilla::Plugin::Test::Compile",
"config" : {
"Dist::Zilla::Plugin::Test::Compile" : {
"bail_out_on_fail" : 0,
"fail_on_warning" : "author",
"fake_home" : 1,
"filename" : "t/00-compile.t",
"module_finder" : [
":InstallModules"
],
"needs_display" : 0,
"phase" : "test",
"script_finder" : [
":PerlExecFiles"
],
"skips" : [],
"switch" : []
}
},
"name" : "@Author::RWSTAUNER/@TestingMania/Test::Compile",
"version" : "2.058"
},
{
"class" : "Dist::Zilla::Plugin::Manifest",
"name" : "@Author::RWSTAUNER/Manifest",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::CheckExtraTests",
"name" : "@Author::RWSTAUNER/CheckExtraTests",
"version" : "0.029"
},
{
"class" : "Dist::Zilla::Plugin::CheckChangesHasContent",
"name" : "@Author::RWSTAUNER/CheckChangesHasContent",
"version" : "0.011"
},
{
"class" : "Dist::Zilla::Plugin::CheckMetaResources",
"name" : "@Author::RWSTAUNER/CheckMetaResources",
"version" : "0.001"
},
{
"class" : "Dist::Zilla::Plugin::CheckPrereqsIndexed",
"name" : "@Author::RWSTAUNER/CheckPrereqsIndexed",
"version" : "0.021"
},
{
"class" : "Dist::Zilla::Plugin::TestRelease",
"name" : "@Author::RWSTAUNER/TestRelease",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::Git::Check",
"config" : {
"Dist::Zilla::Plugin::Git::Check" : {
"untracked_files" : "die"
},
"Dist::Zilla::Role::Git::DirtyFiles" : {
"allow_dirty" : [
"Changes",
"LICENSE",
"README.mkdn",
"README.pod"
],
"allow_dirty_match" : [],
"changelog" : "Changes"
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.42.0",
"repo_root" : "."
}
},
"name" : "@Author::RWSTAUNER/@Git/Check",
"version" : "2.048"
},
{
"class" : "Dist::Zilla::Plugin::Git::Commit",
"config" : {
"Dist::Zilla::Plugin::Git::Commit" : {
"add_files_in" : [],
"commit_msg" : "v%v%t%n%n%c",
"signoff" : 0
},
"Dist::Zilla::Role::Git::DirtyFiles" : {
"allow_dirty" : [
"Changes",
"LICENSE",
"README.mkdn",
"README.pod"
],
"allow_dirty_match" : [],
"changelog" : "Changes"
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.42.0",
"repo_root" : "."
},
"Dist::Zilla::Role::Git::StringFormatter" : {
"time_zone" : "local"
}
},
"name" : "@Author::RWSTAUNER/@Git/Commit",
"version" : "2.048"
},
{
"class" : "Dist::Zilla::Plugin::Git::Tag",
"config" : {
"Dist::Zilla::Plugin::Git::Tag" : {
"branch" : null,
"changelog" : "Changes",
"signed" : 0,
"tag" : "v3.400",
"tag_format" : "v%V",
"tag_message" : "v%V"
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.42.0",
"repo_root" : "."
},
"Dist::Zilla::Role::Git::StringFormatter" : {
"time_zone" : "local"
}
},
"name" : "@Author::RWSTAUNER/@Git/Tag",
"version" : "2.048"
},
{
"class" : "Dist::Zilla::Plugin::Git::Push",
"config" : {
"Dist::Zilla::Plugin::Git::Push" : {
"push_to" : [
"origin"
],
"remotes_must_exist" : 1
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.42.0",
"repo_root" : "."
}
},
"name" : "@Author::RWSTAUNER/@Git/Push",
"version" : "2.048"
},
{
"class" : "Dist::Zilla::Plugin::ConfirmRelease",
"name" : "@Author::RWSTAUNER/ConfirmRelease",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::UploadToCPAN",
"name" : "@Author::RWSTAUNER/UploadToCPAN",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::InstallRelease",
"name" : "@Author::RWSTAUNER/InstallRelease",
"version" : "0.008"
},
{
"class" : "Dist::Zilla::Plugin::Encoding",
"name" : "CP1252",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::Prereqs",
"config" : {
"Dist::Zilla::Plugin::Prereqs" : {
"phase" : "runtime",
"type" : "requires"
}
},
"name" : "RuntimeRequires",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::Prereqs",
"config" : {
"Dist::Zilla::Plugin::Prereqs" : {
"phase" : "runtime",
"type" : "recommends"
}
},
"name" : "RuntimeRecommends",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::Prereqs",
"config" : {
"Dist::Zilla::Plugin::Prereqs" : {
"phase" : "develop",
"type" : "recommends"
}
},
"name" : "DevelopRecommends",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::Run::AfterRelease",
"config" : {
"Dist::Zilla::Plugin::Run::Role::Runner" : {
"fatal_errors" : 1,
"quiet" : 0,
"run" : [
"perl -i -pe '$orig = q[2009-2011 by Marcel Gruenauer.]; /\\Q$orig\\E/ and $already=1; $already or s/^(#?)(\\s*This software is copyright \\(c\\))( \\d+ by Randy Stauner\\.)/$1$2 $orig\\n$1\\n$1$2$3/' %d/lib/Pod/Markdown.pm %d/bin/pod2markdown %d/README* %d/LICENSE README*"
],
"version" : "0.048"
}
},
"name" : "Run::AfterRelease",
"version" : "0.048"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":InstallModules",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":IncModules",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":TestFiles",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":ExtraTestFiles",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":ExecFiles",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":PerlExecFiles",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":ShareFiles",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":MainModule",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":AllFiles",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":NoFiles",
"version" : "6.024"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : "@Author::RWSTAUNER/MetaProvides::Package/AUTOVIV/:InstallModulesPM",
"version" : "6.024"
}
],
"zilla" : {
"class" : "Dist::Zilla::Dist::Builder",
"config" : {
"is_trial" : 0
},
"version" : "6.024"
}
},
"x_authority" : "cpan:RWSTAUNER",
"x_contributors" : [
"Aristotle Pagaltzis ",
"Cindy Wang (CindyLinz) ",
"Graham Ollis ",
"Johannes Schauer Marin Rodrigues ",
"Mike Covington ",
"motemen ",
"moznion ",
"Peter Vereshagin ",
"Ryan C. Thompson ",
"Yasutaka ATARASHI "
],
"x_generated_by_perl" : "v5.34.0",
"x_serialization_backend" : "Cpanel::JSON::XS version 4.27",
"x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later"
}
nested.t 100644 001750 001751 2122 14517525267 17300 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests;
# TODO: Test everything beneath a numbered list and inside a blockquote.
convert_ok(
<<'POD',
=over
=item 1.
lizard
=item 2.
bird
=over
=item 1.
duck
=item 2.
penguin
=item 3.
turkey
gobble
gobble.
=item 4.
eagle
=back
=item 3.
bear
=over
=item 1.
grizzly
=item 2.
polar
=over
=item 1.
angry
=item 2.
sleepy
=back
=back
=back
POD
<<'MKDN',
1. lizard
2. bird
1. duck
2. penguin
3. turkey
gobble
gobble.
4. eagle
3. bear
1. grizzly
2. polar
1. angry
2. sleepy
MKDN
'indent content of numbered list items',
);
convert_ok(
# NOTE: Pod::Simple considers a heading inside over/back an error.
<<'POD',
=over
Quote:
=over
line 1
line 2
=over
=item *
a
=over
=item *
b
para
verbatim
=back
=back
=back
=back
POD
<<'MKDN',
> Quote:
>
> > line 1
> > line 2
> >
> > - a
> > - b
> >
> > para
> >
> > verbatim
MKDN
'test nesting inside blockquotes'
);
done_testing;
escape.t 100644 001750 001751 7115 14517525267 17265 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use utf8;
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests;
convert_ok
q{=head2 _Other_ *Characters* [Should](Be) `Escaped` in headers},
q{## \_Other\_ \*Characters\* \[Should\](Be) \`Escaped\` in headers},
'literal markdown chars escaped in headers';
convert_ok
q{Inline C<< code _need not_ be escaped >>.},
q{Inline `code _need not_ be escaped`.},
'literal markdown chars allowed verbatim in code spans';
convert_ok
q{=head3 Heading C<< code _need not_ be escaped, either >>.},
q{### Heading `code _need not_ be escaped, either`.},
'literal markdown chars allowed verbatim in code spans (in headings)';
convert_ok
q{B<< Nested C _should_ be escaped >> (but not code).},
q{**Nested `c*des` \_should\_ be escaped** (but not code).},
'literal markdown chars escaped in nested sequences';
convert_ok
q{Inline F<< filename_should_not >> be escaped},
q{Inline `filename_should_not` be escaped},
'filenames (F<>) are code spans so no escaping needed';
convert_ok
q{L<<< *chars* in_ `text|inside/"a link" >>>},
q{[\*chars\* in\_ \`text](pod://inside#a link)},
'escape markdown characters in link text';
# Use heredoc to simplify the backslashes.
convert_ok
<<'POD',
Inline L<< link *should* \_ be_escaped|/or\things(can)go\*wrong >>.
POD
<<'MKDN',
Inline [link \*should\* \\\_ be\_escaped](#or\\things\(can\)go\\*wrong).
MKDN
'link targets also escaped';
convert_ok
<<'POD',
=head1 SYNOPSIS
$ pod2markdown < POD_File > Markdown_File
POD
<<'MKDN',
# SYNOPSIS
$ pod2markdown < POD_File > Markdown_File
MKDN
'verbatim paragraph indents and requires no escaping';
convert_ok
<<'POD',
=head1 *Special* characters
html: < & &entity;
foo_bar is the result of 4 * 4
Regular characters like *asterisks* and __underscores__
should be escaped in regular text paragraphs.
Also [brackets],
lists:
+ a
+ b
- a
- b
* A line that starts with an asterisk
*should* be escaped to avoid incorrectly interpreting
the line as a list item.
# fake headings
### fake headings ###
Setext fake
===========
Another fake
------------
> Quote
> blocks
> 1. with
> 2. lists
1996. A year.
* Bird
* Magic
* List item
`code` block
Hr's:
---
* * *
Inline `code`;
Links: [Foo] [1], [Bar](/baz)
An image: 
backslash \
From http://daringfireball.net/projects/markdown/syntax:
\ backslash
` backtick
* asterisk
_ underscore
{} curly braces
[] square brackets
() parentheses
# hash mark
+ plus sign
- minus sign (hyphen)
. dot
! exclamation mark
POD
<<'MKDN',
# \*Special\* characters
html: < & <tag/> &entity;
foo_bar is the result of 4 * 4
Regular characters like \*asterisks\* and \_\_underscores\_\_
should be escaped in regular text paragraphs.
Also \[brackets\],
lists:
\+ a
\+ b
\- a
\- b
\* A line that starts with an asterisk
\*should\* be escaped to avoid incorrectly interpreting
the line as a list item.
\# fake headings
\### fake headings ###
Setext fake
===========
Another fake
\------------
\> Quote
\> blocks
\> 1. with
\> 2. lists
1996\. A year.
\* Bird
\* Magic
\* List item
`code` block
Hr's:
\---
\* \* \*
Inline \`code\`;
Links: \[Foo\] \[1\], \[Bar\](/baz)
An image: !\[image\](/foo)
backslash \\
From http://daringfireball.net/projects/markdown/syntax:
\\ backslash
\` backtick
\* asterisk
\_ underscore
{} curly braces
\[\] square brackets
() parentheses
\# hash mark
\+ plus sign
\- minus sign (hyphen)
. dot
! exclamation mark
MKDN
'literal markdown characters in pod escaped';
done_testing;
formats.t 100644 001750 001751 3360 14517525267 17476 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests;
convert_ok(
<<'POD',
Some I
=for html html
=for markdown **mkdn**
=for something_else `ignored`
POD
<<'MKDN',
Some _pod_
MKDN
'disable html and markdown targets',
init => sub { $_[0]->unaccept_targets(qw(markdown html)) },
);
convert_ok(
<<'POD',
Some I
=for other no
=for html foo
=for :html bar
=for :other nope
=for markdown baz
=for :markdown qux
POD
<<'MKDN',
Some _pod_
foo
bar
baz
qux
MKDN
'by default accept html and markdown targets',
);
convert_ok(
<<'POD',
Some I
=for markdown **BOLD**! B
POD
<<'MKDN',
Some _pod_
**BOLD**! B
MKDN
'=for markdown passed through',
);
convert_ok(
<<'POD',
Some I
=begin markdown
**BOLD**! B
=end markdown
POD
<<'MKDN',
Some _pod_
**BOLD**! B
MKDN
'=begin/end markdown passed through',
);
convert_ok(
<<'POD',
Some I
=for :markdown **BOLD**! B
=for :other `ignored`
POD
<<'MKDN',
Some _pod_
\*\*BOLD\*\*! **real bold**
MKDN
'=for :markdown gets processed and escaped',
);
convert_ok(
<<'POD',
Some I
=begin :markdown
**BOLD**! B
=end :markdown
POD
<<'MKDN',
Some _pod_
\*\*BOLD\*\*! **real bold**
MKDN
'=begin/end :markdown gets processed and escaped',
);
convert_ok(
<<'POD',
Some I
=for html not I *text*
POD
<<'MKDN',
Some _pod_
not I *text*
MKDN
'=for html passes through',
);
convert_ok(
<<'POD',
Some I
=for :html yes I *text*
POD
<<'MKDN',
Some _pod_
<i>yes</i> _pod_ \*text\*
MKDN
'=for :html gets processed and escaped',
);
done_testing;
perldoc.t 100644 001750 001751 1127 14517525267 17452 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests;
use Pod::Perldoc::ToMarkdown;
use File::Temp qw{ tempfile }; # core
use File::Spec::Functions qw( catfile ); # core
my ($tmp_out, $outfile) = tempfile( 'pod2markdown-out.XXXXXX', TMPDIR => 1, UNLINK => 1 );
print $tmp_out "overwrite me\n";
close $tmp_out;
sub corpus {
catfile( corpus => $_[0] );
}
Pod::Perldoc::ToMarkdown->parse_from_file( corpus('copy.pod'), $outfile);
like slurp_file($outfile), qr/# cr\n\n\{ \\`\xc2\xa9\\` \}/,
'ToMarkdown class for perldoc';
done_testing;
Makefile.PL 100644 001750 001751 4455 14517525267 17353 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400 #
# 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.
#
# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.024.
use strict;
use warnings;
use 5.008;
use ExtUtils::MakeMaker;
my %WriteMakefileArgs = (
"ABSTRACT" => "Convert POD to Markdown",
"AUTHOR" => "Marcel Gruenauer , Victor Moral , Ryan C. Thompson , Aristotle Pagaltzis , Randy Stauner ",
"CONFIGURE_REQUIRES" => {
"ExtUtils::MakeMaker" => 0
},
"DISTNAME" => "Pod-Markdown",
"EXE_FILES" => [
"bin/pod2markdown"
],
"LICENSE" => "perl",
"MIN_PERL_VERSION" => "5.008",
"NAME" => "Pod::Markdown",
"PREREQ_PM" => {
"Encode" => 0,
"Getopt::Long" => 0,
"Pod::Simple" => "3.27",
"Pod::Simple::Methody" => 0,
"Pod::Usage" => 0,
"URI::Escape" => 0,
"parent" => 0,
"strict" => 0,
"warnings" => 0
},
"TEST_REQUIRES" => {
"Exporter" => 0,
"ExtUtils::MakeMaker" => 0,
"File::Spec" => 0,
"File::Spec::Functions" => 0,
"File::Temp" => 0,
"IO::Handle" => 0,
"IPC::Open3" => 0,
"Symbol" => 0,
"Test::Differences" => 0,
"Test::More" => "0.88",
"lib" => 0,
"utf8" => 0
},
"VERSION" => "3.400",
"test" => {
"TESTS" => "t/*.t"
}
);
my %FallbackPrereqs = (
"Encode" => 0,
"Exporter" => 0,
"ExtUtils::MakeMaker" => 0,
"File::Spec" => 0,
"File::Spec::Functions" => 0,
"File::Temp" => 0,
"Getopt::Long" => 0,
"IO::Handle" => 0,
"IPC::Open3" => 0,
"Pod::Simple" => "3.27",
"Pod::Simple::Methody" => 0,
"Pod::Usage" => 0,
"Symbol" => 0,
"Test::Differences" => 0,
"Test::More" => "0.88",
"URI::Escape" => 0,
"lib" => 0,
"parent" => 0,
"strict" => 0,
"utf8" => 0,
"warnings" => 0
);
unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
delete $WriteMakefileArgs{TEST_REQUIRES};
delete $WriteMakefileArgs{BUILD_REQUIRES};
$WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
}
delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
unless eval { ExtUtils::MakeMaker->VERSION(6.52) };
WriteMakefile(%WriteMakefileArgs);
encoding.t 100644 001750 001751 6130 14517525267 17607 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests;
# NOTE: All strings in this test file are byte-strings.
no utf8;
sub test_encoding {
my ($enc, $pod, %opts) = @_;
my $desc = delete $opts{desc} || hex_escape $pod;
foreach my $outenc ( keys %opts ){
convert_encodings($pod, $opts{$outenc}, $enc, $outenc, $desc);
}
}
sub convert_encodings {
my ($pod, $exp, $enc, $outenc, $desc) = @_;
convert_ok($pod, $exp, $desc,
attr => $outenc =~ /match(?:_(\w+))?/ ? { match_encoding => 1, output_encoding => $1||'' } : { output_encoding => $outenc },
prefix => ".",
encoding => $enc,
init => sub {
# Ignore errors about high-bit chars without =encoding.
$_[0]->no_errata_section(1) if !$enc || $enc =~ /invalid/;
},
verbose => 1,
);
}
# Pod::Simple defaults to cp1252 (previously latin1) without an =encoding.
with_and_without_entities {
my $char = $_[0] ? 'À' : 'À';
foreach my $enc ( 'latin1', 'cp1252', '' ){
test_encoding( $enc => "\xc0",
utf8 => "\xc3\x80",
latin1 => "\xc0",
ascii => $char,
);
}
};
with_and_without_entities {
my $bullet = $_[0] ? '•' : '•';
test_encoding( cp1252 => "\x95",
utf8 => "\xe2\x80\xa2",
match => "\x95",
(map { ($_ => $bullet) } qw(latin1 ascii)),
);
};
with_and_without_entities {
my $currency = $_[0] ? '¤' : '¤';
test_encoding( latin1 => "\xa4",
match => "\xa4",
utf8 => "\xc2\xa4",
ascii => $currency,
);
test_encoding( "utf-8" => "\xc2\xa4",
match => "\xc2\xa4",
latin1 => "\xa4",
ascii => $currency,
);
};
foreach my $enc ( '', 'invalid' ){
my $utf8 = "\xc2\xa9 a\xc2\xa0b";
test_encoding( $enc => 'E S',
match_ascii => '© a b',
latin1 => "\xa9 a\xa0b",
utf8 => $utf8,
match_utf8 => $utf8,
match => $utf8,
desc => 'ascii; ' . ($enc ? '' : 'no =encoding; ') . 'pod escapes generate non-ascii',
);
}
{
# Verify that output_encoding => 'ascii' (even with match_encoding) is not safe.
# > Inside Markdown code spans and blocks, angle brackets and ampersands are always encoded automatically.
# Therefore we cannot use html entities to encode high-bit chars; they must be output literally.
# It is possible with pod to embed non-ascii characters in a code span without
# using literal high-bit characters (so there will be no detected_encoding).
my $pod = "=pod\n\nC<< a E<0x2022> bullet >>\n";
my $test = sub {
my $p = Pod::Markdown->new(@_);
$p->output_string(\my $markdown);
$p->parse_string_document($pod);
chomp $markdown;
ok !$p->detected_encoding, 'no encoding detected';
return $markdown;
};
eq_or_diff $test->(output_encoding => 'UTF-8'),
"`a \xe2\x80\xa2 bullet`",
'high-bit char UTF-8 encoded in code span';
# Without specifying encoding a character string is returned.
eq_or_diff $test->(),
"`a \x{2022} bullet`",
'high-bit char embedded in code span (character string)';
}
done_testing;
entities.t 100644 001750 001751 14061 14517525267 17667 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use utf8;
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests;
# Escape things that would be interpreted as inline html.
sub entity_encode_ok {
my ($desc, $pod, $markdown, %opts) = @_;
my $verbatim = $opts{verbatim} || $pod;
note hex_escape $pod;
convert_both($pod, $markdown, $verbatim, $desc);
# Encoding some entities (but not [&<]) should produce the same as none.
convert_both($pod, $markdown, $verbatim, "$desc (html_encode_chars => non ascii)",
attr => {html_encode_chars => '\x80-\xff'});
# Encoding [&<] will produce more of those chars.
convert_both($pod, $opts{entities}, $verbatim, "$desc (html_encode_chars => 1)",
attr => {html_encode_chars => 1}) if $opts{entities};
}
sub convert_both {
my ($pod, $markdown, $verbatim, $desc, %opts) = @_;
convert_ok("B<<< $pod >>>", $markdown, "$desc: inline html escaped", %opts);
convert_ok("C<<< $pod >>>", qq{`$verbatim`}, "$desc: html not escaped in code span", %opts);
}
my %_escape = Pod::Markdown::__escape_sequences;
my %_e_escape = do {
my $parser = Pod::Markdown->new(html_encode_chars => 1);
map { ($_ => $parser->encode_entities($_escape{$_})) } keys %_escape;
};
like $_e_escape{amp}, qr/&/, 'entity-encoded escape sanity check';
with_and_without_entities {
my $char = $_[0] ? '•' : '•';
entity_encode_ok 'sanity check' => (
q{< & > E<0x2022>},
q{**< & > •**},
entities => "**< & > ${char}**",
verbatim => q{< & > •},
);
};
# This was an actual bug report.
entity_encode_ok 'command lines args' => (
q{--file=},
q{**--file=<filename>**},
entities => q{**--file=<filename>**},
);
# Ditto
entity_encode_ok 'email address' => (
q{Email Address Efoo@bar.comE},
q{**Email Address **},
entities => q{**Email Address <foo@bar.com>**},
verbatim => q{Email Address },
);
# Use real html tags.
# This is a good example to copy/paste into a markdown processor
# to see how it handles the html.
# For example, github respects "\<" and "\&" but daringfireball does not.
# That's why we use html entity encoding (more portable).
entity_encode_ok 'real html' => (
q{h =
},
q{**h =<hr>**},
entities => q{**h =<hr>**},
);
# Test link text.
entity_encode_ok 'html chars in link text' => (
q{L<< Some & |http://some.where/ >>},
q{**[Some & <thing>](http://some.where/)**},
entities => q{**[Some & <thing>](http://some.where/)**},
# Markdown will print this rather than making it a link,
# but I'm not sure what else to do about it.
verbatim => q{[Some & ](http://some.where/)},
);
entity_encode_ok 'html chars in url' => (
# This may not be a valid url but let this test demonstrate how it currently works.
q{L<< Yo|http://some.where?a=&<= >>},
q{**[Yo](http://some.where?a=&<=)**},
# Same as above (shrug).
verbatim => q{[Yo](http://some.where?a=&<=)},
);
# Test with 'false' values to avoid conditional bugs.
# In this case a bare zero won't trigger the need for an escape.
entity_encode_ok 'false values' => (
q{<0 &0},
q{**<0 &0**},
entities => q{**<0 &0**},
);
# Ensure that two pod "strings" still escape the < and & properly.
# Use S<> since it counts as an event (and therefore creates two separate
# "handle_text" calls) but does not produce boundary characters (the text
# inside and around the S<> will have no characters between them).
entity_encode_ok '< and & are escaped properly even as separate pod strings' => (
q{the E operator and S<&>foobar; (or S<&>fooS;) and eol &},
q{**the <cmp> operator and &foobar; (or &foobar;) and eol &**},
entities => q{**the <cmp> operator and &foobar; (or &foobar;) and eol &**},
verbatim => q{the operator and &foobar; (or &foobar;) and eol &},
);
# Don't undo it for literal ones that happen to be at the end of strings.
entity_encode_ok 'literal entity from pod at end of string stays amp-escaped' => (
q{literal & and <},
q{**literal & and <**},
);
entity_encode_ok 'field splitting: amps at beginning and end and multiple in the middle' => (
q{& ity &&& and &},
q{**& ity &&& and &**},
entities => q{**& ity &&& and &**},
);
entity_encode_ok 'literal occurrences of internal escape sequences are unaltered' => (
qq[hi $_escape{amp} ($_escape{amp_code}) & $_escape{lt} ($_escape{lt_code}) < &exclam;],
qq[**hi $_escape{amp} ($_escape{amp_code}) & $_escape{lt} ($_escape{lt_code}) < &exclam;**],
entities => qq[**hi $_e_escape{amp} ($_e_escape{amp_code}) & $_e_escape{lt} ($_e_escape{lt_code}) < &exclam;**],
);
sub so_example {
# Test case from http://stackoverflow.com/questions/28496298/escape-angle-brackets-using-podmarkdown {
my $str = "=head1 OPTIONS\n\n=over 4\n\n=item B<< --file= >>\n\nFile name \n\n=back\n";
my $parser = Pod::Markdown->new(@_); # (@_) - rwstauner
my $markdown;
$parser->output_string( \$markdown );
$parser->parse_string_document($str);
# }
return $markdown;
}
eq_or_diff so_example(), "# OPTIONS\n\n- **--file=<filename>**\n\n File name \n",
'SO example properly escaped';
eq_or_diff so_example(html_encode_chars => 1), "# OPTIONS\n\n- **--file=<filename>**\n\n File name \n",
'SO example with additional escapes';
my $list_pod = < &you; < &
=over
=item & some < t&e;xt
<
&
=back
=over
=item 1.
item < &
=back
POD
convert_ok($list_pod, < &you; < &
- & some < t&e;xt
<paragraph>
<
&
1. item <text> < &
<para>
MKDN
'escape entities in lists and items properly',
);
convert_ok($list_pod, < { html_encode_chars => 1 }
);
done_testing;
verbatim.t 100644 001750 001751 3336 14517525267 17637 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests tests => 1;
my $parser = Pod::Markdown->new;
$parser->output_string(\my $markdown);
$parser->parse_file(\*DATA);
my $expect = <<'EOMARKDOWN';
# SYNOPSIS
# 4 spaces
# should come out the same
# TABS
These tabs
will be expanded.
# 3 SPACES
3 spaces should be converted to 4.
Here, too
And also
here.
# MIXED (You don't really want to do that, though, do you?)
Mixed paragraphs should all get the same indentation added
to preserve the formatting:
4 spaces (+ 2 = 6)
a tab
3 spaces (+ 2 = 5)
2 spaces (+ 2 = 4) (the minimum)
# 5 spaces
Because you can
if you want to
# 1 space
a little short, but valid
# indented blank lines
one
two
three
four
# nonindented blank lines
one
two
three
four
# THAT'S ENOUGH
EOMARKDOWN
eq_or_diff $markdown, $expect,
'preserve verbatim paragraphs of various initial whitespace combinations';
__DATA__
=head1 SYNOPSIS
# 4 spaces
# should come out the same
=head1 TABS
These tabs
will be expanded.
=head1 3 SPACES
3 spaces should be converted to 4.
Here, too
And also
here.
=head1 MIXED (You don't really want to do that, though, do you?)
Mixed paragraphs should all get the same indentation added
to preserve the formatting:
4 spaces (+ 2 = 6)
a tab
3 spaces (+ 2 = 5)
2 spaces (+ 2 = 4) (the minimum)
=head1 5 spaces
Because you can
if you want to
=head1 1 space
a little short, but valid
=head1 indented blank lines
one
two
three
four
=head1 nonindented blank lines
one
two
three
four
=head1 THAT'S ENOUGH
=cut
MANIFEST.SKIP 100644 001750 001751 145 14517525267 17247 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400
\B\.git\b
\B\.gitignore$
^[\._]build
^blib/
^(Build|Makefile)$
\bpm_to_blib$
^MYMETA\.
^cover_db/
00-compile.t 100644 001750 001751 5467 14517525267 17702 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t use 5.006;
use strict;
use warnings;
# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.058
use Test::More;
plan tests => 3 + ($ENV{AUTHOR_TESTING} ? 1 : 0);
my @module_files = (
'Pod/Markdown.pm',
'Pod/Perldoc/ToMarkdown.pm'
);
my @scripts = (
'bin/pod2markdown'
);
# fake home for cpan-testers
use File::Temp;
local $ENV{HOME} = File::Temp::tempdir( CLEANUP => 1 );
my @switches = (
-d 'blib' ? '-Mblib' : '-Ilib',
);
use File::Spec;
use IPC::Open3;
use IO::Handle;
open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!";
my @warnings;
for my $lib (@module_files)
{
# see L
my $stderr = IO::Handle->new;
diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} }
$^X, @switches, '-e', "require q[$lib]"))
if $ENV{PERL_COMPILE_TEST_DEBUG};
my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-e', "require q[$lib]");
binmode $stderr, ':crlf' if $^O eq 'MSWin32';
my @_warnings = <$stderr>;
waitpid($pid, 0);
is($?, 0, "$lib loaded ok");
shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/
and not eval { +require blib; blib->VERSION('1.01') };
if (@_warnings)
{
warn @_warnings;
push @warnings, @_warnings;
}
}
foreach my $file (@scripts)
{ SKIP: {
open my $fh, '<', $file or warn("Unable to open $file: $!"), next;
my $line = <$fh>;
close $fh and skip("$file isn't perl", 1) unless $line =~ /^#!\s*(?:\S*perl\S*)((?:\s+-\w*)*)(?:\s*#.*)?$/;
@switches = (@switches, split(' ', $1)) if $1;
close $fh and skip("$file uses -T; not testable with PERL5LIB", 1)
if grep { $_ eq '-T' } @switches and $ENV{PERL5LIB};
my $stderr = IO::Handle->new;
diag('Running: ', join(', ', map { my $str = $_; $str =~ s/'/\\'/g; q{'} . $str . q{'} }
$^X, @switches, '-c', $file))
if $ENV{PERL_COMPILE_TEST_DEBUG};
my $pid = open3($stdin, '>&STDERR', $stderr, $^X, @switches, '-c', $file);
binmode $stderr, ':crlf' if $^O eq 'MSWin32';
my @_warnings = <$stderr>;
waitpid($pid, 0);
is($?, 0, "$file compiled ok");
shift @_warnings if @_warnings and $_warnings[0] =~ /^Using .*\bblib/
and not eval { +require blib; blib->VERSION('1.01') };
# in older perls, -c output is simply the file portion of the path being tested
if (@_warnings = grep { !/\bsyntax OK$/ }
grep { chomp; $_ ne (File::Spec->splitpath($file))[2] } @_warnings)
{
warn @_warnings;
push @warnings, @_warnings;
}
} }
is(scalar(@warnings), 0, 'no warnings found')
or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ) if $ENV{AUTHOR_TESTING};
back-compat.t 100644 001750 001751 3221 14517525267 20200 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests;
use File::Spec ();
# Explicitly test using a real file.
my $_pod_path = File::Spec->catfile(qw(corpus tinypod.txt));
my $_pod_text = "This is _pod_.";
sub compare {
my ($got, $exp, $desc) = @_;
chomp $got;
eq_or_diff $got, $exp, $desc;
}
# NOTE: With Pod::Parser apparently as_markdown would return
# strings with html-encoded entities and no utf8 flag.
# We could add that functionality into the parse_file/as_markdown subs
# if needed, but it's been based on Pod::Simple for over a year so far
# with no reports so it likely isn't (needed).
# Dist::Zilla::Plugin::ReadmeAnyFromPod
SKIP: {
eval 'require IO::Scalar'
or skip 'IO::Scalar not available for testing.', 1;
my $pod = "=pod\n\nB\n";
my $parser = Pod::Markdown->new();
my $input_handle = IO::Scalar->new(\$pod);
$parser->parse_from_filehandle($input_handle);
my $content = $parser->as_markdown();
compare $content, '**foo**',
'parse_from_filehandle( IO::Scalar->new(\$string) )';
}
# Minilla
# Module::Build::Pluggable::ReadmeMarkdownFromPod
# Module::Install::ReadmeMarkdownFromPod
{
my $readme_from = $_pod_path;
my $parser = Pod::Markdown->new;
$parser->parse_from_file($readme_from);
my $markdown = $parser->as_markdown;
compare $markdown, $_pod_text,
'parse_from_file( $path )';
}
{
my $pod = $_pod_path;
open my $pod_fh, '<', $pod or die "Can't read POD '$pod'";
my $md = Pod::Markdown->new;
$md->parse_from_filehandle($pod_fh);
compare $md->as_markdown, $_pod_text,
'parse_from_filehandle( open(my) )';
}
done_testing;
corpus 000755 001750 001751 0 14517525267 16544 5 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400 copy.pod 100644 001750 001751 33 14517525267 20316 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/corpus
=head1 cr
{ `E` }
author 000755 001750 001751 0 14517525267 17166 5 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/xt eol.t 100644 001750 001751 1320 14517525267 20266 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/xt/author use strict;
use warnings;
# this test was generated with Dist::Zilla::Plugin::Test::EOL 0.19
use Test::More 0.88;
use Test::EOL;
my @files = (
'bin/pod2markdown',
'lib/Pod/Markdown.pm',
'lib/Pod/Perldoc/ToMarkdown.pm',
't/00-compile.t',
't/00-report-prereqs.dd',
't/00-report-prereqs.t',
't/back-compat.t',
't/basic.t',
't/codes.t',
't/encoding.t',
't/entities.t',
't/escape.t',
't/formats.t',
't/lib/MarkdownTests.pm',
't/links.t',
't/lists.t',
't/meta.t',
't/misc.t',
't/nested.t',
't/new.t',
't/perldoc.t',
't/pod2markdown.t',
't/verbatim.t'
);
eol_unix_ok($_, { trailing_whitespace => 0 }) foreach @files;
done_testing;
bin 000755 001750 001751 0 14517525267 16001 5 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400 pod2markdown 100755 001750 001751 11064 14517525267 20520 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/bin #!/usr/local/bin/perl
#
# 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;
# PODNAME: pod2markdown
# ABSTRACT: Convert POD text to Markdown
use Pod::Markdown;
use Getopt::Long;
use Pod::Usage;
my %opts = (
# Since we're writing to a file the module needs to know that it has to do
# some kind of encoding. Default to UTF-8.
output_encoding => 'UTF-8',
);
GetOptions(\%opts, qw(
help|h
html_encode_chars|html-encode-chars=s
local_module_url_prefix|local-module-url-prefix=s
match_encoding|match-encoding|m
man_url_prefix|man-url-prefix=s
perldoc_url_prefix|perldoc-url-prefix=s
output_encoding|output-encoding|e=s
utf8|utf-8|u
)) or pod2usage(2);
pod2usage(1) if $opts{help};
# TODO: Test PERL_UNICODE and/or layers on the handle?
# Expand alias (-u is an alias for -e UTF-8).
$opts{output_encoding} = 'UTF-8' if delete $opts{utf8};
# TODO: Pod::Simple::parse_from_file(@ARGV[0,1]);
my $in_fh = get_handle(shift(@ARGV), '<', \*STDIN);
my $out_fh = get_handle(shift(@ARGV), '>', \*STDOUT);
# Undo any PERL_UNICODE effects.
# Pod::Simple expects to receive bytes, and we're going to return bytes.
binmode($_, ':bytes') for ($in_fh, $out_fh);
convert($in_fh, $out_fh);
sub convert {
my ($in_file, $out_file) = @_;
my $parser = Pod::Markdown->new(%opts);
$parser->output_fh($out_file);
$parser->parse_file($in_file);
}
sub get_handle {
my ($path, $op, $default) = @_;
(!defined($path) || $path eq '-') ? $default : do {
open(my $fh, $op, $path)
or die "Failed to open '$path': $!\n";
$fh;
};
}
__END__
=pod
=encoding UTF-8
=for :stopwords Marcel Gruenauer Victor Moral Ryan C. Thompson Aristotle Pagaltzis Randy Stauner ACKNOWLEDGEMENTS html
=head1 NAME
pod2markdown - Convert POD text to Markdown
=head1 VERSION
version 3.400
=head1 SYNOPSIS
# parse STDIN, print to STDOUT
$ pod2markdown < POD_File > Markdown_File
# parse file, print to STDOUT
$ pod2markdown input.pod
# parse file, print to file
$ pod2markdown input.pod output.mkdn
# parse STDIN, print to file
$ pod2markdown - output.mkdn
=head1 DESCRIPTION
This program uses L to convert POD into Markdown sources.
UTF-8 is the default output encoding
if no encoding options are specified (see L).
It accepts two optional arguments:
=over 4
=item *
input pod file (defaults to C)
=item *
output markdown file (defaults to C)
=back
=head1 OPTIONS
=over
=item --html-encode-chars
A list of characters to encode as HTML entities.
Pass a regexp character class, or C<1> to mean control chars, high-bit chars, and C<< <&>"' >>.
See L for more information.
=item --match-encoding (-m)
Use the same C<< =encoding >> as the input pod for the output file.
=item --local-module-url-prefix
Alters the perldoc urls that are created from C<< LEE >> codes
when the module is a "local" module (C<"Local::*"> or C<"Foo_Corp::*"> (see L)).
The default is to use C.
See L for more information.
=item --man-url-prefix
Alters the man page urls that are created from C<< LEE >> codes.
The default is C.
See L for more information.
=item --perldoc-url-prefix
Alters the perldoc urls that are created from C<< LEE >> codes.
Can be:
=over 4
=item *
C (shortcut for C )
=item *
C (shortcut for C)
=item *
any url
=back
The default is C.
See L for more information.
=item --output-encoding (-e)
Specify the encoding for the output file.
=item --utf8 (-u)
Alias for C<< -e UTF-8 >>.
=back
=head1 SEE ALSO
This program is strongly based on C from L.
=head1 AUTHORS
=over 4
=item *
Marcel Gruenauer
=item *
Victor Moral
=item *
Ryan C. Thompson
=item *
Aristotle Pagaltzis
=item *
Randy Stauner
=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
pod2markdown.t 100644 001750 001751 5074 14517525267 20436 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/t # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
use strict;
use warnings;
use lib 't/lib';
use MarkdownTests;
use File::Temp qw{ tempfile }; # core
use File::Spec::Functions qw( catfile ); # core
my ($lib, $bin) = scalar(grep { /\bblib\Wlib$/ } @INC)
? ('blib/lib', 'blib/script')
: ('lib', 'bin');
my $script = catfile($bin, qw(pod2markdown));
my ($tmp_in, $infile) = tempfile( 'pod2markdown-in.XXXXXX', TMPDIR => 1, UNLINK => 1 );
print $tmp_in "=head1 Temp\n\nI\n";
close $tmp_in;
my ($tmp_out, $outfile) = tempfile( 'pod2markdown-out.XXXXXX', TMPDIR => 1, UNLINK => 1 );
print $tmp_out "overwrite me\n";
close $tmp_out;
sub corpus {
catfile( corpus => $_[0] );
}
# I tried this with IPC::Open2, but windows hangs waiting for more ...
sub pod2markdown {
my ($args, $exp, $desc) = @_;
local $Test::Builder::Level = $Test::Builder::Level + 1;
unshift @$args, $^X, "-I$lib", $script;
{
open(my $fh, '>', $outfile) or die "Failed to open $outfile: $!";
print $fh "oops\n";
close $fh;
}
is slurp_file($outfile), "oops\n", 'output file prepared';
system(join ' ', map { length($_) > 1 ? qq["$_"] : $_ } @$args);
is slurp_file($outfile), $exp, $desc;
}
{
sub testp2m {
splice @_, 1, 0, "# Temp\n\n_File_\n";
goto &pod2markdown;
}
testp2m(
['<', $infile, '>', $outfile],
'no args: < in > out',
);
testp2m(
[$infile, '>', $outfile],
'1 arg: input file, stdout',
);
testp2m(
[$infile, $outfile],
'2 args: input file, output file',
);
testp2m(
['-', $outfile, '<', $infile],
'2 args: - (stdin), output file',
);
testp2m(
['-', '-', '<', $infile, '>', $outfile],
'both dashes: - (stdin) - (stdout)',
);
}
{
my $in = corpus('copy.pod');
my @args = ($in, $outfile);
my $exp = sub { sprintf "# cr\n\n{ \\`%s\\` }\n", $_[0] };
pod2markdown(
[@args],
$exp->("\xc2\xa9"),
'no encoding specified returns UTF-8',
);
pod2markdown(
['--html-encode-chars=1', @args],
$exp->("©"),
'html_encode_chars=1 encodes entities',
);
pod2markdown(
['-e', 'ascii', @args],
$exp->("©"),
'ascii encoding returns ascii with html entities encoded',
);
pod2markdown(
['--output-encoding=utf-8', @args],
$exp->("\xc2\xa9"),
'specify utf-8 output encoding',
);
pod2markdown(
['--match-encoding', corpus('lit-cp1252-enc.pod'), $outfile],
$exp->("\xa9"),
'match input cp1252',
);
pod2markdown(
['-m', corpus('lit-utf8-enc.pod'), $outfile],
$exp->("\xc2\xa9"),
'match input utf-8',
);
}
done_testing;
tinypod.txt 100644 001750 001751 34 14517525267 21070 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/corpus =pod
This is I.
=cut
critic.t 100644 001750 001751 201 14517525267 20741 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/xt/author #!perl
use strict;
use warnings;
use Test::Perl::Critic (-profile => "perlcritic.rc") x!! -e "perlcritic.rc";
all_critic_ok();
Pod 000755 001750 001751 0 14517525267 16521 5 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/lib Markdown.pm 100644 001750 001751 131256 14517525267 21051 0 ustar 00rwstauner rwstauner 000000 000000 Pod-Markdown-3.400/lib/Pod # 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.300-3-gb01c18d
our $AUTHORITY = 'cpan:RWSTAUNER';
# ABSTRACT: Convert POD to Markdown
$Pod::Markdown::VERSION = '3.400';
use Pod::Simple 3.27 (); # detected_encoding and keep_encoding bug fix
use parent qw(Pod::Simple::Methody);
use Encode ();
use URI::Escape ();
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 $LOCAL_MODULE_RE = qr/^(Local::|\w*?_\w*)/;
## no critic
#{
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,(? '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 critic
# 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
local_module_re
local_module_url_prefix
man_url_prefix
perldoc_url_prefix
perldoc_fragment_format
markdown_fragment_format
include_meta_tags
escape_url
);
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 ));
$self->escape_url(1);
# Default to the global, but allow it to be overwritten in args.
$self->local_module_re($LOCAL_MODULE_RE);
for my $type ( qw( perldoc man ) ){
my $attr = $type . '_url_prefix';
# Initialize to the alias.
$self->$attr($type);
}
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: call from the setters.
$self->_prepare_fragment_formats;
if(defined $self->local_module_url_prefix && $self->local_module_url_prefix eq '' && !$self->escape_url) {
warn("turning escape_url with an empty local_module_url_prefix is not recommended as relative URLs could be confused for IPv6 addresses");
}
return $self;
}
for my $type ( qw( local_module perldoc man ) ){
my $attr = $type . '_url_prefix';
no strict 'refs'; ## no critic
*$attr = sub {
my $self = shift;
if (@_) {
$self->{$attr} = $URL_PREFIXES{ $_[0] } || $_[0];
}
else {
return $self->{$attr};
}
}
}
## 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;', 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 () for Markdown to process.
s,$_escape{lt_re}((?=$EMAIL_MARKER)|(?:[a-z/?\$!])?),
$1 ? '<'.$2 : $2 ? '<'.$2 : '<',egos;
}
return $_;
}
## Parsing ##
sub handle_text {
my $self = $_[0];
my $stash = $self->_private;
local $_ = $_[1];
# Unless we're in a code span, verbatim block, or formatted region.
unless( $stash->{no_escape} ){
# We could, in theory, alter what gets escaped according to context
# (for example, escape square brackets (but not parens) inside link text).
# The markdown produced might look slightly nicer but either way you're
# at the whim of the markdown processor to interpret things correctly.
# For now just escape everything.
# Don't let literal characters be interpreted as markdown.
$_ = $self->_escape_inline_markdown($_);
# Entity-encode (or escape for later processing) necessary/desired chars.
$_ = $self->_encode_or_escape_entities($_);
}
# If this _is_ a code section, do limited/specific handling.
else {
# Always escaping these chars ensures that we won't mangle the text
# in the unlikely event that a sequence matching our escape occurred in the
# input stream (since we're going to escape it and then unescape it).
s/&/$_escape{amp_code}/gos if $stash->{encode_amp};
s/$_escape{lt_code}/gos if $stash->{encode_lt};
}
$self->_save($_);
}
sub start_Document {
my ($self) = @_;
$self->_new_stack;
}
sub end_Document {
my ($self) = @_;
$self->_check_search_header;
my $end = pop @{ $self->_private->{stacks} };
@{ $self->_private->{stacks} } == 0
or die 'Document ended with stacks remaining';
my @doc = $self->_chomp_all(join('', @$end)) . $/;
if( $self->include_meta_tags ){
unshift @doc, $self->_build_markdown_head, ($/ x 2);
}
if( my $encoding = $self->_get_output_encoding ){
# Do the check outside the loop(s) for efficiency.
my $ents = $HAS_HTML_ENTITIES ? \&__entity_encode_ord_he : \&__entity_encode_ord_basic;
# Iterate indices to avoid copying large strings.
for my $i ( 0 .. $#doc ){
print { $self->{output_fh} } Encode::encode($encoding, $doc[$i], $ents);
}
}
else {
print { $self->{output_fh} } @doc;
}
}
sub _get_output_encoding {
my ($self) = @_;
# If 'match_encoding' is set we need to return an encoding.
# If pod has no =encoding, Pod::Simple will guess if it sees a high-bit char.
# If there are no high-bit chars, encoding is undef.
# Use detected_encoding() rather than encoding() because if Pod::Simple
# can't use whatever encoding was specified, we probably can't either.
# Fallback to 'o_e' if no match is found. This gives the user the choice,
# since otherwise there would be no reason to specify 'o_e' *and* 'm_e'.
# Fallback to UTF-8 since it is a reasonable default these days.
return $self->detected_encoding || $self->output_encoding || 'UTF-8'
if $self->match_encoding;
# If output encoding wasn't specified, return false.
return $self->output_encoding;
}
## Blocks ##
sub start_Verbatim {
my ($self) = @_;
$self->_new_stack;
$self->_private->{no_escape} = 1;
}
sub end_Verbatim {
my ($self) = @_;
my $text = $self->_pop_stack_text;
$text = $self->_indent_verbatim($text);
$self->_private->{no_escape} = 0;
# Verbatim blocks do not generate a separate "Para" event.
$self->_save_block($text);
}
sub _indent_verbatim {
my ($self, $paragraph) = @_;
# NOTE: Pod::Simple expands the tabs for us (as suggested by perlpodspec).
# Pod::Simple also has a 'strip_verbatim_indent' attribute
# but it doesn't sound like it gains us anything over this method.
# POD verbatim can start with any number of spaces (or tabs)
# markdown should be 4 spaces (or a tab)
# so indent any paragraphs so that all lines start with at least 4 spaces
my @lines = split /\n/, $paragraph;
my $indent = ' ' x 4;
foreach my $line ( @lines ){
next unless $line =~ m/^( +)/;
# find the smallest indentation
$indent = $1 if length($1) < length($indent);
}
if( (my $smallest = length($indent)) < 4 ){
# invert to get what needs to be prepended
$indent = ' ' x (4 - $smallest);
# Prepend indent to each line.
# We could check /\S/ to only indent non-blank lines,
# but it's backward compatible to respect the whitespace.
# Additionally, both pod and markdown say they ignore blank lines
# so it shouldn't hurt to leave them in.
$paragraph = join "\n", map { length($_) ? $indent . $_ : '' } @lines;
}
return $paragraph;
}
sub start_Para {
$_[0]->_new_stack;
}
sub end_Para {
my ($self) = @_;
my $text = $self->_pop_stack_text;
$text = $self->_escape_paragraph_markdown($text);
$self->_save_block($text);
}
## Headings ##
sub start_head1 { $_[0]->_start_head(1) }
sub end_head1 { $_[0]->_end_head(1) }
sub start_head2 { $_[0]->_start_head(2) }
sub end_head2 { $_[0]->_end_head(2) }
sub start_head3 { $_[0]->_start_head(3) }
sub end_head3 { $_[0]->_end_head(3) }
sub start_head4 { $_[0]->_start_head(4) }
sub end_head4 { $_[0]->_end_head(4) }
sub _check_search_header {
my ($self) = @_;
# Save the text since the last heading if we want it for metadata.
if( my $last = $self->_private->{search_header} ){
for( $self->_private->{$last} = $self->_last_string ){
s/\A\s+//;
s/\s+\z//;
}
}
}
sub _start_head {
my ($self) = @_;
$self->_check_search_header;
$self->_new_stack;
}
sub _end_head {
my ($self, $num) = @_;
my $h = '#' x $num;
my $text = $self->_pop_stack_text;
$self->_private->{search_header} =
$text =~ /NAME/ ? 'Title'
: $text =~ /AUTHOR/ ? 'Author'
: undef;
# TODO: option for $h suffix
# TODO: put a name="" if $self->{embed_anchor_tags}; ?
# https://rt.cpan.org/Ticket/Display.html?id=57776
$self->_save_block(join(' ', $h, $text));
}
## Lists ##
# With Pod::Simple->parse_empty_lists(1) there could be an over_empty event,
# but what would you do with that?
sub _start_list {
my ($self) = @_;
$self->_new_stack;
# Nest again b/c start_item will pop this to look for preceding content.
$self->_increase_indent;
$self->_new_stack;
}
sub _end_list {
my ($self) = @_;
$self->_handle_between_item_content;
# Finish the list.
# All the child elements should be blocks,
# but don't end with a double newline.
my $text = $self->_chomp_all($self->_pop_stack_text);
$_[0]->_save_line($text . $/);
}
sub _handle_between_item_content {
my ($self) = @_;
# This might be empty (if the list item had no additional content).
if( my $text = $self->_pop_stack_text ){
# Else it's a sub-document.
# If there are blocks we need to separate with blank lines.
if( $self->_private->{last_state}->{blocks} ){
$text = $/ . $text;
}
# If not, we can condense the text.
# In this module's history there was a patch contributed to specifically
# produce "huddled" lists so we'll try to maintain that functionality.
else {
$text = $self->_chomp_all($text) . $/;
}
$self->_save($text)
}
$self->_decrease_indent;
}
sub _start_item {
my ($self) = @_;
$self->_handle_between_item_content;
$self->_new_stack;
}
sub _end_item {
my ($self, $marker) = @_;
my $text = $self->_pop_stack_text;
$self->_save_line($self->_indent($marker .
# Add a space only if there is text after the marker.
(defined($text) && length($text) ? ' ' . $text : '')
));
# Store any possible contents in a new stack (like a sub-document).
$self->_increase_indent;
$self->_new_stack;
}
sub start_over_bullet { $_[0]->_start_list }
sub end_over_bullet { $_[0]->_end_list }
sub start_item_bullet { $_[0]->_start_item }
sub end_item_bullet { $_[0]->_end_item('-') }
sub start_over_number { $_[0]->_start_list }
sub end_over_number { $_[0]->_end_list }
sub start_item_number {
$_[0]->_start_item;
# It seems like this should be a stack,
# but from testing it appears that the corresponding 'end' event
# comes right after the text (it doesn't surround any embedded content).
# See t/nested.t which shows start-item, text, end-item, para, start-item....
$_[0]->_private->{item_number} = $_[1]->{number};
}
sub end_item_number {
my ($self) = @_;
$self->_end_item($self->_private->{item_number} . '.');
}
# Markdown doesn't support definition lists
# so do regular (unordered) lists with indented paragraphs.
sub start_over_text { $_[0]->_start_list }
sub end_over_text { $_[0]->_end_list }
sub start_item_text { $_[0]->_start_item }
sub end_item_text { $_[0]->_end_item('-')}
# perlpodspec equates an over/back region with no items to a blockquote.
sub start_over_block {
# NOTE: We don't actually need to indent for a blockquote.
$_[0]->_new_stack;
}
sub end_over_block {
my ($self) = @_;
# Chomp first to avoid prefixing a blank line with a `>`.
my $text = $self->_chomp_all($self->_pop_stack_text);
# NOTE: Paragraphs will already be escaped.
# I don't really like either of these implementations
# but the join/map/split seems a little better and benches a little faster.
# You would lose the last newline but we've already chomped.
#$text =~ s{^(.)?}{'>' . (defined($1) && length($1) ? (' ' . $1) : '')}mge;
$text = join $/, map { length($_) ? '> ' . $_ : '>' } split qr-$/-, $text;
$self->_save_block($text);
}
## Custom Formats ##
sub start_for {
my ($self, $attr) = @_;
$self->_new_stack;
if( $attr->{target} eq 'html' ){
# Use another stack so we can indent
# (not syntactily necessary but seems appropriate).
$self->_new_stack;
$self->_increase_indent;
$self->_private->{no_escape} = 1;
# Mark this so we know to undo it.
$self->_stack_state->{for_html} = 1;
}
}
sub end_for {
my ($self) = @_;
# Data gets saved as a block (which will handle indents),
# but if there was html we'll alter this, so chomp and save a block again.
my $text = $self->_chomp_all($self->_pop_stack_text);
if( $self->_private->{last_state}->{for_html} ){
$self->_private->{no_escape} = 0;
# Save it to the next stack up so we can pop it again (we made two stacks).
$self->_save($text);
$self->_decrease_indent;
$text = join "\n", '', $self->_chomp_all($self->_pop_stack_text), '';
}
$self->_save_block($text);
}
# Data events will be emitted for any formatted regions that have been enabled
# (by default, `markdown` and `html`).
sub start_Data {
my ($self) = @_;
# TODO: limit this to what's in attr?
$self->_private->{no_escape}++;
$self->_new_stack;
}
sub end_Data {
my ($self) = @_;
my $text = $self->_pop_stack_text;
$self->_private->{no_escape}--;
$self->_save_block($text);
}
## Codes ##
sub start_B { $_[0]->_save('**') }
sub end_B { $_[0]->start_B() }
sub start_I { $_[0]->_save('_') }
sub end_I { $_[0]->start_I() }
sub start_C {
my ($self) = @_;
$self->_new_stack;
$self->_private->{no_escape}++;
}
sub end_C {
my ($self) = @_;
$self->_private->{no_escape}--;
$self->_save( $self->_wrap_code_span($self->_pop_stack_text) );
}
# Use code spans for F<>.
sub start_F { shift->start_C(@_); }
sub end_F { shift ->end_C(@_); }
sub start_L {
my ($self, $flags) = @_;
$self->_new_stack;
push @{ $self->_private->{link} }, $flags;
}
sub end_L {
my ($self) = @_;
my $flags = pop @{ $self->_private->{link} }
or die 'Invalid state: link end with no link start';
my ($type, $to, $section) = @{$flags}{qw( type to section )};
my $url = (
$type eq 'url' ? $to
: $type eq 'man' ? $self->format_man_url($to, $section)
: $type eq 'pod' ? $self->format_perldoc_url($to, $section)
: undef
);
my $text = $self->_pop_stack_text;
# NOTE: I don't think the perlpodspec says what to do with L<|blah>
# but it seems like a blank link text just doesn't make sense
if( !length($text) ){
$text =
$section ?
$to ? sprintf('"%s" in %s', $section, $to)
: ('"' . $section . '"')
: $to;
}
# FIXME: What does Pod::Simple::X?HTML do for this?
# if we don't know how to handle the url just print the pod back out
if (!$url) {
$self->_save(sprintf 'L<%s>', $flags->{raw});
return;
}
# In the url we need to escape quotes and parentheses lest markdown
# break the url (cut it short and/or wrongfully interpret a title).
# Backslash escapes do not work for the space and quotes.
# URL-encoding the space is not sufficient
# (the quotes confuse some parsers and produce invalid html).
# I've arbitratily chosen HTML encoding to hide them from markdown
# while mangling the url as litle as possible.
$url =~ s/([ '"])/sprintf '%x;', ord($1)/ge;
# We also need to double any backslashes that may be present
# (lest they be swallowed up) and stop parens from breaking the url.
$url =~ s/([\\()])/\\$1/g;
# TODO: put section name in title if not the same as $text
$self->_save('[' . $text . '](' . $url . ')');
}
sub start_X {
$_[0]->_new_stack;
}
sub end_X {
my ($self) = @_;
my $text = $self->_pop_stack_text;
# TODO: mangle $text?
# TODO: put if configured
}
# A code span can be delimited by multiple backticks (and a space)
# similar to pod codes (C<< code >>), so ensure we use a big enough
# delimiter to not have it broken by embedded backticks.
sub _wrap_code_span {
my ($self, $arg) = @_;
my $longest = 0;
while( $arg =~ /([`]+)/g ){
my $len = length($1);
$longest = $len if $longest < $len;
}
my $delim = '`' x ($longest + 1);
my $pad = $longest > 0 ? ' ' : '';
return $delim . $pad . $arg . $pad . $delim;
}
## Link Formatting (TODO: Move this to another module) ##
sub format_man_url {
my ($self, $to) = @_;
my ($page, $part) = ($to =~ /^ ([^(]+) (?: \( (\S+) \) )? /x);
return $self->man_url_prefix . ($part || 1) . '/' . ($page || $to);
}
sub format_perldoc_url {
my ($self, $name, $section) = @_;
my $url_prefix = $self->perldoc_url_prefix;
if (
defined($name)
&& $self->is_local_module($name)
&& defined($self->local_module_url_prefix)
) {
$url_prefix = $self->local_module_url_prefix;
}
my $url = '';
# If the link is to another module (external link).
if ($name) {
$url = $url_prefix . ($self->escape_url ? URI::Escape::uri_escape($name) : $name);
}
# See https://rt.cpan.org/Ticket/Display.html?id=57776
# for a discussion on the need to mangle the section.
if ($section){
my $method = $url
# If we already have a prefix on the url it's external.
? $self->perldoc_fragment_format
# Else an internal link points to this markdown doc.
: $self->markdown_fragment_format;
$method = 'format_fragment_' . $method
unless ref($method);
{
# Set topic to enable code refs to be simple.
local $_ = $section;
$section = $self->$method($section);
}
$url .= '#' . $section;
}
return $url;
}
# TODO: simple, pandoc, etc?
sub format_fragment_markdown {
my ($self, $section) = @_;
# If this is an internal link (to another section in this doc)
# we can't be sure what the heading id's will look like
# (it depends on what is rendering the markdown to html)
# but we can try to follow popular conventions.
# http://johnmacfarlane.net/pandoc/demo/example9/pandocs-markdown.html#header-identifiers-in-html-latex-and-context
#$section =~ s/(?![-_.])[[:punct:]]//g;
#$section =~ s/\s+/-/g;
$section =~ s/\W+/-/g;
$section =~ s/-+$//;
$section =~ s/^-+//;
$section = lc $section;
#$section =~ s/^[^a-z]+//;
$section ||= 'section';
return $section;
}
{
# From Pod::Simple::XHTML 3.28.
# The strings gets passed through encode_entities() before idify().
# If we don't do it here the substitutions below won't operate consistently.
sub format_fragment_pod_simple_xhtml {
my ($self, $t) = @_;
# encode_entities {
# We need to use the defaults in case html_encode_chars has been customized
# (since the purpose is to match what external sources are doing).
local $self->_private->{html_encode_chars};
$t = $self->encode_entities($t);
# }
# idify {
for ($t) {
s/<[^>]+>//g; # Strip HTML.
s/&[^;]+;//g; # Strip entities.
s/^\s+//; s/\s+$//; # Strip white space.
s/^([^a-zA-Z]+)$/pod$1/; # Prepend "pod" if no valid chars.
s/^[^a-zA-Z]+//; # First char must be a letter.
s/[^-a-zA-Z0-9_:.]+/-/g; # All other chars must be valid.
s/[-:.]+$//; # Strip trailing punctuation.
}
# }
return $t;
}
}
sub format_fragment_pod_simple_html {
my ($self, $section) = @_;
# From Pod::Simple::HTML 3.28.
# section_name_tidy {
$section =~ s/^\s+//;
$section =~ s/\s+$//;
$section =~ tr/ /_/;
$section =~ tr/\x00-\x1F\x80-\x9F//d if 'A' eq chr(65); # drop crazy characters
#$section = $self->unicode_escape_url($section);
# unicode_escape_url {
$section =~ s/([^\x00-\xFF])/'('.ord($1).')'/eg;
# Turn char 1234 into "(1234)"
# }
$section = '_' unless length $section;
return $section;
# }
}
sub format_fragment_metacpan { shift->format_fragment_pod_simple_xhtml(@_); }
sub format_fragment_sco { shift->format_fragment_pod_simple_html(@_); }
sub is_local_module {
my ($self, $name) = @_;
return ($name =~ $self->local_module_re);
}
1;
__END__
=pod
=encoding UTF-8
=for :stopwords Marcel Gruenauer Victor Moral Ryan C. Thompson Aristotle Pagaltzis Randy Stauner ACKNOWLEDGEMENTS html cpan
testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata
placeholders metacpan
=head1 NAME
Pod::Markdown - Convert POD to Markdown
=head1 VERSION
version 3.400
=for test_synopsis my ($pod_string);
=head1 SYNOPSIS
# Pod::Simple API is supported.
# Command line usage: Parse a pod file and print to STDOUT:
# $ perl -MPod::Markdown -e 'Pod::Markdown->new->filter(@ARGV)' path/to/POD/file > README.md
# Work with strings:
my $markdown;
my $parser = Pod::Markdown->new;
$parser->output_string(\$markdown);
$parser->parse_string_document($pod_string);
# See Pod::Simple docs for more.
=head1 DESCRIPTION
This module uses L to convert POD to Markdown.
Literal characters in Pod that are special in Markdown
(like *asterisks*) are backslash-escaped when appropriate.
By default C and C formatted regions are accepted.
Regions of C will be passed through unchanged.
Regions of C will be placed inside a C<< EdivE >> tag
so that markdown characters won't be processed.
Regions of C<:markdown> or C<:html> will be processed as POD and included.
To change which regions are accepted use the L API:
my $parser = Pod::Markdown->new;
$parser->unaccept_targets(qw( markdown html ));
=head2 A note on encoding and escaping
The common L API returns a character string.
If you want Pod::Markdown to return encoded octets, there are two attributes
to assist: L and L.
When an output encoding is requested any characters that are not valid
for that encoding will be escaped as HTML entities.
This is not 100% safe, however.
Markdown escapes all ampersands inside of code spans, so escaping a character
as an HTML entity inside of a code span will not be correct.
However, with pod's C and C sequences it is possible
to end up with high-bit characters inside of code spans.
So, while C<< output_encoding => 'ascii' >> can work, it is not recommended.
For these reasons (and more), C is the default, fallback encoding (when one is required).
If you prefer HTML entities over literal characters you can use
L which will only operate outside of code spans (where it is safe).
=head1 METHODS
=head2 new
Pod::Markdown->new(%options);
The constructor accepts the following named arguments:
=over 4
=item *
C
Alters the perldoc urls that are created from C<< LEE >> codes
when the module is a "local" module (C<"Local::*"> or C<"Foo_Corp::*"> (see L)).
The default is to use C.
=item *
C
Alternate regular expression for determining "local" modules.
Default is C<< our $LOCAL_MODULE_RE = qr/^(Local::|\w*?_\w*)/ >>.
=item *
C
Alters the man page urls that are created from C<< LEE >> codes.
The default is C.
=item *
C
Alters the perldoc urls that are created from C<< LEE >> codes.
Can be:
=over 4
=item *
C (shortcut for C )
=item *
C (shortcut for C)
=item *
any url
=back
The default is C.
Pod::Markdown->new(perldoc_url_prefix => 'http://localhost/perl/pod');
=item *
C
Alters the format of the url fragment for any C<< LEE >> links
that point to a section of an external document (C<< L