Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement yaml metadata hook #3

Merged
merged 7 commits into from
Oct 30, 2024
Merged

Conversation

adriaandens
Copy link
Contributor

I'm using your module in a personal project where I need to parse Markdown files and would find it useful if I can (ab)use your Perl module to do the metadata parsing. As for now I need to make my own little subroutine to read the markdown file, extract the yaml and pass it to a yaml parser, to then pass it to the Markdown::Perl converter.

Since you already make a hooks implementation, I added the functionality as a hook that can be called.

TODO (this is a note for myself):

  • Update docs and notes where it says that the metadata is unused
  • Allow the return value of the hook to decide whether parsingof the Markdown document should continue or not (handy if you want to filter through a huge list of markdown files but only want to parse files with a certain YAML key set)
  • Gather feedback

Copy link
Owner

@mkende mkende left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR, I was indeed considering adding something like that. Please add a new entry in the Changes file:

1.08 - ????

 - Add a new yaml_metadata hook to receive the parsed YAML.

lib/Markdown/Perl.pm Outdated Show resolved Hide resolved
lib/Markdown/Perl/BlockParser.pm Outdated Show resolved Hide resolved
$p->convert($page);
}

# Test 2: Validate that hook is not called if yaml is invalid
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you missing this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, i forgot to git add the test file.
I also tried adding tests for the carp behaviour with Test::Carp but somehow that causes a different codepath to be taken and does not give the expected result whatever I try. :(

For example below, for unknown reasons to me, it does not call the hook (but if i run it as $p->convert($page) it does).

# Test 4: What happens if inside the hook we die()
use Test::Carp;

{
  sub hook_die {
    print "Dying ongoing...\n";
    die "We just die\n";
  }
  $p->set_hooks(yaml_metadata => \&hook_die);
  does_carp_that_matches($p->can("convert"), $page, qr/Hook.+crash/);
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect that this is because Test::Carp is incompatible with Test2 (so the hook is called but not caught by the test util). Instead you can use Test2::Tools::Warnings (which I believe is already included automatically by Test2::V0.

Also it might be because I expect that the current code dies in the call to convert because it’s dereferencing an undef $blocks returned by _parse (this will problem will go away once the exception is just propagated to the caller).

lib/Markdown/Perl/BlockParser.pm Show resolved Hide resolved
lib/Markdown/Perl.pm Outdated Show resolved Hide resolved
$p->convert($page);
}

# Test 2: Validate that hook is not called if yaml is invalid
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect that this is because Test::Carp is incompatible with Test2 (so the hook is called but not caught by the test util). Instead you can use Test2::Tools::Warnings (which I believe is already included automatically by Test2::V0.

Also it might be because I expect that the current code dies in the call to convert because it’s dereferencing an undef $blocks returned by _parse (this will problem will go away once the exception is just propagated to the caller).

lib/Markdown/Perl/BlockParser.pm Outdated Show resolved Hide resolved
t/501-hooks-yaml-metadata.t Outdated Show resolved Hide resolved
lib/Markdown/Perl/BlockParser.pm Outdated Show resolved Hide resolved
@mkende
Copy link
Owner

mkende commented Oct 28, 2024

As a side note, do you mind describing the projects for which you’re using this module?

@adriaandens
Copy link
Contributor Author

As a side note, do you mind describing the projects for which you’re using this module?

I'm building my own internal wiki/notes/kb with Dancer2 with the intention of migrating away from my existing Dokuwiki setup. I have around a 1000 pages in wiki format on that wiki instance and I will convert all of them to Markdown and then have this module do the heavy lifting of generating HTML from the Markdown. To maintain a simple implementation, I intend to store everything as plaintext Markdown on disk (one of the reasons I like(d) Dokuwiki is that is stores all wiki pages as a plaintext file and i don't need a DB) and having certain API calls read the YAML metadata of those files (to parse tags, page titles, ...) without doing the Markdown parsing will (probably) speed up the application. I'll also make handy use of the other existing hook to resolve links to other wiki pages as Dokuwiki uses [[pagename]] for relative links in the wiki and I'll maintain that format (as [pagename] to trigger the hook).

If you want to know more, I'm also on the perl IRC. Happy to have a chat. :)

@@ -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;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can revert this line and line 381 to just return.

die "last words";
}
$p->set_hooks(yaml_metadata => \&hook_die);
my $eval_result = eval { $p->convert($page) };
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could use Test2::Tools::Exception for that.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you can just fix that, I’ll merge the PR and upload a new release to CPAN.

@mkende
Copy link
Owner

mkende commented Oct 29, 2024

I'm building my own internal wiki/notes/kb with Dancer2 with the intention of migrating away from my existing Dokuwiki setup.

Ah, pmarkdown was written to support my own personal wiki/notes/kb written with ... Mojolicious. It’s available here although it’s not really ready for public use.

I'll also make handy use of the other existing hook to resolve links to other wiki pages as Dokuwiki uses [[pagename]] for relative links in the wiki and I'll maintain that format (as [pagename] to trigger the hook).

Nice, I hadn’t thought of that option when the hook was implemented.

@mkende mkende merged commit 724851e into mkende:main Oct 30, 2024
@mkende
Copy link
Owner

mkende commented Oct 30, 2024

Thanks for the PR, I have just pushed version 1.08 to CPAN with your new hook.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants