You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
50 lines
1.5 KiB
50 lines
1.5 KiB
#include "highlighter.h"
|
|
#include <algorithm>
|
|
#include <regex>
|
|
|
|
std::string Highlighter::highlight_text(
|
|
const std::string& text,
|
|
const std::vector<std::string>& keywords,
|
|
const std::string& pre_tag,
|
|
const std::string& post_tag
|
|
) {
|
|
auto spans = find_keyword_positions(text, keywords);
|
|
std::string result = text;
|
|
|
|
// 从后向前插入标签,避免位置偏移
|
|
std::sort(spans.begin(), spans.end(),
|
|
[](const HighlightSpan& a, const HighlightSpan& b) {
|
|
return a.start > b.start;
|
|
});
|
|
|
|
for (const auto& span : spans) {
|
|
result.insert(span.start + span.length, post_tag);
|
|
result.insert(span.start, pre_tag);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
std::vector<Highlighter::HighlightSpan> Highlighter::find_keyword_positions(
|
|
const std::string& text,
|
|
const std::vector<std::string>& keywords
|
|
) {
|
|
std::vector<HighlightSpan> spans;
|
|
|
|
for (const auto& keyword : keywords) {
|
|
std::regex word_regex(keyword, std::regex::icase);
|
|
auto words_begin = std::sregex_iterator(
|
|
text.begin(), text.end(), word_regex
|
|
);
|
|
auto words_end = std::sregex_iterator();
|
|
|
|
for (auto i = words_begin; i != words_end; ++i) {
|
|
spans.push_back({
|
|
static_cast<size_t>(i->position()),
|
|
static_cast<size_t>(i->length())
|
|
});
|
|
}
|
|
}
|
|
|
|
return spans;
|
|
}
|