ph-utils 0.6.0 → 0.6.2

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/date.d.ts CHANGED
@@ -12,9 +12,9 @@ export declare function format(date?: Date | string | number | null, pattern?: s
12
12
  export declare function parse(date?: Date | string | number | null): Date;
13
13
  /**
14
14
  * 设置日期的开始或者结束的点
15
- * @param {Object} date 日期,能够被 parse 解析的日期
16
- * @param {String} unit 单位,Date|date, 默认为 Date
17
- * @param {Boolean} isEnd true则为 endOf
15
+ * @param date 日期,能够被 parse 解析的日期
16
+ * @param unit 单位,Date|date, 默认为 Date
17
+ * @param isEnd true则为 endOf
18
18
  */
19
19
  export declare function dateOf(date?: Date | string | number, unit?: string, isEnd?: boolean): Date;
20
20
  /**
@@ -45,6 +45,10 @@ export declare function timeStamp(ctime?: Date | string | number, pre?: "s" | "m
45
45
  * @param unit 需要添加的单位,date、month、year、hours、minute、second
46
46
  *
47
47
  * 查阅文档: {@link https://gitee.com/towardly/ph/wikis/utils/date ph-utils}
48
+ *
49
+ * @example <caption>1. 分钟加1并格式化显示时间</caption>
50
+ *
51
+ * add(new Date(), 1, 'minute', 'HHMMss')
48
52
  */
49
53
  export declare function add(date: Date | string | number | null, num: number, unit: string): Date;
50
54
  /**
package/lib/date.js CHANGED
@@ -131,9 +131,9 @@ export function parse(date) {
131
131
  }
132
132
  /**
133
133
  * 设置日期的开始或者结束的点
134
- * @param {Object} date 日期,能够被 parse 解析的日期
135
- * @param {String} unit 单位,Date|date, 默认为 Date
136
- * @param {Boolean} isEnd true则为 endOf
134
+ * @param date 日期,能够被 parse 解析的日期
135
+ * @param unit 单位,Date|date, 默认为 Date
136
+ * @param isEnd true则为 endOf
137
137
  */
138
138
  export function dateOf(date, unit, isEnd = false) {
139
139
  /* 如果是设置某一天的开始时刻, 就需要将时、分、秒、毫秒设置为0,依次类推设置 */
package/lib/file.d.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  /**
2
- * 读取文件内容为JSON格式
3
- * @param filepath 读取的文件路径
4
- * @param defaultValue 读取失败时,提供默认值, 如果不提供传参数则[抛出异常]
5
- *
6
- * @example <caption>1. 文件不存在时, 默认为: null</caption>
7
- * await readJSON("./not-exists.json", true);
8
- *
9
- * @returns Promise<unknown>
2
+ * 读取文件内容
3
+ * @example <caption>1. 读取JSON文件, 内容为字符串列表</caption>
4
+ * read<string[]>('a.json', []);
5
+ * @example <caption>2. 读取JSON文件, 内容为对象</caption>
6
+ * read<{ name: string }>('b.json', {});
7
+ * @param filepath 文件路径
8
+ * @param defaultValue 文件不存在时默认值, 不传则抛异常, 如果传递的是对象形式则会将结果转换为 JSON
9
+ * @returns 文件内容
10
10
  */
11
- export declare function readJSON<T>(filepath: string, defaultValue?: T): Promise<T>;
11
+ export declare function read<T>(filepath: string, defaultValue?: T): Promise<any>;
12
12
  /**
13
13
  * 写入 JSON 格式的数据到文件
14
14
  * @param file 待写入的文件
@@ -20,7 +20,7 @@ export declare function readJSON<T>(filepath: string, defaultValue?: T): Promise
20
20
  export declare function write(file: string, data: any, opts?: {
21
21
  json: boolean;
22
22
  format: boolean;
23
- }): Promise<unknown>;
23
+ }): Promise<void>;
24
24
  /**
25
25
  * 根据文件的 stat 获取文件的 etag
26
26
  * @param filePath 文件地址
package/lib/file.js CHANGED
@@ -1,32 +1,30 @@
1
1
  /** nodejs 文件操作工具类 */
2
2
  import path from "node:path";
3
- import fs from "node:fs";
3
+ import fs from "node:fs/promises";
4
4
  /**
5
- * 读取文件内容为JSON格式
6
- * @param filepath 读取的文件路径
7
- * @param defaultValue 读取失败时,提供默认值, 如果不提供传参数则[抛出异常]
8
- *
9
- * @example <caption>1. 文件不存在时, 默认为: null</caption>
10
- * await readJSON("./not-exists.json", true);
11
- *
12
- * @returns Promise<unknown>
5
+ * 读取文件内容
6
+ * @example <caption>1. 读取JSON文件, 内容为字符串列表</caption>
7
+ * read<string[]>('a.json', []);
8
+ * @example <caption>2. 读取JSON文件, 内容为对象</caption>
9
+ * read<{ name: string }>('b.json', {});
10
+ * @param filepath 文件路径
11
+ * @param defaultValue 文件不存在时默认值, 不传则抛异常, 如果传递的是对象形式则会将结果转换为 JSON
12
+ * @returns 文件内容
13
13
  */
14
- export function readJSON(filepath, defaultValue) {
15
- return new Promise((resolve, reject) => {
16
- fs.readFile(path.resolve(filepath), "utf-8", (err, data) => {
17
- if (err) {
18
- if (defaultValue !== undefined) {
19
- resolve(defaultValue);
20
- }
21
- else {
22
- reject(err);
23
- }
24
- }
25
- else {
26
- resolve(JSON.parse(data));
27
- }
28
- });
29
- });
14
+ export async function read(filepath, defaultValue) {
15
+ let content;
16
+ try {
17
+ content = await fs.readFile(filepath, "utf8");
18
+ if (defaultValue != null && typeof defaultValue === "object") {
19
+ return JSON.parse(content);
20
+ }
21
+ return content;
22
+ } catch (error) {
23
+ if (defaultValue === undefined) {
24
+ throw error;
25
+ }
26
+ return defaultValue;
27
+ }
30
28
  }
31
29
  /**
32
30
  * 写入 JSON 格式的数据到文件
@@ -36,22 +34,13 @@ export function readJSON(filepath, defaultValue) {
36
34
  * @property opts.json 是否写入 JSON 格式的数据,写入数据时对数据进行 JSON 格式化,默认为:true
37
35
  * @property opts.format 是否在写入 json 数据时,将 JSON 数据格式化2个空格写入, 默认为 true
38
36
  */
39
- export function write(file, data, opts) {
40
- return new Promise((resolve, reject) => {
41
- let writeData = data.toString();
42
- opts = { json: true, format: true, ...opts };
43
- if (opts.json === true && typeof data === "object") {
44
- writeData = JSON.stringify(data, null, opts.format === true ? 2 : 0);
45
- }
46
- fs.writeFile(path.resolve(file), writeData, (err) => {
47
- if (err) {
48
- reject(err);
49
- }
50
- else {
51
- resolve(0);
52
- }
53
- });
54
- });
37
+ export async function write(file, data, opts) {
38
+ let writeData = data.toString();
39
+ opts = { json: true, format: true, ...opts };
40
+ if (opts.json === true && typeof data === "object") {
41
+ writeData = JSON.stringify(data, null, opts.format === true ? 2 : 0);
42
+ }
43
+ return await fs.writeFile(path.resolve(file), writeData);
55
44
  }
56
45
  /**
57
46
  * 根据文件的 stat 获取文件的 etag
@@ -59,6 +48,6 @@ export function write(file, data, opts) {
59
48
  * @returns file stat etag
60
49
  */
61
50
  export async function statTag(filePath) {
62
- let stat = await fs.promises.stat(filePath);
63
- return `${stat.size.toString(16)}-${stat.mtimeMs.toString(16)}`;
51
+ let stat = await fs.stat(filePath);
52
+ return `${stat.size.toString(16)}-${stat.mtimeMs.toString(16)}`;
64
53
  }
package/package.json CHANGED
@@ -52,7 +52,7 @@
52
52
  },
53
53
  "./*": "./lib/*"
54
54
  },
55
- "version": "0.6.0",
55
+ "version": "0.6.2",
56
56
  "type": "module",
57
57
  "repository": {
58
58
  "type": "git",
@@ -80,9 +80,6 @@
80
80
  "dom",
81
81
  "file"
82
82
  ],
83
- "dependencies": {
84
- "@ctrl/tinycolor": "^4.1.0"
85
- },
86
83
  "scripts": {
87
84
  "build": "node scripts/build.js"
88
85
  }