Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Color 4] Dart JS API implementation #2117

Merged
merged 51 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
b175871
Transition Color Constructors
jamesnw Sep 26, 2023
7d9ea9e
Stub out color methods, getters and procedures
jamesnw Sep 26, 2023
dd9f821
Implement toSpace, isInGamut, toGamut
jamesnw Sep 26, 2023
7b2febf
Implement channelsOrNull and channels
jamesnw Sep 26, 2023
db1beea
Add types, implement channel
jamesnw Sep 26, 2023
f5854ef
Update constructors
jamesnw Sep 27, 2023
d14ace0
revert unintended change
jgerigmeyer Sep 27, 2023
9474871
Implement isChannelMissing, isAlphaMissing, isChannelPowerless
jamesnw Sep 28, 2023
76ee478
Implement color change
jamesnw Sep 29, 2023
0f7e866
Updates to change
jamesnw Oct 2, 2023
c7a87a5
Fix optional parameters
jamesnw Oct 4, 2023
db1f0e4
Merge branch 'feature.color-4' of github.com:oddbird/dart-sass into c…
jamesnw Oct 5, 2023
fced041
Add interpolation
jamesnw Oct 9, 2023
ef6f2e3
fix typo
jgerigmeyer Oct 12, 2023
8ff4546
Merge branch 'feature.color-4' into color-spaces-js
jgerigmeyer Oct 12, 2023
548cb4d
Return immutable lists
jamesnw Oct 13, 2023
5e94b35
Return immutable lists for channels and channelsOrNull
jgerigmeyer Oct 13, 2023
683dc61
Remove isAlphaMissing
jamesnw Oct 13, 2023
bd3ef19
Merge branch 'color-spaces-js' of github.com:oddbird/dart-sass into c…
jamesnw Oct 13, 2023
f90b435
Remove duplicate import
jamesnw Oct 13, 2023
150c498
Remove unneeded parseChannelValue procedure
jamesnw Oct 13, 2023
02ec38c
Define `hash` and `equals` for js colors
jgerigmeyer Oct 13, 2023
c865c9c
Add deprecation logging for Color 4 JS API.
jgerigmeyer Oct 13, 2023
b80a1e0
update comment
jgerigmeyer Oct 16, 2023
cfb1a05
Update Embedded Protocol
jgerigmeyer Oct 16, 2023
9913e62
tests
jgerigmeyer Oct 16, 2023
f6fa77e
Review, refactor change
jamesnw Oct 17, 2023
42b391e
Simplify cases, privatize options classes
jamesnw Oct 17, 2023
af1dbf1
Factor out _toColor
jamesnw Oct 17, 2023
67b4eae
Document functions
jamesnw Oct 17, 2023
d12d7ed
Remove intermediary construction options
jamesnw Oct 17, 2023
283be78
Combined methods and getters
jamesnw Oct 17, 2023
e91e898
Switch from generic constructors
jamesnw Oct 17, 2023
bbccca4
Adjust Embedded Protocol to use color factories.
jgerigmeyer Oct 17, 2023
cfeb456
Add `rec2020` to JS API, and adjust `interpolate` args
jgerigmeyer Oct 17, 2023
9b55256
Update changelog
jgerigmeyer Oct 17, 2023
63c17e3
address review
jgerigmeyer Oct 18, 2023
0cde13b
Add return type, fix null alpha deprecation logic
jamesnw Oct 18, 2023
d88ebf6
Adjust hue interpolation logic
jamesnw Oct 18, 2023
836bab5
Merge branch 'feature.color-4' into color-spaces-js
jgerigmeyer Oct 18, 2023
e1e5d78
Fix hwb vs hsl differentiation, apply better null check for change de…
jamesnw Oct 19, 2023
edc9b2c
Explicit undefined should not change a value
jamesnw Oct 19, 2023
e097949
empty commit to trigger CI
jgerigmeyer Oct 19, 2023
632df8c
Add isNull to js utils
jamesnw Oct 20, 2023
1a8c41a
Update color-4-api deprecations
jamesnw Oct 20, 2023
9985076
Merge branch 'feature.color-4' of github.com:oddbird/dart-sass into c…
jamesnw Oct 26, 2023
d87db2e
Update lib/src/js/value/color.dart
jgerigmeyer Oct 29, 2023
17cf365
empty commit to trigger ci
jgerigmeyer Nov 6, 2023
12bc676
toGamut should return color in its original space
jgerigmeyer Nov 6, 2023
5b04f0c
Fix comment
jgerigmeyer Nov 9, 2023
263ac0d
Merge branch 'feature.color-4' into color-spaces-js
jgerigmeyer Nov 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,32 @@
* Added `InterpolationMethod` and `HueInterpolationMethod` which collectively
represent the method to use to interpolate two colors.

### JS API

* Modify `SassColor` to accept a new `space` option, with support for all the
new color spaces defined in Color Level 4.

* Add `SassColor.space` which returns a color's color space.

* Add `SassColor.channels` and `.channelsOrNull` which returns a list of channel
values, with missing channels converted to 0 or exposed as null, respectively.

* Add `SassColor.isLegacy`, `.isInGamut()`, `.channel()`, `.isChannelMissing()`,
`.isChannelPowerless()`, `.toSpace()`, `.toGamut()`, `.change()`, and
`.interpolate()` which do the same thing as the Sass functions of the
corresponding names.

* Deprecate `SassColor.red`, `.green`, `.blue`, `.hue`, `.saturation`,
`.lightness`, `.whiteness`, and `.blackness` in favor of
`SassColor.channel()`.

### Embedded Sass

* Add `Color` SassScript value, with support for all the new color spaces
defined in Color Level 4.

* Remove `RgbColor`, `HslColor` and `HwbColor` SassScript values.

## 1.69.5

### JS API
Expand Down
4 changes: 4 additions & 0 deletions lib/src/deprecation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ enum Deprecation {
deprecatedIn: '1.70.0',
description: 'Using global Sass color functions.'),

color4Api('color-4-api',
deprecatedIn: '1.70.0',
description: 'Methods of interacting with legacy SassColors.'),

/// Deprecation for `@import` rules.
import.future('import', description: '@import rules.'),

Expand Down
111 changes: 86 additions & 25 deletions lib/src/embedded/protofier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,12 @@ final class Protofier {
..quoted = value.hasQuotes;
case SassNumber():
result.number = _protofyNumber(value);
case SassColor(space: ColorSpace.hsl):
result.hslColor = Value_HslColor()
..hue = value.channel('hue') * 1.0
..saturation = value.channel('saturation')
..lightness = value.channel('lightness')
..alpha = value.alpha * 1.0;
case SassColor():
result.rgbColor = Value_RgbColor()
..red = value.channel('red').clamp(0, 255).round()
..green = value.channel('green').clamp(0, 255).round()
..blue = value.channel('blue').clamp(0, 255).round()
result.color = Value_Color()
..space = value.space.name
..channel1 = value.channel0
..channel2 = value.channel1
..channel3 = value.channel2
..alpha = value.alpha * 1.0;
case SassArgumentList():
_argumentLists.add(value);
Expand Down Expand Up @@ -181,17 +176,85 @@ final class Protofier {
case Value_Value.number:
return _deprotofyNumber(value.number);

case Value_Value.rgbColor:
return SassColor.rgb(value.rgbColor.red, value.rgbColor.green,
value.rgbColor.blue, value.rgbColor.alpha);

case Value_Value.hslColor:
return SassColor.hsl(value.hslColor.hue, value.hslColor.saturation,
value.hslColor.lightness, value.hslColor.alpha);

case Value_Value.hwbColor:
return SassColor.hwb(value.hwbColor.hue, value.hwbColor.whiteness,
value.hwbColor.blackness, value.hwbColor.alpha);
case Value_Value.color:
var space = ColorSpace.fromName(value.color.space);
switch (space) {
case ColorSpace.rgb:
return SassColor.rgb(value.color.channel1, value.color.channel2,
value.color.channel3, value.color.alpha);

case ColorSpace.hsl:
return SassColor.hsl(value.color.channel1, value.color.channel2,
value.color.channel3, value.color.alpha);

case ColorSpace.hwb:
return SassColor.hwb(value.color.channel1, value.color.channel2,
value.color.channel3, value.color.alpha);

case ColorSpace.lab:
return SassColor.lab(value.color.channel1, value.color.channel2,
value.color.channel3, value.color.alpha);
case ColorSpace.oklab:
return SassColor.oklab(value.color.channel1, value.color.channel2,
value.color.channel3, value.color.alpha);

case ColorSpace.lch:
return SassColor.lch(value.color.channel1, value.color.channel2,
value.color.channel3, value.color.alpha);
case ColorSpace.oklch:
return SassColor.oklch(value.color.channel1, value.color.channel2,
value.color.channel3, value.color.alpha);

case ColorSpace.srgb:
return SassColor.srgb(value.color.channel1, value.color.channel2,
value.color.channel3, value.color.alpha);
case ColorSpace.srgbLinear:
return SassColor.srgbLinear(
value.color.channel1,
value.color.channel2,
value.color.channel3,
value.color.alpha);
case ColorSpace.displayP3:
return SassColor.displayP3(
value.color.channel1,
value.color.channel2,
value.color.channel3,
value.color.alpha);
case ColorSpace.a98Rgb:
return SassColor.a98Rgb(
value.color.channel1,
value.color.channel2,
value.color.channel3,
value.color.alpha);
case ColorSpace.prophotoRgb:
return SassColor.prophotoRgb(
value.color.channel1,
value.color.channel2,
value.color.channel3,
value.color.alpha);
case ColorSpace.rec2020:
return SassColor.rec2020(
value.color.channel1,
value.color.channel2,
value.color.channel3,
value.color.alpha);

case ColorSpace.xyzD50:
return SassColor.xyzD50(
value.color.channel1,
value.color.channel2,
value.color.channel3,
value.color.alpha);
case ColorSpace.xyzD65:
return SassColor.xyzD65(
value.color.channel1,
value.color.channel2,
value.color.channel3,
value.color.alpha);

default:
throw "Unreachable";
}

case Value_Value.argumentList:
if (value.argumentList.id != 0) {
Expand Down Expand Up @@ -276,10 +339,8 @@ final class Protofier {
throw paramsError(error.toString());
}

if (value.whichValue() == Value_Value.rgbColor) {
name = 'RgbColor.$name';
} else if (value.whichValue() == Value_Value.hslColor) {
name = 'HslColor.$name';
if (value.whichValue() == Value_Value.color) {
name = 'Color.$name';
}

throw paramsError(
Expand Down
21 changes: 21 additions & 0 deletions lib/src/evaluation_context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'dart:async';
import 'package:source_span/source_span.dart';

import 'deprecation.dart';
import 'logger.dart';

/// An interface that exposes information about the current Sass evaluation.
///
Expand All @@ -25,6 +26,16 @@ abstract interface class EvaluationContext {
}
}

/// The current evaluation context, or null if there isn't a Sass stylesheet
/// currently being evaluated.
static EvaluationContext? get _currentOrNull {
if (Zone.current[#_evaluationContext] case EvaluationContext context) {
return context;
} else {
return null;
}
}

/// Returns the span for the currently executing callable.
///
/// For normal exception reporting, this should be avoided in favor of
Expand Down Expand Up @@ -58,6 +69,16 @@ void warnForDeprecation(String message, Deprecation deprecation) {
EvaluationContext.current.warn(message, deprecation);
}

/// Prints a deprecation warning with [message] of type [deprecation],
/// using stderr if there is no [EvaluationContext.current].
void warnForDeprecationFromApi(String message, Deprecation deprecation) {
if (EvaluationContext._currentOrNull case var context?) {
context.warn(message, deprecation);
} else {
Logger.stderr().warnForDeprecation(deprecation, message);
}
}

/// Runs [callback] with [context] as [EvaluationContext.current].
///
/// This is zone-based, so if [callback] is asynchronous [warn] is set for the
Expand Down
5 changes: 5 additions & 0 deletions lib/src/js/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ bool isUndefined(Object? value) => _isUndefined.call(value) as bool;

final _isUndefined = JSFunction("value", "return value === undefined;");

/// Returns whether or not [value] is the JS `null` value.
bool isNull(Object? value) => _isNull.call(value) as bool;

final _isNull = JSFunction("value", "return value === null;");

@JS("Error")
external JSClass get jsErrorClass;

Expand Down
Loading