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.
- package/LICENSE.md +21 -0
- package/README.md +3 -0
- package/lib/cjs/array.js +217 -0
- package/lib/cjs/async.js +63 -0
- package/lib/cjs/clipboard.js +36 -0
- package/lib/cjs/cookie.js +63 -0
- package/lib/cjs/date.js +114 -0
- package/lib/cjs/dom.js +152 -0
- package/lib/cjs/download.js +82 -0
- package/lib/cjs/easing.js +40 -0
- package/lib/cjs/file.js +30 -0
- package/lib/cjs/index.js +41 -0
- package/lib/cjs/object.js +241 -0
- package/lib/cjs/path.js +66 -0
- package/lib/cjs/qs.js +71 -0
- package/lib/cjs/string.js +134 -0
- package/lib/cjs/type.js +47 -0
- package/lib/cjs/url.js +84 -0
- package/lib/cjs/watermark.js +91 -0
- package/lib/es/array.js +208 -0
- package/lib/es/async.js +60 -0
- package/lib/es/clipboard.js +34 -0
- package/lib/es/cookie.js +59 -0
- package/lib/es/date.js +110 -0
- package/lib/es/dom.js +143 -0
- package/lib/es/download.js +77 -0
- package/lib/es/easing.js +38 -0
- package/lib/es/file.js +28 -0
- package/lib/es/index.js +35 -0
- package/lib/es/object.js +228 -0
- package/lib/es/path.js +63 -0
- package/lib/es/qs.js +68 -0
- package/lib/es/string.js +124 -0
- package/lib/es/type.js +28 -0
- package/lib/es/url.js +79 -0
- package/lib/es/watermark.js +89 -0
- package/lib/index.d.ts +644 -0
- package/lib/umd/index.js +1458 -0
- package/package.json +80 -0
package/lib/es/string.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* sculp-js v0.0.1
|
|
3
|
+
* (c) 2023-2023 chandq
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 将字符串转换为驼峰格式
|
|
9
|
+
* @param {string} string
|
|
10
|
+
* @param {boolean} [bigger] 是否大写第一个字母
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
const stringCamelCase = (string, bigger) => {
|
|
14
|
+
let string2 = string;
|
|
15
|
+
if (bigger) {
|
|
16
|
+
string2 = string.replace(/^./, origin => origin.toUpperCase());
|
|
17
|
+
}
|
|
18
|
+
const HUMP_RE = /[\s_-](.)/g;
|
|
19
|
+
return string2.replace(HUMP_RE, (orign, char) => char.toUpperCase());
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* 将字符串转换为连字格式
|
|
23
|
+
* @param {string} string
|
|
24
|
+
* @param {string} [separator] 分隔符,默认是"-"(短横线)
|
|
25
|
+
* @returns {string}
|
|
26
|
+
*/
|
|
27
|
+
const stringKebabCase = (string, separator = '-') => {
|
|
28
|
+
const string2 = string.replace(/^./, origin => origin.toLowerCase());
|
|
29
|
+
return string2.replace(/[A-Z]/g, origin => `${separator}${origin.toLowerCase()}`);
|
|
30
|
+
};
|
|
31
|
+
const STRING_ARABIC_NUMERALS = '0123456789';
|
|
32
|
+
const STRING_LOWERCASE_ALPHA = 'abcdefghijklmnopqrstuvwxyz';
|
|
33
|
+
const STRING_UPPERCASE_ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
34
|
+
const placeholderRE = /%[%sdo]/g;
|
|
35
|
+
/**
|
|
36
|
+
* 字符串格式化
|
|
37
|
+
* @example
|
|
38
|
+
* ```js
|
|
39
|
+
* stringFormat("My name is %s.", "zhangsan")
|
|
40
|
+
* // => "My name is zhangsan."
|
|
41
|
+
* ```
|
|
42
|
+
* @param {string} string 字符串模板,使用 %s 表示字符串,%d 表示数值,%o 表示对象,%% 表示百分号,参考 console.log
|
|
43
|
+
* @param args
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
46
|
+
const stringFormat = (string, ...args) => {
|
|
47
|
+
let index = 0;
|
|
48
|
+
const result = string.replace(placeholderRE, (origin) => {
|
|
49
|
+
const arg = args[index++];
|
|
50
|
+
switch (origin) {
|
|
51
|
+
case '%%':
|
|
52
|
+
index--;
|
|
53
|
+
return '%';
|
|
54
|
+
default:
|
|
55
|
+
case '%s':
|
|
56
|
+
return String(arg);
|
|
57
|
+
case '%d':
|
|
58
|
+
return String(Number(arg));
|
|
59
|
+
case '%o':
|
|
60
|
+
return JSON.stringify(arg);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return [result, ...args.splice(index).map(String)].join(' ');
|
|
64
|
+
};
|
|
65
|
+
const ev = (expression, data) => {
|
|
66
|
+
try {
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval,@typescript-eslint/no-unsafe-return
|
|
68
|
+
return new Function('with(arguments[0]){' +
|
|
69
|
+
/****/ `if(arguments[0].${expression} === undefined)throw "";` +
|
|
70
|
+
/****/
|
|
71
|
+
/****/ `return String(arguments[0].${expression})` +
|
|
72
|
+
'}')(data);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
throw new SyntaxError(`无法执行表达式:${expression}`);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const templateRE = /\${(.*?)}/g;
|
|
79
|
+
/**
|
|
80
|
+
* 字符串赋值
|
|
81
|
+
* @example
|
|
82
|
+
* ```js
|
|
83
|
+
* stringAssign('My name is ${user}.', { user: 'zhangsan' });
|
|
84
|
+
* // => "My name is zhangsan."
|
|
85
|
+
* ```
|
|
86
|
+
* @param {string} template
|
|
87
|
+
* @param {AnyObject} data
|
|
88
|
+
* @returns {string}
|
|
89
|
+
*/
|
|
90
|
+
const stringAssign = (template, data) => {
|
|
91
|
+
return template.replace(templateRE, (origin, expression) => ev(expression, data));
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* 字符串编码 HTML
|
|
95
|
+
* @example
|
|
96
|
+
* ```js
|
|
97
|
+
* stringEscapeHtml('<b>You & Me speak "xixi"</b>')
|
|
98
|
+
* // => "<b>You & Me speak "xixi"</b>"
|
|
99
|
+
* ```
|
|
100
|
+
* @param {string} html
|
|
101
|
+
* @returns {string}
|
|
102
|
+
*/
|
|
103
|
+
const stringEscapeHtml = (html) => {
|
|
104
|
+
const htmlCharRE = /[&<>"]/g;
|
|
105
|
+
const htmlCharReplacements = {
|
|
106
|
+
'&': '&',
|
|
107
|
+
'<': '<',
|
|
108
|
+
'>': '>',
|
|
109
|
+
'"': '"'
|
|
110
|
+
};
|
|
111
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
112
|
+
// @ts-ignore
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
114
|
+
return html.replace(htmlCharRE, $0 => htmlCharReplacements[$0]);
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* 字符串填充
|
|
118
|
+
* @param {number} length
|
|
119
|
+
* @param {string} value
|
|
120
|
+
* @returns {string}
|
|
121
|
+
*/
|
|
122
|
+
const stringFill = (length, value = ' ') => new Array(length).fill(value).join('');
|
|
123
|
+
|
|
124
|
+
export { STRING_ARABIC_NUMERALS, STRING_LOWERCASE_ALPHA, STRING_UPPERCASE_ALPHA, stringAssign, stringCamelCase, stringEscapeHtml, stringFill, stringFormat, stringKebabCase };
|
package/lib/es/type.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* sculp-js v0.0.1
|
|
3
|
+
* (c) 2023-2023 chandq
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const typeIs = (any) => Object.prototype.toString.call(any).slice(8, -1);
|
|
8
|
+
// 基本数据类型判断
|
|
9
|
+
const isString = (any) => typeof any === 'string';
|
|
10
|
+
const isBoolean = (any) => typeof any === 'boolean';
|
|
11
|
+
const isSymbol = (any) => typeof any === 'symbol';
|
|
12
|
+
const isBigInt = (any) => typeof any === 'bigint';
|
|
13
|
+
const isNumber = (any) => typeof any === 'number' && !Number.isNaN(any);
|
|
14
|
+
const isUndefined = (any) => typeof any === 'undefined';
|
|
15
|
+
const isNull = (any) => any === null;
|
|
16
|
+
const isPrimitive = (any) => any === null || typeof any !== 'object';
|
|
17
|
+
// 复合数据类型判断
|
|
18
|
+
const isObject = (any) => typeIs(any) === 'Object';
|
|
19
|
+
const isArray = (any) => Array.isArray(any);
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
21
|
+
const isFunction = (any) => typeof any === 'function';
|
|
22
|
+
// 对象类型判断
|
|
23
|
+
const isNaN = (any) => Number.isNaN(any);
|
|
24
|
+
const isDate = (any) => typeIs(any) === 'Date';
|
|
25
|
+
const isError = (any) => typeIs(any) === 'Error';
|
|
26
|
+
const isRegExp = (any) => typeIs(any) === 'RegExp';
|
|
27
|
+
|
|
28
|
+
export { typeIs as default, isArray, isBigInt, isBoolean, isDate, isError, isFunction, isNaN, isNull, isNumber, isObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined };
|
package/lib/es/url.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* sculp-js v0.0.1
|
|
3
|
+
* (c) 2023-2023 chandq
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { pathJoin } from './path.js';
|
|
8
|
+
import { qsParse, qsStringify } from './qs.js';
|
|
9
|
+
|
|
10
|
+
const anchorEl = document.createElement('a');
|
|
11
|
+
/**
|
|
12
|
+
* url 解析
|
|
13
|
+
* @param {string} url
|
|
14
|
+
* @returns {Url}
|
|
15
|
+
*/
|
|
16
|
+
const urlParse = (url) => {
|
|
17
|
+
anchorEl.href = url;
|
|
18
|
+
const { protocol, username, password, host, port, hostname, hash, search, pathname: _pathname } = anchorEl;
|
|
19
|
+
// fix: ie 浏览器下,解析出来的 pathname 是没有 / 根的
|
|
20
|
+
const pathname = pathJoin('/', _pathname);
|
|
21
|
+
const auth = username && password ? `${username}:${password}` : '';
|
|
22
|
+
const query = search.replace(/^\?/, '');
|
|
23
|
+
const searchParams = qsParse(query);
|
|
24
|
+
const path = `${pathname}${search}`;
|
|
25
|
+
return {
|
|
26
|
+
protocol,
|
|
27
|
+
auth,
|
|
28
|
+
username,
|
|
29
|
+
password,
|
|
30
|
+
host,
|
|
31
|
+
port,
|
|
32
|
+
hostname,
|
|
33
|
+
hash,
|
|
34
|
+
search,
|
|
35
|
+
searchParams,
|
|
36
|
+
query,
|
|
37
|
+
pathname,
|
|
38
|
+
path,
|
|
39
|
+
href: url
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* url 字符化,url 对象里的 searchParams 会覆盖 url 原有的查询参数
|
|
44
|
+
* @param {Url} url
|
|
45
|
+
* @returns {string}
|
|
46
|
+
*/
|
|
47
|
+
const urlStringify = (url) => {
|
|
48
|
+
const { protocol, auth, host, pathname, searchParams, hash } = url;
|
|
49
|
+
const authorize = auth ? `${auth}@` : '';
|
|
50
|
+
const querystring = qsStringify(searchParams);
|
|
51
|
+
const search = querystring ? `?${querystring}` : '';
|
|
52
|
+
let hashstring = hash.replace(/^#/, '');
|
|
53
|
+
hashstring = hashstring ? '#' + hashstring : '';
|
|
54
|
+
return `${protocol}//${authorize}${host}${pathname}${search}${hashstring}`;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* 设置 url 查询参数
|
|
58
|
+
* @param {string} url
|
|
59
|
+
* @param {AnyObject} setter
|
|
60
|
+
* @returns {string}
|
|
61
|
+
*/
|
|
62
|
+
const urlSetParams = (url, setter) => {
|
|
63
|
+
const p = urlParse(url);
|
|
64
|
+
Object.assign(p.searchParams, setter);
|
|
65
|
+
return urlStringify(p);
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* 删除 url 查询参数
|
|
69
|
+
* @param {string} url
|
|
70
|
+
* @param {string[]} removeKeys
|
|
71
|
+
* @returns {string}
|
|
72
|
+
*/
|
|
73
|
+
const urlDelParams = (url, removeKeys) => {
|
|
74
|
+
const p = urlParse(url);
|
|
75
|
+
removeKeys.forEach(key => delete p.searchParams[key]);
|
|
76
|
+
return urlStringify(p);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export { urlDelParams, urlParse, urlSetParams, urlStringify };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* sculp-js v0.0.1
|
|
3
|
+
* (c) 2023-2023 chandq
|
|
4
|
+
* Released under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* @created: Saturday, 2020-04-18 14:38:23
|
|
9
|
+
* @author: chendq
|
|
10
|
+
* ---------
|
|
11
|
+
* @desc 网页加水印的工具类
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* canvas 实现 watermark
|
|
15
|
+
* @param {ICanvasWM} canvasWM
|
|
16
|
+
*/
|
|
17
|
+
const genCanvasWM = (canvasWM) => {
|
|
18
|
+
const { container = document.body, width = '300px', height = '200px', textAlign = 'center', textBaseline = 'middle', font = '20px PingFangSC-Medium,PingFang SC',
|
|
19
|
+
// fontWeight = 500,
|
|
20
|
+
fillStyle = 'rgba(189, 177, 167, .3)', content = '请勿外传', rotate = 30, zIndex = 2147483647 } = canvasWM;
|
|
21
|
+
// 仅限主页面添加水印
|
|
22
|
+
if (!location.pathname.includes('/home')) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const args = canvasWM;
|
|
26
|
+
const canvas = document.createElement('canvas');
|
|
27
|
+
canvas.setAttribute('width', width);
|
|
28
|
+
canvas.setAttribute('height', height);
|
|
29
|
+
const ctx = canvas.getContext('2d');
|
|
30
|
+
ctx.textAlign = textAlign;
|
|
31
|
+
ctx.textBaseline = textBaseline;
|
|
32
|
+
ctx.font = font;
|
|
33
|
+
// ctx!.fontWeight = fontWeight;
|
|
34
|
+
ctx.fillStyle = fillStyle;
|
|
35
|
+
ctx.rotate((Math.PI / 180) * rotate);
|
|
36
|
+
ctx.fillText(content, parseFloat(width) / 4, parseFloat(height) / 2);
|
|
37
|
+
const base64Url = canvas.toDataURL();
|
|
38
|
+
const __wm = document.querySelector('.__wm');
|
|
39
|
+
const watermarkDiv = __wm || document.createElement('div');
|
|
40
|
+
const styleStr = `opacity: 1 !important; display: block !important; visibility: visible !important; position:absolute; left:0; top:0; width:100%; height:100%; z-index:${zIndex}; pointer-events:none; background-repeat:repeat; background-image:url('${base64Url}')`;
|
|
41
|
+
watermarkDiv.setAttribute('style', styleStr);
|
|
42
|
+
watermarkDiv.classList.add('__wm');
|
|
43
|
+
watermarkDiv.classList.add('nav-height');
|
|
44
|
+
if (!__wm) {
|
|
45
|
+
container.style.position = 'relative';
|
|
46
|
+
container.appendChild(watermarkDiv);
|
|
47
|
+
}
|
|
48
|
+
const getMutableStyle = (ele) => {
|
|
49
|
+
const computedStle = getComputedStyle(ele);
|
|
50
|
+
return {
|
|
51
|
+
opacity: computedStle.getPropertyValue('opacity'),
|
|
52
|
+
zIndex: computedStle.getPropertyValue('z-index'),
|
|
53
|
+
display: computedStle.getPropertyValue('display'),
|
|
54
|
+
visibility: computedStle.getPropertyValue('visibility')
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
//@ts-ignore
|
|
58
|
+
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
|
|
59
|
+
if (MutationObserver) {
|
|
60
|
+
let mo = new MutationObserver(function () {
|
|
61
|
+
const __wm = document.querySelector('.__wm'); // 只在__wm元素变动才重新调用 __canvasWM
|
|
62
|
+
if (!__wm) {
|
|
63
|
+
// 避免一直触发
|
|
64
|
+
// console.log('regenerate watermark by delete::')
|
|
65
|
+
mo.disconnect();
|
|
66
|
+
mo = null;
|
|
67
|
+
genCanvasWM(JSON.parse(JSON.stringify(args)));
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const { opacity, zIndex, display, visibility } = getMutableStyle(__wm);
|
|
71
|
+
if ((__wm && __wm.getAttribute('style') !== styleStr) ||
|
|
72
|
+
!__wm ||
|
|
73
|
+
!(opacity === '1' && zIndex === '2147483647' && display === 'block' && visibility === 'visible')) {
|
|
74
|
+
// 避免一直触发
|
|
75
|
+
// console.log('regenerate watermark by inline style changed ::')
|
|
76
|
+
mo.disconnect();
|
|
77
|
+
mo = null;
|
|
78
|
+
container.removeChild(__wm);
|
|
79
|
+
genCanvasWM(JSON.parse(JSON.stringify(args)));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
mo.observe(container, { attributes: true, subtree: true, childList: true });
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
// 调用
|
|
87
|
+
// __canvasWM({ content: 'QQMusicFE' })
|
|
88
|
+
|
|
89
|
+
export { genCanvasWM };
|