CommonMark-0.310100 000755 001750 001750 0 14656765207 12550 5 ustar 00nik nik 000000 000000 Changes 100644 001750 001750 5517 14656765207 14134 0 ustar 00nik nik 000000 000000 CommonMark-0.310100 Revision history for Perl module CommonMark
0.310100 2024-08-13
- Recommend and test with libcmark 0.31.1
- Fix build with libcmark 0.25
- Expand and improve the documentation (David E. Wheeler)
- Move from Travis/Appveyor to Github CI. Thanks to David E. Wheeler
for the initial commit!
0.290000 2019-04-09
- BREAKING CHANGE: Add support for OPT_UNSAFE
Safe HTML rendering is now enabled by default. Use OPT_UNSAFE to
get the old behavior.
- Fix warning in render helper
- Fix misplaced package statement
- Generate META.json
- Improve test coverage
- Improve documentation
0.280301 2017-10-24
- Add support for NOBREAKS option
- Documentation fixes
- Test suite improvements
0.280300 2017-10-22
- Compilation fix for Perl 5.8
- Compilation fix for C89 compilers
- Throw if NULL pointers are returned
- Fix localized ARGV in Makefile.PL
- Add files generated by Dist::Zilla to version control
- Documentation fixes
0.240100 2016-02-17
- Support custom nodes (requires libcmark 0.23)
- Export constants
- Document more helper functions
- Use new node naming conventions for helpers (old names are still
supported).
- Fix tests under libcmark 0.24.0.
Thanks to A. Sinan Unur for the report.
- Implement $node->replace
0.230002 2015-12-30
- Fixes for libcmark 0.21.0
0.230001 2015-12-30
- Define constants in XS code.
Should add backward compatibility for libcmark 0.21.
0.230000 2015-12-29
- Support and require libcmark 0.23
- Improve and fix documentation
- Fix "unescaped left brace" warning on Perl 5.22
0.210001 2015-07-28
- Stop returning encoded UTF-8 from renderers
BREAKING CHANGE: The renderers now return normal Perl strings.
Use utf8::encode before printing the result to binary streams.
- $node->render convenience method
- Additional parser options for CommonMark->parse
- Fix and improve check for libcmark
0.210000 2015-07-27
- Require libcmark 0.21.0
- Adjust for libcmark API changes
- Add support for Latex renderer
0.180300 2015-04-02
- Require libcmark 0.18.3
- Add options parameter to markdown_to_html
- Add support to render as Commonmark
0.1802 2015-03-16
- Fix build with Perl <= 5.14.
- Test with Travis CI.
0.1801 2015-03-11
- Fix Parser->new to work correctly with libcmark 0.18.
Also fixes compilation with libcmark 0.18.1.
0.1800 2015-03-05
- Adjust to API changes in libcmark 0.18.
- Require libcmark 0.18.
- Add "parse" convenience function.
- Fix build with old EUMM versions.
0.1700 2015-02-04
- Check for libcmark with Devel::CheckLib.
- Accessors for libcmark version.
- Require libcmark 0.16.
- Improve and fix documentation.
0.1601 2015-01-22
- Initial release.
typemap 100644 001750 001750 2153 14656765207 14234 0 ustar 00nik nik 000000 000000 CommonMark-0.310100 TYPEMAP
cmark_node * T_NODE
cmark_iter * T_ITER
cmark_parser * T_PARSER
const char * T_UTF8
char * T_UTF8
# The custom OUTPUT for T_IV generates better code than the default.
# It looks like this is due to weirdness in ExtUtils::ParseXS which creates
# suboptimal code for "targetable" return types.
int T_IV
long T_IV
cmark_node_type T_IV
cmark_event_type T_IV
INPUT
T_NODE
$var = (cmark_node*)S_sv2c(aTHX_ $arg, \"CommonMark::Node\", 16, cv,
\"$var\");
T_ITER
$var = (cmark_iter*)S_sv2c(aTHX_ $arg, \"CommonMark::Iterator\", 20, cv,
\"$var\");
T_PARSER
$var = (cmark_parser*)S_sv2c(aTHX_ $arg, \"CommonMark::Parser\", 18, cv,
\"$var\");
T_UTF8
$var = SvPVutf8_nolen($arg)
OUTPUT
T_NODE
$arg = S_node2sv(aTHX_ $var);
T_ITER
sv_setref_pv($arg, \"CommonMark::Iterator\", $var);
T_PARSER
sv_setref_pv($arg, \"CommonMark::Parser\", $var);
T_UTF8
$arg = newSVpv($var, 0);
SvUTF8_on($arg);
T_IV
$arg = newSViv((IV)$var);
LICENSE 100644 001750 001750 36652 14656765207 13672 0 ustar 00nik nik 000000 000000 CommonMark-0.310100 This software is copyright (C) by Nick Wellnhofer .
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
Terms of the Perl programming language system itself
a) the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any
later version, or
b) the "Artistic License"
--- The GNU General Public License, Version 1, February 1989 ---
This software is Copyright (C) by Nick Wellnhofer.
This is free software, licensed under:
The GNU General Public License, Version 1, February 1989
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of a such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work based
on the Program" means either the Program or any work containing the
Program or a portion of it, either verbatim or with modifications. Each
licensee is addressed as "you".
1. You may copy and distribute verbatim copies of the Program's source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a fee for the physical act of
transferring a copy.
2. You may modify your copy or copies of the Program or any portion of
it, and copy and distribute such modifications under the terms of Paragraph
1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating that
you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish, that
in whole or in part contains the Program or any part thereof, either
with or without modifications, to be licensed at no charge to all
third parties under the terms of this General Public License (except
that you may choose to grant warranty protection to some or all
third parties, at your option).
c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive use
in the simplest and most usual way, to print or display an
announcement including an appropriate copyright notice and a notice
that there is no warranty (or else, saying that you provide a
warranty) and that users may redistribute the program under these
conditions, and telling the user how to view a copy of this General
Public License.
d) You may charge a fee for the physical act of transferring a
copy, and you may at your option offer warranty protection in
exchange for a fee.
Mere aggregation of another independent work with the Program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other work under the scope of these terms.
3. You may copy and distribute the Program (or a portion or derivative of
it, under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal charge
for the cost of distribution) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
Source code for a work means the preferred form of the work for making
modifications to it. For an executable file, complete source code means
all the source code for all modules it contains; but, as a special
exception, it need not include source code for modules which are standard
libraries that accompany the operating system on which the executable
file runs, or for standard header files or definitions files that
accompany that operating system.
4. You may not copy, modify, sublicense, distribute or transfer the
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License will not have their licenses terminated so long as such parties
remain in full compliance.
5. By copying, distributing or modifying the Program (or any work based
on the Program) you indicate your acceptance of this license to do so,
and all its terms and conditions.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these
terms and conditions. You may not impose any further restrictions on the
recipients' exercise of the rights granted herein.
7. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
the license, you may choose any version ever published by the Free Software
Foundation.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
--- The Artistic License 1.0 ---
This software is Copyright (C) by Nick Wellnhofer.
This is free software, licensed under:
The Artistic License 1.0
The Artistic License
Preamble
The intent of this document is to state the conditions under which a Package
may be copied, such that the Copyright Holder maintains some semblance of
artistic control over the development of the package, while giving the users of
the package the right to use and distribute the Package in a more-or-less
customary fashion, plus the right to make reasonable modifications.
Definitions:
- "Package" refers to the collection of files distributed by the Copyright
Holder, and derivatives of that collection of files created through
textual modification.
- "Standard Version" refers to such a Package if it has not been modified,
or has been modified in accordance with the wishes of the Copyright
Holder.
- "Copyright Holder" is whoever is named in the copyright or copyrights for
the package.
- "You" is you, if you're thinking about copying or distributing this Package.
- "Reasonable copying fee" is whatever you can justify on the basis of media
cost, duplication charges, time of people involved, and so on. (You will
not be required to justify it to the Copyright Holder, but only to the
computing community at large as a market that must bear the fee.)
- "Freely Available" means that no fee is charged for the item itself, though
there may be fees involved in handling the item. It also means that
recipients of the item may redistribute it under the same conditions they
received it.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications derived
from the Public Domain or from the Copyright Holder. A Package modified in such
a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided that
you insert a prominent notice in each changed file stating how and when you
changed that file, and provided that you do at least ONE of the following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or an
equivalent medium, or placing the modifications on a major archive site
such as ftp.uu.net, or by allowing the Copyright Holder to include your
modifications in the Standard Version of the Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict with
standard executables, which must also be provided, and provide a separate
manual page for each non-standard executable that clearly documents how it
differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or executable
form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where to
get the Standard Version.
b) accompany the distribution with the machine-readable source of the Package
with your modifications.
c) accompany any non-standard executables with their corresponding Standard
Version executables, giving the non-standard executables non-standard
names, and clearly documenting the differences in manual pages (or
equivalent), together with instructions on where to get the Standard
Version.
d) make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of this
Package. You may charge any fee you choose for support of this Package. You
may not charge a fee for this Package itself. However, you may distribute this
Package in aggregate with other (possibly commercial) programs as part of a
larger (possibly commercial) software distribution provided that you do not
advertise this Package as a product of your own.
6. The scripts and library files supplied as input to or produced as output
from the programs of this Package do not automatically fall under the copyright
of this Package, but belong to whomever generated them, and may be sold
commercially, and may be aggregated with this Package.
7. C or perl subroutines supplied by you and linked into this Package shall not
be considered part of this Package.
8. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End
META.yml 100644 001750 001750 1403 14656765207 14100 0 ustar 00nik nik 000000 000000 CommonMark-0.310100 ---
abstract: 'Interface to the CommonMark C library'
author:
- 'Nick Wellnhofer '
build_requires:
Encode: '0'
Test::More: '0'
configure_requires:
Devel::CheckLib: '0'
ExtUtils::MakeMaker: '0'
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: CommonMark
requires:
perl: '5.008'
resources:
bugtracker: https://github.com/nwellnhof/perl-commonmark/issues
repository: https://github.com/nwellnhof/perl-commonmark.git
version: '0.310100'
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 001750 1053 14656765207 13761 0 ustar 00nik nik 000000 000000 CommonMark-0.310100 # This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.024.
Changes
CommonMark.xs
INSTALL.SKIP
LICENSE
MANIFEST
META.json
META.yml
Makefile.PL
README.pod
dist.ini
lib/CommonMark.pm
lib/CommonMark.pod
lib/CommonMark/Iterator.pod
lib/CommonMark/Node.pod
lib/CommonMark/Parser.pod
t/01_memory.t
t/02_accessors.t
t/03_render.t
t/04_parser.t
t/05_iterator.t
t/06_build_tree.t
t/07_tree_manip.t
t/08_create_helpers.t
t/09_version.t
t/10_wrappers.t
t/11_options.t
t/20_errors.t
t/30_leakcheck.t
t/author-pod-syntax.t
t/files/test.md
typemap
dist.ini 100644 001750 001750 3032 14656765207 14273 0 ustar 00nik nik 000000 000000 CommonMark-0.310100 name = CommonMark
abstract = Interface to the CommonMark C library
version = 0.310100
author = Nick Wellnhofer
license = Perl_5
copyright_holder = Nick Wellnhofer
[@Filter]
-bundle = @Basic
-remove = GatherDir
-remove = License
-remove = Readme
-remove = MakeMaker
[PodSyntaxTests]
[Prereqs]
perl = 5.008
[Prereqs / ConfigureRequires ]
Devel::CheckLib = 0
[Prereqs / TestRequires]
Test::More = 0
Encode = 0
[Prereqs / TestRecommends]
Test::LeakTrace = 0
[MetaJSON]
[MetaResources]
repository.url = https://github.com/nwellnhof/perl-commonmark.git
repository.web = https://github.com/nwellnhof/perl-commonmark
repository.type = git
bugtracker.web = https://github.com/nwellnhof/perl-commonmark/issues
; See https://rt.cpan.org/Public/Bug/Display.html?id=92828
[GatherDir]
exclude_filename = Makefile.PL
exclude_filename = MANIFEST
exclude_filename = META.json
exclude_filename = META.yml
[CopyFilesFromBuild]
copy = Makefile.PL
copy = MANIFEST
copy = META.json
copy = META.yml
[MakeMaker::Awesome]
WriteMakefile_arg = LIBS => '-lcmark'
header = use Devel::CheckLib;
header = {
header = local @ARGV = @ARGV;
header = unshift(@ARGV, ExtUtils::MakeMaker::_shellwords($ENV{PERL_MM_OPT} || ''))
header = if $ExtUtils::MakeMaker::VERSION >= 6.73_08;
header = check_lib(
header = header => 'cmark.h',
header = function => 'return CMARK_VERSION >= 0x001500 ? 0 : 1;',
header = ) or warn('libcmark 0.21.0 or higher not found'), exit;
header = }
META.json 100644 001750 001750 2746 14656765207 14263 0 ustar 00nik nik 000000 000000 CommonMark-0.310100 {
"abstract" : "Interface to the CommonMark C library",
"author" : [
"Nick Wellnhofer "
],
"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" : "CommonMark",
"prereqs" : {
"configure" : {
"requires" : {
"Devel::CheckLib" : "0",
"ExtUtils::MakeMaker" : "0"
}
},
"develop" : {
"requires" : {
"Test::Pod" : "1.41"
}
},
"runtime" : {
"requires" : {
"perl" : "5.008"
}
},
"test" : {
"recommends" : {
"Test::LeakTrace" : "0"
},
"requires" : {
"Encode" : "0",
"Test::More" : "0"
}
}
},
"release_status" : "stable",
"resources" : {
"bugtracker" : {
"web" : "https://github.com/nwellnhof/perl-commonmark/issues"
},
"repository" : {
"type" : "git",
"url" : "https://github.com/nwellnhof/perl-commonmark.git",
"web" : "https://github.com/nwellnhof/perl-commonmark"
}
},
"version" : "0.310100",
"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"
}
README.pod 100644 001750 001750 1111 14656765207 14264 0 ustar 00nik nik 000000 000000 CommonMark-0.310100 =begin html
=end html
=head1 Perl bindings for the CommonMark C library
This distribution is a wrapper around I, the official CommonMark C
library.
=head2 Installation
See section "Installation" in the POD for the CommonMark module.
=head2 Copyright
This software is copyright (C) by Nick Wellnhofer.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
Makefile.PL 100644 001750 001750 2773 14656765207 14614 0 ustar 00nik nik 000000 000000 CommonMark-0.310100 # This Makefile.PL for CommonMark was generated by
# Dist::Zilla::Plugin::MakeMaker::Awesome 0.49.
# Don't edit it but the dist.ini and plugins used to construct it.
use strict;
use warnings;
use 5.008;
use ExtUtils::MakeMaker;
use Devel::CheckLib;
{
local @ARGV = @ARGV;
unshift(@ARGV, ExtUtils::MakeMaker::_shellwords($ENV{PERL_MM_OPT} || ''))
if $ExtUtils::MakeMaker::VERSION >= 6.73_08;
check_lib(
header => 'cmark.h',
function => 'return CMARK_VERSION >= 0x001500 ? 0 : 1;',
) or warn('libcmark 0.21.0 or higher not found'), exit;
}
my %WriteMakefileArgs = (
"ABSTRACT" => "Interface to the CommonMark C library",
"AUTHOR" => "Nick Wellnhofer ",
"CONFIGURE_REQUIRES" => {
"Devel::CheckLib" => 0,
"ExtUtils::MakeMaker" => 0
},
"DISTNAME" => "CommonMark",
"LICENSE" => "perl",
"MIN_PERL_VERSION" => "5.008",
"NAME" => "CommonMark",
"PREREQ_PM" => {},
"TEST_REQUIRES" => {
"Encode" => 0,
"Test::More" => 0
},
"VERSION" => "0.310100",
"test" => {
"TESTS" => "t/*.t"
}
);
%WriteMakefileArgs = (
%WriteMakefileArgs,
LIBS => '-lcmark',
);
my %FallbackPrereqs = (
"Encode" => 0,
"Test::More" => 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);
INSTALL.SKIP 100644 001750 001750 7 14656765207 14344 0 ustar 00nik nik 000000 000000 CommonMark-0.310100 README
CommonMark.xs 100644 001750 001750 40513 14656765207 15273 0 ustar 00nik nik 000000 000000 CommonMark-0.310100 /*
* Notes on memory management
*
* - A pointer to the Perl SV representing a node is stored in the
* user data slot of `struct cmark_node`, so there's a 1:1 mapping
* between Perl and C objects.
* - Every node SV keeps a reference to the parent SV. This is done
* by looking up the parent SV via user data and increasing its refcount.
* - This makes sure that a document isn't freed if the last reference
* from Perl to the root node is dropped, while references to child nodes
* might still exist.
* - As a consequence, as long as a node is referenced from Perl, all its
* ancestor nodes will also be associated with a Perl object.
*/
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include
#include
#if CMARK_VERSION < 0x001500
#error libcmark 0.21.0 is required.
#endif
#if PERL_VERSION <= 8
#define SvREFCNT_inc_simple_void_NN SvREFCNT_inc
#endif
#if PERL_VERSION <= 14
#define sv_derived_from_pvn(sv, name, len, flags) sv_derived_from(sv, name)
#endif
/* Fix prefixes of render functions. */
#define cmark_node_render_html cmark_render_html
#define cmark_node_render_xml cmark_render_xml
#define cmark_node_render_man cmark_render_man
#define cmark_node_render_commonmark cmark_render_commonmark
#define cmark_node_render_latex cmark_render_latex
/* Backward compatibility */
#if CMARK_VERSION < 0x001700
/* Older than 0.23.0 */
static const char*
S_unsupported_get_utf8(cmark_node *node) {
(void)node;
return NULL;
}
static const char*
S_unsupported_set_utf8(cmark_node *node, const char *val) {
(void)node;
(void)val;
return 0;
}
#define cmark_node_get_on_enter S_unsupported_get_utf8
#define cmark_node_get_on_exit S_unsupported_get_utf8
#define cmark_node_set_on_enter S_unsupported_set_utf8
#define cmark_node_set_on_exit S_unsupported_set_utf8
#endif /* CMARK_VERSION < 0x001700 */
#ifdef CMARK_OPT_UNSAFE
#define OPT_UNSAFE CMARK_OPT_UNSAFE
#else
/* Hardcoded value, ignored by old libcmark versions. */
#define OPT_UNSAFE (1 << 17)
#endif
static SV*
S_create_or_incref_node_sv(pTHX_ cmark_node *node) {
SV *new_obj = NULL;
while (node) {
SV *obj;
HV *stash;
/* Look for existing object. */
obj = (SV*)cmark_node_get_user_data(node);
if (obj) {
/* Incref if found. */
SvREFCNT_inc_simple_void_NN(obj);
if (!new_obj) {
new_obj = obj;
}
break;
}
/* Create a new SV. */
obj = newSViv(PTR2IV(node));
cmark_node_set_user_data(node, obj);
if (!new_obj) {
new_obj = obj;
}
/*
* Unfortunately, Perl doesn't offer an API function to bless an SV
* without a reference. The following code is mostly copied from
* sv_bless.
*/
SvOBJECT_on(obj);
#if PERL_VERSION <= 16
PL_sv_objcount++;
#endif
SvUPGRADE(obj, SVt_PVMG);
stash = gv_stashpvn("CommonMark::Node", 16, GV_ADD);
SvSTASH_set(obj, (HV*)SvREFCNT_inc(stash));
/* Recurse into parent. */
node = cmark_node_parent(node);
}
return new_obj;
}
static void
S_decref_node_sv(pTHX_ cmark_node *node) {
SV *obj;
if (!node) {
return;
}
obj = (SV*)cmark_node_get_user_data(node);
if (!obj) {
/* Should never happen. */
croak("Internal error: node SV not found");
}
SvREFCNT_dec(obj);
}
/* Find or create an SV for a cmark_node. */
static SV*
S_node2sv(pTHX_ cmark_node *node) {
SV *obj;
if (!node) {
return &PL_sv_undef;
}
obj = S_create_or_incref_node_sv(aTHX_ node);
return newRV_noinc(obj);
}
/* Transfer refcount from a node to another. */
static void
S_transfer_refcount(pTHX_ cmark_node *from, cmark_node *to) {
if (from != to) {
/*
* It is important to incref first, then decref. Otherwise, node SVs
* of ancestors could be needlessly destroyed and recreated when
* transferring a sole reference to a nearby node.
*/
S_create_or_incref_node_sv(aTHX_ to);
S_decref_node_sv(aTHX_ from);
}
}
/* Get C struct pointer from an SV argument. */
static void*
S_sv2c(pTHX_ SV *sv, const char *class_name, STRLEN len, CV *cv,
const char *var_name) {
if (!SvROK(sv) || !sv_derived_from_pvn(sv, class_name, len, 0)) {
const char *sub_name = GvNAME(CvGV(cv));
croak("%s: %s is not of type %s", sub_name, var_name, class_name);
}
return INT2PTR(void*, SvIV(SvRV(sv)));
}
/* Handle SAFE/UNSAFE options. */
static int
S_process_options(int options) {
if (options & CMARK_OPT_SAFE) {
/* SAFE takes predence over UNSAFE. */
options &= ~OPT_UNSAFE;
}
else if ((options & OPT_UNSAFE) == 0) {
/* For old libcmark versions, set SAFE unless UNSAFE was set. */
options |= CMARK_OPT_SAFE;
}
return options;
}
MODULE = CommonMark PACKAGE = CommonMark PREFIX = cmark_
PROTOTYPES: DISABLE
BOOT:
{ /* Block required for C89 compilers. */
static const struct {
const char *name;
int value;
} constants[] = {
{ "NODE_NONE", CMARK_NODE_NONE },
{ "NODE_DOCUMENT", CMARK_NODE_DOCUMENT },
{ "NODE_BLOCK_QUOTE", CMARK_NODE_BLOCK_QUOTE },
{ "NODE_LIST", CMARK_NODE_LIST },
{ "NODE_ITEM", CMARK_NODE_ITEM },
{ "NODE_CODE_BLOCK", CMARK_NODE_CODE_BLOCK },
{ "NODE_HTML", CMARK_NODE_HTML },
{ "NODE_PARAGRAPH", CMARK_NODE_PARAGRAPH },
{ "NODE_HEADER", CMARK_NODE_HEADER },
{ "NODE_HRULE", CMARK_NODE_HRULE },
{ "NODE_TEXT", CMARK_NODE_TEXT },
{ "NODE_SOFTBREAK", CMARK_NODE_SOFTBREAK },
{ "NODE_LINEBREAK", CMARK_NODE_LINEBREAK },
{ "NODE_CODE", CMARK_NODE_CODE },
{ "NODE_INLINE_HTML", CMARK_NODE_INLINE_HTML },
{ "NODE_EMPH", CMARK_NODE_EMPH },
{ "NODE_STRONG", CMARK_NODE_STRONG },
{ "NODE_LINK", CMARK_NODE_LINK },
{ "NODE_IMAGE", CMARK_NODE_IMAGE },
#if CMARK_VERSION >= 0x001700
/* libcmark 0.23.0 */
{ "NODE_CUSTOM_BLOCK", CMARK_NODE_CUSTOM_BLOCK },
{ "NODE_CUSTOM_INLINE", CMARK_NODE_CUSTOM_INLINE },
{ "NODE_HTML_BLOCK", CMARK_NODE_HTML_BLOCK },
{ "NODE_HEADING", CMARK_NODE_HEADING },
{ "NODE_THEMATIC_BREAK", CMARK_NODE_THEMATIC_BREAK },
{ "NODE_HTML_INLINE", CMARK_NODE_HTML_INLINE },
#else
{ "NODE_CUSTOM_BLOCK", CMARK_NODE_NONE },
{ "NODE_CUSTOM_INLINE", CMARK_NODE_NONE },
{ "NODE_HTML_BLOCK", CMARK_NODE_HTML },
{ "NODE_HEADING", CMARK_NODE_HEADER },
{ "NODE_THEMATIC_BREAK", CMARK_NODE_HRULE },
{ "NODE_HTML_INLINE", CMARK_NODE_INLINE_HTML },
#endif
{ "NO_LIST", CMARK_NO_LIST },
{ "BULLET_LIST", CMARK_BULLET_LIST },
{ "ORDERED_LIST", CMARK_ORDERED_LIST },
{ "NO_DELIM", CMARK_NO_DELIM },
{ "PERIOD_DELIM", CMARK_PERIOD_DELIM },
{ "PAREN_DELIM", CMARK_PAREN_DELIM },
{ "EVENT_NONE", CMARK_EVENT_NONE },
{ "EVENT_DONE", CMARK_EVENT_DONE },
{ "EVENT_ENTER", CMARK_EVENT_ENTER },
{ "EVENT_EXIT", CMARK_EVENT_EXIT },
{ "OPT_DEFAULT", CMARK_OPT_DEFAULT },
{ "OPT_SOURCEPOS", CMARK_OPT_SOURCEPOS },
{ "OPT_HARDBREAKS", CMARK_OPT_HARDBREAKS },
{ "OPT_SAFE", CMARK_OPT_SAFE },
#if CMARK_VERSION >= 0x001A00
/* libcmark 0.26.0 */
{ "OPT_NOBREAKS", CMARK_OPT_NOBREAKS },
#else
{ "OPT_NOBREAKS", 0 },
#endif
{ "OPT_NORMALIZE", CMARK_OPT_NORMALIZE },
{ "OPT_VALIDATE_UTF8", CMARK_OPT_VALIDATE_UTF8 },
{ "OPT_SMART", CMARK_OPT_SMART },
{ "OPT_UNSAFE", OPT_UNSAFE }
};
size_t num_constants = sizeof(constants) / sizeof(constants[0]);
size_t i;
HV *stash = gv_stashpv("CommonMark", 0);
if (cmark_version() != CMARK_VERSION) {
warn("Compiled against libcmark %s, but runtime version is %s",
CMARK_VERSION_STRING, cmark_version_string());
}
for (i = 0; i < num_constants; i++) {
newCONSTSUB(stash, constants[i].name, newSViv(constants[i].value));
}
}
char*
cmark_markdown_to_html(package, string, options = 0)
SV *package = NO_INIT
SV *string
int options
PREINIT:
STRLEN len;
const char *buffer;
CODE:
(void)package;
buffer = SvPVutf8(string, len);
options = S_process_options(options);
RETVAL = cmark_markdown_to_html(buffer, len, options);
OUTPUT:
RETVAL
cmark_node*
cmark_parse_document(package, string, options = 0)
SV *package = NO_INIT
SV *string
int options
PREINIT:
STRLEN len;
const char *buffer;
CODE:
(void)package;
buffer = SvPVutf8(string, len);
RETVAL = cmark_parse_document(buffer, len, options);
if (RETVAL == NULL) {
croak("parse_document: unknown error");
}
OUTPUT:
RETVAL
cmark_node*
cmark_parse_file(package, file, options = 0)
SV *package = NO_INIT
SV *file
int options
PREINIT:
PerlIO *perl_io;
FILE *stream = NULL;
CODE:
(void)package;
perl_io = IoIFP(sv_2io(file));
if (perl_io) {
stream = PerlIO_findFILE(perl_io);
}
if (!stream) {
croak("parse_file: file is not a file handle");
}
RETVAL = cmark_parse_file(stream, options);
if (RETVAL == NULL) {
croak("parse_file: unknown error");
}
OUTPUT:
RETVAL
int
cmark_version(package)
SV *package = NO_INIT
CODE:
(void)package;
RETVAL = cmark_version();
OUTPUT:
RETVAL
const char*
cmark_version_string(package)
SV *package = NO_INIT
CODE:
(void)package;
RETVAL = cmark_version_string();
OUTPUT:
RETVAL
int
cmark_compile_time_version(package)
SV *package = NO_INIT
CODE:
(void)package;
RETVAL = CMARK_VERSION;
OUTPUT:
RETVAL
const char*
cmark_compile_time_version_string(package)
SV *package = NO_INIT
CODE:
(void)package;
RETVAL = CMARK_VERSION_STRING;
OUTPUT:
RETVAL
MODULE = CommonMark PACKAGE = CommonMark::Node PREFIX = cmark_node_
cmark_node*
new(package, type)
SV *package = NO_INIT
cmark_node_type type
CODE:
(void)package;
RETVAL = cmark_node_new(type);
if (RETVAL == NULL) {
croak("new: out of memory");
}
OUTPUT:
RETVAL
void
DESTROY(cmark_node *node)
CODE:
cmark_node *parent = cmark_node_parent(node);
if (parent) {
cmark_node_set_user_data(node, NULL);
S_decref_node_sv(aTHX_ parent);
}
else {
cmark_node_free(node);
}
cmark_iter*
iterator(cmark_node *node)
CODE:
S_create_or_incref_node_sv(aTHX_ node);
RETVAL = cmark_iter_new(node);
if (RETVAL == NULL) {
croak("iterator: out of memory");
}
OUTPUT:
RETVAL
cmark_node*
interface_get_node(cmark_node *node)
INTERFACE:
cmark_node_next
cmark_node_previous
cmark_node_parent
cmark_node_first_child
cmark_node_last_child
int
interface_get_int(cmark_node *node)
INTERFACE:
cmark_node_get_type
cmark_node_get_header_level
cmark_node_get_list_type
cmark_node_get_list_delim
cmark_node_get_list_start
cmark_node_get_list_tight
cmark_node_get_start_line
cmark_node_get_start_column
cmark_node_get_end_line
cmark_node_get_end_column
NO_OUTPUT int
interface_set_int(cmark_node *node, int value)
INTERFACE:
cmark_node_set_header_level
cmark_node_set_list_type
cmark_node_set_list_delim
cmark_node_set_list_start
cmark_node_set_list_tight
POSTCALL:
if (!RETVAL) {
croak("%s: invalid operation", GvNAME(CvGV(cv)));
}
const char*
interface_get_utf8(cmark_node *node)
INTERFACE:
cmark_node_get_type_string
cmark_node_get_literal
cmark_node_get_title
cmark_node_get_url
cmark_node_get_fence_info
cmark_node_get_on_enter
cmark_node_get_on_exit
NO_OUTPUT int
interface_set_utf8(cmark_node *node, const char *value)
INTERFACE:
cmark_node_set_literal
cmark_node_set_title
cmark_node_set_url
cmark_node_set_fence_info
cmark_node_set_on_enter
cmark_node_set_on_exit
POSTCALL:
if (!RETVAL) {
croak("%s: invalid operation", GvNAME(CvGV(cv)));
}
void
cmark_node_unlink(cmark_node *node)
PREINIT:
cmark_node *old_parent;
INIT:
old_parent = cmark_node_parent(node);
POSTCALL:
S_decref_node_sv(aTHX_ old_parent);
void
cmark_node_replace(cmark_node *node, cmark_node *other)
PREINIT:
cmark_node *old_parent;
int retval;
CODE:
old_parent = cmark_node_parent(other);
#if CMARK_VERSION < 0x001800
/* Older than 0.24.0 */
retval = cmark_node_insert_before(node, other);
if (retval) {
cmark_node_unlink(node);
}
#else
retval = cmark_node_replace(node, other);
#endif
if (!retval) {
croak("replace: invalid operation");
}
S_decref_node_sv(aTHX_ old_parent);
NO_OUTPUT int
interface_move_node(cmark_node *node, cmark_node *other)
PREINIT:
cmark_node *old_parent;
cmark_node *new_parent;
INIT:
old_parent = cmark_node_parent(other);
INTERFACE:
cmark_node_insert_before
cmark_node_insert_after
cmark_node_prepend_child
cmark_node_append_child
POSTCALL:
if (!RETVAL) {
croak("%s: invalid operation", GvNAME(CvGV(cv)));
}
new_parent = cmark_node_parent(other);
S_transfer_refcount(aTHX_ old_parent, new_parent);
char*
interface_render(cmark_node *root, int options = 0)
INIT:
options = S_process_options(options);
INTERFACE:
cmark_node_render_html
cmark_node_render_xml
char*
interface_render_width(cmark_node *root, int options = 0, int width = 0)
INIT:
options = S_process_options(options);
INTERFACE:
cmark_node_render_man
cmark_node_render_commonmark
cmark_node_render_latex
MODULE = CommonMark PACKAGE = CommonMark::Iterator PREFIX = cmark_iter_
void
DESTROY(cmark_iter *iter)
CODE:
S_decref_node_sv(aTHX_ cmark_iter_get_node(iter));
S_decref_node_sv(aTHX_ cmark_iter_get_root(iter));
cmark_iter_free(iter);
void
cmark_iter_next(cmark_iter *iter)
PREINIT:
I32 gimme;
cmark_node *old_node;
cmark_event_type ev_type;
PPCODE:
gimme = GIMME_V;
old_node = cmark_iter_get_node(iter);
ev_type = cmark_iter_next(iter);
if (ev_type != CMARK_EVENT_DONE) {
cmark_node *node = cmark_iter_get_node(iter);
ST(0) = sv_2mortal(newSViv((IV)ev_type));
if (gimme == G_ARRAY) {
SV *obj = S_create_or_incref_node_sv(aTHX_ node);
/* A bit more efficient than S_transfer_refcount. */
if (old_node != node) {
S_decref_node_sv(aTHX_ old_node);
SvREFCNT_inc_simple_void_NN(obj);
}
ST(1) = sv_2mortal(newRV_noinc(obj));
XSRETURN(2);
}
else {
S_transfer_refcount(aTHX_ old_node, node);
XSRETURN(1);
}
}
else {
S_decref_node_sv(aTHX_ old_node);
if (gimme == G_ARRAY) {
XSRETURN_EMPTY;
}
else {
ST(0) = sv_2mortal(newSViv((IV)ev_type));
XSRETURN(1);
}
}
cmark_node*
cmark_iter_get_node(cmark_iter *iter)
cmark_event_type
cmark_iter_get_event_type(cmark_iter *iter)
void
cmark_iter_reset(iter, node, event_type)
cmark_iter *iter
cmark_node *node
cmark_event_type event_type
PREINIT:
cmark_node *old_node;
INIT:
old_node = cmark_iter_get_node(iter);
S_transfer_refcount(aTHX_ old_node, node);
MODULE = CommonMark PACKAGE = CommonMark::Parser PREFIX = cmark_parser_
cmark_parser*
cmark_parser_new(package, options = 0)
SV *package = NO_INIT
int options
CODE:
(void)package;
RETVAL = cmark_parser_new(options);
if (RETVAL == NULL) {
croak("new: out of memory");
}
OUTPUT:
RETVAL
void
DESTROY(cmark_parser *parser)
CODE:
cmark_parser_free(parser);
void
cmark_parser_feed(cmark_parser *parser, SV *string)
PREINIT:
STRLEN len;
const char *buffer;
CODE:
buffer = SvPVutf8(string, len);
cmark_parser_feed(parser, buffer, len);
cmark_node*
cmark_parser_finish(cmark_parser *parser)
POSTCALL:
if (RETVAL == NULL) {
croak("finish: unknown error");
}
t 000755 001750 001750 0 14656765207 12734 5 ustar 00nik nik 000000 000000 CommonMark-0.310100 20_errors.t 100644 001750 001750 3757 14656765207 15112 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use Symbol;
use Test::More tests => 11;
BEGIN {
use_ok('CommonMark');
}
{
package MyHandle;
sub TIEHANDLE { return bless({}, shift); }
}
my $handle = Symbol::gensym;
tie *$handle, 'MyHandle';
eval {
CommonMark->parse_file(*$handle);
};
like($@, qr/parse_file: file is not a file handle/,
'parse_file with tied handle dies');
{
package MyClass;
sub new { return bless({}, shift); }
}
my $obj = MyClass->new;
eval {
CommonMark::Node::get_type($obj);
};
like($@, qr/get_type: node is not of type CommonMark::Node/,
'get_type on wrong class dies');
my $doc = CommonMark->parse_document('*text*');
my $paragraph = $doc->first_child;
my $emph = $paragraph->first_child;
my $text = $emph->first_child;
SKIP: {
skip('Crashes for some reason', 3)
if $^O eq 'MSWin32' && $^V >= 5.018 && $^V < 5.022;
eval {
$text->insert_after($emph);
};
like($@, qr/insert_after: invalid operation/, 'insert_after dies');
eval {
$emph->set_list_tight(1);
};
like($@, qr/set_list_tight: invalid operation/, 'set_list_tight dies');
eval {
$paragraph->set_url('/url');
};
like($@, qr/set_url: invalid operation/, 'set_url dies');
}
eval {
$doc->render();
};
like($@, qr/must provide format/, 'render without format');
eval {
$doc->render(format => 'non_existent');
};
like($@, qr/invalid format/, 'render with invalid format');
eval {
my $paragraph = CommonMark->create_paragraph(
children => [
CommonMark->create_text(literal => 'text'),
],
text => 'text',
);
};
like($@, qr/can't set both children and text/,
'create_text with children and text');
eval {
my $doc = CommonMark->parse(smart => 1);
};
like($@, qr/must provide either string or file/, 'parse without input');
eval {
my $doc = CommonMark->parse(string => 'md', file => \*STDIN);
};
like($@, qr/can't provide both string and file/, 'parse with string and file');
04_parser.t 100644 001750 001750 1056 14656765207 15062 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use Test::More tests => 4;
BEGIN {
use_ok('CommonMark');
}
my $parser = CommonMark::Parser->new;
isa_ok($parser, 'CommonMark::Parser', 'Parser->new');
$parser->feed("normal *em");
$parser->feed("ph*\n\n**strong**\n\n> blo");
$parser->feed("ck\n> quote\n");
my $doc = $parser->finish;
isa_ok($doc, 'CommonMark::Node', 'finish');
my $expected_html = <<'EOF';
normal emph
strong
block
quote
EOF
is($doc->render_html, $expected_html, 'parser works');
01_memory.t 100644 001750 001750 1450 14656765207 15071 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use Test::More tests => 5;
BEGIN {
use_ok('CommonMark');
}
diag sprintf "cmark compile time version: %s\ncmark runtime version: %s",
CommonMark->compile_time_version_string,
CommonMark->version_string;
my $md = <parse_document($md);
isa_ok($doc, 'CommonMark::Node', 'parse_document');
my $header = $doc->first_child;
isa_ok($header, 'CommonMark::Node', 'first_child');
is($doc->first_child, $header, 'first_child returns same node');
my $text = $header->first_child;
$doc = undef;
$header = undef;
# Cause some allocations.
CommonMark->parse_document($md)
for 1..5;
my $literal = $text->get_literal;
is($literal, 'Header', 'doc still exists with no refs to root');
03_render.t 100644 001750 001750 2076 14656765207 15047 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use Test::More tests => 10;
BEGIN {
use_ok('CommonMark', 'OPT_DEFAULT');
}
my $md = <Header
Paragraph emph, strong
EOF
is(CommonMark->markdown_to_html($md), $expected_html, 'markdown_to_html');
my $doc = CommonMark->parse_document($md);
isa_ok($doc, 'CommonMark::Node', 'parse_document');
is($doc->render_html, $expected_html, 'parse_document works');
like($doc->render_xml, qr/^<\?xml /, 'render_xml');
like($doc->render_man, qr/^\.SH\n/, 'render_man');
like($doc->render_latex, qr/^\\section\{Header\}/, 'render_latex');
my $rendered_md = $doc->render_commonmark(OPT_DEFAULT, 20);
my $expected_md = <<'EOF';
# Header
Paragraph *emph*,
**strong**
EOF
is($rendered_md, $expected_md, 'render_commonmark');
is(CommonMark->markdown_to_html("\x{263A}"), "\x{263A}
\n",
'render functions return encoded utf8');
is(CommonMark->markdown_to_html("\xC2\xA9"), "\xC2\xA9
\n",
'render functions expect decoded utf8');
09_version.t 100644 001750 001750 505 14656765207 15236 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use Test::More tests => 3;
BEGIN {
use_ok('CommonMark');
}
is(CommonMark->version, CommonMark->compile_time_version,
'version matches compile_time_version');
is(CommonMark->version_string, CommonMark->compile_time_version_string,
'version_string matches compile_time_version_string');
11_options.t 100644 001750 001750 3331 14656765207 15255 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use Encode;
use Test::More tests => 11;
BEGIN {
use_ok('CommonMark', ':opt');
}
my ($md, $expected);
$md = "aaa\n\nbbb";
$expected = <<'EOF';
aaa
bbb
EOF
is(CommonMark->markdown_to_html($md, OPT_SOURCEPOS), $expected, 'SOURCEPOS');
$md = "a\nb";
is(CommonMark->markdown_to_html($md, OPT_HARDBREAKS), "a
\nb
\n",
'HARDBREAKS');
SKIP: {
skip('NOBREAKS not supported by libcmark', 1)
if CommonMark->version < 0x001A00;
is(CommonMark->markdown_to_html($md, OPT_NOBREAKS), "a b
\n",
'NOBREAKS');
}
is(CommonMark->markdown_to_html($md), "a\nb
\n",
'without HARDBREAKS or NOBREAKS');
$md = <<'EOF';
a [link](javascript:alert('XSS'))
EOF
$expected = <<'EOF';
a link
EOF
is(CommonMark->markdown_to_html($md), $expected, 'SAFE is default');
is(CommonMark->markdown_to_html($md, OPT_SAFE|OPT_UNSAFE), $expected,
'SAFE takes precedence over UNSAFE');
$expected = <<'EOF';
a link
EOF
is(CommonMark->markdown_to_html($md, OPT_UNSAFE), $expected, 'UNSAFE');
$md = "a\xC0b";
Encode::_utf8_on($md);
is(CommonMark->markdown_to_html($md, OPT_VALIDATE_UTF8), "a\x{FFFD}b
\n",
'VALIDATE_UTF8');
my $html = CommonMark->markdown_to_html($md);
Encode::_utf8_off($html);
is($html, "a\xC0b
\n", 'without VALIDATE_UTF8');
$md = q{"a" -- 'b' --- c};
$expected = <<"EOF";
\x{201C}a\x{201D} \x{2013} \x{2018}b\x{2019} \x{2014} c
EOF
is(CommonMark->markdown_to_html($md, OPT_SMART), $expected, 'SMART');
05_iterator.t 100644 001750 001750 5622 14656765207 15423 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use Test::More tests => 134;
BEGIN {
use_ok('CommonMark', ':node', ':event');
}
my $md = <parse_document($md);
isa_ok($doc, 'CommonMark::Node', 'parse_document');
my @expected_events = (
[ EVENT_ENTER, NODE_DOCUMENT ],
[ EVENT_ENTER, NODE_LIST ],
[ EVENT_ENTER, NODE_ITEM ],
[ EVENT_ENTER, NODE_PARAGRAPH ],
[ EVENT_ENTER, NODE_TEXT ],
[ EVENT_EXIT, NODE_PARAGRAPH ],
[ EVENT_ENTER, NODE_LIST ],
[ EVENT_ENTER, NODE_ITEM ],
[ EVENT_ENTER, NODE_PARAGRAPH ],
[ EVENT_ENTER, NODE_EMPH ],
[ EVENT_ENTER, NODE_STRONG ],
[ EVENT_ENTER, NODE_TEXT ],
[ EVENT_EXIT, NODE_STRONG ],
[ EVENT_EXIT, NODE_EMPH ],
[ EVENT_EXIT, NODE_PARAGRAPH ],
[ EVENT_EXIT, NODE_ITEM ],
[ EVENT_EXIT, NODE_LIST ],
[ EVENT_EXIT, NODE_ITEM ],
[ EVENT_ENTER, NODE_ITEM ],
[ EVENT_ENTER, NODE_PARAGRAPH ],
[ EVENT_ENTER, NODE_TEXT ],
[ EVENT_EXIT, NODE_PARAGRAPH ],
[ EVENT_EXIT, NODE_ITEM ],
[ EVENT_EXIT, NODE_LIST ],
[ EVENT_EXIT, NODE_DOCUMENT ],
);
{
my $iter = $doc->iterator;
isa_ok($iter, 'CommonMark::Iterator', 'iterator');
for (my $i = 0; $i < @expected_events; ++$i) {
my ($ev_type, $node) = $iter->next;
my $expected = $expected_events[$i];
is($ev_type, $expected->[0], "event $i: next ev_type, list context");
is($iter->get_event_type, $ev_type, "event $i: get_event_type");
is($node->get_type, $expected->[1],
"event $i: next node, list context");
is($iter->get_node, $node, "event $i: get_node");
}
my @list = $iter->next;
is(scalar(@list), 0, 'iterator done, list context');
$iter->reset($doc, EVENT_ENTER);
my ($ev_type, $node) = $iter->next;
is($ev_type, EVENT_ENTER, 'ev_type after iterator reset');
is($node, $doc->first_child, 'node after iterator reset');
}
{
my $iter = $doc->iterator;
for (my $i = 0; $i < @expected_events; ++$i) {
my $ev_type = $iter->next;
my $expected = $expected_events[$i];
is($ev_type, $expected->[0], "event $i: next ev_type, scalar context");
}
my $ev_type = $iter->next;
is($ev_type, EVENT_DONE, 'iterator done, scalar context');
}
{
my $iter = $doc->iterator;
# Make sure iterator survives destruction of document.
$doc = undef;
# Cause some allocations.
CommonMark->parse_document($md)
for 1..5;
my $num = 0;
$iter->next for 1..11;
my $strong = $iter->get_node;
is($strong->get_type, NODE_STRONG, '11th node is strong');
$iter = undef;
# Cause some allocations.
CommonMark->parse_document($md)
for 1..5;
my $literal = $strong->first_child->get_literal;
is($literal, 'Text', 'node survives destruction of iter');
}
10_wrappers.t 100644 001750 001750 4215 14656765207 15426 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use File::Spec::Functions qw(catfile);
use Test::More tests => 11;
BEGIN {
use_ok('CommonMark', ':opt');
}
{
my $filename = catfile(qw(t files test.md));
my $file;
open($file, '<', $filename) or die("$filename: $!");
my $doc1 = CommonMark->parse_file($file);
close($file);
open($file, '<', $filename) or die("$filename: $!");
my $doc2 = CommonMark->parse(file => $file);
close($file);
is($doc2->render_html, $doc1->render_html, 'parse works with file');
}
{
my $md = q{Pretty "smart" -- don't you think?};
my $doc = CommonMark->parse(string => $md, smart => 1);
my $expected_html = <Pretty \x{201C}smart\x{201D} \x{2013} don\x{2019}t you think?
EOF
is($doc->render_html, $expected_html, 'parse works with string and smart');
my $html = $doc->render(format => 'html');
is($html, $expected_html, 'render works with HTML format');
}
{
my $all_opts = CommonMark::_extract_opts({
sourcepos => 1,
hardbreaks => 'yes',
safe => 100,
nobreaks => 1,
normalize => '0e0',
validate_utf8 => '1',
smart => 'true',
unsafe => 1,
});
my $expected = OPT_SOURCEPOS
| OPT_HARDBREAKS
| OPT_SAFE
| OPT_NOBREAKS
| OPT_NORMALIZE
| OPT_VALIDATE_UTF8
| OPT_SMART
| OPT_UNSAFE;
is($all_opts, $expected, 'extracting options works');
my $no_opts = CommonMark::_extract_opts({
sourcepos => undef,
hardbreaks => 0,
safe => -0.0,
normalize => 0e100,
validate_utf8 => '0',
smart => '',
unsafe => 0,
});
is($no_opts, 0, 'extracting unset options works');
}
{
my $doc = CommonMark->parse_document('test');
for my $format (qw(html xml commonmark latex man)) {
my $method = "render_$format";
my $expected = $doc->$method();
my $got = $doc->render(format => $format);
is($got, $expected, "render format $format");
}
}
files 000755 001750 001750 0 14656765207 14036 5 ustar 00nik nik 000000 000000 CommonMark-0.310100/t test.md 100644 001750 001750 170 14656765207 15455 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t/files # Header ☺
4) Item 1
5) Item 2
~~~ perl ☺
my @letters = qw(a b c);
~~~
[Link text](http://example.com/ "title")
30_leakcheck.t 100644 001750 001750 3433 14656765207 15500 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use constant HAS_LEAKTRACE => eval{ require Test::LeakTrace };
use Test::More HAS_LEAKTRACE ?
(tests => 1) :
(skip_all => 'require Test::LeakTrace');
use Test::LeakTrace;
use CommonMark qw(:node :event);
my $md = <parse_document($md);
my $paragraph = $doc->first_child;
my $text = $paragraph->first_child;
my $emph = $text->next;
my $strong = $paragraph->last_child;
my $space = $strong->previous;
$doc = undef;
my $result = CommonMark::Node->new(NODE_DOCUMENT);
$text->unlink;
$strong->unlink;
$result->append_child($paragraph);
$emph->insert_before($text);
$space->insert_after($strong);
$emph->replace($strong);
$space->unlink;
}
sub iterate_list_context {
my $doc = CommonMark->parse_document($md);
my $iter = $doc->iterator;
my $sum = 0;
while (my ($ev_type, $node) = $iter->next) {
$sum += $ev_type;
}
return $sum;
}
sub iterate_scalar_context {
my $doc = CommonMark->parse_document($md);
my $iter = $doc->iterator;
my $sum = 0;
while ((my $ev_type = $iter->next) != EVENT_DONE) {
$sum += $ev_type;
}
return $sum;
}
sub aborted_iteration {
my $doc = CommonMark->parse_document($md);
my $iter = $doc->iterator;
my ($ev_type, $node);
$ev_type = $iter->next;
($ev_type, $node) = $iter->next;
$ev_type = $iter->next;
($ev_type, $node) = $iter->next;
}
sub parser {
my $parser = CommonMark::Parser->new;
$parser->feed("paragraph\n\n")
for 1..5;
$parser->finish;
}
no_leaks_ok {
tree_manip();
iterate_list_context();
iterate_scalar_context();
aborted_iteration();
parser();
};
02_accessors.t 100644 001750 001750 4660 14656765207 15555 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use File::Spec::Functions qw(catfile);
use Test::More tests => 28;
BEGIN {
use_ok('CommonMark', ':all');
}
my $filename = catfile(qw(t files test.md));
open(my $file, '<', $filename)
or die("$filename: $!");
my $doc = CommonMark->parse_file($file);
close($file);
isa_ok($doc, 'CommonMark::Node', 'parse_file');
my $header = $doc->first_child;
is($header->get_type, NODE_HEADER, 'get_type');
like($header->get_type_string, qr/^head(er|ing)\z/, 'get_type_string');
is($header->get_header_level, 1, 'get_header_level');
$header->set_header_level(6);
is($header->get_header_level, 6, 'set_header_level works');
my $text = $header->first_child;
is($text->get_literal, "Header \x{263A}", 'get_literal');
$text->set_literal("New \x{263A} header");
is($text->get_literal, "New \x{263A} header", 'set_literal works');
my $ol = $header->next;
is($ol->get_list_tight, 1, 'get_list_tight');
is($ol->get_list_delim, PAREN_DELIM, 'get_list_delim');
is($ol->get_list_start, 4, 'get_list_start');
is($ol->get_list_type, ORDERED_LIST, 'get_list_type');
$ol->set_list_tight(0);
is($ol->get_list_tight, 0, 'set_list_tight works');
$ol->set_list_delim(1);
is($ol->get_list_delim, 1, 'set_list_delim works');
$ol->set_list_start(7);
is($ol->get_list_start, 7, 'set_list_start works');
$ol->set_list_type(1);
is($ol->get_list_type, 1, 'set_list_type works');
my $fenced = $ol->next;
is($fenced->get_fence_info, "perl \x{263A}", 'get_fence_info');
$fenced->set_fence_info("C \x{2639}");
is($fenced->get_fence_info, "C \x{2639}", 'set_fence_info works');
my $paragraph = $fenced->next;
is($paragraph->get_start_line, 10, 'get_start_line');
is($paragraph->get_start_column, 1, 'get_start_column');
is($paragraph->get_end_line, 10, 'get_end_line');
is($paragraph->get_end_column, 40, 'get_end_column');
my $link = $paragraph->first_child;
is($link->get_url, 'http://example.com/', 'get_url');
is($link->get_title, 'title', 'get_title');
$link->set_url('https://example.com/');
is($link->get_url, 'https://example.com/', 'set_url works');
$link->set_title('new title');
is($link->get_title, 'new title', 'set_title works');
SKIP: {
skip('Requires libcmark 0.23', 2) if CommonMark->version < 0x001700;
my $custom = CommonMark::Node->new(NODE_CUSTOM_INLINE);
$custom->set_on_enter('prefix');
is($custom->get_on_enter, 'prefix', 'get/set on_enter');
$custom->set_on_exit('suffix');
is($custom->get_on_exit, 'suffix', 'get/set on_exit');
}
lib 000755 001750 001750 0 14656765207 13237 5 ustar 00nik nik 000000 000000 CommonMark-0.310100 CommonMark.pm 100644 001750 001750 17224 14656765207 16026 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/lib use 5.008;
use strict;
use warnings;
package CommonMark;
use XSLoader;
BEGIN {
our $VERSION = '0.310100';
XSLoader::load('CommonMark', $VERSION);
}
use Exporter 'import';
our %EXPORT_TAGS = (
opt => [ qw(
OPT_DEFAULT
OPT_SOURCEPOS
OPT_HARDBREAKS
OPT_SAFE
OPT_NOBREAKS
OPT_NORMALIZE
OPT_VALIDATE_UTF8
OPT_SMART
OPT_UNSAFE
) ],
node => [ qw(
NODE_NONE
NODE_DOCUMENT
NODE_BLOCK_QUOTE
NODE_LIST
NODE_ITEM
NODE_CODE_BLOCK
NODE_HTML
NODE_PARAGRAPH
NODE_HEADER
NODE_HRULE
NODE_TEXT
NODE_SOFTBREAK
NODE_LINEBREAK
NODE_CODE
NODE_INLINE_HTML
NODE_EMPH
NODE_STRONG
NODE_LINK
NODE_IMAGE
),
# libcmark 0.23
qw(
NODE_CUSTOM_BLOCK
NODE_CUSTOM_INLINE
NODE_HTML_BLOCK
NODE_HEADING
NODE_THEMATIC_BREAK
NODE_HTML_INLINE
) ],
list => [ qw(
NO_LIST
BULLET_LIST
ORDERED_LIST
) ],
delim => [ qw(
NO_DELIM
PERIOD_DELIM
PAREN_DELIM
) ],
event => [ qw(
EVENT_NONE
EVENT_DONE
EVENT_ENTER
EVENT_EXIT
) ],
);
Exporter::export_ok_tags();
push(@{ $EXPORT_TAGS{all} }, @{ $EXPORT_TAGS{$_} }) for keys %EXPORT_TAGS;
my @option_map = (
sourcepos => OPT_SOURCEPOS,
hardbreaks => OPT_HARDBREAKS,
safe => OPT_SAFE,
nobreaks => OPT_NOBREAKS,
normalize => OPT_NORMALIZE,
validate_utf8 => OPT_VALIDATE_UTF8,
smart => OPT_SMART,
unsafe => OPT_UNSAFE,
);
sub parse {
my ($class, %opts) = @_;
my ($string, $file) = @opts{ qw(string file) };
my $parser_opts = _extract_opts(\%opts);
my $doc;
if (defined($string)) {
die("can't provide both string and file")
if defined($file);
$doc = $class->parse_document($string, $parser_opts);
}
elsif (defined($file)) {
$doc = $class->parse_file($file, $parser_opts);
}
else {
die("must provide either string or file");
}
return $doc;
}
sub _extract_opts {
my $hash = shift;
my $int = 0;
for (my $i = 0; $i < @option_map; $i += 2) {
my ($name, $val) = @option_map[$i,$i+1];
$int |= $val if $hash->{$name};
}
return $int;
}
sub create_document {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_DOCUMENT);
return _add_children($node, \%opts);
}
sub create_block_quote {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_BLOCK_QUOTE);
return _add_children($node, \%opts);
}
sub create_list {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_LIST);
my ($type, $delim, $start, $tight)
= @opts{ qw(type delim start tight) };
$node->set_list_type($type) if defined($type);
$node->set_list_delim($delim) if defined($delim);
$node->set_list_start($start) if defined($start);
$node->set_list_tight($tight) if defined($tight);
return _add_children($node, \%opts);
}
sub create_item {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_ITEM);
return _add_children($node, \%opts);
}
sub create_code_block {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_CODE_BLOCK);
my $fence_info = $opts{fence_info};
$node->set_fence_info($fence_info) if defined($fence_info);
return _add_literal($node, \%opts);
}
sub create_html_block {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_HTML);
return _add_literal($node, \%opts);
}
sub create_html { &create_html_block; }
sub create_paragraph {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_PARAGRAPH);
return _add_children_or_text($node, \%opts);
}
sub create_heading {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_HEADER);
my $level = $opts{level};
$node->set_header_level($level) if defined($level);
return _add_children_or_text($node, \%opts);
}
sub create_header { &create_heading; }
sub create_thematic_break {
return CommonMark::Node->new(NODE_HRULE);
}
sub create_hrule { &create_thematic_break; }
sub create_text {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_TEXT);
return _add_literal($node, \%opts);
}
sub create_softbreak {
return CommonMark::Node->new(NODE_SOFTBREAK);
}
sub create_linebreak {
return CommonMark::Node->new(NODE_LINEBREAK);
}
sub create_code {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_CODE);
return _add_literal($node, \%opts);
}
sub create_html_inline {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_INLINE_HTML);
return _add_literal($node, \%opts);
}
sub create_inline_html { &create_html_inline; }
sub create_emph {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_EMPH);
return _add_children_or_text($node, \%opts);
}
sub create_strong {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_STRONG);
return _add_children_or_text($node, \%opts);
}
sub create_link {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_LINK);
return _add_link_opts($node, \%opts);
}
sub create_image {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_IMAGE);
return _add_link_opts($node, \%opts);
}
sub create_custom_block {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_CUSTOM_BLOCK);
return _add_custom_opts($node, \%opts);
}
sub create_custom_inline {
my (undef, %opts) = @_;
my $node = CommonMark::Node->new(NODE_CUSTOM_INLINE);
return _add_custom_opts($node, \%opts);
}
sub _add_children {
my ($node, $opts) = @_;
my $children = $opts->{children};
if (defined($children)) {
for my $child (@$children) {
$node->append_child($child);
}
}
return $node;
}
sub _add_literal {
my ($node, $opts) = @_;
my $literal = $opts->{literal};
$node->set_literal($literal) if defined($literal);
return $node;
}
sub _add_children_or_text {
my ($node, $opts) = @_;
my $children = $opts->{children};
my $literal = $opts->{text};
if (defined($children)) {
die("can't set both children and text")
if defined($literal);
return _add_children($node, $opts);
}
if (defined($literal)) {
my $text = __PACKAGE__->create_text(literal => $literal);
$node->append_child($text);
}
return $node;
}
sub _add_link_opts {
my ($node, $opts) = @_;
my $url = $opts->{url};
my $title = $opts->{title};
$node->set_url($url) if defined($url);
$node->set_title($title) if defined($title);
return _add_children_or_text($node, $opts);
}
sub _add_custom_opts {
my ($node, $opts) = @_;
my $on_enter = $opts->{on_enter};
my $on_exit = $opts->{on_exit};
$node->set_on_enter($on_enter) if defined($on_enter);
$node->set_on_exit($on_exit) if defined($on_exit);
return _add_children_or_text($node, $opts);
}
package CommonMark::Node;
sub render {
my ($self, %opts) = @_;
my $format = $opts{format};
die("must provide format")
if !defined($format);
my $method = "render_$format";
my $render_opts = CommonMark::_extract_opts(\%opts);
if ($format =~ /^(html|xml)\z/) {
return $self->$method($render_opts);
}
if ($format =~ /^(commonmark|latex|man)\z/) {
my $width = $opts{width};
$width = 0 if !defined($width);
return $self->$method($render_opts, $width);
}
die("invalid format '$format'");
}
1;
07_tree_manip.t 100644 001750 001750 2222 14656765207 15710 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use Symbol;
use Test::More tests => 5;
BEGIN {
use_ok('CommonMark', ':node');
}
my $md = <<'EOF';
normal, *emph*, **strong**
EOF
my $doc = CommonMark->parse_document($md);
my $paragraph = $doc->first_child;
my $text = $paragraph->first_child;
my $emph = $text->next;
my $strong = $paragraph->last_child;
my $space = $strong->first_child->parent->previous;
my $expected_html = $doc->render_html;
$doc = undef;
my $result = CommonMark::Node->new(NODE_DOCUMENT);
$text->unlink;
$strong->unlink;
$result->append_child($paragraph);
$emph->insert_before($text);
$space->insert_after($strong);
is($result->render_html, $expected_html, 'tree manipulation');
for my $i (1..4) {
$paragraph->first_child->insert_before($paragraph->last_child);
}
is($result->render_html, $expected_html, 'rotate right');
for my $i (1..4) {
$paragraph->last_child->insert_after($paragraph->first_child);
}
is($result->render_html, $expected_html, 'rotate left');
$emph->replace($strong);
$space->unlink;
$expected_html = <<'EOF';
normal, strong
EOF
is($result->render_html, $expected_html, 'replace');
06_build_tree.t 100644 001750 001750 2025 14656765207 15703 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use Symbol;
use Test::More tests => 2;
BEGIN {
use_ok('CommonMark', ':node');
}
sub create_text {
my $literal = shift;
my $node = CommonMark::Node->new(NODE_TEXT);
$node->set_literal($literal);
return $node;
}
my $doc = CommonMark::Node->new(NODE_DOCUMENT);
my $paragraph = CommonMark::Node->new(NODE_PARAGRAPH);
my $emph = CommonMark::Node->new(NODE_EMPH);
my $strong = CommonMark::Node->new(NODE_STRONG);
my $normal_text = create_text('normal ');
my $emph_text = create_text('emph');
my $space = create_text(' ');
my $strong_text = create_text('strong');
$paragraph->prepend_child($emph);
$emph->append_child($emph_text);
$emph->insert_before($normal_text);
$paragraph->append_child($strong);
$doc->prepend_child($paragraph);
$strong->append_child($space);
$emph->insert_after($space);
$strong->append_child($strong_text);
my $expected_html = <normal emph strong
EOF
is($doc->render_html, $expected_html, 'build tree');
CommonMark.pod 100644 001750 001750 23752 14656765207 16177 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/lib =head1 NAME
CommonMark - Interface to the CommonMark C library
=head1 SYNOPSIS
use CommonMark;
my $doc = CommonMark->parse(
file => $file,
smart => 1,
);
my $html = CommonMark->markdown_to_html($markdown);
my $doc = CommonMark->parse_file($file);
my $doc = CommonMark->parse_document($markdown);
my $doc = CommonMark->create_document;
=head1 DESCRIPTION
This module is a wrapper around the official CommonMark C library
L|https://github.com/commonmark/cmark/>. It closely follows the
original API.
The main module provides some entry points to parse documents and convenience
functions for node creation. The bulk of features is available through
L objects of which the parse tree is made.
L is a useful class to walk through the nodes in a
tree. L provides a push parser interface.
=head2 Installation
=head3 Installation of libcmark
Please note that the I API isn't stable yet. This version of the
Perl bindings is known to work with all releases between 0.21.0 and 0.31.1,
but there's no guarantee that it can be compiled with later versions. Also
note that upgrading a dynamically linked version of I may require
recompilation of the Perl distribution.
It is recommended to use the I packages provided by recent Linux
distros. On Debian or Ubuntu, run:
sudo apt-get install libcmark-dev
On Red Hat or CentOS, run:
sudo yum install cmark-devel
On macOS using L, run:
brew install cmark
To install I from source:
curl -LJO https://github.com/commonmark/cmark/archive/0.31.1.tar.gz
tar xzf cmark-0.31.1.tar.gz
cd cmark-0.31.1
make [INSTALL_PREFIX=/prefix]
make test
make install
See the I README for details.
=head3 Installation from a CPAN tarball
If I is in a standard location:
perl Makefile.PL
make
make test
make install
On macOS using Homebrew, specify the include and library locations:
perl Makefile.PL \
INC="-I$(brew --prefix)/include" \
LIBS="-L$(brew --prefix)/lib -lcmark"
make
make test
make install
Otherwise, specify the include and library locations:
perl Makefile.PL \
INC="-I/prefix/include" \
LIBS="-L/prefix/lib -lcmark"
make
make test
make install
See the documentation of I for additional options.
The I environment variable is especially useful.
export PERL_MM_OPT='INC="-I..." LIBS="-L... -lcmark"'
=head3 Build from a repository checkout
This distribution uses I with the external plugins
I and I. You can build and test with
I:
dzil test
dzil build
The files generated by I are included in the repository,
so you can use the standard build process as well.
=head2 markdown_to_html
my $html = CommonMark->markdown_to_html( $markdown, [$options] );
Converts a Markdown string to HTML. C<$options> is a bit field
containing the L and
L ORed together. It defaults
to zero (C).
This method is the equivalent to calling C and then
L|CommonMark::Node/C> on the resulting document,
or calling C and then L|CommonMark::Node/C>:
my $html = CommonMark->markdown_to_html( $markdown );
my $html = CommonMark->parse_document($markdown)->render_html;
my $html = CommonMark->parse(string => $markdown)->render(format => 'html');
Equivalent calls with parser and rendering options, which can all be passed
to C but must be sent separately to the parse and render
methods:
my $html = CommonMark->markdown_to_html(
$markdown,
OPT_UNSAFE | OPT_SMART,
);
my $html = CommonMark->parse_document(
$markdown, OPT_SMART,
)->render_html(OPT_UNSAFE);
my $html = CommonMark->parse(
string => $markdown,
smart => 1,
)->render(
format => 'html',
unsafe => 1,
);
=head2 parse
my $doc = CommonMark->parse(
string => $string,
normalize => $bool, # Optional
smart => $bool, # Optional
validate_utf8 => $bool, # Optional
);
my $doc = CommonMark->parse(
file => $handle,
normalize => $bool, # Optional
smart => $bool, # Optional
validate_utf8 => $bool, # Optional
);
Convenience function to parse documents. Exactly one of the C or
C options must be provided. When given a string, calls
L. When given a file, calls L. The remaining
options enable the respective L:
=over
=item * C
=item * C
=item * C (no-op as of libcmark 0.28)
=back
Returns the L of the root document.
=head2 parse_document
my $doc = CommonMark->parse_document( $markdown, [$options] )
Parses a CommonMark document from a string returning the L
of the document root. C<$options> is a bit field containing the parser
options. It defaults to zero (C).
=head2 parse_file
my $doc = CommonMark->parse_file( $file, [$options] );
Parses a CommonMark document from a file handle returning the
L of the document root. C<$options> is a bit field
containing the parser options. It defaults to zero (C).
=head2 Parser options
The parser and rendering options are a bit field created by ORing the
following constants:
CommonMark::OPT_DEFAULT => 0
CommonMark::OPT_NORMALIZE
CommonMark::OPT_VALIDATE_UTF8
CommonMark::OPT_SMART
Parser options can be imported from L with tag C.
use CommonMark qw(:opt);
my $doc = CommonMark->parse_document(
$markdown,
OPT_SMART | OPT_VALIDATE_UTF8,
);
=over
=item C
Makes sure that adjacent text nodes are merged in the parse tree. This option
has no effect with libcmark 0.28 or higher which always normalizes text nodes.
=item C
Enables the "smart quote" feature which turns vertical into typographic
quotation marks, double and triple hyphens into en and em dashes, and triple
periods into ellipses.
=item C
Turns on UTF-8 validation. Normally, this shouldn't be necessary because Perl
strings should always contain valid UTF-8. But it is possible to create
strings flagged as UTF-8 that contain invalid UTF-8, for example with XS. The
option may be used if you don't trust the input data and want to make
absolutely sure that the output is valid UTF-8. If invalid bytes are found,
they are replaced with the Unicode replacement character C.
=back
=head2 Node creation
my $document = CommonMark->create_document(
children => \@children,
);
my $header = CommonMark->create_heading(
level => $level,
children => \@children,
text => $literal,
);
my $paragraph = CommonMark->create_paragraph(
children => \@children,
text => $literal,
);
my $block_quote = CommonMark->create_block_quote(
children => \@children,
);
my $list = CommonMark->create_list(
type => $type,
delim => $delim,
start => $start,
tight => $tight,
children => \@children,
);
my $item = CommonMark->create_item(
children => \@children,
);
my $code_block = CommonMark->create_code_block(
fence_info => $fence_info,
literal => $literal,
);
my $html = CommonMark->create_html_block(
literal => $html,
);
my $custom_block = CommonMark->create_custom_block(
on_enter => $raw_prefix,
on_exit => $raw_suffix,
children => \@children,
text => $literal,
);
my $thematic_break = CommonMark->create_thematic_break;
my $text = CommonMark->create_text(
literal => $literal,
);
my $code = CommonMark->create_code(
literal => $literal,
);
my $html_inline = CommonMark->create_html_inline(
literal => $literal,
);
my $emph = CommonMark->create_emph(
children => \@children,
text => $literal,
);
my $strong = CommonMark->create_strong(
children => \@children,
text => $literal,
);
my $url = CommonMark->create_url(
url => $url,
title => $title,
children => \@children,
text => $literal,
);
my $image = CommonMark->create_image(
url => $url,
title => $title,
children => \@children,
text => $literal,
);
my $custom_inline = CommonMark->create_custom_inline(
on_enter => $raw_prefix,
on_exit => $raw_suffix,
children => \@children,
text => $literal,
);
my $softbreak = CommonMark->create_softbreak;
my $linebreak = CommonMark->create_linebreak;
These convenience functions can be used to create nodes, set properties,
and add children in a single operation. All parameters are optional.
The C parameter expects an arrayref of nodes to be added as
children. The special C parameter adds a single text child with
literal C<$literal>. It can't be used together with C. All other
parameters correspond to a node property.
=head2 libcmark version information
my $version = CommonMark->version;
my $string = CommonMark->version_string;
my $version = CommonMark->compile_time_version;
my $string = CommonMark->compile_time_version_string;
Return the version number or version string of libcmark, either the
library version linked against at run time or compile time.
=head1 COPYRIGHT
This software is copyright (C) by Nick Wellnhofer.
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
author-pod-syntax.t 100644 001750 001750 454 14656765207 16652 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t #!perl
BEGIN {
unless ($ENV{AUTHOR_TESTING}) {
print qq{1..0 # SKIP these tests are for testing by the author\n};
exit
}
}
# This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests.
use strict; use warnings;
use Test::More;
use Test::Pod 1.41;
all_pod_files_ok();
08_create_helpers.t 100644 001750 001750 11364 14656765207 16602 0 ustar 00nik nik 000000 000000 CommonMark-0.310100/t use strict;
use warnings;
use Symbol;
use Test::More tests => 4;
BEGIN {
use_ok('CommonMark', ':opt', ':list', ':delim');
}
my $doc = CommonMark->create_document(
children => [
CommonMark->create_header(
level => 2,
children => [
CommonMark->create_text(
literal => 'Header',
),
],
),
CommonMark->create_block_quote(
children => [
CommonMark->create_paragraph(
text => 'Block quote',
),
],
),
CommonMark->create_list(
type => ORDERED_LIST,
delim => PAREN_DELIM,
start => 2,
tight => 1,
children => [
CommonMark->create_item(
children => [
CommonMark->create_paragraph(
text => 'Item 1',
),
],
),
CommonMark->create_item(
children => [
CommonMark->create_paragraph(
text => 'Item 2',
),
],
),
],
),
CommonMark->create_code_block(
literal => 'Code block',
),
CommonMark->create_html(
literal => 'html