Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Callback Deprecations, Reference Docs Generation, et al #160

Merged
merged 9 commits into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@
- `Vibrant` class is now a named export
- Node 18+ is now required
- ES5 support is dropped
- `Vibrant.getPalette` no longer accepts a `name` or `callback` API
- Please migrate to the promise-based API to replace the `callback` API
- Please let us know if you were using the `name` API: https://github.com/Vibrant-Colors/node-vibrant/issues
- It was unclear how this was used in practice. We can reconsider adding it back if there's usecases I wasn't aware of
- `Vibrant.getPalettes` no longer accepts a `names` or `callback` API
- Please migrate to the promise-based API to replace the `callback` API
- Please let us know if you were using the `names` API: https://github.com/Vibrant-Colors/node-vibrant/issues
- It was unclear how this was used in practice. We can reconsider adding it back if there's usecases I wasn't aware of
- `Builder.getSwatches` alias was removed in favor of calling `Builder.getPalette`
- Removed the deprecated `Builder.getHex` API, use the `Builder.hex` property instead
- Removed the deprecated `Builder.getPopulation` API, use the `Builder.population` property instead
- Removed the deprecated `Builder.getHsl` API, use the `Builder.hsl` property instead
- Removed the deprecated `Builder.getRgb` API, use the `Builder.rgb` property instead

# v3.2.0

Expand Down
6 changes: 0 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,12 @@ import { Vibrant } from "node-vibrant/browser";
import { Vibrant } from "node-vibrant/worker";

// Using builder
Vibrant.from("path/to/image").getPalette((err, palette) =>
console.log(palette),
);
// Promise
Vibrant.from("path/to/image")
.getPalette()
.then((palette) => console.log(palette));

// Using constructor
let v = new Vibrant("path/to/image", opts);
v.getPalette((err, palette) => console.log(palette));
// Promise
v.getPalette().then((palette) => console.log(palette));
```

Expand Down
4 changes: 4 additions & 0 deletions knip.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"ignoreDependencies": ["nx"]
}
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@
"test:types": "lerna run test:types",
"test:eslint": "lerna run test:eslint",
"test:format": "pnpm run prettier --check",
"prepare": "playwright install chromium",
"do:publish": "lerna publish --no-private"
"docs:generate": "node scripts/generateDocs.js",
"do:publish": "lerna publish --no-private",
"prepare": "playwright install chromium"
},
"devDependencies": {
"@tanstack/config": "^0.14.2",
"@tanstack/config": "^0.15.0",
"@types/node": "^18.15.3",
"@types/table": "^4.0.5",
"eslint": "^9.17.0",
"knip": "^5.41.0",
"lerna": "^8.1.9",
"nx": "^20.3.0",
"playwright": "^1.49.1",
"prettier": "^3.4.2",
"sherif": "^1.1.1",
Expand Down
46 changes: 4 additions & 42 deletions packages/node-vibrant/__tests__/common/helper.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { expect } from "vitest";
import * as util from "@vibrant/color";
import { getBorderCharacters, table } from "table";
import type { Builder, VibrantStatic } from "@vibrant/core";
import type { Palette, Swatch } from "@vibrant/color";
import type { Vibrant } from "@vibrant/core";
import type {
SamplePathKey,
TestSample,
Expand Down Expand Up @@ -68,56 +68,18 @@ const assertPalette = (reference: Palette, palette: Palette) => {

expect(
failCount,
`${failCount} colors are too diffrent from reference palettes`,
`${failCount} colors are too different from reference palettes`,
).to.equal(0);
};

const paletteCallback =
(references: any, done: () => void) =>
(err: Error | undefined, palette: Palette | undefined) => {
setTimeout(() => {
expect(err, `should not throw error '${err}'`).to.be.undefined;
assertPalette(references, palette!);

done();
});
};

export const testVibrant = (
Vibrant: VibrantStatic,
sample: TestSample,
pathKey: SamplePathKey,
env: "node" | "browser",
builderCallback: ((b: Builder) => Builder) | null = null,
) => {
return async () => {
let builder = Vibrant.from(sample[pathKey]).quality(1);

if (typeof builderCallback === "function")
builder = builderCallback(builder);

await new Promise<void>((resolve) => {
builder.getPalette(
paletteCallback(sample.palettes[env], () => {
resolve();
}),
);
});
};
};

export const testVibrantAsPromised = (
Vibrant: VibrantStatic,
VibrantClass: typeof Vibrant,
sample: TestSample,
pathKey: SamplePathKey,
env: "node" | "browser",
builderCallback: ((b: Builder) => Builder) | null = null,
) => {
return async () => {
let builder = Vibrant.from(sample[pathKey]).quality(1);

if (typeof builderCallback === "function")
builder = builderCallback(builder);
const builder = VibrantClass.from(sample[pathKey]).quality(1);

const palette = await builder.getPalette();

Expand Down
11 changes: 2 additions & 9 deletions packages/node-vibrant/__tests__/vibrant.browser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { commands } from "@vitest/browser/context";
import { afterAll, beforeAll, describe, it } from "vitest";

import { Vibrant } from "../src/worker";
import { testVibrant, testVibrantAsPromised } from "./common/helper";
import { testVibrant } from "./common/helper";

import type { TestSample } from "../../../fixtures/sample/loader";

Expand All @@ -18,14 +18,7 @@ describe("Palette Extraction", async () => {
const SAMPLES = await commands.loadSamples();

SAMPLES.forEach((example) => {
it(
`${example.name} (callback)`,
testVibrant(Vibrant, example, "url", "browser"),
);
it(
`${example.name} (Promise)`,
testVibrantAsPromised(Vibrant, example, "url", "browser"),
);
it(`${example.name}`, testVibrant(Vibrant, example, "url", "browser"));
});
});

Expand Down
20 changes: 3 additions & 17 deletions packages/node-vibrant/__tests__/vibrant.node.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { loadTestSamples } from "../../../fixtures/sample/loader";
import { createSampleServer } from "../../../fixtures/sample/server";

import { Vibrant } from "../src/node";
import { testVibrant, testVibrantAsPromised } from "./common/helper";
import { testVibrant } from "./common/helper";
import type http from "node:http";

const TEST_PORT = 3444;
Expand Down Expand Up @@ -36,26 +36,12 @@ afterAll(
describe("Palette Extraction", () => {
describe("process samples", () =>
SAMPLES.forEach((sample) => {
it(
`${sample.name} (callback)`,
testVibrant(Vibrant, sample, "filePath", "node"),
);
it(
`${sample.name} (Promise)`,
testVibrantAsPromised(Vibrant, sample, "filePath", "node"),
);
it(`${sample.name}`, testVibrant(Vibrant, sample, "filePath", "node"));
}));

describe("process remote images (http)", function () {
SAMPLES.forEach((sample) => {
it(
`${sample.url} (callback)`,
testVibrant(Vibrant, sample, "url", "node"),
);
it(
`${sample.url} (Promise)`,
testVibrantAsPromised(Vibrant, sample, "url", "node"),
);
it(`${sample.url}`, testVibrant(Vibrant, sample, "url", "node"));
});
});
});
2 changes: 1 addition & 1 deletion packages/node-vibrant/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"@vibrant/quantizer-mmcq": "^4.0.0-alpha.4"
},
"devDependencies": {
"@tanstack/config": "^0.14.2",
"@tanstack/config": "^0.15.0",
"@vibrant/color": "^4.0.0-alpha.4",
"@vitest/browser": "^2.1.8",
"playwright": "^1.49.1",
Expand Down
9 changes: 9 additions & 0 deletions packages/node-vibrant/tsconfig.docs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"exclude": [
"__tests__",
"eslint.config.js",
"vite.config.ts",
"vitest.workspace.ts"
]
}
8 changes: 7 additions & 1 deletion packages/node-vibrant/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@
"compilerOptions": {
"types": ["vite/client", "@vitest/browser/providers/playwright"]
},
"include": ["src", "__tests__", "vite.config.ts", "vitest.workspace.ts"]
"include": [
"src",
"__tests__",
"eslint.config.js",
"vite.config.ts",
"vitest.workspace.ts"
]
}
2 changes: 1 addition & 1 deletion packages/vibrant-color/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"homepage": "https://github.com/akfish/node-vibrant",
"license": "MIT",
"devDependencies": {
"@tanstack/config": "^0.14.2",
"@tanstack/config": "^0.15.0",
"vite": "^6.0.3"
},
"publishConfig": {
Expand Down
20 changes: 20 additions & 0 deletions packages/vibrant-color/src/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ export function rgbToCIELab(r: number, g: number, b: number): Vec3 {
return xyzToCIELab(x, y, z);
}

/**
* Computes CIE delta E 1994 diff between `lab1` and `lab2`. The 2 colors are in CIE-Lab color space. Used in tests to compare 2 colors' perceptual similarity.
*/
export function deltaE94(lab1: Vec3, lab2: Vec3): number {
const WEIGHT_L = 1;
const WEIGHT_C = 1;
Expand Down Expand Up @@ -174,19 +177,36 @@ export function deltaE94(lab1: Vec3, lab2: Vec3): number {
return Math.sqrt(xDL * xDL + xDC * xDC + xDH * xDH);
}

/**
* Compute CIE delta E 1994 diff between `rgb1` and `rgb2`.
*/
export function rgbDiff(rgb1: Vec3, rgb2: Vec3): number {
const lab1 = rgbToCIELab.apply(undefined, rgb1);
const lab2 = rgbToCIELab.apply(undefined, rgb2);
return deltaE94(lab1, lab2);
}

/**
* Compute CIE delta E 1994 diff between `hex1` and `hex2`.
*/
export function hexDiff(hex1: string, hex2: string): number {
const rgb1 = hexToRgb(hex1);
const rgb2 = hexToRgb(hex2);

return rgbDiff(rgb1, rgb2);
}

/**
* Gets a string to describe the meaning of the color diff. Used in tests.
*
* Delta E | Perception | Returns
* -------- | -------------------------------------- | -----------
* <= 1.0 | Not perceptible by human eyes. | `"Perfect"`
* 1 - 2 | Perceptible through close observation. | `"Close"`
* 2 - 10 | Perceptible at a glance. | `"Good"`
* 11 - 49 | Colors are more similar than opposite | `"Similar"`
* 50 - 100 | Colors are exact opposite | `Wrong`
*/
export function getColorDiffStatus(d: number): string {
if (d < DELTAE94_DIFF_STATUS.NA) {
return "N/A";
Expand Down
58 changes: 19 additions & 39 deletions packages/vibrant-color/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { rgbToHex, rgbToHsl } from "./converter";

export * from "./converter";

/**
* @returns `true` if the color is to be kept.
*/
export interface Filter {
(red: number, green: number, blue: number, alpha: number): boolean;
}
Expand All @@ -25,6 +28,9 @@ export interface Palette {
[name: string]: Swatch | null;
}

/**
* Represents a color swatch generated from an image's palette.
*/
export class Swatch {
static applyFilters(colors: Swatch[], filters: Filter[]): Swatch[] {
return filters.length > 0
Expand Down Expand Up @@ -95,6 +101,7 @@ export class Swatch {
}
return this._hex;
}

get population(): number {
return this._population;
}
Expand All @@ -109,38 +116,6 @@ export class Swatch {
};
}

/**
* Get the color value as a rgb value
* @deprecated Use property instead
*/
// TODO: deprecate internally, use property instead
getRgb(): Vec3 {
return this._rgb;
}
/**
* Get the color value as a hsl value
* @deprecated Use property instead
*/
// TODO: deprecate internally, use property instead
getHsl(): Vec3 {
return this.hsl;
}
/**
* @deprecated Use property instead
*/
// TODO: deprecate internally, use property instead
getPopulation(): number {
return this._population;
}
/**
* Get the color value as a hex string
* @deprecated Use property instead
*/
// TODO: deprecate internally, use property instead
getHex(): string {
return this.hex;
}

private getYiq(): number {
if (!this._yiq) {
const rgb = this._rgb;
Expand All @@ -152,26 +127,31 @@ export class Swatch {
private _titleTextColor: string | undefined;
private _bodyTextColor: string | undefined;

/**
* Returns an appropriate color to use for any 'title' text which is displayed over this Swatch's color.
*/
get titleTextColor() {
if (!this._titleTextColor) {
this._titleTextColor = this.getYiq() < 200 ? "#fff" : "#000";
}
return this._titleTextColor;
}

/**
* Returns an appropriate color to use for any 'body' text which is displayed over this Swatch's color.
*/
get bodyTextColor() {
if (!this._bodyTextColor) {
this._bodyTextColor = this.getYiq() < 150 ? "#fff" : "#000";
}
return this._bodyTextColor;
}
getTitleTextColor(): string {
return this.titleTextColor;
}

getBodyTextColor(): string {
return this.bodyTextColor;
}

/**
* Internal use.
* @param rgb `[r, g, b]`
* @param population Population of the color in an image
*/
constructor(rgb: Vec3, population: number) {
this._rgb = rgb;
this._population = population;
Expand Down
4 changes: 4 additions & 0 deletions packages/vibrant-color/tsconfig.docs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"exclude": ["eslint.config.js", "vite.config.ts"]
}
Loading
Loading