Comparing version 0.9.0 to 0.9.1
@@ -93,3 +93,4 @@ const babel = require("@babel/core"); | ||
}, ref) => { | ||
const style = [styles[0], test === true ? styles[1] : null, props.style]; | ||
const baseStyle = test === true ? styles[1] : styles[0]; | ||
const style = props.style != null ? [baseStyle, props.style] : baseStyle; | ||
return <Element {...props} ref={ref} style={style} />; | ||
@@ -131,3 +132,4 @@ });" | ||
}, ref) => { | ||
const style = [styles[0], size === 'small' ? styles[1] : null, size === 'large' ? styles[2] : null, props.style]; | ||
const baseStyle = size === 'large' ? styles[2] : size === 'small' ? styles[1] : styles[0]; | ||
const style = props.style != null ? [baseStyle, props.style] : baseStyle; | ||
return <Element {...props} ref={ref} style={style} />; | ||
@@ -138,2 +140,39 @@ });" | ||
it("Optimizes a single conditional style", () => { | ||
const css = styled.test` | ||
color: green; | ||
&[@test] { | ||
margin: 10px; | ||
} | ||
`; | ||
const code = build(css); | ||
expect(code).toMatchInlineSnapshot(` | ||
"import React from 'react'; | ||
const styles = | ||
/* Some styles have been duplicated to improve performance */ | ||
{ | ||
0: { | ||
color: 'green' | ||
}, | ||
1: { | ||
color: 'green', | ||
marginTop: 10, | ||
marginRight: 10, | ||
marginBottom: 10, | ||
marginLeft: 10 | ||
} | ||
}; | ||
const Example = React.forwardRef(({ | ||
test, | ||
...props | ||
}, ref) => { | ||
const baseStyle = test === true ? styles[1] : styles[0]; | ||
const style = props.style != null ? [baseStyle, props.style] : baseStyle; | ||
return <Element {...props} ref={ref} style={style} />; | ||
});" | ||
`); | ||
}); | ||
it("Supports media queries", () => { | ||
@@ -165,3 +204,4 @@ const css = styled.test` | ||
} = useMediaQuery(); | ||
const style = [styles[0], screenWidth >= 500 ? styles[1] : null, props.style]; | ||
const baseStyle = screenWidth >= 500 ? styles[1] : styles[0]; | ||
const style = props.style != null ? [baseStyle, props.style] : baseStyle; | ||
return <Element {...props} ref={ref} style={style} />; | ||
@@ -208,3 +248,3 @@ });" | ||
} = useMediaQuery(); | ||
const style = [styles[0], screenWidth >= 500 ? styles[1] : null, large === true && screenWidth >= 500 ? styles[2] : null, props.style]; | ||
const style = [screenWidth >= 500 ? styles[1] : styles[0], large === true && screenWidth >= 500 ? styles[2] : null, props.style]; | ||
return <Element {...props} ref={ref} style={style} />; | ||
@@ -237,3 +277,4 @@ });" | ||
const Example = React.forwardRef((props, ref) => { | ||
const style = [styles[0], Platform.OS === 'ios' ? styles[1] : null, props.style]; | ||
const baseStyle = Platform.OS === 'ios' ? styles[1] : styles[0]; | ||
const style = props.style != null ? [baseStyle, props.style] : baseStyle; | ||
return <Element {...props} ref={ref} style={style} />; | ||
@@ -244,2 +285,32 @@ });" | ||
it("Supports color scheme media queries", () => { | ||
const css = styled.test` | ||
color: green; | ||
@media (prefers-color-scheme: dark) { | ||
color: red; | ||
} | ||
`; | ||
const code = build(css); | ||
expect(code).toMatchInlineSnapshot(` | ||
"import React from 'react'; | ||
import { useColorScheme } from 'react-native'; | ||
const styles = { | ||
0: { | ||
color: 'green' | ||
}, | ||
1: { | ||
color: 'red' | ||
} | ||
}; | ||
const Example = React.forwardRef((props, ref) => { | ||
const colorScheme = useColorScheme(); | ||
const baseStyle = colorScheme === 'dark' ? styles[1] : styles[0]; | ||
const style = props.style != null ? [baseStyle, props.style] : baseStyle; | ||
return <Element {...props} ref={ref} style={style} />; | ||
});" | ||
`); | ||
}); | ||
it("Supports combined media queries", () => { | ||
@@ -272,3 +343,4 @@ const css = styled.test` | ||
} = useMediaQuery(); | ||
const style = [styles[0], Platform.OS === 'ios' && screenWidth >= 500 ? styles[1] : null, props.style]; | ||
const baseStyle = Platform.OS === 'ios' && screenWidth >= 500 ? styles[1] : styles[0]; | ||
const style = props.style != null ? [baseStyle, props.style] : baseStyle; | ||
return <Element {...props} ref={ref} style={style} />; | ||
@@ -470,3 +542,4 @@ });" | ||
}, ref) => { | ||
let style = [styles[0], active === true ? styles[1] : null, props.style]; | ||
const baseStyle = active === true ? styles[1] : styles[0]; | ||
let style = props.style != null ? [baseStyle, props.style] : baseStyle; | ||
style = useTransition(transition, style); | ||
@@ -551,3 +624,4 @@ return <Element {...props} ref={ref} style={style} />; | ||
const customProperties = useCustomProperties(null); | ||
let style = [styles[0], active === true ? styles[1] : null, props.style]; | ||
const baseStyle = active === true ? styles[1] : styles[0]; | ||
let style = props.style != null ? [baseStyle, props.style] : baseStyle; | ||
const unresolvedTransitionParts = [{ | ||
@@ -915,3 +989,4 @@ '_': 'color var(--time)' | ||
}, ref) => { | ||
let style = [styles[0], inverted === true ? styles[1] : null, props.style]; | ||
const baseStyle = inverted === true ? styles[1] : styles[0]; | ||
let style = props.style != null ? [baseStyle, props.style] : baseStyle; | ||
style = useTransition(transition, style); | ||
@@ -918,0 +993,0 @@ style = useAnimation(keyframes, animation, style); |
@@ -56,6 +56,8 @@ const extractRules = require("../css/extractRules"); | ||
const styleSheetVariable = styleSheet(babel, path, rules, { | ||
substitutionMap, | ||
customPropertiesVariable | ||
}); | ||
const { styleSheetVariable, stylesheetOptimizationFlags } = styleSheet( | ||
babel, | ||
path, | ||
rules, | ||
{ substitutionMap, selectorFunctions, customPropertiesVariable } | ||
); | ||
@@ -74,2 +76,3 @@ const hasTransition = ruleTuples.some( | ||
styleSheetVariable, | ||
stylesheetOptimizationFlags, | ||
willModifyStyle | ||
@@ -76,0 +79,0 @@ }); |
// @flow | ||
const selectorParser = require("postcss-selector-parser"); | ||
const usePlatform = require("./usePlatform"); | ||
const useColorScheme = require("./useColorScheme"); | ||
const useMediaQuery = require("./useMediaQuery"); | ||
@@ -128,2 +129,10 @@ | ||
const getColorScheme = () => { | ||
if (cache.colorScheme == null) { | ||
cache.colorScheme = useColorScheme(babel, path); | ||
} | ||
return t.cloneDeep(cache.colorScheme); | ||
}; | ||
const getScreenWidth = () => { | ||
@@ -152,2 +161,8 @@ if (cache.screenVariables == null) { | ||
); | ||
case "prefers-color-scheme": | ||
return t.binaryExpression( | ||
"===", | ||
getColorScheme(), | ||
t.stringLiteral(match[2]) | ||
); | ||
case "width": | ||
@@ -154,0 +169,0 @@ return t.binaryExpression( |
@@ -0,55 +1,19 @@ | ||
const { | ||
FLAG_SUPERSETS_PREVIOUS_STYLE | ||
} = require("./styleSheet/optimizationFlags"); | ||
const { createVariable } = require("./util"); | ||
const createSimpleStyleExpression = ( | ||
module.exports = ( | ||
babel, | ||
{ propsVariable, styleSheetVariable } | ||
) => { | ||
const { types: t } = babel; | ||
const propsStyle = t.memberExpression(propsVariable, t.identifier("style")); | ||
const csstaStyle = t.memberExpression( | ||
styleSheetVariable, | ||
t.numericLiteral(0), | ||
true | ||
); | ||
return t.conditionalExpression( | ||
t.binaryExpression("!=", propsStyle, t.nullLiteral()), | ||
t.arrayExpression([csstaStyle, propsStyle]), | ||
csstaStyle | ||
); | ||
}; | ||
const createMultipleStyleExpression = ( | ||
babel, | ||
path, | ||
rules, | ||
{ | ||
ruleTuplesWithStyleTuples, | ||
propsVariable, | ||
selectorFunctions, | ||
styleSheetVariable | ||
styleSheetVariable, | ||
stylesheetOptimizationFlags, | ||
willModifyStyle | ||
} | ||
) => { | ||
const { types: t } = babel; | ||
return t.arrayExpression([ | ||
...ruleTuplesWithStyleTuples.map((rule, i) => { | ||
const styleSheet = t.memberExpression( | ||
styleSheetVariable, | ||
t.numericLiteral(i), | ||
true | ||
); | ||
const ruleCondition = selectorFunctions.get(rule); | ||
return ruleCondition == null | ||
? styleSheet | ||
: t.conditionalExpression(ruleCondition, styleSheet, t.nullLiteral()); | ||
}), | ||
t.memberExpression(propsVariable, t.identifier("style")) | ||
]); | ||
}; | ||
module.exports = ( | ||
babel, | ||
path, | ||
rules, | ||
{ propsVariable, selectorFunctions, styleSheetVariable, willModifyStyle } | ||
) => { | ||
const { types: t } = babel; | ||
const { ruleTuples } = rules; | ||
@@ -62,22 +26,59 @@ | ||
let styleExpression; | ||
if (ruleTuplesWithStyleTuples.length === 0) { | ||
styleExpression = willModifyStyle | ||
? t.memberExpression(propsVariable, t.identifier("style")) | ||
: null; | ||
} else if ( | ||
ruleTuplesWithStyleTuples.length === 1 && | ||
ruleTuplesWithStyleTuples[0].selector == "&" && | ||
ruleTuplesWithStyleTuples[0].mediaQuery == null | ||
) { | ||
styleExpression = createSimpleStyleExpression(babel, { | ||
propsVariable, | ||
styleSheetVariable | ||
const propsStyle = t.memberExpression(propsVariable, t.identifier("style")); | ||
const styleExpressions = ruleTuplesWithStyleTuples | ||
.reduce((accum, rule, i) => { | ||
const optimizationFlags = stylesheetOptimizationFlags[i]; | ||
let styleGroup; | ||
if (optimizationFlags == FLAG_SUPERSETS_PREVIOUS_STYLE) { | ||
styleGroup = accum[accum.length - 1]; | ||
} else { | ||
styleGroup = []; | ||
accum.push(styleGroup); | ||
} | ||
styleGroup.push({ rule, i }); | ||
return accum; | ||
}, []) | ||
.map(rules => { | ||
const ruleExpression = rules.reduce((accum, { rule, i }) => { | ||
const csstaStyle = t.memberExpression( | ||
styleSheetVariable, | ||
t.numericLiteral(i), | ||
true | ||
); | ||
const ruleCondition = selectorFunctions.get(rule); | ||
if (ruleCondition == null) return csstaStyle; | ||
const previousStyle = accum == null ? t.nullLiteral() : accum; | ||
return t.conditionalExpression( | ||
ruleCondition, | ||
csstaStyle, | ||
previousStyle | ||
); | ||
}, null); | ||
return ruleExpression; | ||
}); | ||
if (styleExpressions.length === 0) { | ||
styleExpression = willModifyStyle ? propsStyle : null; | ||
} else if (styleExpressions.length === 1) { | ||
let baseStyleExpression; | ||
if (!t.isConditionalExpression(styleExpressions[0])) { | ||
baseStyleExpression = styleExpressions[0]; | ||
} else { | ||
baseStyleExpression = createVariable( | ||
babel, | ||
path, | ||
"baseStyle", | ||
styleExpressions[0] | ||
); | ||
} | ||
styleExpression = t.conditionalExpression( | ||
t.binaryExpression("!=", propsStyle, t.nullLiteral()), | ||
t.arrayExpression([baseStyleExpression, propsStyle]), | ||
baseStyleExpression | ||
); | ||
} else { | ||
styleExpression = createMultipleStyleExpression(babel, { | ||
propsVariable, | ||
selectorFunctions, | ||
styleSheetVariable, | ||
ruleTuplesWithStyleTuples | ||
}); | ||
styleExpression = t.arrayExpression([...styleExpressions, propsStyle]); | ||
} | ||
@@ -84,0 +85,0 @@ |
@@ -8,2 +8,6 @@ const { | ||
const styleBody = require("./styleBody"); | ||
const { | ||
NO_FLAGS, | ||
FLAG_SUPERSETS_PREVIOUS_STYLE | ||
} = require("./optimizationFlags"); | ||
@@ -13,3 +17,3 @@ const createStaticStyleSheet = ( | ||
path, | ||
{ substitutionMap, ruleTuplesWithStyleTuples } | ||
{ substitutionMap, ruleTuplesWithStyleTuples, comment } | ||
) => { | ||
@@ -27,2 +31,8 @@ const { types: t } = babel; | ||
if (comment != null) { | ||
styleSheet.leadingComments = [ | ||
{ type: "CommentBlock", value: ` ${comment} ` } | ||
]; | ||
} | ||
const styleSheetVariable = createTopLevelVariable( | ||
@@ -75,2 +85,39 @@ babel, | ||
const mergeFirstStyleIntoAllRuleTuples = ruleTuplesWithStyleTuples => { | ||
const mergeeRuleTuple = ruleTuplesWithStyleTuples[0]; | ||
const ruleTuplesWithStyleTuplesMerged = ruleTuplesWithStyleTuples.map( | ||
ruleTuple => { | ||
if (ruleTuple === mergeeRuleTuple) return ruleTuple; | ||
const ownStyleKeys = new Set( | ||
ruleTuple.styleTuples.map(styleTuple => styleTuple[0]) | ||
); | ||
const stylesToMerge = mergeeRuleTuple.styleTuples.filter( | ||
styleTuple => !ownStyleKeys.has(styleTuple[0]) | ||
); | ||
if (stylesToMerge.length === 0) return ruleTuple; | ||
const mergedStyleTuples = [...stylesToMerge, ...ruleTuple.styleTuples]; | ||
return { ...ruleTuple, styleTuples: mergedStyleTuples }; | ||
} | ||
); | ||
return ruleTuplesWithStyleTuplesMerged; | ||
}; | ||
const getOptimizationFlags = ruleTuplesWithStyleTuples => { | ||
let lastStyleKeys = null; | ||
return ruleTuplesWithStyleTuples.map(ruleTuple => { | ||
const ownStyleKeys = ruleTuple.styleTuples.map(styleTuple => styleTuple[0]); | ||
const supersets = | ||
lastStyleKeys != null && | ||
ownStyleKeys.every(key => lastStyleKeys.has(key)); | ||
lastStyleKeys = new Set(ownStyleKeys); | ||
return supersets ? FLAG_SUPERSETS_PREVIOUS_STYLE : NO_FLAGS; | ||
}); | ||
}; | ||
module.exports = ( | ||
@@ -80,3 +127,3 @@ babel, | ||
rules, | ||
{ substitutionMap, customPropertiesVariable } | ||
{ substitutionMap, selectorFunctions, customPropertiesVariable } | ||
) => { | ||
@@ -90,3 +137,5 @@ const { ruleTuples, importedRuleVariables } = rules; | ||
let styleSheetVariable; | ||
let stylesheetOptimizationFlags; | ||
if (importedRuleVariables.length > 0) { | ||
stylesheetOptimizationFlags = ruleTuplesWithStyleTuples.map(() => NO_FLAGS); | ||
styleSheetVariable = createUseCustomPropertyStyles(babel, path, { | ||
@@ -97,3 +146,24 @@ // FIXME: substitutionMap | ||
}); | ||
} else if ( | ||
ruleTuplesWithStyleTuples.length === 2 && | ||
!selectorFunctions.has(ruleTuplesWithStyleTuples[0]) | ||
) { | ||
stylesheetOptimizationFlags = [NO_FLAGS, FLAG_SUPERSETS_PREVIOUS_STYLE]; | ||
const mergedStyleTuples = mergeFirstStyleIntoAllRuleTuples( | ||
ruleTuplesWithStyleTuples | ||
); | ||
const didMergeStyleTuples = ruleTuplesWithStyleTuples.some( | ||
(ruleTuple, i) => ruleTuple !== mergedStyleTuples[i] | ||
); | ||
styleSheetVariable = createStaticStyleSheet(babel, path, { | ||
substitutionMap, | ||
ruleTuplesWithStyleTuples: mergedStyleTuples, | ||
comment: didMergeStyleTuples | ||
? "Some styles have been duplicated to improve performance" | ||
: null | ||
}); | ||
} else if (ruleTuplesWithStyleTuples.length > 0) { | ||
stylesheetOptimizationFlags = getOptimizationFlags( | ||
ruleTuplesWithStyleTuples | ||
); | ||
styleSheetVariable = createStaticStyleSheet(babel, path, { | ||
@@ -105,3 +175,3 @@ substitutionMap, | ||
return styleSheetVariable; | ||
return { styleSheetVariable, stylesheetOptimizationFlags }; | ||
}; |
{ | ||
"name": "cssta", | ||
"version": "0.9.0", | ||
"version": "0.9.1", | ||
"main": "index.js", | ||
@@ -10,2 +10,24 @@ "license": "MIT", | ||
}, | ||
"keywords": [ | ||
"postcss", | ||
"modules", | ||
"css-modules", | ||
"css", | ||
"minify", | ||
"min", | ||
"class", | ||
"className", | ||
"react", | ||
"css-in-js" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/jacobp100/cssta" | ||
}, | ||
"files": [ | ||
"compiler", | ||
"runtime", | ||
"native.macro.js", | ||
"babel-plugin.js" | ||
], | ||
"devDependencies": { | ||
@@ -12,0 +34,0 @@ "@babel/core": "^7.5.5", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
0
1
150607
50
4615
1