Skip to content

Commit

Permalink
Add utility function to split string into component values
Browse files Browse the repository at this point in the history
  • Loading branch information
johannesodland committed Jan 24, 2024
1 parent db93642 commit fb9ecee
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 15 deletions.
4 changes: 2 additions & 2 deletions src/proxy-animation.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import {
removeAnimation,
relativePosition
} from "./scroll-timeline-base";
import {splitIntoComponentValues} from './utils';

const nativeDocumentGetAnimations = document.getAnimations;
const nativeElementGetAnimations = window.Element.prototype.getAnimations;
const nativeElementAnimate = window.Element.prototype.animate;
const nativeAnimation = window.Animation;

export const ANIMATION_RANGE_NAMES = ['entry', 'exit', 'cover', 'contain', 'entry-crossing', 'exit-crossing'];
const rangeNameRegExp = new RegExp(`(${ANIMATION_RANGE_NAMES.join('|')})(?!-)`);

class PromiseWrapper {
constructor() {
Expand Down Expand Up @@ -1782,7 +1782,7 @@ function parseTimelineRangeOffset(value, position) {
}
// Author passed in something like `"cover 100%"`
else {
const parts = value.split(rangeNameRegExp).map(part => part.trim()).filter(Boolean);
const parts = splitIntoComponentValues(value);

if (parts.length === 1) {
if (ANIMATION_RANGE_NAMES.includes(parts[0])) {
Expand Down
22 changes: 10 additions & 12 deletions src/scroll-timeline-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import {installCSSOM} from "./proxy-cssom.js";
import {simplifyCalculation} from "./simplify-calculation";
import {installCSSOM} from './proxy-cssom.js';
import {simplifyCalculation} from './simplify-calculation';
import {splitIntoComponentValues} from './utils';

installCSSOM();

Expand Down Expand Up @@ -713,17 +714,14 @@ function parseInset(value) {
let parts = value;
// Parse string parts to
if (typeof value === 'string') {
// Split value into separate parts
const stringParts = value.split(/(?<!\([^\)]*)\s(?![^\(]*\))/);
parts = stringParts.map(str => {
if (str.trim() === 'auto') {
parts = splitIntoComponentValues(value).map(str => {
if (str === 'auto') {
return 'auto';
} else {
try {
return CSSNumericValue.parse(str);
} catch (e) {
throw TypeError('Invalid inset');
}
}
try {
return CSSNumericValue.parse(str);
} catch (e) {
throw TypeError('Invalid inset');
}
});
}
Expand Down
50 changes: 50 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,54 @@ const canonicalUnits = new Set(["px", "deg", "s", "hz", "dppx", "number", "fr"])

export function isCanonical(unit) {
return canonicalUnits.has(unit.toLowerCase());
}

/**
* Split an input string into a list of individual component value strings,
* so that each can be handled as a keyword or parsed with `CSSNumericValue.parse()`;
*
* Examples:
* splitIntoComponentValues('cover'); // ['cover']
* splitIntoComponentValues('auto 0%'); // ['auto', '100%']
* splitIntoComponentValues('calc(0% + 50px) calc(100% - 50px)'); // ['calc(0% + 50px)', 'calc(100% - 50px)']
* splitIntoComponentValues('1px 2px').map(val => CSSNumericValue.parse(val)) // [new CSSUnitValue(1, 'px'), new CSSUnitValue(2, 'px')]
*
* @param {string} input
* @return {string[]}
*/
export function splitIntoComponentValues(input) {
const res = [];
let i = 0;

function consumeComponentValue() {
let level = 0;
const startIndex = i;
while (i < input.length) {
const char = input.slice(i, i + 1);
if (level === 0 && char === ' '){
break;
} if (char === '(') {
level +=1;
} else if (char === ')') {
level -=1;
}
i++;
}
return input.slice(startIndex, i);
}

function consumeWhitespace() {
while (input.slice(i, i + 1) === ' ') {
i++;
}
}

while(i < input.length) {
if (input.slice(i, i + 1) === ' ') {
consumeWhitespace();
} else {
res.push(consumeComponentValue());
}
}
return res;
}
3 changes: 2 additions & 1 deletion test/expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,7 @@ PASS /scroll-animations/view-timelines/block-view-timeline-current-time.tentativ
FAIL /scroll-animations/view-timelines/block-view-timeline-nested-subject.tentative.html View timeline with subject that is not a direct descendant of the scroll container
FAIL /scroll-animations/view-timelines/change-animation-range-updates-play-state.html Changing the animation range updates the play state
FAIL /scroll-animations/view-timelines/contain-alignment.html Stability of animated elements aligned to the bounds of a contain region
PASS /scroll-animations/view-timelines/fieldset-source.html Fieldset is a valid source for a view timeline
FAIL /scroll-animations/view-timelines/get-keyframes-with-timeline-offset.html Report specified timeline offsets
FAIL /scroll-animations/view-timelines/get-keyframes-with-timeline-offset.html Computed offsets can be outside [0,1] for keyframes with timeline offsets
FAIL /scroll-animations/view-timelines/get-keyframes-with-timeline-offset.html Retain specified ordering of keyframes with timeline offsets
Expand Down Expand Up @@ -957,4 +958,4 @@ FAIL /scroll-animations/view-timelines/view-timeline-sticky-block.html View time
FAIL /scroll-animations/view-timelines/view-timeline-sticky-inline.html View timeline with sticky target, block axis.
FAIL /scroll-animations/view-timelines/view-timeline-subject-size-changes.html View timeline with subject size change after the creation of the animation
FAIL /scroll-animations/view-timelines/zero-intrinsic-iteration-duration.tentative.html Intrinsic iteration duration is non-negative
Passed 432 of 959 tests.
Passed 433 of 960 tests.

0 comments on commit fb9ecee

Please sign in to comment.