hold onto your hats, full-fledged blogging has arrived in ikiwiki!

master
joey 2006-03-24 01:16:32 +00:00
parent ad4760ad78
commit 7b4600df3f
13 changed files with 237 additions and 56 deletions

View File

@ -85,11 +85,99 @@ sub rsspage ($) { #{{{
return $page.".rss";
} #}}}
sub postprocess { #{{{
# Takes content to postprocess followed by a list of postprocessor
# commands and subroutine references to run for the commands.
my $page=shift;
my $content=shift;
my %commands=@_;
my $handle=sub {
my $escape=shift;
my $command=shift;
my $params=shift;
if (length $escape) {
"[[$command $params]]";
}
elsif (exists $commands{$command}) {
my %params;
while ($params =~ /(\w+)=\"([^"]+)"(\s+|$)/g) {
$params{$1}=$2;
}
$commands{$command}->($page, %params);
}
else {
"[[bad directive $command]]";
}
};
$content =~ s{(\\?)$config{wiki_processor_regexp}}{$handle->($1, $2, $3)}eg;
return $content;
} #}}}
sub blog_list ($$) { #{{{
my $globlist=shift;
my $maxitems=shift;
my @list;
foreach my $page (keys %pagesources) {
if (globlist_match($page, $globlist)) {
push @list, $page;
}
}
@list=sort { $pagectime{$b} <=> $pagectime{$a} } @list;
return @list if @list <= $maxitems;
return @list[0..$maxitems - 1];
} #}}}
sub get_inline_content ($$) { #{{{
my $parentpage=shift;
my $page=shift;
my $file=$pagesources{$page};
my $type=pagetype($file);
if ($type ne 'unknown') {
return htmlize($type, linkify(readfile("$config{srcdir}/$file"), $parentpage));
}
else {
return "";
}
} #}}}
sub postprocess_html_inline { #{{{
my $parentpage=shift;
my %params=@_;
if (! exists $params{show}) {
$params{show}=10;
}
if (! exists $params{pages}) {
return "";
}
$inlinepages{$parentpage}=$params{pages};
my $template=HTML::Template->new(blind_cache => 1,
filename => "$config{templatedir}/inlinepage.tmpl");
my $ret="";
foreach my $page (blog_list($params{pages}, $params{show})) {
$template->param(pagelink => htmllink($parentpage, $page));
$template->param(content => get_inline_content($parentpage, $page));
$template->param(ctime => scalar(gmtime($pagectime{$page})));
$ret.=$template->output;
}
return $ret;
} #}}}
sub genpage ($$$) { #{{{
my $content=shift;
my $page=shift;
my $mtime=shift;
$content = postprocess($page, $content, inline => \&postprocess_html_inline);
my $title=pagetitle(basename($page));
my $template=HTML::Template->new(blind_cache => 1,
@ -134,6 +222,7 @@ sub date_822 ($) { #{{{
} #}}}
sub absolute_urls ($$) { #{{{
# sucky sub because rss sucks
my $content=shift;
my $url=shift;
@ -142,29 +231,56 @@ sub absolute_urls ($$) { #{{{
$content=~s/<a\s+href="(?!http:\/\/)([^"]+)"/<a href="$url$1"/ig;
$content=~s/<img\s+src="(?!http:\/\/)([^"]+)"/<img src="$url$1"/ig;
return $content;
} #}}}
} #}}}zo
sub genrss ($$$) { #{{{
my $content=shift;
my $page=shift;
my $mtime=shift;
my $url="$config{url}/".htmlpage($page);
my $template=HTML::Template->new(blind_cache => 1,
filename => "$config{templatedir}/rsspage.tmpl");
my @items;
my $isblog=0;
my $gen_blog=sub {
my $parentpage=shift;
my %params=@_;
if (! exists $params{show}) {
$params{show}=10;
}
if (! exists $params{pages}) {
return "";
}
$inlinepages{$parentpage}=$params{pages};
$isblog=1;
foreach my $page (blog_list($params{pages}, $params{show})) {
push @items, {
itemtitle => pagetitle(basename($page)),
itemurl => "$config{url}/$renderedfiles{$page}",
itempubdate => date_822($pagectime{$page}),
itemcontent => absolute_urls(get_inline_content($parentpage, $page), $url),
} if exists $renderedfiles{$page};
}
return "";
};
$content = postprocess($page, $content, inline => $gen_blog);
# Regular page gets a feed that is updated every time the
# page is changed, so the mtime is encoded in the guid.
my @items=(
{
itemtitle => pagetitle(basename($page)),
itemguid => "$url?mtime=$mtime",
itemurl => $url,
itempubdate => date_822($mtime),
itemcontent => absolute_urls($content, $url), # rss sucks
},
);
push @items, {
itemtitle => pagetitle(basename($page)),
itemguid => "$url?mtime=$mtime",
itemurl => $url,
itempubdate => date_822($mtime),
itemcontent => absolute_urls($content, $url),
} unless $isblog;
$template->param(
title => $config{wikiname},
@ -223,7 +339,7 @@ sub render ($) { #{{{
check_overwrite("$config{destdir}/".htmlpage($page), $page);
writefile("$config{destdir}/".htmlpage($page),
genpage($content, $page, mtime("$config{srcdir}/$file")));
genpage($content, $page, mtime("$config{srcdir}/$file")));
$oldpagemtime{$page}=time;
$renderedfiles{$page}=htmlpage($page);
@ -320,7 +436,7 @@ sub refresh () { #{{{
}
# if any files were added or removed, check to see if each page
# needs an update due to linking to them
# needs an update due to linking to them or inlining them.
# TODO: inefficient; pages may get rendered above and again here;
# problem is the bestlink may have changed and we won't know until
# now
@ -337,6 +453,12 @@ FILE: foreach my $file (@files) {
next FILE;
}
}
if (exists $inlinepages{$page} &&
globlist_match($p, $inlinepages{$page})) {
debug("rendering $file, which inlines $p");
render($file);
$rendered{$file}=1;
}
}
}
}

View File

@ -0,0 +1,8 @@
You can turn any page on this wiki into a weblog by inserting a
[[PostProcessorDirective]]. Like this:
\\[[inline pages="blog/*" show="10"]]
Any pages that match the specified [[GlobList]] (in the exaple, any
[[SubPages]] of "blog") will be part of the blog, and the newest 10
of them will appear in the page.

View File

@ -51,4 +51,9 @@ To link to any other web page, or to an email address, you can just put the url
----
Advanced users can use [[PostProcessorDirective]]s to do additional cool
stuff.
----
This style of text formatting is called [[MarkDown]].

View File

@ -0,0 +1,11 @@
Postprocessor directives are similar to a [[WikiLink]] in form, except they
contain spaces and parameters. The general form is:
\\[[directive param="value" param="value"]]
This gets expanded after the rest of the page is processed, and can be used
to transform the page in various ways.
Currently, these postprocessor directives are available:
* "inline" to make a [[blog]]

8
doc/blog.mdwn 100644
View File

@ -0,0 +1,8 @@
You can turn any page on this wiki into a weblog by inserting a
[[PostProcessorDirective]]. Like this:
\\[[inline pages="blog/*" show="10"]]
Any pages that match the specified [[GlobList]] (in the exaple, any
[[SubPages]] of "blog") will be part of the blog, and the newest 10
of them will appear in the page.

View File

@ -27,13 +27,6 @@ Currently implemented:
and is quite smart about converting it to html. The only additional markup
provided by ikiwiki aside from regular markdown is the [[WikiLink]].
* [[RSS]]
ikiwiki supports generating RSS (2.0) feed for individual pages. These
feeds can be subscribed to, to get an update when a page is changed.
(Support for proper blogs is also planned.)
* support for other file types
ikiwiki also supports files of any other type, including raw html, text,
@ -45,9 +38,21 @@ Currently implemented:
Arbitrarily deep hierarchies of pages with fairly simple and useful [[SubPage/LinkingRUles]]
* [[blog]]s
You can turn any page in the wiki into a [[blog]]. Pages with names
matching a specified [[GlobList]] will be displayed as a weblog within
the blog page. And an RSS feed can be generated to follow the blog.
ikiwiki also supports generating RSS feed for individual pages that
do not contain a [[blog]]. These feeds can be used to be sent a new
version of a page when it is changed.
* Fast compiler
ikiwiki is fast and smart about updating a wiki, it only builds pages that have changed (and tracks things like creation of new pages and links that can indirectly cause a page to need a rebuild)
ikiwiki is fast and smart about updating a wiki, it only builds pages
that have changed (and tracks things like creation of new pages and links
that can indirectly cause a page to need a rebuild)
* [[Templates]]

View File

@ -51,4 +51,9 @@ To link to any other web page, or to an email address, you can just put the url
----
Advanced users can use [[PostProcessorDirective]]s to do additional cool
stuff.
----
This style of text formatting is called [[MarkDown]].

View File

@ -0,0 +1,11 @@
Postprocessor directives are similar to a [[WikiLink]] in form, except they
contain spaces and parameters. The general form is:
\\[[directive param="value" param="value"]]
This gets expanded after the rest of the page is processed, and can be used
to transform the page in various ways.
Currently, these postprocessor directives are available:
* "inline" to make a [[blog]]

View File

@ -36,3 +36,12 @@ Bulleted list
[[WikiLink]]
[[SandBox/SubPage]] -- a page under this one.
----
This sandbox is also a [[blog]]! Any subpage of this page is automatically
added to the blog below.
----
[[inline pages="sandbox/*" show="5"]]

View File

@ -61,38 +61,15 @@ that linked back to it could be added to the page. However, doing linkbacks
also needs to tie into the main logic, to determine what pages need to be
renered, so maybe that won't be a plugin.
## blogging and rss
## blogging
The wiki should emit rss feeds for pages. The simple case is a regular
page (done). The complex case is a blog composed of multiple pages.
### multi-page blog
This also takes care of the feature of wanting to make a wiki page
comprised of several sub-pages that can be independantly edited. Add a
token that can be embedded into a page and that specifies a [[GlobList]] of
pages. Now when any page matching the globs changes, this page must be
updated too.
For the html rendering, just embed the most recently created N pages in the
[[GlobList]], with the title of each being a link to the individual page,
plus a link to an additional page that lists all the titles of every
matching page in creation order (archives). Plus at the bottom a small web
form that prompts for a title and allows creating a new page for a new blog
post.
For the rss rendering, generate a proper weblog of the same pages.
Of course for permalinks use the links to the subpages.
Note that this allows for weblogs with different sections, etc.
Requirements:
* Need to keep track of the globlists in the index file.
* Need to pick a good token and note that the token will need to be passed
multiple parameters. Possibly something like this:
[[inline pages="myblog/*" show="30"]]
- Add a small form at top and bottom of a blog to allow entering
a title for a new item, that goes to a template to create the new page.
- Add a link to the end of a blog to go to the archives; this would
probably best be another cgi script, to avoid needing to generate big
static pages for little used archives.
- Should probably add params to control various rss fields like the blog
title, its author email, its copyright info, etc.
## revisit case
@ -161,6 +138,11 @@ exposing ones from the underlaydir. Will need to make sure that the mtime
for the source file is zeroed when the page is removed, and that it then
finds the underlay file and treats it as newer.
## wikilinks features
- \[[John|Fred]] is a Wikipedia method for linking to the one page
while displaying it as the other, Kyle would like this.
## Logo
ikiwiki needs a logo. I'm thinking something simple like the word "ikiwiki"

13
ikiwiki
View File

@ -9,7 +9,7 @@ use HTML::Template;
use lib '.'; # For use without installation, removed by Makefile.
use vars qw{%config %links %oldlinks %oldpagemtime %pagectime
%renderedfiles %pagesources};
%renderedfiles %pagesources %inlinepages};
sub usage () { #{{{
die "usage: ikiwiki [options] source dest\n";
@ -20,6 +20,7 @@ sub getconfig () { #{{{
%config=(
wiki_file_prune_regexp => qr{((^|/).svn/|\.\.|^\.|\/\.|\.html?$)},
wiki_link_regexp => qr/\[\[([^\s\]]+)\]\]/,
wiki_processor_regexp => qr/\[\[(\w+)\s+([^\]]+)\]\]/,
wiki_file_regexp => qr/(^[-A-Za-z0-9_.\&;:\/+]+$)/,
verbose => 0,
wikiname => "wiki",
@ -273,7 +274,7 @@ sub htmllink ($$;$$) { #{{{
$bestlink=htmlpage($bestlink);
}
if (! grep { $_ eq $bestlink } values %renderedfiles) {
return "<a href=\"$config{cgiurl}?do=create&page=$link&from=$page\">?</a>$linktext"
return "<span><a href=\"$config{cgiurl}?do=create&page=$link&from=$page\">?</a>$linktext</span>"
}
$bestlink=File::Spec->abs2rel($bestlink, dirname($page));
@ -332,6 +333,8 @@ sub loadindex () { #{{{
$oldpagemtime{$page}=$items{mtime}[0];
$oldlinks{$page}=[@{$items{link}}];
$links{$page}=[@{$items{link}}];
$inlinepages{$page}=join(" ", @{$items{inlinepage}})
if exists $items{inlinepage};
$renderedfiles{$page}=$items{dest}[0];
}
$pagectime{$page}=$items{ctime}[0];
@ -346,12 +349,14 @@ sub saveindex () { #{{{
open (OUT, ">$config{wikistatedir}/index") ||
error("cannot write to $config{wikistatedir}/index: $!");
foreach my $page (keys %oldpagemtime) {
next unless $oldpagemtime{$page};
my $line="mtime=$oldpagemtime{$page} ".
"ctime=$pagectime{$page} ".
"src=$pagesources{$page} ".
"dest=$renderedfiles{$page}";
if ($oldpagemtime{$page}) {
$line.=" link=$_" foreach @{$links{$page}};
$line.=" link=$_" foreach @{$links{$page}};
if (exists $inlinepages{$page}) {
$line.=" inlinepage=$_" foreach split " ", $inlinepages{$page};
}
print OUT $line."\n";
}

View File

@ -0,0 +1,8 @@
<h2><TMPL_VAR PAGELINK></h2>
<TMPL_VAR CONTENT>
<p>
<i>(posted <TMPL_VAR CTIME>)</i>
</p>
<hr>

View File

@ -40,11 +40,13 @@
</TMPL_IF>
<p>
<i>
<!-- from <TMPL_VAR NAME=WIKINAME> -->
Last edited <TMPL_VAR NAME=MTIME>
<TMPL_IF NAME="RSSURL">
; <a type="application/rss+xml" href="<TMPL_VAR NAME=RSSURL>">RSS</a>
</TMPL_IF>
</i>
</p>
</body>