1# See bottom of file for license and copyright information
2#
3# This plugin replaces smilies with small smilies bitmaps
4
5package Foswiki::Plugins::SmiliesPlugin;
6
7use strict;
8use warnings;
9
10use Foswiki::Func ();
11
12our %cache = ();
13our $current;
14
15our $VERSION           = '2.03';
16our $RELEASE           = '17 Sep 2015';
17our $NO_PREFS_IN_TOPIC = 1;
18our $SHORTDESCRIPTION  = 'Render smilies like :-) as icons';
19our $doneHeader        = 0;
20
21sub initPlugin {
22
23    Foswiki::Func::registerTagHandler( 'SMILIES', \&_renderSmilies );
24
25    my $web   = $Foswiki::cfg{SystemWebName};
26    my $topic = Foswiki::Func::getPreferencesValue('SMILIESPLUGIN_TOPIC')
27      || "SmiliesPlugin";
28
29    $doneHeader = 0;
30
31    _loadSmilies( $web, $topic );
32
33    return 1;
34}
35
36sub preRenderingHandler {
37
38    if ( $_[0] =~
39        s/(\s|^)$cache{$current}{pattern}(?=\s|$)/_renderSmily($1,$2)/ge )
40    {
41        _addToZone();
42    }
43}
44
45sub _addToZone {
46    return if $doneHeader;
47    $doneHeader = 1;
48    Foswiki::Func::addToZone( "head", "SMILIESPLUGIN",
49"<link rel='stylesheet' href='%PUBURLPATH%/%SYSTEMWEB%/SmiliesPlugin/smilies.css' type='text/css' media='all' />"
50    );
51}
52
53sub _loadSmilies {
54    my ( $web, $topic, $force ) = @_;
55
56    ( $web, $topic ) = Foswiki::Func::normalizeWebTopicName( $web, $topic );
57
58    $current = "$web.$topic";
59    return if !$force && defined $cache{$current};
60
61    $cache{$current} = ();
62
63    $cache{$current}{format} =
64      Foswiki::Func::getPreferencesValue('SMILIESPLUGIN_FORMAT')
65      || '<img class=\'smily\' src=\'$url\' alt=\'$tooltip\' title=\'$tooltip\' />';
66
67    $cache{$current}{pattern} = "(";
68    my $state = 0;
69    my ( $meta, $text ) = Foswiki::Func::readTopic( $web, $topic );
70    foreach my $line ( split( /\n/, $text || '' ) ) {
71
72        # | smily | image | description |
73        if ( $line =~ m/^\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*$/ ) {
74
75            my $alternatives = $1;
76            my $image        = $2;
77            my $desc         = $3;
78
79            if ( $alternatives =~ m/^\*/ ) {
80                $state = 1;
81                next;
82            }
83
84            $image =~ s/%ATTACHURL(PATH)?%//g;
85            $desc  =~ s/"//g;
86
87            next unless $alternatives && $image;
88
89            foreach my $key ( split( /\s+/, $alternatives ) ) {
90                $key =~ s/<nop>|\&nbsp;//g;
91                $cache{$current}{pattern} .= "\Q$key\E|";
92                $cache{$current}{image}{$key} = $image;
93                $cache{$current}{desc}{$key}  = $desc;
94                $cache{$current}{alts}{$key}  = $alternatives;
95            }
96        }
97        else {
98            last if $state == 1;
99        }
100    }
101
102    #$cache{$current}{pattern} =~ s/\|$//;
103    $cache{$current}{pattern} .= ")";
104    $cache{$current}{pubUrl} = Foswiki::Func::getPubUrlPath() . "/$web/$topic";
105
106}
107
108sub _renderSmily {
109    my ( $pre, $smily ) = @_;
110
111    return $pre unless $smily;
112    return $pre . _formatSmily( $cache{$current}{format}, $smily );
113}
114
115sub _formatSmily {
116    my ( $format, $smily ) = @_;
117
118    my $text = $format;
119
120    $text =~ s/\$key/<nop>$smily/g;
121    $text =~ s/\$alternatives/$cache{$current}{alts}{$smily}/g;
122    $text =~ s/\$emoticon/$smily/g;
123    $text =~ s/\$tooltip/$cache{$current}{desc}{$smily}/g;
124    $text =~
125      s/\$url/$cache{$current}{pubUrl}\/$cache{$current}{image}{$smily}/g;
126
127    return $text;
128}
129
130sub _renderSmilies {
131    my ( $session, $params ) = @_;
132
133    my $smily     = $params->{_DEFAULT};
134    my $header    = $params->{header};
135    my $format    = $params->{format};
136    my $footer    = $params->{footer} || '';
137    my $separator = $params->{separator} || '$n';
138
139    $header =
140'| *%MAKETEXT{"Notation"}%* | *%MAKETEXT{"Image"}%* | *%MAKETEXT{"Description"}%* |$n'
141      unless defined $header;
142
143    $format = '| $alternatives | $emoticon | $tooltip |' unless defined $format;
144
145    my @smilies = ();
146    if ( defined $smily ) {
147        push @smilies, $smily;
148    }
149    else {
150        @smilies =
151          sort {
152            lc( $cache{$current}{image}{$a} ) cmp
153              lc( $cache{$current}{image}{$b} )
154          }
155          keys %{ $cache{$current}{alts} };
156    }
157
158    my @result = ();
159    my %seen   = ();
160    foreach my $smily (@smilies) {
161        next if $seen{ $cache{$current}{alts}{$smily} };
162        push @result, _formatSmily( $format, $smily );
163        $seen{ $cache{$current}{alts}{$smily} } = 1;
164    }
165
166    return '' unless @result;
167
168    _addToZone();
169
170    return Foswiki::Func::decodeFormatTokens(
171        $header . join( $separator, @result ) . $footer );
172}
173
1741;
175__END__
176Foswiki - The Free and Open Source Wiki, http://foswiki.org/
177
178Copyright (C) 2008-2014 Foswiki Contributors. Foswiki Contributors
179are listed in the AUTHORS file in the root of this distribution.
180NOTE: Please extend that file, not this notice.
181
182Additional copyrights apply to some or all of the code in this
183file as follows:
184
185Copyright (C) 2000-2001 Andrea Sterbini, a.sterbini@flashnet.it
186Copyright (C) 2002-2006 Peter Thoeny, peter@thoeny.org
187
188This program is free software; you can redistribute it and/or
189modify it under the terms of the GNU General Public License
190as published by the Free Software Foundation; either version 2
191of the License, or (at your option) any later version. For
192more details read LICENSE in the root of this distribution.
193
194This program is distributed in the hope that it will be useful,
195but WITHOUT ANY WARRANTY; without even the implied warranty of
196MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
197
198As per the GPL, removal of this notice is prohibited.
199