hold onto your hats, full-fledged blogging has arrived in ikiwiki!
parent
ad4760ad78
commit
7b4600df3f
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
|
@ -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]].
|
||||
|
|
|
@ -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]]
|
|
@ -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.
|
|
@ -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]]
|
||||
|
||||
|
|
|
@ -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]].
|
||||
|
|
|
@ -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]]
|
|
@ -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"]]
|
||||
|
|
|
@ -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
13
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";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<h2><TMPL_VAR PAGELINK></h2>
|
||||
|
||||
<TMPL_VAR CONTENT>
|
||||
|
||||
<p>
|
||||
<i>(posted <TMPL_VAR CTIME>)</i>
|
||||
</p>
|
||||
<hr>
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue