cssstyle 3.0.0 → 4.0.0
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/README.md +2 -2
- package/lib/CSSStyleDeclaration.js +14 -8
- package/lib/CSSStyleDeclaration.test.js +181 -0
- package/lib/implementedProperties.js +1 -1
- package/lib/parsers.js +22 -10
- package/lib/parsers.test.js +8 -1
- package/lib/properties/margin.js +4 -0
- package/lib/properties/padding.js +4 -0
- package/lib/properties.js +11 -3
- package/lib/utils/colorSpace.js +13 -15
- package/package.json +7 -8
package/README.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
A Node JS implementation of the CSS Object Model [CSSStyleDeclaration interface](https://www.w3.org/TR/cssom-1/#the-cssstyledeclaration-interface).
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/cssstyle) [](https://www.npmjs.com/package/cssstyle) [](https://travis-ci.org/jsdom/cssstyle) [](https://codecov.io/gh/jsdom/cssstyle)
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
#### Background
|
|
10
10
|
|
|
11
|
-
This package is an extension of the CSSStyleDeclaration class in Nikita Vasilyev's [CSSOM](https://github.com/NV/CSSOM) with added support for CSS 2 & 3 properties. The primary use case is for testing browser code in a Node environment.
|
|
11
|
+
This package is an extension of the CSSStyleDeclaration class in Nikita Vasilyev's [CSSOM](https://github.com/NV/CSSOM) with added support for CSS 2 & 3 properties. The primary use case is for testing browser code in a Node environment.
|
|
12
12
|
|
|
13
13
|
It was originally created by Chad Walker, it is now maintained by the jsdom community.
|
|
14
14
|
|
|
@@ -18,11 +18,8 @@ var CSSStyleDeclaration = function CSSStyleDeclaration(onChangeCallback) {
|
|
|
18
18
|
this._values = {};
|
|
19
19
|
this._importants = {};
|
|
20
20
|
this._length = 0;
|
|
21
|
-
this._onChange =
|
|
22
|
-
|
|
23
|
-
function () {
|
|
24
|
-
return;
|
|
25
|
-
};
|
|
21
|
+
this._onChange = onChangeCallback;
|
|
22
|
+
this._setInProgress = false;
|
|
26
23
|
};
|
|
27
24
|
CSSStyleDeclaration.prototype = {
|
|
28
25
|
constructor: CSSStyleDeclaration,
|
|
@@ -77,6 +74,7 @@ CSSStyleDeclaration.prototype = {
|
|
|
77
74
|
this.removeProperty(name);
|
|
78
75
|
return;
|
|
79
76
|
}
|
|
77
|
+
var originalText = this.cssText;
|
|
80
78
|
if (this._values[name]) {
|
|
81
79
|
// Property already exist. Overwrite it.
|
|
82
80
|
var index = Array.prototype.indexOf.call(this, name);
|
|
@@ -91,7 +89,9 @@ CSSStyleDeclaration.prototype = {
|
|
|
91
89
|
}
|
|
92
90
|
this._values[name] = value;
|
|
93
91
|
this._importants[name] = priority;
|
|
94
|
-
this._onChange
|
|
92
|
+
if (this._onChange && this.cssText !== originalText && !this._setInProgress) {
|
|
93
|
+
this._onChange(this.cssText);
|
|
94
|
+
}
|
|
95
95
|
},
|
|
96
96
|
|
|
97
97
|
/**
|
|
@@ -121,7 +121,9 @@ CSSStyleDeclaration.prototype = {
|
|
|
121
121
|
// That's what Firefox does
|
|
122
122
|
//this[index] = ""
|
|
123
123
|
|
|
124
|
-
this._onChange
|
|
124
|
+
if (this._onChange) {
|
|
125
|
+
this._onChange(this.cssText);
|
|
126
|
+
}
|
|
125
127
|
return prevValue;
|
|
126
128
|
},
|
|
127
129
|
|
|
@@ -196,6 +198,7 @@ Object.defineProperties(CSSStyleDeclaration.prototype, {
|
|
|
196
198
|
// malformed css, just return
|
|
197
199
|
return;
|
|
198
200
|
}
|
|
201
|
+
this._setInProgress = true;
|
|
199
202
|
var rule_length = dummyRule.length;
|
|
200
203
|
var name;
|
|
201
204
|
for (i = 0; i < rule_length; ++i) {
|
|
@@ -206,7 +209,10 @@ Object.defineProperties(CSSStyleDeclaration.prototype, {
|
|
|
206
209
|
dummyRule.getPropertyPriority(name)
|
|
207
210
|
);
|
|
208
211
|
}
|
|
209
|
-
this.
|
|
212
|
+
this._setInProgress = false;
|
|
213
|
+
if (this._onChange) {
|
|
214
|
+
this._onChange(this.cssText);
|
|
215
|
+
}
|
|
210
216
|
},
|
|
211
217
|
enumerable: true,
|
|
212
218
|
configurable: true,
|
|
@@ -346,6 +346,114 @@ describe('CSSStyleDeclaration', () => {
|
|
|
346
346
|
testParts('margin', '1px 2px 3px 4px', 'auto');
|
|
347
347
|
});
|
|
348
348
|
|
|
349
|
+
test('setting individual padding and margin properties to an empty string should clear them', () => {
|
|
350
|
+
var style = new CSSStyleDeclaration();
|
|
351
|
+
|
|
352
|
+
var properties = ['padding', 'margin'];
|
|
353
|
+
var parts = ['Top', 'Right', 'Bottom', 'Left'];
|
|
354
|
+
for (var i = 0; i < properties.length; i++) {
|
|
355
|
+
for (var j = 0; j < parts.length; j++) {
|
|
356
|
+
var property = properties[i] + parts[j];
|
|
357
|
+
style[property] = '12px';
|
|
358
|
+
expect(style[property]).toEqual('12px');
|
|
359
|
+
|
|
360
|
+
style[property] = '';
|
|
361
|
+
expect(style[property]).toEqual('');
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
test('removing and setting individual margin properties updates the combined property accordingly', () => {
|
|
367
|
+
var style = new CSSStyleDeclaration();
|
|
368
|
+
style.margin = '1px 2px 3px 4px';
|
|
369
|
+
|
|
370
|
+
style.marginTop = '';
|
|
371
|
+
expect(style.margin).toEqual('');
|
|
372
|
+
expect(style.marginRight).toEqual('2px');
|
|
373
|
+
expect(style.marginBottom).toEqual('3px');
|
|
374
|
+
expect(style.marginLeft).toEqual('4px');
|
|
375
|
+
|
|
376
|
+
style.marginBottom = '';
|
|
377
|
+
expect(style.margin).toEqual('');
|
|
378
|
+
expect(style.marginRight).toEqual('2px');
|
|
379
|
+
expect(style.marginLeft).toEqual('4px');
|
|
380
|
+
|
|
381
|
+
style.marginBottom = '5px';
|
|
382
|
+
expect(style.margin).toEqual('');
|
|
383
|
+
expect(style.marginRight).toEqual('2px');
|
|
384
|
+
expect(style.marginBottom).toEqual('5px');
|
|
385
|
+
expect(style.marginLeft).toEqual('4px');
|
|
386
|
+
|
|
387
|
+
style.marginTop = '6px';
|
|
388
|
+
expect(style.cssText).toEqual('margin: 6px 2px 5px 4px;');
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test.each(['padding', 'margin'])(
|
|
392
|
+
'removing an individual %s property should remove the combined property and replace it with the remaining individual ones',
|
|
393
|
+
(property) => {
|
|
394
|
+
var style = new CSSStyleDeclaration();
|
|
395
|
+
var parts = ['Top', 'Right', 'Bottom', 'Left'];
|
|
396
|
+
var partValues = ['1px', '2px', '3px', '4px'];
|
|
397
|
+
|
|
398
|
+
for (var j = 0; j < parts.length; j++) {
|
|
399
|
+
var partToRemove = parts[j];
|
|
400
|
+
style[property] = partValues.join(' ');
|
|
401
|
+
style[property + partToRemove] = '';
|
|
402
|
+
|
|
403
|
+
// Main property should have been removed
|
|
404
|
+
expect(style[property]).toEqual('');
|
|
405
|
+
|
|
406
|
+
// Expect other parts to still be there
|
|
407
|
+
for (var k = 0; k < parts.length; k++) {
|
|
408
|
+
var propertyCss = property + '-' + parts[k].toLowerCase() + ': ' + partValues[k] + ';';
|
|
409
|
+
if (k === j) {
|
|
410
|
+
expect(style[property + parts[k]]).toEqual('');
|
|
411
|
+
expect(style.cssText).not.toContain(propertyCss);
|
|
412
|
+
} else {
|
|
413
|
+
expect(style[property + parts[k]]).toEqual(partValues[k]);
|
|
414
|
+
expect(style.cssText).toContain(propertyCss);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
test.each(['margin', 'padding'])(
|
|
422
|
+
'setting additional %s properties keeps important status of others',
|
|
423
|
+
(property) => {
|
|
424
|
+
var style = new CSSStyleDeclaration();
|
|
425
|
+
var importantProperty = property + '-top: 3px !important;';
|
|
426
|
+
style.cssText = importantProperty;
|
|
427
|
+
expect(style.cssText).toContain(importantProperty);
|
|
428
|
+
|
|
429
|
+
style[property + 'Right'] = '4px';
|
|
430
|
+
style[property + 'Bottom'] = '5px';
|
|
431
|
+
style[property + 'Left'] = '6px';
|
|
432
|
+
|
|
433
|
+
expect(style.cssText).toContain(importantProperty);
|
|
434
|
+
expect(style.cssText).toContain(property + '-right: 4px;');
|
|
435
|
+
expect(style.cssText).toContain(property + '-bottom: 5px;');
|
|
436
|
+
expect(style.cssText).toContain(property + '-left: 6px;');
|
|
437
|
+
expect(style.cssText).not.toContain('margin:');
|
|
438
|
+
}
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
test.each(['margin', 'padding'])(
|
|
442
|
+
'setting individual %s keeps important status of others',
|
|
443
|
+
(property) => {
|
|
444
|
+
var style = new CSSStyleDeclaration();
|
|
445
|
+
style.cssText = property + ': 3px !important;';
|
|
446
|
+
|
|
447
|
+
style[property + 'Top'] = '4px';
|
|
448
|
+
|
|
449
|
+
expect(style.cssText).toContain(property + '-top: 4px;');
|
|
450
|
+
expect(style.cssText).toContain(property + '-right: 3px !important;');
|
|
451
|
+
expect(style.cssText).toContain(property + '-bottom: 3px !important;');
|
|
452
|
+
expect(style.cssText).toContain(property + '-left: 3px !important;');
|
|
453
|
+
expect(style.cssText).not.toContain('margin:');
|
|
454
|
+
}
|
|
455
|
+
);
|
|
456
|
+
|
|
349
457
|
test('setting a value to 0 should return the string value', () => {
|
|
350
458
|
var style = new CSSStyleDeclaration();
|
|
351
459
|
style.setProperty('fill-opacity', 0);
|
|
@@ -353,10 +461,46 @@ describe('CSSStyleDeclaration', () => {
|
|
|
353
461
|
});
|
|
354
462
|
|
|
355
463
|
test('onchange callback should be called when the csstext changes', () => {
|
|
464
|
+
var called = 0;
|
|
356
465
|
var style = new CSSStyleDeclaration(function (cssText) {
|
|
466
|
+
called++;
|
|
357
467
|
expect(cssText).toEqual('opacity: 0;');
|
|
358
468
|
});
|
|
469
|
+
style.cssText = 'opacity: 0;';
|
|
470
|
+
expect(called).toEqual(1);
|
|
471
|
+
style.cssText = 'opacity: 0;';
|
|
472
|
+
expect(called).toEqual(2);
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
test('onchange callback should be called only once when multiple properties were added', () => {
|
|
476
|
+
var called = 0;
|
|
477
|
+
var style = new CSSStyleDeclaration(function (cssText) {
|
|
478
|
+
called++;
|
|
479
|
+
expect(cssText).toEqual('width: 100px; height: 100px;');
|
|
480
|
+
});
|
|
481
|
+
style.cssText = 'width: 100px;height:100px;';
|
|
482
|
+
expect(called).toEqual(1);
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
test('onchange callback should not be called when property is set to the same value', () => {
|
|
486
|
+
var called = 0;
|
|
487
|
+
var style = new CSSStyleDeclaration(function () {
|
|
488
|
+
called++;
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
style.setProperty('opacity', 0);
|
|
492
|
+
expect(called).toEqual(1);
|
|
359
493
|
style.setProperty('opacity', 0);
|
|
494
|
+
expect(called).toEqual(1);
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
test('onchange callback should not be called when removeProperty was called on non-existing property', () => {
|
|
498
|
+
var called = 0;
|
|
499
|
+
var style = new CSSStyleDeclaration(function () {
|
|
500
|
+
called++;
|
|
501
|
+
});
|
|
502
|
+
style.removeProperty('opacity');
|
|
503
|
+
expect(called).toEqual(0);
|
|
360
504
|
});
|
|
361
505
|
|
|
362
506
|
test('setting float should work the same as cssfloat', () => {
|
|
@@ -402,6 +546,43 @@ describe('CSSStyleDeclaration', () => {
|
|
|
402
546
|
expect(style.marginTop).toEqual('0.5ex');
|
|
403
547
|
});
|
|
404
548
|
|
|
549
|
+
test('setting empty string and null to a padding or margin works', () => {
|
|
550
|
+
var style = new CSSStyleDeclaration();
|
|
551
|
+
var parts = ['Top', 'Right', 'Bottom', 'Left'];
|
|
552
|
+
function testParts(base, nullValue) {
|
|
553
|
+
var props = [base].concat(parts.map((part) => base + part));
|
|
554
|
+
for (let prop of props) {
|
|
555
|
+
expect(style[prop]).toEqual('');
|
|
556
|
+
style[prop] = '10px';
|
|
557
|
+
expect(style[prop]).toEqual('10px');
|
|
558
|
+
style[prop] = nullValue;
|
|
559
|
+
expect(style[prop]).toEqual('');
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
testParts('margin', '');
|
|
564
|
+
testParts('margin', null);
|
|
565
|
+
testParts('padding', '');
|
|
566
|
+
testParts('padding', null);
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
test('setting undefined to a padding or margin does nothing', () => {
|
|
570
|
+
var style = new CSSStyleDeclaration();
|
|
571
|
+
var parts = ['Top', 'Right', 'Bottom', 'Left'];
|
|
572
|
+
function testParts(base) {
|
|
573
|
+
var props = [base].concat(parts.map((part) => base + part));
|
|
574
|
+
for (let prop of props) {
|
|
575
|
+
style[prop] = '10px';
|
|
576
|
+
expect(style[prop]).toEqual('10px');
|
|
577
|
+
style[prop] = undefined;
|
|
578
|
+
expect(style[prop]).toEqual('10px');
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
testParts('margin');
|
|
583
|
+
testParts('padding');
|
|
584
|
+
});
|
|
585
|
+
|
|
405
586
|
test('setting null to background works', () => {
|
|
406
587
|
var style = new CSSStyleDeclaration();
|
|
407
588
|
style.background = 'red';
|
package/lib/parsers.js
CHANGED
|
@@ -683,6 +683,9 @@ exports.subImplicitSetter = function (prefix, part, isValid, parser) {
|
|
|
683
683
|
if (typeof v === 'number') {
|
|
684
684
|
v = v.toString();
|
|
685
685
|
}
|
|
686
|
+
if (v === null) {
|
|
687
|
+
v = '';
|
|
688
|
+
}
|
|
686
689
|
if (typeof v !== 'string') {
|
|
687
690
|
return undefined;
|
|
688
691
|
}
|
|
@@ -691,19 +694,28 @@ exports.subImplicitSetter = function (prefix, part, isValid, parser) {
|
|
|
691
694
|
}
|
|
692
695
|
v = parser(v);
|
|
693
696
|
this._setProperty(property, v);
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
697
|
+
|
|
698
|
+
var combinedPriority = this.getPropertyPriority(prefix);
|
|
699
|
+
var parts = subparts.map((subpart) => this._values[subpart]);
|
|
700
|
+
var priorities = subparts.map((subpart) => this.getPropertyPriority(subpart));
|
|
701
|
+
// Combine into a single property if all values are set and have the same priority
|
|
702
|
+
if (
|
|
703
|
+
parts.every((p) => p !== '' && p != null) &&
|
|
704
|
+
priorities.every((p) => p === priorities[0]) &&
|
|
705
|
+
priorities[0] === combinedPriority
|
|
706
|
+
) {
|
|
707
|
+
for (var i = 0; i < subparts.length; i++) {
|
|
703
708
|
this.removeProperty(subparts[i]);
|
|
704
709
|
this._values[subparts[i]] = parts[i];
|
|
705
710
|
}
|
|
706
|
-
this._setProperty(prefix, parts.join(' '));
|
|
711
|
+
this._setProperty(prefix, parts.join(' '), priorities[0]);
|
|
712
|
+
} else {
|
|
713
|
+
this.removeProperty(prefix);
|
|
714
|
+
for (var j = 0; j < subparts.length; j++) {
|
|
715
|
+
// The property we're setting won't be important, the rest will either keep their priority or inherit it from the combined property
|
|
716
|
+
var priority = subparts[j] === property ? '' : priorities[j] || combinedPriority;
|
|
717
|
+
this._setProperty(subparts[j], parts[j], priority);
|
|
718
|
+
}
|
|
707
719
|
}
|
|
708
720
|
return v;
|
|
709
721
|
};
|
package/lib/parsers.test.js
CHANGED
|
@@ -107,7 +107,14 @@ describe('parseColor', () => {
|
|
|
107
107
|
|
|
108
108
|
expect(output).toEqual('rgba(5, 5, 5, 0.5)');
|
|
109
109
|
});
|
|
110
|
-
|
|
110
|
+
it.each([
|
|
111
|
+
[120, 'rgb(0, 255, 0)'],
|
|
112
|
+
[240, 'rgb(0, 0, 255)'],
|
|
113
|
+
])('should convert not zero hsl with non zero hue %s to %s', (hue, rgbValue) => {
|
|
114
|
+
let input = 'hsl(' + hue + ', 100%, 50%)';
|
|
115
|
+
let output = parsers.parseColor(input);
|
|
116
|
+
expect(output).toEqual(rgbValue);
|
|
117
|
+
});
|
|
111
118
|
it.todo('Add more tests');
|
|
112
119
|
});
|
|
113
120
|
describe('parseAngle', () => {
|
package/lib/properties/margin.js
CHANGED
|
@@ -9,6 +9,7 @@ var isValid = function (v) {
|
|
|
9
9
|
}
|
|
10
10
|
var type = parsers.valueType(v);
|
|
11
11
|
return (
|
|
12
|
+
type === TYPES.NULL_OR_EMPTY_STR ||
|
|
12
13
|
type === TYPES.LENGTH ||
|
|
13
14
|
type === TYPES.PERCENT ||
|
|
14
15
|
(type === TYPES.INTEGER && (v === '0' || v === 0))
|
|
@@ -40,6 +41,9 @@ module.exports.definition = {
|
|
|
40
41
|
if (typeof v === 'number') {
|
|
41
42
|
v = String(v);
|
|
42
43
|
}
|
|
44
|
+
if (v === null) {
|
|
45
|
+
v = '';
|
|
46
|
+
}
|
|
43
47
|
if (typeof v !== 'string') {
|
|
44
48
|
return;
|
|
45
49
|
}
|
|
@@ -6,6 +6,7 @@ var TYPES = parsers.TYPES;
|
|
|
6
6
|
var isValid = function (v) {
|
|
7
7
|
var type = parsers.valueType(v);
|
|
8
8
|
return (
|
|
9
|
+
type === TYPES.NULL_OR_EMPTY_STR ||
|
|
9
10
|
type === TYPES.LENGTH ||
|
|
10
11
|
type === TYPES.PERCENT ||
|
|
11
12
|
(type === TYPES.INTEGER && (v === '0' || v === 0))
|
|
@@ -33,6 +34,9 @@ module.exports.definition = {
|
|
|
33
34
|
if (typeof v === 'number') {
|
|
34
35
|
v = String(v);
|
|
35
36
|
}
|
|
37
|
+
if (v === null) {
|
|
38
|
+
v = '';
|
|
39
|
+
}
|
|
36
40
|
if (typeof v !== 'string') {
|
|
37
41
|
return;
|
|
38
42
|
}
|
package/lib/properties.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
// autogenerated -
|
|
3
|
+
// autogenerated - 12/28/2023
|
|
4
4
|
|
|
5
5
|
/*
|
|
6
6
|
*
|
|
@@ -1225,7 +1225,7 @@ var margin_local_var_isValid = function (v) {
|
|
|
1225
1225
|
}
|
|
1226
1226
|
|
|
1227
1227
|
var type = external_dependency_parsers_0.valueType(v);
|
|
1228
|
-
return type === margin_local_var_TYPES.LENGTH || type === margin_local_var_TYPES.PERCENT || type === margin_local_var_TYPES.INTEGER && (v === '0' || v === 0);
|
|
1228
|
+
return type === margin_local_var_TYPES.NULL_OR_EMPTY_STR || type === margin_local_var_TYPES.LENGTH || type === margin_local_var_TYPES.PERCENT || type === margin_local_var_TYPES.INTEGER && (v === '0' || v === 0);
|
|
1229
1229
|
};
|
|
1230
1230
|
|
|
1231
1231
|
var margin_local_var_parser = function (v) {
|
|
@@ -1250,6 +1250,10 @@ margin_export_definition = {
|
|
|
1250
1250
|
v = String(v);
|
|
1251
1251
|
}
|
|
1252
1252
|
|
|
1253
|
+
if (v === null) {
|
|
1254
|
+
v = '';
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1253
1257
|
if (typeof v !== 'string') {
|
|
1254
1258
|
return;
|
|
1255
1259
|
}
|
|
@@ -1372,7 +1376,7 @@ var padding_local_var_TYPES = external_dependency_parsers_0.TYPES;
|
|
|
1372
1376
|
|
|
1373
1377
|
var padding_local_var_isValid = function (v) {
|
|
1374
1378
|
var type = external_dependency_parsers_0.valueType(v);
|
|
1375
|
-
return type === padding_local_var_TYPES.LENGTH || type === padding_local_var_TYPES.PERCENT || type === padding_local_var_TYPES.INTEGER && (v === '0' || v === 0);
|
|
1379
|
+
return type === padding_local_var_TYPES.NULL_OR_EMPTY_STR || type === padding_local_var_TYPES.LENGTH || type === padding_local_var_TYPES.PERCENT || type === padding_local_var_TYPES.INTEGER && (v === '0' || v === 0);
|
|
1376
1380
|
};
|
|
1377
1381
|
|
|
1378
1382
|
var padding_local_var_parser = function (v) {
|
|
@@ -1391,6 +1395,10 @@ padding_export_definition = {
|
|
|
1391
1395
|
v = String(v);
|
|
1392
1396
|
}
|
|
1393
1397
|
|
|
1398
|
+
if (v === null) {
|
|
1399
|
+
v = '';
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1394
1402
|
if (typeof v !== 'string') {
|
|
1395
1403
|
return;
|
|
1396
1404
|
}
|
package/lib/utils/colorSpace.js
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
if (hue < 1) return (t2 - t1) * hue + t1;
|
|
8
|
-
else if (hue < 3) return t2;
|
|
9
|
-
else if (hue < 4) return (t2 - t1) * (4 - hue) + t1;
|
|
10
|
-
else return t1;
|
|
11
|
-
};
|
|
3
|
+
const MAX_HUE = 360;
|
|
4
|
+
const COLOR_NB = 12;
|
|
5
|
+
const MAX_RGB_VALUE = 255;
|
|
12
6
|
|
|
13
7
|
// https://www.w3.org/TR/css-color-4/#hsl-to-rgb
|
|
14
8
|
exports.hslToRgb = (hue, sat, light) => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
hue = hue % MAX_HUE;
|
|
10
|
+
if (hue < 0) {
|
|
11
|
+
hue += MAX_HUE;
|
|
12
|
+
}
|
|
13
|
+
function f(n) {
|
|
14
|
+
const k = (n + hue / (MAX_HUE / COLOR_NB)) % COLOR_NB;
|
|
15
|
+
const a = sat * Math.min(light, 1 - light);
|
|
16
|
+
return light - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));
|
|
17
|
+
}
|
|
18
|
+
return [f(0), f(8), f(4)].map((value) => Math.round(value * MAX_RGB_VALUE));
|
|
21
19
|
};
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"CSSStyleDeclaration",
|
|
7
7
|
"StyleSheet"
|
|
8
8
|
],
|
|
9
|
-
"version": "
|
|
9
|
+
"version": "4.0.0",
|
|
10
10
|
"homepage": "https://github.com/jsdom/cssstyle",
|
|
11
11
|
"maintainers": [
|
|
12
12
|
{
|
|
@@ -44,13 +44,12 @@
|
|
|
44
44
|
"babel-traverse": "^6.26.0",
|
|
45
45
|
"babel-types": "^6.26.0",
|
|
46
46
|
"babylon": "^6.18.0",
|
|
47
|
-
"eslint": "^8.
|
|
48
|
-
"eslint-config-prettier": "^
|
|
49
|
-
"eslint-plugin-prettier": "^
|
|
50
|
-
"jest": "^29.
|
|
51
|
-
"minipass-fetch": "^3.0.1",
|
|
47
|
+
"eslint": "^8.56.0",
|
|
48
|
+
"eslint-config-prettier": "^9.1.0",
|
|
49
|
+
"eslint-plugin-prettier": "^5.1.2",
|
|
50
|
+
"jest": "^29.7.0",
|
|
52
51
|
"npm-run-all": "^4.1.5",
|
|
53
|
-
"prettier": "^
|
|
52
|
+
"prettier": "^3.1.1",
|
|
54
53
|
"resolve": "^1.22.1"
|
|
55
54
|
},
|
|
56
55
|
"scripts": {
|
|
@@ -67,6 +66,6 @@
|
|
|
67
66
|
},
|
|
68
67
|
"license": "MIT",
|
|
69
68
|
"engines": {
|
|
70
|
-
"node": ">=
|
|
69
|
+
"node": ">=18"
|
|
71
70
|
}
|
|
72
71
|
}
|