|
1 | 1 | import type { Calculation } from '../calculation';
|
2 | 2 | import type { ComponentValue, SimpleBlockNode } from '@csstools/css-parser-algorithms';
|
3 | 3 | import type { Globals } from '../util/globals';
|
4 |
| -import { TokenType, NumberType, isTokenOpenParen, isTokenDelim, isTokenComma, isTokenIdent } from '@csstools/css-tokenizer'; |
| 4 | +import { TokenType, NumberType, isTokenOpenParen, isTokenDelim, isTokenComma, isTokenIdent, isTokenNumber } from '@csstools/css-tokenizer'; |
5 | 5 | import { addition } from '../operation/addition';
|
6 | 6 | import { division } from '../operation/division';
|
7 | 7 | import { isCalculation, solve } from '../calculation';
|
@@ -32,6 +32,7 @@ import { unary } from '../operation/unary';
|
32 | 32 | import { solveLog } from './log';
|
33 | 33 | import { isNone } from '../util/is-none';
|
34 | 34 | import type { conversionOptions } from '../options';
|
| 35 | +import type { RandomValueSharing} from './random'; |
35 | 36 | import { solveRandom } from './random';
|
36 | 37 |
|
37 | 38 | type mathFunction = (node: FunctionNode, globals: Globals, options: conversionOptions) => Calculation | -1
|
@@ -576,65 +577,127 @@ function log(logNode: FunctionNode, globals: Globals, options: conversionOptions
|
576 | 577 | }
|
577 | 578 |
|
578 | 579 | function random(randomNode: FunctionNode, globals: Globals, options: conversionOptions): Calculation | -1 {
|
579 |
| - const nodes: Array<ComponentValue> = randomNode.value.filter(x => !isWhiteSpaceOrCommentNode(x)); |
| 580 | + const randomValueSharingAndNodes = parseRandomValueSharing( |
| 581 | + randomNode.value.filter(x => !isWhiteSpaceOrCommentNode(x)), |
| 582 | + globals, |
| 583 | + options, |
| 584 | + ); |
| 585 | + if (randomValueSharingAndNodes === -1) { |
| 586 | + return -1; |
| 587 | + } |
580 | 588 |
|
581 |
| - let randomCachingOptions = ''; |
582 |
| - const stepValues: Array<ComponentValue> = [] |
583 |
| - const values: Array<ComponentValue> = [] |
| 589 | + const [randomValueSharing, nodes] = randomValueSharingAndNodes; |
584 | 590 |
|
585 |
| - { |
586 |
| - for (let i = 0; i < nodes.length; i++) { |
587 |
| - const node = nodes[i]; |
588 |
| - if (!randomCachingOptions && values.length === 0 && isTokenNode(node) && isTokenIdent(node.value)) { |
589 |
| - const token = node.value; |
590 |
| - const tokenStr = token[4].value.toLowerCase(); |
591 |
| - if (tokenStr === 'per-element' || tokenStr.startsWith('--')) { |
592 |
| - randomCachingOptions = tokenStr; |
| 591 | + const randomArguments = variadicArguments(nodes, globals, options); |
| 592 | + if (randomArguments === -1) { |
| 593 | + return -1; |
| 594 | + } |
593 | 595 |
|
594 |
| - const nextNode = nodes[i + 1]; |
595 |
| - if (!isTokenNode(nextNode) || !isTokenComma(nextNode.value)) { |
596 |
| - return -1; |
597 |
| - } |
| 596 | + const [a, b, c] = randomArguments; |
598 | 597 |
|
599 |
| - i++; |
600 |
| - continue; |
601 |
| - } |
| 598 | + if (!a || !b) { |
| 599 | + return -1 |
| 600 | + } |
| 601 | + |
| 602 | + return solveRandom( |
| 603 | + randomNode, |
| 604 | + randomValueSharing, |
| 605 | + a, |
| 606 | + b, |
| 607 | + c, |
| 608 | + options |
| 609 | + ); |
| 610 | +} |
| 611 | + |
| 612 | +function parseRandomValueSharing(nodes: Array<ComponentValue>, globals: Globals, options: conversionOptions): [RandomValueSharing, Array<ComponentValue>] | -1 { |
| 613 | + const x: RandomValueSharing = { |
| 614 | + isAuto: false, |
| 615 | + dashedIdent: "", |
| 616 | + fixed: -1, |
| 617 | + elementShared: false, |
| 618 | + }; |
| 619 | + |
| 620 | + const firstNode = nodes[0]; |
| 621 | + if (!isTokenNode(firstNode) || !isTokenIdent(firstNode.value)) { |
| 622 | + return [x, nodes]; |
| 623 | + } |
| 624 | + |
| 625 | + for (let i = 0; i < nodes.length; i++) { |
| 626 | + const node = nodes[i]; |
| 627 | + if (!isTokenNode(node)) { |
| 628 | + return -1; |
| 629 | + } |
| 630 | + |
| 631 | + if (isTokenComma(node.value)) { |
| 632 | + return [x, nodes.slice(i+1)]; |
| 633 | + } |
| 634 | + |
| 635 | + if (!isTokenIdent(node.value)) { |
| 636 | + return -1; |
| 637 | + } |
| 638 | + |
| 639 | + const token = node.value; |
| 640 | + const tokenStr = token[4].value.toLowerCase(); |
| 641 | + |
| 642 | + if (tokenStr === 'element-shared') { |
| 643 | + if (x.fixed !== -1) { |
| 644 | + return -1; |
602 | 645 | }
|
603 | 646 |
|
604 |
| - if (isTokenNode(node) && isTokenComma(node.value)) { |
605 |
| - const nextNode = nodes[i + 1]; |
| 647 | + x.elementShared = true; |
| 648 | + continue; |
| 649 | + } |
606 | 650 |
|
607 |
| - if (values.length > 0 && isTokenNode(nextNode) && isTokenIdent(nextNode.value)) { |
608 |
| - const token = nextNode.value; |
609 |
| - const tokenStr = token[4].value.toLowerCase(); |
610 |
| - if (tokenStr === 'by' || tokenStr.startsWith('--')) { |
611 |
| - stepValues.push(...nodes.slice(i + 2)); |
| 651 | + // fixed <number [0,1]> |
| 652 | + if (tokenStr === 'fixed') { |
| 653 | + if (x.elementShared || x.dashedIdent || x.isAuto) { |
| 654 | + return -1; |
| 655 | + } |
612 | 656 |
|
613 |
| - break; |
614 |
| - } |
615 |
| - } |
| 657 | + i++; |
| 658 | + const nextNode = nodes[i]; |
| 659 | + if (!nextNode) { |
| 660 | + return -1; |
| 661 | + } |
| 662 | + |
| 663 | + const fixedNumber = solve(calc(calcWrapper([nextNode]), globals, options)); |
| 664 | + if (fixedNumber === -1) { |
| 665 | + return -1; |
| 666 | + } |
| 667 | + |
| 668 | + if (!isTokenNumber(fixedNumber.value)) { |
| 669 | + return -1; |
| 670 | + } |
| 671 | + |
| 672 | + if (fixedNumber.value[4].value < 0 || fixedNumber.value[4].value > 1) { |
| 673 | + return -1; |
616 | 674 | }
|
617 | 675 |
|
618 |
| - values.push(node); |
| 676 | + x.fixed = Math.max(0, Math.min(fixedNumber.value[4].value, 1 - 0.000_000_001)); |
| 677 | + |
| 678 | + continue; |
619 | 679 | }
|
620 |
| - } |
621 | 680 |
|
622 |
| - const solvedValues = twoCommaSeparatedArguments(values, globals, options); |
623 |
| - if (solvedValues === -1) { |
624 |
| - return -1; |
625 |
| - } |
| 681 | + if (tokenStr === 'auto') { |
| 682 | + if (x.fixed !== -1 || x.dashedIdent) { |
| 683 | + return -1; |
| 684 | + } |
626 | 685 |
|
627 |
| - const [a, b] = solvedValues; |
| 686 | + x.isAuto = true; |
| 687 | + continue; |
| 688 | + } |
628 | 689 |
|
629 |
| - let solvedStepValue: TokenNode | -1 | null = null; |
630 |
| - if (stepValues.length) { |
631 |
| - solvedStepValue = singleArgument(stepValues, globals, options); |
632 |
| - if (solvedStepValue === -1) { |
633 |
| - return -1; |
| 690 | + if (tokenStr.startsWith('--')) { |
| 691 | + if (x.fixed !== -1 || x.isAuto) { |
| 692 | + return -1; |
| 693 | + } |
| 694 | + |
| 695 | + x.dashedIdent = tokenStr; |
| 696 | + continue; |
634 | 697 | }
|
635 | 698 | }
|
636 | 699 |
|
637 |
| - return solveRandom(randomNode, randomCachingOptions, a, b, solvedStepValue, options); |
| 700 | + return -1; |
638 | 701 | }
|
639 | 702 |
|
640 | 703 | function calcWrapper(v: Array<ComponentValue>): FunctionNode {
|
|
0 commit comments