# JavaScript API

URL: https://caijiao.org/pagefind/tutorial-05-search-api
Source: docs/pagefind/tutorial-05-search-api.md
Description: 讲解如何通过 /_pagefind/pagefind.js 动态导入搜索 API，执行查询、按需加载结果、渲染标题、摘要和 URL。

Pagefind 的搜索能力可以直接通过浏览器 JavaScript 调用。这样可以保留自己的搜索弹窗、输入框、结果列表和交互逻辑。

## 动态导入

Pagefind 生成索引后，会在输出目录中提供搜索入口脚本。本项目把搜索资产输出到 `/_pagefind/`：

```js
const pagefind = await import("/_pagefind/pagefind.js");
```

可以手动初始化，也可以等第一次搜索时自动初始化：

```js
await pagefind.init();
```

## 执行搜索

```js
const pagefind = await import("/_pagefind/pagefind.js");
const search = await pagefind.search("静态搜索");
```

搜索结果对象里的 `results` 默认只包含轻量信息。真正的标题、URL、摘要和元数据需要按需加载：

```js
const rows = await Promise.all(
  search.results.slice(0, 8).map((result) => result.data())
);
```

结果数据通常包含：

| 字段 | 说明 |
| --- | --- |
| `url` | 结果页面 URL |
| `excerpt` | 带高亮标记的摘要 |
| `plain_excerpt` | 不带高亮 HTML 的纯文本摘要 |
| `meta.title` | 页面标题 |
| `meta.image` | 页面图片元数据 |
| `sub_results` | 页面内更具体的命中片段 |

## 一个最小搜索框

```html
<input id="search" type="search" placeholder="搜索文档">
<div id="results"></div>

<script type="module">
  const input = document.querySelector("#search");
  const results = document.querySelector("#results");
  let pagefindPromise;

  function loadPagefind() {
    pagefindPromise ||= import("/_pagefind/pagefind.js");
    return pagefindPromise;
  }

  input.addEventListener("input", async () => {
    const query = input.value.trim();
    if (!query) {
      results.innerHTML = "";
      return;
    }

    const pagefind = await loadPagefind();
    const search = await pagefind.search(query);
    const rows = await Promise.all(search.results.slice(0, 5).map((item) => item.data()));

    results.innerHTML = rows
      .map((row) => `<a href="${row.url}"><strong>${row.meta.title}</strong><p>${row.excerpt}</p></a>`)
      .join("");
  });
</script>
```

`excerpt` 已经适合放入结果摘要，但其他原始字段如果来自不可信内容，仍应在模板层做转义。

## 输入防抖

搜索框通常会随着用户输入不断触发查询。可以自己写防抖，也可以使用 `pagefind.debouncedSearch()`。如果用户很快输入了新内容，较旧的防抖搜索可能返回 `null`，渲染前需要判断。
