ph-utils 0.9.13 → 0.9.14

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.js CHANGED
@@ -7,40 +7,42 @@ import { readFileSync } from "node:fs";
7
7
  * @returns
8
8
  */
9
9
  export function exec(command, ...params) {
10
- let argvs = [];
11
- const commandItems = command.split(" ");
12
- const cmd = commandItems.shift();
13
- if (commandItems.length > 0) {
14
- argvs = commandItems;
10
+ let argvs = [];
11
+ const commandItems = command.split(" ");
12
+ const cmd = commandItems.shift();
13
+ if (commandItems.length > 0) {
14
+ argvs = commandItems;
15
+ }
16
+ let opts = {};
17
+ if (params[0] != null) {
18
+ if (params[0] instanceof Array) {
19
+ argvs.push(...params[0]);
20
+ if (params[1] != null) {
21
+ opts = params[1];
22
+ }
23
+ } else {
24
+ opts = params[0];
15
25
  }
16
- let opts = { shell: true };
17
- if (params[0] != null) {
18
- if (params[0] instanceof Array) {
19
- argvs.push(...params[0]);
20
- if (params[1] != null) {
21
- opts = params[1];
22
- }
26
+ }
27
+ return new Promise((resolve, reject) => {
28
+ execFile(cmd, argvs, opts || {}, (err, stdout, stderr) => {
29
+ if (err) {
30
+ reject(err);
31
+ } else {
32
+ let msg = stdout || stderr;
33
+ if (
34
+ stderr != null &&
35
+ (stderr.includes("error") || stderr.includes("Error"))
36
+ ) {
37
+ const error = new Error(stderr);
38
+ error.type = "StdErr";
39
+ reject(error);
40
+ } else {
41
+ resolve(msg);
23
42
  }
24
- else {
25
- opts = params[0];
26
- }
27
- }
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
+ }
43
44
  });
45
+ });
44
46
  }
45
47
  /**
46
48
  * 解析环境变量;
@@ -62,38 +64,37 @@ export function exec(command, ...params) {
62
64
  * @returns
63
65
  */
64
66
  export function parseEnvs() {
65
- // development, test, production
66
- const files = [".env", ".env.local"];
67
- let nodeEnv = process.env.NODE_ENV;
68
- const { values } = parseArgs({
69
- options: {
70
- NODE_ENV: {
71
- type: "string",
72
- short: "n",
73
- },
74
- },
75
- strict: false,
76
- });
77
- if (values.NODE_ENV != null && typeof values.NODE_ENV === "string") {
78
- nodeEnv = values.NODE_ENV;
79
- }
80
- if (nodeEnv == null) {
81
- nodeEnv = "production";
82
- }
83
- process.env.NODE_ENV = nodeEnv;
84
- files.push(`.env.${nodeEnv}`);
85
- let envParsed = {};
86
- for (let i = 0, len = files.length; i < len; i++) {
87
- const file = files[i];
88
- try {
89
- const envContent = readFileSync(file, { encoding: "utf-8" });
90
- const envValue = parseEnv(envContent);
91
- envParsed = { ...envParsed, ...envValue };
92
- }
93
- catch (err) { }
94
- }
95
- for (const key in envParsed) {
96
- process.env[key] = envParsed[key];
97
- }
98
- return envParsed;
67
+ // development, test, production
68
+ const files = [".env", ".env.local"];
69
+ let nodeEnv = process.env.NODE_ENV;
70
+ const { values } = parseArgs({
71
+ options: {
72
+ NODE_ENV: {
73
+ type: "string",
74
+ short: "n",
75
+ },
76
+ },
77
+ strict: false,
78
+ });
79
+ if (values.NODE_ENV != null && typeof values.NODE_ENV === "string") {
80
+ nodeEnv = values.NODE_ENV;
81
+ }
82
+ if (nodeEnv == null) {
83
+ nodeEnv = "production";
84
+ }
85
+ process.env.NODE_ENV = nodeEnv;
86
+ files.push(`.env.${nodeEnv}`);
87
+ let envParsed = {};
88
+ for (let i = 0, len = files.length; i < len; i++) {
89
+ const file = files[i];
90
+ try {
91
+ const envContent = readFileSync(file, { encoding: "utf-8" });
92
+ const envValue = parseEnv(envContent);
93
+ envParsed = { ...envParsed, ...envValue };
94
+ } catch (err) {}
95
+ }
96
+ for (const key in envParsed) {
97
+ process.env[key] = envParsed[key];
98
+ }
99
+ return envParsed;
99
100
  }
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.14",
72
72
  "type": "module",
73
73
  "repository": {
74
74
  "type": "git",