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

Extension support #29

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
9 changes: 8 additions & 1 deletion bin/plerdwatcher
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,17 @@ my $plerd;
my $watcher;
try {
$plerd = Plerd->new( $config_ref );
my $filter;

my $trigger = defined (keys %{$plerd->post_triggers})
? sprintf '\.(md|markdown|%s)$', join('|', keys %{$plerd->post_triggers})
: '\.(md|markdown)$';

$filter = qr/$trigger/;

$watcher = File::ChangeNotify->instantiate_watcher (
directories => [ $plerd->source_directory . '' ],
filter => qr/\.(md|markdown)$/,
filter => $filter,
);
}
catch {
Expand Down
3 changes: 2 additions & 1 deletion cpanfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ requires 'Try::Tiny';
requires 'HTML::Strip';
requires 'HTML::SocialMeta' => '0.72';
requires 'List::Util' => '1.45';
requires 'Module::Load';
requires 'Readonly';
requires 'Web::Mention' => '0.6';
requires 'Web::Mention' => '0.6';
requires 'Mojolicious::Lite';
81 changes: 74 additions & 7 deletions lib/Plerd.pm
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use URI;
use Carp;
use Try::Tiny;

use Module::Load;

use Plerd::Post;
use Plerd::WebmentionQueue;

Expand Down Expand Up @@ -257,6 +259,23 @@ has 'tags_map' => (
clearer => 'clear_tags_map',
);

has 'extensions' => (
is => 'ro',
isa => 'Maybe[ArrayRef[Str]]'
);

has 'extension_preferences' => (
is => 'ro',
isa => 'Maybe[HashRef]',
);

has 'post_triggers' => (
is => 'ro',
isa => 'Maybe[HashRef[Str]]',
lazy_build => 1,
);


sub BUILD {
my $self = shift;

Expand All @@ -273,6 +292,16 @@ sub BUILD {
}
}

foreach my $extension (@{$self->extensions // []}) {
try {
load $extension;
}
catch {
my $error = shift || "Unknown error";
die "Can't load extension: '$extension': $error\n";
};
}

return $self;
}

Expand Down Expand Up @@ -609,15 +638,24 @@ sub _build_recent_posts {

sub _build_posts {
my $self = shift;
my @posts;
my $triggers = $self->post_triggers;

foreach my $file (sort { $a->basename cmp $b->basename } $self->source_directory->children) {
if ($file =~ m/\.(?:markdown|md)$/) {
push @posts, Plerd::Post->new( plerd => $self, source_file => $file )
} else {
foreach my $trigger (keys %{$triggers}) {
if ($file =~ m/\.$trigger$/i) {
push @posts, $$triggers{$trigger}->new(plerd => $self, source_file => $file);
last;
}
}
}
}

my @posts = sort { $b->date <=> $a->date }
map { Plerd::Post->new( plerd => $self, source_file => $_ ) }
sort { $a->basename cmp $b->basename }
grep { /\.markdown$|\.md$/ }
$self->source_directory->children
;
return [sort { $b->date <=> $a->date } @posts];

return \@posts;
}

sub _build_index_of_post_with_guid {
Expand Down Expand Up @@ -664,6 +702,19 @@ sub _throw_template_exception {
. "template file $template_file: $error\n";
}

sub _build_post_triggers {
my $self = shift;
my %triggers;

foreach my $classref (@{$self->extensions // []}){
if ($classref->can('file_type')) {
$triggers{ $classref->file_type } = $classref;
}
}

return \%triggers;
}

sub generates_post_guids {
carp "generates_post_guids() is deprecated. (Also, it doesn't do anything "
. "anyway.)";
Expand Down Expand Up @@ -954,6 +1005,22 @@ tag index HTML files.
This is a L<URI> object that points to the tag index. It is
particularly helpful when creating navigation.

=item extensions

An arrayref of strings, representing the plugins to load when a new Plerd
instance is created.

=item extension_preferences

A hashref of config options for extensions. It is up to each individual extension
to decide how to act upon the contents therein.

=item post_triggers

A hashref that maps extensions to file types. The key is used as a regex to deduce what
source file types the particular Post extension using to render pages.
The value is a reference to that particular extension.

=back

=head1 OBJECT METHODS
Expand Down
28 changes: 26 additions & 2 deletions t/basic.t
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use DateTime;

use FindBin;
use lib "$FindBin::Bin/../lib";
use lib "$FindBin::Bin/lib";

use_ok( 'Plerd' );

Expand Down Expand Up @@ -54,9 +55,10 @@ unlink "$FindBin::Bin/source/no-title.md";

$plerd->publish_all;

# The "+5" below accounts for the generated recent, archive, and RSS files,
# The "+4" below accounts for the generated recent, archive, and RSS files,
# a index.html symlink, and a tags directory.
my $expected_docroot_count = scalar( $source_dir->children( no_hidden => 1 ) ) + 5;
my $expected_docroot_count = scalar( $source_dir->children( no_hidden => 1 ) ) + 4;

is( scalar( $docroot_dir->children ),
$expected_docroot_count,
"Correct number of files generated in docroot."
Expand Down Expand Up @@ -331,6 +333,28 @@ like( $post,
'Metatags: Defined default alt-text',
);

}
{
### Test extension-support
my $extension_plerd = Plerd->new(
path => $FindBin::Bin,
title => 'Test Blog',
author_name => 'Nobody',
author_email => 'nobody@example.com',
extensions => ['TestExtension'],
base_uri => URI->new ( 'http://blog.example.com/' ),
image => URI->new ( 'http://blog.example.com/logo.png' ),

);

$extension_plerd->publish_all;

my $post = Path::Class::File->new( $docroot_dir, "$ymd-a-very-special-source-file.html" )->slurp;
like( $post,
qr{.sdrawkcab dm. si hcihw md.},
'Extensions: Plerd can publish with extensions',
);

}

done_testing();
68 changes: 68 additions & 0 deletions t/lib/TestExtension.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package TestExtension;
Copy link
Owner

Choose a reason for hiding this comment

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

Could you please expand this TextExtension module so that it actually writes a file into the docroot, based on the source file that it reads? That will allow the tests to pass without needing to modify the "+4" magic number (which is has changed to "+5" in more recent master-branch work, anyway) and would also serve to demonstrate a little more clearly how an extension might actually work in practice.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Aha! It does actually publish a file to the docroot, but it doesn't do that until the test extension is explicitly loaded into plerd, thats's at line 344, and you'll find the assert further down that it actually does publish a file, even though the source file was .dm.

But you are right that it's sort of a no-op. Let me see if I can make it do something more interesting.

use Plerd::Post;
use Moose;
use strict;

use 5.010;

use warnings FATAL => 'all';

extends "Plerd::Post";

sub file_type {
'dm';
}

around 'body' => sub {
my $orig = shift;
my $self = shift;
if (@_){
# "Setter"
my $body = shift;

# first time body is called, reverse it!
$body = reverse $body unless $self->$orig;

$self->$orig($body);
} else {
# "Getter"
$self->$orig();
}
};

1;


=head1 NAME

TestExtension - A L<Plerd::Post> extension to showcase the extension capabilities of L<Plerd>.

=head1 DESCRIPTION

This extension doesn't do anything truly useful. It's sole purpose is showcasing the extension capabilities.

What it does in fact do, though, is reversing the body of the document (the first time it's set).

It's rather useless.

=head1 OBJECT ATTRIBUTES

=head2 Read-only attributes, set during construction

=over

=item file_type

A regex-compatible string which indicate what file types to associate with the Extension.
This is set to "dm" (which happens to be "md" spelled backwards)

=item body

The original L<Plerd::Post> body, except that the first time this attribute is set, it gets reversed.

=back

=head2 Other attributes

All other attributes are inherited from L<Plerd::Post> Please consult that documentation for their docs.

4 changes: 4 additions & 0 deletions t/source_model/extension.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
title: A very special source file


It's only special because it's file type is .dm which is .md backwards. This is to see if it gets processed by an extension.