@codingame/monaco-vscode-image-resize-service-override 20.0.0
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/index.d.ts
ADDED
package/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
import '@codingame/monaco-vscode-api/vscode/vs/editor/standalone/browser/standaloneServices';
|
|
3
|
+
import { ImageResizeService } from './vscode/src/vs/platform/imageResize/browser/imageResizeService.js';
|
|
4
|
+
import { IImageResizeService } from '@codingame/monaco-vscode-api/vscode/vs/platform/imageResize/common/imageResizeService.service';
|
|
5
|
+
import { SyncDescriptor } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/descriptors';
|
|
6
|
+
|
|
7
|
+
function getServiceOverride() {
|
|
8
|
+
return {
|
|
9
|
+
[IImageResizeService.toString()]: new SyncDescriptor(ImageResizeService, [], true)
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { getServiceOverride as default };
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codingame/monaco-vscode-image-resize-service-override",
|
|
3
|
+
"version": "20.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "VSCode public API plugged on the monaco editor - image-resize service-override",
|
|
6
|
+
"keywords": [],
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "CodinGame",
|
|
9
|
+
"url": "http://www.codingame.com"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+ssh://git@github.com/CodinGame/monaco-vscode-api.git"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@codingame/monaco-vscode-api": "20.0.0"
|
|
19
|
+
},
|
|
20
|
+
"main": "index.js",
|
|
21
|
+
"module": "index.js",
|
|
22
|
+
"types": "index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"default": "./index.js"
|
|
26
|
+
},
|
|
27
|
+
"./vscode/*.css": {
|
|
28
|
+
"default": "./vscode/src/*.css"
|
|
29
|
+
},
|
|
30
|
+
"./vscode/*": {
|
|
31
|
+
"types": "./vscode/src/*.d.ts",
|
|
32
|
+
"default": "./vscode/src/*.js"
|
|
33
|
+
},
|
|
34
|
+
"./*": {
|
|
35
|
+
"types": "./*.d.ts",
|
|
36
|
+
"default": "./*.js"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"typesVersions": {
|
|
40
|
+
"*": {
|
|
41
|
+
"vscode/*": [
|
|
42
|
+
"./vscode/src/*.d.ts"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { URI } from "@codingame/monaco-vscode-api/vscode/vs/base/common/uri";
|
|
2
|
+
import { IFileService } from "@codingame/monaco-vscode-api/vscode/vs/platform/files/common/files.service";
|
|
3
|
+
import { ILogService } from "@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service";
|
|
4
|
+
import { IImageResizeService } from "@codingame/monaco-vscode-api/vscode/vs/platform/imageResize/common/imageResizeService.service";
|
|
5
|
+
export declare class ImageResizeService implements IImageResizeService {
|
|
6
|
+
readonly _serviceBrand: undefined;
|
|
7
|
+
resizeImage(data: Uint8Array | string, mimeType?: string): Promise<Uint8Array>;
|
|
8
|
+
convertStringToUInt8Array(data: string): Uint8Array;
|
|
9
|
+
convertUint8ArrayToString(data: Uint8Array): string;
|
|
10
|
+
isValidBase64(str: string): boolean;
|
|
11
|
+
createFileForMedia(fileService: IFileService, imagesFolder: URI, dataTransfer: Uint8Array, mimeType: string): Promise<URI | undefined>;
|
|
12
|
+
cleanupOldImages(fileService: IFileService, logService: ILogService, imagesFolder: URI): Promise<void>;
|
|
13
|
+
getTimestampFromFilename(filename: string): number | undefined;
|
|
14
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
|
|
2
|
+
import { createElement } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/dom';
|
|
3
|
+
import { decodeBase64, VSBuffer } from '@codingame/monaco-vscode-api/vscode/vs/base/common/buffer';
|
|
4
|
+
import { joinPath } from '@codingame/monaco-vscode-api/vscode/vs/base/common/resources';
|
|
5
|
+
import '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/extensions';
|
|
6
|
+
import '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation';
|
|
7
|
+
|
|
8
|
+
class ImageResizeService {
|
|
9
|
+
async resizeImage(data, mimeType) {
|
|
10
|
+
const isGif = mimeType === 'image/gif';
|
|
11
|
+
if (typeof data === 'string') {
|
|
12
|
+
data = this.convertStringToUInt8Array(data);
|
|
13
|
+
}
|
|
14
|
+
return ( new Promise((resolve, reject) => {
|
|
15
|
+
const blob = ( new Blob([data], { type: mimeType }));
|
|
16
|
+
const img = ( new Image());
|
|
17
|
+
const url = URL.createObjectURL(blob);
|
|
18
|
+
img.src = url;
|
|
19
|
+
img.onload = () => {
|
|
20
|
+
URL.revokeObjectURL(url);
|
|
21
|
+
let { width, height } = img;
|
|
22
|
+
if ((width <= 768 || height <= 768) && !isGif) {
|
|
23
|
+
resolve(data);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (width > 2048 || height > 2048) {
|
|
27
|
+
const scaleFactor = 2048 / Math.max(width, height);
|
|
28
|
+
width = Math.round(width * scaleFactor);
|
|
29
|
+
height = Math.round(height * scaleFactor);
|
|
30
|
+
}
|
|
31
|
+
const scaleFactor = 768 / Math.min(width, height);
|
|
32
|
+
width = Math.round(width * scaleFactor);
|
|
33
|
+
height = Math.round(height * scaleFactor);
|
|
34
|
+
const canvas = createElement('canvas');
|
|
35
|
+
canvas.width = width;
|
|
36
|
+
canvas.height = height;
|
|
37
|
+
const ctx = canvas.getContext('2d');
|
|
38
|
+
if (ctx) {
|
|
39
|
+
ctx.drawImage(img, 0, 0, width, height);
|
|
40
|
+
const jpegTypes = ['image/jpeg', 'image/jpg'];
|
|
41
|
+
const outputMimeType = mimeType && jpegTypes.includes(mimeType) ? 'image/jpeg' : 'image/png';
|
|
42
|
+
canvas.toBlob(blob => {
|
|
43
|
+
if (blob) {
|
|
44
|
+
const reader = ( new FileReader());
|
|
45
|
+
reader.onload = () => {
|
|
46
|
+
resolve(( new Uint8Array(reader.result)));
|
|
47
|
+
};
|
|
48
|
+
reader.onerror = (error) => reject(error);
|
|
49
|
+
reader.readAsArrayBuffer(blob);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
reject(( new Error('Failed to create blob from canvas')));
|
|
53
|
+
}
|
|
54
|
+
}, outputMimeType);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
reject(( new Error('Failed to get canvas context')));
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
img.onerror = (error) => {
|
|
61
|
+
URL.revokeObjectURL(url);
|
|
62
|
+
reject(error);
|
|
63
|
+
};
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
convertStringToUInt8Array(data) {
|
|
67
|
+
const base64Data = data.includes(',') ? data.split(',')[1] : data;
|
|
68
|
+
if (this.isValidBase64(base64Data)) {
|
|
69
|
+
return decodeBase64(base64Data).buffer;
|
|
70
|
+
}
|
|
71
|
+
return ( new TextEncoder()).encode(data);
|
|
72
|
+
}
|
|
73
|
+
convertUint8ArrayToString(data) {
|
|
74
|
+
try {
|
|
75
|
+
const decoder = ( new TextDecoder());
|
|
76
|
+
const decodedString = decoder.decode(data);
|
|
77
|
+
return decodedString;
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return '';
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
isValidBase64(str) {
|
|
84
|
+
try {
|
|
85
|
+
decodeBase64(str);
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async createFileForMedia(fileService, imagesFolder, dataTransfer, mimeType) {
|
|
93
|
+
const exists = await fileService.exists(imagesFolder);
|
|
94
|
+
if (!exists) {
|
|
95
|
+
await fileService.createFolder(imagesFolder);
|
|
96
|
+
}
|
|
97
|
+
const ext = mimeType.split('/')[1] || 'png';
|
|
98
|
+
const filename = `image-${Date.now()}.${ext}`;
|
|
99
|
+
const fileUri = joinPath(imagesFolder, filename);
|
|
100
|
+
const buffer = VSBuffer.wrap(dataTransfer);
|
|
101
|
+
await fileService.writeFile(fileUri, buffer);
|
|
102
|
+
return fileUri;
|
|
103
|
+
}
|
|
104
|
+
async cleanupOldImages(fileService, logService, imagesFolder) {
|
|
105
|
+
const exists = await fileService.exists(imagesFolder);
|
|
106
|
+
if (!exists) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const duration = 7 * 24 * 60 * 60 * 1000;
|
|
110
|
+
const files = await fileService.resolve(imagesFolder);
|
|
111
|
+
if (!files.children) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
await Promise.all(( files.children.map(async (file) => {
|
|
115
|
+
try {
|
|
116
|
+
const timestamp = this.getTimestampFromFilename(file.name);
|
|
117
|
+
if (timestamp && (Date.now() - timestamp > duration)) {
|
|
118
|
+
await fileService.del(file.resource);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
logService.error('Failed to clean up old images', err);
|
|
123
|
+
}
|
|
124
|
+
})));
|
|
125
|
+
}
|
|
126
|
+
getTimestampFromFilename(filename) {
|
|
127
|
+
const match = filename.match(/image-(\d+)\./);
|
|
128
|
+
if (match) {
|
|
129
|
+
return parseInt(match[1], 10);
|
|
130
|
+
}
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export { ImageResizeService };
|