use crate::{AnalysisResult, Analyzer};
use uqa_core::memory::{Budgeted, MemoryBudget};
#[derive(Debug, Clone)]
pub struct HighlightOptions {
pub start_tag: String,
pub end_tag: String,
pub max_fragments: usize,
pub fragment_size: usize,
}
impl Default for HighlightOptions {
fn default() -> Self {
Self {
start_tag: "<b>".into(),
end_tag: "</b>".into(),
max_fragments: 0,
fragment_size: 150,
}
}
}
mod render;
mod rich;
mod terms;
mod words;
pub use rich::{highlight_compiled, highlight_compiled_budgeted};
pub use words::highlight_words_budgeted;
pub fn highlight(
text: &str,
query_terms: &[String],
analyzer: Option<&Analyzer>,
opts: &HighlightOptions,
) -> AnalysisResult<String> {
Ok(highlight_budgeted(
text,
query_terms,
analyzer,
opts,
&MemoryBudget::new(usize::MAX),
|| Ok(()),
)?
.into_parts()
.0)
}
pub fn highlight_budgeted(
text: &str,
query_terms: &[String],
analyzer: Option<&Analyzer>,
opts: &HighlightOptions,
budget: &MemoryBudget,
mut poll: impl FnMut() -> AnalysisResult<()>,
) -> AnalysisResult<Budgeted<String>> {
poll()?;
if text.is_empty() || query_terms.is_empty() {
return crate::allocation::copy_text(text, budget, &mut poll);
}
if let Some(analyzer) = analyzer {
let compiled = analyzer.compile()?;
highlight_compiled_budgeted(text, query_terms, &compiled, opts, budget, poll)
} else {
highlight_words_budgeted(
text,
query_terms.iter().map(String::as_str),
None,
opts,
budget,
poll,
)
}
}
pub fn highlight_words(
text: &str,
query_terms: &[String],
analyzer: Option<&Analyzer>,
opts: &HighlightOptions,
) -> AnalysisResult<String> {
Ok(highlight_words_budgeted(
text,
query_terms.iter().map(String::as_str),
analyzer,
opts,
&MemoryBudget::new(usize::MAX),
|| Ok(()),
)?
.into_parts()
.0)
}
#[cfg(test)]
mod tests;