X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/c1196acadcec8f36c0bb018bb3baedcb92f2a278..c7bdebaaf134729356852918b387071c92f85e72:/doc/plugins/write/tutorial.mdwn diff --git a/doc/plugins/write/tutorial.mdwn b/doc/plugins/write/tutorial.mdwn index 8b12fd183..1912c8a2f 100644 --- a/doc/plugins/write/tutorial.mdwn +++ b/doc/plugins/write/tutorial.mdwn @@ -5,9 +5,9 @@ What should the plugin do? Let's make it calculate and output the Fibonacci sequence. To output the next number in the sequence, all a user has to do is write this on a wiki page: - [[fib ]] + \[[!fib]] -When the page is built, the [[ikiwiki/PreProcessorDirective]] will be +When the page is built, the [[ikiwiki/directive]] will be replaced by the next number in the sequence. Most of ikiwiki's plugins are written in Perl, and it's currently easiest @@ -27,7 +27,7 @@ important one is the IkiWiki module. use warnings; use strict; - use IkiWiki 2.00; + use IkiWiki 3.00; Ok, boilerplate is out of the way. Now to add the one function that ikiwiki expects to find in any module: `import`. The import function is called when @@ -39,16 +39,16 @@ register hooks that ikiwiki will call later. } This has hooked our plugin into the preprocess hook, which ikiwiki uses to -expand [[PreprocessorDirectives|ikiwiki/preprocessordirective]]. Notice +expand preprocessor [[directives|ikiwiki/directive]]. Notice that "fib" has shown up again. It doesn't actually have to match the module name this time, but it generally will. This "fib" is telling ikiwiki what -kind of PreprocessorDirective to handle, namely one that looks like this: +kind of preprocessor directive to handle, namely one that looks like this: - [[fib ]] + [[!fib ]] Notice the `\&preprocess`? This is how you pass a reference to a function, and the `preprocess` function is the one that ikiwiki will call to expand -the PreprocessorDirective. So, time to write that function: +the preprocessor directive. So, time to write that function: sub preprocess { my %params=@_; @@ -81,8 +81,8 @@ textbook. sub fib { my $num=shift; - return 0 if $num == 1; - return 1 if $num == 2; + return 0 if $num == 0; + return 1 if $num == 1; return fib($num - 1) + fib($num - 2); } @@ -92,17 +92,17 @@ And let's change the `preprocess` sub to use it: sub preprocess { my %params=@_; - my $num=$last++; + my $num=++$last; return fib($num); } Feel free to try it out with a simple page like this: - [[fib ]], [[fib ]], [[fib ]], [[fib ]], [[fib ]] + [[!fib ]], [[!fib ]], [[!fib ]], [[!fib ]], [[!fib ]] Looks like it works ok, doesn't it? That creates a page that lists: - 1, 1, 3, 5, 8 + 1, 1, 2, 3, 5 But what happens if there are two pages that both use fib? Try it out. If ikiwiki builds both pages in one pass, the sequence will continue @@ -116,7 +116,7 @@ a page that uses fib. Now the inlined page will have one set of numbers, and the standalone page another. The numbers might even skip over part of the sequence in some cases. -Obviously, using a global `$last` veriable was a bad idea. It would +Obviously, using a global `$last` variable was a bad idea. It would work ok in a more regular cgi-based wiki, which only outputs one page per run. But since ikiwiki is a wiki *compiler*, things are a bit more complicated. It's not very hard to fix, though, if we do want the sequence @@ -127,7 +127,7 @@ to start from 1 in every page that uses it. sub preprocess { my %params=@_; my $page=$params{destpage}; - my $num=$last{$page}++; + my $num=++$last{$page}; return fib($num); } @@ -139,13 +139,13 @@ Ok, one more enhancement. Just incrementing the numbers is pretty boring. It would be nice to be able to jump directly to a given point in the sequence: - \[[fib seed=20]], [[fib ]], [[fib ]] + \[[!fib seed=20]], [[!fib ]], [[!fib ]] Just insert these lines of code inside `preprocess`, in the appropriate spot: if (exists $params{seed}) { - $last{$page}=$params{seed}-1; + $last{$page}=$params{seed}; } But this highlights another issue with the plugin. The `fib()` function is @@ -158,7 +158,7 @@ Now, we could try to fix `fib()` to run in constant time for any number, but that's not the focus of this tutorial. Instead, let's concentrate on making the plugin use the existing function safely. A good first step would be a guard on how high it will go. - + my %last; sub preprocess { @@ -167,9 +167,9 @@ be a guard on how high it will go. if (exists $params{seed}) { $last{$page}=$params{seed}-1; } - my $num=$last{$page}++; + my $num=++$last{$page}; if ($num > 25) { - return "[[fib will only calculate the first 25 numbers in the sequence]]"; + error "can only calculate the first 25 numbers in the sequence"; } return fib($num); } @@ -178,11 +178,11 @@ Returning an error message like this is standard for preprocessor plugins, so that the user can look at the built page and see what went wrong. Are we done? Nope, there's still a security hole. Consider what `fib()` -does for numbers less than 1. Or for any number that's not an integer. In +does for numbers less than 0. Or for any number that's not an integer. In either case, it will run forever. Here's one way to fix that: - if (int($num) != $num || $num < 1) { - return "[[fib positive integers only, please]]"; + if (int($num) != $num || $num < 0) { + error "positive integers only, please"; } As these security problems have demonstrated, even a simple input from the