@jayfong/x-utils 1.0.0-202407012223

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.
Files changed (77) hide show
  1. package/_cjs/ai.js +80 -0
  2. package/_cjs/cli.js +51 -0
  3. package/_cjs/clipboard.js +65 -0
  4. package/_cjs/cmd.js +42 -0
  5. package/_cjs/crawler.js +341 -0
  6. package/_cjs/csv.js +97 -0
  7. package/_cjs/data_set.js +115 -0
  8. package/_cjs/env.js +63 -0
  9. package/_cjs/fs.js +35 -0
  10. package/_cjs/html.js +62 -0
  11. package/_cjs/http_server.js +56 -0
  12. package/_cjs/json.js +49 -0
  13. package/_cjs/ksb.js +217 -0
  14. package/_cjs/number.js +39 -0
  15. package/_cjs/ocr.js +74 -0
  16. package/_cjs/path.js +35 -0
  17. package/_cjs/pinyin.js +32 -0
  18. package/_cjs/puppeteer.js +271 -0
  19. package/_cjs/runner.js +88 -0
  20. package/_cjs/task.js +41 -0
  21. package/_cjs/text.js +136 -0
  22. package/_cjs/unicode/lib_unicode.js +58643 -0
  23. package/_cjs/unicode/unicode.js +441 -0
  24. package/_cjs/upload.js +100 -0
  25. package/_cjs/yaml.js +52 -0
  26. package/ai.d.ts +26 -0
  27. package/ai.js +60 -0
  28. package/cli.d.ts +14 -0
  29. package/cli.js +21 -0
  30. package/clipboard.d.ts +6 -0
  31. package/clipboard.js +35 -0
  32. package/cmd.d.ts +5 -0
  33. package/cmd.js +22 -0
  34. package/crawler.d.ts +162 -0
  35. package/crawler.js +332 -0
  36. package/csv.d.ts +14 -0
  37. package/csv.js +67 -0
  38. package/data_set.d.ts +22 -0
  39. package/data_set.js +85 -0
  40. package/env.d.ts +4 -0
  41. package/env.js +32 -0
  42. package/fs.d.ts +2 -0
  43. package/fs.js +5 -0
  44. package/html.d.ts +7 -0
  45. package/html.js +45 -0
  46. package/http_server.d.ts +10 -0
  47. package/http_server.js +26 -0
  48. package/json.d.ts +6 -0
  49. package/json.js +19 -0
  50. package/ksb.d.ts +32 -0
  51. package/ksb.js +197 -0
  52. package/number.d.ts +3 -0
  53. package/number.js +9 -0
  54. package/ocr.d.ts +10 -0
  55. package/ocr.js +54 -0
  56. package/ofd.d.ts +1 -0
  57. package/package.json +158 -0
  58. package/path.d.ts +2 -0
  59. package/path.js +5 -0
  60. package/pinyin.d.ts +3 -0
  61. package/pinyin.js +12 -0
  62. package/puppeteer.d.ts +38 -0
  63. package/puppeteer.js +241 -0
  64. package/runner.d.ts +13 -0
  65. package/runner.js +58 -0
  66. package/task.d.ts +6 -0
  67. package/task.js +21 -0
  68. package/text.d.ts +63 -0
  69. package/text.js +119 -0
  70. package/unicode/lib_unicode.d.ts +4 -0
  71. package/unicode/lib_unicode.js +58623 -0
  72. package/unicode/unicode.d.ts +347 -0
  73. package/unicode/unicode.js +426 -0
  74. package/upload.d.ts +22 -0
  75. package/upload.js +70 -0
  76. package/yaml.d.ts +6 -0
  77. package/yaml.js +22 -0
package/package.json ADDED
@@ -0,0 +1,158 @@
1
+ {
2
+ "name": "@jayfong/x-utils",
3
+ "description": "123456",
4
+ "version": "1.0.0-202407012223",
5
+ "type": "module",
6
+ "dependencies": {
7
+ "vtils": "^4.115.0",
8
+ "cli-table3": "^0.6.3",
9
+ "inquirer": "^9.2.13",
10
+ "clipboardy": "^4.0.0",
11
+ "execa": "^8.0.1",
12
+ "@jayfong/x-request": "^2.35.2",
13
+ "node-html-parser": "^6.1.12",
14
+ "csv": "^6.3.6",
15
+ "exit-hook": "^4.0.0",
16
+ "fs-extra": "^11.2.0",
17
+ "dotenv": "^16.4.5",
18
+ "docx": "^8.5.0",
19
+ "image-dimensions": "^2.3.0",
20
+ "@fastify/cors": "^9.0.1",
21
+ "fastify": "^4.26.0",
22
+ "nzh": "^1.0.12",
23
+ "pathe": "^1.1.2",
24
+ "pinyin-pro": "^3.19.4",
25
+ "puppeteer": "^22.3.0",
26
+ "consola": "^3.2.3",
27
+ "html-entities": "^2.5.2",
28
+ "file-type": "^19.0.0",
29
+ "sharp": "^0.32.5",
30
+ "yaml": "^2.3.4"
31
+ },
32
+ "exports": {
33
+ "./package.json": "./package.json",
34
+ "./ai": {
35
+ "require": "./_cjs/ai.js",
36
+ "import": "./ai.js",
37
+ "types": "./ai.d.ts"
38
+ },
39
+ "./cli": {
40
+ "require": "./_cjs/cli.js",
41
+ "import": "./cli.js",
42
+ "types": "./cli.d.ts"
43
+ },
44
+ "./clipboard": {
45
+ "require": "./_cjs/clipboard.js",
46
+ "import": "./clipboard.js",
47
+ "types": "./clipboard.d.ts"
48
+ },
49
+ "./cmd": {
50
+ "require": "./_cjs/cmd.js",
51
+ "import": "./cmd.js",
52
+ "types": "./cmd.d.ts"
53
+ },
54
+ "./crawler": {
55
+ "require": "./_cjs/crawler.js",
56
+ "import": "./crawler.js",
57
+ "types": "./crawler.d.ts"
58
+ },
59
+ "./csv": {
60
+ "require": "./_cjs/csv.js",
61
+ "import": "./csv.js",
62
+ "types": "./csv.d.ts"
63
+ },
64
+ "./data_set": {
65
+ "require": "./_cjs/data_set.js",
66
+ "import": "./data_set.js",
67
+ "types": "./data_set.d.ts"
68
+ },
69
+ "./env": {
70
+ "require": "./_cjs/env.js",
71
+ "import": "./env.js",
72
+ "types": "./env.d.ts"
73
+ },
74
+ "./fs": {
75
+ "require": "./_cjs/fs.js",
76
+ "import": "./fs.js",
77
+ "types": "./fs.d.ts"
78
+ },
79
+ "./html": {
80
+ "require": "./_cjs/html.js",
81
+ "import": "./html.js",
82
+ "types": "./html.d.ts"
83
+ },
84
+ "./http_server": {
85
+ "require": "./_cjs/http_server.js",
86
+ "import": "./http_server.js",
87
+ "types": "./http_server.d.ts"
88
+ },
89
+ "./json": {
90
+ "require": "./_cjs/json.js",
91
+ "import": "./json.js",
92
+ "types": "./json.d.ts"
93
+ },
94
+ "./ksb": {
95
+ "require": "./_cjs/ksb.js",
96
+ "import": "./ksb.js",
97
+ "types": "./ksb.d.ts"
98
+ },
99
+ "./number": {
100
+ "require": "./_cjs/number.js",
101
+ "import": "./number.js",
102
+ "types": "./number.d.ts"
103
+ },
104
+ "./ocr": {
105
+ "require": "./_cjs/ocr.js",
106
+ "import": "./ocr.js",
107
+ "types": "./ocr.d.ts"
108
+ },
109
+ "./path": {
110
+ "require": "./_cjs/path.js",
111
+ "import": "./path.js",
112
+ "types": "./path.d.ts"
113
+ },
114
+ "./pinyin": {
115
+ "require": "./_cjs/pinyin.js",
116
+ "import": "./pinyin.js",
117
+ "types": "./pinyin.d.ts"
118
+ },
119
+ "./puppeteer": {
120
+ "require": "./_cjs/puppeteer.js",
121
+ "import": "./puppeteer.js",
122
+ "types": "./puppeteer.d.ts"
123
+ },
124
+ "./runner": {
125
+ "require": "./_cjs/runner.js",
126
+ "import": "./runner.js",
127
+ "types": "./runner.d.ts"
128
+ },
129
+ "./task": {
130
+ "require": "./_cjs/task.js",
131
+ "import": "./task.js",
132
+ "types": "./task.d.ts"
133
+ },
134
+ "./text": {
135
+ "require": "./_cjs/text.js",
136
+ "import": "./text.js",
137
+ "types": "./text.d.ts"
138
+ },
139
+ "./upload": {
140
+ "require": "./_cjs/upload.js",
141
+ "import": "./upload.js",
142
+ "types": "./upload.d.ts"
143
+ },
144
+ "./yaml": {
145
+ "require": "./_cjs/yaml.js",
146
+ "import": "./yaml.js",
147
+ "types": "./yaml.d.ts"
148
+ },
149
+ "./unicode": {
150
+ "require": "./_cjs/unicode/unicode.js",
151
+ "import": "./unicode/unicode.js",
152
+ "types": "./unicode/unicode.d.ts"
153
+ }
154
+ },
155
+ "publishConfig": {
156
+ "access": "public"
157
+ }
158
+ }
package/path.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import path from 'pathe';
2
+ export declare const XPath: typeof path;
package/path.js ADDED
@@ -0,0 +1,5 @@
1
+ import path from "pathe";
2
+ const XPath = path;
3
+ export {
4
+ XPath
5
+ };
package/pinyin.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export declare class XPinyin {
2
+ static getTonelessPinyin(text: string): string[];
3
+ }
package/pinyin.js ADDED
@@ -0,0 +1,12 @@
1
+ import { pinyin } from "pinyin-pro";
2
+ class XPinyin {
3
+ static getTonelessPinyin(text) {
4
+ return pinyin(text, {
5
+ type: "array",
6
+ toneType: "none"
7
+ });
8
+ }
9
+ }
10
+ export {
11
+ XPinyin
12
+ };
package/puppeteer.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ /// <reference types="lodash" />
2
+ import { Browser, ElementHandle, Page } from 'puppeteer';
3
+ export type XPuppeteerBrowser = Browser;
4
+ export type XPuppeteerPage = Page;
5
+ export type XPuppeteerOpenBrowserOptions = {
6
+ headful?: boolean;
7
+ proxy?: string;
8
+ dataDir?: string;
9
+ };
10
+ export type XPuppeteerOpenPageOptions = {
11
+ match?: string | RegExp;
12
+ blockAssets?: boolean;
13
+ referer?: string;
14
+ };
15
+ export type XPuppeteerGetPageHtmlOptions = XPuppeteerOpenBrowserOptions & XPuppeteerOpenPageOptions & {
16
+ instanceId?: string | number;
17
+ useSystemBrowser?: boolean;
18
+ afterOpenPage?: (payload: {
19
+ browser: XPuppeteer;
20
+ page: XPuppeteerPage;
21
+ }) => any;
22
+ };
23
+ export declare class XPuppeteer {
24
+ browser: Browser;
25
+ connectSystemBrowser(): Promise<Browser>;
26
+ openBrowser(options?: XPuppeteerOpenBrowserOptions): Promise<Browser>;
27
+ openPage(urlOrHtml: string, options?: XPuppeteerOpenPageOptions): Promise<Page>;
28
+ input(page: Page, selector: string, textOrHtml: string, frameIndex?: number): Promise<void>;
29
+ selectAll(page: Page): Promise<void>;
30
+ paste(page: Page): Promise<void>;
31
+ queryByText<T extends Node = HTMLDivElement>(page: Page, text: string | RegExp | ((el: T) => boolean)): Promise<ElementHandle<T>>;
32
+ disconnect(): Promise<void>;
33
+ close(): Promise<void>;
34
+ static openBrowser(options?: XPuppeteerOpenBrowserOptions): Promise<XPuppeteer>;
35
+ static openPage(urlOrHtml: string, options?: XPuppeteerGetPageHtmlOptions): Promise<Page>;
36
+ static getPageHtmlXp: ((options: XPuppeteerGetPageHtmlOptions) => Promise<XPuppeteer>) & import("lodash").MemoizedFunction;
37
+ static getPageHtml(url: string, options?: XPuppeteerGetPageHtmlOptions): Promise<string>;
38
+ }
package/puppeteer.js ADDED
@@ -0,0 +1,241 @@
1
+ import { xr } from "@jayfong/x-request";
2
+ import { asyncExitHook } from "exit-hook";
3
+ import puppeteer from "puppeteer";
4
+ import { isFunction, isRegExp, memoize } from "vtils";
5
+ import { XClipboard } from "./clipboard.js";
6
+ class XPuppeteer {
7
+ browser;
8
+ async connectSystemBrowser() {
9
+ const {
10
+ data: { webSocketDebuggerUrl }
11
+ } = await xr.getJson({
12
+ url: "http://localhost:9222/json/version"
13
+ });
14
+ const browser = await puppeteer.connect({
15
+ browserWSEndpoint: webSocketDebuggerUrl,
16
+ // 都设为 0 以保持原有的宽高
17
+ defaultViewport: {
18
+ width: 0,
19
+ height: 0
20
+ }
21
+ });
22
+ this.browser = browser;
23
+ asyncExitHook(() => this.disconnect(), {
24
+ wait: 1e3
25
+ });
26
+ return browser;
27
+ }
28
+ async openBrowser(options = {}) {
29
+ const browser = await puppeteer.launch({
30
+ headless: options.headful ? false : true,
31
+ defaultViewport: {
32
+ width: 1440,
33
+ height: 900
34
+ },
35
+ userDataDir: options.dataDir,
36
+ args: options.proxy ? [`--proxy-server=${options.proxy}`] : void 0
37
+ });
38
+ this.browser = browser;
39
+ asyncExitHook(() => this.close(), {
40
+ wait: 1e3
41
+ });
42
+ return browser;
43
+ }
44
+ async openPage(urlOrHtml, options = {}) {
45
+ const isUrl = /^https?:\/\//i.test(urlOrHtml);
46
+ const pages = await this.browser.pages();
47
+ if (isUrl) {
48
+ const inputUrl = new URL(urlOrHtml);
49
+ const foundPage = pages.find((item) => {
50
+ const pageUrl = item.url();
51
+ const url = new URL(pageUrl);
52
+ return inputUrl.origin === url.origin && (pageUrl === urlOrHtml || !!options.match && (typeof options.match === "string" ? `${url.pathname}${url.search}`.includes(options.match) : options.match.test(`${url.pathname}${url.search}`)));
53
+ });
54
+ if (foundPage) {
55
+ return foundPage;
56
+ }
57
+ }
58
+ const page2 = await this.browser.newPage();
59
+ await page2.setUserAgent(
60
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
61
+ );
62
+ if (options.blockAssets) {
63
+ await page2.setRequestInterception(true);
64
+ page2.on("request", (req) => {
65
+ const resourceType = req.resourceType();
66
+ if (resourceType === "stylesheet" || resourceType === "font" || resourceType === "image") {
67
+ req.abort();
68
+ } else {
69
+ req.continue();
70
+ }
71
+ });
72
+ }
73
+ if (isUrl) {
74
+ await page2.goto(urlOrHtml, {
75
+ referer: options.referer || urlOrHtml
76
+ });
77
+ } else {
78
+ await page2.setContent(urlOrHtml);
79
+ }
80
+ return page2;
81
+ }
82
+ async input(page2, selector, textOrHtml, frameIndex) {
83
+ const mainPage = page2;
84
+ const keyboard = page2.keyboard;
85
+ if (frameIndex != null) {
86
+ page2 = page2.frames()[frameIndex];
87
+ }
88
+ const el2 = await page2.$(selector);
89
+ const isText = await el2.evaluate((el3) => {
90
+ const isInput = el3.tagName === "INPUT" || el3.tagName === "TEXTAREA";
91
+ const isText2 = isInput || el3.tagName === "SPAN";
92
+ return isText2;
93
+ });
94
+ if (isText) {
95
+ await XClipboard.writeText(textOrHtml);
96
+ } else {
97
+ await XClipboard.writeHtml(textOrHtml);
98
+ }
99
+ await el2.click();
100
+ await this.selectAll(page2);
101
+ await keyboard.press("Backspace");
102
+ await this.paste(mainPage);
103
+ }
104
+ async selectAll(page2) {
105
+ await page2.evaluate(() => {
106
+ const isMac = /Mac|iPod|iPhone|iPad/.test(window.navigator.platform);
107
+ document.activeElement.dispatchEvent(
108
+ new KeyboardEvent("keydown", {
109
+ bubbles: true,
110
+ cancelable: true,
111
+ key: isMac ? "Meta" : "Control",
112
+ code: isMac ? "MetaLeft" : "ControlLeft",
113
+ location: window.KeyboardEvent.DOM_KEY_LOCATION_LEFT,
114
+ // @ts-ignore
115
+ getModifierState: (keyArg) => keyArg === (isMac ? "Meta" : "Control"),
116
+ ctrlKey: !isMac,
117
+ metaKey: isMac,
118
+ charCode: 0,
119
+ keyCode: isMac ? 93 : 17,
120
+ which: isMac ? 93 : 17
121
+ })
122
+ );
123
+ const preventableEvent = new KeyboardEvent("keydown", {
124
+ bubbles: true,
125
+ cancelable: true,
126
+ key: "a",
127
+ code: "KeyA",
128
+ location: window.KeyboardEvent.DOM_KEY_LOCATION_STANDARD,
129
+ // @ts-ignore
130
+ getModifierState: (keyArg) => keyArg === (isMac ? "Meta" : "Control"),
131
+ ctrlKey: !isMac,
132
+ metaKey: isMac,
133
+ charCode: 0,
134
+ keyCode: 65,
135
+ which: 65
136
+ });
137
+ const wasPrevented = !document.activeElement.dispatchEvent(preventableEvent) || preventableEvent.defaultPrevented;
138
+ if (!wasPrevented) {
139
+ document.execCommand("selectall", false, null);
140
+ }
141
+ document.activeElement.dispatchEvent(
142
+ new KeyboardEvent("keyup", {
143
+ bubbles: true,
144
+ cancelable: true,
145
+ key: isMac ? "Meta" : "Control",
146
+ code: isMac ? "MetaLeft" : "ControlLeft",
147
+ location: window.KeyboardEvent.DOM_KEY_LOCATION_LEFT,
148
+ // @ts-ignore
149
+ getModifierState: () => false,
150
+ charCode: 0,
151
+ keyCode: isMac ? 93 : 17,
152
+ which: isMac ? 93 : 17
153
+ })
154
+ );
155
+ });
156
+ }
157
+ async paste(page2) {
158
+ await page2.keyboard.down("Shift");
159
+ await page2.keyboard.press("Insert");
160
+ await page2.keyboard.up("Shift");
161
+ }
162
+ async queryByText(page, text) {
163
+ const el = await page.evaluateHandle(
164
+ (text, isRegExp, isFunction) => {
165
+ const textRe = isRegExp ? (() => {
166
+ const m = text.match(/^\/(.+)\/([^/]*)$/);
167
+ return new RegExp(m[1], m[2] || void 0);
168
+ })() : void 0;
169
+ const textFn = isFunction ? eval(`(() => {return ${text}})()`) : void 0;
170
+ const walker = document.createTreeWalker(
171
+ document.body,
172
+ NodeFilter.SHOW_TEXT,
173
+ {
174
+ acceptNode: (node) => {
175
+ return (isRegExp ? textRe.test(node.textContent) : isFunction ? textFn(node) : node.textContent.includes(text)) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
176
+ }
177
+ }
178
+ );
179
+ walker.nextNode();
180
+ return walker.currentNode.parentElement;
181
+ },
182
+ String(text),
183
+ isRegExp(text),
184
+ isFunction(text)
185
+ );
186
+ return el;
187
+ }
188
+ async disconnect() {
189
+ await this.browser.disconnect();
190
+ }
191
+ async close() {
192
+ await this.browser.close();
193
+ }
194
+ static async openBrowser(options = {}) {
195
+ const xp = new XPuppeteer();
196
+ await xp.openBrowser(options);
197
+ return xp;
198
+ }
199
+ static async openPage(urlOrHtml, options = {}) {
200
+ const xp = new XPuppeteer();
201
+ await xp.openBrowser(options);
202
+ const page2 = await xp.openPage(urlOrHtml, options);
203
+ page2.close = () => xp.close();
204
+ return page2;
205
+ }
206
+ static getPageHtmlXp = memoize(
207
+ async (options) => {
208
+ const xp = new XPuppeteer();
209
+ await (options.useSystemBrowser ? xp.connectSystemBrowser() : xp.openBrowser(options));
210
+ return xp;
211
+ },
212
+ (options) => options.instanceId
213
+ );
214
+ static async getPageHtml(url, options = {}) {
215
+ const hasInstanceId = !!options.instanceId;
216
+ options.instanceId ||= Date.now();
217
+ const xp = await XPuppeteer.getPageHtmlXp(options);
218
+ try {
219
+ const page2 = await xp.openPage(url, options);
220
+ if (options.afterOpenPage) {
221
+ await options.afterOpenPage({
222
+ browser: xp,
223
+ page: page2
224
+ });
225
+ }
226
+ const html = await page2.content();
227
+ return html;
228
+ } finally {
229
+ if (!hasInstanceId) {
230
+ if (options.useSystemBrowser) {
231
+ await xp.disconnect();
232
+ } else {
233
+ await xp.close();
234
+ }
235
+ }
236
+ }
237
+ }
238
+ }
239
+ export {
240
+ XPuppeteer
241
+ };
package/runner.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { DistinctQuestion } from 'inquirer';
2
+ import { MsValue } from 'vtils';
3
+ export type XRunnerOptions<TConfig extends Record<any, any>> = {
4
+ configFile: string;
5
+ delay: MsValue | ((retryCount: number) => MsValue);
6
+ questions: Array<DistinctQuestion<TConfig>>;
7
+ run: (config: TConfig) => any;
8
+ };
9
+ export declare class XRunner<TConfig extends Record<any, any>> {
10
+ private options;
11
+ constructor(options: XRunnerOptions<TConfig>);
12
+ run(): Promise<void>;
13
+ }
package/runner.js ADDED
@@ -0,0 +1,58 @@
1
+ import inquirer from "inquirer";
2
+ import { ms, wait } from "vtils";
3
+ import { XFs } from "./fs.js";
4
+ class XRunner {
5
+ constructor(options) {
6
+ this.options = options;
7
+ }
8
+ async run() {
9
+ await XFs.ensureFile(this.options.configFile);
10
+ const savedConfig = await XFs.readJson(this.options.configFile, { throws: false }) || {};
11
+ const config = await inquirer.prompt(
12
+ this.options.questions.map((item) => {
13
+ return {
14
+ ...item,
15
+ default: savedConfig[item.name] ?? item.default
16
+ };
17
+ })
18
+ );
19
+ await XFs.writeJson(this.options.configFile, config, { spaces: 2 });
20
+ let retryCount = 0;
21
+ while (true) {
22
+ try {
23
+ await this.options.run(config);
24
+ retryCount = 0;
25
+ } catch (err) {
26
+ const delay = typeof this.options.delay === "function" ? this.options.delay(retryCount) : this.options.delay;
27
+ console.log(err);
28
+ console.log(`\u6267\u884C\u62A5\u9519, \u7B49\u5F85${delay}`);
29
+ await wait(ms(delay));
30
+ retryCount++;
31
+ }
32
+ }
33
+ }
34
+ }
35
+ new XRunner({
36
+ configFile: "./temp/test.json",
37
+ delay: "1s",
38
+ questions: [
39
+ {
40
+ name: "perCount",
41
+ message: "\u6BCF\u8F6E\u5904\u7406\u6761\u6570",
42
+ type: "number",
43
+ default: 500
44
+ },
45
+ {
46
+ name: "concurrencyCount",
47
+ message: "\u6BCF\u8F6E\u5E76\u884C\u5904\u7406\u6761\u6570",
48
+ type: "number",
49
+ default: 1
50
+ }
51
+ ],
52
+ run: (config) => {
53
+ console.log(config);
54
+ }
55
+ }).run();
56
+ export {
57
+ XRunner
58
+ };
package/task.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export declare abstract class XTask {
2
+ log: import("consola/core").ConsolaInstance;
3
+ abstract start(): Promise<void>;
4
+ dispose(): Promise<void>;
5
+ run(): Promise<void>;
6
+ }
package/task.js ADDED
@@ -0,0 +1,21 @@
1
+ import { consola as log } from "consola";
2
+ import { asyncExitHook, gracefulExit } from "exit-hook";
3
+ class XTask {
4
+ log = log;
5
+ async dispose() {
6
+ }
7
+ run() {
8
+ asyncExitHook(() => this.dispose(), {
9
+ wait: 3e3
10
+ });
11
+ return this.start().then(() => {
12
+ gracefulExit(0);
13
+ }).catch((err) => {
14
+ log.error(err);
15
+ gracefulExit(1);
16
+ });
17
+ }
18
+ }
19
+ export {
20
+ XTask
21
+ };
package/text.d.ts ADDED
@@ -0,0 +1,63 @@
1
+ export declare class XText {
2
+ private text;
3
+ /**
4
+ * 将字符串分割为字符数组。
5
+ *
6
+ * @see https://stackoverflow.com/a/71619350
7
+ */
8
+ static split(text: string): string[];
9
+ /**
10
+ * 纯粹为了书写 HTML 有提示。
11
+ */
12
+ static html(literals: any, ...interpolations: any): string;
13
+ /**
14
+ * 切割字符串。
15
+ */
16
+ static cut(text: string, start: string, end: string): string;
17
+ /**
18
+ * 移除全部空白字符。
19
+ */
20
+ static stripWhitespace(text: string): string;
21
+ /**
22
+ * 移除首尾空白字符。
23
+ */
24
+ static stripMarginWhitespace(text: string): string;
25
+ /**
26
+ * HTML 实体编码。
27
+ */
28
+ static encodeHtmlEntity(text: string): string;
29
+ /**
30
+ * HTML 实体解码。
31
+ */
32
+ static decodeHtmlEntity(text: string): string;
33
+ /**
34
+ * 移除 HTML 代码。
35
+ */
36
+ static stripHtml(text: string): string;
37
+ constructor(text: string);
38
+ /**
39
+ * 切割字符串。
40
+ */
41
+ cut(start: string, end: string): this;
42
+ /**
43
+ * 移除全部空白字符。
44
+ */
45
+ stripWhitespace(): this;
46
+ /**
47
+ * 移除首尾空白字符。
48
+ */
49
+ stripMarginWhitespace(): this;
50
+ /**
51
+ * HTML 实体编码。
52
+ */
53
+ encodeHtmlEntity(): this;
54
+ /**
55
+ * HTML 实体解码。
56
+ */
57
+ decodeHtmlEntity(): this;
58
+ /**
59
+ * 移除 HTML 代码。
60
+ */
61
+ stripHtml(): this;
62
+ toString(): string;
63
+ }