big updat:

- update dependencies
- add webp support and webp conversion for profile images
This commit is contained in:
olcxja 2026-07-02 22:40:46 +02:00
commit 95aaaa69ea
244 changed files with 121382 additions and 86 deletions

76
node_modules/super-image-cropper/esm/index.d.ts generated vendored Normal file
View file

@ -0,0 +1,76 @@
import type Cropper from 'cropperjs';
export interface CustomCropper extends Cropper {
url: '';
cropBoxData: Cropper.ImageData;
canvasData: Cropper.ImageData;
cropper?: HTMLDivElement;
}
export declare enum OutputType {
BASE64 = "base64",
BLOB = "blob",
BLOB_URL = "blobURL"
}
export type IOutputTypeUnion = `${OutputType}`;
export interface ICropperOptions {
cropperInstance?: CustomCropper | Cropper;
src?: string;
crossOrigin?: '' | 'anonymous' | 'use-credentials';
cropperJsOpts?: ICropOpts;
gifJsOptions?: IGifOpts;
outputType?: IOutputTypeUnion;
}
export interface IGifOpts {
repeat?: number;
quality?: number;
workers?: number;
workerScript?: string;
background?: string;
width?: number;
height?: number;
transparent?: string | null;
dither?: boolean;
debug?: boolean;
}
export interface ICropOpts {
width?: number;
height?: number;
scaleX?: number;
scaleY?: number;
x?: number;
y?: number;
background?: string;
rotate?: number;
left?: number;
top?: number;
}
export interface IImageData {
width: number;
height: number;
naturalWidth: number;
naturalHeight: number;
}
export interface ICommonCropOptions {
cropperJsOpts: Required<ICropOpts>;
imageData: IImageData;
cropBoxData: Cropper.CropBoxData;
}
export declare class SuperImageCropper {
private cropperJsInstance?;
private parsedFrameInfo;
private commonCropOptions;
private frameCropperInstance;
private inputCropperOptions;
private imageTypeInfo;
crop(inputCropperOptions: ICropperOptions): Promise<string | Blob>;
private init;
private cleanUserInput;
private userInputValidator;
private normalizeRotate;
private imageDataFormat;
private decodeGIF;
private ensureFrameCropperExist;
private cropFrames;
private saveGif;
private checkIsStaticImage;
private handleStaticImage;
}

2
node_modules/super-image-cropper/esm/index.js generated vendored Normal file
View file

@ -0,0 +1,2 @@
import{Decoder as t}from"./lib/decoder.js";import{SyntheticGIF as e}from"./lib/synthetic-gif.js";import{FrameCropper as r}from"./lib/cropper.js";import{getImageInfo as s,loadImage as i}from"./lib/helper.js";var o;!function(t){t.BASE64="base64",t.BLOB="blob",t.BLOB_URL="blobURL"}(o||(o={}));class p{cropperJsInstance;parsedFrameInfo;commonCropOptions;frameCropperInstance;inputCropperOptions;imageTypeInfo=null;async crop(t){this.userInputValidator(t),this.inputCropperOptions=this.cleanUserInput(t),await this.init(),await this.decodeGIF();const e=await this.checkIsStaticImage();if(e.isStatic)return this.handleStaticImage(e.imageInfo.imageInstance);{const t=await this.cropFrames();return this.saveGif(t,this.parsedFrameInfo?.delays||[])}}async init(){this.cropperJsInstance=this.inputCropperOptions.cropperInstance;const t=Object.assign({width:100,height:100,scaleX:1,scaleY:1,x:0,y:0,rotate:0,left:0,top:0},this.inputCropperOptions.cropperJsOpts||{},this.cropperJsInstance?.getData()||{}),e=this.cropperJsInstance?.getImageData()||await s({src:this.inputCropperOptions.src,crossOrigin:this.inputCropperOptions.crossOrigin})||{};this.commonCropOptions={cropperJsOpts:this.imageDataFormat(t,e),imageData:e,cropBoxData:this.cropperJsInstance?.getCropBoxData()||t},this.commonCropOptions.cropperJsOpts.rotate=this.normalizeRotate(this.commonCropOptions.cropperJsOpts.rotate)}cleanUserInput(t){const{cropperInstance:e}=t;return e&&(delete t.cropperJsOpts,delete t.src),t}userInputValidator(t){const{cropperInstance:e,cropperJsOpts:r,src:s}=t;if(!e){if(!r)throw new Error("If cropperInstance is not specified, cropperJsOpts must be specified.");if(!s)throw new Error("If cropperInstance is not specified, src must be specified.")}}normalizeRotate(t){return t<0?360+t%360:t}imageDataFormat(t,e){return t.left=t.x,t.top=t.y,t.width=t.width||e.naturalWidth,t.height=t.height||e.naturalHeight,t}async decodeGIF(){const e=new t(this.inputCropperOptions.src||this.cropperJsInstance?.url||""),r=await e.decompressFrames();this.parsedFrameInfo=r}ensureFrameCropperExist(){this.frameCropperInstance||(this.frameCropperInstance=new r({commonCropOptions:this.commonCropOptions}))}async cropFrames(){return this.ensureFrameCropperExist(),this.frameCropperInstance.init({commonCropOptions:this.commonCropOptions}),this.frameCropperInstance.cropGif(this.parsedFrameInfo)}async saveGif(t,r){return new e({frames:t,commonCropOptions:this.commonCropOptions,frameDelays:r,gifJsOptions:this.inputCropperOptions.gifJsOptions,outputType:this.inputCropperOptions.outputType}).bootstrap()}async checkIsStaticImage(){const t=this.cropperJsInstance?.url??this.inputCropperOptions?.src,e=await i({src:t,crossOrigin:this.inputCropperOptions.crossOrigin});return{isStatic:"image/gif"!==e?.imageType?.mime,imageInfo:e}}async handleStaticImage(t){const e=document.createElement("canvas"),r=e.getContext("2d");e.width=t.width,e.height=t.height,r?.drawImage(t,0,0),this.ensureFrameCropperExist(),this.frameCropperInstance.init({commonCropOptions:this.commonCropOptions});const s=await this.frameCropperInstance.cropStaticImage(e);return r?.clearRect(0,0,e.width,e.height),e.width=s.width,e.height=s.height,r?.putImageData(s,0,0),new Promise(((t,r)=>{const{outputType:s=o.BLOB_URL}=this.inputCropperOptions;s===o.BASE64?t(e.toDataURL(this.imageTypeInfo?.mime)):e.toBlob((e=>{if(!e)return r(null);if(s===o.BLOB)t(e);else{const r=window.URL.createObjectURL(e);t(r)}}),this.imageTypeInfo?.mime)}))}}export{o as OutputType,p as SuperImageCropper};
//# sourceMappingURL=index.js.map

1
node_modules/super-image-cropper/esm/index.js.map generated vendored Normal file
View file

@ -0,0 +1 @@
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}

31
node_modules/super-image-cropper/esm/lib/cropper.d.ts generated vendored Normal file
View file

@ -0,0 +1,31 @@
import { ICommonCropOptions } from '../index';
import type { IParsedFrameInfo } from './decoder';
export interface IFrameCropperProps {
commonCropOptions: ICommonCropOptions;
}
export declare class FrameCropper {
private frames;
private parsedFrames;
private commonCropOptions;
private convertorCanvas;
private containerCanvas;
private convertCtx;
private containerCtx;
private cropperJsOpts;
private offsetX;
private offsetY;
private containerCenterX;
private containerCenterY;
private resultFrames;
constructor(props: IFrameCropperProps);
init({ commonCropOptions }: IFrameCropperProps): void;
cropGif(parsedFrameInfo: IParsedFrameInfo): Promise<ImageData[]>;
cropStaticImage(canvasImageContainer: HTMLCanvasElement): ImageData;
private transformFrame;
private drawImgDataToCanvas;
private ifDebugRun;
private renderEachFrame;
private setupCanvas;
private setCanvasWH;
private frameToImgData;
}

2
node_modules/super-image-cropper/esm/lib/cropper.js generated vendored Normal file
View file

@ -0,0 +1,2 @@
class t{frames;parsedFrames;commonCropOptions;convertorCanvas;containerCanvas;convertCtx;containerCtx;cropperJsOpts;offsetX=0;offsetY=0;containerCenterX=0;containerCenterY=0;resultFrames=[];constructor(t){this.init(t)}init({commonCropOptions:t}){this.commonCropOptions=t,this.cropperJsOpts=t.cropperJsOpts,this.resultFrames=[],this.containerCanvas&&this.convertorCanvas||this.setupCanvas(),this.setCanvasWH()}async cropGif(t){const{frames:s,parsedFrames:e}=t;this.frames=s,this.parsedFrames=e;let a=0;for(;a<this.frames.length;){const t=this.frames[a];if(1!==this.parsedFrames[a].disposalType&&this.containerCtx.clearRect(0,0,this.containerCanvas.width,this.containerCanvas.height),this.containerCtx.globalCompositeOperation&&this.cropperJsOpts?.background&&(this.containerCtx.fillStyle=this.cropperJsOpts?.background||"",this.containerCtx.globalCompositeOperation="destination-over",this.containerCtx.fillRect(0,0,this.containerCanvas.width,this.containerCanvas.height),this.containerCtx.globalCompositeOperation="source-over"),!t)continue;const s=this.transformFrame(this.drawImgDataToCanvas(t,a));this.resultFrames.push(s),this.ifDebugRun(s,a),a++}return this.resultFrames}cropStaticImage(t){return this.transformFrame(t)}transformFrame(t){this.containerCtx.save(),this.containerCtx.translate(this.containerCenterX,this.containerCenterY),this.containerCtx.rotate(this.cropperJsOpts.rotate*Math.PI/180),this.containerCtx.scale(this.cropperJsOpts.scaleX,this.cropperJsOpts.scaleY),this.containerCtx.drawImage(t,-this.convertorCanvas.width/2,-this.convertorCanvas.height/2),this.containerCtx.restore();return this.containerCtx.getImageData(1*this.cropperJsOpts.x+this.offsetX,1*this.cropperJsOpts.y+this.offsetY,this.cropperJsOpts.width,this.cropperJsOpts.height)}drawImgDataToCanvas(t,s){const e=this.parsedFrames[s]?.dims;return this.convertCtx.clearRect(0,0,this.convertorCanvas.width,this.convertorCanvas.height),this.convertCtx.putImageData(t,e.left,e.top),this.convertorCanvas}ifDebugRun(t,s){location.search.includes("isCropDebug=true")&&s&&this.renderEachFrame(t,s)}renderEachFrame(t,s){const e=this.parsedFrames[s]?.dims,a=document.createElement("canvas");a.width=this.convertorCanvas.width,a.height=this.convertorCanvas.height;const r=a.getContext("2d");r&&(r?.putImageData(t,e.left,e.top),r.fillStyle="red",r.strokeStyle="blue",r.lineWidth=5,r.save(),r.beginPath(),r.font="70px orbitron",r.fillText(String(s),10,50),r.restore(),r.closePath(),document.body.appendChild(a))}setupCanvas(){const t=this.containerCanvas=document.createElement("canvas"),s=this.convertorCanvas=document.createElement("canvas");t.className="containerCanvas",s.className="convertorCanvas",t.style.display="none",s.style.display="none";const e=t.getContext("2d",{willReadFrequently:!0}),a=s.getContext("2d");e&&(this.containerCtx=e),a&&(this.convertCtx=a),document.body.appendChild(s),document.body.appendChild(t)}setCanvasWH(){Math.PI,this.cropperJsOpts.rotate;const t=this.commonCropOptions.imageData,s=t.naturalWidth,e=t.naturalHeight;this.offsetX=-Math.min(this.cropperJsOpts.x,0),this.offsetY=-Math.min(this.cropperJsOpts.y,0),this.containerCenterX=this.offsetX+s/2,this.containerCenterY=this.offsetY+e/2,this.containerCanvas.width=Math.max(this.offsetX+s,this.offsetX+this.cropperJsOpts.width,this.cropperJsOpts.x+this.cropperJsOpts.width),this.containerCanvas.height=Math.max(this.offsetY+e,this.offsetY+this.cropperJsOpts.height,this.cropperJsOpts.y+this.cropperJsOpts.height),this.convertorCanvas.width=t.naturalWidth,this.convertorCanvas.height=t.naturalHeight,this.containerCtx.clearRect(0,0,this.containerCanvas.width,this.containerCanvas.height),this.convertCtx.clearRect(0,0,this.convertorCanvas.width,this.convertorCanvas.height)}frameToImgData(t,s){if(!t)return;const e=s.pixels.length,a=t.createImageData(s.dims.width,s.dims.height),r=a.data;for(let t=0;t<e;t++){const e=4*t,a=s.pixels[t],n=s.colorTable[a];r[e]=n[0],r[e+1]=n[1],r[e+2]=n[2],r[e+3]=a!==s.transparentIndex?255:0}return a}}export{t as FrameCropper};
//# sourceMappingURL=cropper.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"cropper.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}

38
node_modules/super-image-cropper/esm/lib/decoder.d.ts generated vendored Normal file
View file

@ -0,0 +1,38 @@
import { ParsedGif, ParsedFrame } from 'gifuct-js';
import { GetArrTypeUnion } from './helper';
export type IFrames = Pick<ParsedGif, 'frames'>['frames'];
export type IFrame = GetArrTypeUnion<IFrames>;
export interface IParsedFrameInfo {
frames: ImageData[];
delays: number[];
parsedFrames: ParsedFrame[];
}
export declare class Decoder {
private url;
private parseGIF;
constructor(url: string);
decode(): Promise<ParsedGif>;
decompressFrames(): Promise<IParsedFrameInfo>;
/**
* Validates and fixes frames that have lost pixels.
* @param gif
*/
private validateAndFixFrame;
/**
* Generates ImageData objects from parsed frames.
* @param frames
*/
private generate2ImageData;
/**
* Generates ImageData objects from frames with modified pixels.
* @param frames
*/
private generate2ImageDataWithPixelsModified;
/**
* @param {string} url
* @returns
*/
private fetchImageData;
private handlePixels;
private putPixels;
}

2
node_modules/super-image-cropper/esm/lib/decoder.js generated vendored Normal file
View file

@ -0,0 +1,2 @@
import{parseGIF as e,decompressFrames as t}from"gifuct-js";class a{url;parseGIF;constructor(e){this.url=e}async decode(){const t=await this.fetchImageData(this.url);return this.parseGIF=e(t),this.validateAndFixFrame(this.parseGIF),this.parseGIF}async decompressFrames(){this.parseGIF||await this.decode();const e=await t(this.parseGIF,!0);return{frames:this.generate2ImageData(e),delays:e.map((e=>e.delay)),parsedFrames:e}}validateAndFixFrame=e=>{let t=null;for(const a of e.frames)t=a.gce?a.gce:t,"image"in a&&!("gce"in a)&&(a.gce=t)};generate2ImageData(e){return e.map((e=>{const t=e?.dims,a=new ImageData(t.width,t.height);return a.data.set(e.patch),a}))}generate2ImageDataWithPixelsModified(e,t){return e.map(((e,a)=>{t[a];const r=this.parseGIF.lsd,s=new ImageData(r.width,r.height);return s.data.set(new Uint8ClampedArray(e)),s}))}fetchImageData(e){return new Promise(((t,a)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.responseType="arraybuffer",r.onload=e=>{if(!(e.target instanceof XMLHttpRequest))return;if(200!==e.target.status&&304!==e.target.status)return void a("Status Error: "+e.target.status);let r=e.target.response;r.toString().indexOf("ArrayBuffer")>0&&(r=new Uint8Array(r)),t(r)},r.onerror=e=>{a(e)},r.send()}))}handlePixels(e){const t=this.parseGIF.lsd,a=t.width*t.height*4,r=[];for(let s=0;s<e.length;++s){const i=e[s],n=0===s||2===e[s-1].disposalType?new Uint8ClampedArray(a):r[s-1].slice();r.push(this.putPixels(n,i,t))}return r}putPixels(e,t,a){if(!t.dims)return e;const{width:r,height:s,top:i,left:n}=t.dims,o=i*a.width+n;for(let i=0;i<s;i++)for(let s=0;s<r;s++){const n=i*r+s,d=t.pixels[n],h=o+i*a.width+s,l=t.colorTable[d]||[0,0,0];d===t.transparentIndex?(e[4*h]=0,e[4*h+1]=0,e[4*h+2]=0,e[4*h+3]=0):(e[4*h]=l[0],e[4*h+1]=l[1],e[4*h+2]=l[2],e[4*h+3]=255)}return e}}export{a as Decoder};
//# sourceMappingURL=decoder.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"decoder.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}

20
node_modules/super-image-cropper/esm/lib/helper.d.ts generated vendored Normal file
View file

@ -0,0 +1,20 @@
import { IImageData } from '../index';
export type GetArrTypeUnion<T extends any[]> = T extends (infer I)[] ? I : never;
export type IImageLoadData = {
imageInstance: HTMLImageElement;
data: Event;
imageType: IImageTypeInfo | null;
};
export interface IImageTypeInfo {
ext: string;
mime: string;
}
export interface IGetImageParams {
src?: string;
crossOrigin?: '' | 'anonymous' | 'use-credentials';
}
export declare const getImageInfo: (params: IGetImageParams) => Promise<IImageData>;
export declare const getImageType: (imageBufferData: ArrayBuffer) => Promise<IImageTypeInfo | null>;
export declare const loadImage: (params: IGetImageParams) => Promise<IImageLoadData>;
export declare const transformImageData2ArrayBuffer: (image: HTMLImageElement) => ArrayBufferLike;
export declare const getImageBufferFromRemote: (url?: string) => Promise<ArrayBuffer>;

2
node_modules/super-image-cropper/esm/lib/helper.js generated vendored Normal file
View file

@ -0,0 +1,2 @@
import t from"image-type";const n=async t=>{const{src:n=""}=t;if(!n)return{width:0,height:0,naturalWidth:0,naturalHeight:0};const{imageInstance:a}=await e(t);return{width:a.width,height:a.height,naturalWidth:a.naturalWidth,naturalHeight:a.naturalHeight}},a=async n=>t(new Uint8Array(n)),e=async t=>{const{src:n="",crossOrigin:e}=t;return{...await new Promise(((t,a)=>{const r=new Image;void 0!==e&&(r.crossOrigin=e),r.onload=async n=>{t({imageInstance:r,data:n})},r.src=n,r.onerror=a})),imageType:await a(await r(n))}},r=(t="")=>new Promise(((n,a)=>{const e=new XMLHttpRequest;e.open("GET",t),e.responseType="arraybuffer",e.onload=()=>{n(e.response)},e.onerror=a,e.send()}));export{r as getImageBufferFromRemote,n as getImageInfo,a as getImageType,e as loadImage};
//# sourceMappingURL=helper.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"helper.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}

View file

@ -0,0 +1,19 @@
import { ICommonCropOptions, ICropperOptions } from '../index';
import { IOutputTypeUnion } from '../index';
export interface IFrameCropperProps {
commonCropOptions: ICommonCropOptions;
frames: ImageData[];
frameDelays: number[];
gifJsOptions?: ICropperOptions['gifJsOptions'];
outputType?: IOutputTypeUnion;
}
export declare class SyntheticGIF {
private cropperJsOpts;
private frames;
private frameDelays;
private gifJsOptions;
private outputType;
constructor({ frames, commonCropOptions, frameDelays, gifJsOptions, outputType }: IFrameCropperProps);
bootstrap(): Promise<string | Blob>;
private convertBlob2Base64;
}

View file

@ -0,0 +1,2 @@
import{transformToUrl as t}from"gif-build-worker-js";import s from"gif.js";import{OutputType as e}from"../index.js";class r{cropperJsOpts;frames;frameDelays;gifJsOptions;outputType;constructor({frames:t,commonCropOptions:s,frameDelays:e,gifJsOptions:r={},outputType:o}){this.cropperJsOpts=s.cropperJsOpts,this.frames=t,this.frameDelays=e,this.gifJsOptions=r,this.outputType=o}bootstrap(){return new Promise(((r,o)=>{const i=t(),p=Object.assign({workers:2,quality:10,workerScript:i,width:this.cropperJsOpts.width,height:this.cropperJsOpts.height,transparent:"transparent"},this.gifJsOptions||{}),a=new s(p);a.on("finished",(t=>{if(this.outputType===e.BLOB)r(t);else if(this.outputType===e.BASE64)r(this.convertBlob2Base64(t));else{const s=window.URL.createObjectURL(t);r(s)}})),this.frames.forEach(((t,s)=>{a.addFrame(t,{delay:this.frameDelays[s],copy:!0})})),a.render()}))}convertBlob2Base64(t){return new Promise(((s,e)=>{const r=new FileReader;r.onload=function(t){s(t?.target?.result)},r.onerror=t=>{e(t)},r.readAsDataURL(t)}))}}export{r as SyntheticGIF};
//# sourceMappingURL=synthetic-gif.js.map

View file

@ -0,0 +1 @@
{"version":3,"file":"synthetic-gif.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}

View file

@ -0,0 +1 @@
export declare const renderImageData2Canvas: (imageData: ImageData) => void;

11
node_modules/super-image-cropper/esm/utils/index.js generated vendored Normal file
View file

@ -0,0 +1,11 @@
export const renderImageData2Canvas = (imageData) => {
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
const targetCanvas = document.createElement('canvas');
const targetCtx = targetCanvas.getContext('2d');
document.body.appendChild(targetCanvas);
tempCanvas.width = imageData.width;
tempCanvas.height = imageData.height;
tempCtx?.putImageData(imageData, 0, 0);
targetCtx?.drawImage(tempCanvas, 0, 0);
};