diff --git a/package.json b/package.json index cdc99cf0..175f8975 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@editorjs/image", - "version": "2.10.2", + "version": "2.10.3", "keywords": [ "codex editor", "image", @@ -25,10 +25,12 @@ }, "scripts": { "dev": "concurrently \"vite\" \"node ./dev/server.js\"", - "build": "vite build", - "lint": "eslint", - "lint:errors": "eslint --quiet", - "lint:fix": "eslint --fix" + "build": "vite build && tsc --emitDeclarationOnly", + "lint": "eslint ./src --ext .ts", + "lint:errors": "eslint ./src --ext .ts --quiet", + "lint:fix": "eslint ./src --ext .ts --fix", + "type-check": "tsc --noEmit", + "type-check:watch": "tsc --noEmit --watch" }, "author": { "name": "CodeX", diff --git a/src/index.ts b/src/index.ts index c35f436b..64038bc9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,16 +29,46 @@ */ import type { TunesMenuConfig } from '@editorjs/editorjs/types/tools'; -import type { API, ToolboxConfig, PasteConfig, BlockToolConstructorOptions, BlockTool, BlockAPI, PasteEvent, PatternPasteEventDetail, FilePasteEventDetail } from '@editorjs/editorjs'; +import type { + API, + ToolboxConfig, + PasteConfig, + BlockToolConstructorOptions, + BlockTool, + BlockAPI, + PasteEvent, + PatternPasteEventDetail, + FilePasteEventDetail, +} from '@editorjs/editorjs'; import './index.css'; import Ui from './ui'; import Uploader from './uploader'; -import { IconAddBorder, IconStretch, IconAddBackground, IconPicture, IconText } from '@codexteam/icons'; -import type { ActionConfig, UploadResponseFormat, ImageToolData, ImageConfig, HTMLPasteEventDetailExtended, ImageSetterParam, FeaturesConfig } from './types/types'; +import { + IconAddBorder, + IconStretch, + IconAddBackground, + IconPicture, + IconText, +} from '@codexteam/icons'; +import type { + ActionConfig, + UploadResponseFormat, + ImageToolData, + ImageConfig, + HTMLPasteEventDetailExtended, + ImageSetterParam, + FeaturesConfig, +} from './types/types'; -type ImageToolConstructorOptions = BlockToolConstructorOptions; +/** + * Constructor options for ImageTool + */ +type ImageToolConstructorOptions = BlockToolConstructorOptions< + ImageToolData, + ImageConfig +>; /** * Implementation of ImageTool class @@ -47,27 +77,27 @@ export default class ImageTool implements BlockTool { /** * Editor.js API instance */ - private api: API; + private readonly api: API; /** * Current Block API instance */ - private block: BlockAPI; + private readonly block: BlockAPI; /** * Configuration for the ImageTool */ - private config: ImageConfig; + private readonly config: ImageConfig; /** * Uploader module instance */ - private uploader: Uploader; + private readonly uploader: Uploader; /** * UI module instance */ - private ui: Ui; + private readonly ui: Ui; /** * Stores current block data internally @@ -90,7 +120,13 @@ export default class ImageTool implements BlockTool { * @param tool.readOnly - read-only mode flag * @param tool.block - current Block API */ - constructor({ data, config, api, readOnly, block }: ImageToolConstructorOptions) { + constructor({ + data, + config, + api, + readOnly, + block, + }: ImageToolConstructorOptions) { this.api = api; this.block = block; @@ -103,7 +139,9 @@ export default class ImageTool implements BlockTool { additionalRequestHeaders: config.additionalRequestHeaders, field: config.field, types: config.types, - captionPlaceholder: this.api.i18n.t(config.captionPlaceholder ?? 'Caption'), + captionPlaceholder: this.api.i18n.t( + config.captionPlaceholder ?? 'Caption' + ), buttonContent: config.buttonContent, uploader: config.uploader, actions: config.actions, @@ -199,7 +237,11 @@ export default class ImageTool implements BlockTool { * Renders Block content */ public render(): HTMLDivElement { - if (this.config.features?.caption === true || this.config.features?.caption === undefined || (this.config.features?.caption === 'optional' && this.data.caption)) { + if ( + this.config.features?.caption === true || + this.config.features?.caption === undefined || + (this.config.features?.caption === 'optional' && this.data.caption) + ) { this.isCaptionEnabled = true; } @@ -251,13 +293,18 @@ export default class ImageTool implements BlockTool { } const availableTunes = tunes.filter((tune) => { - const featureKey = Object.keys(featureTuneMap).find(key => featureTuneMap[key] === tune.name); + const featureKey = Object.keys(featureTuneMap).find( + (key) => featureTuneMap[key] === tune.name + ); if (featureKey === 'caption') { return this.config.features?.caption !== false; } - return featureKey == null || this.config.features?.[featureKey as keyof FeaturesConfig] !== false; + return ( + featureKey == null || + this.config.features?.[featureKey as keyof FeaturesConfig] !== false + ); }); /** @@ -274,7 +321,7 @@ export default class ImageTool implements BlockTool { return currentState; }; - return availableTunes.map(tune => ({ + return availableTunes.map((tune) => ({ icon: tune.icon, label: this.api.i18n.t(tune.title), name: tune.name, @@ -382,7 +429,7 @@ export default class ImageTool implements BlockTool { /** * Private methods - * ̿̿ ̿̿ ̿̿ ̿'̿'\̵͇̿̿\з= ( ▀ ͜͞ʖ▀) =ε/̵͇̿̿/’̿’̿ ̿ ̿̿ ̿̿ ̿̿ + * ̿̿ ̿̿ ̿̿ ̿'̿'\̵͇̿̿\з= ( ▀ ͜͞ʖ▀) =ε/̵͇̿̿/’̿'̿ ̿ ̿̿ ̿̿ ̿̿ */ /** @@ -396,7 +443,11 @@ export default class ImageTool implements BlockTool { this.ui.fillCaption(this._data.caption); ImageTool.tunes.forEach(({ name: tune }) => { - const value = typeof data[tune as keyof ImageToolData] !== 'undefined' ? data[tune as keyof ImageToolData] === true || data[tune as keyof ImageToolData] === 'true' : false; + const value = + typeof data[tune as keyof ImageToolData] !== 'undefined' + ? data[tune as keyof ImageToolData] === true || + data[tune as keyof ImageToolData] === 'true' + : false; this.setTune(tune as keyof ImageToolData, value); }); @@ -445,7 +496,7 @@ export default class ImageTool implements BlockTool { console.log('Image Tool: uploading failed because of', errorText); this.api.notifier.show({ - message: this.api.i18n.t('Couldn’t upload image. Please try another.'), + message: this.api.i18n.t("Couldn't upload image. Please try another."), style: 'error', }); this.ui.hidePreloader(); @@ -485,9 +536,10 @@ export default class ImageTool implements BlockTool { /** * Wait until the API is ready */ - Promise.resolve().then(() => { - this.block.stretched = value; - }) + Promise.resolve() + .then(() => { + this.block.stretched = value; + }) .catch((err) => { console.error(err); }); diff --git a/src/types/codexteam__ajax.d.ts b/src/types/codexteam__ajax.d.ts index 49e1e38b..71f27be8 100644 --- a/src/types/codexteam__ajax.d.ts +++ b/src/types/codexteam__ajax.d.ts @@ -1,9 +1,17 @@ /** * Module declaration for '@codexteam/ajax'. */ -declare module '@codexteam/ajax' { +declare module "@codexteam/ajax" { /** - * Options for configuring an Ajax request. + * Options for configuring an AJAX request + * @typedef {Object} AjaxOptions + * @property {string} [url] - The target URL for the request + * @property {Object} [data] - Payload to send with the request + * @property {string} [accept] - MIME type to accept in response + * @property {Object} [headers] - Custom headers to include + * @property {function(File[]): void} [beforeSend] - Callback before sending files + * @property {string} [fieldName] - Form data field name for file uploads + * @property {string} [type] - HTTP method type (GET/POST/etc) */ export interface AjaxOptions { /** @@ -37,7 +45,9 @@ declare module '@codexteam/ajax' { } /** - * Parameter type of selectFiles function in AjaxOptions interface + * File selection options structure + * @typedef {Object} AjaxFileOptionsParam + * @property {string} accept - Allowed file types (e.g. 'image/*') */ export type AjaxFileOptionsParam = { /** @@ -47,35 +57,64 @@ declare module '@codexteam/ajax' { }; /** - * Represents the response from an Ajax request. - * @template T - The type of the response body. + * AJAX response wrapper with typed body + * @template T - Type of the response body content + * @typedef {Object} AjaxResponse + * @property {number} status - HTTP status code + * @property {T} body - Parsed response content */ - export interface AjaxResponse { - /** The body of the response. */ + export interface AjaxResponse { + status: number; body: T; } /** - * Prompts the user to select files and returns a promise that resolves with the selected files. - * @param options - Options for file selection. - * @param options.accept - The accepted file types. - * @returns A promise that resolves with the selected files. + * File selection handler + * @function selectFiles + * @param {AjaxFileOptionsParam} options - File type restrictions + * @returns {Promise} Array of selected files */ export function selectFiles(options: AjaxFileOptionsParam): Promise; /** - * Sends an Ajax request with the specified options. - * @param options - Options for the Ajax request. - * @returns A promise that resolves with the Ajax response. + * Core transport method for AJAX requests + * @function transport + * @template T - Expected response body type + * @param {Object} options - Transport configuration + * @param {string} options.url - Endpoint URL + * @param {FormData|Record} [options.data] - Request payload + * @param {string} [options.accept] - Response MIME type + * @param {Record} [options.headers] - Request headers + * @param {function(File[]): void} [options.beforeSend] - File preprocessor + * @param {string} [options.fieldName] - Form field name + * @returns {Promise>} Response wrapper */ - export function transport(options: AjaxOptions): Promise; + export function transport(options: { + url: string; + data?: FormData | Record; + accept?: string; + headers?: Record; + beforeSend?: (files: File[]) => void; + fieldName?: string; + }): Promise>; /** - * Sends a POST request with the specified options. - * @param options - Options for the POST request. - * @returns A promise that resolves with the Ajax response. + * POST request shortcut + * @function post + * @template T - Expected response body type + * @param {Object} options - Request configuration + * @param {string} options.url - Target endpoint + * @param {FormData|Record} options.data - POST payload + * @param {string} [options.type] - Content type header + * @param {Record} [options.headers] - Custom headers + * @returns {Promise>} Response wrapper */ - export function post(options: AjaxOptions): Promise; + export function post(options: { + url: string; + data: FormData | Record; + type?: string; + headers?: Record; + }): Promise>; /** * Represents common content types. diff --git a/src/types/types.ts b/src/types/types.ts index 3de55056..4688403a 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -1,19 +1,18 @@ -import type { HTMLPasteEventDetail } from '@editorjs/editorjs'; +import type { HTMLPasteEventDetail } from "@editorjs/editorjs"; /** - * Represents options for uploading, including a function to handle previewing. + * Configuration options for file upload preview handling */ export interface UploadOptions { /** - * Callback function to be called when the preview is ready. - * @param src - The source of the preview as a string. - * @returns void + * Callback when preview is available + * @param {string} src - Preview image source URL */ onPreview: (src: string) => void; } /** - * User configuration of Image block tunes. Allows to add custom tunes through the config + * Configuration for custom block tune actions */ export interface ActionConfig { /** @@ -39,11 +38,11 @@ export interface ActionConfig { /** * An optional action function to be executed when the tune is activated. */ - action?: Function; -}; + action?: (name: string) => void; +} /** - * UploadResponseFormat interface representing the response format expected from the backend on file uploading. + * Standard upload response format */ export interface UploadResponseFormat { /** @@ -53,8 +52,7 @@ export interface UploadResponseFormat { /** * Object with file data. - * 'url' is required, - * also can contain any additional data that will be saved and passed back + * 'url' is required, also can contain any additional data that will be saved and passed back */ file: { /** @@ -65,7 +63,7 @@ export interface UploadResponseFormat { } /** - * ImageToolData type representing the input and output data format for the image tool, including optional custome actions. + * Core image tool data structure */ export type ImageToolData = { /** @@ -101,22 +99,25 @@ export type ImageToolData = { } & (Actions extends Record ? Actions : {}); /** - * @description Allows to enable or disable features. + * Feature toggle configuration */ export type FeaturesConfig = { /** * Flag to enable/disable tune - background. */ background?: boolean; + /** * Flag to enable/disable tune - border. */ border?: boolean; + /** * Flag to enable/disable caption. * Can be set to 'optional' to allow users to toggle via block tunes. */ - caption?: boolean | 'optional'; + caption?: boolean | "optional"; + /** * Flag to enable/disable tune - stretched */ @@ -124,15 +125,13 @@ export type FeaturesConfig = { }; /** - * - * @description Config supported by Tool + * Main image tool configuration */ export interface ImageConfig { /** * Endpoints for upload, whether using file or URL. */ endpoints: { - /** * Endpoint for file upload. */ @@ -162,12 +161,12 @@ export interface ImageConfig { /** * Additional data to send with requests. */ - additionalRequestData?: object; + additionalRequestData?: Record; /** * Additional headers to send with requests. */ - additionalRequestHeaders?: object; + additionalRequestHeaders?: Record; /** * Custom content for the select file button. @@ -178,11 +177,10 @@ export interface ImageConfig { * Optional custom uploader. */ uploader?: { - /** * Method to upload an image by file. */ - uploadByFile?: (file: Blob) => Promise; + uploadByFile?: (file: File) => Promise; /** * Method to upload an image by URL. @@ -202,8 +200,7 @@ export interface ImageConfig { } /** - * Interface representing the details of a paste event for HTML elements. - * Extends the `HTMLPasteEventDetail` interface to include additional data properties. + * Extended paste event details */ export interface HTMLPasteEventDetailExtended extends HTMLPasteEventDetail { /** @@ -218,7 +215,7 @@ export interface HTMLPasteEventDetailExtended extends HTMLPasteEventDetail { } /** - * Parameter type of Image setter function in ImageTool + * Image setter parameter type */ export type ImageSetterParam = { /** diff --git a/src/ui.ts b/src/ui.ts index f66afa01..44410475 100644 --- a/src/ui.ts +++ b/src/ui.ts @@ -20,8 +20,8 @@ export enum UiState { /** * The UI is in a filled state, with an image successfully loaded. */ - Filled = 'filled' -}; + Filled = 'filled', +} /** * Nodes interface representing various elements in the UI. @@ -30,32 +30,32 @@ interface Nodes { /** * Wrapper element in the UI. */ - wrapper: HTMLElement; + wrapper: HTMLDivElement; /** * Container for the image element in the UI. */ - imageContainer: HTMLElement; + imageContainer: HTMLDivElement; /** * Button for selecting files. */ - fileButton: HTMLElement; + fileButton: HTMLButtonElement; /** * Represents the image element in the UI, if one is present; otherwise, it's undefined. */ - imageEl?: HTMLElement; + imageEl?: HTMLImageElement | HTMLVideoElement; /** * Preloader element for the image. */ - imagePreloader: HTMLElement; + imagePreloader: HTMLDivElement; /** * Caption element for the image. */ - caption: HTMLElement; + caption: HTMLDivElement; } /** @@ -127,7 +127,7 @@ export default class Ui { this.nodes = { wrapper: make('div', [this.CSS.baseClass, this.CSS.wrapper]), imageContainer: make('div', [this.CSS.imageContainer]), - fileButton: this.createFileButton(), + fileButton: this.createFileButton() as HTMLButtonElement, imageEl: undefined, imagePreloader: make('div', this.CSS.imagePreloader), caption: make('div', [this.CSS.input, this.CSS.caption], { @@ -158,7 +158,10 @@ export default class Ui { * @param status - true for enable, false for disable */ public applyTune(tuneName: string, status: boolean): void { - this.nodes.wrapper.classList.toggle(`${this.CSS.wrapper}--${tuneName}`, status); + this.nodes.wrapper.classList.toggle( + `${this.CSS.wrapper}--${tuneName}`, + status + ); } /** @@ -268,7 +271,10 @@ export default class Ui { if (Object.prototype.hasOwnProperty.call(UiState, statusType)) { const state = UiState[statusType as keyof typeof UiState]; - this.nodes.wrapper.classList.toggle(`${this.CSS.wrapper}--${state}`, state === status); + this.nodes.wrapper.classList.toggle( + `${this.CSS.wrapper}--${state}`, + state === status + ); } } } @@ -292,7 +298,7 @@ export default class Ui { imageEl: 'image-tool__image-picture', caption: 'image-tool__caption', }; - }; + } /** * Creates upload-file button @@ -300,7 +306,9 @@ export default class Ui { private createFileButton(): HTMLElement { const button = make('div', [this.CSS.button]); - button.innerHTML = this.config.buttonContent ?? `${IconPicture} ${this.api.i18n.t('Select an Image')}`; + button.innerHTML = + this.config.buttonContent ?? + `${IconPicture} ${this.api.i18n.t('Select an Image')}`; button.addEventListener('click', () => { this.onSelectFile(); diff --git a/src/uploader.ts b/src/uploader.ts index 19dabb29..8e30675f 100644 --- a/src/uploader.ts +++ b/src/uploader.ts @@ -55,7 +55,7 @@ export default class Uploader { * Fires ajax.transport() * @param onPreview - callback fired when preview is ready */ - public uploadSelectedFile({ onPreview }: UploadOptions): void { + public uploadSelectedFile({ onPreview }: UploadOptions): Promise { const preparePreview = function (file: File): void { const reader = new FileReader(); @@ -72,40 +72,57 @@ export default class Uploader { let upload: Promise; // custom uploading - if (this.config.uploader && typeof this.config.uploader.uploadByFile === 'function') { + if ( + this.config.uploader && + typeof this.config.uploader.uploadByFile === 'function' + ) { const uploadByFile = this.config.uploader.uploadByFile; - upload = ajax.selectFiles({ accept: this.config.types ?? 'image/*' }).then((files: File[]) => { - preparePreview(files[0]); + upload = ajax + .selectFiles({ accept: this.config.types ?? 'image/*' }) + .then((files: File[]) => { + preparePreview(files[0]); - const customUpload = uploadByFile(files[0]); + const customUpload = uploadByFile(files[0]); - if (!isPromise(customUpload)) { - console.warn('Custom uploader method uploadByFile should return a Promise'); - } + if (!isPromise(customUpload)) { + console.warn( + 'Custom uploader method uploadByFile should return a Promise' + ); + } - return customUpload; - }); + return customUpload; + }); - // default uploading + // default uploading } else { - upload = ajax.transport({ - url: this.config.endpoints.byFile, - data: this.config.additionalRequestData, - accept: this.config.types ?? 'image/*', - headers: this.config.additionalRequestHeaders as Record, - beforeSend: (files: File[]) => { - preparePreview(files[0]); - }, - fieldName: this.config.field ?? 'image', - }).then((response: AjaxResponse) => response.body as UploadResponseFormat); + upload = ajax + .transport({ + url: this.config.endpoints.byFile ?? '', + data: this.config.additionalRequestData, + accept: this.config.types ?? 'image/*', + headers: this.config.additionalRequestHeaders as Record< + string, + string + >, + beforeSend: (files: File[]) => { + preparePreview(files[0]); + }, + fieldName: this.config.field ?? 'image', + }) + .then( + (response: AjaxResponse) => response.body as UploadResponseFormat + ); } - upload.then((response) => { - this.onUpload(response); - }).catch((error: string) => { - this.onError(error); - }); + // Return the upload promise instead of resolving immediately + return upload + .then((response) => { + this.onUpload(response); + }) + .catch((error: string) => { + this.onError(error); + }); } /** @@ -113,37 +130,55 @@ export default class Uploader { * Fires ajax.post() * @param url - image source url */ - public uploadByUrl(url: string): void { + public uploadByUrl(url: string): Promise { let upload; /** * Custom uploading */ - if (this.config.uploader && typeof this.config.uploader.uploadByUrl === 'function') { + if ( + this.config.uploader && + typeof this.config.uploader.uploadByUrl === 'function' + ) { upload = this.config.uploader.uploadByUrl(url); if (!isPromise(upload)) { - console.warn('Custom uploader method uploadByUrl should return a Promise'); + console.warn( + 'Custom uploader method uploadByUrl should return a Promise' + ); } } else { /** * Default uploading */ - upload = ajax.post({ - url: this.config.endpoints.byUrl, - data: Object.assign({ - url: url, - }, this.config.additionalRequestData), - type: ajax.contentType.JSON, - headers: this.config.additionalRequestHeaders as Record, - }).then((response: AjaxResponse) => response.body as UploadResponseFormat); + upload = ajax + .post({ + url: this.config.endpoints.byUrl ?? '', + data: Object.assign( + { + url: url, + }, + this.config.additionalRequestData + ), + type: ajax.contentType.JSON, + headers: this.config.additionalRequestHeaders as Record< + string, + string + >, + }) + .then( + (response: AjaxResponse) => response.body as UploadResponseFormat + ); } - upload.then((response: UploadResponseFormat) => { - this.onUpload(response); - }).catch((error: string) => { - this.onError(error); - }); + // Return the upload promise instead of resolving immediately + return upload + .then((response: UploadResponseFormat) => { + this.onUpload(response); + }) + .catch((error: string) => { + this.onError(error); + }); } /** @@ -152,7 +187,7 @@ export default class Uploader { * @param file - file pasted by drag-n-drop * @param onPreview - file pasted by drag-n-drop */ - public uploadByFile(file: Blob, { onPreview }: UploadOptions): void { + public uploadByFile(file: Blob, { onPreview }: UploadOptions): Promise { /** * Load file for preview */ @@ -168,11 +203,18 @@ export default class Uploader { /** * Custom uploading */ - if (this.config.uploader && typeof this.config.uploader.uploadByFile === 'function') { - upload = this.config.uploader.uploadByFile(file); + if ( + this.config.uploader && + typeof this.config.uploader.uploadByFile === 'function' + ) { + // Convert Blob to File with a dummy filename + const fileObj = new File([file], 'pasted-image', { type: file.type }); + upload = this.config.uploader.uploadByFile(fileObj); if (!isPromise(upload)) { - console.warn('Custom uploader method uploadByFile should return a Promise'); + console.warn( + 'Custom uploader method uploadByFile should return a Promise' + ); } } else { /** @@ -182,24 +224,39 @@ export default class Uploader { formData.append(this.config.field ?? 'image', file); - if (this.config.additionalRequestData && Object.keys(this.config.additionalRequestData).length) { - Object.entries(this.config.additionalRequestData).forEach(([name, value]: [string, string | Blob]) => { - formData.append(name, value); - }); + if ( + this.config.additionalRequestData && + Object.keys(this.config.additionalRequestData).length + ) { + Object.entries(this.config.additionalRequestData).forEach( + ([name, value]) => { + formData.append(name, value as string | Blob); + } + ); } - upload = ajax.post({ - url: this.config.endpoints.byFile, - data: formData, - type: ajax.contentType.JSON, - headers: this.config.additionalRequestHeaders as Record, - }).then((response: AjaxResponse) => response.body as UploadResponseFormat); + upload = ajax + .post({ + url: this.config.endpoints.byFile ?? '', + data: formData, + type: ajax.contentType.JSON, + headers: this.config.additionalRequestHeaders as Record< + string, + string + >, + }) + .then( + (response: AjaxResponse) => response.body as UploadResponseFormat + ); } - upload.then((response) => { - this.onUpload(response); - }).catch((error: string) => { - this.onError(error); - }); + // Return the upload promise instead of resolving immediately + return upload + .then((response) => { + this.onUpload(response); + }) + .catch((error: string) => { + this.onError(error); + }); } } diff --git a/src/utils/dom.ts b/src/utils/dom.ts index 70bf38a2..9a756d17 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -5,18 +5,23 @@ * @param attributes - any attributes * @returns */ -export function make(tagName: string, classNames: string[] | string | null = null, attributes: { [key: string]: string | boolean } = {}): HTMLElement { - const el = document.createElement(tagName); +export function make( + tagName: string, + classNames?: string[] | string | null, + attributes?: Record +): T { + const el = document.createElement(tagName) as T; if (Array.isArray(classNames)) { el.classList.add(...classNames); - } else if (classNames !== null) { + } else if (typeof classNames === "string") { el.classList.add(classNames); } for (const attrName in attributes) { if (attributes.hasOwnProperty(attrName)) { - (el as unknown as { [key: string]: string | boolean })[attrName] = attributes[attrName]; + (el as unknown as { [key: string]: string | boolean })[attrName] = + attributes[attrName]; } } diff --git a/tsconfig.json b/tsconfig.json index 3454236b..862c831c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,15 +1,31 @@ { - "compilerOptions": { - /* Language and Environment */ - "target": "es2017", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - /* Modules */ - "module": "CommonJS", /* Specify what module code is generated. */ - "typeRoots": ["./node_modules/@types", "./types"], /* Specify multiple folders that act like './node_modules/@types'. */ - /* Interop Constraints */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - }, - "include": ["src/**/*.ts"] - } \ No newline at end of file + "compilerOptions": { + /* Language and Environment */ + "target": "es2017" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "jsx": "preserve", + /* Modules */ + "module": "ESNext", + "moduleResolution": "node", + "typeRoots": [ + "./node_modules/@types", + "./types" + ] /* Specify multiple folders that act like './node_modules/@types'. */, + /* Interop Constraints */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + "skipLibCheck": true, + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + /* Emit */ + "declaration": true, + "declarationDir": "./dist", + "outDir": "./dist", + "sourceMap": true + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist"] +} diff --git a/vite.config.js b/vite.config.js index 44a9dbed..82bcb6a7 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,20 +1,21 @@ -import path from "path"; -import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js"; -import * as pkg from "./package.json"; +import path from 'path'; +import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'; import dts from 'vite-plugin-dts'; +import * as pkg from './package.json'; - -const NODE_ENV = process.argv.mode || "development"; +const NODE_ENV = process.argv.mode || 'development'; const VERSION = pkg.version; export default { build: { copyPublicDir: false, lib: { - entry: path.resolve(__dirname, "src", "index.ts"), - name: "ImageTool", - fileName: "image", - } + entry: path.resolve(__dirname, 'src', 'index.ts'), + name: 'ImageTool', + fileName: 'image', + formats: ['es', 'umd'] + }, + sourcemap: true, }, server: { open: './dev/index.html', @@ -23,10 +24,11 @@ export default { NODE_ENV: JSON.stringify(NODE_ENV), VERSION: JSON.stringify(VERSION), }, - - plugins: [cssInjectedByJsPlugin(), + plugins: [ + cssInjectedByJsPlugin(), dts({ - tsconfigPath: './tsconfig.json' + tsconfigPath: './tsconfig.json', + insertTypesEntry: true }) ], };