diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml
new file mode 100644
index 0000000..2eb9238
--- /dev/null
+++ b/.github/workflows/publish-npm.yml
@@ -0,0 +1,26 @@
+name: Publish Package to npmjs
+
+on:
+ workflow_dispatch:
+
+jobs:
+ build:
+ runs-on: ubuntu-24.04
+ permissions:
+ id-token: write
+ contents: read
+ steps:
+ - uses: actions/checkout@v4
+ - uses: pnpm/action-setup@v3
+ with:
+ version: 9.15.9
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '20.x'
+ registry-url: 'https://registry.npmjs.org'
+ - run: |
+ pnpm i
+ cd packages/pdf2md && pnpm build && pnpm publish
+ cd ../mcp && pnpm build && pnpm publish
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 995b14b..4e5a7d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,5 @@
-/node_modules
-/test/samples
-/test/output
-/test/results
-/test/imahes
-/test/tt.js
-/test/mm.js
\ No newline at end of file
+**/node_modules
+**/dist
+.vscode/mcp.json
+samples
+packages/mcp/output
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..51fb693
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "printWidth": 160,
+ "singleQuote": true,
+ "endOfLine": "lf"
+}
diff --git a/README.md b/README.md
index 36a52cb..a364a57 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# PDF2MD Node.js
-
+
@@ -20,17 +20,15 @@ A powerful Node.js tool for converting PDF documents to Markdown format using ad
## 🚀 Installation
```bash
-# Clone the repository
-git clone https://github.com/yourusername/pdf2md.git
-cd pdf2md/pdf2md-node
-
# Install dependencies
-npm install
+pnpm add pdf2md-js
+# or
+npm add pdf2md-js
```
## 📋 Requirements
-- Node.js 16.0.0 or higher
+- Node.js 20.0.0 or higher
- API key for at least one of the supported vision models
## 🔧 Usage
@@ -38,7 +36,7 @@ npm install
### Basic Usage
```javascript
-import { parsePdf } from './src/index.js';
+import { parsePdf } from 'pdf2md-js';
const result = await parsePdf('path/to/your.pdf', {
apiKey: 'your-api-key',
@@ -107,19 +105,19 @@ The project includes several test scripts to verify functionality:
```bash
# Test the full PDF to Markdown conversion process
-node test/testFullProcess.js
+pnpm vite-node test/testFullProcess.js
# Test only the PDF to image conversion
-node test/testFullPageImages.js
+pnpm vite-node test/testFullPageImages.js
# Test specific vision models
-node test/testModel.js
+pnpm vite-node test/testModel.js
```
## 📁 Project Structure
```
-pdf2md-node/
+pdf2md-js/
├── src/
│ ├── index.js # Main entry point
│ ├── pdfParser.js # PDF parsing module
diff --git a/README.zh-CN.md b/README.zh-CN.md
index f70b117..703c65e 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -1,7 +1,7 @@
# PDF2MD Node.js
-
+
@@ -18,17 +18,15 @@
## 🚀 安装
```bash
-# 克隆仓库
-git clone https://github.com/yourusername/pdf2md.git
-cd pdf2md/pdf2md-node
-
-# 安装依赖
-npm install
+# Install dependencies
+pnpm add pdf2md-js
+# or
+npm add pdf2md-js
```
## 📋 系统要求
-- Node.js 16.0.0 或更高版本
+- Node.js 20.0.0 或更高版本
- 至少一个支持的视觉模型的API密钥
## 🔧 使用方法
@@ -36,7 +34,7 @@ npm install
### 基本用法
```javascript
-import { parsePdf } from './src/index.js';
+import { parsePdf } from 'pdf2md-js';
const result = await parsePdf('path/to/your.pdf', {
apiKey: 'your-api-key',
@@ -106,19 +104,19 @@ const result = await parsePdf('path/to/your.pdf', options);
```bash
# 测试完整的PDF到Markdown转换流程
-node test/testFullProcess.js
+pnpm vite-node test/testFullProcess.js
# 仅测试PDF到图像的转换
-node test/testFullPageImages.js
+pnpm vite-node test/testFullPageImages.js
# 测试特定视觉模型
-node test/testModel.js
+pnpm vite-node test/testModel.js
```
## 📁 项目结构
```
-pdf2md-node/
+pdf2md-js/
├── src/
│ ├── index.js # 主入口点
│ ├── pdfParser.js # PDF解析模块
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index 5a6a7d3..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,3563 +0,0 @@
-{
- "name": "pdf2md-node",
- "version": "1.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "pdf2md-node",
- "version": "1.0.0",
- "license": "MIT",
- "dependencies": {
- "@turf/turf": "^6.5.0",
- "canvas": "^2.11.2",
- "fs-extra": "^11.1.1",
- "openai": "^4.28.0",
- "pdf-lib": "^1.17.1",
- "pdf-parse": "^1.1.1",
- "pdf.js-extract": "^0.2.1",
- "pdfjs-dist": "^3.11.174",
- "sharp": "^0.33.1"
- }
- },
- "node_modules/@emnapi/runtime": {
- "version": "1.4.0",
- "resolved": "https://registry.npmmirror.com/@emnapi/runtime/-/runtime-1.4.0.tgz",
- "integrity": "sha512-64WYIf4UYcdLnbKn/umDlNjQDSS8AgZrI/R9+x5ilkUVFxXcA1Ebl+gQLc/6mERA4407Xof0R7wEyEuj091CVw==",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@emnapi/runtime/node_modules/tslib": {
- "version": "2.8.1",
- "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
- "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
- "optional": true
- },
- "node_modules/@img/sharp-darwin-arm64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmmirror.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
- "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-darwin-arm64": "1.0.4"
- }
- },
- "node_modules/@img/sharp-darwin-x64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmmirror.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz",
- "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-darwin-x64": "1.0.4"
- }
- },
- "node_modules/@img/sharp-libvips-darwin-arm64": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz",
- "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-darwin-x64": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz",
- "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-arm": {
- "version": "1.0.5",
- "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz",
- "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==",
- "cpu": [
- "arm"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-arm64": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
- "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-s390x": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz",
- "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==",
- "cpu": [
- "s390x"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linux-x64": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz",
- "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz",
- "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-libvips-linuxmusl-x64": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz",
- "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-linux-arm": {
- "version": "0.33.5",
- "resolved": "https://registry.npmmirror.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz",
- "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==",
- "cpu": [
- "arm"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-arm": "1.0.5"
- }
- },
- "node_modules/@img/sharp-linux-arm64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmmirror.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
- "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-arm64": "1.0.4"
- }
- },
- "node_modules/@img/sharp-linux-s390x": {
- "version": "0.33.5",
- "resolved": "https://registry.npmmirror.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz",
- "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==",
- "cpu": [
- "s390x"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-s390x": "1.0.4"
- }
- },
- "node_modules/@img/sharp-linux-x64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmmirror.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz",
- "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linux-x64": "1.0.4"
- }
- },
- "node_modules/@img/sharp-linuxmusl-arm64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmmirror.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz",
- "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-arm64": "1.0.4"
- }
- },
- "node_modules/@img/sharp-linuxmusl-x64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmmirror.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz",
- "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-x64": "1.0.4"
- }
- },
- "node_modules/@img/sharp-wasm32": {
- "version": "0.33.5",
- "resolved": "https://registry.npmmirror.com/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz",
- "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==",
- "cpu": [
- "wasm32"
- ],
- "optional": true,
- "dependencies": {
- "@emnapi/runtime": "^1.2.0"
- },
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-win32-ia32": {
- "version": "0.33.5",
- "resolved": "https://registry.npmmirror.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz",
- "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==",
- "cpu": [
- "ia32"
- ],
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@img/sharp-win32-x64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmmirror.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz",
- "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- }
- },
- "node_modules/@mapbox/node-pre-gyp": {
- "version": "1.0.11",
- "resolved": "https://registry.npmmirror.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
- "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
- "dependencies": {
- "detect-libc": "^2.0.0",
- "https-proxy-agent": "^5.0.0",
- "make-dir": "^3.1.0",
- "node-fetch": "^2.6.7",
- "nopt": "^5.0.0",
- "npmlog": "^5.0.1",
- "rimraf": "^3.0.2",
- "semver": "^7.3.5",
- "tar": "^6.1.11"
- },
- "bin": {
- "node-pre-gyp": "bin/node-pre-gyp"
- }
- },
- "node_modules/@pdf-lib/standard-fonts": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",
- "integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==",
- "dependencies": {
- "pako": "^1.0.6"
- }
- },
- "node_modules/@pdf-lib/upng": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/@pdf-lib/upng/-/upng-1.0.1.tgz",
- "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==",
- "dependencies": {
- "pako": "^1.0.10"
- }
- },
- "node_modules/@turf/along": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/along/-/along-6.5.0.tgz",
- "integrity": "sha512-LLyWQ0AARqJCmMcIEAXF4GEu8usmd4Kbz3qk1Oy5HoRNpZX47+i5exQtmIWKdqJ1MMhW26fCTXgpsEs5zgJ5gw==",
- "dependencies": {
- "@turf/bearing": "^6.5.0",
- "@turf/destination": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/angle": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/angle/-/angle-6.5.0.tgz",
- "integrity": "sha512-4pXMbWhFofJJAOvTMCns6N4C8CMd5Ih4O2jSAG9b3dDHakj3O4yN1+Zbm+NUei+eVEZ9gFeVp9svE3aMDenIkw==",
- "dependencies": {
- "@turf/bearing": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/rhumb-bearing": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/area": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/area/-/area-6.5.0.tgz",
- "integrity": "sha512-xCZdiuojokLbQ+29qR6qoMD89hv+JAgWjLrwSEWL+3JV8IXKeNFl6XkEJz9HGkVpnXvQKJoRz4/liT+8ZZ5Jyg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/bbox": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/bbox/-/bbox-6.5.0.tgz",
- "integrity": "sha512-RBbLaao5hXTYyyg577iuMtDB8ehxMlUqHEJiMs8jT1GHkFhr6sYre3lmLsPeYEi/ZKj5TP5tt7fkzNdJ4GIVyw==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/bbox-clip": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/bbox-clip/-/bbox-clip-6.5.0.tgz",
- "integrity": "sha512-F6PaIRF8WMp8EmgU/Ke5B1Y6/pia14UAYB5TiBC668w5rVVjy5L8rTm/m2lEkkDMHlzoP9vNY4pxpNthE7rLcQ==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/bbox-polygon": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/bbox-polygon/-/bbox-polygon-6.5.0.tgz",
- "integrity": "sha512-+/r0NyL1lOG3zKZmmf6L8ommU07HliP4dgYToMoTxqzsWzyLjaj/OzgQ8rBmv703WJX+aS6yCmLuIhYqyufyuw==",
- "dependencies": {
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/bearing": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/bearing/-/bearing-6.5.0.tgz",
- "integrity": "sha512-dxINYhIEMzgDOztyMZc20I7ssYVNEpSv04VbMo5YPQsqa80KO3TFvbuCahMsCAW5z8Tncc8dwBlEFrmRjJG33A==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/bezier-spline": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/bezier-spline/-/bezier-spline-6.5.0.tgz",
- "integrity": "sha512-vokPaurTd4PF96rRgGVm6zYYC5r1u98ZsG+wZEv9y3kJTuJRX/O3xIY2QnTGTdbVmAJN1ouOsD0RoZYaVoXORQ==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/boolean-clockwise": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/boolean-clockwise/-/boolean-clockwise-6.5.0.tgz",
- "integrity": "sha512-45+C7LC5RMbRWrxh3Z0Eihsc8db1VGBO5d9BLTOAwU4jR6SgsunTfRWR16X7JUwIDYlCVEmnjcXJNi/kIU3VIw==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/boolean-contains": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/boolean-contains/-/boolean-contains-6.5.0.tgz",
- "integrity": "sha512-4m8cJpbw+YQcKVGi8y0cHhBUnYT+QRfx6wzM4GI1IdtYH3p4oh/DOBJKrepQyiDzFDaNIjxuWXBh0ai1zVwOQQ==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/boolean-point-on-line": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/boolean-crosses": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/boolean-crosses/-/boolean-crosses-6.5.0.tgz",
- "integrity": "sha512-gvshbTPhAHporTlQwBJqyfW+2yV8q/mOTxG6PzRVl6ARsqNoqYQWkd4MLug7OmAqVyBzLK3201uAeBjxbGw0Ng==",
- "dependencies": {
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/line-intersect": "^6.5.0",
- "@turf/polygon-to-line": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/boolean-disjoint": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/boolean-disjoint/-/boolean-disjoint-6.5.0.tgz",
- "integrity": "sha512-rZ2ozlrRLIAGo2bjQ/ZUu4oZ/+ZjGvLkN5CKXSKBcu6xFO6k2bgqeM8a1836tAW+Pqp/ZFsTA5fZHsJZvP2D5g==",
- "dependencies": {
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/line-intersect": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/polygon-to-line": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/boolean-equal": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/boolean-equal/-/boolean-equal-6.5.0.tgz",
- "integrity": "sha512-cY0M3yoLC26mhAnjv1gyYNQjn7wxIXmL2hBmI/qs8g5uKuC2hRWi13ydufE3k4x0aNRjFGlg41fjoYLwaVF+9Q==",
- "dependencies": {
- "@turf/clean-coords": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "geojson-equality": "0.1.6"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/boolean-intersects": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/boolean-intersects/-/boolean-intersects-6.5.0.tgz",
- "integrity": "sha512-nIxkizjRdjKCYFQMnml6cjPsDOBCThrt+nkqtSEcxkKMhAQj5OO7o2CecioNTaX8EayqwMGVKcsz27oP4mKPTw==",
- "dependencies": {
- "@turf/boolean-disjoint": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/boolean-overlap": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/boolean-overlap/-/boolean-overlap-6.5.0.tgz",
- "integrity": "sha512-8btMIdnbXVWUa1M7D4shyaSGxLRw6NjMcqKBcsTXcZdnaixl22k7ar7BvIzkaRYN3SFECk9VGXfLncNS3ckQUw==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/line-intersect": "^6.5.0",
- "@turf/line-overlap": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "geojson-equality": "0.1.6"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/boolean-parallel": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/boolean-parallel/-/boolean-parallel-6.5.0.tgz",
- "integrity": "sha512-aSHJsr1nq9e5TthZGZ9CZYeXklJyRgR5kCLm5X4urz7+MotMOp/LsGOsvKvK9NeUl9+8OUmfMn8EFTT8LkcvIQ==",
- "dependencies": {
- "@turf/clean-coords": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/line-segment": "^6.5.0",
- "@turf/rhumb-bearing": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/boolean-point-in-polygon": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-6.5.0.tgz",
- "integrity": "sha512-DtSuVFB26SI+hj0SjrvXowGTUCHlgevPAIsukssW6BG5MlNSBQAo70wpICBNJL6RjukXg8d2eXaAWuD/CqL00A==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/boolean-point-on-line": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/boolean-point-on-line/-/boolean-point-on-line-6.5.0.tgz",
- "integrity": "sha512-A1BbuQ0LceLHvq7F/P7w3QvfpmZqbmViIUPHdNLvZimFNLo4e6IQunmzbe+8aSStH9QRZm3VOflyvNeXvvpZEQ==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/boolean-within": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/boolean-within/-/boolean-within-6.5.0.tgz",
- "integrity": "sha512-YQB3oU18Inx35C/LU930D36RAVe7LDXk1kWsQ8mLmuqYn9YdPsDQTMTkLJMhoQ8EbN7QTdy333xRQ4MYgToteQ==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/boolean-point-on-line": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/buffer": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/buffer/-/buffer-6.5.0.tgz",
- "integrity": "sha512-qeX4N6+PPWbKqp1AVkBVWFerGjMYMUyencwfnkCesoznU6qvfugFHNAngNqIBVnJjZ5n8IFyOf+akcxnrt9sNg==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/center": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/projection": "^6.5.0",
- "d3-geo": "1.7.1",
- "turf-jsts": "*"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/center": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/center/-/center-6.5.0.tgz",
- "integrity": "sha512-T8KtMTfSATWcAX088rEDKjyvQCBkUsLnK/Txb6/8WUXIeOZyHu42G7MkdkHRoHtwieLdduDdmPLFyTdG5/e7ZQ==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/center-mean": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/center-mean/-/center-mean-6.5.0.tgz",
- "integrity": "sha512-AAX6f4bVn12pTVrMUiB9KrnV94BgeBKpyg3YpfnEbBpkN/znfVhL8dG8IxMAxAoSZ61Zt9WLY34HfENveuOZ7Q==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/center-median": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/center-median/-/center-median-6.5.0.tgz",
- "integrity": "sha512-dT8Ndu5CiZkPrj15PBvslpuf01ky41DEYEPxS01LOxp5HOUHXp1oJxsPxvc+i/wK4BwccPNzU1vzJ0S4emd1KQ==",
- "dependencies": {
- "@turf/center-mean": "^6.5.0",
- "@turf/centroid": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/center-of-mass": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/center-of-mass/-/center-of-mass-6.5.0.tgz",
- "integrity": "sha512-EWrriU6LraOfPN7m1jZi+1NLTKNkuIsGLZc2+Y8zbGruvUW+QV7K0nhf7iZWutlxHXTBqEXHbKue/o79IumAsQ==",
- "dependencies": {
- "@turf/centroid": "^6.5.0",
- "@turf/convex": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/centroid": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/centroid/-/centroid-6.5.0.tgz",
- "integrity": "sha512-MwE1oq5E3isewPprEClbfU5pXljIK/GUOMbn22UM3IFPDJX0KeoyLNwghszkdmFp/qMGL/M13MMWvU+GNLXP/A==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/circle": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/circle/-/circle-6.5.0.tgz",
- "integrity": "sha512-oU1+Kq9DgRnoSbWFHKnnUdTmtcRUMmHoV9DjTXu9vOLNV5OWtAAh1VZ+mzsioGGzoDNT/V5igbFOkMfBQc0B6A==",
- "dependencies": {
- "@turf/destination": "^6.5.0",
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/clean-coords": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/clean-coords/-/clean-coords-6.5.0.tgz",
- "integrity": "sha512-EMX7gyZz0WTH/ET7xV8MyrExywfm9qUi0/MY89yNffzGIEHuFfqwhcCqZ8O00rZIPZHUTxpmsxQSTfzJJA1CPw==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/clone": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/clone/-/clone-6.5.0.tgz",
- "integrity": "sha512-mzVtTFj/QycXOn6ig+annKrM6ZlimreKYz6f/GSERytOpgzodbQyOgkfwru100O1KQhhjSudKK4DsQ0oyi9cTw==",
- "dependencies": {
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/clusters": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/clusters/-/clusters-6.5.0.tgz",
- "integrity": "sha512-Y6gfnTJzQ1hdLfCsyd5zApNbfLIxYEpmDibHUqR5z03Lpe02pa78JtgrgUNt1seeO/aJ4TG1NLN8V5gOrHk04g==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/clusters-dbscan": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/clusters-dbscan/-/clusters-dbscan-6.5.0.tgz",
- "integrity": "sha512-SxZEE4kADU9DqLRiT53QZBBhu8EP9skviSyl+FGj08Y01xfICM/RR9ACUdM0aEQimhpu+ZpRVcUK+2jtiCGrYQ==",
- "dependencies": {
- "@turf/clone": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "density-clustering": "1.3.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/clusters-kmeans": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/clusters-kmeans/-/clusters-kmeans-6.5.0.tgz",
- "integrity": "sha512-DwacD5+YO8kwDPKaXwT9DV46tMBVNsbi1IzdajZu1JDSWoN7yc7N9Qt88oi+p30583O0UPVkAK+A10WAQv4mUw==",
- "dependencies": {
- "@turf/clone": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "skmeans": "0.9.7"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/collect": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/collect/-/collect-6.5.0.tgz",
- "integrity": "sha512-4dN/T6LNnRg099m97BJeOcTA5fSI8cu87Ydgfibewd2KQwBexO69AnjEFqfPX3Wj+Zvisj1uAVIZbPmSSrZkjg==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "rbush": "2.x"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/combine": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/combine/-/combine-6.5.0.tgz",
- "integrity": "sha512-Q8EIC4OtAcHiJB3C4R+FpB4LANiT90t17uOd851qkM2/o6m39bfN5Mv0PWqMZIHWrrosZqRqoY9dJnzz/rJxYQ==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/concave": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/concave/-/concave-6.5.0.tgz",
- "integrity": "sha512-I/sUmUC8TC5h/E2vPwxVht+nRt+TnXIPRoztDFvS8/Y0+cBDple9inLSo9nnPXMXidrBlGXZ9vQx/BjZUJgsRQ==",
- "dependencies": {
- "@turf/clone": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/tin": "^6.5.0",
- "topojson-client": "3.x",
- "topojson-server": "3.x"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/convex": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/convex/-/convex-6.5.0.tgz",
- "integrity": "sha512-x7ZwC5z7PJB0SBwNh7JCeCNx7Iu+QSrH7fYgK0RhhNop13TqUlvHMirMLRgf2db1DqUetrAO2qHJeIuasquUWg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "concaveman": "*"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/destination": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/destination/-/destination-6.5.0.tgz",
- "integrity": "sha512-4cnWQlNC8d1tItOz9B4pmJdWpXqS0vEvv65bI/Pj/genJnsL7evI0/Xw42RvEGROS481MPiU80xzvwxEvhQiMQ==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/difference": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/difference/-/difference-6.5.0.tgz",
- "integrity": "sha512-l8iR5uJqvI+5Fs6leNbhPY5t/a3vipUF/3AeVLpwPQcgmedNXyheYuy07PcMGH5Jdpi5gItOiTqwiU/bUH4b3A==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "polygon-clipping": "^0.15.3"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/dissolve": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/dissolve/-/dissolve-6.5.0.tgz",
- "integrity": "sha512-WBVbpm9zLTp0Bl9CE35NomTaOL1c4TQCtEoO43YaAhNEWJOOIhZMFJyr8mbvYruKl817KinT3x7aYjjCMjTAsQ==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "polygon-clipping": "^0.15.3"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/distance": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/distance/-/distance-6.5.0.tgz",
- "integrity": "sha512-xzykSLfoURec5qvQJcfifw/1mJa+5UwByZZ5TZ8iaqjGYN0vomhV9aiSLeYdUGtYRESZ+DYC/OzY+4RclZYgMg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/distance-weight": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/distance-weight/-/distance-weight-6.5.0.tgz",
- "integrity": "sha512-a8qBKkgVNvPKBfZfEJZnC3DV7dfIsC3UIdpRci/iap/wZLH41EmS90nM+BokAJflUHYy8PqE44wySGWHN1FXrQ==",
- "dependencies": {
- "@turf/centroid": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/ellipse": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/ellipse/-/ellipse-6.5.0.tgz",
- "integrity": "sha512-kuXtwFviw/JqnyJXF1mrR/cb496zDTSbGKtSiolWMNImYzGGkbsAsFTjwJYgD7+4FixHjp0uQPzo70KDf3AIBw==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/rhumb-destination": "^6.5.0",
- "@turf/transform-rotate": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/envelope": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/envelope/-/envelope-6.5.0.tgz",
- "integrity": "sha512-9Z+FnBWvOGOU4X+fMZxYFs1HjFlkKqsddLuMknRaqcJd6t+NIv5DWvPtDL8ATD2GEExYDiFLwMdckfr1yqJgHA==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/bbox-polygon": "^6.5.0",
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/explode": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/explode/-/explode-6.5.0.tgz",
- "integrity": "sha512-6cSvMrnHm2qAsace6pw9cDmK2buAlw8+tjeJVXMfMyY+w7ZUi1rprWMsY92J7s2Dar63Bv09n56/1V7+tcj52Q==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/flatten": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/flatten/-/flatten-6.5.0.tgz",
- "integrity": "sha512-IBZVwoNLVNT6U/bcUUllubgElzpMsNoCw8tLqBw6dfYg9ObGmpEjf9BIYLr7a2Yn5ZR4l7YIj2T7kD5uJjZADQ==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/flip": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/flip/-/flip-6.5.0.tgz",
- "integrity": "sha512-oyikJFNjt2LmIXQqgOGLvt70RgE2lyzPMloYWM7OR5oIFGRiBvqVD2hA6MNw6JewIm30fWZ8DQJw1NHXJTJPbg==",
- "dependencies": {
- "@turf/clone": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/great-circle": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/great-circle/-/great-circle-6.5.0.tgz",
- "integrity": "sha512-7ovyi3HaKOXdFyN7yy1yOMa8IyOvV46RC1QOQTT+RYUN8ke10eyqExwBpL9RFUPvlpoTzoYbM/+lWPogQlFncg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/helpers": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/helpers/-/helpers-6.5.0.tgz",
- "integrity": "sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw==",
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/hex-grid": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/hex-grid/-/hex-grid-6.5.0.tgz",
- "integrity": "sha512-Ln3tc2tgZT8etDOldgc6e741Smg1CsMKAz1/Mlel+MEL5Ynv2mhx3m0q4J9IB1F3a4MNjDeVvm8drAaf9SF33g==",
- "dependencies": {
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/intersect": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/interpolate": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/interpolate/-/interpolate-6.5.0.tgz",
- "integrity": "sha512-LSH5fMeiGyuDZ4WrDJNgh81d2DnNDUVJtuFryJFup8PV8jbs46lQGfI3r1DJ2p1IlEJIz3pmAZYeTfMMoeeohw==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/centroid": "^6.5.0",
- "@turf/clone": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/hex-grid": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/point-grid": "^6.5.0",
- "@turf/square-grid": "^6.5.0",
- "@turf/triangle-grid": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/intersect": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/intersect/-/intersect-6.5.0.tgz",
- "integrity": "sha512-2legGJeKrfFkzntcd4GouPugoqPUjexPZnOvfez+3SfIMrHvulw8qV8u7pfVyn2Yqs53yoVCEjS5sEpvQ5YRQg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "polygon-clipping": "^0.15.3"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/invariant": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/invariant/-/invariant-6.5.0.tgz",
- "integrity": "sha512-Wv8PRNCtPD31UVbdJE/KVAWKe7l6US+lJItRR/HOEW3eh+U/JwRCSUl/KZ7bmjM/C+zLNoreM2TU6OoLACs4eg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/isobands": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/isobands/-/isobands-6.5.0.tgz",
- "integrity": "sha512-4h6sjBPhRwMVuFaVBv70YB7eGz+iw0bhPRnp+8JBdX1UPJSXhoi/ZF2rACemRUr0HkdVB/a1r9gC32vn5IAEkw==",
- "dependencies": {
- "@turf/area": "^6.5.0",
- "@turf/bbox": "^6.5.0",
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/explode": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "object-assign": "*"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/isolines": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/isolines/-/isolines-6.5.0.tgz",
- "integrity": "sha512-6ElhiLCopxWlv4tPoxiCzASWt/jMRvmp6mRYrpzOm3EUl75OhHKa/Pu6Y9nWtCMmVC/RcWtiiweUocbPLZLm0A==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "object-assign": "*"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/kinks": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/kinks/-/kinks-6.5.0.tgz",
- "integrity": "sha512-ViCngdPt1eEL7hYUHR2eHR662GvCgTc35ZJFaNR6kRtr6D8plLaDju0FILeFFWSc+o8e3fwxZEJKmFj9IzPiIQ==",
- "dependencies": {
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/length": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/length/-/length-6.5.0.tgz",
- "integrity": "sha512-5pL5/pnw52fck3oRsHDcSGrj9HibvtlrZ0QNy2OcW8qBFDNgZ4jtl6U7eATVoyWPKBHszW3dWETW+iLV7UARig==",
- "dependencies": {
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/line-arc": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/line-arc/-/line-arc-6.5.0.tgz",
- "integrity": "sha512-I6c+V6mIyEwbtg9P9zSFF89T7QPe1DPTG3MJJ6Cm1MrAY0MdejwQKOpsvNl8LDU2ekHOlz2kHpPVR7VJsoMllA==",
- "dependencies": {
- "@turf/circle": "^6.5.0",
- "@turf/destination": "^6.5.0",
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/line-chunk": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/line-chunk/-/line-chunk-6.5.0.tgz",
- "integrity": "sha512-i1FGE6YJaaYa+IJesTfyRRQZP31QouS+wh/pa6O3CC0q4T7LtHigyBSYjrbjSLfn2EVPYGlPCMFEqNWCOkC6zg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/length": "^6.5.0",
- "@turf/line-slice-along": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/line-intersect": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/line-intersect/-/line-intersect-6.5.0.tgz",
- "integrity": "sha512-CS6R1tZvVQD390G9Ea4pmpM6mJGPWoL82jD46y0q1KSor9s6HupMIo1kY4Ny+AEYQl9jd21V3Scz20eldpbTVA==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/line-segment": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "geojson-rbush": "3.x"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/line-offset": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/line-offset/-/line-offset-6.5.0.tgz",
- "integrity": "sha512-CEXZbKgyz8r72qRvPchK0dxqsq8IQBdH275FE6o4MrBkzMcoZsfSjghtXzKaz9vvro+HfIXal0sTk2mqV1lQTw==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/line-overlap": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/line-overlap/-/line-overlap-6.5.0.tgz",
- "integrity": "sha512-xHOaWLd0hkaC/1OLcStCpfq55lPHpPNadZySDXYiYjEz5HXr1oKmtMYpn0wGizsLwrOixRdEp+j7bL8dPt4ojQ==",
- "dependencies": {
- "@turf/boolean-point-on-line": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/line-segment": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/nearest-point-on-line": "^6.5.0",
- "deep-equal": "1.x",
- "geojson-rbush": "3.x"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/line-segment": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/line-segment/-/line-segment-6.5.0.tgz",
- "integrity": "sha512-jI625Ho4jSuJESNq66Mmi290ZJ5pPZiQZruPVpmHkUw257Pew0alMmb6YrqYNnLUuiVVONxAAKXUVeeUGtycfw==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/line-slice": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/line-slice/-/line-slice-6.5.0.tgz",
- "integrity": "sha512-vDqJxve9tBHhOaVVFXqVjF5qDzGtKWviyjbyi2QnSnxyFAmLlLnBfMX8TLQCAf2GxHibB95RO5FBE6I2KVPRuw==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/nearest-point-on-line": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/line-slice-along": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/line-slice-along/-/line-slice-along-6.5.0.tgz",
- "integrity": "sha512-KHJRU6KpHrAj+BTgTNqby6VCTnDzG6a1sJx/I3hNvqMBLvWVA2IrkR9L9DtsQsVY63IBwVdQDqiwCuZLDQh4Ng==",
- "dependencies": {
- "@turf/bearing": "^6.5.0",
- "@turf/destination": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/line-split": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/line-split/-/line-split-6.5.0.tgz",
- "integrity": "sha512-/rwUMVr9OI2ccJjw7/6eTN53URtGThNSD5I0GgxyFXMtxWiloRJ9MTff8jBbtPWrRka/Sh2GkwucVRAEakx9Sw==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/line-intersect": "^6.5.0",
- "@turf/line-segment": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/nearest-point-on-line": "^6.5.0",
- "@turf/square": "^6.5.0",
- "@turf/truncate": "^6.5.0",
- "geojson-rbush": "3.x"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/line-to-polygon": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/line-to-polygon/-/line-to-polygon-6.5.0.tgz",
- "integrity": "sha512-qYBuRCJJL8Gx27OwCD1TMijM/9XjRgXH/m/TyuND4OXedBpIWlK5VbTIO2gJ8OCfznBBddpjiObLBrkuxTpN4Q==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/clone": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/mask": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/mask/-/mask-6.5.0.tgz",
- "integrity": "sha512-RQha4aU8LpBrmrkH8CPaaoAfk0Egj5OuXtv6HuCQnHeGNOQt3TQVibTA3Sh4iduq4EPxnZfDjgsOeKtrCA19lg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "polygon-clipping": "^0.15.3"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/meta": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/meta/-/meta-6.5.0.tgz",
- "integrity": "sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA==",
- "dependencies": {
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/midpoint": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/midpoint/-/midpoint-6.5.0.tgz",
- "integrity": "sha512-MyTzV44IwmVI6ec9fB2OgZ53JGNlgOpaYl9ArKoF49rXpL84F9rNATndbe0+MQIhdkw8IlzA6xVP4lZzfMNVCw==",
- "dependencies": {
- "@turf/bearing": "^6.5.0",
- "@turf/destination": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/moran-index": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/moran-index/-/moran-index-6.5.0.tgz",
- "integrity": "sha512-ItsnhrU2XYtTtTudrM8so4afBCYWNaB0Mfy28NZwLjB5jWuAsvyV+YW+J88+neK/ougKMTawkmjQqodNJaBeLQ==",
- "dependencies": {
- "@turf/distance-weight": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/nearest-point": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/nearest-point/-/nearest-point-6.5.0.tgz",
- "integrity": "sha512-fguV09QxilZv/p94s8SMsXILIAMiaXI5PATq9d7YWijLxWUj6Q/r43kxyoi78Zmwwh1Zfqz9w+bCYUAxZ5+euA==",
- "dependencies": {
- "@turf/clone": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/nearest-point-on-line": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/nearest-point-on-line/-/nearest-point-on-line-6.5.0.tgz",
- "integrity": "sha512-WthrvddddvmymnC+Vf7BrkHGbDOUu6Z3/6bFYUGv1kxw8tiZ6n83/VG6kHz4poHOfS0RaNflzXSkmCi64fLBlg==",
- "dependencies": {
- "@turf/bearing": "^6.5.0",
- "@turf/destination": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/line-intersect": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/nearest-point-to-line": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/nearest-point-to-line/-/nearest-point-to-line-6.5.0.tgz",
- "integrity": "sha512-PXV7cN0BVzUZdjj6oeb/ESnzXSfWmEMrsfZSDRgqyZ9ytdiIj/eRsnOXLR13LkTdXVOJYDBuf7xt1mLhM4p6+Q==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/point-to-line-distance": "^6.5.0",
- "object-assign": "*"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/planepoint": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/planepoint/-/planepoint-6.5.0.tgz",
- "integrity": "sha512-R3AahA6DUvtFbka1kcJHqZ7DMHmPXDEQpbU5WaglNn7NaCQg9HB0XM0ZfqWcd5u92YXV+Gg8QhC8x5XojfcM4Q==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/point-grid": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/point-grid/-/point-grid-6.5.0.tgz",
- "integrity": "sha512-Iq38lFokNNtQJnOj/RBKmyt6dlof0yhaHEDELaWHuECm1lIZLY3ZbVMwbs+nXkwTAHjKfS/OtMheUBkw+ee49w==",
- "dependencies": {
- "@turf/boolean-within": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/point-on-feature": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/point-on-feature/-/point-on-feature-6.5.0.tgz",
- "integrity": "sha512-bDpuIlvugJhfcF/0awAQ+QI6Om1Y1FFYE8Y/YdxGRongivix850dTeXCo0mDylFdWFPGDo7Mmh9Vo4VxNwW/TA==",
- "dependencies": {
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/center": "^6.5.0",
- "@turf/explode": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/nearest-point": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/point-to-line-distance": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/point-to-line-distance/-/point-to-line-distance-6.5.0.tgz",
- "integrity": "sha512-opHVQ4vjUhNBly1bob6RWy+F+hsZDH9SA0UW36pIRzfpu27qipU18xup0XXEePfY6+wvhF6yL/WgCO2IbrLqEA==",
- "dependencies": {
- "@turf/bearing": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/projection": "^6.5.0",
- "@turf/rhumb-bearing": "^6.5.0",
- "@turf/rhumb-distance": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/points-within-polygon": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/points-within-polygon/-/points-within-polygon-6.5.0.tgz",
- "integrity": "sha512-YyuheKqjliDsBDt3Ho73QVZk1VXX1+zIA2gwWvuz8bR1HXOkcuwk/1J76HuFMOQI3WK78wyAi+xbkx268PkQzQ==",
- "dependencies": {
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/polygon-smooth": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/polygon-smooth/-/polygon-smooth-6.5.0.tgz",
- "integrity": "sha512-LO/X/5hfh/Rk4EfkDBpLlVwt3i6IXdtQccDT9rMjXEP32tRgy0VMFmdkNaXoGlSSKf/1mGqLl4y4wHd86DqKbg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/polygon-tangents": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/polygon-tangents/-/polygon-tangents-6.5.0.tgz",
- "integrity": "sha512-sB4/IUqJMYRQH9jVBwqS/XDitkEfbyqRy+EH/cMRJURTg78eHunvJ708x5r6umXsbiUyQU4eqgPzEylWEQiunw==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/boolean-within": "^6.5.0",
- "@turf/explode": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/nearest-point": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/polygon-to-line": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/polygon-to-line/-/polygon-to-line-6.5.0.tgz",
- "integrity": "sha512-5p4n/ij97EIttAq+ewSnKt0ruvuM+LIDzuczSzuHTpq4oS7Oq8yqg5TQ4nzMVuK41r/tALCk7nAoBuw3Su4Gcw==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/polygonize": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/polygonize/-/polygonize-6.5.0.tgz",
- "integrity": "sha512-a/3GzHRaCyzg7tVYHo43QUChCspa99oK4yPqooVIwTC61npFzdrmnywMv0S+WZjHZwK37BrFJGFrZGf6ocmY5w==",
- "dependencies": {
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/envelope": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/projection": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/projection/-/projection-6.5.0.tgz",
- "integrity": "sha512-/Pgh9mDvQWWu8HRxqpM+tKz8OzgauV+DiOcr3FCjD6ubDnrrmMJlsf6fFJmggw93mtVPrZRL6yyi9aYCQBOIvg==",
- "dependencies": {
- "@turf/clone": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/random": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/random/-/random-6.5.0.tgz",
- "integrity": "sha512-8Q25gQ/XbA7HJAe+eXp4UhcXM9aOOJFaxZ02+XSNwMvY8gtWSCBLVqRcW4OhqilgZ8PeuQDWgBxeo+BIqqFWFQ==",
- "dependencies": {
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/rectangle-grid": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/rectangle-grid/-/rectangle-grid-6.5.0.tgz",
- "integrity": "sha512-yQZ/1vbW68O2KsSB3OZYK+72aWz/Adnf7m2CMKcC+aq6TwjxZjAvlbCOsNUnMAuldRUVN1ph6RXMG4e9KEvKvg==",
- "dependencies": {
- "@turf/boolean-intersects": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/rewind": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/rewind/-/rewind-6.5.0.tgz",
- "integrity": "sha512-IoUAMcHWotBWYwSYuYypw/LlqZmO+wcBpn8ysrBNbazkFNkLf3btSDZMkKJO/bvOzl55imr/Xj4fi3DdsLsbzQ==",
- "dependencies": {
- "@turf/boolean-clockwise": "^6.5.0",
- "@turf/clone": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/rhumb-bearing": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/rhumb-bearing/-/rhumb-bearing-6.5.0.tgz",
- "integrity": "sha512-jMyqiMRK4hzREjQmnLXmkJ+VTNTx1ii8vuqRwJPcTlKbNWfjDz/5JqJlb5NaFDcdMpftWovkW5GevfnuzHnOYA==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/rhumb-destination": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/rhumb-destination/-/rhumb-destination-6.5.0.tgz",
- "integrity": "sha512-RHNP1Oy+7xTTdRrTt375jOZeHceFbjwohPHlr9Hf68VdHHPMAWgAKqiX2YgSWDcvECVmiGaBKWus1Df+N7eE4Q==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/rhumb-distance": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/rhumb-distance/-/rhumb-distance-6.5.0.tgz",
- "integrity": "sha512-oKp8KFE8E4huC2Z1a1KNcFwjVOqa99isxNOwfo4g3SUABQ6NezjKDDrnvC4yI5YZ3/huDjULLBvhed45xdCrzg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/sample": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/sample/-/sample-6.5.0.tgz",
- "integrity": "sha512-kSdCwY7el15xQjnXYW520heKUrHwRvnzx8ka4eYxX9NFeOxaFITLW2G7UtXb6LJK8mmPXI8Aexv23F2ERqzGFg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/sector": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/sector/-/sector-6.5.0.tgz",
- "integrity": "sha512-cYUOkgCTWqa23SOJBqxoFAc/yGCUsPRdn/ovbRTn1zNTm/Spmk6hVB84LCKOgHqvSF25i0d2kWqpZDzLDdAPbw==",
- "dependencies": {
- "@turf/circle": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/line-arc": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/shortest-path": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/shortest-path/-/shortest-path-6.5.0.tgz",
- "integrity": "sha512-4de5+G7+P4hgSoPwn+SO9QSi9HY5NEV/xRJ+cmoFVRwv2CDsuOPDheHKeuIAhKyeKDvPvPt04XYWbac4insJMg==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/bbox-polygon": "^6.5.0",
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/clean-coords": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/transform-scale": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/simplify": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/simplify/-/simplify-6.5.0.tgz",
- "integrity": "sha512-USas3QqffPHUY184dwQdP8qsvcVH/PWBYdXY5am7YTBACaQOMAlf6AKJs9FT8jiO6fQpxfgxuEtwmox+pBtlOg==",
- "dependencies": {
- "@turf/clean-coords": "^6.5.0",
- "@turf/clone": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/square": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/square/-/square-6.5.0.tgz",
- "integrity": "sha512-BM2UyWDmiuHCadVhHXKIx5CQQbNCpOxB6S/aCNOCLbhCeypKX5Q0Aosc5YcmCJgkwO5BERCC6Ee7NMbNB2vHmQ==",
- "dependencies": {
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/square-grid": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/square-grid/-/square-grid-6.5.0.tgz",
- "integrity": "sha512-mlR0ayUdA+L4c9h7p4k3pX6gPWHNGuZkt2c5II1TJRmhLkW2557d6b/Vjfd1z9OVaajb1HinIs1FMSAPXuuUrA==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/rectangle-grid": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/standard-deviational-ellipse": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/standard-deviational-ellipse/-/standard-deviational-ellipse-6.5.0.tgz",
- "integrity": "sha512-02CAlz8POvGPFK2BKK8uHGUk/LXb0MK459JVjKxLC2yJYieOBTqEbjP0qaWhiBhGzIxSMaqe8WxZ0KvqdnstHA==",
- "dependencies": {
- "@turf/center-mean": "^6.5.0",
- "@turf/ellipse": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/points-within-polygon": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/tag": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/tag/-/tag-6.5.0.tgz",
- "integrity": "sha512-XwlBvrOV38CQsrNfrxvBaAPBQgXMljeU0DV8ExOyGM7/hvuGHJw3y8kKnQ4lmEQcmcrycjDQhP7JqoRv8vFssg==",
- "dependencies": {
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/clone": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/tesselate": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/tesselate/-/tesselate-6.5.0.tgz",
- "integrity": "sha512-M1HXuyZFCfEIIKkglh/r5L9H3c5QTEsnMBoZOFQiRnGPGmJWcaBissGb7mTFX2+DKE7FNWXh4TDnZlaLABB0dQ==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "earcut": "^2.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/tin": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/tin/-/tin-6.5.0.tgz",
- "integrity": "sha512-YLYikRzKisfwj7+F+Tmyy/LE3d2H7D4kajajIfc9mlik2+esG7IolsX/+oUz1biguDYsG0DUA8kVYXDkobukfg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/transform-rotate": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/transform-rotate/-/transform-rotate-6.5.0.tgz",
- "integrity": "sha512-A2Ip1v4246ZmpssxpcL0hhiVBEf4L8lGnSPWTgSv5bWBEoya2fa/0SnFX9xJgP40rMP+ZzRaCN37vLHbv1Guag==",
- "dependencies": {
- "@turf/centroid": "^6.5.0",
- "@turf/clone": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/rhumb-bearing": "^6.5.0",
- "@turf/rhumb-destination": "^6.5.0",
- "@turf/rhumb-distance": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/transform-scale": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/transform-scale/-/transform-scale-6.5.0.tgz",
- "integrity": "sha512-VsATGXC9rYM8qTjbQJ/P7BswKWXHdnSJ35JlV4OsZyHBMxJQHftvmZJsFbOqVtQnIQIzf2OAly6rfzVV9QLr7g==",
- "dependencies": {
- "@turf/bbox": "^6.5.0",
- "@turf/center": "^6.5.0",
- "@turf/centroid": "^6.5.0",
- "@turf/clone": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/rhumb-bearing": "^6.5.0",
- "@turf/rhumb-destination": "^6.5.0",
- "@turf/rhumb-distance": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/transform-translate": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/transform-translate/-/transform-translate-6.5.0.tgz",
- "integrity": "sha512-NABLw5VdtJt/9vSstChp93pc6oel4qXEos56RBMsPlYB8hzNTEKYtC146XJvyF4twJeeYS8RVe1u7KhoFwEM5w==",
- "dependencies": {
- "@turf/clone": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/rhumb-destination": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/triangle-grid": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/triangle-grid/-/triangle-grid-6.5.0.tgz",
- "integrity": "sha512-2jToUSAS1R1htq4TyLQYPTIsoy6wg3e3BQXjm2rANzw4wPQCXGOxrur1Fy9RtzwqwljlC7DF4tg0OnWr8RjmfA==",
- "dependencies": {
- "@turf/distance": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/intersect": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/truncate": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/truncate/-/truncate-6.5.0.tgz",
- "integrity": "sha512-pFxg71pLk+eJj134Z9yUoRhIi8vqnnKvCYwdT4x/DQl/19RVdq1tV3yqOT3gcTQNfniteylL5qV1uTBDV5sgrg==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/turf": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/turf/-/turf-6.5.0.tgz",
- "integrity": "sha512-ipMCPnhu59bh92MNt8+pr1VZQhHVuTMHklciQURo54heoxRzt1neNYZOBR6jdL+hNsbDGAECMuIpAutX+a3Y+w==",
- "dependencies": {
- "@turf/along": "^6.5.0",
- "@turf/angle": "^6.5.0",
- "@turf/area": "^6.5.0",
- "@turf/bbox": "^6.5.0",
- "@turf/bbox-clip": "^6.5.0",
- "@turf/bbox-polygon": "^6.5.0",
- "@turf/bearing": "^6.5.0",
- "@turf/bezier-spline": "^6.5.0",
- "@turf/boolean-clockwise": "^6.5.0",
- "@turf/boolean-contains": "^6.5.0",
- "@turf/boolean-crosses": "^6.5.0",
- "@turf/boolean-disjoint": "^6.5.0",
- "@turf/boolean-equal": "^6.5.0",
- "@turf/boolean-intersects": "^6.5.0",
- "@turf/boolean-overlap": "^6.5.0",
- "@turf/boolean-parallel": "^6.5.0",
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/boolean-point-on-line": "^6.5.0",
- "@turf/boolean-within": "^6.5.0",
- "@turf/buffer": "^6.5.0",
- "@turf/center": "^6.5.0",
- "@turf/center-mean": "^6.5.0",
- "@turf/center-median": "^6.5.0",
- "@turf/center-of-mass": "^6.5.0",
- "@turf/centroid": "^6.5.0",
- "@turf/circle": "^6.5.0",
- "@turf/clean-coords": "^6.5.0",
- "@turf/clone": "^6.5.0",
- "@turf/clusters": "^6.5.0",
- "@turf/clusters-dbscan": "^6.5.0",
- "@turf/clusters-kmeans": "^6.5.0",
- "@turf/collect": "^6.5.0",
- "@turf/combine": "^6.5.0",
- "@turf/concave": "^6.5.0",
- "@turf/convex": "^6.5.0",
- "@turf/destination": "^6.5.0",
- "@turf/difference": "^6.5.0",
- "@turf/dissolve": "^6.5.0",
- "@turf/distance": "^6.5.0",
- "@turf/distance-weight": "^6.5.0",
- "@turf/ellipse": "^6.5.0",
- "@turf/envelope": "^6.5.0",
- "@turf/explode": "^6.5.0",
- "@turf/flatten": "^6.5.0",
- "@turf/flip": "^6.5.0",
- "@turf/great-circle": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/hex-grid": "^6.5.0",
- "@turf/interpolate": "^6.5.0",
- "@turf/intersect": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "@turf/isobands": "^6.5.0",
- "@turf/isolines": "^6.5.0",
- "@turf/kinks": "^6.5.0",
- "@turf/length": "^6.5.0",
- "@turf/line-arc": "^6.5.0",
- "@turf/line-chunk": "^6.5.0",
- "@turf/line-intersect": "^6.5.0",
- "@turf/line-offset": "^6.5.0",
- "@turf/line-overlap": "^6.5.0",
- "@turf/line-segment": "^6.5.0",
- "@turf/line-slice": "^6.5.0",
- "@turf/line-slice-along": "^6.5.0",
- "@turf/line-split": "^6.5.0",
- "@turf/line-to-polygon": "^6.5.0",
- "@turf/mask": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "@turf/midpoint": "^6.5.0",
- "@turf/moran-index": "^6.5.0",
- "@turf/nearest-point": "^6.5.0",
- "@turf/nearest-point-on-line": "^6.5.0",
- "@turf/nearest-point-to-line": "^6.5.0",
- "@turf/planepoint": "^6.5.0",
- "@turf/point-grid": "^6.5.0",
- "@turf/point-on-feature": "^6.5.0",
- "@turf/point-to-line-distance": "^6.5.0",
- "@turf/points-within-polygon": "^6.5.0",
- "@turf/polygon-smooth": "^6.5.0",
- "@turf/polygon-tangents": "^6.5.0",
- "@turf/polygon-to-line": "^6.5.0",
- "@turf/polygonize": "^6.5.0",
- "@turf/projection": "^6.5.0",
- "@turf/random": "^6.5.0",
- "@turf/rewind": "^6.5.0",
- "@turf/rhumb-bearing": "^6.5.0",
- "@turf/rhumb-destination": "^6.5.0",
- "@turf/rhumb-distance": "^6.5.0",
- "@turf/sample": "^6.5.0",
- "@turf/sector": "^6.5.0",
- "@turf/shortest-path": "^6.5.0",
- "@turf/simplify": "^6.5.0",
- "@turf/square": "^6.5.0",
- "@turf/square-grid": "^6.5.0",
- "@turf/standard-deviational-ellipse": "^6.5.0",
- "@turf/tag": "^6.5.0",
- "@turf/tesselate": "^6.5.0",
- "@turf/tin": "^6.5.0",
- "@turf/transform-rotate": "^6.5.0",
- "@turf/transform-scale": "^6.5.0",
- "@turf/transform-translate": "^6.5.0",
- "@turf/triangle-grid": "^6.5.0",
- "@turf/truncate": "^6.5.0",
- "@turf/union": "^6.5.0",
- "@turf/unkink-polygon": "^6.5.0",
- "@turf/voronoi": "^6.5.0"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/union": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/union/-/union-6.5.0.tgz",
- "integrity": "sha512-igYWCwP/f0RFHIlC2c0SKDuM/ObBaqSljI3IdV/x71805QbIvY/BYGcJdyNcgEA6cylIGl/0VSlIbpJHZ9ldhw==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "polygon-clipping": "^0.15.3"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/unkink-polygon": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/unkink-polygon/-/unkink-polygon-6.5.0.tgz",
- "integrity": "sha512-8QswkzC0UqKmN1DT6HpA9upfa1HdAA5n6bbuzHy8NJOX8oVizVAqfEPY0wqqTgboDjmBR4yyImsdPGUl3gZ8JQ==",
- "dependencies": {
- "@turf/area": "^6.5.0",
- "@turf/boolean-point-in-polygon": "^6.5.0",
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0",
- "rbush": "^2.0.1"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@turf/voronoi": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@turf/voronoi/-/voronoi-6.5.0.tgz",
- "integrity": "sha512-C/xUsywYX+7h1UyNqnydHXiun4UPjK88VDghtoRypR9cLlb7qozkiLRphQxxsCM0KxyxpVPHBVQXdAL3+Yurow==",
- "dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/invariant": "^6.5.0",
- "d3-voronoi": "1.1.2"
- },
- "funding": {
- "url": "https://opencollective.com/turf"
- }
- },
- "node_modules/@types/geojson": {
- "version": "7946.0.8",
- "resolved": "https://registry.npmmirror.com/@types/geojson/-/geojson-7946.0.8.tgz",
- "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA=="
- },
- "node_modules/@types/node": {
- "version": "18.19.84",
- "resolved": "https://registry.npmmirror.com/@types/node/-/node-18.19.84.tgz",
- "integrity": "sha512-ACYy2HGcZPHxEeWTqowTF7dhXN+JU1o7Gr4b41klnn6pj2LD6rsiGqSZojMdk1Jh2ys3m76ap+ae1vvE4+5+vg==",
- "dependencies": {
- "undici-types": "~5.26.4"
- }
- },
- "node_modules/@types/node-fetch": {
- "version": "2.6.12",
- "resolved": "https://registry.npmmirror.com/@types/node-fetch/-/node-fetch-2.6.12.tgz",
- "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==",
- "dependencies": {
- "@types/node": "*",
- "form-data": "^4.0.0"
- }
- },
- "node_modules/abbrev": {
- "version": "1.1.1",
- "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz",
- "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
- },
- "node_modules/abort-controller": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/abort-controller/-/abort-controller-3.0.0.tgz",
- "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
- "dependencies": {
- "event-target-shim": "^5.0.0"
- },
- "engines": {
- "node": ">=6.5"
- }
- },
- "node_modules/agent-base": {
- "version": "6.0.2",
- "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz",
- "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
- "dependencies": {
- "debug": "4"
- },
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/agent-base/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/agentkeepalive": {
- "version": "4.6.0",
- "resolved": "https://registry.npmmirror.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
- "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
- "dependencies": {
- "humanize-ms": "^1.2.1"
- },
- "engines": {
- "node": ">= 8.0.0"
- }
- },
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/aproba": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/aproba/-/aproba-2.0.0.tgz",
- "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
- },
- "node_modules/are-we-there-yet": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
- "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
- "deprecated": "This package is no longer supported.",
- "dependencies": {
- "delegates": "^1.0.0",
- "readable-stream": "^3.6.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/call-bind": {
- "version": "1.0.8",
- "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.8.tgz",
- "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.0",
- "es-define-property": "^1.0.0",
- "get-intrinsic": "^1.2.4",
- "set-function-length": "^1.2.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/canvas": {
- "version": "2.11.2",
- "resolved": "https://registry.npmmirror.com/canvas/-/canvas-2.11.2.tgz",
- "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==",
- "hasInstallScript": true,
- "dependencies": {
- "@mapbox/node-pre-gyp": "^1.0.0",
- "nan": "^2.17.0",
- "simple-get": "^3.0.3"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/chownr": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz",
- "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/color": {
- "version": "4.2.3",
- "resolved": "https://registry.npmmirror.com/color/-/color-4.2.3.tgz",
- "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
- "dependencies": {
- "color-convert": "^2.0.1",
- "color-string": "^1.9.0"
- },
- "engines": {
- "node": ">=12.5.0"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
- },
- "node_modules/color-string": {
- "version": "1.9.1",
- "resolved": "https://registry.npmmirror.com/color-string/-/color-string-1.9.1.tgz",
- "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
- "dependencies": {
- "color-name": "^1.0.0",
- "simple-swizzle": "^0.2.2"
- }
- },
- "node_modules/color-support": {
- "version": "1.1.3",
- "resolved": "https://registry.npmmirror.com/color-support/-/color-support-1.1.3.tgz",
- "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
- "bin": {
- "color-support": "bin.js"
- }
- },
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
- },
- "node_modules/concaveman": {
- "version": "1.2.1",
- "resolved": "https://registry.npmmirror.com/concaveman/-/concaveman-1.2.1.tgz",
- "integrity": "sha512-PwZYKaM/ckQSa8peP5JpVr7IMJ4Nn/MHIaWUjP4be+KoZ7Botgs8seAZGpmaOM+UZXawcdYRao/px9ycrCihHw==",
- "dependencies": {
- "point-in-polygon": "^1.1.0",
- "rbush": "^3.0.1",
- "robust-predicates": "^2.0.4",
- "tinyqueue": "^2.0.3"
- }
- },
- "node_modules/concaveman/node_modules/quickselect": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/quickselect/-/quickselect-2.0.0.tgz",
- "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="
- },
- "node_modules/concaveman/node_modules/rbush": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/rbush/-/rbush-3.0.1.tgz",
- "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==",
- "dependencies": {
- "quickselect": "^2.0.0"
- }
- },
- "node_modules/console-control-strings": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/console-control-strings/-/console-control-strings-1.1.0.tgz",
- "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
- },
- "node_modules/d3-array": {
- "version": "1.2.4",
- "resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-1.2.4.tgz",
- "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
- },
- "node_modules/d3-geo": {
- "version": "1.7.1",
- "resolved": "https://registry.npmmirror.com/d3-geo/-/d3-geo-1.7.1.tgz",
- "integrity": "sha512-O4AempWAr+P5qbk2bC2FuN/sDW4z+dN2wDf9QV3bxQt4M5HfOEeXLgJ/UKQW0+o1Dj8BE+L5kiDbdWUMjsmQpw==",
- "dependencies": {
- "d3-array": "1"
- }
- },
- "node_modules/d3-voronoi": {
- "version": "1.1.2",
- "resolved": "https://registry.npmmirror.com/d3-voronoi/-/d3-voronoi-1.1.2.tgz",
- "integrity": "sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw=="
- },
- "node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/decompress-response": {
- "version": "4.2.1",
- "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-4.2.1.tgz",
- "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
- "dependencies": {
- "mimic-response": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/deep-equal": {
- "version": "1.1.2",
- "resolved": "https://registry.npmmirror.com/deep-equal/-/deep-equal-1.1.2.tgz",
- "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
- "dependencies": {
- "is-arguments": "^1.1.1",
- "is-date-object": "^1.0.5",
- "is-regex": "^1.1.4",
- "object-is": "^1.1.5",
- "object-keys": "^1.1.1",
- "regexp.prototype.flags": "^1.5.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/define-data-property": {
- "version": "1.1.4",
- "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz",
- "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
- "dependencies": {
- "es-define-property": "^1.0.0",
- "es-errors": "^1.3.0",
- "gopd": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/define-properties": {
- "version": "1.2.1",
- "resolved": "https://registry.npmmirror.com/define-properties/-/define-properties-1.2.1.tgz",
- "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
- "dependencies": {
- "define-data-property": "^1.0.1",
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/delegates": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/delegates/-/delegates-1.0.0.tgz",
- "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
- },
- "node_modules/density-clustering": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/density-clustering/-/density-clustering-1.3.0.tgz",
- "integrity": "sha512-icpmBubVTwLnsaor9qH/4tG5+7+f61VcqMN3V3pm9sxxSCt2Jcs0zWOgwZW9ARJYaKD3FumIgHiMOcIMRRAzFQ=="
- },
- "node_modules/detect-libc": {
- "version": "2.0.3",
- "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.0.3.tgz",
- "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/dommatrix": {
- "version": "0.0.24",
- "resolved": "https://registry.npmmirror.com/dommatrix/-/dommatrix-0.0.24.tgz",
- "integrity": "sha512-PatEhAW5pIHr28MvFQGV5iiHNloqvecQZlxs7/8s/eulLqZI3uVqPkrO7YDuqsebovr/9mmcWDSWzVG4amEZgQ=="
- },
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/earcut": {
- "version": "2.2.4",
- "resolved": "https://registry.npmmirror.com/earcut/-/earcut-2.2.4.tgz",
- "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ=="
- },
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
- },
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-set-tostringtag": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
- "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
- "dependencies": {
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/event-target-shim": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/event-target-shim/-/event-target-shim-5.0.1.tgz",
- "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/form-data": {
- "version": "4.0.2",
- "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.2.tgz",
- "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "es-set-tostringtag": "^2.1.0",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/form-data-encoder": {
- "version": "1.7.2",
- "resolved": "https://registry.npmmirror.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
- "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="
- },
- "node_modules/formdata-node": {
- "version": "4.4.1",
- "resolved": "https://registry.npmmirror.com/formdata-node/-/formdata-node-4.4.1.tgz",
- "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
- "dependencies": {
- "node-domexception": "1.0.0",
- "web-streams-polyfill": "4.0.0-beta.3"
- },
- "engines": {
- "node": ">= 12.20"
- }
- },
- "node_modules/fs-extra": {
- "version": "11.3.0",
- "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.0.tgz",
- "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=14.14"
- }
- },
- "node_modules/fs-minipass": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz",
- "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/fs-minipass/node_modules/minipass": {
- "version": "3.3.6",
- "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz",
- "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/functions-have-names": {
- "version": "1.2.3",
- "resolved": "https://registry.npmmirror.com/functions-have-names/-/functions-have-names-1.2.3.tgz",
- "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gauge": {
- "version": "3.0.2",
- "resolved": "https://registry.npmmirror.com/gauge/-/gauge-3.0.2.tgz",
- "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
- "deprecated": "This package is no longer supported.",
- "dependencies": {
- "aproba": "^1.0.3 || ^2.0.0",
- "color-support": "^1.1.2",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.1",
- "object-assign": "^4.1.1",
- "signal-exit": "^3.0.0",
- "string-width": "^4.2.3",
- "strip-ansi": "^6.0.1",
- "wide-align": "^1.1.2"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/geojson-equality": {
- "version": "0.1.6",
- "resolved": "https://registry.npmmirror.com/geojson-equality/-/geojson-equality-0.1.6.tgz",
- "integrity": "sha512-TqG8YbqizP3EfwP5Uw4aLu6pKkg6JQK9uq/XZ1lXQntvTHD1BBKJWhNpJ2M0ax6TuWMP3oyx6Oq7FCIfznrgpQ==",
- "dependencies": {
- "deep-equal": "^1.0.0"
- }
- },
- "node_modules/geojson-rbush": {
- "version": "3.2.0",
- "resolved": "https://registry.npmmirror.com/geojson-rbush/-/geojson-rbush-3.2.0.tgz",
- "integrity": "sha512-oVltQTXolxvsz1sZnutlSuLDEcQAKYC/uXt9zDzJJ6bu0W+baTI8LZBaTup5afzibEH4N3jlq2p+a152wlBJ7w==",
- "dependencies": {
- "@turf/bbox": "*",
- "@turf/helpers": "6.x",
- "@turf/meta": "6.x",
- "@types/geojson": "7946.0.8",
- "rbush": "^3.0.1"
- }
- },
- "node_modules/geojson-rbush/node_modules/quickselect": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/quickselect/-/quickselect-2.0.0.tgz",
- "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="
- },
- "node_modules/geojson-rbush/node_modules/rbush": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/rbush/-/rbush-3.0.1.tgz",
- "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==",
- "dependencies": {
- "quickselect": "^2.0.0"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
- },
- "node_modules/has-property-descriptors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
- "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
- "dependencies": {
- "es-define-property": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-tostringtag": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
- "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
- "dependencies": {
- "has-symbols": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-unicode": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/has-unicode/-/has-unicode-2.0.1.tgz",
- "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
- },
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/https-proxy-agent": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
- "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
- "dependencies": {
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/https-proxy-agent/node_modules/debug": {
- "version": "4.4.0",
- "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/humanize-ms": {
- "version": "1.2.1",
- "resolved": "https://registry.npmmirror.com/humanize-ms/-/humanize-ms-1.2.1.tgz",
- "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
- "dependencies": {
- "ms": "^2.0.0"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- },
- "node_modules/is-arguments": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/is-arguments/-/is-arguments-1.2.0.tgz",
- "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
- "dependencies": {
- "call-bound": "^1.0.2",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-arrayish": {
- "version": "0.3.2",
- "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.3.2.tgz",
- "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
- },
- "node_modules/is-date-object": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/is-date-object/-/is-date-object-1.1.0.tgz",
- "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
- "dependencies": {
- "call-bound": "^1.0.2",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-regex": {
- "version": "1.2.1",
- "resolved": "https://registry.npmmirror.com/is-regex/-/is-regex-1.2.1.tgz",
- "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
- "dependencies": {
- "call-bound": "^1.0.2",
- "gopd": "^1.2.0",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/make-dir": {
- "version": "3.1.0",
- "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-3.1.0.tgz",
- "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
- "dependencies": {
- "semver": "^6.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/make-dir/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/math-intrinsics": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
- "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mimic-response": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-2.1.0.tgz",
- "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/minipass": {
- "version": "5.0.0",
- "resolved": "https://registry.npmmirror.com/minipass/-/minipass-5.0.0.tgz",
- "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minizlib": {
- "version": "2.1.2",
- "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz",
- "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
- "dependencies": {
- "minipass": "^3.0.0",
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/minizlib/node_modules/minipass": {
- "version": "3.3.6",
- "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz",
- "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/nan": {
- "version": "2.22.2",
- "resolved": "https://registry.npmmirror.com/nan/-/nan-2.22.2.tgz",
- "integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ=="
- },
- "node_modules/node-domexception": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/node-domexception/-/node-domexception-1.0.0.tgz",
- "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "github",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
- "engines": {
- "node": ">=10.5.0"
- }
- },
- "node_modules/node-ensure": {
- "version": "0.0.0",
- "resolved": "https://registry.npmmirror.com/node-ensure/-/node-ensure-0.0.0.tgz",
- "integrity": "sha512-DRI60hzo2oKN1ma0ckc6nQWlHU69RH6xN0sjQTjMpChPfTYvKZdcQFfdYK2RWbJcKyUizSIy/l8OTGxMAM1QDw=="
- },
- "node_modules/node-fetch": {
- "version": "2.7.0",
- "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz",
- "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
- "dependencies": {
- "whatwg-url": "^5.0.0"
- },
- "engines": {
- "node": "4.x || >=6.0.0"
- },
- "peerDependencies": {
- "encoding": "^0.1.0"
- },
- "peerDependenciesMeta": {
- "encoding": {
- "optional": true
- }
- }
- },
- "node_modules/nopt": {
- "version": "5.0.0",
- "resolved": "https://registry.npmmirror.com/nopt/-/nopt-5.0.0.tgz",
- "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
- "dependencies": {
- "abbrev": "1"
- },
- "bin": {
- "nopt": "bin/nopt.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/npmlog": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/npmlog/-/npmlog-5.0.1.tgz",
- "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
- "deprecated": "This package is no longer supported.",
- "dependencies": {
- "are-we-there-yet": "^2.0.0",
- "console-control-strings": "^1.1.0",
- "gauge": "^3.0.0",
- "set-blocking": "^2.0.0"
- }
- },
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-is": {
- "version": "1.1.6",
- "resolved": "https://registry.npmmirror.com/object-is/-/object-is-1.1.6.tgz",
- "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
- "dependencies": {
- "call-bind": "^1.0.7",
- "define-properties": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmmirror.com/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/openai": {
- "version": "4.90.0",
- "resolved": "https://registry.npmmirror.com/openai/-/openai-4.90.0.tgz",
- "integrity": "sha512-YCuHMMycqtCg1B8G9ezkOF0j8UnBWD3Al/zYaelpuXwU1yhCEv+Y4n9G20MnyGy6cH4GsFwOMrgstQ+bgG1PtA==",
- "dependencies": {
- "@types/node": "^18.11.18",
- "@types/node-fetch": "^2.6.4",
- "abort-controller": "^3.0.0",
- "agentkeepalive": "^4.2.1",
- "form-data-encoder": "1.7.2",
- "formdata-node": "^4.3.2",
- "node-fetch": "^2.6.7"
- },
- "bin": {
- "openai": "bin/cli"
- },
- "peerDependencies": {
- "ws": "^8.18.0",
- "zod": "^3.23.8"
- },
- "peerDependenciesMeta": {
- "ws": {
- "optional": true
- },
- "zod": {
- "optional": true
- }
- }
- },
- "node_modules/pako": {
- "version": "1.0.11",
- "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz",
- "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path2d-polyfill": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz",
- "integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==",
- "optional": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/pdf-lib": {
- "version": "1.17.1",
- "resolved": "https://registry.npmmirror.com/pdf-lib/-/pdf-lib-1.17.1.tgz",
- "integrity": "sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==",
- "dependencies": {
- "@pdf-lib/standard-fonts": "^1.0.0",
- "@pdf-lib/upng": "^1.0.1",
- "pako": "^1.0.11",
- "tslib": "^1.11.1"
- }
- },
- "node_modules/pdf-parse": {
- "version": "1.1.1",
- "resolved": "https://registry.npmmirror.com/pdf-parse/-/pdf-parse-1.1.1.tgz",
- "integrity": "sha512-v6ZJ/efsBpGrGGknjtq9J/oC8tZWq0KWL5vQrk2GlzLEQPUDB1ex+13Rmidl1neNN358Jn9EHZw5y07FFtaC7A==",
- "dependencies": {
- "debug": "^3.1.0",
- "node-ensure": "^0.0.0"
- },
- "engines": {
- "node": ">=6.8.1"
- }
- },
- "node_modules/pdf.js-extract": {
- "version": "0.2.1",
- "resolved": "https://registry.npmmirror.com/pdf.js-extract/-/pdf.js-extract-0.2.1.tgz",
- "integrity": "sha512-oUs5KaTVCelIyiBajCx3zAZKurkN9oVwRdqbSeDqeofddxNuwJRur86fCETvKZ/tX5nZJUSZWq3ie76PsArz7A==",
- "dependencies": {
- "dommatrix": "0.0.24",
- "web-streams-polyfill": "3.2.0"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/pdf.js-extract/node_modules/web-streams-polyfill": {
- "version": "3.2.0",
- "resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz",
- "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/pdfjs-dist": {
- "version": "3.11.174",
- "resolved": "https://registry.npmmirror.com/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz",
- "integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==",
- "engines": {
- "node": ">=18"
- },
- "optionalDependencies": {
- "canvas": "^2.11.2",
- "path2d-polyfill": "^2.0.1"
- }
- },
- "node_modules/point-in-polygon": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/point-in-polygon/-/point-in-polygon-1.1.0.tgz",
- "integrity": "sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw=="
- },
- "node_modules/polygon-clipping": {
- "version": "0.15.7",
- "resolved": "https://registry.npmmirror.com/polygon-clipping/-/polygon-clipping-0.15.7.tgz",
- "integrity": "sha512-nhfdr83ECBg6xtqOAJab1tbksbBAOMUltN60bU+llHVOL0e5Onm1WpAXXWXVB39L8AJFssoIhEVuy/S90MmotA==",
- "dependencies": {
- "robust-predicates": "^3.0.2",
- "splaytree": "^3.1.0"
- }
- },
- "node_modules/polygon-clipping/node_modules/robust-predicates": {
- "version": "3.0.2",
- "resolved": "https://registry.npmmirror.com/robust-predicates/-/robust-predicates-3.0.2.tgz",
- "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg=="
- },
- "node_modules/quickselect": {
- "version": "1.1.1",
- "resolved": "https://registry.npmmirror.com/quickselect/-/quickselect-1.1.1.tgz",
- "integrity": "sha512-qN0Gqdw4c4KGPsBOQafj6yj/PA6c/L63f6CaZ/DCF/xF4Esu3jVmKLUDYxghFx8Kb/O7y9tI7x2RjTSXwdK1iQ=="
- },
- "node_modules/rbush": {
- "version": "2.0.2",
- "resolved": "https://registry.npmmirror.com/rbush/-/rbush-2.0.2.tgz",
- "integrity": "sha512-XBOuALcTm+O/H8G90b6pzu6nX6v2zCKiFG4BJho8a+bY6AER6t8uQUZdi5bomQc0AprCWhEGa7ncAbbRap0bRA==",
- "dependencies": {
- "quickselect": "^1.0.1"
- }
- },
- "node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/regexp.prototype.flags": {
- "version": "1.5.4",
- "resolved": "https://registry.npmmirror.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
- "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
- "dependencies": {
- "call-bind": "^1.0.8",
- "define-properties": "^1.2.1",
- "es-errors": "^1.3.0",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "set-function-name": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/robust-predicates": {
- "version": "2.0.4",
- "resolved": "https://registry.npmmirror.com/robust-predicates/-/robust-predicates-2.0.4.tgz",
- "integrity": "sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg=="
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/semver": {
- "version": "7.7.1",
- "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.1.tgz",
- "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
- },
- "node_modules/set-function-length": {
- "version": "1.2.2",
- "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz",
- "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
- "dependencies": {
- "define-data-property": "^1.1.4",
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.4",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/set-function-name": {
- "version": "2.0.2",
- "resolved": "https://registry.npmmirror.com/set-function-name/-/set-function-name-2.0.2.tgz",
- "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
- "dependencies": {
- "define-data-property": "^1.1.4",
- "es-errors": "^1.3.0",
- "functions-have-names": "^1.2.3",
- "has-property-descriptors": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/sharp": {
- "version": "0.33.5",
- "resolved": "https://registry.npmmirror.com/sharp/-/sharp-0.33.5.tgz",
- "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
- "hasInstallScript": true,
- "dependencies": {
- "color": "^4.2.3",
- "detect-libc": "^2.0.3",
- "semver": "^7.6.3"
- },
- "engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/libvips"
- },
- "optionalDependencies": {
- "@img/sharp-darwin-arm64": "0.33.5",
- "@img/sharp-darwin-x64": "0.33.5",
- "@img/sharp-libvips-darwin-arm64": "1.0.4",
- "@img/sharp-libvips-darwin-x64": "1.0.4",
- "@img/sharp-libvips-linux-arm": "1.0.5",
- "@img/sharp-libvips-linux-arm64": "1.0.4",
- "@img/sharp-libvips-linux-s390x": "1.0.4",
- "@img/sharp-libvips-linux-x64": "1.0.4",
- "@img/sharp-libvips-linuxmusl-arm64": "1.0.4",
- "@img/sharp-libvips-linuxmusl-x64": "1.0.4",
- "@img/sharp-linux-arm": "0.33.5",
- "@img/sharp-linux-arm64": "0.33.5",
- "@img/sharp-linux-s390x": "0.33.5",
- "@img/sharp-linux-x64": "0.33.5",
- "@img/sharp-linuxmusl-arm64": "0.33.5",
- "@img/sharp-linuxmusl-x64": "0.33.5",
- "@img/sharp-wasm32": "0.33.5",
- "@img/sharp-win32-ia32": "0.33.5",
- "@img/sharp-win32-x64": "0.33.5"
- }
- },
- "node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
- },
- "node_modules/simple-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz",
- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/simple-get": {
- "version": "3.1.1",
- "resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-3.1.1.tgz",
- "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
- "dependencies": {
- "decompress-response": "^4.2.0",
- "once": "^1.3.1",
- "simple-concat": "^1.0.0"
- }
- },
- "node_modules/simple-swizzle": {
- "version": "0.2.2",
- "resolved": "https://registry.npmmirror.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
- "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
- "dependencies": {
- "is-arrayish": "^0.3.1"
- }
- },
- "node_modules/skmeans": {
- "version": "0.9.7",
- "resolved": "https://registry.npmmirror.com/skmeans/-/skmeans-0.9.7.tgz",
- "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg=="
- },
- "node_modules/splaytree": {
- "version": "3.1.2",
- "resolved": "https://registry.npmmirror.com/splaytree/-/splaytree-3.1.2.tgz",
- "integrity": "sha512-4OM2BJgC5UzrhVnnJA4BkHKGtjXNzzUfpQjCO8I05xYPsfS/VuQDwjCGGMi8rYQilHEV4j8NBqTFbls/PZEE7A=="
- },
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
- "node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/tar": {
- "version": "6.2.1",
- "resolved": "https://registry.npmmirror.com/tar/-/tar-6.2.1.tgz",
- "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
- "dependencies": {
- "chownr": "^2.0.0",
- "fs-minipass": "^2.0.0",
- "minipass": "^5.0.0",
- "minizlib": "^2.1.1",
- "mkdirp": "^1.0.3",
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/tinyqueue": {
- "version": "2.0.3",
- "resolved": "https://registry.npmmirror.com/tinyqueue/-/tinyqueue-2.0.3.tgz",
- "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA=="
- },
- "node_modules/topojson-client": {
- "version": "3.1.0",
- "resolved": "https://registry.npmmirror.com/topojson-client/-/topojson-client-3.1.0.tgz",
- "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==",
- "dependencies": {
- "commander": "2"
- },
- "bin": {
- "topo2geo": "bin/topo2geo",
- "topomerge": "bin/topomerge",
- "topoquantize": "bin/topoquantize"
- }
- },
- "node_modules/topojson-server": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/topojson-server/-/topojson-server-3.0.1.tgz",
- "integrity": "sha512-/VS9j/ffKr2XAOjlZ9CgyyeLmgJ9dMwq6Y0YEON8O7p/tGGk+dCWnrE03zEdu7i4L7YsFZLEPZPzCvcB7lEEXw==",
- "dependencies": {
- "commander": "2"
- },
- "bin": {
- "geo2topo": "bin/geo2topo"
- }
- },
- "node_modules/tr46": {
- "version": "0.0.3",
- "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
- },
- "node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/turf-jsts": {
- "version": "1.2.3",
- "resolved": "https://registry.npmmirror.com/turf-jsts/-/turf-jsts-1.2.3.tgz",
- "integrity": "sha512-Ja03QIJlPuHt4IQ2FfGex4F4JAr8m3jpaHbFbQrgwr7s7L6U8ocrHiF3J1+wf9jzhGKxvDeaCAnGDot8OjGFyA=="
- },
- "node_modules/undici-types": {
- "version": "5.26.5",
- "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz",
- "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
- },
- "node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
- },
- "node_modules/web-streams-polyfill": {
- "version": "4.0.0-beta.3",
- "resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
- "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/webidl-conversions": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
- },
- "node_modules/whatwg-url": {
- "version": "5.0.0",
- "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz",
- "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "dependencies": {
- "tr46": "~0.0.3",
- "webidl-conversions": "^3.0.0"
- }
- },
- "node_modules/wide-align": {
- "version": "1.1.5",
- "resolved": "https://registry.npmmirror.com/wide-align/-/wide-align-1.1.5.tgz",
- "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
- "dependencies": {
- "string-width": "^1.0.2 || 2 || 3 || 4"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
- },
- "node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
- }
- }
-}
diff --git a/package.json b/package.json
index ecd225b..f7bbd67 100644
--- a/package.json
+++ b/package.json
@@ -1,30 +1,13 @@
{
- "name": "pdf2md-js",
- "version": "1.0.2",
- "description": "Convert PDF to Markdown using Node.js",
- "main": "src/index.js",
- "type": "module",
"scripts": {
- "start": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
- "keywords": [
- "pdf",
- "markdown",
- "converter",
- "ocr"
- ],
- "author": "",
"license": "MIT",
- "dependencies": {
- "@turf/turf": "^6.5.0",
- "canvas": "^2.11.2",
- "fs-extra": "^11.1.1",
- "openai": "^4.28.0",
- "pdf-lib": "^1.17.1",
- "pdf-parse": "^1.1.1",
- "pdf.js-extract": "^0.2.1",
- "pdfjs-dist": "^3.11.174",
- "sharp": "^0.33.1"
+ "packageManager": "pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531",
+ "devDependencies": {
+ "@rslib/core": "^0.6.4",
+ "@types/node": "^22.14.1",
+ "prettier": "^3.5.3",
+ "typescript": "^5.8.3"
}
-}
\ No newline at end of file
+}
diff --git a/packages/mcp/package.json b/packages/mcp/package.json
new file mode 100644
index 0000000..86f2ee3
--- /dev/null
+++ b/packages/mcp/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "@tiny-tool/pdf2md-mcp",
+ "version": "2.0.0",
+ "bin": "dist/index.js",
+ "repository": {
+ "url": "https://github.com/tiny-tool/pdf2md"
+ },
+ "scripts": {
+ "build": "rslib build",
+ "build:watch": "rslib build --watch"
+ },
+ "author": "muzea ",
+ "license": "MIT",
+ "dependencies": {
+ "@modelcontextprotocol/sdk": "^1.9.0",
+ "@tiny-tool/pdf2md": "workspace:*",
+ "express": "^5.1.0",
+ "zod": "^3.24.3",
+ "zod-to-json-schema": "^3.24.5"
+ },
+ "devDependencies": {
+ "@types/express": "^5.0.1"
+ },
+ "publishConfig": {
+ "access": "public",
+ "provenance": true
+ }
+}
diff --git a/packages/mcp/rslib.config.ts b/packages/mcp/rslib.config.ts
new file mode 100644
index 0000000..0cc25e1
--- /dev/null
+++ b/packages/mcp/rslib.config.ts
@@ -0,0 +1,15 @@
+import { defineConfig } from '@rslib/core';
+
+export default defineConfig({
+ lib: [
+ {
+ syntax: ['node 20'],
+ format: 'cjs',
+ },
+ ],
+ source: {
+ entry: {
+ index: './src/index.ts',
+ },
+ },
+});
diff --git a/packages/mcp/src/index.ts b/packages/mcp/src/index.ts
new file mode 100644
index 0000000..d5b7251
--- /dev/null
+++ b/packages/mcp/src/index.ts
@@ -0,0 +1,153 @@
+#!/usr/bin/env node
+
+import { Server } from '@modelcontextprotocol/sdk/server/index.js';
+import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
+import { CallToolRequestSchema, ListToolsRequestSchema, ToolSchema } from '@modelcontextprotocol/sdk/types.js';
+import { z } from 'zod';
+import { zodToJsonSchema } from 'zod-to-json-schema';
+import express from 'express';
+import fs from 'node:fs/promises';
+import { parsePdf } from '@tiny-tool/pdf2md';
+
+/**
+ * Reads a file from the specified path.
+ *
+ *
+ * @TODO read file from various protocols, such as http, https, ftp, etc.
+ * @param filePath
+ * @returns The content of the file as a Buffer.
+ */
+async function readFile(filePath: string) {
+ try {
+ const data = await fs.readFile(filePath);
+ return data;
+ } catch (error) {
+ console.error(`Error reading file ${filePath}:`, error);
+ throw error;
+ }
+}
+
+// Server setup
+const server = new Server(
+ {
+ name: '@tiny-tool/pdf2md-mcp',
+ version: '2.0.0',
+ },
+ {
+ capabilities: {
+ tools: {},
+ },
+ },
+);
+
+const ToolInputSchema = ToolSchema.shape.inputSchema;
+type ToolInput = z.infer;
+
+const ConvertSchema = z.object({
+ file_path: z.string(),
+});
+
+// Tool handlers
+server.setRequestHandler(ListToolsRequestSchema, async () => {
+ return {
+ tools: [
+ {
+ name: 'pdf2md',
+ description: 'Convert PDF files to Markdown format, extract text content from the document',
+ inputSchema: zodToJsonSchema(ConvertSchema) as ToolInput,
+ },
+ ],
+ };
+});
+
+server.setRequestHandler(CallToolRequestSchema, async (request) => {
+ try {
+ const { name, arguments: args } = request.params;
+
+ switch (name) {
+ case 'pdf2md': {
+ const parsed = ConvertSchema.safeParse(args);
+ if (!parsed.success) {
+ throw new Error(`Invalid arguments for pdf2md: ${parsed.error}`);
+ }
+
+ console.log('pdf2md called with args:', parsed.data);
+
+ // const parsedResult = await parsePdf(
+ // parsed.data.file_path,
+ // {
+ // apiKey: '',
+ // baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1/',
+ // model: 'qwen2.5-vl-72b-instruct',
+ // },
+ // { scale: 2, concurrency: 1 },
+ // );
+ const parsedResult = await parsePdf(
+ parsed.data.file_path,
+ {
+ baseURL: 'http://localhost:11434/v1/',
+ model: 'gemma3:12b',
+ },
+ { scale: 1, concurrency: 1 },
+ );
+ return {
+ content: [{ type: 'text', text: parsedResult.content }],
+ };
+ }
+
+ default:
+ throw new Error(`Unknown tool: ${name}`);
+ }
+ } catch (error) {
+ const errorMessage = error instanceof Error ? error.message : String(error);
+ return {
+ content: [{ type: 'text', text: `Error: ${errorMessage}` }],
+ isError: true,
+ };
+ }
+});
+
+const connections = new Map();
+
+const app = express();
+app.get('/sse', async (req, res) => {
+ const transport = new SSEServerTransport('/messages', res);
+
+ const sessionId = transport.sessionId;
+ console.log(`[${new Date().toISOString()}] 新的SSE连接建立: ${sessionId}`);
+ connections.set(sessionId, transport);
+
+ req.on('close', () => {
+ console.log(`[${new Date().toISOString()}] SSE连接关闭: ${sessionId}`);
+ connections.delete(sessionId);
+ });
+
+ // 将传输对象与MCP服务器连接
+ await server.connect(transport);
+ console.log(`[${new Date().toISOString()}] MCP服务器连接成功: ${sessionId}`);
+});
+
+app.post('/messages', async (req, res) => {
+ try {
+ console.log(`[${new Date().toISOString()}] 收到客户端消息:`, req.query);
+ const sessionId = req.query.sessionId as string;
+
+ // 查找对应的SSE连接并处理消息
+ if (connections.size > 0) {
+ const transport: SSEServerTransport = connections.get(sessionId) as SSEServerTransport;
+ // 使用transport处理消息
+ if (transport) {
+ await transport.handlePostMessage(req, res);
+ } else {
+ throw new Error('没有活跃的SSE连接');
+ }
+ } else {
+ throw new Error('没有活跃的SSE连接');
+ }
+ } catch (error: any) {
+ console.error(`[${new Date().toISOString()}] 处理客户端消息失败:`, error);
+ res.status(500).json({ error: '处理消息失败', message: error.message });
+ }
+});
+
+app.listen(3002);
diff --git a/packages/mcp/tsconfig.json b/packages/mcp/tsconfig.json
new file mode 100644
index 0000000..276fda8
--- /dev/null
+++ b/packages/mcp/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "lib": ["DOM", "ES2020"],
+ "module": "NodeNext",
+ "strict": true,
+ "noEmit": true,
+ "moduleResolution": "nodenext",
+ "skipLibCheck": true,
+ "isolatedModules": true,
+ "useDefineForClassFields": true,
+ "allowImportingTsExtensions": true,
+ "allowSyntheticDefaultImports": true,
+ "allowJs": true
+ },
+ "include": ["src"]
+}
diff --git a/packages/pdf2md/package.json b/packages/pdf2md/package.json
new file mode 100644
index 0000000..4854a85
--- /dev/null
+++ b/packages/pdf2md/package.json
@@ -0,0 +1,50 @@
+{
+ "name": "@tiny-tool/pdf2md",
+ "version": "2.0.0",
+ "repository": {
+ "url": "https://github.com/tiny-tool/pdf2md"
+ },
+ "description": "Convert PDF to Markdown using Node.js",
+ "main": "./dist/index.js",
+ "module": "./dist/index.mjs",
+ "types": "./dist/index.d.ts",
+ "exports": {
+ ".": {
+ "require": "./dist/index.js",
+ "import": "./dist/index.mjs",
+ "types": "./dist/index.d.ts"
+ }
+ },
+ "scripts": {
+ "build": "rslib build",
+ "build:watch": "rslib build --watch"
+ },
+ "keywords": [
+ "pdf",
+ "markdown",
+ "converter",
+ "ocr"
+ ],
+ "author": "muzea ",
+ "license": "MIT",
+ "dependencies": {
+ "@napi-rs/canvas": "^0.1.69",
+ "@xsai/generate-text": "0.2.0-beta.3",
+ "fs-extra": "^11.3.0",
+ "pdfjs-dist": "^5.1.91"
+ },
+ "devDependencies": {
+ "@types/fs-extra": "^11.0.4",
+ "@xsai/shared-chat": "0.2.0-beta.3"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "files": [
+ "dist/*"
+ ],
+ "publishConfig": {
+ "access": "public",
+ "provenance": true
+ }
+}
diff --git a/packages/pdf2md/rslib.config.ts b/packages/pdf2md/rslib.config.ts
new file mode 100644
index 0000000..88a4cfa
--- /dev/null
+++ b/packages/pdf2md/rslib.config.ts
@@ -0,0 +1,20 @@
+import { defineConfig } from '@rslib/core';
+
+export default defineConfig({
+ lib: [
+ {
+ syntax: ['node 20'],
+ format: 'cjs',
+ },
+ {
+ syntax: ['node 20'],
+ format: 'esm',
+ dts: true,
+ },
+ ],
+ source: {
+ entry: {
+ index: './src/index.ts',
+ },
+ },
+});
diff --git a/packages/pdf2md/src/const.ts b/packages/pdf2md/src/const.ts
new file mode 100644
index 0000000..3546aee
--- /dev/null
+++ b/packages/pdf2md/src/const.ts
@@ -0,0 +1,59 @@
+export const DefaultPrompt = `使用markdown语法,将图片中识别到的文字转换为markdown格式输出。你必须做到:
+1. 输出和使用识别到的图片的相同的语言,例如,识别到英语的字段,输出的内容必须是英语。
+2. 不要解释和输出无关的文字,直接输出图片中的内容。
+3. 内容不要包含在\`\`\`markdown \`\`\`中、段落公式使用 $$ $$ 的形式、行内公式使用 $ $ 的形式。
+4. 忽略掉页眉页脚里的内容
+5. 请不要对图片的标题进行markdown的格式化,直接以文本形式输出到内容中。
+6. 有可能每页都会出现期刊名称,论文名称,会议名称或者书籍名称,请忽略他们不要识别成标题
+7. 请精确分析当前PDF页面的文本结构和视觉布局,按以下要求处理:
+ 1. 识别所有标题文本,并判断其层级(根据字体大小、加粗、位置等视觉特征)
+ 2. 输出为带层级的Markdown格式,严格使用以下规则:
+ - 一级标题:字体最大/顶部居中,前面加 #
+ - 二级标题:字体较大/左对齐加粗,有可能是数字开头也有可能是罗马数组开头,前面加 ##
+ - 三级标题:字体稍大/左对齐加粗,前面加 ###
+ - 正文文本:直接转换为普通段落
+ 3. 不确定层级的标题请标记[?]
+ 4. 如果是中文文献,但是有英文标题和摘要可以省略不输出
+
+
+示例输出:
+
+## 4研究方法
+### 4.1数据收集
+本文采用问卷调查...
+`;
+
+export const DefaultTextPrompt = `你是一个专业的文本结构化处理助手,擅长根据前缀规则和标题语义分析并优化Markdown文档的标题层级结构。请根据以下要求处理我提供的Markdown标题:
+## 任务描述
+请根据markdown文章标题的实际含义,以及标题的前缀特征调整各级标题的正确层级关系,具体要求如下:
+1. 一般相同格式的前缀的标题是同级关系({title}代表实际的标题内容):
+ 例如:
+ 纯数字前缀开头\`1 {title}\`, \` 2 {title}\` ,\` 3 {title}\`,\` 4 {title}\`,\` 5 {title}\` ... 等
+ 罗马数字前缀开头的\`I {title}\`,\`II {title}\` ,\`III {title}\`,\`IV {title}\`,\`V {title}\` ... 等
+ 小数点分隔数组前缀开头 \`1.1 {title}\`, \`1.2 {title}\`, \`1.3 {title}\`.... \`2.1 {title}\`, \`2.2 {title}\` 等
+2. 将子标题正确嵌套到父标题下(如\`1.1 {title}\`应作为\`1 {title}\`的子标题)
+3. 剔除与文章内容无关的标题
+4. 保持输出标题内容与输入完全一致
+5. 确保内容无缺失
+6. 如果是中文文献,但有英文的文章题目,可以省略
+
+## 输入输出格式
+- 输入:包含错误层级关系的markdown标题结构
+- 输出:修正后的标准markdown标题层级结构
+
+## 处理原则
+1. 严格根据标题语义确定所属关系
+2. 仅调整层级不修改原标题文本
+3. 无关标题直接移除不保留占位
+4. 相同前缀规则的标题必须是同一级别,不能出现 一部分是 n级标题,一部分是其他级别的标题
+
+## 输出要求
+请将修正后的完整标题结构放在代码块中返回,格式示例如下:
+
+期望输出:
+ \`\`\`markdown
+
+ \`\`\`
+
+请处理以下数据:
+`;
diff --git a/packages/pdf2md/src/image-generator.ts b/packages/pdf2md/src/image-generator.ts
new file mode 100644
index 0000000..1662880
--- /dev/null
+++ b/packages/pdf2md/src/image-generator.ts
@@ -0,0 +1,71 @@
+/**
+ * 图像生成模块,负责将PDF区域转换为图像
+ */
+import { getDocument } from 'pdfjs-dist/legacy/build/pdf.mjs';
+import type { PageViewport } from 'pdfjs-dist/types/src/display/display_utils.d.ts';
+import type { PDFPageProxy, PDFDocumentProxy } from 'pdfjs-dist/types/src/display/api.d.ts';
+import fs from 'fs-extra';
+import { createCanvas, Canvas } from '@napi-rs/canvas';
+
+// 定义一些类型
+export type PageImage = { index: number; data: Buffer };
+
+/**
+ * 直接生成PDF文档的所有页面图像,不依赖区域识别
+ * @param pdfData PDF文件数据或路径
+ * @param outputDir 输出目录
+ * @param scale 缩放比例
+ * @returns 生成的图像文件路径数组
+ */
+export const generateFullPageImages = async (pdfData: Buffer | string, outputDir: string, scale: number = 3): Promise => {
+ // 确保输出目录存在
+ await fs.ensureDir(outputDir);
+
+ // 如果pdfData是字符串,则当作路径处理
+ let data: Uint8Array;
+ if (typeof pdfData === 'string') {
+ data = new Uint8Array(await fs.readFile(pdfData));
+ } else {
+ data = new Uint8Array(pdfData);
+ }
+
+ // 加载PDF文档
+ const pdfDocument: PDFDocumentProxy = await getDocument({ data }).promise;
+ const numPages = pdfDocument.numPages;
+ console.log(`PDF文档共 ${numPages} 页`);
+
+ // 存储生成的图像路径
+ const pageImages: PageImage[] = [];
+
+ // 处理每一页
+ for (let i = 0; i < numPages; i++) {
+ const pageIndex = i + 1;
+ console.log(`处理第 ${pageIndex} 页...`);
+
+ // 获取页面
+ const page: PDFPageProxy = await pdfDocument.getPage(pageIndex);
+ const viewport: PageViewport = page.getViewport({ scale });
+
+ // 创建canvas
+ const canvas: Canvas = createCanvas(viewport.width, viewport.height);
+ const context = canvas.getContext('2d') as any as CanvasRenderingContext2D;
+
+ // 填充白色背景
+ context.fillStyle = '#ffffff';
+ context.fillRect(0, 0, viewport.width, viewport.height);
+
+ // 渲染页面
+ await page.render({
+ canvasContext: context,
+ viewport: viewport,
+ }).promise;
+
+ // 将canvas转换为图像并保存
+ const buffer = canvas.toBuffer('image/png');
+
+ // 添加到结果数组
+ pageImages.push({ index: pageIndex, data: buffer });
+ }
+
+ return pageImages;
+};
diff --git a/packages/pdf2md/src/index.ts b/packages/pdf2md/src/index.ts
new file mode 100644
index 0000000..50eab0e
--- /dev/null
+++ b/packages/pdf2md/src/index.ts
@@ -0,0 +1,186 @@
+/**
+ * PDF2MD 主入口模块
+ * 提供PDF转Markdown的完整功能
+ */
+import fs from 'fs-extra';
+import path from 'path';
+import { generateFullPageImages, PageImage } from './image-generator';
+import { extractMdFromLLMOutput, adjustMarkdownHeadings, getOldMarkdownHeadings } from './utils';
+import ModelClient, { ModelConfig } from './model-client';
+import { DefaultPrompt, DefaultTextPrompt } from './const';
+
+interface ParseOptions {
+ outputDir?: string;
+ prompt?: string;
+ textPrompt?: string;
+ verbose?: boolean;
+ scale?: number;
+ concurrency?: number;
+ onProgress?: (progress: ProgressInfo) => void;
+}
+
+interface ProgressInfo {
+ current: number;
+ total: number;
+ taskStatus: 'starting' | 'running' | 'finished';
+}
+
+interface PageContent {
+ pageIndex: number;
+ content: string;
+}
+
+interface ParseResult {
+ content: string;
+ mdFilePath: string;
+}
+
+/**
+ * 将PDF文件解析为Markdown
+ */
+export const parsePdf = async (pdfPath: string, modelConfig: ModelConfig = {}, options: ParseOptions = {}): Promise => {
+ const { outputDir = './output', prompt = DefaultPrompt, textPrompt = DefaultTextPrompt, verbose = false, scale = 3, concurrency = 2, onProgress } = options;
+
+ // 确保输出目录存在
+ await fs.ensureDir(outputDir);
+
+ console.log('开始解析PDF文件(全页模式):', pdfPath);
+
+ try {
+ // 第一步:生成全页图像
+ console.log('生成全页图像...');
+ const imageOutputDir = path.join(outputDir, 'pages');
+ await fs.ensureDir(imageOutputDir);
+
+ const imageFiles = await generateFullPageImages(pdfPath, imageOutputDir, scale);
+
+ //先把总页数传递回调用方法
+ if (onProgress) {
+ onProgress({
+ current: 0,
+ total: imageFiles.length,
+ taskStatus: 'starting',
+ });
+ }
+
+ // 第二步:使用视觉模型处理每个页面图像
+ console.log('处理全页图像...');
+
+ // 创建模型客户端
+ const modelClient = new ModelClient(modelConfig);
+
+ const pageContents: PageContent[] = [];
+ const processImages = async (item: PageImage) => {
+ console.log(`处理页面 ${item.index}/${imageFiles.length}`);
+ try {
+ // 处理图像 - 确保传入有效的prompt
+ const defaultPrompt = '请将图像中的所有文本内容转换为Markdown格式,包括标题、段落、列表和表格等。';
+ const pageContent = await modelClient.processImage(item.data, prompt || defaultPrompt);
+
+ if (true) {
+ await fs.writeFile(`${imageOutputDir}/page_${item.index}.md`, pageContent, { encoding: 'utf8' });
+ }
+
+ // 添加页面内容
+ pageContents.push({
+ pageIndex: item.index,
+ content: pageContent,
+ });
+ // 处理完成后,更新调用者的信息
+ if (onProgress) {
+ onProgress({
+ current: pageContents.length,
+ total: imageFiles.length,
+ taskStatus: 'running',
+ });
+ }
+ return { success: true, item, data: pageContent };
+ } catch (error) {
+ console.error('Markdown 转换失败:', error);
+ return { success: false, item, error: (error as Error).message };
+ }
+ };
+
+ // 并行处理所有问题,最多同时处理concurrency个
+ await processInParallel(imageFiles, processImages, concurrency);
+
+ //并行处理生成结果是乱序的,根据pageIndex进行排序再输出Markdown
+ pageContents.sort((a, b) => a.pageIndex - b.pageIndex);
+
+ // 第三步:生成Markdown文件
+ console.log('生成Markdown文档...');
+
+ // 生成Markdown内容
+ let content = '';
+ for (const page of pageContents) {
+ content += page.content + '\n';
+ }
+
+ console.log('正在重新调整目录...');
+
+ // 提取转换后的标题
+ const title = await getOldMarkdownHeadings(content);
+
+ //使用大模型重新调整目录结构
+ const defaultPrompt = '请将图像中的所有文本内容转换为Markdown格式,包括标题、段落、列表和表格等。';
+ const convertedTitleLLMResult = await modelClient.processImage(null, textPrompt + JSON.stringify(title) || defaultPrompt);
+ const convertedTitle = await extractMdFromLLMOutput(convertedTitleLLMResult);
+
+ //根据调整后的结果重新生成md文件
+ const convertContent = await adjustMarkdownHeadings(content, convertedTitle || '');
+
+ console.log('目录调整完成...');
+
+ // 第四步:保存Markdown文件
+ const mdFilePath = path.join(outputDir, path.basename(pdfPath, '.pdf') + '.md');
+ await fs.writeFile(mdFilePath, convertContent);
+ console.log('Markdown文件已保存至:', mdFilePath);
+
+ // 将任务执行结束传递回调用方法
+ if (onProgress) {
+ onProgress({
+ current: imageFiles.length,
+ total: imageFiles.length,
+ taskStatus: 'finished',
+ });
+ }
+
+ return {
+ content,
+ mdFilePath,
+ };
+ } catch (error) {
+ console.error('PDF解析过程中发生错误:', error);
+ throw error;
+ }
+};
+
+// 定义并行处理的辅助函数类型
+type ProcessFunction = (item: T) => Promise;
+
+// 并行处理数组的辅助函数,限制并发数
+const processInParallel = async (items: T[], processFunction: ProcessFunction, concurrencyLimit: number): Promise => {
+ const results: Promise[] = [];
+ const inProgress = new Set>();
+ const queue = [...items];
+
+ while (queue.length > 0 || inProgress.size > 0) {
+ // 如果有空闲槽位且队列中还有任务,启动新任务
+ while (inProgress.size < concurrencyLimit && queue.length > 0) {
+ const item = queue.shift()!;
+ const promise = processFunction(item).then((result) => {
+ inProgress.delete(promise);
+ return result;
+ });
+ inProgress.add(promise);
+ results.push(promise);
+ }
+
+ // 等待其中一个任务完成
+ if (inProgress.size > 0) {
+ await Promise.race(inProgress);
+ }
+ }
+
+ return Promise.all(results);
+};
diff --git a/packages/pdf2md/src/model-client.ts b/packages/pdf2md/src/model-client.ts
new file mode 100644
index 0000000..b82c4ef
--- /dev/null
+++ b/packages/pdf2md/src/model-client.ts
@@ -0,0 +1,105 @@
+/**
+ * 模型客户端模块,用于处理不同视觉模型的API调用
+ */
+import { generateText } from '@xsai/generate-text';
+import type { UserMessagePart } from '@xsai/shared-chat';
+
+// 默认角色提示词(中文版)
+const DEFAULT_ROLE_PROMPT = `你是一个PDF文档解析器,使用markdown和latex语法输出图片的内容。`;
+
+/**
+ * 模型配置接口
+ */
+export interface ModelConfig {
+ apiKey?: string;
+ baseURL?: string;
+ model?: string;
+}
+
+/**
+ * 处理图像选项接口
+ */
+interface ProcessImageOptions extends ModelConfig {
+ rolePrompt?: string;
+}
+
+/**
+ * 模型客户端类,处理与不同视觉模型的交互
+ */
+export class ModelClient {
+ private config: ModelConfig;
+
+ /**
+ * 创建模型客户端实例
+ */
+ constructor(config: ModelConfig) {
+ this.config = {
+ baseURL: 'http://localhost:11434/v1/',
+ model: 'gemma3:12b',
+ ...config,
+ };
+ }
+
+ /**
+ * 处理图像并转换为Markdown文本
+ */
+ async processImage(imageData: Buffer | null, prompt: string, options: ProcessImageOptions = {}): Promise {
+ const { rolePrompt = DEFAULT_ROLE_PROMPT } = options;
+
+ // 读取图像文件
+ let base64Image: string | null = null;
+ if (imageData) {
+ base64Image = imageData.toString('base64');
+ }
+
+ const modelConfig: ModelConfig = {
+ apiKey: options.apiKey || this.config.apiKey,
+ baseURL: options.baseURL || this.config.baseURL,
+ model: options.model || this.config.model,
+ };
+
+ return this.callLLM(rolePrompt, prompt, base64Image, modelConfig);
+ }
+
+ /**
+ * 通过API调用OpenAI视觉模型
+ * @private
+ */
+ private async callLLM(rolePrompt: string, prompt: string, base64Image: string | null, modelConfig: ModelConfig): Promise {
+ // 使用OpenAI API
+ const baseURL = modelConfig.baseURL || 'https://api.openai.com/v1/';
+
+ // 构建用户消息内容
+ const userContent: Array = [{ type: 'text', text: prompt }];
+
+ // 如果有base64图片,添加图片内容
+ if (base64Image) {
+ userContent.push({
+ type: 'image_url',
+ image_url: {
+ url: `data:image/png;base64,${base64Image}`,
+ },
+ });
+ }
+
+ const { text } = await generateText({
+ apiKey: modelConfig.apiKey!,
+ baseURL: baseURL,
+ messages: [
+ {
+ role: 'system',
+ content: rolePrompt,
+ },
+ {
+ role: 'user',
+ content: userContent,
+ },
+ ],
+ model: modelConfig.model!,
+ });
+
+ return text || '';
+ }
+}
+
+export default ModelClient;
diff --git a/packages/pdf2md/src/utils.ts b/packages/pdf2md/src/utils.ts
new file mode 100644
index 0000000..7d6f9d7
--- /dev/null
+++ b/packages/pdf2md/src/utils.ts
@@ -0,0 +1,85 @@
+/**
+ * 工具函数模块,提供常用的辅助功能
+ */
+import fs from 'fs-extra';
+
+/**
+ * 删除文件
+ * @param filePath 文件路径
+ */
+export const removeFile = async (filePath: string): Promise => {
+ try {
+ await fs.remove(filePath);
+ } catch (error: any) {
+ console.error(`删除文件 ${filePath} 失败:`, error);
+ }
+};
+
+// 从 LLM 输出中提取标题
+export const extractMdFromLLMOutput = (output: string): string | undefined => {
+ const mdStart = output.indexOf('```markdown');
+ const mdEnd = output.lastIndexOf('```');
+ if (mdStart !== -1 && mdEnd !== -1) {
+ const mdString = output.substring(mdStart + 12, mdEnd);
+ return mdString;
+ } else {
+ console.error('模型未按标准格式输出:', output);
+ return undefined;
+ }
+};
+
+//获取优化前的 markdwon 标题
+export const getOldMarkdownHeadings = (markdownText: string): string => {
+ const title: string[] = [];
+ const lines = markdownText.split('\n');
+ lines.forEach((line) => {
+ // 匹配 # 开头,并捕获后面的内容
+ const match = line.match(/^#+\s*(.*)/);
+ if (match) {
+ title.push(line);
+ }
+ });
+ return title.join('\n');
+};
+
+//根据新生成的标题结构,重新设置原文章中标题级别
+export const adjustMarkdownHeadings = (markdownText: string, newTitle: string): string => {
+ const map = createTitleLevelMap(newTitle);
+ const lines = markdownText.split('\n');
+ const processedLines: string[] = [];
+ lines.forEach((line) => {
+ // 匹配 # 开头,并捕获后面的内容
+ const match = line.match(/^#+\s*(.*)/);
+ if (!match) {
+ processedLines.push(line);
+ return;
+ }
+ const content = match ? match[1] : line;
+ // 检查 content 是否在 map 中存在
+ let newLine = line;
+ if (map.has(content)) {
+ const level = map.get(content);
+ // 生成对应数量的 #(例如 level=2 -> "##")
+ const hashes = '#'.repeat(level!);
+ newLine = `${hashes} ${content}`;
+ console.log('转换前:' + line + '===>转换后' + newLine);
+ }
+ processedLines.push(newLine);
+ });
+ return processedLines.join('\n');
+};
+
+//根据标题#数量,建立内容和数量的map映射
+function createTitleLevelMap(data: string, map: Map = new Map()): Map {
+ const lines = data.split('\n');
+ for (const line of lines) {
+ // 匹配以#开头的标题行
+ const headerMatch = line.match(/^(#+)\s*(.+)/);
+ if (headerMatch) {
+ const level = headerMatch[1].length; // #号的数量
+ const text = headerMatch[2].trim(); // #号后的文本内容
+ map.set(text, level);
+ }
+ }
+ return map;
+}
diff --git a/packages/pdf2md/tsconfig.json b/packages/pdf2md/tsconfig.json
new file mode 100644
index 0000000..276fda8
--- /dev/null
+++ b/packages/pdf2md/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "lib": ["DOM", "ES2020"],
+ "module": "NodeNext",
+ "strict": true,
+ "noEmit": true,
+ "moduleResolution": "nodenext",
+ "skipLibCheck": true,
+ "isolatedModules": true,
+ "useDefineForClassFields": true,
+ "allowImportingTsExtensions": true,
+ "allowSyntheticDefaultImports": true,
+ "allowJs": true
+ },
+ "include": ["src"]
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..64bf668
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,1438 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ devDependencies:
+ '@rslib/core':
+ specifier: ^0.6.4
+ version: 0.6.4(typescript@5.8.3)
+ '@types/node':
+ specifier: ^22.14.1
+ version: 22.14.1
+ prettier:
+ specifier: ^3.5.3
+ version: 3.5.3
+ typescript:
+ specifier: ^5.8.3
+ version: 5.8.3
+
+ packages/mcp:
+ dependencies:
+ '@modelcontextprotocol/sdk':
+ specifier: ^1.9.0
+ version: 1.9.0
+ '@tiny-tool/pdf2md':
+ specifier: workspace:*
+ version: link:../pdf2md
+ express:
+ specifier: ^5.1.0
+ version: 5.1.0
+ zod:
+ specifier: ^3.24.3
+ version: 3.24.3
+ zod-to-json-schema:
+ specifier: ^3.24.5
+ version: 3.24.5(zod@3.24.3)
+ devDependencies:
+ '@types/express':
+ specifier: ^5.0.1
+ version: 5.0.1
+
+ packages/pdf2md:
+ dependencies:
+ '@napi-rs/canvas':
+ specifier: ^0.1.69
+ version: 0.1.69
+ '@xsai/generate-text':
+ specifier: 0.2.0-beta.3
+ version: 0.2.0-beta.3
+ fs-extra:
+ specifier: ^11.3.0
+ version: 11.3.0
+ pdfjs-dist:
+ specifier: ^5.1.91
+ version: 5.1.91
+ devDependencies:
+ '@types/fs-extra':
+ specifier: ^11.0.4
+ version: 11.0.4
+ '@xsai/shared-chat':
+ specifier: 0.2.0-beta.3
+ version: 0.2.0-beta.3
+
+packages:
+
+ '@ast-grep/napi-darwin-arm64@0.37.0':
+ resolution: {integrity: sha512-QAiIiaAbLvMEg/yBbyKn+p1gX2/FuaC0SMf7D7capm/oG4xGMzdeaQIcSosF4TCxxV+hIH4Bz9e4/u7w6Bnk3Q==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@ast-grep/napi-darwin-x64@0.37.0':
+ resolution: {integrity: sha512-zvcvdgekd4ySV3zUbUp8HF5nk5zqwiMXTuVzTUdl/w08O7JjM6XPOIVT+d2o/MqwM9rsXdzdergY5oY2RdhSPA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@ast-grep/napi-linux-arm64-gnu@0.37.0':
+ resolution: {integrity: sha512-L7Sj0lXy8X+BqSMgr1LB8cCoWk0rericdeu+dC8/c8zpsav5Oo2IQKY1PmiZ7H8IHoFBbURLf8iklY9wsD+cyA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@ast-grep/napi-linux-arm64-musl@0.37.0':
+ resolution: {integrity: sha512-LF9sAvYy6es/OdyJDO3RwkX3I82Vkfsng1sqUBcoWC1jVb1wX5YVzHtpQox9JrEhGl+bNp7FYxB4Qba9OdA5GA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@ast-grep/napi-linux-x64-gnu@0.37.0':
+ resolution: {integrity: sha512-TViz5/klqre6aSmJzswEIjApnGjJzstG/SE8VDWsrftMBMYt2PTu3MeluZVwzSqDao8doT/P+6U11dU05UOgxw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@ast-grep/napi-linux-x64-musl@0.37.0':
+ resolution: {integrity: sha512-/BcCH33S9E3ovOAEoxYngUNXgb+JLg991sdyiNP2bSoYd30a9RHrG7CYwW6fMgua3ijQ474eV6cq9yZO1bCpXg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@ast-grep/napi-win32-arm64-msvc@0.37.0':
+ resolution: {integrity: sha512-TjQA4cFoIEW2bgjLkaL9yqT4XWuuLa5MCNd0VCDhGRDMNQ9+rhwi9eLOWRaap3xzT7g+nlbcEHL3AkVCD2+b3A==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@ast-grep/napi-win32-ia32-msvc@0.37.0':
+ resolution: {integrity: sha512-uNmVka8fJCdYsyOlF9aZqQMLTatEYBynjChVTzUfFMDfmZ0bihs/YTqJVbkSm8TZM7CUX82apvn50z/dX5iWRA==}
+ engines: {node: '>= 10'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@ast-grep/napi-win32-x64-msvc@0.37.0':
+ resolution: {integrity: sha512-vCiFOT3hSCQuHHfZ933GAwnPzmL0G04JxQEsBRfqONywyT8bSdDc/ECpAfr3S9VcS4JZ9/F6tkePKW/Om2Dq2g==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@ast-grep/napi@0.37.0':
+ resolution: {integrity: sha512-Hb4o6h1Pf6yRUAX07DR4JVY7dmQw+RVQMW5/m55GoiAT/VRoKCWBtIUPPOnqDVhbx1Cjfil9b6EDrgJsUAujEQ==}
+ engines: {node: '>= 10'}
+
+ '@jridgewell/sourcemap-codec@1.5.0':
+ resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
+
+ '@modelcontextprotocol/sdk@1.9.0':
+ resolution: {integrity: sha512-Jq2EUCQpe0iyO5FGpzVYDNFR6oR53AIrwph9yWl7uSc7IWUMsrmpmSaTGra5hQNunXpM+9oit85p924jWuHzUA==}
+ engines: {node: '>=18'}
+
+ '@module-federation/error-codes@0.11.2':
+ resolution: {integrity: sha512-ik1Qnn0I+WyEdprTck9WGlH41vGsVdUg8cfO+ZM02qOb2cZm5Vu3SlxGAobj6g7uAj0g8yINnd7h7Dci40BxQA==}
+
+ '@module-federation/runtime-core@0.11.2':
+ resolution: {integrity: sha512-dia5kKybi6MFU0s5PgglJwN27k7n9Sf69Cy5xZ4BWaP0qlaXTsxHKO0PECHNt2Pt8jDdyU29sQ4DwAQfxpnXJQ==}
+
+ '@module-federation/runtime-tools@0.11.2':
+ resolution: {integrity: sha512-4MJTGAxVq6vxQRkTtTlH7Mm9AVqgn0X9kdu+7RsL7T/qU+jeYsbrntN2CWG3GVVA8r5JddXyTI1iJ0VXQZLV1w==}
+
+ '@module-federation/runtime@0.11.2':
+ resolution: {integrity: sha512-Ya9u/L6z2LvhgpqxuKCB7LcigIIRf1BbaxAZIH7mzbq/A7rZtTP7v+73E433jvgiAlbAfPSZkeoYGele6hfRwA==}
+
+ '@module-federation/sdk@0.11.2':
+ resolution: {integrity: sha512-SBFe5xOamluT900J4AGBx+2/kCH/JbfqXoUwPSAC6PRzb8Y7LB0posnOGzmqYsLZXT37vp3d6AmJDsVoajDqxw==}
+
+ '@module-federation/webpack-bundler-runtime@0.11.2':
+ resolution: {integrity: sha512-WdwIE6QF+MKs/PdVu0cKPETF743JB9PZ62/qf7Uo3gU4fjsUMc37RnbJZ/qB60EaHHfjwp1v6NnhZw1r4eVsnw==}
+
+ '@napi-rs/canvas-android-arm64@0.1.69':
+ resolution: {integrity: sha512-4icWTByY8zPvM9SelfQKf3I6kwXw0aI5drBOVrwfER5kjwXJd78FPSDSZkxDHjvIo9Q86ljl18Yr963ehA4sHQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [android]
+
+ '@napi-rs/canvas-darwin-arm64@0.1.69':
+ resolution: {integrity: sha512-HOanhhYlHdukA+unjelT4Dg3ta7e820x87/AG2dKUMsUzH19jaeZs9bcYjzEy2vYi/dFWKz7cSv2yaIOudB8Yg==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@napi-rs/canvas-darwin-x64@0.1.69':
+ resolution: {integrity: sha512-SIp7WfhxAPnSVK9bkFfJp+84rbATCIq9jMUzDwpCLhQ+v+OqtXe4pggX1oeV+62/HK6BT1t18qRmJfyqwJ9f3g==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@napi-rs/canvas-linux-arm-gnueabihf@0.1.69':
+ resolution: {integrity: sha512-Ls+KujCp6TGpkuMVFvrlx+CxtL+casdkrprFjqIuOAnB30Mct6bCEr+I83Tu29s3nNq4EzIGjdmA3fFAZG/Dtw==}
+ engines: {node: '>= 10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-arm64-gnu@0.1.69':
+ resolution: {integrity: sha512-m8VcGmeSBNRbHZBd1srvdM1aq/ScS2y8KqGqmCCEgJlytYK4jdULzAo2K/BPKE1v3xvn8oUPZDLI/NBJbJkEoA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-arm64-musl@0.1.69':
+ resolution: {integrity: sha512-a3xjNRIeK2m2ZORGv2moBvv3vbkaFZG1QKMeiEv/BKij+rkztuEhTJGMar+buICFgS0fLgphXXsKNkUSJb7eRQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-riscv64-gnu@0.1.69':
+ resolution: {integrity: sha512-pClUoJF5wdC9AvD0mc15G9JffL1Q85nuH1rLSQPRkGmGmQOtRjw5E9xNbanz7oFUiPbjH7xcAXUjVAcf7tdgPQ==}
+ engines: {node: '>= 10'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-x64-gnu@0.1.69':
+ resolution: {integrity: sha512-96X3bFAmzemfw84Ts6Jg/omL86uuynvK06MWGR/mp3JYNumY9RXofA14eF/kJIYelbYFWXcwpbcBR71lJ6G/YQ==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@napi-rs/canvas-linux-x64-musl@0.1.69':
+ resolution: {integrity: sha512-2QTsEFO72Kwkj53W9hc5y1FAUvdGx0V+pjJB+9oQF6Ys9+y989GyPIl5wZDzeh8nIJW6koZZ1eFa8pD+pA5BFQ==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@napi-rs/canvas-win32-x64-msvc@0.1.69':
+ resolution: {integrity: sha512-Q4YA8kVnKarApBVLu7F8icGlIfSll5Glswo5hY6gPS4Is2dCI8+ig9OeDM8RlwYevUIxKq8lZBypN8Q1iLAQ7w==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@napi-rs/canvas@0.1.69':
+ resolution: {integrity: sha512-ydvNeJMRm+l3T14yCoUKqjYQiEdXDq1isznI93LEBGYssXKfSaLNLHOkeM4z9Fnw9Pkt2EKOCAtW9cS4b00Zcg==}
+ engines: {node: '>= 10'}
+
+ '@rsbuild/core@1.3.8':
+ resolution: {integrity: sha512-J3WfY7XH5RRswfXFFUYizhrsEe/ueufALBSYfNyXpDnzTWgO/NGcjtB7iRgOsXs5z1WLRBMukiFUdDFf0iTcMQ==}
+ engines: {node: '>=16.10.0'}
+ hasBin: true
+
+ '@rslib/core@0.6.4':
+ resolution: {integrity: sha512-7UDx1/Rm3YB/hPkp51GeGybrI9/7cEMVXOF47crXMDb1TRpa69aJxN/o/L6/GFSRQzQMhS1q17S/jyDE+x+SFA==}
+ engines: {node: '>=16.7.0'}
+ hasBin: true
+ peerDependencies:
+ '@microsoft/api-extractor': ^7
+ typescript: ^5
+ peerDependenciesMeta:
+ '@microsoft/api-extractor':
+ optional: true
+ typescript:
+ optional: true
+
+ '@rspack/binding-darwin-arm64@1.3.5':
+ resolution: {integrity: sha512-bhqi9nZ0jrlQc/YgTklzD02y0E8Emdrov6HLcxt/Dzwq5SZryl4Ik8yc/8E1M0PWNkr09+TO8i1Zc51z0Gfu2g==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rspack/binding-darwin-x64@1.3.5':
+ resolution: {integrity: sha512-ysNn7bd/5NdVb0mTDBQl+D9GypCSS7FJoJJEeSpPcN01zFF8lRUsvdbOvzrG/CUBA2qbeWhwZvG2eKOy3p2NRA==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rspack/binding-linux-arm64-gnu@1.3.5':
+ resolution: {integrity: sha512-oEfPjYx3RVsMeHG/kI9k96nLJUQhYfQS9HUKS37Ko3RWC84qTuzMAAdWIXE9ys8GHwpks7pL953AfYNK5PLhPw==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rspack/binding-linux-arm64-musl@1.3.5':
+ resolution: {integrity: sha512-4cUoxd8nGsCCnqWBqortJRF+VKWzUm7ac9YRMQ+wpoL5i0abcQf8GqeilsNtRBRNqAlAh3mfgRlyeZgWvoS44g==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rspack/binding-linux-x64-gnu@1.3.5':
+ resolution: {integrity: sha512-JehI/z61Y9wwkcTxbAdPtjUnAyyAUCJZOqP3FwQTAd2gBFG/8k7v1quGwrfOLsCLOcT3azbd8YFoHmkveGQayQ==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rspack/binding-linux-x64-musl@1.3.5':
+ resolution: {integrity: sha512-t8BqaOXrqIXZHTrz4ItX/m6BOvbBkeb7qTewlkN5mMHtPAF/Xg203rQ814VXx59kjgGF7i79PXIK2dQxHnCYDA==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rspack/binding-win32-arm64-msvc@1.3.5':
+ resolution: {integrity: sha512-k9vf/WgEwxtXzV4la1H6eL07GIlvNjdPdvo1AJZdu0Zcnm600Kv5NSBjySJCp3zUHIKkCE9A0+ibifqbliG0fw==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rspack/binding-win32-ia32-msvc@1.3.5':
+ resolution: {integrity: sha512-dGfGJySHC/ktbNkK/FY2vEpFNK4UT+fgChhmUxIyQaHWjloFGVmEr6NttS0GtdtvblfF3tTzkTe9pGMIkdlegw==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rspack/binding-win32-x64-msvc@1.3.5':
+ resolution: {integrity: sha512-GujYFTr043jse5gdvofsRvltkH/E8G5h3Yu9JG/+6EyQpFJebYm/NpRQrOyqZLIQP39+tbdViTfW4nOpUuurNA==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rspack/binding@1.3.5':
+ resolution: {integrity: sha512-2oluCT+iBnTg0w7XfR8AmfkvgMPSuqEndzhrlHY//qgyyI04CW1lCMgsh+9wcSOUWUKYSOMCiGiVlYFtae5Lcg==}
+
+ '@rspack/core@1.3.5':
+ resolution: {integrity: sha512-PwIpzXj9wjHM0Ohq6geIKPoh3yNb5oSK74gqzs0plR7pTYLbhrjG/1DSV/JLFF4C5WCpLHHiDEX5E0IYm2Aqeg==}
+ engines: {node: '>=16.0.0'}
+ peerDependencies:
+ '@rspack/tracing': ^1.x
+ '@swc/helpers': '>=0.5.1'
+ peerDependenciesMeta:
+ '@rspack/tracing':
+ optional: true
+ '@swc/helpers':
+ optional: true
+
+ '@rspack/lite-tapable@1.0.1':
+ resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==}
+ engines: {node: '>=16.0.0'}
+
+ '@swc/helpers@0.5.17':
+ resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==}
+
+ '@types/body-parser@1.19.5':
+ resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
+
+ '@types/connect@3.4.38':
+ resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
+
+ '@types/express-serve-static-core@5.0.6':
+ resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==}
+
+ '@types/express@5.0.1':
+ resolution: {integrity: sha512-UZUw8vjpWFXuDnjFTh7/5c2TWDlQqeXHi6hcN7F2XSVT5P+WmUnnbFS3KA6Jnc6IsEqI2qCVu2bK0R0J4A8ZQQ==}
+
+ '@types/fs-extra@11.0.4':
+ resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==}
+
+ '@types/http-errors@2.0.4':
+ resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==}
+
+ '@types/jsonfile@6.1.4':
+ resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==}
+
+ '@types/mime@1.3.5':
+ resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
+
+ '@types/node@22.14.1':
+ resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==}
+
+ '@types/qs@6.9.18':
+ resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==}
+
+ '@types/range-parser@1.2.7':
+ resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
+
+ '@types/send@0.17.4':
+ resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==}
+
+ '@types/serve-static@1.15.7':
+ resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==}
+
+ '@xsai/generate-text@0.2.0-beta.3':
+ resolution: {integrity: sha512-dE01PDM3WDsI9FBzCxOyNQ8uqwae5/Y9hU16iO0DX/HAYSE44zgZ51Yaj3nEmf3idfZq66tswBAYh8eOHuA8Zg==}
+
+ '@xsai/shared-chat@0.2.0-beta.3':
+ resolution: {integrity: sha512-mjgo+YaUwXXxY1Bfvnj2aW3Brhu2Q8gr5SLaIfiOjI0oXuOxN1Fq3GPnBlVBkAzOLEwIQZ82Q2p9zUlBAljm3g==}
+
+ '@xsai/shared@0.2.0-beta.3':
+ resolution: {integrity: sha512-bpp848WfOCmmkuSePe7czB5Vy1lZxNqV1pSX/N0gZVXxfBQC6wVqkjoScl17v13hsThDbqB6dyrN4ca3mwVBog==}
+
+ accepts@2.0.0:
+ resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
+ engines: {node: '>= 0.6'}
+
+ body-parser@2.2.0:
+ resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==}
+ engines: {node: '>=18'}
+
+ bytes@3.1.2:
+ resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
+ engines: {node: '>= 0.8'}
+
+ call-bind-apply-helpers@1.0.2:
+ resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+ engines: {node: '>= 0.4'}
+
+ call-bound@1.0.4:
+ resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
+ engines: {node: '>= 0.4'}
+
+ caniuse-lite@1.0.30001714:
+ resolution: {integrity: sha512-mtgapdwDLSSBnCI3JokHM7oEQBLxiJKVRtg10AxM1AyeiKcM96f0Mkbqeq+1AbiCtvMcHRulAAEMu693JrSWqg==}
+
+ content-disposition@1.0.0:
+ resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==}
+ engines: {node: '>= 0.6'}
+
+ content-type@1.0.5:
+ resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
+ engines: {node: '>= 0.6'}
+
+ cookie-signature@1.2.2:
+ resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
+ engines: {node: '>=6.6.0'}
+
+ cookie@0.7.2:
+ resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
+ engines: {node: '>= 0.6'}
+
+ core-js@3.41.0:
+ resolution: {integrity: sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==}
+
+ cors@2.8.5:
+ resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
+ engines: {node: '>= 0.10'}
+
+ cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+ engines: {node: '>= 8'}
+
+ debug@4.4.0:
+ resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ depd@2.0.0:
+ resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+ engines: {node: '>= 0.8'}
+
+ dunder-proto@1.0.1:
+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+ engines: {node: '>= 0.4'}
+
+ ee-first@1.1.1:
+ resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+
+ encodeurl@2.0.0:
+ resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
+ engines: {node: '>= 0.8'}
+
+ es-define-property@1.0.1:
+ resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+ engines: {node: '>= 0.4'}
+
+ es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+
+ es-object-atoms@1.1.1:
+ resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
+ engines: {node: '>= 0.4'}
+
+ escape-html@1.0.3:
+ resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+
+ etag@1.8.1:
+ resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
+ engines: {node: '>= 0.6'}
+
+ eventsource-parser@3.0.1:
+ resolution: {integrity: sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==}
+ engines: {node: '>=18.0.0'}
+
+ eventsource@3.0.6:
+ resolution: {integrity: sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==}
+ engines: {node: '>=18.0.0'}
+
+ express-rate-limit@7.5.0:
+ resolution: {integrity: sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==}
+ engines: {node: '>= 16'}
+ peerDependencies:
+ express: ^4.11 || 5 || ^5.0.0-beta.1
+
+ express@5.1.0:
+ resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==}
+ engines: {node: '>= 18'}
+
+ fdir@6.4.3:
+ resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ finalhandler@2.1.0:
+ resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==}
+ engines: {node: '>= 0.8'}
+
+ forwarded@0.2.0:
+ resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
+ engines: {node: '>= 0.6'}
+
+ fresh@2.0.0:
+ resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
+ engines: {node: '>= 0.8'}
+
+ fs-extra@11.3.0:
+ resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==}
+ engines: {node: '>=14.14'}
+
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ get-intrinsic@1.3.0:
+ resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
+ engines: {node: '>= 0.4'}
+
+ get-proto@1.0.1:
+ resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+ engines: {node: '>= 0.4'}
+
+ gopd@1.2.0:
+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+ engines: {node: '>= 0.4'}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ has-symbols@1.1.0:
+ resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+ engines: {node: '>= 0.4'}
+
+ hasown@2.0.2:
+ resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ engines: {node: '>= 0.4'}
+
+ http-errors@2.0.0:
+ resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
+ engines: {node: '>= 0.8'}
+
+ iconv-lite@0.6.3:
+ resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+ engines: {node: '>=0.10.0'}
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
+ ipaddr.js@1.9.1:
+ resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
+ engines: {node: '>= 0.10'}
+
+ is-promise@4.0.0:
+ resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ jiti@2.4.2:
+ resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
+ hasBin: true
+
+ json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ jsonfile@6.1.0:
+ resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
+
+ magic-string@0.30.17:
+ resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
+
+ math-intrinsics@1.1.0:
+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+ engines: {node: '>= 0.4'}
+
+ media-typer@1.1.0:
+ resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
+ engines: {node: '>= 0.8'}
+
+ merge-descriptors@2.0.0:
+ resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==}
+ engines: {node: '>=18'}
+
+ mime-db@1.54.0:
+ resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@3.0.1:
+ resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==}
+ engines: {node: '>= 0.6'}
+
+ minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ negotiator@1.0.0:
+ resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
+ engines: {node: '>= 0.6'}
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ object-inspect@1.13.4:
+ resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
+ engines: {node: '>= 0.4'}
+
+ on-finished@2.4.1:
+ resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
+ engines: {node: '>= 0.8'}
+
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+ parseurl@1.3.3:
+ resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
+ engines: {node: '>= 0.8'}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ path-to-regexp@8.2.0:
+ resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==}
+ engines: {node: '>=16'}
+
+ pdfjs-dist@5.1.91:
+ resolution: {integrity: sha512-qSIADdagooJB4wWCBnrBJjRvASevmxL0BwafvOuKJG5uTQdYoFBrhrRYnucKNiSc9qS6JIk0hC5y1yktFljXkA==}
+ engines: {node: '>=20'}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@4.0.2:
+ resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
+ engines: {node: '>=12'}
+
+ pkce-challenge@5.0.0:
+ resolution: {integrity: sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==}
+ engines: {node: '>=16.20.0'}
+
+ prettier@3.5.3:
+ resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==}
+ engines: {node: '>=14'}
+ hasBin: true
+
+ proxy-addr@2.0.7:
+ resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
+ engines: {node: '>= 0.10'}
+
+ qs@6.14.0:
+ resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
+ engines: {node: '>=0.6'}
+
+ range-parser@1.2.1:
+ resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
+ engines: {node: '>= 0.6'}
+
+ raw-body@3.0.0:
+ resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==}
+ engines: {node: '>= 0.8'}
+
+ router@2.2.0:
+ resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==}
+ engines: {node: '>= 18'}
+
+ rsbuild-plugin-dts@0.6.4:
+ resolution: {integrity: sha512-1sVfKuY2MQPoemFlpmlNjNw+Kx4jNj7ckD0GGNyRjdVqvTGAJJ8bFKoJEgaSmlgbYn2CXv3x1BriqQny23Z9EA==}
+ engines: {node: '>=16.7.0'}
+ peerDependencies:
+ '@microsoft/api-extractor': ^7
+ '@rsbuild/core': 1.x
+ typescript: ^5
+ peerDependenciesMeta:
+ '@microsoft/api-extractor':
+ optional: true
+ typescript:
+ optional: true
+
+ safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
+ send@1.2.0:
+ resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==}
+ engines: {node: '>= 18'}
+
+ serve-static@2.2.0:
+ resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==}
+ engines: {node: '>= 18'}
+
+ setprototypeof@1.2.0:
+ resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ side-channel-list@1.0.0:
+ resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-map@1.0.1:
+ resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-weakmap@1.0.2:
+ resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
+ engines: {node: '>= 0.4'}
+
+ side-channel@1.1.0:
+ resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
+ engines: {node: '>= 0.4'}
+
+ statuses@2.0.1:
+ resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
+ engines: {node: '>= 0.8'}
+
+ strip-bom@3.0.0:
+ resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
+ engines: {node: '>=4'}
+
+ tinyglobby@0.2.12:
+ resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==}
+ engines: {node: '>=12.0.0'}
+
+ toidentifier@1.0.1:
+ resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
+ engines: {node: '>=0.6'}
+
+ tsconfig-paths@4.2.0:
+ resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==}
+ engines: {node: '>=6'}
+
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ type-is@2.0.1:
+ resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
+ engines: {node: '>= 0.6'}
+
+ typescript@5.8.3:
+ resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ undici-types@6.21.0:
+ resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+
+ universalify@2.0.1:
+ resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+ engines: {node: '>= 10.0.0'}
+
+ unpipe@1.0.0:
+ resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
+ engines: {node: '>= 0.8'}
+
+ vary@1.1.2:
+ resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+ engines: {node: '>= 0.8'}
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+ zod-to-json-schema@3.24.5:
+ resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==}
+ peerDependencies:
+ zod: ^3.24.1
+
+ zod@3.24.3:
+ resolution: {integrity: sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==}
+
+snapshots:
+
+ '@ast-grep/napi-darwin-arm64@0.37.0':
+ optional: true
+
+ '@ast-grep/napi-darwin-x64@0.37.0':
+ optional: true
+
+ '@ast-grep/napi-linux-arm64-gnu@0.37.0':
+ optional: true
+
+ '@ast-grep/napi-linux-arm64-musl@0.37.0':
+ optional: true
+
+ '@ast-grep/napi-linux-x64-gnu@0.37.0':
+ optional: true
+
+ '@ast-grep/napi-linux-x64-musl@0.37.0':
+ optional: true
+
+ '@ast-grep/napi-win32-arm64-msvc@0.37.0':
+ optional: true
+
+ '@ast-grep/napi-win32-ia32-msvc@0.37.0':
+ optional: true
+
+ '@ast-grep/napi-win32-x64-msvc@0.37.0':
+ optional: true
+
+ '@ast-grep/napi@0.37.0':
+ optionalDependencies:
+ '@ast-grep/napi-darwin-arm64': 0.37.0
+ '@ast-grep/napi-darwin-x64': 0.37.0
+ '@ast-grep/napi-linux-arm64-gnu': 0.37.0
+ '@ast-grep/napi-linux-arm64-musl': 0.37.0
+ '@ast-grep/napi-linux-x64-gnu': 0.37.0
+ '@ast-grep/napi-linux-x64-musl': 0.37.0
+ '@ast-grep/napi-win32-arm64-msvc': 0.37.0
+ '@ast-grep/napi-win32-ia32-msvc': 0.37.0
+ '@ast-grep/napi-win32-x64-msvc': 0.37.0
+
+ '@jridgewell/sourcemap-codec@1.5.0': {}
+
+ '@modelcontextprotocol/sdk@1.9.0':
+ dependencies:
+ content-type: 1.0.5
+ cors: 2.8.5
+ cross-spawn: 7.0.6
+ eventsource: 3.0.6
+ express: 5.1.0
+ express-rate-limit: 7.5.0(express@5.1.0)
+ pkce-challenge: 5.0.0
+ raw-body: 3.0.0
+ zod: 3.24.3
+ zod-to-json-schema: 3.24.5(zod@3.24.3)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@module-federation/error-codes@0.11.2': {}
+
+ '@module-federation/runtime-core@0.11.2':
+ dependencies:
+ '@module-federation/error-codes': 0.11.2
+ '@module-federation/sdk': 0.11.2
+
+ '@module-federation/runtime-tools@0.11.2':
+ dependencies:
+ '@module-federation/runtime': 0.11.2
+ '@module-federation/webpack-bundler-runtime': 0.11.2
+
+ '@module-federation/runtime@0.11.2':
+ dependencies:
+ '@module-federation/error-codes': 0.11.2
+ '@module-federation/runtime-core': 0.11.2
+ '@module-federation/sdk': 0.11.2
+
+ '@module-federation/sdk@0.11.2': {}
+
+ '@module-federation/webpack-bundler-runtime@0.11.2':
+ dependencies:
+ '@module-federation/runtime': 0.11.2
+ '@module-federation/sdk': 0.11.2
+
+ '@napi-rs/canvas-android-arm64@0.1.69':
+ optional: true
+
+ '@napi-rs/canvas-darwin-arm64@0.1.69':
+ optional: true
+
+ '@napi-rs/canvas-darwin-x64@0.1.69':
+ optional: true
+
+ '@napi-rs/canvas-linux-arm-gnueabihf@0.1.69':
+ optional: true
+
+ '@napi-rs/canvas-linux-arm64-gnu@0.1.69':
+ optional: true
+
+ '@napi-rs/canvas-linux-arm64-musl@0.1.69':
+ optional: true
+
+ '@napi-rs/canvas-linux-riscv64-gnu@0.1.69':
+ optional: true
+
+ '@napi-rs/canvas-linux-x64-gnu@0.1.69':
+ optional: true
+
+ '@napi-rs/canvas-linux-x64-musl@0.1.69':
+ optional: true
+
+ '@napi-rs/canvas-win32-x64-msvc@0.1.69':
+ optional: true
+
+ '@napi-rs/canvas@0.1.69':
+ optionalDependencies:
+ '@napi-rs/canvas-android-arm64': 0.1.69
+ '@napi-rs/canvas-darwin-arm64': 0.1.69
+ '@napi-rs/canvas-darwin-x64': 0.1.69
+ '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.69
+ '@napi-rs/canvas-linux-arm64-gnu': 0.1.69
+ '@napi-rs/canvas-linux-arm64-musl': 0.1.69
+ '@napi-rs/canvas-linux-riscv64-gnu': 0.1.69
+ '@napi-rs/canvas-linux-x64-gnu': 0.1.69
+ '@napi-rs/canvas-linux-x64-musl': 0.1.69
+ '@napi-rs/canvas-win32-x64-msvc': 0.1.69
+
+ '@rsbuild/core@1.3.8':
+ dependencies:
+ '@rspack/core': 1.3.5(@swc/helpers@0.5.17)
+ '@rspack/lite-tapable': 1.0.1
+ '@swc/helpers': 0.5.17
+ core-js: 3.41.0
+ jiti: 2.4.2
+ transitivePeerDependencies:
+ - '@rspack/tracing'
+
+ '@rslib/core@0.6.4(typescript@5.8.3)':
+ dependencies:
+ '@rsbuild/core': 1.3.8
+ rsbuild-plugin-dts: 0.6.4(@rsbuild/core@1.3.8)(typescript@5.8.3)
+ tinyglobby: 0.2.12
+ optionalDependencies:
+ typescript: 5.8.3
+ transitivePeerDependencies:
+ - '@rspack/tracing'
+
+ '@rspack/binding-darwin-arm64@1.3.5':
+ optional: true
+
+ '@rspack/binding-darwin-x64@1.3.5':
+ optional: true
+
+ '@rspack/binding-linux-arm64-gnu@1.3.5':
+ optional: true
+
+ '@rspack/binding-linux-arm64-musl@1.3.5':
+ optional: true
+
+ '@rspack/binding-linux-x64-gnu@1.3.5':
+ optional: true
+
+ '@rspack/binding-linux-x64-musl@1.3.5':
+ optional: true
+
+ '@rspack/binding-win32-arm64-msvc@1.3.5':
+ optional: true
+
+ '@rspack/binding-win32-ia32-msvc@1.3.5':
+ optional: true
+
+ '@rspack/binding-win32-x64-msvc@1.3.5':
+ optional: true
+
+ '@rspack/binding@1.3.5':
+ optionalDependencies:
+ '@rspack/binding-darwin-arm64': 1.3.5
+ '@rspack/binding-darwin-x64': 1.3.5
+ '@rspack/binding-linux-arm64-gnu': 1.3.5
+ '@rspack/binding-linux-arm64-musl': 1.3.5
+ '@rspack/binding-linux-x64-gnu': 1.3.5
+ '@rspack/binding-linux-x64-musl': 1.3.5
+ '@rspack/binding-win32-arm64-msvc': 1.3.5
+ '@rspack/binding-win32-ia32-msvc': 1.3.5
+ '@rspack/binding-win32-x64-msvc': 1.3.5
+
+ '@rspack/core@1.3.5(@swc/helpers@0.5.17)':
+ dependencies:
+ '@module-federation/runtime-tools': 0.11.2
+ '@rspack/binding': 1.3.5
+ '@rspack/lite-tapable': 1.0.1
+ caniuse-lite: 1.0.30001714
+ optionalDependencies:
+ '@swc/helpers': 0.5.17
+
+ '@rspack/lite-tapable@1.0.1': {}
+
+ '@swc/helpers@0.5.17':
+ dependencies:
+ tslib: 2.8.1
+
+ '@types/body-parser@1.19.5':
+ dependencies:
+ '@types/connect': 3.4.38
+ '@types/node': 22.14.1
+
+ '@types/connect@3.4.38':
+ dependencies:
+ '@types/node': 22.14.1
+
+ '@types/express-serve-static-core@5.0.6':
+ dependencies:
+ '@types/node': 22.14.1
+ '@types/qs': 6.9.18
+ '@types/range-parser': 1.2.7
+ '@types/send': 0.17.4
+
+ '@types/express@5.0.1':
+ dependencies:
+ '@types/body-parser': 1.19.5
+ '@types/express-serve-static-core': 5.0.6
+ '@types/serve-static': 1.15.7
+
+ '@types/fs-extra@11.0.4':
+ dependencies:
+ '@types/jsonfile': 6.1.4
+ '@types/node': 22.14.1
+
+ '@types/http-errors@2.0.4': {}
+
+ '@types/jsonfile@6.1.4':
+ dependencies:
+ '@types/node': 22.14.1
+
+ '@types/mime@1.3.5': {}
+
+ '@types/node@22.14.1':
+ dependencies:
+ undici-types: 6.21.0
+
+ '@types/qs@6.9.18': {}
+
+ '@types/range-parser@1.2.7': {}
+
+ '@types/send@0.17.4':
+ dependencies:
+ '@types/mime': 1.3.5
+ '@types/node': 22.14.1
+
+ '@types/serve-static@1.15.7':
+ dependencies:
+ '@types/http-errors': 2.0.4
+ '@types/node': 22.14.1
+ '@types/send': 0.17.4
+
+ '@xsai/generate-text@0.2.0-beta.3':
+ dependencies:
+ '@xsai/shared': 0.2.0-beta.3
+ '@xsai/shared-chat': 0.2.0-beta.3
+
+ '@xsai/shared-chat@0.2.0-beta.3':
+ dependencies:
+ '@xsai/shared': 0.2.0-beta.3
+
+ '@xsai/shared@0.2.0-beta.3': {}
+
+ accepts@2.0.0:
+ dependencies:
+ mime-types: 3.0.1
+ negotiator: 1.0.0
+
+ body-parser@2.2.0:
+ dependencies:
+ bytes: 3.1.2
+ content-type: 1.0.5
+ debug: 4.4.0
+ http-errors: 2.0.0
+ iconv-lite: 0.6.3
+ on-finished: 2.4.1
+ qs: 6.14.0
+ raw-body: 3.0.0
+ type-is: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ bytes@3.1.2: {}
+
+ call-bind-apply-helpers@1.0.2:
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+
+ call-bound@1.0.4:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ get-intrinsic: 1.3.0
+
+ caniuse-lite@1.0.30001714: {}
+
+ content-disposition@1.0.0:
+ dependencies:
+ safe-buffer: 5.2.1
+
+ content-type@1.0.5: {}
+
+ cookie-signature@1.2.2: {}
+
+ cookie@0.7.2: {}
+
+ core-js@3.41.0: {}
+
+ cors@2.8.5:
+ dependencies:
+ object-assign: 4.1.1
+ vary: 1.1.2
+
+ cross-spawn@7.0.6:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ debug@4.4.0:
+ dependencies:
+ ms: 2.1.3
+
+ depd@2.0.0: {}
+
+ dunder-proto@1.0.1:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ ee-first@1.1.1: {}
+
+ encodeurl@2.0.0: {}
+
+ es-define-property@1.0.1: {}
+
+ es-errors@1.3.0: {}
+
+ es-object-atoms@1.1.1:
+ dependencies:
+ es-errors: 1.3.0
+
+ escape-html@1.0.3: {}
+
+ etag@1.8.1: {}
+
+ eventsource-parser@3.0.1: {}
+
+ eventsource@3.0.6:
+ dependencies:
+ eventsource-parser: 3.0.1
+
+ express-rate-limit@7.5.0(express@5.1.0):
+ dependencies:
+ express: 5.1.0
+
+ express@5.1.0:
+ dependencies:
+ accepts: 2.0.0
+ body-parser: 2.2.0
+ content-disposition: 1.0.0
+ content-type: 1.0.5
+ cookie: 0.7.2
+ cookie-signature: 1.2.2
+ debug: 4.4.0
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ finalhandler: 2.1.0
+ fresh: 2.0.0
+ http-errors: 2.0.0
+ merge-descriptors: 2.0.0
+ mime-types: 3.0.1
+ on-finished: 2.4.1
+ once: 1.4.0
+ parseurl: 1.3.3
+ proxy-addr: 2.0.7
+ qs: 6.14.0
+ range-parser: 1.2.1
+ router: 2.2.0
+ send: 1.2.0
+ serve-static: 2.2.0
+ statuses: 2.0.1
+ type-is: 2.0.1
+ vary: 1.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ fdir@6.4.3(picomatch@4.0.2):
+ optionalDependencies:
+ picomatch: 4.0.2
+
+ finalhandler@2.1.0:
+ dependencies:
+ debug: 4.4.0
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ on-finished: 2.4.1
+ parseurl: 1.3.3
+ statuses: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ forwarded@0.2.0: {}
+
+ fresh@2.0.0: {}
+
+ fs-extra@11.3.0:
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 6.1.0
+ universalify: 2.0.1
+
+ function-bind@1.1.2: {}
+
+ get-intrinsic@1.3.0:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ function-bind: 1.1.2
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.2
+ math-intrinsics: 1.1.0
+
+ get-proto@1.0.1:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-object-atoms: 1.1.1
+
+ gopd@1.2.0: {}
+
+ graceful-fs@4.2.11: {}
+
+ has-symbols@1.1.0: {}
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ http-errors@2.0.0:
+ dependencies:
+ depd: 2.0.0
+ inherits: 2.0.4
+ setprototypeof: 1.2.0
+ statuses: 2.0.1
+ toidentifier: 1.0.1
+
+ iconv-lite@0.6.3:
+ dependencies:
+ safer-buffer: 2.1.2
+
+ inherits@2.0.4: {}
+
+ ipaddr.js@1.9.1: {}
+
+ is-promise@4.0.0: {}
+
+ isexe@2.0.0: {}
+
+ jiti@2.4.2: {}
+
+ json5@2.2.3: {}
+
+ jsonfile@6.1.0:
+ dependencies:
+ universalify: 2.0.1
+ optionalDependencies:
+ graceful-fs: 4.2.11
+
+ magic-string@0.30.17:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.0
+
+ math-intrinsics@1.1.0: {}
+
+ media-typer@1.1.0: {}
+
+ merge-descriptors@2.0.0: {}
+
+ mime-db@1.54.0: {}
+
+ mime-types@3.0.1:
+ dependencies:
+ mime-db: 1.54.0
+
+ minimist@1.2.8: {}
+
+ ms@2.1.3: {}
+
+ negotiator@1.0.0: {}
+
+ object-assign@4.1.1: {}
+
+ object-inspect@1.13.4: {}
+
+ on-finished@2.4.1:
+ dependencies:
+ ee-first: 1.1.1
+
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
+ parseurl@1.3.3: {}
+
+ path-key@3.1.1: {}
+
+ path-to-regexp@8.2.0: {}
+
+ pdfjs-dist@5.1.91:
+ optionalDependencies:
+ '@napi-rs/canvas': 0.1.69
+
+ picocolors@1.1.1: {}
+
+ picomatch@4.0.2: {}
+
+ pkce-challenge@5.0.0: {}
+
+ prettier@3.5.3: {}
+
+ proxy-addr@2.0.7:
+ dependencies:
+ forwarded: 0.2.0
+ ipaddr.js: 1.9.1
+
+ qs@6.14.0:
+ dependencies:
+ side-channel: 1.1.0
+
+ range-parser@1.2.1: {}
+
+ raw-body@3.0.0:
+ dependencies:
+ bytes: 3.1.2
+ http-errors: 2.0.0
+ iconv-lite: 0.6.3
+ unpipe: 1.0.0
+
+ router@2.2.0:
+ dependencies:
+ debug: 4.4.0
+ depd: 2.0.0
+ is-promise: 4.0.0
+ parseurl: 1.3.3
+ path-to-regexp: 8.2.0
+ transitivePeerDependencies:
+ - supports-color
+
+ rsbuild-plugin-dts@0.6.4(@rsbuild/core@1.3.8)(typescript@5.8.3):
+ dependencies:
+ '@ast-grep/napi': 0.37.0
+ '@rsbuild/core': 1.3.8
+ magic-string: 0.30.17
+ picocolors: 1.1.1
+ tinyglobby: 0.2.12
+ tsconfig-paths: 4.2.0
+ optionalDependencies:
+ typescript: 5.8.3
+
+ safe-buffer@5.2.1: {}
+
+ safer-buffer@2.1.2: {}
+
+ send@1.2.0:
+ dependencies:
+ debug: 4.4.0
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ fresh: 2.0.0
+ http-errors: 2.0.0
+ mime-types: 3.0.1
+ ms: 2.1.3
+ on-finished: 2.4.1
+ range-parser: 1.2.1
+ statuses: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ serve-static@2.2.0:
+ dependencies:
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ parseurl: 1.3.3
+ send: 1.2.0
+ transitivePeerDependencies:
+ - supports-color
+
+ setprototypeof@1.2.0: {}
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ side-channel-list@1.0.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-map@1.0.1:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-weakmap@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-map: 1.0.1
+
+ side-channel@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-list: 1.0.0
+ side-channel-map: 1.0.1
+ side-channel-weakmap: 1.0.2
+
+ statuses@2.0.1: {}
+
+ strip-bom@3.0.0: {}
+
+ tinyglobby@0.2.12:
+ dependencies:
+ fdir: 6.4.3(picomatch@4.0.2)
+ picomatch: 4.0.2
+
+ toidentifier@1.0.1: {}
+
+ tsconfig-paths@4.2.0:
+ dependencies:
+ json5: 2.2.3
+ minimist: 1.2.8
+ strip-bom: 3.0.0
+
+ tslib@2.8.1: {}
+
+ type-is@2.0.1:
+ dependencies:
+ content-type: 1.0.5
+ media-typer: 1.1.0
+ mime-types: 3.0.1
+
+ typescript@5.8.3: {}
+
+ undici-types@6.21.0: {}
+
+ universalify@2.0.1: {}
+
+ unpipe@1.0.0: {}
+
+ vary@1.1.2: {}
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ wrappy@1.0.2: {}
+
+ zod-to-json-schema@3.24.5(zod@3.24.3):
+ dependencies:
+ zod: 3.24.3
+
+ zod@3.24.3: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..833a27f
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,2 @@
+packages:
+ - 'packages/*'
diff --git a/src/imageGenerator.js b/src/imageGenerator.js
deleted file mode 100644
index ab2b7ab..0000000
--- a/src/imageGenerator.js
+++ /dev/null
@@ -1,253 +0,0 @@
-/**
- * 图像生成模块,负责将PDF区域转换为图像
- */
-import pkg from 'pdfjs-dist/legacy/build/pdf.js';
-const { getDocument } = pkg;
-import sharp from 'sharp';
-import path from 'path';
-import fs from 'fs-extra';
-import { generateRandomFileName } from './utils.js';
-import { createCanvas } from 'canvas';
-
-// 设置PDF.js的worker路径
-try {
- // 获取当前文件的目录
- const currentDir = path.dirname(new URL(import.meta.url).pathname);
- // 构建 worker 的绝对路径
- const pdfjsWorker = path.join(currentDir, '..', 'node_modules/pdfjs-dist/legacy/build/pdf.worker.js');
- const pdfjsWorkerUrl = new URL(`file://${pdfjsWorker}`).href;
-
- // 全局设置worker路径
- globalThis.pdfjsWorkerSrc = pdfjsWorkerUrl;
-
- console.log('设置PDF.js worker路径:', pdfjsWorkerUrl);
-} catch (error) {
- console.warn('设置PDF.js worker路径时出错:', error.message);
-}
-
-/**
- * 将PDF页面的指定区域渲染为图像
- * @param {Object} page PDF.js页面对象
- * @param {Array} rect 区域坐标 [x0, y0, x1, y1]
- * @param {number} scale 渲染缩放比例
- * @returns {Buffer} 图像缓冲区
- */
-export const renderRectToImage = async (page, rect, scale = 4) => {
- const viewport = page.getViewport({ scale });
-
- // 计算渲染区域 - 添加内边距确保文本不被截断
- const [x0, y0, x1, y1] = rect;
-
- // 添加内边距(单位:原始坐标系下的点)
- const padding = 20 / scale; // 添加相当20像素的填充
-
- // 确保填充后的坐标不超出页面范围
- const paddedX0 = Math.max(0, x0 - padding);
- const paddedY0 = Math.max(0, y0 - padding);
- const paddedX1 = Math.min(viewport.width / scale, x1 + padding);
- const paddedY1 = Math.min(viewport.height / scale, y1 + padding);
-
- // 计算最终宽度和高度
- const width = (paddedX1 - paddedX0) * scale;
- const height = (paddedY1 - paddedY0) * scale;
-
- // 创建canvas - 使用Node.js版的canvas
- const canvas = createCanvas(width, height);
- const context = canvas.getContext('2d');
-
- // 填充背景色
- context.fillStyle = '#ffffff';
- context.fillRect(0, 0, width, height);
-
- // 设置渲染参数 - 使用填充后的坐标
- const renderContext = {
- canvasContext: context,
- viewport: viewport,
- transform: [scale, 0, 0, scale, -paddedX0 * scale, -paddedY0 * scale]
- };
-
- // 渲染页面
- await page.render(renderContext).promise;
-
- // 获取图像数据 - 使用Node.js版的canvas
- const pngData = canvas.toBuffer('image/png');
-
- // 使用Sharp处理图像
- const buffer = await sharp(pngData).png().toBuffer();
-
- return buffer;
-};
-
-/**
- * 从PDF文件生成区域图像
- * @param {string} pdfPath PDF文件路径
- * @param {Array} pageRects 每个页面的区域信息 [{ pageIndex, rects }, ...]
- * @param {string} outputDir 输出目录
- * @param {boolean} drawBoundingBoxes 是否绘制边界框
- * @returns {Array} 图像信息 [{ pageImage, rectImages }, ...]
- */
-export const generateImagesFromPdf = async (pdfPath, pageRects, outputDir, drawBoundingBoxes = true) => {
- // 确保输出目录存在
- await fs.ensureDir(outputDir);
-
- // 加载PDF文档
- const data = new Uint8Array(await fs.readFile(pdfPath));
- const pdfDocument = await getDocument({ data }).promise;
-
- const imageInfos = [];
-
- // 处理每一页
- for (const { pageIndex, rects } of pageRects) {
- console.log(`生成页面 ${pageIndex + 1} 的图像`);
-
- // 获取页面
- const page = await pdfDocument.getPage(pageIndex + 1);
- const viewport = page.getViewport({ scale: 1.0 });
-
- // 用于存储区域图像文件名
- const rectImages = [];
-
- // 处理每个区域
- for (let i = 0; i < rects.length; i++) {
- const rect = rects[i];
- // 生成区域图像
- const buffer = await renderRectToImage(page, rect);
-
- // 保存图像
- const imageName = `${pageIndex}_${i}.png`;
- const imagePath = path.join(outputDir, imageName);
- await fs.writeFile(imagePath, buffer);
-
- rectImages.push(imageName);
- }
-
- // 如果需要绘制边界框,渲染整个页面并标记区域
- let pageImage = null;
- if (drawBoundingBoxes) {
- // 渲染整个页面 - 使用Node.js版的canvas
- const scale = 3;
- const canvas = createCanvas(viewport.width * scale, viewport.height * scale);
- const context = canvas.getContext('2d');
-
- // 填充白色背景
- context.fillStyle = '#ffffff';
- context.fillRect(0, 0, canvas.width, canvas.height);
-
- // 渲染页面
- await page.render({
- canvasContext: context,
- viewport: page.getViewport({ scale })
- }).promise;
-
- // 绘制区域标记
- context.lineWidth = 1;
- context.strokeStyle = 'red';
- context.fillStyle = 'white';
-
- for (let i = 0; i < rects.length; i++) {
- const [x0, y0, x1, y1] = rects[i];
-
- // 绘制矩形
- context.strokeRect(x0 * scale, y0 * scale, (x1 - x0) * scale, (y1 - y0) * scale);
-
- // 绘制标签背景
- context.fillRect(x0 * scale + 2, y0 * scale + 2, 80, 12);
-
- // 绘制标签文本
- context.fillStyle = 'red';
- context.font = '10px Arial';
- context.fillText(`${pageIndex}_${i}`, x0 * scale + 5, y0 * scale + 12);
- context.fillStyle = 'white';
- }
-
- // 保存页面图像
- const pageImageName = `${pageIndex}.png`;
- const pageImagePath = path.join(outputDir, pageImageName);
-
- const pageBuffer = await sharp(canvas.toBuffer('image/png')).png().toBuffer();
- await fs.writeFile(pageImagePath, pageBuffer);
-
- pageImage = pageImageName;
- }
-
- imageInfos.push({
- pageImage,
- rectImages
- });
- }
-
- return imageInfos;
-};
-
-/**
- * 直接生成PDF文档的所有页面图像,不依赖区域识别
- * @param {Buffer|string} pdfData PDF文件数据或路径
- * @param {string} outputDir 输出目录
- * @param {number} scale 缩放比例
- * @returns {Promise>} 生成的图像文件路径数组
- */
-export const generateFullPageImages = async (pdfData, outputDir, scale = 3) => {
- // 确保输出目录存在
- await fs.ensureDir(outputDir);
-
- // 如果pdfData是字符串,则当作路径处理
- let data;
- if (typeof pdfData === 'string') {
- data = new Uint8Array(await fs.readFile(pdfData));
- } else {
- data = pdfData;
- }
-
- // 加载PDF文档
- const pdfDocument = await getDocument({ data }).promise;
- const numPages = pdfDocument.numPages;
- console.log(`PDF文档共 ${numPages} 页`);
-
- // 存储生成的图像路径
- const pageImages = [];
-
- // 处理每一页
- for (let i = 0; i < numPages; i++) {
- const pageIndex = i + 1;
- console.log(`处理第 ${pageIndex} 页...`);
-
- // 获取页面
- const page = await pdfDocument.getPage(pageIndex);
- const viewport = page.getViewport({ scale });
-
- // 创建canvas
- const canvas = createCanvas(viewport.width, viewport.height);
- const context = canvas.getContext('2d');
-
- // 填充白色背景
- context.fillStyle = '#ffffff';
- context.fillRect(0, 0, viewport.width, viewport.height);
-
- // 渲染页面
- await page.render({
- canvasContext: context,
- viewport: viewport
- }).promise;
-
- // 保存为图像
- const imageName = `page_${pageIndex}.png`;
- const imagePath = path.join(outputDir, imageName);
-
- // 将canvas转换为图像并保存
- const buffer = await sharp(canvas.toBuffer('image/png')).png().toBuffer();
- await fs.writeFile(imagePath, buffer);
-
- // 添加到结果数组
- pageImages.push({"index":pageIndex,"path":imagePath});
-
- console.log(`页面 ${pageIndex} 已保存到: ${imagePath}`);
- }
-
- return pageImages;
-};
-
-export default {
- renderRectToImage,
- generateImagesFromPdf,
- generateFullPageImages
-};
diff --git a/src/index.js b/src/index.js
deleted file mode 100644
index 57a197a..0000000
--- a/src/index.js
+++ /dev/null
@@ -1,265 +0,0 @@
-/**
- * PDF2MD 主入口模块
- * 提供PDF转Markdown的完整功能
- */
-import fs from 'fs-extra';
-import path from 'path';
-import { parsePdfRects } from './pdfParser.js';
-import { generateImagesFromPdf, generateFullPageImages } from './imageGenerator.js';
-import { convertImagesToMarkdown } from './markdownConverter.js';
-import { ensureDir, removeFile, extractMdFromLLMOutput, adjustMarkdownHeadings, getOldMarkdownHeadings } from './utils.js';
-import ModelClient from './modelClient.js';
-
-/**
- * 将PDF文件解析为Markdown
- * @param {string} pdfPath PDF文件路径
- * @param {Object} options 配置选项
- * @returns {Object} 处理结果 { content, imageFiles }
- */
-/**
- * 将PDF文件解析为Markdown,使用全页图像识别
- * @param {string} pdfPath PDF文件路径
- * @param {Object} options 配置选项
- * @returns {Object} 处理结果 { content, imageFiles, mdFilePath }
- */
-export const parsePdfFullPage = async (pdfPath, options = {}) => {
- const {
- outputDir = './output',
- apiKey,
- baseUrl,
- openAiApicompatible = false,
- model = 'gpt-4-vision-preview',
- prompt = `使用markdown语法,将图片中识别到的文字转换为markdown格式输出。你必须做到:
- 1. 输出和使用识别到的图片的相同的语言,例如,识别到英语的字段,输出的内容必须是英语。
- 2. 不要解释和输出无关的文字,直接输出图片中的内容。
- 3. 内容不要包含在\`\`\`markdown \`\`\`中、段落公式使用 $$ $$ 的形式、行内公式使用 $ $ 的形式。
- 4. 忽略掉页眉页脚里的内容
- 5. 请不要对图片的标题进行markdown的格式化,直接以文本形式输出到内容中。
- 6. 有可能每页都会出现期刊名称,论文名称,会议名称或者书籍名称,请忽略他们不要识别成标题
- 7. 请精确分析当前PDF页面的文本结构和视觉布局,按以下要求处理:
- 1. 识别所有标题文本,并判断其层级(根据字体大小、加粗、位置等视觉特征)
- 2. 输出为带层级的Markdown格式,严格使用以下规则:
- - 一级标题:字体最大/顶部居中,前面加 #
- - 二级标题:字体较大/左对齐加粗,有可能是数字开头也有可能是罗马数组开头,前面加 ##
- - 三级标题:字体稍大/左对齐加粗,前面加 ###
- - 正文文本:直接转换为普通段落
- 3. 不确定层级的标题请标记[?]
- 4. 如果是中文文献,但是有英文标题和摘要可以省略不输出
- 示例输出:
- ## 4研究方法
- ### 4.1数据收集
- 本文采用问卷调查...`,
- textPrompt = `你是一个专业的文本结构化处理助手,擅长根据前缀规则和标题语义分析并优化Markdown文档的标题层级结构。请根据以下要求处理我提供的Markdown标题:
- ## 任务描述
- 请根据markdown文章标题的实际含义,以及标题的前缀特征调整各级标题的正确层级关系,具体要求如下:
- 1. 一般相同格式的前缀的标题是同级关系({title}代表实际的标题内容):
- 例如:
- 纯数字前缀开头\`1 {title}\`, \` 2 {title}\` ,\` 3 {title}\`,\` 4 {title}\`,\` 5 {title}\` ... 等
- 罗马数字前缀开头的\`I {title}\`,\`II {title}\` ,\`III {title}\`,\`IV {title}\`,\`V {title}\` ... 等
- 小数点分隔数组前缀开头 \`1.1 {title}\`, \`1.2 {title}\`, \`1.3 {title}\`.... \`2.1 {title}\`, \`2.2 {title}\` 等
- 2. 将子标题正确嵌套到父标题下(如\`1.1 {title}\`应作为\`1 {title}\`的子标题)
- 3. 剔除与文章内容无关的标题
- 4. 保持输出标题内容与输入完全一致
- 5. 确保内容无缺失
- 6. 如果是中文文献,但有英文的文章题目,可以省略
-
- ## 输入输出格式
- - 输入:包含错误层级关系的markdown标题结构
- - 输出:修正后的标准markdown标题层级结构
-
- ## 处理原则
- 1. 严格根据标题语义确定所属关系
- 2. 仅调整层级不修改原标题文本
- 3. 无关标题直接移除不保留占位
- 4. 相同前缀规则的标题必须是同一级别,不能出现 一部分是 n级标题,一部分是其他级别的标题
-
- ## 输出要求
- 请将修正后的完整标题结构放在代码块中返回,格式示例如下:
-
- 期望输出:
- \`\`\`markdown
-
- \`\`\`
-
- 请处理以下数据:
- `,
- verbose = false,
- scale = 3,
- concurrency = 2,
- onProgress
- } = options;
-
- // 确保输出目录存在
- await ensureDir(outputDir);
-
- console.log('开始解析PDF文件(全页模式):', pdfPath);
-
- try {
- // 第一步:生成全页图像
- console.log('生成全页图像...');
- const imageOutputDir = path.join(outputDir, 'pages');
- await ensureDir(imageOutputDir);
-
- const imageFiles = await generateFullPageImages(pdfPath, imageOutputDir, scale);
-
- //先把总页数传递回调用方法
- if(onProgress){
- onProgress({
- current: 0,
- total: imageFiles.length,
- taskStatus: "starting"
- });
- }
-
- // 第二步:使用视觉模型处理每个页面图像
- console.log('处理全页图像...');
-
- // 创建模型客户端
- const modelClient = new ModelClient({
- apiKey,
- baseUrl,
- model,
- openAiApicompatible
- });
-
- const pageContents = [];
- const processImages = async item => {
- console.log(`处理页面 ${item.index}/${imageFiles.length}: ${path.basename(item.path)}`);
- try {
- // 处理图像 - 确保传入有效的prompt
- const defaultPrompt = '请将图像中的所有文本内容转换为Markdown格式,包括标题、段落、列表和表格等。';
- const pageContent = await modelClient.processImage(item.path, prompt || defaultPrompt);
- // 添加页面内容
- pageContents.push({
- pageIndex: item.index,
- content: pageContent
- });
- // 处理完成后,更新调用者的信息
- if(onProgress){
- onProgress({
- current: pageContents.length,
- total: imageFiles.length,
- taskStatus: "running"
- });
- }
- return { success: true, item, data: pageContent };
- } catch (error) {
- console.error('Markdown 转换失败:', error);
- return { success: false, item, error: error.message };
- }
- }
-
- // 并行处理所有问题,最多同时处理5个
- await processInParallel(imageFiles, processImages, concurrency);
-
- //并行处理生成结果是乱序的,根据pageIndex进行排序再输出Markdown
- pageContents.sort((a, b) => a.pageIndex - b.pageIndex);
-
- // 第三步:生成Markdown文件
- console.log('生成Markdown文档...');
-
- // 生成Markdown内容
- let content = '';
- for (const page of pageContents) {
- content += page.content;
- }
-
- console.log("正在重新调整目录...");
-
- // 提取转换后的标题
- const title = await getOldMarkdownHeadings(content);
-
- //使用大模型重新调整目录结构
- const convertedTitleLLMResult = await modelClient.processImage(null, textPrompt + JSON.stringify(title) || defaultPrompt);
- const convertedTitle = await extractMdFromLLMOutput(convertedTitleLLMResult);
-
- //根据调整后的结果重新生成md文件
- const convertContent = await adjustMarkdownHeadings(content, convertedTitle);
-
- console.log("目录调整完成...");
-
- // 第四步:保存Markdown文件
- const mdFilePath = path.join(outputDir, path.basename(pdfPath, '.pdf') + '.md');
- await fs.writeFile(mdFilePath, convertContent);
- console.log('Markdown文件已保存至:', mdFilePath);
-
- // 第五步:清理临时图像文件(如果不需要保留)
- if (!verbose) {
- console.log('清理临时文件...');
- for (const imagePath of imageFiles) {
- await removeFile(imagePath.path);
- }
- }
-
- // 将任务执行结束传递回调用方法
- if(onProgress){
- onProgress({
- current: imageFiles.length,
- total: imageFiles.length,
- taskStatus:"finished"
- });
- }
-
- return {
- content,
- mdFilePath,
- imageFiles
- };
- } catch (error) {
- console.error('PDF解析过程中发生错误:', error);
- throw error;
- }
-};
-
-/**
- * 将PDF文件解析为Markdown(使用区域识别)
- * @param {string} pdfPath PDF文件路径
- * @param {Object} options 配置选项
- * @returns {Object} 处理结果 { content, imageFiles }
- */
-/**
- * 将PDF文件解析为Markdown
- * @param {string} pdfPath PDF文件路径
- * @param {Object} options 配置选项
- * @returns {Object} 处理结果 { content, imageFiles, mdFilePath }
- */
-export const parsePdf = async (pdfPath, options = {}) => {
- // 直接使用全页图像处理,不再使用子图
- return parsePdfFullPage(pdfPath, options);
-};
-
-// 并行处理数组的辅助函数,限制并发数
-const processInParallel = async (items, processFunction, concurrencyLimit) => {
- const results = [];
- const inProgress = new Set();
- const queue = [...items];
-
- while (queue.length > 0 || inProgress.size > 0) {
- // 如果有空闲槽位且队列中还有任务,启动新任务
- while (inProgress.size < concurrencyLimit && queue.length > 0) {
- const item = queue.shift();
- const promise = processFunction(item).then(result => {
- inProgress.delete(promise);
- return result;
- });
- inProgress.add(promise);
- results.push(promise);
- }
-
- // 等待其中一个任务完成
- if (inProgress.size > 0) {
- await Promise.race(inProgress);
- }
- }
-
- return Promise.all(results);
-};
-
-
-/**
- * PDF2MD模块导出
- */
-export default {
- parsePdf,
- parsePdfFullPage
-};
diff --git a/src/markdownConverter.js b/src/markdownConverter.js
deleted file mode 100644
index e1a8a0a..0000000
--- a/src/markdownConverter.js
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * Markdown转换模块,使用模型客户端将图像转换为Markdown
- */
-import fs from 'fs-extra';
-import path from 'path';
-import ModelClient from './modelClient.js';
-
-// 默认提示词(中文版)
-const DEFAULT_PROMPT = `使用markdown语法,将图片中识别到的文字转换为markdown格式输出。你必须做到:
-1. 输出和使用识别到的图片的相同的语言,例如,识别到英语的字段,输出的内容必须是英语。
-2. 不要解释和输出无关的文字,直接输出图片中的内容。例如,严禁输出 "以下是我根据图片内容生成的markdown文本:"这样的例子,而是应该直接输出markdown。
-3. 内容不要包含在\`\`\`markdown \`\`\`中、段落公式使用 $$ $$ 的形式、行内公式使用 $ $ 的形式、忽略掉长直线、忽略掉页码。
-再次强调,不要解释和输出无关的文字,直接输出图片中的内容。`;
-
-// 默认区域提示词(中文版)
-const DEFAULT_RECT_PROMPT = `图片中用红色框和名称(%s)标注出了一些区域。如果区域是表格或者图片,使用 ![]() 的形式插入到输出内容中,否则直接输出文字内容。`;
-
-// 此处移除DEFAULT_ROLE_PROMPT,它已经被迁移到modelClient.js
-
-/**
- * 处理单个图像并转换为Markdown
- * @param {ModelClient} modelClient 模型客户端实例
- * @param {string} imagePath 图像文件路径
- * @param {string} prompt 提示词
- * @param {Object} options 模型选项
- * @returns {string} Markdown内容
- */
-export const processImageToMarkdown = async (modelClient, imagePath, prompt, options = {}) => {
- return modelClient.processImage(imagePath, prompt, options);
-};
-
-/**
- * 处理一组图像并合并成完整的Markdown
- * @param {Array} imageInfos 图像信息数组 [{ pageImage, rectImages }, ...]
- * @param {string} outputDir 输出目录
- * @param {Object} options 配置选项
- * @returns {string} 合并后的Markdown内容
- */
-export const convertImagesToMarkdown = async (imageInfos, outputDir, options) => {
- const {
- apiKey,
- baseUrl,
- model = 'gpt-4-vision-preview',
- prompt: customPrompt,
- rectPrompt: customRectPrompt,
- verbose = false,
- concurrency = 1,
- modelConfig = {}
- } = options;
-
- // 创建模型客户端
- const modelClient = new ModelClient({
- apiKey,
- baseUrl,
- model,
- modelConfig
- });
-
- // 使用自定义提示词或默认提示词
- const prompt = customPrompt || DEFAULT_PROMPT;
- const rectPrompt = customRectPrompt || DEFAULT_RECT_PROMPT;
-
- // 存储每个图像的Markdown内容
- const markdownParts = [];
-
- // 处理每个页面的图像
- for (let pageIndex = 0; pageIndex < imageInfos.length; pageIndex++) {
- const { pageImage, rectImages } = imageInfos[pageIndex];
- console.log(`处理页面 ${pageIndex + 1} 的 ${rectImages.length} 个区域图像`);
-
- // 处理页面上的每个区域图像
- const tasks = rectImages.map(async (rectImage, rectIndex) => {
- const imagePath = path.join(outputDir, rectImage);
- const imageName = `${pageIndex}_${rectIndex}`;
-
- // 构建提示词
- const fullPrompt = prompt + '\n' + rectPrompt.replace('%s', imageName);
-
- try {
- // 处理图像
- const markdown = await processImageToMarkdown(modelClient, imagePath, fullPrompt, { model });
- return { rectIndex, markdown };
- } catch (error) {
- console.error(`处理图像 ${imageName} 失败:`, error);
- return { rectIndex, markdown: `` };
- }
- });
-
- // 并行处理图像(根据并发度)
- const results = [];
- for (let i = 0; i < tasks.length; i += concurrency) {
- const batch = tasks.slice(i, i + concurrency);
- const batchResults = await Promise.all(batch);
- results.push(...batchResults);
- }
-
- // 按原始顺序整理结果
- const sortedResults = results.sort((a, b) => a.rectIndex - b.rectIndex);
- const pageMarkdownParts = sortedResults.map(result => result.markdown);
-
- // 添加页面标记
- // markdownParts.push(`\n\n`);
- markdownParts.push(...pageMarkdownParts);
- // markdownParts.push(`\n\n\n\n`);
- }
-
- // 合并所有Markdown内容
- return markdownParts.join('\n\n');
-};
-
-export default {
- processImageToMarkdown,
- convertImagesToMarkdown,
- DEFAULT_PROMPT,
- DEFAULT_RECT_PROMPT
-};
diff --git a/src/modelClient.js b/src/modelClient.js
deleted file mode 100644
index d9fc696..0000000
--- a/src/modelClient.js
+++ /dev/null
@@ -1,370 +0,0 @@
-/**
- * 模型客户端模块,用于处理不同视觉模型的API调用
- */
-import fs from 'fs-extra';
-import path from 'path';
-import https from 'https';
-import http from 'http';
-import { promisify } from 'util';
-
-// 默认角色提示词(中文版)
-const DEFAULT_ROLE_PROMPT = `你是一个PDF文档解析器,使用markdown和latex语法输出图片的内容。`;
-
-/**
- * 模型客户端类,处理与不同视觉模型的交互
- */
-export class ModelClient {
- /**
- * 创建模型客户端实例
- * @param {Object} config 配置对象
- * @param {string} config.apiKey OpenAI API密钥
- * @param {string} [config.baseUrl] 自定义API基础URL
- * @param {string} [config.model='gpt-4-vision-preview'] 默认使用的模型
- * @param {Object} [config.modelConfig={}] 模型特定配置
- */
- constructor(config) {
- this.config = {
- model: 'gpt-4-vision-preview',
- modelConfig: {},
- ...config
- };
-
- // 初始化模型客户端
- this.initClient();
- }
-
- /**
- * 初始化模型客户端
- * @private
- */
- initClient() {
- const { apiKey } = this.config;
-
- if (!apiKey) {
- throw new Error('必须提供API密钥');
- }
-
- // 不再创建SDK实例,而是保存必要的配置信息用于API调用
- this.apiKey = apiKey;
- }
-
- /**
- * 处理图像并转换为Markdown文本
- * @param {string} imagePath 图像文件路径
- * @param {string} prompt 提示词
- * @param {Object} [options={}] 附加选项
- * @param {string} [options.model] 覆盖默认模型
- * @param {string} [options.rolePrompt] 覆盖默认角色提示词
- * @param {number} [options.maxTokens] 最大生成token数
- * @param {string} [options.endpoint] 自定义API端点
- * @returns {Promise} Markdown文本
- */
- async processImage(imagePath, prompt, options = {}) {
- const {
- model = this.config.model,
- rolePrompt = DEFAULT_ROLE_PROMPT,
- maxTokens = 4096,
- endpoint = this.config.baseUrl
- } = options;
-
- // 读取图像文件
- let base64Image = null;
- if (imagePath) {
- const imageBuffer = await fs.readFile(imagePath);
- base64Image = imageBuffer.toString('base64');
- }
-
-
- // 根据不同模型类型调用对应API
- if (model.startsWith('gpt-4') || model.startsWith('gpt-3.5')) {
- return this.callOpenAIAPI(model, rolePrompt, prompt, base64Image, maxTokens, endpoint);
- } else if (model.startsWith('claude') && !this.config.openAiApicompatible) {
- return this.callClaudeAPI(model, rolePrompt, prompt, base64Image, maxTokens, endpoint);
- } else if (model.startsWith('gemini') && !this.config.openAiApicompatible) {
- return this.callGeminiAPI(model, rolePrompt, prompt, base64Image, maxTokens, endpoint);
- } else if (model.startsWith('doubao') && !this.config.openAiApicompatible) {
- return this.callDoubaoAPI(model, rolePrompt, prompt, base64Image, maxTokens, endpoint);
- } else {
- // 默认使用OpenAI
- return this.callOpenAIAPI(model, rolePrompt, prompt, base64Image, maxTokens, endpoint);
- }
- }
-
- /**
- * 通过API调用OpenAI视觉模型
- * @private
- */
- async callOpenAIAPI(model, rolePrompt, prompt, base64Image, maxTokens, endpoint) {
- // 使用OpenAI API
- const apiEndpoint = endpoint || 'https://api.openai.com/v1/chat/completions';
-
- // 构建用户消息内容
- const userContent = [{ type: 'text', text: prompt }];
-
- // 如果有base64图片,添加图片内容
- if (base64Image) {
- userContent.push({
- type: 'image_url',
- image_url: {
- url: `data:image/png;base64,${base64Image}`
- }
- });
- }
-
- const requestData = {
- model,
- messages: [
- {
- role: 'system',
- content: rolePrompt
- },
- {
- role: 'user',
- content: userContent
- }
- ],
- max_tokens: maxTokens
- };
-
- const response = await this.makeHttpRequest(apiEndpoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': `Bearer ${this.apiKey}`
- },
- body: JSON.stringify(requestData)
- });
-
- if (response.error) {
- throw new Error(`OpenAI API调用失败: ${response.error.message || JSON.stringify(response.error)}`);
- }
-
- return response.choices[0].message.content;
- }
-
- /**
- * 通过API调用Claude视觉模型
- * @private
- */
- async callClaudeAPI(model, rolePrompt, prompt, base64Image, maxTokens, endpoint) {
- // 使用Claude API
- const apiEndpoint = endpoint || 'https://api.anthropic.com/v1/messages';
-
- // 构建消息内容
- const messageContent = [{ type: 'text', text: prompt }];
-
- // 如果有base64图片,添加图片内容
- if (base64Image) {
- messageContent.push({
- type: 'image',
- source: {
- type: 'base64',
- media_type: 'image/png',
- data: base64Image
- }
- });
- }
-
- const requestData = {
- model,
- system: rolePrompt,
- max_tokens: maxTokens,
- messages: [
- {
- role: 'user',
- content: messageContent
- }
- ]
- };
-
- const response = await this.makeHttpRequest(apiEndpoint, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'x-api-key': this.apiKey,
- 'anthropic-version': '2023-06-01'
- },
- body: JSON.stringify(requestData)
- });
-
- if (response.error) {
- throw new Error(`Claude API调用失败: ${response.error.message || JSON.stringify(response.error)}`);
- }
-
- return response.content[0].text;
- }
-
- /**
- * 通过API调用Gemini视觉模型
- * @private
- */
- async callGeminiAPI(model, rolePrompt, prompt, base64Image, maxTokens, endpoint) {
- // 使用Google Gemini API
- const apiEndpoint = endpoint || `https://generativelanguage.googleapis.com/v1/models/${model}:generateContent`;
-
- // 构建消息部分
- const parts = [
- { text: `${rolePrompt}\n${prompt}` } // 合并系统提示和用户提示
- ];
-
- // 如果有base64图片,添加图片内容
- if (base64Image) {
- parts.push({
- inline_data: {
- mime_type: 'image/png', // 可以根据实际情况调整MIME类型
- data: base64Image
- }
- });
- }
-
- const requestData = {
- contents: [{
- parts: parts
- }],
- generation_config: {
- max_output_tokens: maxTokens
- }
- };
-
- // Gemini API使用URL参数传递API密钥
- const fullUrl = `${apiEndpoint}?key=${this.apiKey}`;
-
- const response = await this.makeHttpRequest(fullUrl, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(requestData)
- });
-
- if (response.error) {
- throw new Error(`Gemini API调用失败: ${response.error.message || JSON.stringify(response.error)}`);
- }
-
- return response.candidates[0].content.parts[0].text;
- }
-
- /**
- * 通过API调用豆包视觉模型
- * @private
- */
- async callDoubaoAPI(model, rolePrompt, prompt, base64Image, maxTokens, endpoint) {
- // 使用豆包API
- const apiEndpoint = endpoint || 'https://ark.cn-beijing.volces.com/api/v3';
-
- // 构建用户消息内容
- const userContent = [{ type: 'text', text: prompt }];
-
- // 如果有base64图片,添加图片内容
- if (base64Image) {
- userContent.push({
- type: 'image_url',
- image_url: {
- url: `data:image/png;base64,${base64Image}`
- }
- });
- }
-
- const requestData = {
- model,
- messages: [
- {
- role: 'system',
- content: rolePrompt
- },
- {
- role: 'user',
- content: userContent
- }
- ],
- max_tokens: maxTokens // 添加max_tokens参数
- };
-
- const response = await this.makeHttpRequest(endpoint.endsWith('/chat/completions') ? apiEndpoint : `${apiEndpoint}/chat/completions`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Content-Length': Buffer.byteLength(JSON.stringify(requestData)),
- 'Authorization': `Bearer ${this.apiKey}`
- },
- body: JSON.stringify(requestData)
- });
-
- if (response.error) {
- throw new Error(`豆包API调用失败: ${response.error.message || JSON.stringify(response.error)}`);
- }
-
- return response.choices[0].message.content;
- }
-
- /**
- * 通用HTTP请求方法
- * @param {string} url API端点URL
- * @param {Object} options 请求选项
- * @returns {Promise} API响应对象
- * @private
- */
- makeHttpRequest(url, options) {
- return new Promise((resolve, reject) => {
- const urlObj = new URL(url);
- const client = urlObj.protocol === 'https:' ? https : http;
- const requestOptions = {
- method: options.method || 'GET',
- headers: options.headers || {},
- hostname: urlObj.hostname,
- port: urlObj.port || (urlObj.protocol === 'https:' ? 443 : 80),
- path: urlObj.pathname + urlObj.search
- };
- const req = client.request(requestOptions, (res) => {
- let data = '';
- res.on('data', (chunk) => {
- data += chunk;
- });
-
- res.on('end', () => {
- try {
- if (res.statusCode >= 200 && res.statusCode < 300) {
- const parsedData = JSON.parse(data);
- resolve(parsedData);
- } else {
- reject(new Error(`请求失败,状态码: ${res.statusCode}, 响应: ${data}`));
- }
- } catch (e) {
- reject(new Error(`API响应解析失败: ${e.message}, 原始响应: ${data}`));
- }
- });
- });
-
- req.on('error', (error) => {
- reject(new Error(`请求失败: ${error.message}`));
- });
-
- if (options.body) {
- req.write(options.body);
- }
-
- req.end();
- });
- }
-
- /**
- * 获取支持的模型列表
- * @returns {Array} 支持的模型列表
- */
- getSupportedModels() {
- return [
- // OpenAI视觉模型
- 'gpt-4-vision-preview',
- 'gpt-4o',
- // Claude视觉模型
- 'claude-3-opus-20240229',
- 'claude-3-sonnet-20240229',
- // Gemini模型
- 'gemini-pro-vision',
- // 豆包模型
- 'doubao-1.5-vision-pro-32k-250115'
- ];
- }
-}
-
-export default ModelClient;
diff --git a/src/pdfParser.js b/src/pdfParser.js
deleted file mode 100644
index 5c5cf9b..0000000
--- a/src/pdfParser.js
+++ /dev/null
@@ -1,177 +0,0 @@
-/**
- * PDF解析模块,负责从PDF文件中提取文本和图像信息
- */
-import pkg from 'pdfjs-dist/legacy/build/pdf.js';
-const { getDocument, OPS } = pkg;
-import { createRect } from './utils.js';
-import { mergeRects, adsorbRectsToRects, filterSmallRects } from './rectProcessor.js';
-import fs from 'fs-extra';
-import path from 'path';
-
-/**
- * 解析PDF页面,识别区域
- * @param {Object} page PDF.js页面对象
- * @returns {Array} 识别出的区域坐标数组 [[x0, y0, x1, y1], ...]
- */
-export const parseRects = async (page) => {
- console.log('\n开始解析页面区域...');
- // 获取页面尺寸
- const viewport = page.getViewport({ scale: 1.0 });
- console.log(`页面尺寸: ${viewport.width} x ${viewport.height}`);
-
- // 提取文本内容
- const textContent = await page.getTextContent();
-
- // 创建文本区域的矩形列表
- const textRects = textContent.items.map(item => {
- const { str, transform } = item;
- // 获取文本项的位置和尺寸
- const x = transform[4];
- const y = transform[5];
- const width = item.width || 0;
- const height = item.height || 12; // 默认高度
-
- // 创建文本区域矩形
- return {
- rect: createRect([x, viewport.height - y - height, x + width, viewport.height - y]),
- text: str,
- isLarge: str.length / Math.max(1, str.split('\n').length) > 5 // 判断是否为大文本块
- };
- });
-
- // 分离大文本和小文本区域
- const largeTextRects = textRects.filter(item => item.isLarge).map(item => item.rect);
- const smallTextRects = textRects.filter(item => !item.isLarge).map(item => item.rect);
- console.log(`创建了 ${textRects.length} 个文本区域,其中大文本 ${largeTextRects.length} 个,小文本 ${smallTextRects.length} 个`);
-
- // 获取操作列表,找出图像和绘图元素
- const operatorList = await page.getOperatorList();
- console.log(`提取到 ${operatorList.fnArray.length} 个操作`);
-
- // 提取图像和绘图元素
- const drawingRects = [];
- const imageRects = [];
-
- for (let i = 0; i < operatorList.fnArray.length; i++) {
- const fn = operatorList.fnArray[i];
- const args = operatorList.argsArray[i];
-
- // 处理绘图操作
- if (fn === OPS.stroke || fn === OPS.fill) {
- // 简化处理:假设前面有一个矩形路径定义
- if (i > 0 && operatorList.fnArray[i - 1] === OPS.constructPath) {
- const pathArgs = operatorList.argsArray[i - 1];
- // 简化:仅处理第一个矩形
- if (pathArgs.length >= 2 && pathArgs[0].length >= 4) {
- const coords = pathArgs[0].slice(0, 4);
- // 创建矩形,简化处理
- const rect = createRect([
- coords[0],
- viewport.height - coords[1],
- coords[2],
- viewport.height - coords[3]
- ]);
-
- // 忽略小的水平线
- const bbox = rect.bbox;
- const isShortLine = Math.abs(bbox[3] - bbox[1]) < 1 && Math.abs(bbox[2] - bbox[0]) < 30;
-
- if (!isShortLine) {
- drawingRects.push(rect);
- }
- }
- }
- }
-
- // 处理图像操作
- if (fn === OPS.paintImageXObject) {
- // 简化:假设前面有setTransform操作
- if (i > 0 && operatorList.fnArray[i - 1] === OPS.setTransform) {
- const transform = operatorList.argsArray[i - 1];
- // 简化:根据变换矩阵创建近似的矩形
- const x = transform[4];
- const y = transform[5];
- const width = transform[0] * 100; // 简化估计
- const height = transform[3] * 100; // 简化估计
-
- const rect = createRect([
- x,
- viewport.height - y - height,
- x + width,
- viewport.height - y
- ]);
-
- imageRects.push(rect);
- }
- }
- }
-
- // 合并所有矩形
- let allRects = [...drawingRects, ...imageRects, ...largeTextRects, ...smallTextRects];
- console.log(`提取到 ${drawingRects.length} 个绘图区域、${imageRects.length} 个图像区域、${largeTextRects.length} 个大文本区域和 ${smallTextRects.length} 个小文本区域`);
-
- // 合并相近的矩形 - 增加合并阈值以确保文本不被截断
- let mergedRects = mergeRects(allRects, 25, 150); // 将距离阈值从10增加到25,高度阈值从100增加到150
- console.log(`合并后有 ${mergedRects.length} 个区域`);
-
- // 如果有绘图或图像区域,才进行吸附
- let updatedMergedRects = mergedRects;
- if (drawingRects.length > 0 || imageRects.length > 0) {
- // 将大文本区域吸附到合并后的矩形
- let [_, temp] = adsorbRectsToRects(largeTextRects, mergedRects, 0.1);
- updatedMergedRects = temp;
-
- // 将小文本区域吸附到更新后的矩形
- [_, updatedMergedRects] = adsorbRectsToRects(smallTextRects, updatedMergedRects, 5);
- }
-
- // 再次合并相近的矩形
- mergedRects = mergeRects(updatedMergedRects, 10);
-
- // 过滤掉太小的矩形 - 减小过滤阈值以保留更多区域
- mergedRects = filterSmallRects(mergedRects, 15, 10); // 降低尺寸阈值,从20x20高度改为15x10
- console.log(`过滤小矩形后剩下 ${mergedRects.length} 个区域`);
-
- // 将矩形转换为坐标数组
- const result = mergedRects.map(rect => {
- const bbox = rect.bbox;
- return [bbox[0], bbox[1], bbox[2], bbox[3]];
- });
-
- console.log(`最终返回 ${result.length} 个区域`);
- return result;
-};
-
-/**
- * 从PDF文件解析出所有页面的区域
- * @param {string} pdfPath PDF文件路径
- * @returns {Array} 每个页面的区域信息 [{ pageIndex, rects: [[x0, y0, x1, y1], ...] }, ...]
- */
-export const parsePdfRects = async (pdfPath) => {
- // 加载PDF文档
- const data = new Uint8Array(await fs.readFile(pdfPath));
- const pdf = await getDocument({ data }).promise;
-
- const pageCount = pdf.numPages;
- const results = [];
-
- // 处理每一页
- for (let i = 1; i <= pageCount; i++) {
- const page = await pdf.getPage(i);
- const rects = await parseRects(page);
-
- results.push({
- pageIndex: i - 1,
- rects
- });
-
- console.log(`处理页面 ${i}/${pageCount},找到 ${rects.length} 个区域`);
- }
-
- return results;
-};
-
-export default {
- parseRects,
- parsePdfRects
-};
diff --git a/src/rectProcessor.js b/src/rectProcessor.js
deleted file mode 100644
index c85600c..0000000
--- a/src/rectProcessor.js
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * 矩形区域处理模块,用于合并和处理PDF中的矩形区域
- */
-import * as turf from '@turf/turf';
-import { isNear, isHorizontalNear, unionRects, createRect, isValidRect } from './utils.js';
-
-/**
- * 合并矩形列表中相近的矩形
- * @param {Array} rectList 矩形列表
- * @param {number} distance 合并距离阈值
- * @param {number|null} horizontalDistance 水平合并距离阈值
- * @returns {Array} 合并后的矩形列表
- */
-export const mergeRects = (rectList, distance = 20, horizontalDistance = null) => {
- try {
- // 防止空列表
- if (!rectList || !Array.isArray(rectList) || rectList.length === 0) {
- return [];
- }
-
- // 预处理:过滤无效矩形
- let validRects = rectList.filter(rect => rect && isValidRect(rect));
- if (validRects.length === 0) {
- return [];
- }
-
- // 复制数组,避免修改原数组
- let workingRects = [...validRects];
- let merged = true;
-
- while (merged && workingRects.length > 0) {
- merged = false;
- const newRectList = [];
-
- while (workingRects.length > 0) {
- let rect = workingRects.shift();
- if (!rect) continue; // 跳过空值
-
- for (let i = 0; i < workingRects.length; i++) {
- const otherRect = workingRects[i];
- if (!otherRect) continue; // 跳过空值
-
- if (isNear(rect, otherRect, distance) ||
- (horizontalDistance && isHorizontalNear(rect, otherRect, horizontalDistance))) {
- // 合并矩形
- const mergedRect = unionRects(rect, otherRect);
- if (mergedRect) {
- rect = mergedRect;
- // 从列表中移除已合并的矩形
- workingRects.splice(i, 1);
- i--; // 调整索引
- merged = true;
- }
- }
- }
-
- if (rect) {
- newRectList.push(rect);
- }
- }
-
- workingRects = newRectList;
- }
-
- // 过滤无效的矩形
- return workingRects.filter(rect => rect && isValidRect(rect));
- } catch (error) {
- console.error('合并矩形时出错:', error.message);
- return [];
- }
-};
-
-/**
- * 将源矩形列表吸附到目标矩形列表
- * @param {Array} sourceRects 源矩形列表
- * @param {Array} targetRects 目标矩形列表
- * @param {number} distance 吸附距离阈值
- * @returns {Array} [未吸附的源矩形列表, 更新后的目标矩形列表]
- */
-export const adsorbRectsToRects = (sourceRects, targetRects, distance = 10) => {
- const newSourceRects = [];
- const updatedTargetRects = [...targetRects];
-
- for (const rect of sourceRects) {
- let adsorbed = false;
-
- for (let i = 0; i < updatedTargetRects.length; i++) {
- if (isNear(rect, updatedTargetRects[i], distance)) {
- // 合并矩形
- updatedTargetRects[i] = unionRects(rect, updatedTargetRects[i]);
- adsorbed = true;
- break;
- }
- }
-
- if (!adsorbed) {
- newSourceRects.push(rect);
- }
- }
-
- return [newSourceRects, updatedTargetRects];
-};
-
-/**
- * 将几何对象数组转换为矩形的坐标数组
- * @param {Array} rects 几何对象数组
- * @returns {Array} 矩形坐标数组 [[x0, y0, x1, y1], ...]
- */
-export const rectsToCoordinates = (rects) => {
- return rects.map(rect => {
- const bbox = turf.bbox(rect);
- return [bbox[0], bbox[1], bbox[2], bbox[3]];
- });
-};
-
-/**
- * 过滤掉太小的矩形
- * @param {Array} rects 矩形列表
- * @param {number} minWidth 最小宽度
- * @param {number} minHeight 最小高度
- * @returns {Array} 过滤后的矩形列表
- */
-export const filterSmallRects = (rects, minWidth = 20, minHeight = 20) => {
- return rects.filter(rect => {
- const bbox = turf.bbox(rect);
- const width = bbox[2] - bbox[0];
- const height = bbox[3] - bbox[1];
- return width > minWidth && height > minHeight;
- });
-};
-
-export default {
- mergeRects,
- adsorbRectsToRects,
- rectsToCoordinates,
- filterSmallRects
-};
diff --git a/src/utils.js b/src/utils.js
deleted file mode 100644
index 745c72a..0000000
--- a/src/utils.js
+++ /dev/null
@@ -1,301 +0,0 @@
-/**
- * 工具函数模块,提供常用的辅助功能
- */
-import fs from 'fs-extra';
-import path from 'path';
-import * as turf from '@turf/turf';
-
-/**
- * 确保目录存在,不存在则创建
- * @param {string} directory 目录路径
- */
-export const ensureDir = async (directory) => {
- await fs.ensureDir(directory);
-};
-
-/**
- * 创建矩形几何对象
- * @param {Array} bounds [x0, y0, x1, y1] 表示矩形的左上和右下坐标
- * @returns {Object} turf几何对象
- */
-export const createRect = (bounds) => {
- const [x0, y0, x1, y1] = bounds;
- // 创建一个矩形几何对象
- return turf.bboxPolygon([x0, y0, x1, y1]);
-};
-
-/**
- * 计算两个矩形之间的距离
- * @param {Object} rect1 第一个矩形
- * @param {Object} rect2 第二个矩形
- * @param {number} buffer 缓冲区大小
- * @returns {number} 距离
- */
-export const getDistance = (rect1, rect2, buffer = 0.1) => {
- // 直接使用几何计算来获取距离
- const bbox1 = turf.bbox(rect1);
- const bbox2 = turf.bbox(rect2);
-
- // 计算矩形之间的距离
- // 如果矩形重叠,返回0
- if (bbox1[0] <= bbox2[2] && bbox2[0] <= bbox1[2] && bbox1[1] <= bbox2[3] && bbox2[1] <= bbox1[3]) {
- return 0;
- }
-
- // 计算水平和垂直方向的距离
- let dx = 0;
- let dy = 0;
-
- if (bbox1[2] < bbox2[0]) {
- dx = bbox2[0] - bbox1[2]; // rect1在rect2的左边
- } else if (bbox2[2] < bbox1[0]) {
- dx = bbox1[0] - bbox2[2]; // rect1在rect2的右边
- }
-
- if (bbox1[3] < bbox2[1]) {
- dy = bbox2[1] - bbox1[3]; // rect1在rect2的上边
- } else if (bbox2[3] < bbox1[1]) {
- dy = bbox1[1] - bbox2[3]; // rect1在rect2的下边
- }
-
- // 计算欧几里得距离
- return Math.sqrt(dx * dx + dy * dy) - buffer * 2;
-};
-
-/**
- * 检查两个矩形是否足够接近
- * @param {Object} rect1 第一个矩形
- * @param {Object} rect2 第二个矩形
- * @param {number} distance 距离阈值
- * @returns {boolean} 是否接近
- */
-export const isNear = (rect1, rect2, distance = 20) => {
- try {
- // 检查矩形是否有效
- if (!rect1 || !rect2) return false;
-
- // 计算距离
- const dist = getDistance(rect1, rect2);
-
- // 返回是否小于阈值
- return dist < distance;
- } catch (error) {
- console.error('检查矩形接近性时出错:', error.message);
- return false;
- }
-};
-
-/**
- * 检查两个矩形是否在水平方向上接近
- * @param {Object} rect1 第一个矩形
- * @param {Object} rect2 第二个矩形
- * @param {number} distance 距离阈值
- * @returns {boolean} 是否水平接近
- */
-export const isHorizontalNear = (rect1, rect2, distance = 100) => {
- try {
- // 检查矩形是否有效
- if (!rect1 || !rect2) return false;
-
- const bbox1 = turf.bbox(rect1);
- const bbox2 = turf.bbox(rect2);
-
- // 获取矩形的高度和宽度
- const height1 = bbox1[3] - bbox1[1];
- const height2 = bbox2[3] - bbox2[1];
- const width1 = bbox1[2] - bbox1[0];
- const width2 = bbox2[2] - bbox2[0];
-
- // 判断是否为水平线(高度很小,宽度较大)
- const isHorizontalLine1 = height1 < 2 && width1 > 10;
- const isHorizontalLine2 = height2 < 2 && width2 > 10;
-
- // 如果两个矩形都是水平线
- if (isHorizontalLine1 && isHorizontalLine2) {
- // 检查水平方向上是否重叠或接近
- const horizontalOverlap = (
- (bbox1[0] <= bbox2[2] && bbox2[0] <= bbox1[2]) || // x方向重叠
- Math.abs(bbox1[0] - bbox2[0]) < 5 || // 左边界接近
- Math.abs(bbox1[2] - bbox2[2]) < 5 // 右边界接近
- );
-
- // 如果水平方向重叠或接近,检查垂直距离
- if (horizontalOverlap) {
- const verticalDistance = Math.min(
- Math.abs(bbox1[1] - bbox2[3]),
- Math.abs(bbox1[3] - bbox2[1])
- );
- return verticalDistance < distance;
- }
- }
-
- return false;
- } catch (error) {
- console.error('检查水平接近性时出错:', error.message);
- return false;
- }
-};
-
-/**
- * 合并两个矩形
- * @param {Object} rect1 第一个矩形
- * @param {Object} rect2 第二个矩形
- * @returns {Object} 合并后的矩形
- */
-export const unionRects = (rect1, rect2) => {
- try {
- // 检查矩形是否有效
- if (!rect1 && !rect2) return null;
- if (!rect1) return rect2;
- if (!rect2) return rect1;
-
- // 获取边界框
- const bbox1 = turf.bbox(rect1);
- const bbox2 = turf.bbox(rect2);
-
- // 创建一个包含两个矩形的最小矩形
- const minX = Math.min(bbox1[0], bbox2[0]);
- const minY = Math.min(bbox1[1], bbox2[1]);
- const maxX = Math.max(bbox1[2], bbox2[2]);
- const maxY = Math.max(bbox1[3], bbox2[3]);
-
- // 创建新的矩形
- return turf.bboxPolygon([minX, minY, maxX, maxY]);
- } catch (error) {
- console.error('合并矩形时出错:', error.message);
- return null;
- }
-};
-
-/**
- * 生成随机文件名
- * @param {string} prefix 前缀
- * @param {string} extension 文件扩展名
- * @returns {string} 随机文件名
- */
-export const generateRandomFileName = (prefix = 'img', extension = 'png') => {
- return `${prefix}_${Date.now()}_${Math.floor(Math.random() * 10000)}.${extension}`;
-};
-
-/**
- * 删除文件
- * @param {string} filePath 文件路径
- */
-export const removeFile = async (filePath) => {
- try {
- await fs.remove(filePath);
- } catch (error) {
- console.error(`删除文件 ${filePath} 失败:`, error);
- }
-};
-
-/**
- * 判断矩形是否有效
- * @param {Object} rect 矩形对象
- * @returns {boolean} 是否有效
- */
-export const isValidRect = (rect) => {
- try {
- // 检查是否为空
- if (!rect) return false;
-
- // 检查是否有效的几何对象
- if (!rect.type || !rect.geometry) {
- // 如果不是GeoJSON对象,尝试获取其边界框
- const bbox = turf.bbox(rect);
- // 检查边界框是否有效
- return bbox && bbox.length === 4 &&
- bbox[0] <= bbox[2] && bbox[1] <= bbox[3] && // 确保坐标正确
- (bbox[2] - bbox[0]) > 0 && (bbox[3] - bbox[1]) > 0; // 确保矩形有面积
- }
-
- return true;
- } catch (error) {
- console.error('检查矩形有效性时出错:', error.message);
- return false;
- }
-};
-
-// 从 LLM 输出中提取标题
-export const extractMdFromLLMOutput = (output) => {
- const mdStart = output.indexOf('```markdown');
- const mdEnd = output.lastIndexOf('```');
- if (mdStart !== -1 && mdEnd !== -1) {
- const mdString = output.substring(mdStart + 12, mdEnd)
- return mdString;
- } else {
- console.error('模型未按标准格式输出:', output);
- return undefined;
- }
-}
-
-//获取优化前的 markdwon 标题
-export const getOldMarkdownHeadings = (markdownText) => {
- const title = [];
- const lines = markdownText.split('\n');
- lines.forEach((line) => {
- // 匹配 # 开头,并捕获后面的内容
- const match = line.match(/^#+\s*(.*)/);
- if (match) {
- title.push(line);
- }
- })
- return title.join('\n');;
-}
-
-//根据新生成的标题结构,重新设置原文章中标题级别
-export const adjustMarkdownHeadings = (markdownText, newTitle) => {
- const map = createTitleLevelMap(newTitle);
- const lines = markdownText.split('\n');
- const processedLines = [];
- lines.forEach((line) => {
- // 匹配 # 开头,并捕获后面的内容
- const match = line.match(/^#+\s*(.*)/);
- if (!match) {
- processedLines.push(line);
- return;
- }
- const content = match ? match[1] : line;
- // 检查 content 是否在 map 中存在
- let newLine = line;
- if (map.has(content)) {
- const level = map.get(content);
- // 生成对应数量的 #(例如 level=2 -> "##")
- const hashes = '#'.repeat(level);
- newLine = `${hashes} ${content}`;
- console.log("转换前:" + line + "===>转换后" + newLine);
- }
- processedLines.push(newLine);
- });
- return processedLines.join('\n');
-}
-
-//根据标题#数量,建立内容和数量的map映射
-function createTitleLevelMap(data, map = new Map()) {
- const lines = data.split('\n');
- for (const line of lines) {
- // 匹配以#开头的标题行
- const headerMatch = line.match(/^(#+)\s*(.+)/);
- if (headerMatch) {
- const level = headerMatch[1].length; // #号的数量
- const text = headerMatch[2].trim(); // #号后的文本内容
- map.set(text, level);
- }
- }
- return map;
-}
-
-export default {
- ensureDir,
- createRect,
- getDistance,
- isNear,
- isHorizontalNear,
- unionRects,
- generateRandomFileName,
- removeFile,
- isValidRect,
- extractMdFromLLMOutput,
- adjustMarkdownHeadings,
- getOldMarkdownHeadings
-};
diff --git a/test/README.md b/test/README.md
deleted file mode 100644
index ac76fb1..0000000
--- a/test/README.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# 模型测试工具使用说明
-
-这个测试工具用于测试不同视觉模型的处理能力,方便您对比和选择最适合PDF转Markdown任务的模型。
-
-## 准备工作
-
-1. 创建测试图片目录:
-```bash
-mkdir -p test/images
-```
-
-2. 将测试图片放入 `test/images` 目录中(支持PNG、JPG格式)
-
-3. 设置环境变量(可选):
-```bash
-# OpenAI API密钥
-export OPENAI_API_KEY=sk-your-key
-
-# Claude API密钥
-export ANTHROPIC_API_KEY=sk-ant-your-key
-
-# Gemini API密钥
-export GEMINI_API_KEY=your-key
-
-# 豆包API密钥
-export DOUBAO_API_KEY=your-key
-```
-
-## 运行测试
-
-```bash
-node test/testModel.js
-```
-
-## 功能说明
-
-1. **选择模型**:支持多种视觉模型,包括OpenAI、Claude、Gemini和豆包
-2. **选择测试图片**:从test/images目录中选择要测试的图片
-3. **选择提示词模板**:提供多种预设的提示词模板,也可以自定义提示词
-4. **保存结果**:可以将处理结果保存到test/results目录中,方便对比不同模型的效果
-
-## 支持的模型
-
-- GPT-4 Vision Preview (OpenAI)
-- GPT-4o (OpenAI)
-- Claude 3 Opus (Anthropic)
-- Claude 3 Sonnet (Anthropic)
-- Gemini Pro Vision (Google)
-- 豆包 1.5 Vision Pro (ByteDance)
-
-## 提示词模板
-
-- **default**: 默认的PDF转Markdown提示词
-- **simple**: 简单描述图片内容
-- **detailed**: 详细分析图片内容,包括文本、图表、公式等
-
-## 结果对比
-
-测试结果会保存在 `test/results` 目录中,文件名格式为 `{模型ID}_{时间戳}.md`,方便您对比不同模型的处理效果。
diff --git a/test/images/test.png b/test/images/test.png
deleted file mode 100644
index 8ed3fdf..0000000
Binary files a/test/images/test.png and /dev/null differ
diff --git a/test/results/doubao-1.5-vision-pro-32k-250115_2025-03-30T03-03-21-341Z.md b/test/results/doubao-1.5-vision-pro-32k-250115_2025-03-30T03-03-21-341Z.md
deleted file mode 100644
index c015eff..0000000
--- a/test/results/doubao-1.5-vision-pro-32k-250115_2025-03-30T03-03-21-341Z.md
+++ /dev/null
@@ -1,9 +0,0 @@
-## 二、营销危机的解决方案——故事化营销
-### 1. 为什么是故事拯救营销?
-最早的人类,通过自我意识、他者意识、记忆、智慧、想象力、洞察力、关联能力和自我表达能力,将发生的现实在头脑中转化成故事来总结并与他人分享经验。
-
-人类从故事中就可以汲取生活经验用于现实生活,所以人本能地就喜欢故事,这也就是为什么说故事是最适合人类心智的学习工具的原因,因此故事可以作为一个切入口成为有效的营销工具。
-
-### 2. 什么是故事?
-#### (1)故事的定义
-所有的故事都是叙事,但并不是所有的叙事都是故事。零部件的堆砌不是故事、公司层级制度展示不是故事、大事记不是故事、被动的流水账也不是故事。
\ No newline at end of file
diff --git a/test/testFullImageGeneration.js b/test/testFullImageGeneration.js
deleted file mode 100644
index c8784f0..0000000
--- a/test/testFullImageGeneration.js
+++ /dev/null
@@ -1,145 +0,0 @@
-/**
- * 完整PDF到图像转换测试
- * 用于测试将PDF文件及其识别出的区域转换为图像
- */
-import fs from 'fs-extra';
-import path from 'path';
-import { fileURLToPath } from 'url';
-import pkg from 'pdfjs-dist/legacy/build/pdf.js';
-const { getDocument } = pkg;
-import { renderRectToImage, generateImagesFromPdf } from '../src/imageGenerator.js';
-import { parsePdfRects } from '../src/pdfParser.js';
-
-// 获取当前文件的目录
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-
-// 设置PDF.js的worker路径
-try {
- const pdfjsWorker = path.join(__dirname, '..', 'node_modules/pdfjs-dist/legacy/build/pdf.worker.js');
- const pdfjsWorkerUrl = new URL(`file://${pdfjsWorker}`).href;
-
- // 全局设置worker路径
- globalThis.pdfjsWorkerSrc = pdfjsWorkerUrl;
-
- console.log('设置PDF.js worker路径:', pdfjsWorkerUrl);
-} catch (error) {
- console.warn('设置PDF.js worker路径时出错:', error.message);
-}
-
-// 测试配置
-const CONFIG = {
- // 测试PDF文件路径
- pdfPath: path.join(__dirname, 'samples', '2.pdf'),
-
- // 输出目录
- outputDir: path.join(__dirname, 'output', 'full_images'),
-
- // 是否绘制边界框
- drawBoundingBox: true,
-
- // 缩放比例
- scale: 2
-};
-
-/**
- * 测试完整的PDF到图像转换流程
- */
-async function testFullPdfToImage() {
- console.log('=== 测试完整的PDF到图像转换流程 ===');
-
- try {
- // 确保输出目录存在
- await fs.ensureDir(CONFIG.outputDir);
-
- // 检查PDF文件是否存在
- if (!await fs.pathExists(CONFIG.pdfPath)) {
- console.error(`错误: 测试PDF文件不存在: ${CONFIG.pdfPath}`);
- console.log('请将测试PDF文件放在 test/samples 目录下,并更新 CONFIG.pdfPath');
- return;
- }
-
- console.log(`加载PDF文件: ${CONFIG.pdfPath}`);
-
- // 第一步:解析PDF获取所有区域
- console.log('\n步骤1: 解析PDF获取所有区域...');
- const startParseTime = Date.now();
- const pageRects = await parsePdfRects(CONFIG.pdfPath);
- const endParseTime = Date.now();
-
- if (!pageRects || pageRects.length === 0) {
- console.log('未找到有效区域,测试结束');
- return;
- }
-
- console.log(`解析完成,耗时: ${(endParseTime - startParseTime) / 1000}秒`);
- console.log(`共 ${pageRects.length} 页`);
-
- // 记录矩形数量
- let totalRects = 0;
- for (const { pageIndex, rects } of pageRects) {
- console.log(`页面 ${pageIndex + 1}: ${rects.length} 个矩形`);
- totalRects += rects.length;
- }
- console.log(`总计 ${totalRects} 个矩形`);
-
- // 第二步:生成所有区域的图像
- console.log('\n步骤2: 生成所有区域的图像...');
- const startGenTime = Date.now();
- const imageInfos = await generateImagesFromPdf(
- CONFIG.pdfPath,
- pageRects,
- CONFIG.outputDir,
- CONFIG.drawBoundingBox,
- CONFIG.scale
- );
- const endGenTime = Date.now();
-
- console.log(`图像生成完成,耗时: ${(endGenTime - startGenTime) / 1000}秒`);
-
- // 输出图像生成结果
- console.log(`\n生成了 ${imageInfos.length} 页的图像:`);
-
- let totalImages = 0;
- for (let i = 0; i < imageInfos.length; i++) {
- const { pageImage, rectImages } = imageInfos[i];
- console.log(`页面 ${i + 1}:`);
-
- // 输出页面图像路径
- console.log(` 页面图像: ${pageImage}`);
-
- // 输出区域图像路径
- console.log(` 区域图像 (${rectImages.length} 个):`);
- for (let j = 0; j < rectImages.length; j++) {
- console.log(` - ${rectImages[j]}`);
- }
-
- totalImages += rectImages.length + 1; // +1 是页面图像
- }
-
- console.log(`\n总共生成了 ${totalImages} 张图像,包括 ${imageInfos.length} 张完整页面图像和 ${totalImages - imageInfos.length} 张区域图像`);
- console.log(`所有图像已保存到: ${CONFIG.outputDir}`);
-
- } catch (error) {
- console.error('测试过程中发生错误:', error);
- }
-
- console.log('');
-}
-
-/**
- * 主函数
- */
-async function main() {
- console.log('开始测试完整的PDF到图像转换...\n');
-
- // 测试完整流程
- await testFullPdfToImage();
-
- console.log('PDF到图像转换测试完成');
-}
-
-// 运行测试
-main().catch(error => {
- console.error('测试过程中发生错误:', error);
-});
diff --git a/test/testFullPageImages.js b/test/testFullPageImages.js
deleted file mode 100644
index e8d98f0..0000000
--- a/test/testFullPageImages.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * 测试直接生成整页PDF图像功能
- * 不使用区域识别,简化处理流程
- */
-
-import fs from 'fs-extra';
-import path from 'path';
-import { fileURLToPath } from 'url';
-import { generateFullPageImages } from '../src/imageGenerator.js';
-
-// 获取当前文件的目录
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-
-// 测试配置
-const CONFIG = {
- // 测试PDF文件路径
- pdfPath: path.join(__dirname, 'samples', '2.pdf'),
-
- // 输出目录
- outputDir: path.join(__dirname, 'output', 'full_pages'),
-
- // 缩放比例
- scale: 3
-};
-
-/**
- * 测试整页PDF图像生成
- */
-async function testFullPageImageGeneration() {
- console.log('=== 测试整页PDF图像生成 ===');
-
- try {
- // 确保输出目录存在
- await fs.ensureDir(CONFIG.outputDir);
-
- // 检查PDF文件是否存在
- if (!await fs.pathExists(CONFIG.pdfPath)) {
- console.error(`错误: 测试PDF文件不存在: ${CONFIG.pdfPath}`);
- return;
- }
-
- console.log(`加载PDF文件: ${CONFIG.pdfPath}`);
-
- // 开始时间
- const startTime = Date.now();
-
- // 执行转换
- const imageFiles = await generateFullPageImages(
- CONFIG.pdfPath,
- CONFIG.outputDir,
- CONFIG.scale
- );
-
- // 结束时间
- const endTime = Date.now();
-
- // 输出结果
- console.log(`\n转换完成,耗时: ${(endTime - startTime) / 1000}秒`);
- console.log(`生成了 ${imageFiles.length} 个页面图像:`);
-
- for (const file of imageFiles) {
- console.log(`- ${file}`);
- }
-
- console.log(`\n所有图像已保存到: ${CONFIG.outputDir}`);
-
- } catch (error) {
- console.error('测试过程中发生错误:', error);
- }
-}
-
-/**
- * 主函数
- */
-async function main() {
- console.log('开始测试整页PDF图像生成...\n');
-
- // 测试整页图像生成
- await testFullPageImageGeneration();
-
- console.log('整页PDF图像生成测试完成');
-}
-
-// 执行测试
-main().catch(error => {
- console.error('执行测试时发生错误:', error);
-});
diff --git a/test/testFullProcess.js b/test/testFullProcess.js
deleted file mode 100644
index 5e3dfae..0000000
--- a/test/testFullProcess.js
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * 完整流程测试
- * 用于测试PDF转Markdown的整个流程
- */
-import fs from 'fs';
-import path from 'path';
-import { fileURLToPath } from 'url';
-import { parsePdf } from '../src/index.js';
-
-// 获取当前文件的目录
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-
-// 定义进度状态
-const progressState = { current: 0, total: 0, taskStatus: "pending" };
-
-// 测试配置
-const CONFIG = {
- // 测试PDF文件路径
- pdfPath: path.join(__dirname, 'samples', '2.pdf'),
-
- // 输出目录
- outputDir: path.join(__dirname, 'output'),
-
- // API密钥 (从环境变量获取或手动设置)
- apiKey: process.env.DOUBAO_API_KEY || '',
-
- // 模型配置
- model: 'doubao-1.5-vision-pro-32k-250115',
- endpoint: 'https://ark.cn-beijing.volces.com/api/v3/',
-
- // 使用全页模式
- useFullPage: true,
-
- // 是否保留中间生成的图像文件
- verbose: true,
-
- // 并发处理数量
- concurrency: 5
-};
-
-/**
- * 测试完整的PDF转Markdown流程
- */
-async function testFullProcess() {
- console.log('=== 测试完整的PDF转Markdown流程 ===');
-
- try {
- // 确保输出目录存在
- if (!fs.existsSync(CONFIG.outputDir)) {
- fs.mkdirSync(CONFIG.outputDir, { recursive: true });
- }
-
- // 检查PDF文件是否存在
- if (!fs.existsSync(CONFIG.pdfPath)) {
- console.error(`错误: 测试PDF文件不存在: ${CONFIG.pdfPath}`);
- console.log('请将测试PDF文件放在 test/samples 目录下,并更新 CONFIG.pdfPath');
- return;
- }
-
- console.log(`处理PDF文件: ${CONFIG.pdfPath}`);
- console.log(`使用模型: ${CONFIG.model}`);
-
- // 开始处理
- const startTime = Date.now();
-
- let parseResult = null;
-
- parsePdf(CONFIG.pdfPath, {
- outputDir: CONFIG.outputDir,
- apiKey: CONFIG.apiKey,
- baseUrl: CONFIG.endpoint,
- model: CONFIG.model,
- verbose: CONFIG.verbose,
- gptWorker: CONFIG.concurrency,
- useFullPage: CONFIG.useFullPage, // 添加useFullPage参数
- concurrency: CONFIG.concurrency,
- //增加处理进度结果回调
- onProgress: ({ current, total, taskStatus }) => {
- progressState.current = current;
- progressState.total = total;
- progressState.taskStatus = taskStatus;
- }
- }).then(result => {
- parseResult = result;
- });
-
- // 如果需要主动查询
- await new Promise((resolve) => {
- const interval = setInterval(() => {
- console.log(`[主动查询] 进度: ${progressState.current}/${progressState.total},${progressState.taskStatus}`);
- if (progressState.taskStatus === "finished") {
- clearInterval(interval);
- resolve();
- }
- }, 1000);
- });
-
- const endTime = Date.now();
-
- console.log(`\n处理完成,耗时: ${(endTime - startTime) / 1000}秒`);
- console.log(`生成的Markdown文件: ${parseResult.mdFilePath}`);
- console.log(`生成的图像文件数量: ${parseResult.imageFiles.length}`);
-
- // 显示Markdown内容预览
- const mdContent = fs.readFileSync(parseResult.mdFilePath, 'utf-8');
- const previewLength = Math.min(500, mdContent.length);
-
- console.log('\nMarkdown内容预览:');
- console.log('-----------------------------------');
- console.log(mdContent.substring(0, previewLength) + (mdContent.length > previewLength ? '...' : ''));
- console.log('-----------------------------------');
-
- } catch (error) {
- console.error('处理PDF时发生错误:', error);
- }
-}
-
-/**
- * 主函数
- */
-async function main() {
- console.log('开始测试完整流程...\n');
-
- // 测试完整流程
- await testFullProcess();
-
- console.log('\n完整流程测试完成');
-}
-
-// 运行测试
-main();
diff --git a/test/testImageGenerator.js b/test/testImageGenerator.js
deleted file mode 100644
index b1bdfab..0000000
--- a/test/testImageGenerator.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * 图像生成模块测试
- * 用于测试PDF区域转图像功能
- */
-import fs from 'fs';
-import path from 'path';
-import { fileURLToPath } from 'url';
-import { getDocument } from 'pdfjs-dist/legacy/build/pdf.js';
-import { renderRectToImage } from '../src/imageGenerator.js';
-
-// 获取当前文件的目录
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-
-// 设置PDF.js的worker路径
-try {
- // 3.x 版本的设置方式
- const pdfjsWorker = path.join(__dirname, '..', 'node_modules/pdfjs-dist/legacy/build/pdf.worker.js');
- const pdfjsWorkerUrl = new URL(`file://${pdfjsWorker}`).href;
-
- // 全局设置worker路径
- globalThis.pdfjsWorkerSrc = pdfjsWorkerUrl;
-
- console.log('设置PDF.js worker路径:', pdfjsWorkerUrl);
-} catch (error) {
- console.warn('设置PDF.js worker路径时出错:', error.message);
-}
-
-// 测试配置
-const CONFIG = {
- // 测试PDF文件路径
- pdfPath: path.join(__dirname, 'samples', 'sample.pdf'),
-
- // 输出目录
- outputDir: path.join(__dirname, 'output'),
-
- // 测试区域 [x0, y0, x1, y1]
- testRect: [100, 100, 300, 200]
-};
-
-/**
- * 测试渲染PDF区域为图像
- */
-async function testRenderRectToImage() {
- console.log('=== 测试渲染PDF区域为图像 ===');
-
- try {
- // 确保输出目录存在
- if (!fs.existsSync(CONFIG.outputDir)) {
- fs.mkdirSync(CONFIG.outputDir, { recursive: true });
- }
-
- // 检查PDF文件是否存在
- if (!fs.existsSync(CONFIG.pdfPath)) {
- console.error(`错误: 测试PDF文件不存在: ${CONFIG.pdfPath}`);
- console.log('请将测试PDF文件放在 test/samples 目录下,并更新 CONFIG.pdfPath');
- return;
- }
-
- console.log(`加载PDF文件: ${CONFIG.pdfPath}`);
-
- // 加载PDF文档
- const data = new Uint8Array(fs.readFileSync(CONFIG.pdfPath));
- const pdfDocument = await getDocument({ data }).promise;
-
- console.log(`PDF加载成功,共 ${pdfDocument.numPages} 页`);
-
- // 获取第一页
- const page = await pdfDocument.getPage(1);
-
- console.log(`渲染区域: [${CONFIG.testRect.join(', ')}]`);
-
- // 渲染区域为图像
- const imageBuffer = await renderRectToImage(page, CONFIG.testRect, 2);
-
- // 保存图像
- const outputPath = path.join(CONFIG.outputDir, 'test_rect.png');
- fs.writeFileSync(outputPath, imageBuffer);
-
- console.log(`图像已保存到: ${outputPath}`);
- console.log(`图像大小: ${(imageBuffer.length / 1024).toFixed(2)} KB`);
-
- } catch (error) {
- console.error('渲染区域为图像时发生错误:', error);
- }
-
- console.log('');
-}
-
-/**
- * 主函数
- */
-async function main() {
- console.log('开始测试图像生成模块...\n');
-
- // 测试渲染区域为图像
- await testRenderRectToImage();
-
- console.log('图像生成模块测试完成');
-}
-
-// 运行测试
-main();
diff --git a/test/testModel.js b/test/testModel.js
deleted file mode 100644
index a53c5f8..0000000
--- a/test/testModel.js
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * 简化版模型测试工具
- * 用于测试不同视觉模型的处理能力
- */
-import fs from 'fs';
-import path from 'path';
-import { fileURLToPath } from 'url';
-import ModelClient from '../src/modelClient.js';
-
-// 获取当前文件的目录
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-
-// 测试配置
-const CONFIG = {
- // 要测试的模型
- model: 'doubao-1.5-vision-pro-32k-250115', // 可选: gpt-4-vision-preview, gpt-4o, claude-3-opus-20240229, gemini-pro-vision
-
- // API密钥 (也可以从环境变量中获取)
- apiKey: process.env.DOUBAO_API_KEY || '',
-
- // 自定义API端点 (可选)
- endpoint: 'https://ark.cn-beijing.volces.com/api/v3/',
-
- // 测试图片路径
- imagePath: path.join(__dirname, 'images', 'test.png'),
-
- // 提示词
- prompt: `使用markdown语法,将图片中识别到的文字转换为markdown格式输出。你必须做到:
-1. 输出和使用识别到的图片的相同的语言,例如,识别到英语的字段,输出的内容必须是英语。
-2. 不要解释和输出无关的文字,直接输出图片中的内容。
-3. 内容不要包含在\`\`\`markdown \`\`\`中、段落公式使用 $$ $$ 的形式、行内公式使用 $ $ 的形式。`,
-
- // 是否保存结果到文件
- saveResult: true,
-
- // 结果保存目录
- resultsDir: path.join(__dirname, 'results')
-};
-
-/**
- * 保存结果到文件
- * @param {string} result 处理结果
- * @param {string} modelId 模型ID
- */
-async function saveResult(result, modelId) {
- // 确保结果目录存在
- if (!fs.existsSync(CONFIG.resultsDir)) {
- fs.mkdirSync(CONFIG.resultsDir, { recursive: true });
- }
-
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
- const filename = `${modelId}_${timestamp}.md`;
- const filePath = path.join(CONFIG.resultsDir, filename);
-
- fs.writeFileSync(filePath, result);
- console.log(`\n结果已保存到: ${filePath}`);
-}
-
-/**
- * 主函数
- */
-async function main() {
- try {
- console.log('=== 视觉模型测试工具 (简化版) ===\n');
-
- // 确保测试图片存在
- if (!fs.existsSync(CONFIG.imagePath)) {
- console.error(`错误: 测试图片不存在: ${CONFIG.imagePath}`);
- console.log('请将测试图片放在 test/images 目录下,并更新 CONFIG.imagePath');
- return;
- }
-
- console.log(`测试模型: ${CONFIG.model}`);
- console.log(`测试图片: ${path.basename(CONFIG.imagePath)}`);
-
- // 创建模型客户端
- const modelClient = new ModelClient({
- apiKey: CONFIG.apiKey,
- model: CONFIG.model,
- endpoint: CONFIG.endpoint
- });
-
- console.log('\n开始处理图像...');
-
- // 处理图像
- const startTime = Date.now();
- const result = await modelClient.processImage(CONFIG.imagePath, CONFIG.prompt, {
- model: CONFIG.model,
- endpoint: CONFIG.endpoint
- });
- const endTime = Date.now();
-
- console.log(`\n处理完成,耗时: ${(endTime - startTime) / 1000}秒`);
- console.log('\n=== 处理结果 ===\n');
- console.log(result);
-
- // 保存结果
- if (CONFIG.saveResult) {
- await saveResult(result, CONFIG.model);
- }
-
- } catch (error) {
- console.error('发生错误:', error);
- }
-}
-
-// 运行主函数
-main();
\ No newline at end of file
diff --git a/test/testPdfParser.js b/test/testPdfParser.js
deleted file mode 100644
index 729ebfd..0000000
--- a/test/testPdfParser.js
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- * PDF解析模块测试
- * 用于测试PDF文件解析和区域识别功能
- */
-import fs from 'fs';
-import path from 'path';
-import { fileURLToPath } from 'url';
-import pkg from 'pdfjs-dist/legacy/build/pdf.js';
-const { getDocument } = pkg;
-import { parseRects, parsePdfRects } from '../src/pdfParser.js';
-
-// 获取当前文件的目录
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-
-// 设置PDF.js的worker路径
-try {
- const pdfjsWorker = path.join(__dirname, '..', 'node_modules/pdfjs-dist/legacy/build/pdf.worker.js');
- const pdfjsWorkerUrl = new URL(`file://${pdfjsWorker}`).href;
-
- // 全局设置worker路径
- globalThis.pdfjsWorkerSrc = pdfjsWorkerUrl;
-
- console.log('设置PDF.js worker路径:', pdfjsWorkerUrl);
-} catch (error) {
- console.warn('设置PDF.js worker路径时出错:', error.message);
-}
-
-// 测试配置
-const CONFIG = {
- // 测试PDF文件路径
- pdfPath: path.join(__dirname, 'samples', '1.pdf'),
-
- // 输出目录
- outputDir: path.join(__dirname, 'output')
-};
-
-/**
- * 测试PDF区域识别功能
- */
-async function testParseRects() {
- console.log('=== 测试PDF区域识别功能 ===');
-
- try {
- // 确保输出目录存在
- if (!fs.existsSync(CONFIG.outputDir)) {
- fs.mkdirSync(CONFIG.outputDir, { recursive: true });
- }
-
- // 检查PDF文件是否存在
- if (!fs.existsSync(CONFIG.pdfPath)) {
- console.error(`错误: 测试PDF文件不存在: ${CONFIG.pdfPath}`);
- console.log('请将测试PDF文件放在 test/samples 目录下,并更新 CONFIG.pdfPath');
- return;
- }
-
- console.log(`加载PDF文件: ${CONFIG.pdfPath}`);
-
- // 加载PDF文档
- const data = new Uint8Array(fs.readFileSync(CONFIG.pdfPath));
- const pdf = await getDocument({ data }).promise;
-
- console.log(`PDF加载成功,共 ${pdf.numPages} 页`);
-
- // 处理每一页
- for (let i = 1; i <= Math.min(pdf.numPages, 3); i++) {
- console.log(`\n处理第 ${i} 页...`);
-
- // 获取页面
- const page = await pdf.getPage(i);
-
- // 解析区域
- const startTime = Date.now();
- const rects = await parseRects(page);
- const endTime = Date.now();
-
- console.log(`识别出 ${rects.length} 个区域,耗时: ${(endTime - startTime) / 1000}秒`);
-
- // 输出前5个区域的坐标
- if (rects.length > 0) {
- console.log('前5个区域的坐标:');
- rects.slice(0, 5).forEach((rect, index) => {
- console.log(` 区域 ${index + 1}: [${rect.map(v => v.toFixed(2)).join(', ')}]`);
- });
- }
-
- // 保存区域信息到JSON文件
- const outputPath = path.join(CONFIG.outputDir, `page_${i}_rects.json`);
- fs.writeFileSync(outputPath, JSON.stringify(rects, null, 2));
- console.log(`区域信息已保存到: ${outputPath}`);
- }
-
- } catch (error) {
- console.error('解析PDF区域时发生错误:', error);
- }
-
- console.log('');
-}
-
-/**
- * 主函数
- */
-async function main() {
- console.log('开始测试PDF解析模块...\n');
-
- // 测试PDF区域识别
- await testParseRects();
-
- console.log('PDF解析模块测试完成');
-}
-
-// 运行测试
-main();
diff --git a/test/testRectProcessor.js b/test/testRectProcessor.js
deleted file mode 100644
index 34e893a..0000000
--- a/test/testRectProcessor.js
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * 矩形处理模块测试
- * 用于测试矩形合并、吸附等功能
- */
-import fs from 'fs';
-import path from 'path';
-import { fileURLToPath } from 'url';
-import * as turf from '@turf/turf';
-import { mergeRects, adsorbRectsToRects, filterSmallRects } from '../src/rectProcessor.js';
-import { createRect } from '../src/utils.js';
-
-// 获取当前文件的目录
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-
-// 测试数据
-const TEST_RECTS = [
- // 两个相近的矩形
- createRect([10, 10, 30, 20]),
- createRect([32, 12, 50, 22]),
-
- // 两个远离的矩形
- createRect([100, 100, 120, 120]),
- createRect([200, 200, 220, 220]),
-
- // 一个水平线
- createRect([10, 50, 100, 51]),
-
- // 一个小矩形
- createRect([300, 300, 305, 305])
-];
-
-/**
- * 测试矩形合并功能
- */
-function testMergeRects() {
- console.log('=== 测试矩形合并功能 ===');
-
- // 测试1: 合并相近的矩形
- const mergedRects1 = mergeRects(TEST_RECTS.slice(0, 2), 5);
- console.log(`合并相近矩形 (距离=5): 期望合并成1个,实际合并成 ${mergedRects1.length} 个`);
-
- // 测试2: 不合并远离的矩形
- const mergedRects2 = mergeRects(TEST_RECTS.slice(2, 4), 5);
- console.log(`合并远离矩形 (距离=5): 期望保持2个,实际合并成 ${mergedRects2.length} 个`);
-
- // 测试3: 水平线合并
- const horizontalTestRects = [
- createRect([10, 50, 100, 51]),
- createRect([10, 80, 100, 81])
- ];
- const mergedRects3 = mergeRects(horizontalTestRects, 5, 50);
- console.log(`水平线合并 (水平距离=50): 期望合并成1个,实际合并成 ${mergedRects3.length} 个`);
-
- console.log('');
-}
-
-/**
- * 测试矩形吸附功能
- */
-function testAdsorbRects() {
- console.log('=== 测试矩形吸附功能 ===');
-
- // 源矩形
- const sourceRects = [
- createRect([15, 15, 25, 25]),
- createRect([150, 150, 160, 160])
- ];
-
- // 目标矩形
- const targetRects = [
- createRect([10, 10, 30, 30]),
- createRect([200, 200, 220, 220])
- ];
-
- // 测试吸附
- const [remainingSourceRects, updatedTargetRects] = adsorbRectsToRects(sourceRects, targetRects, 10);
-
- console.log(`吸附前: 源矩形=${sourceRects.length}个, 目标矩形=${targetRects.length}个`);
- console.log(`吸附后: 未吸附源矩形=${remainingSourceRects.length}个, 更新后目标矩形=${updatedTargetRects.length}个`);
-
- console.log('');
-}
-
-/**
- * 测试小矩形过滤功能
- */
-function testFilterSmallRects() {
- console.log('=== 测试小矩形过滤功能 ===');
-
- // 测试过滤
- const filteredRects = filterSmallRects(TEST_RECTS, 10, 10);
-
- console.log(`过滤前矩形数量: ${TEST_RECTS.length}`);
- console.log(`过滤后矩形数量: ${filteredRects.length}`);
-
- console.log('');
-}
-
-/**
- * 主函数
- */
-function main() {
- console.log('开始测试矩形处理模块...\n');
-
- // 测试矩形合并
- testMergeRects();
-
- // 测试矩形吸附
- testAdsorbRects();
-
- // 测试小矩形过滤
- testFilterSmallRects();
-
- console.log('矩形处理模块测试完成');
-}
-
-// 运行测试
-main();
diff --git a/test/testSimpleFullProcess.js b/test/testSimpleFullProcess.js
deleted file mode 100644
index acf8a4a..0000000
--- a/test/testSimpleFullProcess.js
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * 简化版完整流程测试
- * 使用整页图像功能,直接处理PDF页面
- */
-import fs from 'fs';
-import path from 'path';
-import { fileURLToPath } from 'url';
-import { generateFullPageImages } from '../src/imageGenerator.js';
-import { processImage } from '../src/modelClient.js';
-import { generateMarkdown } from '../src/markdownConverter.js';
-
-// 获取当前文件的目录
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-
-// 测试配置
-const CONFIG = {
- // 测试PDF文件路径
- pdfPath: path.join(__dirname, 'samples', 'sample.pdf'),
-
- // 输出目录
- outputDir: path.join(__dirname, 'output'),
-
- // 图像输出目录
- imageOutputDir: path.join(__dirname, 'output', 'pages'),
-
- // API密钥 (从环境变量获取或手动设置)
- apiKey: process.env.DOUBAO_API_KEY || 'your-api-key-here',
-
- // 模型配置
- model: 'doubao-1.5-vision-pro-32k-250115',
- endpoint: 'https://ark.cn-beijing.volces.com/api/v3/',
-
- // 是否保留中间生成的图像文件
- verbose: true,
-
- // 缩放比例
- scale: 3
-};
-
-/**
- * 简化版PDF转Markdown流程
- */
-async function simpleFullProcess() {
- console.log('=== 测试简化版PDF转Markdown流程 ===');
-
- try {
- // 确保输出目录存在
- if (!fs.existsSync(CONFIG.outputDir)) {
- fs.mkdirSync(CONFIG.outputDir, { recursive: true });
- }
-
- if (!fs.existsSync(CONFIG.imageOutputDir)) {
- fs.mkdirSync(CONFIG.imageOutputDir, { recursive: true });
- }
-
- // 检查PDF文件是否存在
- if (!fs.existsSync(CONFIG.pdfPath)) {
- console.error(`错误: 测试PDF文件不存在: ${CONFIG.pdfPath}`);
- console.log('请将测试PDF文件放在 test/samples 目录下,并更新 CONFIG.pdfPath');
- return;
- }
-
- console.log(`处理PDF文件: ${CONFIG.pdfPath}`);
- console.log(`使用模型: ${CONFIG.model}`);
-
- // 步骤1: 生成整页图像
- console.log('\n步骤1: 生成整页图像...');
- const startImageTime = Date.now();
- const imageFiles = await generateFullPageImages(
- CONFIG.pdfPath,
- CONFIG.imageOutputDir,
- CONFIG.scale
- );
- const endImageTime = Date.now();
- console.log(`生成整页图像完成,耗时: ${(endImageTime - startImageTime) / 1000}秒`);
- console.log(`共生成 ${imageFiles.length} 张页面图像`);
-
- // 步骤2: 处理每个页面图像
- console.log('\n步骤2: 使用视觉模型处理图像...');
- const startProcessTime = Date.now();
-
- const pageContents = [];
- for (let i = 0; i < imageFiles.length; i++) {
- const imagePath = imageFiles[i];
- console.log(`处理图像 ${i + 1}/${imageFiles.length}: ${path.basename(imagePath)}`);
-
- // 读取图像文件
- const imageData = fs.readFileSync(imagePath);
- const base64Image = imageData.toString('base64');
-
- // 调用模型处理图像
- const pageContent = await processImage(
- base64Image,
- CONFIG.model,
- CONFIG.apiKey,
- CONFIG.endpoint
- );
-
- // 添加页面内容
- pageContents.push({
- pageIndex: i,
- content: pageContent
- });
- }
-
- const endProcessTime = Date.now();
- console.log(`图像处理完成,耗时: ${(endProcessTime - startProcessTime) / 1000}秒`);
-
- // 步骤3: 生成Markdown文档
- console.log('\n步骤3: 生成Markdown文档...');
- const startMdTime = Date.now();
-
- // 生成Markdown文件名
- const pdfBaseName = path.basename(CONFIG.pdfPath, '.pdf');
- const mdFilePath = path.join(CONFIG.outputDir, `${pdfBaseName}_simple.md`);
-
- // 生成Markdown内容
- const mdContent = generateMarkdown(pageContents);
-
- // 保存Markdown文件
- fs.writeFileSync(mdFilePath, mdContent, 'utf-8');
-
- const endMdTime = Date.now();
- console.log(`Markdown生成完成,耗时: ${(endMdTime - startMdTime) / 1000}秒`);
-
- // 计算总耗时
- const totalTime = (endMdTime - startImageTime) / 1000;
-
- console.log(`\n处理完成,总耗时: ${totalTime}秒`);
- console.log(`生成的Markdown文件: ${mdFilePath}`);
- console.log(`生成的图像文件数量: ${imageFiles.length}`);
-
- // 显示Markdown内容预览
- const previewLength = Math.min(500, mdContent.length);
-
- console.log('\nMarkdown内容预览:');
- console.log('-----------------------------------');
- console.log(mdContent.substring(0, previewLength) + (mdContent.length > previewLength ? '...' : ''));
- console.log('-----------------------------------');
-
- return {
- mdFilePath,
- imageFiles
- };
-
- } catch (error) {
- console.error('处理PDF时发生错误:', error);
- }
-}
-
-/**
- * 主函数
- */
-async function main() {
- console.log('开始测试简化版完整流程...\n');
-
- // 测试简化版完整流程
- await simpleFullProcess();
-
- console.log('\n简化版完整流程测试完成');
-}
-
-// 运行测试
-main();
diff --git a/test/testSimpleImageGeneration.js b/test/testSimpleImageGeneration.js
deleted file mode 100644
index 44b135c..0000000
--- a/test/testSimpleImageGeneration.js
+++ /dev/null
@@ -1,156 +0,0 @@
-/**
- * 简化版PDF到图像转换测试
- * 这个版本只生成完整页面图像,不再分割为子图
- */
-
-const fs = require('fs-extra');
-const path = require('path');
-const { createCanvas } = require('canvas');
-const sharp = require('sharp');
-const pdfjsLib = require('pdfjs-dist/legacy/build/pdf.js');
-
-// 设置PDF.js的worker路径
-try {
- const pdfjsWorker = path.join(__dirname, '..', 'node_modules/pdfjs-dist/legacy/build/pdf.worker.js');
- const pdfjsWorkerUrl = new URL(`file://${pdfjsWorker}`).href;
-
- // 全局设置worker路径
- globalThis.pdfjsWorkerSrc = pdfjsWorkerUrl;
-
- console.log('设置PDF.js worker路径:', pdfjsWorkerUrl);
-} catch (error) {
- console.warn('设置PDF.js worker路径时出错:', error.message);
-}
-
-// 测试配置
-const CONFIG = {
- // 测试PDF文件路径
- pdfPath: path.join(__dirname, 'samples', '1.pdf'),
-
- // 输出目录
- outputDir: path.join(__dirname, 'output', 'simple_images'),
-
- // 缩放比例 - 可以调整以获得更高清晰度的图像
- scale: 3
-};
-
-/**
- * 简化版PDF到图像转换函数 - 每页生成一个完整图像
- * @param {Buffer} pdfData PDF文件数据
- * @param {string} outputDir 输出目录
- * @param {number} scale 缩放比例
- * @returns {Promise>} 生成的图像文件路径数组
- */
-async function generateImagesFromPdf(pdfData, outputDir, scale = 3) {
- // 确保输出目录存在
- await fs.ensureDir(outputDir);
-
- // 加载PDF文档
- const pdfDocument = await pdfjsLib.getDocument({ data: pdfData }).promise;
- const numPages = pdfDocument.numPages;
- console.log(`PDF文档共 ${numPages} 页`);
-
- // 存储生成的图像路径
- const pageImages = [];
-
- // 处理每一页
- for (let i = 0; i < numPages; i++) {
- const pageIndex = i + 1;
- console.log(`处理第 ${pageIndex} 页...`);
-
- // 获取页面
- const page = await pdfDocument.getPage(pageIndex);
- const viewport = page.getViewport({ scale });
-
- // 创建canvas
- const canvas = createCanvas(viewport.width, viewport.height);
- const context = canvas.getContext('2d');
-
- // 填充白色背景
- context.fillStyle = '#ffffff';
- context.fillRect(0, 0, viewport.width, viewport.height);
-
- // 渲染页面
- await page.render({
- canvasContext: context,
- viewport: viewport
- }).promise;
-
- // 保存为图像
- const imageName = `page_${pageIndex}.png`;
- const imagePath = path.join(outputDir, imageName);
-
- // 将canvas转换为图像并保存
- const buffer = await sharp(canvas.toBuffer('image/png')).png().toBuffer();
- await fs.writeFile(imagePath, buffer);
-
- // 添加到结果数组
- pageImages.push(imagePath);
-
- console.log(`页面 ${pageIndex} 已保存到: ${imagePath}`);
- }
-
- return pageImages;
-}
-
-/**
- * 测试简化版PDF到图像转换
- */
-async function testSimplePdfToImage() {
- console.log('=== 测试简化版PDF到图像转换 ===');
-
- try {
- // 确保输出目录存在
- await fs.ensureDir(CONFIG.outputDir);
-
- // 检查PDF文件是否存在
- if (!await fs.pathExists(CONFIG.pdfPath)) {
- console.error(`错误: 测试PDF文件不存在: ${CONFIG.pdfPath}`);
- return;
- }
-
- console.log(`加载PDF文件: ${CONFIG.pdfPath}`);
-
- // 读取PDF文件
- const pdfData = await fs.readFile(CONFIG.pdfPath);
-
- // 开始时间
- const startTime = Date.now();
-
- // 执行转换
- const imageFiles = await generateImagesFromPdf(pdfData, CONFIG.outputDir, CONFIG.scale);
-
- // 结束时间
- const endTime = Date.now();
-
- // 输出结果
- console.log(`\n转换完成,耗时: ${(endTime - startTime) / 1000}秒`);
- console.log(`生成了 ${imageFiles.length} 个页面图像:`);
-
- for (const file of imageFiles) {
- console.log(`- ${file}`);
- }
-
- console.log(`\n所有图像已保存到: ${CONFIG.outputDir}`);
-
- } catch (error) {
- console.error('测试过程中发生错误:', error);
- }
-}
-
-/**
- * 主函数
- */
-async function main() {
- console.log('开始测试简化版PDF到图像转换...\n');
-
- // 测试简化流程
- await testSimplePdfToImage();
-
- console.log('简化版PDF到图像转换测试完成');
-}
-
-// 执行测试
-main().catch(error => {
- console.error('执行测试时发生错误:', error);
-});