Skip to content

Commit

Permalink
feat: ESM support fixes, perf, tests, hex RGBA
Browse files Browse the repository at this point in the history
  • Loading branch information
miyaokamarina committed Nov 17, 2019
1 parent e4f560d commit 2055f6e
Show file tree
Hide file tree
Showing 14 changed files with 16,557 additions and 119 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# @ripreact/hsl

> Minimal (≈560 bytes minigzip) [HSLᵤᵥ](http://hsluv.org) implementation with
> TypeScript support.
> Minimal (≈650 bytes minigzip) and fast (≈13% faster than original)
> [HSLᵤᵥ](http://hsluv.org) implementation with TypeScript support.
```shell script
yarn add @ripreact/hsl
Expand All @@ -10,10 +10,9 @@ yarn add @ripreact/hsl
## Usage

```javascript
// const { hsl } = require('@ripreact/hsl');
import { hsl } from '@ripreact/hsl';

console.log(hsl(0, 100, 50, 0.5)); // → `rgba(234,0,100,0.5)`
console.log(hsl(0, 100, 50, 0.5)); // → `'#ea006480'`
```

## Environment
Expand Down
3 changes: 3 additions & 0 deletions examples/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { hsl } = require('..');

console.log(hsl(0, 100, 50, 0.5));
3 changes: 3 additions & 0 deletions examples/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { hsl } from '@ripreact/hsl';

console.log(hsl(0, 100, 50, 0.5));
106 changes: 0 additions & 106 deletions index.js

This file was deleted.

16 changes: 11 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
{
"name": "@ripreact/hsl",
"version": "1.0.1",
"description": "Minimal HSLᵤᵥ implementation.",
"main": "index.js",
"types": "index.d.ts",
"version": "1.1.0",
"description": "Minimal and fast HSLᵤᵥ implementation.",
"repository": "https://github.com/ripreact/hsl",
"author": "Marina Miyaoka <[email protected]> (https://twitter.com/miyaokamarina)",
"license": "MIT",
"devDependencies": {}
"main": "./src/main.js",
"types": "./src/index.d.ts",
"module": "./src/bundlers.mjs",
"exports": "./src/node.mjs",
"devDependencies": {
"hsluv": "^0.0.3",
"prettier": "^1.19.1",
"typescript": "^3.7.2"
}
}
3 changes: 3 additions & 0 deletions src/bundlers.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { hsl } from './main.js';

export { hsl };
2 changes: 1 addition & 1 deletion index.d.ts → src/main.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
declare module '@ripreact/hsl' {
/**
* Minimal HSLᵤᵥ implementation. Returns `rgba(r, g, b, a)` string.
* Minimal and fast HSLᵤᵥ implementation. Returns `#rrggbbaa` string.
*
* @param h HSLᵤᵥ hue.
* @param s HSLᵤᵥ saturation.
Expand Down
84 changes: 84 additions & 0 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

let { sin, cos, min, max, round, PI } = Math;
let normalize = a => round(max(0, min(a, 1)) * 255);

let M = [
3.240969941904521,
-1.537383177570093,
-0.498610760293,

-0.96924363628087,
1.87596750150772,
0.041555057407175,

0.055630079696993,
-0.20397695888897,
1.056971514242878,
];

let q = 126452;
let r = 769860;

/**
* Minimal and fast HSLᵤᵥ implementation. Returns `#rrggbbaa` string.
*
* @param h HSLᵤᵥ hue (0..360, will be normalized).
* @param s HSLᵤᵥ saturation.
* @param l HSLᵤᵥ lightness.
* @param a Alpha.
*/
exports.hsl = (h, s, l, a = 1) => {
let p = l + 16;
let i = p ** 3 / 1560896; // ← `sub1`
let j;
let x;
let y;
let z;
let m = i > 0.0088564516 ? i : l / 903.2962962; // ← `sub2`
let n;
let o = Infinity; // ← `c`

h = (h * PI) / 180; // ← `hrad`

for (i = 0; i < 9; ) {
x = M[i++];
y = M[i++];
z = M[i++];

for (j = 0; j < 2; j++) {
n = (632260 * z - q * y) * m + q * j; // ← `bottom`

// `length` ↓
n =
((838422 * z + r * y + 731718 * x) * l * m - r * j * l) /
n /
(sin(h) - (((284517 * x - 94839 * z) * m) / n) * cos(h));

o = n >= 0 ? min(o, (n / 100) * s) : o; // ← `c`
}
}

i = l * 13;
m = (cos(h) * o) / i + 0.19783000664283; // ← `varU`
n = (sin(h) * o) / i + 0.46831999493879; // ← `varV`

l = l <= 8 ? l / 903.2962962 : (p / 116) ** 3; // ← `y`
m = -(9 * l * m) / ((m - 4) * n - m * n); // ← `x`
o = normalize(a); // ← `rgba`

for (i = 0, j = 24; i < 9; j -= 8) {
o +=
(normalize(
(a = M[i++] * m + M[i++] * l + (M[i++] * (9 * l - 15 * n * l - n * m)) / (3 * n)) <= 0.0031308
? 12.92 * a
: 1.055 * a ** 0.416666666666666685 - 0.055,
) <<
j) >>>
0;
}

return '#' + o.toString(16).padStart(8, 0);
};
3 changes: 3 additions & 0 deletions src/node.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import cjs from './main.js';

export const { hsl } = cjs;
31 changes: 31 additions & 0 deletions test/bench.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const { performance } = require('perf_hooks');
const { hsluvToHex } = require('hsluv');
const { hsl } = require('..');

const { min, max, round, random } = Math;

const normalize = n => round(max(0, min(n, 1)) * 255);

// prettier-ignore
const FunA = (h, s, l, a) => (hsluvToHex([h, s, l]) + normalize(a).toString(16).padStart(2, 0));
const FunB = (h, s, l, a) => hsl(h, s, l, a);

let sum = [];

for (let i = 0; i < 10000; i++) {
sum.push(FunB(random(), random(), random(), random()));
sum.push(FunA(random(), random(), random(), random()));
}
sum = [];

const r = 1000000;

a = performance.now();
for (let i = 0; i < r; i++) sum.push(FunA(random(), random(), random(), random()));
console.log('FunA : %s rps, side effect = %s.', (r / (performance.now() - a)) * 1000, sum.length);
sum = [];

a = performance.now();
for (let i = 0; i < r; i++) sum.push(FunB(random(), random(), random(), random()));
console.log('FunB : %s rps, side effect = %s.', (r / (performance.now() - a)) * 1000, sum.length);
sum = [];
Loading

0 comments on commit 2055f6e

Please sign in to comment.