From c036b250bac32155b465843135a2d7711238337c Mon Sep 17 00:00:00 2001 From: upstream Date: Wed, 23 Sep 2026 10:26:08 +0200 Subject: [PATCH] Upstream Pagefind/pagefind state of the touched files before e920ec18c5 --- docs/content/docs/config-options.md | 2 +- pagefind/src/fossick/parser.rs | 145 +++++------ pagefind/src/options.rs | 368 ++++++++++++++++++++++++++++ 3 files changed, 434 insertions(+), 81 deletions(-) create mode 100644 pagefind/src/options.rs diff --git a/docs/content/docs/config-options.md b/docs/content/docs/config-options.md index d6f063f..b3eedce 100644 --- a/docs/content/docs/config-options.md +++ b/docs/content/docs/config-options.md @@ -63,7 +63,7 @@ exclude_selectors: - "[id^='prefix-']" ``` -All children will also be excluded, so using a `#my_navigation *` selector is not required. In other words, the semantics are the same as the [data-pagefind-ignore="all"](/docs/indexing/#removing-individual-elements-from-the-index) attribute: matched elements are skipped for metadata and filters as well as for content. +All children will also be ignored, so using a `#my_navigation *` selector is not required — in other words, the semantics are the same as the [data-pagefind-ignore](/docs/indexing/#removing-individual-elements-from-the-index) attribute. Note that currently Pagefind only supports lists of options via configuration files. If using the `--exclude-selectors` CLI flag or the `PAGEFIND_EXCLUDE_SELECTORS` environment variable, only one selector may be supplied. The selector may be a comma-separated CSS selector though, so the above example can be passed as `--exclude-selectors "#my_navigation, blockquote > span, [id^='prefix-']"`. diff --git a/pagefind/src/fossick/parser.rs b/pagefind/src/fossick/parser.rs index 7793083..ac0136a 100644 --- a/pagefind/src/fossick/parser.rs +++ b/pagefind/src/fossick/parser.rs @@ -1,6 +1,6 @@ use lazy_static::lazy_static; use lol_html::html_content::Element; -use lol_html::{element, text, HtmlRewriter, Settings}; +use lol_html::{element, text, HtmlRewriter, Selector, Settings}; use regex::Regex; use std::cell::RefCell; use std::collections::BTreeMap; @@ -63,9 +63,6 @@ struct DomParserData { has_html_element: bool, has_old_bundle_reference: bool, has_default_ui_reference: bool, - // Set when an --exclude-selectors match fires, and taken by the handler that - // builds the node for that same element. - exclude_element: bool, } #[derive(Clone, Copy, Debug, PartialEq)] @@ -137,28 +134,28 @@ impl<'a> DomParser<'a> { pub fn new(options: &'a SearchOptions) -> Self { let data = Rc::new(RefCell::new(DomParserData::default())); let root = format!("{}, {} *", options.root_selector, options.root_selector); - let scope_to_root = |selectors: &mut dyn Iterator| { - selectors - .map(|e| format!("{} {}", options.root_selector, e)) - .collect::>() - .join(", ") - }; - let user_exclusions = - scope_to_root(&mut options.exclude_selectors.iter().map(String::as_str)); - let auto_exclusions = scope_to_root(&mut REMOVE_SELECTORS.iter().copied()); + let mut custom_exclusions = options.exclude_selectors.clone(); + custom_exclusions.extend(REMOVE_SELECTORS.iter().map(|s| s.to_string())); + let custom_exclusions = custom_exclusions + .iter() + .filter_map(|e| { + let selector = format!("{} {}", options.root_selector, e); + match selector.parse::() { + Ok(_) => Some(selector), + Err(error) => { + options.logger.warn(format!( + "Ignoring the exclude selector {e:?}, which Pagefind can't parse: {error}. Indexing will continue without it." + )); + None + } + } + }) + .collect::>() + .join(", "); let mut anchor_counter = 0; - // Registered ahead of the handler below so that the element's own status - // is known before any of its metadata is read. - let user_exclusion_handler = (!user_exclusions.is_empty()).then(|| { - enclose! { (data) element!(user_exclusions, move |_el| { - data.borrow_mut().exclude_element = true; - Ok(()) - })} - }); - let rewriter = HtmlRewriter::new( - user_exclusion_handler.into_iter().chain(vec![ + vec![ enclose! { (data) element!("html", move |el| { let mut data = data.borrow_mut(); data.has_html_element = true; @@ -168,7 +165,6 @@ impl<'a> DomParser<'a> { Ok(()) })}, enclose! { (data) element!(root, move |el| { - let excluded_by_selector = std::mem::take(&mut data.borrow_mut().exclude_element); let explicit_ignore_flag = el.get_attribute("data-pagefind-ignore").map(|attr| { match attr.to_ascii_lowercase().as_str() { "" | "index" | "true" => NodeStatus::Ignored, @@ -190,9 +186,7 @@ impl<'a> DomParser<'a> { let index_attrs: Option> = el.get_attribute("data-pagefind-index-attrs").map(|attr| attr.split(',').map(|a| a.trim().to_string()).collect()); let tag_name = el.tag_name(); - let status = if excluded_by_selector { - NodeStatus::Excluded - } else if treat_as_body { + let status = if treat_as_body { NodeStatus::Body } else if let Some(explicit_ignore_flag) = explicit_ignore_flag { explicit_ignore_flag @@ -512,9 +506,8 @@ impl<'a> DomParser<'a> { } Ok(()) })}, - // Elements we always skip stay "ignored" rather than "excluded", - // so that metadata tagged inside a or a