Merge branch 'autotag'
commit
3ee571390e
14
IkiWiki.pm
14
IkiWiki.pm
|
@ -14,7 +14,8 @@ 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 %typedlinks %oldtypedlinks};
|
||||
%forcerebuild %loaded_plugins %typedlinks %oldtypedlinks
|
||||
%autofiles};
|
||||
|
||||
use Exporter q{import};
|
||||
our @EXPORT = qw(hook debug error template htmlpage deptype
|
||||
|
@ -22,7 +23,7 @@ our @EXPORT = qw(hook debug error template htmlpage deptype
|
|||
htmllink readfile writefile pagetype srcfile pagename
|
||||
displaytime will_render gettext ngettext urlto targetpage
|
||||
add_underlay pagetitle titlepage linkpage newpagefile
|
||||
inject add_link
|
||||
inject add_link add_autofile
|
||||
%config %links %pagestate %wikistate %renderedfiles
|
||||
%pagesources %destsources %typedlinks);
|
||||
our $VERSION = 3.00; # plugin interface version, next is ikiwiki version
|
||||
|
@ -1952,6 +1953,15 @@ sub add_link ($$;$) {
|
|||
}
|
||||
}
|
||||
|
||||
sub add_autofile ($$$) {
|
||||
my $file=shift;
|
||||
my $plugin=shift;
|
||||
my $generator=shift;
|
||||
|
||||
$autofiles{$file}{plugin}=$plugin;
|
||||
$autofiles{$file}{generator}=$generator;
|
||||
}
|
||||
|
||||
sub sortspec_translate ($$) {
|
||||
my $spec = shift;
|
||||
my $reverse = shift;
|
||||
|
|
|
@ -34,9 +34,16 @@ sub getsetup () {
|
|||
safe => 1,
|
||||
rebuild => 1,
|
||||
},
|
||||
tag_autocreate => {
|
||||
type => "boolean",
|
||||
example => 1,
|
||||
description => "autocreate new tag pages?",
|
||||
safe => 1,
|
||||
rebuild => undef,
|
||||
},
|
||||
}
|
||||
|
||||
sub tagpage ($) {
|
||||
sub taglink ($) {
|
||||
my $tag=shift;
|
||||
|
||||
if ($tag !~ m{^/} &&
|
||||
|
@ -48,13 +55,46 @@ sub tagpage ($) {
|
|||
return $tag;
|
||||
}
|
||||
|
||||
sub taglink ($$$;@) {
|
||||
sub htmllink_tag ($$$;@) {
|
||||
my $page=shift;
|
||||
my $destpage=shift;
|
||||
my $tag=shift;
|
||||
my %opts=@_;
|
||||
|
||||
return htmllink($page, $destpage, tagpage($tag), %opts);
|
||||
return htmllink($page, $destpage, taglink($tag), %opts);
|
||||
}
|
||||
|
||||
sub gentag ($) {
|
||||
my $tag=shift;
|
||||
|
||||
if ($config{tag_autocreate} ||
|
||||
($config{tagbase} && ! defined $config{tag_autocreate})) {
|
||||
my $tagpage=taglink($tag);
|
||||
if ($tagpage=~/^\.\/(.*)/) {
|
||||
$tagpage=$1;
|
||||
}
|
||||
else {
|
||||
$tagpage=~s/^\///;
|
||||
}
|
||||
|
||||
my $tagfile = newpagefile($tagpage, $config{default_pageext});
|
||||
|
||||
add_autofile($tagfile, "tag", sub {
|
||||
my $message=sprintf(gettext("creating tag page %s"), $tagpage);
|
||||
debug($message);
|
||||
|
||||
my $template=template("autotag.tmpl");
|
||||
$template->param(tagname => IkiWiki::basename($tag));
|
||||
$template->param(tag => $tag);
|
||||
writefile($tagfile, $config{srcdir}, $template->output);
|
||||
if ($config{rcs}) {
|
||||
IkiWiki::disable_commit_hook();
|
||||
IkiWiki::rcs_add($tagfile);
|
||||
IkiWiki::rcs_commit_staged($message, undef, undef);
|
||||
IkiWiki::enable_commit_hook();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
sub preprocess_tag (@) {
|
||||
|
@ -69,8 +109,11 @@ sub preprocess_tag (@) {
|
|||
|
||||
foreach my $tag (keys %params) {
|
||||
$tag=linkpage($tag);
|
||||
|
||||
# hidden WikiLink
|
||||
add_link($page, tagpage($tag), 'tag');
|
||||
add_link($page, taglink($tag), 'tag');
|
||||
|
||||
gentag($tag);
|
||||
}
|
||||
|
||||
return "";
|
||||
|
@ -84,14 +127,16 @@ sub preprocess_taglink (@) {
|
|||
return join(" ", map {
|
||||
if (/(.*)\|(.*)/) {
|
||||
my $tag=linkpage($2);
|
||||
add_link($params{page}, tagpage($tag), 'tag');
|
||||
return taglink($params{page}, $params{destpage}, $tag,
|
||||
add_link($params{page}, taglink($tag), 'tag');
|
||||
gentag($tag);
|
||||
return htmllink_tag($params{page}, $params{destpage}, $tag,
|
||||
linktext => pagetitle($1));
|
||||
}
|
||||
else {
|
||||
my $tag=linkpage($_);
|
||||
add_link($params{page}, tagpage($tag), 'tag');
|
||||
return taglink($params{page}, $params{destpage}, $tag);
|
||||
add_link($params{page}, taglink($tag), 'tag');
|
||||
gentag($tag);
|
||||
return htmllink_tag($params{page}, $params{destpage}, $tag);
|
||||
}
|
||||
}
|
||||
grep {
|
||||
|
@ -109,7 +154,7 @@ sub pagetemplate (@) {
|
|||
|
||||
$template->param(tags => [
|
||||
map {
|
||||
link => taglink($page, $destpage, $_, rel => "tag")
|
||||
link => htmllink_tag($page, $destpage, $_, rel => "tag")
|
||||
}, sort keys %$tags
|
||||
]) if defined $tags && %$tags && $template->query(name => "tags");
|
||||
|
||||
|
@ -126,8 +171,8 @@ package IkiWiki::PageSpec;
|
|||
|
||||
sub match_tagged ($$;@) {
|
||||
my $page=shift;
|
||||
my $glob=shift;
|
||||
return match_link($page, IkiWiki::Plugin::tag::tagpage($glob), linktype => 'tag', @_);
|
||||
my $glob=IkiWiki::Plugin::tag::taglink(shift);
|
||||
return match_link($page, $glob, linktype => 'tag', @_);
|
||||
}
|
||||
|
||||
1
|
||||
|
|
|
@ -286,13 +286,15 @@ sub find_src_files () {
|
|||
my %pages;
|
||||
eval q{use File::Find};
|
||||
error($@) if $@;
|
||||
find({
|
||||
no_chdir => 1,
|
||||
wanted => sub {
|
||||
|
||||
my ($page, $dir, $underlay);
|
||||
my $helper=sub {
|
||||
my $file=decode_utf8($_);
|
||||
$file=~s/^\Q$config{srcdir}\E\/?//;
|
||||
return if -l $_ || -d _ || ! length $file;
|
||||
my $page = pagename($file);
|
||||
|
||||
return if -l $file || -d _;
|
||||
$file=~s/^\Q$dir\E\/?//;
|
||||
return if ! length $file;
|
||||
$page = pagename($file);
|
||||
if (! exists $pagesources{$page} &&
|
||||
file_pruned($file)) {
|
||||
$File::Find::prune=1;
|
||||
|
@ -303,6 +305,16 @@ sub find_src_files () {
|
|||
if (! defined $f) {
|
||||
warn(sprintf(gettext("skipping bad filename %s"), $file)."\n");
|
||||
}
|
||||
|
||||
if ($underlay) {
|
||||
# avoid underlaydir override attacks; see security.mdwn
|
||||
if (! -l "$config{srcdir}/$f" && ! -e _) {
|
||||
if (! $pages{$page}) {
|
||||
push @files, $f;
|
||||
$pages{$page}=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
push @files, $f;
|
||||
if ($pages{$page}) {
|
||||
|
@ -310,39 +322,18 @@ sub find_src_files () {
|
|||
}
|
||||
$pages{$page}=1;
|
||||
}
|
||||
},
|
||||
}, $config{srcdir});
|
||||
foreach my $dir (@{$config{underlaydirs}}, $config{underlaydir}) {
|
||||
};
|
||||
|
||||
find({
|
||||
no_chdir => 1,
|
||||
wanted => sub {
|
||||
my $file=decode_utf8($_);
|
||||
$file=~s/^\Q$dir\E\/?//;
|
||||
return if -l $_ || -d _ || ! length $file;
|
||||
my $page=pagename($file);
|
||||
if (! exists $pagesources{$page} &&
|
||||
file_pruned($file)) {
|
||||
$File::Find::prune=1;
|
||||
return;
|
||||
}
|
||||
|
||||
my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint
|
||||
if (! defined $f) {
|
||||
warn(sprintf(gettext("skipping bad filename %s"), $file)."\n");
|
||||
}
|
||||
else {
|
||||
# avoid underlaydir override
|
||||
# attacks; see security.mdwn
|
||||
if (! -l "$config{srcdir}/$f" &&
|
||||
! -e _) {
|
||||
if (! $pages{$page}) {
|
||||
push @files, $f;
|
||||
$pages{$page}=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}, $dir);
|
||||
wanted => $helper,
|
||||
}, $dir=$config{srcdir});
|
||||
$underlay=1;
|
||||
foreach (@{$config{underlaydirs}}, $config{underlaydir}) {
|
||||
find({
|
||||
no_chdir => 1,
|
||||
wanted => $helper,
|
||||
}, $dir=$_);
|
||||
};
|
||||
return \@files, \%pages;
|
||||
}
|
||||
|
@ -686,6 +677,49 @@ sub render_backlinks ($) {
|
|||
}
|
||||
}
|
||||
|
||||
sub gen_autofile ($$$) {
|
||||
my $autofile=shift;
|
||||
my $pages=shift;
|
||||
my $del=shift;
|
||||
|
||||
if (file_pruned($autofile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
my ($file)="$config{srcdir}/$autofile" =~ /$config{wiki_file_regexp}/; # untaint
|
||||
if (! defined $file) {
|
||||
return;
|
||||
}
|
||||
|
||||
# Remember autofiles that were tried, and never try them again later.
|
||||
if (exists $wikistate{$autofiles{$autofile}{plugin}}{autofile}{$autofile}) {
|
||||
return;
|
||||
}
|
||||
$wikistate{$autofiles{$autofile}{plugin}}{autofile}{$autofile}=1;
|
||||
|
||||
if (srcfile($autofile, 1) || file_pruned($autofile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (-l $file || -d _ || -e _) {
|
||||
return;
|
||||
}
|
||||
|
||||
my $page = pagename($file);
|
||||
if ($pages->{$page}) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (grep { $_ eq $autofile } @$del) {
|
||||
return;
|
||||
}
|
||||
|
||||
$autofiles{$autofile}{generator}->();
|
||||
$pages->{$page}=1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
sub refresh () {
|
||||
srcdir_check();
|
||||
run_hooks(refresh => sub { shift->() });
|
||||
|
@ -700,6 +734,16 @@ sub refresh () {
|
|||
scan($file);
|
||||
}
|
||||
|
||||
foreach my $autofile (keys %autofiles) {
|
||||
if (gen_autofile($autofile, $pages, $del)) {
|
||||
push @{$files}, $autofile;
|
||||
push @{$new}, $autofile if find_new_files([$autofile]);
|
||||
push @{$changed}, $autofile if find_changed([$autofile]);
|
||||
|
||||
scan($autofile);
|
||||
}
|
||||
}
|
||||
|
||||
calculate_links();
|
||||
|
||||
remove_del(@$del, @$internal_del);
|
||||
|
|
|
@ -11,6 +11,10 @@ ikiwiki (3.20100422) unstable; urgency=low
|
|||
not regular wikilinks. If your wiki accidentially relied on the old,
|
||||
buggy behavior, you might need to change pagespecs to use `link()`.
|
||||
|
||||
Tag pages can automatically be created as new tags are used. This
|
||||
feature is enabled by default if you have configured a tagbase. It
|
||||
can be turned on or off using the `tag_autocreate` setting.
|
||||
|
||||
The title_natural sort method (as used by the inline directive, etc)
|
||||
have been moved to the new sortnaturally plugin, which is not enabled
|
||||
by default since it requires the Sort::Naturally perl module.
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
ikiwiki (3.20100422) UNRELEASED; urgency=low
|
||||
|
||||
[ Joey Hess ]
|
||||
* tag: Automatic creation of tag pages can now be enabled using
|
||||
the tag_autocreate setting. (David Riebenbauer)
|
||||
* bzr: Fix bzr log parsing to work with bzr 2.0. (liw)
|
||||
* comments: Fix missing entity encoding in title.
|
||||
* txt: Add a special case for robots.txt.
|
||||
|
|
|
@ -19,7 +19,8 @@ instead:
|
|||
Note that if the wiki is configured to use a tagbase, then the tags will be
|
||||
located under a base directory, such as "tags/". This is a useful way to
|
||||
avoid having to write the full path to tags, if you want to keep them
|
||||
grouped together out of the way.
|
||||
grouped together out of the way. Also, since ikiwiki then knows where to put
|
||||
tags, it will automatically create tag pages when new tags are used.
|
||||
|
||||
Bear in mind that specifying a tagbase means you will need to incorporate it
|
||||
into the `link()` [[ikiwiki/PageSpec]] you use: e.g., if your tagbase is
|
||||
|
|
|
@ -8,6 +8,13 @@ These directives allow tagging pages.
|
|||
It also provides the `tagged()` [[ikiwiki/PageSpec]], which can be used to
|
||||
match pages that are tagged with a specific tag.
|
||||
|
||||
The `tagbase` setting can be used to make tags default to being put in a
|
||||
particular subdirectory.
|
||||
|
||||
The `tag_autocreate` setting can be used to control whether new tag pages
|
||||
are created as needed. It defaults to being done only if a `tagbase` is
|
||||
set.
|
||||
|
||||
[[!if test="enabled(tag)" then="""
|
||||
This wiki has the tag plugin enabled, so you'll see a note below that this
|
||||
page is tagged with the "tags" tag.
|
||||
|
|
|
@ -28,3 +28,4 @@ See [[todo/auto-create tag pages according to a template]]
|
|||
|
||||
-- Jeremy Schultz <jeremy.schultz@uleth.ca>
|
||||
|
||||
`tag_autocreate` can now enable this. --[[Joey]]
|
||||
|
|
|
@ -966,6 +966,23 @@ added. Pass it the page that contains the link, and the link text.
|
|||
An optional third parameter sets the link type. If not specified,
|
||||
it is an ordinary [[ikiwiki/WikiLink]].
|
||||
|
||||
### `add_autofile($$$)`
|
||||
|
||||
Sometimes you may want to add a file to the `srcdir` as a result of content
|
||||
of other pages. For example, [[plugins/tag]] pages can be automatically
|
||||
created as needed. This function can be used to do that.
|
||||
|
||||
The three parameters are the filename to create (relative to the `srcdir`),
|
||||
the name of the plugin, and a callback function. The callback will be
|
||||
called if it is appropriate to automatically add the file, and should then
|
||||
take care of creating it, and doing anything else it needs to (such as
|
||||
checking it into revision control). Note that the callback may not always
|
||||
be called. For example, if an automatically added file is deleted by the
|
||||
user, ikiwiki will avoid re-adding it again.
|
||||
|
||||
This function needs to be called during the scan hook, or earlier in the
|
||||
build process, in order to add the file early enough for it to be built.
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
### Internal use pages
|
||||
|
|
|
@ -78,6 +78,7 @@ Probably incomplete list:
|
|||
* Make pagespecs match relative by default? (see [[discussion]])
|
||||
* Flip wikilinks? (see [[todo/link_plugin_perhaps_too_general?]])
|
||||
* YADA format setup files per default?
|
||||
* Enable `tag_autocreate` by default.
|
||||
|
||||
In general, we try to use [[ikiwiki-transition]] or forced rebuilds on
|
||||
upgrade to deal with changes that break compatability. Some things that
|
||||
|
|
|
@ -247,3 +247,5 @@ I've tested it fairly thouroughly. --[[Joey]]
|
|||
[da5d29f95f6e693e8c14be1b896cf25cf4fdb3c0]: http://git.liegesta.at/?p=ikiwiki.git;a=commitdiff;h=da5d29f95f6e693e8c14be1b896cf25cf4fdb3c0 (commitdiff for da5d29f95f6e693e8c14be1b896cf25cf4fdb3c0)
|
||||
[a358d74bef51dae31332ff27e897fe04834571e6]: http://git.liegesta.at/?p=ikiwiki.git;a=commitdiff;h=a358d74bef51dae31332ff27e897fe04834571e6 (commitdiff for a358d74bef51dae31332ff27e897fe04834571e6)
|
||||
[981400177d68a279f485727be3f013e68f0bf691]: http://git.liegesta.at/?p=ikiwiki.git;a=commitdiff;h=981400177d68a279f485727be3f013e68f0bf691 (commitdiff for 981400177d68a279f485727be3f013e68f0bf691)
|
||||
|
||||
[[!tag done]]
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
## Pages tagged <TMPL_VAR TAGNAME> ##
|
||||
|
||||
[[!inline pages="tagged(<TMPL_VAR TAG>)" actions="no" archive="yes"]]
|
Loading…
Reference in New Issue