├── .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 | Sponsor 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 | ![autocomplete](https://user-images.githubusercontent.com/737065/30726961-1fbd6794-9f1c-11e7-828b-fc6793b238bc.gif) 48 | 49 | ### Convert CSS in JS 50 | ![demo](https://user-images.githubusercontent.com/737065/28219279-6ffbf4c4-6889-11e7-8d3d-51637fe90856.gif) 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 | Sponsor 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
element whose content fails to validate according to the input's type setting." 62 | }, 63 | ":lang": { 64 | "argument": "language", 65 | "description": "Matches elements based on the language the element is determined to be in." 66 | }, 67 | ":last-child": { 68 | "description": "Matches any element that is the last child element of its parent." 69 | }, 70 | ":last-of-type": { 71 | "description": "Matches the last sibling with the given element name in the list of children of its parent element." 72 | }, 73 | ":left": { 74 | "description": "Matches any left page when printing a page." 75 | }, 76 | ":link": { 77 | "description": "Matches links inside elements." 78 | }, 79 | ":not": { 80 | "argument": "selector", 81 | "description": "Matches an element that is not represented by the argument." 82 | }, 83 | ":nth-child": { 84 | "argument": "an+b", 85 | "description": "Matches an element that has an+b-1 siblings before it in the document tree." 86 | }, 87 | ":nth-last-child": { 88 | "argument": "an+b", 89 | "description": "Matches an element that has an+b-1 siblings after it in the document tree." 90 | }, 91 | ":nth-last-of-type": { 92 | "argument": "an+b", 93 | "description": "Matches an element that has an+b-1 siblings with the same element name after it in the document tree." 94 | }, 95 | ":nth-of-type": { 96 | "argument": "an+b", 97 | "description": "Matches an element that has an+b-1 siblings with the same element name before it in the document tree" 98 | }, 99 | ":only-child": { 100 | "description": "Matches any element which is the only child of its parent." 101 | }, 102 | ":only-of-type": { 103 | "description": "Matches any element that has no siblings of the given type." 104 | }, 105 | ":optional": { 106 | "description": "Matches any element that does not have the required attribute set on it." 107 | }, 108 | ":out-of-range": { 109 | "description": "Matches when an element has its value attribute outside the specified range limitations for this element." 110 | }, 111 | ":read-only": { 112 | "description": "Matches when an element is not writable by the user." 113 | }, 114 | ":read-write": { 115 | "description": "Matches when an element is editable by user like text input element." 116 | }, 117 | ":required": { 118 | "description": "Matches any element that has the required attribute set on it." 119 | }, 120 | ":right": { 121 | "description": "Matches any right page when printing a page. It allows to describe the styling of right-side page." 122 | }, 123 | ":root": { 124 | "description": "Matches the root element of a tree representing the document." 125 | }, 126 | ":scope": { 127 | "description": "Matches the elements that are a reference point for selectors to match against." 128 | }, 129 | ":target": { 130 | "description": "Matches the unique element, if any, with an id matching the fragment identifier of the URI of the document." 131 | }, 132 | ":valid": { 133 | "description": "Matches any or element whose content validates correctly according to the input's type setting" 134 | }, 135 | ":visited": { 136 | "description": "Matches links that have been visited." 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /packages/atom-css-in-js/scripts/css/sorted-property-names.json: -------------------------------------------------------------------------------- 1 | [ 2 | "width", 3 | "height", 4 | "margin", 5 | "margin-left", 6 | "margin-right", 7 | "margin-top", 8 | "margin-bottom", 9 | "padding", 10 | "padding-left", 11 | "padding-right", 12 | "padding-top", 13 | "padding-bottom", 14 | "font", 15 | "font-size", 16 | "font-style", 17 | "font-weight", 18 | "font-family", 19 | "border", 20 | "border-radius", 21 | "border-top", 22 | "border-bottom", 23 | "border-left", 24 | "border-right", 25 | "border-color", 26 | "border-width", 27 | "position", 28 | "text-align", 29 | "background", 30 | "background-color", 31 | "background-position", 32 | "background-repeat", 33 | "background-image", 34 | "background-size", 35 | "background-clip", 36 | "right", 37 | "left", 38 | "top", 39 | "bottom", 40 | "overflow", 41 | "overflow-x", 42 | "overflow-y", 43 | "opacity", 44 | "cursor", 45 | "display", 46 | "color", 47 | "visibility", 48 | "float", 49 | "text-decoration", 50 | "line-height", 51 | "z-index", 52 | "vertical-align", 53 | "box-sizing", 54 | "clear", 55 | "white-space", 56 | "max-width", 57 | "outline", 58 | "content", 59 | "min-width", 60 | "min-height", 61 | "list-style", 62 | "box-shadow", 63 | "webkit-border-radius", 64 | "webkit-user-select", 65 | "webkit-box-shadow", 66 | "text-shadow", 67 | "text-indent", 68 | "max-height", 69 | "text-overflow", 70 | "border-style", 71 | "border-spacing", 72 | "border-collapse", 73 | "border-left-color", 74 | "border-left-style", 75 | "border-left-width", 76 | "border-right-color", 77 | "border-right-style", 78 | "border-right-width", 79 | "border-top-color", 80 | "border-top-style", 81 | "border-top-width", 82 | "border-bottom-color", 83 | "border-bottom-style", 84 | "border-bottom-width", 85 | "border-top-left-radius", 86 | "border-top-right-radius", 87 | "border-bottom-left-radius", 88 | "border-bottom-right-radius", 89 | "user-select", 90 | "text-transform", 91 | "webkit-transition", 92 | "zoom", 93 | "list-style-type", 94 | "word-wrap", 95 | "webkit-transform", 96 | "transition", 97 | "webkit-appearance", 98 | "letter-spacing", 99 | "transform", 100 | "pointer-events", 101 | "webkit-font-smoothing", 102 | "webkit-animation", 103 | "direction", 104 | "clip", 105 | "table-layout", 106 | "src", 107 | "webkit-tap-highlight-color", 108 | "resize", 109 | "webkit-transform-origin", 110 | "word-break", 111 | "webkit-background-clip", 112 | "webkit-background-size", 113 | "filter", 114 | "transform-origin", 115 | "font-variant", 116 | "webkit-filter", 117 | "quotes", 118 | "unicode-bidi", 119 | "word-spacing", 120 | "text-rendering", 121 | "fill", 122 | "webkit-backface-visibility", 123 | "webkit-transition-duration", 124 | "outline-color", 125 | "list-style-position", 126 | "webkit-box-orient", 127 | "webkit-animation-timing-function", 128 | "outline-offset", 129 | "webkit-transition-property", 130 | "webkit-animation-duration", 131 | "webkit-animation-name", 132 | "orphans", 133 | "outline-style", 134 | "outline-width", 135 | "flex", 136 | "flex-grow", 137 | "flex-direction", 138 | "flex-flow", 139 | "flex-wrap", 140 | "flex-shrink", 141 | "flex-basis", 142 | "list-style-image", 143 | "unicode-range", 144 | "align-items", 145 | "transition-delay", 146 | "webkit-animation-fill-mode", 147 | "transition-duration", 148 | "justify-content", 149 | "transition-property", 150 | "webkit-animation-iteration-count", 151 | "webkit-line-clamp", 152 | "webkit-transition-timing-function", 153 | "order", 154 | "transition-timing-function", 155 | "background-attachment", 156 | "background-position-y", 157 | "background-origin", 158 | "background-position-x", 159 | "backface-visibility", 160 | "page-break-inside", 161 | "page-break-after", 162 | "speak", 163 | "stroke", 164 | "webkit-box-flex", 165 | "webkit-transition-delay", 166 | "widows", 167 | "webkit-perspective", 168 | "stroke-width", 169 | "webkit-animation-direction", 170 | "fill-opacity", 171 | "webkit-box-pack", 172 | "webkit-user-drag", 173 | "overflow-wrap", 174 | "webkit-box-align", 175 | "webkit-animation-play-state", 176 | "counter-increment", 177 | "counter-reset", 178 | "webkit-animation-delay", 179 | "image-rendering", 180 | "perspective-origin", 181 | "webkit-perspective-origin", 182 | "perspective", 183 | "webkit-margin-start", 184 | "webkit-transform-style", 185 | "empty-cells", 186 | "stroke-opacity", 187 | "caption-side", 188 | "webkit-mask-image", 189 | "webkit-margin-end", 190 | "transform-style", 191 | "border-image", 192 | "touch-action", 193 | "webkit-box-ordinal-group", 194 | "webkit-column-count", 195 | "font-stretch", 196 | "webkit-print-color-adjust", 197 | "webkit-mask-size", 198 | "webkit-column-gap", 199 | "webkit-margin-top-collapse", 200 | "webkit-border-image", 201 | "will-change", 202 | "webkit-padding-start", 203 | "webkit-mask-repeat", 204 | "webkit-text-fill-color", 205 | "webkit-margin-before", 206 | "webkit-mask-box-image", 207 | "webkit-border-horizontal-spacing", 208 | "animation", 209 | "webkit-column-break-inside", 210 | "page-break-before", 211 | "webkit-margin-after", 212 | "webkit-user-modify", 213 | "webkit-font-feature-settings", 214 | "webkit-line-break", 215 | "webkit-mask-position", 216 | "align-self", 217 | "webkit-box-direction", 218 | "size", 219 | "align-content", 220 | "webkit-text-stroke", 221 | "webkit-padding-end", 222 | "webkit-text-stroke-width", 223 | "border-image-slice", 224 | "border-image-width", 225 | "webkit-column-width", 226 | "border-image-outset", 227 | "webkit-columns", 228 | "border-image-repeat", 229 | "tab-size", 230 | "stop-color", 231 | "object-fit", 232 | "fill-rule", 233 | "writing-mode", 234 | "clip-rule", 235 | "shape-rendering", 236 | "stroke-dasharray", 237 | "webkit-text-stroke-color", 238 | "font-kerning", 239 | "webkit-background-origin", 240 | "stroke-linecap", 241 | "webkit-box-reflect", 242 | "animation-name", 243 | "text-anchor", 244 | "animation-duration", 245 | "stop-opacity", 246 | "webkit-border-vertical-spacing", 247 | "webkit-perspective-origin-y", 248 | "border-image-source", 249 | "stroke-linejoin", 250 | "webkit-perspective-origin-x", 251 | "animation-fill-mode", 252 | "webkit-padding-before", 253 | "webkit-column-rule-color", 254 | "webkit-column-span", 255 | "webkit-column-rule", 256 | "animation-timing-function", 257 | "mask", 258 | "webkit-mask", 259 | "stroke-miterlimit", 260 | "webkit-text-security", 261 | "webkit-box-lines", 262 | "webkit-padding-after", 263 | "webkit-border-end", 264 | "webkit-text-emphasis-color", 265 | "webkit-border-start-color", 266 | "webkit-border-start-width", 267 | "animation-iteration-count", 268 | "stroke-dashoffset", 269 | "animation-delay", 270 | "webkit-rtl-ordering", 271 | "page", 272 | "webkit-margin-collapse", 273 | "webkit-border-start", 274 | "webkit-transform-origin-y", 275 | "webkit-writing-mode", 276 | "alignment-baseline", 277 | "dominant-baseline", 278 | "webkit-column-rule-style", 279 | "webkit-column-rule-width", 280 | "baseline-shift", 281 | "webkit-highlight", 282 | "font-variant-ligatures", 283 | "webkit-transform-origin-x", 284 | "webkit-app-region", 285 | "webkit-clip-path", 286 | "background-blend-mode", 287 | "clip-path", 288 | "object-position", 289 | "webkit-box-decoration-break", 290 | "x", 291 | "webkit-border-end-color", 292 | "enable-background", 293 | "webkit-hyphenate-character", 294 | "mask-type", 295 | "webkit-column-break-before", 296 | "webkit-column-break-after", 297 | "mix-blend-mode", 298 | "webkit-text-decorations-in-effect", 299 | "webkit-box-flex-group", 300 | "webkit-line-box-contain", 301 | "webkit-mask-composite", 302 | "vector-effect", 303 | "marker-start", 304 | "marker-end", 305 | "webkit-border-end-width", 306 | "webkit-mask-clip", 307 | "flood-color", 308 | "flood-opacity", 309 | "webkit-background-composite", 310 | "marker-mid", 311 | "webkit-mask-origin", 312 | "webkit-text-emphasis-style", 313 | "color-rendering", 314 | "color-interpolation-filters", 315 | "webkit-margin-before-collapse", 316 | "color-interpolation", 317 | "webkit-border-after-color", 318 | "webkit-border-before-color", 319 | "webkit-text-orientation", 320 | "webkit-border-after-width", 321 | "background-repeat-y", 322 | "webkit-border-before-width", 323 | "glyph-orientation-vertical", 324 | "lighting-color", 325 | "glyph-orientation-horizontal", 326 | "webkit-mask-box-image-source", 327 | "webkit-mask-box-image-repeat", 328 | "shape-outside", 329 | "webkit-mask-box-image-slice", 330 | "paint-order", 331 | "webkit-text-combine", 332 | "webkit-text-emphasis-position", 333 | "shape-margin", 334 | "webkit-mask-box-image-width", 335 | "webkit-mask-box-image-outset", 336 | "webkit-margin-after-collapse", 337 | "isolation", 338 | "buffered-rendering", 339 | "shape-image-threshold", 340 | "background-repeat-x", 341 | "animation-direction", 342 | "animation-play-state", 343 | "webkit-locale", 344 | "webkit-border-end-style", 345 | "webkit-margin-bottom-collapse", 346 | "all", 347 | "marker", 348 | "webkit-border-after", 349 | "y", 350 | "rx", 351 | "ry", 352 | "cx", 353 | "cy", 354 | "r", 355 | "webkit-border-start-style", 356 | "webkit-mask-position-x", 357 | "webkit-border-fit", 358 | "webkit-transform-origin-z", 359 | "text-justify", 360 | "column-fill", 361 | "text-align-last", 362 | "webkit-min-logical-height", 363 | "text-decoration-color", 364 | "webkit-min-logical-width", 365 | "webkit-logical-height", 366 | "text-decoration-style", 367 | "text-decoration-line", 368 | "webkit-mask-position-y", 369 | "min-zoom", 370 | "max-zoom", 371 | "webkit-max-logical-height", 372 | "webkit-border-before", 373 | "webkit-text-emphasis", 374 | "webkit-max-logical-width", 375 | "webkit-logical-width", 376 | "user-zoom", 377 | "webkit-border-after-style", 378 | "font-size-adjust", 379 | "text-underline-style", 380 | "orientation", 381 | "webkit-font-size-delta", 382 | "text-underline-position", 383 | "webkit-border-before-style", 384 | "text-underline-color", 385 | "touch-action-delay", 386 | "webkit-ruby-position", 387 | "webkit-mask-repeat-x", 388 | "webkit-mask-repeat-y", 389 | "scroll-behavior", 390 | "justify-self", 391 | "text-overline-width", 392 | "grid-column", 393 | "grid-row", 394 | "grid-template", 395 | "text-line-through-width", 396 | "caret-color", 397 | "justify-items", 398 | "grid-template-columns", 399 | "grid-auto-columns", 400 | "grid-auto-flow", 401 | "mask-source-type", 402 | "grid-auto-rows", 403 | "grid-column-start", 404 | "grid-template-rows", 405 | "scroll-blocks-on", 406 | "grid-row-end", 407 | "grid-column-end", 408 | "grid-row-start", 409 | "text-line-through-style", 410 | "text-line-through-mode", 411 | "webkit-wrap-flow", 412 | "webkit-wrap-through", 413 | "text-line-through-color", 414 | "text-overline-color", 415 | "webkit-aspect-ratio", 416 | "text-underline-width", 417 | "text-underline-mode", 418 | "box-decoration-break", 419 | "break-after", 420 | "break-before", 421 | "break-inside", 422 | "columns", 423 | "column-count", 424 | "column-gap", 425 | "column-rule", 426 | "column-rule-color", 427 | "column-rule-style", 428 | "column-rule-width", 429 | "column-span", 430 | "column-width", 431 | "flow-into", 432 | "flow-from", 433 | "font-feature-settings", 434 | "font-language-override", 435 | "font-synthesis", 436 | "font-variant-alternates", 437 | "font-variant-caps", 438 | "font-variant-east-asian", 439 | "font-variant-numeric", 440 | "font-variant-position", 441 | "hyphens", 442 | "image-orientation", 443 | "image-resolution", 444 | "region-break-after", 445 | "region-break-before", 446 | "region-break-inside", 447 | "region-fragment", 448 | "shape-inside", 449 | "text-decoration-skip", 450 | "text-emphasis", 451 | "text-emphasis-color", 452 | "text-emphasis-position", 453 | "text-emphasis-style", 454 | "font-display", 455 | "grid", 456 | "grid-area", 457 | "grid-column-gap", 458 | "grid-gap", 459 | "grid-row-gap", 460 | "grid-template-areas", 461 | "hanging-punctuation" 462 | ] 463 | -------------------------------------------------------------------------------- /packages/atom-css-in-js/scripts/rn/completions.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const fs = require('fs') 3 | const docgen = require('react-docgen') 4 | 5 | const paths = [ 6 | 'Libraries/StyleSheet/LayoutPropTypes.js', 7 | 'Libraries/StyleSheet/TransformPropTypes.js', 8 | 'Libraries/Components/View/ShadowPropTypesIOS.js', 9 | 'Libraries/Components/View/ViewStylePropTypes.js', 10 | 'Libraries/Text/TextStylePropTypes.js', 11 | 'Libraries/Image/ImageStylePropTypes.js', 12 | ] 13 | 14 | //Forked from 15 | //https://github.com/facebook/react-native/blob/master/website/server/extractDocs.js#L508 16 | const styleDocs = paths.reduce((docs, filepath) => { 17 | const props = docgen.parse( 18 | fs.readFileSync(path.resolve('node_modules/react-native', filepath)), 19 | findExportedObject, 20 | [docgen.handlers.propTypeHandler, docgen.handlers.propDocBlockHandler] 21 | ).props 22 | 23 | // Remove deprecated transform props from docs 24 | if (filepath === 'Libraries/StyleSheet/TransformPropTypes.js') { 25 | ;[ 26 | 'rotation', 27 | 'scaleX', 28 | 'scaleY', 29 | 'translateX', 30 | 'translateY', 31 | ].forEach(function(key) { 32 | delete props[key] 33 | }) 34 | } 35 | 36 | let newProps = {} 37 | const propType = path.basename(filepath).replace(path.extname(filepath), '') 38 | Object.keys(props).forEach(function(key) { 39 | newProps[key] = { 40 | type: getType(props[key].type), 41 | propType: getPropType(propType), 42 | values: 43 | props[key].type.name === 'enum' && 44 | typeof props[key].type.value !== 'string' 45 | ? props[key].type.value.map(x => x.value.replace(/("|')/g, '')) 46 | : [], 47 | description: 48 | props[key].description === '' 49 | ? propType 50 | : props[key].description.replace(/`/g, "'"), 51 | } 52 | }) 53 | return Object.assign(docs, newProps) 54 | }, {}) 55 | 56 | fs.writeFile( 57 | path.resolve(__dirname, '../../completions-rn.json'), 58 | `${JSON.stringify(styleDocs, null, ' ')}\n`, 59 | error => (error ? console.log(error) : console.log('Done')) 60 | ) 61 | 62 | function getType(type) { 63 | switch (type.name) { 64 | case 'union': 65 | return type.value.map(x => x.name).join(' | ') 66 | case 'custom': 67 | return '' 68 | default: 69 | return type.name 70 | } 71 | } 72 | 73 | function getPropType(type) { 74 | switch (type) { 75 | case 'LayoutPropTypes': 76 | return 'layout-props' 77 | case 'TransformPropTypes': 78 | return 'transforms' 79 | case 'ShadowPropTypesIOS': 80 | return 'shadow-props' 81 | default: 82 | return type.toLowerCase() 83 | } 84 | } 85 | 86 | //Helpers 87 | //https://github.com/facebook/react-native/blob/master/website/server/docgenHelpers.js#L180 88 | function findExportedObject(ast, recast) { 89 | let objPath 90 | recast.visit(ast, { 91 | visitAssignmentExpression: function(path) { 92 | if (!objPath && docgen.utils.isExportsOrModuleAssignment(path)) { 93 | objPath = docgen.utils.resolveToValue(path.get('right')) 94 | } 95 | return false 96 | }, 97 | }) 98 | 99 | if (objPath) { 100 | // Hack: This is easier than replicating the default propType 101 | // handler. 102 | // This converts any expression, e.g. `foo` to an object expression of 103 | // the form `{propTypes: foo}` 104 | const b = recast.types.builders 105 | const nt = recast.types.namedTypes 106 | let obj = objPath.node 107 | 108 | // Hack: This is converting calls like 109 | // 110 | // Object.apply(Object.create(foo), { bar: 42 }) 111 | // 112 | // to an AST representing an object literal: 113 | // 114 | // { ...foo, bar: 42 } 115 | if ( 116 | nt.CallExpression.check(obj) && 117 | recast.print(obj.callee).code === 'Object.assign' 118 | ) { 119 | obj = objPath.node.arguments[1] 120 | let firstArg = objPath.node.arguments[0] 121 | if (recast.print(firstArg.callee).code === 'Object.create') { 122 | firstArg = firstArg.arguments[0] 123 | } 124 | obj.properties.unshift(b.spreadProperty(firstArg)) 125 | } 126 | 127 | objPath.replace( 128 | b.objectExpression([b.property('init', b.literal('propTypes'), obj)]) 129 | ) 130 | } 131 | return objPath 132 | } 133 | -------------------------------------------------------------------------------- /packages/atom-css-in-js/spec/css-in-js-spec.js: -------------------------------------------------------------------------------- 1 | 'use babel' 2 | 3 | import CssInJs from '../lib/css-in-js' 4 | 5 | // Use the command `window:run-package-specs` (cmd-alt-ctrl-p) to run specs. 6 | // 7 | // To run a specific `it` or `describe` block add an `f` to the front (e.g. `fit` 8 | // or `fdescribe`). Remove the `f` to unfocus the block. 9 | 10 | describe('CssInJs', () => { 11 | let workspaceElement, activationPromise 12 | 13 | beforeEach(() => { 14 | workspaceElement = atom.views.getView(atom.workspace) 15 | activationPromise = atom.packages.activatePackage('css-in-js') 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /packages/atom-css-in-js/styles/css-in-js.less: -------------------------------------------------------------------------------- 1 | // The ui-variables file is provided by base themes provided by Atom. 2 | // 3 | // See https://github.com/atom/atom-dark-ui/blob/master/styles/ui-variables.less 4 | // for a full listing of what's available. 5 | @import "ui-variables"; 6 | 7 | .css-in-js { 8 | display: flex; 9 | font-size: 20px; 10 | } 11 | -------------------------------------------------------------------------------- /packages/css-in-js-helpers/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } -------------------------------------------------------------------------------- /packages/css-in-js-helpers/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/css-in-js-helpers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-in-js-helpers", 3 | "version": "1.0.2", 4 | "description": "CSS in JS helpers", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "update-css": "node scripts/css/completions.js", 8 | "update-rn": "node scripts/rn/completions.js", 9 | "build": "babel src -d dist", 10 | "postinstall": "npm run build" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/ansumanshah/css-in-js.git" 15 | }, 16 | "keywords": [ 17 | "CSSinJS" 18 | ], 19 | "author": "Ansuman Shah", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/ansumanshah/css-in-js/issues" 23 | }, 24 | "homepage": "https://github.com/ansumanshah/css-in-js#readme", 25 | "devDependencies": { 26 | "babel-cli": "^6.24.1", 27 | "babel-core": "^6.25.0", 28 | "babel-preset-es2015": "^6.24.1" 29 | }, 30 | "dependencies": { 31 | "react-docgen": "^2.18.0", 32 | "request": "^2.82.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/css-in-js-helpers/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/css-in-js-helpers/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/css-in-js-helpers/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/css-in-js-helpers/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 element whose content fails to validate according to the input's type setting." 62 | }, 63 | ":lang": { 64 | "argument": "language", 65 | "description": "Matches elements based on the language the element is determined to be in." 66 | }, 67 | ":last-child": { 68 | "description": "Matches any element that is the last child element of its parent." 69 | }, 70 | ":last-of-type": { 71 | "description": "Matches the last sibling with the given element name in the list of children of its parent element." 72 | }, 73 | ":left": { 74 | "description": "Matches any left page when printing a page." 75 | }, 76 | ":link": { 77 | "description": "Matches links inside elements." 78 | }, 79 | ":not": { 80 | "argument": "selector", 81 | "description": "Matches an element that is not represented by the argument." 82 | }, 83 | ":nth-child": { 84 | "argument": "an+b", 85 | "description": "Matches an element that has an+b-1 siblings before it in the document tree." 86 | }, 87 | ":nth-last-child": { 88 | "argument": "an+b", 89 | "description": "Matches an element that has an+b-1 siblings after it in the document tree." 90 | }, 91 | ":nth-last-of-type": { 92 | "argument": "an+b", 93 | "description": "Matches an element that has an+b-1 siblings with the same element name after it in the document tree." 94 | }, 95 | ":nth-of-type": { 96 | "argument": "an+b", 97 | "description": "Matches an element that has an+b-1 siblings with the same element name before it in the document tree" 98 | }, 99 | ":only-child": { 100 | "description": "Matches any element which is the only child of its parent." 101 | }, 102 | ":only-of-type": { 103 | "description": "Matches any element that has no siblings of the given type." 104 | }, 105 | ":optional": { 106 | "description": "Matches any element that does not have the required attribute set on it." 107 | }, 108 | ":out-of-range": { 109 | "description": "Matches when an element has its value attribute outside the specified range limitations for this element." 110 | }, 111 | ":read-only": { 112 | "description": "Matches when an element is not writable by the user." 113 | }, 114 | ":read-write": { 115 | "description": "Matches when an element is editable by user like text input element." 116 | }, 117 | ":required": { 118 | "description": "Matches any element that has the required attribute set on it." 119 | }, 120 | ":right": { 121 | "description": "Matches any right page when printing a page. It allows to describe the styling of right-side page." 122 | }, 123 | ":root": { 124 | "description": "Matches the root element of a tree representing the document." 125 | }, 126 | ":scope": { 127 | "description": "Matches the elements that are a reference point for selectors to match against." 128 | }, 129 | ":target": { 130 | "description": "Matches the unique element, if any, with an id matching the fragment identifier of the URI of the document." 131 | }, 132 | ":valid": { 133 | "description": "Matches any or element whose content validates correctly according to the input's type setting" 134 | }, 135 | ":visited": { 136 | "description": "Matches links that have been visited." 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /packages/css-in-js-helpers/scripts/css/sorted-property-names.json: -------------------------------------------------------------------------------- 1 | [ 2 | "width", 3 | "height", 4 | "margin", 5 | "margin-left", 6 | "margin-right", 7 | "margin-top", 8 | "margin-bottom", 9 | "padding", 10 | "padding-left", 11 | "padding-right", 12 | "padding-top", 13 | "padding-bottom", 14 | "font", 15 | "font-size", 16 | "font-style", 17 | "font-weight", 18 | "font-family", 19 | "border", 20 | "border-radius", 21 | "border-top", 22 | "border-bottom", 23 | "border-left", 24 | "border-right", 25 | "border-color", 26 | "border-width", 27 | "position", 28 | "text-align", 29 | "background", 30 | "background-color", 31 | "background-position", 32 | "background-repeat", 33 | "background-image", 34 | "background-size", 35 | "background-clip", 36 | "right", 37 | "left", 38 | "top", 39 | "bottom", 40 | "overflow", 41 | "overflow-x", 42 | "overflow-y", 43 | "opacity", 44 | "cursor", 45 | "display", 46 | "color", 47 | "visibility", 48 | "float", 49 | "text-decoration", 50 | "line-height", 51 | "z-index", 52 | "vertical-align", 53 | "box-sizing", 54 | "clear", 55 | "white-space", 56 | "max-width", 57 | "outline", 58 | "content", 59 | "min-width", 60 | "min-height", 61 | "list-style", 62 | "box-shadow", 63 | "webkit-border-radius", 64 | "webkit-user-select", 65 | "webkit-box-shadow", 66 | "text-shadow", 67 | "text-indent", 68 | "max-height", 69 | "text-overflow", 70 | "border-style", 71 | "border-spacing", 72 | "border-collapse", 73 | "border-left-color", 74 | "border-left-style", 75 | "border-left-width", 76 | "border-right-color", 77 | "border-right-style", 78 | "border-right-width", 79 | "border-top-color", 80 | "border-top-style", 81 | "border-top-width", 82 | "border-bottom-color", 83 | "border-bottom-style", 84 | "border-bottom-width", 85 | "border-top-left-radius", 86 | "border-top-right-radius", 87 | "border-bottom-left-radius", 88 | "border-bottom-right-radius", 89 | "user-select", 90 | "text-transform", 91 | "webkit-transition", 92 | "zoom", 93 | "list-style-type", 94 | "word-wrap", 95 | "webkit-transform", 96 | "transition", 97 | "webkit-appearance", 98 | "letter-spacing", 99 | "transform", 100 | "pointer-events", 101 | "webkit-font-smoothing", 102 | "webkit-animation", 103 | "direction", 104 | "clip", 105 | "table-layout", 106 | "src", 107 | "webkit-tap-highlight-color", 108 | "resize", 109 | "webkit-transform-origin", 110 | "word-break", 111 | "webkit-background-clip", 112 | "webkit-background-size", 113 | "filter", 114 | "transform-origin", 115 | "font-variant", 116 | "webkit-filter", 117 | "quotes", 118 | "unicode-bidi", 119 | "word-spacing", 120 | "text-rendering", 121 | "fill", 122 | "webkit-backface-visibility", 123 | "webkit-transition-duration", 124 | "outline-color", 125 | "list-style-position", 126 | "webkit-box-orient", 127 | "webkit-animation-timing-function", 128 | "outline-offset", 129 | "webkit-transition-property", 130 | "webkit-animation-duration", 131 | "webkit-animation-name", 132 | "orphans", 133 | "outline-style", 134 | "outline-width", 135 | "flex", 136 | "flex-grow", 137 | "flex-direction", 138 | "flex-flow", 139 | "flex-wrap", 140 | "flex-shrink", 141 | "flex-basis", 142 | "list-style-image", 143 | "unicode-range", 144 | "align-items", 145 | "transition-delay", 146 | "webkit-animation-fill-mode", 147 | "transition-duration", 148 | "justify-content", 149 | "transition-property", 150 | "webkit-animation-iteration-count", 151 | "webkit-line-clamp", 152 | "webkit-transition-timing-function", 153 | "order", 154 | "transition-timing-function", 155 | "background-attachment", 156 | "background-position-y", 157 | "background-origin", 158 | "background-position-x", 159 | "backface-visibility", 160 | "page-break-inside", 161 | "page-break-after", 162 | "speak", 163 | "stroke", 164 | "webkit-box-flex", 165 | "webkit-transition-delay", 166 | "widows", 167 | "webkit-perspective", 168 | "stroke-width", 169 | "webkit-animation-direction", 170 | "fill-opacity", 171 | "webkit-box-pack", 172 | "webkit-user-drag", 173 | "overflow-wrap", 174 | "webkit-box-align", 175 | "webkit-animation-play-state", 176 | "counter-increment", 177 | "counter-reset", 178 | "webkit-animation-delay", 179 | "image-rendering", 180 | "perspective-origin", 181 | "webkit-perspective-origin", 182 | "perspective", 183 | "webkit-margin-start", 184 | "webkit-transform-style", 185 | "empty-cells", 186 | "stroke-opacity", 187 | "caption-side", 188 | "webkit-mask-image", 189 | "webkit-margin-end", 190 | "transform-style", 191 | "border-image", 192 | "touch-action", 193 | "webkit-box-ordinal-group", 194 | "webkit-column-count", 195 | "font-stretch", 196 | "webkit-print-color-adjust", 197 | "webkit-mask-size", 198 | "webkit-column-gap", 199 | "webkit-margin-top-collapse", 200 | "webkit-border-image", 201 | "will-change", 202 | "webkit-padding-start", 203 | "webkit-mask-repeat", 204 | "webkit-text-fill-color", 205 | "webkit-margin-before", 206 | "webkit-mask-box-image", 207 | "webkit-border-horizontal-spacing", 208 | "animation", 209 | "webkit-column-break-inside", 210 | "page-break-before", 211 | "webkit-margin-after", 212 | "webkit-user-modify", 213 | "webkit-font-feature-settings", 214 | "webkit-line-break", 215 | "webkit-mask-position", 216 | "align-self", 217 | "webkit-box-direction", 218 | "size", 219 | "align-content", 220 | "webkit-text-stroke", 221 | "webkit-padding-end", 222 | "webkit-text-stroke-width", 223 | "border-image-slice", 224 | "border-image-width", 225 | "webkit-column-width", 226 | "border-image-outset", 227 | "webkit-columns", 228 | "border-image-repeat", 229 | "tab-size", 230 | "stop-color", 231 | "object-fit", 232 | "fill-rule", 233 | "writing-mode", 234 | "clip-rule", 235 | "shape-rendering", 236 | "stroke-dasharray", 237 | "webkit-text-stroke-color", 238 | "font-kerning", 239 | "webkit-background-origin", 240 | "stroke-linecap", 241 | "webkit-box-reflect", 242 | "animation-name", 243 | "text-anchor", 244 | "animation-duration", 245 | "stop-opacity", 246 | "webkit-border-vertical-spacing", 247 | "webkit-perspective-origin-y", 248 | "border-image-source", 249 | "stroke-linejoin", 250 | "webkit-perspective-origin-x", 251 | "animation-fill-mode", 252 | "webkit-padding-before", 253 | "webkit-column-rule-color", 254 | "webkit-column-span", 255 | "webkit-column-rule", 256 | "animation-timing-function", 257 | "mask", 258 | "webkit-mask", 259 | "stroke-miterlimit", 260 | "webkit-text-security", 261 | "webkit-box-lines", 262 | "webkit-padding-after", 263 | "webkit-border-end", 264 | "webkit-text-emphasis-color", 265 | "webkit-border-start-color", 266 | "webkit-border-start-width", 267 | "animation-iteration-count", 268 | "stroke-dashoffset", 269 | "animation-delay", 270 | "webkit-rtl-ordering", 271 | "page", 272 | "webkit-margin-collapse", 273 | "webkit-border-start", 274 | "webkit-transform-origin-y", 275 | "webkit-writing-mode", 276 | "alignment-baseline", 277 | "dominant-baseline", 278 | "webkit-column-rule-style", 279 | "webkit-column-rule-width", 280 | "baseline-shift", 281 | "webkit-highlight", 282 | "font-variant-ligatures", 283 | "webkit-transform-origin-x", 284 | "webkit-app-region", 285 | "webkit-clip-path", 286 | "background-blend-mode", 287 | "clip-path", 288 | "object-position", 289 | "webkit-box-decoration-break", 290 | "x", 291 | "webkit-border-end-color", 292 | "enable-background", 293 | "webkit-hyphenate-character", 294 | "mask-type", 295 | "webkit-column-break-before", 296 | "webkit-column-break-after", 297 | "mix-blend-mode", 298 | "webkit-text-decorations-in-effect", 299 | "webkit-box-flex-group", 300 | "webkit-line-box-contain", 301 | "webkit-mask-composite", 302 | "vector-effect", 303 | "marker-start", 304 | "marker-end", 305 | "webkit-border-end-width", 306 | "webkit-mask-clip", 307 | "flood-color", 308 | "flood-opacity", 309 | "webkit-background-composite", 310 | "marker-mid", 311 | "webkit-mask-origin", 312 | "webkit-text-emphasis-style", 313 | "color-rendering", 314 | "color-interpolation-filters", 315 | "webkit-margin-before-collapse", 316 | "color-interpolation", 317 | "webkit-border-after-color", 318 | "webkit-border-before-color", 319 | "webkit-text-orientation", 320 | "webkit-border-after-width", 321 | "background-repeat-y", 322 | "webkit-border-before-width", 323 | "glyph-orientation-vertical", 324 | "lighting-color", 325 | "glyph-orientation-horizontal", 326 | "webkit-mask-box-image-source", 327 | "webkit-mask-box-image-repeat", 328 | "shape-outside", 329 | "webkit-mask-box-image-slice", 330 | "paint-order", 331 | "webkit-text-combine", 332 | "webkit-text-emphasis-position", 333 | "shape-margin", 334 | "webkit-mask-box-image-width", 335 | "webkit-mask-box-image-outset", 336 | "webkit-margin-after-collapse", 337 | "isolation", 338 | "buffered-rendering", 339 | "shape-image-threshold", 340 | "background-repeat-x", 341 | "animation-direction", 342 | "animation-play-state", 343 | "webkit-locale", 344 | "webkit-border-end-style", 345 | "webkit-margin-bottom-collapse", 346 | "all", 347 | "marker", 348 | "webkit-border-after", 349 | "y", 350 | "rx", 351 | "ry", 352 | "cx", 353 | "cy", 354 | "r", 355 | "webkit-border-start-style", 356 | "webkit-mask-position-x", 357 | "webkit-border-fit", 358 | "webkit-transform-origin-z", 359 | "text-justify", 360 | "column-fill", 361 | "text-align-last", 362 | "webkit-min-logical-height", 363 | "text-decoration-color", 364 | "webkit-min-logical-width", 365 | "webkit-logical-height", 366 | "text-decoration-style", 367 | "text-decoration-line", 368 | "webkit-mask-position-y", 369 | "min-zoom", 370 | "max-zoom", 371 | "webkit-max-logical-height", 372 | "webkit-border-before", 373 | "webkit-text-emphasis", 374 | "webkit-max-logical-width", 375 | "webkit-logical-width", 376 | "user-zoom", 377 | "webkit-border-after-style", 378 | "font-size-adjust", 379 | "text-underline-style", 380 | "orientation", 381 | "webkit-font-size-delta", 382 | "text-underline-position", 383 | "webkit-border-before-style", 384 | "text-underline-color", 385 | "touch-action-delay", 386 | "webkit-ruby-position", 387 | "webkit-mask-repeat-x", 388 | "webkit-mask-repeat-y", 389 | "scroll-behavior", 390 | "justify-self", 391 | "text-overline-width", 392 | "grid-column", 393 | "grid-row", 394 | "grid-template", 395 | "text-line-through-width", 396 | "caret-color", 397 | "justify-items", 398 | "grid-template-columns", 399 | "grid-auto-columns", 400 | "grid-auto-flow", 401 | "mask-source-type", 402 | "grid-auto-rows", 403 | "grid-column-start", 404 | "grid-template-rows", 405 | "scroll-blocks-on", 406 | "grid-row-end", 407 | "grid-column-end", 408 | "grid-row-start", 409 | "text-line-through-style", 410 | "text-line-through-mode", 411 | "webkit-wrap-flow", 412 | "webkit-wrap-through", 413 | "text-line-through-color", 414 | "text-overline-color", 415 | "webkit-aspect-ratio", 416 | "text-underline-width", 417 | "text-underline-mode", 418 | "box-decoration-break", 419 | "break-after", 420 | "break-before", 421 | "break-inside", 422 | "columns", 423 | "column-count", 424 | "column-gap", 425 | "column-rule", 426 | "column-rule-color", 427 | "column-rule-style", 428 | "column-rule-width", 429 | "column-span", 430 | "column-width", 431 | "flow-into", 432 | "flow-from", 433 | "font-feature-settings", 434 | "font-language-override", 435 | "font-synthesis", 436 | "font-variant-alternates", 437 | "font-variant-caps", 438 | "font-variant-east-asian", 439 | "font-variant-numeric", 440 | "font-variant-position", 441 | "hyphens", 442 | "image-orientation", 443 | "image-resolution", 444 | "region-break-after", 445 | "region-break-before", 446 | "region-break-inside", 447 | "region-fragment", 448 | "shape-inside", 449 | "text-decoration-skip", 450 | "text-emphasis", 451 | "text-emphasis-color", 452 | "text-emphasis-position", 453 | "text-emphasis-style", 454 | "font-display", 455 | "grid", 456 | "grid-area", 457 | "grid-column-gap", 458 | "grid-gap", 459 | "grid-row-gap", 460 | "grid-template-areas", 461 | "hanging-punctuation" 462 | ] 463 | -------------------------------------------------------------------------------- /packages/css-in-js-helpers/scripts/rn/completions.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const fs = require('fs') 3 | const docgen = require('react-docgen') 4 | 5 | const paths = [ 6 | 'Libraries/StyleSheet/LayoutPropTypes.js', 7 | 'Libraries/StyleSheet/TransformPropTypes.js', 8 | 'Libraries/Components/View/ShadowPropTypesIOS.js', 9 | 'Libraries/Components/View/ViewStylePropTypes.js', 10 | 'Libraries/Text/TextStylePropTypes.js', 11 | 'Libraries/Image/ImageStylePropTypes.js', 12 | ] 13 | 14 | //Forked from 15 | //https://github.com/facebook/react-native/blob/master/website/server/extractDocs.js#L508 16 | const styleDocs = paths.reduce((docs, filepath) => { 17 | const props = docgen.parse( 18 | fs.readFileSync(path.resolve('node_modules/react-native', filepath)), 19 | findExportedObject, 20 | [docgen.handlers.propTypeHandler, docgen.handlers.propDocBlockHandler] 21 | ).props 22 | 23 | // Remove deprecated transform props from docs 24 | if (filepath === 'Libraries/StyleSheet/TransformPropTypes.js') { 25 | ;[ 26 | 'rotation', 27 | 'scaleX', 28 | 'scaleY', 29 | 'translateX', 30 | 'translateY', 31 | ].forEach(function(key) { 32 | delete props[key] 33 | }) 34 | } 35 | 36 | let newProps = {} 37 | const propType = path.basename(filepath).replace(path.extname(filepath), '') 38 | Object.keys(props).forEach(function(key) { 39 | newProps[key] = { 40 | type: getType(props[key].type), 41 | propType: getPropType(propType), 42 | values: 43 | props[key].type.name === 'enum' && 44 | typeof props[key].type.value !== 'string' 45 | ? props[key].type.value.map(x => x.value.replace(/("|')/g, '')) 46 | : [], 47 | description: 48 | props[key].description === '' 49 | ? propType 50 | : props[key].description.replace(/`/g, "'"), 51 | } 52 | }) 53 | return Object.assign(docs, newProps) 54 | }, {}) 55 | 56 | fs.writeFile( 57 | path.resolve(__dirname, '../../completions-rn.json'), 58 | `${JSON.stringify(styleDocs, null, ' ')}\n`, 59 | error => (error ? console.log(error) : console.log('Done')) 60 | ) 61 | 62 | function getType(type) { 63 | switch (type.name) { 64 | case 'union': 65 | return type.value.map(x => x.name).join(' | ') 66 | case 'custom': 67 | return '' 68 | default: 69 | return type.name 70 | } 71 | } 72 | 73 | function getPropType(type) { 74 | switch (type) { 75 | case 'LayoutPropTypes': 76 | return 'layout-props' 77 | case 'TransformPropTypes': 78 | return 'transforms' 79 | case 'ShadowPropTypesIOS': 80 | return 'shadow-props' 81 | default: 82 | return type.toLowerCase() 83 | } 84 | } 85 | 86 | //Helpers 87 | //https://github.com/facebook/react-native/blob/master/website/server/docgenHelpers.js#L180 88 | function findExportedObject(ast, recast) { 89 | let objPath 90 | recast.visit(ast, { 91 | visitAssignmentExpression: function(path) { 92 | if (!objPath && docgen.utils.isExportsOrModuleAssignment(path)) { 93 | objPath = docgen.utils.resolveToValue(path.get('right')) 94 | } 95 | return false 96 | }, 97 | }) 98 | 99 | if (objPath) { 100 | // Hack: This is easier than replicating the default propType 101 | // handler. 102 | // This converts any expression, e.g. `foo` to an object expression of 103 | // the form `{propTypes: foo}` 104 | const b = recast.types.builders 105 | const nt = recast.types.namedTypes 106 | let obj = objPath.node 107 | 108 | // Hack: This is converting calls like 109 | // 110 | // Object.apply(Object.create(foo), { bar: 42 }) 111 | // 112 | // to an AST representing an object literal: 113 | // 114 | // { ...foo, bar: 42 } 115 | if ( 116 | nt.CallExpression.check(obj) && 117 | recast.print(obj.callee).code === 'Object.assign' 118 | ) { 119 | obj = objPath.node.arguments[1] 120 | let firstArg = objPath.node.arguments[0] 121 | if (recast.print(firstArg.callee).code === 'Object.create') { 122 | firstArg = firstArg.arguments[0] 123 | } 124 | obj.properties.unshift(b.spreadProperty(firstArg)) 125 | } 126 | 127 | objPath.replace( 128 | b.objectExpression([b.property('init', b.literal('propTypes'), obj)]) 129 | ) 130 | } 131 | return objPath 132 | } 133 | -------------------------------------------------------------------------------- /packages/css-in-js-helpers/src/index.js: -------------------------------------------------------------------------------- 1 | const CSS_COMPLETIONS = require('../completions-css.json') 2 | const RN_COMPLETIONS = require('../completions-rn.json') 3 | 4 | const getBeginningWhitespace = string => 5 | string.match(/^\s+/) !== null ? string.match(/^\s+/)[0] : '' 6 | 7 | // return if the item ends with ; and such semi-colon the only one in the item 8 | const isCSS = item => 9 | item.trim().endsWith(';') && (item.match(/;/g) || []).length == 1 10 | 11 | // return if the item ends with , such comma is the only one which is not wrapped with quotes 12 | const isJS = item => 13 | item.trim().endsWith(',') && 14 | item.match(/(,)(?=(?:[^"']|("|')[^"']*("|'))*$)/g).length === 1 15 | 16 | const toHyphen = prop => 17 | prop.replace(/([A-Z])/g, char => `-${char[0].toLowerCase()}`) 18 | 19 | const toCamel = prop => 20 | prop.replace(/-(\w|$)/g, (dash, next) => next.toUpperCase()) 21 | 22 | const toJS = item => { 23 | let [prop, val] = item.split(/:(.+)/, 2) // in case of bg-url, the value might contain colon : 24 | val = val.trim().slice(0, -1) // remove trailing semi-colon 25 | let wrappingQuotes = "'" // handle if the property already contains quotes 26 | if (!isNaN(val)) { 27 | wrappingQuotes = '' 28 | } else if (val.includes("'") && val.includes('"')) { 29 | return item 30 | } else if (val.includes("'")) { 31 | wrappingQuotes = '"' 32 | } 33 | return `${getBeginningWhitespace(prop)}${toCamel( 34 | prop.trim() 35 | )}: ${wrappingQuotes}${val}${wrappingQuotes},` 36 | } 37 | 38 | const toCSS = item => { 39 | let [prop, val] = item.split(/:(.+)/, 2) 40 | val = val.trim().slice(0, -1) // remove trailing comma 41 | return `${getBeginningWhitespace(prop)}${toHyphen(prop.trim())}: ${isNaN(val.trim()) ? val.slice(1, -1) : Number(val) 42 | };` 43 | } 44 | 45 | const firstCharsEqual = (str1, str2) => str1[0].toLowerCase() === str2[0].toLowerCase() 46 | 47 | const lineEndsWithComma = text => /,\s*$/.test(text) 48 | 49 | const isPropertyValuePrefix = prefix => prefix.trim().length > 0 && prefix.trim() !== ':' 50 | 51 | const firstInlinePropertyNameWithColonPattern = /(?:{{|{)\s*(\S+)\s*:/ 52 | 53 | const inlinePropertyNameWithColonPattern = /(?:,.+?)*,\s*(\S+)\s*:/ 54 | 55 | const inlinePropertyStartWithColonPattern = /(?::.+?)*,\s*/ 56 | 57 | const propertyNameWithColonPattern = /^\s*(\S+)\s*:/ 58 | 59 | const propertyNamePrefixPattern = /[a-zA-Z]+[-a-zA-Z]*$/ 60 | 61 | const pseudoSelectorPrefixPattern = /\':(:)?([a-z]+[a-z-]*)?(\')?$/ 62 | 63 | const tagSelectorPrefixPattern = /(^|\s|,)([a-z]+)?$/ 64 | 65 | const importantPrefixPattern = /(![a-z]+)$/ 66 | 67 | const cssDocsURL = 'https://developer.mozilla.org/en-US/docs/Web/CSS' 68 | 69 | const rnDocsURL = 'https://facebook.github.io/react-native/docs' 70 | 71 | function __guard__(value, transform) { 72 | return typeof value !== 'undefined' && value !== null 73 | ? transform(value) 74 | : undefined 75 | } 76 | 77 | function isPropertyNamePrefix(prefix) { 78 | if (prefix == null) { 79 | return false 80 | } 81 | prefix = prefix.trim() 82 | return prefix.length > 0 && prefix.match(/^[a-zA-Z-]+$/) 83 | } 84 | 85 | function getImportantPrefix(text) { 86 | return __guard__(importantPrefixPattern.exec(text), x => x[1]) 87 | } 88 | 89 | export default function convert(s) { 90 | const lines = s.split('\n') 91 | return lines 92 | .map(item => (isCSS(item) ? toJS(item) : isJS(item) ? toCSS(item) : item)) 93 | .join('\n') 94 | } 95 | 96 | export { 97 | CSS_COMPLETIONS, 98 | RN_COMPLETIONS, 99 | firstCharsEqual, 100 | lineEndsWithComma, 101 | isPropertyValuePrefix, 102 | firstInlinePropertyNameWithColonPattern, 103 | inlinePropertyNameWithColonPattern, 104 | inlinePropertyStartWithColonPattern, 105 | propertyNameWithColonPattern, 106 | propertyNamePrefixPattern, 107 | pseudoSelectorPrefixPattern, 108 | tagSelectorPrefixPattern, 109 | importantPrefixPattern, 110 | cssDocsURL, 111 | rnDocsURL, 112 | __guard__, 113 | isPropertyNamePrefix, 114 | toHyphen, 115 | getImportantPrefix 116 | } -------------------------------------------------------------------------------- /packages/vscode-css-in-js/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } -------------------------------------------------------------------------------- /packages/vscode-css-in-js/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /packages/vscode-css-in-js/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Extension", 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "runtimeExecutable": "${execPath}", 9 | "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], 10 | "stopOnEntry": false 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /packages/vscode-css-in-js/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /packages/vscode-css-in-js/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.1.0 2 | - Add support for typescript and javascriptreact to package.json 3 | 4 | ## 1.0.0 5 | - Add autocompletion 💪 6 | 7 | ## 0.3.0 8 | - Add support for typescript files 9 | 10 | ## 0.2.1 11 | - Update package.json info for marketplace 12 | 13 | ## 0.2.0 14 | - Change current line if nothing is selected 15 | 16 | ## 0.1.0 17 | - Add in keyboard shortcut for converting text 18 | 19 | ## 0.0.2 20 | - Change header color for VS Code marketplace 21 | 22 | ## 0.0.1 23 | - Initial release -------------------------------------------------------------------------------- /packages/vscode-css-in-js/README.md: -------------------------------------------------------------------------------- 1 | # [CSS in JS for VS Code](https://marketplace.visualstudio.com/items?itemName=paulmolluzzo.convert-css-in-js) 2 | 3 | > Provides CSS in JS autocompletion and converts kebab-case CSS to camelCase CSS and vice versa 4 | 5 | * Provides autocompletion options for CSS styles as a style object for use in CSS in JS (like [`glamorous`](https://github.com/paypal/glamorous/)!) 6 | * Converts CSS between regular CSS syntax (strings) and CSS-in-JS syntax (style objects) 7 | 8 | ## Autocomplete 9 | ![autocomplete](https://user-images.githubusercontent.com/737065/30726961-1fbd6794-9f1c-11e7-828b-fc6793b238bc.gif) 10 | 11 | ## Convert CSS in JS 12 | ![demo](https://user-images.githubusercontent.com/737065/28219279-6ffbf4c4-6889-11e7-8d3d-51637fe90856.gif) 13 | 14 | ## How to Use CSS Conversion 15 | 16 | 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`. 17 | 18 | Or use the keyboard shortcut `cmd+shift+j` (`ctrl+shift+j` on Windows). 19 | 20 | --- 21 | 22 | MIT 23 | 24 | © 2017 Paul Molluzzo 25 | -------------------------------------------------------------------------------- /packages/vscode-css-in-js/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansumanshah/css-in-js/304fc7d9bf6fd2b382f3a2cf73542af368376cce/packages/vscode-css-in-js/demo.gif -------------------------------------------------------------------------------- /packages/vscode-css-in-js/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansumanshah/css-in-js/304fc7d9bf6fd2b382f3a2cf73542af368376cce/packages/vscode-css-in-js/icon.png -------------------------------------------------------------------------------- /packages/vscode-css-in-js/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "lib": [ 6 | "es6" 7 | ] 8 | }, 9 | "exclude": [ 10 | "node_modules" 11 | ] 12 | } -------------------------------------------------------------------------------- /packages/vscode-css-in-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "convert-css-in-js", 3 | "displayName": "CSS-in-JS", 4 | "description": "CSS-in-JS autocomplete and conversion", 5 | "version": "1.1.0", 6 | "publisher": "paulmolluzzo", 7 | "author": { 8 | "email": "paul@molluzzo.com", 9 | "name": "Paul Molluzzo", 10 | "url": "https://paul.molluzzo.com" 11 | }, 12 | "license": "MIT", 13 | "homepage": "https://github.com/ansumanshah/css-in-js", 14 | "bugs": { 15 | "url": "https://github.com/ansumanshah/css-in-js/issues" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/ansumanshah/css-in-js.git" 20 | }, 21 | "engines": { 22 | "vscode": "^1.13.0" 23 | }, 24 | "scripts": { 25 | "build": "babel src -d dist", 26 | "postinstall": "npm run build", 27 | "vscode:prepublish": "npm run build", 28 | "prettier": "prettier-standard 'src/**/*.js'", 29 | "lint": "standard" 30 | }, 31 | "categories": [ 32 | "Other", 33 | "Formatters", 34 | "Snippets" 35 | ], 36 | "keywords": [ 37 | "css", 38 | "css-in-js", 39 | "keybindings", 40 | "javascript", 41 | "autocomplete" 42 | ], 43 | "activationEvents": [ 44 | "onCommand:extension.convertCSSinJS", 45 | "onLanguage:javascript", 46 | "onLanguage:javascriptreact", 47 | "onLanguage:typescript" 48 | ], 49 | "main": "./dist/extension.js", 50 | "contributes": { 51 | "commands": [ 52 | { 53 | "command": "extension.convertCSSinJS", 54 | "title": "Convert CSS-in-JS" 55 | } 56 | ], 57 | "configurationDefaults": { 58 | "[javascript]": { 59 | "editor.quickSuggestions": { 60 | "other": true, 61 | "comments": true, 62 | "strings": true 63 | } 64 | } 65 | }, 66 | "keybindings": [ 67 | { 68 | "command": "extension.convertCSSinJS", 69 | "key": "ctrl+shift+j", 70 | "mac": "cmd+shift+j", 71 | "when": "editorTextFocus" 72 | } 73 | ] 74 | }, 75 | "capabilities": { 76 | "completionProvider": { 77 | "resolveProvider": "true", 78 | "triggerCharacters": [ 79 | "." 80 | ] 81 | } 82 | }, 83 | "devDependencies": { 84 | "@types/node": "^6.0.40", 85 | "babel-cli": "^6.24.1", 86 | "babel-core": "^6.25.0", 87 | "babel-loader": "^7.1.1", 88 | "babel-preset-env": "^1.6.0", 89 | "babel-preset-es2015": "^6.24.1", 90 | "prettier": "^1.5.2", 91 | "prettier-standard": "^6.0.0", 92 | "standard": "^10.0.2", 93 | "vscode": "^1.0.0" 94 | }, 95 | "dependencies": { 96 | "css-in-js-helpers": "^1.0.1" 97 | }, 98 | "icon": "icon.png", 99 | "galleryBanner": { 100 | "color": "#2b3e50", 101 | "theme": "dark" 102 | }, 103 | "standard": { 104 | "ignore": [ 105 | "dist/" 106 | ] 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /packages/vscode-css-in-js/src/autocomplete.js: -------------------------------------------------------------------------------- 1 | import vscode from 'vscode' 2 | import { 3 | CSS_COMPLETIONS, 4 | RN_COMPLETIONS, 5 | firstCharsEqual, 6 | lineEndsWithComma, 7 | isPropertyValuePrefix, 8 | firstInlinePropertyNameWithColonPattern, 9 | inlinePropertyNameWithColonPattern, 10 | propertyNameWithColonPattern, 11 | propertyNamePrefixPattern, 12 | pseudoSelectorPrefixPattern, 13 | cssDocsURL, 14 | __guard__, 15 | isPropertyNamePrefix, 16 | toHyphen, 17 | getImportantPrefix 18 | } from 'css-in-js-helpers' 19 | 20 | module.exports = { 21 | properties: CSS_COMPLETIONS.properties, 22 | pseudoSelectors: CSS_COMPLETIONS.pseudoSelectors, 23 | rnProperties: RN_COMPLETIONS, // TODO: actually use this 24 | 25 | getPseudoSelectorPrefix (text) { 26 | return __guard__(text.match(pseudoSelectorPrefixPattern), x => x[0]) 27 | }, 28 | 29 | getPropertyNamePrefix (text) { 30 | return __guard__(propertyNamePrefixPattern.exec(text), x => x[0]) 31 | }, 32 | 33 | isCompletingPseudoSelector (text) { 34 | return this.getPseudoSelectorPrefix(text) 35 | }, 36 | 37 | isCompletingValue (text) { 38 | if ( 39 | text.length - text.replace(/:/g, '').length === 40 | text.length - text.replace(/,/g, '').length 41 | ) { 42 | return false 43 | } 44 | return ( 45 | inlinePropertyNameWithColonPattern.exec(text) || 46 | firstInlinePropertyNameWithColonPattern.exec(text) || 47 | propertyNameWithColonPattern.exec(text) 48 | ) 49 | }, 50 | 51 | isCompletingName (text) { 52 | const prefix = this.getPropertyNamePrefix(text) 53 | return isPropertyNamePrefix(prefix) 54 | }, 55 | 56 | getPseudoSelectorCompletions (text) { 57 | const completions = [] 58 | const prefix = this.getPseudoSelectorPrefix(text).replace("'", '') 59 | const colonsFromText = text.trim().match(/:?:/)[0] || '' 60 | 61 | if (!prefix) { 62 | return null 63 | } 64 | 65 | for (let pseudoSelector in this.pseudoSelectors) { 66 | const options = this.pseudoSelectors[pseudoSelector] 67 | if (firstCharsEqual(pseudoSelector, prefix)) { 68 | completions.push( 69 | this.buildPseudoSelectorCompletion( 70 | pseudoSelector, 71 | options, 72 | colonsFromText 73 | ) 74 | ) 75 | } 76 | } 77 | 78 | return completions 79 | }, 80 | 81 | getPropertyValueCompletions (text) { 82 | const prefix = this.getPropertyNamePrefix(text) 83 | const property = text.substr(0, text.lastIndexOf(':')).trim() 84 | const styles = this.properties 85 | const values = 86 | styles[property] != null ? styles[property].values : undefined 87 | 88 | if (values === null) { 89 | return null 90 | } 91 | 92 | const addComma = !lineEndsWithComma(text) 93 | const completions = [] 94 | let value 95 | 96 | if (isPropertyValuePrefix(prefix)) { 97 | for (value of Array.from(values)) { 98 | if (firstCharsEqual(value, prefix)) { 99 | completions.push( 100 | this.buildPropertyValueCompletion(property, value, addComma) 101 | ) 102 | } 103 | } 104 | } else { 105 | for (value of Array.from(values)) { 106 | completions.push( 107 | this.buildPropertyValueCompletion(property, value, addComma) 108 | ) 109 | } 110 | } 111 | 112 | if (getImportantPrefix(text)) { 113 | completions.push( 114 | this.vsCompletionItem( 115 | 'important', 116 | 'Forces this property to override any other declaration of the same property. Use with caution.', 117 | `${cssDocsURL}/Specificity#The_!important_exception` 118 | ) 119 | ) 120 | } 121 | 122 | return completions 123 | }, 124 | 125 | getPropertyNameCompletions (text) { 126 | const prefix = this.getPropertyNamePrefix(text) 127 | const completions = [] 128 | const styles = this.properties 129 | for (let property in styles) { 130 | const options = styles[property] 131 | if (!prefix || firstCharsEqual(property, prefix)) { 132 | completions.push(this.buildPropertyNameCompletion(property, options)) 133 | } 134 | } 135 | return completions 136 | }, 137 | 138 | buildPseudoSelectorCompletion ( 139 | pseudoSelector, 140 | { description }, 141 | colonsFromText 142 | ) { 143 | return this.vsCompletionItem( 144 | pseudoSelector, 145 | description, 146 | `${cssDocsURL}/${pseudoSelector}`, 147 | pseudoSelector.replace(colonsFromText, '') 148 | ) 149 | }, 150 | 151 | buildPropertyNameCompletion (propertyName, { description }) { 152 | return this.vsCompletionItem( 153 | propertyName, 154 | description, 155 | `${cssDocsURL}/${toHyphen(propertyName)}`, 156 | `${propertyName}: ` 157 | ) 158 | }, 159 | 160 | buildPropertyValueCompletion (propertyName, value, addComma) { 161 | const text = `'${value}'${addComma ? ',' : ''}` 162 | const detail = `${value} value for the ${propertyName} property` 163 | return this.vsCompletionItem( 164 | value, 165 | detail, 166 | `${cssDocsURL}/${toHyphen(propertyName)}#Values`, 167 | text, 168 | 'Value' 169 | ) 170 | }, 171 | 172 | vsCompletionItem (text, detail, documentation = '', insertedText = false, itemKind = 'Property') { 173 | const item = new vscode.CompletionItem( 174 | text, 175 | vscode.CompletionItemKind[itemKind] 176 | ) 177 | item.detail = detail 178 | item.documentation = documentation 179 | item.insertText = insertedText 180 | return item 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /packages/vscode-css-in-js/src/extension.js: -------------------------------------------------------------------------------- 1 | import vscode from 'vscode' 2 | import convert from 'css-in-js-helpers' 3 | import autocomplete from './autocomplete' 4 | 5 | function positionFactory (positionObj) { 6 | return new vscode.Position(positionObj._line, positionObj._character) 7 | } 8 | 9 | function rangeFactory (selection, length) { 10 | if (length === 0) { 11 | selection.start._character = 0 12 | selection.end._character = vscode.window.activeTextEditor.document.lineAt( 13 | selection.start.line 14 | ).text.length 15 | } 16 | 17 | return new vscode.Range( 18 | positionFactory(selection.start), 19 | positionFactory(selection.end) 20 | ) 21 | } 22 | 23 | function activate (context) { 24 | const convertCommand = vscode.commands.registerCommand( 25 | 'extension.convertCSSinJS', 26 | () => { 27 | const editor = vscode.window.activeTextEditor 28 | 29 | // return if there's no editor or it's not a javascript file 30 | if ( 31 | !editor || 32 | !/javascript|typescript/.test(editor.document.languageId) 33 | ) { 34 | return 35 | } 36 | 37 | const selection = editor.selection 38 | const lineText = editor.document.lineAt(selection.start.line).text 39 | const selectedText = editor.document.getText(selection) 40 | const convertableText = selectedText || lineText 41 | const range = rangeFactory(selection, selectedText.length) 42 | 43 | editor.edit(builder => builder.replace(range, convert(convertableText))) 44 | } 45 | ) 46 | const codeCompletion = vscode.languages.registerCompletionItemProvider( 47 | 'javascript', 48 | { 49 | provideCompletionItems (document, position, token) { 50 | const start = new vscode.Position(position.line, 0) 51 | const range = new vscode.Range(start, position) 52 | const text = document.getText(range) 53 | 54 | if (autocomplete.isCompletingPseudoSelector(text)) { 55 | return autocomplete.getPseudoSelectorCompletions(text) 56 | } 57 | 58 | if (autocomplete.isCompletingValue(text)) { 59 | return autocomplete.getPropertyValueCompletions(text) 60 | } 61 | 62 | if (autocomplete.isCompletingName(text)) { 63 | return autocomplete.getPropertyNameCompletions(text) 64 | } 65 | }, 66 | resolveCompletionItem (item, token) { 67 | return item 68 | } 69 | } 70 | ) 71 | 72 | context.subscriptions.push(convertCommand) 73 | context.subscriptions.push(codeCompletion) 74 | } 75 | 76 | module.exports = { activate } 77 | --------------------------------------------------------------------------------