Skip to content

Commit 830ec16

Browse files
committed
feat(cssToJS): implemented plugin
1 parent 955870c commit 830ec16

File tree

11 files changed

+464
-138
lines changed

11 files changed

+464
-138
lines changed

.travis.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,3 @@ before_script:
1313
- npm prune
1414
script:
1515
- yarn lint && yarn test
16-
after_success:
17-
- yarn semantic-release

Readme.md

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,46 @@
1-
# javascript-plugin-boilerplate
2-
3-
> A boilerplate to write plugins in pure JavaScript using ES2015. Includes mocha, chai, prettier, husky, Rollup and Eslint
4-
5-
### Features
6-
* ES2015 support (using [rollup.js](http://rollupjs.org/) and [Babel](http://babeljs.io/))
7-
* [UMD](https://github.com/umdjs/umd) supported build
8-
* Automatic versioning using [semantic-release](https://github.com/semantic-release/semantic-release)
9-
* [Mocha](http://mochajs.org/) and [Chai](http://chaijs.com/) for testing
10-
* Lint using [babel-eslint](https://github.com/babel/babel-eslint)
11-
* Code coverage recording with [istanbul](https://gotwarlost.github.io/istanbul/)
12-
* Code coverage reporting to codecov.io
13-
* Prettier for code formatting as a precommit hook
14-
15-
## npm scripts
16-
- **test**: Run tests
17-
- **test:watch**: Run tests while watching at the same time
18-
- **test:cover**: Create code coverage report using istanbul
19-
- **test:report**: Report code coverage report to codecov.io
20-
- **build**: Build all JS files to different formats
21-
- **build:watch**: Build all JS files to different formats while watching
22-
- **lint**: Run eslint on all JS files
23-
- **lint:fix**: Fix linting errors
24-
- **format**: Run prettier on js files
1+
# transform css-to-js
2+
3+
> A utility to convert your CSS into JS or React Native compatible styles.
4+
5+
The online repl is available at https://transform.now.sh/css-to-js
6+
7+
### Installation
8+
```
9+
npm i transform-css-to-js
10+
```
11+
12+
### Usage
13+
14+
import cssToJS from "transform-css-to-js"
15+
16+
const css = `.main-wrapper {
17+
flex-direction: row;
18+
display: flex;
19+
flex: 1;
20+
}
21+
22+
#content {
23+
flex: 1;
24+
}
25+
26+
ul {
27+
padding: 20px 0;
28+
flex: 1;
29+
}
30+
31+
li {
32+
font-family:'Lato';
33+
color: whitesmoke;
34+
line-height: 44px;
35+
}`
36+
37+
const jsStyle = cssToJS(css)
38+
const reactNativeCompatibleCSS = cssToJS(css, true)
39+
```
40+
41+
### API
42+
43+
#### cssToJS(CSS, [supportReactNative])
2544
2645
## License
2746
MIT @ Ritesh Kumar

package.json

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"name": "javascript-plugin-boilerplate",
3-
"version": "0.0.0-semantically-released",
2+
"name": "transform-css-to-js",
3+
"version": "0.1.0",
44
"description": "A boilerplate to write plugins in pure JavaScript using ES2015",
55
"main": "dist/lunar.umd.js",
66
"module": "dist/lunar.es.js",
@@ -15,11 +15,9 @@
1515
"test:cover": "nyc ava",
1616
"test:report": "cat ./coverage/lcov.info | codecov && rm -rf ./coverage",
1717
"semantic-release": "semantic-release pre && npm publish && semantic-release post",
18-
"build": "npm run build:umd && npm run build:es && npm run build:cjs",
19-
"build:umd": "rollup -c rollup.umd.js",
20-
"build:es": "rollup -c rollup.es.js",
18+
"build": "npm run build:cjs",
2119
"build:cjs": "rollup -c rollup.cjs.js",
22-
"build:watch": "concurrently 'npm run build:umd -- -w' 'npm run build:es -- -w' 'npm run build:cjs -- -w'",
20+
"build:watch": "npm run build:cjs -- -w",
2321
"lint": "eslint src/**/*.js *.js tests/**/*.js",
2422
"lint:fix": "npm run lint -- -fix",
2523
"format": "prettier --write src/**/*.js *.js tests/**/*.js",
@@ -34,7 +32,6 @@
3432
"babel-preset-env": "^1.6.0",
3533
"babel-register": "^6.24.1",
3634
"codecov.io": "^0.1.6",
37-
"concurrently": "^3.5.0",
3835
"cz-conventional-changelog": "^2.0.0",
3936
"eslint": "^4.2.0",
4037
"eslint-config-prettier": "^2.3.0",
@@ -71,11 +68,16 @@
7168
"git add"
7269
]
7370
},
74-
"homepage": "https://github.com/ritz078/javascript-plugin-boilerplate",
71+
"homepage": "https://github.com/ritz078/transform-css-to-js",
7572
"ava": {
7673
"require": [
7774
"babel-register",
7875
"babel-polyfill"
7976
]
77+
},
78+
"dependencies": {
79+
"css-to-react-native": "^2.0.4",
80+
"lodash": "^4.17.4",
81+
"stringify-object": "^3.2.0"
8082
}
8183
}

rollup.cjs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const banner = `/*
1313

1414
const config = {
1515
entry: "src/index.js",
16-
dest: "dist/lunar.cjs.js",
16+
dest: "dist/index.js",
1717
format: "cjs",
1818
banner,
1919
plugins: [fileSize()]

rollup.es.js

Lines changed: 0 additions & 12 deletions
This file was deleted.

rollup.umd.js

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/index.js

Lines changed: 218 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,219 @@
1-
export default function(a, b) {
2-
return a + b;
1+
import cssToReactNative from "css-to-react-native";
2+
import kebabCase from "lodash/kebabCase";
3+
import stringify from "stringify-object";
4+
5+
const SPACE = " ";
6+
function toProperty(name) {
7+
if (name.charAt(0) === "-") name = name.slice(0);
8+
9+
return name.replace(/[^a-z0-9]([a-z0-9])?/gi, function(v, l) {
10+
if (l) return l.toUpperCase();
11+
return "";
12+
});
13+
}
14+
15+
function toSelectors(name) {
16+
const names = name.split(",");
17+
18+
return names.map(function(name) {
19+
name = name.trim();
20+
let newName = "";
21+
22+
if (name.charAt(0) === ".") {
23+
newName += "Class";
24+
name = name.slice(1);
25+
} else if (name.charAt(0) === "#") {
26+
newName += "Id";
27+
name = name.slice(1);
28+
} else {
29+
newName += "Element";
30+
}
31+
32+
return (
33+
name.replace(/([^a-z0-9])([a-z0-9])?/gi, function(v, c, l) {
34+
if (l)
35+
return c === "," || c === " " ? l.toLowerCase() : l.toUpperCase();
36+
return "";
37+
}) + newName
38+
);
39+
});
40+
}
41+
42+
function tokenizer(code) {
43+
const tokens = [];
44+
let token = "";
45+
const whitespc = ["\r\n", "\n\r", "\n", "\r"];
46+
let lastChar = "\0";
47+
let nextChar = "\0";
48+
let char = "\0";
49+
const specialChars = ["{", "}", ":", ";"];
50+
const specialCharsPB = ["{", "}", ";"];
51+
let sc = null;
52+
let inBrackets = false;
53+
54+
for (let i = 0; i < code.length; i++) {
55+
if (i) lastChar = code.charAt(i - 1);
56+
char = code.charAt(i);
57+
if (i + 1 < code.length) nextChar = code.charAt(i + 1);
58+
59+
if (~whitespc.indexOf(char) && ~whitespc.indexOf(lastChar)) {
60+
continue;
61+
}
62+
63+
sc = inBrackets ? specialChars : specialCharsPB;
64+
65+
if (~sc.indexOf(char)) {
66+
if (char === "{") inBrackets = true;
67+
if (char === "}") inBrackets = false;
68+
tokens.push(token);
69+
tokens.push(char);
70+
token = "";
71+
continue;
72+
}
73+
74+
token += char;
75+
}
76+
77+
if (token) tokens.push(token);
78+
79+
return tokens
80+
.map(function(token) {
81+
return token.trim();
82+
})
83+
.filter(function(token) {
84+
return token;
85+
});
86+
}
87+
88+
function convertoToJS(tokens) {
89+
const items = [];
90+
let actualItem = null;
91+
let actualProp = null;
92+
function readSelector(token) {
93+
const selectors = toSelectors(token);
94+
95+
actualItem = {
96+
originalValue: token,
97+
selectors: selectors,
98+
values: {}
99+
};
100+
101+
actualProp = null;
102+
items.push(actualItem);
103+
104+
return readBracketO;
105+
}
106+
107+
function readBracketO(token) {
108+
if (token !== "{") throw new Error("expected '{' ");
109+
110+
return readProperty;
111+
}
112+
113+
function readBracketC(token) {
114+
if (token !== "}") throw new Error("expected '}' ");
115+
return readSelector;
116+
}
117+
118+
function readDefinition(token) {
119+
if (token !== ":") throw new Error("expected ':' ");
120+
121+
return readValue;
122+
}
123+
124+
function readProperty(token) {
125+
if (token === "}") return readBracketC(token);
126+
127+
const property = toProperty(token);
128+
actualProp = property;
129+
130+
if (!actualItem.values[property]) {
131+
actualItem.values[property] = [];
132+
}
133+
134+
return readDefinition;
135+
}
136+
137+
function readValue(token) {
138+
actualItem.values[actualProp].push(token);
139+
140+
return readFinal;
141+
}
142+
143+
function readFinal(token) {
144+
if (token === "}") return readBracketC(token);
145+
if (token !== ";") throw new Error("expected ';' ");
146+
return readProperty;
147+
}
148+
149+
let nextAction = readSelector;
150+
let i = 0;
151+
tokens.forEach(function(token) {
152+
i++;
153+
nextAction = nextAction(token);
154+
});
155+
156+
return renderJS(items);
157+
}
158+
159+
function renderJS(items) {
160+
let objects = ["{"];
161+
objects = objects.concat(items.map(renderItem).join(","));
162+
objects.push("}");
163+
return objects.join("\n");
164+
}
165+
166+
function renderItem(item) {
167+
const code = ["\n //" + item.originalValue];
168+
169+
let properties = [];
170+
171+
for (const prop in item.values) {
172+
if (item.values.hasOwnProperty(prop)) {
173+
const propitem = {
174+
name: prop,
175+
value: item.values[prop][item.values[prop].length - 1]
176+
};
177+
let markup = '"';
178+
if (~propitem.value.indexOf('"')) {
179+
markup = "'";
180+
propitem.value = propitem.value.replace(/'/gi, "\\'");
181+
}
182+
properties.push(
183+
SPACE + SPACE + propitem.name + ": " + markup + propitem.value + markup
184+
);
185+
}
186+
}
187+
188+
properties = properties.map(function(x) {
189+
return SPACE + x;
190+
});
191+
192+
item.selectors.forEach(function(i) {
193+
code.push(SPACE + i + ": {");
194+
code.push(properties.join(",\n"));
195+
code.push(SPACE + "}");
196+
});
197+
198+
return code.join("\n");
199+
}
200+
201+
function getRnCode(css) {
202+
const styles = {};
203+
const code = eval("(" + convertoToJS(tokenizer(css)) + ")");
204+
Object.keys(code).forEach(key => {
205+
styles[key] = {};
206+
const arr = [];
207+
Object.keys(code[key]).forEach(key2 => {
208+
arr.push([kebabCase(key2), code[key][key2]]);
209+
});
210+
styles[key] = cssToReactNative(arr);
211+
});
212+
return stringify(styles, {
213+
indent: " "
214+
});
215+
}
216+
217+
export default function(code, reactNative = false) {
218+
return reactNative ? getRnCode(code) : convertoToJS(tokenizer(code));
3219
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy