package Bugzilla::Markdown::GFM::Parser; use 5.10.1; use strict; use warnings; use FFI::Platypus::Buffer qw( scalar_to_buffer buffer_to_scalar ); sub new { my ($class, $options) = @_; my $extensions = delete $options->{extensions} // []; my $parser = $class->_new($options); $parser->{_options} = $options; eval { foreach my $name (@$extensions) { my $extension = Bugzilla::Markdown::GFM::SyntaxExtension->find($name) or die "unknown extension: $name"; $parser->attach_syntax_extension($extension); } }; return $parser; } sub render_html { my ($self, $markdown) = @_; $self->feed($markdown); my $node = $self->finish; return $node->render_html($self->{_options}, $self->get_syntax_extensions); } sub SETUP { my ($class, $FFI) = @_; $FFI->custom_type( markdown_parser_t => { native_type => 'opaque', native_to_perl => sub { bless { _pointer => $_[0] }, $class; }, perl_to_native => sub { $_[0]->{_pointer} }, } ); $FFI->attach( [ cmark_parser_new => '_new' ], [ 'markdown_options_t' ] => 'markdown_parser_t', sub { my $c_func = shift; return $c_func->($_[1]); } ); $FFI->attach( [ cmark_parser_free => 'DESTROY' ], [ 'markdown_parser_t' ] => 'void' ); $FFI->attach( [ cmark_parser_feed => 'feed'], ['markdown_parser_t', 'opaque', 'int'] => 'void', sub { my $c_func = shift; $c_func->($_[0], scalar_to_buffer $_[1]); } ); $FFI->attach( [ cmark_parser_finish => 'finish' ], [ 'markdown_parser_t' ] => 'markdown_node_t', ); $FFI->attach( [ cmark_parser_attach_syntax_extension => 'attach_syntax_extension' ], [ 'markdown_parser_t', 'markdown_syntax_extension_t' ] => 'void', ); $FFI->attach( [ cmark_parser_get_syntax_extensions => 'get_syntax_extensions' ], [ 'markdown_parser_t' ] => 'markdown_syntax_extension_list_t', ); } 1; __END__ =head1 NAME Bugzilla::Markdown::GFM::Parser - Transforms markdown into HTML via libcmark_gfm. =head1 SYNOPSIS use Bugzilla::Markdown::GFM; use Bugzilla::Markdown::GFM::Parser; my $parser = Bugzilla::Markdown::GFM::Parser->new({ extensions => [qw( autolink tagfilter table strikethrough )] }); say $parser->render_html(<<'MARKDOWN'); # My header This is **markdown**! - list item 1 - list item 2 MARKDOWN