Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into cleanup--witty-common…
Browse files Browse the repository at this point in the history
…-loon-1313670dd0
  • Loading branch information
romainmenke committed Nov 11, 2024
2 parents 9a37883 + 8fcf47d commit 0abd59a
Show file tree
Hide file tree
Showing 43 changed files with 1,266 additions and 54 deletions.
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/css-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ body:
- PostCSS Place
- PostCSS Progressive Custom Properties
- PostCSS Pseudo Class Any Link
- PostCSS Random Function
- PostCSS Rebase URL
- PostCSS Rewrite URL
- PostCSS Rebeccapurple
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/plugin-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ body:
- PostCSS Place
- PostCSS Progressive Custom Properties
- PostCSS Pseudo Class Any Link
- PostCSS Random Function
- PostCSS Rebase URL
- PostCSS Rewrite URL
- PostCSS Rebeccapurple
Expand Down
6 changes: 6 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,12 @@
- plugins/postcss-pseudo-class-any-link/**
- experimental/postcss-pseudo-class-any-link/**

"plugins/postcss-random-function":
- changed-files:
- any-glob-to-any-file:
- plugins/postcss-random-function/**
- experimental/postcss-random-function/**

"plugins/postcss-rebase-url":
- changed-files:
- any-glob-to-any-file:
Expand Down
41 changes: 37 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions packages/css-calc/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changes to CSS Calc

### Unreleased (minor)

- Add support for `random()`

### 2.0.4

_November 1, 2024_
Expand Down
2 changes: 1 addition & 1 deletion packages/css-calc/dist/index.cjs

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions packages/css-calc/dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export declare type conversionOptions = {
* @see https://drafts.csswg.org/css-values-4/#calc-simplification
*/
rawPercentages?: boolean;
/**
* Seed the pseudo random number generator used in `random()`
*/
randomSeed?: number;
};

export declare type GlobalsWithStrings = Map<string, TokenDimension | TokenNumber | TokenPercentage | string>;
Expand Down
2 changes: 1 addition & 1 deletion packages/css-calc/dist/index.mjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/css-calc/docs/css-calc.api.json
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@
},
{
"kind": "Content",
"text": ";\n precision?: number;\n toCanonicalUnits?: boolean;\n censorIntoStandardRepresentableValues?: boolean;\n rawPercentages?: boolean;\n}"
"text": ";\n precision?: number;\n toCanonicalUnits?: boolean;\n censorIntoStandardRepresentableValues?: boolean;\n rawPercentages?: boolean;\n randomSeed?: number;\n}"
},
{
"kind": "Content",
Expand Down
1 change: 1 addition & 0 deletions packages/css-calc/docs/css-calc.conversionoptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type conversionOptions = {
toCanonicalUnits?: boolean;
censorIntoStandardRepresentableValues?: boolean;
rawPercentages?: boolean;
randomSeed?: number;
};
```
**References:** [GlobalsWithStrings](./css-calc.globalswithstrings.md)
Expand Down
129 changes: 111 additions & 18 deletions packages/css-calc/src/functions/calc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { TokenType, NumberType, isTokenOpenParen, isTokenDelim, isTokenComma, is
import { addition } from '../operation/addition';
import { division } from '../operation/division';
import { isCalculation, solve } from '../calculation';
import { isCommentNode, FunctionNode, TokenNode, isFunctionNode, isSimpleBlockNode, isTokenNode, isWhitespaceNode } from '@csstools/css-parser-algorithms';
import { FunctionNode, TokenNode, isFunctionNode, isSimpleBlockNode, isTokenNode, isWhiteSpaceOrCommentNode } from '@csstools/css-parser-algorithms';
import { multiplication } from '../operation/multiplication';
import { resolveGlobalsAndConstants } from './globals-and-constants';
import { solveACos } from './acos';
Expand All @@ -32,6 +32,7 @@ import { unary } from '../operation/unary';
import { solveLog } from './log';
import { isNone } from '../util/is-none';
import type { conversionOptions } from '../options';
import { solveRandom } from './random';

type mathFunction = (node: FunctionNode, globals: Globals, options: conversionOptions) => Calculation | -1

Expand All @@ -51,6 +52,7 @@ export const mathFunctions: Map<string, mathFunction> = new Map([
['min', min],
['mod', mod],
['pow', pow],
['random', random],
['rem', rem],
['round', round],
['sign', sign],
Expand All @@ -61,7 +63,7 @@ export const mathFunctions: Map<string, mathFunction> = new Map([

function calc(calcNode: FunctionNode | SimpleBlockNode, globals: Globals, options: conversionOptions): Calculation | -1 {
const nodes: Array<ComponentValue | Calculation> = resolveGlobalsAndConstants(
[...(calcNode.value.filter(x => !isCommentNode(x) && !isWhitespaceNode(x)))],
[...(calcNode.value.filter(x => !isWhiteSpaceOrCommentNode(x)))],
globals,
);

Expand Down Expand Up @@ -215,8 +217,17 @@ function calc(calcNode: FunctionNode | SimpleBlockNode, globals: Globals, option
}

function singleNodeSolver(fnNode: FunctionNode, globals: Globals, options: conversionOptions, solveFn: (node: FunctionNode, a: TokenNode, options: conversionOptions) => Calculation | -1): Calculation | -1 {
const a = singleArgument(fnNode.value, globals, options);
if (a === -1) {
return -1;
}

return solveFn(fnNode, a, options);
}

function singleArgument(values: Array<ComponentValue>, globals: Globals, options: conversionOptions): TokenNode | -1 {
const nodes: Array<ComponentValue> = resolveGlobalsAndConstants(
[...(fnNode.value.filter(x => !isCommentNode(x) && !isWhitespaceNode(x)))],
[...(values.filter(x => !isWhiteSpaceOrCommentNode(x)))],
globals,
);

Expand All @@ -225,12 +236,23 @@ function singleNodeSolver(fnNode: FunctionNode, globals: Globals, options: conve
return -1;
}

return solveFn(fnNode, a, options);
return a;
}

function twoCommaSeparatedNodesSolver(fnNode: FunctionNode, globals: Globals, options: conversionOptions, solveFn: (node: FunctionNode, a: TokenNode, b: TokenNode, options: conversionOptions) => Calculation | -1): Calculation | -1 {
const solvedNodes = twoCommaSeparatedArguments(fnNode.value, globals, options);
if (solvedNodes === -1) {
return -1;
}

const [a, b] = solvedNodes;

return solveFn(fnNode, a, b, options);
}

function twoCommaSeparatedArguments(values: Array<ComponentValue>, globals: Globals, options: conversionOptions): [TokenNode, TokenNode] | -1 {
const nodes: Array<ComponentValue> = resolveGlobalsAndConstants(
[...(fnNode.value.filter(x => !isCommentNode(x) && !isWhitespaceNode(x)))],
[...(values.filter(x => !isWhiteSpaceOrCommentNode(x)))],
globals,
);

Expand Down Expand Up @@ -270,20 +292,29 @@ function twoCommaSeparatedNodesSolver(fnNode: FunctionNode, globals: Globals, op
return -1;
}

return solveFn(fnNode, a, b, options);
return [a, b];
}

function variadicNodesSolver(fnNode: FunctionNode, values: Array<ComponentValue>, globals: Globals, options: conversionOptions, solveFn: (node: FunctionNode, x: Array<ComponentValue>, options: conversionOptions) => Calculation | -1): Calculation | -1 {
const solvedNodes = variadicArguments(fnNode.value, globals, options);
if (solvedNodes === -1) {
return -1;
}

return solveFn(fnNode, solvedNodes, options);
}

function variadicNodesSolver(fnNode: FunctionNode, globals: Globals, options: conversionOptions, solveFn: (node: FunctionNode, x: Array<ComponentValue>, options: conversionOptions) => Calculation | -1): Calculation | -1 {
function variadicArguments(values: Array<ComponentValue>, globals: Globals, options: conversionOptions): Array<TokenNode> | -1 {
const nodes: Array<ComponentValue> = resolveGlobalsAndConstants(
[...(fnNode.value.filter(x => !isCommentNode(x) && !isWhitespaceNode(x)))],
[...(values.filter(x => !isWhiteSpaceOrCommentNode(x)))],
globals,
);

const solvedNodes: Array<ComponentValue> = [];
const solvedNodes: Array<TokenNode> = [];

{
const chunks = [];
let chunk = [];
const chunks: Array<Array<ComponentValue>> = [];
let chunk: Array<ComponentValue> = [];
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (isTokenNode(node) && isTokenComma(node.value)) {
Expand Down Expand Up @@ -311,12 +342,12 @@ function variadicNodesSolver(fnNode: FunctionNode, globals: Globals, options: co
}
}

return solveFn(fnNode, solvedNodes, options);
return solvedNodes;
}

function clamp(clampNode: FunctionNode, globals: Globals, options: conversionOptions): Calculation | -1 {
const nodes: Array<ComponentValue> = resolveGlobalsAndConstants(
[...(clampNode.value.filter(x => !isCommentNode(x) && !isWhitespaceNode(x)))],
[...(clampNode.value.filter(x => !isWhiteSpaceOrCommentNode(x)))],
globals,
);

Expand Down Expand Up @@ -394,11 +425,11 @@ function clamp(clampNode: FunctionNode, globals: Globals, options: conversionOpt
}

function max(maxNode: FunctionNode, globals: Globals, options: conversionOptions): Calculation | -1 {
return variadicNodesSolver(maxNode, globals, options, solveMax);
return variadicNodesSolver(maxNode, maxNode.value, globals, options, solveMax);
}

function min(minNode: FunctionNode, globals: Globals, options: conversionOptions): Calculation | -1 {
return variadicNodesSolver(minNode, globals, options, solveMin);
return variadicNodesSolver(minNode, minNode.value, globals, options, solveMin);
}

const roundingStrategies = new Set([
Expand All @@ -410,7 +441,7 @@ const roundingStrategies = new Set([

function round(roundNode: FunctionNode, globals: Globals, options: conversionOptions): Calculation | -1 {
const nodes: Array<ComponentValue> = resolveGlobalsAndConstants(
[...(roundNode.value.filter(x => !isCommentNode(x) && !isWhitespaceNode(x)))],
[...(roundNode.value.filter(x => !isWhiteSpaceOrCommentNode(x)))],
globals,
);

Expand Down Expand Up @@ -537,11 +568,73 @@ function pow(powNode: FunctionNode, globals: Globals, options: conversionOptions
}

function hypot(hypotNode: FunctionNode, globals: Globals, options: conversionOptions): Calculation | -1 {
return variadicNodesSolver(hypotNode, globals, options, solveHypot);
return variadicNodesSolver(hypotNode, hypotNode.value, globals, options, solveHypot);
}

function log(logNode: FunctionNode, globals: Globals, options: conversionOptions): Calculation | -1 {
return variadicNodesSolver(logNode, globals, options, solveLog);
return variadicNodesSolver(logNode, logNode.value, globals, options, solveLog);
}

function random(randomNode: FunctionNode, globals: Globals, options: conversionOptions): Calculation | -1 {
const nodes: Array<ComponentValue> = randomNode.value.filter(x => !isWhiteSpaceOrCommentNode(x));

let randomCachingOptions = '';
const stepValues: Array<ComponentValue> = []
const values: Array<ComponentValue> = []

{
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (!randomCachingOptions && values.length === 0 && isTokenNode(node) && isTokenIdent(node.value)) {
const token = node.value;
const tokenStr = token[4].value.toLowerCase();
if (tokenStr === 'per-element' || tokenStr.startsWith('--')) {
randomCachingOptions = tokenStr;

const nextNode = nodes[i + 1];
if (!isTokenNode(nextNode) || !isTokenComma(nextNode.value)) {
return -1;
}

i++;
continue;
}
}

if (isTokenNode(node) && isTokenComma(node.value)) {
const nextNode = nodes[i + 1];

if (values.length > 0 && isTokenNode(nextNode) && isTokenIdent(nextNode.value)) {
const token = nextNode.value;
const tokenStr = token[4].value.toLowerCase();
if (tokenStr === 'by' || tokenStr.startsWith('--')) {
stepValues.push(...nodes.slice(i + 2));

break;
}
}
}

values.push(node);
}
}

const solvedValues = twoCommaSeparatedArguments(values, globals, options);
if (solvedValues === -1) {
return -1;
}

const [a, b] = solvedValues;

let solvedStepValue: TokenNode | -1 | null = null;
if (stepValues.length) {
solvedStepValue = singleArgument(stepValues, globals, options);
if (solvedStepValue === -1) {
return -1;
}
}

return solveRandom(randomNode, randomCachingOptions, a, b, solvedStepValue, options);
}

function calcWrapper(v: Array<ComponentValue>): FunctionNode {
Expand Down
14 changes: 5 additions & 9 deletions packages/css-calc/src/functions/hypot.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Calculation } from '../calculation';
import type { ComponentValue, FunctionNode, TokenNode } from '@csstools/css-parser-algorithms';
import type { ComponentValue, FunctionNode } from '@csstools/css-parser-algorithms';
import { convertUnit } from '../unit-conversions';
import { isTokenNode } from '@csstools/css-parser-algorithms';
import { resultToCalculation } from './result-to-calculation';
Expand All @@ -8,15 +8,11 @@ import { isTokenNumeric, isTokenPercentage } from '@csstools/css-tokenizer';
import type { conversionOptions } from '../options';

export function solveHypot(hypotNode: FunctionNode, solvedNodes: Array<ComponentValue>, options: conversionOptions): Calculation | -1 {
const firstSolvedNode = solvedNodes[0];
if (!firstSolvedNode || !isTokenNode(firstSolvedNode)) {
return -1;
if (!solvedNodes.every(isTokenNode)) {
return -1
}

const componentTypes = new Set(solvedNodes.map((x) => x.type));
if (componentTypes.size !== 1) {
return -1;
}
const firstSolvedNode = solvedNodes[0];

const firstSolvedToken = firstSolvedNode.value;
if (!isTokenNumeric(firstSolvedToken)) {
Expand All @@ -27,7 +23,7 @@ export function solveHypot(hypotNode: FunctionNode, solvedNodes: Array<Component
return -1;
}

const tokens = solvedNodes.map((x) => convertUnit(firstSolvedToken, (x as TokenNode).value));
const tokens = solvedNodes.map((x) => convertUnit(firstSolvedToken, x.value));
if (!arrayOfSameNumeric(tokens)) {
return -1;
}
Expand Down
Loading

0 comments on commit 0abd59a

Please sign in to comment.