feat: improved css-shadow parser

This commit is contained in:
Igor Randjelovic
2021-02-20 00:20:35 +01:00
committed by Nathan Walker
parent 945656fe3e
commit 527c70b465
7 changed files with 87 additions and 72 deletions

View File

@@ -1,9 +1,65 @@
import { Color } from '../../color';
import { Length } from './style-properties';
export class CSSShadow {
public offsetX: number;
public offsetY: number;
public blurRadius: number;
public spreadRadius: number;
public color: Color;
export interface CSSShadow {
inset: boolean;
offsetX: Length;
offsetY: Length;
blurRadius?: Length;
spreadRadius?: Length;
color: Color;
}
/**
* Matches whitespace except if the whitespace is contained in parenthesis - ex. rgb(a), hsl color.
*/
const PARTS_RE = /\s(?![^(]*\))/;
/**
* Matches a Length value with or without a unit
*/
const LENGTH_RE = /^-?[0-9]+[a-zA-Z%]*?$/;
/**
* Checks if the value is a Length or 0
*/
const isLength = (v) => v === '0' || LENGTH_RE.test(v);
/**
* Parse a string into a CSSShadow
* Supports any valid css box/text shadow combination.
*
* inspired by https://github.com/jxnblk/css-box-shadow/blob/master/index.js (MIT License)
*
* @param value
*/
export function parseCSSShadow(value: string): CSSShadow {
const parts = value.split(PARTS_RE);
const inset = parts.includes('inset');
const first = parts[0];
const last = parts[parts.length - 1];
let colorRaw = 'black';
if (!isLength(first) && first !== 'inset') {
colorRaw = first;
} else if (!isLength(last)) {
colorRaw = last;
}
const nums = parts
.filter((n) => n !== 'inset')
.filter((n) => n !== colorRaw)
.map((val) => {
console.log(val);
return Length.parse(val);
});
const [offsetX, offsetY, blurRadius, spreadRadius] = nums;
return {
inset,
offsetX: offsetX,
offsetY: offsetY,
blurRadius: blurRadius,
spreadRadius: spreadRadius,
color: new Color(colorRaw),
};
}

View File

@@ -17,7 +17,7 @@ import { Trace } from '../../trace';
import * as parser from '../../css/parser';
import { LinearGradient } from './linear-gradient';
import { CSSShadow } from './css-shadow';
import { CSSShadow, parseCSSShadow } from './css-shadow';
export type LengthDipUnit = { readonly unit: 'dip'; readonly value: dip };
export type LengthPxUnit = { readonly unit: 'px'; readonly value: px };
@@ -452,53 +452,6 @@ export const verticalAlignmentProperty = new CssProperty<Style, VerticalAlignmen
});
verticalAlignmentProperty.register(Style);
export function parseShadowProperites(value: string): CSSShadow {
if (typeof value === 'string') {
let arr;
let colorRaw = 'black';
if (value.indexOf('rgb') > -1) {
arr = value.split(' ');
colorRaw = arr.pop();
} else {
arr = value.split(/[ ,]+/);
colorRaw = arr.pop();
}
let offsetX = 0;
let offsetY = 0;
let blurRadius = 0; // not currently in use
let spreadRadius = 0; // maybe rename this to just radius
let color: Color = new Color(colorRaw);
if (arr.length === 1) {
Trace.write('Expected 3, 4 or 5 parameters. Actual: ' + value, Trace.categories.Error, Trace.messageType.error);
}
if (arr.length > 1) {
offsetX = parseFloat(arr[0]);
offsetY = parseFloat(arr[1]);
}
if (arr.length > 2) {
blurRadius = parseFloat(arr[2]);
}
if (arr.length > 3) {
spreadRadius = parseFloat(arr[3]);
}
return {
offsetX: offsetX,
offsetY: offsetY,
blurRadius: blurRadius,
spreadRadius: spreadRadius,
color: color,
};
} else {
return value;
}
}
interface Thickness {
top: string;
right: string;
@@ -1330,7 +1283,7 @@ const boxShadowProperty = new CssProperty<Style, CSSShadow>({
target.boxShadow = newValue;
},
valueConverter: (value) => {
return parseShadowProperites(value);
return parseCSSShadow(value);
},
});
boxShadowProperty.register(Style);

View File

@@ -10,7 +10,7 @@ import { Observable } from '../../../data/observable';
import { FlexDirection, FlexWrap, JustifyContent, AlignItems, AlignContent, Order, FlexGrow, FlexShrink, FlexWrapBefore, AlignSelf } from '../../layouts/flexbox-layout';
import { Trace } from '../../../trace';
import { TextAlignment, TextDecoration, TextTransform, WhiteSpace, TextShadow } from '../../text-base';
import { TextAlignment, TextDecoration, TextTransform, WhiteSpace } from '../../text-base';
import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState } from '../../../accessibility/accessibility-types';
import { CSSShadow } from '../css-shadow';
@@ -159,7 +159,7 @@ export class Style extends Observable implements StyleDefinition {
public textAlignment: TextAlignment;
public textDecoration: TextDecoration;
public textTransform: TextTransform;
public textShadow: TextShadow;
public textShadow: CSSShadow;
public whiteSpace: WhiteSpace;
public minWidth: Length;