| @@ -5,66 +5,59 @@ from re import sub, UNICODE | |||
| from markupsafe import escape | |||
| def highlight_delta(context, chain, delta): | |||
| degree = chain.degree - 1 | |||
| highlights = [False] * degree | |||
| block = [chain.START] * degree | |||
| for word in chain.text.split() + ([chain.END] * degree): | |||
| word = _strip_word(chain, word) | |||
| tblock = tuple(block) | |||
| if tblock in delta.chain and word in delta.chain[tblock]: | |||
| highlights[-1 * degree:] = [True] * degree | |||
| highlights.append(True) | |||
| else: | |||
| highlights.append(False) | |||
| block.pop(0) | |||
| block.append(word) | |||
| i = degree | |||
| numwords = len(chain.text.split()) | |||
| processed = [] | |||
| dchain = delta.chain | |||
| prev_prev = prev = chain.START | |||
| i = 0 | |||
| all_words = chain.text.split() | |||
| paragraphs = chain.text.split("\n") | |||
| for paragraph in paragraphs: | |||
| processed_words = [] | |||
| words = paragraph.split(" ") | |||
| for i, word in enumerate(words, i): | |||
| try: | |||
| next = _strip_word(all_words[i + 1]) | |||
| try: | |||
| next_next = _strip_word(all_words[i + 2]) | |||
| except IndexError: | |||
| next_next = chain.END | |||
| except IndexError: | |||
| next = next_next = chain.END | |||
| sword = _strip_word(word) | |||
| middle = (prev, sword) in dchain and next in dchain[(prev, sword)] | |||
| if middle: | |||
| before = after = True | |||
| else: | |||
| b_block = (prev_prev, prev) | |||
| a_block = (sword, next) | |||
| before = b_block in dchain and sword in dchain[b_block] | |||
| after = a_block in dchain and next_next in dchain[a_block] | |||
| is_first = i == 0 | |||
| is_last = i + 1 == len(all_words) | |||
| res = _highlight_word(word, before, after, is_first, is_last) | |||
| processed_words.append(res) | |||
| prev_prev = prev | |||
| prev = sword | |||
| processed.append(u" ".join(processed_words)) | |||
| for paragraph in chain.text.split("\n"): | |||
| words = [] | |||
| for i, word in enumerate(paragraph.split(), i): | |||
| before = highlights[i - 1] | |||
| after = highlights[i + 1] | |||
| first = i == degree | |||
| last = i - degree + 1 == numwords | |||
| words.append(_highlight_word(word, before, after, first, last)) | |||
| processed.append(u" ".join(words)) | |||
| i += 1 | |||
| return u"<p>" + u"</p>\n<p>".join(processed) + u"</p>" | |||
| def _highlight_word(word, before, after, is_first, is_last): | |||
| def _highlight_word(word, before, after, first, last): | |||
| if before and after: | |||
| # Word is in the middle of a highlighted block, so don't change | |||
| # anything unless this is the first word (force block to start) or the | |||
| # last word (force block to end): | |||
| res = unicode(escape(word)) | |||
| if is_first: | |||
| if first: | |||
| res = u'<span class="cv-hl">' + res | |||
| if is_last: | |||
| if last: | |||
| res += u'</span>' | |||
| elif before: | |||
| # Word is the last in a highlighted block, so fade it out and then end | |||
| # the block; force open a block before the word if this is the first | |||
| # word: | |||
| res = _fade_word(word, u"out") + u"</span>" | |||
| if is_first: | |||
| if first: | |||
| res = u'<span class="cv-hl">' + res | |||
| elif after: | |||
| # Word is the first in a highlighted block, so start the block and then | |||
| # fade it in; force close the block after the word if this is the last | |||
| # word: | |||
| res = u'<span class="cv-hl">' + _fade_word(word, u"in") | |||
| if is_last: | |||
| if last: | |||
| res += u"</span>" | |||
| else: | |||
| # Word is completely outside of a highlighted block, so do nothing: | |||
| @@ -84,5 +77,7 @@ def _fade_word(word, dir): | |||
| base = u'<span class="cv-hl-in">{0}</span>{1}' | |||
| return base.format(before, after) | |||
| def _strip_word(word): | |||
| def _strip_word(chain, word): | |||
| if word == chain.START or word == chain.END: | |||
| return word | |||
| return sub("[^\w\s-]", "", word.lower(), flags=UNICODE) | |||