@cloudcome/utils-browser 1.1.0 → 1.1.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/CHANGELOG.md +27 -0
- package/LICENSE +21 -0
- package/package.json +122 -1
- package/src/base64.ts +25 -0
- package/{dist/cache.cjs → src/cache.ts} +48 -20
- package/src/canvas.ts +147 -0
- package/{dist/clipboard.d.ts → src/clipboard.ts} +12 -1
- package/src/cookie.ts +118 -0
- package/{dist/dom.d.ts → src/dom.ts} +21 -3
- package/src/download.ts +22 -0
- package/src/dts/global.d.ts +27 -0
- package/src/image.ts +45 -0
- package/src/index.ts +1 -0
- package/src/timer.ts +56 -0
- package/src/video.ts +19 -0
- package/test/base64.test.ts +47 -0
- package/test/cache.test.ts +199 -0
- package/test/canvas.test.ts +124 -0
- package/test/clipboard.test.ts +18 -0
- package/test/cookie.test.ts +52 -0
- package/test/dom.test.ts +67 -0
- package/test/download.test.ts +15 -0
- package/test/image.test.ts +75 -0
- package/test/index.test.ts +6 -0
- package/test/timer.test.ts +109 -0
- package/test/video.test.ts +36 -0
- package/tsconfig.json +31 -0
- package/vite.config.mts +100 -0
- package/dist/base64.cjs +0 -15
- package/dist/base64.cjs.map +0 -1
- package/dist/base64.d.ts +0 -14
- package/dist/base64.mjs +0 -15
- package/dist/base64.mjs.map +0 -1
- package/dist/cache.cjs.map +0 -1
- package/dist/cache.d.ts +0 -49
- package/dist/cache.mjs +0 -87
- package/dist/cache.mjs.map +0 -1
- package/dist/canvas.cjs +0 -58
- package/dist/canvas.cjs.map +0 -1
- package/dist/canvas.d.ts +0 -92
- package/dist/canvas.mjs +0 -58
- package/dist/canvas.mjs.map +0 -1
- package/dist/clipboard.cjs +0 -16
- package/dist/clipboard.cjs.map +0 -1
- package/dist/clipboard.mjs +0 -16
- package/dist/clipboard.mjs.map +0 -1
- package/dist/cookie.cjs +0 -50
- package/dist/cookie.cjs.map +0 -1
- package/dist/cookie.d.ts +0 -55
- package/dist/cookie.mjs +0 -50
- package/dist/cookie.mjs.map +0 -1
- package/dist/dom.cjs +0 -18
- package/dist/dom.cjs.map +0 -1
- package/dist/dom.mjs +0 -18
- package/dist/dom.mjs.map +0 -1
- package/dist/download.cjs +0 -16
- package/dist/download.cjs.map +0 -1
- package/dist/download.d.ts +0 -12
- package/dist/download.mjs +0 -16
- package/dist/download.mjs.map +0 -1
- package/dist/image.cjs +0 -35
- package/dist/image.cjs.map +0 -1
- package/dist/image.d.ts +0 -9
- package/dist/image.mjs +0 -35
- package/dist/image.mjs.map +0 -1
- package/dist/index.cjs +0 -5
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.mjs +0 -5
- package/dist/index.mjs.map +0 -1
- package/dist/timer.cjs +0 -41
- package/dist/timer.cjs.map +0 -1
- package/dist/timer.d.ts +0 -9
- package/dist/timer.mjs +0 -41
- package/dist/timer.mjs.map +0 -1
- package/dist/video.cjs +0 -14
- package/dist/video.cjs.map +0 -1
- package/dist/video.d.ts +0 -9
- package/dist/video.mjs +0 -14
- package/dist/video.mjs.map +0 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { imageLoad } from '../src/image';
|
|
3
|
+
|
|
4
|
+
describe('图片工具函数', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
vi.restoreAllMocks();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('应该能够成功加载图片', async () => {
|
|
10
|
+
const mockImage = new Image();
|
|
11
|
+
vi.spyOn(window, 'Image').mockReturnValue(mockImage);
|
|
12
|
+
vi.spyOn(document.body, 'appendChild');
|
|
13
|
+
vi.spyOn(document.body, 'removeChild');
|
|
14
|
+
|
|
15
|
+
const url = 'https://example.com/image.png';
|
|
16
|
+
const promise = imageLoad(url);
|
|
17
|
+
|
|
18
|
+
mockImage.onload?.({} as Event);
|
|
19
|
+
const result = await promise;
|
|
20
|
+
|
|
21
|
+
expect(result).toBe(mockImage);
|
|
22
|
+
expect(mockImage.src).toBe(url);
|
|
23
|
+
expect(mockImage.crossOrigin).toBe('anonymous');
|
|
24
|
+
expect(document.body.appendChild).toHaveBeenCalledWith(mockImage);
|
|
25
|
+
expect(document.body.removeChild).toHaveBeenCalledWith(mockImage);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('图片加载失败时应抛出错误', async () => {
|
|
29
|
+
const mockImage = new Image();
|
|
30
|
+
vi.spyOn(window, 'Image').mockReturnValue(mockImage);
|
|
31
|
+
|
|
32
|
+
const url = 'https://example.com/invalid.png';
|
|
33
|
+
const promise = imageLoad(url);
|
|
34
|
+
|
|
35
|
+
mockImage.onerror?.({} as Event);
|
|
36
|
+
|
|
37
|
+
await expect(promise).rejects.toThrow('图片加载失败');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('如果图片已经加载完成应立即返回', async () => {
|
|
41
|
+
const mockImage = new Image();
|
|
42
|
+
vi.spyOn(window, 'Image').mockReturnValue(mockImage);
|
|
43
|
+
Object.defineProperty(mockImage, 'complete', { value: true });
|
|
44
|
+
Object.defineProperty(mockImage, 'width', { value: 100 });
|
|
45
|
+
|
|
46
|
+
const url = 'https://example.com/image.png';
|
|
47
|
+
const result = await imageLoad(url);
|
|
48
|
+
|
|
49
|
+
expect(result).toBe(mockImage);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('应该为图片元素设置正确的样式', async () => {
|
|
53
|
+
const mockImage = new Image();
|
|
54
|
+
vi.spyOn(window, 'Image').mockReturnValue(mockImage);
|
|
55
|
+
|
|
56
|
+
const url = 'https://example.com/image.png';
|
|
57
|
+
const promise = imageLoad(url);
|
|
58
|
+
|
|
59
|
+
mockImage.onload?.({} as Event);
|
|
60
|
+
await promise;
|
|
61
|
+
|
|
62
|
+
expect(mockImage.style.visibility).toBe('hidden');
|
|
63
|
+
expect(mockImage.style.position).toBe('absolute');
|
|
64
|
+
expect(mockImage.style.top).toBe('-99999%');
|
|
65
|
+
expect(mockImage.style.left).toBe('-99999%');
|
|
66
|
+
expect(mockImage.style.maxWidth).toBe('');
|
|
67
|
+
expect(mockImage.style.maxHeight).toBe('');
|
|
68
|
+
expect(mockImage.style.border).toBe('0px');
|
|
69
|
+
expect(mockImage.style.width).toBe('auto');
|
|
70
|
+
expect(mockImage.style.height).toBe('auto');
|
|
71
|
+
expect(mockImage.style.margin).toBe('0px');
|
|
72
|
+
expect(mockImage.style.padding).toBe('0px');
|
|
73
|
+
expect(mockImage.style.transform).toBe('');
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { frameInterval } from '@/timer';
|
|
2
|
+
import { type Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
|
|
4
|
+
describe('帧间隔计时器', () => {
|
|
5
|
+
let mockRAF: number;
|
|
6
|
+
let mockCAF: Mock;
|
|
7
|
+
let callbacks: FrameRequestCallback[] = [];
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
mockRAF = 0;
|
|
11
|
+
callbacks = [];
|
|
12
|
+
mockCAF = vi.fn();
|
|
13
|
+
|
|
14
|
+
vi.stubGlobal('requestAnimationFrame', (cb: FrameRequestCallback) => {
|
|
15
|
+
callbacks.push(cb);
|
|
16
|
+
return ++mockRAF;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
vi.stubGlobal('cancelAnimationFrame', mockCAF);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
vi.unstubAllGlobals();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('启动时应在每一帧调用回调函数', () => {
|
|
27
|
+
const callback = vi.fn();
|
|
28
|
+
const timer = frameInterval(callback);
|
|
29
|
+
|
|
30
|
+
timer.start();
|
|
31
|
+
callbacks[0]?.(0);
|
|
32
|
+
const arg = callback.mock.calls[0][0];
|
|
33
|
+
expect(Object.keys(arg)).toEqual(
|
|
34
|
+
expect.arrayContaining([
|
|
35
|
+
'times',
|
|
36
|
+
'startAt',
|
|
37
|
+
'stopAt',
|
|
38
|
+
'pauseAt',
|
|
39
|
+
'resumeAt',
|
|
40
|
+
'currentAt',
|
|
41
|
+
'elapsedTime',
|
|
42
|
+
'runningTime',
|
|
43
|
+
'intervalTime',
|
|
44
|
+
]),
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('应该支持 leading 选项', () => {
|
|
49
|
+
const callback = vi.fn();
|
|
50
|
+
const timer = frameInterval(callback, { leading: true });
|
|
51
|
+
|
|
52
|
+
timer.start();
|
|
53
|
+
expect(callback).toHaveBeenCalled();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('停止时应支持 trailing 选项', () => {
|
|
57
|
+
const callback = vi.fn();
|
|
58
|
+
const timer = frameInterval(callback, { trailing: true });
|
|
59
|
+
|
|
60
|
+
timer.start();
|
|
61
|
+
callbacks[0]?.(0);
|
|
62
|
+
|
|
63
|
+
timer.stop();
|
|
64
|
+
expect(callback).toHaveBeenCalledTimes(2);
|
|
65
|
+
expect(mockCAF).toHaveBeenCalledWith(mockRAF);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('暂停时应支持 trailing 选项', () => {
|
|
69
|
+
const callback = vi.fn();
|
|
70
|
+
const timer = frameInterval(callback, { trailing: true });
|
|
71
|
+
|
|
72
|
+
timer.start();
|
|
73
|
+
callbacks[0]?.(0);
|
|
74
|
+
|
|
75
|
+
timer.pause();
|
|
76
|
+
expect(callback).toHaveBeenCalledTimes(2);
|
|
77
|
+
expect(mockCAF).toHaveBeenCalledWith(mockRAF);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('使用 immediate 标志时应立即恢复', () => {
|
|
81
|
+
const callback = vi.fn();
|
|
82
|
+
const timer = frameInterval(callback);
|
|
83
|
+
|
|
84
|
+
timer.start();
|
|
85
|
+
callbacks[0]?.(0);
|
|
86
|
+
timer.pause();
|
|
87
|
+
|
|
88
|
+
timer.resume(true);
|
|
89
|
+
callbacks[1]?.(16);
|
|
90
|
+
|
|
91
|
+
expect(callback).toHaveBeenCalledTimes(3);
|
|
92
|
+
expect(callback.mock.calls[1][0].times).toBe(2);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('不使用 immediate 标志时应下一帧恢复', () => {
|
|
96
|
+
const callback = vi.fn();
|
|
97
|
+
const timer = frameInterval(callback);
|
|
98
|
+
|
|
99
|
+
timer.start();
|
|
100
|
+
callbacks[0]?.(0);
|
|
101
|
+
timer.pause();
|
|
102
|
+
|
|
103
|
+
timer.resume();
|
|
104
|
+
callbacks[1]?.(16);
|
|
105
|
+
|
|
106
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
107
|
+
expect(callback.mock.calls[0][0].times).toBe(1);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { videoLoad } from '../src/video';
|
|
3
|
+
|
|
4
|
+
describe('视频工具函数', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
vi.restoreAllMocks();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('应该能够成功加载视频', async () => {
|
|
10
|
+
const mockVideo = document.createElement('video');
|
|
11
|
+
vi.spyOn(document, 'createElement').mockReturnValue(mockVideo);
|
|
12
|
+
|
|
13
|
+
const url = 'https://example.com/video.mp4';
|
|
14
|
+
const promise = videoLoad(url);
|
|
15
|
+
|
|
16
|
+
mockVideo.onloadedmetadata?.({} as Event);
|
|
17
|
+
const result = await promise;
|
|
18
|
+
|
|
19
|
+
expect(result).toBe(mockVideo);
|
|
20
|
+
expect(mockVideo.src).toBe(url);
|
|
21
|
+
expect(mockVideo.crossOrigin).toBe('anonymous');
|
|
22
|
+
expect(mockVideo.currentTime).toBe(1);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('视频加载失败时应抛出错误', async () => {
|
|
26
|
+
const mockVideo = document.createElement('video');
|
|
27
|
+
vi.spyOn(document, 'createElement').mockReturnValue(mockVideo);
|
|
28
|
+
|
|
29
|
+
const url = 'https://example.com/invalid.mp4';
|
|
30
|
+
const promise = videoLoad(url);
|
|
31
|
+
|
|
32
|
+
mockVideo.onerror?.({} as Event);
|
|
33
|
+
|
|
34
|
+
await expect(promise).rejects.toThrow('视频加载失败');
|
|
35
|
+
});
|
|
36
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"jsx": "preserve",
|
|
4
|
+
"jsxImportSource": "vue",
|
|
5
|
+
"target": "ES2024",
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"moduleResolution": "bundler",
|
|
8
|
+
|
|
9
|
+
"strict": true,
|
|
10
|
+
"noEmit": true,
|
|
11
|
+
"allowJs": true,
|
|
12
|
+
"sourceMap": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"esModuleInterop": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"verbatimModuleSyntax": true,
|
|
17
|
+
"allowImportingTsExtensions": false,
|
|
18
|
+
"allowSyntheticDefaultImports": true,
|
|
19
|
+
"forceConsistentCasingInFileNames": true,
|
|
20
|
+
|
|
21
|
+
"lib": ["ES2024", "DOM"],
|
|
22
|
+
"types": ["node", "vite/client", "vitest/globals"],
|
|
23
|
+
"plugins": [],
|
|
24
|
+
"paths": {
|
|
25
|
+
"@/*": ["./src/*"]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
"include": ["**/*.ts", "**/.*.ts", "**/*.mts", "**/*.tsx", "**/*.vue"],
|
|
30
|
+
"exclude": []
|
|
31
|
+
}
|
package/vite.config.mts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file vite.config.mts
|
|
3
|
+
* @ref https://vitejs.dev/
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import dts from 'vite-plugin-dts';
|
|
7
|
+
import { externalizeDeps } from 'vite-plugin-externalize-deps';
|
|
8
|
+
import tsconfigPaths from 'vite-tsconfig-paths';
|
|
9
|
+
import { defineConfig } from 'vitest/config';
|
|
10
|
+
import pkg from './package.json';
|
|
11
|
+
|
|
12
|
+
export default defineConfig((env) => {
|
|
13
|
+
const isProd = env.mode === 'production';
|
|
14
|
+
const isTest = env.mode === 'test';
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
base: '/',
|
|
18
|
+
server: {
|
|
19
|
+
port: 15170,
|
|
20
|
+
},
|
|
21
|
+
preview: {
|
|
22
|
+
port: 15171,
|
|
23
|
+
},
|
|
24
|
+
define: {
|
|
25
|
+
PKG_NAME: JSON.stringify(isTest ? 'pkg-name-for-test' : pkg.name),
|
|
26
|
+
PKG_VERSION: JSON.stringify(isTest ? 'pkg-version-for-test' : pkg.version),
|
|
27
|
+
PKG_DESCRIPTION: JSON.stringify(isTest ? 'pkg-description-for-test' : pkg.description),
|
|
28
|
+
IS_TEST: JSON.stringify(isTest),
|
|
29
|
+
},
|
|
30
|
+
build: {
|
|
31
|
+
minify: false,
|
|
32
|
+
sourcemap: true,
|
|
33
|
+
copyPublicDir: false,
|
|
34
|
+
reportCompressedSize: false,
|
|
35
|
+
lib: {
|
|
36
|
+
entry:
|
|
37
|
+
// expose-start
|
|
38
|
+
{
|
|
39
|
+
index: 'src/index.ts',
|
|
40
|
+
base64: './src/base64.ts',
|
|
41
|
+
cache: './src/cache.ts',
|
|
42
|
+
canvas: './src/canvas.ts',
|
|
43
|
+
clipboard: './src/clipboard.ts',
|
|
44
|
+
cookie: './src/cookie.ts',
|
|
45
|
+
dom: './src/dom.ts',
|
|
46
|
+
download: './src/download.ts',
|
|
47
|
+
image: './src/image.ts',
|
|
48
|
+
timer: './src/timer.ts',
|
|
49
|
+
video: './src/video.ts',
|
|
50
|
+
},
|
|
51
|
+
// expose-end
|
|
52
|
+
},
|
|
53
|
+
rollupOptions: {
|
|
54
|
+
output: [
|
|
55
|
+
{
|
|
56
|
+
format: 'esm',
|
|
57
|
+
entryFileNames: '[name].mjs',
|
|
58
|
+
chunkFileNames: '[name].mjs',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
format: 'cjs',
|
|
62
|
+
entryFileNames: '[name].cjs',
|
|
63
|
+
chunkFileNames: '[name].cjs',
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
test: {
|
|
69
|
+
globals: true,
|
|
70
|
+
environment: 'jsdom',
|
|
71
|
+
environmentOptions: {
|
|
72
|
+
jsdom: {
|
|
73
|
+
// 加载外部资源
|
|
74
|
+
resources: 'usable',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
coverage: {
|
|
78
|
+
all: true,
|
|
79
|
+
include: ['src/**/*.ts'],
|
|
80
|
+
reporter: ['lcov', 'text'],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
// esbuild: {
|
|
84
|
+
// drop: isProd ? ['console', 'debugger'] : [],
|
|
85
|
+
// },
|
|
86
|
+
plugins: [
|
|
87
|
+
tsconfigPaths(),
|
|
88
|
+
externalizeDeps({
|
|
89
|
+
deps: true,
|
|
90
|
+
devDeps: true,
|
|
91
|
+
peerDeps: true,
|
|
92
|
+
optionalDeps: true,
|
|
93
|
+
nodeBuiltins: true,
|
|
94
|
+
}),
|
|
95
|
+
dts({
|
|
96
|
+
include: 'src',
|
|
97
|
+
}),
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
});
|
package/dist/base64.cjs
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
function encodeBase64(input) {
|
|
4
|
-
const encoder = new TextEncoder();
|
|
5
|
-
const unit8Array = encoder.encode(input);
|
|
6
|
-
return btoa(String.fromCharCode(...unit8Array));
|
|
7
|
-
}
|
|
8
|
-
function decodeBase64(input) {
|
|
9
|
-
const decoder = new TextDecoder();
|
|
10
|
-
const unit8Array = Uint8Array.from(atob(input), (c) => c.charCodeAt(0));
|
|
11
|
-
return decoder.decode(unit8Array);
|
|
12
|
-
}
|
|
13
|
-
exports.decodeBase64 = decodeBase64;
|
|
14
|
-
exports.encodeBase64 = encodeBase64;
|
|
15
|
-
//# sourceMappingURL=base64.cjs.map
|
package/dist/base64.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"base64.cjs","sources":["../src/base64.ts"],"sourcesContent":["// @ref https://blog.csdn.net/m0_72642319/article/details/139743196\n\n/**\n * 【浏览器环境】将字符串编码为 Base64 格式\n * @param input 要编码的字符串\n * @returns 编码后的 Base64 字符串\n * @remarks\n * 在 Node.js 环境中使用 Buffer 实现,在浏览器环境中使用 TextEncoder 和 btoa 实现\n */\nexport function encodeBase64(input: string) {\n const encoder = new TextEncoder();\n const unit8Array = encoder.encode(input);\n return btoa(String.fromCharCode(...unit8Array));\n}\n\n/**\n * 【浏览器环境】 将 Base64 字符串解码为原始字符串\n * @param input 要解码的 Base64 字符串\n * @returns 解码后的原始字符串\n */\nexport function decodeBase64(input: string) {\n const decoder = new TextDecoder();\n const unit8Array = Uint8Array.from(atob(input), (c) => c.charCodeAt(0));\n return decoder.decode(unit8Array);\n}\n"],"names":[],"mappings":";;AASO,SAAS,aAAa,OAAe;AACpC,QAAA,UAAU,IAAI,YAAY;AAC1B,QAAA,aAAa,QAAQ,OAAO,KAAK;AACvC,SAAO,KAAK,OAAO,aAAa,GAAG,UAAU,CAAC;AAChD;AAOO,SAAS,aAAa,OAAe;AACpC,QAAA,UAAU,IAAI,YAAY;AAC1B,QAAA,aAAa,WAAW,KAAK,KAAK,KAAK,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAC/D,SAAA,QAAQ,OAAO,UAAU;AAClC;;;"}
|
package/dist/base64.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 【浏览器环境】将字符串编码为 Base64 格式
|
|
3
|
-
* @param input 要编码的字符串
|
|
4
|
-
* @returns 编码后的 Base64 字符串
|
|
5
|
-
* @remarks
|
|
6
|
-
* 在 Node.js 环境中使用 Buffer 实现,在浏览器环境中使用 TextEncoder 和 btoa 实现
|
|
7
|
-
*/
|
|
8
|
-
export declare function encodeBase64(input: string): string;
|
|
9
|
-
/**
|
|
10
|
-
* 【浏览器环境】 将 Base64 字符串解码为原始字符串
|
|
11
|
-
* @param input 要解码的 Base64 字符串
|
|
12
|
-
* @returns 解码后的原始字符串
|
|
13
|
-
*/
|
|
14
|
-
export declare function decodeBase64(input: string): string;
|
package/dist/base64.mjs
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
function encodeBase64(input) {
|
|
2
|
-
const encoder = new TextEncoder();
|
|
3
|
-
const unit8Array = encoder.encode(input);
|
|
4
|
-
return btoa(String.fromCharCode(...unit8Array));
|
|
5
|
-
}
|
|
6
|
-
function decodeBase64(input) {
|
|
7
|
-
const decoder = new TextDecoder();
|
|
8
|
-
const unit8Array = Uint8Array.from(atob(input), (c) => c.charCodeAt(0));
|
|
9
|
-
return decoder.decode(unit8Array);
|
|
10
|
-
}
|
|
11
|
-
export {
|
|
12
|
-
decodeBase64,
|
|
13
|
-
encodeBase64
|
|
14
|
-
};
|
|
15
|
-
//# sourceMappingURL=base64.mjs.map
|
package/dist/base64.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"base64.mjs","sources":["../src/base64.ts"],"sourcesContent":["// @ref https://blog.csdn.net/m0_72642319/article/details/139743196\n\n/**\n * 【浏览器环境】将字符串编码为 Base64 格式\n * @param input 要编码的字符串\n * @returns 编码后的 Base64 字符串\n * @remarks\n * 在 Node.js 环境中使用 Buffer 实现,在浏览器环境中使用 TextEncoder 和 btoa 实现\n */\nexport function encodeBase64(input: string) {\n const encoder = new TextEncoder();\n const unit8Array = encoder.encode(input);\n return btoa(String.fromCharCode(...unit8Array));\n}\n\n/**\n * 【浏览器环境】 将 Base64 字符串解码为原始字符串\n * @param input 要解码的 Base64 字符串\n * @returns 解码后的原始字符串\n */\nexport function decodeBase64(input: string) {\n const decoder = new TextDecoder();\n const unit8Array = Uint8Array.from(atob(input), (c) => c.charCodeAt(0));\n return decoder.decode(unit8Array);\n}\n"],"names":[],"mappings":"AASO,SAAS,aAAa,OAAe;AACpC,QAAA,UAAU,IAAI,YAAY;AAC1B,QAAA,aAAa,QAAQ,OAAO,KAAK;AACvC,SAAO,KAAK,OAAO,aAAa,GAAG,UAAU,CAAC;AAChD;AAOO,SAAS,aAAa,OAAe;AACpC,QAAA,UAAU,IAAI,YAAY;AAC1B,QAAA,aAAa,WAAW,KAAK,KAAK,KAAK,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAC/D,SAAA,QAAQ,OAAO,UAAU;AAClC;"}
|
package/dist/cache.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cache.cjs","sources":["../src/cache.ts"],"sourcesContent":["import { AbstractCache, type TCacheOptions, type TCached } from '@cloudcome/utils-core/cache';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\n\n/**\n * 使用浏览器存储(localStorage 或 sessionStorage)实现的缓存类\n * @template T - 缓存数据的类型\n */\nexport class StorageCache<T> extends AbstractCache<T> {\n /**\n * 创建一个新的 StorageCache 实例\n * @param storage - 使用的存储实现(localStorage 或 sessionStorage)\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n */\n constructor(\n readonly storage: Storage,\n readonly namespace = '',\n ) {\n super();\n }\n\n /**\n * 通过ID获取缓存数据\n * @param id - 要获取的缓存键\n * @returns 如果找到且未过期则返回缓存数据,否则返回null\n */\n get(id: string): TCached<T> | null {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n const cachedString = storage.getItem(fullId);\n if (!cachedString) return null;\n\n const cached = JSON.parse(cachedString);\n\n if (cached.createdAt + cached.maxAge < Date.now()) {\n this.del(id);\n return null;\n }\n\n return cached;\n } catch (e) {\n return null;\n }\n }\n\n /**\n * 将数据存储到缓存中\n * @param id - 存储数据使用的缓存键\n * @param data - 要缓存的数据\n * @param options - 可选的缓存配置\n * @returns 成功返回true,存储失败返回false\n */\n set(id: string, data: T, options?: TCacheOptions) {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n storage.setItem(\n fullId,\n JSON.stringify({\n id,\n data,\n createdAt: Date.now(),\n maxAge: options?.maxAge || 0,\n }),\n );\n } catch (cause) {\n //\n }\n }\n\n /**\n * 通过ID删除缓存数据\n * @param id - 要删除的缓存键\n */\n del(id: string) {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n storage.removeItem(fullId);\n } catch (cause) {\n //\n }\n }\n\n clear() {\n try {\n this.storage.clear();\n } catch (err) {\n //\n }\n }\n}\n\n/**\n * 创建一个使用 localStorage 的缓存实例\n * @template T - 缓存数据的类型\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n * @returns 使用 localStorage 的新 StorageCache 实例\n */\nexport function createLocalCache<T>(namespace?: string): AbstractCache<T> {\n return new StorageCache<T>(localStorage, namespace);\n}\n\n/**\n * 创建一个使用 sessionStorage 的缓存实例\n * @template T - 缓存数据的类型\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n * @returns 使用 sessionStorage 的新 StorageCache 实例\n */\nexport function createSessionCache<T>(namespace?: string): AbstractCache<T> {\n return new StorageCache<T>(sessionStorage, namespace);\n}\n"],"names":["AbstractCache"],"mappings":";;;AAOO,MAAM,qBAAwBA,MAAAA,cAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpD,YACW,SACA,YAAY,IACrB;AACM,UAAA;AAHG,SAAA,UAAA;AACA,SAAA,YAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUX,IAAI,IAA+B;AAC3B,UAAA,EAAE,SAAS,UAAA,IAAc;AAC/B,UAAM,SAAS,YAAY,GAAG,SAAS,IAAI,EAAE,KAAK;AAE9C,QAAA;AACI,YAAA,eAAe,QAAQ,QAAQ,MAAM;AACvC,UAAA,CAAC,aAAqB,QAAA;AAEpB,YAAA,SAAS,KAAK,MAAM,YAAY;AAEtC,UAAI,OAAO,YAAY,OAAO,SAAS,KAAK,OAAO;AACjD,aAAK,IAAI,EAAE;AACJ,eAAA;AAAA,MAAA;AAGF,aAAA;AAAA,aACA,GAAG;AACH,aAAA;AAAA,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUF,IAAI,IAAY,MAAS,SAAyB;AAC1C,UAAA,EAAE,SAAS,UAAA,IAAc;AAC/B,UAAM,SAAS,YAAY,GAAG,SAAS,IAAI,EAAE,KAAK;AAE9C,QAAA;AACM,cAAA;AAAA,QACN;AAAA,QACA,KAAK,UAAU;AAAA,UACb;AAAA,UACA;AAAA,UACA,WAAW,KAAK,IAAI;AAAA,UACpB,SAAQ,mCAAS,WAAU;AAAA,QAC5B,CAAA;AAAA,MACH;AAAA,aACO,OAAO;AAAA,IAAA;AAAA,EAEhB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOF,IAAI,IAAY;AACR,UAAA,EAAE,SAAS,UAAA,IAAc;AAC/B,UAAM,SAAS,YAAY,GAAG,SAAS,IAAI,EAAE,KAAK;AAE9C,QAAA;AACF,cAAQ,WAAW,MAAM;AAAA,aAClB,OAAO;AAAA,IAAA;AAAA,EAEhB;AAAA,EAGF,QAAQ;AACF,QAAA;AACF,WAAK,QAAQ,MAAM;AAAA,aACZ,KAAK;AAAA,IAAA;AAAA,EAEd;AAEJ;AAQO,SAAS,iBAAoB,WAAsC;AACjE,SAAA,IAAI,aAAgB,cAAc,SAAS;AACpD;AAQO,SAAS,mBAAsB,WAAsC;AACnE,SAAA,IAAI,aAAgB,gBAAgB,SAAS;AACtD;;;;"}
|
package/dist/cache.d.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { AbstractCache, TCacheOptions, TCached } from '@cloudcome/utils-core/cache';
|
|
2
|
-
/**
|
|
3
|
-
* 使用浏览器存储(localStorage 或 sessionStorage)实现的缓存类
|
|
4
|
-
* @template T - 缓存数据的类型
|
|
5
|
-
*/
|
|
6
|
-
export declare class StorageCache<T> extends AbstractCache<T> {
|
|
7
|
-
readonly storage: Storage;
|
|
8
|
-
readonly namespace: string;
|
|
9
|
-
/**
|
|
10
|
-
* 创建一个新的 StorageCache 实例
|
|
11
|
-
* @param storage - 使用的存储实现(localStorage 或 sessionStorage)
|
|
12
|
-
* @param namespace - 可选,用于为缓存键添加前缀的命名空间
|
|
13
|
-
*/
|
|
14
|
-
constructor(storage: Storage, namespace?: string);
|
|
15
|
-
/**
|
|
16
|
-
* 通过ID获取缓存数据
|
|
17
|
-
* @param id - 要获取的缓存键
|
|
18
|
-
* @returns 如果找到且未过期则返回缓存数据,否则返回null
|
|
19
|
-
*/
|
|
20
|
-
get(id: string): TCached<T> | null;
|
|
21
|
-
/**
|
|
22
|
-
* 将数据存储到缓存中
|
|
23
|
-
* @param id - 存储数据使用的缓存键
|
|
24
|
-
* @param data - 要缓存的数据
|
|
25
|
-
* @param options - 可选的缓存配置
|
|
26
|
-
* @returns 成功返回true,存储失败返回false
|
|
27
|
-
*/
|
|
28
|
-
set(id: string, data: T, options?: TCacheOptions): void;
|
|
29
|
-
/**
|
|
30
|
-
* 通过ID删除缓存数据
|
|
31
|
-
* @param id - 要删除的缓存键
|
|
32
|
-
*/
|
|
33
|
-
del(id: string): void;
|
|
34
|
-
clear(): void;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* 创建一个使用 localStorage 的缓存实例
|
|
38
|
-
* @template T - 缓存数据的类型
|
|
39
|
-
* @param namespace - 可选,用于为缓存键添加前缀的命名空间
|
|
40
|
-
* @returns 使用 localStorage 的新 StorageCache 实例
|
|
41
|
-
*/
|
|
42
|
-
export declare function createLocalCache<T>(namespace?: string): AbstractCache<T>;
|
|
43
|
-
/**
|
|
44
|
-
* 创建一个使用 sessionStorage 的缓存实例
|
|
45
|
-
* @template T - 缓存数据的类型
|
|
46
|
-
* @param namespace - 可选,用于为缓存键添加前缀的命名空间
|
|
47
|
-
* @returns 使用 sessionStorage 的新 StorageCache 实例
|
|
48
|
-
*/
|
|
49
|
-
export declare function createSessionCache<T>(namespace?: string): AbstractCache<T>;
|
package/dist/cache.mjs
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { AbstractCache } from "@cloudcome/utils-core/cache";
|
|
2
|
-
class StorageCache extends AbstractCache {
|
|
3
|
-
/**
|
|
4
|
-
* 创建一个新的 StorageCache 实例
|
|
5
|
-
* @param storage - 使用的存储实现(localStorage 或 sessionStorage)
|
|
6
|
-
* @param namespace - 可选,用于为缓存键添加前缀的命名空间
|
|
7
|
-
*/
|
|
8
|
-
constructor(storage, namespace = "") {
|
|
9
|
-
super();
|
|
10
|
-
this.storage = storage;
|
|
11
|
-
this.namespace = namespace;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* 通过ID获取缓存数据
|
|
15
|
-
* @param id - 要获取的缓存键
|
|
16
|
-
* @returns 如果找到且未过期则返回缓存数据,否则返回null
|
|
17
|
-
*/
|
|
18
|
-
get(id) {
|
|
19
|
-
const { storage, namespace } = this;
|
|
20
|
-
const fullId = namespace ? `${namespace}:${id}` : id;
|
|
21
|
-
try {
|
|
22
|
-
const cachedString = storage.getItem(fullId);
|
|
23
|
-
if (!cachedString) return null;
|
|
24
|
-
const cached = JSON.parse(cachedString);
|
|
25
|
-
if (cached.createdAt + cached.maxAge < Date.now()) {
|
|
26
|
-
this.del(id);
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
return cached;
|
|
30
|
-
} catch (e) {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* 将数据存储到缓存中
|
|
36
|
-
* @param id - 存储数据使用的缓存键
|
|
37
|
-
* @param data - 要缓存的数据
|
|
38
|
-
* @param options - 可选的缓存配置
|
|
39
|
-
* @returns 成功返回true,存储失败返回false
|
|
40
|
-
*/
|
|
41
|
-
set(id, data, options) {
|
|
42
|
-
const { storage, namespace } = this;
|
|
43
|
-
const fullId = namespace ? `${namespace}:${id}` : id;
|
|
44
|
-
try {
|
|
45
|
-
storage.setItem(
|
|
46
|
-
fullId,
|
|
47
|
-
JSON.stringify({
|
|
48
|
-
id,
|
|
49
|
-
data,
|
|
50
|
-
createdAt: Date.now(),
|
|
51
|
-
maxAge: (options == null ? void 0 : options.maxAge) || 0
|
|
52
|
-
})
|
|
53
|
-
);
|
|
54
|
-
} catch (cause) {
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* 通过ID删除缓存数据
|
|
59
|
-
* @param id - 要删除的缓存键
|
|
60
|
-
*/
|
|
61
|
-
del(id) {
|
|
62
|
-
const { storage, namespace } = this;
|
|
63
|
-
const fullId = namespace ? `${namespace}:${id}` : id;
|
|
64
|
-
try {
|
|
65
|
-
storage.removeItem(fullId);
|
|
66
|
-
} catch (cause) {
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
clear() {
|
|
70
|
-
try {
|
|
71
|
-
this.storage.clear();
|
|
72
|
-
} catch (err) {
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
function createLocalCache(namespace) {
|
|
77
|
-
return new StorageCache(localStorage, namespace);
|
|
78
|
-
}
|
|
79
|
-
function createSessionCache(namespace) {
|
|
80
|
-
return new StorageCache(sessionStorage, namespace);
|
|
81
|
-
}
|
|
82
|
-
export {
|
|
83
|
-
StorageCache,
|
|
84
|
-
createLocalCache,
|
|
85
|
-
createSessionCache
|
|
86
|
-
};
|
|
87
|
-
//# sourceMappingURL=cache.mjs.map
|
package/dist/cache.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cache.mjs","sources":["../src/cache.ts"],"sourcesContent":["import { AbstractCache, type TCacheOptions, type TCached } from '@cloudcome/utils-core/cache';\nimport type { MaybePromise } from '@cloudcome/utils-core/types';\n\n/**\n * 使用浏览器存储(localStorage 或 sessionStorage)实现的缓存类\n * @template T - 缓存数据的类型\n */\nexport class StorageCache<T> extends AbstractCache<T> {\n /**\n * 创建一个新的 StorageCache 实例\n * @param storage - 使用的存储实现(localStorage 或 sessionStorage)\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n */\n constructor(\n readonly storage: Storage,\n readonly namespace = '',\n ) {\n super();\n }\n\n /**\n * 通过ID获取缓存数据\n * @param id - 要获取的缓存键\n * @returns 如果找到且未过期则返回缓存数据,否则返回null\n */\n get(id: string): TCached<T> | null {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n const cachedString = storage.getItem(fullId);\n if (!cachedString) return null;\n\n const cached = JSON.parse(cachedString);\n\n if (cached.createdAt + cached.maxAge < Date.now()) {\n this.del(id);\n return null;\n }\n\n return cached;\n } catch (e) {\n return null;\n }\n }\n\n /**\n * 将数据存储到缓存中\n * @param id - 存储数据使用的缓存键\n * @param data - 要缓存的数据\n * @param options - 可选的缓存配置\n * @returns 成功返回true,存储失败返回false\n */\n set(id: string, data: T, options?: TCacheOptions) {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n storage.setItem(\n fullId,\n JSON.stringify({\n id,\n data,\n createdAt: Date.now(),\n maxAge: options?.maxAge || 0,\n }),\n );\n } catch (cause) {\n //\n }\n }\n\n /**\n * 通过ID删除缓存数据\n * @param id - 要删除的缓存键\n */\n del(id: string) {\n const { storage, namespace } = this;\n const fullId = namespace ? `${namespace}:${id}` : id;\n\n try {\n storage.removeItem(fullId);\n } catch (cause) {\n //\n }\n }\n\n clear() {\n try {\n this.storage.clear();\n } catch (err) {\n //\n }\n }\n}\n\n/**\n * 创建一个使用 localStorage 的缓存实例\n * @template T - 缓存数据的类型\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n * @returns 使用 localStorage 的新 StorageCache 实例\n */\nexport function createLocalCache<T>(namespace?: string): AbstractCache<T> {\n return new StorageCache<T>(localStorage, namespace);\n}\n\n/**\n * 创建一个使用 sessionStorage 的缓存实例\n * @template T - 缓存数据的类型\n * @param namespace - 可选,用于为缓存键添加前缀的命名空间\n * @returns 使用 sessionStorage 的新 StorageCache 实例\n */\nexport function createSessionCache<T>(namespace?: string): AbstractCache<T> {\n return new StorageCache<T>(sessionStorage, namespace);\n}\n"],"names":[],"mappings":";AAOO,MAAM,qBAAwB,cAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpD,YACW,SACA,YAAY,IACrB;AACM,UAAA;AAHG,SAAA,UAAA;AACA,SAAA,YAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUX,IAAI,IAA+B;AAC3B,UAAA,EAAE,SAAS,UAAA,IAAc;AAC/B,UAAM,SAAS,YAAY,GAAG,SAAS,IAAI,EAAE,KAAK;AAE9C,QAAA;AACI,YAAA,eAAe,QAAQ,QAAQ,MAAM;AACvC,UAAA,CAAC,aAAqB,QAAA;AAEpB,YAAA,SAAS,KAAK,MAAM,YAAY;AAEtC,UAAI,OAAO,YAAY,OAAO,SAAS,KAAK,OAAO;AACjD,aAAK,IAAI,EAAE;AACJ,eAAA;AAAA,MAAA;AAGF,aAAA;AAAA,aACA,GAAG;AACH,aAAA;AAAA,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUF,IAAI,IAAY,MAAS,SAAyB;AAC1C,UAAA,EAAE,SAAS,UAAA,IAAc;AAC/B,UAAM,SAAS,YAAY,GAAG,SAAS,IAAI,EAAE,KAAK;AAE9C,QAAA;AACM,cAAA;AAAA,QACN;AAAA,QACA,KAAK,UAAU;AAAA,UACb;AAAA,UACA;AAAA,UACA,WAAW,KAAK,IAAI;AAAA,UACpB,SAAQ,mCAAS,WAAU;AAAA,QAC5B,CAAA;AAAA,MACH;AAAA,aACO,OAAO;AAAA,IAAA;AAAA,EAEhB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOF,IAAI,IAAY;AACR,UAAA,EAAE,SAAS,UAAA,IAAc;AAC/B,UAAM,SAAS,YAAY,GAAG,SAAS,IAAI,EAAE,KAAK;AAE9C,QAAA;AACF,cAAQ,WAAW,MAAM;AAAA,aAClB,OAAO;AAAA,IAAA;AAAA,EAEhB;AAAA,EAGF,QAAQ;AACF,QAAA;AACF,WAAK,QAAQ,MAAM;AAAA,aACZ,KAAK;AAAA,IAAA;AAAA,EAEd;AAEJ;AAQO,SAAS,iBAAoB,WAAsC;AACjE,SAAA,IAAI,aAAgB,cAAc,SAAS;AACpD;AAQO,SAAS,mBAAsB,WAAsC;AACnE,SAAA,IAAI,aAAgB,gBAAgB,SAAS;AACtD;"}
|
package/dist/canvas.cjs
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const object = require("@cloudcome/utils-core/object");
|
|
4
|
-
const image = require("./image.cjs");
|
|
5
|
-
function canvasToBase64(canvas, type, quality) {
|
|
6
|
-
return canvas.toDataURL(type, quality);
|
|
7
|
-
}
|
|
8
|
-
async function canvasToBlob(canvas, type, quality) {
|
|
9
|
-
return new Promise((resolve, reject) => {
|
|
10
|
-
canvas.toBlob(
|
|
11
|
-
(blob) => {
|
|
12
|
-
if (blob) {
|
|
13
|
-
resolve(blob);
|
|
14
|
-
} else {
|
|
15
|
-
reject(new Error("canvas 导出二进制对象失败"));
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
type,
|
|
19
|
-
quality
|
|
20
|
-
);
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
async function canvasDrawImage(canvas, url, options) {
|
|
24
|
-
const ctx = canvas.getContext("2d");
|
|
25
|
-
if (!ctx) throw new Error("canvas context is null");
|
|
26
|
-
const img = await image.imageLoad(url);
|
|
27
|
-
const defaults = {
|
|
28
|
-
srcLeft: 0,
|
|
29
|
-
srcTop: 0,
|
|
30
|
-
srcWidth: img.width,
|
|
31
|
-
srcHeight: img.height,
|
|
32
|
-
destLeft: 0,
|
|
33
|
-
destTop: 0,
|
|
34
|
-
destWidth: canvas.width,
|
|
35
|
-
destHeight: canvas.height
|
|
36
|
-
};
|
|
37
|
-
const { srcLeft, srcTop, srcWidth, srcHeight, destLeft, destTop, destWidth, destHeight } = object.objectDefaults(
|
|
38
|
-
options || {},
|
|
39
|
-
defaults
|
|
40
|
-
);
|
|
41
|
-
ctx.drawImage(
|
|
42
|
-
img,
|
|
43
|
-
// source
|
|
44
|
-
srcLeft,
|
|
45
|
-
srcTop,
|
|
46
|
-
srcWidth,
|
|
47
|
-
srcHeight,
|
|
48
|
-
// dest
|
|
49
|
-
destLeft,
|
|
50
|
-
destTop,
|
|
51
|
-
destWidth,
|
|
52
|
-
destHeight
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
exports.canvasDrawImage = canvasDrawImage;
|
|
56
|
-
exports.canvasToBase64 = canvasToBase64;
|
|
57
|
-
exports.canvasToBlob = canvasToBlob;
|
|
58
|
-
//# sourceMappingURL=canvas.cjs.map
|
package/dist/canvas.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"canvas.cjs","sources":["../src/canvas.ts"],"sourcesContent":["import { objectDefaults } from '@cloudcome/utils-core/object';\nimport { imageLoad } from './image';\n\n/**\n * 将 Canvas 转换为 Base64 编码的字符串\n * @param {HTMLCanvasElement} canvas - 需要转换的 Canvas 元素\n * @param {string} [type] - 图片格式,默认为 'image/png'\n * @param {number} [quality] - 图片质量,范围 0 到 1,仅适用于 'image/jpeg' 或 'image/webp'\n * @returns {string} Base64 编码的图片数据\n * @example\n * const base64 = canvasToBase64(canvas, 'image/jpeg', 0.8);\n */\nexport function canvasToBase64(canvas: HTMLCanvasElement, type?: string, quality?: number) {\n return canvas.toDataURL(type, quality);\n}\n\n/**\n * 将 Canvas 转换为 Blob 对象\n * @param {HTMLCanvasElement} canvas - 需要转换的 Canvas 元素\n * @param {string} [type] - 图片格式,默认为 'image/png'\n * @param {number} [quality] - 图片质量,范围 0 到 1,仅适用于 'image/jpeg' 或 'image/webp'\n * @returns {Promise<Blob>} 返回一个包含 Blob 对象的 Promise\n * @example\n * const blob = await canvasToBlob(canvas, 'image/jpeg', 0.8);\n */\nexport async function canvasToBlob(canvas: HTMLCanvasElement, type?: string, quality?: number) {\n return new Promise<Blob>((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error('canvas 导出二进制对象失败'));\n }\n },\n type,\n quality,\n );\n });\n}\n\n/**\n * Canvas 绘制图片的配置选项\n */\nexport type CanvasDrawImageOptions = {\n /**\n * 源图片的左上角 x 坐标\n * @type {number}\n * @default 0\n */\n srcLeft?: number;\n /**\n * 源图片的左上角 y 坐标\n * @type {number}\n * @default 0\n */\n srcTop?: number;\n /**\n * 源图片的宽度\n * @type {number}\n * @default 图片的原始宽度\n */\n srcWidth?: number;\n /**\n * 源图片的高度\n * @type {number}\n * @default 图片的原始高度\n */\n srcHeight?: number;\n\n /**\n * 目标 Canvas 的左上角 x 坐标\n * @type {number}\n * @default 0\n */\n destLeft?: number;\n /**\n * 目标 Canvas 的左上角 y 坐标\n * @type {number}\n * @default 0\n */\n destTop?: number;\n /**\n * 目标 Canvas 的宽度\n * @type {number}\n * @default Canvas 的宽度\n */\n destWidth?: number;\n /**\n * 目标 Canvas 的高度\n * @type {number}\n * @default Canvas 的高度\n */\n destHeight?: number;\n};\n\n/**\n * 在 Canvas 上绘制图片\n * @param {HTMLCanvasElement} canvas - 目标 Canvas 元素\n * @param {string} url - 图片的 URL\n * @param {CanvasDrawImageOptions} [options] - 绘制图片的配置选项\n * @returns {Promise<void>} 返回一个 Promise,表示绘制完成\n * @example\n * await canvasDrawImage(canvas, 'https://example.com/image.png', {\n * srcLeft: 10,\n * srcTop: 10,\n * srcWidth: 100,\n * srcHeight: 100,\n * destLeft: 0,\n * destTop: 0,\n * destWidth: 200,\n * destHeight: 200\n * });\n */\nexport async function canvasDrawImage(canvas: HTMLCanvasElement, url: string, options?: CanvasDrawImageOptions) {\n const ctx = canvas.getContext('2d');\n if (!ctx) throw new Error('canvas context is null');\n\n const img = await imageLoad(url);\n const defaults: CanvasDrawImageOptions = {\n srcLeft: 0,\n srcTop: 0,\n srcWidth: img.width,\n srcHeight: img.height,\n destLeft: 0,\n destTop: 0,\n destWidth: canvas.width,\n destHeight: canvas.height,\n };\n const { srcLeft, srcTop, srcWidth, srcHeight, destLeft, destTop, destWidth, destHeight } = objectDefaults(\n options || {},\n defaults,\n ) as Required<CanvasDrawImageOptions>;\n ctx.drawImage(\n img,\n // source\n srcLeft,\n srcTop,\n srcWidth,\n srcHeight,\n // dest\n destLeft,\n destTop,\n destWidth,\n destHeight,\n );\n}\n"],"names":["imageLoad","objectDefaults"],"mappings":";;;;AAYgB,SAAA,eAAe,QAA2B,MAAe,SAAkB;AAClF,SAAA,OAAO,UAAU,MAAM,OAAO;AACvC;AAWsB,eAAA,aAAa,QAA2B,MAAe,SAAkB;AAC7F,SAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AACrC,WAAA;AAAA,MACL,CAAC,SAAS;AACR,YAAI,MAAM;AACR,kBAAQ,IAAI;AAAA,QAAA,OACP;AACE,iBAAA,IAAI,MAAM,kBAAkB,CAAC;AAAA,QAAA;AAAA,MAExC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EAAA,CACD;AACH;AA2EsB,eAAA,gBAAgB,QAA2B,KAAa,SAAkC;AACxG,QAAA,MAAM,OAAO,WAAW,IAAI;AAClC,MAAI,CAAC,IAAW,OAAA,IAAI,MAAM,wBAAwB;AAE5C,QAAA,MAAM,MAAMA,MAAA,UAAU,GAAG;AAC/B,QAAM,WAAmC;AAAA,IACvC,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU,IAAI;AAAA,IACd,WAAW,IAAI;AAAA,IACf,UAAU;AAAA,IACV,SAAS;AAAA,IACT,WAAW,OAAO;AAAA,IAClB,YAAY,OAAO;AAAA,EACrB;AACM,QAAA,EAAE,SAAS,QAAQ,UAAU,WAAW,UAAU,SAAS,WAAW,WAAA,IAAeC,OAAA;AAAA,IACzF,WAAW,CAAC;AAAA,IACZ;AAAA,EACF;AACI,MAAA;AAAA,IACF;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;;"}
|