@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.
Files changed (307) hide show
  1. package/dist/cli/index.cjs +31 -8
  2. package/dist/cli/index.cjs.map +1 -1
  3. package/dist/cli/index.js +30 -8
  4. package/dist/cli/index.js.map +1 -1
  5. package/package.json +2 -1
  6. package/src/bundler/bundle-schema.ts +146 -0
  7. package/src/bundler/index.ts +151 -0
  8. package/src/bundler/schema-dependency-resolver.ts +299 -0
  9. package/src/bundler/selective-bundler.test.ts +94 -0
  10. package/src/bundler/selective-bundler.ts +159 -0
  11. package/src/bundler/types.ts +93 -0
  12. package/src/bundler/utils.ts +74 -0
  13. package/src/cli/commands/bundle.integration.test.ts +153 -0
  14. package/src/cli/commands/bundle.test.ts +57 -0
  15. package/src/cli/commands/bundle.ts +237 -0
  16. package/src/cli/commands/list.ts +109 -0
  17. package/src/cli/config-schema.ts +36 -0
  18. package/src/cli/index.ts +50 -0
  19. package/src/cli/output-generator.ts +63 -0
  20. package/src/downloader/index.ts +248 -0
  21. package/src/downloader/types.ts +48 -0
  22. package/src/index.ts +8 -0
  23. package/src/schemas/functions/adjust_chroma/adjust-chroma.tokenscript +27 -0
  24. package/src/schemas/functions/adjust_chroma/schema.json +48 -0
  25. package/src/schemas/functions/adjust_chroma/unit.test.ts +76 -0
  26. package/src/schemas/functions/adjust_hue/adjust-hue.tokenscript +32 -0
  27. package/src/schemas/functions/adjust_hue/schema.json +48 -0
  28. package/src/schemas/functions/adjust_hue/unit.test.ts +68 -0
  29. package/src/schemas/functions/adjust_lightness/adjust-lightness.tokenscript +31 -0
  30. package/src/schemas/functions/adjust_lightness/schema.json +48 -0
  31. package/src/schemas/functions/adjust_lightness/unit.test.ts +88 -0
  32. package/src/schemas/functions/adjust_to_contrast/adjust-to-contrast.tokenscript +131 -0
  33. package/src/schemas/functions/adjust_to_contrast/schema.json +56 -0
  34. package/src/schemas/functions/adjust_to_contrast/unit.test.ts +81 -0
  35. package/src/schemas/functions/alpha_blend/alpha-blend.tokenscript +46 -0
  36. package/src/schemas/functions/alpha_blend/schema.json +28 -0
  37. package/src/schemas/functions/alpha_blend/unit.test.ts +135 -0
  38. package/src/schemas/functions/alpha_scale/alpha-scale.tokenscript +38 -0
  39. package/src/schemas/functions/alpha_scale/schema.json +24 -0
  40. package/src/schemas/functions/alpha_scale/unit.test.ts +50 -0
  41. package/src/schemas/functions/analogous/analogous.tokenscript +47 -0
  42. package/src/schemas/functions/analogous/schema.json +28 -0
  43. package/src/schemas/functions/analogous/unit.test.ts +64 -0
  44. package/src/schemas/functions/apca_contrast/apca-contrast.tokenscript +129 -0
  45. package/src/schemas/functions/apca_contrast/schema.json +24 -0
  46. package/src/schemas/functions/apca_contrast/unit.test.ts +259 -0
  47. package/src/schemas/functions/are_similar/are-similar.tokenscript +24 -0
  48. package/src/schemas/functions/are_similar/schema.json +57 -0
  49. package/src/schemas/functions/are_similar/unit.test.ts +57 -0
  50. package/src/schemas/functions/auto_text_color/auto-text-color.tokenscript +41 -0
  51. package/src/schemas/functions/auto_text_color/schema.json +53 -0
  52. package/src/schemas/functions/auto_text_color/unit.test.ts +122 -0
  53. package/src/schemas/functions/best_contrast/best-contrast.tokenscript +66 -0
  54. package/src/schemas/functions/best_contrast/schema.json +24 -0
  55. package/src/schemas/functions/best_contrast/unit.test.ts +64 -0
  56. package/src/schemas/functions/chroma/chroma.tokenscript +12 -0
  57. package/src/schemas/functions/chroma/schema.json +44 -0
  58. package/src/schemas/functions/chroma/unit.test.ts +86 -0
  59. package/src/schemas/functions/clamp_chroma/clamp-chroma.tokenscript +21 -0
  60. package/src/schemas/functions/clamp_chroma/schema.json +52 -0
  61. package/src/schemas/functions/clamp_chroma/unit.test.ts +60 -0
  62. package/src/schemas/functions/clamp_lightness/clamp-lightness.tokenscript +21 -0
  63. package/src/schemas/functions/clamp_lightness/schema.json +52 -0
  64. package/src/schemas/functions/clamp_lightness/unit.test.ts +76 -0
  65. package/src/schemas/functions/clamp_to_gamut/clamp-to-gamut.tokenscript +41 -0
  66. package/src/schemas/functions/clamp_to_gamut/schema.json +20 -0
  67. package/src/schemas/functions/clamp_to_gamut/unit.test.ts +167 -0
  68. package/src/schemas/functions/complement/complement.tokenscript +21 -0
  69. package/src/schemas/functions/complement/schema.json +20 -0
  70. package/src/schemas/functions/complement/unit.test.ts +81 -0
  71. package/src/schemas/functions/contrast_ratio/contrast-ratio.tokenscript +36 -0
  72. package/src/schemas/functions/contrast_ratio/schema.json +24 -0
  73. package/src/schemas/functions/contrast_ratio/unit.test.ts +91 -0
  74. package/src/schemas/functions/cooler/cooler.tokenscript +45 -0
  75. package/src/schemas/functions/cooler/schema.json +43 -0
  76. package/src/schemas/functions/cooler/unit.test.ts +69 -0
  77. package/src/schemas/functions/darken/darken.tokenscript +37 -0
  78. package/src/schemas/functions/darken/schema.json +24 -0
  79. package/src/schemas/functions/darken/unit.test.ts +105 -0
  80. package/src/schemas/functions/delta_e_2000/delta-e-2000.tokenscript +184 -0
  81. package/src/schemas/functions/delta_e_2000/schema.json +36 -0
  82. package/src/schemas/functions/delta_e_2000/unit.test.ts +243 -0
  83. package/src/schemas/functions/delta_e_76/delta-e-76.tokenscript +45 -0
  84. package/src/schemas/functions/delta_e_76/schema.json +24 -0
  85. package/src/schemas/functions/delta_e_76/unit.test.ts +123 -0
  86. package/src/schemas/functions/delta_e_ok/delta-e-ok.tokenscript +43 -0
  87. package/src/schemas/functions/delta_e_ok/schema.json +24 -0
  88. package/src/schemas/functions/delta_e_ok/unit.test.ts +235 -0
  89. package/src/schemas/functions/desaturate/desaturate.tokenscript +32 -0
  90. package/src/schemas/functions/desaturate/schema.json +24 -0
  91. package/src/schemas/functions/desaturate/unit.test.ts +54 -0
  92. package/src/schemas/functions/distributed/distributed.tokenscript +54 -0
  93. package/src/schemas/functions/distributed/schema.json +32 -0
  94. package/src/schemas/functions/distributed/unit.test.ts +58 -0
  95. package/src/schemas/functions/diverging/diverging.tokenscript +58 -0
  96. package/src/schemas/functions/diverging/schema.json +32 -0
  97. package/src/schemas/functions/diverging/unit.test.ts +70 -0
  98. package/src/schemas/functions/grayscale/grayscale.tokenscript +17 -0
  99. package/src/schemas/functions/grayscale/schema.json +20 -0
  100. package/src/schemas/functions/grayscale/unit.test.ts +79 -0
  101. package/src/schemas/functions/harmonize/harmonize.tokenscript +61 -0
  102. package/src/schemas/functions/harmonize/schema.json +52 -0
  103. package/src/schemas/functions/harmonize/unit.test.ts +56 -0
  104. package/src/schemas/functions/hue/hue.tokenscript +12 -0
  105. package/src/schemas/functions/hue/schema.json +44 -0
  106. package/src/schemas/functions/hue/unit.test.ts +75 -0
  107. package/src/schemas/functions/hue_difference/hue-difference.tokenscript +42 -0
  108. package/src/schemas/functions/hue_difference/schema.json +24 -0
  109. package/src/schemas/functions/hue_difference/unit.test.ts +125 -0
  110. package/src/schemas/functions/in_gamut/in-gamut.tokenscript +51 -0
  111. package/src/schemas/functions/in_gamut/schema.json +24 -0
  112. package/src/schemas/functions/in_gamut/unit.test.ts +178 -0
  113. package/src/schemas/functions/interpolate/interpolate.tokenscript +61 -0
  114. package/src/schemas/functions/interpolate/schema.json +52 -0
  115. package/src/schemas/functions/interpolate/unit.test.ts +96 -0
  116. package/src/schemas/functions/invert/invert-initializer.tokenscript +29 -0
  117. package/src/schemas/functions/invert/schema.json +20 -0
  118. package/src/schemas/functions/invert/unit.test.ts +216 -0
  119. package/src/schemas/functions/is_cool/is-cool.tokenscript +41 -0
  120. package/src/schemas/functions/is_cool/schema.json +20 -0
  121. package/src/schemas/functions/is_cool/unit.test.ts +189 -0
  122. package/src/schemas/functions/is_dark/is-dark.tokenscript +16 -0
  123. package/src/schemas/functions/is_dark/schema.json +24 -0
  124. package/src/schemas/functions/is_dark/unit.test.ts +87 -0
  125. package/src/schemas/functions/is_light/is-light.tokenscript +16 -0
  126. package/src/schemas/functions/is_light/schema.json +24 -0
  127. package/src/schemas/functions/is_light/unit.test.ts +86 -0
  128. package/src/schemas/functions/is_neutral/is-neutral.tokenscript +16 -0
  129. package/src/schemas/functions/is_neutral/schema.json +53 -0
  130. package/src/schemas/functions/is_neutral/unit.test.ts +85 -0
  131. package/src/schemas/functions/is_warm/is-warm.tokenscript +62 -0
  132. package/src/schemas/functions/is_warm/schema.json +20 -0
  133. package/src/schemas/functions/is_warm/unit.test.ts +161 -0
  134. package/src/schemas/functions/lighten/lighten.tokenscript +37 -0
  135. package/src/schemas/functions/lighten/schema.json +24 -0
  136. package/src/schemas/functions/lighten/unit.test.ts +109 -0
  137. package/src/schemas/functions/lightness/lightness.tokenscript +12 -0
  138. package/src/schemas/functions/lightness/schema.json +49 -0
  139. package/src/schemas/functions/lightness/unit.test.ts +99 -0
  140. package/src/schemas/functions/luminance/luminance.tokenscript +16 -0
  141. package/src/schemas/functions/luminance/schema.json +20 -0
  142. package/src/schemas/functions/luminance/unit.test.ts +105 -0
  143. package/src/schemas/functions/meets_contrast/meets-contrast.tokenscript +49 -0
  144. package/src/schemas/functions/meets_contrast/schema.json +28 -0
  145. package/src/schemas/functions/meets_contrast/unit.test.ts +170 -0
  146. package/src/schemas/functions/mix/mix.tokenscript +47 -0
  147. package/src/schemas/functions/mix/schema.json +28 -0
  148. package/src/schemas/functions/mix/unit.test.ts +95 -0
  149. package/src/schemas/functions/monochromatic/monochromatic.tokenscript +72 -0
  150. package/src/schemas/functions/monochromatic/schema.json +24 -0
  151. package/src/schemas/functions/monochromatic/unit.test.ts +91 -0
  152. package/src/schemas/functions/muted/muted.tokenscript +25 -0
  153. package/src/schemas/functions/muted/schema.json +48 -0
  154. package/src/schemas/functions/muted/unit.test.ts +100 -0
  155. package/src/schemas/functions/neutral_variant/neutral-variant.tokenscript +23 -0
  156. package/src/schemas/functions/neutral_variant/schema.json +48 -0
  157. package/src/schemas/functions/neutral_variant/unit.test.ts +102 -0
  158. package/src/schemas/functions/relative_luminance/relative-luminance.tokenscript +15 -0
  159. package/src/schemas/functions/relative_luminance/schema.json +49 -0
  160. package/src/schemas/functions/relative_luminance/unit.test.ts +104 -0
  161. package/src/schemas/functions/rotate_hue/rotate-hue.tokenscript +20 -0
  162. package/src/schemas/functions/rotate_hue/schema.json +24 -0
  163. package/src/schemas/functions/rotate_hue/unit.test.ts +86 -0
  164. package/src/schemas/functions/saturate/saturate.tokenscript +33 -0
  165. package/src/schemas/functions/saturate/schema.json +24 -0
  166. package/src/schemas/functions/saturate/unit.test.ts +59 -0
  167. package/src/schemas/functions/scale_chroma/scale-chroma.tokenscript +22 -0
  168. package/src/schemas/functions/scale_chroma/schema.json +48 -0
  169. package/src/schemas/functions/scale_chroma/unit.test.ts +79 -0
  170. package/src/schemas/functions/scale_lightness/scale-lightness.tokenscript +23 -0
  171. package/src/schemas/functions/scale_lightness/schema.json +48 -0
  172. package/src/schemas/functions/scale_lightness/unit.test.ts +73 -0
  173. package/src/schemas/functions/sepia/schema.json +48 -0
  174. package/src/schemas/functions/sepia/sepia.tokenscript +54 -0
  175. package/src/schemas/functions/sepia/unit.test.ts +88 -0
  176. package/src/schemas/functions/set_chroma/schema.json +24 -0
  177. package/src/schemas/functions/set_chroma/set-chroma.tokenscript +18 -0
  178. package/src/schemas/functions/set_chroma/unit.test.ts +79 -0
  179. package/src/schemas/functions/set_hue/schema.json +24 -0
  180. package/src/schemas/functions/set_hue/set-hue.tokenscript +18 -0
  181. package/src/schemas/functions/set_hue/unit.test.ts +90 -0
  182. package/src/schemas/functions/set_lightness/schema.json +24 -0
  183. package/src/schemas/functions/set_lightness/set-lightness.tokenscript +18 -0
  184. package/src/schemas/functions/set_lightness/unit.test.ts +80 -0
  185. package/src/schemas/functions/shade_scale/schema.json +24 -0
  186. package/src/schemas/functions/shade_scale/shade-scale.tokenscript +61 -0
  187. package/src/schemas/functions/shade_scale/unit.test.ts +64 -0
  188. package/src/schemas/functions/split_complement/schema.json +24 -0
  189. package/src/schemas/functions/split_complement/split-complement.tokenscript +38 -0
  190. package/src/schemas/functions/split_complement/unit.test.ts +53 -0
  191. package/src/schemas/functions/steps/schema.json +28 -0
  192. package/src/schemas/functions/steps/steps.tokenscript +54 -0
  193. package/src/schemas/functions/steps/unit.test.ts +71 -0
  194. package/src/schemas/functions/tetradic/schema.json +20 -0
  195. package/src/schemas/functions/tetradic/tetradic.tokenscript +40 -0
  196. package/src/schemas/functions/tetradic/unit.test.ts +50 -0
  197. package/src/schemas/functions/tint_scale/schema.json +32 -0
  198. package/src/schemas/functions/tint_scale/tint-scale.tokenscript +71 -0
  199. package/src/schemas/functions/tint_scale/unit.test.ts +64 -0
  200. package/src/schemas/functions/to_gamut/schema.json +48 -0
  201. package/src/schemas/functions/to_gamut/to-gamut.tokenscript +96 -0
  202. package/src/schemas/functions/to_gamut/unit.test.ts +97 -0
  203. package/src/schemas/functions/triadic/schema.json +20 -0
  204. package/src/schemas/functions/triadic/triadic.tokenscript +33 -0
  205. package/src/schemas/functions/triadic/unit.test.ts +64 -0
  206. package/src/schemas/functions/vibrant/schema.json +48 -0
  207. package/src/schemas/functions/vibrant/unit.test.ts +55 -0
  208. package/src/schemas/functions/vibrant/vibrant.tokenscript +29 -0
  209. package/src/schemas/functions/warmer/schema.json +43 -0
  210. package/src/schemas/functions/warmer/unit.test.ts +69 -0
  211. package/src/schemas/functions/warmer/warmer.tokenscript +45 -0
  212. package/src/schemas/functions/wcag_level/schema.json +48 -0
  213. package/src/schemas/functions/wcag_level/unit.test.ts +75 -0
  214. package/src/schemas/functions/wcag_level/wcag-level.tokenscript +50 -0
  215. package/src/schemas/types/css-color/from-hsl-color.tokenscript +16 -0
  216. package/src/schemas/types/css-color/from-hwb-color.tokenscript +16 -0
  217. package/src/schemas/types/css-color/from-lab-color.tokenscript +16 -0
  218. package/src/schemas/types/css-color/from-lch-color.tokenscript +16 -0
  219. package/src/schemas/types/css-color/from-oklab-color.tokenscript +16 -0
  220. package/src/schemas/types/css-color/from-oklch-color.tokenscript +16 -0
  221. package/src/schemas/types/css-color/from-p3-color.tokenscript +16 -0
  222. package/src/schemas/types/css-color/from-rgb-color.tokenscript +15 -0
  223. package/src/schemas/types/css-color/from-srgb-color.tokenscript +16 -0
  224. package/src/schemas/types/css-color/from-srgb-linear-color.tokenscript +16 -0
  225. package/src/schemas/types/css-color/from-xyz-d50-color.tokenscript +16 -0
  226. package/src/schemas/types/css-color/from-xyz-d65-color.tokenscript +16 -0
  227. package/src/schemas/types/css-color/initializer.tokenscript +13 -0
  228. package/src/schemas/types/css-color/schema.json +148 -0
  229. package/src/schemas/types/css-color/unit.test.ts +402 -0
  230. package/src/schemas/types/hex-color/initializer.tokenscript +3 -0
  231. package/src/schemas/types/hex-color/schema.json +24 -0
  232. package/src/schemas/types/hex-color/unit.test.ts +123 -0
  233. package/src/schemas/types/hsl-color/from-srgb.tokenscript +87 -0
  234. package/src/schemas/types/hsl-color/initializer.tokenscript +16 -0
  235. package/src/schemas/types/hsl-color/schema.json +48 -0
  236. package/src/schemas/types/hsl-color/unit.test.ts +201 -0
  237. package/src/schemas/types/hsv-color/from-srgb.tokenscript +80 -0
  238. package/src/schemas/types/hsv-color/initializer.tokenscript +16 -0
  239. package/src/schemas/types/hsv-color/schema.json +48 -0
  240. package/src/schemas/types/hsv-color/unit.test.ts +162 -0
  241. package/src/schemas/types/hwb-color/from-hsv.tokenscript +31 -0
  242. package/src/schemas/types/hwb-color/initializer.tokenscript +16 -0
  243. package/src/schemas/types/hwb-color/schema.json +48 -0
  244. package/src/schemas/types/hwb-color/unit.test.ts +150 -0
  245. package/src/schemas/types/lab-color/from-xyz-d50.tokenscript +78 -0
  246. package/src/schemas/types/lab-color/initializer.tokenscript +16 -0
  247. package/src/schemas/types/lab-color/schema.json +48 -0
  248. package/src/schemas/types/lab-color/unit.test.ts +263 -0
  249. package/src/schemas/types/lch-color/from-lab.tokenscript +44 -0
  250. package/src/schemas/types/lch-color/initializer.tokenscript +16 -0
  251. package/src/schemas/types/lch-color/schema.json +48 -0
  252. package/src/schemas/types/lch-color/unit.test.ts +173 -0
  253. package/src/schemas/types/okhsl-color/from-oklab.tokenscript +410 -0
  254. package/src/schemas/types/okhsl-color/initializer.tokenscript +24 -0
  255. package/src/schemas/types/okhsl-color/schema.json +48 -0
  256. package/src/schemas/types/okhsl-color/unit.test.ts +514 -0
  257. package/src/schemas/types/okhsv-color/from-oklab.tokenscript +286 -0
  258. package/src/schemas/types/okhsv-color/initializer.tokenscript +24 -0
  259. package/src/schemas/types/okhsv-color/schema.json +48 -0
  260. package/src/schemas/types/okhsv-color/unit.test.ts +499 -0
  261. package/src/schemas/types/oklab-color/from-okhsl.tokenscript +195 -0
  262. package/src/schemas/types/oklab-color/from-okhsv.tokenscript +197 -0
  263. package/src/schemas/types/oklab-color/from-oklch.tokenscript +39 -0
  264. package/src/schemas/types/oklab-color/from-xyz-d65.tokenscript +43 -0
  265. package/src/schemas/types/oklab-color/initializer.tokenscript +16 -0
  266. package/src/schemas/types/oklab-color/schema.json +78 -0
  267. package/src/schemas/types/oklab-color/unit.test.ts +345 -0
  268. package/src/schemas/types/oklch-color/from-oklab.tokenscript +45 -0
  269. package/src/schemas/types/oklch-color/initializer.tokenscript +16 -0
  270. package/src/schemas/types/oklch-color/schema.json +48 -0
  271. package/src/schemas/types/oklch-color/unit.test.ts +267 -0
  272. package/src/schemas/types/p3-color/from-p3-linear.tokenscript +59 -0
  273. package/src/schemas/types/p3-color/initializer.tokenscript +16 -0
  274. package/src/schemas/types/p3-color/schema.json +48 -0
  275. package/src/schemas/types/p3-color/unit.test.ts +119 -0
  276. package/src/schemas/types/p3-linear-color/from-xyz-d65.tokenscript +47 -0
  277. package/src/schemas/types/p3-linear-color/initializer.tokenscript +16 -0
  278. package/src/schemas/types/p3-linear-color/schema.json +48 -0
  279. package/src/schemas/types/p3-linear-color/unit.test.ts +82 -0
  280. package/src/schemas/types/rgb-color/from-hex.tokenscript +43 -0
  281. package/src/schemas/types/rgb-color/initializer.tokenscript +16 -0
  282. package/src/schemas/types/rgb-color/schema.json +55 -0
  283. package/src/schemas/types/rgb-color/to-hex.tokenscript +42 -0
  284. package/src/schemas/types/rgb-color/unit.test.ts +302 -0
  285. package/src/schemas/types/srgb-color/from-hsl.tokenscript +106 -0
  286. package/src/schemas/types/srgb-color/from-linear.tokenscript +58 -0
  287. package/src/schemas/types/srgb-color/from-rgb.tokenscript +20 -0
  288. package/src/schemas/types/srgb-color/initializer.tokenscript +16 -0
  289. package/src/schemas/types/srgb-color/schema.json +68 -0
  290. package/src/schemas/types/srgb-color/unit.test.ts +303 -0
  291. package/src/schemas/types/srgb-linear-color/from-srgb.tokenscript +55 -0
  292. package/src/schemas/types/srgb-linear-color/from-xyz-d65.tokenscript +34 -0
  293. package/src/schemas/types/srgb-linear-color/initializer.tokenscript +13 -0
  294. package/src/schemas/types/srgb-linear-color/schema.json +58 -0
  295. package/src/schemas/types/srgb-linear-color/unit.test.ts +291 -0
  296. package/src/schemas/types/xyz-d50-color/from-xyz-d65.tokenscript +36 -0
  297. package/src/schemas/types/xyz-d50-color/initializer.tokenscript +16 -0
  298. package/src/schemas/types/xyz-d50-color/schema.json +48 -0
  299. package/src/schemas/types/xyz-d50-color/unit.test.ts +240 -0
  300. package/src/schemas/types/xyz-d65-color/from-linear-p3.tokenscript +47 -0
  301. package/src/schemas/types/xyz-d65-color/from-linear-srgb.tokenscript +38 -0
  302. package/src/schemas/types/xyz-d65-color/from-oklab.tokenscript +44 -0
  303. package/src/schemas/types/xyz-d65-color/initializer.tokenscript +16 -0
  304. package/src/schemas/types/xyz-d65-color/schema.json +68 -0
  305. package/src/schemas/types/xyz-d65-color/unit.test.ts +319 -0
  306. package/src/utils/schema-uri.ts +192 -0
  307. package/src/utils/type.ts +194 -0
@@ -0,0 +1,291 @@
1
+ /**
2
+ * Linear sRGB Color Schema Tests
3
+ *
4
+ * Tests for the Linear sRGB color space (gamma-decoded)
5
+ * Validates against ColorJS for parity
6
+ */
7
+
8
+ import { log } from "@tests/helpers/logger";
9
+ import { executeWithSchema, getBundledSchema } from "@tests/helpers/schema-test-utils";
10
+ import Color from "colorjs.io";
11
+ import { describe, expect, it } from "vitest";
12
+ import type { ColorSpecification } from "@/bundler/types";
13
+
14
+ // ColorJS reference tolerance
15
+ const TOLERANCE = 1e-9;
16
+
17
+ describe("Linear sRGB Color Schema", () => {
18
+ describe("Schema Definition", () => {
19
+ it("should have correct schema structure", async () => {
20
+ const schema = (await getBundledSchema("srgb-linear-color")) as ColorSpecification;
21
+
22
+ expect(schema.name).toBe("LinearSRGB");
23
+ expect(schema.type).toBe("color");
24
+ expect(schema.schema).toBeDefined();
25
+ expect(schema.schema?.properties).toHaveProperty("r");
26
+ expect(schema.schema?.properties).toHaveProperty("g");
27
+ expect(schema.schema?.properties).toHaveProperty("b");
28
+ expect(schema.schema?.required).toEqual(["r", "g", "b"]);
29
+ });
30
+
31
+ it("should have linearsrgb initializer", async () => {
32
+ const schema = (await getBundledSchema("srgb-linear-color")) as ColorSpecification;
33
+
34
+ expect(schema.initializers).toHaveLength(1);
35
+ expect(schema.initializers[0].keyword).toBe("linearsrgb");
36
+ expect(schema.initializers[0].script.script).toContain("Color.LinearSRGB");
37
+ });
38
+
39
+ it("should have conversion from sRGB", async () => {
40
+ const schema = (await getBundledSchema("srgb-linear-color")) as ColorSpecification;
41
+
42
+ expect(schema.conversions.length).toBeGreaterThanOrEqual(1);
43
+
44
+ const srgbToLinear = schema.conversions.find((c: { source: string }) =>
45
+ c.source.includes("srgb-color"),
46
+ );
47
+ expect(srgbToLinear).toBeDefined();
48
+ expect(srgbToLinear?.lossless).toBe(true);
49
+ });
50
+ });
51
+
52
+ describe("Initialization", () => {
53
+ it("should create linear sRGB color from values", async () => {
54
+ const result = await executeWithSchema(
55
+ "srgb-linear-color",
56
+ "type",
57
+ `
58
+ variable c: Color.LinearSRGB;
59
+ c.r = 0.5;
60
+ c.g = 0.25;
61
+ c.b = 0.1;
62
+ c
63
+ `,
64
+ );
65
+
66
+ expect(result?.constructor.name).toBe("ColorSymbol");
67
+ expect((result as any).subType).toBe("LinearSRGB");
68
+ expect((result as any).value.r.value).toBeCloseTo(0.5, 10);
69
+ expect((result as any).value.g.value).toBeCloseTo(0.25, 10);
70
+ expect((result as any).value.b.value).toBeCloseTo(0.1, 10);
71
+ });
72
+ });
73
+
74
+ describe("Conversion from sRGB to Linear sRGB", () => {
75
+ it("should convert sRGB red to linear sRGB", async () => {
76
+ const result = await executeWithSchema(
77
+ "srgb-linear-color",
78
+ "type",
79
+ `
80
+ variable srgb: Color.SRGB;
81
+ srgb.r = 1;
82
+ srgb.g = 0;
83
+ srgb.b = 0;
84
+ srgb.to.linearsrgb()
85
+ `,
86
+ );
87
+
88
+ // ColorJS reference
89
+ const colorJS = new Color("srgb", [1, 0, 0]).to("srgb-linear");
90
+
91
+ expect(result?.constructor.name).toBe("ColorSymbol");
92
+ expect((result as any).subType).toBe("LinearSRGB");
93
+ expect((result as any).value.r.value).toBeCloseTo(colorJS.coords[0], 9);
94
+ expect((result as any).value.g.value).toBeCloseTo(colorJS.coords[1], 9);
95
+ expect((result as any).value.b.value).toBeCloseTo(colorJS.coords[2], 9);
96
+ });
97
+
98
+ it("should convert mid-gray sRGB to linear (tests gamma curve)", async () => {
99
+ // Mid-gray (0.5) is a good test for the gamma curve
100
+ // Linear value should be ~0.214 (not 0.5!)
101
+ const result = await executeWithSchema(
102
+ "srgb-linear-color",
103
+ "type",
104
+ `
105
+ variable srgb: Color.SRGB;
106
+ srgb.r = 0.5;
107
+ srgb.g = 0.5;
108
+ srgb.b = 0.5;
109
+ srgb.to.linearsrgb()
110
+ `,
111
+ );
112
+
113
+ // ColorJS reference
114
+ const colorJS = new Color("srgb", [0.5, 0.5, 0.5]).to("srgb-linear");
115
+
116
+ log.info(`\n=== MID-GRAY Gamma Conversion ===`);
117
+ log.info(`Input sRGB: { r: 0.5, g: 0.5, b: 0.5 }`);
118
+ log.info(
119
+ `TokenScript: { r: ${(result as any).value.r.value}, g: ${(result as any).value.g.value}, b: ${(result as any).value.b.value} }`,
120
+ );
121
+ log.info(
122
+ `ColorJS: { r: ${colorJS.coords[0]}, g: ${colorJS.coords[1]}, b: ${colorJS.coords[2]} }`,
123
+ );
124
+
125
+ expect((result as any).value.r.value).toBeCloseTo(colorJS.coords[0], 9);
126
+ expect((result as any).value.g.value).toBeCloseTo(colorJS.coords[1], 9);
127
+ expect((result as any).value.b.value).toBeCloseTo(colorJS.coords[2], 9);
128
+ });
129
+
130
+ it("should handle linear region (sRGB ≤ 0.04045)", async () => {
131
+ // Test value below threshold - should use linear formula
132
+ const result = await executeWithSchema(
133
+ "srgb-linear-color",
134
+ "type",
135
+ `
136
+ variable srgb: Color.SRGB;
137
+ srgb.r = 0.03;
138
+ srgb.g = 0.03;
139
+ srgb.b = 0.03;
140
+ srgb.to.linearsrgb()
141
+ `,
142
+ );
143
+
144
+ // ColorJS reference
145
+ const colorJS = new Color("srgb", [0.03, 0.03, 0.03]).to("srgb-linear");
146
+
147
+ // Linear formula: 0.03 / 12.92 ≈ 0.00232
148
+ expect((result as any).value.r.value).toBeCloseTo(colorJS.coords[0], 9);
149
+ expect((result as any).value.g.value).toBeCloseTo(colorJS.coords[1], 9);
150
+ expect((result as any).value.b.value).toBeCloseTo(colorJS.coords[2], 9);
151
+ });
152
+
153
+ it("should handle threshold boundary (0.04045)", async () => {
154
+ // Test exactly at threshold
155
+ const result = await executeWithSchema(
156
+ "srgb-linear-color",
157
+ "type",
158
+ `
159
+ variable srgb: Color.SRGB;
160
+ srgb.r = 0.04045;
161
+ srgb.g = 0.04045;
162
+ srgb.b = 0.04045;
163
+ srgb.to.linearsrgb()
164
+ `,
165
+ );
166
+
167
+ const colorJS = new Color("srgb", [0.04045, 0.04045, 0.04045]).to("srgb-linear");
168
+
169
+ expect((result as any).value.r.value).toBeCloseTo(colorJS.coords[0], 9);
170
+ });
171
+ });
172
+
173
+ describe("ColorJS Parity", () => {
174
+ const testCases = [
175
+ { name: "red", srgb: [1, 0, 0] },
176
+ { name: "green", srgb: [0, 1, 0] },
177
+ { name: "blue", srgb: [0, 0, 1] },
178
+ { name: "black", srgb: [0, 0, 0] },
179
+ { name: "white", srgb: [1, 1, 1] },
180
+ { name: "gray-50%", srgb: [0.5, 0.5, 0.5] },
181
+ { name: "gray-21.8%", srgb: [0.218, 0.218, 0.218] }, // Linear 0.04 approx
182
+ { name: "coral", srgb: [1, 0.341, 0.2] },
183
+ { name: "near-black", srgb: [0.01, 0.01, 0.01] },
184
+ { name: "near-white", srgb: [0.99, 0.99, 0.99] },
185
+ ];
186
+
187
+ for (const { name, srgb } of testCases) {
188
+ it(`should match ColorJS for ${name}`, async () => {
189
+ const result = await executeWithSchema(
190
+ "srgb-linear-color",
191
+ "type",
192
+ `
193
+ variable srgb: Color.SRGB;
194
+ srgb.r = ${srgb[0]};
195
+ srgb.g = ${srgb[1]};
196
+ srgb.b = ${srgb[2]};
197
+ srgb.to.linearsrgb()
198
+ `,
199
+ );
200
+
201
+ // ColorJS reference
202
+ const colorJS = new Color("srgb", srgb as [number, number, number]).to("srgb-linear");
203
+
204
+ const tsR = (result as any).value.r.value;
205
+ const tsG = (result as any).value.g.value;
206
+ const tsB = (result as any).value.b.value;
207
+
208
+ const diffR = Math.abs(tsR - colorJS.coords[0]);
209
+ const diffG = Math.abs(tsG - colorJS.coords[1]);
210
+ const diffB = Math.abs(tsB - colorJS.coords[2]);
211
+ const maxDiff = Math.max(diffR, diffG, diffB);
212
+
213
+ log.info(`\n=== ${name.toUpperCase()} ColorJS Parity ===`);
214
+ log.info(`Input sRGB: { r: ${srgb[0]}, g: ${srgb[1]}, b: ${srgb[2]} }`);
215
+ log.info(
216
+ `TokenScript: { r: ${tsR.toFixed(9)}, g: ${tsG.toFixed(9)}, b: ${tsB.toFixed(9)} }`,
217
+ );
218
+ log.info(
219
+ `ColorJS: { r: ${colorJS.coords[0].toFixed(9)}, g: ${colorJS.coords[1].toFixed(9)}, b: ${colorJS.coords[2].toFixed(9)} }`,
220
+ );
221
+ log.info(`Max Diff: ${maxDiff.toExponential(2)}`);
222
+ log.info(`Status: ${maxDiff < TOLERANCE ? "✅ PASS" : "❌ FAIL"}`);
223
+
224
+ expect(maxDiff).toBeLessThan(TOLERANCE);
225
+ });
226
+ }
227
+ });
228
+
229
+ describe("Edge Cases", () => {
230
+ it("should handle pure black (0, 0, 0)", async () => {
231
+ const result = await executeWithSchema(
232
+ "srgb-linear-color",
233
+ "type",
234
+ `
235
+ variable srgb: Color.SRGB;
236
+ srgb.r = 0;
237
+ srgb.g = 0;
238
+ srgb.b = 0;
239
+ srgb.to.linearsrgb()
240
+ `,
241
+ );
242
+
243
+ expect((result as any).value.r.value).toBe(0);
244
+ expect((result as any).value.g.value).toBe(0);
245
+ expect((result as any).value.b.value).toBe(0);
246
+ });
247
+
248
+ it("should handle pure white (1, 1, 1)", async () => {
249
+ const result = await executeWithSchema(
250
+ "srgb-linear-color",
251
+ "type",
252
+ `
253
+ variable srgb: Color.SRGB;
254
+ srgb.r = 1;
255
+ srgb.g = 1;
256
+ srgb.b = 1;
257
+ srgb.to.linearsrgb()
258
+ `,
259
+ );
260
+
261
+ expect((result as any).value.r.value).toBeCloseTo(1, 9);
262
+ expect((result as any).value.g.value).toBeCloseTo(1, 9);
263
+ expect((result as any).value.b.value).toBeCloseTo(1, 9);
264
+ });
265
+ });
266
+
267
+ describe("Conversion Chain: RGB → sRGB → Linear sRGB", () => {
268
+ it("should convert RGB 255 through to linear sRGB", async () => {
269
+ const result = await executeWithSchema(
270
+ "srgb-linear-color",
271
+ "type",
272
+ `
273
+ variable rgb: Color.Rgb;
274
+ rgb.r = 255;
275
+ rgb.g = 128;
276
+ rgb.b = 64;
277
+
278
+ variable srgb: Color.SRGB = rgb.to.srgb();
279
+ srgb.to.linearsrgb()
280
+ `,
281
+ );
282
+
283
+ // ColorJS reference: RGB → sRGB → Linear sRGB
284
+ const colorJS = new Color("srgb", [1, 128 / 255, 64 / 255]).to("srgb-linear");
285
+
286
+ expect((result as any).value.r.value).toBeCloseTo(colorJS.coords[0], 9);
287
+ expect((result as any).value.g.value).toBeCloseTo(colorJS.coords[1], 9);
288
+ expect((result as any).value.b.value).toBeCloseTo(colorJS.coords[2], 9);
289
+ });
290
+ });
291
+ });
@@ -0,0 +1,36 @@
1
+ // XYZ-D65 to XYZ-D50 Conversion
2
+ // Chromatic adaptation using Bradford transform
3
+ // Reference: https://github.com/color-js/color.js/blob/main/src/adapt.js
4
+ //
5
+ // Bradford CAT matrix for D65 → D50:
6
+ // [1.0479298 0.0229469 -0.0501923]
7
+ // [0.0296278 0.9904344 -0.0170738]
8
+ // [-0.0092430 0.0150552 0.7518743]
9
+ //
10
+ // Input: Color.XYZD65 with x, y, z tristimulus (D65 white)
11
+ // Output: Color.XYZD50 with x, y, z tristimulus (D50 white)
12
+
13
+ // Get input XYZ-D65 values
14
+ variable x65: Number = {input}.x;
15
+ variable y65: Number = {input}.y;
16
+ variable z65: Number = {input}.z;
17
+
18
+ // Bradford chromatic adaptation matrix (ColorJS exact values)
19
+ // Row 1
20
+ variable x50: Number = x65 * 1.0479297925449969 + y65 * 0.022946870601609652 + z65 * -0.05019226628920524;
21
+ // Row 2
22
+ variable y50: Number = x65 * 0.02962780877005599 + y65 * 0.9904344267538799 + z65 * -0.017073799063418826;
23
+ // Row 3
24
+ variable z50: Number = x65 * -0.009243040646204504 + y65 * 0.015055191490298152 + z65 * 0.7518742814281371;
25
+
26
+ // Create output
27
+ variable output: Color.XYZD50;
28
+ output.x = x50;
29
+ output.y = y50;
30
+ output.z = z50;
31
+
32
+ return output;
33
+
34
+
35
+
36
+
@@ -0,0 +1,16 @@
1
+ // XYZ-D50 Color Initializer
2
+ // Creates an XYZ-D50 color from tristimulus values
3
+ // Input: List of [x, y, z] tristimulus values
4
+
5
+ variable xyz_values: List = {input};
6
+ variable output: Color.XYZD50;
7
+
8
+ output.x = xyz_values.get(0);
9
+ output.y = xyz_values.get(1);
10
+ output.z = xyz_values.get(2);
11
+
12
+ return output;
13
+
14
+
15
+
16
+
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "XYZD50",
3
+ "type": "color",
4
+ "description": "CIE XYZ color space with D50 white point. Used for Lab and LCH color spaces.",
5
+ "schema": {
6
+ "type": "object",
7
+ "properties": {
8
+ "x": {
9
+ "type": "number",
10
+ "description": "X tristimulus value"
11
+ },
12
+ "y": {
13
+ "type": "number",
14
+ "description": "Y tristimulus value (luminance)"
15
+ },
16
+ "z": {
17
+ "type": "number",
18
+ "description": "Z tristimulus value"
19
+ }
20
+ },
21
+ "required": ["x", "y", "z"],
22
+ "order": ["x", "y", "z"],
23
+ "additionalProperties": false
24
+ },
25
+ "initializers": [
26
+ {
27
+ "title": "XYZ-D50 Color Initializer",
28
+ "keyword": "xyzd50",
29
+ "description": "Creates an XYZ-D50 color from tristimulus values",
30
+ "script": {
31
+ "type": "/api/v1/core/tokenscript/0/",
32
+ "script": "./initializer.tokenscript"
33
+ }
34
+ }
35
+ ],
36
+ "conversions": [
37
+ {
38
+ "source": "/api/v1/core/xyz-d65-color/0/",
39
+ "target": "$self",
40
+ "description": "Converts XYZ-D65 to XYZ-D50 using Bradford chromatic adaptation",
41
+ "lossless": true,
42
+ "script": {
43
+ "type": "/api/v1/core/tokenscript/0/",
44
+ "script": "./from-xyz-d65.tokenscript"
45
+ }
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,240 @@
1
+ /**
2
+ * XYZ-D50 Color Schema Tests
3
+ *
4
+ * Tests for the CIE XYZ-D50 color space (D50 white point)
5
+ * Validates against ColorJS for parity
6
+ */
7
+
8
+ import { log } from "@tests/helpers/logger";
9
+ import { executeWithSchema, getBundledSchema } from "@tests/helpers/schema-test-utils";
10
+ import Color from "colorjs.io";
11
+ import { describe, expect, it } from "vitest";
12
+ import type { ColorSpecification } from "@/bundler/types";
13
+
14
+ // ColorJS reference tolerance
15
+ const TOLERANCE = 1e-9;
16
+
17
+ describe("XYZ-D50 Color Schema", () => {
18
+ describe("Schema Definition", () => {
19
+ it("should have correct schema structure", async () => {
20
+ const schema = (await getBundledSchema("xyz-d50-color")) as ColorSpecification;
21
+
22
+ expect(schema.name).toBe("XYZD50");
23
+ expect(schema.type).toBe("color");
24
+ expect(schema.schema).toBeDefined();
25
+ expect(schema.schema?.properties).toHaveProperty("x");
26
+ expect(schema.schema?.properties).toHaveProperty("y");
27
+ expect(schema.schema?.properties).toHaveProperty("z");
28
+ expect(schema.schema?.required).toEqual(["x", "y", "z"]);
29
+ });
30
+
31
+ it("should have xyzd50 initializer", async () => {
32
+ const schema = (await getBundledSchema("xyz-d50-color")) as ColorSpecification;
33
+
34
+ expect(schema.initializers).toHaveLength(1);
35
+ expect(schema.initializers[0].keyword).toBe("xyzd50");
36
+ });
37
+
38
+ it("should have conversion from XYZ-D65", async () => {
39
+ const schema = (await getBundledSchema("xyz-d50-color")) as ColorSpecification;
40
+
41
+ expect(schema.conversions).toHaveLength(1);
42
+
43
+ const d65ToD50 = schema.conversions.find((c: { source: string }) =>
44
+ c.source.includes("xyz-d65-color"),
45
+ );
46
+ expect(d65ToD50).toBeDefined();
47
+ expect(d65ToD50?.lossless).toBe(true);
48
+ });
49
+ });
50
+
51
+ describe("Initialization", () => {
52
+ it("should create XYZ-D50 color from values", async () => {
53
+ const result = await executeWithSchema(
54
+ "xyz-d50-color",
55
+ "type",
56
+ `
57
+ variable c: Color.XYZD50;
58
+ c.x = 0.5;
59
+ c.y = 0.4;
60
+ c.z = 0.3;
61
+ c
62
+ `,
63
+ );
64
+
65
+ expect(result?.constructor.name).toBe("ColorSymbol");
66
+ expect((result as any).subType).toBe("XYZD50");
67
+ expect((result as any).value.x.value).toBeCloseTo(0.5, 10);
68
+ expect((result as any).value.y.value).toBeCloseTo(0.4, 10);
69
+ expect((result as any).value.z.value).toBeCloseTo(0.3, 10);
70
+ });
71
+ });
72
+
73
+ describe("Chromatic Adaptation: XYZ-D65 to XYZ-D50", () => {
74
+ it("should convert D65 white point to D50 white point", async () => {
75
+ // D65 white point
76
+ const result = await executeWithSchema(
77
+ "xyz-d50-color",
78
+ "type",
79
+ `
80
+ variable xyz65: Color.XYZD65;
81
+ xyz65.x = 0.95047;
82
+ xyz65.y = 1.0;
83
+ xyz65.z = 1.08883;
84
+ xyz65.to.xyzd50()
85
+ `,
86
+ );
87
+
88
+ // ColorJS reference
89
+ const colorJS = new Color("xyz-d65", [0.95047, 1.0, 1.08883]).to("xyz-d50");
90
+
91
+ log.info(`\n=== D65 White → D50 ===`);
92
+ log.info(`Input D65: { x: 0.95047, y: 1.0, z: 1.08883 }`);
93
+ log.info(
94
+ `TokenScript: { x: ${(result as any).value.x.value}, y: ${(result as any).value.y.value}, z: ${(result as any).value.z.value} }`,
95
+ );
96
+ log.info(
97
+ `ColorJS: { x: ${colorJS.coords[0]}, y: ${colorJS.coords[1]}, z: ${colorJS.coords[2]} }`,
98
+ );
99
+
100
+ expect((result as any).value.x.value).toBeCloseTo(colorJS.coords[0], 9);
101
+ expect((result as any).value.y.value).toBeCloseTo(colorJS.coords[1], 9);
102
+ expect((result as any).value.z.value).toBeCloseTo(colorJS.coords[2], 9);
103
+ });
104
+
105
+ it("should convert red XYZ-D65 to XYZ-D50", async () => {
106
+ // Red in XYZ-D65
107
+ const colorJSRed = new Color("srgb", [1, 0, 0]).to("xyz-d65");
108
+
109
+ const result = await executeWithSchema(
110
+ "xyz-d50-color",
111
+ "type",
112
+ `
113
+ variable xyz65: Color.XYZD65;
114
+ xyz65.x = ${colorJSRed.coords[0]};
115
+ xyz65.y = ${colorJSRed.coords[1]};
116
+ xyz65.z = ${colorJSRed.coords[2]};
117
+ xyz65.to.xyzd50()
118
+ `,
119
+ );
120
+
121
+ const colorJS = new Color("srgb", [1, 0, 0]).to("xyz-d50");
122
+
123
+ expect((result as any).value.x.value).toBeCloseTo(colorJS.coords[0], 9);
124
+ expect((result as any).value.y.value).toBeCloseTo(colorJS.coords[1], 9);
125
+ expect((result as any).value.z.value).toBeCloseTo(colorJS.coords[2], 9);
126
+ });
127
+ });
128
+
129
+ describe("Full Conversion Chain: sRGB → Linear → XYZ-D65 → XYZ-D50", () => {
130
+ it("should convert sRGB red through to XYZ-D50", async () => {
131
+ const result = await executeWithSchema(
132
+ "xyz-d50-color",
133
+ "type",
134
+ `
135
+ variable srgb: Color.SRGB;
136
+ srgb.r = 1;
137
+ srgb.g = 0;
138
+ srgb.b = 0;
139
+
140
+ variable linear: Color.LinearSRGB = srgb.to.linearsrgb();
141
+ variable xyz65: Color.XYZD65 = linear.to.xyzd65();
142
+ xyz65.to.xyzd50()
143
+ `,
144
+ );
145
+
146
+ // ColorJS reference
147
+ const colorJS = new Color("srgb", [1, 0, 0]).to("xyz-d50");
148
+
149
+ log.info(`\n=== sRGB RED → XYZ-D50 (full chain) ===`);
150
+ log.info(
151
+ `TokenScript: { x: ${(result as any).value.x.value}, y: ${(result as any).value.y.value}, z: ${(result as any).value.z.value} }`,
152
+ );
153
+ log.info(
154
+ `ColorJS: { x: ${colorJS.coords[0]}, y: ${colorJS.coords[1]}, z: ${colorJS.coords[2]} }`,
155
+ );
156
+
157
+ expect((result as any).value.x.value).toBeCloseTo(colorJS.coords[0], 9);
158
+ expect((result as any).value.y.value).toBeCloseTo(colorJS.coords[1], 9);
159
+ expect((result as any).value.z.value).toBeCloseTo(colorJS.coords[2], 9);
160
+ });
161
+ });
162
+
163
+ describe("ColorJS Parity", () => {
164
+ const testCases = [
165
+ { name: "red", srgb: [1, 0, 0] },
166
+ { name: "green", srgb: [0, 1, 0] },
167
+ { name: "blue", srgb: [0, 0, 1] },
168
+ { name: "white", srgb: [1, 1, 1] },
169
+ { name: "black", srgb: [0, 0, 0] },
170
+ { name: "gray-50%", srgb: [0.5, 0.5, 0.5] },
171
+ { name: "cyan", srgb: [0, 1, 1] },
172
+ { name: "magenta", srgb: [1, 0, 1] },
173
+ { name: "yellow", srgb: [1, 1, 0] },
174
+ ];
175
+
176
+ for (const { name, srgb } of testCases) {
177
+ it(`should match ColorJS for ${name}`, async () => {
178
+ const result = await executeWithSchema(
179
+ "xyz-d50-color",
180
+ "type",
181
+ `
182
+ variable srgb: Color.SRGB;
183
+ srgb.r = ${srgb[0]};
184
+ srgb.g = ${srgb[1]};
185
+ srgb.b = ${srgb[2]};
186
+
187
+ variable linear: Color.LinearSRGB = srgb.to.linearsrgb();
188
+ variable xyz65: Color.XYZD65 = linear.to.xyzd65();
189
+ xyz65.to.xyzd50()
190
+ `,
191
+ );
192
+
193
+ // ColorJS reference
194
+ const colorJS = new Color("srgb", srgb as [number, number, number]).to("xyz-d50");
195
+
196
+ const tsX = (result as any).value.x.value;
197
+ const tsY = (result as any).value.y.value;
198
+ const tsZ = (result as any).value.z.value;
199
+
200
+ const diffX = Math.abs(tsX - colorJS.coords[0]);
201
+ const diffY = Math.abs(tsY - colorJS.coords[1]);
202
+ const diffZ = Math.abs(tsZ - colorJS.coords[2]);
203
+ const maxDiff = Math.max(diffX, diffY, diffZ);
204
+
205
+ log.info(`\n=== ${name.toUpperCase()} ColorJS Parity ===`);
206
+ log.info(`Input sRGB: { r: ${srgb[0]}, g: ${srgb[1]}, b: ${srgb[2]} }`);
207
+ log.info(
208
+ `TokenScript: { x: ${tsX.toFixed(9)}, y: ${tsY.toFixed(9)}, z: ${tsZ.toFixed(9)} }`,
209
+ );
210
+ log.info(
211
+ `ColorJS: { x: ${colorJS.coords[0].toFixed(9)}, y: ${colorJS.coords[1].toFixed(9)}, z: ${colorJS.coords[2].toFixed(9)} }`,
212
+ );
213
+ log.info(`Max Diff: ${maxDiff.toExponential(2)}`);
214
+ log.info(`Status: ${maxDiff < TOLERANCE ? "✅ PASS" : "❌ FAIL"}`);
215
+
216
+ expect(maxDiff).toBeLessThan(TOLERANCE);
217
+ });
218
+ }
219
+ });
220
+
221
+ describe("Edge Cases", () => {
222
+ it("should handle black (0, 0, 0)", async () => {
223
+ const result = await executeWithSchema(
224
+ "xyz-d50-color",
225
+ "type",
226
+ `
227
+ variable xyz65: Color.XYZD65;
228
+ xyz65.x = 0;
229
+ xyz65.y = 0;
230
+ xyz65.z = 0;
231
+ xyz65.to.xyzd50()
232
+ `,
233
+ );
234
+
235
+ expect((result as any).value.x.value).toBe(0);
236
+ expect((result as any).value.y.value).toBe(0);
237
+ expect((result as any).value.z.value).toBe(0);
238
+ });
239
+ });
240
+ });
@@ -0,0 +1,47 @@
1
+ // Linear P3 to XYZ-D65 Conversion
2
+ // Converts linear Display-P3 RGB to CIE XYZ (D65)
3
+ // Reference: CSS Color Level 4 specification
4
+ //
5
+ // Uses the P3 to XYZ-D65 transformation matrix
6
+ // Matrix values from ColorJS / CSS Color Level 4
7
+ //
8
+ // Input: Color.LinearP3 with linear r, g, b values
9
+ // Output: Color.XYZD65 with x, y, z tristimulus values
10
+
11
+ // Get linear P3 values
12
+ variable r: Number = {input}.r;
13
+ variable g: Number = {input}.g;
14
+ variable b: Number = {input}.b;
15
+
16
+ // Linear P3 to XYZ-D65 matrix
17
+ // Row 1
18
+ variable m00: Number = 0.4865709486482162;
19
+ variable m01: Number = 0.26566769316909306;
20
+ variable m02: Number = 0.1982172852343625;
21
+
22
+ // Row 2
23
+ variable m10: Number = 0.2289745640697488;
24
+ variable m11: Number = 0.6917385218365064;
25
+ variable m12: Number = 0.079286914093745;
26
+
27
+ // Row 3
28
+ variable m20: Number = 0.0;
29
+ variable m21: Number = 0.04511338185890264;
30
+ variable m22: Number = 1.043944368900976;
31
+
32
+ // Matrix multiplication: [x, y, z] = M × [r, g, b]
33
+ variable x: Number = m00 * r + m01 * g + m02 * b;
34
+ variable y: Number = m10 * r + m11 * g + m12 * b;
35
+ variable z: Number = m20 * r + m21 * g + m22 * b;
36
+
37
+ // Create output
38
+ variable output: Color.XYZD65;
39
+ output.x = x;
40
+ output.y = y;
41
+ output.z = z;
42
+
43
+ return output;
44
+
45
+
46
+
47
+