css-to-react-native
Advanced tools
Comparing version
@@ -10,20 +10,29 @@ 'use strict'; | ||
/* eslint-disable no-param-reassign */ | ||
var nearley = require('nearley'); | ||
var parse = require('postcss-value-parser'); | ||
var camelizeStyleName = require('fbjs/lib/camelizeStyleName'); | ||
var grammar = require('./grammar'); | ||
var transforms = require('./transforms'); | ||
var TokenStream = require('./TokenStream'); | ||
var transforms = ['background', 'border', 'borderColor', 'borderRadius', 'borderWidth', 'flex', 'flexFlow', 'font', 'fontVariant', 'fontWeight', 'margin', 'padding', 'shadowOffset', 'textShadowOffset', 'transform']; | ||
// Note if this is wrong, you'll need to change tokenTypes.js too | ||
var numberOrLengthRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?)(?:px)?$/; | ||
var transformRawValue = function transformRawValue(input) { | ||
return input !== '' && !isNaN(input) ? Number(input) : input; | ||
// Undocumented export | ||
var transformRawValue = exports.transformRawValue = function transformRawValue(input) { | ||
var value = input.trim().match(numberOrLengthRe); | ||
return value ? Number(value[1]) : input; | ||
}; | ||
var parseProp = exports.parseProp = function parseProp(propName, value) { | ||
return new nearley.Parser(grammar.ParserRules, propName).feed(value).results[0]; | ||
}; | ||
var getStylesForProperty = exports.getStylesForProperty = function getStylesForProperty(propName, inputValue, allowShorthand) { | ||
var value = inputValue.trim(); | ||
// Undocumented: allow ast to be passed in | ||
var propValue = void 0; | ||
var propValue = allowShorthand && transforms.indexOf(propName) !== -1 ? parseProp(propName, value) : transformRawValue(value); | ||
var isRawValue = allowShorthand === false || !(propName in transforms); | ||
if (isRawValue) { | ||
var value = typeof inputValue === 'string' ? inputValue : parse.stringify(inputValue); | ||
propValue = transformRawValue(value); | ||
} else { | ||
var ast = typeof inputValue === 'string' ? parse(inputValue.trim()) : inputValue; | ||
var tokenStream = new TokenStream(ast.nodes); | ||
propValue = transforms[propName](tokenStream); | ||
} | ||
@@ -30,0 +39,0 @@ return propValue && propValue.$merge ? propValue.$merge : _defineProperty({}, propName, propValue); |
{ | ||
"name": "css-to-react-native", | ||
"version": "1.0.6", | ||
"version": "2.0.0", | ||
"description": "Convert CSS text to a React Native stylesheet object", | ||
"main": "dist/index.js", | ||
"scripts": { | ||
"build-grammar": "nearleyc src/grammar.ne -o src/grammar.js", | ||
"build": "npm run build-grammar; babel src --ignore test.js --out-dir dist", | ||
"test": "npm run build-grammar; jest", | ||
"build": "babel src --ignore test.js --out-dir dist", | ||
"test": "jest", | ||
"test:watch": "jest --watch", | ||
"prepublish": "npm run build" | ||
@@ -38,6 +38,6 @@ }, | ||
"dependencies": { | ||
"css-color-list": "0.0.1", | ||
"css-color-keywords": "^1.0.0", | ||
"fbjs": "^0.8.5", | ||
"nearley": "^2.7.7" | ||
"postcss-value-parser": "^3.3.0" | ||
} | ||
} |
@@ -6,4 +6,4 @@ # css-to-react-native | ||
```css | ||
font-size: 18; | ||
line-height: 24; | ||
font-size: 18px; | ||
line-height: 24px; | ||
color: red; | ||
@@ -25,5 +25,5 @@ ``` | ||
```css | ||
text-shadow-offset: 10 5; | ||
text-shadow-offset: 10px 5px; | ||
font-variant: small-caps; | ||
transform: translate(10, 5) scale(5); | ||
transform: translate(10px, 5px) scale(5); | ||
``` | ||
@@ -47,4 +47,4 @@ | ||
```css | ||
font: bold 14/16 "Helvetica"; | ||
margin: 5 7 2; | ||
font: bold 14px/16px "Helvetica"; | ||
margin: 5px 7px 2px; | ||
``` | ||
@@ -73,4 +73,2 @@ | ||
`flex` does not support putting `flexBasis` before `flexGrow`. The supported syntax is `flex: <flex-grow> <flex-shrink> <flex-basis>`. | ||
# API | ||
@@ -85,5 +83,5 @@ | ||
transform([ | ||
['font', 'bold 14/16 "Helvetica"'], | ||
['margin', '5 7 2'], | ||
['border-left-width', '5'], | ||
['font', 'bold 14px/16px "Helvetica"'], | ||
['margin', '5px 7px 2px'], | ||
['border-left-width', '5px'], | ||
]); // => { fontFamily: 'Helvetica', ... } | ||
@@ -98,3 +96,3 @@ ``` | ||
getPropertyName('border-width'); // => 'borderWidth' | ||
getStylesForProperty('borderWidth', '1 0 2 0'); // => { borderTopWidth: 1, ... } | ||
getStylesForProperty('borderWidth', '1px 0px 2px 0px'); // => { borderTopWidth: 1, ... } | ||
``` | ||
@@ -105,6 +103,8 @@ | ||
```js | ||
transform([['border-radius', '50']], ['borderRadius']); | ||
transform([['border-radius', '50px']], ['borderRadius']); | ||
// { borderRadius: 50 } rather than { borderTopLeft: ... } | ||
``` | ||
This can also be done by passing a third argument, `false` to `getStylesForProperty`. | ||
## License | ||
@@ -111,0 +111,0 @@ |
/* eslint-disable no-param-reassign */ | ||
const nearley = require('nearley'); | ||
const parse = require('postcss-value-parser'); | ||
const camelizeStyleName = require('fbjs/lib/camelizeStyleName'); | ||
const grammar = require('./grammar'); | ||
const transforms = require('./transforms'); | ||
const TokenStream = require('./TokenStream'); | ||
const transforms = [ | ||
'background', | ||
'border', | ||
'borderColor', | ||
'borderRadius', | ||
'borderWidth', | ||
'flex', | ||
'flexFlow', | ||
'font', | ||
'fontVariant', | ||
'fontWeight', | ||
'margin', | ||
'padding', | ||
'shadowOffset', | ||
'textShadowOffset', | ||
'transform', | ||
]; | ||
// Note if this is wrong, you'll need to change tokenTypes.js too | ||
const numberOrLengthRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?)(?:px)?$/; | ||
const transformRawValue = input => ( | ||
(input !== '' && !isNaN(input)) | ||
? Number(input) | ||
: input | ||
); | ||
// Undocumented export | ||
export const transformRawValue = (input) => { | ||
const value = input.trim().match(numberOrLengthRe); | ||
return value ? Number(value[1]) : input; | ||
}; | ||
export const parseProp = (propName, value) => | ||
new nearley.Parser(grammar.ParserRules, propName).feed(value).results[0]; | ||
export const getStylesForProperty = (propName, inputValue, allowShorthand) => { | ||
const value = inputValue.trim(); | ||
// Undocumented: allow ast to be passed in | ||
let propValue; | ||
const propValue = (allowShorthand && transforms.indexOf(propName) !== -1) | ||
? parseProp(propName, value) | ||
: transformRawValue(value); | ||
const isRawValue = (allowShorthand === false) || !(propName in transforms); | ||
if (isRawValue) { | ||
const value = typeof inputValue === 'string' ? inputValue : parse.stringify(inputValue); | ||
propValue = transformRawValue(value); | ||
} else { | ||
const ast = typeof inputValue === 'string' ? parse(inputValue.trim()) : inputValue; | ||
const tokenStream = new TokenStream(ast.nodes); | ||
propValue = transforms[propName](tokenStream); | ||
} | ||
@@ -40,0 +30,0 @@ return (propValue && propValue.$merge) |
/* global jest it, expect */ | ||
import transformCss, { parseProp } from '.'; | ||
import transformCss, { getStylesForProperty } from '.'; | ||
@@ -16,17 +16,25 @@ const runTest = (inputCss, expectedStyles) => { | ||
it('allows pixels in unspecialized transform', () => runTest([ | ||
['top', '0px'], | ||
], { top: 0 })); | ||
it('allows percent in unspecialized transform', () => runTest([ | ||
['top', '0%'], | ||
], { top: '0%' })); | ||
it('allows decimal values', () => { | ||
expect(parseProp('number', '0.5')).toBe(0.5); | ||
expect(parseProp('number', '1.5')).toBe(1.5); | ||
expect(parseProp('number', '10.5')).toBe(10.5); | ||
expect(parseProp('number', '100.5')).toBe(100.5); | ||
expect(parseProp('number', '-0.5')).toBe(-0.5); | ||
expect(parseProp('number', '-1.5')).toBe(-1.5); | ||
expect(parseProp('number', '-10.5')).toBe(-10.5); | ||
expect(parseProp('number', '-100.5')).toBe(-100.5); | ||
expect(parseProp('number', '.5')).toBe(0.5); | ||
expect(parseProp('number', '-.5')).toBe(-0.5); | ||
expect(getStylesForProperty('margin', '0.5px').marginTop).toBe(0.5); | ||
expect(getStylesForProperty('margin', '1.5px').marginTop).toBe(1.5); | ||
expect(getStylesForProperty('margin', '10.5px').marginTop).toBe(10.5); | ||
expect(getStylesForProperty('margin', '100.5px').marginTop).toBe(100.5); | ||
expect(getStylesForProperty('margin', '-0.5px').marginTop).toBe(-0.5); | ||
expect(getStylesForProperty('margin', '-1.5px').marginTop).toBe(-1.5); | ||
expect(getStylesForProperty('margin', '-10.5px').marginTop).toBe(-10.5); | ||
expect(getStylesForProperty('margin', '-100.5px').marginTop).toBe(-100.5); | ||
expect(getStylesForProperty('margin', '.5px').marginTop).toBe(0.5); | ||
expect(getStylesForProperty('margin', '-.5px').marginTop).toBe(-0.5); | ||
}); | ||
it('allows decimal values in transformed values', () => runTest([ | ||
['border-radius', '1.5'], | ||
['border-radius', '1.5px'], | ||
], { | ||
@@ -40,3 +48,3 @@ borderTopLeftRadius: 1.5, | ||
it('allows negative values in transformed values', () => runTest([ | ||
['border-radius', '-1.5'], | ||
['border-radius', '-1.5px'], | ||
], { | ||
@@ -49,2 +57,11 @@ borderTopLeftRadius: -1.5, | ||
it('allows percent values in transformed values', () => runTest([ | ||
['margin', '10%'], | ||
], { | ||
marginTop: '10%', | ||
marginRight: '10%', | ||
marginBottom: '10%', | ||
marginLeft: '10%', | ||
})); | ||
it('transforms strings', () => runTest([ | ||
@@ -87,7 +104,7 @@ ['color', 'red'], | ||
it('transforms shadow offsets', () => runTest([ | ||
['shadow-offset', ' 10 5'], | ||
['shadow-offset', '10px 5px'], | ||
], { shadowOffset: { width: 10, height: 5 } })); | ||
it('transforms text shadow offsets', () => runTest([ | ||
['text-shadow-offset', '10 5'], | ||
['text-shadow-offset', '10px 5px'], | ||
], { textShadowOffset: { width: 10, height: 5 } })); | ||
@@ -115,8 +132,8 @@ | ||
it('transforms translate(number, number) to translateX and translateY', () => runTest([ | ||
['transform', 'translate(2, 3)'], | ||
it('transforms translate(length, length) to translateX and translateY', () => runTest([ | ||
['transform', 'translate(2px, 3px)'], | ||
], { transform: [{ translateY: 3 }, { translateX: 2 }] })); | ||
it('transforms translate(number) to translateX and translateY', () => runTest([ | ||
['transform', 'translate(5)'], | ||
it('transforms translate(length) to translateX and translateY', () => runTest([ | ||
['transform', 'translate(5px)'], | ||
], { transform: [{ translateY: 0 }, { translateX: 5 }] })); | ||
@@ -133,15 +150,15 @@ | ||
it('transforms border shorthand', () => runTest([ | ||
['border', '2 dashed #f00'], | ||
['border', '2px dashed #f00'], | ||
], { borderWidth: 2, borderColor: '#f00', borderStyle: 'dashed' })); | ||
it('transforms border shorthand in other order', () => runTest([ | ||
['border', '#f00 2 dashed'], | ||
['border', '#f00 2px dashed'], | ||
], { borderWidth: 2, borderColor: '#f00', borderStyle: 'dashed' })); | ||
it('transforms border shorthand missing color', () => runTest([ | ||
['border', '2 dashed'], | ||
['border', '2px dashed'], | ||
], { borderWidth: 2, borderColor: 'black', borderStyle: 'dashed' })); | ||
it('transforms border shorthand missing style', () => runTest([ | ||
['border', '2 #f00'], | ||
['border', '2px #f00'], | ||
], { borderWidth: 2, borderColor: '#f00', borderStyle: 'solid' })); | ||
@@ -162,30 +179,34 @@ | ||
it('transforms border shorthand missing color & style', () => runTest([ | ||
['border', '2'], | ||
['border', '2px'], | ||
], { borderWidth: 2, borderColor: 'black', borderStyle: 'solid' })); | ||
it('transforms margin shorthands using 4 values', () => runTest([ | ||
['margin', '10 20 30 40'], | ||
['margin', '10px 20px 30px 40px'], | ||
], { marginTop: 10, marginRight: 20, marginBottom: 30, marginLeft: 40 })); | ||
it('transforms margin shorthands using 3 values', () => runTest([ | ||
['margin', '10 20 30'], | ||
['margin', '10px 20px 30px'], | ||
], { marginTop: 10, marginRight: 20, marginBottom: 30, marginLeft: 20 })); | ||
it('transforms margin shorthands using 2 values', () => runTest([ | ||
['margin', '10 20'], | ||
['margin', '10px 20px'], | ||
], { marginTop: 10, marginRight: 20, marginBottom: 10, marginLeft: 20 })); | ||
it('transforms margin shorthands using 1 value', () => runTest([ | ||
['margin', '10'], | ||
['margin', '10px'], | ||
], { marginTop: 10, marginRight: 10, marginBottom: 10, marginLeft: 10 })); | ||
it('shorthand with 1 value should override previous values', () => runTest([ | ||
['margin-top', '2'], | ||
['margin', '1'], | ||
['margin-top', '2px'], | ||
['margin', '1px'], | ||
], { marginTop: 1, marginRight: 1, marginBottom: 1, marginLeft: 1 })); | ||
it('transforms flex shorthand with 3 values', () => runTest([ | ||
['flex', '1 2 3'], | ||
['flex', '1 2 3px'], | ||
], { flexGrow: 1, flexShrink: 2, flexBasis: 3 })); | ||
it('transforms flex shorthand with 3 values in reverse order', () => runTest([ | ||
['flex', '3px 1 2'], | ||
], { flexGrow: 1, flexShrink: 2, flexBasis: 3 })); | ||
it('transforms flex shorthand with 2 values', () => runTest([ | ||
@@ -212,3 +233,3 @@ ['flex', '1 2'], | ||
it('transforms font', () => runTest([ | ||
['font', 'bold italic small-caps 16/18 "Helvetica"'], | ||
['font', 'bold italic small-caps 16px/18px "Helvetica"'], | ||
], { | ||
@@ -224,3 +245,3 @@ fontFamily: 'Helvetica', | ||
it('transforms font missing font-variant', () => runTest([ | ||
['font', 'bold italic 16/18 "Helvetica"'], | ||
['font', 'bold italic 16px/18px "Helvetica"'], | ||
], { | ||
@@ -236,3 +257,3 @@ fontFamily: 'Helvetica', | ||
it('transforms font missing font-style', () => runTest([ | ||
['font', 'bold small-caps 16/18 "Helvetica"'], | ||
['font', 'bold small-caps 16px/18px "Helvetica"'], | ||
], { | ||
@@ -248,3 +269,3 @@ fontFamily: 'Helvetica', | ||
it('transforms font missing font-weight', () => runTest([ | ||
['font', 'italic small-caps 16/18 "Helvetica"'], | ||
['font', 'italic small-caps 16px/18px "Helvetica"'], | ||
], { | ||
@@ -260,3 +281,3 @@ fontFamily: 'Helvetica', | ||
it('transforms font with font-weight normal', () => runTest([ | ||
['font', 'normal 16/18 "Helvetica"'], | ||
['font', 'normal 16px/18px "Helvetica"'], | ||
], { | ||
@@ -272,3 +293,3 @@ fontFamily: 'Helvetica', | ||
it('transforms font with font-weight and font-style normal', () => runTest([ | ||
['font', 'normal normal 16/18 "Helvetica"'], | ||
['font', 'normal normal 16px/18px "Helvetica"'], | ||
], { | ||
@@ -284,3 +305,3 @@ fontFamily: 'Helvetica', | ||
it('transforms font with no font-weight, font-style, and font-variant', () => runTest([ | ||
['font', '16/18 "Helvetica"'], | ||
['font', '16px/18px "Helvetica"'], | ||
], { | ||
@@ -296,3 +317,3 @@ fontFamily: 'Helvetica', | ||
it('omits line height if not specified', () => runTest([ | ||
['font', '16 "Helvetica"'], | ||
['font', '16px "Helvetica"'], | ||
], { | ||
@@ -306,2 +327,64 @@ fontFamily: 'Helvetica', | ||
it('allows line height as multiple', () => runTest([ | ||
['font', '16px/1.5 "Helvetica"'], | ||
], { | ||
fontFamily: 'Helvetica', | ||
fontSize: 16, | ||
fontWeight: 'normal', | ||
fontStyle: 'normal', | ||
fontVariant: [], | ||
lineHeight: 24, | ||
})); | ||
it('transforms font without quotes', () => runTest([ | ||
['font', 'bold italic small-caps 16px/18px Helvetica Neue'], | ||
], { | ||
fontFamily: 'Helvetica Neue', | ||
fontSize: 16, | ||
fontWeight: 'bold', | ||
fontStyle: 'italic', | ||
fontVariant: ['small-caps'], | ||
lineHeight: 18, | ||
})); | ||
it('transforms font-family with double quotes', () => runTest([ | ||
['font-family', '"Helvetica Neue"'], | ||
], { | ||
fontFamily: 'Helvetica Neue', | ||
})); | ||
it('transforms font-family with single quotes', () => runTest([ | ||
['font-family', '\'Helvetica Neue\''], | ||
], { | ||
fontFamily: 'Helvetica Neue', | ||
})); | ||
it('transforms font-family without quotes', () => runTest([ | ||
['font-family', 'Helvetica Neue'], | ||
], { | ||
fontFamily: 'Helvetica Neue', | ||
})); | ||
it('transforms font-family with quotes with otherwise invalid values', () => runTest([ | ||
['font-family', '"Goudy Bookletter 1911"'], | ||
], { | ||
fontFamily: 'Goudy Bookletter 1911', | ||
})); | ||
it('transforms font-family with quotes with escaped values', () => runTest([ | ||
['font-family', '"test\\A test"'], | ||
], { | ||
fontFamily: 'test\ntest', | ||
})); | ||
it('transforms font-family with quotes with escaped quote', () => runTest([ | ||
['font-family', '"test\\"test"'], | ||
], { | ||
fontFamily: 'test"test', | ||
})); | ||
it('does not transform invalid unquoted font-family', () => { | ||
expect(() => transformCss([['font-family', 'Goudy Bookletter 1911']])).toThrow(); | ||
}); | ||
it('allows blacklisting shorthands', () => { | ||
@@ -308,0 +391,0 @@ const actualStyles = transformCss([['border-radius', '50']], ['borderRadius']); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
25
108.33%1311
78.85%167269
-10.66%1
Infinity%+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed