Skip to content

Commit 16d02a4

Browse files
committed
Improve tokenstream performance, implement prettier
1 parent 7beef8f commit 16d02a4

14 files changed

+737
-679
lines changed

.eslintrc.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module.exports = {
2-
extends: 'airbnb-base',
2+
extends: ["airbnb-base", "prettier"]
33
};

package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "css-to-react-native",
3-
"version": "2.1.0",
3+
"version": "2.1.1",
44
"description": "Convert CSS text to a React Native stylesheet object",
55
"main": "dist/index.js",
66
"scripts": {
@@ -35,8 +35,10 @@
3535
"babel-preset-es2015": "^6.18.0",
3636
"eslint": "^3.9.1",
3737
"eslint-config-airbnb-base": "^10.0.1",
38+
"eslint-config-prettier": "^2.9.0",
3839
"eslint-plugin-import": "^2.2.0",
39-
"jest": "^17.0.0"
40+
"jest": "^17.0.0",
41+
"prettier": "^1.10.2"
4042
},
4143
"dependencies": {
4244
"css-color-keywords": "^1.0.0",

src/TokenStream.js

+29-39
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,74 @@
1-
const SYMBOL_BASE_MATCH = 'SYMBOL_BASE_MATCH';
2-
const SYMBOL_MATCH = 'SYMBOL_MATCH';
1+
const SYMBOL_MATCH = "SYMBOL_MATCH";
32

43
module.exports = class TokenStream {
54
constructor(nodes, parent) {
5+
this.index = 0;
66
this.nodes = nodes;
7-
this.parent = parent;
8-
this.lastFunction = null;
7+
this.functionName = parent != null ? parent.value : null;
98
this.lastValue = null;
10-
}
11-
12-
get node() {
13-
return this.nodes[0];
9+
this.rewindIndex = -1;
1410
}
1511

1612
hasTokens() {
17-
return this.nodes.length > 0;
18-
}
19-
20-
lookAhead() {
21-
return new TokenStream(this.nodes.slice(1), this.parent);
13+
return this.index <= this.nodes.length - 1;
2214
}
2315

24-
[SYMBOL_BASE_MATCH](...tokenDescriptors) {
25-
const node = this.node;
16+
[SYMBOL_MATCH](...tokenDescriptors) {
17+
if (!this.hasTokens()) return null;
2618

27-
if (!node) return null;
19+
const node = this.nodes[this.index];
2820

2921
for (let i = 0; i < tokenDescriptors.length; i += 1) {
3022
const tokenDescriptor = tokenDescriptors[i];
3123
const value = tokenDescriptor(node);
32-
if (value !== null) return value;
24+
if (value !== null) {
25+
this.index += 1;
26+
this.lastValue = value;
27+
return value;
28+
}
3329
}
3430

3531
return null;
3632
}
3733

38-
[SYMBOL_MATCH](...tokenDescriptors) {
39-
const value = this[SYMBOL_BASE_MATCH](...tokenDescriptors);
40-
if (value === null) return null;
41-
this.nodes = this.nodes.slice(1);
42-
this.lastFunction = null;
43-
this.lastValue = value;
44-
return value;
45-
}
46-
47-
test(...tokenDescriptors) {
48-
return this[SYMBOL_BASE_MATCH](...tokenDescriptors) !== null;
49-
}
50-
5134
matches(...tokenDescriptors) {
5235
return this[SYMBOL_MATCH](...tokenDescriptors) !== null;
5336
}
5437

5538
expect(...tokenDescriptors) {
5639
const value = this[SYMBOL_MATCH](...tokenDescriptors);
57-
if (value !== null) return value;
58-
return this.throw();
40+
return value !== null ? value : this.throw();
5941
}
6042

6143
matchesFunction() {
62-
const node = this.node;
63-
if (node.type !== 'function') return null;
44+
const node = this.nodes[this.index];
45+
if (node.type !== "function") return null;
6446
const value = new TokenStream(node.nodes, node);
65-
this.nodes = this.nodes.slice(1);
66-
this.lastFunction = value;
47+
this.index += 1;
6748
this.lastValue = null;
6849
return value;
6950
}
7051

7152
expectFunction() {
7253
const value = this.matchesFunction();
73-
if (value !== null) return value;
74-
return this.throw();
54+
return value !== null ? value : this.throw();
7555
}
7656

7757
expectEmpty() {
7858
if (this.hasTokens()) this.throw();
7959
}
8060

8161
throw() {
82-
throw new Error(`Unexpected token type: ${this.node.type}`);
62+
throw new Error(`Unexpected token type: ${this.nodes[this.index].type}`);
63+
}
64+
65+
saveRewindPoint() {
66+
this.rewindIndex = this.index;
67+
}
68+
69+
rewind() {
70+
if (this.rewindIndex === -1) throw new Error("Internal error");
71+
this.index = this.rewindIndex;
72+
this.lastValue = null;
8373
}
8474
};

src/index.js

+30-23
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/* eslint-disable no-param-reassign */
2-
const parse = require('postcss-value-parser');
3-
const camelizeStyleName = require('fbjs/lib/camelizeStyleName');
4-
const transforms = require('./transforms');
5-
const TokenStream = require('./TokenStream');
2+
const parse = require("postcss-value-parser");
3+
const camelizeStyleName = require("fbjs/lib/camelizeStyleName");
4+
const transforms = require("./transforms");
5+
const TokenStream = require("./TokenStream");
66

77
// Note if this is wrong, you'll need to change tokenTypes.js too
88
const numberOrLengthRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?)(?:px)?$/i;
@@ -11,14 +11,14 @@ const nullRe = /^null$/i;
1111
const undefinedRe = /^undefined$/i;
1212

1313
// Undocumented export
14-
export const transformRawValue = (input) => {
14+
export const transformRawValue = input => {
1515
const value = input.trim();
1616

1717
const numberMatch = value.match(numberOrLengthRe);
1818
if (numberMatch !== null) return Number(numberMatch[1]);
1919

2020
const boolMatch = input.match(boolRe);
21-
if (boolMatch !== null) return boolMatch[0].toLowerCase() === 'true';
21+
if (boolMatch !== null) return boolMatch[0].toLowerCase() === "true";
2222

2323
const nullMatch = input.match(nullRe);
2424
if (nullMatch !== null) return null;
@@ -35,32 +35,39 @@ const baseTransformShorthandValue = (propName, inputValue) => {
3535
return transforms[propName](tokenStream);
3636
};
3737

38-
const transformShorthandValue = (process.env.NODE_ENV === 'production')
39-
? baseTransformShorthandValue
40-
: (propName, inputValue) => {
41-
try {
42-
return baseTransformShorthandValue(propName, inputValue);
43-
} catch (e) {
44-
throw new Error(`Failed to parse declaration "${propName}: ${inputValue}"`);
45-
}
46-
};
38+
const transformShorthandValue =
39+
process.env.NODE_ENV === "production"
40+
? baseTransformShorthandValue
41+
: (propName, inputValue) => {
42+
try {
43+
return baseTransformShorthandValue(propName, inputValue);
44+
} catch (e) {
45+
throw new Error(
46+
`Failed to parse declaration "${propName}: ${inputValue}"`
47+
);
48+
}
49+
};
4750

4851
export const getStylesForProperty = (propName, inputValue, allowShorthand) => {
49-
const isRawValue = (allowShorthand === false) || !(propName in transforms);
52+
const isRawValue = allowShorthand === false || !(propName in transforms);
5053
const propValue = isRawValue
5154
? transformRawValue(inputValue)
5255
: transformShorthandValue(propName, inputValue.trim());
5356

54-
return (propValue && propValue.$merge)
57+
return propValue && propValue.$merge
5558
? propValue.$merge
5659
: { [propName]: propValue };
5760
};
5861

5962
export const getPropertyName = camelizeStyleName;
6063

61-
export default (rules, shorthandBlacklist = []) => rules.reduce((accum, rule) => {
62-
const propertyName = getPropertyName(rule[0]);
63-
const value = rule[1];
64-
const allowShorthand = shorthandBlacklist.indexOf(propertyName) === -1;
65-
return Object.assign(accum, getStylesForProperty(propertyName, value, allowShorthand));
66-
}, {});
64+
export default (rules, shorthandBlacklist = []) =>
65+
rules.reduce((accum, rule) => {
66+
const propertyName = getPropertyName(rule[0]);
67+
const value = rule[1];
68+
const allowShorthand = shorthandBlacklist.indexOf(propertyName) === -1;
69+
return Object.assign(
70+
accum,
71+
getStylesForProperty(propertyName, value, allowShorthand)
72+
);
73+
}, {});

0 commit comments

Comments
 (0)