ph-utils 0.2.23 → 0.3.1
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/LICENSE +21 -0
- package/README.md +11 -11
- package/lib/date.d.ts +55 -34
- package/lib/date.js +203 -126
- package/lib/dom.d.ts +92 -92
- package/lib/dom.js +190 -190
- package/lib/file.d.ts +31 -34
- package/lib/file.js +96 -99
- package/lib/index.d.ts +97 -61
- package/lib/index.js +171 -96
- package/lib/server.d.ts +32 -39
- package/lib/server.js +77 -93
- package/lib/validator.d.ts +47 -47
- package/lib/validator.js +212 -215
- package/lib/web.d.ts +13 -55
- package/lib/web.js +57 -141
- package/package.json +10 -9
- package/lib/date_m.d.ts +0 -34
- package/lib/date_m.js +0 -119
- package/lib/index_m.d.ts +0 -61
- package/lib/index_m.js +0 -82
- package/lib/validator_m.d.ts +0 -47
- package/lib/validator_m.js +0 -210
package/lib/dom.js
CHANGED
@@ -1,190 +1,190 @@
|
|
1
|
-
/**
|
2
|
-
* web(浏览器端) DOM 文件操作
|
3
|
-
* 现今不推荐在使用这种方式,现在开发前端的时候,推荐使用一些成熟的框架例如:React、Preact、Vue、Angular、Svelte、Ember、Knockout等
|
4
|
-
* 在使用这些框架的时候额外的一些不可避免的 dom 操作时才使用这个工具;如果确实需要使用原生开发推荐使用 jquery 或者想要更精简的话可以使用 https://github.com/finom/bala 封装
|
5
|
-
*/
|
6
|
-
const vendorPrefix = ['', '-webkit', '-moz-'];
|
7
|
-
/**
|
8
|
-
* 根据选择器获取节点
|
9
|
-
* @param {string} selector 选择器
|
10
|
-
*/
|
11
|
-
export function elem(selector, dom) {
|
12
|
-
if (typeof selector === 'string') {
|
13
|
-
return (dom || document).querySelectorAll(selector);
|
14
|
-
}
|
15
|
-
else {
|
16
|
-
return [selector];
|
17
|
-
}
|
18
|
-
}
|
19
|
-
/**
|
20
|
-
* 为节点添加 class
|
21
|
-
* @param {HTMLElement} elem 待添加 class 的节点
|
22
|
-
* @param {string} clazz 需要添加的 class
|
23
|
-
*/
|
24
|
-
export function addClass(elem, clazz) {
|
25
|
-
elem.classList.add(clazz);
|
26
|
-
}
|
27
|
-
/**
|
28
|
-
* 节点移除 class
|
29
|
-
* @param {HTMLElement} elem 待移除 class 的节点
|
30
|
-
* @param {string} clazz 需要移除的 class
|
31
|
-
*/
|
32
|
-
export function removeClass(elem, clazz) {
|
33
|
-
elem.classList.remove(clazz);
|
34
|
-
}
|
35
|
-
/**
|
36
|
-
* 判断节点是否包含某个 class
|
37
|
-
* @param elem 待判断 class 的节点
|
38
|
-
* @param clazz 待判断的 class
|
39
|
-
* @returns
|
40
|
-
*/
|
41
|
-
export function hasClass(elem, clazz) {
|
42
|
-
return elem.classList.contains(clazz);
|
43
|
-
}
|
44
|
-
/**
|
45
|
-
* 为节点添加 transition 属性,包括浏览器前缀
|
46
|
-
* @param {HTMLElement} element 需要添加 css Transition 属性的节点
|
47
|
-
* @param {string} value css transition 值
|
48
|
-
*/
|
49
|
-
export function transition(element, value) {
|
50
|
-
vendorPrefix.forEach((prefix) => {
|
51
|
-
let t = prefix === '' ? 'transition' : prefix + 'Transition';
|
52
|
-
element.style[t] = value;
|
53
|
-
});
|
54
|
-
}
|
55
|
-
/**
|
56
|
-
* 为节点添加 transform 属性,包括浏览器前缀
|
57
|
-
* @param {HTMLElement} element 需要添加 css transform 属性的节点
|
58
|
-
* @param {string} value css transform 值
|
59
|
-
*/
|
60
|
-
export function transform(element, value) {
|
61
|
-
vendorPrefix.forEach((prefix) => {
|
62
|
-
let t = prefix === '' ? 'transform' : prefix + 'Transform';
|
63
|
-
element.style[t] = value;
|
64
|
-
});
|
65
|
-
}
|
66
|
-
/**
|
67
|
-
* 为节点添加事件处理
|
68
|
-
* @param {HTMLElement} element 添加事件的节点
|
69
|
-
* @param {string} listener 事件名称
|
70
|
-
* @param {function} event 事件处理函数
|
71
|
-
* @param {boolean} onceOrConfig 是否是只运行一次的处理函数或者配置,其中 eventFlag 为 string,如果配置该项,则表明为委托事件
|
72
|
-
*/
|
73
|
-
export function on(element, listener, fn, once = false) {
|
74
|
-
let eventExtra = { eventStop: false };
|
75
|
-
if (typeof once === 'boolean') {
|
76
|
-
eventExtra.once = once;
|
77
|
-
}
|
78
|
-
else {
|
79
|
-
eventExtra = once;
|
80
|
-
}
|
81
|
-
if (eventExtra.eventFlag != null) {
|
82
|
-
element.setAttribute(eventExtra.eventFlag, '__stop__');
|
83
|
-
element.addEventListener(listener, (e) => {
|
84
|
-
let target = e.target;
|
85
|
-
let flag = '';
|
86
|
-
do {
|
87
|
-
flag = target.getAttribute(eventExtra.eventFlag) || '';
|
88
|
-
if (flag === '') {
|
89
|
-
target = target.parentNode;
|
90
|
-
}
|
91
|
-
} while (flag === '');
|
92
|
-
if (flag !== '__stop__' || eventExtra.eventStop) {
|
93
|
-
fn(e, target, flag);
|
94
|
-
}
|
95
|
-
}, eventExtra);
|
96
|
-
}
|
97
|
-
else {
|
98
|
-
element.addEventListener(listener, fn, eventExtra);
|
99
|
-
}
|
100
|
-
}
|
101
|
-
/**
|
102
|
-
* 设置或获取节点的 innerHTML 属性
|
103
|
-
* @param element
|
104
|
-
* @param htmlstr 可选,如果传递该参数,则表示设置;否则表示获取
|
105
|
-
* @returns
|
106
|
-
*/
|
107
|
-
export function html(element, htmlstr) {
|
108
|
-
if (htmlstr == null) {
|
109
|
-
return element.innerHTML;
|
110
|
-
}
|
111
|
-
else {
|
112
|
-
element.innerHTML = htmlstr;
|
113
|
-
return undefined;
|
114
|
-
}
|
115
|
-
}
|
116
|
-
/**
|
117
|
-
* 设置或获取节点的 textContent 属性
|
118
|
-
* @param element
|
119
|
-
* @param textstr 可选,如果传递该参数,则表示设置;否则表示获取
|
120
|
-
* @returns
|
121
|
-
*/
|
122
|
-
export function text(element, textstr) {
|
123
|
-
if (textstr == null) {
|
124
|
-
return element.textContent;
|
125
|
-
}
|
126
|
-
else {
|
127
|
-
element.textContent = textstr;
|
128
|
-
return undefined;
|
129
|
-
}
|
130
|
-
}
|
131
|
-
/**
|
132
|
-
* 节点列表遍历
|
133
|
-
* @param elems
|
134
|
-
* @param fn 遍历到节点时的回调,回调第一个参数为遍历到的节点,第2个参数为 index;如果回调函数返回 true,则会终止遍历(break)
|
135
|
-
*/
|
136
|
-
export function iterate(elems, fn) {
|
137
|
-
for (let i = 0, len = elems.length; i < len; i++) {
|
138
|
-
let r = fn(elems[i], i);
|
139
|
-
if (r === true) {
|
140
|
-
break;
|
141
|
-
}
|
142
|
-
}
|
143
|
-
}
|
144
|
-
/**
|
145
|
-
* 设置或获取节点 data-* 属性
|
146
|
-
* @param elem
|
147
|
-
* @param key data- 后面跟随的值
|
148
|
-
* @param value 如果传递该值表示获取;否则表示设置
|
149
|
-
* @returns
|
150
|
-
*/
|
151
|
-
export function attr(elem, key, value) {
|
152
|
-
if (value != null) {
|
153
|
-
elem.setAttribute('data-' + key, value);
|
154
|
-
}
|
155
|
-
else {
|
156
|
-
return elem.getAttribute('data-' + key);
|
157
|
-
}
|
158
|
-
}
|
159
|
-
/**
|
160
|
-
* 获取指定节点的父节点
|
161
|
-
* @param el
|
162
|
-
* @returns
|
163
|
-
*/
|
164
|
-
export function parent(el) {
|
165
|
-
return el.parentNode;
|
166
|
-
}
|
167
|
-
/**
|
168
|
-
* 获取隐藏节点的尺寸
|
169
|
-
* @param {string | HTMLElement} hideNode - The node to hide.
|
170
|
-
* @param parent - 添加临时节点的父节点,默认为: body.
|
171
|
-
* @returns The DOMRect of the element.
|
172
|
-
*/
|
173
|
-
export function queryHideNodeSize(hideNode, parent = document.body) {
|
174
|
-
// 计算折叠菜单的高度
|
175
|
-
let $tmp = document.createElement('div');
|
176
|
-
$tmp.style.cssText = 'position:fixed;left:-1000px;top:-1000px;opacity:0;';
|
177
|
-
let $tmpInner = document.createElement('div');
|
178
|
-
$tmpInner.style.cssText = 'position:relative;';
|
179
|
-
if (typeof hideNode === 'string') {
|
180
|
-
$tmpInner.innerHTML = hideNode;
|
181
|
-
}
|
182
|
-
else {
|
183
|
-
$tmpInner.appendChild(hideNode.cloneNode(true));
|
184
|
-
}
|
185
|
-
$tmp.appendChild($tmpInner);
|
186
|
-
parent.appendChild($tmp);
|
187
|
-
let rect = $tmpInner.children[0].getBoundingClientRect();
|
188
|
-
parent.removeChild($tmp);
|
189
|
-
return { width: rect.width, height: rect.height };
|
190
|
-
}
|
1
|
+
/**
|
2
|
+
* web(浏览器端) DOM 文件操作
|
3
|
+
* 现今不推荐在使用这种方式,现在开发前端的时候,推荐使用一些成熟的框架例如:React、Preact、Vue、Angular、Svelte、Ember、Knockout等
|
4
|
+
* 在使用这些框架的时候额外的一些不可避免的 dom 操作时才使用这个工具;如果确实需要使用原生开发推荐使用 jquery 或者想要更精简的话可以使用 https://github.com/finom/bala 封装
|
5
|
+
*/
|
6
|
+
const vendorPrefix = ['', '-webkit', '-moz-'];
|
7
|
+
/**
|
8
|
+
* 根据选择器获取节点
|
9
|
+
* @param {string} selector 选择器
|
10
|
+
*/
|
11
|
+
export function elem(selector, dom) {
|
12
|
+
if (typeof selector === 'string') {
|
13
|
+
return (dom || document).querySelectorAll(selector);
|
14
|
+
}
|
15
|
+
else {
|
16
|
+
return [selector];
|
17
|
+
}
|
18
|
+
}
|
19
|
+
/**
|
20
|
+
* 为节点添加 class
|
21
|
+
* @param {HTMLElement} elem 待添加 class 的节点
|
22
|
+
* @param {string} clazz 需要添加的 class
|
23
|
+
*/
|
24
|
+
export function addClass(elem, clazz) {
|
25
|
+
elem.classList.add(clazz);
|
26
|
+
}
|
27
|
+
/**
|
28
|
+
* 节点移除 class
|
29
|
+
* @param {HTMLElement} elem 待移除 class 的节点
|
30
|
+
* @param {string} clazz 需要移除的 class
|
31
|
+
*/
|
32
|
+
export function removeClass(elem, clazz) {
|
33
|
+
elem.classList.remove(clazz);
|
34
|
+
}
|
35
|
+
/**
|
36
|
+
* 判断节点是否包含某个 class
|
37
|
+
* @param elem 待判断 class 的节点
|
38
|
+
* @param clazz 待判断的 class
|
39
|
+
* @returns
|
40
|
+
*/
|
41
|
+
export function hasClass(elem, clazz) {
|
42
|
+
return elem.classList.contains(clazz);
|
43
|
+
}
|
44
|
+
/**
|
45
|
+
* 为节点添加 transition 属性,包括浏览器前缀
|
46
|
+
* @param {HTMLElement} element 需要添加 css Transition 属性的节点
|
47
|
+
* @param {string} value css transition 值
|
48
|
+
*/
|
49
|
+
export function transition(element, value) {
|
50
|
+
vendorPrefix.forEach((prefix) => {
|
51
|
+
let t = prefix === '' ? 'transition' : prefix + 'Transition';
|
52
|
+
element.style[t] = value;
|
53
|
+
});
|
54
|
+
}
|
55
|
+
/**
|
56
|
+
* 为节点添加 transform 属性,包括浏览器前缀
|
57
|
+
* @param {HTMLElement} element 需要添加 css transform 属性的节点
|
58
|
+
* @param {string} value css transform 值
|
59
|
+
*/
|
60
|
+
export function transform(element, value) {
|
61
|
+
vendorPrefix.forEach((prefix) => {
|
62
|
+
let t = prefix === '' ? 'transform' : prefix + 'Transform';
|
63
|
+
element.style[t] = value;
|
64
|
+
});
|
65
|
+
}
|
66
|
+
/**
|
67
|
+
* 为节点添加事件处理
|
68
|
+
* @param {HTMLElement} element 添加事件的节点
|
69
|
+
* @param {string} listener 事件名称
|
70
|
+
* @param {function} event 事件处理函数
|
71
|
+
* @param {boolean} onceOrConfig 是否是只运行一次的处理函数或者配置,其中 eventFlag 为 string,如果配置该项,则表明为委托事件
|
72
|
+
*/
|
73
|
+
export function on(element, listener, fn, once = false) {
|
74
|
+
let eventExtra = { eventStop: false };
|
75
|
+
if (typeof once === 'boolean') {
|
76
|
+
eventExtra.once = once;
|
77
|
+
}
|
78
|
+
else {
|
79
|
+
eventExtra = once;
|
80
|
+
}
|
81
|
+
if (eventExtra.eventFlag != null) {
|
82
|
+
element.setAttribute(eventExtra.eventFlag, '__stop__');
|
83
|
+
element.addEventListener(listener, (e) => {
|
84
|
+
let target = e.target;
|
85
|
+
let flag = '';
|
86
|
+
do {
|
87
|
+
flag = target.getAttribute(eventExtra.eventFlag) || '';
|
88
|
+
if (flag === '') {
|
89
|
+
target = target.parentNode;
|
90
|
+
}
|
91
|
+
} while (flag === '');
|
92
|
+
if (flag !== '__stop__' || eventExtra.eventStop) {
|
93
|
+
fn(e, target, flag);
|
94
|
+
}
|
95
|
+
}, eventExtra);
|
96
|
+
}
|
97
|
+
else {
|
98
|
+
element.addEventListener(listener, fn, eventExtra);
|
99
|
+
}
|
100
|
+
}
|
101
|
+
/**
|
102
|
+
* 设置或获取节点的 innerHTML 属性
|
103
|
+
* @param element
|
104
|
+
* @param htmlstr 可选,如果传递该参数,则表示设置;否则表示获取
|
105
|
+
* @returns
|
106
|
+
*/
|
107
|
+
export function html(element, htmlstr) {
|
108
|
+
if (htmlstr == null) {
|
109
|
+
return element.innerHTML;
|
110
|
+
}
|
111
|
+
else {
|
112
|
+
element.innerHTML = htmlstr;
|
113
|
+
return undefined;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
/**
|
117
|
+
* 设置或获取节点的 textContent 属性
|
118
|
+
* @param element
|
119
|
+
* @param textstr 可选,如果传递该参数,则表示设置;否则表示获取
|
120
|
+
* @returns
|
121
|
+
*/
|
122
|
+
export function text(element, textstr) {
|
123
|
+
if (textstr == null) {
|
124
|
+
return element.textContent;
|
125
|
+
}
|
126
|
+
else {
|
127
|
+
element.textContent = textstr;
|
128
|
+
return undefined;
|
129
|
+
}
|
130
|
+
}
|
131
|
+
/**
|
132
|
+
* 节点列表遍历
|
133
|
+
* @param elems
|
134
|
+
* @param fn 遍历到节点时的回调,回调第一个参数为遍历到的节点,第2个参数为 index;如果回调函数返回 true,则会终止遍历(break)
|
135
|
+
*/
|
136
|
+
export function iterate(elems, fn) {
|
137
|
+
for (let i = 0, len = elems.length; i < len; i++) {
|
138
|
+
let r = fn(elems[i], i);
|
139
|
+
if (r === true) {
|
140
|
+
break;
|
141
|
+
}
|
142
|
+
}
|
143
|
+
}
|
144
|
+
/**
|
145
|
+
* 设置或获取节点 data-* 属性
|
146
|
+
* @param elem
|
147
|
+
* @param key data- 后面跟随的值
|
148
|
+
* @param value 如果传递该值表示获取;否则表示设置
|
149
|
+
* @returns
|
150
|
+
*/
|
151
|
+
export function attr(elem, key, value) {
|
152
|
+
if (value != null) {
|
153
|
+
elem.setAttribute('data-' + key, value);
|
154
|
+
}
|
155
|
+
else {
|
156
|
+
return elem.getAttribute('data-' + key);
|
157
|
+
}
|
158
|
+
}
|
159
|
+
/**
|
160
|
+
* 获取指定节点的父节点
|
161
|
+
* @param el
|
162
|
+
* @returns
|
163
|
+
*/
|
164
|
+
export function parent(el) {
|
165
|
+
return el.parentNode;
|
166
|
+
}
|
167
|
+
/**
|
168
|
+
* 获取隐藏节点的尺寸
|
169
|
+
* @param {string | HTMLElement} hideNode - The node to hide.
|
170
|
+
* @param parent - 添加临时节点的父节点,默认为: body.
|
171
|
+
* @returns The DOMRect of the element.
|
172
|
+
*/
|
173
|
+
export function queryHideNodeSize(hideNode, parent = document.body) {
|
174
|
+
// 计算折叠菜单的高度
|
175
|
+
let $tmp = document.createElement('div');
|
176
|
+
$tmp.style.cssText = 'position:fixed;left:-1000px;top:-1000px;opacity:0;';
|
177
|
+
let $tmpInner = document.createElement('div');
|
178
|
+
$tmpInner.style.cssText = 'position:relative;';
|
179
|
+
if (typeof hideNode === 'string') {
|
180
|
+
$tmpInner.innerHTML = hideNode;
|
181
|
+
}
|
182
|
+
else {
|
183
|
+
$tmpInner.appendChild(hideNode.cloneNode(true));
|
184
|
+
}
|
185
|
+
$tmp.appendChild($tmpInner);
|
186
|
+
parent.appendChild($tmp);
|
187
|
+
let rect = $tmpInner.children[0].getBoundingClientRect();
|
188
|
+
parent.removeChild($tmp);
|
189
|
+
return { width: rect.width, height: rect.height };
|
190
|
+
}
|
package/lib/file.d.ts
CHANGED
@@ -1,34 +1,31 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
statTag(filePath: string): Promise<string>;
|
33
|
-
};
|
34
|
-
export = _default;
|
1
|
+
/**
|
2
|
+
* 读取文件内容为JSON格式
|
3
|
+
* @param filepath 读取的文件路径
|
4
|
+
* @returns Promise<unknown>
|
5
|
+
*/
|
6
|
+
export declare function readJSON<T>(filepath: string): Promise<T>;
|
7
|
+
/**
|
8
|
+
* 写入 JSON 格式的数据到文件
|
9
|
+
* @param file 待写入的文件
|
10
|
+
* @param data 待写入的数据
|
11
|
+
* @param opts 写入配置
|
12
|
+
* @property opts.json 是否写入 JSON 格式的数据,写入数据时对数据进行 JSON 格式化,默认为:true
|
13
|
+
* @property opts.format 是否在写入 json 数据时,将 JSON 数据格式化2个空格写入, 默认为 true
|
14
|
+
*/
|
15
|
+
export declare function write(file: string, data: any, opts?: {
|
16
|
+
json: boolean;
|
17
|
+
format: boolean;
|
18
|
+
}): Promise<unknown>;
|
19
|
+
/**
|
20
|
+
* 遍历文件夹
|
21
|
+
* @param dir 待遍历的目录
|
22
|
+
* @param callback 遍历到文件后的回调
|
23
|
+
* @param done 遍历完成后的回调
|
24
|
+
*/
|
25
|
+
export declare function traverseDir(dir: string, callback?: (filename: string) => void, done?: () => void): void;
|
26
|
+
/**
|
27
|
+
* 根据文件的 stat 获取文件的 etag
|
28
|
+
* @param filePath 文件地址
|
29
|
+
* @returns file stat etag
|
30
|
+
*/
|
31
|
+
export declare function statTag(filePath: string): Promise<string>;
|
package/lib/file.js
CHANGED
@@ -1,99 +1,96 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
if (
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
return `${stat.size.toString(16)}-${stat.mtimeMs.toString(16)}`;
|
98
|
-
},
|
99
|
-
};
|
1
|
+
/** nodejs 文件操作工具类 */
|
2
|
+
import path from 'node:path';
|
3
|
+
import fs from 'node:fs';
|
4
|
+
/**
|
5
|
+
* 读取文件内容为JSON格式
|
6
|
+
* @param filepath 读取的文件路径
|
7
|
+
* @returns Promise<unknown>
|
8
|
+
*/
|
9
|
+
export function readJSON(filepath) {
|
10
|
+
return new Promise((resolve, reject) => {
|
11
|
+
fs.readFile(path.resolve(filepath), 'utf-8', (err, data) => {
|
12
|
+
if (err) {
|
13
|
+
reject(err);
|
14
|
+
}
|
15
|
+
else {
|
16
|
+
resolve(JSON.parse(data));
|
17
|
+
}
|
18
|
+
});
|
19
|
+
});
|
20
|
+
}
|
21
|
+
/**
|
22
|
+
* 写入 JSON 格式的数据到文件
|
23
|
+
* @param file 待写入的文件
|
24
|
+
* @param data 待写入的数据
|
25
|
+
* @param opts 写入配置
|
26
|
+
* @property opts.json 是否写入 JSON 格式的数据,写入数据时对数据进行 JSON 格式化,默认为:true
|
27
|
+
* @property opts.format 是否在写入 json 数据时,将 JSON 数据格式化2个空格写入, 默认为 true
|
28
|
+
*/
|
29
|
+
export function write(file, data, opts) {
|
30
|
+
return new Promise((resolve, reject) => {
|
31
|
+
let writeData = data.toString();
|
32
|
+
opts = { json: true, format: true, ...(opts || {}) };
|
33
|
+
if (opts.json === true && typeof data === 'object') {
|
34
|
+
writeData = JSON.stringify(data, null, opts.format === true ? 2 : 0);
|
35
|
+
}
|
36
|
+
fs.writeFile(path.resolve(file), writeData, (err) => {
|
37
|
+
if (err) {
|
38
|
+
reject(err);
|
39
|
+
}
|
40
|
+
else {
|
41
|
+
resolve(0);
|
42
|
+
}
|
43
|
+
});
|
44
|
+
});
|
45
|
+
}
|
46
|
+
/**
|
47
|
+
* 遍历文件夹
|
48
|
+
* @param dir 待遍历的目录
|
49
|
+
* @param callback 遍历到文件后的回调
|
50
|
+
* @param done 遍历完成后的回调
|
51
|
+
*/
|
52
|
+
export function traverseDir(dir, callback, done) {
|
53
|
+
let t = -1; // 定时任务,简单延迟作为遍历完成计算
|
54
|
+
function list(dr, cb, d) {
|
55
|
+
fs.readdir(path.resolve(dr), { withFileTypes: true }, (err, files) => {
|
56
|
+
if (err && err.errno === -4052) {
|
57
|
+
// 本身就是文件
|
58
|
+
if (typeof cb === 'function')
|
59
|
+
cb(dr);
|
60
|
+
if (typeof d === 'function')
|
61
|
+
d(); // 遍历完成
|
62
|
+
}
|
63
|
+
else {
|
64
|
+
for (let i = 0, len = files.length; i < len; i++) {
|
65
|
+
const file = files[i];
|
66
|
+
if (file.isFile()) {
|
67
|
+
if (typeof cb === 'function')
|
68
|
+
cb(path.join(dr, file.name));
|
69
|
+
clearTimeout(t);
|
70
|
+
t = setTimeout(() => {
|
71
|
+
setImmediate(() => {
|
72
|
+
if (typeof done === 'function') {
|
73
|
+
done();
|
74
|
+
}
|
75
|
+
});
|
76
|
+
}, 10);
|
77
|
+
}
|
78
|
+
else {
|
79
|
+
// 文件夹
|
80
|
+
list(path.join(dr, file.name), cb, d);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
});
|
85
|
+
}
|
86
|
+
list(dir, callback, done);
|
87
|
+
}
|
88
|
+
/**
|
89
|
+
* 根据文件的 stat 获取文件的 etag
|
90
|
+
* @param filePath 文件地址
|
91
|
+
* @returns file stat etag
|
92
|
+
*/
|
93
|
+
export async function statTag(filePath) {
|
94
|
+
let stat = await fs.promises.stat(filePath);
|
95
|
+
return `${stat.size.toString(16)}-${stat.mtimeMs.toString(16)}`;
|
96
|
+
}
|