aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--IkiWiki/Render.pm148
-rw-r--r--basewiki/blog.mdwn8
-rw-r--r--basewiki/helponformatting.mdwn5
-rw-r--r--basewiki/postprocessordirective.mdwn11
-rw-r--r--doc/blog.mdwn8
-rw-r--r--doc/features.mdwn21
-rw-r--r--doc/helponformatting.mdwn5
-rw-r--r--doc/postprocessordirective.mdwn11
-rw-r--r--doc/sandbox.mdwn9
-rw-r--r--doc/todo.mdwn44
-rwxr-xr-xikiwiki13
-rw-r--r--templates/inlinepage.tmpl8
-rw-r--r--templates/page.tmpl2
13 files changed, 237 insertions, 56 deletions
diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
index f397ff320..8f755e8f5 100644
--- a/IkiWiki/Render.pm
+++ b/IkiWiki/Render.pm
@@ -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;
+ }
}
}
}
diff --git a/basewiki/blog.mdwn b/basewiki/blog.mdwn
new file mode 100644
index 000000000..d300736a8
--- /dev/null
+++ b/basewiki/blog.mdwn
@@ -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.
diff --git a/basewiki/helponformatting.mdwn b/basewiki/helponformatting.mdwn
index 545148e86..4ef41d16f 100644
--- a/basewiki/helponformatting.mdwn
+++ b/basewiki/helponformatting.mdwn
@@ -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]].
diff --git a/basewiki/postprocessordirective.mdwn b/basewiki/postprocessordirective.mdwn
new file mode 100644
index 000000000..fa8432e3f
--- /dev/null
+++ b/basewiki/postprocessordirective.mdwn
@@ -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]]
diff --git a/doc/blog.mdwn b/doc/blog.mdwn
new file mode 100644
index 000000000..d300736a8
--- /dev/null
+++ b/doc/blog.mdwn
@@ -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.
diff --git a/doc/features.mdwn b/doc/features.mdwn
index 4699f3096..4a83604ad 100644
--- a/doc/features.mdwn
+++ b/doc/features.mdwn
@@ -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]]
diff --git a/doc/helponformatting.mdwn b/doc/helponformatting.mdwn
index 545148e86..4ef41d16f 100644
--- a/doc/helponformatting.mdwn
+++ b/doc/helponformatting.mdwn
@@ -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]].
diff --git a/doc/postprocessordirective.mdwn b/doc/postprocessordirective.mdwn
new file mode 100644
index 000000000..fa8432e3f
--- /dev/null
+++ b/doc/postprocessordirective.mdwn
@@ -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]]
diff --git a/doc/sandbox.mdwn b/doc/sandbox.mdwn
index d39f76032..37bb6bd89 100644
--- a/doc/sandbox.mdwn
+++ b/doc/sandbox.mdwn
@@ -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"]]
diff --git a/doc/todo.mdwn b/doc/todo.mdwn
index 4ae62867e..f918bf156 100644
--- a/doc/todo.mdwn
+++ b/doc/todo.mdwn
@@ -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"
diff --git a/ikiwiki b/ikiwiki
index 7b0a718d9..77c7744f9 100755
--- a/ikiwiki
+++ b/ikiwiki
@@ -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";
}
diff --git a/templates/inlinepage.tmpl b/templates/inlinepage.tmpl
new file mode 100644
index 000000000..96e20e53f
--- /dev/null
+++ b/templates/inlinepage.tmpl
@@ -0,0 +1,8 @@
+<h2><TMPL_VAR PAGELINK></h2>
+
+<TMPL_VAR CONTENT>
+
+<p>
+<i>(posted <TMPL_VAR CTIME>)</i>
+</p>
+<hr>
diff --git a/templates/page.tmpl b/templates/page.tmpl
index 5a7450af7..468361a9d 100644
--- a/templates/page.tmpl
+++ b/templates/page.tmpl
@@ -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>