Skip to content

Commit

Permalink
Merge remote branch 'bcherry/master' into hit_highlighting
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Sanford committed Apr 26, 2010
2 parents 5f857ed + b5dadc9 commit 176a61d
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 1 deletion.
5 changes: 5 additions & 0 deletions README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ Special care has been taken to be sure that auto-linking and extraction work
in Tweets of all languages. This means that languages without spaces between
words should work equally well.

=== Hit Highlighting

Use to provide emphasis around the "hits" returned from the Search API, built
to work against text that has been auto-linked already.

=== Conformance

To run the Conformance suite, you'll need to add that project as a git submodule. From the root twitter-text-rb directory, run:
Expand Down
2 changes: 1 addition & 1 deletion lib/autolink.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def auto_link(text, options = {})
options),
options)
end

# Add <tt><a></a></tt> tags around the usernames and lists in the provided <tt>text</tt>. The
# <tt><a></tt> tags can be controlled with the following entries in the <tt>options</tt>
# hash:
Expand Down
66 changes: 66 additions & 0 deletions lib/hithighlighter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@

module Twitter
# Module for doing "hit highlighting" on tweets that have been auto-linked already.
# Useful with the results returned from the Search API.
module HitHighlighter
# Default Tag used for hit highlighting
DEFAULT_HIGHLIGHT_TAG = "em"

# Add <tt><em></em></tt> tags around the <tt>hits</tt> provided in the <tt>text</tt>. The
# <tt>hits</tt> should be an array of (start, end) index pairs, relative to the original
# text, before auto-linking (but the <tt>text</tt> may already be auto-linked if desired)
def hit_highlight(text, hits = [])
if hits.empty?
return text
end

chunks = text.split("<").map do |item|
item.blank? ? item : item.split(">")
end.flatten

tags = ["<" + DEFAULT_HIGHLIGHT_TAG + ">", "</" + DEFAULT_HIGHLIGHT_TAG + ">"]

result = ""
chunk_index, chunk = 0, chunks[0]
prev_chunks_len = 0
chunk_cursor = 0
start_in_chunk = false
for hit, index in hits.flatten.each_with_index do
tag = tags[index % 2]

placed = false
until chunk.nil? || hit < prev_chunks_len + chunk.length do
result << chunk[chunk_cursor..-1]
if start_in_chunk && hit == prev_chunks_len + chunk.length
result << tag
placed = true
end
result << "<#{chunks[chunk_index+1]}>"
prev_chunks_len += chunk.length
chunk_cursor = 0
chunk_index += 2
chunk = chunks[chunk_index]
start_in_chunk = false
end

if !placed && !chunk.nil?
hit_spot = hit - prev_chunks_len
result << chunk[chunk_cursor...hit_spot] + tag
chunk_cursor = hit_spot
if index % 2 == 0
start_in_chunk = true
end
end
end

if !chunk.nil?
result << chunk[chunk_cursor..-1]
for index in chunk_index+1..chunks.length-1
result << (index.even? ? chunks[index] : "<#{chunks[index]}>")
end
end

result
end
end
end
1 change: 1 addition & 0 deletions lib/twitter-text.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
require File.join(File.dirname(__FILE__), 'extractor')
require File.join(File.dirname(__FILE__), 'unicode')
require File.join(File.dirname(__FILE__), 'validation')
require File.join(File.dirname(__FILE__), 'hithighlighter')
1 change: 1 addition & 0 deletions spec/autolinking_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ def original_text; "I like www.foobar.com dudes"; end
end

end

end

end
61 changes: 61 additions & 0 deletions spec/hithighlighter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
require File.dirname(__FILE__) + '/spec_helper'

class TestHitHighlighter
include Twitter::HitHighlighter
end

describe Twitter::HitHighlighter do
describe "highlight" do
before do
@highlighter = TestHitHighlighter.new
end

context "without links" do
before do
@original = "Hey! this is a test tweet"
end

it "should return original when no hits are provided" do
@highlighter.hit_highlight(@original).should == @original
end

it "should highlight one hit" do
@highlighter.hit_highlight(@original, hits = [[5, 9]]).should == "Hey! <em>this</em> is a test tweet"
end

it "should highlight two hits" do
@highlighter.hit_highlight(@original, hits = [[5, 9], [15, 19]]).should == "Hey! <em>this</em> is a <em>test</em> tweet"
end

end

context "with links" do
it "should highlight with a single link" do
@highlighter.hit_highlight("@<a>bcherry</a> this was a test tweet", [[9, 13]]).should == "@<a>bcherry</a> <em>this</em> was a test tweet"
end

it "should highlight with link at the end" do
@highlighter.hit_highlight("test test <a>test</a>", [[5, 9]]).should == "test <em>test</em> <a>test</a>"
end

it "should highlight with a link at the beginning" do
@highlighter.hit_highlight("<a>test</a> test test", [[5, 9]]).should == "<a>test</a> <em>test</em> test"
end

it "should highlight an entire link" do
@highlighter.hit_highlight("test <a>test</a> test", [[5, 9]]).should == "test <a><em>test</em></a> test"
end

it "should highlight within a link" do
@highlighter.hit_highlight("test <a>test</a> test", [[6, 8]]).should == "test <a>t<em>es</em>t</a> test"
end

it "should highlight around a link" do
@highlighter.hit_highlight("test <a>test</a> test", [[3, 11]]).should == "tes<em>t <a>test</a> t</em>est"
end

end

end

end

0 comments on commit 176a61d

Please sign in to comment.