|
2 | 2 | import parse from 'postcss-value-parser'
|
3 | 3 | import camelizeStyleName from 'camelize'
|
4 | 4 | import transforms from './transforms/index'
|
| 5 | +import devPropertiesWithoutUnitsRegExp from './devPropertiesWithoutUnitsRegExp' |
5 | 6 | import TokenStream from './TokenStream'
|
6 | 7 |
|
7 | 8 | // Note if this is wrong, you'll need to change tokenTypes.js too
|
8 |
| -const numberOrLengthRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?)(?:px)?$/i |
| 9 | +const numberOrLengthRe = /^([+-]?(?:\d*\.)?\d+(?:e[+-]?\d+)?)(?:px)?$/i |
| 10 | +const numberOnlyRe = /^[+-]?(?:\d*\.\d*|[1-9]\d*)(?:e[+-]?\d+)?$/i |
9 | 11 | const boolRe = /^true|false$/i
|
10 | 12 | const nullRe = /^null$/i
|
11 | 13 | const undefinedRe = /^undefined$/i
|
12 | 14 |
|
13 | 15 | // Undocumented export
|
14 |
| -export const transformRawValue = input => { |
15 |
| - const value = input.trim() |
| 16 | +export const transformRawValue = (propName, value) => { |
| 17 | + if (process.env.NODE_ENV !== 'production') { |
| 18 | + const needsUnit = !devPropertiesWithoutUnitsRegExp.test(propName) |
| 19 | + const isNumberWithoutUnit = numberOnlyRe.test(value) |
| 20 | + if (needsUnit && isNumberWithoutUnit) { |
| 21 | + // eslint-disable-next-line no-console |
| 22 | + console.warn(`Expected style "${propName}: ${value}" to contain units`) |
| 23 | + } |
| 24 | + if (!needsUnit && value !== '0' && !isNumberWithoutUnit) { |
| 25 | + // eslint-disable-next-line no-console |
| 26 | + console.warn(`Expected style "${propName}: ${value}" to be unitless`) |
| 27 | + } |
| 28 | + } |
16 | 29 |
|
17 | 30 | const numberMatch = value.match(numberOrLengthRe)
|
18 | 31 | if (numberMatch !== null) return Number(numberMatch[1])
|
19 | 32 |
|
20 |
| - const boolMatch = input.match(boolRe) |
| 33 | + const boolMatch = value.match(boolRe) |
21 | 34 | if (boolMatch !== null) return boolMatch[0].toLowerCase() === 'true'
|
22 | 35 |
|
23 |
| - const nullMatch = input.match(nullRe) |
| 36 | + const nullMatch = value.match(nullRe) |
24 | 37 | if (nullMatch !== null) return null
|
25 | 38 |
|
26 |
| - const undefinedMatch = input.match(undefinedRe) |
| 39 | + const undefinedMatch = value.match(undefinedRe) |
27 | 40 | if (undefinedMatch !== null) return undefined
|
28 | 41 |
|
29 | 42 | return value
|
30 | 43 | }
|
31 | 44 |
|
32 |
| -const baseTransformShorthandValue = (propName, inputValue) => { |
33 |
| - const ast = parse(inputValue.trim()) |
| 45 | +const baseTransformShorthandValue = (propName, value) => { |
| 46 | + const ast = parse(value) |
34 | 47 | const tokenStream = new TokenStream(ast.nodes)
|
35 | 48 | return transforms[propName](tokenStream)
|
36 | 49 | }
|
37 | 50 |
|
38 | 51 | const transformShorthandValue =
|
39 | 52 | process.env.NODE_ENV === 'production'
|
40 | 53 | ? baseTransformShorthandValue
|
41 |
| - : (propName, inputValue) => { |
| 54 | + : (propName, value) => { |
42 | 55 | try {
|
43 |
| - return baseTransformShorthandValue(propName, inputValue) |
| 56 | + return baseTransformShorthandValue(propName, value) |
44 | 57 | } catch (e) {
|
45 |
| - throw new Error( |
46 |
| - `Failed to parse declaration "${propName}: ${inputValue}"` |
47 |
| - ) |
| 58 | + throw new Error(`Failed to parse declaration "${propName}: ${value}"`) |
48 | 59 | }
|
49 | 60 | }
|
50 | 61 |
|
51 | 62 | export const getStylesForProperty = (propName, inputValue, allowShorthand) => {
|
52 | 63 | const isRawValue = allowShorthand === false || !(propName in transforms)
|
| 64 | + const value = inputValue.trim() |
| 65 | + |
53 | 66 | const propValues = isRawValue
|
54 |
| - ? { [propName]: transformRawValue(inputValue) } |
55 |
| - : transformShorthandValue(propName, inputValue.trim()) |
| 67 | + ? { [propName]: transformRawValue(propName, value) } |
| 68 | + : transformShorthandValue(propName, value) |
56 | 69 |
|
57 | 70 | return propValues
|
58 | 71 | }
|
|
0 commit comments