@base-web-kits/base-tools-ts 0.9.4 → 0.9.6
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/base-tools-ts.umd.global.js +2 -1
- package/dist/base-tools-ts.umd.global.js +2 -1
- package/dist/base-tools-ts.umd.global.js.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/package.json +1 -1
- package/src/ts/array/index.ts +13 -0
- package/src/ts/async/index.ts +20 -0
- package/src/ts/bean/EventBus.ts +61 -0
- package/src/ts/bean/index.ts +1 -0
- package/src/ts/day/index.ts +184 -0
- package/src/ts/index.ts +14 -0
- package/src/ts/lodash/index.ts +7 -0
- package/src/ts/number/big.ts +192 -0
- package/src/ts/number/format.ts +253 -0
- package/src/ts/number/index.ts +3 -0
- package/src/ts/number/random.ts +65 -0
- package/src/ts/object/index.ts +12 -0
- package/src/ts/string/format.ts +52 -0
- package/src/ts/string/index.ts +3 -0
- package/src/ts/string/other.ts +33 -0
- package/src/ts/string/random.ts +42 -0
- package/src/ts/typing/index.ts +161 -0
- package/src/ts/url/file/index.ts +57 -0
- package/src/ts/url/index.ts +4 -0
- package/src/ts/url/oss/index.d.ts +120 -0
- package/src/ts/url/oss/index.ts +168 -0
- package/src/ts/url/param/index.ts +119 -0
- package/src/ts/url/qn/index.d.ts +103 -0
- package/src/ts/url/qn/index.ts +237 -0
- package/src/ts/validator/index.ts +601 -0
- package/index.cjs +0 -2
- package/index.d.ts +0 -1
- package/index.js +0 -1
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import type { QnImgOption, QnMogr2Option, QnWatermarkOption, QnImageView2Option } from './index.d';
|
|
2
|
+
|
|
3
|
+
export * from './index.d';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* qn图片处理
|
|
7
|
+
* 参考官方文档: https://developer.qiniu.com/kodo/8623/dev-the-picture-style
|
|
8
|
+
* @param src 原始图片URL
|
|
9
|
+
* @param option 图片处理选项
|
|
10
|
+
* @returns 处理后的图片URL(格式: `{src}?imageView2/...|imageMogr2/...|watermark/...|imageslim|imageInfo`)
|
|
11
|
+
* @example
|
|
12
|
+
* 缩略: getQnImg('xx.jpg', { imageView2: { mode: 2, w: 100, h: 100 } })
|
|
13
|
+
* 高级缩放: getQnImg('xx.jpg', { thumbnail: '!50p' })
|
|
14
|
+
* 裁剪: getQnImg('xx.jpg', { crop: '100x100' })
|
|
15
|
+
* 旋转: getQnImg('xx.jpg', { rotate: 90 })
|
|
16
|
+
* 自适应方向: getQnImg('xx.jpg', { 'auto-orient': true })
|
|
17
|
+
* 格式转换: getQnImg('xx.jpg', { format: 'webp' })
|
|
18
|
+
* 质量: getQnImg('xx.jpg', { q: 80 })
|
|
19
|
+
* 渐进显示: getQnImg('xx.jpg', { interlace: 1 })
|
|
20
|
+
* 背景色填充: getQnImg('xx.jpg', { background: 'white' })
|
|
21
|
+
* 模糊: getQnImg('xx.jpg', { blur: { r: 10, s: 10 } })
|
|
22
|
+
* GIF颜色控制: getQnImg('xx.jpg', { colors: 64 })
|
|
23
|
+
* 图片瘦身: getQnImg('xx.jpg', { imageslim: true })
|
|
24
|
+
* 图片信息: getQnImg('xx.jpg', { imageInfo: true })
|
|
25
|
+
* 图片水印: getQnImg('xx.jpg', { watermark: { type: 'image', image: 'http://example.com/logo.png' } })
|
|
26
|
+
* 文字水印: getQnImg('xx.jpg', { watermark: { type: 'text', text: '水印', fontsize: 18 } })
|
|
27
|
+
*/
|
|
28
|
+
export function getQnImg(src: string, option: QnImgOption) {
|
|
29
|
+
if (!src || !option) return src;
|
|
30
|
+
if (src.startsWith('blob:')) return src;
|
|
31
|
+
if (src.includes('.svg')) return src;
|
|
32
|
+
|
|
33
|
+
const segs: string[] = [];
|
|
34
|
+
|
|
35
|
+
if (option.imageslim) segs.push('imageslim');
|
|
36
|
+
|
|
37
|
+
if (option.imageView2) segs.push(getImageView2(option.imageView2));
|
|
38
|
+
|
|
39
|
+
const mogr = getImageMogr2(option.imageMogr2 ?? option);
|
|
40
|
+
if (mogr) segs.push(mogr);
|
|
41
|
+
|
|
42
|
+
if (option.watermark) segs.push(getWatermark(option.watermark));
|
|
43
|
+
|
|
44
|
+
if (option.imageInfo) segs.push('imageInfo');
|
|
45
|
+
|
|
46
|
+
if (!segs.length) return src;
|
|
47
|
+
|
|
48
|
+
const base = src.split('?')[0];
|
|
49
|
+
return `${base}?${segs.join('|')}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* qn视频处理
|
|
54
|
+
* 参考官方文档: https://developer.qiniu.com/kodo/12654/video-process
|
|
55
|
+
* @param src 原始视频URL
|
|
56
|
+
* @param option 视频处理选项(支持 avthumb、vframe)
|
|
57
|
+
* @returns 处理后的URL(格式: `{src}?avthumb/...|vframe/...`)
|
|
58
|
+
* @example
|
|
59
|
+
* 视频转码: getQnVideo('xx.mp4', { avthumb: { format: 'mp4', s: '1280x720', vcodec: 'libx264', vb: '1.25m' } })
|
|
60
|
+
* 截帧: getQnVideo('xx.mp4', { vframe: { format: 'jpg', offset: 3, w: 480, h: 360 } })
|
|
61
|
+
*/
|
|
62
|
+
export function getQnVideo(src: string, option: import('.').QnVideoOption) {
|
|
63
|
+
if (!src || !option) return src;
|
|
64
|
+
if (src.startsWith('blob:')) return src;
|
|
65
|
+
if (src.includes('.svg')) return src;
|
|
66
|
+
const segs: string[] = [];
|
|
67
|
+
if (option.avthumb) segs.push(getAvthumb(option.avthumb));
|
|
68
|
+
if (option.vframe) segs.push(getVframe(option.vframe));
|
|
69
|
+
if (!segs.length) return src;
|
|
70
|
+
const base = src.split('?')[0];
|
|
71
|
+
return `${base}?${segs.join('|')}`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* qn音频处理
|
|
76
|
+
* 参考官方文档: https://developer.qiniu.com/kodo/12654/video-process
|
|
77
|
+
* @param src 原始音频URL
|
|
78
|
+
* @param option 音频处理选项(通过 avthumb 转码)
|
|
79
|
+
* @returns 处理后的URL(格式: `{src}?avthumb/...`)
|
|
80
|
+
* @example
|
|
81
|
+
* 音频转码: getQnAudio('xx.aac', { avthumb: { format: 'mp3', ab: '128k', ar: 44100, acodec: 'libmp3lame' } })
|
|
82
|
+
*/
|
|
83
|
+
export function getQnAudio(src: string, option: import('.').QnAudioOption) {
|
|
84
|
+
if (!src || !option) return src;
|
|
85
|
+
if (src.startsWith('blob:')) return src;
|
|
86
|
+
const segs: string[] = [];
|
|
87
|
+
if (option.avthumb) segs.push(getAvthumb(option.avthumb));
|
|
88
|
+
if (!segs.length) return src;
|
|
89
|
+
const base = src.split('?')[0];
|
|
90
|
+
return `${base}?${segs.join('|')}`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* qn实时转码(HLS 边转边播)
|
|
95
|
+
* 参考官方文档: https://developer.qiniu.com/kodo/12654/video-process、实时转码
|
|
96
|
+
* @param src 原始视频URL
|
|
97
|
+
* @param option HLS 选项
|
|
98
|
+
* @returns 处理后的URL(格式: `{src}?avcvt/{level}/format/m3u8/...`)
|
|
99
|
+
* @example
|
|
100
|
+
* 720P HLS: getQnHls('xx.mp4', { level: 3, format: 'm3u8', segtime: 6 })
|
|
101
|
+
*/
|
|
102
|
+
export function getQnHls(src: string, option: import('.').QnHlsOption) {
|
|
103
|
+
if (!src || !option) return src;
|
|
104
|
+
if (src.startsWith('blob:')) return src;
|
|
105
|
+
const seg = getAvcvt(option);
|
|
106
|
+
if (!seg) return src;
|
|
107
|
+
const base = src.split('?')[0];
|
|
108
|
+
return `${base}?${seg}`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function getImageView2(opt?: QnImageView2Option) {
|
|
112
|
+
if (!opt) return '';
|
|
113
|
+
const mode = typeof opt.mode === 'number' ? opt.mode : 0;
|
|
114
|
+
const kv: string[] = [];
|
|
115
|
+
for (const [k, v] of Object.entries(opt)) {
|
|
116
|
+
if (k === 'mode') continue;
|
|
117
|
+
if (typeof v === 'boolean') {
|
|
118
|
+
if (v) kv.push(`${k}/1`);
|
|
119
|
+
} else if (typeof v === 'number' || typeof v === 'string') {
|
|
120
|
+
kv.push(`${k}/${v}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return kv.length ? `imageView2/${mode}/${kv.join('/')}` : `imageView2/${mode}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function getImageMogr2(opt?: QnMogr2Option | QnImgOption) {
|
|
127
|
+
if (!opt) return '';
|
|
128
|
+
const parts: string[] = [];
|
|
129
|
+
|
|
130
|
+
const tn = (opt as QnMogr2Option).thumbnail;
|
|
131
|
+
if (typeof tn !== 'undefined') parts.push(`thumbnail/${tn}`);
|
|
132
|
+
|
|
133
|
+
const cp = (opt as QnMogr2Option).crop;
|
|
134
|
+
if (typeof cp !== 'undefined') parts.push(`crop/${cp}`);
|
|
135
|
+
|
|
136
|
+
const rot = (opt as QnMogr2Option).rotate;
|
|
137
|
+
if (typeof rot === 'number') parts.push(`rotate/${rot}`);
|
|
138
|
+
|
|
139
|
+
const ao = (opt as QnMogr2Option)['auto-orient'];
|
|
140
|
+
if (ao) parts.push('auto-orient');
|
|
141
|
+
|
|
142
|
+
const fmt = (opt as QnMogr2Option).format;
|
|
143
|
+
if (typeof fmt === 'string') parts.push(`format/${fmt}`);
|
|
144
|
+
|
|
145
|
+
const il = (opt as QnMogr2Option).interlace;
|
|
146
|
+
if (il === 0 || il === 1) parts.push(`interlace/${il}`);
|
|
147
|
+
|
|
148
|
+
const bg = (opt as QnMogr2Option).background;
|
|
149
|
+
if (typeof bg === 'string') parts.push(`background/${bg}`);
|
|
150
|
+
|
|
151
|
+
const q = (opt as QnMogr2Option).q;
|
|
152
|
+
if (typeof q === 'number') parts.push(`q/${q}`);
|
|
153
|
+
|
|
154
|
+
const blur = (opt as QnMogr2Option).blur;
|
|
155
|
+
if (typeof blur !== 'undefined') {
|
|
156
|
+
if (typeof blur === 'string') parts.push(`blur/${blur}`);
|
|
157
|
+
else parts.push(`blur/${blur.r}x${blur.s}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const colors = (opt as QnMogr2Option).colors;
|
|
161
|
+
if (typeof colors === 'number') parts.push(`colors/${colors}`);
|
|
162
|
+
|
|
163
|
+
return parts.length ? `imageMogr2/${parts.join('/')}` : '';
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function getWatermark(w?: QnWatermarkOption) {
|
|
167
|
+
if (!w) return '';
|
|
168
|
+
const mode =
|
|
169
|
+
w.type === 'image' ? 1 : w.type === 'text' ? 2 : typeof w.type === 'number' ? w.type : 2;
|
|
170
|
+
const segs: string[] = [`watermark/${mode}`];
|
|
171
|
+
if (mode === 1 && w.image) segs.push(`image/${toBase64Url(w.image)}`);
|
|
172
|
+
if (mode === 2 && w.text) segs.push(`text/${toBase64Url(w.text)}`);
|
|
173
|
+
if (w.font) segs.push(`font/${toBase64Url(w.font)}`);
|
|
174
|
+
if (typeof w.fontsize === 'number') segs.push(`fontsize/${w.fontsize}`);
|
|
175
|
+
if (w.fill) segs.push(`fill/${toBase64Url(w.fill)}`);
|
|
176
|
+
if (w.gravity) segs.push(`gravity/${w.gravity}`);
|
|
177
|
+
if (typeof w.dx === 'number') segs.push(`dx/${w.dx}`);
|
|
178
|
+
if (typeof w.dy === 'number') segs.push(`dy/${w.dy}`);
|
|
179
|
+
if (typeof w.dissolve === 'number') segs.push(`dissolve/${w.dissolve}`);
|
|
180
|
+
return segs.join('/');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function toBase64Url(s: string) {
|
|
184
|
+
let b64 = '';
|
|
185
|
+
if (typeof Buffer !== 'undefined') {
|
|
186
|
+
const buf = Buffer.from(s, 'utf-8');
|
|
187
|
+
b64 = buf.toString('base64');
|
|
188
|
+
} else {
|
|
189
|
+
try {
|
|
190
|
+
b64 = btoa(unescape(encodeURIComponent(s)));
|
|
191
|
+
} catch {
|
|
192
|
+
b64 = '';
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return b64.replace(/=+$/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function getAvthumb(opt: import('.').QnAvthumbOption) {
|
|
199
|
+
const parts: string[] = [];
|
|
200
|
+
if (opt.format) parts.push(`avthumb/${opt.format}`);
|
|
201
|
+
else parts.push('avthumb');
|
|
202
|
+
if (opt.s) parts.push(`s/${opt.s}`);
|
|
203
|
+
if (opt.vcodec) parts.push(`vcodec/${opt.vcodec}`);
|
|
204
|
+
if (typeof opt.vb !== 'undefined') parts.push(`vb/${opt.vb}`);
|
|
205
|
+
if (typeof opt.r === 'number') parts.push(`r/${opt.r}`);
|
|
206
|
+
if (typeof opt.ab !== 'undefined') parts.push(`ab/${opt.ab}`);
|
|
207
|
+
if (typeof opt.ar === 'number') parts.push(`ar/${opt.ar}`);
|
|
208
|
+
if (opt.acodec) parts.push(`acodec/${opt.acodec}`);
|
|
209
|
+
return parts.join('/');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function getVframe(opt: import('.').QnVframeOption) {
|
|
213
|
+
const parts: string[] = [];
|
|
214
|
+
parts.push(`vframe/${opt.format || 'jpg'}`);
|
|
215
|
+
if (typeof opt.offset === 'number') parts.push(`offset/${opt.offset}`);
|
|
216
|
+
if (typeof opt.w === 'number') parts.push(`w/${opt.w}`);
|
|
217
|
+
if (typeof opt.h === 'number') parts.push(`h/${opt.h}`);
|
|
218
|
+
return parts.join('/');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function getAvcvt(opt: import('.').QnHlsOption) {
|
|
222
|
+
const parts: string[] = [];
|
|
223
|
+
const level = typeof opt.level === 'number' ? `/${opt.level}` : '/3';
|
|
224
|
+
parts.push(`avcvt${level}`);
|
|
225
|
+
parts.push(`format/${opt.format || 'm3u8'}`);
|
|
226
|
+
if (typeof opt.segtime === 'number') parts.push(`segtime/${opt.segtime}`);
|
|
227
|
+
if (typeof opt.t === 'string') parts.push(`t/${opt.t}`);
|
|
228
|
+
if (opt.vcodec) parts.push(`vcodec/${opt.vcodec}`);
|
|
229
|
+
if (typeof opt.vb !== 'undefined') parts.push(`vb/${opt.vb}`);
|
|
230
|
+
if (typeof opt.r === 'number') parts.push(`r/${opt.r}`);
|
|
231
|
+
if (typeof opt.s === 'string') parts.push(`s/${opt.s}`);
|
|
232
|
+
if (opt.acodec) parts.push(`acodec/${opt.acodec}`);
|
|
233
|
+
if (typeof opt.ab !== 'undefined') parts.push(`ab/${opt.ab}`);
|
|
234
|
+
if (typeof opt.ar === 'number') parts.push(`ar/${opt.ar}`);
|
|
235
|
+
if (typeof opt.output === 'string') parts.push(`output/${toBase64Url(opt.output)}`);
|
|
236
|
+
return parts.join('/');
|
|
237
|
+
}
|