ph-utils 0.4.6 → 0.4.8

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/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` 颜色相关工具
package/lib/index.d.ts CHANGED
@@ -50,6 +50,13 @@ interface RandomConfig {
50
50
  * 1. 生成指定长度的随机数
51
51
  * 2. 生成介于 [min, max] 之间的随机数
52
52
  * @param opts 生成随机数的配置
53
+ *
54
+ * @example <caption>1. 生成指定长度的随机字符串</caption>
55
+ * random(1); // 长度为 1 的随机字符串
56
+ *
57
+ * @example <caption>2. 生成纯数字且不能为0长度为1的随机字符</caption>
58
+ * random({ length: 1, hasLetter: false, firstIsZero: false })
59
+ *
53
60
  * @returns
54
61
  */
55
62
  export declare function random(opts: number | RandomConfig): string | number;
package/lib/index.js CHANGED
@@ -58,6 +58,13 @@ export function isBoolean(str) {
58
58
  * 1. 生成指定长度的随机数
59
59
  * 2. 生成介于 [min, max] 之间的随机数
60
60
  * @param opts 生成随机数的配置
61
+ *
62
+ * @example <caption>1. 生成指定长度的随机字符串</caption>
63
+ * random(1); // 长度为 1 的随机字符串
64
+ *
65
+ * @example <caption>2. 生成纯数字且不能为0长度为1的随机字符</caption>
66
+ * random({ length: 1, hasLetter: false, firstIsZero: false })
67
+ *
61
68
  * @returns
62
69
  */
63
70
  export function random(opts) {
@@ -74,12 +81,11 @@ export function random(opts) {
74
81
  }
75
82
  const len = typeof opts === "object" ? opts.length : opts;
76
83
  /* 生成指定长度的随机数 */
77
- const charLens = RANDOM_CHARS.length;
78
84
  let chars = RANDOM_CHARS;
79
85
  if (typeof opts === "object" && opts.hasLetter === false) {
80
86
  chars = NUMBER_RANDOM_CHARTS;
81
87
  }
82
- const resRandom = Array.from({ length: len }, () => chars.charAt(Math.floor(Math.random() * charLens))).join("");
88
+ const resRandom = Array.from({ length: len }, () => chars.charAt(random({ min: 0, max: 9, hasEnd: true }))).join("");
83
89
  if (typeof opts === "object" &&
84
90
  opts.firstIsZero === false &&
85
91
  resRandom.indexOf("0") === 0) {
@@ -2,7 +2,7 @@
2
2
  * 数据验证器
3
3
  */
4
4
  interface RuleItem {
5
- rule: RegExp | ((v: any) => boolean) | 'required';
5
+ rule: RegExp | ((v: any) => boolean) | "required";
6
6
  message: string;
7
7
  sameKey?: string;
8
8
  }
@@ -18,7 +18,7 @@ export interface SchemaType {
18
18
  message?: string;
19
19
  }
20
20
  /**
21
- * 数据验证器,除了进行数据验证外,还可以同时进行数据转化
21
+ * 数据验证器
22
22
  */
23
23
  declare class Validator {
24
24
  rules: {
@@ -40,7 +40,10 @@ declare class Validator {
40
40
  * @param key 指定待验证的 key
41
41
  * @param value 待验证的数据
42
42
  */
43
- validateKey(key: string, value: any, data?: any): Promise<boolean>;
43
+ validateKey(key: string, value: any, data?: any): Promise<{
44
+ key: string;
45
+ value: any;
46
+ }>;
44
47
  private _validateRule;
45
48
  private _parseStringRule;
46
49
  }
package/lib/validator.js CHANGED
@@ -3,17 +3,17 @@
3
3
  */
4
4
  // 默认的错误提示信息
5
5
  const defaultMsgs = {
6
- mobile: '请输入正确的手机号',
7
- same: '两次输入不一致',
8
- required: '%s为必填字段',
6
+ mobile: "请输入正确的手机号",
7
+ same: "两次输入不一致",
8
+ required: "%s为必填字段",
9
9
  };
10
- const defaultMsg = '请输入正确的数据';
10
+ const defaultMsg = "请输入正确的数据";
11
11
  // 一些常用的验证正则
12
12
  const ruleRegexs = {
13
13
  /** 验证跟其余数据相等的正则,一般用于验证再次输入密码 */
14
14
  same: /^same:(.+)$/i,
15
15
  /** 验证手机号的正则表达式 */
16
- mobile: /^1[34578]\d{9}$/,
16
+ mobile: /^1[345678]\d{9}$/,
17
17
  /** 非空验证的正则表达式 */
18
18
  required: /^\S{1}.*/,
19
19
  };
@@ -36,12 +36,12 @@ class ValidateError extends Error {
36
36
  key;
37
37
  constructor(key, msg) {
38
38
  super(msg);
39
- this.name = 'ValidateError';
39
+ this.name = "ValidateError";
40
40
  this.key = key;
41
41
  }
42
42
  }
43
43
  /**
44
- * 数据验证器,除了进行数据验证外,还可以同时进行数据转化
44
+ * 数据验证器
45
45
  */
46
46
  class Validator {
47
47
  rules;
@@ -56,22 +56,23 @@ class Validator {
56
56
  let rules = [];
57
57
  let rule = schema.rules;
58
58
  if (rule != null) {
59
- if (typeof rule === 'string') {
59
+ if (typeof rule === "string") {
60
60
  rules = rules.concat(this._parseStringRule(rule, schema.message));
61
61
  }
62
62
  else if (rule instanceof Array) {
63
63
  for (let ruleItem of rule) {
64
- if (typeof ruleItem === 'string') {
64
+ if (typeof ruleItem === "string") {
65
65
  rules.push(...this._parseStringRule(ruleItem, schema.message));
66
66
  }
67
- else if (ruleItem instanceof RegExp || typeof ruleItem === 'function') {
67
+ else if (ruleItem instanceof RegExp ||
68
+ typeof ruleItem === "function") {
68
69
  rules.push({
69
70
  rule: ruleItem,
70
71
  message: schema.message || defaultMsg,
71
72
  });
72
73
  }
73
74
  else {
74
- if (typeof ruleItem.rule === 'string') {
75
+ if (typeof ruleItem.rule === "string") {
75
76
  rules.push(...this._parseStringRule(ruleItem.rule, ruleItem.message));
76
77
  }
77
78
  else {
@@ -87,8 +88,9 @@ class Validator {
87
88
  rules.push({ rule, message: defaultMsg });
88
89
  }
89
90
  }
90
- if (schema.required === true && (rules == null || rules.findIndex((r) => r.rule === 'required') === -1)) {
91
- rules.push(...this._parseStringRule('required', schema.message));
91
+ if (schema.required === true &&
92
+ (rules == null || rules.findIndex((r) => r.rule === "required") === -1)) {
93
+ rules.push(...this._parseStringRule("required", schema.message));
92
94
  }
93
95
  parsedRules[schema.key] = rules;
94
96
  }
@@ -99,57 +101,54 @@ class Validator {
99
101
  * @param data 待验证的数据
100
102
  * @returns
101
103
  */
102
- validate(data) {
103
- return new Promise((resolve, reject) => {
104
- let errMsg = '';
105
- let errKey = '';
106
- for (let key in this.rules) {
107
- // eslint-disable-next-line no-prototype-builtins
108
- if (this.rules.hasOwnProperty(key)) {
109
- errMsg = this._validateRule(this.rules[key], data[key], data);
110
- if (errMsg !== '') {
111
- errKey = key;
112
- errMsg = errMsg.replace('%s', key);
113
- break;
114
- }
104
+ async validate(data) {
105
+ let errMsg = "";
106
+ let errKey = "";
107
+ for (let key in this.rules) {
108
+ // eslint-disable-next-line no-prototype-builtins
109
+ if (this.rules.hasOwnProperty(key)) {
110
+ errMsg = this._validateRule(this.rules[key], data[key], data);
111
+ if (errMsg !== "") {
112
+ errKey = key;
113
+ errMsg = errMsg.replace("%s", key);
114
+ break;
115
115
  }
116
116
  }
117
- if (errMsg === '') {
118
- resolve(true);
119
- }
120
- else {
121
- reject(new ValidateError(errKey, errMsg));
122
- }
123
- });
117
+ }
118
+ if (errMsg === "") {
119
+ return true;
120
+ }
121
+ else {
122
+ throw new ValidateError(errKey, errMsg);
123
+ }
124
124
  }
125
125
  /**
126
126
  * 只验证指定 key 的数据格式
127
127
  * @param key 指定待验证的 key
128
128
  * @param value 待验证的数据
129
129
  */
130
- validateKey(key, value, data) {
131
- return new Promise((resolve, reject) => {
132
- let keyRules = this.rules[key];
133
- let errMsg = this._validateRule(keyRules, value, data);
134
- if (errMsg !== '') {
135
- errMsg = errMsg.replace('%s', key);
136
- reject(new ValidateError(key, errMsg));
137
- }
138
- else {
139
- resolve(true);
140
- }
141
- });
130
+ async validateKey(key, value, data) {
131
+ let keyRules = this.rules[key];
132
+ let errMsg = this._validateRule(keyRules, value, data);
133
+ if (errMsg !== "") {
134
+ errMsg = errMsg.replace("%s", key);
135
+ throw new ValidateError(key, errMsg);
136
+ }
137
+ else {
138
+ return { key, value };
139
+ }
142
140
  }
143
141
  _validateRule(rules, value, data) {
144
- let errMsg = '';
142
+ this.validateKey("", 1).catch((err) => { });
143
+ let errMsg = "";
145
144
  for (let rule of rules) {
146
145
  // 如果数据为空,则判断是否是必填
147
- if (rule.rule === 'required') {
146
+ if (rule.rule === "required") {
148
147
  if (value == null || !ruleFns.pattern(ruleRegexs.required, value)) {
149
148
  errMsg = rule.message;
150
149
  }
151
150
  }
152
- if (typeof rule.rule === 'function') {
151
+ if (typeof rule.rule === "function") {
153
152
  if (!rule.rule(value)) {
154
153
  errMsg = rule.message;
155
154
  }
@@ -161,7 +160,7 @@ class Validator {
161
160
  }
162
161
  }
163
162
  }
164
- else if (rule.rule === 'required') {
163
+ else if (rule.rule === "required") {
165
164
  if (!ruleFns.pattern(ruleRegexs.required, String(value))) {
166
165
  errMsg = rule.message;
167
166
  }
@@ -171,7 +170,7 @@ class Validator {
171
170
  errMsg = rule.message;
172
171
  }
173
172
  }
174
- if (errMsg !== '') {
173
+ if (errMsg !== "") {
175
174
  break;
176
175
  }
177
176
  }
@@ -179,7 +178,7 @@ class Validator {
179
178
  }
180
179
  _parseStringRule(rule, ruleErrMsg) {
181
180
  let rules = [];
182
- let trule = rule.split('|');
181
+ let trule = rule.split("|");
183
182
  for (let r of trule) {
184
183
  let message = ruleErrMsg;
185
184
  let rrule = null;
@@ -192,11 +191,11 @@ class Validator {
192
191
  if (m != null) {
193
192
  sameKey = m[1];
194
193
  }
195
- message = message || defaultMsgs['same'];
194
+ message = message || defaultMsgs["same"];
196
195
  }
197
196
  }
198
- else if (rule === 'required') {
199
- rrule = 'required';
197
+ else if (rule === "required") {
198
+ rrule = "required";
200
199
  message = message || ruleErrMsg || defaultMsgs.required;
201
200
  // eslint-disable-next-line no-prototype-builtins
202
201
  }
package/package.json CHANGED
@@ -52,7 +52,7 @@
52
52
  },
53
53
  "./*": "./lib/*"
54
54
  },
55
- "version": "0.4.6",
55
+ "version": "0.4.8",
56
56
  "type": "module",
57
57
  "repository": {
58
58
  "type": "git",
@@ -1,11 +0,0 @@
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>;
package/lib/clipboard.js DELETED
@@ -1,101 +0,0 @@
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
- }