Skip to content

Instantly share code, notes, and snippets.

@baweaver
Created January 23, 2022 07:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save baweaver/5dbca4296db0651de41267c2c1267c68 to your computer and use it in GitHub Desktop.
Save baweaver/5dbca4296db0651de41267c2c1267c68 to your computer and use it in GitHub Desktop.
class Emboldener
def initialize(text:, targets:)
@text = text
@targets = targets
end
def run
cursor = 0
result = ""
merged_indexes.each do |range|
result << @text[cursor...range.begin]
result << embolden(@text[range])
cursor = range.end + 1
end
result
end
private def embolden(s) = "<b>#{s}</b>"
private def merged_indexes
all_matching_indexes.reduce([]) do |merged, range|
next [range] if merged.empty?
last_range = merged.pop
overlapped_range = merge_range(range, last_range)
if overlapped_range
merged.push(overlapped_range)
else
merged.push(last_range, range)
end
end
end
private def all_matching_indexes
@targets.flat_map { index_all(_1) }.sort_by(&:begin)
end
private def index_all(target)
ranges = []
cursor = 0
loop do
found_index = @text.index(target, cursor) or break
ranges.push(found_index..found_index + target.size)
cursor = found_index + target.size
end
ranges
end
private def merge_range(a, b)
return Range.new(a.begin, b.end) if a.cover?(b.begin)
return Range.new(b.begin, a.end) if b.cover?(a.begin)
nil
end
end
Emboldener.new(text: "aaabbcc", targets: ["aaa","aab","bc"]).run
# => "<b>aaabbcc</b>"
Emboldener.new(text: "abcxyz123", targets: ["abc", "bcx", "123"]).run
# => "<b>abcxy</b>z<b>123</b>"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment