feat: add support for 'auto' values in clip property

This commit is contained in:
Nick Badal 2022-05-21 22:42:08 -07:00
parent 83eec2d24a
commit 5d2f14f37f
No known key found for this signature in database
GPG Key ID: 829D8559E7019BAD
5 changed files with 42 additions and 20 deletions

View File

@ -1,31 +1,34 @@
import {IPropertyValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';
import {CSSValue, isDimensionToken, isIdentWithValue, nonFunctionArgSeparator} from '../syntax/parser';
import {CSSValue, isAutoIdentToken, isDimensionToken} from '../syntax/parser';
import {Context} from '../../core/context';
import {DimensionToken, TokenType} from '../syntax/tokenizer';
import {AutoIdentToken, DimensionToken, TokenType} from '../syntax/tokenizer';
export interface RectClip {
top: DimensionToken;
right: DimensionToken;
bottom: DimensionToken;
left: DimensionToken;
top: DimensionToken | AutoIdentToken;
right: DimensionToken | AutoIdentToken;
bottom: DimensionToken | AutoIdentToken;
left: DimensionToken | AutoIdentToken;
}
const isDimensionOrAutoToken = (token: CSSValue): token is DimensionToken | AutoIdentToken =>
isDimensionToken(token) || isAutoIdentToken(token);
export const clip: IPropertyValueDescriptor<RectClip | null> = {
name: 'clip',
initialValue: 'auto',
type: PropertyDescriptorParsingType.VALUE,
prefix: false,
parse: (_context: Context, token: CSSValue) => {
if (isIdentWithValue(token, 'auto')) {
if (isAutoIdentToken(token)) {
return null;
}
if (token.type !== TokenType.FUNCTION || token.name !== 'rect') {
throw new Error('Clip value must be auto or a rect function');
}
const rectArgs = token.values.filter(nonFunctionArgSeparator).filter(isDimensionToken);
const rectArgs = token.values.filter(isDimensionOrAutoToken);
if (rectArgs.length !== 4) {
throw new Error('Rect clip must have 4 dimension elements');
throw new Error('Rect clip must have 4 elements that are either a dimension or "auto"');
}
return {

View File

@ -1,4 +1,5 @@
import {
AutoIdentToken,
CSSToken,
DimensionToken,
EOF_TOKEN,
@ -145,6 +146,7 @@ export const isDimensionToken = (token: CSSValue): token is DimensionToken => to
export const isNumberToken = (token: CSSValue): token is NumberValueToken => token.type === TokenType.NUMBER_TOKEN;
export const isIdentToken = (token: CSSValue): token is StringValueToken => token.type === TokenType.IDENT_TOKEN;
export const isStringToken = (token: CSSValue): token is StringValueToken => token.type === TokenType.STRING_TOKEN;
export const isAutoIdentToken = (token: CSSValue): token is AutoIdentToken => isIdentWithValue(token, 'auto');
export const isIdentWithValue = (token: CSSValue, value: string): boolean =>
isIdentToken(token) && token.value === value;

View File

@ -97,6 +97,11 @@ export interface DimensionToken extends IToken {
number: number;
}
export interface AutoIdentToken extends IToken {
type: TokenType.IDENT_TOKEN;
value: 'auto';
}
export interface UnicodeRangeToken extends IToken {
type: TokenType.UNICODE_RANGE_TOKEN;
start: number;

View File

@ -1,8 +1,9 @@
import {ElementContainer} from '../dom/element-container';
import {getAbsoluteValue, getAbsoluteValueForTuple, getAbsoluteValueForDimension} from '../css/types/length-percentage';
import {getAbsoluteValue, getAbsoluteValueForDimension, getAbsoluteValueForTuple} from '../css/types/length-percentage';
import {Vector} from './vector';
import {BezierCurve} from './bezier-curve';
import {Path} from './path';
import {TokenType} from '../css/syntax/tokenizer';
export class BoundCurves {
readonly topLeftBorderDoubleOuterBox: Path;
@ -76,16 +77,19 @@ export class BoundCurves {
const paddingBottom = getAbsoluteValue(styles.paddingBottom, element.bounds.width);
const paddingLeft = getAbsoluteValue(styles.paddingLeft, element.bounds.width);
let rectClipTop = 0;
let rectClipRight = 0;
let rectClipBottom = 0;
let rectClipLeft = 0;
if (styles.clip) {
rectClipTop = getAbsoluteValueForDimension(styles.clip.top);
rectClipRight = getAbsoluteValueForDimension(styles.clip.right);
rectClipBottom = getAbsoluteValueForDimension(styles.clip.bottom);
rectClipLeft = getAbsoluteValueForDimension(styles.clip.left);
}
const rectClipTop =
styles.clip?.top.type == TokenType.DIMENSION_TOKEN ? getAbsoluteValueForDimension(styles.clip.top) : 0;
const rectClipLeft =
styles.clip?.left.type == TokenType.DIMENSION_TOKEN ? getAbsoluteValueForDimension(styles.clip.left) : 0;
const rectClipBottom =
styles.clip?.bottom.type == TokenType.DIMENSION_TOKEN
? getAbsoluteValueForDimension(styles.clip.bottom)
: bounds.height;
const rectClipRight =
styles.clip?.right.type == TokenType.DIMENSION_TOKEN
? getAbsoluteValueForDimension(styles.clip.right)
: bounds.width;
this.topLeftBorderDoubleOuterBox =
tlh > 0 || tlv > 0

View File

@ -45,5 +45,13 @@
<div style="clip: rect(0px, 400px, 50px, 200px); position: absolute; top: 500px; left: 500px; border-radius: 100%; overflow: hidden;">Some inline text <span> followed by text in span </span> followed by more inline text.
<p>Then a block level element.</p>
Then more inline text.</div>
<div style="clip: rect(auto, auto, auto, 30px); position: absolute; top: 750px;">Some inline text <span> followed by text in span </span> followed by more inline text.
<p>Then a block level element.</p>
Then more inline text.</div>
<div style="clip: auto; position: absolute; top: 750px; left: 500px;">Some inline text <span> followed by text in span </span> followed by more inline text.
<p>Then a block level element.</p>
Then more inline text.</div>
</body>
</html>