Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

page rendering support

  • Loading branch information...
commit ca023038e3633ca7e54f38f9fc1387e6aeb30426 1 parent 6f866e2
@typester authored
Showing with 1,266 additions and 482 deletions.
  1. +1 −1  Changes
  2. +0 −26 MANIFEST
  3. +4 −0 Makefile.PL
  4. +54 −26 bin/nim
  5. +79 −94 lib/Nim.pm
  6. +16 −25 lib/Nim/Config.pm
  7. +48 −84 lib/Nim/Entry.pm
  8. +10 −10 lib/Nim/Log.pm
  9. +43 −0 lib/Nim/Operator.pm
  10. +28 −0 lib/Nim/Page.pm
  11. +26 −2 lib/Nim/Plugin.pm
  12. +94 −0 lib/Nim/Plugin/AutoIndex.pm
  13. +22 −0 lib/Nim/Plugin/Default.pm
  14. +164 −0 lib/Nim/Plugin/Entry/Clmemo.pm
  15. +63 −0 lib/Nim/Plugin/Entry/File.pm
  16. +0 −35 lib/Nim/Plugin/EntryLoader.pm
  17. +0 −60 lib/Nim/Plugin/Filter/Markdown.pm
  18. +56 −0 lib/Nim/Plugin/Index.pm
  19. +36 −0 lib/Nim/Plugin/Markdown.pm
  20. +65 −0 lib/Nim/Plugin/Meta.pm
  21. +88 −0 lib/Nim/Plugin/Paginate.pm
  22. +49 −15 lib/Nim/Plugin/Render/Entry.pm
  23. +65 −0 lib/Nim/Plugin/TagIndex.pm
  24. +119 −0 lib/Nim/Plugin/Template/MicroTemplate.pm
  25. +0 −38 lib/Nim/Plugin/Template/TT.pm
  26. +0 −41 lib/Nim/Plugin/TemplateLoader/Single.pm
  27. +21 −0 lib/Nim/Rule.pm
  28. +8 −0 lib/Nim/Rule/Always.pm
  29. +41 −0 lib/Nim/Rule/Expression.pm
  30. +36 −0 lib/Nim/Rules.pm
  31. +20 −0 lib/Nim/Types.pm
  32. +0 −25 lib/Nim/Types/Path/Class.pm
  33. 0  {t → xt}/pod.t
  34. 0  {t → xt}/pod_coverage.t
  35. +10 −0 xt/pod_spell.t
View
2  Changes
@@ -1,4 +1,4 @@
Revision history for Perl extension Nim
- 0.01 Wed Jan 14 10:31:43 2009
+ 0.01 Thu Nov 5 20:48:07 2009
- original version
View
26 MANIFEST
@@ -1,26 +0,0 @@
-Changes
-inc/Module/Install.pm
-inc/Module/Install/Base.pm
-inc/Module/Install/Can.pm
-inc/Module/Install/Fetch.pm
-inc/Module/Install/Include.pm
-inc/Module/Install/Makefile.pm
-inc/Module/Install/Metadata.pm
-inc/Module/Install/TestBase.pm
-inc/Module/Install/Win32.pm
-inc/Module/Install/WriteAll.pm
-inc/Spiffy.pm
-inc/Test/Base.pm
-inc/Test/Base/Filter.pm
-inc/Test/Builder.pm
-inc/Test/Builder/Module.pm
-inc/Test/More.pm
-lib/Nim.pm
-LICENSE
-Makefile.PL
-MANIFEST This list of files
-META.yml
-README
-t/00_compile.t
-t/pod.t
-t/pod_coverage.t
View
4 Makefile.PL
@@ -4,5 +4,9 @@ all_from 'lib/Nim.pm';
test_requires 'Test::More';
use_test_base;
+author_tests('xt');
+
auto_include;
+auto_set_repository;
+
WriteAll;
View
80 bin/nim
@@ -9,37 +9,65 @@ use Getopt::Long;
use Nim;
+use Carp;
+
+local $SIG{__DIE__} = sub { Carp::confess(@_) };
+
GetOptions(
\my %options,
- qw/help flavour=s debug/
+ qw/help server port=i host=s/
);
pod2usage(0) if $options{help};
my $nim = Nim->new;
$nim->run;
-__END__
-
-=head1 NAME
-
-nim - minimal command-line based contents generator
-
-=head1 SYNOPSIS
-
- nim [options]
-
-=head1 AUTHOR
-
-Daisuke Murase <typester@cpan.org>
-
-=head1 COPYRIGHT & LICENSE
-
-Copyright (c) 2009 KAYAC Inc. All rights reserved.
-
-This program is free software; you can redistribute
-it and/or modify it under the same terms as Perl itself.
-
-The full text of the license can be found in the
-LICENSE file included with this module.
-
-=cut
+# delay the build process for reloader
+sub build(&;$) {
+ my $block = shift;
+ my $app = shift || sub { };
+ return sub { $block->($app->()) };
+}
+
+if ($options{server}) {
+ $nim->log->info('Starting build-in server');
+
+ my $handler = sub {
+ sub {
+ my $env = shift;
+ my @path = grep { $_ } split '/', $env->{PATH_INFO};
+ my $fn = pop @path || 'index.html';
+
+ my $dir = $nim->conf->site_dir;
+ $dir = $dir->subdir(@path) if @path;
+
+ my $file = $dir->file($fn);
+ $file = $dir->subdir($file->basename)->file('index.html') if -d $file;
+
+ if (-f $file) {
+ require Plack::App::File;
+ my $type = Plack::App::File->mime_type_for($file);
+
+ my $fh = $file->openr or die $!;
+ return [
+ 200,
+ [ 'Content-Type' => $type, 'Content-Length' => -s $fh ],
+ $fh
+ ];
+ }
+ else {
+ return [ 404, [ "Content-Type" => "text/plain" ], [ "Not Found" ] ];
+ }
+ };
+ };
+ require Plack::Middleware::AccessLog;
+ $handler = build {
+ Plack::Middleware::AccessLog->wrap( $_[0], logger => sub { print STDERR @_ } );
+ } $handler;
+
+ require Plack::Loader;
+ $options{port} ||= 4423;
+ $options{host} ||= '0.0.0.0';
+
+ Plack::Loader->auto(%options)->run($handler->());
+}
View
173 lib/Nim.pm
@@ -1,6 +1,5 @@
package Nim;
-use utf8;
-use Mouse;
+use Any::Moose;
our $VERSION = '0.01';
@@ -9,6 +8,7 @@ use Cwd qw/getcwd/;
use Path::Class qw/file dir/;
use Nim::Config;
+use Nim::Entry;
use Nim::Log;
has conf => (
@@ -25,49 +25,36 @@ has hooks => (
has entries => (
is => 'rw',
isa => 'ArrayRef[Nim::Entry]',
- lazy => 1,
default => sub { [] },
);
-has logger => (
+has pages => (
is => 'rw',
- isa => 'Nim::Log',
- lazy => 1,
- default => sub {
- my $self = shift;
- Nim::Log->new( log_level => $self->conf->log_level );
- },
+ isa => 'ArrayRef[Nim::Page]',
+ default => sub { [] },
);
-no Mouse;
-
-=head1 NAME
-
-Nim - Module abstract (<= 44 characters) goes here
-
-=head1 SYNOPSIS
-
- use Nim;
- blah blah blah
-
-=head1 DESCRIPTION
-
-Stub documentation for this module was created by ExtUtils::ModuleMaker.
-It looks like the author of the extension was negligent enough
-to leave the stub unedited.
-
-Blah blah blah.
-
-=head1 METHODS
-
-=head2 new
+has log => (
+ is => 'rw',
+ isa => 'Nim::Log',
+ lazy_build => 1,
+);
-=head2 run
+no Any::Moose;
-=cut
+do {
+ my $CONTEXT;
+ sub context {
+ my ($class, $context) = @_;
+ $CONTEXT = $context if $context;
+ $CONTEXT;
+ }
+};
sub run {
- my $self = shift;
+ my ($self) = @_;
+
+ $self->context($self);
$self->load_config;
$self->load_plugins;
@@ -75,36 +62,32 @@ sub run {
$self->run_hooks;
}
-=head2 run_hooks
-
-
-
-=cut
-
sub run_hooks {
- my $self = shift;
+ my ($self) = @_;
$self->run_hook('initialize');
- $self->run_hook('find_entries');
+ $self->run_hook('find_entries');
for my $entry (@{ $self->entries }) {
- $self->run_hook( filter => $entry );
- $self->run_hook( interpolate => $entry );
- $self->run_hook( render_entry => $entry );
+ $self->run_hook( 'entry.filter' => $entry );
+ $self->run_hook( 'entry.interpolate' => $entry );
+ $self->run_hook( 'entry.render' => $entry );
+ }
+
+ $self->run_hook('init_pages');
+ for my $page (@{ $self->pages }) {
+ $self->run_hook('page.filer' => $page );
+ $self->run_hook('page.interpolate' => $page );
+ $self->run_hook('page.render' => $page );
}
- $self->run_hook('render_pages');
$self->run_hook('finalize');
}
-=head2 run_hook
-
-=cut
-
sub run_hook {
my ($self, $name, @args) = @_;
- $self->logger->debug('run_hook: %s', $name);
+ $self->log->debug('run_hook: %s', $name);
my @hooks = (
@{ $self->hooks->{ 'before_' . $name } || [] },
@@ -113,80 +96,58 @@ sub run_hook {
);
for my $hook (@hooks) {
- $hook->{callback}->( $hook->{plugin}, $self, @args );
+ if ($hook->{plugin}->rule->dispatch($hook->{plugin}, $name, @args)) {
+ $hook->{callback}->( $hook->{plugin}, $self, @args );
+ }
}
}
-=head2 run_hook_once
-
-=cut
-
sub run_hook_once {
my ($self, $name, @args) = @_;
- for my $hook (@{ $self->hooks->{$name} }) {
+ for my $hook (@{ $self->hooks->{$name} || [] }) {
my $res = $hook->{callback}->( $hook->{plugin}, $self, @args );
- return $res if $res;
+ return $res if defined $res;
}
return;
}
-=head2 load_config
-
-=cut
-
sub load_config {
- my $self = shift;
+ my ($self) = @_;
my $config_file = dir(getcwd)->file('.nim');
croak 'config file ".nim" is not found on this directory' unless -f $config_file;
$self->conf( Nim::Config->load($config_file) );
- $self->logger->debug('data_dir: %s', $self->conf->data_dir->absolute);
- $self->logger->debug('output_dir: %s', $self->conf->output_dir->absolute);
- $self->logger->debug('templates_dir: %s', $self->conf->templates_dir->absolute);
+ $self->log->debug("Config file loaded");
+ $self->log->debug('data_dir: %s', $self->conf->data_dir->absolute);
+ $self->log->debug('site_dir: %s', $self->conf->site_dir->absolute);
+ $self->log->debug('templates_dir: %s', $self->conf->templates_dir->absolute);
}
-=head2 load_plugins
-
-=cut
-
sub load_plugins {
- my $self = shift;
+ my ($self) = @_;
for my $conf (@{ $self->conf->plugins }) {
+ $conf->{config}{rule} ||= $conf->{rule};
$self->load_plugin( $conf->{module}, $conf->{config} );
}
-
- # load default plugins
- $self->load_plugin('EntryLoader') unless $self->hooks->{find_entries};
- $self->load_plugin('TemplateLoader::Single') unless $self->hooks->{load_template};
- $self->load_plugin('Template::TT') unless $self->hooks->{interpolate};
- $self->load_plugin('Render::Entry') unless $self->hooks->{render_entry};
+ $self->load_plugin('Default');
}
-=head2 load_plugin
-
-=cut
-
sub load_plugin {
my ($self, $module, $conf) = @_;
- unless ($module =~ s/^\+//) {
- $module = "Nim::Plugin::${module}";
- }
+ $module =~ s/^\+//
+ or $module = "Nim::Plugin::${module}";
- Mouse::load_class($module) unless Mouse::is_class_loaded($module);
+ Any::Moose::load_class($module) unless Any::Moose::is_class_loaded($module);
my $plugin = $module->new($conf || ());
$plugin->register($self);
}
-=head2 register_hook
-
-=cut
-
sub register_hook {
my ($self, $plugin, @hooks) = @_;
@@ -198,13 +159,39 @@ sub register_hook {
}
}
+sub _build_log {
+ my ($self) = @_;
+ Nim::Log->new( log_level => $self->conf->log_level );
+}
+
+__PACKAGE__->meta->make_immutable;
+
+__END__
+
+=head1 NAME
+
+Nim - Module abstract (<= 44 characters) goes here
+
+=head1 SYNOPSIS
+
+ use Nim;
+ blah blah blah
+
+=head1 DESCRIPTION
+
+Stub documentation for this module was created by ExtUtils::ModuleMaker.
+It looks like the author of the extension was negligent enough
+to leave the stub unedited.
+
+Blah blah blah.
+
=head1 AUTHOR
Daisuke Murase <typester@cpan.org>
-=head1 COPYRIGHT & LICENSE
+=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2009 KAYAC Inc. All rights reserved.
+Copyright (c) 2009 by KAYAC Inc.
This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.
@@ -213,5 +200,3 @@ The full text of the license can be found in the
LICENSE file included with this module.
=cut
-
-1;
View
41 lib/Nim/Config.pm
@@ -1,51 +1,43 @@
package Nim::Config;
-use utf8;
-use Mouse;
+use Any::Moose;
+use Nim::Types;
use YAML::Syck;
-use Nim::Types::Path::Class;
-has 'log_level' => (
+has log_level => (
is => 'rw',
isa => 'Str',
- default => sub { 'error' },
+ default => 'info',
);
-has [qw/output_dir data_dir/] => (
+has time_zone => (
+ is => 'rw',
+ isa => 'Str',
+ default => 'local',
+);
+
+has [qw/data_dir site_dir/] => (
is => 'rw',
- isa => 'Path::Class::Dir',
+ isa => 'Nim::Types::Dir',
required => 1,
coerce => 1,
);
has templates_dir => (
is => 'rw',
- isa => 'Path::Class::Dir',
+ isa => 'Nim::Types::Dir',
lazy => 1,
- default => sub { $_[0]->data_dir },
coerce => 1,
-);
-
-has default_flavour => (
- is => 'rw',
- isa => 'Str',
- default => sub { 'html' },
-);
-
-has data_extension => (
- is => 'rw',
- isa => 'Str',
- default => sub { 'txt' },
+ default => sub { shift->data_dir },
);
has plugins => (
is => 'rw',
isa => 'ArrayRef',
- lazy => 1,
default => sub { [] },
);
-no Mouse;
+no Any::Moose;
sub load {
my ($class, $file) = @_;
@@ -54,6 +46,5 @@ sub load {
$class->new($conf);
}
-1;
-
+__PACKAGE__->meta->make_immutable;
View
132 lib/Nim/Entry.pm
@@ -1,113 +1,77 @@
package Nim::Entry;
-use utf8;
-use Mouse;
+use Any::Moose;
-use Encode;
-use Nim::Types::Path::Class;
+use Nim::Types;
+use DateTime;
-has context => (
+has [qw/path filename/] => (
is => 'rw',
- isa => 'Nim',
- weak_ref => 1,
+ isa => 'Str',
+ required => 1,
);
-has file => (
+has time => (
is => 'rw',
- isa => 'Path::Class::File',
+ isa => 'Int',
required => 1,
- coerce => 1,
-);
-
-has path => (
- is => 'rw',
- isa => 'Str',
- lazy => 1,
- default => sub {
- my $self = shift;
- my $conf = $self->context->conf;
-
- my $d = $conf->data_dir->stringify;
- my $p = $self->file->parent;
- $p =~ s/^$d//;
- $p ||= '/';
-
- $p;
- },
);
-has fn => (
- is => 'rw',
- isa => 'Str',
- lazy => 1,
- default => sub {
- my $self = $_[0];
- (my $fn = $self->file->basename) =~ s/\.[^.]+$//;
- $fn;
- },
+has datetime => (
+ is => 'rw',
+ isa => 'DateTime',
+ lazy_build => 1,
);
-has headers => (
- is => 'rw',
- isa => 'HashRef',
- lazy => 1,
- default => sub { {} },
+has loader => (
+ is => 'rw',
+ isa => 'CodeRef',
+ required => 1,
);
-has body => (
- is => 'rw',
- isa => 'Str',
- lazy => 1,
- default => sub { '' },
+has [qw/title body/] => (
+ is => 'rw',
+ isa => 'Str',
+ lazy_build => 1,
);
has rendered_body => (
- is => 'rw',
- isa => 'Str',
- lazy => 1,
- default => sub { '' },
+ is => 'rw',
);
-no Mouse;
+no Any::Moose;
+
+sub year {
+ my ($self) = @_;
+ $self->datetime->year;
+}
+
+sub month {
+ my ($self) = @_;
+ sprintf '%02d', $self->datetime->month;
+}
-sub BUILD {
- $_[0]->load_data; # TODO: lazy load
+sub day {
+ my ($self) = @_;
+ sprintf '%02d', $self->datetime->day;
}
-sub load {
- my ($class, $file) = @_;
- $class->new( file => $file );
+sub _build_title {
+ my ($self) = @_;
+ $self->loader->( $self, 'title' );
}
-sub load_data {
- my $self = shift;
-
- my $data = $self->file->slurp;
- my ($meta, $body) = @_;
- if ($data =~ /^\S+:/) {
- ($meta, $body) = $data =~ /(.*?)\r?\n\r?\n(.*)/s;
- for my $line (split /\r?\n/, $meta) {
- my ($key, $value) = $line =~ /^(\S+):\s*(.*)/;
- $self->header( $key => $value );
- }
- }
- else {
- $body = $data;
- }
-
- my $charset = $self->header('charset') || 'utf-8';
- for my $k (keys %{ $self->headers }) {
- $self->header( $k, decode($charset, $self->header($k)) );
- }
- $self->body( decode($charset, $body) );
+sub _build_body {
+ my ($self) = @_;
+ $self->loader->( $self, 'body' );
}
-sub header {
- my ($self, $key, $value) = @_;
+sub _build_datetime {
+ my ($self) = @_;
- if ($value) {
- return $self->headers->{ lc $key } = $value;
- }
- $self->headers->{ lc $key };
+ DateTime->from_epoch(
+ epoch => $self->time,
+ time_zone => Nim->context->conf->time_zone,
+ );
}
-1;
+__PACKAGE__->meta->make_immutable;
View
20 lib/Nim/Log.pm
@@ -1,14 +1,13 @@
package Nim::Log;
-use utf8;
-use Mouse;
+use Any::Moose;
has log_level => (
is => 'rw',
isa => 'Str',
- default => sub { 'error' },
+ default => 'info',
);
-no Mouse;
+no Any::Moose;
our %log_levels = (
fatal => 0,
@@ -19,9 +18,9 @@ our %log_levels = (
);
sub log {
- my ($self, $type, $format, @args) = @_;
+ my ($self, $caller, $type, $format, @args) = @_;
return if $log_levels{ $self->log_level } < $log_levels{ $type };
- print sprintf("[${type}] ${format}\n", @args);
+ print sprintf("[${type}] $caller: ${format}\n", @args);
}
{
@@ -29,11 +28,12 @@ sub log {
my $pkg = __PACKAGE__;
for my $type (qw/fatal error warn info debug/) {
*{"$pkg\::$type"} = sub {
- my $self = shift;
- $self->log( $type => @_ );
+ my $self = shift;
+ my $caller = caller;
+
+ $self->log( $caller, $type => @_ );
};
}
}
-1;
-
+__PACKAGE__->meta->make_immutable;
View
43 lib/Nim/Operator.pm
@@ -0,0 +1,43 @@
+package Nim::Operator;
+use Any::Moose;
+use Any::Moose '::Util::TypeConstraints';
+
+use Nim::Rule;
+
+use List::Util qw(reduce);
+
+our %Ops = (
+ AND => [ sub { $_[0] && $_[1] } ],
+ OR => [ sub { $_[0] || $_[1] } ],
+ XOR => [ sub { $_[0] xor $_[1] } ],
+ NAND => [ sub { $_[0] && $_[1] }, 1 ],
+ NOT => [ sub { $_[0] && $_[1] }, 1 ], # alias of NAND
+ NOR => [ sub { $_[0] || $_[1] }, 1 ],
+);
+
+sub is_valid_op {
+ my($class, $op) = @_;
+ exists $Ops{$op};
+}
+
+sub call {
+ my($class, $op, @bool) = @_;
+
+ no warnings 'once';
+ my $bool = reduce { $Ops{$op}->[0]->($a, $b) } @bool;
+ $bool = !$bool if $Ops{$op}->[1];
+ $bool;
+}
+
+subtype 'NimOperator' => as 'Str' => where { __PACKAGE__->is_valid_op($_) };
+coerce 'NimOperator'
+ => from 'Str'
+ => via { uc $_ };
+
+subtype 'NimRulesHash' => as 'ArrayRef[HashRef]';
+subtype 'NimRules' => as 'ArrayRef[Object]';
+coerce 'NimRules'
+ => from 'NimRulesHash'
+ => via { [map Nim::Rule->new($_), @$_ ] };
+
+1;
View
28 lib/Nim/Page.pm
@@ -0,0 +1,28 @@
+package Nim::Page;
+use Any::Moose;
+
+has filename => (
+ is => 'rw',
+ isa => 'Str',
+ required => 1,
+);
+
+has entries => (
+ is => 'rw',
+ isa => 'ArrayRef[Nim::Entry]',
+ default => sub { [] },
+);
+
+has rendered => (
+ is => 'rw',
+);
+
+has creator => (
+ is => 'rw',
+ isa => 'Object',
+ weak_ref => 1,
+);
+
+no Any::Moose;
+
+__PACKAGE__->meta->make_immutable;
View
28 lib/Nim/Plugin.pm
@@ -1,7 +1,31 @@
package Nim::Plugin;
-use utf8;
-use Mouse::Role;
+use Any::Moose '::Role';
+
+use Nim::Rule;
+use Nim::Rules;
requires 'register';
+has rule => (
+ is => 'rw',
+ isa => 'Object',
+);
+
+sub BUILDARGS {
+ my ($self, $args) = @_;
+
+ if (my $rule = $args->{rule}) {
+ $rule = [$rule] if ref $rule eq 'HASH';
+ $args->{rule} = Nim::Rules->new(
+ op => $args->{rule_op} || 'AND',
+ rules => $rule
+ );
+ }
+ else {
+ $args->{rule} = Nim::Rule->new({ module => 'Always' });
+ }
+
+ $args;
+}
+
1;
View
94 lib/Nim/Plugin/AutoIndex.pm
@@ -0,0 +1,94 @@
+package Nim::Plugin::AutoIndex;
+use Any::Moose;
+
+use URI::Escape;
+
+with 'Nim::Plugin';
+
+extends 'Nim::Plugin::Index';
+
+has path => (
+ is => 'rw',
+ isa => 'Str',
+ default => '{path}',
+);
+
+has filename => (
+ is => 'rw',
+ isa => 'Str',
+ default => 'index.html',
+);
+
+has filter => (
+ is => 'rw',
+ isa => 'Str',
+ default => '1',
+);
+
+has limit => (
+ is => 'rw',
+ isa => 'Int',
+ default => 0,
+);
+
+no Any::Moose;
+
+sub register {
+ my ($self, $context) = @_;
+
+ $context->register_hook(
+ $self,
+ 'init_pages' => $self->can('init'),
+ 'page.render' => $self->can('render'),
+ );
+}
+
+sub init {
+ my ($self, $context) = @_;
+
+ my $t = URI::Template->new( $self->path );
+ my %entries_path;
+
+ for my $entry (@{ $context->entries }) {
+ local $@;
+ my $r = eval $self->filter;
+ die $@ if $@;
+ next unless $r;
+
+ if ($entry->can('meta') and $self->path =~ /{tag}/) {
+ # support tags
+ for my $tag (@{ $entry->meta->{tags} || [] }) {
+ my $uri = $t->process(
+ path => $entry->path || '/',
+ filename => $entry->filename,
+ year => $entry->year,
+ month => $entry->month,
+ day => $entry->day,
+ tag => uri_escape_utf8($tag),
+ );
+ push @{ $entries_path{$uri} }, $entry;
+ }
+ }
+ else {
+ my $uri = $t->process(
+ path => $entry->path || '/',
+ filename => $entry->filename,
+ year => $entry->year,
+ month => $entry->month,
+ day => $entry->day,
+ );
+ push @{ $entries_path{$uri} }, $entry;
+ }
+ }
+
+ while (my ($path, $entries) = each %entries_path) {
+ my $page = Nim::Page->new(
+ creator => $self,
+ filename => join('/', $path, $self->filename),
+ entries => $entries,
+ );
+ push @{ $context->pages }, $page;
+ }
+}
+
+__PACKAGE__->meta->make_immutable;
View
22 lib/Nim/Plugin/Default.pm
@@ -0,0 +1,22 @@
+package Nim::Plugin::Default;
+use Any::Moose;
+
+with 'Nim::Plugin';
+
+no Any::Moose;
+
+sub register {
+ my ($self, $context) = @_;
+
+ $context->load_plugin('Entry::File')
+ unless $context->hooks->{find_entries};
+
+ $context->load_plugin('Template::MicroTemplate')
+ unless $context->hooks->{'entry.interpolate'};
+
+ $context->load_plugin('Render::Entry')
+ unless $context->hooks->{'entry.render'};
+}
+
+__PACKAGE__->meta->make_immutable;
+
View
164 lib/Nim/Plugin/Entry/Clmemo.pm
@@ -0,0 +1,164 @@
+package Nim::Plugin::Entry::Clmemo;
+use Any::Moose;
+
+use Path::Class qw/file/;
+use DateTime::Format::DateManip;
+
+with 'Nim::Plugin';
+
+has file => (
+ is => 'rw',
+ isa => 'Str',
+ required => 1,
+);
+
+has path => (
+ is => 'rw',
+ isa => 'Str',
+ default => 'clmemo',
+);
+
+has open_layer => (
+ is => 'rw',
+ isa => 'Str',
+ default => ':utf8',
+);
+
+has limit => (
+ is => 'rw',
+ isa => 'Int',
+ default => 0,
+);
+
+no Any::Moose;
+
+sub register {
+ my ($self, $context) = @_;
+
+ $context->register_hook(
+ $self,
+ find_entries => $self->can('find'),
+ );
+}
+
+sub find {
+ my ($self, $context) = @_;
+
+ my $clmemo = Path::Class::File->new($self->file);
+ die qq[Can't find clmemo file: $clmemo] unless -f $clmemo;
+
+ open my $fh, '<' . $self->open_layer, $clmemo;
+
+ my @cache;
+ my ($parsed, $added);
+ my ($date, $author, $time, $title, @tags, $body);
+ while (my $line = <$fh>) {
+ if ($line =~ /^\d+/) {
+ # header
+ if ($parsed) {
+ push @cache, {
+ date => $time || $date,
+ author => $author,
+ title => $title,
+ tags => [@tags],
+ body => $body,
+ };
+ }
+ $parsed = 0;
+
+ if (@cache) {
+ $self->add_entries($context, @cache);
+ $added += scalar @cache;
+ @cache = ();
+
+ last if ($self->limit and $added >= $self->limit);
+ }
+
+ my ($d, $a) = $line =~ m!^([\d\-]+\s*(?: \(.*?\))?)\s*(.*)$!;
+ $date = DateTime::Format::DateManip->parse_datetime($d);
+ $author = $a;
+ }
+ else {
+ if ($line =~ /^\t\*/) {
+ # entry header
+ if ($parsed) {
+ push @cache, {
+ date => $time || $date,
+ author => $author,
+ title => $title,
+ tags => [@tags],
+ body => $body,
+ };
+ }
+ $parsed++;
+
+ my ($d, $t, $tags, $b) =
+ $line =~ m!^\t\*\s*(\d+:\d+)?\s*(.*?)(\[.*?\])?:\s*$!;
+
+ if ($date && $d) {
+ $time = $date->clone;
+ my ($h, $m) = split ':', $d;
+ $time->set_hour($h);
+ $time->set_minute($m);
+ }
+ else {
+ undef $time;
+ }
+
+ $title = $t || q[];
+
+ if ($tags) {
+ $tags =~ s/^\[|\]$//g;
+ @tags = split /\]\s*?\[/, $tags;
+ }
+ else {
+ @tags = ();
+ }
+
+ $body = $b || q[];
+ }
+ else {
+ $line =~ s/^\t//;
+ $body .= $line;
+ }
+ }
+ }
+
+ $self->add_entries($context, @cache)
+ if @cache;
+
+ close $fh;
+}
+
+sub add_entries {
+ my ($self, $context, @day_entries) = @_;
+
+ my @entries;
+ my $id = 0;
+ for my $info (reverse @day_entries) {
+ $info->{title} =~ s/(^\s+|\s+$)//g;
+
+ push @entries, Nim::Entry->new(
+ context => $context,
+ path => join('/', $self->path, $info->{date}->ymd('/')),
+ filename => ++$id,
+ time => $info->{date}->epoch,
+ datetime => $info->{date},
+ loader => sub {
+ my ($entry, $want) = @_;
+
+ $entry->title( $info->{title} );
+ $entry->body( $info->{body} );
+
+ $want eq 'title' ? $info->{title} : $info->{body};
+ },
+ meta => {
+ tags => $info->{tags},
+ },
+ );
+ }
+
+ push @{ $context->entries }, reverse @entries;
+}
+
+__PACKAGE__->meta->make_immutable;
View
63 lib/Nim/Plugin/Entry/File.pm
@@ -0,0 +1,63 @@
+package Nim::Plugin::Entry::File;
+use Any::Moose;
+
+with 'Nim::Plugin';
+
+use Carp;
+use Nim::Entry;
+
+no Any::Moose;
+
+sub register {
+ my ($self, $context) = @_;
+
+ $context->register_hook(
+ $self,
+ find_entries => \&find,
+ );
+}
+
+sub find {
+ my ($self, $context) = @_;
+
+ my $dir = $context->conf->data_dir->stringify;
+
+ $context->conf->data_dir->recurse( callback => sub {
+ my $f = $_[0];
+ return unless -f $f;
+ return unless $f->basename =~ /\.txt$/;
+
+ (my $path = $f->parent) =~ s/^$dir//;
+ (my $name = $f->basename) =~ s/\.txt$//;
+
+ $context->log->info('find: %s', $f);
+
+ my $entry = Nim::Entry->new(
+ context => $context,
+ path => $path,
+ filename => $name,
+ time => $f->stat->mtime,
+ loader => sub {
+ my ($entry, $want) = @_;
+
+ open my $fh, '<:utf8', "$f"
+ or croak qq[Can't open entry file: "$f", $!];
+
+ my $title = <$fh>;
+ my $body = do { local $/; <$fh> };
+ $fh->close;
+
+ chomp $title;
+
+ $entry->title( $title );
+ $entry->body( $body );
+
+ $want eq 'title' ? $title : $body;
+ },
+ );
+
+ push @{ $context->entries }, $entry;
+ });
+}
+
+__PACKAGE__->meta->make_immutable;
View
35 lib/Nim/Plugin/EntryLoader.pm
@@ -1,35 +0,0 @@
-package Nim::Plugin::EntryLoader;
-use utf8;
-use Mouse;
-
-with 'Nim::Plugin';
-
-use Nim::Entry;
-
-no Mouse;
-
-sub register {
- my ($self, $context) = @_;
-
- $context->register_hook(
- $self,
- find_entries => \&find,
- );
-}
-
-sub find {
- my ($self, $context) = @_;
-
- my $data_ext = $context->conf->data_extension;
-
- $context->conf->data_dir->recurse( callback => sub {
- my $f = $_[0];
- return unless -f $f;
- return unless $f->basename =~ /\.$data_ext$/;
-
- my $entry = Nim::Entry->new( file => $f, context => $context );
- push @{ $context->entries }, $entry;
- });
-}
-
-1;
View
60 lib/Nim/Plugin/Filter/Markdown.pm
@@ -1,60 +0,0 @@
-package Nim::Plugin::Filter::Markdown;
-use utf8;
-use Mouse;
-
-with 'Nim::Plugin';
-
-use Text::Markdown;
-
-has md => (
- is => 'rw',
- isa => 'Text::Markdown',
- lazy => 1,
- default => sub { Text::Markdown->new },
- handles => ['markdown'],
-);
-
-no Mouse;
-
-sub register {
- my ($self, $context) = @_;
-
- $context->register_hook(
- $self,
- filter => \&process,
- );
-}
-
-sub process {
- my ($self, $context, $entry) = @_;
- $entry->body( $self->markdown($entry->body) );
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Nim::Plugin::Filter::Markdown - upgrade content by Markdown
-
-=head1 SYNOSPS
-
- plugins:
- - module: Filter::Markdown
-
-=head1 AUTHOR
-
-Daisuke Murase <typester@cpan.org>
-
-=head1 COPYRIGHT & LICENSE
-
-Copyright (c) 2009 KAYAC Inc. All rights reserved.
-
-This program is free software; you can redistribute
-it and/or modify it under the same terms as Perl itself.
-
-The full text of the license can be found in the
-LICENSE file included with this module.
-
-=cut
View
56 lib/Nim/Plugin/Index.pm
@@ -0,0 +1,56 @@
+package Nim::Plugin::Index;
+use Any::Moose;
+
+use Carp;
+use Nim::Page;
+
+has output => (
+ is => 'rw',
+ isa => 'Str',
+);
+
+no Any::Moose;
+
+sub register {
+ my ($self, $context) = @_;
+
+ $context->register_hook(
+ $self,
+ 'init_pages' => \&init,
+ 'page.render' => \&render,
+ );
+}
+
+sub init {
+ my ($self, $context) = @_;
+
+ my $page = Nim::Page->new(
+ creator => $self,
+ filename => $self->output,
+ entries => $context->entries,
+ );
+ push @{ $context->pages }, $page;
+}
+
+sub render {
+ my ($self, $context, $page) = @_;
+ return unless $page->creator eq $self; # not my job
+
+ my $dir = $context->conf->site_dir;
+ my @path = grep { $_ } split '/', $page->filename;
+ my $fn = pop @path;
+
+ $dir = $dir->subdir(@path) if @path;
+ my $file = $dir->file($fn);
+
+ $context->log->info('render: %s', $file);
+
+ $dir->mkpath unless -d $dir;
+
+ my $fh = $file->openw or croak "Can't write file: $!";
+ print $fh $page->rendered;
+ $fh->close;
+}
+
+__PACKAGE__->meta->make_immutable;
+
View
36 lib/Nim/Plugin/Markdown.pm
@@ -0,0 +1,36 @@
+package Nim::Plugin::Markdown;
+use Any::Moose;
+
+with 'Nim::Plugin';
+
+use Text::Markdown;
+
+has md => (
+ is => 'rw',
+ isa => 'Text::Markdown',
+ lazy_build => 1,
+ handles => ['markdown'],
+);
+
+no Any::Moose;
+
+sub register {
+ my ($self, $context) = @_;
+
+ $context->register_hook(
+ $self,
+ 'before_entry.interpolate' => \&process,
+ );
+}
+
+sub process {
+ my ($self, $context, $entry) = @_;
+ $entry->body( $self->markdown( $entry->body ) );
+}
+
+sub _build_md {
+ my ($self) = @_;
+ Text::Markdown->new;
+}
+
+__PACKAGE__->meta->make_immutable;
View
65 lib/Nim/Plugin/Meta.pm
@@ -0,0 +1,65 @@
+package Nim::Plugin::Meta;
+use Any::Moose;
+
+with 'Nim::Plugin';
+
+use DateTime::Format::W3CDTF;
+
+no Any::Moose;
+
+{
+ package Nim::Plugin::Meta::Entry;
+ use Any::Moose '::Role';
+
+ has meta => (
+ is => 'rw',
+ isa => 'HashRef',
+ default => sub { {} },
+ );
+}
+
+sub register {
+ my ($self, $context) = @_;
+
+ $context->register_hook(
+ $self,
+ 'after_find_entries' => \&apply,
+ );
+
+ # apply role
+ my $entry = Nim::Entry->meta;
+
+ $entry->make_mutable if $Any::Moose::PREFERRED eq 'Moose';
+ Nim::Plugin::Meta::Entry->meta->apply( $entry );
+ $entry->make_immutable;
+}
+
+sub apply {
+ my ($self, $context) = @_;
+
+ ENTRY:
+ for my $entry (@{ $context->entries }) {
+ my $src = $entry->body;
+
+ my $meta = ref $entry->{meta} eq 'HASH' ? $entry->{meta} : {};
+ my ($header, $body) = $src =~ /^(.*?)\r?\n\r?\n(.*)$/s;
+ next unless $header;
+
+ for my $line (split /\r?\n/, $header) {
+ my ($key, $value) = $line =~ /^([\w\-_]+):\s*(.+)$/;
+ next ENTRY unless $key; # invalid header
+
+ $meta->{ lc $key } = $value || '';
+ }
+
+ if ($meta->{date}) {
+ my $dt = DateTime::Format::W3CDTF->parse_datetime($meta->{date});
+ $entry->time( $dt->epoch );
+ }
+
+ $entry->meta( $meta );
+ $entry->body( $body );
+ }
+}
+
+__PACKAGE__->meta->make_immutable;
View
88 lib/Nim/Plugin/Paginate.pm
@@ -0,0 +1,88 @@
+package Nim::Plugin::Paginate;
+use Any::Moose;
+
+use Data::Page;
+
+with 'Nim::Plugin';
+
+has entries_per_page => (
+ is => 'rw',
+ isa => 'Int',
+ default => 10,
+);
+
+has filter => (
+ is => 'rw',
+ isa => 'Str',
+ default => '',
+);
+
+no Any::Moose;
+
+{
+ package Nim::Plugin::Paginate::Page;
+ use Any::Moose '::Role';
+
+ has pager => (
+ is => 'rw',
+ isa => 'Data::Page',
+ );
+}
+
+sub register {
+ my ($self, $context) = @_;
+
+ $context->register_hook(
+ $self,
+ after_init_pages => $self->can('paginate'),
+ );
+
+ my $page = Nim::Page->meta;
+ $page->make_mutable if $Any::Moose::PREFERRED eq 'Moose';
+ Nim::Plugin::Paginate::Page->meta->apply($page);
+ $page->make_immutable;
+}
+
+sub paginate {
+ my ($self, $context) = @_;
+
+ my @pages;
+ for my $page (@{ $context->pages }) {
+ if ($self->filter) {
+ local $@;
+ my $r = eval $self->filter;
+ die $@ if $@;
+ next unless $r;
+ }
+
+ my $current_page = 1;
+
+ my @entries = @{ $page->entries };
+ while (my @e = splice @entries, 0, $self->entries_per_page) {
+ my @path = split '/', $page->filename;
+ my $fn = pop @path;
+
+ if ($current_page > 1) {
+ push @path, "page/${current_page}";
+ }
+
+ my $pager = Data::Page->new;
+ $pager->total_entries(scalar @{ $page->entries });
+ $pager->entries_per_page( $self->entries_per_page );
+ $pager->current_page( $current_page );
+
+ push @pages, Nim::Page->new(
+ %$page,
+ filename => join('/', @path, $fn),
+ pager => $pager,
+ entries => \@e,
+ );
+
+ $current_page++;
+ }
+ }
+
+ $context->pages( \@pages );
+}
+
+__PACKAGE__->meta->make_immutable;
View
64 lib/Nim/Plugin/Render/Entry.pm
@@ -1,40 +1,74 @@
package Nim::Plugin::Render::Entry;
-use utf8;
-use Mouse;
+use Any::Moose;
+
+use DateTime;
+use URI::Template;
with 'Nim::Plugin';
-no Mouse;
+has path => (
+ is => 'rw',
+ isa => 'Str',
+ default => '{path}',
+);
+
+has filename => (
+ is => 'rw',
+ isa => 'Str',
+ default => '{filename}.html',
+);
+
+use Carp;
+
+no Any::Moose;
sub register {
my ($self, $context) = @_;
$context->register_hook(
$self,
- render_entry => \&render,
+ 'entry.render' => \&render,
);
}
sub render {
my ($self, $context, $entry) = @_;
- my ($fn) = $entry->file->basename =~ /^(.*)\./;
- $fn .= '.' . $context->conf->default_flavour;
+ my $template = URI::Template->new( $self->path );
+ my $dt = DateTime->from_epoch(
+ epoch => $entry->time,
+ time_zone => $context->conf->time_zone,
+ );
+
+ my $uri = $template->process(
+ path => $entry->path || '/',
+ filename => $entry->filename,
+ year => $entry->year,
+ month => $entry->month,
+ day => $entry->day,
+ );
- my $path = $entry->file->parent->stringify;
- my $root = $context->conf->data_dir->stringify;
- $path =~ s/^$root//;
+ my $dir = $context->conf->site_dir;
+ my @path = grep { $_ } split '/', $uri;
+ $dir = $dir->subdir(@path) if @path;
- my $file = $path
- ? $context->conf->output_dir->subdir($path)->file($fn)
- : $context->conf->output_dir->file($fn);
+ $template = URI::Template->new($self->filename);
+ $uri = $template->process(
+ path => $entry->path || '/',
+ filename => $entry->filename,
+ year => $entry->year,
+ month => $entry->month,
+ day => $entry->day,
+ );
+
+ my $file = $dir->file($uri);
+ $context->log->info('render: %s', $file);
$file->parent->mkpath unless -d $file->parent;
- my $fh = $file->openw;
+ my $fh = $file->openw or croak "Can't write file: $!";
print $fh $entry->rendered_body;
$fh->close;
}
-1;
-
+__PACKAGE__->meta->make_immutable;
View
65 lib/Nim/Plugin/TagIndex.pm
@@ -0,0 +1,65 @@
+package Nim::Plugin::TagIndex;
+use Any::Moose;
+
+with 'Nim::Plugin';
+
+extends 'Nim::Plugin::Index';
+
+has path => (
+ is => 'rw',
+ isa => 'Str',
+ default => 'tag/{tag}',
+);
+
+has filename => (
+ is => 'rw',
+ isa => 'Str',
+ default => 'index.html',
+);
+
+has filter => (
+ is => 'rw',
+ isa => 'Str',
+ default => 1,
+);
+
+no Any::Moose;
+
+sub register {
+ my ($self, $context) = @_;
+
+ $context->register_hook(
+ $self,
+ 'init_pages' => $self->can('init'),
+ 'page.render' => $self->can('render'),
+ );
+}
+
+sub init {
+ my ($self, $context) = @_;
+
+ my $t = URI::Template->new( $self->path );
+ my %entries_by_tag;
+
+ for my $entry (@{ $context->entries }) {
+ local $@;
+ my $r = eval $self->filter;
+ die $@ if $@;
+ next unless $r;
+
+ for my $tag (@{ $entry->meta->{tags} || [] }) {
+ my $uri = $t->process(
+ path => $entry->path || '/',
+ filename => $entry->filename,
+ year => $entry->year,
+ month => $entry->month,
+ day => $entry->day,
+ tag => $tag,
+ );
+
+ push @{ $entries_by_tag{$uri} }, $entry;
+ }
+ }
+}
+
+__PACKAGE__->meta->make_immutable;
View
119 lib/Nim/Plugin/Template/MicroTemplate.pm
@@ -0,0 +1,119 @@
+package Nim::Plugin::Template::MicroTemplate;
+use Any::Moose;
+
+with 'Nim::Plugin';
+
+use Carp;
+use Text::MicroTemplate::Extended;
+use Path::Class qw/file dir/;
+
+has mt => (
+ is => 'rw',
+ isa => 'Text::MicroTemplate::Extended',
+ lazy_build => 1,
+);
+
+has context => (
+ is => 'rw',
+ isa => 'Nim',
+ weak_ref => 1,
+);
+
+has handle_entry => (
+ is => 'rw',
+ isa => 'Nim::Entry',
+ weak_ref => 1,
+ clearer => 'clear_entry',
+);
+
+has handle_page => (
+ is => 'rw',
+ isa => 'Nim::Page',
+ weak_ref => 1,
+ clearer => 'clear_page',
+);
+
+no Any::Moose;
+
+sub register {
+ my ($self, $context) = @_;
+ $self->context( $context );
+
+ $context->register_hook(
+ $self,
+ 'entry.interpolate' => \&interpolate_entry,
+ 'page.interpolate' => \&interpolate_page,
+ );
+}
+
+sub interpolate_entry {
+ my ($self, $context, $entry) = @_;
+
+ my $template = $self->find_template($context, $entry->path, 'entry.html')
+ or die qq[Can't find template "entry.html" for entry: @{[ $entry->path ]}/@{[ $entry->filename ]}];
+
+ $self->handle_entry( $entry );
+ $self->clear_page;
+
+ $entry->rendered_body( $self->mt->render($template) );
+}
+
+sub interpolate_page {
+ my ($self, $context, $page) = @_;
+
+ my @path = grep { $_ } split '/', $page->filename;
+ my $fn = pop @path;
+
+ my $template = $self->find_template($context, join('/', '', @path), $fn)
+ or die qq[Can't find template for @{[ $page->filename ]}];
+
+ $context->log->debug('Find template %s for %s', $template, $page->filename);
+
+ $self->clear_entry;
+ $self->handle_page($page);
+
+ $page->rendered( $self->mt->render($template) );
+}
+
+sub find_template {
+ my ($self, $context, $path, $filename) = @_;
+
+ my $dir = $context->conf->templates_dir;
+ $path = $dir->subdir( grep { $_ } split '/', $path );
+
+# $path->mkpath unless -d $path;
+
+ while ($dir->subsumes($path)) {
+ my $t = $path->file($filename);
+ if (-f $t) {
+ $t =~ s/^$dir//;
+
+ return $t;
+ }
+ $path = $path->parent;
+ }
+
+ return;
+}
+
+sub _build_mt {
+ my ($self) = @_;
+ my $context = $self->context or return;
+
+ Text::MicroTemplate::Extended->new(
+ include_path => [$context->conf->templates_dir],
+ template_args => {
+ nim => sub { $self->context },
+ entry => sub { $self->handle_entry },
+ page => sub { $self->handle_page },
+ },
+ macro => {
+ encoded_string => sub ($) {
+ Text::MicroTemplate::encoded_string(@_);
+ },
+ },
+ extension => '',
+ );
+}
+
+__PACKAGE__->meta->make_immutable;
View
38 lib/Nim/Plugin/Template/TT.pm
@@ -1,38 +0,0 @@
-package Nim::Plugin::Template::TT;
-use utf8;
-use Mouse;
-
-with 'Nim::Plugin';
-
-use Carp;
-use Template;
-
-has tt => (
- is => 'rw',
- isa => 'Template',
- lazy => 1,
- default => sub { Template->new },
-);
-
-no Mouse;
-
-sub register {
- my ($self, $context) = @_;
-
- $context->register_hook(
- $self,
- interpolate => \&interpolate,
- );
-}
-
-sub interpolate {
- my ($self, $context, $entry) = @_;
-
- my $template = $context->run_hook_once( load_template => $entry );
- $self->tt->process(\$template, { nim => $context, entry => $entry }, \my $rendered);
-
- $entry->rendered_body( $rendered );
-}
-
-1;
-
View
41 lib/Nim/Plugin/TemplateLoader/Single.pm
@@ -1,41 +0,0 @@
-package Nim::Plugin::TemplateLoader::Single;
-use utf8;
-use Mouse;
-
-with 'Nim::Plugin';
-
-no Mouse;
-
-sub register {
- my ($self, $context) = @_;
-
- $context->register_hook(
- $self,
- load_template => \&load,
- );
-}
-
-sub load {
- my ($self, $context, $entry) = @_;
-
- my $template;
- my $data_dir = $context->conf->data_dir;
- my $path = $entry->file->parent;
- my $fn = 'template.' . $context->conf->default_flavour;
-
- while ($data_dir->contains($path)) {
- my $t = $path->file($fn);
- if (-f $t) {
- open my $fh, "<:utf8", $t or die $!;
- $template = do { local $/; <$fh>};
- close $fh;
- last;
- }
- $path = $path->parent;
- }
-
- return $template;
-}
-
-1;
-
View
21 lib/Nim/Rule.pm
@@ -0,0 +1,21 @@
+package Nim::Rule;
+use strict;
+
+sub new {
+ my($class, $config) = @_;
+
+ if (my $exp = $config->{expression}) {
+ $config->{module} = 'Expression';
+ }
+
+ my $module = delete $config->{module};
+ $module = "Nim::Rule::$module";
+ Any::Moose::load_class($module) unless Any::Moose::is_class_loaded($module);
+
+ $module->new($config);
+}
+
+1;
+
+
+
View
8 lib/Nim/Rule/Always.pm
@@ -0,0 +1,8 @@
+package Nim::Rule::Always;
+use Any::Moose;
+
+no Any::Moose;
+
+sub dispatch { 1 };
+
+__PACKAGE__->meta->make_immutable;
View
41 lib/Nim/Rule/Expression.pm
@@ -0,0 +1,41 @@
+package Nim::Rule::Expression;
+use Any::Moose;
+
+use Carp;
+use Try::Tiny;
+
+has expression => (
+ is => 'rw',
+ isa => 'Str',
+ required => 1,
+);
+
+no Any::Moose;
+
+sub dispatch {
+ my ($self, @args) = @_;
+
+ my $entry_or_page = $args[0];
+ my ($entry, $page);
+
+ if ($entry_or_page) {
+ if ($entry_or_page->isa('Nim::Entry')) {
+ $entry = $entry_or_page;
+ }
+ elsif ($entry_or_page->isa('Nim::Page')) {
+ $page = $entry_or_page;
+ }
+ }
+
+ my $status;
+ try {
+ $status = eval $self->expression
+ }
+ catch {
+ die +__PACKAGE__ . ": expression error: $_";
+ };
+
+ $status;
+}
+
+__PACKAGE__->meta->make_immutable;
View
36 lib/Nim/Rules.pm
@@ -0,0 +1,36 @@
+package Nim::Rules;
+use Any::Moose;
+
+use Nim::Operator;
+
+has op => (
+ is => 'rw',
+ isa => 'NimOperator',
+ default => 'AND',
+ coerce => 1,
+);
+
+has rules => (
+ is => 'rw',
+ isa => 'NimRules',
+ default => sub { [] },
+ coerce => 1,
+);
+
+no Any::Moose;
+
+sub dispatch {
+ my ($self, $plugin, $hook, @args) = @_;
+
+ my @bool;
+ for my $rule (@{ $self->rules }) {
+ push @bool, !!$rule->dispatch(@args);
+ }
+
+ # can't find rules for this phase: execute it
+ return 1 unless @bool;
+
+ Nim::Operator->call( $self->op, @bool );
+}
+
+__PACKAGE__->meta->make_immutable;
View
20 lib/Nim/Types.pm
@@ -0,0 +1,20 @@
+package Nim::Types;
+use Any::Moose;
+use Any::Moose '::Util::TypeConstraints';
+
+use Path::Class;
+
+subtype 'Nim::Types::Dir'
+ => as 'Object' => where { $_->isa('Path::Class::Dir') };
+coerce 'Nim::Types::Dir'
+ => from 'Str'
+ => via { Path::Class::Dir->new($_) };
+
+subtype 'Nim::Types::File'
+ => as 'Object' => where { $_->isa('Path::Class::File') };
+coerce 'Nim::Types::File'
+ => from 'Str'
+ => via { Path::Class::File->new($_) };
+
+1;
+
View
25 lib/Nim/Types/Path/Class.pm
@@ -1,25 +0,0 @@
-package Nim::Types::Path::Class;
-use MouseX::Types;
-use Path::Class;
-
-subtype 'Path::Class::File',
- as 'Object',
- where { $_->isa('Path::Class::File') };
-
-subtype 'Path::Class::Dir',
- as 'Object',
- where { $_->isa('Path::Class::Dir') };
-
-coerce 'Path::Class::File',
- from 'Str',
- via {
- Path::Class::File->new($_);
- };
-
-coerce 'Path::Class::Dir',
- from 'Str',
- via {
- Path::Class::Dir->new($_);
- };
-
-1;
View
0  t/pod.t → xt/pod.t
File renamed without changes
View
0  t/pod_coverage.t → xt/pod_coverage.t
File renamed without changes
View
10 xt/pod_spell.t
@@ -0,0 +1,10 @@
+use Test::More;
+eval q{ use Test::Spelling };
+plan skip_all => "Test::Spelling is not installed." if $@;
+add_stopwords(<DATA>);
+set_spell_cmd("aspell -l en list");
+all_pod_files_spelling_ok('lib');
+__DATA__
+Daisuke
+Murase
+KAYAC
Please sign in to comment.
Something went wrong with that request. Please try again.