summaryrefslogtreecommitdiff
path: root/IkiWiki/Plugin/smiley.pm
blob: 50f2686277afa2de60ef86bd88a870938f1c96e4 (plain)
  1. #!/usr/bin/perl
  2. package IkiWiki::Plugin::smiley;
  3. use warnings;
  4. use strict;
  5. use IkiWiki 2.00;
  6. my %smileys;
  7. my $smiley_regexp;
  8. sub import { #{{{
  9. add_underlay("smiley");
  10. hook(type => "sanitize", id => "smiley", call => \&sanitize);
  11. } # }}}
  12. sub build_regexp () { #{{{
  13. my $list=readfile(srcfile("smileys.mdwn"));
  14. while ($list =~ m/^\s*\*\s+\\\\([^\s]+)\s+\[\[([^]]+)\]\]/mg) {
  15. my $smiley=$1;
  16. my $file=$2;
  17. $smileys{$smiley}=$file;
  18. # Add a version with < and > escaped, since they probably
  19. # will be (by markdown) by the time the sanitize hook runs.
  20. $smiley=~s/</&lt;/g;
  21. $smiley=~s/>/&gt;/g;
  22. $smileys{$smiley}=$file;
  23. }
  24. if (! %smileys) {
  25. debug(gettext("failed to parse any smileys"));
  26. $smiley_regexp='';
  27. return;
  28. }
  29. # sort and reverse so that substrings come after longer strings
  30. # that contain them, in most cases.
  31. $smiley_regexp='('.join('|', map { quotemeta }
  32. reverse sort keys %smileys).')';
  33. #debug($smiley_regexp);
  34. } #}}}
  35. sub sanitize (@) { #{{{
  36. my %params=@_;
  37. build_regexp() unless defined $smiley_regexp;
  38. $_=$params{content};
  39. return $_ unless length $smiley_regexp;
  40. MATCH: while (m{(?:^|(?<=\s|>))(\\?)$smiley_regexp(?:(?=\s|<)|$)}g) {
  41. my $escape=$1;
  42. my $smiley=$2;
  43. my $epos=$-[1];
  44. my $spos=$-[2];
  45. # Smilies are not allowed inside <pre> or <code>.
  46. # For each tag in turn, match forward to find the next <tag>
  47. # or </tag> after the smiley.
  48. my $pos=pos;
  49. foreach my $tag ("pre", "code") {
  50. if (m/<(\/)?\s*$tag\s*>/isg && defined $1) {
  51. # </tag> found first, so the smiley is
  52. # inside the tag, so do not expand it.
  53. next MATCH;
  54. }
  55. # Reset pos back to where it was before this test.
  56. pos=$pos;
  57. }
  58. if ($escape) {
  59. # Remove escape.
  60. substr($_, $epos, 1)="";
  61. pos=$epos+1;
  62. }
  63. else {
  64. # Replace the smiley with its expanded value.
  65. substr($_, $spos, length($smiley))=
  66. htmllink($params{page}, $params{destpage},
  67. $smileys{$smiley}, linktext => $smiley);
  68. pos=$epos+1;
  69. }
  70. # Breaks out at end, otherwise it will scan through again,
  71. # replacing de-escaped ones.
  72. #last unless defined pos;
  73. }
  74. return $_;
  75. } # }}}
  76. 1