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

Style cleanup #1510

Merged
merged 16 commits into from
Nov 28, 2023
5 changes: 5 additions & 0 deletions .changeset/gentle-berries-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@siteimprove/alfa-css": patch
---

**Added:** all `Value` subtype now correctly implement the `(Partially)Resovable` interfaces.
5 changes: 5 additions & 0 deletions .changeset/pretty-waves-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@siteimprove/alfa-css": minor
---

**Breaking:** `Image.partiallyResolve()` and `Shape.partiallyResolve()` functions has been replaced by instance methods of the same name.
127 changes: 114 additions & 13 deletions docs/review/api/alfa-css.api.md

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions docs/review/api/alfa-style.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { Percentage } from '@siteimprove/alfa-css';
import { Position } from '@siteimprove/alfa-css';
import { Predicate } from '@siteimprove/alfa-predicate';
import { Rectangle } from '@siteimprove/alfa-css';
import type { Resolvable } from '@siteimprove/alfa-css';
import { Rotate } from '@siteimprove/alfa-css';
import { Serializable } from '@siteimprove/alfa-json';
import { Shadow } from '@siteimprove/alfa-css';
Expand Down Expand Up @@ -136,7 +137,7 @@ export namespace Longhands {
readonly "border-end-start-radius": Longhand<Tuple<[horizontal: LengthPercentage, vertical: LengthPercentage]>, Tuple<[horizontal: LengthPercentage, vertical: LengthPercentage]>>;
readonly "border-image-outset": Longhand<Specified_2, Tuple<[top: Length | Number_2, right: Length | Number_2, bottom: Length | Number_2, left: Length | Number_2]>>;
readonly "border-image-repeat": Longhand<Specified_4, Specified_4>;
readonly "border-image-slice": Longhand<Specified_6, Specified_6>;
readonly "border-image-slice": Longhand<Specified_6, Tuple<[top: Number_2.Fixed | Percentage.Canonical, right: Number_2.Fixed | Percentage.Canonical, bottom: Number_2.Fixed | Percentage.Canonical, left: Number_2.Fixed | Percentage.Canonical]> | Tuple<[top: Number_2.Fixed | Percentage.Canonical, right: Number_2.Fixed | Percentage.Canonical, bottom: Number_2.Fixed | Percentage.Canonical, left: Number_2.Fixed | Percentage.Canonical, fill: Keyword<"fill">]>>;
readonly "border-image-source": Longhand<Specified_7, Image.PartiallyResolved | Keyword<"none">>;
readonly "border-image-width": Longhand<Specified_8, Tuple<[top: Number_2.Fixed | LengthPercentage | Keyword<"auto">, right: Number_2.Fixed | LengthPercentage | Keyword<"auto">, bottom: Number_2.Fixed | LengthPercentage | Keyword<"auto">, left: Number_2.Fixed | LengthPercentage | Keyword<"auto">]>>;
readonly "border-inline-end-color": Longhand<Color, Color.Canonical>;
Expand All @@ -163,14 +164,14 @@ export namespace Longhands {
readonly "clip-path": Longhand<URL | Keyword<"none"> | Shape<Shape.Basic, Box.Geometry>, URL | Keyword<"none"> | Shape<Shape.Basic, Box.Geometry>>;
readonly clip: Longhand<Keyword<"auto"> | Shape<Rectangle<Length | Rectangle.Auto>, Keyword<"border-box">>, Keyword<"auto"> | Shape<Rectangle<Length | Rectangle.Auto>, Keyword<"border-box">>>;
readonly color: Longhand<Color, Color.Canonical>;
readonly cursor: Longhand<Tuple<[List<URL | Tuple<[URL, Number_2, Number_2]>>, Keyword<"auto"> | Keyword<"none"> | Keyword<"default"> | Keyword<"context-menu"> | Keyword<"help"> | Keyword<"pointer"> | Keyword<"progress"> | Keyword<"wait"> | Keyword<"cell"> | Keyword<"crosshair"> | Keyword<"text"> | Keyword<"vertical-text"> | Keyword<"alias"> | Keyword<"copy"> | Keyword<"move"> | Keyword<"no-drop"> | Keyword<"not-allowed"> | Keyword<"grab"> | Keyword<"grabbing"> | Keyword<"e-resize"> | Keyword<"n-resize"> | Keyword<"ne-resize"> | Keyword<"nw-resize"> | Keyword<"s-resize"> | Keyword<"se-resize"> | Keyword<"sw-resize"> | Keyword<"w-resize"> | Keyword<"ew-resize"> | Keyword<"ns-resize"> | Keyword<"nesw-resize"> | Keyword<"nwse-resize"> | Keyword<"col-resize"> | Keyword<"row-resize"> | Keyword<"all-scroll"> | Keyword<"zoom-in"> | Keyword<"zoom-out">]>, Tuple<[List<URL | Tuple<[URL, Number_2, Number_2]>>, Keyword<"auto"> | Keyword<"none"> | Keyword<"default"> | Keyword<"context-menu"> | Keyword<"help"> | Keyword<"pointer"> | Keyword<"progress"> | Keyword<"wait"> | Keyword<"cell"> | Keyword<"crosshair"> | Keyword<"text"> | Keyword<"vertical-text"> | Keyword<"alias"> | Keyword<"copy"> | Keyword<"move"> | Keyword<"no-drop"> | Keyword<"not-allowed"> | Keyword<"grab"> | Keyword<"grabbing"> | Keyword<"e-resize"> | Keyword<"n-resize"> | Keyword<"ne-resize"> | Keyword<"nw-resize"> | Keyword<"s-resize"> | Keyword<"se-resize"> | Keyword<"sw-resize"> | Keyword<"w-resize"> | Keyword<"ew-resize"> | Keyword<"ns-resize"> | Keyword<"nesw-resize"> | Keyword<"nwse-resize"> | Keyword<"col-resize"> | Keyword<"row-resize"> | Keyword<"all-scroll"> | Keyword<"zoom-in"> | Keyword<"zoom-out">]>>;
readonly cursor: Longhand<Tuple<[List<URL | Tuple<[URL, Number_2, Number_2]>>, Keyword<"auto"> | Keyword<"none"> | Keyword<"default"> | Keyword<"context-menu"> | Keyword<"help"> | Keyword<"pointer"> | Keyword<"progress"> | Keyword<"wait"> | Keyword<"cell"> | Keyword<"crosshair"> | Keyword<"text"> | Keyword<"vertical-text"> | Keyword<"alias"> | Keyword<"copy"> | Keyword<"move"> | Keyword<"no-drop"> | Keyword<"not-allowed"> | Keyword<"grab"> | Keyword<"grabbing"> | Keyword<"e-resize"> | Keyword<"n-resize"> | Keyword<"ne-resize"> | Keyword<"nw-resize"> | Keyword<"s-resize"> | Keyword<"se-resize"> | Keyword<"sw-resize"> | Keyword<"w-resize"> | Keyword<"ew-resize"> | Keyword<"ns-resize"> | Keyword<"nesw-resize"> | Keyword<"nwse-resize"> | Keyword<"col-resize"> | Keyword<"row-resize"> | Keyword<"all-scroll"> | Keyword<"zoom-in"> | Keyword<"zoom-out">]>, Tuple<[List<URL | Tuple<[URL, Number_2.Fixed, Number_2.Fixed]>>, Keyword<"auto"> | Keyword<"none"> | Keyword<"default"> | Keyword<"context-menu"> | Keyword<"help"> | Keyword<"pointer"> | Keyword<"progress"> | Keyword<"wait"> | Keyword<"cell"> | Keyword<"crosshair"> | Keyword<"text"> | Keyword<"vertical-text"> | Keyword<"alias"> | Keyword<"copy"> | Keyword<"move"> | Keyword<"no-drop"> | Keyword<"not-allowed"> | Keyword<"grab"> | Keyword<"grabbing"> | Keyword<"e-resize"> | Keyword<"n-resize"> | Keyword<"ne-resize"> | Keyword<"nw-resize"> | Keyword<"s-resize"> | Keyword<"se-resize"> | Keyword<"sw-resize"> | Keyword<"w-resize"> | Keyword<"ew-resize"> | Keyword<"ns-resize"> | Keyword<"nesw-resize"> | Keyword<"nwse-resize"> | Keyword<"col-resize"> | Keyword<"row-resize"> | Keyword<"all-scroll"> | Keyword<"zoom-in"> | Keyword<"zoom-out">]>>;
readonly display: Longhand<Tuple<[outside: Keyword<"block"> | Keyword<"inline"> | Keyword<"run-in">, inside: Keyword<"flow"> | Keyword<"flow-root"> | Keyword<"table"> | Keyword<"flex"> | Keyword<"grid"> | Keyword<"ruby">]> | Tuple<[outside: Keyword<"block"> | Keyword<"inline"> | Keyword<"run-in">, inside: Keyword<"flow"> | Keyword<"flow-root"> | Keyword<"table"> | Keyword<"flex"> | Keyword<"grid"> | Keyword<"ruby">, listitem: Keyword<"list-item">]> | Tuple<[outside: Keyword<"table-row-group"> | Keyword<"table-header-group"> | Keyword<"table-footer-group"> | Keyword<"table-row"> | Keyword<"table-cell"> | Keyword<"table-column-group"> | Keyword<"table-column"> | Keyword<"table-caption"> | Keyword<"ruby-base"> | Keyword<"ruby-text"> | Keyword<"ruby-base-container"> | Keyword<"ruby-text-container">, inside: Keyword<"flow"> | Keyword<"flow-root"> | Keyword<"table"> | Keyword<"flex"> | Keyword<"grid"> | Keyword<"ruby">]> | Tuple<[Keyword<"none"> | Keyword<"contents">]>, Tuple<[outside: Keyword<"block"> | Keyword<"inline"> | Keyword<"run-in">, inside: Keyword<"flow"> | Keyword<"flow-root"> | Keyword<"table"> | Keyword<"flex"> | Keyword<"grid"> | Keyword<"ruby">]> | Tuple<[outside: Keyword<"block"> | Keyword<"inline"> | Keyword<"run-in">, inside: Keyword<"flow"> | Keyword<"flow-root"> | Keyword<"table"> | Keyword<"flex"> | Keyword<"grid"> | Keyword<"ruby">, listitem: Keyword<"list-item">]> | Tuple<[outside: Keyword<"table-row-group"> | Keyword<"table-header-group"> | Keyword<"table-footer-group"> | Keyword<"table-row"> | Keyword<"table-cell"> | Keyword<"table-column-group"> | Keyword<"table-column"> | Keyword<"table-caption"> | Keyword<"ruby-base"> | Keyword<"ruby-text"> | Keyword<"ruby-base-container"> | Keyword<"ruby-text-container">, inside: Keyword<"flow"> | Keyword<"flow-root"> | Keyword<"table"> | Keyword<"flex"> | Keyword<"grid"> | Keyword<"ruby">]> | Tuple<[Keyword<"none"> | Keyword<"contents">]>>;
readonly "flex-direction": Longhand<Keyword.ToKeywords<"row" | "row-reverse" | "column" | "column-reverse">, Keyword.ToKeywords<"row" | "row-reverse" | "column" | "column-reverse">>;
readonly "flex-wrap": Longhand<Keyword.ToKeywords<"nowrap" | "wrap" | "wrap-reverse">, Keyword.ToKeywords<"nowrap" | "wrap" | "wrap-reverse">>;
readonly float: Longhand<Keyword.ToKeywords<"none" | "left" | "right">, Keyword.ToKeywords<"none" | "left" | "right">>;
readonly "font-family": Longhand<List<String_2 | Keyword<"serif"> | Keyword<"sans-serif"> | Keyword<"cursive"> | Keyword<"fantasy"> | Keyword<"monospace">>, List<String_2 | Keyword<"serif"> | Keyword<"sans-serif"> | Keyword<"cursive"> | Keyword<"fantasy"> | Keyword<"monospace">>>;
readonly "font-size": Longhand<LengthPercentage | Keyword<"medium"> | Keyword<"xx-small"> | Keyword<"x-small"> | Keyword<"small"> | Keyword<"large"> | Keyword<"x-large"> | Keyword<"xx-large"> | Keyword<"xxx-large"> | Keyword<"larger"> | Keyword<"smaller">, Length>;
readonly "font-stretch": Longhand<Specified_10, Percentage.Fixed<Numeric.Type> | Percentage.Calculated<Numeric.Type>>;
readonly "font-stretch": Longhand<Specified_10, Percentage.Calculated<Numeric.Type> | Percentage.Fixed<Numeric.Type>>;
readonly "font-style": Longhand<Keyword.ToKeywords<"normal" | "italic" | "oblique">, Keyword.ToKeywords<"normal" | "italic" | "oblique">>;
readonly "font-variant-caps": Longhand<Keyword.ToKeywords<"normal" | "small-caps" | "all-small-caps" | "petite-caps" | "all-petite-caps" | "unicase" | "titling-caps">, Keyword.ToKeywords<"normal" | "small-caps" | "all-small-caps" | "petite-caps" | "all-petite-caps" | "unicase" | "titling-caps">>;
readonly "font-variant-east-asian": Longhand<Specified_11, Specified_11>;
Expand Down Expand Up @@ -216,7 +217,7 @@ export namespace Longhands {
readonly "vertical-align": Longhand<LengthPercentage | (Keyword<"top"> | Keyword<"bottom"> | Keyword<"sub"> | Keyword<"super"> | Keyword<"baseline"> | Keyword<"text-top"> | Keyword<"text-bottom"> | Keyword<"middle">), Length | (Keyword<"top"> | Keyword<"bottom"> | Keyword<"sub"> | Keyword<"super"> | Keyword<"baseline"> | Keyword<"text-top"> | Keyword<"text-bottom"> | Keyword<"middle">)>;
readonly visibility: Longhand<Keyword.ToKeywords<"hidden" | "collapse" | "visible">, Keyword.ToKeywords<"hidden" | "collapse" | "visible">>;
readonly "white-space": Longhand<Keyword.ToKeywords<"nowrap" | "normal" | "pre" | "pre-wrap" | "break-spaces" | "pre-line">, Keyword.ToKeywords<"nowrap" | "normal" | "pre" | "pre-wrap" | "break-spaces" | "pre-line">>;
readonly width: Longhand<Percentage | Length | Keyword<"auto">, Length | Percentage.Canonical | Keyword<"auto">>;
readonly width: Longhand<LengthPercentage | Keyword<"auto">, LengthPercentage | Keyword<"auto">>;
readonly "word-spacing": Longhand<Length | Keyword<"normal">, Length>;
};
// (undocumented)
Expand Down Expand Up @@ -420,6 +421,8 @@ export class Value<T = unknown> implements Functor<T>, Applicative<T>, Monad<T>,
// (undocumented)
static of<T>(value: T, source?: Option<Declaration>): Value<T>;
// (undocumented)
resolve<T extends Value_2>(this: Value<T>, resolver?: Resolvable.Resolver<T>): Value<Resolvable.Resolved<T>>;
// (undocumented)
some(predicate: Predicate<T, [source: Option<Declaration>]>): boolean;
// (undocumented)
get source(): Option<Declaration>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Parser } from "@siteimprove/alfa-parser";

import { type Parser as CSSParser, Token } from "../../../../syntax";

import { Resolvable } from "../../../resolvable";
import { Value } from "../../../value";

import { Position } from "./position";
Expand All @@ -12,7 +13,10 @@ const { map, either, pair, option, right } = Parser;
/**
* @internal
*/
export class Corner extends Value<"corner", false> {
export class Corner
extends Value<"corner", false>
implements Resolvable<Corner.Canonical, Corner.Resolver>
{
public static of(
vertical: Position.Vertical,
horizontal: Position.Horizontal,
Expand Down
6 changes: 5 additions & 1 deletion packages/alfa-css/src/value/image/gradient/linear/side.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Parser } from "@siteimprove/alfa-parser";

import { Token } from "../../../../syntax";

import { Resolvable } from "../../../resolvable";
import { Value } from "../../../value";

import { Position } from "./position";
Expand All @@ -12,7 +13,10 @@ const { map, option, right } = Parser;
/**
* @internal
*/
export class Side extends Value<"side", false> {
export class Side
extends Value<"side", false>
implements Resolvable<Side.Canonical, Side.Resolver>
{
public static of(side: Position.Vertical | Position.Horizontal): Side {
return new Side(side);
}
Expand Down
9 changes: 5 additions & 4 deletions packages/alfa-css/src/value/image/gradient/radial/circle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ import { Parser as CSSParser, Token } from "../../../../syntax";

import { Keyword } from "../../../keyword";
import { Length } from "../../../numeric";
import { Resolvable } from "../../../resolvable";
import { Value } from "../../../value";

/**
* {@link https://drafts.csswg.org/css-images/#valdef-ending-shape-circle}
*
* @internal
*/
export class Circle<R extends Length = Length> extends Value<
"circle",
Value.HasCalculation<[R]>
> {
export class Circle<R extends Length = Length>
extends Value<"circle", Value.HasCalculation<[R]>>
implements Resolvable<Circle.Canonical, Circle.Resolver>
{
public static of<R extends Length>(radius: R): Circle<R> {
return new Circle(radius);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ import { Err, Result } from "@siteimprove/alfa-result";
import { Parser as CSSParser, Token } from "../../../../syntax";

import { Keyword } from "../../../keyword";
import { Resolvable } from "../../../resolvable";
import { Value } from "../../../value";

const { map } = Parser;

/**
* @internal
*/
export class Extent extends Value<"extent", false> {
export class Extent
extends Value<"extent", false>
implements Resolvable<Extent.Canonical, Extent.Resolver>
{
public static of(
shape: Extent.Shape = Extent.Shape.Circle,
size: Extent.Size = Extent.Size.FarthestCorner,
Expand Down
34 changes: 18 additions & 16 deletions packages/alfa-css/src/value/image/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Parser } from "@siteimprove/alfa-parser";
import { Selective } from "@siteimprove/alfa-selective";

import type { Parser as CSSParser } from "../../syntax";
import { PartiallyResolvable, Resolvable } from "../resolvable";

import { Value } from "../value";

Expand All @@ -16,10 +17,12 @@ const { map, either } = Parser;
*
* @public
*/
export class Image<I extends URL | Gradient = URL | Gradient> extends Value<
"image",
Value.HasCalculation<[I]>
> {
export class Image<I extends URL | Gradient = URL | Gradient>
extends Value<"image", Value.HasCalculation<[I]>>
implements
Resolvable<Image.Canonical, Image.Resolver>,
PartiallyResolvable<Image.PartiallyResolved, Image.PartialResolver>
{
public static of<I extends URL | Gradient>(image: I): Image<I> {
return new Image(image);
}
Expand All @@ -39,6 +42,17 @@ export class Image<I extends URL | Gradient = URL | Gradient> extends Value<
return new Image(this._image.resolve(resolver));
}

public partiallyResolve(
resolver: Image.PartialResolver,
): Image.PartiallyResolved {
return Image.of(
Selective.of(this._image)
.if(URL.isURL, (url) => url.resolve())
.else((gradient) => gradient.partiallyResolve(resolver))
.get(),
);
}

public equals(value: unknown): value is this {
return value instanceof Image && value._image.equals(this._image);
}
Expand Down Expand Up @@ -77,18 +91,6 @@ export namespace Image {

export type PartialResolver = URL.Resolver & Gradient.PartialResolver;

export function partiallyResolve(
resolver: PartialResolver,
): (value: Image) => PartiallyResolved {
return (value) =>
Image.of(
Selective.of(value.image)
.if(URL.isURL, (url) => url.resolve())
.else((gradient) => gradient.partiallyResolve(resolver))
.get(),
);
}

export function isImage<I extends URL | Gradient>(
value: unknown,
): value is Image<I> {
Expand Down
3 changes: 2 additions & 1 deletion packages/alfa-css/src/value/image/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Hash } from "@siteimprove/alfa-hash";
import { Parser } from "@siteimprove/alfa-parser";

import { Function, type Parser as CSSParser, Token } from "../../syntax";
import { Resolvable } from "../resolvable";

import { Value } from "../value";

Expand All @@ -12,7 +13,7 @@ const { map, either } = Parser;
*
* @public
*/
export class URL extends Value<"url", false> {
export class URL extends Value<"url", false> implements Resolvable<URL, never> {
public static of(url: string): URL {
return new URL(url);
}
Expand Down
1 change: 1 addition & 0 deletions packages/alfa-css/src/value/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from "./image";
export * from "./keyword";
export * from "./numeric";
export * from "./position";
export * from "./resolvable";
export * from "./shadow";
export * from "./shape";
export * from "./string";
Expand Down
6 changes: 3 additions & 3 deletions packages/alfa-css/src/value/numeric/percentage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export type Percentage<H extends BaseNumeric.Type = BaseNumeric.Type> =
* @public
*/
export namespace Percentage {
export type Canonical = Fixed;
export type Canonical = Fixed<"percentage">;

export type PartiallyResolved<H extends BaseNumeric.Type> = Fixed<H>;

Expand Down Expand Up @@ -80,13 +80,13 @@ export namespace Percentage {
return true;
}

public resolve(): Canonical;
public resolve(): Fixed<H>;

public resolve<T extends Canonicals[H]>(resolver: Resolver<H>): T;

public resolve<T extends Canonicals[H]>(
resolver?: Resolver<H>,
): Canonical | T {
): Fixed<H> | T {
const percentage = Fixed.of<H>(
this._math
.resolve()
Expand Down
8 changes: 6 additions & 2 deletions packages/alfa-css/src/value/shape/rectangle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Comma, Function, type Parser as CSSParser, Token } from "../../syntax";

import { Keyword } from "../keyword";
import { Length } from "../numeric";
import { Resolvable } from "../resolvable";
import { Value } from "../value";

import { BasicShape } from "./basic-shape";
Expand All @@ -18,8 +19,11 @@ const { either, map, option, separatedList } = Parser;
* @deprecated Deprecated as of CSS Masking Module Level 1
*/
export class Rectangle<
O extends Length | Rectangle.Auto = Length | Rectangle.Auto,
> extends BasicShape<"rectangle", Value.HasCalculation<[O, O, O, O]>> {
O extends Length | Rectangle.Auto = Length | Rectangle.Auto,
>
extends BasicShape<"rectangle", Value.HasCalculation<[O, O, O, O]>>
implements Resolvable<Rectangle.Canonical, Rectangle.Resolver>
{
public static of<O extends Length | Rectangle.Auto = Length | Rectangle.Auto>(
top: O,
right: O,
Expand Down
Loading