X-Git-Url: https://sipb.mit.edu/gitweb.cgi/ikiwiki.git/blobdiff_plain/1202b4fd7b305b223d64f9e9f24424b72c81ab6d..fb802f8d2d58b92fd8f47137f8b29cb3970441f3:/IkiWiki.pm diff --git a/IkiWiki.pm b/IkiWiki.pm index 763f24e6c..1c310d391 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -5,19 +5,23 @@ use warnings; use strict; use Encode; use HTML::Entities; +use URI::Escape q{uri_escape_utf8}; +use POSIX; use open qw{:utf8 :std}; -use vars qw{%config %links %oldlinks %oldpagemtime %pagectime %pagecase - %renderedfiles %oldrenderedfiles %pagesources %depends %hooks - %forcerebuild $gettext_obj}; +use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase + %renderedfiles %oldrenderedfiles %pagesources %destsources + %depends %hooks %forcerebuild $gettext_obj}; use Exporter q{import}; our @EXPORT = qw(hook debug error template htmlpage add_depends pagespec_match bestlink htmllink readfile writefile pagetype srcfile pagename - displaytime will_render gettext + displaytime will_render gettext urlto targetpage %config %links %renderedfiles %pagesources); our $VERSION = 1.02; # plugin interface version, next is ikiwiki version -our $version="1.45";my $installdir="/usr"; +our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE +my $installdir=''; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE + # Optimisation. use Memoize; memoize("abs2rel"); @@ -71,6 +75,8 @@ sub defaultconfig () { #{{{ sslcookie => 0, httpauth => 0, userdir => "", + usedirs => 0, + numbacklinks => 10, } #}}} sub checkconfig () { #{{{ @@ -80,8 +86,6 @@ sub checkconfig () { #{{{ delete $ENV{LC_ALL}; } if (defined $config{locale}) { - eval q{use POSIX}; - error($@) if $@; if (POSIX::setlocale(&POSIX::LC_ALL, $config{locale})) { $ENV{LANG}=$config{locale}; $gettext_obj=undef; @@ -149,7 +153,7 @@ sub error ($;$) { #{{{ print misctemplate(gettext("Error"), "

".gettext("Error").": $message

"); } - log_message(debug => $message) if $config{syslog}; + log_message('err' => $message) if $config{syslog}; if (defined $cleaner) { $cleaner->(); } @@ -174,7 +178,7 @@ sub log_message ($$) { #{{{ } eval { Sys::Syslog::syslog($type, "%s", join(" ", @_)); - } + }; } elsif (! $config{cgi}) { print "@_\n"; @@ -222,10 +226,21 @@ sub pagename ($) { #{{{ return $page; } #}}} -sub htmlpage ($) { #{{{ +sub targetpage ($$) { #{{{ my $page=shift; + my $ext=shift; + + if (! $config{usedirs} || $page =~ /^index$/ ) { + return $page.".".$ext; + } else { + return $page."/index.".$ext; + } +} #}}} - return $page.".html"; +sub htmlpage ($) { #{{{ + my $page=shift; + + return targetpage($page, "html"); } #}}} sub srcfile ($) { #{{{ @@ -233,7 +248,7 @@ sub srcfile ($) { #{{{ return "$config{srcdir}/$file" if -e "$config{srcdir}/$file"; return "$config{underlaydir}/$file" if -e "$config{underlaydir}/$file"; - error("internal error: $file cannot be found"); + error("internal error: $file cannot be found in $config{srcdir} or $config{underlaydir}"); } #}}} sub readfile ($;$$) { #{{{ @@ -314,9 +329,13 @@ sub will_render ($$;$) { #{{{ $renderedfiles{$page}=[$dest, grep { $_ ne $dest } @{$renderedfiles{$page}}]; } else { + foreach my $old (@{$renderedfiles{$page}}) { + delete $destsources{$old}; + } $renderedfiles{$page}=[$dest]; $cleared{$page}=1; } + $destsources{$dest}=$page; } #}}} sub bestlink ($$) { #{{{ @@ -376,10 +395,17 @@ sub titlepage ($) { #{{{ return $title; } #}}} +sub linkpage ($) { #{{{ + my $link=shift; + $link=~s/([^-[:alnum:]:+\/._])/$1 eq ' ' ? '_' : "__".ord($1)."__"/eg; + return $link; +} #}}} + sub cgiurl (@) { #{{{ my %params=@_; - return $config{cgiurl}."?".join("&", map "$_=$params{$_}", keys %params); + return $config{cgiurl}."?". + join("&", map $_."=".uri_escape_utf8($params{$_}), keys %params); } #}}} sub baseurl (;$) { #{{{ @@ -387,6 +413,7 @@ sub baseurl (;$) { #{{{ return "$config{url}/" if ! defined $page; + $page=htmlpage($page); $page=~s/[^\/]+$//; $page=~s/[^\/]+\//..\//g; return $page; @@ -408,14 +435,38 @@ sub abs2rel ($$) { #{{{ sub displaytime ($) { #{{{ my $time=shift; - eval q{use POSIX}; - error($@) if $@; # strftime doesn't know about encodings, so make sure # its output is properly treated as utf8 return decode_utf8(POSIX::strftime( $config{timeformat}, localtime($time))); } #}}} +sub beautify_url ($) { #{{{ + my $url=shift; + + $url =~ s!/index.html$!/!; + $url =~ s!^$!./!; # Browsers don't like empty links... + + return $url; +} #}}} + +sub urlto ($$) { #{{{ + my $to=shift; + my $from=shift; + + if (! length $to) { + return beautify_url(baseurl($from)); + } + + if (! $destsources{$to}) { + $to=htmlpage($to); + } + + my $link = abs2rel($to, dirname(htmlpage($from))); + + return beautify_url($link); +} #}}} + sub htmllink ($$$;@) { #{{{ my $lpage=shift; # the page doing the linking my $page=shift; # the page that will contain the link (different for inline) @@ -441,17 +492,23 @@ sub htmllink ($$$;@) { #{{{ return "$linktext" if length $bestlink && $page eq $bestlink; - if (! grep { $_ eq $bestlink } map { @{$_} } values %renderedfiles) { + if (! $destsources{$bestlink}) { $bestlink=htmlpage($bestlink); - } - if (! grep { $_ eq $bestlink } map { @{$_} } values %renderedfiles) { - return $linktext unless length $config{cgiurl}; - return " "create", page => lc($link), from => $page). - "\">?$linktext" + + if (! $destsources{$bestlink}) { + return $linktext unless length $config{cgiurl}; + return " "create", + page => pagetitle(lc($link), 1), + from => $lpage + ). + "\">?$linktext" + } } - $bestlink=abs2rel($bestlink, dirname($page)); + $bestlink=abs2rel($bestlink, dirname(htmlpage($page))); + $bestlink=beautify_url($bestlink); if (! $opts{noimageinline} && isinlinableimage($bestlink)) { return "\"$linktext\""; @@ -496,8 +553,14 @@ sub linkify ($$$) { #{{{ $content =~ s{(\\?)$config{wiki_link_regexp}}{ defined $2 - ? ( $1 ? "[[$2|$3]]" : htmllink($lpage, $page, titlepage($3), anchor => $4, linktext => pagetitle($2))) - : ( $1 ? "[[$3]]" : htmllink($lpage, $page, titlepage($3), anchor => $4)) + ? ( $1 + ? "[[$2|$3".($4 ? "#$4" : "")."]]" + : htmllink($lpage, $page, linkpage($3), + anchor => $4, linktext => pagetitle($2))) + : ( $1 + ? "[[$3".($4 ? "#$4" : "")."]]" + : htmllink($lpage, $page, linkpage($3), + anchor => $4)) }eg; return $content; @@ -660,10 +723,11 @@ sub loadindex () { #{{{ my $page=pagename($items{src}[0]); if (! $config{rebuild}) { $pagesources{$page}=$items{src}[0]; - $oldpagemtime{$page}=$items{mtime}[0]; + $pagemtime{$page}=$items{mtime}[0]; $oldlinks{$page}=[@{$items{link}}]; $links{$page}=[@{$items{link}}]; $depends{$page}=$items{depends}[0] if exists $items{depends}; + $destsources{$_}=$page foreach @{$items{dest}}; $renderedfiles{$page}=[@{$items{dest}}]; $oldrenderedfiles{$page}=[@{$items{dest}}]; $pagecase{lc $page}=$page; @@ -682,9 +746,9 @@ sub saveindex () { #{{{ my $newfile="$config{wikistatedir}/index.new"; my $cleanup = sub { unlink($newfile) }; open (OUT, ">$newfile") || error("cannot write to $newfile: $!", $cleanup); - foreach my $page (keys %oldpagemtime) { - next unless $oldpagemtime{$page}; - my $line="mtime=$oldpagemtime{$page} ". + foreach my $page (keys %pagemtime) { + next unless $pagemtime{$page}; + my $line="mtime=$pagemtime{$page} ". "ctime=$pagectime{$page} ". "src=$pagesources{$page}"; $line.=" dest=$_" foreach @{$renderedfiles{$page}}; @@ -909,7 +973,7 @@ sub pagespec_translate ($) { #{{{ } elsif ($word =~ /^(\w+)\((.*)\)$/) { if (exists $IkiWiki::PageSpec::{"match_$1"}) { - $code.=" IkiWiki::PageSpec::match_$1(\$page, ".safequote($2).")"; + $code.="IkiWiki::PageSpec::match_$1(\$page, ".safequote($2).", \$from)"; } else { $code.=" 0"; @@ -956,22 +1020,36 @@ sub match_glob ($$$) { #{{{ return $page=~/^$glob$/i; } #}}} -sub match_link ($$) { #{{{ +sub match_link ($$$) { #{{{ my $page=shift; my $link=lc(shift); + my $from=shift; + if (! defined $from){ + $from = ""; + } + + # relative matching + if ($link =~ m!^\.! && defined $from) { + $from=~s!/?[^/]+$!!; + $link=~s!^\./!!; + $link="$from/$link" if length $from; + } my $links = $IkiWiki::links{$page} or return undef; + return 0 unless @$links; + my $bestlink = IkiWiki::bestlink($from, $link); + return 0 unless length $bestlink; foreach my $p (@$links) { - return 1 if lc $p eq $link; + return 1 if $bestlink eq IkiWiki::bestlink($page, $p); } return 0; } #}}} -sub match_backlink ($$) { #{{{ - match_link(pop, pop); +sub match_backlink ($$$) { #{{{ + match_link($_[1], $_[0], $_[3]); } #}}} -sub match_created_before ($$) { #{{{ +sub match_created_before ($$$) { #{{{ my $page=shift; my $testpage=shift; @@ -983,7 +1061,7 @@ sub match_created_before ($$) { #{{{ } } #}}} -sub match_created_after ($$) { #{{{ +sub match_created_after ($$$) { #{{{ my $page=shift; my $testpage=shift; @@ -995,15 +1073,15 @@ sub match_created_after ($$) { #{{{ } } #}}} -sub match_creation_day ($$) { #{{{ +sub match_creation_day ($$$) { #{{{ return ((gmtime($IkiWiki::pagectime{shift()}))[3] == shift); } #}}} -sub match_creation_month ($$) { #{{{ +sub match_creation_month ($$$) { #{{{ return ((gmtime($IkiWiki::pagectime{shift()}))[4] + 1 == shift); } #}}} -sub match_creation_year ($$) { #{{{ +sub match_creation_year ($$$) { #{{{ return ((gmtime($IkiWiki::pagectime{shift()}))[5] + 1900 == shift); } #}}}