hold onto your hats, full-fledged blogging has arrived in ikiwiki!
authorjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Fri, 24 Mar 2006 01:16:32 +0000 (01:16 +0000)
committerjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Fri, 24 Mar 2006 01:16:32 +0000 (01:16 +0000)
13 files changed:
IkiWiki/Render.pm
basewiki/blog.mdwn [new file with mode: 0644]
basewiki/helponformatting.mdwn
basewiki/postprocessordirective.mdwn [new file with mode: 0644]
doc/blog.mdwn [new file with mode: 0644]
doc/features.mdwn
doc/helponformatting.mdwn
doc/postprocessordirective.mdwn [new file with mode: 0644]
doc/sandbox.mdwn
doc/todo.mdwn
ikiwiki
templates/inlinepage.tmpl [new file with mode: 0644]
templates/page.tmpl

index f397ff3207add69a0b7a2b1b7a0fc31256c6b356..8f755e8f5a79c354cb604693455a25a010dc5005 100644 (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;
+                               }
                        }
                }
        }
diff --git a/basewiki/blog.mdwn b/basewiki/blog.mdwn
new file mode 100644 (file)
index 0000000..d300736
--- /dev/null
@@ -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.
index 545148e864323492e0edef0e75e3727018423513..4ef41d16fcb15b71437d86c21941a76bef76da00 100644 (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]].
diff --git a/basewiki/postprocessordirective.mdwn b/basewiki/postprocessordirective.mdwn
new file mode 100644 (file)
index 0000000..fa8432e
--- /dev/null
@@ -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 (file)
index 0000000..d300736
--- /dev/null
@@ -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.
index 4699f309676b899cae6aa79965673691c7b22e78..4a83604ad2b130e38ad0297ddd0ca4c5d7efb6d4 100644 (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]]
 
index 545148e864323492e0edef0e75e3727018423513..4ef41d16fcb15b71437d86c21941a76bef76da00 100644 (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]].
diff --git a/doc/postprocessordirective.mdwn b/doc/postprocessordirective.mdwn
new file mode 100644 (file)
index 0000000..fa8432e
--- /dev/null
@@ -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]]
index d39f760329e23b5d6ad3a521572de49df6ae2fb1..37bb6bd89cdbd01fa3c917af5ab30771bf289c9a 100644 (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"]]
index 4ae62867ec01d1755891e272e0a9a08e31af74ec..f918bf156462e75ac8ba280542d9a5c8e4ab79cb 100644 (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"
diff --git a/ikiwiki b/ikiwiki
index 7b0a718d9aca941ccae0d21792eb0b9d97bcfa94..77c7744f912fd8a5050319d257156edc8208d080 100755 (executable)
--- 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 (file)
index 0000000..96e20e5
--- /dev/null
@@ -0,0 +1,8 @@
+<h2><TMPL_VAR PAGELINK></h2>
+
+<TMPL_VAR CONTENT>
+
+<p>
+<i>(posted <TMPL_VAR CTIME>)</i>
+</p>
+<hr>
index 5a7450af7b7e19e69f060c1fbf3733ce0f5b8dca..468361a9d05657890b5c261f96b6767056562d85 100644 (file)
 </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>