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

Add support for hyphenation properties #1762

Draft
wants to merge 21 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 16 commits
Commits
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
5 changes: 5 additions & 0 deletions .changeset/dull-snakes-jam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@siteimprove/alfa-result": minor
---

**Added:** `Result#forEach` and `Result#forEachErr` methods are now available.
5 changes: 5 additions & 0 deletions .changeset/quick-moles-argue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@siteimprove/alfa-style": minor
---

**Added:** Legacy name alias properties are now supported.
5 changes: 5 additions & 0 deletions .changeset/silly-years-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@siteimprove/alfa-style": minor
---

**Added:** Properties `overflow-wrap` and `word-wrap` are now supported.
5 changes: 5 additions & 0 deletions .changeset/two-steaks-hope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@siteimprove/alfa-test": minor
---

**Added:** A timeout can now be passed to vitest.
12 changes: 12 additions & 0 deletions docs/review/api/alfa-result.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ export class Err<E> implements Result<never, E> {
// (undocumented)
flatten<T, E>(this: Result<never, E>): Result<T, E>;
// (undocumented)
forEach(callback: Callback<never>): void;
// (undocumented)
forEachErr(callback: Callback<E>): void;
// (undocumented)
getErr(): E;
// (undocumented)
getErrOr(): E;
Expand Down Expand Up @@ -150,6 +154,10 @@ export class Ok<T> implements Result<T, never> {
// (undocumented)
flatten<T, E>(this: Ok<Result<T, E>>): Result<T, E>;
// (undocumented)
forEach(callback: Callback<T>): void;
// (undocumented)
forEachErr(callback: Callback<never>): void;
// (undocumented)
get(): T;
// (undocumented)
getErrOr<F>(error: F): F;
Expand Down Expand Up @@ -251,6 +259,10 @@ export interface Result<T, E = T> extends Monad<T>, Foldable<T>, Iterable<T>, Eq
// (undocumented)
flatten<T, E>(this: Result<Result<T, E>, E>): Result<T, E>;
// (undocumented)
forEach(callback: Callback<T>): void;
// (undocumented)
forEachErr(callback: Callback<E>): void;
// (undocumented)
getErrOr<F>(error: F): E | F;
// (undocumented)
getErrOrElse<F>(error: Callback<T, F>): E | F;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"package-dependency-graph": "^1.14.4",
"prettier": "^3.0.0",
"typescript": "^5.7.3",
"vitest": "^3.0.4"
"vitest": "^3.0.6"
},
"packageManager": "[email protected]"
}
10 changes: 2 additions & 8 deletions packages/alfa-cascade/src/cascade.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { Cache } from "@siteimprove/alfa-cache";
import type { Device } from "@siteimprove/alfa-device";
import type {
Document,
Node} from "@siteimprove/alfa-dom";
import {
Element,
Shadow,
Slotable,
} from "@siteimprove/alfa-dom";
import type { Document, Node } from "@siteimprove/alfa-dom";
import { Element, Shadow, Slotable } from "@siteimprove/alfa-dom";
import { Iterable } from "@siteimprove/alfa-iterable";
import type { Serializable } from "@siteimprove/alfa-json";
import { Context } from "@siteimprove/alfa-selector";
Expand Down
4 changes: 1 addition & 3 deletions packages/alfa-equatable/test/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"extends": "../tsconfig.json",
"compilerOptions": {
"noEmit": true
},
"compilerOptions": { "noEmit": true },
"files": ["./equatable.spec.ts"],
"references": [{ "path": "../src" }, { "path": "../../alfa-test" }]
}
6 changes: 6 additions & 0 deletions packages/alfa-result/src/err.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ export class Err<E> implements Result<never, E> {
return err(this._error);
}

public forEach(callback: Callback<never>): void {}

public forEachErr(callback: Callback<E>): void {
callback(this._error);
}

public apply(): Err<E> {
return this;
}
Expand Down
7 changes: 6 additions & 1 deletion packages/alfa-result/src/ok.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { None, Option } from "@siteimprove/alfa-option";
import { Predicate } from "@siteimprove/alfa-predicate";
import type { Reducer } from "@siteimprove/alfa-reducer";
import type { Refinement } from "@siteimprove/alfa-refinement";
import type { Thunk } from "@siteimprove/alfa-thunk";

import type * as json from "@siteimprove/alfa-json";

Expand Down Expand Up @@ -49,6 +48,12 @@ export class Ok<T> implements Result<T, never> {
return ok(this._value);
}

public forEach(callback: Callback<T>): void {
callback(this._value);
}

public forEachErr(callback: Callback<never>): void {}

public apply<E, U>(mapper: Result<Mapper<T, U>, E>): Result<U, E> {
return mapper.map((mapper) => mapper(this._value));
}
Expand Down
2 changes: 2 additions & 0 deletions packages/alfa-result/src/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export interface Result<T, E = T>
map<U>(mapper: Mapper<T, U>): Result<U, E>;
mapErr<F>(mapper: Mapper<E, F>): Result<T, F>;
mapOrElse<U>(ok: Mapper<T, U>, err: Mapper<E, U>): U;
forEach(callback: Callback<T>): void;
forEachErr(callback: Callback<E>): void;
apply<U>(mapper: Result<Mapper<T, U>, E>): Result<U, E>;
flatMap<U>(mapper: Mapper<T, Result<U, E>>): Result<U, E>;
flatten<T, E>(this: Result<Result<T, E>, E>): Result<T, E>;
Expand Down
28 changes: 28 additions & 0 deletions packages/alfa-result/test/result.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,34 @@ test("#map() does nothing to an err value", (t) => {
);
});

test("#forEach() applies a callback to an ok value", (t) => {
let actual = 0;
n.forEach((n) => (actual = n));

t.deepEqual(actual, 1);
});

test("#forEach() does nothing to an err value", (t) => {
let actual = "";
err.forEach((n) => (actual = `${n}`));

t.equal(actual, "");
});

test("#forEachErr() does nothing to an ok value", (t) => {
let actual = 0;
n.forEachErr((msg) => (actual = msg.length));

t.deepEqual(actual, 0);
});

test("#forEachErr() applies a callback to an err value", (t) => {
let actual = "";
err.forEachErr((msg) => (actual = msg));

t.equal(actual, "error");
});

test(".from() constructs a result from a thunk", (t) => {
const n = Result.from(() => 1);

Expand Down
2 changes: 1 addition & 1 deletion packages/alfa-rng/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"@siteimprove/alfa-mapper": "workspace:^"
},
"devDependencies": {
"vitest": "^3.0.4"
"vitest": "^3.0.6"
},
"publishConfig": {
"access": "public",
Expand Down
2 changes: 2 additions & 0 deletions packages/alfa-style/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
"@siteimprove/alfa-applicative": "workspace:^",
"@siteimprove/alfa-array": "workspace:^",
"@siteimprove/alfa-cache": "workspace:^",
"@siteimprove/alfa-callback": "workspace:^",
"@siteimprove/alfa-cascade": "workspace:^",
"@siteimprove/alfa-css": "workspace:^",
"@siteimprove/alfa-device": "workspace:^",
"@siteimprove/alfa-dom": "workspace:^",
"@siteimprove/alfa-either": "workspace:^",
"@siteimprove/alfa-equatable": "workspace:^",
"@siteimprove/alfa-functor": "workspace:^",
"@siteimprove/alfa-iterable": "workspace:^",
Expand Down
61 changes: 53 additions & 8 deletions packages/alfa-style/src/longhands.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Refinement } from "@siteimprove/alfa-refinement";
import type { Longhand } from "./longhand.js";

import BackgroundAttachment from "./property/background-attachment.js";
Expand Down Expand Up @@ -50,8 +51,8 @@ import BorderTopStyle from "./property/border-top-style.js";
import BorderTopWidth from "./property/border-top-width.js";
import Bottom from "./property/bottom.js";
import BoxShadow from "./property/box-shadow.js";
import Clip from "./property/clip.js";
import ClipPath from "./property/clip-path.js";
import Clip from "./property/clip.js";
import Color from "./property/color.js";
import Contain from "./property/contain.js";
import ContainerType from "./property/container-type.js";
Expand Down Expand Up @@ -99,6 +100,7 @@ import OutlineColor from "./property/outline-color.js";
import OutlineOffset from "./property/outline-offset.js";
import OutlineStyle from "./property/outline-style.js";
import OutlineWidth from "./property/outline-width.js";
import OverflowWrap from "./property/overflow-wrap.js";
import OverflowX from "./property/overflow-x.js";
import OverflowY from "./property/overflow-y.js";
import Perspective from "./property/perspective.js";
Expand Down Expand Up @@ -132,8 +134,24 @@ import ZIndex from "./property/z-index.js";
*/
export namespace Longhands {
export type Property = typeof longHands;
/**
* @internal
*/
export type PropName = keyof Property;

type Aliases = typeof aliases;
type AliasesName = keyof Aliases;

export type Name = keyof Property;
export type Name = PropName | AliasesName;

/**
* @internal
*/
export type TrueName<N extends Name> = N extends PropName
? N
: N extends AliasesName
? Aliases[N]
: never;

/**
* Extract the parsed type of a named property.
Expand All @@ -147,7 +165,7 @@ export namespace Longhands {
* The parsed type doesn't really exist in CSS. It is an artefact on how we
* handle the default keywords.
*/
export type Parsed<N extends Name> = Longhand.Parsed<Property[N]>;
export type Parsed<N extends Name> = Longhand.Parsed<Property[TrueName<N>]>;

/**
* Extract the declared type of a named property.
Expand Down Expand Up @@ -180,7 +198,9 @@ export namespace Longhands {
*
* {@link https://drafts.csswg.org/css-cascade/#computed}
*/
export type Computed<N extends Name> = Longhand.Computed<Property[N]>;
export type Computed<N extends Name> = Longhand.Computed<
Property[TrueName<N>]
>;

/**
* Extract the initial type of a named property.
Expand Down Expand Up @@ -292,6 +312,7 @@ export namespace Longhands {
"outline-offset": OutlineOffset,
"outline-style": OutlineStyle,
"outline-width": OutlineWidth,
"overflow-wrap": OverflowWrap,
"overflow-x": OverflowX,
"overflow-y": OverflowY,
perspective: Perspective,
Expand Down Expand Up @@ -319,13 +340,37 @@ export namespace Longhands {
"will-change": WillChange,
"word-spacing": WordSpacing,
"z-index": ZIndex,
} as const;
};

/**
* {@link https://drafts.csswg.org/css-cascade-5/#legacy-name-alias}
*/
const aliases = {
// https://developer.mozilla.org/en-US/docs/Web/CSS/word-wrap
"word-wrap": "overflow-wrap",
} satisfies { [alias in string]: PropName };

export function isName(name: string): name is Name {
function isPropName(name: string): name is PropName {
return name in longHands;
}

export function get<N extends Name>(name: N): Property[N] {
return longHands[name];
function isAliasesName(name: string): name is AliasesName {
return name in aliases;
}

export const isName: (name: string) => name is Name = Refinement.or(
isPropName,
isAliasesName,
);

/**
* @internal
*/
export function propName<N extends Name>(name: N): TrueName<N> {
return (isAliasesName(name) ? aliases[name] : name) as TrueName<N>;
}

export function get<N extends Name>(name: N): Property[TrueName<N>] {
return longHands[propName(name)];
}
}
12 changes: 12 additions & 0 deletions packages/alfa-style/src/property/overflow-wrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Longhand } from "../longhand.js";

/**
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap}
* @internal
*/
export default Longhand.fromKeywords(
{ inherits: true },
"normal",
"break-word",
"anywhere",
);
Loading
Loading