├── .gitignore
├── LICENSE.md
├── README.md
├── lerna.json
├── package.json
└── packages
├── atom-css-in-js
├── CHANGELOG.md
├── README.md
├── completions-css.json
├── completions-rn.json
├── cssinjs.gif
├── example.gif
├── keymaps
│ └── css-in-js.json
├── lib
│ ├── autocomplete.js
│ ├── config.json
│ ├── convertCSS.js
│ ├── convertLines.js
│ └── css-in-js.js
├── menus
│ └── css-in-js.json
├── native.gif
├── package.json
├── scripts
│ ├── css
│ │ ├── completions.js
│ │ ├── fetchDocs.js
│ │ ├── html-tags.json
│ │ ├── pseudo-selectors.json
│ │ └── sorted-property-names.json
│ └── rn
│ │ └── completions.js
├── spec
│ └── css-in-js-spec.js
└── styles
│ └── css-in-js.less
├── css-in-js-helpers
├── .babelrc
├── completions-css.json
├── completions-rn.json
├── package.json
├── scripts
│ ├── css
│ │ ├── completions.js
│ │ ├── fetchDocs.js
│ │ ├── html-tags.json
│ │ ├── pseudo-selectors.json
│ │ └── sorted-property-names.json
│ └── rn
│ │ └── completions.js
└── src
│ └── index.js
└── vscode-css-in-js
├── .babelrc
├── .vscode
├── extensions.json
├── launch.json
└── settings.json
├── CHANGELOG.md
├── README.md
├── demo.gif
├── icon.png
├── jsconfig.json
├── package.json
└── src
├── autocomplete.js
└── extension.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea
3 | node_modules
4 | dist
5 | *.log
6 | yarn.lock
7 | package-lock.json
8 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 Ansuman Shah
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Autocomplete for React Native and css-in-js for Atom and VS Code
2 |
3 | [![Star on GitHub][github-star-badge]][github-star][![Tweet][twitter-badge]][twitter]
4 | [![PRs Welcome][prs-badge]][prs]
5 | [![Version][version-badge]][package]
6 | [![MIT License][license-badge]][LICENSE]
7 |
8 | Now get Autocomplete for CSSinJS libraries using object styles.
9 |
10 |
11 | ## Installation
12 | ```
13 | apm install css-in-js
14 | ```
15 | Or go to Settings → Install and search for `css-in-js`
16 |
17 | ## Usage
18 | ```js
19 | const btnA = css({ /* styles */ });
20 | const btnB = glamorous.div({ /* styles */ });
21 | const btnC = StyleSheet.create({ /* styles */ });
22 | ```
23 | Only works for these keywords by default you can edit in settings for more.
24 |
25 | `glamorous | css | StyleSheet.create`
26 |
27 | ![ReactNative][native-demo]
28 |
29 | ![Autocomplete][autocomplete-demo]
30 |
31 | Does not work for general objects
32 | ```js
33 | let styles = {
34 | /* styles */
35 | }
36 | ```
37 | This is basically a fork of [autocomplete-css](https://github.com/atom/autocomplete-css)
38 |
39 | ## [CSS in JS for VS Code](https://marketplace.visualstudio.com/items?itemName=paulmolluzzo.convert-css-in-js)
40 |
41 | > Provides CSS in JS autocompletion and converts kebab-case CSS to camelCase CSS and vice versa
42 |
43 | * Provides autocompletion options for CSS styles as a style object for use in CSS in JS (like [`glamorous`](https://github.com/paypal/glamorous/)!)
44 | * Converts CSS between regular CSS syntax (strings) and CSS-in-JS syntax (style objects)
45 |
46 | ### Autocomplete
47 | 
48 |
49 | ### Convert CSS in JS
50 | 
51 |
52 | ### How to Use CSS Conversion
53 |
54 | Select some block of text in a `javascript` or `typescript` file and use `cmd+shift+p` to bring up the command palette, then select `Convert CSS-in-JS`.
55 |
56 | Or use the keyboard shortcut `cmd+shift+j` (`ctrl+shift+j` on Windows).
57 |
58 | ---
59 |
60 | Coming Soon
61 |
62 | *Codemods for easy shifting between css-in-js libraries*
63 |
64 | [autocomplete-demo]: https://raw.githubusercontent.com/ansumanshah/css-in-js/master/packages/atom-css-in-js/cssinjs.gif
65 | [native-demo]: https://raw.githubusercontent.com/ansumanshah/css-in-js/master/packages/atom-css-in-js/native.gif
66 | [converter-demo]: https://raw.githubusercontent.com/ansumanshah/css-in-js/master/packages/atom-css-in-js/example.gif
67 |
68 | [github-star-badge]: https://img.shields.io/github/stars/ansumanshah/css-in-js.svg?style=social
69 | [github-star]: https://github.com/ansumanshah/css-in-js/stargazers
70 | [twitter]: https://twitter.com/intent/tweet?text=Check%20out%20Atom%20Autocomplete%20css-in-js!%20https://github.com/ansumanshah/css-in-js%20%F0%9F%91%8D
71 | [twitter-badge]: https://img.shields.io/twitter/url/https/github.com/ansumanshah/css-in-js.svg?style=social
72 |
73 | [version-badge]: https://img.shields.io/apm/v/css-in-js.svg?style=flat-square
74 | [package]: https://atom.io/packages/css-in-js
75 | [license-badge]: https://img.shields.io/apm/l/css-in-js.svg?style=flat-square
76 | [license]: https://github.com/ansumanshah/css-in-js/blob/master/LICENSE
77 | [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
78 | [prs]: http://makeapullrequest.com
79 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "lerna": "2.1.2",
3 | "packages": [
4 | "packages/*"
5 | ],
6 | "version": "0.0.0"
7 | }
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "format": "prettier --trailing-comma es5 --no-semi --single-quote --write 'packages/*/*.js' 'packages/*/!(node_modules)/**/*.js'",
5 | "precommit": "lint-staged"
6 | },
7 | "devDependencies": {
8 | "husky": "^0.14.3",
9 | "lerna": "^2.1.2",
10 | "lint-staged": "^4.1.0",
11 | "prettier": "^1.6.1"
12 | },
13 | "author": "Ansuman Shah",
14 | "homepage": "https://github.com/ansumanshah/css-in-js#readme",
15 | "license": "MIT",
16 | "repository": {
17 | "type": "git",
18 | "url": "git+https://github.com/ansumanshah/css-in-js.git"
19 | },
20 | "lint-staged": {
21 | "*.js": [
22 | "prettier --trailing-comma es5 --no-semi --single-quote --write",
23 | "git add"
24 | ],
25 | "yarn.lock": [
26 | "git rm --cached"
27 | ]
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 0.1.0 - First Release
2 | * Can convert CSS to JS inline styles and vice versa
3 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/README.md:
--------------------------------------------------------------------------------
1 | # Atom Autocomplete for React Native and css-in-js [![Star on GitHub][github-star-badge]][github-star][![Tweet][twitter-badge]][twitter]
2 |
3 | [![PRs Welcome][prs-badge]][prs]
4 | [![Version][version-badge]][package]
5 | [![MIT License][license-badge]][LICENSE]
6 |
7 | Now get Autocomplete for CSSinJS libraries using object styles.
8 |
9 | ## Installation
10 | ```
11 | apm install css-in-js
12 | ```
13 | Or go to Settings → Install and search for `css-in-js`
14 |
15 |
16 |
17 | ## Usage
18 | ```js
19 | const btnA = css({ /* styles */ });
20 | const btnB = glamorous.div({ /* styles */ });
21 | const btnC = StyleSheet.create({ /* styles */ });
22 | ```
23 | Only works for these keywords by default you can edit in settings for more.
24 |
25 | `glamorous | css | StyleSheet.create`
26 |
27 | ![ReactNative][native-demo]
28 |
29 | ![Autocomplete][autocomplete-demo]
30 |
31 | Does not work for general objects
32 | ```js
33 | let styles = {
34 | /* styles */
35 | }
36 | ```
37 | This is basically a fork of [autocomplete-css](https://github.com/atom/autocomplete-css)
38 |
39 | CTRL + ALT + J to convert the css lines to js
40 |
41 | ![Convert][converter-demo]
42 |
43 | Coming Soon
44 |
45 | *Codemods for easy shifting between css-in-js libraries*
46 |
47 | [autocomplete-demo]: https://github.com/ansumanshah/css-in-js/raw/master/cssinjs.gif
48 | [native-demo]: https://github.com/ansumanshah/css-in-js/raw/master/native.gif
49 | [converter-demo]: https://github.com/ansumanshah/css-in-js/raw/master/example.gif
50 |
51 | [github-star-badge]: https://img.shields.io/github/stars/ansumanshah/css-in-js.svg?style=social
52 | [github-star]: https://github.com/ansumanshah/css-in-js/stargazers
53 | [twitter]: https://twitter.com/intent/tweet?text=Check%20out%20Atom%20Autocomplete%20css-in-js!%20https://github.com/ansumanshah/css-in-js%20%F0%9F%91%8D
54 | [twitter-badge]: https://img.shields.io/twitter/url/https/github.com/ansumanshah/css-in-js.svg?style=social
55 |
56 | [version-badge]: https://img.shields.io/apm/v/css-in-js.svg?style=flat-square
57 | [package]: https://atom.io/packages/css-in-js
58 | [license-badge]: https://img.shields.io/apm/l/css-in-js.svg?style=flat-square
59 | [license]: https://github.com/ansumanshah/css-in-js/blob/master/LICENSE
60 | [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
61 | [prs]: http://makeapullrequest.com
62 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/completions-rn.json:
--------------------------------------------------------------------------------
1 | {
2 | "display": {
3 | "type": "enum",
4 | "propType": "layout-props",
5 | "values": [
6 | "none",
7 | "flex"
8 | ],
9 | "description": "'display' sets the display type of this component.\n\n It works similarly to 'display' in CSS, but only support 'flex' and 'none'.\n 'flex' is the default."
10 | },
11 | "width": {
12 | "type": "number | string",
13 | "propType": "layout-props",
14 | "values": [],
15 | "description": "'width' sets the width of this component.\n\n It works similarly to 'width' in CSS, but in React Native you\n must use points or percentages. Ems and other units are not supported.\n See https://developer.mozilla.org/en-US/docs/Web/CSS/width for more details."
16 | },
17 | "height": {
18 | "type": "number | string",
19 | "propType": "layout-props",
20 | "values": [],
21 | "description": "'height' sets the height of this component.\n\n It works similarly to 'height' in CSS, but in React Native you\n must use points or percentages. Ems and other units are not supported.\n See https://developer.mozilla.org/en-US/docs/Web/CSS/height for more details."
22 | },
23 | "top": {
24 | "type": "number | string",
25 | "propType": "layout-props",
26 | "values": [],
27 | "description": "'top' is the number of logical pixels to offset the top edge of\n this component.\n\n It works similarly to 'top' in CSS, but in React Native you\n must use points or percentages. Ems and other units are not supported.\n\n See https://developer.mozilla.org/en-US/docs/Web/CSS/top\n for more details of how 'top' affects layout."
28 | },
29 | "left": {
30 | "type": "number | string",
31 | "propType": "layout-props",
32 | "values": [],
33 | "description": "'left' is the number of logical pixels to offset the left edge of\n this component.\n\n It works similarly to 'left' in CSS, but in React Native you\n must use points or percentages. Ems and other units are not supported.\n\n See https://developer.mozilla.org/en-US/docs/Web/CSS/left\n for more details of how 'left' affects layout."
34 | },
35 | "right": {
36 | "type": "number | string",
37 | "propType": "layout-props",
38 | "values": [],
39 | "description": "'right' is the number of logical pixels to offset the right edge of\n this component.\n\n It works similarly to 'right' in CSS, but in React Native you\n must use points or percentages. Ems and other units are not supported.\n\n See https://developer.mozilla.org/en-US/docs/Web/CSS/right\n for more details of how 'right' affects layout."
40 | },
41 | "bottom": {
42 | "type": "number | string",
43 | "propType": "layout-props",
44 | "values": [],
45 | "description": "'bottom' is the number of logical pixels to offset the bottom edge of\n this component.\n\n It works similarly to 'bottom' in CSS, but in React Native you\n must use points or percentages. Ems and other units are not supported.\n\n See https://developer.mozilla.org/en-US/docs/Web/CSS/bottom\n for more details of how 'bottom' affects layout."
46 | },
47 | "minWidth": {
48 | "type": "number | string",
49 | "propType": "layout-props",
50 | "values": [],
51 | "description": "'minWidth' is the minimum width for this component, in logical pixels.\n\n It works similarly to 'min-width' in CSS, but in React Native you\n must use points or percentages. Ems and other units are not supported.\n\n See https://developer.mozilla.org/en-US/docs/Web/CSS/min-width\n for more details."
52 | },
53 | "maxWidth": {
54 | "type": "number | string",
55 | "propType": "layout-props",
56 | "values": [],
57 | "description": "'maxWidth' is the maximum width for this component, in logical pixels.\n\n It works similarly to 'max-width' in CSS, but in React Native you\n must use points or percentages. Ems and other units are not supported.\n\n See https://developer.mozilla.org/en-US/docs/Web/CSS/max-width\n for more details."
58 | },
59 | "minHeight": {
60 | "type": "number | string",
61 | "propType": "layout-props",
62 | "values": [],
63 | "description": "'minHeight' is the minimum height for this component, in logical pixels.\n\n It works similarly to 'min-height' in CSS, but in React Native you\n must use points or percentages. Ems and other units are not supported.\n\n See https://developer.mozilla.org/en-US/docs/Web/CSS/min-height\n for more details."
64 | },
65 | "maxHeight": {
66 | "type": "number | string",
67 | "propType": "layout-props",
68 | "values": [],
69 | "description": "'maxHeight' is the maximum height for this component, in logical pixels.\n\n It works similarly to 'max-height' in CSS, but in React Native you\n must use points or percentages. Ems and other units are not supported.\n\n See https://developer.mozilla.org/en-US/docs/Web/CSS/max-height\n for more details."
70 | },
71 | "margin": {
72 | "type": "number | string",
73 | "propType": "layout-props",
74 | "values": [],
75 | "description": "Setting 'margin' has the same effect as setting each of\n 'marginTop', 'marginLeft', 'marginBottom', and 'marginRight'.\n See https://developer.mozilla.org/en-US/docs/Web/CSS/margin\n for more details."
76 | },
77 | "marginVertical": {
78 | "type": "number | string",
79 | "propType": "layout-props",
80 | "values": [],
81 | "description": "Setting 'marginVertical' has the same effect as setting both\n 'marginTop' and 'marginBottom'."
82 | },
83 | "marginHorizontal": {
84 | "type": "number | string",
85 | "propType": "layout-props",
86 | "values": [],
87 | "description": "Setting 'marginHorizontal' has the same effect as setting\n both 'marginLeft' and 'marginRight'."
88 | },
89 | "marginTop": {
90 | "type": "number | string",
91 | "propType": "layout-props",
92 | "values": [],
93 | "description": "'marginTop' works like 'margin-top' in CSS.\n See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top\n for more details."
94 | },
95 | "marginBottom": {
96 | "type": "number | string",
97 | "propType": "layout-props",
98 | "values": [],
99 | "description": "'marginBottom' works like 'margin-bottom' in CSS.\n See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom\n for more details."
100 | },
101 | "marginLeft": {
102 | "type": "number | string",
103 | "propType": "layout-props",
104 | "values": [],
105 | "description": "'marginLeft' works like 'margin-left' in CSS.\n See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left\n for more details."
106 | },
107 | "marginRight": {
108 | "type": "number | string",
109 | "propType": "layout-props",
110 | "values": [],
111 | "description": "'marginRight' works like 'margin-right' in CSS.\n See https://developer.mozilla.org/en-US/docs/Web/CSS/margin-right\n for more details."
112 | },
113 | "padding": {
114 | "type": "number | string",
115 | "propType": "layout-props",
116 | "values": [],
117 | "description": "Setting 'padding' has the same effect as setting each of\n 'paddingTop', 'paddingBottom', 'paddingLeft', and 'paddingRight'.\n See https://developer.mozilla.org/en-US/docs/Web/CSS/padding\n for more details."
118 | },
119 | "paddingVertical": {
120 | "type": "number | string",
121 | "propType": "layout-props",
122 | "values": [],
123 | "description": "Setting 'paddingVertical' is like setting both of\n 'paddingTop' and 'paddingBottom'."
124 | },
125 | "paddingHorizontal": {
126 | "type": "number | string",
127 | "propType": "layout-props",
128 | "values": [],
129 | "description": "Setting 'paddingHorizontal' is like setting both of\n 'paddingLeft' and 'paddingRight'."
130 | },
131 | "paddingTop": {
132 | "type": "number | string",
133 | "propType": "layout-props",
134 | "values": [],
135 | "description": "'paddingTop' works like 'padding-top' in CSS.\nSee https://developer.mozilla.org/en-US/docs/Web/CSS/padding-top\nfor more details."
136 | },
137 | "paddingBottom": {
138 | "type": "number | string",
139 | "propType": "layout-props",
140 | "values": [],
141 | "description": "'paddingBottom' works like 'padding-bottom' in CSS.\nSee https://developer.mozilla.org/en-US/docs/Web/CSS/padding-bottom\nfor more details."
142 | },
143 | "paddingLeft": {
144 | "type": "number | string",
145 | "propType": "layout-props",
146 | "values": [],
147 | "description": "'paddingLeft' works like 'padding-left' in CSS.\nSee https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left\nfor more details."
148 | },
149 | "paddingRight": {
150 | "type": "number | string",
151 | "propType": "layout-props",
152 | "values": [],
153 | "description": "'paddingRight' works like 'padding-right' in CSS.\nSee https://developer.mozilla.org/en-US/docs/Web/CSS/padding-right\nfor more details."
154 | },
155 | "borderWidth": {
156 | "type": "number",
157 | "propType": "imagestyleproptypes",
158 | "values": [],
159 | "description": "ImageStylePropTypes"
160 | },
161 | "borderTopWidth": {
162 | "type": "number",
163 | "propType": "viewstyleproptypes",
164 | "values": [],
165 | "description": "ViewStylePropTypes"
166 | },
167 | "borderRightWidth": {
168 | "type": "number",
169 | "propType": "viewstyleproptypes",
170 | "values": [],
171 | "description": "ViewStylePropTypes"
172 | },
173 | "borderBottomWidth": {
174 | "type": "number",
175 | "propType": "viewstyleproptypes",
176 | "values": [],
177 | "description": "ViewStylePropTypes"
178 | },
179 | "borderLeftWidth": {
180 | "type": "number",
181 | "propType": "viewstyleproptypes",
182 | "values": [],
183 | "description": "ViewStylePropTypes"
184 | },
185 | "position": {
186 | "type": "enum",
187 | "propType": "layout-props",
188 | "values": [
189 | "absolute",
190 | "relative"
191 | ],
192 | "description": "'position' in React Native is similar to regular CSS, but\n everything is set to 'relative' by default, so 'absolute'\n positioning is always just relative to the parent.\n\n If you want to position a child using specific numbers of logical\n pixels relative to its parent, set the child to have 'absolute'\n position.\n\n If you want to position a child relative to something\n that is not its parent, just don't use styles for that. Use the\n component tree.\n\n See https://github.com/facebook/yoga\n for more details on how 'position' differs between React Native\n and CSS."
193 | },
194 | "flexDirection": {
195 | "type": "enum",
196 | "propType": "layout-props",
197 | "values": [
198 | "row",
199 | "row-reverse",
200 | "column",
201 | "column-reverse"
202 | ],
203 | "description": "'flexDirection' controls which directions children of a container go.\n 'row' goes left to right, 'column' goes top to bottom, and you may\n be able to guess what the other two do. It works like 'flex-direction'\n in CSS, except the default is 'column'.\n See https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction\n for more details."
204 | },
205 | "flexWrap": {
206 | "type": "enum",
207 | "propType": "layout-props",
208 | "values": [
209 | "wrap",
210 | "nowrap"
211 | ],
212 | "description": "'flexWrap' controls whether children can wrap around after they\n hit the end of a flex container.\n It works like 'flex-wrap' in CSS (default: nowrap).\n See https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap\n for more details."
213 | },
214 | "justifyContent": {
215 | "type": "enum",
216 | "propType": "layout-props",
217 | "values": [
218 | "flex-start",
219 | "flex-end",
220 | "center",
221 | "space-between",
222 | "space-around"
223 | ],
224 | "description": "'justifyContent' aligns children in the main direction.\n For example, if children are flowing vertically, 'justifyContent'\n controls how they align vertically.\n It works like 'justify-content' in CSS (default: flex-start).\n See https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content\n for more details."
225 | },
226 | "alignItems": {
227 | "type": "enum",
228 | "propType": "layout-props",
229 | "values": [
230 | "flex-start",
231 | "flex-end",
232 | "center",
233 | "stretch",
234 | "baseline"
235 | ],
236 | "description": "'alignItems' aligns children in the cross direction.\n For example, if children are flowing vertically, 'alignItems'\n controls how they align horizontally.\n It works like 'align-items' in CSS (default: stretch).\n See https://developer.mozilla.org/en-US/docs/Web/CSS/align-items\n for more details."
237 | },
238 | "alignSelf": {
239 | "type": "enum",
240 | "propType": "layout-props",
241 | "values": [
242 | "auto",
243 | "flex-start",
244 | "flex-end",
245 | "center",
246 | "stretch",
247 | "baseline"
248 | ],
249 | "description": "'alignSelf' controls how a child aligns in the cross direction,\n overriding the 'alignItems' of the parent. It works like 'align-self'\n in CSS (default: auto).\n See https://developer.mozilla.org/en-US/docs/Web/CSS/align-self\n for more details."
250 | },
251 | "alignContent": {
252 | "type": "enum",
253 | "propType": "layout-props",
254 | "values": [
255 | "flex-start",
256 | "flex-end",
257 | "center",
258 | "stretch",
259 | "space-between",
260 | "space-around"
261 | ],
262 | "description": "'alignContent' controls how rows align in the cross direction,\n overriding the 'alignContent' of the parent.\n See https://developer.mozilla.org/en-US/docs/Web/CSS/align-content\n for more details."
263 | },
264 | "overflow": {
265 | "type": "enum",
266 | "propType": "imagestyleproptypes",
267 | "values": [
268 | "visible",
269 | "hidden"
270 | ],
271 | "description": "ImageStylePropTypes"
272 | },
273 | "flex": {
274 | "type": "number",
275 | "propType": "layout-props",
276 | "values": [],
277 | "description": "In React Native 'flex' does not work the same way that it does in CSS.\n 'flex' is a number rather than a string, and it works\n according to the 'Yoga' library\n at https://github.com/facebook/yoga\n\n When 'flex' is a positive number, it makes the component flexible\n and it will be sized proportional to its flex value. So a\n component with 'flex' set to 2 will take twice the space as a\n component with 'flex' set to 1.\n\n When 'flex' is 0, the component is sized according to 'width'\n and 'height' and it is inflexible.\n\n When 'flex' is -1, the component is normally sized according\n 'width' and 'height'. However, if there's not enough space,\n the component will shrink to its 'minWidth' and 'minHeight'.\n\nflexGrow, flexShrink, and flexBasis work the same as in CSS."
278 | },
279 | "flexGrow": {
280 | "type": "number",
281 | "propType": "layout-props",
282 | "values": [],
283 | "description": "LayoutPropTypes"
284 | },
285 | "flexShrink": {
286 | "type": "number",
287 | "propType": "layout-props",
288 | "values": [],
289 | "description": "LayoutPropTypes"
290 | },
291 | "flexBasis": {
292 | "type": "number | string",
293 | "propType": "layout-props",
294 | "values": [],
295 | "description": "LayoutPropTypes"
296 | },
297 | "aspectRatio": {
298 | "type": "number",
299 | "propType": "layout-props",
300 | "values": [],
301 | "description": "Aspect ratio control the size of the undefined dimension of a node. Aspect ratio is a\nnon-standard property only available in react native and not CSS.\n\n- On a node with a set width/height aspect ratio control the size of the unset dimension\n- On a node with a set flex basis aspect ratio controls the size of the node in the cross axis\n if unset\n- On a node with a measure function aspect ratio works as though the measure function measures\n the flex basis\n- On a node with flex grow/shrink aspect ratio controls the size of the node in the cross axis\n if unset\n- Aspect ratio takes min/max dimensions into account"
302 | },
303 | "zIndex": {
304 | "type": "number",
305 | "propType": "layout-props",
306 | "values": [],
307 | "description": "'zIndex' controls which components display on top of others.\n Normally, you don't use 'zIndex'. Components render according to\n their order in the document tree, so later components draw over\n earlier ones. 'zIndex' may be useful if you have animations or custom\n modal interfaces where you don't want this behavior.\n\n It works like the CSS 'z-index' property - components with a larger\n 'zIndex' will render on top. Think of the z-direction like it's\n pointing from the phone into your eyeball.\n See https://developer.mozilla.org/en-US/docs/Web/CSS/z-index for\n more details."
308 | },
309 | "direction": {
310 | "type": "enum",
311 | "propType": "layout-props",
312 | "values": [
313 | "inherit",
314 | "ltr",
315 | "rtl"
316 | ],
317 | "description": "'direction' specifies the directional flow of the user interface.\n The default is 'inherit', except for root node which will have\n value based on the current locale.\n See https://facebook.github.io/yoga/docs/rtl/\n for more details.\n @platform ios"
318 | },
319 | "transform": {
320 | "type": "arrayOf",
321 | "propType": "transforms",
322 | "values": [],
323 | "description": "TransformPropTypes"
324 | },
325 | "transformMatrix": {
326 | "type": "",
327 | "propType": "transforms",
328 | "values": [],
329 | "description": "TransformPropTypes"
330 | },
331 | "decomposedMatrix": {
332 | "type": "",
333 | "propType": "transforms",
334 | "values": [],
335 | "description": "TransformPropTypes"
336 | },
337 | "shadowColor": {
338 | "type": "",
339 | "propType": "shadow-props",
340 | "values": [],
341 | "description": "Sets the drop shadow color\n@platform ios"
342 | },
343 | "shadowOffset": {
344 | "type": "shape",
345 | "propType": "shadow-props",
346 | "values": [],
347 | "description": "Sets the drop shadow offset\n@platform ios"
348 | },
349 | "shadowOpacity": {
350 | "type": "number",
351 | "propType": "shadow-props",
352 | "values": [],
353 | "description": "Sets the drop shadow opacity (multiplied by the color's alpha component)\n@platform ios"
354 | },
355 | "shadowRadius": {
356 | "type": "number",
357 | "propType": "shadow-props",
358 | "values": [],
359 | "description": "Sets the drop shadow blur radius\n@platform ios"
360 | },
361 | "backfaceVisibility": {
362 | "type": "enum",
363 | "propType": "imagestyleproptypes",
364 | "values": [
365 | "visible",
366 | "hidden"
367 | ],
368 | "description": "ImageStylePropTypes"
369 | },
370 | "backgroundColor": {
371 | "type": "",
372 | "propType": "imagestyleproptypes",
373 | "values": [],
374 | "description": "ImageStylePropTypes"
375 | },
376 | "borderColor": {
377 | "type": "",
378 | "propType": "imagestyleproptypes",
379 | "values": [],
380 | "description": "ImageStylePropTypes"
381 | },
382 | "borderTopColor": {
383 | "type": "",
384 | "propType": "viewstyleproptypes",
385 | "values": [],
386 | "description": "ViewStylePropTypes"
387 | },
388 | "borderRightColor": {
389 | "type": "",
390 | "propType": "viewstyleproptypes",
391 | "values": [],
392 | "description": "ViewStylePropTypes"
393 | },
394 | "borderBottomColor": {
395 | "type": "",
396 | "propType": "viewstyleproptypes",
397 | "values": [],
398 | "description": "ViewStylePropTypes"
399 | },
400 | "borderLeftColor": {
401 | "type": "",
402 | "propType": "viewstyleproptypes",
403 | "values": [],
404 | "description": "ViewStylePropTypes"
405 | },
406 | "borderRadius": {
407 | "type": "number",
408 | "propType": "imagestyleproptypes",
409 | "values": [],
410 | "description": "ImageStylePropTypes"
411 | },
412 | "borderTopLeftRadius": {
413 | "type": "number",
414 | "propType": "imagestyleproptypes",
415 | "values": [],
416 | "description": "ImageStylePropTypes"
417 | },
418 | "borderTopRightRadius": {
419 | "type": "number",
420 | "propType": "imagestyleproptypes",
421 | "values": [],
422 | "description": "ImageStylePropTypes"
423 | },
424 | "borderBottomLeftRadius": {
425 | "type": "number",
426 | "propType": "imagestyleproptypes",
427 | "values": [],
428 | "description": "ImageStylePropTypes"
429 | },
430 | "borderBottomRightRadius": {
431 | "type": "number",
432 | "propType": "imagestyleproptypes",
433 | "values": [],
434 | "description": "ImageStylePropTypes"
435 | },
436 | "borderStyle": {
437 | "type": "enum",
438 | "propType": "viewstyleproptypes",
439 | "values": [
440 | "solid",
441 | "dotted",
442 | "dashed"
443 | ],
444 | "description": "ViewStylePropTypes"
445 | },
446 | "opacity": {
447 | "type": "number",
448 | "propType": "imagestyleproptypes",
449 | "values": [],
450 | "description": "ImageStylePropTypes"
451 | },
452 | "elevation": {
453 | "type": "number",
454 | "propType": "viewstyleproptypes",
455 | "values": [],
456 | "description": "(Android-only) Sets the elevation of a view, using Android's underlying\n[elevation API](https://developer.android.com/training/material/shadows-clipping.html#Elevation).\nThis adds a drop shadow to the item and affects z-order for overlapping views.\nOnly supported on Android 5.0+, has no effect on earlier versions.\n@platform android"
457 | },
458 | "color": {
459 | "type": "",
460 | "propType": "textstyleproptypes",
461 | "values": [],
462 | "description": "TextStylePropTypes"
463 | },
464 | "fontFamily": {
465 | "type": "string",
466 | "propType": "textstyleproptypes",
467 | "values": [],
468 | "description": "TextStylePropTypes"
469 | },
470 | "fontSize": {
471 | "type": "number",
472 | "propType": "textstyleproptypes",
473 | "values": [],
474 | "description": "TextStylePropTypes"
475 | },
476 | "fontStyle": {
477 | "type": "enum",
478 | "propType": "textstyleproptypes",
479 | "values": [
480 | "normal",
481 | "italic"
482 | ],
483 | "description": "TextStylePropTypes"
484 | },
485 | "fontWeight": {
486 | "type": "enum",
487 | "propType": "textstyleproptypes",
488 | "values": [
489 | "normal",
490 | "bold",
491 | "100",
492 | "200",
493 | "300",
494 | "400",
495 | "500",
496 | "600",
497 | "700",
498 | "800",
499 | "900"
500 | ],
501 | "description": "Specifies font weight. The values 'normal' and 'bold' are supported for\nmost fonts. Not all fonts have a variant for each of the numeric values,\nin that case the closest one is chosen."
502 | },
503 | "fontVariant": {
504 | "type": "arrayOf",
505 | "propType": "textstyleproptypes",
506 | "values": [],
507 | "description": "@platform ios"
508 | },
509 | "textShadowOffset": {
510 | "type": "shape",
511 | "propType": "textstyleproptypes",
512 | "values": [],
513 | "description": "TextStylePropTypes"
514 | },
515 | "textShadowRadius": {
516 | "type": "number",
517 | "propType": "textstyleproptypes",
518 | "values": [],
519 | "description": "TextStylePropTypes"
520 | },
521 | "textShadowColor": {
522 | "type": "",
523 | "propType": "textstyleproptypes",
524 | "values": [],
525 | "description": "TextStylePropTypes"
526 | },
527 | "letterSpacing": {
528 | "type": "number",
529 | "propType": "textstyleproptypes",
530 | "values": [],
531 | "description": "@platform ios"
532 | },
533 | "lineHeight": {
534 | "type": "number",
535 | "propType": "textstyleproptypes",
536 | "values": [],
537 | "description": "TextStylePropTypes"
538 | },
539 | "textAlign": {
540 | "type": "enum",
541 | "propType": "textstyleproptypes",
542 | "values": [
543 | "auto",
544 | "left",
545 | "right",
546 | "center",
547 | "justify"
548 | ],
549 | "description": "Specifies text alignment. The value 'justify' is only supported on iOS and\nfallbacks to 'left' on Android."
550 | },
551 | "textAlignVertical": {
552 | "type": "enum",
553 | "propType": "textstyleproptypes",
554 | "values": [
555 | "auto",
556 | "top",
557 | "bottom",
558 | "center"
559 | ],
560 | "description": "@platform android"
561 | },
562 | "includeFontPadding": {
563 | "type": "bool",
564 | "propType": "textstyleproptypes",
565 | "values": [],
566 | "description": "Set to 'false' to remove extra font padding intended to make space for certain ascenders / descenders.\nWith some fonts, this padding can make text look slightly misaligned when centered vertically.\nFor best results also set 'textAlignVertical' to 'center'. Default is true.\n@platform android"
567 | },
568 | "textDecorationLine": {
569 | "type": "enum",
570 | "propType": "textstyleproptypes",
571 | "values": [
572 | "none",
573 | "underline",
574 | "line-through",
575 | "underline line-through"
576 | ],
577 | "description": "TextStylePropTypes"
578 | },
579 | "textDecorationStyle": {
580 | "type": "enum",
581 | "propType": "textstyleproptypes",
582 | "values": [
583 | "solid",
584 | "double",
585 | "dotted",
586 | "dashed"
587 | ],
588 | "description": "@platform ios"
589 | },
590 | "textDecorationColor": {
591 | "type": "",
592 | "propType": "textstyleproptypes",
593 | "values": [],
594 | "description": "@platform ios"
595 | },
596 | "writingDirection": {
597 | "type": "enum",
598 | "propType": "textstyleproptypes",
599 | "values": [
600 | "auto",
601 | "ltr",
602 | "rtl"
603 | ],
604 | "description": "@platform ios"
605 | },
606 | "resizeMode": {
607 | "type": "enum",
608 | "propType": "imagestyleproptypes",
609 | "values": [],
610 | "description": "ImageStylePropTypes"
611 | },
612 | "tintColor": {
613 | "type": "",
614 | "propType": "imagestyleproptypes",
615 | "values": [],
616 | "description": "Changes the color of all the non-transparent pixels to the tintColor."
617 | },
618 | "overlayColor": {
619 | "type": "string",
620 | "propType": "imagestyleproptypes",
621 | "values": [],
622 | "description": "When the image has rounded corners, specifying an overlayColor will\ncause the remaining space in the corners to be filled with a solid color.\nThis is useful in cases which are not supported by the Android\nimplementation of rounded corners:\n - Certain resize modes, such as 'contain'\n - Animated GIFs\n\nA typical way to use this prop is with images displayed on a solid\nbackground and setting the 'overlayColor' to the same color\nas the background.\n\nFor details of how this works under the hood, see\nhttp://frescolib.org/docs/rounded-corners-and-circles.html\n\n@platform android"
623 | }
624 | }
625 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/cssinjs.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ansumanshah/css-in-js/304fc7d9bf6fd2b382f3a2cf73542af368376cce/packages/atom-css-in-js/cssinjs.gif
--------------------------------------------------------------------------------
/packages/atom-css-in-js/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ansumanshah/css-in-js/304fc7d9bf6fd2b382f3a2cf73542af368376cce/packages/atom-css-in-js/example.gif
--------------------------------------------------------------------------------
/packages/atom-css-in-js/keymaps/css-in-js.json:
--------------------------------------------------------------------------------
1 | {
2 | "atom-workspace": {
3 | "ctrl-alt-j": "css-in-js:convert"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/lib/autocomplete.js:
--------------------------------------------------------------------------------
1 | // copied from https://github.com/atom/autocomplete-css
2 | // Copyright (c) 2015 GitHub Inc.
3 | const CSS_COMPLETIONS = require('../completions-css.json')
4 | const RN_COMPLETIONS = require('../completions-rn.json')
5 |
6 | const firstInlinePropertyNameWithColonPattern = /(?:{{|{)\s*(\S+)\s*:/
7 | // example { display: }
8 | const inlinePropertyNameWithColonPattern = /(?:,.+?)*,\s*(\S+)\s*:/
9 | // example { display: block, float: left, color: } (match the last one)
10 | const inlinePropertyStartWithColonPattern = /(?::.+?)*,\s*/
11 | // example { display: block, float: left, co } (match the last one)
12 | const propertyNameWithColonPattern = /^\s*(\S+)\s*:/
13 | // display:
14 | const propertyNamePrefixPattern = /[a-zA-Z]+[-a-zA-Z]*$/
15 | const pseudoSelectorPrefixPattern = /\':(:)?([a-z]+[a-z-]*)?(\')?$/
16 | const tagSelectorPrefixPattern = /(^|\s|,)([a-z]+)?$/
17 | const importantPrefixPattern = /(![a-z]+)$/
18 | const cssDocsURL = 'https://developer.mozilla.org/en-US/docs/Web/CSS'
19 | const rnDocsURL = 'https://facebook.github.io/react-native/docs'
20 |
21 | module.exports = {
22 | selector: '.source.js.jsx',
23 | disableForSelector: '.source.js.jsx .comment',
24 | properties: CSS_COMPLETIONS.properties,
25 | pseudoSelectors: CSS_COMPLETIONS.pseudoSelectors,
26 | rnProperties: RN_COMPLETIONS,
27 |
28 | // Tell autocomplete to fuzzy filter the results of getSuggestions(). We are
29 | // still filtering by the first character of the prefix in this provider for
30 | // efficiency.
31 | inclusionPriority: 1,
32 | suggestionPriority: 2,
33 | filterSuggestions: true,
34 | rnStyles: false,
35 |
36 | getSuggestions(request) {
37 | scopes = request.scopeDescriptor.getScopesArray()
38 | isJSX = hasScope(scopes, 'JSXAttrs')
39 |
40 | const pos = isJSX
41 | ? getStartingPosition(request, '{', '}')
42 | : getStartingPosition(request)
43 | if (pos == null) {
44 | // Exclude undefined
45 | return
46 | }
47 | let completions = null
48 | let line = request.editor.getTextInRange([[pos.row, 0], pos])
49 | let regex = new RegExp(atom.config.get('css-in-js.cssRegEx'))
50 | if (!regex.test(line)) {
51 | return
52 | }
53 |
54 | this.rnStyles =
55 | atom.config.get('css-in-js.rnStyles') && /StyleSheet\.create/.test(line)
56 |
57 | if (this.isCompletingPseudoSelector(request)) {
58 | completions = this.getPseudoSelectorCompletions(request)
59 | } else if (this.isCompletingValue(request)) {
60 | completions = this.getPropertyValueCompletions(request)
61 | } else {
62 | if (this.isCompletingName(request)) {
63 | completions = this.getPropertyNameCompletions(request)
64 | }
65 | // else if (this.isCompletingNameOrTag(request)) {
66 | // completions = this.getPropertyNameCompletions(request).concat(
67 | // this.getTagCompletions(request)
68 | // );
69 | // }
70 | }
71 | return completions
72 | },
73 |
74 | onDidInsertSuggestion({ editor, suggestion }) {
75 | if (suggestion.type === 'property') {
76 | return setTimeout(this.triggerAutocomplete.bind(this, editor), 1)
77 | }
78 | },
79 |
80 | triggerAutocomplete(editor) {
81 | return atom.commands.dispatch(
82 | atom.views.getView(editor),
83 | 'autocomplete-plus:activate',
84 | { activatedManually: false }
85 | )
86 | },
87 |
88 | isCompletingValue({ scopeDescriptor, bufferPosition, prefix, editor }) {
89 | let line = editor.lineTextForBufferRow(bufferPosition.row)
90 |
91 | // TODO this is a QuickFIX write RegExp if possible
92 | if (
93 | line.length - line.replace(/:/g, '').length ===
94 | line.length - line.replace(/,/g, '').length
95 | ) {
96 | return false
97 | }
98 |
99 | return (
100 | inlinePropertyNameWithColonPattern.exec(line) ||
101 | firstInlinePropertyNameWithColonPattern.exec(line) ||
102 | propertyNameWithColonPattern.exec(line)
103 | )
104 | },
105 |
106 | isCompletingPseudoSelector({ editor, scopeDescriptor, bufferPosition }) {
107 | const prefix = this.getPseudoSelectorPrefix(editor, bufferPosition)
108 | return prefix
109 | },
110 |
111 | isCompletingName({ scopeDescriptor, bufferPosition, editor }) {
112 | const prefix = this.getPropertyNamePrefix(bufferPosition, editor)
113 | return this.isPropertyNamePrefix(prefix)
114 | },
115 |
116 | isPropertyValuePrefix(prefix) {
117 | prefix = prefix.trim()
118 | return prefix.length > 0 && prefix !== ':'
119 | },
120 |
121 | isPropertyNamePrefix(prefix) {
122 | if (prefix == null) {
123 | return false
124 | }
125 | prefix = prefix.trim()
126 | return prefix.length > 0 && prefix.match(/^[a-zA-Z-]+$/)
127 | },
128 |
129 | getPreviousPropertyName(bufferPosition, editor) {
130 | let { row, column } = bufferPosition
131 | while (row >= 0) {
132 | let line = editor.lineTextForBufferRow(row)
133 | if (row === bufferPosition.row) {
134 | line = line.substr(0, column)
135 | }
136 | let propertyName = __guard__(
137 | inlinePropertyNameWithColonPattern.exec(line),
138 | x => x[1]
139 | )
140 | if (propertyName == null) {
141 | propertyName = __guard__(
142 | firstInlinePropertyNameWithColonPattern.exec(line),
143 | x1 => x1[1]
144 | )
145 | }
146 | if (propertyName == null) {
147 | propertyName = __guard__(
148 | propertyNameWithColonPattern.exec(line),
149 | x2 => x2[1]
150 | )
151 | }
152 | if (propertyName) {
153 | return propertyName
154 | }
155 | row--
156 | }
157 | },
158 |
159 | getPropertyValueCompletions({
160 | bufferPosition,
161 | editor,
162 | prefix,
163 | scopeDescriptor,
164 | }) {
165 | let importantPrefix, value
166 | const property = this.getPreviousPropertyName(bufferPosition, editor)
167 | const styles = this.rnStyles ? this.rnProperties : this.properties
168 | const values =
169 | styles[property] != null ? styles[property].values : undefined
170 | if (values == null) {
171 | return null
172 | }
173 |
174 | const scopes = scopeDescriptor.getScopesArray()
175 | const addComma = !lineEndsWithComma(bufferPosition, editor)
176 |
177 | const completions = []
178 | if (this.isPropertyValuePrefix(prefix)) {
179 | for (value of Array.from(values)) {
180 | if (firstCharsEqual(value, prefix)) {
181 | completions.push(
182 | this.buildPropertyValueCompletion(value, property, addComma)
183 | )
184 | }
185 | }
186 | } else {
187 | for (value of Array.from(values)) {
188 | completions.push(
189 | this.buildPropertyValueCompletion(value, property, addComma)
190 | )
191 | }
192 | }
193 |
194 | if ((importantPrefix = this.getImportantPrefix(editor, bufferPosition))) {
195 | // attention: règle dangereux
196 | completions.push({
197 | type: 'keyword',
198 | text: '!important',
199 | displayText: '!important',
200 | replacementPrefix: importantPrefix,
201 | description:
202 | 'Forces this property to override any other declaration of the same property. Use with caution.',
203 | descriptionMoreURL: `${cssDocsURL}/Specificity#The_!important_exception`,
204 | })
205 | }
206 |
207 | return completions
208 | },
209 |
210 | getImportantPrefix(editor, bufferPosition) {
211 | const line = editor.getTextInRange([
212 | [bufferPosition.row, 0],
213 | bufferPosition,
214 | ])
215 | return __guard__(importantPrefixPattern.exec(line), x => x[1])
216 | },
217 |
218 | buildPropertyValueCompletion(value, propertyName, addComma) {
219 | let text = "'" + value + "'"
220 | if (addComma) {
221 | text += ','
222 | }
223 |
224 | return {
225 | type: 'value',
226 | text,
227 | displayText: value,
228 | description: `${value} value for the ${propertyName} property`,
229 | descriptionMoreURL: this.rnStyles
230 | ? `${rnDocsURL}/${this.rnProperties[propertyName].propType}.html#props`
231 | : `${cssDocsURL}/${toHyphen(propertyName)}#Values`,
232 | }
233 | },
234 |
235 | getPropertyNamePrefix(bufferPosition, editor) {
236 | const line = editor.getTextInRange([
237 | [bufferPosition.row, 0],
238 | bufferPosition,
239 | ])
240 | return __guard__(propertyNamePrefixPattern.exec(line), x => x[0])
241 | },
242 |
243 | getPropertyNameCompletions({
244 | bufferPosition,
245 | editor,
246 | scopeDescriptor,
247 | activatedManually,
248 | }) {
249 | // Don't autocomplete property names in SASS on root level
250 | const scopes = scopeDescriptor.getScopesArray()
251 | const line = editor.getTextInRange([
252 | [bufferPosition.row, 0],
253 | bufferPosition,
254 | ])
255 |
256 | const prefix = this.getPropertyNamePrefix(bufferPosition, editor)
257 | if (!activatedManually && !prefix) {
258 | return []
259 | }
260 |
261 | const completions = []
262 | const styles = this.rnStyles ? this.rnProperties : this.properties
263 | for (let property in styles) {
264 | const options = styles[property]
265 | if (!prefix || firstCharsEqual(property, prefix)) {
266 | completions.push(
267 | this.buildPropertyNameCompletion(property, prefix, options)
268 | )
269 | }
270 | }
271 | return completions
272 | },
273 |
274 | buildPropertyNameCompletion(
275 | propertyName,
276 | prefix,
277 | { description, type, propType }
278 | ) {
279 | return {
280 | type: 'property',
281 | text: `${propertyName}: `,
282 | displayText: propertyName,
283 | replacementPrefix: prefix,
284 | rightLabel: type,
285 | description,
286 | descriptionMoreURL: this.rnStyles
287 | ? `${rnDocsURL}/${propType}.html#${propertyName.toLowerCase()}`
288 | : `${cssDocsURL}/${toHyphen(propertyName)}`,
289 | }
290 | },
291 |
292 | getPseudoSelectorPrefix(editor, bufferPosition) {
293 | const line = editor.getTextInRange([
294 | [bufferPosition.row, 0],
295 | bufferPosition,
296 | ])
297 | return __guard__(line.match(pseudoSelectorPrefixPattern), x => x[0])
298 | },
299 |
300 | getPseudoSelectorCompletions({ bufferPosition, editor }) {
301 | let prefix = this.getPseudoSelectorPrefix(editor, bufferPosition)
302 | prefix = prefix.replace("'", '')
303 | if (!prefix) {
304 | return null
305 | }
306 |
307 | const completions = []
308 | for (let pseudoSelector in this.pseudoSelectors) {
309 | const options = this.pseudoSelectors[pseudoSelector]
310 | if (firstCharsEqual(pseudoSelector, prefix)) {
311 | completions.push(
312 | this.buildPseudoSelectorCompletion(pseudoSelector, prefix, options)
313 | )
314 | }
315 | }
316 | return completions
317 | },
318 |
319 | buildPseudoSelectorCompletion(
320 | pseudoSelector,
321 | prefix,
322 | { argument, description }
323 | ) {
324 | const completion = {
325 | type: 'pseudo-selector',
326 | replacementPrefix: prefix,
327 | description,
328 | descriptionMoreURL: `${cssDocsURL}/${pseudoSelector}`,
329 | }
330 |
331 | if (argument != null) {
332 | completion.snippet = `${pseudoSelector}(\${1:${argument}})`
333 | } else {
334 | completion.text = pseudoSelector
335 | }
336 | return completion
337 | },
338 | }
339 |
340 | const lineEndsWithComma = (bufferPosition, editor) => {
341 | const { row } = bufferPosition
342 | const line = editor.lineTextForBufferRow(row)
343 | return /,\s*$/.test(line)
344 | }
345 |
346 | const toHyphen = prop =>
347 | prop.replace(/([A-Z])/g, char => `-${char[0].toLowerCase()}`)
348 | const hyphentoCamel = prop =>
349 | prop.replace(/-(\w|$)/g, (dash, next) => next.toUpperCase())
350 |
351 | const getStartingPosition = (request, beginChar = '(', endChar = ')') => {
352 | let pos = request.bufferPosition.copy()
353 | let depth = 0
354 | while (pos.row >= 0) {
355 | const line = request.editor.lineTextForBufferRow(pos.row)
356 | if (pos.column === -1) {
357 | pos.column = line.length - 1
358 | }
359 | while (pos.column >= 0) {
360 | switch (line[pos.column]) {
361 | case endChar:
362 | ++depth
363 | break
364 | case beginChar:
365 | if (--depth < 0) {
366 | return pos
367 | }
368 | break
369 | }
370 | --pos.column
371 | }
372 | pos.column = -1
373 | --pos.row
374 | }
375 | }
376 |
377 | var hasScope = (scopesArray, scope) => scopesArray.indexOf(scope) !== -1
378 |
379 | var firstCharsEqual = (str1, str2) =>
380 | str1[0].toLowerCase() === str2[0].toLowerCase()
381 |
382 | function __guard__(value, transform) {
383 | return typeof value !== 'undefined' && value !== null
384 | ? transform(value)
385 | : undefined
386 | }
387 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/lib/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "cssRegEx": {
3 | "title": "Autocomplete RegEx",
4 | "description": "Will work on function names satisfying the following fields",
5 | "type": "string",
6 | "default": "glamorous|css|style|StyleSheet.create",
7 | "order": 1
8 | },
9 | "rnStyles": {
10 | "title": "React Native Styles",
11 | "description": "Show React Native specific styles for StyleSheet.create()",
12 | "type": "boolean",
13 | "default": true,
14 | "order": 2
15 | },
16 | "cssInJsOptions": {
17 | "type": "object",
18 | "order": 3,
19 | "properties": {
20 | "singleQuote": {
21 | "title": "Single Quotes",
22 | "description": "Use single instead of double quotes.",
23 | "type": "boolean",
24 | "default": true,
25 | "order": 1
26 | },
27 | "snippet": {
28 | "title": "Snippets",
29 | "description": "Use either the [glamorous](https://github.com/paypal/glamorous), [glamor](https://github.com/threepointone/glamor) snippet.",
30 | "type": "string",
31 | "default": "glamorous",
32 | "enum": ["glamorous", "glamor"],
33 | "order": 2
34 | }
35 | }
36 | },
37 | "silenceErrors": {
38 | "title": "Silence Errors",
39 | "description": "Don't show an error message if there is a problem parsing your code",
40 | "type": "boolean",
41 | "default": true,
42 | "order": 4
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/lib/convertCSS.js:
--------------------------------------------------------------------------------
1 | 'use babel'
2 |
3 | import css from 'css'
4 | import stringifyObject from 'stringify-object'
5 |
6 | let toCamel = prop => {
7 | return prop
8 | .replace('.', '')
9 | .replace(/-(\w|$)/g, (dash, next) => next.toUpperCase())
10 | }
11 |
12 | let toUpperCamel = prop => {
13 | return prop
14 | .replace('.', '-')
15 | .replace(/-(\w|$)/g, (dash, next) => next.toUpperCase())
16 | }
17 |
18 | let getSnippet = snippet => {
19 | switch (atom.config.get('css-in-js.cssInJsOptions.snippet')) {
20 | case 'glamorous':
21 | return `const ${toUpperCamel(
22 | snippet.key
23 | )} = glamorous.div(${stringifyObject(snippet.style, {
24 | indent: ' ',
25 | singleQuotes: true,
26 | })})`
27 | case 'glamor':
28 | return `const ${toCamel(
29 | snippet.key
30 | )} = css(${stringifyObject(snippet.style, {
31 | indent: ' ',
32 | singleQuotes: true,
33 | })})`
34 | }
35 | }
36 | let toJS = (rules, options) => {
37 | let snippets = []
38 | rules.forEach(rule => {
39 | if (rule.type === 'comment') return
40 | else if (rule.type === 'rule') {
41 | var key,
42 | style = {}
43 | key = rule.selectors.join('-')
44 | rule.declarations.forEach(function(declaration) {
45 | style[toCamel(declaration.property)] = declaration.value
46 | })
47 | snippets.push({ key, style })
48 | }
49 | })
50 | return snippets
51 | .map(snippet => {
52 | return getSnippet(snippet)
53 | })
54 | .join('\n\n')
55 | }
56 |
57 | export default function convert(s) {
58 | const ast = css.parse(s, {
59 | silent: atom.config.get('css-in-js.silenceErrors'),
60 | })
61 | if (ast.stylesheet && ast.stylesheet.rules) {
62 | return toJS(ast.stylesheet.rules, {})
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/lib/convertLines.js:
--------------------------------------------------------------------------------
1 | 'use babel'
2 |
3 | let isCSS = item => {
4 | return (item.match(/;/g) || []).length === 1
5 | }
6 |
7 | let toCamel = prop => {
8 | return prop.replace(/-(\w|$)/g, (dash, next) => next.toUpperCase())
9 | }
10 |
11 | let toJS = item => {
12 | let [prop, val] = item.split(':')
13 | let whiteSpace = prop.indexOf(prop.trim()) + 1
14 | return (
15 | Array(whiteSpace).join(' ') +
16 | toCamel(prop.trim()) +
17 | ": '" +
18 | val.trim().replace(';', '') +
19 | "',"
20 | )
21 | }
22 |
23 | let isJS = item => {
24 | return (item.match(/,/g) || []).length === 1
25 | }
26 |
27 | let toHyphen = prop => {
28 | return prop.replace(/([A-Z])/g, char => `-${char[0].toLowerCase()}`)
29 | }
30 |
31 | let toCSS = item => {
32 | let [prop, val] = item.split(':')
33 | let whiteSpace = prop.indexOf(prop.trim()) + 1
34 | return (
35 | Array(whiteSpace).join(' ') +
36 | toHyphen(prop.trim()) +
37 | ': ' +
38 | val.trim().replace(/'|,/g, '') +
39 | ';'
40 | )
41 | }
42 |
43 | export default function convert(s) {
44 | let lines = s.split('\n')
45 | return lines
46 | .map(item => {
47 | if (isCSS(item)) {
48 | return toJS(item)
49 | } else if (isJS(item)) {
50 | return toCSS(item)
51 | } else {
52 | return item
53 | }
54 | })
55 | .join('\n')
56 | }
57 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/lib/css-in-js.js:
--------------------------------------------------------------------------------
1 | 'use babel'
2 |
3 | import { CompositeDisposable } from 'atom'
4 | import lines from './convertLines'
5 | import css from './convertCSS'
6 | import config from './config.json'
7 | import autocomplete from './autocomplete'
8 |
9 | export default {
10 | subscriptions: null,
11 | config: config,
12 | activate(state) {
13 | // Events subscribed to in atom's system can be easily cleaned up with a CompositeDisposable
14 | this.subscriptions = new CompositeDisposable()
15 |
16 | // Register command that toggles this view
17 | this.subscriptions.add(
18 | atom.commands.add('atom-workspace', {
19 | 'css-in-js:convert': () => this.convert(),
20 | })
21 | )
22 | },
23 |
24 | deactivate() {
25 | this.subscriptions.dispose()
26 | },
27 |
28 | getProvider() {
29 | return [autocomplete]
30 | },
31 |
32 | convert() {
33 | let editor
34 | if ((editor = atom.workspace.getActiveTextEditor())) {
35 | let selection = editor.getSelectedText()
36 | if (selection.length > 0) {
37 | if (selection.match(/{/g)) {
38 | editor.insertText(css(selection))
39 | } else {
40 | editor.insertText(lines(selection))
41 | }
42 | }
43 | }
44 | },
45 | }
46 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/menus/css-in-js.json:
--------------------------------------------------------------------------------
1 | {
2 | "context-menu": {
3 | "atom-text-editor": [
4 | {
5 | "label": "Convert CSS in JS",
6 | "command": "css-in-js:convert"
7 | }
8 | ]
9 | },
10 | "menu": [
11 | {
12 | "label": "Packages",
13 | "submenu": [
14 | {
15 | "label": "CSS in JS",
16 | "submenu": [
17 | {
18 | "label": "Convert",
19 | "command": "css-in-js:convert"
20 | }
21 | ]
22 | }
23 | ]
24 | }
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/native.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ansumanshah/css-in-js/304fc7d9bf6fd2b382f3a2cf73542af368376cce/packages/atom-css-in-js/native.gif
--------------------------------------------------------------------------------
/packages/atom-css-in-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "css-in-js",
3 | "main": "./lib/css-in-js",
4 | "version": "1.4.0",
5 | "description": "Autocomplete JS and React Native styles, and converting copied CSS to JS styles and vice versa",
6 | "repository": "https://github.com/ansumanshah/css-in-js",
7 | "license": "MIT",
8 | "providedServices": {
9 | "autocomplete.provider": {
10 | "versions": {
11 | "2.0.0": "getProvider"
12 | }
13 | }
14 | },
15 | "scripts": {
16 | "update-css": "node scripts/css/completions.js",
17 | "update-rn": "node scripts/rn/completions.js"
18 | },
19 | "keywords": [
20 | "atom",
21 | "autocomplete",
22 | "react",
23 | "react-native",
24 | "glamourous",
25 | "glamour",
26 | "snippets"
27 | ],
28 | "engines": {
29 | "atom": ">=1.0.0 <2.0.0"
30 | },
31 | "dependencies": {
32 | "css": "^2.2.1",
33 | "stringify-object": "^3.2.0"
34 | },
35 | "devDependencies": {
36 | "path": "^0.12.7",
37 | "react-docgen": "3.0.0-beta6",
38 | "request": "^2.81.0"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/scripts/css/completions.js:
--------------------------------------------------------------------------------
1 | // copied from https://github.com/atom/autocomplete-css
2 | // Copyright (c) 2015 GitHub Inc.
3 |
4 | const path = require('path')
5 | const fs = require('fs')
6 | const request = require('request')
7 | const fetchDocs = require('./fetchDocs')
8 |
9 | const PropertiesURL =
10 | 'https://raw.githubusercontent.com/adobe/brackets/master/src/extensions/default/CSSCodeHints/CSSProperties.json'
11 |
12 | const propertiesPromise = new Promise(resolve =>
13 | request({ json: true, url: PropertiesURL }, (error, response, properties) => {
14 | if (error != null) {
15 | console.error(error.message)
16 | resolve(null)
17 | }
18 | if (response.statusCode !== 200) {
19 | console.error(
20 | `Request for CSSProperties.json failed: ${response.statusCode}`
21 | )
22 | resolve(null)
23 | }
24 | return resolve(properties)
25 | })
26 | )
27 |
28 | const propertyDescriptionsPromise = fetchDocs()
29 |
30 | const hyphentoCamel = prop =>
31 | prop.replace(/-(\w|$)/g, (dash, next) => next.toUpperCase())
32 |
33 | Promise.all([propertiesPromise, propertyDescriptionsPromise]).then(values => {
34 | const properties = {}
35 | const propertiesRaw = values[0]
36 | const propertyDescriptions = values[1]
37 | const sortedPropertyNames = JSON.parse(
38 | fs.readFileSync(path.join(__dirname, 'sorted-property-names.json'))
39 | )
40 | for (var propertyName of Array.from(sortedPropertyNames)) {
41 | let metadata
42 | if (!(metadata = propertiesRaw[propertyName])) {
43 | continue
44 | }
45 | metadata.description = propertyDescriptions[propertyName]
46 | properties[hyphentoCamel(propertyName)] = metadata
47 | if (propertyDescriptions[propertyName] == null) {
48 | console.warn(`No description for property ${propertyName}`)
49 | }
50 | }
51 |
52 | for (propertyName in propertiesRaw) {
53 | if (!sortedPropertyNames.includes(propertyName)) {
54 | console.warn(
55 | `Ignoring ${propertyName}; not in sorted-property-names.json`
56 | )
57 | }
58 | }
59 |
60 | const tags = JSON.parse(
61 | fs.readFileSync(path.join(__dirname, 'html-tags.json'))
62 | )
63 | const pseudoSelectors = JSON.parse(
64 | fs.readFileSync(path.join(__dirname, 'pseudo-selectors.json'))
65 | )
66 |
67 | const completions = { properties, pseudoSelectors, tags }
68 | return fs.writeFile(
69 | path.join(__dirname, '../../completions-css.json'), //root folder
70 | `${JSON.stringify(completions, null, ' ')}\n`,
71 | error => (error ? console.log(error) : console.log('Done'))
72 | )
73 | })
74 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/scripts/css/fetchDocs.js:
--------------------------------------------------------------------------------
1 | // copied from https://github.com/atom/autocomplete-css
2 | // Copyright (c) 2015 GitHub Inc.
3 |
4 | const path = require('path')
5 | const fs = require('fs')
6 | const request = require('request')
7 |
8 | const mdnCSSURL = 'https://developer.mozilla.org/en-US/docs/Web/CSS'
9 | const mdnJSONAPI =
10 | 'https://developer.mozilla.org/en-US/search.json?topic=css&highlight=false'
11 | const PropertiesURL =
12 | 'https://raw.githubusercontent.com/adobe/brackets/master/src/extensions/default/CSSCodeHints/CSSProperties.json'
13 |
14 | const fetch = () => {
15 | const propertiesPromise = new Promise(resolve =>
16 | request(
17 | { json: true, url: PropertiesURL },
18 | (error, response, properties) => {
19 | if (error != null) {
20 | console.error(error.message)
21 | resolve(null)
22 | }
23 | if (response.statusCode !== 200) {
24 | console.error(
25 | `Request for CSSProperties.json failed: ${response.statusCode}`
26 | )
27 | resolve(null)
28 | }
29 | return resolve(properties)
30 | }
31 | )
32 | )
33 |
34 | return propertiesPromise.then(properties => {
35 | if (properties == null) {
36 | return
37 | }
38 |
39 | const MAX = 10
40 | const queue = Object.keys(properties)
41 | const running = []
42 | const docs = {}
43 |
44 | return new Promise(resolve => {
45 | const checkEnd = () => {
46 | if (queue.length === 0 && running.length === 0) {
47 | return resolve(docs)
48 | }
49 | }
50 |
51 | const removeRunning = propertyName => {
52 | const index = running.indexOf(propertyName)
53 | if (index > -1) {
54 | return running.splice(index, 1)
55 | }
56 | }
57 |
58 | const runNext = () => {
59 | checkEnd()
60 | if (queue.length !== 0) {
61 | const propertyName = queue.pop()
62 | running.push(propertyName)
63 | return run(propertyName)
64 | }
65 | }
66 |
67 | var run = propertyName => {
68 | const url = `${mdnJSONAPI}&q=${propertyName}`
69 | return request(
70 | { json: true, url },
71 | (error, response, searchResults) => {
72 | if (error == null && response.statusCode === 200) {
73 | handleRequest(propertyName, searchResults)
74 | } else {
75 | console.error(
76 | `Req failed ${url}; ${response.statusCode}, ${error}`
77 | )
78 | }
79 | removeRunning(propertyName)
80 | checkEnd()
81 | return runNext()
82 | }
83 | )
84 | }
85 |
86 | var handleRequest = (propertyName, searchResults) => {
87 | if (searchResults.documents != null) {
88 | for (let doc of Array.from(searchResults.documents)) {
89 | if (doc.url === `${mdnCSSURL}/${propertyName}`) {
90 | docs[propertyName] = filterExcerpt(propertyName, doc.excerpt)
91 | break
92 | }
93 | }
94 | }
95 | }
96 |
97 | for (
98 | let i = 0, end = MAX, asc = 0 <= end;
99 | asc ? i <= end : i >= end;
100 | asc ? i++ : i--
101 | ) {
102 | runNext()
103 | }
104 | })
105 | })
106 | }
107 |
108 | var filterExcerpt = (propertyName, excerpt) => {
109 | const beginningPattern = /^the (css )?[a-z-]+ (css )?property (is )?(\w+)/i
110 | excerpt = excerpt.replace(beginningPattern, match => {
111 | const matches = beginningPattern.exec(match)
112 | const firstWord = matches[4]
113 | return firstWord[0].toUpperCase() + firstWord.slice(1)
114 | })
115 | const periodIndex = excerpt.indexOf('.')
116 | if (periodIndex > -1) {
117 | excerpt = excerpt.slice(0, periodIndex + 1)
118 | }
119 | return excerpt
120 | }
121 |
122 | // Save a file if run from the command line
123 | if (require.main === module) {
124 | fetch().then(docs => {
125 | if (docs != null) {
126 | return fs.writeFileSync(
127 | path.join(__dirname, 'property-docs.json'),
128 | `${JSON.stringify(docs, null, ' ')}\n`
129 | )
130 | } else {
131 | return console.error('No docs')
132 | }
133 | })
134 | }
135 |
136 | module.exports = fetch
137 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/scripts/css/html-tags.json:
--------------------------------------------------------------------------------
1 | [
2 | "a",
3 | "b",
4 | "blockquote",
5 | "body",
6 | "br",
7 | "button",
8 | "canvas",
9 | "code",
10 | "div",
11 | "em",
12 | "form",
13 | "footer",
14 | "h1",
15 | "h2",
16 | "h3",
17 | "h4",
18 | "h5",
19 | "h6",
20 | "head",
21 | "header",
22 | "hgroup",
23 | "hr",
24 | "html",
25 | "i",
26 | "iframe",
27 | "img",
28 | "input",
29 | "label",
30 | "li",
31 | "nav",
32 | "ol",
33 | "p",
34 | "pre",
35 | "select",
36 | "span",
37 | "strong",
38 | "sub",
39 | "summary",
40 | "table",
41 | "td",
42 | "textarea",
43 | "th",
44 | "title",
45 | "tr",
46 | "ul",
47 | "abbr",
48 | "address",
49 | "area",
50 | "article",
51 | "aside",
52 | "audio",
53 | "base",
54 | "bdi",
55 | "bdo",
56 | "big",
57 | "caption",
58 | "cite",
59 | "col",
60 | "colgroup",
61 | "command",
62 | "datalist",
63 | "dd",
64 | "del",
65 | "details",
66 | "dfn",
67 | "dialog",
68 | "dl",
69 | "dt",
70 | "embed",
71 | "fieldset",
72 | "figcaption",
73 | "figure",
74 | "ilayer",
75 | "ins",
76 | "kbd",
77 | "keygen",
78 | "legend",
79 | "link",
80 | "main",
81 | "map",
82 | "mark",
83 | "marquee",
84 | "menu",
85 | "meta",
86 | "meter",
87 | "noscript",
88 | "object",
89 | "optgroup",
90 | "option",
91 | "output",
92 | "param",
93 | "progress",
94 | "q",
95 | "rp",
96 | "rt",
97 | "ruby",
98 | "samp",
99 | "script",
100 | "section",
101 | "small",
102 | "source",
103 | "style",
104 | "sup",
105 | "tbody",
106 | "tfoot",
107 | "thead",
108 | "time",
109 | "track",
110 | "tt",
111 | "var",
112 | "video",
113 | "wbr"
114 | ]
115 |
--------------------------------------------------------------------------------
/packages/atom-css-in-js/scripts/css/pseudo-selectors.json:
--------------------------------------------------------------------------------
1 | {
2 | "::after": {
3 | "description": "Matches a virtual last child of the selected element."
4 | },
5 | "::before": {
6 | "description": "Creates a pseudo-element that is the first child of the element matched."
7 | },
8 | "::first-letter": {
9 | "description": "Matches the first letter of the first line of a block, if it is not preceded by any other content."
10 | },
11 | "::first-line": {
12 | "description": "Applies styles only to the first line of an element."
13 | },
14 | "::selection": {
15 | "description": "Applies rules to the portion of a document that has been highlighted."
16 | },
17 | ":active": {
18 | "description": "Matches when an element is being activated by the user."
19 | },
20 | ":checked": {
21 | "description": "Matches any radio input, checkbox input or option element that is checked or toggled to an on state."
22 | },
23 | ":default": {
24 | "description": "Matches any user interface element that is the default among a group of similar elements"
25 | },
26 | ":dir": {
27 | "argument": "direction",
28 | "description": "Matches elements based on the directionality of the text contained in it."
29 | },
30 | ":disabled": {
31 | "description": "Matches any disabled element."
32 | },
33 | ":empty": {
34 | "description": "Matches any element that has no children at all."
35 | },
36 | ":enabled": {
37 | "description": "Matches any enabled element."
38 | },
39 | ":first": {
40 | "description": "Describes the styling of the first page when printing a document."
41 | },
42 | ":first-child": {
43 | "description": "Matches any element that is the first child element of its parent."
44 | },
45 | ":first-of-type": {
46 | "description": "Matches the first sibling of its type in the list of children of its parent element."
47 | },
48 | ":focus": {
49 | "description": "Matches an element that has focus."
50 | },
51 | ":fullscreen": {
52 | "description": "Applies to any element that's currently being displayed in full-screen mode."
53 | },
54 | ":hover": {
55 | "description": "Matches when the user designates an element with a pointing device, but does not necessarily activate it."
56 | },
57 | ":indeterminate": {
58 | "description": "Matches any checkbox input whose indeterminate DOM property is set to true by JavaScript."
59 | },
60 | ":invalid": {
61 | "description": "Matches any or