# https://github.com/NeXTs/Jets.js 项目说明书

生成时间：2026-06-27 19:18:28 UTC

## 目录

- [Overview & Getting Started](#page-overview)
- [Configuration & API Reference](#page-config)
- [Advanced Usage & Community Patterns](#page-advanced)
- [Architecture & Internals](#page-architecture)

<a id='page-overview'></a>

## Overview & Getting Started

### 相关页面

相关主题：[Configuration & API Reference](#page-config)

```markdown
<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/NeXTs/Jets.js/blob/main/README.md)
- [package.json](https://github.com/NeXTs/Jets.js/blob/main/package.json)
- [bower.json](https://github.com/NeXTs/Jets.js/blob/main/bower.json)
- [jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)
- [jets.min.js](https://github.com/NeXTs/Jets.js/blob/main/jets.min.js)
</details>

# Overview & Getting Started

## 项目定位与核心思想

Jets.js 是由 Denis Lukov 维护、采用 MIT 协议发布的"原生 CSS 搜索引擎"前端库，仓库自我定位为 *Native CSS search engine*（[README.md](https://github.com/NeXTs/Jets.js/blob/main/README.md)）。当前发布版本为 `0.15.0`（2022-12-11），主入口指向 `jets.js`（[package.json:2-4](https://github.com/NeXTs/Jets.js/blob/main/package.json)）；通过 Bower 安装时则使用压缩包 `jets.min.js`（[bower.json:2-4](https://github.com/NeXTs/Jets.js/blob/main/bower.json)）。

它的核心思路是把"匹配/过滤"完全交给浏览器原生 CSS 选择器完成：库在初始化时为每个列表项写入一个 `data-jets` 属性（内容为该节点文本经归一化处理后的字符串），随后向 `<head>` 注入一个 `<style>` 标签，根据用户输入动态生成 `:not([data-jets~="..."])` 形式的 CSS 规则，从而实现即时过滤（[jets.js:121-138](https://github.com/NeXTs/Jets.js/blob/main/jets.js)）。由于比对过程发生在浏览器内部，即使上千条记录也能保持顺滑；正式环境可直接引入压缩版 [jets.min.js](https://github.com/NeXTs/Jets.js/blob/main/jets.min.js)，无任何外部依赖。

```mermaid
flowchart LR
    A[searchTag 输入框] -->|input/keydown/change| B(Jets 实例)
    B -->|读取 value 并归一化| C{生成 CSS 规则}
    C --> D[styleTag.innerHTML 写入]
    D --> E[浏览器原生匹配 :not 选择器]
    E --> F[列表项显示/隐藏]
    B -.->|回调| G[didSearch]
```

## 安装、加载与最小示例

### 安装与加载方式

- **npm**：`npm install jets`，主入口为 `jets.js`（[package.json:3-4](https://github.com/NeXTs/Jets.js/blob/main/package.json)）。
- **Bower**：`bower install jets`，主入口为 `jets.min.js`（[bower.json:2-4](https://github.com/NeXTs/Jets.js/blob/main/bower.json)）。
- **直接 `<script>` 引入**：库通过 UMD 包装同时支持 CommonJS、AMD 与全局 `script` 三种加载方式（[jets.js:2-7](https://github.com/NeXTs/Jets.js/blob/main/jets.js)），全局模式下挂载 `window.Jets`。

### 最小可用示例

```html
<input id="search" type="search" />
<div id="content">
  <p>Apple</p>
  <p>Banana</p>
  <p>Cherry</p>
</div>
<script src="jets.min.js"></script>
<script>
  new Jets({
    searchTag: '#search',
    contentTag: '#content'
  });
</script>
```

构造函数 `new Jets(opts)` 中 `contentTag` 为必填；若未提供 `searchTag`，则必须开启 `callSearchManually: true` 并自行调用实例上的 `.search('关键词')`，否则会抛出错误（[jets.js:30-33](https://github.com/NeXTs/Jets.js/blob/main/jets.js)）。

## 配置选项速查

下列选项在构造函数中传入，未指定字段取默认值（[jets.js:11-15](https://github.com/NeXTs/Jets.js/blob/main/jets.js)）。

| 选项 | 默认值 | 说明 |
|---|---|---|
| `contentTag` | （必填） | 列表容器 CSS 选择器 |
| `searchTag` | （二选一） | 搜索输入框选择器；缺失时需开启 `callSearchManually` |
| `callSearchManually` | `false` | 关闭自动事件绑定，改用 `.search(phrase)` 手动触发 |
| `searchSelector` | `'*AND'` | 第 1 字符为匹配前缀（`*`、`~`、`^`、`$`），后续字母 `AND`/`OR` 决定多词匹配模式 |
| `hideBy` | `'display:none'` | 隐藏规则，多条用 `;` 分隔 |
| `addImportant` | `false` | 是否为隐藏规则追加 `!important` |
| `columns` | `[]` | 指定作为可搜索文本的子节点索引数组 |
| `manualContentHandling` | `null` | 自定义文本提取函数，返回字符串 |
| `searchInSpecificColumn` | `false` | 启用 `data-jets-col-N` 列索引 |
| `diacriticsMap` | `{}` | 注音字符替换映射 |
| `didSearch` | `null` | 每次搜索结束后的回调（接收当前查询字符串） |
| `invert` | `false` | 反转匹配语义，命中项被隐藏 |
| `nonceId` | `undefined` | 注入 `<style>` 时附带的 CSP nonce |

## 社区常见问题与解决思路

- **"无匹配"提示**：库本身不内置空状态文案。可在 `didSearch` 回调中检查当前是否还有可见项，配合 `display` 切换提示元素即可（[jets.js:36-42](https://github.com/NeXTs/Jets.js/blob/main/jets.js)）。参见 issue #39。
- **自定义属性名**：当前版本硬编码 `data-jets` 与 `data-jets-col-N`，未提供 `attrName` 配置（[jets.js:132](https://github.com/NeXTs/Jets.js/blob/main/jets.js)）。issue #18 中的社区方案可作参考，但需自行 fork 修改源码。
- **大小写敏感**：`_sanitize` 会强制将文本与查询都 `toLowerCase()`（[jets.js:78](https://github.com/NeXTs/Jets.js/blob/main/jets.js)），匹配天然不区分大小写——参见 issue #40。如需在同一节点上保留原始大小写供其他库使用，应避免共享 `data-*` 属性。
- **CSP 违规**：库会向 `<head>` 注入并修改 `<style>` 的 `innerHTML`，未启用 `unsafe-inline` 的 `style-src` 会拒绝；库已提供 `nonceId` 选项（[jets.js:69-71](https://github.com/NeXTs/Jets.js/blob/main/jets.js)），将其设为页面 nonce 值即可解决，参见 issue #44。
- **CI 状态**：Travis 配置可能已过期（issue #43），本地可运行 `npm test`（[package.json:6-7](https://github.com/NeXTs/Jets.js/blob/main/package.json)），由 `mocha-headless-chrome` 驱动 `test/index.html` 验证。

## See Also

- [Configuration Options 详解](#)
- [manualContentHandling 自定义文本提取](#)
- [CSP 与 nonceId 部署指南](#)

---

<a id='page-config'></a>

## Configuration & API Reference

### 相关页面

相关主题：[Overview & Getting Started](#page-overview), [Advanced Usage & Community Patterns](#page-advanced)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)
- [jets.min.js](https://github.com/NeXTs/Jets.js/blob/main/jets.min.js)
- [package.json](https://github.com/NeXTs/Jets.js/blob/main/package.json)
- [bower.json](https://github.com/NeXTs/Jets.js/blob/main/bower.json)
- [README.md](https://github.com/NeXTs/Jets.js/blob/main/README.md)
</details>

# Configuration & API Reference

## 概述

Jets.js 是一个"原生 CSS 搜索引擎"（Native CSS search engine），通过将搜索文本写入 DOM 节点的 `data-jets` 属性，再动态注入 `<style>` 块来隐藏不匹配的节点，从而实现纯前端的列表过滤功能 [资料来源：[package.json:1-4]()]。本页聚焦其构造函数选项与公开方法，便于开发者在项目中进行精确控制 [资料来源：[README.md:1-15]()]。

库以 UMD 形式发布，同时支持 CommonJS、AMD 和全局变量 `Jets` [资料来源：[bower.json:9-14]()]。当前稳定版本为 `0.15.0`（发布于 2022-12-11）[资料来源：[package.json:2-3]()]。

## 构造函数与必需选项

构造函数 `new Jets(opts)` 在未通过 `new` 调用时会自动包装实例 [资料来源：[jets.js:13-15]()]。以下两个选项为必需项：

- **`contentTag`**：被搜索内容的容器选择器，库会遍历其直接子节点。
- **`searchTag`**：搜索输入框选择器；若提供 `callSearchManually: true`，则可省略 [资料来源：[jets.js:24-29]()]。

若缺少 `contentTag`，构造函数抛出 `Error! Could not find contentTag element`；若缺少 `searchTag` 且未启用手动搜索，则抛出 `Error! Provide one of search methods` [资料来源：[jets.js:25-29]()]。

## 配置选项

下表汇总了 `Jets` 支持的全部配置项及其默认值，所有选项在构造函数内通过 `self.options[name] = opts[name] || defaults[name]` 进行合并 [资料来源：[jets.js:17-22]()]。

| 选项 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `searchSelector` | string | `*AND` | 首位字符为匹配运算符（`^`、`$`、`*`、`=`、`@`），其后可选 `AND`/`OR` 模式 [资料来源：[jets.js:22-26]()] |
| `hideBy` | string | `display:none` | 隐藏规则，可使用分号分隔多条规则 [资料来源：[jets.js:18-19]()] |
| `addImportant` | boolean | `false` | 是否在隐藏规则后追加 `!important` [资料来源：[jets.js:30-37]()] |
| `columns` | number[] | — | 指定参与匹配的列下标（从 0 开始）[资料来源：[jets.js:75-83]()] |
| `searchInSpecificColumn` | boolean | `false` | 启用后为每一列生成独立的 `data-jets-col-i` 属性 [资料来源：[jets.js:62-70]()] |
| `manualContentHandling` | function | — | 自定义提取每行文本的回调 [资料来源：[jets.js:75-83]()] |
| `callSearchManually` | boolean | `false` | 关闭输入框事件绑定，改由 `jets.search("phrase")` 手动触发 [资料来源：[jets.js:23-29]()] |
| `didSearch` | function | — | 每次搜索完成后的回调，参数为当前查询字符串 [资料来源：[jets.js:30-37]()] |
| `invert` | boolean | `false` | 反转匹配逻辑，仅隐藏命中的项 [资料来源：[jets.js:30-37]()] |
| `diacriticsMap` | object | `{}` | 注音字符映射表，用于在 `_sanitize` 时替换变音符号 [资料来源：[jets.js:86-94]()] |
| `nonceId` | string | — | CSP nonce 值，会写入注入的 `<style>` 标签以通过 `style-src` 校验 [资料来源：[jets.js:43-47]()] |

> 注：搜索文本在写入 `data-jets` 之前会通过 `_sanitize` 执行去注音、`trim()`、合并空白和小写化处理，因此匹配天然大小写不敏感 [资料来源：[jets.js:51-53]()]。这与社区议题 #40 中"希望大小写不敏感"的需求一致 [资料来源：[README.md:1-15]()]。

## 公开 API

### `Jets#search(query, optional_column)`

执行一次过滤并将结果写入注入的 `<style>` 块。若 `query` 与上一次相同则提前返回，避免无谓的样式更新 [资料来源：[jets.js:30-37]()]。当传入 `optional_column` 时仅作用于指定列，配合 `searchInSpecificColumn` 使用 [资料来源：[jets.js:38-43]()]。

### `Jets#update(force)`

为新增的 DOM 节点补充 `data-jets` 属性；传入 `force: true` 会重写已有节点 [资料来源：[jets.js:96-98]()]。适用于通过 AJAX 动态追加列表项的场景。

### `Jets#destroy()`

移除注入的 `<style>` 标签并解绑输入框事件，同时清除所有 `data-jets` 与 `data-jets-col-i` 属性 [资料来源：[jets.js:44-47]()]([jets.js:99-105]())。

### `Jets#replaceDiacritics(text)`

按 `options.diacriticsMap` 将变音字符替换为基础字母，可独立调用以复用工具方法 [资料来源：[jets.js:86-94]()]。

## 常见问题与社区反馈

### CSP 违规

社区议题 #44 报告 Jets.js 注入的 `<style>` 块违反 `style-src` 策略。从源码可见，库在 `_addStyleTag` 中创建 `<style>` 并写入 `innerHTML` [资料来源：[jets.js:43-47]()]。解决方式是通过 `nonceId` 选项传入 nonce 值，库会自动将其设置为 `<style>` 的 `nonce` 属性，从而通过严格的 CSP 校验 [资料来源：[jets.js:45-47]()]。

### 无匹配提示

议题 #39 希望在无结果时显示"Sorry, nothing found"。库本身不会自动渲染该提示，但提供了 `didSearch` 回调，每次过滤完成后都会以当前查询字符串为参数调用，开发者可在回调中统计 `styleTag.innerHTML` 是否非空并切换提示元素的可见性 [资料来源：[jets.js:30-37]()]。

### 自定义属性名

议题 #18 希望允许自定义属性名以避免与已有 `data-jets` 冲突。仓库目前默认使用 `data-jets` 作为匹配属性，可通过 `searchSelector` 选项中的首位字符切换运算符，但属性名本身不可配置；如需隔离，可结合自定义选择器在多个容器上分别实例化 `new Jets()` 以避免相互影响。

## See Also

- [项目主页与演示](https://jets.js.org/) — 官方介绍与交互示例
- [package.json](https://github.com/NeXTs/Jets.js/blob/main/package.json) — 版本与依赖信息
- [jets.js 源码](https://github.com/NeXTs/Jets.js/blob/main/jets.js) — 完整实现

---

<a id='page-advanced'></a>

## Advanced Usage & Community Patterns

### 相关页面

相关主题：[Configuration & API Reference](#page-config), [Architecture & Internals](#page-architecture)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)
- [README.md](https://github.com/NeXTs/Jets.js/blob/main/README.md)
- [package.json](https://github.com/NeXTs/Jets.js/blob/main/package.json)
- [bower.json](https://github.com/NeXTs/Jets.js/blob/main/bower.json)
- [jets.min.js](https://github.com/NeXTs/Jets.js/blob/main/jets.min.js)
</details>

# Advanced Usage & Community Patterns

本页聚焦 Jets.js 在真实项目中常见的高级用法与社区诉求，覆盖 CSP 合规、空匹配提示、自定义属性/列搜索、手动调用与动态内容更新等场景，并对照 issue #18、#39、#40、#44 给出的方案。Jets.js 是一个“原生 CSS 搜索引擎”，核心思路是把待搜索文本挂到 `data-jets` 属性上，再通过运行时注入 `<style>` 标签写 CSS 选择器来隐藏不匹配节点，因此许多“高级”用法本质上都是围绕这套机制展开的。资料来源：[jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)、[README.md](https://github.com/NeXTs/Jets.js/blob/main/README.md)。

## 构造函数与可配置选项

构造函数 `Jets(opts)` 接受一个配置对象，缺省值定义如下：资料来源：[jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)。

```js
var defaults = {
  searchSelector: '*AND',
  hideBy: 'display:none',
  diacriticsMap: {}
}
```

被显式读取的选项包括 `columns`、`addImportant`、`searchSelector`、`hideBy`、`manualContentHandling`、`callSearchManually`、`searchInSpecificColumn`、`diacriticsMap`、`didSearch`、`invert`、`nonceId`。`searchSelector` 字符串如果长度大于 1，会被拆分为首字符 + 模式后缀（如 `'*AND'`），由 `_applyCSS` 据此决定是 AND 还是 OR 匹配。资料来源：[jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)。

## CSP 合规：`nonceId` 选项

Issue #44 报告 Jets.js 会违反 CSP，因为库动态向 `<head>` 注入并修改 `<style>` 元素的 `innerHTML`。源代码已为此提供解决方案：在初始化时给动态创建的 `<style>` 标签设置 `nonce` 属性。资料来源：[jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)。

```js
_addStyleTag: function() {
  var options = this.options;
  this.styleTag = document.createElement('style');
  if(typeof options.nonceId != 'undefined') this.styleTag.setAttribute('nonce', options.nonceId);
  document.head.appendChild(this.styleTag);
}
```

使用方式：

```js
new Jets({
  contentTag: '#myList',
  searchTag: '#mySearch',
  nonceId: window.__CSP_NONCE__ // 与服务端渲染出的 nonce 一致
});
```

这样既不破坏 CSP 的 `style-src 'nonce-...'` 策略，又保留了 Jets.js 注入样式的核心能力。

## 空结果提示（“Nothing Found”）

Jets.js 自身并不会在“零匹配”时输出任何文本——它只生成 CSS 隐藏规则，因此 UI 上列表会变成空白，这正是 Issue #39 反馈的现象。社区常用的解决方法是结合 `didSearch` 回调与 `searchInSpecificColumn`/`columns`，在搜索结束后由应用层判断可见项数量。资料来源：[jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)。

```js
var jets = new Jets({
  contentTag: '#list',
  searchTag: '#q',
  didSearch: function(query) {
    var visible = Array.prototype.filter.call(
      document.querySelectorAll('#list > *'),
      function(el) { return getComputedStyle(el).display !== 'none'; }
    );
    document.getElementById('empty').hidden = visible.length > 0;
  }
});
```

> 提示：因为 `_applyCSS` 是通过 CSS 把不匹配项隐藏，而非删除 DOM 节点，所以“可见数量”必须用 `getComputedStyle`/`offsetParent` 等运行时手段判断，不能依赖 `children.length`。资料来源：[jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)。

## 自定义属性名与大小写敏感性

Issue #18 提到希望在同一个元素上同时支持多套独立的搜索（不同 `attrName`）；Issue #40 则希望搜索关键字本身大小写不敏感，但 DOM 文本保持原样。当前 0.15.0 版本（`package.json` 中声明）并未开放自定义 `attrName` 选项——`_setJets` 始终写入 `data-jets`，列模式使用 `data-jets-col-<i>`，全部硬编码在源码中。资料来源：[package.json](https://github.com/NeXTs/Jets.js/blob/main/package.json)、[jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)。

大小写不敏感的搜索其实已经“免费”实现：`_sanitize` 会在建立索引时统一转小写：

```js
_sanitize: function(text) {
  return this.replaceDiacritics(text).trim().replace(/\s+/g, ' ').toLowerCase()
}
```

而 `_applyCSS` 也会对查询串做同样处理：

```js
var search_phrase = this.replaceDiacritics(search_query.trim().toLowerCase()...)
```

因此 DOM 上的原始文本保持原样，CSS 选择器两端都是小写匹配，用户输入 `Apple` 也能命中索引中的 `apple`。资料来源：[jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)。

需要“自定义属性名”的场景，可结合 `manualContentHandling` 选项 + 自建搜索后端，或者临时改用 fork；不建议在大型数据集上为同一元素复制多份 `data-*`（Issue #40 中提到的性能顾虑）。

## 手动控制与动态内容

当输入控件位于 Shadow DOM、跨 iframe 或不希望绑定原生事件时，可启用 `callSearchManually`，库就不会自动监听 `input/keydown/change`，改由业务侧调用 `jets.search(phrase, optionalColumn)`。资料来源：[jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)。

```js
var jets = new Jets({
  contentTag: '#list',
  callSearchManually: true
});
externalInput.addEventListener('input', function(e) {
  jets.search(e.target.value);
});
```

而当列表在初始化之后又新增/修改了节点，应调用 `jets.update(force)` 让其重新读取并写入 `data-jets`：

```js
update: function(force) {
  this._setJets(':scope > :not([data-jets])', force);
}
```

`force=true` 时会重写所有已有节点的 `data-jets`，适合数据被远程替换的场景；默认只补齐尚未建立索引的新节点。资料来源：[jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)。

## 常见配置组合一览

| 场景 | 推荐选项 | 说明 |
| --- | --- | --- |
| 严格 CSP 环境 | `nonceId` | 解决 Issue #44 |
| 多关键词全匹配 | `searchSelector: '*AND'`（默认） | 仅当所有词都存在时显示 |
| 多关键词任一命中 | `searchSelector: '*OR'` | 拆分词组后并集匹配 |
| 行内有多个数据字段 | `columns: [0, 2]` + `searchInSpecificColumn: true` | 仅索引指定列 |
| 反向过滤（黑名单） | `invert: true` | 命中的元素被隐藏 |
| 内容由 JS 渲染 | `manualContentHandling: fn` | 自定义索引文本 |
| 无原生输入框 | `callSearchManually: true` | 手动调用 `.search()` |

资料来源：[jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)、[README.md](https://github.com/NeXTs/Jets.js/blob/main/README.md)。

## See Also

- 项目首页与用法：[README.md](https://github.com/NeXTs/Jets.js/blob/main/README.md)
- 核心源码：[jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)
- 构建产物：[jets.min.js](https://github.com/NeXTs/Jets.js/blob/main/jets.min.js)
- 版本与脚本：[package.json](https://github.com/NeXTs/Jets.js/blob/main/package.json)
- Bower 注册信息：[bower.json](https://github.com/NeXTs/Jets.js/blob/main/bower.json)

---

<a id='page-architecture'></a>

## Architecture & Internals

### 相关页面

相关主题：[Configuration & API Reference](#page-config)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [jets.js](https://github.com/NeXTs/Jets.js/blob/main/jets.js)
- [jets.min.js](https://github.com/NeXTs/Jets.js/blob/main/jets.min.js)
- [package.json](https://github.com/NeXTs/Jets.js/blob/main/package.json)
- [bower.json](https://github.com/NeXTs/Jets.js/blob/main/bower.json)
- [README.md](https://github.com/NeXTs/Jets.js/blob/main/README.md)
</details>

# Architecture & Internals

Jets.js 是一个"原生 CSS 搜索引擎"——它通过在 HTML 元素上注入 `data-jets` 索引属性，并在 `<head>` 中动态写入一个 `<style>` 块来隐藏不匹配项，从而避免任何运行时计算参与匹配过程。本页面向希望理解 Jets 内部机制、二次开发或排查故障的读者。

## 模块结构与分发

库以 UMD（Universal Module Definition）模式包裹，使同一份源码可在 CommonJS、AMD 与浏览器全局三种环境中加载。资料来源：[jets.js:1-7]() 实现了这层分发逻辑；若 `module` 存在则通过 `module.exports` 暴露；若 `define.amd` 可用则注册为 AMD 模块；否则挂载到 `root['Jets']`。

`package.json` 将入口声明为 `jets.js`（NPM 场景），`bower.json` 则将 `jets.min.js` 声明为 Bower 主入口。资料来源：[package.json:4]()、[bower.json:3]()。这意味着 NPM 用户获得的是可读源码，而 Bower 用户获得的是压缩后的运行时文件。仓库当前版本号为 `0.15.0`（2022-12-11 更新）。资料来源：[package.json:3]()。

## 初始化与配置合并

构造函数 `Jets(opts)` 既可作为普通函数调用，也可通过 `new` 实例化；若未使用 `new`，它会内部自调 `new Jets(opts)` 重新返回实例。资料来源：[jets.js:11-13]()。

内部默认值为：

| 选项 | 默认值 | 含义 |
|---|---|---|
| `searchSelector` | `*AND` | 选择子字符 + 多关键字模式 |
| `hideBy` | `display:none` | 隐藏元素的 CSS 规则集 |
| `diacriticsMap` | `{}` | 变音符替换映射 |

`searchSelector` 字段同时承担两个角色：第一个字符作为属性比较运算符（默认 `*`，表示子串包含），其后追加的大写字母作为多关键字组合模式（`AND` 表示交集，其他值则视作"任一命中"）。资料来源：[jets.js:15-30]()。

构造函数进一步要求提供 `contentTag`（被搜索的容器选择器）和 `searchTag`（输入框选择器）。若希望以编程方式触发搜索而非监听输入框，可设置 `callSearchManually: true`。资料来源：[jets.js:31-39]()。

## 索引建立与查询应用

Jets 的工作流可总结为两阶段：**索引（Indexing）**与**查询（Query）**。下图描绘了从初始化到写入隐藏样式的完整流程。

```mermaid
flowchart TD
  A[实例化 Jets opts] --> B[合并默认值 + 解析 searchSelector]
  B --> C[查询 contentTag 与 searchTag]
  C --> D[创建 style 标签并注入 head]
  D --> E[_setJets: 遍历内容元素]
  E --> F[_sanitize: 去变音符 + 压缩空白 + 转小写]
  F --> G[写入 data-jets 属性]
  G --> H{用户输入或手动调用 search}
  H --> I[_applyCSS: 拆分关键字为属性选择器]
  I --> J[写入 style.innerHTML 实现隐藏]
```

**索引阶段**由 `_setJets` 完成。它会跳过已经存在 `data-jets` 属性的元素（除非传入 `force`），并对每个元素提取文本。可通过 `manualContentHandling(tag)` 完全接管文本抽取，或通过 `columns` 数组指定按子元素下标拼接文本。资料来源：[jets.js:90-110]()。文本随后经过 `_sanitize` 标准化：去除变音符（依赖 `diacriticsMap`）、压缩多余空白、转小写，最终写入 `data-jets` 属性。资料来源：[jets.js:81-88]()。

**查询阶段**由 `_applyCSS` 完成。它接收查询字符串，先做同样的标准化处理；若启用了 `AND` 模式则按空格切分为多个独立关键字，每个关键字构造一个属性选择器，再拼接成一段 CSS 写入 `styleTag.innerHTML`。资料来源：[jets.js:60-78]()。`hideBy` 中的规则会附加到每个匹配项之后，可通过 `addImportant: true` 强制使用 `!important` 提升优先级。

## 事件、生命周期与扩展点

库监听 `input`、`keydown`、`change` 三种事件，其中 `keydown` 通过 `setTimeout(self.search, 0)` 延迟到下一帧，以避免与 IME 输入冲突。资料来源：[jets.js:42-44]()、[jets.js:51-56]()。

主要生命周期方法包括：

- `Jets#search(query, optional_column)`：手动触发一次过滤，传入 `optional_column` 可限定在某个 `data-jets-col-N` 列上匹配。资料来源：[jets.js:40-47]()。
- `Jets#update(force)`：在内容动态变化后重新建立索引，传入 `force` 会重建所有元素。资料来源：[jets.js:115-117]()。
- `Jets#destroy()`：移除事件监听、删除注入的 `<style>` 标签并清理 `data-jets` 属性。资料来源：[jets.js:48-50]()、[jets.js:118-122]()。
- `Jets#replaceDiacritics(text)`：公开的方法允许外部复用变音符替换逻辑。资料来源：[jets.js:111-114]()。

为兼容旧版浏览器，库还内嵌了一段 `:scope` 选择器 polyfill，会在 `querySelector(':scope body')` 抛错时通过临时 ID 重写选择器。资料来源：[jets.js:124-138]()。

## 与社区反馈的关联

由于 Jets 完全依赖 CSS 属性选择器与 `display:none` 隐藏非匹配项，要实现"未找到结果"提示（社区讨论 #39）就必须额外维护一个计数器或在 `didSearch` 回调中检查可见行数。资料来源：[jets.js:46-47]() 暴露的 `didSearch` 钩子是实现此功能的推荐位置。类似地，关于 #44 CSP 违规的问题，库通过 `_addStyleTag` 直接创建并写入 `<style>` 元素（资料来源：[jets.js:79-83]()），可通过 `nonceId` 选项为该标签附加 CSP 所需的 `nonce` 属性加以缓解。#40 提出的"保持原始大小写"问题与 `_sanitize` 强制小写相关（资料来源：[jets.js:86-88]()），如需保留原始大小写，可在 `manualContentHandling` 中返回未处理的文本，但需自行承担属性选择器大小写敏感性带来的成本。#18 关于自定义属性名（"attrName"）的功能请求，目前 Jets 固定使用 `data-jets`，但 `manualContentHandling` 与 `update`/`destroy` 的组合为自行维护备用索引属性提供了扩展空间。

---

### See Also

- 入门与基础用法请参见 [README.md](https://github.com/NeXTs/Jets.js/blob/main/README.md)
- 完整配置项默认值与脚本命令参见 [package.json](https://github.com/NeXTs/Jets.js/blob/main/package.json)
- Bower 分发入口声明参见 [bower.json](https://github.com/NeXTs/Jets.js/blob/main/bower.json)

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：NeXTs/Jets.js

摘要：发现 12 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：身份坑 - 仓库名和安装名不一致。

## 1. 身份坑 · 仓库名和安装名不一致

- 严重度：medium
- 证据强度：runtime_trace
- 发现：仓库名 `jets.js` 与安装入口 `jets` 不完全一致。
- 对用户的影响：用户照着仓库名搜索包或照着包名找仓库时容易走错入口。
- 复现命令：`npm install jets`
- 证据：identity.distribution | https://github.com/NeXTs/Jets.js | repo=jets.js; install=jets

## 2. 安装坑 · 来源证据：Failing CI

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Failing CI
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/NeXTs/Jets.js/issues/43 | 来源类型 github_issue 暴露的待验证使用条件。

## 3. 安装坑 · 来源证据：Feature: non-selector searchTag

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Feature: non-selector searchTag
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/NeXTs/Jets.js/issues/28 | 来源类型 github_issue 暴露的待验证使用条件。

## 4. 配置坑 · 来源证据：if the table is generate by innerHTML

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个配置相关的待验证问题：if the table is generate by innerHTML
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/NeXTs/Jets.js/issues/33 | 来源类型 github_issue 暴露的待验证使用条件。

## 5. 能力坑 · 来源证据：nested items

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个能力理解相关的待验证问题：nested items
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/NeXTs/Jets.js/issues/5 | 来源类型 github_issue 暴露的待验证使用条件。

## 6. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/NeXTs/Jets.js | README/documentation is current enough for a first validation pass.

## 7. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/NeXTs/Jets.js | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/NeXTs/Jets.js | no_demo; severity=medium

## 9. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/NeXTs/Jets.js | no_demo; severity=medium

## 10. 安全/权限坑 · 来源证据：CSP violation

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：CSP violation
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/NeXTs/Jets.js/issues/44 | 来源类型 github_issue 暴露的待验证使用条件。

## 11. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/NeXTs/Jets.js | issue_or_pr_quality=unknown

## 12. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/NeXTs/Jets.js | release_recency=unknown

<!-- canonical_name: NeXTs/Jets.js; human_manual_source: deepwiki_human_wiki -->
