]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blobdiff - IkiWiki.pm
formatting
[git.ikiwiki.info.git] / IkiWiki.pm
index 7547f175115753abfede918cdaf10c166a9c7c82..2cad6a3ef4333c782e5ccfb83c3e828f8ed19e17 100644 (file)
@@ -14,7 +14,7 @@ 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
@@ -24,7 +24,7 @@ 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
@@ -37,7 +37,7 @@ our $DEPEND_LINKS=4;
 # Optimisation.
 use Memoize;
 memoize("abs2rel");
-memoize("cmpspec_translate");
+memoize("sortspec_translate");
 memoize("pagespec_translate");
 memoize("template_file");
 
@@ -1165,7 +1165,7 @@ sub htmlize ($$$$) {
        my $content=shift;
        
        my $oneline = $content !~ /\n/;
-
+       
        if (exists $hooks{htmlize}{$type}) {
                $content=$hooks{htmlize}{$type}{call}->(
                        page => $page,
@@ -1186,10 +1186,9 @@ sub htmlize ($$$$) {
        
        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;
@@ -1504,7 +1503,7 @@ sub loadindex () {
        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")) {
@@ -1570,6 +1569,14 @@ sub loadindex () {
                        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}}];
        }
@@ -1618,6 +1625,10 @@ sub saveindex () {
                        $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}}) {
@@ -1797,7 +1808,7 @@ sub add_depends ($$;$) {
 
        # 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;
@@ -1927,15 +1938,20 @@ sub inject {
        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 cmpspec_translate ($) {
+sub sortspec_translate ($) {
        my $spec = shift;
 
        my $code = "";
@@ -1972,13 +1988,13 @@ sub cmpspec_translate ($) {
                        $code .= "-";
                }
 
-               if (exists $IkiWiki::PageSpec::{"cmp_$word"}) {
+               if (exists $IkiWiki::SortSpec::{"cmp_$word"}) {
                        if (defined $params) {
                                push @data, $params;
-                               $code .= "IkiWiki::PageSpec::cmp_$word(\@_, \$data[$#data])";
+                               $code .= "IkiWiki::SortSpec::cmp_$word(\$data[$#data])";
                        }
                        else {
-                               $code .= "IkiWiki::PageSpec::cmp_$word(\@_, undef)";
+                               $code .= "IkiWiki::SortSpec::cmp_$word(undef)";
                        }
                }
                else {
@@ -2062,7 +2078,7 @@ sub pagespec_match ($$;@) {
 
        my $sub=pagespec_translate($spec);
        return IkiWiki::ErrorReason->new("syntax error in pagespec \"$spec\"")
-               if $@ || ! defined $sub;
+               if ! defined $sub;
        return $sub->($page, @params);
 }
 
@@ -2080,7 +2096,7 @@ sub pagespec_match_list ($$;@) {
 
        my $sub=pagespec_translate($pagespec);
        error "syntax error in pagespec \"$pagespec\""
-               if $@ || ! defined $sub;
+               if ! defined $sub;
 
        my @candidates;
        if (exists $params{list}) {
@@ -2095,9 +2111,8 @@ sub pagespec_match_list ($$;@) {
        }
 
        if (defined $params{sort}) {
-               my $f = cmpspec_translate($params{sort});
-
-               @candidates = sort { $f->($a, $b) } @candidates;
+               @candidates = IkiWiki::SortSpec::sort_pages($params{sort},
+                       @candidates);
        }
 
        @candidates=reverse(@candidates) if $params{reverse};
@@ -2135,8 +2150,7 @@ sub pagespec_match_list ($$;@) {
 sub pagespec_valid ($) {
        my $spec=shift;
 
-       my $sub=pagespec_translate($spec);
-       return ! $@;
+       return defined pagespec_translate($spec);
 }
 
 sub glob2re ($) {
@@ -2256,26 +2270,34 @@ sub match_link ($$;@) {
 
        $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 ($$;@) {
@@ -2410,13 +2432,23 @@ sub match_ip ($$;@) {
        }
 }
 
+package IkiWiki::SortSpec;
+
+# This is in the SortSpec namespace so that the $a and $b that sort() uses
+# are easily available in this namespace, for cmp functions to use them.
+sub sort_pages {
+       my $f = IkiWiki::sortspec_translate(shift);
+
+       return sort $f @_;
+}
+
 sub cmp_title {
-       IkiWiki::pagetitle(IkiWiki::basename($_[0]))
+       IkiWiki::pagetitle(IkiWiki::basename($a))
        cmp
-       IkiWiki::pagetitle(IkiWiki::basename($_[1]))
+       IkiWiki::pagetitle(IkiWiki::basename($b))
 }
 
-sub cmp_mtime { $IkiWiki::pagemtime{$_[1]} <=> $IkiWiki::pagemtime{$_[0]} }
-sub cmp_age { $IkiWiki::pagectime{$_[1]} <=> $IkiWiki::pagectime{$_[0]} }
+sub cmp_mtime { $IkiWiki::pagemtime{$b} <=> $IkiWiki::pagemtime{$a} }
+sub cmp_age { $IkiWiki::pagectime{$b} <=> $IkiWiki::pagectime{$a} }
 
 1