diff --git a/docs/content/docs/_index.md b/docs/content/docs/_index.md index 027c0c46..274c81fc 100644 --- a/docs/content/docs/_index.md +++ b/docs/content/docs/_index.md @@ -53,19 +53,6 @@ We can see that a bunch of content was indexed, and Pagefind will be running a p Loading this in your browser, you should see a search input on your page. Try searching for some content and you will see results appear from your site. -## Highlighting - -To highlight the search terms on results page, add the following snippet on every page that has been indexed - -```html - - - ``` -To see the options available to PagefindHighlight, see [Highlight Config](/docs/highlight-config). +Ensure that the `highlightParam` configured here matches the `highlightParam` given to Pagefind when searching. + +To see all options available to PagefindHighlight, see [Highlight Config](/docs/highlight-config). diff --git a/docs/content/docs/search-config.md b/docs/content/docs/search-config.md index b1697222..7fb114e9 100644 --- a/docs/content/docs/search-config.md +++ b/docs/content/docs/search-config.md @@ -67,6 +67,18 @@ Overrides the bundle directory. In most cases this should be automatically detec Set the maximum length for generated excerpts. Defaults to `30`. +### Highlight query parameter + +```json +{ + "highlightParam": "highlight" +} +``` + +If set, Pagefind will add the search term as a query parameter under the same name. + +If using the [Pagefind highlight script](/docs/highlighting/), make sure this is configured to match. + ### Index weight See [multisite search > weighting](/docs/multisite/#changing-the-weighting-of-individual-indexes) diff --git a/docs/content/docs/ui.md b/docs/content/docs/ui.md index 2ef280b7..a578e9fe 100644 --- a/docs/content/docs/ui.md +++ b/docs/content/docs/ui.md @@ -152,19 +152,6 @@ new PagefindUI({ The number of milliseconds to wait after a user stops typing before performing a search. Defaults to `300`. If you wish to disable this, set to `0`. -### Highlight query param name - -{{< diffcode >}} -```javascript -new PagefindUI({ - element: "#search", -+ highlightQueryParamName: 'highlight' -}); -``` -{{< /diffcode >}} - -If the parameter is changed here, it *must* be changed in the [`PagefindHighlight` object](/docs/highlight-config/#pagefindQueryParamName) as well. - ### Translations {{< diffcode >}} diff --git a/pagefind/features/highlighting/highlighting_base.feature b/pagefind/features/highlighting/highlighting_results.feature similarity index 98% rename from pagefind/features/highlighting/highlighting_base.feature rename to pagefind/features/highlighting/highlighting_results.feature index 4ec035ed..fdd63ffb 100644 --- a/pagefind/features/highlighting/highlighting_base.feature +++ b/pagefind/features/highlighting/highlighting_results.feature @@ -1,4 +1,4 @@ -Feature: Highlighting Tests +Feature: Highlighting Result Tests Background: Given I have the environment variables: @@ -56,7 +56,7 @@ Feature: Highlighting Tests - """ + """ Given I have a "public/cat/index.html" file with the body: """

hello world

@@ -53,18 +53,18 @@ Feature: Base UI Tests } """ Then There should be no logs - Then The selector ".pagefind-ui__result-link[href$='?pagefind-highlight=hello&pagefind-highlight=world%21']" should contain "hello world" + Then The selector ".pagefind-ui__result-link[href$='?pagefind-highlight=hello&pagefind-highlight=world']" should contain "hello world" - Scenario: Pagefind UI does not add highlight query params + Scenario: Pagefind UI does not add highlight query params by default Given I have a "public/index.html" file with the body: - """ + """ - """ + """ Given I have a "public/cat/index.html" file with the body: """

hello world

@@ -96,14 +96,14 @@ Feature: Base UI Tests Scenario: Pagefind UI uses custom highlight query param name Given I have a "public/index.html" file with the body: - """ + """ - """ + """ Given I have a "public/cat/index.html" file with the body: """

hello world

@@ -132,12 +132,3 @@ Feature: Base UI Tests """ Then There should be no logs Then The selector ".pagefind-ui__result-link[href$='?custom-param=hello&custom-param=world']" should contain "hello world" - When I evaluate: - """ - async function() { - window.pui.triggerSearch("hello world!"); - await new Promise(r => setTimeout(r, 1500)); // TODO: await el in humane - } - """ - Then There should be no logs - Then The selector ".pagefind-ui__result-link[href$='?custom-param=hello&custom-param=world%21']" should contain "hello world" diff --git a/pagefind/features/ui/ui_hooks.feature b/pagefind/features/ui/ui_hooks.feature index 3c645c4a..2dd637b9 100644 --- a/pagefind/features/ui/ui_hooks.feature +++ b/pagefind/features/ui/ui_hooks.feature @@ -13,8 +13,7 @@ Feature: UI Hooks """ diff --git a/pagefind_ui/default/svelte/ui.svelte b/pagefind_ui/default/svelte/ui.svelte index c74cdb5e..1522b7fa 100644 --- a/pagefind_ui/default/svelte/ui.svelte +++ b/pagefind_ui/default/svelte/ui.svelte @@ -34,9 +34,6 @@ export let merge_index = []; export let trigger_search_term = ""; export let translations = {}; - // this is the name of the query param which is used to highlight the search terms after the user has navigated to a result page - // consider exposing the prop in the constructor in camelCase if needed - export let highlight_query_param_name = "pagefind-highlight"; let val = ""; $: if (trigger_search_term) { @@ -44,16 +41,6 @@ trigger_search_term = ""; } - // this could be changed to not split if the value is quoted - // ex: val = `hello world "foo bar"` highlightWords = ["hello", "world", "foo bar"] - - $: highlightWords = val.split(" "); - - $: highlight_query_param = new URLSearchParams( - highlightWords.map((word) => { - return [highlight_query_param_name, word]; - }) - ).toString(); let pagefind; let input_el, clear_el, @@ -318,23 +305,9 @@
    {#each searchResult.results.slice(0, show) as result (result.id)} {#if show_sub_results} - + {:else} - + {/if} {/each}
diff --git a/pagefind_ui/default/ui-core.js b/pagefind_ui/default/ui-core.js index cd2fcdea..07e6a2b2 100644 --- a/pagefind_ui/default/ui-core.js +++ b/pagefind_ui/default/ui-core.js @@ -26,11 +26,6 @@ export class PagefindUI { let debounceTimeoutMs = opts.debounceTimeoutMs ?? 300; let mergeIndex = opts.mergeIndex ?? []; let translations = opts.translations ?? []; - // setting the param to null should disable highlighting, hence this more complicated check - let highlightQueryParamName = "pagefind-highlight"; - if (opts.highlightQueryParamName !== undefined) { - highlightQueryParamName = opts.highlightQueryParamName; - } // Remove the UI-specific config before passing it along to the Pagefind backend delete opts["element"]; @@ -67,7 +62,6 @@ export class PagefindUI { debounce_timeout_ms: debounceTimeoutMs, merge_index: mergeIndex, translations, - highlight_query_param_name: highlightQueryParamName, pagefind_options: opts, }, }); diff --git a/pagefind_web_js/lib/coupled_search.ts b/pagefind_web_js/lib/coupled_search.ts index 0e9567f5..d340971b 100644 --- a/pagefind_web_js/lib/coupled_search.ts +++ b/pagefind_web_js/lib/coupled_search.ts @@ -22,6 +22,7 @@ class PagefindInstance { indexWeight: number; excerptLength: number; mergeFilter: Object; + highlightParam: string | null; loaded_chunks: Record>; loaded_filters: Record>; @@ -60,6 +61,7 @@ class PagefindInstance { this.indexWeight = opts.indexWeight ?? 1; this.excerptLength = opts.excerptLength ?? 30; this.mergeFilter = opts.mergeFilter ?? {}; + this.highlightParam = opts.highlightParam ?? null; this.loaded_chunks = {}; this.loaded_filters = {}; @@ -88,7 +90,7 @@ class PagefindInstance { } async options(options: PagefindIndexOptions) { - const opts = ["basePath", "baseUrl", "indexWeight", "excerptLength", "mergeFilter"]; + const opts = ["basePath", "baseUrl", "indexWeight", "excerptLength", "mergeFilter", "highlightParam"]; for (const [k, v] of Object.entries(options)) { if (k === "mergeFilter") { let filters = this.stringifyFilters(v); @@ -100,6 +102,7 @@ class PagefindInstance { if (k === "indexWeight" && typeof v === "number") this.indexWeight = v; if (k === "excerptLength" && typeof v === "number") this.excerptLength = v; if (k === "mergeFilter" && typeof v === "object") this.mergeFilter = v; + if (k === "highlightParam" && typeof v === "string") this.highlightParam = v; } else { console.warn(`Unknown Pagefind option ${k}. Allowed options: [${opts.join(', ')}]`); } @@ -245,7 +248,7 @@ class PagefindInstance { return JSON.parse(new TextDecoder().decode(fragment)); } - async loadFragment(hash: string, weighted_locations: PagefindWordLocation[] = []) { + async loadFragment(hash: string, weighted_locations: PagefindWordLocation[] = [], search_term: string) { if (!this.loaded_fragments[hash]) { this.loaded_fragments[hash] = this._loadFragment(hash); } @@ -262,8 +265,8 @@ class PagefindInstance { } if (!fragment.raw_url) { fragment.raw_url = fragment.url; - fragment.url = this.fullUrl(fragment.raw_url); } + fragment.url = this.processedUrl(fragment.raw_url, search_term); const excerpt_start = calculate_excerpt_region(weighted_locations, this.excerptLength); fragment.excerpt = build_excerpt(fragment.raw_content, excerpt_start, this.excerptLength, fragment.locations); @@ -281,6 +284,32 @@ class PagefindInstance { return `${this.baseUrl}/${raw}`.replace(/\/+/g, "/").replace(/^(https?:\/)/, "$1/"); } + processedUrl(url: string, search_term: string) { + const normalized = this.fullUrl(url); + if (this.highlightParam === null) { + return normalized; + } + let individual_terms = search_term.split(/\s+/); + try { + // This will error is it is not a FQDN + let processed = new URL(normalized); + for (const term of individual_terms) { + processed.searchParams.append(this.highlightParam, term); + } + return processed.toString(); + } catch(e) { + try { + let processed = new URL(`https://example.com${normalized}`); + for (const term of individual_terms) { + processed.searchParams.append(this.highlightParam, term); + } + return processed.toString().replace(/^https:\/\/example\.com/, ""); + } catch (e) { + return normalized; + } + } + } + async getPtr() { while (this.raw_ptr === null) { await asyncSleep(50); @@ -438,7 +467,7 @@ class PagefindInstance { id: hash, score: parseFloat(score) * this.indexWeight, words: locations, - data: async () => await this.loadFragment(hash, weighted_locations) + data: async () => await this.loadFragment(hash, weighted_locations, term) } }); diff --git a/pagefind_web_js/lib/highlight.ts b/pagefind_web_js/lib/highlight.ts index 7feeabd5..aa0ff12a 100644 --- a/pagefind_web_js/lib/highlight.ts +++ b/pagefind_web_js/lib/highlight.ts @@ -12,13 +12,13 @@ import Mark from "mark.js"; type pagefindHighlightOptions = { markContext?: string | HTMLElement | HTMLElement[] | NodeList | null; - pagefindQueryParamName?: string; + highlightParam?: string; markOptions?: Omit; addStyles?: boolean; }; export default class PagefindHighlight { - pagefindQueryParamName: string; + highlightParam: string; markContext: string | HTMLElement | HTMLElement[] | NodeList | null; markOptions: Mark.MarkOptions; addStyles: boolean; @@ -26,7 +26,7 @@ export default class PagefindHighlight { constructor( options: pagefindHighlightOptions = { markContext: null, - pagefindQueryParamName: "pagefind-highlight", + highlightParam: "pagefind-highlight", markOptions: { className: "pagefind-highlight", exclude: ["[data-pagefind-ignore]", "[data-pagefind-ignore] *"], @@ -34,11 +34,11 @@ export default class PagefindHighlight { addStyles: true, } ) { - const { pagefindQueryParamName, markContext, markOptions, addStyles } = + const { highlightParam, markContext, markOptions, addStyles } = options; - this.pagefindQueryParamName = - pagefindQueryParamName ?? "pagefind-highlight"; + this.highlightParam = + highlightParam ?? "pagefind-highlight"; this.addStyles = addStyles ?? true; this.markContext = markContext !== undefined ? markContext : null; this.markOptions = @@ -92,7 +92,7 @@ export default class PagefindHighlight { } highlight() { - const params = this.getHighlightParams(this.pagefindQueryParamName); + const params = this.getHighlightParams(this.highlightParam); if (!params || params.length === 0) return; this.addStyles && this.addHighlightStyles(this.markOptions.className as string); diff --git a/pagefind_web_js/types/index.d.ts b/pagefind_web_js/types/index.d.ts index 761d94e8..aad34393 100644 --- a/pagefind_web_js/types/index.d.ts +++ b/pagefind_web_js/types/index.d.ts @@ -21,6 +21,10 @@ declare global { * Only applies in multisite setups. */ mergeFilter?: Object, + /** + * If set, will ass the search term as a query parameter under this key, for use with Pagefind's highlighting script. + */ + highlightParam?: string, language?: string, /** * Whether an instance of Pagefind is the primary index or not (for multisite).