# MTSpeling 0.2 ($Date: 2003/01/25 21:57:35 $) # by Alexei Kosut # CONFIGURATION # Set this to the path to your installation of ispell # (usually /usr/local/bin/ispell or /usr/bin/ispell) $Lingua::Ispell::path = '/usr/local/bin/ispell'; # END CONFIGURATION. You should not need to edit below this line. use MT::Template::Context; use Lingua::Ispell qw( :all ); use CGI::Cookie; use strict; sub check_word($$$); MT::Template::Context->add_global_filter(check_spelling => sub { my ($str, $val, $ctx) = @_; my $stashed = $ctx->stash('speling') || $ctx->stash('speling', []); my $result = ''; my $format; if ($val == 2) { $format = '%s'; } elsif ($val == 1) { $format = '%s'; } # Add words from personal dictionary if it exists my %cookies = fetch CGI::Cookie; if ($cookies{'spelling-dict'}) { foreach my $word (split(/:/, $cookies{'spelling-dict'}->value)) { accept_word($word); } } # Find each word that is not inside an HTML tag or an HTML entity $str =~ s/(?)/check_word($1, $stashed, $format)/ge; return $str; }); sub check_word ($$$) { my ($s, $stashed, $format) = @_; my @results = spellcheck($s); my $offset = -1; for my $r (@results) { my ($type, $term) = ($r->{'type'}, $r->{'term'}); if ($type eq 'none' || $type eq 'miss' || $type eq 'guess') { push @$stashed, $r; next unless $format; # Note that we assume the terms are output in order my $rterm = sprintf $format, $term; if ($offset + $r->{'offset'} <= length($s)) { substr($s, $offset + $r->{'offset'}, length($term), $rterm); $offset += length($rterm) - length($term); } else { die "Received an invalid offset " . $r->{'offset'} . " while spell-checking\n"; } } } return $s; } MT::Template::Context->add_conditional_tag(SpellingIfErrors => sub { my $stashed = $_[0]->stash('speling'); return defined $stashed && scalar @$stashed; }); MT::Template::Context->add_container_tag(SpellingResults => sub { my ($ctx, $args) = @_; my $stashed = $ctx->stash('speling') || []; my $builder = $ctx->stash('builder'); my $tokens = $ctx->stash('tokens'); my $result = ''; for my $r (@$stashed) { $ctx->stash('speling_entry', $r); defined(my $out = $builder->build($ctx, $tokens)) or return $ctx->error($ctx->errstr); $result .= $out; } # Clear spelling results before returning $ctx->stash('speling_entry', undef); $ctx->stash('speling', undef); return $result; }); MT::Template::Context->add_tag(SpellingResultTerm => sub { my $ctx = shift; my $entry = $ctx->stash('speling_entry') or return $ctx->error("Tag called without a speling_entry in context"); return $entry->{'term'}; }); MT::Template::Context->add_conditional_tag(SpellingResultIfSuggestions => sub { my $ctx = shift; my $entry = $ctx->stash('speling_entry') or return $ctx->error("Tag called without a speling_entry in context"); return $entry->{'type'} eq 'miss' || $entry->{'type'} eq 'guess'; }); MT::Template::Context->add_conditional_tag(SpellingResultUnlessSuggestions => sub { my $ctx = shift; my $entry = $ctx->stash('speling_entry') or return $ctx->error("Tag called without a speling_entry in context"); return $entry->{'type'} ne 'miss' && $entry->{'type'} ne 'guess'; }); MT::Template::Context->add_container_tag(SpellingResultSuggestions => sub { my ($ctx, $args) = @_; my $builder = $ctx->stash('builder'); my $tokens = $ctx->stash('tokens'); my $entry = $ctx->stash('speling_entry') or return $ctx->error("Tag called without a speling_entry in context"); my $guesses; if ($entry->{'type'} eq 'miss') { $guesses = $entry->{'misses'}; } elsif ($entry->{'type'} eq 'guess') { $guesses = $entry->{'guesses'}; } else { return ''; } my $result = ''; for my $guess (@$guesses) { $ctx->stash('speling_guess', $guess); defined(my $out = $builder->build($ctx, $tokens)) or return $ctx->error($ctx->errstr); $result .= $out; } $ctx->stash('speling_guess', undef); return $result; }); MT::Template::Context->add_tag(SpellingSuggestion => sub { my $ctx = shift; my $guess = $ctx->stash('speling_guess') or return $ctx->error("Tag called without a speling_entry in context"); return $guess; });