@jayfong/x-utils 1.0.0-202510061015 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/case.d.mts +184 -0
- package/lib/case.mjs +120 -0
- package/lib/chinese.d.mts +39 -0
- package/lib/chinese.mjs +52 -0
- package/lib/cli.d.mts +64 -0
- package/lib/cli.mjs +59 -0
- package/lib/clipboard.d.mts +50 -0
- package/lib/clipboard.mjs +122 -0
- package/lib/cmd.d.mts +38 -0
- package/lib/cmd.mjs +52 -0
- package/lib/crawler.d.mts +330 -0
- package/lib/crawler.mjs +313 -0
- package/lib/csv.d.mts +67 -0
- package/lib/csv.mjs +76 -0
- package/lib/data_set.d.mts +76 -0
- package/lib/data_set.mjs +104 -0
- package/lib/fs.d.mts +49 -0
- package/lib/fs.mjs +65 -0
- package/lib/json.d.mts +50 -0
- package/lib/json.mjs +74 -0
- package/lib/puppeteer.d.mts +88 -0
- package/lib/puppeteer.mjs +219 -0
- package/lib/runner.d.mts +52 -0
- package/lib/runner.mjs +50 -0
- package/lib/task.d.mts +37 -0
- package/lib/task.mjs +43 -0
- package/lib/text.d.mts +84 -0
- package/lib/text.mjs +141 -0
- package/lib/yaml.d.mts +51 -0
- package/lib/yaml.mjs +64 -0
- package/package.json +50 -164
- package/_cjs/ai.js +0 -80
- package/_cjs/alipan.js +0 -173
- package/_cjs/cli.js +0 -51
- package/_cjs/clipboard.js +0 -65
- package/_cjs/cmd.js +0 -42
- package/_cjs/compressor.js +0 -47
- package/_cjs/crawler.js +0 -341
- package/_cjs/csv.js +0 -97
- package/_cjs/data_set.js +0 -115
- package/_cjs/env.js +0 -82
- package/_cjs/fs.js +0 -86
- package/_cjs/html.js +0 -62
- package/_cjs/http_server.js +0 -79
- package/_cjs/json.js +0 -49
- package/_cjs/ksb.js +0 -218
- package/_cjs/number.js +0 -39
- package/_cjs/ocr.js +0 -74
- package/_cjs/package.json +0 -3
- package/_cjs/path.js +0 -35
- package/_cjs/pinyin.js +0 -37
- package/_cjs/puppeteer.js +0 -271
- package/_cjs/runner.js +0 -88
- package/_cjs/task.js +0 -41
- package/_cjs/text.js +0 -136
- package/_cjs/unicode/lib_unicode.js +0 -58643
- package/_cjs/unicode/unicode.js +0 -441
- package/_cjs/upload.js +0 -101
- package/_cjs/yaml.js +0 -52
- package/ai.d.ts +0 -26
- package/ai.js +0 -60
- package/alipan.d.ts +0 -209
- package/alipan.js +0 -153
- package/cli.d.ts +0 -14
- package/cli.js +0 -21
- package/clipboard.d.ts +0 -6
- package/clipboard.js +0 -35
- package/cmd.d.ts +0 -5
- package/cmd.js +0 -22
- package/compressor.d.ts +0 -5
- package/compressor.js +0 -17
- package/crawler.d.ts +0 -162
- package/crawler.js +0 -332
- package/csv.d.ts +0 -14
- package/csv.js +0 -67
- package/data_set.d.ts +0 -22
- package/data_set.js +0 -85
- package/env.d.ts +0 -6
- package/env.js +0 -52
- package/fs.d.ts +0 -23
- package/fs.js +0 -56
- package/html.d.ts +0 -7
- package/html.js +0 -45
- package/http_server.d.ts +0 -13
- package/http_server.js +0 -49
- package/json.d.ts +0 -6
- package/json.js +0 -19
- package/ksb.d.ts +0 -37
- package/ksb.js +0 -198
- package/number.d.ts +0 -3
- package/number.js +0 -9
- package/ocr.d.ts +0 -17
- package/ocr.js +0 -54
- package/path.d.ts +0 -2
- package/path.js +0 -5
- package/pinyin.d.ts +0 -8
- package/pinyin.js +0 -17
- package/puppeteer.d.ts +0 -38
- package/puppeteer.js +0 -241
- package/runner.d.ts +0 -13
- package/runner.js +0 -58
- package/task.d.ts +0 -6
- package/task.js +0 -21
- package/text.d.ts +0 -63
- package/text.js +0 -119
- package/unicode/lib_unicode.d.ts +0 -4
- package/unicode/lib_unicode.js +0 -58623
- package/unicode/unicode.d.ts +0 -347
- package/unicode/unicode.js +0 -426
- package/upload.d.ts +0 -34
- package/upload.js +0 -71
- package/yaml.d.ts +0 -6
- package/yaml.js +0 -22
package/alipan.d.ts
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
/// <reference types="lodash" />
|
|
2
|
-
/// <reference types="node" />
|
|
3
|
-
type GetUserInfoResult = {
|
|
4
|
-
name: string;
|
|
5
|
-
avatar: string;
|
|
6
|
-
user_id: string;
|
|
7
|
-
user_name: string;
|
|
8
|
-
nick_name: string;
|
|
9
|
-
default_drive_id: string;
|
|
10
|
-
backup_drive_id: string;
|
|
11
|
-
resource_drive_id: string;
|
|
12
|
-
album_drive_id: string;
|
|
13
|
-
};
|
|
14
|
-
type CreateFilePayload = {
|
|
15
|
-
drive_id: string;
|
|
16
|
-
parent_file_id: string;
|
|
17
|
-
name: string;
|
|
18
|
-
type: 'file' | 'folder';
|
|
19
|
-
check_name_mode: 'auto_rename' | 'refuse' | 'ignore';
|
|
20
|
-
};
|
|
21
|
-
type CreateFileResult = {
|
|
22
|
-
trashed?: any;
|
|
23
|
-
name?: any;
|
|
24
|
-
thumbnail?: any;
|
|
25
|
-
type: string;
|
|
26
|
-
category?: any;
|
|
27
|
-
hidden?: any;
|
|
28
|
-
status?: any;
|
|
29
|
-
description?: any;
|
|
30
|
-
meta?: any;
|
|
31
|
-
url?: any;
|
|
32
|
-
size?: any;
|
|
33
|
-
starred?: any;
|
|
34
|
-
available?: any;
|
|
35
|
-
exist?: any;
|
|
36
|
-
user_tags?: any;
|
|
37
|
-
mime_type?: any;
|
|
38
|
-
parent_file_id: string;
|
|
39
|
-
drive_id: string;
|
|
40
|
-
file_id: string;
|
|
41
|
-
file_extension?: any;
|
|
42
|
-
revision_id: string;
|
|
43
|
-
content_hash?: any;
|
|
44
|
-
content_hash_name?: any;
|
|
45
|
-
encrypt_mode: string;
|
|
46
|
-
domain_id: string;
|
|
47
|
-
download_url?: any;
|
|
48
|
-
user_meta?: any;
|
|
49
|
-
content_type?: any;
|
|
50
|
-
created_at?: any;
|
|
51
|
-
updated_at?: any;
|
|
52
|
-
local_created_at?: any;
|
|
53
|
-
local_modified_at?: any;
|
|
54
|
-
trashed_at?: any;
|
|
55
|
-
punish_flag?: any;
|
|
56
|
-
file_name: string;
|
|
57
|
-
upload_id: string;
|
|
58
|
-
location: string;
|
|
59
|
-
rapid_upload: boolean;
|
|
60
|
-
part_info_list: {
|
|
61
|
-
etag?: any;
|
|
62
|
-
part_number: number;
|
|
63
|
-
part_size?: any;
|
|
64
|
-
upload_url: string;
|
|
65
|
-
content_type: string;
|
|
66
|
-
upload_form_info?: any;
|
|
67
|
-
}[];
|
|
68
|
-
streams_upload_info?: any;
|
|
69
|
-
};
|
|
70
|
-
type UploadFilePayload = {
|
|
71
|
-
uploadUrl: string;
|
|
72
|
-
file: Buffer;
|
|
73
|
-
useIntranet?: boolean;
|
|
74
|
-
};
|
|
75
|
-
type CompleteFilePayload = {
|
|
76
|
-
drive_id: string;
|
|
77
|
-
file_id: string;
|
|
78
|
-
upload_id: string;
|
|
79
|
-
};
|
|
80
|
-
type GetFileInfoByPathPayload = {
|
|
81
|
-
drive_id: string;
|
|
82
|
-
file_path: string;
|
|
83
|
-
};
|
|
84
|
-
type GetFileInfoByPathResult = {
|
|
85
|
-
trashed: boolean;
|
|
86
|
-
name: string;
|
|
87
|
-
thumbnail: string;
|
|
88
|
-
type: string;
|
|
89
|
-
category: string;
|
|
90
|
-
hidden: boolean;
|
|
91
|
-
status: string;
|
|
92
|
-
description?: any;
|
|
93
|
-
meta?: any;
|
|
94
|
-
url?: any;
|
|
95
|
-
size: number;
|
|
96
|
-
starred: boolean;
|
|
97
|
-
location?: any;
|
|
98
|
-
deleted?: any;
|
|
99
|
-
channel?: any;
|
|
100
|
-
user_tags?: any;
|
|
101
|
-
mime_type?: any;
|
|
102
|
-
parent_file_id: string;
|
|
103
|
-
drive_id: string;
|
|
104
|
-
file_id: string;
|
|
105
|
-
file_extension: string;
|
|
106
|
-
revision_id: string;
|
|
107
|
-
content_hash: string;
|
|
108
|
-
content_hash_name: string;
|
|
109
|
-
encrypt_mode: string;
|
|
110
|
-
domain_id?: any;
|
|
111
|
-
download_url?: any;
|
|
112
|
-
user_meta?: any;
|
|
113
|
-
content_type: string;
|
|
114
|
-
created_at: string;
|
|
115
|
-
updated_at: string;
|
|
116
|
-
local_created_at: string;
|
|
117
|
-
local_modified_at: string;
|
|
118
|
-
trashed_at?: any;
|
|
119
|
-
punish_flag: number;
|
|
120
|
-
video_media_metadata?: any;
|
|
121
|
-
image_media_metadata: {
|
|
122
|
-
address_line?: any;
|
|
123
|
-
city?: any;
|
|
124
|
-
country?: any;
|
|
125
|
-
district?: any;
|
|
126
|
-
faces?: any;
|
|
127
|
-
height: number;
|
|
128
|
-
image_quality: {
|
|
129
|
-
clarity?: any;
|
|
130
|
-
clarityScore?: any;
|
|
131
|
-
color?: any;
|
|
132
|
-
colorScore?: any;
|
|
133
|
-
compositionScore?: any;
|
|
134
|
-
contrast?: any;
|
|
135
|
-
contrastScore?: any;
|
|
136
|
-
exposure?: any;
|
|
137
|
-
exposureScore?: any;
|
|
138
|
-
overallScore: {
|
|
139
|
-
s: number;
|
|
140
|
-
e: number;
|
|
141
|
-
c: number[];
|
|
142
|
-
};
|
|
143
|
-
};
|
|
144
|
-
location?: any;
|
|
145
|
-
province?: any;
|
|
146
|
-
story_image_score?: any;
|
|
147
|
-
time?: any;
|
|
148
|
-
township?: any;
|
|
149
|
-
width: number;
|
|
150
|
-
exif?: any;
|
|
151
|
-
};
|
|
152
|
-
};
|
|
153
|
-
type GetFileDownloadUrlPayload = {
|
|
154
|
-
drive_id: string;
|
|
155
|
-
file_id: string;
|
|
156
|
-
expire_sec?: number;
|
|
157
|
-
};
|
|
158
|
-
type GetFileDownloadUrlResult = {
|
|
159
|
-
method: string;
|
|
160
|
-
url: string;
|
|
161
|
-
expiration: string;
|
|
162
|
-
size: number;
|
|
163
|
-
streamsUrl?: any;
|
|
164
|
-
content_hash: string;
|
|
165
|
-
content_hash_name: string;
|
|
166
|
-
file_id: string;
|
|
167
|
-
};
|
|
168
|
-
type DriveType = 'backup' | 'resource' | 'album';
|
|
169
|
-
type GetDriveIdPayload = {
|
|
170
|
-
drive: DriveType;
|
|
171
|
-
};
|
|
172
|
-
type ExistsFileHumanPayload = {
|
|
173
|
-
drive: DriveType;
|
|
174
|
-
path: string;
|
|
175
|
-
};
|
|
176
|
-
type EnsurePathHumanPayload = {
|
|
177
|
-
drive: DriveType;
|
|
178
|
-
path: string;
|
|
179
|
-
};
|
|
180
|
-
type UploadFileHumanPayload = {
|
|
181
|
-
drive: DriveType;
|
|
182
|
-
path: string;
|
|
183
|
-
file: Buffer;
|
|
184
|
-
useIntranet?: boolean;
|
|
185
|
-
};
|
|
186
|
-
type GetFileDownloadUrlHumanPayload = {
|
|
187
|
-
drive: DriveType;
|
|
188
|
-
path: string;
|
|
189
|
-
};
|
|
190
|
-
export type XAlipanOptions = {
|
|
191
|
-
accessToken: string;
|
|
192
|
-
};
|
|
193
|
-
export declare class XAlipan {
|
|
194
|
-
private options;
|
|
195
|
-
private xr;
|
|
196
|
-
constructor(options: XAlipanOptions);
|
|
197
|
-
getUserInfo: (() => Promise<GetUserInfoResult>) & import("lodash").MemoizedFunction;
|
|
198
|
-
createFile(payload: CreateFilePayload): Promise<CreateFileResult>;
|
|
199
|
-
uploadFile(payload: UploadFilePayload): Promise<void>;
|
|
200
|
-
completeFile(payload: CompleteFilePayload): Promise<void>;
|
|
201
|
-
getFileInfoByPath(payload: GetFileInfoByPathPayload): Promise<GetFileInfoByPathResult>;
|
|
202
|
-
getFileDownloadUrl(payload: GetFileDownloadUrlPayload): Promise<GetFileDownloadUrlResult>;
|
|
203
|
-
getDriveId: ((payload: GetDriveIdPayload) => Promise<string>) & import("lodash").MemoizedFunction;
|
|
204
|
-
existsFileHuman(payload: ExistsFileHumanPayload): Promise<string | false>;
|
|
205
|
-
ensurePathHuman: ((payload: EnsurePathHumanPayload) => Promise<string>) & import("lodash").MemoizedFunction;
|
|
206
|
-
uploadFileHuman(payload: UploadFileHumanPayload): Promise<void>;
|
|
207
|
-
getFileDownloadUrlHuman(payload: GetFileDownloadUrlHumanPayload): Promise<string>;
|
|
208
|
-
}
|
|
209
|
-
export {};
|
package/alipan.js
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { xr } from "@jayfong/x-request";
|
|
2
|
-
import { memoize, ms } from "vtils";
|
|
3
|
-
import { XPath } from "./path.js";
|
|
4
|
-
class XAlipan {
|
|
5
|
-
constructor(options) {
|
|
6
|
-
this.options = options;
|
|
7
|
-
this.xr = xr.extend({
|
|
8
|
-
baseUrl: "https://open.aliyundrive.com",
|
|
9
|
-
headers: {
|
|
10
|
-
Authorization: `Bearer ${options.accessToken}`
|
|
11
|
-
},
|
|
12
|
-
timeoutMs: ms("30s")
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
xr;
|
|
16
|
-
getUserInfo = memoize(async () => {
|
|
17
|
-
const res = await this.xr.postJson({
|
|
18
|
-
url: "/adrive/v1.0/user/getDriveInfo"
|
|
19
|
-
});
|
|
20
|
-
return res.data;
|
|
21
|
-
});
|
|
22
|
-
async createFile(payload) {
|
|
23
|
-
const res = await this.xr.postJson({
|
|
24
|
-
url: "/adrive/v1.0/openFile/create",
|
|
25
|
-
data: payload
|
|
26
|
-
});
|
|
27
|
-
return res.data;
|
|
28
|
-
}
|
|
29
|
-
async uploadFile(payload) {
|
|
30
|
-
await this.xr.post({
|
|
31
|
-
method: "PUT",
|
|
32
|
-
url: payload.useIntranet ? payload.uploadUrl.replace(
|
|
33
|
-
"https://cn-beijing-data.aliyundrive.net/",
|
|
34
|
-
"http://ccp-bj29-bj-1592982087.oss-cn-beijing-internal.aliyuncs.com/"
|
|
35
|
-
) : payload.uploadUrl,
|
|
36
|
-
data: payload.file,
|
|
37
|
-
headers: {
|
|
38
|
-
"Content-Type": ""
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
async completeFile(payload) {
|
|
43
|
-
await this.xr.post({
|
|
44
|
-
url: "/adrive/v1.0/openFile/complete",
|
|
45
|
-
data: payload
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
async getFileInfoByPath(payload) {
|
|
49
|
-
const res = await this.xr.postJson({
|
|
50
|
-
url: "/adrive/v1.0/openFile/get_by_path",
|
|
51
|
-
data: payload
|
|
52
|
-
});
|
|
53
|
-
return res.data;
|
|
54
|
-
}
|
|
55
|
-
async getFileDownloadUrl(payload) {
|
|
56
|
-
const res = await this.xr.postJson({
|
|
57
|
-
url: "/adrive/v1.0/openFile/getDownloadUrl",
|
|
58
|
-
data: payload
|
|
59
|
-
});
|
|
60
|
-
return res.data;
|
|
61
|
-
}
|
|
62
|
-
getDriveId = memoize(
|
|
63
|
-
async (payload) => {
|
|
64
|
-
{
|
|
65
|
-
const userInfo = await this.getUserInfo();
|
|
66
|
-
return payload.drive === "backup" ? userInfo.backup_drive_id : payload.drive === "resource" ? userInfo.resource_drive_id : payload.drive === "album" ? userInfo.album_drive_id : "";
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
(payload) => payload.drive
|
|
70
|
-
);
|
|
71
|
-
async existsFileHuman(payload) {
|
|
72
|
-
try {
|
|
73
|
-
const driveId = await this.getDriveId(payload);
|
|
74
|
-
const res = await this.getFileInfoByPath({
|
|
75
|
-
drive_id: driveId,
|
|
76
|
-
file_path: payload.path
|
|
77
|
-
});
|
|
78
|
-
return res.file_id;
|
|
79
|
-
} catch {
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
ensurePathHuman = memoize(
|
|
84
|
-
async (payload) => {
|
|
85
|
-
const driveId = await this.getDriveId(payload);
|
|
86
|
-
const pathParts = payload.path.split("/");
|
|
87
|
-
let prevFileId = "root";
|
|
88
|
-
for (let i = 1; i < pathParts.length; i++) {
|
|
89
|
-
const path = pathParts.slice(0, i + 1).join("/");
|
|
90
|
-
const fileId = await this.existsFileHuman({
|
|
91
|
-
drive: payload.drive,
|
|
92
|
-
path
|
|
93
|
-
});
|
|
94
|
-
if (!fileId) {
|
|
95
|
-
const createRes = await this.createFile({
|
|
96
|
-
drive_id: driveId,
|
|
97
|
-
parent_file_id: prevFileId,
|
|
98
|
-
type: "folder",
|
|
99
|
-
check_name_mode: "refuse",
|
|
100
|
-
name: pathParts[i]
|
|
101
|
-
});
|
|
102
|
-
prevFileId = createRes.file_id;
|
|
103
|
-
} else {
|
|
104
|
-
prevFileId = fileId;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return prevFileId;
|
|
108
|
-
},
|
|
109
|
-
(payload) => `${payload.drive}:${payload.path}`
|
|
110
|
-
);
|
|
111
|
-
async uploadFileHuman(payload) {
|
|
112
|
-
const driveId = await this.getDriveId(payload);
|
|
113
|
-
const fileId = await this.ensurePathHuman({
|
|
114
|
-
drive: payload.drive,
|
|
115
|
-
path: XPath.dirname(payload.path)
|
|
116
|
-
});
|
|
117
|
-
const createRes = await this.createFile({
|
|
118
|
-
drive_id: driveId,
|
|
119
|
-
parent_file_id: fileId,
|
|
120
|
-
type: "file",
|
|
121
|
-
check_name_mode: "refuse",
|
|
122
|
-
name: XPath.basename(payload.path)
|
|
123
|
-
});
|
|
124
|
-
if (!createRes.exist && createRes.part_info_list?.length === 1) {
|
|
125
|
-
await this.uploadFile({
|
|
126
|
-
uploadUrl: createRes.part_info_list[0].upload_url,
|
|
127
|
-
file: payload.file,
|
|
128
|
-
useIntranet: payload.useIntranet
|
|
129
|
-
});
|
|
130
|
-
await this.completeFile({
|
|
131
|
-
drive_id: createRes.drive_id,
|
|
132
|
-
file_id: createRes.file_id,
|
|
133
|
-
upload_id: createRes.upload_id
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
async getFileDownloadUrlHuman(payload) {
|
|
138
|
-
const driveId = await this.getDriveId(payload);
|
|
139
|
-
const fileInfo = await this.getFileInfoByPath({
|
|
140
|
-
drive_id: driveId,
|
|
141
|
-
file_path: payload.path
|
|
142
|
-
});
|
|
143
|
-
const downloadInfo = await this.getFileDownloadUrl({
|
|
144
|
-
drive_id: driveId,
|
|
145
|
-
file_id: fileInfo.file_id,
|
|
146
|
-
expire_sec: 900
|
|
147
|
-
});
|
|
148
|
-
return downloadInfo.url;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
export {
|
|
152
|
-
XAlipan
|
|
153
|
-
};
|
package/cli.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export type XCliPromptType = 'confirm' | 'input';
|
|
2
|
-
export type XCliPromptResult = {
|
|
3
|
-
confirm: boolean;
|
|
4
|
-
input: string;
|
|
5
|
-
};
|
|
6
|
-
export type XCliPromptOptions<T extends XCliPromptType> = {
|
|
7
|
-
message: string;
|
|
8
|
-
type: T;
|
|
9
|
-
default?: XCliPromptResult[T];
|
|
10
|
-
};
|
|
11
|
-
export declare class XCli {
|
|
12
|
-
static prompt<T extends XCliPromptType>(options: XCliPromptOptions<T>): Promise<XCliPromptResult[T]>;
|
|
13
|
-
static table(data: any[][]): string;
|
|
14
|
-
}
|
package/cli.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import Table from "cli-table3";
|
|
2
|
-
import inquirer from "inquirer";
|
|
3
|
-
class XCli {
|
|
4
|
-
static async prompt(options) {
|
|
5
|
-
const { x } = await inquirer.prompt({
|
|
6
|
-
name: "x",
|
|
7
|
-
message: options.message,
|
|
8
|
-
type: options.type,
|
|
9
|
-
default: options.default
|
|
10
|
-
});
|
|
11
|
-
return x;
|
|
12
|
-
}
|
|
13
|
-
static table(data) {
|
|
14
|
-
const table = new Table();
|
|
15
|
-
table.push(...data);
|
|
16
|
-
return table.toString();
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
export {
|
|
20
|
-
XCli
|
|
21
|
-
};
|
package/clipboard.d.ts
DELETED
package/clipboard.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import clipboardy from "clipboardy";
|
|
2
|
-
import { XCmd } from "./cmd.js";
|
|
3
|
-
class XClipboard {
|
|
4
|
-
static async readText() {
|
|
5
|
-
return clipboardy.read();
|
|
6
|
-
}
|
|
7
|
-
static async readHtml() {
|
|
8
|
-
const hex = await XCmd.exec(
|
|
9
|
-
// 读取剪切板为 HTML
|
|
10
|
-
// https://stackoverflow.com/questions/2545289/getting-rtf-data-out-of-mac-os-x-pasteboard-clipboard
|
|
11
|
-
// https://stackoverflow.com/a/17217886
|
|
12
|
-
`osascript -e "the clipboard as \xABclass HTML\xBB"`
|
|
13
|
-
);
|
|
14
|
-
const html = Buffer.from(
|
|
15
|
-
hex.substring(10, hex.length - 1),
|
|
16
|
-
"hex"
|
|
17
|
-
).toString();
|
|
18
|
-
return html;
|
|
19
|
-
}
|
|
20
|
-
static async writeText(text) {
|
|
21
|
-
await clipboardy.write(text);
|
|
22
|
-
}
|
|
23
|
-
static async writeHtml(html) {
|
|
24
|
-
const hex = Buffer.from(html).toString("hex");
|
|
25
|
-
await XCmd.exec(
|
|
26
|
-
// 设置剪切板为 HTML
|
|
27
|
-
// https://stackoverflow.com/questions/11085654/apple-script-how-can-i-copy-html-content-to-the-clipboard
|
|
28
|
-
// https://stackoverflow.com/a/11089226
|
|
29
|
-
`osascript -e "set the clipboard to \xABdata HTML${hex}\xBB"`
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
export {
|
|
34
|
-
XClipboard
|
|
35
|
-
};
|
package/cmd.d.ts
DELETED
package/cmd.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { execa } from "execa";
|
|
2
|
-
class XCmd {
|
|
3
|
-
static execDivider = "clrue91c60000e6rl7w03b40p";
|
|
4
|
-
static async exec(command, options) {
|
|
5
|
-
const { stdout } = await execa(
|
|
6
|
-
"zsh",
|
|
7
|
-
[
|
|
8
|
-
"-c",
|
|
9
|
-
`
|
|
10
|
-
echo ${XCmd.execDivider}
|
|
11
|
-
${command}
|
|
12
|
-
echo ${XCmd.execDivider}
|
|
13
|
-
`
|
|
14
|
-
],
|
|
15
|
-
options
|
|
16
|
-
);
|
|
17
|
-
return stdout.split(XCmd.execDivider)[1].trim();
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
export {
|
|
21
|
-
XCmd
|
|
22
|
-
};
|
package/compressor.d.ts
DELETED
package/compressor.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import sharp from "sharp";
|
|
2
|
-
class XCompressor {
|
|
3
|
-
static png(content) {
|
|
4
|
-
return sharp(content).png({
|
|
5
|
-
quality: 80,
|
|
6
|
-
compressionLevel: 6
|
|
7
|
-
}).toBuffer();
|
|
8
|
-
}
|
|
9
|
-
static jpg(content) {
|
|
10
|
-
return sharp(content).jpeg({
|
|
11
|
-
quality: 80
|
|
12
|
-
}).toBuffer();
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
export {
|
|
16
|
-
XCompressor
|
|
17
|
-
};
|
package/crawler.d.ts
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { HTMLElement } from 'node-html-parser';
|
|
2
|
-
import { EventBus } from 'vtils';
|
|
3
|
-
import { AsyncOrSync, OneOrMore } from 'vtils/types';
|
|
4
|
-
import { VaeObjectSchemaShapeOf, v } from 'vtils/vae';
|
|
5
|
-
import { XPuppeteerGetPageHtmlOptions } from './puppeteer';
|
|
6
|
-
export type XCrawlerData = Record<any, any>;
|
|
7
|
-
export type XCrawlerDataFieldSelectSelector = string;
|
|
8
|
-
export type XCrawlerDataFieldSelectFilter = [
|
|
9
|
-
string,
|
|
10
|
-
string | RegExp | ((el: HTMLElement) => boolean)
|
|
11
|
-
];
|
|
12
|
-
export type XCrawlerDataFieldSelectFunction = (el: HTMLElement) => AsyncOrSync<string | HTMLElement | undefined>;
|
|
13
|
-
export type XCrawlerDataFieldSelect = XCrawlerDataFieldSelectSelector | XCrawlerDataFieldSelectFilter | XCrawlerDataFieldSelectFunction;
|
|
14
|
-
export type XCrawlerDataFieldExtractExtract = 'getPlainText' | 'getHTML' | 'getFirstImageUrl' | 'getFirstLinkUrl';
|
|
15
|
-
export type XCrawlerDataFieldExtract<V> = {
|
|
16
|
-
/**
|
|
17
|
-
* 选择元素
|
|
18
|
-
*
|
|
19
|
-
* - 可以是一个选择器字符串;
|
|
20
|
-
* - 可以是一个筛选器数组,[选择器, 筛选条件];
|
|
21
|
-
* - 也可以是一个返回元素的函数;
|
|
22
|
-
* - 也可以是一个返回文本的函数,若此,将跳过 ocr 和 action。
|
|
23
|
-
*/
|
|
24
|
-
select?: XCrawlerDataFieldSelect;
|
|
25
|
-
/**
|
|
26
|
-
* 是否识别选中内容中的图片为文本并替换
|
|
27
|
-
*
|
|
28
|
-
* @default false
|
|
29
|
-
*/
|
|
30
|
-
ocr?: boolean;
|
|
31
|
-
/**
|
|
32
|
-
* 对选中元素导出结果文本
|
|
33
|
-
*
|
|
34
|
-
* @default 'getPlainText'
|
|
35
|
-
*/
|
|
36
|
-
extract?: XCrawlerDataFieldExtractExtract;
|
|
37
|
-
/**
|
|
38
|
-
* 若有需要,可对结果文本进行转换
|
|
39
|
-
*
|
|
40
|
-
* @param text 结果文本
|
|
41
|
-
*/
|
|
42
|
-
transform?: (text: string) => AsyncOrSync<V>;
|
|
43
|
-
};
|
|
44
|
-
export type XCrawlerDataExtract<T extends XCrawlerData> = {
|
|
45
|
-
[K in keyof T]?: XCrawlerDataFieldSelect | XCrawlerDataFieldExtract<T[K]>;
|
|
46
|
-
};
|
|
47
|
-
export type XCrawlerEngine = 'headless' | 'headful' | 'request';
|
|
48
|
-
export type XCrawlerContentType = 'html' | 'json';
|
|
49
|
-
export type XCrawlerNext<T extends XCrawlerData> = {
|
|
50
|
-
/**
|
|
51
|
-
* ID,可给其他 next 跳转以实现逻辑复用
|
|
52
|
-
*/
|
|
53
|
-
id?: string;
|
|
54
|
-
/**
|
|
55
|
-
* 过滤
|
|
56
|
-
*/
|
|
57
|
-
filter?: (data: T) => AsyncOrSync<boolean>;
|
|
58
|
-
/**
|
|
59
|
-
* 内容类型
|
|
60
|
-
*/
|
|
61
|
-
contentType?: XCrawlerContentType;
|
|
62
|
-
/**
|
|
63
|
-
* 通过元素
|
|
64
|
-
*/
|
|
65
|
-
element?: string | ((el: HTMLElement, extra: {
|
|
66
|
-
index: number;
|
|
67
|
-
root: HTMLElement;
|
|
68
|
-
}) => AsyncOrSync<OneOrMore<HTMLElement>>);
|
|
69
|
-
/**
|
|
70
|
-
* 通过字段(json)
|
|
71
|
-
*/
|
|
72
|
-
field?: string | ((json: any) => AsyncOrSync<any>);
|
|
73
|
-
/**
|
|
74
|
-
* 通过网址
|
|
75
|
-
*/
|
|
76
|
-
url?: keyof T | ((payload: {
|
|
77
|
-
data: T;
|
|
78
|
-
el: HTMLElement;
|
|
79
|
-
}) => AsyncOrSync<OneOrMore<string>>);
|
|
80
|
-
/**
|
|
81
|
-
* 下一页网址(有分页时用)
|
|
82
|
-
*
|
|
83
|
-
* 返回空字符串或跟当前页面网址相同的网址时将跳过
|
|
84
|
-
*/
|
|
85
|
-
nextPageUrl?: (payload: {
|
|
86
|
-
data: T;
|
|
87
|
-
/** 当前页面元素 */
|
|
88
|
-
el: HTMLElement;
|
|
89
|
-
/** 当前页面网址 */
|
|
90
|
-
url: string;
|
|
91
|
-
}) => AsyncOrSync<string | undefined>;
|
|
92
|
-
/** @inner */
|
|
93
|
-
_url?: string[];
|
|
94
|
-
/**
|
|
95
|
-
* 抓取引擎
|
|
96
|
-
*/
|
|
97
|
-
engine?: XCrawlerEngine;
|
|
98
|
-
engineOptions?: XPuppeteerGetPageHtmlOptions;
|
|
99
|
-
/**
|
|
100
|
-
* 数据提取
|
|
101
|
-
*/
|
|
102
|
-
extract?: XCrawlerDataExtract<T>;
|
|
103
|
-
/**
|
|
104
|
-
* 下一步
|
|
105
|
-
*/
|
|
106
|
-
next?: OneOrMore<string | XCrawlerNext<T>>;
|
|
107
|
-
};
|
|
108
|
-
export type XCrawlerConfig<T extends XCrawlerData> = {
|
|
109
|
-
/**
|
|
110
|
-
* 入口页链接
|
|
111
|
-
*/
|
|
112
|
-
entry: string;
|
|
113
|
-
/**
|
|
114
|
-
* 使用代理
|
|
115
|
-
*/
|
|
116
|
-
proxy?: string;
|
|
117
|
-
/**
|
|
118
|
-
* 内容类型
|
|
119
|
-
*/
|
|
120
|
-
contentType?: XCrawlerContentType;
|
|
121
|
-
/**
|
|
122
|
-
* 抓取引擎
|
|
123
|
-
*/
|
|
124
|
-
engine?: XCrawlerEngine;
|
|
125
|
-
engineOptions?: XPuppeteerGetPageHtmlOptions;
|
|
126
|
-
/**
|
|
127
|
-
* 数据格式
|
|
128
|
-
*/
|
|
129
|
-
schema: (_: typeof v) => VaeObjectSchemaShapeOf<T>;
|
|
130
|
-
/**
|
|
131
|
-
* 数据提取
|
|
132
|
-
*/
|
|
133
|
-
extract?: XCrawlerDataExtract<T>;
|
|
134
|
-
/**
|
|
135
|
-
* 下一步
|
|
136
|
-
*/
|
|
137
|
-
next?: OneOrMore<XCrawlerNext<T>>;
|
|
138
|
-
/**
|
|
139
|
-
* 数据监听
|
|
140
|
-
*/
|
|
141
|
-
listen?: (data: T) => any;
|
|
142
|
-
};
|
|
143
|
-
export declare class XCrawler<T extends XCrawlerData> extends EventBus<{
|
|
144
|
-
newData: (data: T) => any;
|
|
145
|
-
}> {
|
|
146
|
-
private config;
|
|
147
|
-
private schemaMap;
|
|
148
|
-
private id;
|
|
149
|
-
constructor(config: XCrawlerConfig<T>);
|
|
150
|
-
private normalizeUrl;
|
|
151
|
-
private fetchUrlHeadless;
|
|
152
|
-
private fetchUrlHeadful;
|
|
153
|
-
private fetchUrlRequest;
|
|
154
|
-
private fetchUrl;
|
|
155
|
-
private fetchUrlAsHTMLElement;
|
|
156
|
-
private fetchUrlAsJSON;
|
|
157
|
-
private ocr;
|
|
158
|
-
private findNextById;
|
|
159
|
-
private pageUrlCache;
|
|
160
|
-
next(pageUrl: string, contentType: XCrawlerContentType, engine: XCrawlerEngine, elOrField: any, data: Partial<T>, next: XCrawlerNext<T>, index: number, rootElement: HTMLElement): Promise<void>;
|
|
161
|
-
start(): Promise<void>;
|
|
162
|
-
}
|