static void test_Highlight_Excerpt(TestBatchRunner *runner, Searcher *searcher, Obj *query) { String *content = (String*)SSTR_WRAP_UTF8("content", 7); Highlighter *highlighter = Highlighter_new(searcher, query, content, 3); String *highlighted; Vector *spans = Vec_new(1); Vec_Push(spans, (Obj*)Span_new(2, 1, 0.0f)); String *raw_excerpt = (String *)SSTR_WRAP_UTF8("a b c", 5); highlighted = Highlighter_Highlight_Excerpt(highlighter, spans, raw_excerpt, 0); TEST_TRUE(runner, Str_Equals_Utf8(highlighted, "a <strong>b</strong> c", 22), "basic Highlight_Excerpt"); DECREF(highlighted); DECREF(spans); spans = Vec_new(2); Vec_Push(spans, (Obj*)Span_new(0, 1, 1.0f)); Vec_Push(spans, (Obj*)Span_new(10, 10, 1.0f)); raw_excerpt = (String *)SSTR_WRAP_UTF8(PHI, 2); highlighted = Highlighter_Highlight_Excerpt(highlighter, spans, raw_excerpt, 0); TEST_TRUE(runner, Str_Equals_Utf8(highlighted, "<strong>Φ</strong>", 23), "don't surround spans off end of raw excerpt."); DECREF(highlighted); DECREF(spans); spans = Vec_new(1); Vec_Push(spans, (Obj*)Span_new(3, 1, 1.0f)); raw_excerpt = (String *)SSTR_WRAP_UTF8(PHI " " PHI " " PHI, 8); highlighted = Highlighter_Highlight_Excerpt(highlighter, spans, raw_excerpt, 1); TEST_TRUE(runner, Str_Equals_Utf8(highlighted, "Φ <strong>Φ</strong> Φ", 37), "Highlight_Excerpt pays attention to offset"); DECREF(highlighted); DECREF(spans); spans = Vec_new(4); Vec_Push(spans, (Obj*)Span_new(2, 10, 1.0f)); Vec_Push(spans, (Obj*)Span_new(2, 4, 1.0f)); Vec_Push(spans, (Obj*)Span_new(8, 9, 1.0f)); Vec_Push(spans, (Obj*)Span_new(8, 4, 1.0f)); raw_excerpt = (String *)SSTR_WRAP_UTF8(PHI " Oook. Urk. Ick. " PHI, 21); highlighted = Highlighter_Highlight_Excerpt(highlighter, spans, raw_excerpt, 0); TEST_TRUE(runner, Str_Equals_Utf8(highlighted, "Φ <strong>Oook. Urk. Ick.</strong> Φ", 46), "Highlight_Excerpt works with overlapping spans"); DECREF(highlighted); DECREF(spans); DECREF(highlighter); }
String* Highlighter_Create_Excerpt_IMP(Highlighter *self, HitDoc *hit_doc) { HighlighterIVARS *const ivars = Highlighter_IVARS(self); String *field_val = (String*)HitDoc_Extract(hit_doc, ivars->field); String *retval; if (!field_val || !Obj_Is_A((Obj*)field_val, STRING)) { retval = NULL; } else if (!Str_Get_Size(field_val)) { // Empty string yields empty string. retval = Str_new_from_trusted_utf8("", 0); } else { DocVector *doc_vec = Searcher_Fetch_Doc_Vec(ivars->searcher, HitDoc_Get_Doc_ID(hit_doc)); VArray *maybe_spans = Compiler_Highlight_Spans(ivars->compiler, ivars->searcher, doc_vec, ivars->field); VArray *score_spans = maybe_spans ? maybe_spans : VA_new(0); VA_Sort(score_spans, NULL, NULL); HeatMap *heat_map = HeatMap_new(score_spans, (ivars->excerpt_length * 2) / 3); int32_t top; String *raw_excerpt = Highlighter_Raw_Excerpt(self, field_val, &top, heat_map); String *highlighted = Highlighter_Highlight_Excerpt(self, score_spans, raw_excerpt, top); DECREF(raw_excerpt); DECREF(heat_map); DECREF(score_spans); DECREF(doc_vec); retval = highlighted; } DECREF(field_val); return retval; }