diff --git a/Changes b/Changes
index c5dd6a0..65eab37 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,9 @@
Revision history for pmarkdown and the Markdown::Perl module.
+1.08 - ?
+
+ - Add a new yaml_metadata hook to receive the parsed YAML.
+
1.07 - 2024-05-25
- Allow to specify a link content through the resolve_link_ref hook.
diff --git a/lib/Markdown/Perl.pm b/lib/Markdown/Perl.pm
index cb8d777..1722666 100644
--- a/lib/Markdown/Perl.pm
+++ b/lib/Markdown/Perl.pm
@@ -50,7 +50,7 @@ sub set_mode {
return;
}
-Readonly::Array my @VALID_HOOKS => qw(resolve_link_ref);
+Readonly::Array my @VALID_HOOKS => qw(resolve_link_ref yaml_metadata);
sub set_hooks {
my ($this, %hooks) = &_get_this_and_args; ## no critic (ProhibitAmpersandSigils)
@@ -324,6 +324,13 @@ optionally a C
key containing the title of the key. The hash-ref can also
contain a C key, in which case its value should be a span of HTML which
will replace whatever would have been used for the link content.
+=item *
+
+C: this hook will trigger if there is valid (!) YAML metadata in
+the file and will give you a hashref as an argument. If the hook throws a die(),
+the Markdown parsing will stop as the die() needs to be handled by your code.
+This allows for conditional parsing based on values in the metadata section.
+
=back
=head1 AUTHOR
diff --git a/lib/Markdown/Perl/BlockParser.pm b/lib/Markdown/Perl/BlockParser.pm
index f72de83..7374ad5 100644
--- a/lib/Markdown/Perl/BlockParser.pm
+++ b/lib/Markdown/Perl/BlockParser.pm
@@ -137,7 +137,6 @@ sub process {
# Done at a later stage, as escaped characters don’t have their Markdown
# meaning, we need a way to represent that.
- # Note: for now, nothing is done with the extracted metadata.
$this->_parse_yaml_metadata() if $this->get_parse_file_metadata eq 'yaml';
while (defined (my $l = $this->next_line())) {
@@ -372,11 +371,14 @@ sub _parse_yaml_metadata {
my $metadata = eval { YAML::Tiny->read_string($+{YAML}) };
if ($EVAL_ERROR) {
pos($this->{md}) = 0;
- return;
+ carp 'YAML Metadata (Markdown frontmatter) is invalid.';
+ return 1;
+ }
+ if(exists($this->{pmarkdown}{hooks}{yaml_metadata})) {
+ $this->{pmarkdown}{hooks}{yaml_metadata}->($metadata->[0]);
}
}
-
- return;
+ return 1;
}
# https://spec.commonmark.org/0.30/#atx-headings
diff --git a/lib/Markdown/Perl/Options.pm b/lib/Markdown/Perl/Options.pm
index 127c771..bde11c4 100644
--- a/lib/Markdown/Perl/Options.pm
+++ b/lib/Markdown/Perl/Options.pm
@@ -181,9 +181,8 @@ sub _word_list {
=head3 B I<(enum, default: yaml)>
This option controls whether the parser accepts optional metadata at the
-beginning of the file. Currently, it does nothing with these metadata, even when
-they are accepted. In the future they might be used to build complete HTML file
-instead of just fragment.
+beginning of the file. The module does nothing with the metadata itself but you
+can configure a hook to intercept the YAML.
The possible values are:
diff --git a/t/501-hooks-yaml-metadata.t b/t/501-hooks-yaml-metadata.t
new file mode 100644
index 0000000..17c6955
--- /dev/null
+++ b/t/501-hooks-yaml-metadata.t
@@ -0,0 +1,71 @@
+use strict;
+use warnings;
+use utf8;
+
+use Markdown::Perl 'convert', 'set_hooks';
+use Test::More;
+use Test2::Tools::Warnings;
+use Test2::Tools::Exception;
+
+my $p = Markdown::Perl->new();
+my $page = <{name}) && $x->{name} eq 'Mark is down', "key 'name' was retrieved and validated as being 'Mark is down'");
+ }
+ $p->set_hooks(yaml_metadata => \&hook_is_name_mark);
+ $p->convert($page);
+}
+
+# Test 2: Validate that hook is not called if yaml is invalid
+{
+ my $hook_called = 0;
+ sub hook_called {
+ $hook_called = 1;
+ }
+ $p->set_hooks(yaml_metadata => \&hook_called);
+ ok(!$hook_called, "Hook was not called because metadata was invalid.");
+ $p->convert($invalid_page);
+}
+
+# Test 3: Validate that invalid yaml causes a carp()
+{
+ sub hook {
+ }
+ $p->set_hooks(yaml_metadata => \&hook);
+ like(warning { $p->convert($invalid_page) }, qr/invalid/, "Got expected warning");
+}
+
+# Test 4: What happens if inside the hook we die()
+{
+ sub hook_die {
+ die "last words";
+ }
+ $p->set_hooks(yaml_metadata => \&hook_die);
+ like( dies { $p->convert($page) }, qr/last words/, "The hook correctly died.");
+}
+
+done_testing;