@tokens-studio/tokenscript-schemas 0.0.11 → 0.0.13
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/dist/cli/index.cjs +31 -8
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +30 -8
- package/dist/cli/index.js.map +1 -1
- package/package.json +2 -1
- package/src/bundler/bundle-schema.ts +146 -0
- package/src/bundler/index.ts +151 -0
- package/src/bundler/schema-dependency-resolver.ts +299 -0
- package/src/bundler/selective-bundler.test.ts +94 -0
- package/src/bundler/selective-bundler.ts +159 -0
- package/src/bundler/types.ts +93 -0
- package/src/bundler/utils.ts +74 -0
- package/src/cli/commands/bundle.integration.test.ts +153 -0
- package/src/cli/commands/bundle.test.ts +57 -0
- package/src/cli/commands/bundle.ts +237 -0
- package/src/cli/commands/list.ts +109 -0
- package/src/cli/config-schema.ts +36 -0
- package/src/cli/index.ts +50 -0
- package/src/cli/output-generator.ts +63 -0
- package/src/downloader/index.ts +248 -0
- package/src/downloader/types.ts +48 -0
- package/src/index.ts +8 -0
- package/src/schemas/functions/adjust_chroma/adjust-chroma.tokenscript +27 -0
- package/src/schemas/functions/adjust_chroma/schema.json +48 -0
- package/src/schemas/functions/adjust_chroma/unit.test.ts +76 -0
- package/src/schemas/functions/adjust_hue/adjust-hue.tokenscript +32 -0
- package/src/schemas/functions/adjust_hue/schema.json +48 -0
- package/src/schemas/functions/adjust_hue/unit.test.ts +68 -0
- package/src/schemas/functions/adjust_lightness/adjust-lightness.tokenscript +31 -0
- package/src/schemas/functions/adjust_lightness/schema.json +48 -0
- package/src/schemas/functions/adjust_lightness/unit.test.ts +88 -0
- package/src/schemas/functions/adjust_to_contrast/adjust-to-contrast.tokenscript +131 -0
- package/src/schemas/functions/adjust_to_contrast/schema.json +56 -0
- package/src/schemas/functions/adjust_to_contrast/unit.test.ts +81 -0
- package/src/schemas/functions/alpha_blend/alpha-blend.tokenscript +46 -0
- package/src/schemas/functions/alpha_blend/schema.json +28 -0
- package/src/schemas/functions/alpha_blend/unit.test.ts +135 -0
- package/src/schemas/functions/alpha_scale/alpha-scale.tokenscript +38 -0
- package/src/schemas/functions/alpha_scale/schema.json +24 -0
- package/src/schemas/functions/alpha_scale/unit.test.ts +50 -0
- package/src/schemas/functions/analogous/analogous.tokenscript +47 -0
- package/src/schemas/functions/analogous/schema.json +28 -0
- package/src/schemas/functions/analogous/unit.test.ts +64 -0
- package/src/schemas/functions/apca_contrast/apca-contrast.tokenscript +129 -0
- package/src/schemas/functions/apca_contrast/schema.json +24 -0
- package/src/schemas/functions/apca_contrast/unit.test.ts +259 -0
- package/src/schemas/functions/are_similar/are-similar.tokenscript +24 -0
- package/src/schemas/functions/are_similar/schema.json +57 -0
- package/src/schemas/functions/are_similar/unit.test.ts +57 -0
- package/src/schemas/functions/auto_text_color/auto-text-color.tokenscript +41 -0
- package/src/schemas/functions/auto_text_color/schema.json +53 -0
- package/src/schemas/functions/auto_text_color/unit.test.ts +122 -0
- package/src/schemas/functions/best_contrast/best-contrast.tokenscript +66 -0
- package/src/schemas/functions/best_contrast/schema.json +24 -0
- package/src/schemas/functions/best_contrast/unit.test.ts +64 -0
- package/src/schemas/functions/chroma/chroma.tokenscript +12 -0
- package/src/schemas/functions/chroma/schema.json +44 -0
- package/src/schemas/functions/chroma/unit.test.ts +86 -0
- package/src/schemas/functions/clamp_chroma/clamp-chroma.tokenscript +21 -0
- package/src/schemas/functions/clamp_chroma/schema.json +52 -0
- package/src/schemas/functions/clamp_chroma/unit.test.ts +60 -0
- package/src/schemas/functions/clamp_lightness/clamp-lightness.tokenscript +21 -0
- package/src/schemas/functions/clamp_lightness/schema.json +52 -0
- package/src/schemas/functions/clamp_lightness/unit.test.ts +76 -0
- package/src/schemas/functions/clamp_to_gamut/clamp-to-gamut.tokenscript +41 -0
- package/src/schemas/functions/clamp_to_gamut/schema.json +20 -0
- package/src/schemas/functions/clamp_to_gamut/unit.test.ts +167 -0
- package/src/schemas/functions/complement/complement.tokenscript +21 -0
- package/src/schemas/functions/complement/schema.json +20 -0
- package/src/schemas/functions/complement/unit.test.ts +81 -0
- package/src/schemas/functions/contrast_ratio/contrast-ratio.tokenscript +36 -0
- package/src/schemas/functions/contrast_ratio/schema.json +24 -0
- package/src/schemas/functions/contrast_ratio/unit.test.ts +91 -0
- package/src/schemas/functions/cooler/cooler.tokenscript +45 -0
- package/src/schemas/functions/cooler/schema.json +43 -0
- package/src/schemas/functions/cooler/unit.test.ts +69 -0
- package/src/schemas/functions/darken/darken.tokenscript +37 -0
- package/src/schemas/functions/darken/schema.json +24 -0
- package/src/schemas/functions/darken/unit.test.ts +105 -0
- package/src/schemas/functions/delta_e_2000/delta-e-2000.tokenscript +184 -0
- package/src/schemas/functions/delta_e_2000/schema.json +36 -0
- package/src/schemas/functions/delta_e_2000/unit.test.ts +243 -0
- package/src/schemas/functions/delta_e_76/delta-e-76.tokenscript +45 -0
- package/src/schemas/functions/delta_e_76/schema.json +24 -0
- package/src/schemas/functions/delta_e_76/unit.test.ts +123 -0
- package/src/schemas/functions/delta_e_ok/delta-e-ok.tokenscript +43 -0
- package/src/schemas/functions/delta_e_ok/schema.json +24 -0
- package/src/schemas/functions/delta_e_ok/unit.test.ts +235 -0
- package/src/schemas/functions/desaturate/desaturate.tokenscript +32 -0
- package/src/schemas/functions/desaturate/schema.json +24 -0
- package/src/schemas/functions/desaturate/unit.test.ts +54 -0
- package/src/schemas/functions/distributed/distributed.tokenscript +54 -0
- package/src/schemas/functions/distributed/schema.json +32 -0
- package/src/schemas/functions/distributed/unit.test.ts +58 -0
- package/src/schemas/functions/diverging/diverging.tokenscript +58 -0
- package/src/schemas/functions/diverging/schema.json +32 -0
- package/src/schemas/functions/diverging/unit.test.ts +70 -0
- package/src/schemas/functions/grayscale/grayscale.tokenscript +17 -0
- package/src/schemas/functions/grayscale/schema.json +20 -0
- package/src/schemas/functions/grayscale/unit.test.ts +79 -0
- package/src/schemas/functions/harmonize/harmonize.tokenscript +61 -0
- package/src/schemas/functions/harmonize/schema.json +52 -0
- package/src/schemas/functions/harmonize/unit.test.ts +56 -0
- package/src/schemas/functions/hue/hue.tokenscript +12 -0
- package/src/schemas/functions/hue/schema.json +44 -0
- package/src/schemas/functions/hue/unit.test.ts +75 -0
- package/src/schemas/functions/hue_difference/hue-difference.tokenscript +42 -0
- package/src/schemas/functions/hue_difference/schema.json +24 -0
- package/src/schemas/functions/hue_difference/unit.test.ts +125 -0
- package/src/schemas/functions/in_gamut/in-gamut.tokenscript +51 -0
- package/src/schemas/functions/in_gamut/schema.json +24 -0
- package/src/schemas/functions/in_gamut/unit.test.ts +178 -0
- package/src/schemas/functions/interpolate/interpolate.tokenscript +61 -0
- package/src/schemas/functions/interpolate/schema.json +52 -0
- package/src/schemas/functions/interpolate/unit.test.ts +96 -0
- package/src/schemas/functions/invert/invert-initializer.tokenscript +29 -0
- package/src/schemas/functions/invert/schema.json +20 -0
- package/src/schemas/functions/invert/unit.test.ts +216 -0
- package/src/schemas/functions/is_cool/is-cool.tokenscript +41 -0
- package/src/schemas/functions/is_cool/schema.json +20 -0
- package/src/schemas/functions/is_cool/unit.test.ts +189 -0
- package/src/schemas/functions/is_dark/is-dark.tokenscript +16 -0
- package/src/schemas/functions/is_dark/schema.json +24 -0
- package/src/schemas/functions/is_dark/unit.test.ts +87 -0
- package/src/schemas/functions/is_light/is-light.tokenscript +16 -0
- package/src/schemas/functions/is_light/schema.json +24 -0
- package/src/schemas/functions/is_light/unit.test.ts +86 -0
- package/src/schemas/functions/is_neutral/is-neutral.tokenscript +16 -0
- package/src/schemas/functions/is_neutral/schema.json +53 -0
- package/src/schemas/functions/is_neutral/unit.test.ts +85 -0
- package/src/schemas/functions/is_warm/is-warm.tokenscript +62 -0
- package/src/schemas/functions/is_warm/schema.json +20 -0
- package/src/schemas/functions/is_warm/unit.test.ts +161 -0
- package/src/schemas/functions/lighten/lighten.tokenscript +37 -0
- package/src/schemas/functions/lighten/schema.json +24 -0
- package/src/schemas/functions/lighten/unit.test.ts +109 -0
- package/src/schemas/functions/lightness/lightness.tokenscript +12 -0
- package/src/schemas/functions/lightness/schema.json +49 -0
- package/src/schemas/functions/lightness/unit.test.ts +99 -0
- package/src/schemas/functions/luminance/luminance.tokenscript +16 -0
- package/src/schemas/functions/luminance/schema.json +20 -0
- package/src/schemas/functions/luminance/unit.test.ts +105 -0
- package/src/schemas/functions/meets_contrast/meets-contrast.tokenscript +49 -0
- package/src/schemas/functions/meets_contrast/schema.json +28 -0
- package/src/schemas/functions/meets_contrast/unit.test.ts +170 -0
- package/src/schemas/functions/mix/mix.tokenscript +47 -0
- package/src/schemas/functions/mix/schema.json +28 -0
- package/src/schemas/functions/mix/unit.test.ts +95 -0
- package/src/schemas/functions/monochromatic/monochromatic.tokenscript +72 -0
- package/src/schemas/functions/monochromatic/schema.json +24 -0
- package/src/schemas/functions/monochromatic/unit.test.ts +91 -0
- package/src/schemas/functions/muted/muted.tokenscript +25 -0
- package/src/schemas/functions/muted/schema.json +48 -0
- package/src/schemas/functions/muted/unit.test.ts +100 -0
- package/src/schemas/functions/neutral_variant/neutral-variant.tokenscript +23 -0
- package/src/schemas/functions/neutral_variant/schema.json +48 -0
- package/src/schemas/functions/neutral_variant/unit.test.ts +102 -0
- package/src/schemas/functions/relative_luminance/relative-luminance.tokenscript +15 -0
- package/src/schemas/functions/relative_luminance/schema.json +49 -0
- package/src/schemas/functions/relative_luminance/unit.test.ts +104 -0
- package/src/schemas/functions/rotate_hue/rotate-hue.tokenscript +20 -0
- package/src/schemas/functions/rotate_hue/schema.json +24 -0
- package/src/schemas/functions/rotate_hue/unit.test.ts +86 -0
- package/src/schemas/functions/saturate/saturate.tokenscript +33 -0
- package/src/schemas/functions/saturate/schema.json +24 -0
- package/src/schemas/functions/saturate/unit.test.ts +59 -0
- package/src/schemas/functions/scale_chroma/scale-chroma.tokenscript +22 -0
- package/src/schemas/functions/scale_chroma/schema.json +48 -0
- package/src/schemas/functions/scale_chroma/unit.test.ts +79 -0
- package/src/schemas/functions/scale_lightness/scale-lightness.tokenscript +23 -0
- package/src/schemas/functions/scale_lightness/schema.json +48 -0
- package/src/schemas/functions/scale_lightness/unit.test.ts +73 -0
- package/src/schemas/functions/sepia/schema.json +48 -0
- package/src/schemas/functions/sepia/sepia.tokenscript +54 -0
- package/src/schemas/functions/sepia/unit.test.ts +88 -0
- package/src/schemas/functions/set_chroma/schema.json +24 -0
- package/src/schemas/functions/set_chroma/set-chroma.tokenscript +18 -0
- package/src/schemas/functions/set_chroma/unit.test.ts +79 -0
- package/src/schemas/functions/set_hue/schema.json +24 -0
- package/src/schemas/functions/set_hue/set-hue.tokenscript +18 -0
- package/src/schemas/functions/set_hue/unit.test.ts +90 -0
- package/src/schemas/functions/set_lightness/schema.json +24 -0
- package/src/schemas/functions/set_lightness/set-lightness.tokenscript +18 -0
- package/src/schemas/functions/set_lightness/unit.test.ts +80 -0
- package/src/schemas/functions/shade_scale/schema.json +24 -0
- package/src/schemas/functions/shade_scale/shade-scale.tokenscript +61 -0
- package/src/schemas/functions/shade_scale/unit.test.ts +64 -0
- package/src/schemas/functions/split_complement/schema.json +24 -0
- package/src/schemas/functions/split_complement/split-complement.tokenscript +38 -0
- package/src/schemas/functions/split_complement/unit.test.ts +53 -0
- package/src/schemas/functions/steps/schema.json +28 -0
- package/src/schemas/functions/steps/steps.tokenscript +54 -0
- package/src/schemas/functions/steps/unit.test.ts +71 -0
- package/src/schemas/functions/tetradic/schema.json +20 -0
- package/src/schemas/functions/tetradic/tetradic.tokenscript +40 -0
- package/src/schemas/functions/tetradic/unit.test.ts +50 -0
- package/src/schemas/functions/tint_scale/schema.json +32 -0
- package/src/schemas/functions/tint_scale/tint-scale.tokenscript +71 -0
- package/src/schemas/functions/tint_scale/unit.test.ts +64 -0
- package/src/schemas/functions/to_gamut/schema.json +48 -0
- package/src/schemas/functions/to_gamut/to-gamut.tokenscript +96 -0
- package/src/schemas/functions/to_gamut/unit.test.ts +97 -0
- package/src/schemas/functions/triadic/schema.json +20 -0
- package/src/schemas/functions/triadic/triadic.tokenscript +33 -0
- package/src/schemas/functions/triadic/unit.test.ts +64 -0
- package/src/schemas/functions/vibrant/schema.json +48 -0
- package/src/schemas/functions/vibrant/unit.test.ts +55 -0
- package/src/schemas/functions/vibrant/vibrant.tokenscript +29 -0
- package/src/schemas/functions/warmer/schema.json +43 -0
- package/src/schemas/functions/warmer/unit.test.ts +69 -0
- package/src/schemas/functions/warmer/warmer.tokenscript +45 -0
- package/src/schemas/functions/wcag_level/schema.json +48 -0
- package/src/schemas/functions/wcag_level/unit.test.ts +75 -0
- package/src/schemas/functions/wcag_level/wcag-level.tokenscript +50 -0
- package/src/schemas/types/css-color/from-hsl-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-hwb-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-lab-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-lch-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-oklab-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-oklch-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-p3-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-rgb-color.tokenscript +15 -0
- package/src/schemas/types/css-color/from-srgb-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-srgb-linear-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-xyz-d50-color.tokenscript +16 -0
- package/src/schemas/types/css-color/from-xyz-d65-color.tokenscript +16 -0
- package/src/schemas/types/css-color/initializer.tokenscript +13 -0
- package/src/schemas/types/css-color/schema.json +148 -0
- package/src/schemas/types/css-color/unit.test.ts +402 -0
- package/src/schemas/types/hex-color/initializer.tokenscript +3 -0
- package/src/schemas/types/hex-color/schema.json +24 -0
- package/src/schemas/types/hex-color/unit.test.ts +123 -0
- package/src/schemas/types/hsl-color/from-srgb.tokenscript +87 -0
- package/src/schemas/types/hsl-color/initializer.tokenscript +16 -0
- package/src/schemas/types/hsl-color/schema.json +48 -0
- package/src/schemas/types/hsl-color/unit.test.ts +201 -0
- package/src/schemas/types/hsv-color/from-srgb.tokenscript +80 -0
- package/src/schemas/types/hsv-color/initializer.tokenscript +16 -0
- package/src/schemas/types/hsv-color/schema.json +48 -0
- package/src/schemas/types/hsv-color/unit.test.ts +162 -0
- package/src/schemas/types/hwb-color/from-hsv.tokenscript +31 -0
- package/src/schemas/types/hwb-color/initializer.tokenscript +16 -0
- package/src/schemas/types/hwb-color/schema.json +48 -0
- package/src/schemas/types/hwb-color/unit.test.ts +150 -0
- package/src/schemas/types/lab-color/from-xyz-d50.tokenscript +78 -0
- package/src/schemas/types/lab-color/initializer.tokenscript +16 -0
- package/src/schemas/types/lab-color/schema.json +48 -0
- package/src/schemas/types/lab-color/unit.test.ts +263 -0
- package/src/schemas/types/lch-color/from-lab.tokenscript +44 -0
- package/src/schemas/types/lch-color/initializer.tokenscript +16 -0
- package/src/schemas/types/lch-color/schema.json +48 -0
- package/src/schemas/types/lch-color/unit.test.ts +173 -0
- package/src/schemas/types/okhsl-color/from-oklab.tokenscript +410 -0
- package/src/schemas/types/okhsl-color/initializer.tokenscript +24 -0
- package/src/schemas/types/okhsl-color/schema.json +48 -0
- package/src/schemas/types/okhsl-color/unit.test.ts +514 -0
- package/src/schemas/types/okhsv-color/from-oklab.tokenscript +286 -0
- package/src/schemas/types/okhsv-color/initializer.tokenscript +24 -0
- package/src/schemas/types/okhsv-color/schema.json +48 -0
- package/src/schemas/types/okhsv-color/unit.test.ts +499 -0
- package/src/schemas/types/oklab-color/from-okhsl.tokenscript +195 -0
- package/src/schemas/types/oklab-color/from-okhsv.tokenscript +197 -0
- package/src/schemas/types/oklab-color/from-oklch.tokenscript +39 -0
- package/src/schemas/types/oklab-color/from-xyz-d65.tokenscript +43 -0
- package/src/schemas/types/oklab-color/initializer.tokenscript +16 -0
- package/src/schemas/types/oklab-color/schema.json +78 -0
- package/src/schemas/types/oklab-color/unit.test.ts +345 -0
- package/src/schemas/types/oklch-color/from-oklab.tokenscript +45 -0
- package/src/schemas/types/oklch-color/initializer.tokenscript +16 -0
- package/src/schemas/types/oklch-color/schema.json +48 -0
- package/src/schemas/types/oklch-color/unit.test.ts +267 -0
- package/src/schemas/types/p3-color/from-p3-linear.tokenscript +59 -0
- package/src/schemas/types/p3-color/initializer.tokenscript +16 -0
- package/src/schemas/types/p3-color/schema.json +48 -0
- package/src/schemas/types/p3-color/unit.test.ts +119 -0
- package/src/schemas/types/p3-linear-color/from-xyz-d65.tokenscript +47 -0
- package/src/schemas/types/p3-linear-color/initializer.tokenscript +16 -0
- package/src/schemas/types/p3-linear-color/schema.json +48 -0
- package/src/schemas/types/p3-linear-color/unit.test.ts +82 -0
- package/src/schemas/types/rgb-color/from-hex.tokenscript +43 -0
- package/src/schemas/types/rgb-color/initializer.tokenscript +16 -0
- package/src/schemas/types/rgb-color/schema.json +55 -0
- package/src/schemas/types/rgb-color/to-hex.tokenscript +42 -0
- package/src/schemas/types/rgb-color/unit.test.ts +302 -0
- package/src/schemas/types/srgb-color/from-hsl.tokenscript +106 -0
- package/src/schemas/types/srgb-color/from-linear.tokenscript +58 -0
- package/src/schemas/types/srgb-color/from-rgb.tokenscript +20 -0
- package/src/schemas/types/srgb-color/initializer.tokenscript +16 -0
- package/src/schemas/types/srgb-color/schema.json +68 -0
- package/src/schemas/types/srgb-color/unit.test.ts +303 -0
- package/src/schemas/types/srgb-linear-color/from-srgb.tokenscript +55 -0
- package/src/schemas/types/srgb-linear-color/from-xyz-d65.tokenscript +34 -0
- package/src/schemas/types/srgb-linear-color/initializer.tokenscript +13 -0
- package/src/schemas/types/srgb-linear-color/schema.json +58 -0
- package/src/schemas/types/srgb-linear-color/unit.test.ts +291 -0
- package/src/schemas/types/xyz-d50-color/from-xyz-d65.tokenscript +36 -0
- package/src/schemas/types/xyz-d50-color/initializer.tokenscript +16 -0
- package/src/schemas/types/xyz-d50-color/schema.json +48 -0
- package/src/schemas/types/xyz-d50-color/unit.test.ts +240 -0
- package/src/schemas/types/xyz-d65-color/from-linear-p3.tokenscript +47 -0
- package/src/schemas/types/xyz-d65-color/from-linear-srgb.tokenscript +38 -0
- package/src/schemas/types/xyz-d65-color/from-oklab.tokenscript +44 -0
- package/src/schemas/types/xyz-d65-color/initializer.tokenscript +16 -0
- package/src/schemas/types/xyz-d65-color/schema.json +68 -0
- package/src/schemas/types/xyz-d65-color/unit.test.ts +319 -0
- package/src/utils/schema-uri.ts +192 -0
- package/src/utils/type.ts +194 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Darken function
|
|
3
|
+
* Decreases color lightness in OKLab perceptual space
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { executeWithSchema, getBundledSchema } from "@tests/helpers/schema-test-utils";
|
|
7
|
+
import { describe, expect, it } from "vitest";
|
|
8
|
+
import type { FunctionSpecification } from "@/bundler/types";
|
|
9
|
+
|
|
10
|
+
describe("Darken Function", () => {
|
|
11
|
+
describe("Schema Definition", () => {
|
|
12
|
+
it("should have correct schema structure", async () => {
|
|
13
|
+
const schema = (await getBundledSchema("darken", "function")) as FunctionSpecification;
|
|
14
|
+
|
|
15
|
+
expect(schema.name).toBe("Darken");
|
|
16
|
+
expect(schema.type).toBe("function");
|
|
17
|
+
expect(schema.keyword).toBe("darken");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("should have script defined", async () => {
|
|
21
|
+
const schema = (await getBundledSchema("darken", "function")) as FunctionSpecification;
|
|
22
|
+
|
|
23
|
+
expect(schema.script).toBeDefined();
|
|
24
|
+
expect(schema.script.script).toBeTruthy();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe("Function Execution", () => {
|
|
29
|
+
it("should darken a light color", async () => {
|
|
30
|
+
const result = await executeWithSchema(
|
|
31
|
+
"darken",
|
|
32
|
+
"function",
|
|
33
|
+
`
|
|
34
|
+
variable light: Color.SRGB;
|
|
35
|
+
light.r = 0.8; light.g = 0.8; light.b = 0.9;
|
|
36
|
+
darken(light, 0.2).to.srgb()
|
|
37
|
+
`,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
expect(result?.constructor.name).toBe("ColorSymbol");
|
|
41
|
+
const r = (result as any).value.r.value;
|
|
42
|
+
const g = (result as any).value.g.value;
|
|
43
|
+
const b = (result as any).value.b.value;
|
|
44
|
+
expect(r).toBeLessThan(0.8);
|
|
45
|
+
expect(g).toBeLessThan(0.8);
|
|
46
|
+
expect(b).toBeLessThan(0.9);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should use default amount of 0.25", async () => {
|
|
50
|
+
const result = await executeWithSchema(
|
|
51
|
+
"darken",
|
|
52
|
+
"function",
|
|
53
|
+
`
|
|
54
|
+
variable color: Color.SRGB;
|
|
55
|
+
color.r = 0.7; color.g = 0.7; color.b = 0.7;
|
|
56
|
+
darken(color).to.srgb()
|
|
57
|
+
`,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
expect(result?.constructor.name).toBe("ColorSymbol");
|
|
61
|
+
const r = (result as any).value.r.value;
|
|
62
|
+
expect(r).toBeLessThan(0.7);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should not go below minimum lightness", async () => {
|
|
66
|
+
const result = await executeWithSchema(
|
|
67
|
+
"darken",
|
|
68
|
+
"function",
|
|
69
|
+
`
|
|
70
|
+
variable dark: Color.SRGB;
|
|
71
|
+
dark.r = 0.1; dark.g = 0.1; dark.b = 0.1;
|
|
72
|
+
darken(dark, 0.5).to.srgb()
|
|
73
|
+
`,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
expect(result?.constructor.name).toBe("ColorSymbol");
|
|
77
|
+
const r = (result as any).value.r.value;
|
|
78
|
+
const g = (result as any).value.g.value;
|
|
79
|
+
const b = (result as any).value.b.value;
|
|
80
|
+
expect(r).toBeGreaterThanOrEqual(0);
|
|
81
|
+
expect(g).toBeGreaterThanOrEqual(0);
|
|
82
|
+
expect(b).toBeGreaterThanOrEqual(0);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("should preserve hue when darkening", async () => {
|
|
86
|
+
const result = await executeWithSchema(
|
|
87
|
+
"darken",
|
|
88
|
+
"function",
|
|
89
|
+
`
|
|
90
|
+
variable blue: Color.SRGB;
|
|
91
|
+
blue.r = 0.3; blue.g = 0.5; blue.b = 0.9;
|
|
92
|
+
darken(blue, 0.15).to.srgb()
|
|
93
|
+
`,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
expect(result?.constructor.name).toBe("ColorSymbol");
|
|
97
|
+
const r = (result as any).value.r.value;
|
|
98
|
+
const g = (result as any).value.g.value;
|
|
99
|
+
const b = (result as any).value.b.value;
|
|
100
|
+
// Blue should still dominate
|
|
101
|
+
expect(b).toBeGreaterThan(r);
|
|
102
|
+
expect(b).toBeGreaterThan(g);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// CIEDE2000 Color Difference Formula (ΔE00)
|
|
2
|
+
// Reference: CIE 142-2001 (Technical Report)
|
|
3
|
+
// Reference: Color.js deltaE2000 implementation
|
|
4
|
+
// Reference: Sharma, Wu, Dalal "The CIEDE2000 Color-Difference Formula" (2005)
|
|
5
|
+
//
|
|
6
|
+
// This is the CIE-recommended color difference formula, providing
|
|
7
|
+
// better correlation with visual perception than CIE76 or CIE94.
|
|
8
|
+
//
|
|
9
|
+
// Parametric factors (kL, kC, kH):
|
|
10
|
+
// - All default to 1.0 for reference conditions
|
|
11
|
+
// - kL can be increased for lightness texture/noise
|
|
12
|
+
// - kC can be increased for chroma noise
|
|
13
|
+
//
|
|
14
|
+
// Interpretation (approximate):
|
|
15
|
+
// 0.0 - Identical colors
|
|
16
|
+
// < 1.0 - Not perceptible by human eye
|
|
17
|
+
// 1.0 - 2.0 - Perceptible through close observation
|
|
18
|
+
// 2.0 - 10.0 - Perceptible at a glance
|
|
19
|
+
// > 10.0 - Colors are obviously different
|
|
20
|
+
|
|
21
|
+
variable input: List = {input};
|
|
22
|
+
|
|
23
|
+
// Convert both colors to CIE Lab
|
|
24
|
+
variable color1: Color.Lab = input.get(0).to.lab();
|
|
25
|
+
variable color2: Color.Lab = input.get(1).to.lab();
|
|
26
|
+
|
|
27
|
+
// Get parametric weighting factors (default to 1)
|
|
28
|
+
variable k_l: Number = 1;
|
|
29
|
+
variable k_c: Number = 1;
|
|
30
|
+
variable k_h: Number = 1;
|
|
31
|
+
if (input.length() > 2) [ k_l = input.get(2); ];
|
|
32
|
+
if (input.length() > 3) [ k_c = input.get(3); ];
|
|
33
|
+
if (input.length() > 4) [ k_h = input.get(4); ];
|
|
34
|
+
|
|
35
|
+
// Constants
|
|
36
|
+
variable pi: Number = pi();
|
|
37
|
+
variable r2d: Number = 180 / pi;
|
|
38
|
+
variable d2r: Number = pi / 180;
|
|
39
|
+
variable g_factor: Number = 6103515625; // 25^7
|
|
40
|
+
variable e: Number = 2.718281828459045; // Euler's number
|
|
41
|
+
|
|
42
|
+
// Get Lab values
|
|
43
|
+
variable l1: Number = color1.l;
|
|
44
|
+
variable a1: Number = color1.a;
|
|
45
|
+
variable b1: Number = color1.b;
|
|
46
|
+
|
|
47
|
+
variable l2: Number = color2.l;
|
|
48
|
+
variable a2: Number = color2.a;
|
|
49
|
+
variable b2: Number = color2.b;
|
|
50
|
+
|
|
51
|
+
// Calculate C* (chroma) for both colors
|
|
52
|
+
variable c1: Number = sqrt(a1 * a1 + b1 * b1);
|
|
53
|
+
variable c2: Number = sqrt(a2 * a2 + b2 * b2);
|
|
54
|
+
|
|
55
|
+
// Ensure non-negative chroma
|
|
56
|
+
if (c1 < 0) [ c1 = 0; ];
|
|
57
|
+
if (c2 < 0) [ c2 = 0; ];
|
|
58
|
+
|
|
59
|
+
// Mean chroma
|
|
60
|
+
variable c_bar: Number = (c1 + c2) / 2;
|
|
61
|
+
|
|
62
|
+
// Calculate G (a-axis asymmetry factor)
|
|
63
|
+
variable c7: Number = c_bar * c_bar * c_bar * c_bar * c_bar * c_bar * c_bar;
|
|
64
|
+
variable g: Number = 0.5 * (1 - sqrt(c7 / (c7 + g_factor)));
|
|
65
|
+
|
|
66
|
+
// Scale a* values by asymmetry factor
|
|
67
|
+
variable a_prime1: Number = (1 + g) * a1;
|
|
68
|
+
variable a_prime2: Number = (1 + g) * a2;
|
|
69
|
+
|
|
70
|
+
// Calculate C' from scaled a' and original b
|
|
71
|
+
variable c_prime1: Number = sqrt(a_prime1 * a_prime1 + b1 * b1);
|
|
72
|
+
variable c_prime2: Number = sqrt(a_prime2 * a_prime2 + b2 * b2);
|
|
73
|
+
|
|
74
|
+
// Calculate h' (hue angles in degrees)
|
|
75
|
+
variable h1: Number = 0;
|
|
76
|
+
if (a_prime1 != 0) [ h1 = atan2(b1, a_prime1); ];
|
|
77
|
+
if (b1 != 0) [ h1 = atan2(b1, a_prime1); ];
|
|
78
|
+
if (a_prime1 == 0) [
|
|
79
|
+
if (b1 == 0) [ h1 = 0; ] else [ h1 = atan2(b1, a_prime1); ];
|
|
80
|
+
];
|
|
81
|
+
h1 = h1 * r2d;
|
|
82
|
+
if (h1 < 0) [ h1 = h1 + 360; ];
|
|
83
|
+
|
|
84
|
+
variable h2: Number = 0;
|
|
85
|
+
if (a_prime2 != 0) [ h2 = atan2(b2, a_prime2); ];
|
|
86
|
+
if (b2 != 0) [ h2 = atan2(b2, a_prime2); ];
|
|
87
|
+
if (a_prime2 == 0) [
|
|
88
|
+
if (b2 == 0) [ h2 = 0; ] else [ h2 = atan2(b2, a_prime2); ];
|
|
89
|
+
];
|
|
90
|
+
h2 = h2 * r2d;
|
|
91
|
+
if (h2 < 0) [ h2 = h2 + 360; ];
|
|
92
|
+
|
|
93
|
+
// Lightness and Chroma differences
|
|
94
|
+
variable delta_l: Number = l2 - l1;
|
|
95
|
+
variable delta_c: Number = c_prime2 - c_prime1;
|
|
96
|
+
|
|
97
|
+
// Hue difference (getting the sign correct)
|
|
98
|
+
variable h_diff: Number = h2 - h1;
|
|
99
|
+
variable h_sum: Number = h1 + h2;
|
|
100
|
+
variable h_abs: Number = h_diff;
|
|
101
|
+
if (h_abs < 0) [ h_abs = 0 - h_abs; ];
|
|
102
|
+
|
|
103
|
+
variable delta_h: Number = 0;
|
|
104
|
+
variable c_product: Number = c_prime1 * c_prime2;
|
|
105
|
+
|
|
106
|
+
if (c_product == 0) [
|
|
107
|
+
delta_h = 0;
|
|
108
|
+
] else [
|
|
109
|
+
if (h_abs <= 180) [
|
|
110
|
+
delta_h = h_diff;
|
|
111
|
+
] else [
|
|
112
|
+
if (h_diff > 180) [
|
|
113
|
+
delta_h = h_diff - 360;
|
|
114
|
+
] else [
|
|
115
|
+
if (h_diff < -180) [
|
|
116
|
+
delta_h = h_diff + 360;
|
|
117
|
+
] else [
|
|
118
|
+
delta_h = h_diff;
|
|
119
|
+
];
|
|
120
|
+
];
|
|
121
|
+
];
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
// Weighted hue difference (ΔH')
|
|
125
|
+
variable delta_h_prime: Number = 2 * sqrt(c_prime2 * c_prime1) * sin(delta_h * d2r / 2);
|
|
126
|
+
|
|
127
|
+
// Mean lightness and chroma
|
|
128
|
+
variable l_bar: Number = (l1 + l2) / 2;
|
|
129
|
+
variable c_bar_prime: Number = (c_prime1 + c_prime2) / 2;
|
|
130
|
+
variable c_bar_prime7: Number = c_bar_prime * c_bar_prime * c_bar_prime * c_bar_prime * c_bar_prime * c_bar_prime * c_bar_prime;
|
|
131
|
+
|
|
132
|
+
// Mean hue (handling the 0/360 wraparound)
|
|
133
|
+
variable h_bar: Number = 0;
|
|
134
|
+
if (c_product == 0) [
|
|
135
|
+
h_bar = h_sum;
|
|
136
|
+
] else [
|
|
137
|
+
if (h_abs <= 180) [
|
|
138
|
+
h_bar = h_sum / 2;
|
|
139
|
+
] else [
|
|
140
|
+
if (h_sum < 360) [
|
|
141
|
+
h_bar = (h_sum + 360) / 2;
|
|
142
|
+
] else [
|
|
143
|
+
h_bar = (h_sum - 360) / 2;
|
|
144
|
+
];
|
|
145
|
+
];
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
// SL - Lightness crispening factor (assumes L=50 background)
|
|
149
|
+
variable l_bar_minus_50: Number = l_bar - 50;
|
|
150
|
+
variable l_sq: Number = l_bar_minus_50 * l_bar_minus_50;
|
|
151
|
+
variable s_l: Number = 1 + (0.015 * l_sq) / sqrt(20 + l_sq);
|
|
152
|
+
|
|
153
|
+
// SC - Chroma factor
|
|
154
|
+
variable s_c: Number = 1 + 0.045 * c_bar_prime;
|
|
155
|
+
|
|
156
|
+
// T - Cross term for blue non-linearity
|
|
157
|
+
variable t: Number = 1;
|
|
158
|
+
t = t - 0.17 * cos((h_bar - 30) * d2r);
|
|
159
|
+
t = t + 0.24 * cos(2 * h_bar * d2r);
|
|
160
|
+
t = t + 0.32 * cos((3 * h_bar + 6) * d2r);
|
|
161
|
+
t = t - 0.20 * cos((4 * h_bar - 63) * d2r);
|
|
162
|
+
|
|
163
|
+
// SH - Hue factor
|
|
164
|
+
variable s_h: Number = 1 + 0.015 * c_bar_prime * t;
|
|
165
|
+
|
|
166
|
+
// RT - Hue rotation term (for blue region 225-315 degrees)
|
|
167
|
+
variable h_bar_minus_275: Number = h_bar - 275;
|
|
168
|
+
variable exp_arg: Number = -1 * (h_bar_minus_275 / 25) * (h_bar_minus_275 / 25);
|
|
169
|
+
variable delta_theta: Number = 30 * pow(e, exp_arg);
|
|
170
|
+
variable r_c: Number = 2 * sqrt(c_bar_prime7 / (c_bar_prime7 + g_factor));
|
|
171
|
+
variable r_t: Number = -1 * sin(2 * delta_theta * d2r) * r_c;
|
|
172
|
+
|
|
173
|
+
// Calculate final ΔE00
|
|
174
|
+
variable term_l: Number = delta_l / (k_l * s_l);
|
|
175
|
+
variable term_c: Number = delta_c / (k_c * s_c);
|
|
176
|
+
variable term_h: Number = delta_h_prime / (k_h * s_h);
|
|
177
|
+
|
|
178
|
+
variable de: Number = term_l * term_l + term_c * term_c + term_h * term_h;
|
|
179
|
+
de = de + r_t * (delta_c / (k_c * s_c)) * (delta_h_prime / (k_h * s_h));
|
|
180
|
+
|
|
181
|
+
variable result: Number = sqrt(de);
|
|
182
|
+
|
|
183
|
+
return result;
|
|
184
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Delta E 2000",
|
|
3
|
+
"type": "function",
|
|
4
|
+
"description": "Calculates perceptual color difference using CIEDE2000 (ΔE00), the CIE-recommended color difference formula. More accurate than CIE76 for small differences. Industry standard for color quality control. Uses parametric weighting factors kL, kC, kH (all default to 1).",
|
|
5
|
+
"keyword": "delta_e_2000",
|
|
6
|
+
"input": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"color1": {
|
|
10
|
+
"type": "color",
|
|
11
|
+
"description": "First color (reference)"
|
|
12
|
+
},
|
|
13
|
+
"color2": {
|
|
14
|
+
"type": "color",
|
|
15
|
+
"description": "Second color (sample)"
|
|
16
|
+
},
|
|
17
|
+
"kL": {
|
|
18
|
+
"type": "number",
|
|
19
|
+
"description": "Lightness weight (default 1)"
|
|
20
|
+
},
|
|
21
|
+
"kC": {
|
|
22
|
+
"type": "number",
|
|
23
|
+
"description": "Chroma weight (default 1)"
|
|
24
|
+
},
|
|
25
|
+
"kH": {
|
|
26
|
+
"type": "number",
|
|
27
|
+
"description": "Hue weight (default 1)"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"script": {
|
|
32
|
+
"type": "/api/v1/core/tokenscript/0/",
|
|
33
|
+
"script": "./delta-e-2000.tokenscript"
|
|
34
|
+
},
|
|
35
|
+
"requirements": ["/api/v1/core/lab-color/0/", "/api/v1/core/lch-color/0/"]
|
|
36
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { executeWithSchema } from "@tests/helpers/schema-test-utils";
|
|
2
|
+
import Color from "colorjs.io";
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
|
|
5
|
+
describe("Delta E 2000 Function", () => {
|
|
6
|
+
describe("Schema Definition", () => {
|
|
7
|
+
it("should have correct schema structure", async () => {
|
|
8
|
+
const { getBundledSchema } = await import("@tests/helpers/schema-test-utils");
|
|
9
|
+
const schema = await getBundledSchema("delta_e_2000", "function");
|
|
10
|
+
|
|
11
|
+
expect(schema.name).toBe("Delta E 2000");
|
|
12
|
+
expect(schema.type).toBe("function");
|
|
13
|
+
expect((schema as any).keyword).toBe("delta_e_2000");
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe("Basic Calculations", () => {
|
|
18
|
+
it("should return 0 for identical colors", async () => {
|
|
19
|
+
const result = await executeWithSchema(
|
|
20
|
+
"delta_e_2000",
|
|
21
|
+
"function",
|
|
22
|
+
`
|
|
23
|
+
variable c1: Color.SRGB;
|
|
24
|
+
c1.r = 0.5; c1.g = 0.3; c1.b = 0.7;
|
|
25
|
+
variable c2: Color.SRGB;
|
|
26
|
+
c2.r = 0.5; c2.g = 0.3; c2.b = 0.7;
|
|
27
|
+
delta_e_2000(c1, c2)
|
|
28
|
+
`,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
expect(result.value).toBeCloseTo(0, 3);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("should return large value for black vs white", async () => {
|
|
35
|
+
const result = await executeWithSchema(
|
|
36
|
+
"delta_e_2000",
|
|
37
|
+
"function",
|
|
38
|
+
`
|
|
39
|
+
variable c1: Color.SRGB;
|
|
40
|
+
c1.r = 0; c1.g = 0; c1.b = 0;
|
|
41
|
+
variable c2: Color.SRGB;
|
|
42
|
+
c2.r = 1; c2.g = 1; c2.b = 1;
|
|
43
|
+
delta_e_2000(c1, c2)
|
|
44
|
+
`,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// Black vs white is a very large difference (should be ~100)
|
|
48
|
+
expect(result.value).toBeGreaterThan(90);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe("Symmetry", () => {
|
|
53
|
+
it("should be symmetric - order should not matter", async () => {
|
|
54
|
+
const result1 = await executeWithSchema(
|
|
55
|
+
"delta_e_2000",
|
|
56
|
+
"function",
|
|
57
|
+
`
|
|
58
|
+
variable c1: Color.SRGB;
|
|
59
|
+
c1.r = 0.2; c1.g = 0.4; c1.b = 0.6;
|
|
60
|
+
variable c2: Color.SRGB;
|
|
61
|
+
c2.r = 0.6; c2.g = 0.2; c2.b = 0.4;
|
|
62
|
+
delta_e_2000(c1, c2)
|
|
63
|
+
`,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const result2 = await executeWithSchema(
|
|
67
|
+
"delta_e_2000",
|
|
68
|
+
"function",
|
|
69
|
+
`
|
|
70
|
+
variable c1: Color.SRGB;
|
|
71
|
+
c1.r = 0.6; c1.g = 0.2; c1.b = 0.4;
|
|
72
|
+
variable c2: Color.SRGB;
|
|
73
|
+
c2.r = 0.2; c2.g = 0.4; c2.b = 0.6;
|
|
74
|
+
delta_e_2000(c1, c2)
|
|
75
|
+
`,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
expect(result1.value).toBeCloseTo(result2.value, 5);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe("Color.js Parity", () => {
|
|
83
|
+
it("should match Color.js for black vs white", async () => {
|
|
84
|
+
const result = await executeWithSchema(
|
|
85
|
+
"delta_e_2000",
|
|
86
|
+
"function",
|
|
87
|
+
`
|
|
88
|
+
variable c1: Color.SRGB;
|
|
89
|
+
c1.r = 0; c1.g = 0; c1.b = 0;
|
|
90
|
+
variable c2: Color.SRGB;
|
|
91
|
+
c2.r = 1; c2.g = 1; c2.b = 1;
|
|
92
|
+
delta_e_2000(c1, c2)
|
|
93
|
+
`,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const black = new Color("srgb", [0, 0, 0]);
|
|
97
|
+
const white = new Color("srgb", [1, 1, 1]);
|
|
98
|
+
const colorJsDeltaE = black.deltaE(white, "2000");
|
|
99
|
+
|
|
100
|
+
expect(result.value).toBeCloseTo(colorJsDeltaE, 1);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("should match Color.js for red vs blue", async () => {
|
|
104
|
+
const result = await executeWithSchema(
|
|
105
|
+
"delta_e_2000",
|
|
106
|
+
"function",
|
|
107
|
+
`
|
|
108
|
+
variable c1: Color.SRGB;
|
|
109
|
+
c1.r = 1; c1.g = 0; c1.b = 0;
|
|
110
|
+
variable c2: Color.SRGB;
|
|
111
|
+
c2.r = 0; c2.g = 0; c2.b = 1;
|
|
112
|
+
delta_e_2000(c1, c2)
|
|
113
|
+
`,
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const red = new Color("srgb", [1, 0, 0]);
|
|
117
|
+
const blue = new Color("srgb", [0, 0, 1]);
|
|
118
|
+
const colorJsDeltaE = red.deltaE(blue, "2000");
|
|
119
|
+
|
|
120
|
+
expect(result.value).toBeCloseTo(colorJsDeltaE, 1);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("should match Color.js for similar grays", async () => {
|
|
124
|
+
const result = await executeWithSchema(
|
|
125
|
+
"delta_e_2000",
|
|
126
|
+
"function",
|
|
127
|
+
`
|
|
128
|
+
variable c1: Color.SRGB;
|
|
129
|
+
c1.r = 0.5; c1.g = 0.5; c1.b = 0.5;
|
|
130
|
+
variable c2: Color.SRGB;
|
|
131
|
+
c2.r = 0.55; c2.g = 0.55; c2.b = 0.55;
|
|
132
|
+
delta_e_2000(c1, c2)
|
|
133
|
+
`,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const gray1 = new Color("srgb", [0.5, 0.5, 0.5]);
|
|
137
|
+
const gray2 = new Color("srgb", [0.55, 0.55, 0.55]);
|
|
138
|
+
const colorJsDeltaE = gray1.deltaE(gray2, "2000");
|
|
139
|
+
|
|
140
|
+
expect(result.value).toBeCloseTo(colorJsDeltaE, 1);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("should match Color.js for chromatic colors", async () => {
|
|
144
|
+
const result = await executeWithSchema(
|
|
145
|
+
"delta_e_2000",
|
|
146
|
+
"function",
|
|
147
|
+
`
|
|
148
|
+
variable c1: Color.SRGB;
|
|
149
|
+
c1.r = 0.8; c1.g = 0.2; c1.b = 0.4;
|
|
150
|
+
variable c2: Color.SRGB;
|
|
151
|
+
c2.r = 0.3; c2.g = 0.6; c2.b = 0.5;
|
|
152
|
+
delta_e_2000(c1, c2)
|
|
153
|
+
`,
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const color1 = new Color("srgb", [0.8, 0.2, 0.4]);
|
|
157
|
+
const color2 = new Color("srgb", [0.3, 0.6, 0.5]);
|
|
158
|
+
const colorJsDeltaE = color1.deltaE(color2, "2000");
|
|
159
|
+
|
|
160
|
+
expect(result.value).toBeCloseTo(colorJsDeltaE, 1);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe("Perceptual Thresholds", () => {
|
|
165
|
+
it("should detect imperceptible difference (< 1.0)", async () => {
|
|
166
|
+
const result = await executeWithSchema(
|
|
167
|
+
"delta_e_2000",
|
|
168
|
+
"function",
|
|
169
|
+
`
|
|
170
|
+
variable c1: Color.SRGB;
|
|
171
|
+
c1.r = 0.5; c1.g = 0.5; c1.b = 0.5;
|
|
172
|
+
variable c2: Color.SRGB;
|
|
173
|
+
c2.r = 0.505; c2.g = 0.5; c2.b = 0.5;
|
|
174
|
+
delta_e_2000(c1, c2)
|
|
175
|
+
`,
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
// Very small differences should be < 1.0 (imperceptible threshold)
|
|
179
|
+
expect(result.value).toBeLessThan(2);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe("Blue Region Correction", () => {
|
|
184
|
+
it("should handle blue region colors (RT correction)", async () => {
|
|
185
|
+
// Blue region (225-315 degrees) has special rotation term
|
|
186
|
+
const result = await executeWithSchema(
|
|
187
|
+
"delta_e_2000",
|
|
188
|
+
"function",
|
|
189
|
+
`
|
|
190
|
+
variable c1: Color.SRGB;
|
|
191
|
+
c1.r = 0.2; c1.g = 0.2; c1.b = 0.8;
|
|
192
|
+
variable c2: Color.SRGB;
|
|
193
|
+
c2.r = 0.3; c2.g = 0.2; c2.b = 0.7;
|
|
194
|
+
delta_e_2000(c1, c2)
|
|
195
|
+
`,
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
const blue1 = new Color("srgb", [0.2, 0.2, 0.8]);
|
|
199
|
+
const blue2 = new Color("srgb", [0.3, 0.2, 0.7]);
|
|
200
|
+
const colorJsDeltaE = blue1.deltaE(blue2, "2000");
|
|
201
|
+
|
|
202
|
+
// Should be close to Color.js (allows for some tolerance due to complexity)
|
|
203
|
+
expect(result.value).toBeCloseTo(colorJsDeltaE, 0);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
describe("Edge Cases", () => {
|
|
208
|
+
it("should handle achromatic colors (C=0)", async () => {
|
|
209
|
+
const result = await executeWithSchema(
|
|
210
|
+
"delta_e_2000",
|
|
211
|
+
"function",
|
|
212
|
+
`
|
|
213
|
+
variable c1: Color.SRGB;
|
|
214
|
+
c1.r = 0.3; c1.g = 0.3; c1.b = 0.3;
|
|
215
|
+
variable c2: Color.SRGB;
|
|
216
|
+
c2.r = 0.7; c2.g = 0.7; c2.b = 0.7;
|
|
217
|
+
delta_e_2000(c1, c2)
|
|
218
|
+
`,
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
// Two grays - should give valid result
|
|
222
|
+
expect(typeof result.value).toBe("number");
|
|
223
|
+
expect(Number.isFinite(result.value)).toBe(true);
|
|
224
|
+
expect(result.value).toBeGreaterThan(0);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("should always return non-negative values", async () => {
|
|
228
|
+
const result = await executeWithSchema(
|
|
229
|
+
"delta_e_2000",
|
|
230
|
+
"function",
|
|
231
|
+
`
|
|
232
|
+
variable c1: Color.SRGB;
|
|
233
|
+
c1.r = 0.1; c1.g = 0.9; c1.b = 0.5;
|
|
234
|
+
variable c2: Color.SRGB;
|
|
235
|
+
c2.r = 0.9; c2.g = 0.1; c2.b = 0.5;
|
|
236
|
+
delta_e_2000(c1, c2)
|
|
237
|
+
`,
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
expect(result.value).toBeGreaterThanOrEqual(0);
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Delta E 76 (CIE76 Color Difference)
|
|
2
|
+
// Reference: CIE Publication 15.2 (1986)
|
|
3
|
+
// Reference: ASTM E308 Standard
|
|
4
|
+
//
|
|
5
|
+
// The original CIE color difference formula from 1976.
|
|
6
|
+
// Simple Euclidean distance in CIE Lab space.
|
|
7
|
+
//
|
|
8
|
+
// Formula: ΔE*ab = sqrt((L1-L2)² + (a1-a2)² + (b1-b2)²)
|
|
9
|
+
//
|
|
10
|
+
// Interpretation:
|
|
11
|
+
// 0 - 1: Not perceptible by human eye
|
|
12
|
+
// 1 - 2: Perceptible through close observation
|
|
13
|
+
// 2 - 10: Perceptible at a glance
|
|
14
|
+
// 11 - 49: Colors are more similar than opposite
|
|
15
|
+
// 100+: Colors are exact opposite
|
|
16
|
+
//
|
|
17
|
+
// Limitations:
|
|
18
|
+
// - Lab is not perfectly perceptually uniform
|
|
19
|
+
// - Overestimates differences for saturated colors
|
|
20
|
+
// - Use Delta E 2000 for critical color matching
|
|
21
|
+
|
|
22
|
+
variable input: List = {input};
|
|
23
|
+
variable color1: Color.Lab = input.get(0).to.lab();
|
|
24
|
+
variable color2: Color.Lab = input.get(1).to.lab();
|
|
25
|
+
|
|
26
|
+
// Get Lab components
|
|
27
|
+
variable l1: Number = color1.l;
|
|
28
|
+
variable a1: Number = color1.a;
|
|
29
|
+
variable b1: Number = color1.b;
|
|
30
|
+
|
|
31
|
+
variable l2: Number = color2.l;
|
|
32
|
+
variable a2: Number = color2.a;
|
|
33
|
+
variable b2: Number = color2.b;
|
|
34
|
+
|
|
35
|
+
// Calculate differences
|
|
36
|
+
variable delta_l: Number = l1 - l2;
|
|
37
|
+
variable delta_a: Number = a1 - a2;
|
|
38
|
+
variable delta_b: Number = b1 - b2;
|
|
39
|
+
|
|
40
|
+
// Euclidean distance
|
|
41
|
+
variable sum_squares: Number = delta_l * delta_l + delta_a * delta_a + delta_b * delta_b;
|
|
42
|
+
variable result: Number = sqrt(sum_squares);
|
|
43
|
+
|
|
44
|
+
return result;
|
|
45
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Delta E 76",
|
|
3
|
+
"type": "function",
|
|
4
|
+
"description": "Calculates color difference using CIE76 formula (ΔE*ab). Simple Euclidean distance in CIE Lab space. Less accurate than Delta E 2000 for small differences, but faster and adequate for many applications. Formula: sqrt((L1-L2)² + (a1-a2)² + (b1-b2)²).",
|
|
5
|
+
"keyword": "delta_e_76",
|
|
6
|
+
"input": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"color1": {
|
|
10
|
+
"type": "color",
|
|
11
|
+
"description": "First color (reference)"
|
|
12
|
+
},
|
|
13
|
+
"color2": {
|
|
14
|
+
"type": "color",
|
|
15
|
+
"description": "Second color (sample)"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"script": {
|
|
20
|
+
"type": "/api/v1/core/tokenscript/0/",
|
|
21
|
+
"script": "./delta-e-76.tokenscript"
|
|
22
|
+
},
|
|
23
|
+
"requirements": ["/api/v1/core/lab-color/0/"]
|
|
24
|
+
}
|