add paths to plugin files in copyright
[ikiwiki.git] / IkiWiki / Plugin / smiley.pm
blob6f4f49d18f4b3fb08d0d73a8ba877987fb12a94d
1 #!/usr/bin/perl
2 package IkiWiki::Plugin::smiley;
4 use warnings;
5 use strict;
6 use IkiWiki 3.00;
8 my %smileys;
9 my $smiley_regexp;
11 sub import {
12 add_underlay("smiley");
13 hook(type => "getsetup", id => "smiley", call => \&getsetup);
14 hook(type => "sanitize", id => "smiley", call => \&sanitize);
17 sub getsetup () {
18 return
19 plugin => {
20 safe => 1,
21 # force a rebuild because turning it off
22 # removes the smileys, which would break links
23 rebuild => 1,
27 sub build_regexp () {
28 my $srcfile = srcfile("smileys.mdwn", 1);
29 if (! defined $srcfile) {
30 print STDERR sprintf(gettext("smiley plugin will not work without %s"),
31 "smileys.mdwn")."\n";
32 $smiley_regexp='';
33 return;
35 my $list=readfile($srcfile);
36 while ($list =~ m/^\s*\*\s+\\\\([^\s]+)\s+\[\[([^]]+)\]\]/mg) {
37 my $smiley=$1;
38 my $file=$2;
40 $smileys{$smiley}=$file;
42 # Add a version with < and > escaped, since they probably
43 # will be (by markdown) by the time the sanitize hook runs.
44 $smiley=~s/</&lt;/g;
45 $smiley=~s/>/&gt;/g;
46 $smileys{$smiley}=$file;
49 if (! %smileys) {
50 debug(gettext("failed to parse any smileys"));
51 $smiley_regexp='';
52 return;
55 # sort and reverse so that substrings come after longer strings
56 # that contain them, in most cases.
57 $smiley_regexp='('.join('|', map { quotemeta }
58 reverse sort keys %smileys).')';
59 #debug($smiley_regexp);
62 sub sanitize (@) {
63 my %params=@_;
65 build_regexp() unless defined $smiley_regexp;
67 $_=$params{content};
68 return $_ unless length $smiley_regexp;
70 MATCH: while (m{(?:^|(?<=\s|>))(\\?)$smiley_regexp(?:(?=\s|<)|$)}g) {
71 my $escape=$1;
72 my $smiley=$2;
73 my $epos=$-[1];
74 my $spos=$-[2];
76 # Smilies are not allowed inside <pre> or <code>.
77 # For each tag in turn, match forward to find the next <tag>
78 # or </tag> after the smiley.
79 my $pos=pos;
80 foreach my $tag ("pre", "code") {
81 if (m/<(\/)?\s*$tag\s*>/isg && defined $1) {
82 # </tag> found first, so the smiley is
83 # inside the tag, so do not expand it.
84 next MATCH;
86 # Reset pos back to where it was before this test.
87 pos=$pos;
90 if ($escape) {
91 # Remove escape.
92 substr($_, $epos, 1)="";
93 pos=$epos+1;
95 else {
96 # Replace the smiley with its expanded value.
97 my $link=htmllink($params{page}, $params{destpage},
98 $smileys{$smiley}, linktext => $smiley);
99 substr($_, $spos, length($smiley))=$link;
100 pos=$epos+length($link);
104 return $_;