use Encode;
use HTML::Entities;
use URI::Escape q{uri_escape_utf8};
-use POSIX;
+use POSIX ();
use Storable;
use open qw{:utf8 :std};
use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase
%pagestate %wikistate %renderedfiles %oldrenderedfiles
%pagesources %destsources %depends %depends_simple %hooks
- %forcerebuild %loaded_plugins};
+ %forcerebuild %loaded_plugins %typedlinks %oldtypedlinks};
use Exporter q{import};
our @EXPORT = qw(hook debug error template htmlpage deptype
add_underlay pagetitle titlepage linkpage newpagefile
inject add_link
%config %links %pagestate %wikistate %renderedfiles
- %pagesources %destsources);
+ %pagesources %destsources %typedlinks);
our $VERSION = 3.00; # plugin interface version, next is ikiwiki version
our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE
our $installdir='/usr'; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE
safe => 0, # paranoia
rebuild => 0,
},
+ include => {
+ type => "string",
+ default => undef,
+ example => '^\.htaccess$',
+ description => "regexp of normally excluded files to include",
+ advanced => 1,
+ safe => 0, # regexp
+ rebuild => 1,
+ },
exclude => {
type => "string",
default => undef,
- example => '\.wav$',
- description => "regexp of source files to ignore",
+ example => '^(*\.private|Makefile)$',
+ description => "regexp of files that should be skipped",
advanced => 1,
safe => 0, # regexp
rebuild => 1,
safe => 0,
rebuild => 0,
},
+ clean => {
+ type => "internal",
+ default => 0,
+ description => "running in clean mode",
+ safe => 0,
+ rebuild => 0,
+ },
refresh => {
type => "internal",
default => 0,
safe => 0,
rebuild => 0,
},
+ setuptype => {
+ type => "internal",
+ default => "Standard",
+ description => "perl class to use to dump setup file",
+ safe => 0,
+ rebuild => 0,
+ },
allow_symlinks_before_srcdir => {
type => "boolean",
default => 0,
# Convert "http://somehost.com/user" to "user [somehost.com]".
# (also "https://somehost.com/user/")
if ($display !~ /\[/) {
- $display=~s/^https?:\/\/(.+)\/([^\/]+)\/?$/$2 [$1]/;
+ $display=~s/^https?:\/\/(.+)\/([^\/#?]+)\/?(?:[#?].*)?$/$2 [$1]/;
}
$display=~s!^https?://!!; # make sure this is removed
eval q{use CGI 'escapeHTML'};
my $content=shift;
my $oneline = $content !~ /\n/;
-
+
if (exists $hooks{htmlize}{$type}) {
$content=$hooks{htmlize}{$type}{call}->(
page => $page,
if ($oneline) {
# hack to get rid of enclosing junk added by markdown
- # and other htmlizers
+ # and other htmlizers/sanitizers
$content=~s/^<p>//i;
- $content=~s/<\/p>$//i;
- chomp $content;
+ $content=~s/<\/p>\n*$//i;
}
return $content;
if (! $config{rebuild}) {
%pagesources=%pagemtime=%oldlinks=%links=%depends=
%destsources=%renderedfiles=%pagecase=%pagestate=
- %depends_simple=();
+ %depends_simple=%typedlinks=%oldtypedlinks=();
}
my $in;
if (! open ($in, "<", "$config{wikistatedir}/indexdb")) {
if (exists $d->{state}) {
$pagestate{$page}=$d->{state};
}
+ if (exists $d->{typedlinks}) {
+ $typedlinks{$page}=$d->{typedlinks};
+
+ while (my ($type, $links) = each %{$typedlinks{$page}}) {
+ next unless %$links;
+ $oldtypedlinks{$page}{$type} = {%$links};
+ }
+ }
}
$oldrenderedfiles{$page}=[@{$d->{dest}}];
}
$index{page}{$src}{depends_simple} = $depends_simple{$page};
}
+ if (exists $typedlinks{$page} && %{$typedlinks{$page}}) {
+ $index{page}{$src}{typedlinks} = $typedlinks{$page};
+ }
+
if (exists $pagestate{$page}) {
foreach my $id (@hookids) {
foreach my $key (keys %{$pagestate{$page}{$id}}) {
# Add explicit dependencies for influences.
my $sub=pagespec_translate($pagespec);
- return if $@;
+ return unless defined $sub;
foreach my $p (keys %pagesources) {
my $r=$sub->($p, location => $page);
my $i=$r->influences;
return $deptype;
}
+my $file_prune_regexp;
sub file_pruned ($;$) {
my $file=shift;
if (@_) {
$file =~ s#^\Q$base\E/+##;
}
- my $regexp='('.join('|', @{$config{wiki_file_prune_regexps}}).')';
- return $file =~ m/$regexp/;
+ if (defined $config{include} && length $config{include}) {
+ return 0 if $file =~ m/$config{include}/;
+ }
+
+ if (! defined $file_prune_regexp) {
+ $file_prune_regexp='('.join('|', @{$config{wiki_file_prune_regexps}}).')';
+ $file_prune_regexp=qr/$file_prune_regexp/;
+ }
+ return $file =~ m/$file_prune_regexp/;
}
sub define_gettext () {
use warnings;
}
-sub add_link ($$) {
+sub add_link ($$;$) {
my $page=shift;
my $link=shift;
+ my $type=shift;
push @{$links{$page}}, $link
unless grep { $_ eq $link } @{$links{$page}};
+
+ if (defined $type) {
+ $typedlinks{$page}{$type}{$link} = 1;
+ }
}
sub pagespec_translate ($) {
my $sub=pagespec_translate($spec);
return IkiWiki::ErrorReason->new("syntax error in pagespec \"$spec\"")
- if $@ || ! defined $sub;
+ if ! defined $sub;
return $sub->($page, @params);
}
my $sub=pagespec_translate($pagespec);
error "syntax error in pagespec \"$pagespec\""
- if $@ || ! defined $sub;
+ if ! defined $sub;
my @candidates;
if (exists $params{list}) {
sub pagespec_valid ($) {
my $spec=shift;
- my $sub=pagespec_translate($spec);
- return ! $@;
+ return defined pagespec_translate($spec);
}
sub glob2re ($) {
$link=derel($link, $params{location});
my $from=exists $params{location} ? $params{location} : '';
+ my $linktype=$params{linktype};
+ my $qualifier='';
+ if (defined $linktype) {
+ $qualifier=" with type $linktype";
+ }
my $links = $IkiWiki::links{$page};
- return IkiWiki::FailReason->new("$page has no links", "" => 1)
+ return IkiWiki::FailReason->new("$page has no links", $page => $IkiWiki::DEPEND_LINKS, "" => 1)
unless $links && @{$links};
my $bestlink = IkiWiki::bestlink($from, $link);
foreach my $p (@{$links}) {
if (length $bestlink) {
- return IkiWiki::SuccessReason->new("$page links to $link", $page => $IkiWiki::DEPEND_LINKS, "" => 1)
- if $bestlink eq IkiWiki::bestlink($page, $p);
+ if ((!defined $linktype || exists $IkiWiki::typedlinks{$page}{$linktype}{$p}) && $bestlink eq IkiWiki::bestlink($page, $p)) {
+ return IkiWiki::SuccessReason->new("$page links to $link$qualifier", $page => $IkiWiki::DEPEND_LINKS, "" => 1)
+ }
}
else {
- return IkiWiki::SuccessReason->new("$page links to page $p matching $link", $page => $IkiWiki::DEPEND_LINKS, "" => 1)
- if match_glob($p, $link, %params);
+ if ((!defined $linktype || exists $IkiWiki::typedlinks{$page}{$linktype}{$p}) && match_glob($p, $link, %params)) {
+ return IkiWiki::SuccessReason->new("$page links to page $p$qualifier, matching $link", $page => $IkiWiki::DEPEND_LINKS, "" => 1)
+ }
my ($p_rel)=$p=~/^\/?(.*)/;
$link=~s/^\///;
- return IkiWiki::SuccessReason->new("$page links to page $p_rel matching $link", $page => $IkiWiki::DEPEND_LINKS, "" => 1)
- if match_glob($p_rel, $link, %params);
+ if ((!defined $linktype || exists $IkiWiki::typedlinks{$page}{$linktype}{$p_rel}) && match_glob($p_rel, $link, %params)) {
+ return IkiWiki::SuccessReason->new("$page links to page $p_rel$qualifier, matching $link", $page => $IkiWiki::DEPEND_LINKS, "" => 1)
+ }
}
}
- return IkiWiki::FailReason->new("$page does not link to $link", "" => 1);
+ return IkiWiki::FailReason->new("$page does not link to $link$qualifier", $page => $IkiWiki::DEPEND_LINKS, "" => 1);
}
sub match_backlink ($$;@) {