summaryrefslogtreecommitdiffstats
path: root/Bugzilla/Markdown/GFM.pm
blob: 367dc7a53e68ce2a2342b1646a0daa8e124dbd9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package Bugzilla::Markdown::GFM;

use 5.10.1;
use strict;
use warnings;

use Alien::libcmark_gfm;
use FFI::Platypus;
use FFI::Platypus::Buffer qw( scalar_to_buffer buffer_to_scalar );
use Exporter qw(import);

use Bugzilla::Markdown::GFM::SyntaxExtension;
use Bugzilla::Markdown::GFM::SyntaxExtensionList;
use Bugzilla::Markdown::GFM::Parser;
use Bugzilla::Markdown::GFM::Node;

our @EXPORT_OK = qw(cmark_markdown_to_html);

my %OPTIONS = (
    default                       => 0,
    sourcepos                     => ( 1 << 1 ),
    hardbreaks                    => ( 1 << 2 ),
    safe                          => ( 1 << 3 ),
    nobreaks                      => ( 1 << 4 ),
    normalize                     => ( 1 << 8 ),
    validate_utf8                 => ( 1 << 9 ),
    smart                         => ( 1 << 10 ),
    github_pre_lang               => ( 1 << 11 ),
    liberal_html_tag              => ( 1 << 12 ),
    footnotes                     => ( 1 << 13 ),
    strikethrough_double_tilde    => ( 1 << 14 ),
    table_prefer_style_attributes => ( 1 << 15 ),
);

my $FFI = FFI::Platypus->new(
    lib => [grep { not -l $_ } Alien::libcmark_gfm->dynamic_libs],
);

$FFI->custom_type(
    markdown_options_t => {
        native_type => 'int',
        native_to_perl => sub {
            my ($options) = @_;
            my $result = {};
            foreach my $key (keys %OPTIONS) {
                $result->{$key} = ($options & $OPTIONS{$key}) != 0;
            }
            return $result;
        },
        perl_to_native => sub {
            my ($options) = @_;
            my $result = 0;
            foreach my $key (keys %OPTIONS) {
                if ($options->{$key}) {
                    $result |= $OPTIONS{$key};
                }
            }
            return $result;
        }
    }
);

$FFI->attach(cmark_markdown_to_html => ['opaque', 'int', 'markdown_options_t'] => 'string',
    sub {
        my $c_func = shift;
         my($markdown, $markdown_length) = scalar_to_buffer $_[0];
         return $c_func->($markdown, $markdown_length, $_[1]);
    }
);

# This has to happen after something from the main lib is loaded
$FFI->attach('cmark_gfm_core_extensions_ensure_registered' => [] => 'void');

cmark_gfm_core_extensions_ensure_registered();

Bugzilla::Markdown::GFM::SyntaxExtension->SETUP($FFI);
Bugzilla::Markdown::GFM::SyntaxExtensionList->SETUP($FFI);
Bugzilla::Markdown::GFM::Node->SETUP($FFI);
Bugzilla::Markdown::GFM::Parser->SETUP($FFI);

1;

__END__

=head1 NAME

Bugzilla::Markdown::GFM - Sets up the FFI to libcmark_gfm.

=head1 DESCRIPTION

This modules mainly just does setup work. See L<Bugzilla::Markdown::GFM::Parser>
to actually render markdown to html.