-
-
Save bogdanRada/1de449a4b60ddb7c80be to your computer and use it in GitHub Desktop.
rack_spellcheck.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# If you'd like this packaged up as a gem, send me a note. You can get | |
# in touch with me at http://www.techiferous.com/about | |
require 'nokogiri' | |
require 'ispell' | |
module Rack | |
class SpellCheck | |
def initialize(app, options = {}) | |
@app = app | |
@options = options | |
# The way ispell parses words means that it's hard to skip URLs. | |
# Ignoring these "words" eases the pain somewhat. | |
@ignore = ["www", "com", "http", "org", "html"] | |
if options[:ignore].is_a? Array | |
@ignore += options[:ignore].map(&:downcase) | |
end | |
end | |
def call(env) | |
@doc = nil | |
@request = Rack::Request.new(env) | |
status, @headers, @body = @app.call(env) | |
if html? | |
find_spelling_errors | |
highlight_spelling_errors | |
update_content_length | |
end | |
[status, @headers, @body] | |
end | |
private | |
def find_spelling_errors | |
@speller = Ispell.new('ispell', 'english') # note: we are forking a process | |
doc.at_css("body").traverse do |node| | |
if node.text? | |
node.content = spellcheck(node.content) | |
end | |
end | |
@speller.destroy! # stop the process | |
@body = doc.to_html | |
end | |
def highlight_spelling_errors | |
style = "background-color: yellow; color: red; font-weight: bold;" | |
@body.gsub!('changethistobeginningtaglater', "<span style=\"#{style}\">") | |
@body.gsub!('changethistoendingtaglater', '</span>') | |
end | |
def spellcheck(text) | |
results = @speller.spellcheck(text) | |
new_text = text | |
results.each do |res| | |
case res.type | |
when :miss, :guess, :none | |
unless @ignore.include?(res.original.downcase) | |
new_text.gsub!(res.original, | |
"changethistobeginningtaglater#{res.original}changethistoendingtaglater") | |
end | |
end | |
end | |
new_text | |
end | |
def html? | |
@headers["Content-Type"] && @headers["Content-Type"].include?("text/html") | |
end | |
def doc | |
@doc ||= Nokogiri::HTML(body_to_string) | |
end | |
def body_to_string | |
s = "" | |
@body.each { |x| s << x } | |
s | |
end | |
def update_content_length | |
@headers['Content-Length'] = Rack::Utils.bytesize(@body).to_s | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment