Skip to content

Commit 186ce6d

Browse files
committed
init: 🎉 添加 xpath 选择器库
1 parent 875a6e4 commit 186ce6d

11 files changed

Lines changed: 10909 additions & 5 deletions

File tree

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
"commitlint",
9696
"contenteditable",
9797
"dede",
98+
"fontoxpath",
9899
"jsqr",
99100
"labelledby",
100101
"notiflix",

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
## 📦 封装工具
2020

21-
| 名称 | 功能 | 使用 |
22-
| ---------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
23-
| [downloader](./apps/libs/downloader/README.md) | 资源下载器(下载资源、Zip 压缩、下载到本地) | [🐒Greasy Fork](https://greasyfork.org/zh-CN/scripts/559087) \| [🐱Script Cat](https://scriptcat.org/zh-CN/script-show-page/4893) |
21+
| 名称 | 功能 | 使用 |
22+
| ------------------------------------------------------ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
23+
| [downloader](./apps/libs/downloader/README.md) | 资源下载器(下载资源、Zip 压缩、下载到本地) | [🐒Greasy Fork](https://greasyfork.org/zh-CN/scripts/559087) \| [🐱Script Cat](https://scriptcat.org/zh-CN/script-show-page/4893) |
24+
| [xpath-selector](./apps/libs/xpath-selector/README.md) | 一个 XPath 选择器库,快速节点获取数据 | [🐒Greasy Fork](https://greasyfork.org/zh-CN/scripts/559142) \| [🐱Script Cat](https://scriptcat.org/zh-CN/script-show-page/4900) |

apps/libs/downloader/README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@
2020
### ✍ 添加元数据
2121

2222
```typescript
23-
// ==UserScript==
2423
// @require https://**/downloader.js?*
2524
// @grant GM_download
26-
// ==/UserScript==
2725
```
2826

2927
### 📥 参数说明
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# xpath-selector
2+
3+
## 1.0.0
4+
5+
### Major Changes
6+
7+
- init

apps/libs/xpath-selector/README.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# XPath Selector
2+
3+
**一个 XPath 选择器库,快速节点获取数据**
4+
5+
<a href="https://github.com/xiaohuohumax/userscripts/tree/main/apps/libs/xpath-selector">
6+
<img src="https://img.shields.io/badge/GITHUB-项目地址-brightgreen?style=for-the-badge&logo=github" alt="项目地址" />
7+
</a>
8+
<a href="https://github.com/xiaohuohumax/userscripts/blob/main/LICENSE">
9+
<img src="https://img.shields.io/badge/MIT-开源协议-orange?style=for-the-badge&logo=github" alt="开源协议" />
10+
</a>
11+
<a href="https://github.com/xiaohuohumax/userscripts/blob/main/apps/libs/xpath-selector/CHANGELOG.md">
12+
<img src="https://img.shields.io/badge/CHANGELOG-更新日志-blue?style=for-the-badge&logo=github" alt="更新日志" />
13+
</a>
14+
<a href="https://github.com/xiaohuohumax/userscripts/issues">
15+
<img src="https://img.shields.io/badge/issues-问题反馈-yellow?style=for-the-badge&logo=github" alt="问题反馈" />
16+
</a>
17+
18+
## 📖 使用方式
19+
20+
### ✍ 添加元数据
21+
22+
```typescript
23+
// @require https://**/xpath-selector.js?*
24+
```
25+
### 📥 参数说明
26+
27+
**Options 参数说明:**
28+
29+
| 参数名 | 类型 | 是否必填 | 默认值 | 说明 |
30+
| ------------ | ------ | -------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------- |
31+
| `expression` | string || | 要获取的节点的 XPath 表达式 |
32+
| `returnType` | string || | 获取结果的类型,可选值:`string``strings``number``numbers``boolean``nodes``first-node``map``array``all-results` |
33+
| `node` | Node || `document` | 要搜索的节点 |
34+
35+
### 📦 使用示例
36+
37+
**获取 title 节点的文本内容**
38+
39+
```typescript
40+
const title = xpathSelector({
41+
expression: '//title/text()',
42+
returnType: 'string'
43+
})
44+
console.log(title) // hello world
45+
```
46+
47+
**获取所有 p 节点的文本内容**
48+
49+
```typescript
50+
const pList = xpathSelector({
51+
expression: '//p/text()',
52+
returnType: 'strings'
53+
})
54+
console.log(pList) // ['hello', 'world']
55+
```
56+
57+
**统计所有 a 节点的个数**
58+
59+
```typescript
60+
const aCount = xpathSelector({
61+
expression: 'count(//a)',
62+
returnType: 'number'
63+
})
64+
console.log(aCount) // 2
65+
```
66+
67+
**判断是否存在 section 节点**
68+
69+
```typescript
70+
const hasSection = xpathSelector({
71+
expression: 'boolean(//section)',
72+
returnType: 'boolean'
73+
})
74+
console.log(hasSection) // true
75+
```
76+
77+
**获取全部的 a 节点**
78+
79+
```typescript
80+
const aList = xpathSelector({
81+
expression: '//a',
82+
returnType: 'nodes'
83+
})
84+
console.log(aList) // [<a>hello</a>, <a>world</a>]
85+
```
86+
87+
**获取第一个 a 节点**
88+
89+
```typescript
90+
const firstA = xpathSelector({
91+
expression: '//a',
92+
returnType: 'first-node'
93+
})
94+
console.log(firstA) // <a>hello</a>
95+
```
96+
97+
**获取 html 节点的全部属性**
98+
99+
```typescript
100+
const htmlAttributes = xpathSelector({
101+
expression: `map:merge(
102+
for $attr in //html/@*
103+
return map:entry(local-name($attr), string($attr))
104+
)`,
105+
returnType: 'map'
106+
})
107+
console.log(htmlAttributes) // {lang: "en", charset: "UTF-8"}
108+
```
109+
110+
## 🚨 免责声明
111+
112+
- 本脚本仅供学习交流使用
113+
- 请勿用于任何商业用途
114+
- 使用本脚本产生的任何后果由用户自行承担
115+
116+
## ♻ 其他说明
117+
118+
GreasyFork 或者 ScriptCat 回复不及时,问题反馈推荐直接在 Github 提 Issue。
119+
120+
**如果觉得本脚本对你有帮助,欢迎点个 ⭐ Star 支持一下!**
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "xpath-selector",
3+
"type": "module",
4+
"version": "1.0.0",
5+
"private": true,
6+
"description": "XPath Selector -- 一个 XPath 选择器库,快速节点获取数据",
7+
"author": {
8+
"name": "xiaohuohumax",
9+
"url": "https://github.com/xiaohuohumax"
10+
},
11+
"license": "MIT",
12+
"repository": {
13+
"type": "git",
14+
"url": "https://github.com/xiaohuohumax/userscripts.git"
15+
},
16+
"keywords": [
17+
"typescript",
18+
"tampermonkey",
19+
"xpath",
20+
"selector"
21+
],
22+
"scripts": {
23+
"build": "vite build --emptyOutDir=false"
24+
},
25+
"dependencies": {
26+
"fontoxpath": "^3.33.2"
27+
},
28+
"devDependencies": {
29+
"vite-plugin-banner": "^0.8.1"
30+
}
31+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import fontoxpath from 'fontoxpath'
2+
3+
export type ReturnType =
4+
'string'
5+
| 'strings'
6+
| 'number'
7+
| 'numbers'
8+
| 'boolean'
9+
| 'nodes'
10+
| 'first-node'
11+
| 'map'
12+
| 'array'
13+
| 'all-results'
14+
15+
export interface Options<T> {
16+
expression: string
17+
returnType: T
18+
node?: Node
19+
}
20+
21+
type ReturnTypeTransition<T extends ReturnType> = {
22+
'string': fontoxpath.ReturnType.STRING
23+
'strings': fontoxpath.ReturnType.STRINGS
24+
'number': fontoxpath.ReturnType.NUMBER
25+
'numbers': fontoxpath.ReturnType.NUMBERS
26+
'boolean': fontoxpath.ReturnType.BOOLEAN
27+
'nodes': fontoxpath.ReturnType.NODES
28+
'first-node': fontoxpath.ReturnType.FIRST_NODE
29+
'map': fontoxpath.ReturnType.MAP
30+
'array': fontoxpath.ReturnType.ARRAY
31+
'all-results': fontoxpath.ReturnType.ALL_RESULTS
32+
}[T]
33+
34+
function returnTypeTransition<T extends ReturnType>(returnType: T): ReturnTypeTransition<T> {
35+
const returnTypeMap: { [key in ReturnType]: ReturnTypeTransition<key> } = {
36+
'string': fontoxpath.ReturnType.STRING,
37+
'strings': fontoxpath.ReturnType.STRINGS,
38+
'number': fontoxpath.ReturnType.NUMBER,
39+
'numbers': fontoxpath.ReturnType.NUMBERS,
40+
'boolean': fontoxpath.ReturnType.BOOLEAN,
41+
'nodes': fontoxpath.ReturnType.NODES,
42+
'first-node': fontoxpath.ReturnType.FIRST_NODE,
43+
'map': fontoxpath.ReturnType.MAP,
44+
'array': fontoxpath.ReturnType.ARRAY,
45+
'all-results': fontoxpath.ReturnType.ALL_RESULTS,
46+
}
47+
48+
if (!returnTypeMap[returnType]) {
49+
throw new Error(`Invalid return type: ${returnType}, expected one of ${Object.keys(returnTypeMap).join(', ')}`)
50+
}
51+
52+
return returnTypeMap[returnType]
53+
}
54+
55+
export default function xpathSelector<T extends ReturnType>(options: Options<T>) {
56+
return fontoxpath.evaluateXPath<fontoxpath.Node, ReturnTypeTransition<T>>(
57+
options.expression,
58+
options.node || document,
59+
null,
60+
null,
61+
returnTypeTransition(options.returnType),
62+
)
63+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "../../../tsconfig.base.json"
3+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { defineConfig } from 'vite'
2+
import banner from 'vite-plugin-banner'
3+
import { author, description, license, version } from './package.json'
4+
5+
export default defineConfig({
6+
plugins: [
7+
banner({
8+
content: `// ==UserScript==
9+
// @name DXPath Selector 一个 XPath 选择器库,快速节点获取数据
10+
// @namespace xiaohuohumax/userscripts/xpath-selector
11+
// @version ${version}
12+
// @author ${author.name}
13+
// @description ${description}
14+
// @license ${license}
15+
// ==/UserScript==
16+
`,
17+
verify: false,
18+
}),
19+
],
20+
build: {
21+
outDir: '../../../dist/',
22+
minify: false,
23+
lib: {
24+
entry: 'src/index.ts',
25+
formats: ['iife'],
26+
fileName: () => 'xpath-selector.js',
27+
name: 'xpathSelector',
28+
},
29+
},
30+
})

0 commit comments

Comments
 (0)