sculp-js 0.0.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.
@@ -0,0 +1,82 @@
1
+ /*!
2
+ * sculp-js v0.0.1
3
+ * (c) 2023-2023 chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ var url = require('./url.js');
10
+
11
+ /**
12
+ * 通过打开新窗口的方式下载
13
+ * @param {string} url
14
+ * @param {LooseParams} params
15
+ */
16
+ const downloadURL = (url$1, params) => {
17
+ window.open(params ? url.urlSetParams(url$1, params) : url$1);
18
+ };
19
+ /**
20
+ * 通过 A 链接的方式下载
21
+ * @param {string} href
22
+ * @param {string} filename
23
+ */
24
+ const downloadHref = (href, filename) => {
25
+ const eleLink = document.createElement('a');
26
+ eleLink.download = filename;
27
+ eleLink.style.display = 'none';
28
+ eleLink.href = href;
29
+ document.body.appendChild(eleLink);
30
+ eleLink.click();
31
+ setTimeout(() => document.body.removeChild(eleLink));
32
+ };
33
+ /**
34
+ * 将大文件对象通过 A 链接的方式下载
35
+ * @param {Blob} blob
36
+ * @param {string} filename
37
+ */
38
+ const downloadBlob = (blob, filename) => {
39
+ const objURL = URL.createObjectURL(blob);
40
+ downloadHref(objURL, filename);
41
+ setTimeout(() => URL.revokeObjectURL(objURL));
42
+ };
43
+ /**
44
+ * 将指定数据格式通过 A 链接的方式下载
45
+ * @param {AnyObject | AnyObject[]} data
46
+ * @param {FileType} fileType 支持 json/csv/xls/xlsx 四种格式
47
+ * @param {string} filename
48
+ * @param {string[]} [headers]
49
+ */
50
+ const downloadData = (data, fileType, filename, headers) => {
51
+ filename = filename.replace(`.${fileType}`, '') + `.${fileType}`;
52
+ if (fileType === 'json') {
53
+ const blob = new Blob([JSON.stringify(data, null, 4)]);
54
+ downloadBlob(blob, filename);
55
+ }
56
+ else {
57
+ // xlsx实际生成的也为csv,仅后缀名名不同
58
+ if (!headers || !headers.length)
59
+ throw new Error('未传入表头数据');
60
+ if (!Array.isArray(data))
61
+ throw new Error('data error! expected array!');
62
+ const headerStr = headers.join(',') + '\n';
63
+ let bodyStr = '';
64
+ data.forEach(row => {
65
+ // \t防止数字被科学计数法显示
66
+ bodyStr += Object.values(row).join(',\t') + ',\n';
67
+ });
68
+ const MIMETypes = {
69
+ csv: 'text/csv',
70
+ xls: 'application/vnd.ms-excel',
71
+ xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
72
+ };
73
+ // encodeURIComponent解决中文乱码
74
+ const href = 'data:' + MIMETypes[fileType] + ';charset=utf-8,\ufeff' + encodeURIComponent(headerStr + bodyStr);
75
+ downloadHref(href, filename);
76
+ }
77
+ };
78
+
79
+ exports.downloadBlob = downloadBlob;
80
+ exports.downloadData = downloadData;
81
+ exports.downloadHref = downloadHref;
82
+ exports.downloadURL = downloadURL;
@@ -0,0 +1,40 @@
1
+ /*!
2
+ * sculp-js v0.0.1
3
+ * (c) 2023-2023 chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ var bezier = require('bezier-easing');
10
+ var type = require('./type.js');
11
+
12
+ // @ref https://cubic-bezier.com/
13
+ const easingDefines = {
14
+ linear: [0, 0, 1, 1],
15
+ ease: [0.25, 0.1, 0.25, 1],
16
+ 'ease-in': [0.42, 0, 1, 1],
17
+ 'ease-out': [0, 0, 0.58, 1],
18
+ 'ease-in-out': [0.42, 0, 0.58, 1]
19
+ };
20
+ /**
21
+ * 缓冲函数化,用于 js 计算缓冲进度
22
+ * @param {EasingNameOrDefine} [name=linear]
23
+ * @returns {EasingFunction}
24
+ */
25
+ function easingFunctional(name) {
26
+ let fn;
27
+ if (type.isArray(name)) {
28
+ fn = bezier(...name);
29
+ }
30
+ else {
31
+ const define = easingDefines[name];
32
+ if (!define) {
33
+ throw new Error(`${name} 缓冲函数未定义`);
34
+ }
35
+ fn = bezier(...define);
36
+ }
37
+ return (input) => fn(Math.max(0, Math.min(input, 1)));
38
+ }
39
+
40
+ exports.easingFunctional = easingFunctional;
@@ -0,0 +1,30 @@
1
+ /*!
2
+ * sculp-js v0.0.1
3
+ * (c) 2023-2023 chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ /**
10
+ * 选择本地文件
11
+ * @param {function} changeCb 选择文件回调
12
+ * @return {*}
13
+ */
14
+ function chooseLocalFile({ accept }, changeCb) {
15
+ const inputObj = document.createElement('input');
16
+ inputObj.setAttribute('id', String(Date.now()));
17
+ inputObj.setAttribute('type', 'file');
18
+ inputObj.setAttribute('style', 'visibility:hidden');
19
+ inputObj.setAttribute('accept', accept);
20
+ document.body.appendChild(inputObj);
21
+ inputObj.click();
22
+ // @ts-ignore
23
+ inputObj.onchange = (e) => {
24
+ changeCb(e.target.files);
25
+ setTimeout(() => document.body.removeChild(inputObj));
26
+ };
27
+ return inputObj;
28
+ }
29
+
30
+ exports.chooseLocalFile = chooseLocalFile;
@@ -0,0 +1,41 @@
1
+ /*!
2
+ * sculp-js v0.0.1
3
+ * (c) 2023-2023 chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ var array = require('./array.js');
10
+ var clipboard = require('./clipboard.js');
11
+ var cookie = require('./cookie.js');
12
+ var date = require('./date.js');
13
+ var dom = require('./dom.js');
14
+ var download = require('./download.js');
15
+ var object = require('./object.js');
16
+ var path = require('./path.js');
17
+ var qs = require('./qs.js');
18
+ var string = require('./string.js');
19
+ var type = require('./type.js');
20
+ var url = require('./url.js');
21
+ var async = require('./async.js');
22
+ var file = require('./file.js');
23
+ var watermark = require('./watermark.js');
24
+
25
+
26
+
27
+ exports.array = array;
28
+ exports.clipboard = clipboard;
29
+ exports.cookie = cookie;
30
+ exports.date = date;
31
+ exports.dom = dom;
32
+ exports.download = download;
33
+ exports.object = object;
34
+ exports.path = path;
35
+ exports.qs = qs;
36
+ exports.string = string;
37
+ exports.type = type;
38
+ exports.url = url;
39
+ exports.async = async;
40
+ exports.file = file;
41
+ exports.genCanvasWM = watermark.genCanvasWM;
@@ -0,0 +1,241 @@
1
+ /*!
2
+ * sculp-js v0.0.1
3
+ * (c) 2023-2023 chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ var type = require('./type.js');
10
+
11
+ /**
12
+ * 判断对象是否为纯对象
13
+ * @param {object} obj
14
+ * @returns {boolean}
15
+ */
16
+ const isPlainObject = (obj) => {
17
+ if (!type.isObject(obj))
18
+ return false;
19
+ const proto = Object.getPrototypeOf(obj);
20
+ // 对象无原型
21
+ if (!proto)
22
+ return true;
23
+ // 是否对象直接实例
24
+ return proto === Object.prototype;
25
+ };
26
+ /**
27
+ * 判断对象内是否有该静态属性
28
+ * @param {object} obj
29
+ * @param {string} key
30
+ * @returns {boolean}
31
+ */
32
+ const objectHas = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
33
+ /**
34
+ * 遍历对象,返回 false 中断遍历
35
+ * @param {O} obj
36
+ * @param {(val: O[keyof O], key: keyof O) => (boolean | void)} iterator
37
+ */
38
+ const objectEach = (obj, iterator) => {
39
+ for (const key in obj) {
40
+ if (!objectHas(obj, key))
41
+ continue;
42
+ if (iterator(obj[key], key) === false)
43
+ break;
44
+ }
45
+ };
46
+ /**
47
+ * 异步遍历对象,返回 false 中断遍历
48
+ * @param {O} obj
49
+ * @param {(val: O[keyof O], key: keyof O) => (boolean | void)} iterator
50
+ */
51
+ async function objectEachAsync(obj, iterator) {
52
+ for (const key in obj) {
53
+ if (!objectHas(obj, key))
54
+ continue;
55
+ if ((await iterator(obj[key], key)) === false)
56
+ break;
57
+ }
58
+ }
59
+ /**
60
+ * 对象映射
61
+ * @param {O} obj
62
+ * @param {(val: O[keyof O], key: Extract<keyof O, string>) => any} iterator
63
+ * @returns {Record<Extract<keyof O, string>, T>}
64
+ */
65
+ function objectMap(obj, iterator) {
66
+ const obj2 = {};
67
+ for (const key in obj) {
68
+ if (!objectHas(obj, key))
69
+ continue;
70
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
71
+ obj2[key] = iterator(obj[key], key);
72
+ }
73
+ return obj2;
74
+ }
75
+ /**
76
+ * 对象提取
77
+ * @param {O} obj
78
+ * @param {K} keys
79
+ * @returns {Pick<O, ArrayElements<K>>}
80
+ */
81
+ function objectPick(obj, keys) {
82
+ const obj2 = {};
83
+ objectEach(obj, (v, k) => {
84
+ if (keys.includes(k)) {
85
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
86
+ // @ts-ignore
87
+ obj2[k] = v;
88
+ }
89
+ });
90
+ return obj2;
91
+ }
92
+ /**
93
+ * 对象祛除
94
+ * @param {O} obj
95
+ * @param {K} keys
96
+ * @returns {Pick<O, ArrayElements<K>>}
97
+ */
98
+ function objectOmit(obj, keys) {
99
+ const obj2 = {};
100
+ objectEach(obj, (v, k) => {
101
+ if (!keys.includes(k)) {
102
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
103
+ // @ts-ignore
104
+ obj2[k] = v;
105
+ }
106
+ });
107
+ return obj2;
108
+ }
109
+ const merge = (map, source, target) => {
110
+ if (type.isUndefined(target))
111
+ return source;
112
+ const sourceType = type.default(source);
113
+ const targetType = type.default(target);
114
+ if (sourceType !== targetType) {
115
+ if (type.isArray(target))
116
+ return merge(map, [], target);
117
+ if (type.isObject(target))
118
+ return merge(map, {}, target);
119
+ return target;
120
+ }
121
+ // 朴素对象
122
+ if (isPlainObject(target)) {
123
+ const exist = map.get(target);
124
+ if (exist)
125
+ return exist;
126
+ map.set(target, source);
127
+ objectEach(target, (val, key) => {
128
+ source[key] = merge(map, source[key], val);
129
+ });
130
+ return source;
131
+ }
132
+ // 数组
133
+ else if (type.isArray(target)) {
134
+ const exist = map.get(target);
135
+ if (exist)
136
+ return exist;
137
+ map.set(target, source);
138
+ target.forEach((val, index) => {
139
+ source[index] = merge(map, source[index], val);
140
+ });
141
+ return source;
142
+ }
143
+ return target;
144
+ };
145
+ /**
146
+ * 对象合并,返回原始对象
147
+ * @param {ObjectAssignItem} source
148
+ * @param {ObjectAssignItem | undefined} targets
149
+ * @returns {R}
150
+ */
151
+ const objectAssign = (source, ...targets) => {
152
+ const map = new Map();
153
+ for (let i = 0; i < targets.length; i++) {
154
+ const target = targets[i];
155
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
156
+ // @ts-ignore
157
+ source = merge(map, source, target);
158
+ }
159
+ map.clear();
160
+ return source;
161
+ };
162
+ /**
163
+ * 对象填充
164
+ * @param {Partial<R>} source
165
+ * @param {Partial<R>} target
166
+ * @param {(s: Partial<R>, t: Partial<R>, key: keyof R) => boolean} fillable
167
+ * @returns {R}
168
+ */
169
+ const objectFill = (source, target, fillable) => {
170
+ const _fillable = fillable || ((source, target, key) => source[key] === undefined);
171
+ objectEach(target, (val, key) => {
172
+ if (_fillable(source, target, key)) {
173
+ source[key] = val;
174
+ }
175
+ });
176
+ return source;
177
+ };
178
+ function objectGet(obj, path, strict = false) {
179
+ path = path.replace(/\[(\w+)\]/g, '.$1');
180
+ path = path.replace(/^\./, '');
181
+ const keyArr = path.split('.');
182
+ let tempObj = obj;
183
+ let i = 0;
184
+ for (let len = keyArr.length; i < len - 1; ++i) {
185
+ const key = keyArr[i];
186
+ if (key in tempObj) {
187
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment
188
+ tempObj = tempObj[key];
189
+ }
190
+ else {
191
+ tempObj = undefined;
192
+ if (strict) {
193
+ throw new Error('[berry/js-utils/object] objectGet path 路径不正确');
194
+ }
195
+ break;
196
+ }
197
+ }
198
+ return {
199
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
200
+ p: tempObj,
201
+ k: tempObj ? keyArr[i] : undefined,
202
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment
203
+ v: tempObj ? tempObj[keyArr[i]] : undefined
204
+ };
205
+ }
206
+ /**
207
+ * 深拷贝堪称完全体 即:任何类型的数据都会被深拷贝
208
+ * @param {AnyObject | AnyArray} obj
209
+ * @param {WeakMap} map
210
+ * @return {AnyObject | AnyArray}
211
+ */
212
+ function cloneDeep(obj, map = new WeakMap()) {
213
+ if (obj instanceof Date)
214
+ return new Date(obj);
215
+ if (obj instanceof RegExp)
216
+ return new RegExp(obj);
217
+ if (map.has(obj)) {
218
+ return map.get(obj);
219
+ }
220
+ const allDesc = Object.getOwnPropertyDescriptors(obj);
221
+ const cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc);
222
+ map.set(obj, cloneObj);
223
+ for (const key of Reflect.ownKeys(obj)) {
224
+ const value = obj[key];
225
+ cloneObj[key] = value instanceof Object && typeof value !== 'function' ? cloneDeep(value, map) : value;
226
+ }
227
+ return cloneObj;
228
+ }
229
+
230
+ exports.cloneDeep = cloneDeep;
231
+ exports.isPlainObject = isPlainObject;
232
+ exports.objectAssign = objectAssign;
233
+ exports.objectEach = objectEach;
234
+ exports.objectEachAsync = objectEachAsync;
235
+ exports.objectFill = objectFill;
236
+ exports.objectGet = objectGet;
237
+ exports.objectHas = objectHas;
238
+ exports.objectMap = objectMap;
239
+ exports.objectMerge = objectAssign;
240
+ exports.objectOmit = objectOmit;
241
+ exports.objectPick = objectPick;
@@ -0,0 +1,66 @@
1
+ /*!
2
+ * sculp-js v0.0.1
3
+ * (c) 2023-2023 chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ /**
10
+ * 标准化路径
11
+ * @param {string} path
12
+ * @returns {string}
13
+ */
14
+ const pathNormalize = (path) => {
15
+ const slicees = path
16
+ .replace(/\\/g, '/')
17
+ .replace(/\/{2,}/g, '/')
18
+ .replace(/\.{3,}/g, '..')
19
+ .replace(/\/\.\//g, '/')
20
+ .split('/')
21
+ .map(point => point.trim());
22
+ const isCurrentSlice = (slice) => slice === '.';
23
+ const isParentSlice = (slice) => slice === '..';
24
+ const points = [];
25
+ let inPoints = false;
26
+ const push = (point) => {
27
+ points.push(point);
28
+ };
29
+ const back = () => {
30
+ if (points.length === 0)
31
+ return;
32
+ const lastSlice = points[points.length - 1];
33
+ if (isParentSlice(lastSlice)) {
34
+ points.push('..');
35
+ }
36
+ else {
37
+ points.pop();
38
+ }
39
+ };
40
+ slicees.forEach(slice => {
41
+ const isCurrent = isCurrentSlice(slice);
42
+ const isParent = isParentSlice(slice);
43
+ // 未进入实际路径
44
+ if (!inPoints) {
45
+ push(slice);
46
+ inPoints = !isCurrent && !isParent;
47
+ return;
48
+ }
49
+ if (isCurrent)
50
+ return;
51
+ if (isParent)
52
+ return back();
53
+ push(slice);
54
+ });
55
+ return points.join('/');
56
+ };
57
+ /**
58
+ * 路径合并
59
+ * @param {string} from
60
+ * @param {string} to
61
+ * @returns {string}
62
+ */
63
+ const pathJoin = (from, ...to) => pathNormalize([from, ...to].join('/'));
64
+
65
+ exports.pathJoin = pathJoin;
66
+ exports.pathNormalize = pathNormalize;
package/lib/cjs/qs.js ADDED
@@ -0,0 +1,71 @@
1
+ /*!
2
+ * sculp-js v0.0.1
3
+ * (c) 2023-2023 chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ var object = require('./object.js');
10
+ var type = require('./type.js');
11
+
12
+ /**
13
+ * 解析查询参数,内部使用的是浏览器内置的 URLSearchParams 进行处理
14
+ * @param {string} queryString
15
+ * @returns {Params}
16
+ */
17
+ const qsParse = (queryString) => {
18
+ const params = new URLSearchParams(queryString);
19
+ const result = {};
20
+ for (const [key, val] of params.entries()) {
21
+ if (type.isUndefined(result[key])) {
22
+ result[key] = val;
23
+ continue;
24
+ }
25
+ if (type.isArray(result[key])) {
26
+ continue;
27
+ }
28
+ result[key] = params.getAll(key);
29
+ }
30
+ return result;
31
+ };
32
+ const defaultReplacer = (val) => {
33
+ if (type.isString(val))
34
+ return val;
35
+ if (type.isNumber(val))
36
+ return String(val);
37
+ if (type.isBoolean(val))
38
+ return val ? 'true' : 'false';
39
+ if (type.isDate(val))
40
+ return val.toISOString();
41
+ return null;
42
+ };
43
+ /**
44
+ * 字符化查询对象,内部使用的是浏览器内置的 URLSearchParams 进行处理
45
+ * @param {LooseParams} query
46
+ * @param {Replacer} replacer
47
+ * @returns {string}
48
+ */
49
+ const qsStringify = (query, replacer = defaultReplacer) => {
50
+ const params = new URLSearchParams();
51
+ object.objectEach(query, (val, key) => {
52
+ if (type.isArray(val)) {
53
+ val.forEach(i => {
54
+ const replaced = replacer(i);
55
+ if (replaced === null)
56
+ return;
57
+ params.append(key.toString(), replaced);
58
+ });
59
+ }
60
+ else {
61
+ const replaced = replacer(val);
62
+ if (replaced === null)
63
+ return;
64
+ params.set(key.toString(), replaced);
65
+ }
66
+ });
67
+ return params.toString();
68
+ };
69
+
70
+ exports.qsParse = qsParse;
71
+ exports.qsStringify = qsStringify;
@@ -0,0 +1,134 @@
1
+ /*!
2
+ * sculp-js v0.0.1
3
+ * (c) 2023-2023 chandq
4
+ * Released under the MIT License.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ /**
10
+ * 将字符串转换为驼峰格式
11
+ * @param {string} string
12
+ * @param {boolean} [bigger] 是否大写第一个字母
13
+ * @returns {string}
14
+ */
15
+ const stringCamelCase = (string, bigger) => {
16
+ let string2 = string;
17
+ if (bigger) {
18
+ string2 = string.replace(/^./, origin => origin.toUpperCase());
19
+ }
20
+ const HUMP_RE = /[\s_-](.)/g;
21
+ return string2.replace(HUMP_RE, (orign, char) => char.toUpperCase());
22
+ };
23
+ /**
24
+ * 将字符串转换为连字格式
25
+ * @param {string} string
26
+ * @param {string} [separator] 分隔符,默认是"-"(短横线)
27
+ * @returns {string}
28
+ */
29
+ const stringKebabCase = (string, separator = '-') => {
30
+ const string2 = string.replace(/^./, origin => origin.toLowerCase());
31
+ return string2.replace(/[A-Z]/g, origin => `${separator}${origin.toLowerCase()}`);
32
+ };
33
+ const STRING_ARABIC_NUMERALS = '0123456789';
34
+ const STRING_LOWERCASE_ALPHA = 'abcdefghijklmnopqrstuvwxyz';
35
+ const STRING_UPPERCASE_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
36
+ const placeholderRE = /%[%sdo]/g;
37
+ /**
38
+ * 字符串格式化
39
+ * @example
40
+ * ```js
41
+ * stringFormat("My name is %s.", "zhangsan")
42
+ * // => "My name is zhangsan."
43
+ * ```
44
+ * @param {string} string 字符串模板,使用 %s 表示字符串,%d 表示数值,%o 表示对象,%% 表示百分号,参考 console.log
45
+ * @param args
46
+ * @returns {string}
47
+ */
48
+ const stringFormat = (string, ...args) => {
49
+ let index = 0;
50
+ const result = string.replace(placeholderRE, (origin) => {
51
+ const arg = args[index++];
52
+ switch (origin) {
53
+ case '%%':
54
+ index--;
55
+ return '%';
56
+ default:
57
+ case '%s':
58
+ return String(arg);
59
+ case '%d':
60
+ return String(Number(arg));
61
+ case '%o':
62
+ return JSON.stringify(arg);
63
+ }
64
+ });
65
+ return [result, ...args.splice(index).map(String)].join(' ');
66
+ };
67
+ const ev = (expression, data) => {
68
+ try {
69
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval,@typescript-eslint/no-unsafe-return
70
+ return new Function('with(arguments[0]){' +
71
+ /****/ `if(arguments[0].${expression} === undefined)throw "";` +
72
+ /****/
73
+ /****/ `return String(arguments[0].${expression})` +
74
+ '}')(data);
75
+ }
76
+ catch (err) {
77
+ throw new SyntaxError(`无法执行表达式:${expression}`);
78
+ }
79
+ };
80
+ const templateRE = /\${(.*?)}/g;
81
+ /**
82
+ * 字符串赋值
83
+ * @example
84
+ * ```js
85
+ * stringAssign('My name is ${user}.', { user: 'zhangsan' });
86
+ * // => "My name is zhangsan."
87
+ * ```
88
+ * @param {string} template
89
+ * @param {AnyObject} data
90
+ * @returns {string}
91
+ */
92
+ const stringAssign = (template, data) => {
93
+ return template.replace(templateRE, (origin, expression) => ev(expression, data));
94
+ };
95
+ /**
96
+ * 字符串编码 HTML
97
+ * @example
98
+ * ```js
99
+ * stringEscapeHtml('<b>You & Me speak "xixi"</b>')
100
+ * // => "&lt;b&gt;You &amp; Me speak &quot;xixi&quot;&lt;/b&gt;"
101
+ * ```
102
+ * @param {string} html
103
+ * @returns {string}
104
+ */
105
+ const stringEscapeHtml = (html) => {
106
+ const htmlCharRE = /[&<>"]/g;
107
+ const htmlCharReplacements = {
108
+ '&': '&amp;',
109
+ '<': '&lt;',
110
+ '>': '&gt;',
111
+ '"': '&quot;'
112
+ };
113
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
114
+ // @ts-ignore
115
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
116
+ return html.replace(htmlCharRE, $0 => htmlCharReplacements[$0]);
117
+ };
118
+ /**
119
+ * 字符串填充
120
+ * @param {number} length
121
+ * @param {string} value
122
+ * @returns {string}
123
+ */
124
+ const stringFill = (length, value = ' ') => new Array(length).fill(value).join('');
125
+
126
+ exports.STRING_ARABIC_NUMERALS = STRING_ARABIC_NUMERALS;
127
+ exports.STRING_LOWERCASE_ALPHA = STRING_LOWERCASE_ALPHA;
128
+ exports.STRING_UPPERCASE_ALPHA = STRING_UPPERCASE_ALPHA;
129
+ exports.stringAssign = stringAssign;
130
+ exports.stringCamelCase = stringCamelCase;
131
+ exports.stringEscapeHtml = stringEscapeHtml;
132
+ exports.stringFill = stringFill;
133
+ exports.stringFormat = stringFormat;
134
+ exports.stringKebabCase = stringKebabCase;