ph-utils 0.9.13 → 0.9.15

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
- ## ph-utils
2
-
3
- 整理了 js 前后端开发(web + nodejs)时常用的一些工具;[详细文档](https://gitee.com/towardly/ph/wikis/Home?sort_id=4035190)
4
-
5
- ### 包含如下工具文件
6
-
7
- `index` 基础工具类、`date` 跟日期相关的工具类、`file` 文件操作相关工具类[**服务端**]、`server` 服务端工具类、`validator` 数据验证、`dom` 浏览器节点操作相关[**前端**]、`web` 一些只适用于前端相关的工具、`color` 颜色相关工具
1
+ ## ph-utils
2
+
3
+ 整理了 js 前后端开发(web + nodejs)时常用的一些工具;[详细文档](https://gitee.com/towardly/ph/wikis/Home?sort_id=4035190)
4
+
5
+ ### 包含如下工具文件
6
+
7
+ `index` 基础工具类、`date` 跟日期相关的工具类、`file` 文件操作相关工具类[**服务端**]、`server` 服务端工具类、`validator` 数据验证、`dom` 浏览器节点操作相关[**前端**]、`web` 一些只适用于前端相关的工具、`color` 颜色相关工具
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 复制数据, 可以从多种类型的数据
3
+ * 1. 直接复制文本: await copy("待复制的文本")
4
+ * 2. 复制节点上的 data-copy-text:
5
+ * <button data-copy-text="这是待复制的文本">复制</button>
6
+ * await copy(e.target) // or await copy("#a") or await copy(document.querySelector('#a'))
7
+ * 3. 直接复制节点本身数据: await copy('#a')
8
+ * @param {string | HTMLElement} source 复制源, 从中解析待复制的数据
9
+ * @returns {Promise<boolean>} 是否复制成功
10
+ */
11
+ export declare function copy(source: string | HTMLElement): Promise<boolean>;
@@ -0,0 +1,101 @@
1
+ /**
2
+ * 创建一个临时节点缓存待复制数据
3
+ * @param {String} value - 待复制文本
4
+ * @return {HTMLElement}
5
+ */
6
+ function createFakeElement(value) {
7
+ const fakeElement = document.createElement("textarea");
8
+ fakeElement.style.border = "0";
9
+ fakeElement.style.padding = "0";
10
+ fakeElement.style.margin = "0";
11
+ fakeElement.style.position = "absolute";
12
+ fakeElement.style.left = "-9999px";
13
+ fakeElement.style.top = "-9999";
14
+ fakeElement.setAttribute("readonly", "");
15
+ fakeElement.value = value;
16
+ return fakeElement;
17
+ }
18
+ /** 通过执行 execCommand 来执行复制 */
19
+ function copyFromCommand(text) {
20
+ // 添加节点
21
+ const fakeEl = createFakeElement(text);
22
+ document.body.append(fakeEl);
23
+ fakeEl.focus();
24
+ fakeEl.select();
25
+ // 执行复制
26
+ const res = document.execCommand("copy");
27
+ fakeEl.remove(); // 删除节点
28
+ return Promise.resolve(res);
29
+ }
30
+ /** 使用 navigator.clipboard 复制 */
31
+ function copyFromClipboard(text) {
32
+ const theClipboard = navigator.clipboard;
33
+ if (theClipboard != null) {
34
+ return theClipboard
35
+ .writeText(text)
36
+ .then(() => {
37
+ Promise.resolve(true);
38
+ })
39
+ .catch(() => Promise.resolve(false));
40
+ }
41
+ return Promise.resolve(false);
42
+ }
43
+ /** 解析待复制的文本 */
44
+ function parseCopyText(source) {
45
+ let copyText = null; // 待复制文本
46
+ let sourceEl = null;
47
+ // 获取待复制数据
48
+ if (typeof source === "string") {
49
+ // 从节点拿数据
50
+ if (source.startsWith("#") || source.startsWith(".")) {
51
+ sourceEl = document.querySelector(source);
52
+ if (sourceEl == null) {
53
+ copyText = source;
54
+ }
55
+ }
56
+ else {
57
+ copyText = source;
58
+ }
59
+ }
60
+ if (source instanceof HTMLElement) {
61
+ sourceEl = source;
62
+ }
63
+ // 从节点获取待复制数据
64
+ if (sourceEl != null) {
65
+ if (sourceEl.hasAttribute("data-copy-text")) {
66
+ copyText = sourceEl.getAttribute("data-copy-text");
67
+ }
68
+ else {
69
+ const tagName = sourceEl.tagName;
70
+ if (tagName === "INPUT" || tagName === "TEXTAREA") {
71
+ copyText = sourceEl.value;
72
+ }
73
+ else {
74
+ copyText = sourceEl.textContent;
75
+ }
76
+ }
77
+ }
78
+ return copyText;
79
+ }
80
+ /**
81
+ * 复制数据, 可以从多种类型的数据
82
+ * 1. 直接复制文本: await copy("待复制的文本")
83
+ * 2. 复制节点上的 data-copy-text:
84
+ * <button data-copy-text="这是待复制的文本">复制</button>
85
+ * await copy(e.target) // or await copy("#a") or await copy(document.querySelector('#a'))
86
+ * 3. 直接复制节点本身数据: await copy('#a')
87
+ * @param {string | HTMLElement} source 复制源, 从中解析待复制的数据
88
+ * @returns {Promise<boolean>} 是否复制成功
89
+ */
90
+ export async function copy(source) {
91
+ // 待复制文本
92
+ const copyText = parseCopyText(source);
93
+ if (copyText == null) {
94
+ return Promise.resolve(false);
95
+ }
96
+ const v = await copyFromClipboard(copyText);
97
+ if (v === false) {
98
+ return copyFromCommand(copyText);
99
+ }
100
+ return Promise.resolve(true);
101
+ }
package/lib/server.d.ts CHANGED
@@ -5,9 +5,18 @@ import type { SpawnOptions } from "node:child_process";
5
5
  * @param command 待执行的命令
6
6
  * @param args 命令参数
7
7
  */
8
- export declare function exec(command: string, args?: string[]): Promise<string>;
9
- export declare function exec(command: string, options?: SpawnOptions): Promise<string>;
10
- export declare function exec(command: string, args?: string[], options?: SpawnOptions): Promise<string>;
8
+ export declare function exec(command: string, args?: string[]): Promise<{
9
+ stdout: string;
10
+ stderr: string;
11
+ }>;
12
+ export declare function exec(command: string, options?: SpawnOptions): Promise<{
13
+ stdout: string;
14
+ stderr: string;
15
+ }>;
16
+ export declare function exec(command: string, args?: string[], options?: SpawnOptions): Promise<{
17
+ stdout: string;
18
+ stderr: string;
19
+ }>;
11
20
  /**
12
21
  * 解析环境变量;
13
22
  * 同时读取多个环境变量文件: .env, .env.local, .env.[development|test|production];
package/lib/server.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { execFile } from "node:child_process";
2
- import { parseEnv, parseArgs } from "node:util";
2
+ import { parseEnv, parseArgs, promisify } from "node:util";
3
3
  import { readFileSync } from "node:fs";
4
+ const execFilePromise = promisify(execFile);
4
5
  /**
5
6
  * 执行命令
6
7
  * @param cmd 执行的命令
@@ -25,22 +26,7 @@ export function exec(command, ...params) {
25
26
  opts = params[0];
26
27
  }
27
28
  }
28
- return new Promise((resolve, reject) => {
29
- execFile(cmd, argvs, opts, (err, stdout, stderr) => {
30
- if (err) {
31
- reject(err);
32
- }
33
- else {
34
- let msg = stdout || stderr;
35
- if (msg.includes("error") || msg.includes("Error")) {
36
- const error = new Error(msg);
37
- error.type = "StdErr";
38
- reject(error);
39
- }
40
- resolve(msg);
41
- }
42
- });
43
- });
29
+ return execFilePromise(cmd, argvs, opts);
44
30
  }
45
31
  /**
46
32
  * 解析环境变量;
@@ -89,6 +75,7 @@ export function parseEnvs() {
89
75
  const envContent = readFileSync(file, { encoding: "utf-8" });
90
76
  const envValue = parseEnv(envContent);
91
77
  envParsed = { ...envParsed, ...envValue };
78
+ // eslint-disable-next-line
92
79
  }
93
80
  catch (err) { }
94
81
  }
package/lib/theme.js CHANGED
@@ -19,10 +19,10 @@ export async function initTheme() {
19
19
  if ($themeStyle == null) {
20
20
  $themeStyle = document.createElement("style");
21
21
  $themeStyle.id = "theme-style";
22
- $themeStyle.innerHTML = `
23
- :root{color-scheme:light dark;}
24
- html.light{color-scheme: light;}
25
- html.dark {color-scheme: dark;}
22
+ $themeStyle.innerHTML = `
23
+ :root{color-scheme:light dark;}
24
+ html.light{color-scheme: light;}
25
+ html.dark {color-scheme: dark;}
26
26
  `;
27
27
  document.head.appendChild($themeStyle);
28
28
  }
package/package.json CHANGED
@@ -68,7 +68,7 @@
68
68
  },
69
69
  "./*": "./lib/*"
70
70
  },
71
- "version": "0.9.13",
71
+ "version": "0.9.15",
72
72
  "type": "module",
73
73
  "repository": {
74
74
  "type": "git",
@@ -82,7 +82,7 @@
82
82
  },
83
83
  "homepage": "https://gitee.com/towardly/ph/tree/master/packages/utils",
84
84
  "devDependencies": {
85
- "@types/node": "^22.7.9",
85
+ "@types/node": "^22.8.2",
86
86
  "typescript": "^5.6.3"
87
87
  },
88
88
  "files": [