From 7d37ea67aac9325af66289ea2afe7ed6bf270f00 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Fri, 21 Sep 2007 13:05:15 +0200 Subject: Rework, to not duplicate the `meta' plugin's ``license'' facility. --- .library/IkiWiki/Plugin/license.pm | 56 ++++++++++++-------------------------- 1 file changed, 18 insertions(+), 38 deletions(-) (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/license.pm b/.library/IkiWiki/Plugin/license.pm index e608461f..47fb34d8 100644 --- a/.library/IkiWiki/Plugin/license.pm +++ b/.library/IkiWiki/Plugin/license.pm @@ -1,5 +1,5 @@ # A plugin for ikiwiki to implement adding a footer with licensing information -# to every rendered page. +# based on a default value taken out of a file. # Copyright © 2007 Thomas Schwinge # @@ -18,12 +18,14 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # A footer with licensing information will be added to every rendered page if -# either (a) a file `license.mdwn' is found (using the same rules as for the -# sidebar plugin) or (b) (which be used to override (a)) a statement à la -# ``[[license text=WHATEVER]]'' is found in the source page. +# (a) such a footer isn't present already (see the `meta' plugin's ``license'' +# facility) and (b) a file `license.html' is found (using the same rules as for +# the sidebar plugin). # # The state which page's license text was gathered from which source is not -# tracked, so you'll need a full wiki-rebuild if (a)'s files are changed. +# tracked, so you'll need a full wiki-rebuild if (b)'s files are changed. +# +# You can use wiki links in `license.html'. package IkiWiki::Plugin::license; @@ -33,20 +35,9 @@ use IkiWiki 2.00; sub import { - hook (type => "preprocess", id => "license", call => \&preprocess); - hook (type => "pagetemplate", id => "license", call => \&pagetemplate); -} - -my %text; - -sub preprocess (@) -{ - my %params = @_; - my $page = $params {page}; - - # We don't return any text here, but record the passed text. - $text {$page} = $params {text}; - return ""; + hook (type => "pagetemplate", id => "license", call => \&pagetemplate, + # Run last, as to have the `meta' plugin do its work first. + last => 1); } sub pagetemplate (@) @@ -57,31 +48,20 @@ sub pagetemplate (@) my $template = $params {template}; - if ($template->query (name => "license")) + if ($template->query (name => "license") && + ! defined $template->param('license')) { my $content; - my $pagetype; - if (defined $text {$page}) - { - $pagetype = pagetype ($pagesources {$page}); - $content = $text {$page}; - } - else - { - my $license_page = bestlink ($page, "license") || return; - my $license_file = $pagesources {$license_page} || return; - $pagetype = pagetype ($license_file); - $content = readfile (srcfile ($license_file)); - } + my $license_page = bestlink ($page, "license") || return; + my $license_file = $pagesources {$license_page} || return; + #my $pagetype = pagetype ($license_file); + # Check if ``$pagetype eq 'html'''? + $content = readfile (srcfile ($license_file)); if (defined $content && length $content) { $template->param (license => - IkiWiki::htmlize ($destpage, $pagetype, - IkiWiki::linkify ($page, $destpage, - IkiWiki::preprocess ($page, $destpage, - IkiWiki::filter ($page, $destpage, $content))))); - + IkiWiki::linkify ($page, $destpage, $content)); } } } -- cgit v1.2.3 From 4a4033e7e5207fdf7db74f4032de0ed88273bacf Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Fri, 21 Sep 2007 13:10:07 +0200 Subject: Add (and enable) a `copyright' plugin, a copy of the `license' one. --- .library/IkiWiki/Plugin/copyright.pm | 69 ++++++++++++++++++++++++++++++++++++ render_locally | 1 + 2 files changed, 70 insertions(+) create mode 100644 .library/IkiWiki/Plugin/copyright.pm (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/copyright.pm b/.library/IkiWiki/Plugin/copyright.pm new file mode 100644 index 00000000..6497547f --- /dev/null +++ b/.library/IkiWiki/Plugin/copyright.pm @@ -0,0 +1,69 @@ +# A plugin for ikiwiki to implement adding a footer with copyright information +# based on a default value taken out of a file. + +# Copyright © 2007 Thomas Schwinge +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# A footer with copyright information will be added to every rendered page if +# (a) such a footer isn't present already (see the `meta' plugin's +# ``copyright'' facility) and (b) a file `copyright.html' is found (using the +# same rules as for the sidebar plugin). +# +# The state which page's copyright text was gathered from which source is not +# tracked, so you'll need a full wiki-rebuild if (b)'s files are changed. +# +# You can use wiki links in `copyright.html'. + +package IkiWiki::Plugin::copyright; + +use warnings; +use strict; +use IkiWiki 2.00; + +sub import +{ + hook (type => "pagetemplate", id => "copyright", call => \&pagetemplate, + # Run last, as to have the `meta' plugin do its work first. + last => 1); +} + +sub pagetemplate (@) +{ + my %params = @_; + my $page = $params {page}; + my $destpage = $params {destpage}; + + my $template = $params {template}; + + if ($template->query (name => "copyright") && + ! defined $template->param('copyright')) + { + my $content; + my $copyright_page = bestlink ($page, "copyright") || return; + my $copyright_file = $pagesources {$copyright_page} || return; + #my $pagetype = pagetype ($copyright_file); + # Check if ``$pagetype eq 'html'''? + $content = readfile (srcfile ($copyright_file)); + + if (defined $content && length $content) + { + $template->param (copyright => + IkiWiki::linkify ($page, $destpage, $content)); + } + } +} + +1 diff --git a/render_locally b/render_locally index 25a738ea..9864542d 100755 --- a/render_locally +++ b/render_locally @@ -29,6 +29,7 @@ ikiwiki \ --plugin sidebar \ --plugin table \ --libdir "$src"/.library \ + --plugin copyright \ --plugin license \ ${1+"$@"} \ "$src" "$dest" && -- cgit v1.2.3 From 9fd6a8ac202b18e83ee67d27e6d96f61ffe66510 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Thu, 8 Nov 2007 00:59:14 +0100 Subject: Use more consistent Perl syntax. --- .library/IkiWiki/Plugin/copyright.pm | 10 +++++----- .library/IkiWiki/Plugin/fill_empty_page.pm | 4 ++-- .library/IkiWiki/Plugin/license.pm | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/copyright.pm b/.library/IkiWiki/Plugin/copyright.pm index 6497547f..2806e9ef 100644 --- a/.library/IkiWiki/Plugin/copyright.pm +++ b/.library/IkiWiki/Plugin/copyright.pm @@ -43,17 +43,17 @@ sub import sub pagetemplate (@) { my %params = @_; - my $page = $params {page}; - my $destpage = $params {destpage}; + my $page = $params{page}; + my $destpage = $params{destpage}; - my $template = $params {template}; + my $template = $params{template}; if ($template->query (name => "copyright") && - ! defined $template->param('copyright')) + ! defined $template->param ('copyright')) { my $content; my $copyright_page = bestlink ($page, "copyright") || return; - my $copyright_file = $pagesources {$copyright_page} || return; + my $copyright_file = $pagesources{$copyright_page} || return; #my $pagetype = pagetype ($copyright_file); # Check if ``$pagetype eq 'html'''? $content = readfile (srcfile ($copyright_file)); diff --git a/.library/IkiWiki/Plugin/fill_empty_page.pm b/.library/IkiWiki/Plugin/fill_empty_page.pm index b2ce1fc0..e10aff21 100644 --- a/.library/IkiWiki/Plugin/fill_empty_page.pm +++ b/.library/IkiWiki/Plugin/fill_empty_page.pm @@ -37,7 +37,7 @@ sub import sub formbuilder_setup { my %params = @_; - my $form = $params {form}; + my $form = $params{form}; my $page = $form->field ("page"); return if $form->title ne "editpage"; @@ -47,7 +47,7 @@ sub formbuilder_setup # This is obviously not the last conclusion of wisdom. my $empty_page_page = bestlink ($page, "empty_page") || return; - my $empty_page_file = $pagesources {$empty_page_page} || return; + my $empty_page_file = $pagesources{$empty_page_page} || return; my $empty_page_type = pagetype ($empty_page_file); return unless defined $empty_page_type; diff --git a/.library/IkiWiki/Plugin/license.pm b/.library/IkiWiki/Plugin/license.pm index 47fb34d8..da337f29 100644 --- a/.library/IkiWiki/Plugin/license.pm +++ b/.library/IkiWiki/Plugin/license.pm @@ -43,17 +43,17 @@ sub import sub pagetemplate (@) { my %params = @_; - my $page = $params {page}; - my $destpage = $params {destpage}; + my $page = $params{page}; + my $destpage = $params{destpage}; - my $template = $params {template}; + my $template = $params{template}; if ($template->query (name => "license") && - ! defined $template->param('license')) + ! defined $template->param ('license')) { my $content; my $license_page = bestlink ($page, "license") || return; - my $license_file = $pagesources {$license_page} || return; + my $license_file = $pagesources{$license_page} || return; #my $pagetype = pagetype ($license_file); # Check if ``$pagetype eq 'html'''? $content = readfile (srcfile ($license_file)); -- cgit v1.2.3 From e00edb71860553e5d75b0e1cbf26625431c1c2d4 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Thu, 8 Nov 2007 17:44:02 +0100 Subject: First version of a GNU Texinfo rendering plugin. Written by Thomas Schwinge . See for details. --- .library/IkiWiki/Plugin/texinfo.pm | 212 +++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 .library/IkiWiki/Plugin/texinfo.pm (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/texinfo.pm b/.library/IkiWiki/Plugin/texinfo.pm new file mode 100644 index 00000000..8df2e38c --- /dev/null +++ b/.library/IkiWiki/Plugin/texinfo.pm @@ -0,0 +1,212 @@ +# A GNU Texinfo rendering plugin. + +# Copyright © 2007 Thomas Schwinge +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# http://ikiwiki.info/plugins/contrib/texinfo/ + +package IkiWiki::Plugin::texinfo; + +use warnings; +use strict; +use IkiWiki 2.00; + +# From `Ikiwiki/Plugins/teximg.pm'. +sub create_tmp_dir ($) +{ + # Create a temp directory, it will be removed when ikiwiki exits. + my $base = shift; + + my $template = $base . ".XXXXXXXXXX"; + use File::Temp qw (tempdir); + my $tmpdir = tempdir ($template, TMPDIR => 1, CLEANUP => 1); + return $tmpdir; +} + +sub import +{ + hook (type => "filter", id => "texi", call => \&filter); + hook (type => "htmlize", id => "texi", call => \&htmlize); + hook (type => "pagetemplate", id => "texi", call => \&pagetemplate); +} + +my %copyright; +my %license; + +sub filter (@) +{ + my %params = @_; + my $page = $params{page}; + +# TODO. For ``$page eq 'shortcuts''' this fails. Is this expected? + goto out unless defined $pagesources{$page}; + + # Only care for `.texi' files. + goto out unless pagetype ($pagesources{$page}) eq 'texi'; + + # No need to parse twice. + goto out if exists $copyright{$page}; + +# TODO. Check the `meta' plugin about when to do this at all. + $copyright{$page} = undef; + $license{$page} = undef; + # We assume that the copyright and licensing information is to be taken + # from the main `.texi' file. + @_ = split /\n/, $params{content}; + # Do some parsing to cut out the interesting bits, if there are any. + while (defined ($_ = shift @_)) + { + # Did we find a start tag? + last if /^\@copying$/; + } + # Already at the end of the page? + goto out unless defined $_; + while (defined ($_ = shift @_)) + { + # Already at the end of the copying section? (Shouldn't happen.) + goto out if /^\@end\ copying/; + # Found the ``^Copyright'' line? + last if /^Copyright/; + } + # Already at the end of the page? (Shouldn't happen.) + goto out unless defined $_; + # Copyright text will follow. + $copyright{$page} = $_; + while (defined ($_ = shift @_)) + { + # Found the separator of copyright and licensind information? + last if /^$/; + # Already at the end of the copying section? + goto finish if /^\@end\ copying/; + $copyright{$page} .= ' ' . $_; + } + # Already at the end of the page? (Shouldn't happen.) + goto finish unless defined $_; + # Licensing text will follow. + while (defined ($_ = shift @_)) + { + # Already at the end of the copying section? + last if /^\@end\ copying/; + $license{$page} .= ' ' . $_; + } + + finish: + # ``Render'' by hand some stuff that is commonly found in this section. + if (defined $copyright{$page}) + { + $copyright{$page} =~ s/\@copyright{}/©/g; + } + if (defined $license{$page}) + { + $license{$page} =~ s/\@quotation//g; + $license{$page} =~ s/\@end\ quotation//g; + $license{$page} =~ s/\@ignore//g; + } + + out: + return $params{content}; +} + +sub htmlize (@) +{ + my %params = @_; + my $page = $params{page}; + + my $pid; + my $sigpipe = 0; + $SIG{PIPE} = sub + { + $sigpipe = 1; + }; + + my $tmp = eval + { + create_tmp_dir ("texinfo") + }; + if (! $@ && + # `makeinfo' can't work directly on stdin. + writefile ("texinfo.texi", $tmp, $params{content}) == 0) + { + return "couldn't write temporary file"; + } + + use File::Basename; + use IPC::Open2; + $pid = open2 (*IN, *OUT, + 'makeinfo', + '--html', + '--no-split', '--output=-', + # We might be run from a directory different from the one the + # `.texi' file is stored in. +# TODO. Should we `cd' to this directory instead? + '-P', $config{srcdir} . '/' . dirname ($pagesources{$page}), +# TODO. Adding the following allows for putting files like `gpl.texinfo' into +# the top-level wiki directory. + '-I', $config{srcdir}, + $tmp . "/texinfo.texi"); + # open2 doesn't respect "use open ':utf8'" + binmode (IN, ':utf8'); +# binmode (OUT, ':utf8'); + +# print OUT $params{content}; + close OUT; + + local $/ = undef; + my $ret = ; + close IN; + waitpid $pid, 0; + $SIG{PIPE} = "DEFAULT"; + + return "failed to render" if $sigpipe; + + # Cut out the interesting bits. + $ret =~ s/.*//s; + $ret =~ s/<\/body>.*//s; + + return $ret; +} + +sub pagetemplate (@) +{ + my %params = @_; + my $page = $params{page}; + my $destpage = $params{destpage}; + + my $template = $params{template}; + +# TODO. Check the `meta' plugin about when to do this at all. + if ($template->query (name => "copyright") && + ! defined $template->param ('copyright')) + { + if (defined $copyright{$page} && length $copyright{$page}) + { + $template->param (copyright => + IkiWiki::linkify ($page, $destpage, $copyright{$page})); + } + } + if ($template->query (name => "license") && + ! defined $template->param ('license')) + { + if (defined $license{$page} && length $license{$page}) + { + $template->param (license => + IkiWiki::linkify ($page, $destpage, $license{$page})); + } + } +} + +1 -- cgit v1.2.3 From 3590f319ea80d8a153eba50be0b45bc5e6b87ef8 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Fri, 9 Nov 2007 14:59:21 +0100 Subject: Fix : ``500 Internal Server Error'' with *Preview* when creating new pages. --- .library/IkiWiki/Plugin/texinfo.pm | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/texinfo.pm b/.library/IkiWiki/Plugin/texinfo.pm index 8df2e38c..8c651160 100644 --- a/.library/IkiWiki/Plugin/texinfo.pm +++ b/.library/IkiWiki/Plugin/texinfo.pm @@ -126,6 +126,20 @@ sub htmlize (@) my %params = @_; my $page = $params{page}; + my $home; + if (defined $pagesources{$page}) + { + $home = $config{srcdir} . '/' . dirname ($pagesources{$page}); + } + else + { + # This happens in the CGI web frontent, when freshly creating a + # `texi'-type page and selecting to ``Preview'' the page before doing a + # ``Save Page''. +# TODO. + $home = $config{srcdir}; + } + my $pid; my $sigpipe = 0; $SIG{PIPE} = sub @@ -153,7 +167,7 @@ sub htmlize (@) # We might be run from a directory different from the one the # `.texi' file is stored in. # TODO. Should we `cd' to this directory instead? - '-P', $config{srcdir} . '/' . dirname ($pagesources{$page}), + '-P', $home, # TODO. Adding the following allows for putting files like `gpl.texinfo' into # the top-level wiki directory. '-I', $config{srcdir}, -- cgit v1.2.3 From ceb3811aeb93546fe0b85a9b91e0acb93bc4f52b Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Sun, 16 Dec 2007 23:08:44 +0100 Subject: .library/IkiWiki/Plugin/fill_empty_page.pm: Delete; ikiwiki's `edittemplate' plugin is to be used now. --- .library/IkiWiki/Plugin/fill_empty_page.pm | 65 ------------------------------ 1 file changed, 65 deletions(-) delete mode 100644 .library/IkiWiki/Plugin/fill_empty_page.pm (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/fill_empty_page.pm b/.library/IkiWiki/Plugin/fill_empty_page.pm deleted file mode 100644 index e10aff21..00000000 --- a/.library/IkiWiki/Plugin/fill_empty_page.pm +++ /dev/null @@ -1,65 +0,0 @@ -# A plugin for ikiwiki to implement filling newly created pages from a template -# file. - -# Copyright © 2007 Thomas Schwinge -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2, or (at your option) any later -# version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -# Newly created pages will be filled from a file `empty_page.mdwn' if such a -# file can be found by using the same rules as for the sidebar plugin. -# -# - -package IkiWiki::Plugin::fill_empty_page; - -use warnings; -use strict; -use IkiWiki 2.00; - -sub import -{ - hook (type => "formbuilder_setup", id => "fill_empty_page", - call => \&formbuilder_setup); -} - -sub formbuilder_setup -{ - my %params = @_; - my $form = $params{form}; - my $page = $form->field ("page"); - - return if $form->title ne "editpage"; - return if $form->field("do") ne "create"; - - return if defined $form->field ("editcontent"); - - # This is obviously not the last conclusion of wisdom. - my $empty_page_page = bestlink ($page, "empty_page") || return; - my $empty_page_file = $pagesources{$empty_page_page} || return; - my $empty_page_type = pagetype ($empty_page_file); - return unless defined $empty_page_type; - - my $content = readfile (srcfile ($empty_page_file)); - - if (defined $content && length $content) - { - $form->field (name => "editcontent", value => $content); - - $form->tmpl_param ("page_preview", "Filled automagically from `" - . $empty_page_file . "`."); - } -} - -1 -- cgit v1.2.3 From 74c454805d3abf40f33977aee7d2585fcedacad1 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Tue, 30 Sep 2008 23:33:33 +0200 Subject: Rewrite copyright.pm and license.pm in order to make them work properly. --- .library/IkiWiki/Plugin/copyright.pm | 49 +++++++++++++++--------------------- .library/IkiWiki/Plugin/license.pm | 48 ++++++++++++++--------------------- copyright.html | 1 - copyright.mdwn | 1 + license.html | 5 ---- license.mdwn | 5 ++++ 6 files changed, 45 insertions(+), 64 deletions(-) delete mode 100644 copyright.html create mode 100644 copyright.mdwn delete mode 100644 license.html create mode 100644 license.mdwn (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/copyright.pm b/.library/IkiWiki/Plugin/copyright.pm index 2806e9ef..16acaccd 100644 --- a/.library/IkiWiki/Plugin/copyright.pm +++ b/.library/IkiWiki/Plugin/copyright.pm @@ -1,7 +1,7 @@ # A plugin for ikiwiki to implement adding a footer with copyright information # based on a default value taken out of a file. -# Copyright © 2007 Thomas Schwinge +# Copyright © 2007, 2008 Thomas Schwinge # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the @@ -17,15 +17,14 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# A footer with copyright information will be added to every rendered page if -# (a) such a footer isn't present already (see the `meta' plugin's -# ``copyright'' facility) and (b) a file `copyright.html' is found (using the -# same rules as for the sidebar plugin). +# Unless overridden with the `meta' plugin, a footer with copyright information +# will be added to every page using a source file `copyright' (e.g., +# `copyright.mdwn') (using the same ``locating rules'' as for the sidebar +# plugin). # # The state which page's copyright text was gathered from which source is not -# tracked, so you'll need a full wiki-rebuild if (b)'s files are changed. -# -# You can use wiki links in `copyright.html'. +# tracked, so you'll need a full wiki-rebuild if the `copyright' file is +# changed. package IkiWiki::Plugin::copyright; @@ -33,37 +32,29 @@ use warnings; use strict; use IkiWiki 2.00; +my %copyright; + sub import { - hook (type => "pagetemplate", id => "copyright", call => \&pagetemplate, - # Run last, as to have the `meta' plugin do its work first. - last => 1); + hook (type => "scan", id => "copyright", call => \&scan); } -sub pagetemplate (@) +sub scan (@) { my %params = @_; my $page = $params{page}; - my $destpage = $params{destpage}; - my $template = $params{template}; + return if defined $pagestate{$page}{meta}{copyright}; + + my $content; + my $copyright_page = bestlink ($page, "copyright") || return; + my $copyright_file = $pagesources{$copyright_page} || return; - if ($template->query (name => "copyright") && - ! defined $template->param ('copyright')) - { - my $content; - my $copyright_page = bestlink ($page, "copyright") || return; - my $copyright_file = $pagesources{$copyright_page} || return; - #my $pagetype = pagetype ($copyright_file); - # Check if ``$pagetype eq 'html'''? - $content = readfile (srcfile ($copyright_file)); + # Only an optimization to avoid reading the same file again and again. + $copyright{$copyright_file} = readfile (srcfile ($copyright_file)) + unless defined $copyright{$copyright_file}; - if (defined $content && length $content) - { - $template->param (copyright => - IkiWiki::linkify ($page, $destpage, $content)); - } - } + $pagestate{$page}{meta}{copyright} = $copyright{$copyright_file}; } 1 diff --git a/.library/IkiWiki/Plugin/license.pm b/.library/IkiWiki/Plugin/license.pm index da337f29..651c039a 100644 --- a/.library/IkiWiki/Plugin/license.pm +++ b/.library/IkiWiki/Plugin/license.pm @@ -1,7 +1,7 @@ # A plugin for ikiwiki to implement adding a footer with licensing information # based on a default value taken out of a file. -# Copyright © 2007 Thomas Schwinge +# Copyright © 2007, 2008 Thomas Schwinge # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the @@ -17,15 +17,13 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# A footer with licensing information will be added to every rendered page if -# (a) such a footer isn't present already (see the `meta' plugin's ``license'' -# facility) and (b) a file `license.html' is found (using the same rules as for -# the sidebar plugin). +# Unless overridden with the `meta' plugin, a footer with licensing information +# will be added to every page using a source file `license' (e.g., +# `license.mdwn') (using the same ``locating rules'' as for the sidebar +# plugin). # # The state which page's license text was gathered from which source is not -# tracked, so you'll need a full wiki-rebuild if (b)'s files are changed. -# -# You can use wiki links in `license.html'. +# tracked, so you'll need a full wiki-rebuild if the `license' file is changed. package IkiWiki::Plugin::license; @@ -33,37 +31,29 @@ use warnings; use strict; use IkiWiki 2.00; +my %license; + sub import { - hook (type => "pagetemplate", id => "license", call => \&pagetemplate, - # Run last, as to have the `meta' plugin do its work first. - last => 1); + hook (type => "scan", id => "license", call => \&scan); } -sub pagetemplate (@) +sub scan (@) { my %params = @_; my $page = $params{page}; - my $destpage = $params{destpage}; - my $template = $params{template}; + return if defined $pagestate{$page}{meta}{license}; + + my $content; + my $license_page = bestlink ($page, "license") || return; + my $license_file = $pagesources{$license_page} || return; - if ($template->query (name => "license") && - ! defined $template->param ('license')) - { - my $content; - my $license_page = bestlink ($page, "license") || return; - my $license_file = $pagesources{$license_page} || return; - #my $pagetype = pagetype ($license_file); - # Check if ``$pagetype eq 'html'''? - $content = readfile (srcfile ($license_file)); + # Only an optimization to avoid reading the same file again and again. + $license{$license_file} = readfile (srcfile ($license_file)) + unless defined $license{$license_file}; - if (defined $content && length $content) - { - $template->param (license => - IkiWiki::linkify ($page, $destpage, $content)); - } - } + $pagestate{$page}{meta}{license} = $license{$license_file}; } 1 diff --git a/copyright.html b/copyright.html deleted file mode 100644 index fcdab55d..00000000 --- a/copyright.html +++ /dev/null @@ -1 +0,0 @@ -Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008 The Contributing Authors diff --git a/copyright.mdwn b/copyright.mdwn new file mode 100644 index 00000000..fcdab55d --- /dev/null +++ b/copyright.mdwn @@ -0,0 +1 @@ +Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008 The Contributing Authors diff --git a/license.html b/license.html deleted file mode 100644 index 9b2ddd4f..00000000 --- a/license.html +++ /dev/null @@ -1,5 +0,0 @@ -Permission is granted to copy, distribute and/or modify this document under the -terms of the GNU Free Documentation License, Version 1.2 or any later version -published by the Free Software Foundation; with no Invariant Sections, no -Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included -in the section entitled [[GNU_Free_Documentation_License|/fdl]]. diff --git a/license.mdwn b/license.mdwn new file mode 100644 index 00000000..9b2ddd4f --- /dev/null +++ b/license.mdwn @@ -0,0 +1,5 @@ +Permission is granted to copy, distribute and/or modify this document under the +terms of the GNU Free Documentation License, Version 1.2 or any later version +published by the Free Software Foundation; with no Invariant Sections, no +Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included +in the section entitled [[GNU_Free_Documentation_License|/fdl]]. -- cgit v1.2.3 From 6fc97a71b0594afa47781571654e71cb18d4d08a Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Wed, 9 Jun 2010 15:15:12 +0200 Subject: .library/IkiWiki/Plugin/reset_mtimes.pm: New. --- .library/IkiWiki/Plugin/reset_mtimes.pm | 84 +++++++++++++++++++++++++++++++++ render_locally | 21 +++++++-- 2 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 .library/IkiWiki/Plugin/reset_mtimes.pm (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/reset_mtimes.pm b/.library/IkiWiki/Plugin/reset_mtimes.pm new file mode 100644 index 00000000..a168652b --- /dev/null +++ b/.library/IkiWiki/Plugin/reset_mtimes.pm @@ -0,0 +1,84 @@ +# Copyright © 2010 Thomas Schwinge + +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +package IkiWiki::Plugin::reset_mtimes; + +use warnings; +use strict; +use IkiWiki 3.00; + +# This plugin resets pages' / files' mtimes according to the RCS information +# when using --refresh mode. +# +# Note that the files' mtimes are *always* set, even if the file has +# un-committed changes. +# +# + +sub import +{ + hook (type => "needsbuild", + id => "reset_mtimes", + call => \&needsbuild); +} + +sub needsbuild (@) +{ + # Only proceed if --gettime is in effect, as we're clearly not intersted in + # this functionality otherwise. + return unless $config{gettime}; + + my $files = shift; + foreach my $file (@$files) + { + # [TODO. Perhaps not necessary. Can this hook ever be called for + # removed pages -- that need to be ``rebuilt'' in the sense that + # they're to be removed?] Don't bother for pages that don't exist + # anymore. + next unless -e "$config{srcdir}/$file"; + + my $page = pagename ($file); + debug ("needsbuild: <$file> <$page>"); + + # Only ever update -- otherwise ikiwiki shall do its own thing. + if (defined $IkiWiki::pagemtime{$page}) + { + debug ("pagemtime: " . $IkiWiki::pagemtime{$page}); + + my $mtime = 0; + eval + { + $mtime = IkiWiki::rcs_getmtime ($file); + }; + if ($@) + { + print STDERR $@; + } + elsif ($mtime > 0) + { + $IkiWiki::pagemtime{$page} = $mtime; + + # We have to set the actual file's mtime too, as otherwise + # ikiwiki will update it again and again. + utime($mtime, $mtime, "$config{srcdir}/$file"); + } + + debug ("pagemtime: " . $IkiWiki::pagemtime{$page}); + } + } +} + +1 diff --git a/render_locally b/render_locally index 9e257560..ca7856f5 100755 --- a/render_locally +++ b/render_locally @@ -12,27 +12,32 @@ export ROOT && ROOT=$(readlink -f "$(dirname "$0")") && export LC_MESSAGES && LC_MESSAGES=C && case $1 in + # Use this for rendering the set of pages which are to be installed under + # . --official) - # Use this for rendering the set of pages which are to be installed under - # . shift && + export TZ && TZ=UTC && export DESTDIR && DESTDIR=$ROOT.rendered.official && + # Use ``--no-usedirs'' here, so that not too many separate directories have # to be created. # - # ``--gettime --rebuild'': - # + # Use ``--gettime --plugin update_mtimes'' to reset pages' / files' mtimes + # according to the RCS information when using --refresh mode. set x \ --set wikistatedir="$ROOT"/.ikiwiki-official \ --url http://www.gnu.org/software/hurd \ --no-usedirs \ - --gettime --rebuild \ + --gettime --plugin reset_mtimes \ "$@" && shift;; + --w3m-wrapper) shift && + export NO_MSG && NO_MSG=y && + # Disable the configured VCS, as the CGI wrapper together with using the # anonok plugin inhibits the propagation of authorship information. set x \ @@ -41,21 +46,27 @@ case $1 in --rcs norcs \ "$@" && shift && + exec \ "$0" \ --w3m \ "$@";; + --w3m) shift && + export DESTDIR && DESTDIR=$ROOT.rendered.w3m && + set x \ --set wikistatedir="$ROOT"/.ikiwiki-w3m \ --cgiurl hurd-web.cgi --w3mmode \ "$@" && shift && + exec \ "$0" \ "$@";; + *) # Use ``--no-usedirs'' here, because when browsing local files, the web # browsers don't display `index.html' files by default when a hyperlink -- cgit v1.2.3 From 3d846b2d27e80386e058b0ca9ef2739674ef7736 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Thu, 9 Sep 2010 14:06:35 +0200 Subject: Add (part of) YAML field infrastructure. New files copied from a2482475a7ed0b6f54df10a87a8665e2361f3598 of by Kathryn Andersen . --- .library/IkiWiki/Plugin/field.pm | 662 ++++++++++++++++++++++++++++++++++++ .library/IkiWiki/Plugin/getfield.pm | 123 +++++++ .library/IkiWiki/Plugin/ymlfront.pm | 426 +++++++++++++++++++++++ ikiwiki.setup | 22 +- 4 files changed, 1229 insertions(+), 4 deletions(-) create mode 100644 .library/IkiWiki/Plugin/field.pm create mode 100644 .library/IkiWiki/Plugin/getfield.pm create mode 100644 .library/IkiWiki/Plugin/ymlfront.pm (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/field.pm b/.library/IkiWiki/Plugin/field.pm new file mode 100644 index 00000000..e53474e9 --- /dev/null +++ b/.library/IkiWiki/Plugin/field.pm @@ -0,0 +1,662 @@ +#!/usr/bin/perl +# Ikiwiki field plugin. +# See doc/plugin/contrib/field.mdwn for documentation. +package IkiWiki::Plugin::field; +use warnings; +use strict; +=head1 NAME + +IkiWiki::Plugin::field - front-end for per-page record fields. + +=head1 VERSION + +This describes version B<0.05> of IkiWiki::Plugin::field + +=cut + +our $VERSION = '0.05'; + +=head1 PREREQUISITES + + IkiWiki + +=head1 AUTHOR + + Kathryn Andersen (RUBYKAT) + http://github.com/rubykat + +=head1 COPYRIGHT + +Copyright (c) 2009-2010 Kathryn Andersen + +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +=cut + +use IkiWiki 3.00; + +my %Fields = ( + _first => { + id => '_first', + seq => 'BB', + }, + _last => { + id => '_last', + seq => 'YY', + }, + _middle => { + id => '_middle', + seq => 'MM', + }, +); +my @FieldsLookupOrder = (); + +my %Cache = (); + +sub field_get_value ($$); + +sub import { + hook(type => "getsetup", id => "field", call => \&getsetup); + hook(type => "checkconfig", id => "field", call => \&checkconfig); + hook(type => "scan", id => "field", call => \&scan, last=>1); + hook(type => "pagetemplate", id => "field", call => \&pagetemplate); +} + +# =============================================== +# Hooks +# --------------------------- +sub getsetup () { + return + plugin => { + safe => 1, + rebuild => undef, + }, + field_register => { + type => "hash", + example => "field_register => {meta => 'last'}", + description => "simple registration of fields by plugin", + safe => 0, + rebuild => undef, + }, + field_allow_config => { + type => "boolean", + example => "field_allow_config => 1", + description => "allow config settings to be queried", + safe => 0, + rebuild => undef, + }, + field_tags => { + type => "hash", + example => "field_tags => {BookAuthor => '/books/authors'}", + description => "fields flagged as tag-fields", + safe => 0, + rebuild => undef, + }, +} + +sub checkconfig () { + # use the simple by-plugin pagestatus method for + # those plugins registered with the field_register config option. + if (defined $config{field_register}) + { + if (ref $config{field_register} eq 'ARRAY') + { + foreach my $id (@{$config{field_register}}) + { + field_register(id=>$id); + } + } + elsif (ref $config{field_register} eq 'HASH') + { + foreach my $id (keys %{$config{field_register}}) + { + field_register(id=>$id, order=>$config{field_register}->{$id}); + } + } + else + { + field_register(id=>$config{field_register}); + } + } + if (!defined $config{field_allow_config}) + { + $config{field_allow_config} = 0; + } +} # checkconfig + +sub scan (@) { + my %params=@_; + my $page=$params{page}; + my $content=$params{content}; + + # scan for tag fields + if ($config{field_tags}) + { + foreach my $field (sort keys %{$config{field_tags}}) + { + my @values = field_get_value($field, $page); + if (@values) + { + foreach my $tag (@values) + { + if ($tag) + { + my $link = $config{field_tags}{$field} . '/' + . titlepage($tag); + add_link($page, $link, lc($field)); + } + } + } + } + } +} # scan + +sub pagetemplate (@) { + my %params=@_; + my $page=$params{page}; + my $template=$params{template}; + + field_set_template_values($template, $page); +} # pagetemplate + +# =============================================== +# Field interface +# --------------------------- + +sub field_register (%) { + my %param=@_; + if (!exists $param{id}) + { + error 'field_register requires id parameter'; + return 0; + } + if (exists $param{call} and !ref $param{call}) + { + error 'field_register call parameter must be function'; + return 0; + } + + $Fields{$param{id}} = \%param; + if (!exists $param{call}) + { + # closure to get the data from the pagestate hash + $Fields{$param{id}}->{call} = sub { + my $field_name = shift; + my $page = shift; + if (exists $pagestate{$page}{$param{id}}{$field_name}) + { + return (wantarray + ? ($pagestate{$page}{$param{id}}{$field_name}) + : $pagestate{$page}{$param{id}}{$field_name}); + } + elsif (exists $pagestate{$page}{$param{id}}{lc($field_name)}) + { + return (wantarray + ? ($pagestate{$page}{$param{id}}{lc($field_name)}) + : $pagestate{$page}{$param{id}}{lc($field_name)}); + } + return undef; + }; + } + # add this to the ordering hash + # first, last, order; by default, middle + my $when = ($param{first} + ? '_first' + : ($param{last} + ? '_last' + : ($param{order} + ? ($param{order} eq 'first' + ? '_first' + : ($param{order} eq 'last' + ? '_last' + : ($param{order} eq 'middle' + ? '_middle' + : $param{order} + ) + ) + ) + : '_middle' + ) + )); + add_lookup_order($param{id}, $when); + return 1; +} # field_register + +sub field_get_value ($$) { + my $field_name = shift; + my $page = shift; + + # This will return the first value it finds + # where the value returned is not undefined. + # This will return an array of values if wantarray is true. + + # The reason why it checks every registered plugin rather than have + # plugins declare which fields they know about, is that it is quite + # possible that a plugin doesn't know, ahead of time, what fields + # will be available; for example, a YAML format plugin would return + # any field that happens to be defined in a YAML page file, which + # could be anything! + + my $value = undef; + my @array_value = undef; + + # check the cache first + if (exists $Cache{$page}{$field_name} + and defined $Cache{$page}{$field_name}) + { + return (wantarray + ? @{$Cache{$page}{$field_name}{array}} + : $Cache{$page}{$field_name}{scalar}); + } + + if (!@FieldsLookupOrder) + { + build_fields_lookup_order(); + } + foreach my $id (@FieldsLookupOrder) + { + $value = $Fields{$id}{call}->($field_name, $page); + @array_value = $Fields{$id}{call}->($field_name, $page); + if (defined $value) + { + last; + } + } + + # extra definitions + if (!defined $value) + { + # Exception for titles + # If the title hasn't been found, construct it + if ($field_name eq 'title') + { + $value = pagetitle(IkiWiki::basename($page)); + } + # and set "page" if desired + elsif ($field_name eq 'page') + { + $value = $page; + } + # the page above this page; aka the current directory + elsif ($field_name eq 'parent_page') + { + if ($page =~ m{^(.*)/[-\.\w]+$}) + { + $value = $1; + } + } + elsif ($field_name eq 'basename') + { + $value = IkiWiki::basename($page); + } + elsif ($config{field_allow_config} + and $field_name =~ /^config-(.*)$/i) + { + my $cfield = $1; + if (exists $config{$cfield}) + { + $value = $config{$cfield}; + } + } + elsif ($field_name =~ /^(.*)-tagpage$/) + { + my $real_fn = $1; + if (exists $config{field_tags}{$real_fn} + and defined $config{field_tags}{$real_fn}) + { + my @values = field_get_value($real_fn, $page); + if (@values) + { + foreach my $tag (@values) + { + if ($tag) + { + my $link = $config{field_tags}{$real_fn} . '/' . $tag; + push @array_value, $link; + } + } + $value = join(",", @array_value); + } + } + } + } + if (defined $value) + { + if (!@array_value) + { + @array_value = ($value); + } + # cache the value + $Cache{$page}{$field_name}{scalar} = $value; + $Cache{$page}{$field_name}{array} = \@array_value; + } + return (wantarray ? @array_value : $value); +} # field_get_value + +# set the values for the given HTML::Template template +sub field_set_template_values ($$;@) { + my $template = shift; + my $page = shift; + my %params = @_; + + my $get_value_fn = (exists $params{value_fn} + ? $params{value_fn} + : \&field_get_value); + + # Find the parameter names in this template + # and see if you can find their values. + + # The reason we check the template for field names is because we + # don't know what fields the registered plugins provide; and this is + # reasonable because for some plugins (e.g. a YAML data plugin) they + # have no way of knowing, ahead of time, what fields they might be + # able to provide. + + my @parameter_names = $template->param(); + foreach my $field (@parameter_names) + { + my $type = $template->query(name => $field); + if ($type eq 'LOOP' and $field =~ /_LOOP$/i) + { + # Loop fields want arrays. + # Figure out what field names to look for: + # * names are from the enclosed loop fields + my @loop_fields = $template->query(loop => $field); + + my @loop_vals = (); + my %loop_field_arrays = (); + foreach my $fn (@loop_fields) + { + if ($fn !~ /^__/) # not a special loop variable + { + my @ival_array = $get_value_fn->($fn, $page); + if (@ival_array) + { + $loop_field_arrays{$fn} = \@ival_array; + } + } + } + foreach my $fn (sort keys %loop_field_arrays) + { + my $i = 0; + foreach my $v (@{$loop_field_arrays{$fn}}) + { + if (!defined $loop_vals[$i]) + { + $loop_vals[$i] = {}; + } + $loop_vals[$i]{$fn} = $v; + $i++; + } + } + $template->param($field => \@loop_vals); + } + else # not a loop field + { + my $value = $get_value_fn->($field, $page); + if (defined $value) + { + $template->param($field => $value); + } + } + } +} # field_set_template_values + +# =============================================== +# Private Functions +# --------------------------- + +# Calculate the lookup order +# module, AZ +# This is crabbed from the PmWiki Markup function +sub add_lookup_order { + my $id = shift; + my $when = shift; + + # may have given an explicit ordering + if ($when =~ /^[A-Z][A-Z]$/) + { + $Fields{$id}{seq} = $when; + } + else + { + my $cmp = '='; + my $seq_field = $when; + if ($when =~ /^([<>])(.+)$/) + { + $cmp = $1; + $seq_field = $2; + } + $Fields{$seq_field}{dep}{$id} = $cmp; + if (exists $Fields{$seq_field}{seq} + and defined $Fields{$seq_field}{seq}) + { + $Fields{$id}{seq} = $Fields{$seq_field}{seq} . $cmp; + } + } + if ($Fields{$id}{seq}) + { + foreach my $i (keys %{$Fields{$id}{dep}}) + { + my $m = $Fields{$id}{dep}{$i}; + add_lookup_order($i, "$m$id"); + } + delete $Fields{$id}{dep}; + } +} + +sub build_fields_lookup_order { + + # remove the _first, _last and _middle dummy fields + # because we don't need them anymore + delete $Fields{_first}; + delete $Fields{_last}; + delete $Fields{_middle}; + my %lookup_spec = (); + # Make a hash of the lookup sequences + foreach my $id (sort keys %Fields) + { + my $seq = ($Fields{$id}{seq} + ? $Fields{$id}{seq} + : 'MM'); + if (!exists $lookup_spec{$seq}) + { + $lookup_spec{$seq} = {}; + } + $lookup_spec{$seq}{$id} = 1; + } + + # get the field-lookup order by (a) sorting by lookup_spec + # and (b) sorting by field-name for the fields that registered + # the same field-lookup order + foreach my $ord (sort keys %lookup_spec) + { + push @FieldsLookupOrder, sort keys %{$lookup_spec{$ord}}; + } +} # build_fields_lookup_order + +# match field funcs +# page-to-check, wanted +sub match_a_field ($$) { + my $page=shift; + my $wanted=shift; + + # The field name is first; the rest is the match + my $field_name; + my $glob; + if ($wanted =~ /^(\w+)\s+(.*)$/) + { + $field_name = $1; + $glob = $2; + } + else + { + return IkiWiki::FailReason->new("cannot match field"); + } + + # turn glob into a safe regexp + my $re=IkiWiki::glob2re($glob); + + my $val = IkiWiki::Plugin::field::field_get_value($field_name, $page); + + if (defined $val) { + if ($val=~/^$re$/i) { + return IkiWiki::SuccessReason->new("$re matches $field_name of $page", $page => $IkiWiki::DEPEND_CONTENT, "" => 1); + } + else { + return IkiWiki::FailReason->new("$re does not match $field_name of $page", "" => 1); + } + } + else { + return IkiWiki::FailReason->new("$page does not have a $field_name", "" => 1); + } +} # match_a_field + +# check against individual items of a field +# (treat the field as an array) +# page-to-check, wanted +sub match_a_field_item ($$) { + my $page=shift; + my $wanted=shift; + + # The field name is first; the rest is the match + my $field_name; + my $glob; + if ($wanted =~ /^(\w+)\s+(.*)$/) + { + $field_name = $1; + $glob = $2; + } + else + { + return IkiWiki::FailReason->new("cannot match field"); + } + + # turn glob into a safe regexp + my $re=IkiWiki::glob2re($glob); + + my @val_array = IkiWiki::Plugin::field::field_get_value($field_name, $page); + + if (@val_array) + { + foreach my $val (@val_array) + { + if (defined $val) { + if ($val=~/^$re$/i) { + return IkiWiki::SuccessReason->new("$re matches $field_name of $page", $page => $IkiWiki::DEPEND_CONTENT, "" => 1); + } + } + } + # not found + return IkiWiki::FailReason->new("$re does not match $field_name of $page", "" => 1); + } + else { + return IkiWiki::FailReason->new("$page does not have a $field_name", "" => 1); + } +} # match_a_field_item + +# =============================================== +# PageSpec functions +# --------------------------- + +package IkiWiki::PageSpec; + +sub match_field ($$;@) { + my $page=shift; + my $wanted=shift; + return IkiWiki::Plugin::field::match_a_field($page, $wanted); +} # match_field + +sub match_destfield ($$;@) { + my $page=shift; + my $wanted=shift; + my %params=@_; + + return IkiWiki::FailReason->new("cannot match destpage") unless exists $params{destpage}; + + # Match the field on the destination page, not the source page + return IkiWiki::Plugin::field::match_a_field($params{destpage}, $wanted); +} # match_destfield + +sub match_field_item ($$;@) { + my $page=shift; + my $wanted=shift; + return IkiWiki::Plugin::field::match_a_field_item($page, $wanted); +} # match_field + +sub match_destfield_item ($$;@) { + my $page=shift; + my $wanted=shift; + my %params=@_; + + return IkiWiki::FailReason->new("cannot match destpage") unless exists $params{destpage}; + + # Match the field on the destination page, not the source page + return IkiWiki::Plugin::field::match_a_field_item($params{destpage}, $wanted); +} # match_destfield + +sub match_field_tagged ($$;@) { + my $page=shift; + my $wanted=shift; + my %params=@_; + + # The field name is first; the rest is the match + my $field_name; + my $glob; + if ($wanted =~ /^(\w+)\s+(.*)$/) + { + $field_name = $1; + $glob = $2; + } + else + { + return IkiWiki::FailReason->new("cannot match field"); + } + return match_link($page, $glob, linktype => lc($field_name), @_); +} + +sub match_destfield_tagged ($$;@) { + my $page=shift; + my $wanted=shift; + my %params=@_; + + return IkiWiki::FailReason->new("cannot match destpage") unless exists $params{destpage}; + + # Match the field on the destination page, not the source page + return IkiWiki::Plugin::field::match_field_tagged($params{destpage}, $wanted); +} + +# =============================================== +# SortSpec functions +# --------------------------- +package IkiWiki::SortSpec; + +sub cmp_field { + my $field = shift; + error(gettext("sort=field requires a parameter")) unless defined $field; + + my $left = IkiWiki::Plugin::field::field_get_value($field, $a); + my $right = IkiWiki::Plugin::field::field_get_value($field, $b); + + $left = "" unless defined $left; + $right = "" unless defined $right; + return $left cmp $right; +} + +sub cmp_field_natural { + my $field = shift; + error(gettext("sort=field requires a parameter")) unless defined $field; + + eval q{use Sort::Naturally}; + error $@ if $@; + + my $left = IkiWiki::Plugin::field::field_get_value($field, $a); + my $right = IkiWiki::Plugin::field::field_get_value($field, $b); + + $left = "" unless defined $left; + $right = "" unless defined $right; + return Sort::Naturally::ncmp($left, $right); +} + +1; diff --git a/.library/IkiWiki/Plugin/getfield.pm b/.library/IkiWiki/Plugin/getfield.pm new file mode 100644 index 00000000..3a967d8e --- /dev/null +++ b/.library/IkiWiki/Plugin/getfield.pm @@ -0,0 +1,123 @@ +#!/usr/bin/perl +# Ikiwiki getfield plugin. +# Substitute field values in the content of the page. +# See plugin/contrib/getfield for documentation. +package IkiWiki::Plugin::getfield; +use strict; +=head1 NAME + +IkiWiki::Plugin::getfield - query the values of fields + +=head1 VERSION + +This describes version B<0.02> of IkiWiki::Plugin::getfield + +=cut + +our $VERSION = '0.02'; + +=head1 PREREQUISITES + + IkiWiki + IkiWiki::Plugin::field + +=head1 AUTHOR + + Kathryn Andersen (RUBYKAT) + http://github.com/rubykat + +=head1 COPYRIGHT + +Copyright (c) 2009 Kathryn Andersen + +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +=cut + +use IkiWiki 3.00; + +sub import { + hook(type => "getsetup", id => "getfield", call => \&getsetup); + hook(type => "filter", id => "getfield", call => \&do_filter, last=>1); + + IkiWiki::loadplugin("field"); +} + +#--------------------------------------------------------------- +# Hooks +# -------------------------------- + +sub getsetup () { + return + plugin => { + safe => 1, + rebuild => undef, + }, +} + +sub do_filter (@) { + my %params=@_; + my $page = $params{page}; + my $destpage = ($params{destpage} ? $params{destpage} : $params{page}); + + my $page_file=$pagesources{$page}; + my $page_type=pagetype($page_file); + if (defined $page_type) + { + while ($params{content} =~ /{{\$([-\w\/]+#)?[-\w]+}}/) + { + # substitute {{$var}} variables (source-page) + $params{content} =~ s/{{\$([-\w]+)}}/get_field_value($1,$page)/eg; + + # substitute {{$page#var}} variables (source-page) + $params{content} =~ s/{{\$([-\w\/]+)#([-\w]+)}}/get_other_page_field_value($2,$page,$1)/eg; + } + } + + $page_file=$pagesources{$destpage}; + $page_type=pagetype($page_file); + if (defined $page_type) + { + while ($params{content} =~ /{{\+\$([-\w\/]+#)?[-\w]+\+}}/) + { + # substitute {{+$var+}} variables (dest-page) + $params{content} =~ s/{{\+\$([-\w]+)\+}}/get_field_value($1,$destpage)/eg; + # substitute {{+$page#var+}} variables (source-page) + $params{content} =~ s/{{\+\$([-\w\/]+)#([-\w]+)\+}}/get_other_page_field_value($2,$destpage,$1)/eg; + } + } + + return $params{content}; +} # do_filter + +#--------------------------------------------------------------- +# Private functions +# -------------------------------- +sub get_other_page_field_value ($$$) { + my $field = shift; + my $page = shift; + my $other_page = shift; + + my $use_page = bestlink($page, $other_page); + my $val = get_field_value($field, $use_page); + if ($val eq $field) + { + return "${other_page}#$field"; + } + return $val; + +} # get_other_page_field_value + +sub get_field_value ($$) { + my $field = shift; + my $page = shift; + + my $value = IkiWiki::Plugin::field::field_get_value($field,$page); + return $value if defined $value; + + # if there is no value, return the field name. + return $field; +} # get_field_value + +1; diff --git a/.library/IkiWiki/Plugin/ymlfront.pm b/.library/IkiWiki/Plugin/ymlfront.pm new file mode 100644 index 00000000..3811591b --- /dev/null +++ b/.library/IkiWiki/Plugin/ymlfront.pm @@ -0,0 +1,426 @@ +#!/usr/bin/perl +# YAML format for structured data +# See plugins/contrib/ymlfront for documentation. +package IkiWiki::Plugin::ymlfront; +use warnings; +use strict; +=head1 NAME + +IkiWiki::Plugin::ymlfront - add YAML-format data to a page + +=head1 VERSION + +This describes version B<0.03> of IkiWiki::Plugin::ymlfront + +=cut + +our $VERSION = '0.03'; + +=head1 PREREQUISITES + + IkiWiki + IkiWiki::Plugin::field + YAML::Any + +=head1 AUTHOR + + Kathryn Andersen (RUBYKAT) + http://github.com/rubykat + +=head1 COPYRIGHT + +Copyright (c) 2009 Kathryn Andersen + +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +=cut +use IkiWiki 3.00; + +sub import { + hook(type => "getsetup", id => "ymlfront", call => \&getsetup); + hook(type => "checkconfig", id => "ymlfront", call => \&checkconfig); + hook(type => "filter", id => "ymlfront", call => \&filter, first=>1); + hook(type => "preprocess", id => "ymlfront", call => \&preprocess, scan=>1); + hook(type => "scan", id => "ymlfront", call => \&scan); + hook(type => "checkcontent", id => "ymlfront", call => \&checkcontent); + + IkiWiki::loadplugin('field'); + IkiWiki::Plugin::field::field_register(id=>'ymlfront', + call=>\&yml_get_value, + first=>1); +} + +# ------------------------------------------------------------ +# Hooks +# -------------------------------- +sub getsetup () { + return + plugin => { + safe => 1, + rebuild => 1, + }, + ymlfront_delim => { + type => "array", + example => "ymlfront_sep => [qw(--YAML-START-- --YAML-END--)]", + description => "delimiters of YAML data", + safe => 0, + rebuild => undef, + }, +} + +sub checkconfig () { + eval q{use YAML::Any}; + eval q{use YAML} if $@; + if ($@) + { + return error ("ymlfront: failed to use YAML::Any or YAML"); + } + + $YAML::UseBlock = 1; + $YAML::Syck::ImplicitUnicode = 1; + + if (!defined $config{ymlfront_delim}) + { + $config{ymlfront_delim} = [qw(--- ---)]; + } +} # checkconfig + +# scan gets called before filter +sub scan (@) { + my %params=@_; + my $page = $params{page}; + + my $page_file=$pagesources{$page} || return; + my $page_type=pagetype($page_file); + if (!defined $page_type) + { + return; + } + # clear the old data + if (exists $pagestate{$page}{ymlfront}) + { + delete $pagestate{$page}{ymlfront}; + } + my $parsed_yml = parse_yml(%params); + if (defined $parsed_yml + and defined $parsed_yml->{yml}) + { + # save the data to pagestate + foreach my $fn (keys %{$parsed_yml->{yml}}) + { + my $fval = $parsed_yml->{yml}->{$fn}; + $pagestate{$page}{ymlfront}{$fn} = $fval; + } + } + # update meta hash + if (exists $pagestate{$page}{ymlfront}{title} + and $pagestate{$page}{ymlfront}{title}) + { + $pagestate{$page}{meta}{title} = $pagestate{$page}{ymlfront}{title}; + } + if (exists $pagestate{$page}{ymlfront}{description} + and $pagestate{$page}{ymlfront}{description}) + { + $pagestate{$page}{meta}{description} = $pagestate{$page}{ymlfront}{description}; + } + if (exists $pagestate{$page}{ymlfront}{author} + and $pagestate{$page}{ymlfront}{author}) + { + $pagestate{$page}{meta}{author} = $pagestate{$page}{ymlfront}{author}; + } +} # scan + +# use this for data in a [[!ymlfront ...]] directive +sub preprocess (@) { + my %params=@_; + my $page = $params{page}; + + if (! exists $params{data} + or ! defined $params{data} + or !$params{data}) + { + error gettext("missing data parameter") + } + # All the work of this is done in scan mode; + # when in preprocessing mode, just return an empty string. + my $scan=! defined wantarray; + + if (!$scan) + { + return ''; + } + + # clear the old data + if (exists $pagestate{$page}{ymlfront}) + { + delete $pagestate{$page}{ymlfront}; + } + my $parsed_yml = parse_yml(%params); + if (defined $parsed_yml + and defined $parsed_yml->{yml}) + { + # save the data to pagestate + foreach my $fn (keys %{$parsed_yml->{yml}}) + { + my $fval = $parsed_yml->{yml}->{$fn}; + $pagestate{$page}{ymlfront}{$fn} = $fval; + } + } + # update meta hash + if (exists $pagestate{$page}{ymlfront}{title} + and $pagestate{$page}{ymlfront}{title}) + { + $pagestate{$page}{meta}{title} = $pagestate{$page}{ymlfront}{title}; + } + if (exists $pagestate{$page}{ymlfront}{description} + and $pagestate{$page}{ymlfront}{description}) + { + $pagestate{$page}{meta}{description} = $pagestate{$page}{ymlfront}{description}; + } + if (exists $pagestate{$page}{ymlfront}{author} + and $pagestate{$page}{ymlfront}{author}) + { + $pagestate{$page}{meta}{author} = $pagestate{$page}{ymlfront}{author}; + } + return ''; +} # preprocess + +sub filter (@) { + my %params=@_; + my $page = $params{page}; + + my $page_file=$pagesources{$page} || return $params{content}; + my $page_type=pagetype($page_file); + if (!defined $page_type) + { + return $params{content}; + } + my $parsed_yml = parse_yml(%params); + if (defined $parsed_yml + and defined $parsed_yml->{yml} + and defined $parsed_yml->{content}) + { + $params{content} = $parsed_yml->{content}; + # also check for a content value + if (exists $pagestate{$page}{ymlfront}{content} + and defined $pagestate{$page}{ymlfront}{content} + and $pagestate{$page}{ymlfront}{content}) + { + $params{content} .= $pagestate{$page}{ymlfront}{content}; + } + } + + return $params{content}; +} # filter + +# check the correctness of the YAML code before saving a page +sub checkcontent { + my %params=@_; + my $page = $params{page}; + + my $page_file=$pagesources{$page}; + if ($page_file) + { + my $page_type=pagetype($page_file); + if (!defined $page_type) + { + return undef; + } + } + my $parsed_yml = parse_yml(%params); + if (!defined $parsed_yml) + { + debug("ymlfront: Save of $page failed: $@"); + return gettext("YAML data incorrect: $@"); + } + return undef; +} # checkcontent + +# ------------------------------------------------------------ +# Field functions +# -------------------------------- +sub yml_get_value ($$) { + my $field_name = shift; + my $page = shift; + + my $value = undef; + if (exists $pagestate{$page}{ymlfront}{$field_name}) + { + $value = $pagestate{$page}{ymlfront}{$field_name}; + } + elsif (exists $pagestate{$page}{ymlfront}{lc($field_name)}) + { + $value = $pagestate{$page}{ymlfront}{lc($field_name)}; + } + if (defined $value) + { + if (ref $value) + { + my @value_array = @{$value}; + return (wantarray + ? @value_array + : join(",", @value_array)); + } + else + { + return (wantarray ? ($value) : $value); + } + } + return undef; +} # yml_get_value + +# ------------------------------------------------------------ +# Helper functions +# -------------------------------- + +# parse the YAML data from the given content +# Expects page, content +# Returns { yml=>%yml_data, content=>$content } or undef +sub parse_yml { + my %params=@_; + my $page = $params{page}; + my $content = $params{content}; + + my $page_file=$pagesources{$page}; + if ($page_file) + { + my $page_type=pagetype($page_file); + if (!defined $page_type) + { + return undef; + } + } + my $start_of_content = ''; + my $yml_str = ''; + my $rest_of_content = ''; + if ($params{data}) + { + $yml_str = $params{data}; + } + elsif ($content) + { + my $regex = qr{ + (\\?) # 1: escape? + \[\[(!) # directive open; 2: prefix + (ymlfront) # 3: command + ( # 4: the parameters.. + \s+ # Must have space if parameters present + (?: + (?:[-\w]+=)? # named parameter key? + (?: + """.*?""" # triple-quoted value + | + "[^"]*?" # single-quoted value + | + [^"\s\]]+ # unquoted value + ) + \s* # whitespace or end + # of directive + ) + *)? # 0 or more parameters + \]\] # directive closed + }sx; + my $ystart = $config{ymlfront_delim}[0]; + my $yend = $config{ymlfront_delim}[1]; + if ($ystart eq '---' + and $yend eq '---' + and $content =~ /^---[\n\r](.*?[\n\r])---[\n\r](.*)$/s) + { + $yml_str = $1; + $rest_of_content = $2; + } + elsif ($content =~ /^(.*?)${ystart}[\n\r](.*?[\n\r])${yend}([\n\r].*)$/s) + { + $yml_str = $2; + $rest_of_content = $1 . $3; + } + elsif ($content =~ /$regex/) + { + my $escape=$1; + my $prefix=$2; + my $command=$3; + my $params=$4; + if ($escape) + { + $rest_of_content = $content; + } + else + { + my %phash = (); + while ($params =~ m{ + (?:([-\w]+)=)? # 1: named parameter key? + (?: + """(.*?)""" # 2: triple-quoted value + | + "([^"]*?)" # 3: single-quoted value + | + (\S+) # 4: unquoted value + ) + (?:\s+|$) # delimiter to next param + }sgx) { + my $key=$1; + my $val; + if (defined $2) { + $val=$2; + $val=~s/\r\n/\n/mg; + $val=~s/^\n+//g; + $val=~s/\n+$//g; + } + elsif (defined $3) { + $val=$3; + } + elsif (defined $4) { + $val=$4; + } + + if (defined $key) { + $phash{$key} = $val; + } + else { + $phash{''} = $val; + } + } + if (defined $phash{data}) + { + $yml_str = $phash{data}; + $content =~ /^(.*?)\[\[!ymlfront.*?\]\](.*?)$/s; + $start_of_content = $1; + $rest_of_content = $2; + } + } + } + } + if ($yml_str) + { + # if {{$page}} is there, do an immediate substitution + $yml_str =~ s/\{\{\$page\}\}/$page/sg; + + my $ydata; + eval q{$ydata = Load($yml_str);}; + if ($@) + { + debug("ymlfront: Load of $page failed: $@"); + return undef; + } + if (!$ydata) + { + debug("ymlfront: no YAML for $page"); + return undef; + } + my %lc_data = (); + if ($ydata) + { + # make lower-cased versions of the data + foreach my $fn (keys %{$ydata}) + { + my $fval = $ydata->{$fn}; + $lc_data{lc($fn)} = $fval; + } + } + return { yml=>\%lc_data, + content=>$start_of_content . $rest_of_content}; + } + return { yml=>undef, content=>$content }; +} # parse_yml +1; diff --git a/ikiwiki.setup b/ikiwiki.setup index 071df640..ea8a266d 100644 --- a/ikiwiki.setup +++ b/ikiwiki.setup @@ -62,6 +62,7 @@ IkiWiki::Setup::Standard->import({ add_plugins => [qw{goodstuff cutpaste editdiff edittemplate favicon html search sidebar table txt + field getfield ymlfront copyright license texinfo}], # plugins to disable disable_plugins => [], @@ -316,10 +317,11 @@ IkiWiki::Setup::Standard->import({ ###################################################################### # other plugins # (aggregate, autoindex, brokenlinks, camelcase, ddate, embed, - # favicon, flattr, goodstuff, htmlbalance, localstyle, - # pagetemplate, pingee, pinger, prettydate, recentchanges, - # recentchangesdiff, relativedate, rsync, sidebar, smiley, - # sortnaturally, tag, testpagespec, underlay) + # favicon, field, flattr, getfield, goodstuff, htmlbalance, + # localstyle, pagetemplate, pingee, pinger, prettydate, + # recentchanges, recentchangesdiff, relativedate, rsync, + # sidebar, smiley, sortnaturally, tag, testpagespec, underlay, + # ymlfront) ###################################################################### # aggregate plugin @@ -332,6 +334,14 @@ IkiWiki::Setup::Standard->import({ # list of words to not turn into links #camelcase_ignore => [], + # field plugin + # simple registration of fields by plugin + #field_register => 'field_register => {meta => \'last\'}', + # allow config settings to be queried + #field_allow_config => 0, + # fields flagged as tag-fields + #field_tags => 'field_tags => {BookAuthor => \'/books/authors\'}', + # flattr plugin # userid or user name to use by default for Flattr buttons #flattr_userid => 'joeyh', @@ -367,4 +377,8 @@ IkiWiki::Setup::Standard->import({ # underlay plugin # extra underlay directories to add #add_underlays => '', + + # ymlfront plugin + # delimiters of YAML data + ymlfront_delim => [qw{--YAML-START-- --YAML-END--}], }) -- cgit v1.2.3 From 5197f363475e6218c56b1629d6509fd4fcc61cda Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Thu, 9 Sep 2010 14:09:12 +0200 Subject: .library/IkiWiki/Plugin/getfield.pm (get_other_page_field_value): Add a dependency for the page from which we get the value. --- .library/IkiWiki/Plugin/getfield.pm | 3 +++ 1 file changed, 3 insertions(+) (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/getfield.pm b/.library/IkiWiki/Plugin/getfield.pm index 3a967d8e..d6564eaf 100644 --- a/.library/IkiWiki/Plugin/getfield.pm +++ b/.library/IkiWiki/Plugin/getfield.pm @@ -100,6 +100,9 @@ sub get_other_page_field_value ($$$) { my $other_page = shift; my $use_page = bestlink($page, $other_page); + # add a dependency for the page from which we get the value + add_depends($page, $other_page); + my $val = get_field_value($field, $use_page); if ($val eq $field) { -- cgit v1.2.3 From 7621d5ef5b43eff237fc6bad0fe03c89be5ea2eb Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Mon, 13 Sep 2010 09:20:03 +0200 Subject: .library/IkiWiki/Plugin/field.pm (field_set_template_values): Don't redefine if the field already has a value. --- .library/IkiWiki/Plugin/field.pm | 3 +++ ikiwiki.setup | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/field.pm b/.library/IkiWiki/Plugin/field.pm index e53474e9..77247ad4 100644 --- a/.library/IkiWiki/Plugin/field.pm +++ b/.library/IkiWiki/Plugin/field.pm @@ -356,6 +356,9 @@ sub field_set_template_values ($$;@) { my @parameter_names = $template->param(); foreach my $field (@parameter_names) { + # Don't redefine if the field already has a value. + next if ($template->param($field)); + my $type = $template->query(name => $field); if ($type eq 'LOOP' and $field =~ /_LOOP$/i) { diff --git a/ikiwiki.setup b/ikiwiki.setup index 2a6e6540..4c61028f 100644 --- a/ikiwiki.setup +++ b/ikiwiki.setup @@ -339,7 +339,7 @@ IkiWiki::Setup::Standard->import({ # field plugin # simple registration of fields by plugin - field_register => {meta => 'last'}, + #field_register => {meta => 'last'}, # allow config settings to be queried #field_allow_config => 0, # fields flagged as tag-fields -- cgit v1.2.3 From 3a2cf01b8d9adcd2628dcf7af371264f6b9841bb Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Fri, 17 Sep 2010 12:06:31 +0200 Subject: .library/IkiWiki/Plugin/getfield.pm (get_other_page_field_value): Depend on use_page, not other_page. --- .library/IkiWiki/Plugin/getfield.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/getfield.pm b/.library/IkiWiki/Plugin/getfield.pm index d6564eaf..ecdd4672 100644 --- a/.library/IkiWiki/Plugin/getfield.pm +++ b/.library/IkiWiki/Plugin/getfield.pm @@ -101,7 +101,7 @@ sub get_other_page_field_value ($$$) { my $use_page = bestlink($page, $other_page); # add a dependency for the page from which we get the value - add_depends($page, $other_page); + add_depends($page, $use_page); my $val = get_field_value($field, $use_page); if ($val eq $field) -- cgit v1.2.3 From fe368cda90cd374c68780c238481b1208056655f Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Thu, 25 Nov 2010 14:18:54 +0100 Subject: Update to b329454a41390ca8b3f31215d62542a27e6a8b80 of . --- .library/IkiWiki/Plugin/field.pm | 261 ++++++++++++++++++++++-------------- .library/IkiWiki/Plugin/getfield.pm | 4 +- .library/IkiWiki/Plugin/ymlfront.pm | 52 +++---- 3 files changed, 189 insertions(+), 128 deletions(-) (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/field.pm b/.library/IkiWiki/Plugin/field.pm index 77247ad4..d77e7282 100644 --- a/.library/IkiWiki/Plugin/field.pm +++ b/.library/IkiWiki/Plugin/field.pm @@ -10,11 +10,11 @@ IkiWiki::Plugin::field - front-end for per-page record fields. =head1 VERSION -This describes version B<0.05> of IkiWiki::Plugin::field +This describes version B<1.20101101> of IkiWiki::Plugin::field =cut -our $VERSION = '0.05'; +our $VERSION = '1.20101115'; =head1 PREREQUISITES @@ -133,7 +133,7 @@ sub scan (@) { # scan for tag fields if ($config{field_tags}) { - foreach my $field (sort keys %{$config{field_tags}}) + foreach my $field (keys %{$config{field_tags}}) { my @values = field_get_value($field, $page); if (@values) @@ -177,28 +177,9 @@ sub field_register (%) { return 0; } - $Fields{$param{id}} = \%param; - if (!exists $param{call}) - { - # closure to get the data from the pagestate hash - $Fields{$param{id}}->{call} = sub { - my $field_name = shift; - my $page = shift; - if (exists $pagestate{$page}{$param{id}}{$field_name}) - { - return (wantarray - ? ($pagestate{$page}{$param{id}}{$field_name}) - : $pagestate{$page}{$param{id}}{$field_name}); - } - elsif (exists $pagestate{$page}{$param{id}}{lc($field_name)}) - { - return (wantarray - ? ($pagestate{$page}{$param{id}}{lc($field_name)}) - : $pagestate{$page}{$param{id}}{lc($field_name)}); - } - return undef; - }; - } + my $id = $param{id}; + $Fields{$id} = \%param; + # add this to the ordering hash # first, last, order; by default, middle my $when = ($param{first} @@ -219,7 +200,7 @@ sub field_register (%) { : '_middle' ) )); - add_lookup_order($param{id}, $when); + add_lookup_order($id, $when); return 1; } # field_register @@ -238,100 +219,105 @@ sub field_get_value ($$) { # any field that happens to be defined in a YAML page file, which # could be anything! - my $value = undef; - my @array_value = undef; - # check the cache first - if (exists $Cache{$page}{$field_name} - and defined $Cache{$page}{$field_name}) + my $lc_field_name = lc($field_name); + if (wantarray) + { + if (exists $Cache{$page}{$lc_field_name}{array} + and defined $Cache{$page}{$lc_field_name}{array}) + { + return @{$Cache{$page}{$lc_field_name}{array}}; + } + } + else { - return (wantarray - ? @{$Cache{$page}{$field_name}{array}} - : $Cache{$page}{$field_name}{scalar}); + if (exists $Cache{$page}{$lc_field_name}{scalar} + and defined $Cache{$page}{$lc_field_name}{scalar}) + { + return $Cache{$page}{$lc_field_name}{scalar}; + } } if (!@FieldsLookupOrder) { build_fields_lookup_order(); } - foreach my $id (@FieldsLookupOrder) - { - $value = $Fields{$id}{call}->($field_name, $page); - @array_value = $Fields{$id}{call}->($field_name, $page); - if (defined $value) - { - last; - } - } - # extra definitions - if (!defined $value) + # Get either the scalar or the array value depending + # on what is requested - don't get both because it wastes time. + if (wantarray) { - # Exception for titles - # If the title hasn't been found, construct it - if ($field_name eq 'title') - { - $value = pagetitle(IkiWiki::basename($page)); - } - # and set "page" if desired - elsif ($field_name eq 'page') + my @array_value = undef; + foreach my $id (@FieldsLookupOrder) { - $value = $page; - } - # the page above this page; aka the current directory - elsif ($field_name eq 'parent_page') - { - if ($page =~ m{^(.*)/[-\.\w]+$}) + # get the data from the pagestate hash if it's there + if (exists $pagestate{$page}{$id}{$field_name} + and defined $pagestate{$page}{$id}{$field_name}) + { + @array_value = (ref $pagestate{$page}{$id}{$field_name} + ? @{$pagestate{$page}{$id}{$field_name}} + : ($pagestate{$page}{$id}{$field_name})); + } + elsif (exists $pagestate{$page}{$id}{$lc_field_name} + and defined $pagestate{$page}{$id}{$lc_field_name}) + { + @array_value = (ref $pagestate{$page}{$id}{$lc_field_name} + ? @{$pagestate{$page}{$id}{$lc_field_name}} + : ($pagestate{$page}{$id}{$lc_field_name})); + } + elsif (exists $Fields{$id}{call}) { - $value = $1; + @array_value = $Fields{$id}{call}->($field_name, $page); + } + if (@array_value and $array_value[0]) + { + last; } } - elsif ($field_name eq 'basename') + if (!@array_value) { - $value = IkiWiki::basename($page); + @array_value = field_calculated_values($field_name, $page); } - elsif ($config{field_allow_config} - and $field_name =~ /^config-(.*)$/i) + # cache the value + $Cache{$page}{$lc_field_name}{array} = \@array_value; + return @array_value; + } + else # scalar + { + my $value = undef; + foreach my $id (@FieldsLookupOrder) { - my $cfield = $1; - if (exists $config{$cfield}) + # get the data from the pagestate hash if it's there + # but only if it's already a scalar + if (exists $pagestate{$page}{$id}{$field_name} + and !ref $pagestate{$page}{$id}{$field_name}) { - $value = $config{$cfield}; + $value = $pagestate{$page}{$id}{$field_name}; } - } - elsif ($field_name =~ /^(.*)-tagpage$/) - { - my $real_fn = $1; - if (exists $config{field_tags}{$real_fn} - and defined $config{field_tags}{$real_fn}) + elsif (exists $pagestate{$page}{$id}{$lc_field_name} + and !ref $pagestate{$page}{$id}{$lc_field_name}) { - my @values = field_get_value($real_fn, $page); - if (@values) - { - foreach my $tag (@values) - { - if ($tag) - { - my $link = $config{field_tags}{$real_fn} . '/' . $tag; - push @array_value, $link; - } - } - $value = join(",", @array_value); - } + $value = $pagestate{$page}{$id}{$lc_field_name}; + } + elsif (exists $Fields{$id}{call}) + { + $value = $Fields{$id}{call}->($field_name, $page); + } + if (defined $value) + { + last; } } - } - if (defined $value) - { - if (!@array_value) + if (!defined $value) { - @array_value = ($value); + $value = field_calculated_values($field_name, $page); } # cache the value - $Cache{$page}{$field_name}{scalar} = $value; - $Cache{$page}{$field_name}{array} = \@array_value; + $Cache{$page}{$lc_field_name}{scalar} = $value; + return $value; } - return (wantarray ? @array_value : $value); + + return undef; } # field_get_value # set the values for the given HTML::Template template @@ -356,11 +342,11 @@ sub field_set_template_values ($$;@) { my @parameter_names = $template->param(); foreach my $field (@parameter_names) { - # Don't redefine if the field already has a value. + # Don't redefine if the field already has a value set. next if ($template->param($field)); my $type = $template->query(name => $field); - if ($type eq 'LOOP' and $field =~ /_LOOP$/i) + if ($type eq 'LOOP' and $field =~ /_LOOP$/oi) { # Loop fields want arrays. # Figure out what field names to look for: @@ -371,7 +357,7 @@ sub field_set_template_values ($$;@) { my %loop_field_arrays = (); foreach my $fn (@loop_fields) { - if ($fn !~ /^__/) # not a special loop variable + if ($fn !~ /^__/o) # not a special loop variable { my @ival_array = $get_value_fn->($fn, $page); if (@ival_array) @@ -418,7 +404,7 @@ sub add_lookup_order { my $when = shift; # may have given an explicit ordering - if ($when =~ /^[A-Z][A-Z]$/) + if ($when =~ /^[A-Z][A-Z]$/o) { $Fields{$id}{seq} = $when; } @@ -426,7 +412,7 @@ sub add_lookup_order { { my $cmp = '='; my $seq_field = $when; - if ($when =~ /^([<>])(.+)$/) + if ($when =~ /^([<>])(.+)$/o) { $cmp = $1; $seq_field = $2; @@ -479,6 +465,77 @@ sub build_fields_lookup_order { } } # build_fields_lookup_order +# standard values deduced from other values +sub field_calculated_values { + my $field_name = shift; + my $page = shift; + + my $value = undef; + + # Exception for titles + # If the title hasn't been found, construct it + if ($field_name eq 'title') + { + $value = pagetitle(IkiWiki::basename($page)); + } + # and set "page" if desired + elsif ($field_name eq 'page') + { + $value = $page; + } + # the page above this page; aka the current directory + elsif ($field_name eq 'parent_page') + { + if ($page =~ m{^(.*)/[-\.\w]+$}o) + { + $value = $1; + } + } + elsif ($field_name eq 'basename') + { + $value = IkiWiki::basename($page); + } + elsif ($config{field_allow_config} + and $field_name =~ /^config-(.*)$/oi) + { + my $cfield = $1; + if (exists $config{$cfield}) + { + $value = $config{$cfield}; + } + } + elsif ($field_name =~ /^(.*)-tagpage$/o) + { + my @array_value = undef; + my $real_fn = $1; + if (exists $config{field_tags}{$real_fn} + and defined $config{field_tags}{$real_fn}) + { + my @values = field_get_value($real_fn, $page); + if (@values) + { + foreach my $tag (@values) + { + if ($tag) + { + my $link = $config{field_tags}{$real_fn} . '/' . $tag; + push @array_value, $link; + } + } + if (wantarray) + { + return @array_value; + } + else + { + $value = join(",", @array_value) if $array_value[0]; + } + } + } + } + return (wantarray ? ($value) : $value); +} # field_calculated_values + # match field funcs # page-to-check, wanted sub match_a_field ($$) { @@ -488,7 +545,7 @@ sub match_a_field ($$) { # The field name is first; the rest is the match my $field_name; my $glob; - if ($wanted =~ /^(\w+)\s+(.*)$/) + if ($wanted =~ /^(\w+)\s+(.*)$/o) { $field_name = $1; $glob = $2; @@ -526,7 +583,7 @@ sub match_a_field_item ($$) { # The field name is first; the rest is the match my $field_name; my $glob; - if ($wanted =~ /^(\w+)\s+(.*)$/) + if ($wanted =~ /^(\w+)\s+(.*)$/o) { $field_name = $1; $glob = $2; @@ -607,7 +664,7 @@ sub match_field_tagged ($$;@) { # The field name is first; the rest is the match my $field_name; my $glob; - if ($wanted =~ /^(\w+)\s+(.*)$/) + if ($wanted =~ /^(\w+)\s+(.*)$/o) { $field_name = $1; $glob = $2; diff --git a/.library/IkiWiki/Plugin/getfield.pm b/.library/IkiWiki/Plugin/getfield.pm index ecdd4672..971e7ecb 100644 --- a/.library/IkiWiki/Plugin/getfield.pm +++ b/.library/IkiWiki/Plugin/getfield.pm @@ -10,11 +10,11 @@ IkiWiki::Plugin::getfield - query the values of fields =head1 VERSION -This describes version B<0.02> of IkiWiki::Plugin::getfield +This describes version B<1.20101101> of IkiWiki::Plugin::getfield =cut -our $VERSION = '0.02'; +our $VERSION = '1.20101101'; =head1 PREREQUISITES diff --git a/.library/IkiWiki/Plugin/ymlfront.pm b/.library/IkiWiki/Plugin/ymlfront.pm index 3811591b..6af4e5d6 100644 --- a/.library/IkiWiki/Plugin/ymlfront.pm +++ b/.library/IkiWiki/Plugin/ymlfront.pm @@ -10,11 +10,11 @@ IkiWiki::Plugin::ymlfront - add YAML-format data to a page =head1 VERSION -This describes version B<0.03> of IkiWiki::Plugin::ymlfront +This describes version B<1.20100808> of IkiWiki::Plugin::ymlfront =cut -our $VERSION = '0.03'; +our $VERSION = '1.20101116'; =head1 PREREQUISITES @@ -51,6 +51,31 @@ sub import { first=>1); } +# ------------------------------------------------------------ +# Package Vars +# -------------------------------- +my $ymlfront_regex = qr{ + (\\?) # 1: escape? + \[\[(!) # directive open; 2: prefix + (ymlfront) # 3: command + ( # 4: the parameters.. + \s+ # Must have space if parameters present + (?: + (?:[-\w]+=)? # named parameter key? + (?: + """.*?""" # triple-quoted value + | + "[^"]*?" # single-quoted value + | + [^"\s\]]+ # unquoted value + ) + \s* # whitespace or end + # of directive + ) + *)? # 0 or more parameters + \]\] # directive closed + }sx; + # ------------------------------------------------------------ # Hooks # -------------------------------- @@ -300,27 +325,6 @@ sub parse_yml { } elsif ($content) { - my $regex = qr{ - (\\?) # 1: escape? - \[\[(!) # directive open; 2: prefix - (ymlfront) # 3: command - ( # 4: the parameters.. - \s+ # Must have space if parameters present - (?: - (?:[-\w]+=)? # named parameter key? - (?: - """.*?""" # triple-quoted value - | - "[^"]*?" # single-quoted value - | - [^"\s\]]+ # unquoted value - ) - \s* # whitespace or end - # of directive - ) - *)? # 0 or more parameters - \]\] # directive closed - }sx; my $ystart = $config{ymlfront_delim}[0]; my $yend = $config{ymlfront_delim}[1]; if ($ystart eq '---' @@ -335,7 +339,7 @@ sub parse_yml { $yml_str = $2; $rest_of_content = $1 . $3; } - elsif ($content =~ /$regex/) + elsif ($content =~ $ymlfront_regex) { my $escape=$1; my $prefix=$2; -- cgit v1.2.3 From 7280981382b9dabd94874b9dca6591e7d351fc36 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Fri, 26 Nov 2010 11:37:26 +0100 Subject: .library/IkiWiki/Plugin/ymlfront.pm: Workaround for YAML strings containing ]]. For now, all [[!ymlfront [...]]] directives shall be at the end of the files. --- .library/IkiWiki/Plugin/ymlfront.pm | 4 ++++ 1 file changed, 4 insertions(+) (limited to '.library/IkiWiki/Plugin') diff --git a/.library/IkiWiki/Plugin/ymlfront.pm b/.library/IkiWiki/Plugin/ymlfront.pm index 6af4e5d6..9c033833 100644 --- a/.library/IkiWiki/Plugin/ymlfront.pm +++ b/.library/IkiWiki/Plugin/ymlfront.pm @@ -391,6 +391,10 @@ sub parse_yml { $content =~ /^(.*?)\[\[!ymlfront.*?\]\](.*?)$/s; $start_of_content = $1; $rest_of_content = $2; + # TODO: This breaks if the YAML string itself contains ]]. + # Workaround: all [[!ymlfront [...]]] directives shall be + # at the end of the files. + $rest_of_content = ''; } } } -- cgit v1.2.3