diff --git a/packages/core/package.json b/packages/core/package.json index 50a795b25..70c729a1c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -9,7 +9,8 @@ "dist", "es", "index.d.ts", - "fonts" + "fonts", + "types" ], "repository": { "type": "git", diff --git a/packages/core/types/index.d.ts b/packages/core/types/index.d.ts index c53d3c251..be6255223 100644 --- a/packages/core/types/index.d.ts +++ b/packages/core/types/index.d.ts @@ -2,8 +2,8 @@ export * from './etc'; export * from './functions'; export * from './plugins'; export * from './utils'; -import {Jimp} from './jimp'; +import {Jimp, JimpConstructors} from './jimp'; -export { Jimp }; +export { Jimp, JimpConstructors }; declare const defaultExp: Jimp; export default defaultExp; diff --git a/packages/core/types/jimp.d.ts b/packages/core/types/jimp.d.ts index 715977f22..49b448742 100644 --- a/packages/core/types/jimp.d.ts +++ b/packages/core/types/jimp.d.ts @@ -10,22 +10,24 @@ import { RGB } from './etc'; -export declare class Jimp { - // Constructors - constructor(path: string, cb?: ImageCallback); - constructor(urlOptions: URLOptions, cb?: ImageCallback); - constructor(image: Jimp, cb?: ImageCallback); - constructor(data: Buffer, cb?: ImageCallback); - constructor(data: Bitmap, cb?: ImageCallback); - constructor(w: number, h: number, cb?: ImageCallback); - constructor( +export interface JimpConstructors { + new(path: string, cb?: ImageCallback): this; + new(urlOptions: URLOptions, cb?: ImageCallback): this; + new(image: Jimp, cb?: ImageCallback): this; + new(data: Buffer, cb?: ImageCallback): this; + new(data: Bitmap, cb?: ImageCallback): this; + new(w: number, h: number, cb?: ImageCallback): this; + new( w: number, h: number, background?: number | string, cb?: ImageCallback - ); + ): this; // For custom constructors when using Jimp.appendConstructorOption - constructor(...args: any[]); + new(...args: any[]): this; +} + +export interface Jimp extends JimpConstructors { prototype: this; // Constants AUTO: -1; @@ -75,7 +77,7 @@ export declare class Jimp { getExtension(): string; distanceFromHash(hash: string): number; write(path: string, cb?: ImageCallback): this; - writeAsync(path: string): Promise; + writeAsync(path: string): Promise; rgba(bool: boolean, cb?: ImageCallback): this; getBase64(mime: string, cb: GenericCallback): this; getBase64Async(mime: string): Promise; @@ -150,8 +152,8 @@ export declare class Jimp { name: string, test: (...args: T[]) => boolean, run: ( - this: Jimp, - resolve: (jimp: Jimp) => any, + this: this, + resolve: (jimp: this) => any, reject: (reason: Error) => any, ...args: T[] ) => any diff --git a/packages/custom/types/index.d.ts b/packages/custom/types/index.d.ts index 5ae06a01b..196f27f5e 100644 --- a/packages/custom/types/index.d.ts +++ b/packages/custom/types/index.d.ts @@ -5,44 +5,29 @@ import { Jimp, JimpPlugin, JimpType, - GetIntersectionFromPlugins + GetIntersectionFromPlugins, + JimpConstructors } from '@jimp/core'; -declare function configure< - PluginFuncArr extends FunctionRet, - JimpInstance extends Jimp = Jimp ->( - configuration: { - plugins: PluginFuncArr; - }, - jimpInstance?: JimpInstance -): Exclude & - GetIntersectionFromPlugins; - -declare function configure< - TypesFuncArr extends FunctionRet, - JimpInstance extends Jimp = Jimp ->( - configuration: { - types: TypesFuncArr; - }, - jimpInstance?: JimpInstance -): Exclude & - GetIntersectionFromPlugins; +type JimpInstance< + TypesFuncArr extends FunctionRet | undefined, + PluginFuncArr extends FunctionRet | undefined, + J extends Jimp +> = Exclude & + GetIntersectionFromPlugins> & + JimpConstructors; declare function configure< - TypesFuncArr extends FunctionRet, - PluginFuncArr extends FunctionRet, - JimpInstance extends Jimp = Jimp + TypesFuncArr extends FunctionRet | undefined = undefined, + PluginFuncArr extends FunctionRet | undefined = undefined, + J extends Jimp = Jimp >( configuration: { types?: TypesFuncArr; plugins?: PluginFuncArr; }, - jimpInstance?: JimpInstance + jimpInstance?: J // Since JimpInstance is required, we want to use the default `Jimp` type -): Exclude & - GetIntersectionFromPlugins & - GetIntersectionFromPlugins; +): JimpInstance; - export default configure; +export default configure; diff --git a/packages/custom/types/test.ts b/packages/custom/types/test.ts index 3cf91dfe8..489512ead 100644 --- a/packages/custom/types/test.ts +++ b/packages/custom/types/test.ts @@ -13,29 +13,56 @@ const CustomJimp = configure({ plugins: [displace, resize] }); -// Methods from types should be applied -CustomJimp.deflateLevel(4); -// Constants from types should be applied -// $ExpectType 0 -CustomJimp.PNG_FILTER_NONE; +test('can handle custom jimp', () => { + // Methods from types should be applied + CustomJimp.deflateLevel(4); + // Constants from types should be applied + // $ExpectType 0 + CustomJimp.PNG_FILTER_NONE; + + // Core functions should still work from Jimp + CustomJimp.read('Test'); + + // Constants should be applied from ill-formed plugins + CustomJimp.displace(CustomJimp, 2); + + // Methods should be applied from well-formed plugins + CustomJimp.resize(40, 40) + + // Constants should be applied from well-formed plugins + CustomJimp.RESIZE_NEAREST_NEIGHBOR + + // $ExpectError + CustomJimp.test; + + // $ExpectError + CustomJimp.func(); -// Core functions should still work from Jimp -CustomJimp.read('Test'); + const Jiimp = new CustomJimp('test'); + // Methods from types should be applied + Jiimp.deflateLevel(4); + // Constants from types should be applied + // $ExpectType 0 + Jiimp.PNG_FILTER_NONE; -// Constants should be applied from ill-formed plugins -CustomJimp.displace(CustomJimp, 2); + // Core functions should still work from Jimp + Jiimp.read('Test'); -// Methods should be applied from well-formed plugins -CustomJimp.resize(40, 40) + // Constants should be applied from ill-formed plugins + Jiimp.displace(Jiimp, 2); -// Constants should be applied from well-formed plugins -CustomJimp.RESIZE_NEAREST_NEIGHBOR + // Methods should be applied from well-formed plugins + Jiimp.resize(40, 40) + + // Constants should be applied from well-formed plugins + Jiimp.RESIZE_NEAREST_NEIGHBOR -// $ExpectError -CustomJimp.test; + // $ExpectError + Jiimp.test; -// $ExpectError -CustomJimp.func(); + // $ExpectError + Jiimp.func(); +}); test('can compose', () => { const OtherCustomJimp = configure({ @@ -68,6 +95,31 @@ test('can compose', () => { // $ExpectError OtherCustomJimp.func(); + + const Jiimp = new OtherCustomJimp('test'); + // Methods from types should be applied + Jiimp.deflateLevel(4); + // Constants from types should be applied + // $ExpectType 0 + Jiimp.PNG_FILTER_NONE; + + // Core functions should still work from Jimp + Jiimp.read('Test'); + + // Constants should be applied from ill-formed plugins + Jiimp.displace(Jiimp, 2); + + // Methods should be applied from well-formed plugins + Jiimp.resize(40, 40) + + // Constants should be applied from well-formed plugins + Jiimp.RESIZE_NEAREST_NEIGHBOR + + // $ExpectError + Jiimp.test; + + // $ExpectError + Jiimp.func(); }); test('can handle only plugins', () => { @@ -93,6 +145,26 @@ test('can handle only plugins', () => { // $ExpectError PluginsJimp.func(); + + const Jiimp = new PluginsJimp('test'); + + // Core functions should still work from Jimp + Jiimp.read('Test'); + + // Constants should be applied from ill-formed plugins + Jiimp.displace(Jiimp, 2); + + // Methods should be applied from well-formed plugins + Jiimp.resize(40, 40) + + // Constants should be applied from well-formed plugins + Jiimp.RESIZE_NEAREST_NEIGHBOR + + // $ExpectError + Jiimp.test; + + // $ExpectError + Jiimp.func(); }) test('can handle only all types', () => { @@ -103,7 +175,6 @@ test('can handle only all types', () => { // Methods from types should be applied TypesJimp.filterType(4); // Constants from types should be applied - // Commented for complexity errors // $ExpectType 0 TypesJimp.PNG_FILTER_NONE; @@ -112,6 +183,19 @@ test('can handle only all types', () => { // $ExpectError TypesJimp.func(); + + const Jiimp = new TypesJimp('test'); + // Methods from types should be applied + Jiimp.filterType(4); + // Constants from types should be applied + // $ExpectType 0 + Jiimp.PNG_FILTER_NONE; + + // $ExpectError + Jiimp.test; + + // $ExpectError + Jiimp.func(); }); test('can handle only one type', () => { @@ -119,8 +203,11 @@ test('can handle only one type', () => { types: [png] }); + // Constants from other types should be not applied + // $ExpectError + PngJimp.MIME_TIFF; + // Constants from types should be applied - // Commented for complexity errors // $ExpectType 0 PngJimp.PNG_FILTER_NONE; @@ -129,24 +216,61 @@ test('can handle only one type', () => { // $ExpectError PngJimp.func(); + + + const Jiimp = new PngJimp('test'); + // Constants from other types should be not applied + // $ExpectError + Jiimp.MIME_TIFF; + + // Constants from types should be applied + // $ExpectType 0 + Jiimp.PNG_FILTER_NONE; + + // $ExpectError + Jiimp.test; + + // $ExpectError + Jiimp.func(); }); test('can handle only one plugin', () => { - const PngJimp = configure({ + const ResizeJimp = configure({ plugins: [resize] }); - // Constants from types should be applied - // Commented for complexity errors + // Constants from other plugins should be not applied + // $ExpectError + ResizeJimp.FONT_SANS_8_BLACK; + + // Constants from plugin should be applied // $ExpectType "nearestNeighbor" - PngJimp.RESIZE_NEAREST_NEIGHBOR; + ResizeJimp.RESIZE_NEAREST_NEIGHBOR; - PngJimp.resize(2, 2); + ResizeJimp.resize(2, 2); // $ExpectError - PngJimp.test; + ResizeJimp.test; // $ExpectError - PngJimp.func(); + ResizeJimp.func(); + + + const Jiimp: typeof ResizeJimp = new ResizeJimp('test'); + // Constants from other plugins should be not applied + // $ExpectError + Jiimp.FONT_SANS_8_BLACK; + + // Constants from plugin should be applied + // $ExpectType "nearestNeighbor" + Jiimp.RESIZE_NEAREST_NEIGHBOR; + + Jiimp.resize(2, 2); + + // $ExpectError + Jiimp.test; + + // $ExpectError + Jiimp.func(); }); diff --git a/packages/jimp/README.md b/packages/jimp/README.md index 509f104ed..3ff32cb6a 100644 --- a/packages/jimp/README.md +++ b/packages/jimp/README.md @@ -57,29 +57,13 @@ Jimp.read('lenna.png') ## TypeScript Usage -If you're using this library with TypeScript the method of importing slightly differs from JavaScript. You can import the library with three methods - -First of all using [`import = require()`](https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require) method to import it as a `commonJS` module: - -```ts -import Jimp = require('jimp'); -``` - -Alternatively you can import it with ES6 default import scheme, if you set the `esModuleInterop` compiler flag to `true` in your `tsconfig` +If you're using this library with TypeScript the method of importing slightly differs from JavaScript. Instead of using require, you must import it with ES6 default import scheme ```ts import Jimp from 'jimp'; ``` -Lastly you can import it with a synthetic default import. This requires setting the `allowSyntheticDefaultImports` compiler option to `true` in your `tsconfig` - -```ts -import * as Jimp from 'jimp'; -``` - -**Note 1**: `esModuleInterop` implicitly sets `allowSyntheticDefaultImports` to `true` - -**Note 2**: `allowSyntheticDefaultImports` nor `esModuleInterop` change the runtime behavior of your code at all. They are just flags that tells TypeScript you need the compatibility they offer. +**Note**: This change in import does not change the runtime behavior of your code at all. ## Module Build diff --git a/packages/jimp/package.json b/packages/jimp/package.json index b782faaee..766ccd7f5 100644 --- a/packages/jimp/package.json +++ b/packages/jimp/package.json @@ -6,20 +6,14 @@ "module": "es/index.js", "browser": "browser/lib/jimp.js", "types": "types/index.d.ts", - "typesVersions": { - ">=3.1.0-0": { - "*": [ - "types/ts3.1/index.d.ts" - ] - } - }, "tonicExampleFilename": "example.js", "files": [ "browser", "dist", "es", "index.d.ts", - "fonts" + "fonts", + "types" ], "repository": { "type": "git", diff --git a/packages/jimp/types/index.d.ts b/packages/jimp/types/index.d.ts index 74f0dc9da..6976b3a6d 100644 --- a/packages/jimp/types/index.d.ts +++ b/packages/jimp/types/index.d.ts @@ -1,23 +1,28 @@ // TypeScript Version: 2.8 + +declare const Jimp: Jimp; + +export default Jimp; + /** * @deprecated Jimp typings for TS <3.1 are being depreciated. Please upgrade your TypeScript version */ -declare class Jimp { +interface Jimp { // Constructors - constructor(path: string, cb?: ImageCallback); - constructor(urlOptions: URLOptions, cb?: ImageCallback); - constructor(image: Jimp, cb?: ImageCallback); - constructor(data: Buffer | Bitmap, cb?: ImageCallback); - constructor(w: number, h: number, cb?: ImageCallback); - constructor( + new(path: string, cb?: ImageCallback): Jimp; + new(urlOptions: URLOptions, cb?: ImageCallback): Jimp; + new(image: Jimp, cb?: ImageCallback): Jimp; + new(data: Buffer | Bitmap, cb?: ImageCallback): Jimp; + new(w: number, h: number, cb?: ImageCallback): Jimp; + new( w: number, h: number, background?: number | string, cb?: ImageCallback - ); + ): Jimp; // For custom constructors when using Jimp.appendConstructorOption - constructor(...args: any[]); + new(...args: any[]): Jimp; prototype: Jimp; // Constants @@ -411,10 +416,6 @@ declare class Jimp { ): this; } -declare const JimpInst: Jimp; - -export default JimpInst; - type GenericCallback = ( this: TThis, err: Error | null, @@ -467,26 +468,26 @@ type ListenerData = T extends 'any' ? any : T extends ChangeName ? { - eventName: 'before-change' | 'changed'; - methodName: T; - [key: string]: any; - } + eventName: 'before-change' | 'changed'; + methodName: T; + [key: string]: any; + } : { - eventName: T; - methodName: T extends 'initialized' - ? 'constructor' - : T extends 'before-change' | 'changed' - ? ChangeName - : T extends 'before-clone' | 'cloned' ? 'clone' : any; - }; + eventName: T; + methodName: T extends 'initialized' + ? 'constructor' + : T extends 'before-change' | 'changed' + ? ChangeName + : T extends 'before-clone' | 'cloned' ? 'clone' : any; + }; type PrintableText = | any | { - text: string; - alignmentX: number; - alignmentY: number; - }; + text: string; + alignmentX: number; + alignmentY: number; +}; type URLOptions = { url: string; diff --git a/packages/jimp/types/test.ts b/packages/jimp/types/test.ts index 67220b5c7..3c36bc14c 100644 --- a/packages/jimp/types/test.ts +++ b/packages/jimp/types/test.ts @@ -1,5 +1,20 @@ import Jimp from 'jimp'; +const jimpInst: Jimp = new Jimp('test'); + +// Main Jimp export should already have all of these already applied +jimpInst.read('Test'); +jimpInst.displace(jimpInst, 2); +jimpInst.resize(40, 40); +// $ExpectType 0 +jimpInst.PNG_FILTER_NONE; + +// $ExpectError +jimpInst.test; + +// $ExpectError +jimpInst.func(); + // Main Jimp export should already have all of these already applied Jimp.read('Test'); Jimp.displace(Jimp, 2); @@ -12,3 +27,11 @@ Jimp.test; // $ExpectError Jimp.func(); + +test('can clone properly', async () => { + const baseImage = await Jimp.read('filename'); + const finalImage = baseImage.clone() + .resize(1, 1) + .setPixelColor(0x00000000, 0, 0) + .resize(2, 2); +}); diff --git a/packages/jimp/types/ts3.1/index.d.ts b/packages/jimp/types/ts3.1/index.d.ts index 8125aeb7b..9e259f1f8 100644 --- a/packages/jimp/types/ts3.1/index.d.ts +++ b/packages/jimp/types/ts3.1/index.d.ts @@ -10,9 +10,9 @@ import { Bitmap, RGB, RGBA, - WellFormedValues, UnionToIntersection, - GetPluginVal + GetPluginVal, + JimpConstructors } from '@jimp/core'; import typeFn from '@jimp/types'; import pluginFn from '@jimp/plugins'; @@ -24,6 +24,12 @@ export { Bitmap, RGB, RGBA }; export { FontChar, FontInfo, FontCommon, Font } from '@jimp/plugin-print'; -export type FullJimpType = JimpType & UnionToIntersection> & UnionToIntersection>; -declare const Jimp: FullJimpType; +type IntersectedPluginTypes = UnionToIntersection< + GetPluginVal | GetPluginVal + >; + +type Jimp = InstanceType> & ThisType & IntersectedPluginTypes; + +declare const Jimp: JimpConstructors & ThisType & Jimp; + export default Jimp; diff --git a/packages/jimp/types/ts3.1/test.ts b/packages/jimp/types/ts3.1/test.ts index 67220b5c7..1f2c16d77 100644 --- a/packages/jimp/types/ts3.1/test.ts +++ b/packages/jimp/types/ts3.1/test.ts @@ -1,5 +1,20 @@ import Jimp from 'jimp'; +const jimpInst: Jimp = new Jimp('test'); + +// Main Jimp export should already have all of these already applied +jimpInst.read('Test'); +jimpInst.displace(jimpInst, 2); +jimpInst.resize(40, 40); +// $ExpectType 0 +jimpInst.PNG_FILTER_NONE; + +// $ExpectError +jimpInst.test; + +// $ExpectError +jimpInst.func(); + // Main Jimp export should already have all of these already applied Jimp.read('Test'); Jimp.displace(Jimp, 2); @@ -12,3 +27,24 @@ Jimp.test; // $ExpectError Jimp.func(); + +/** + * FIXME: Enable the 3.1 typings again, this is the last part that needs + * fixing. + * + * 3.1 typing can be fixed by adding the following to the package.json: + "typesVersions": { + ">=3.1.0-0": { + "*": [ + "types/ts3.1/index.d.ts" + ] + } + }, + */ +test('can clone properly', async () => { + const baseImage = await Jimp.read('filename'); + const finalImage = baseImage.clone() + .resize(1, 1) + .setPixelColor(0x00000000, 0, 0) + .resize(2, 2); +});