diff --git a/pagefind/features/ui/ui_base.feature b/pagefind/features/ui/ui_base.feature
new file mode 100644
index 00000000..88ba40d3
--- /dev/null
+++ b/pagefind/features/ui/ui_base.feature
@@ -0,0 +1,26 @@
+Feature: Base UI Tests
+ Background:
+ Given I have the environment variables:
+ | PAGEFIND_SOURCE | public |
+ Given I have a "public/index.html" file with the body:
+ """
+
+
+
+
+ """
+
+ Scenario: Pagefind UI loads
+ Given I have a "public/cat/index.html" file with the body:
+ """
+ world
+ """
+ When I run my program
+ Then I should see "Running Pagefind" in stdout
+ Then I should see the file "public/_pagefind/pagefind.js"
+ When I serve the "public" directory
+ When I load "/"
+ Then There should be no logs
+ Then The selector ".pagefind-ui" should exist
diff --git a/pagefind/tests/browser.rs b/pagefind/tests/browser.rs
index ff6b2127..95bb9d32 100644
--- a/pagefind/tests/browser.rs
+++ b/pagefind/tests/browser.rs
@@ -83,6 +83,35 @@ impl BrowserTester {
Ok(())
}
+ pub async fn selector_exists(
+ &mut self,
+ selector: &str,
+ ) -> Result<(), Box> {
+ let _ = self
+ .page
+ .as_mut()
+ .expect("No page launched")
+ .evaluate_function(format!(
+ "
+ async function() {{
+ const time = Date.now();
+ const timeout = 2000;
+ const selector = \"{}\";
+ while (!document.querySelector(selector) && (Date.now() - time) < timeout) {{
+ await new Promise(r => setTimeout(r, 50));
+ }}
+
+ if (!document.querySelector(selector)) {{
+ throw new Error(`${{selector}} did not appear within ${{timeout}}ms`);
+ }}
+ }}",
+ selector
+ ))
+ .await?;
+
+ Ok(())
+ }
+
pub async fn contents(&mut self, selector: &str) -> Result> {
let el = self
.page
diff --git a/pagefind/tests/steps/web_steps.rs b/pagefind/tests/steps/web_steps.rs
index 6ba6eb3c..bd2dad0a 100644
--- a/pagefind/tests/steps/web_steps.rs
+++ b/pagefind/tests/steps/web_steps.rs
@@ -48,6 +48,12 @@ async fn eval_js(world: &mut TestWorld, step: &Step) {
}
}
+#[then(regex = "^The selector (?:\"|')(.*)(?:\"|') should exist$")]
+async fn selector_exists(world: &mut TestWorld, selector: String) {
+ let browser = world.ensure_browser().await;
+ browser.selector_exists(&selector).await;
+}
+
#[then(regex = "^The selector (?:\"|')(.*)(?:\"|') should contain (?:\"|')(.*)(?:\"|')$")]
async fn selector_contains(world: &mut TestWorld, selector: String, contents: String) {
let browser = world.ensure_browser().await;
diff --git a/pagefind_ui/svelte/ui.svelte b/pagefind_ui/svelte/ui.svelte
index e578f9ef..0f9d002c 100644
--- a/pagefind_ui/svelte/ui.svelte
+++ b/pagefind_ui/svelte/ui.svelte
@@ -2,6 +2,7 @@
import Result from "./result.svelte";
export let base_path = "/_pagefind/";
+ export let pagefind_options = {};
let val = "";
let pagefind;
@@ -21,6 +22,7 @@
initializing = true;
if (!pagefind) {
pagefind = await import(`${base_path}pagefind.js`);
+ pagefind.options(pagefind_options || {});
}
};
diff --git a/pagefind_ui/ui.js b/pagefind_ui/ui.js
index 34a8564a..2e5a3c1d 100644
--- a/pagefind_ui/ui.js
+++ b/pagefind_ui/ui.js
@@ -1,18 +1,37 @@
-import PagefindUi from './svelte/ui.svelte';
+import Pagefind from './svelte/ui.svelte';
-(() => {
- let base_path = "/_pagefind/";
- try {
- base_path = new URL(document.currentScript.src).pathname.match(/^(.*\/)(?:pagefind-)?ui.js.*$/)[1];
- } catch (e) {
- console.warn("Pagefind couldn't determine the base of the bundle from the import path. Falling back to the default.");
- }
+class PagefindUi {
+ constructor(opts) {
+ let selector = opts.element ?? "[data-pagefind-ui]";
+ let bundlePath = opts.bundlePath;
+
+ if (!bundlePath) {
+ try {
+ bundlePath = new URL(document.currentScript.src).pathname.match(/^(.*\/)(?:pagefind-)?ui.js.*$/)[1];
+ } catch (e) {
+ bundlePath = "/_pagefind/";
+ console.warn(`Pagefind couldn't determine the base of the bundle from the javascript import path. Falling back to the default of ${bundlePath}.`);
+ console.warn("You can configure this by passing a bundlePath option to PagefindUi");
+ }
+ }
- const dom = document.querySelector("[data-pagefind-ui]");
- new PagefindUi({
- target: dom,
- props: {
- base_path
+ // Remove the UI-specific config before passing it along to the Pagefind backend
+ delete opts["element"];
+ delete opts["bundlePath"];
+
+ const dom = document.querySelector(selector);
+ if (dom) {
+ new Pagefind({
+ target: dom,
+ props: {
+ base_path: bundlePath,
+ pagefind_options: opts,
+ }
+ })
+ } else {
+ console.error(`Pagefind UI couldn't find the selector ${selector}`);
}
- })
-})();
+ }
+}
+
+window.PagefindUi = PagefindUi;