Skip to content

Commit

Permalink
Style cleanup (#1510)
Browse files Browse the repository at this point in the history
* Properly use calculatable length-percentages

* Correctly hint percentages

* Improve resolving

* Clean up

* Correctly resolve

* Add resolve mapper to Style Value

* Clean up

* Replace function with method

* Replace function with method

* Correctly implement (Partially)Resolvable

* Deep clean up

* Extract API

* Clean up

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
Jym77 and github-actions[bot] authored Nov 28, 2023
1 parent 6674a4f commit 75adbe4
Show file tree
Hide file tree
Showing 33 changed files with 270 additions and 161 deletions.
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
6 changes: 5 additions & 1 deletion packages/alfa-css/src/value/image/gradient/linear/corner.ts
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
6 changes: 5 additions & 1 deletion packages/alfa-css/src/value/image/gradient/radial/extent.ts
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

0 comments on commit 75adbe4

Please sign in to comment.