├── .babelrc ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── examples ├── app.js ├── bundle.js ├── external.css ├── index.html └── index.js ├── index.js ├── macro ├── __tests__ │ ├── __fixtures__ │ │ ├── empty │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports by array multi of selectors │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports by array of selectors │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports by object multi-key of selectors │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports by object of selectors │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports by regex global │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports by regex │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports by string selector │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports from node_modules stylesheet by string selector │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports multiple by string selector │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports react by array multi of selectors │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports react by array of selectors │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports react by object multi-key of selectors │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports react by object of selectors │ │ │ ├── code.js │ │ │ └── output.js │ │ ├── imports react by string selector │ │ │ ├── code.js │ │ │ └── output.js │ │ └── imports react multiple by string selector │ │ │ ├── code.js │ │ │ └── output.js │ ├── index.test.js │ └── sample.css └── index.js ├── package-lock.json ├── package.json ├── package.npm.json ├── scripts ├── dev.sh └── prepublish.sh └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["macros"], 3 | "presets": ["react"] 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .tern-port 2 | node_modules 3 | tags 4 | tags.lock 5 | tags.temp 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .babelrc 2 | .tern-port 3 | node_modules 4 | package.dev.json 5 | scripts 6 | tags 7 | tags.lock 8 | tags.temp 9 | webpack.config.js 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | ### Added 10 | 11 | ### Changed 12 | 13 | ### Fixed 14 | 15 | 16 | ## [0.3.0] - 2018-12-21 17 | 18 | ### Added 19 | 20 | - Return declarations from selectors that match regex -- see tests for 21 | [regex](https://github.com/glortho/styled-import/tree/development/macro/__tests__/__fixtures__/imports%20by%20regex) and [global 22 | regex](https://github.com/glortho/styled-import/tree/development/macro/__tests__/__fixtures__/imports%20by%20regex%20global) matching 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 junk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Styled Import 3 | > Extreme lightweight CSS parser for stealing rules from stylesheets (without adding the stylesheet to your bundle), to compose into [Styled Components](https://www.styled-components.com/) or anywhere else you might be doing CSS in JS. 4 | 5 | [![npm package](https://badge.fury.io/js/styled-import.svg)](https://badge.fury.io/js/styled-import) 6 | [![Babel Macro](https://img.shields.io/badge/babel--macro-%F0%9F%8E%A3-f5da55.svg?style=flat-square)](https://github.com/kentcdodds/babel-plugin-macros) 7 | [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/glortho/styled-import/issues) 8 | 9 | ## Motivation 10 | 11 | Working with global or 3rd party CSS creates constant challenges when implementing other CSS solutions. styled-import is meant to ease some of the pain by letting you steal styles from those stylesheets without needing to link or bundle or otherwise include the stylesheets themselves. 12 | 13 | Note that this library currently operates as a Babel macro, replacing all 14 | references to styled-import calls at compile-time with the actual style declarations from the 15 | referenced stylesheets. 16 | 17 | ## Installation 18 | 19 | ``` 20 | $ npm install -D styled-import 21 | ``` 22 | 23 | ## Dependencies 24 | 25 | Styled Import currently runs only as a Babel macro, so be sure you have 26 | configured Babel to use [babel-plugin-macros](https://www.npmjs.com/package/babel-plugin-macros). 27 | 28 | Here is one example of how to do that: 29 | 30 | _.babelrc_ 31 | 32 | ```javascript 33 | { 34 | "plugins": ["macros"] 35 | } 36 | ``` 37 | 38 | NOTE: Macros are included in create-react-app 2 by default. 39 | 40 | ## Use 41 | 42 | _./stylesheets/global.css_ 43 | 44 | ```css 45 | .button { 46 | color: blue; 47 | } 48 | ``` 49 | 50 | _./component.js_ 51 | 52 | ```javascript 53 | const styledImport = require('styled-import/macro') 54 | 55 | const btnStyle = styledImport('./stylesheets/global.css', '.button') 56 | 57 | console.log(btnStyle) // 'color: blue;' 58 | ``` 59 | 60 | ### Use with Styled Components 61 | 62 | ```javascript 63 | const styled = require('styled-components') 64 | const styledImport = require('styled-import/macro') 65 | 66 | const btnStyle = styledImport('./stylesheets/global.css', '.button') 67 | 68 | const Button = styled.button` 69 | padding: 10px; 70 | ${btnStyle} 71 | ` 72 | ``` 73 | 74 | String composition works like inheritance/cascade: 75 | 76 | ```javascript 77 | const btnBlue = styledImport('./stylesheets/global.css', '.button-blue') 78 | 79 | const Button = styled.button` 80 | color: green; 81 | padding: 10px; 82 | ${btnBlue} 83 | ` 84 | 85 | // color: green is overridden by color: blue in btnBlue 86 | ``` 87 | 88 | ### Use with React or other CSS-in-JS 89 | 90 | ```javascript 91 | const btnStyle = styledImport.react('./stylesheets/global.css', '.button') 92 | 93 | // btnStyle is now an object {'color': 'blue'} with camelCased properties, instead of a CSS string 94 | ``` 95 | 96 | ### Import from node_modules stylesheet 97 | 98 | ```javascript 99 | const btnStyle = styledImport('@org/stylesheets/global.css', '.button') 100 | ``` 101 | 102 | ### Import multiple styles 103 | 104 | 105 | ```javascript 106 | const [btnStyle, headerStyle] = styledImport('@org/styles/global.css', ['.button', '.header']) 107 | 108 | const {button, header} = styledImport('@org/styles/global.css', {button: '.button', header: '.header'}) 109 | ``` 110 | 111 | ### Import nested styles 112 | 113 | ```javascript 114 | const cardBtnStyle = styledImport('./stylesheets/global.css', '.card .button') 115 | ``` 116 | 117 | ### Search selectors with regular expressions 118 | 119 | ```javascript 120 | const cardBtnStyle = styledImport('./stylesheets/global.css', /\.button/gi) 121 | 122 | // returns an array of declarations from selectors that matched the regex (omit 123 | g flag to return just the first match) 124 | ``` 125 | 126 | ## Test 127 | 128 | Make sure you're on the development branch and then: 129 | 130 | ``` 131 | $ npm test 132 | ``` 133 | 134 | NOTE: Tests will only run in a git cloned repo. They are disabled in the 135 | published npm module. 136 | 137 | ## Restrictions 138 | 139 | - This currently only works with static values. Dynamic arguments can/will 140 | break it. Some dynamic support is coming soon. 141 | - Better error handling coming soon! 142 | - Selectors passed as arguments must match stylesheet selectors exactly. Partial matches/regex matches coming soon. 143 | - There is no de-duplication or other optimizations at this time. Currently styled-import just copies out the rules from the classes. It does not import the whole stylesheet into your bundle. Optimizations coming soon. 144 | - See the warning at top -- this is experimental and untested in many 145 | environments! Production-ready version...you guessed it...is coming soon. 146 | 147 | -------------------------------------------------------------------------------- /examples/app.js: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | const styled = require('styled-components/macro'); 3 | const styleImport = require('../macro'); 4 | 5 | const sectionRules = styleImport('./external.css', (selector, declarations, idx) => { 6 | return /foo/.test(selector) 7 | }); 8 | console.log(sectionRules); 9 | 10 | const Title = styled.div` 11 | color: blue; 12 | ${sectionRules.title} 13 | `; 14 | 15 | module.exports = () =>
fooFoo
16 | -------------------------------------------------------------------------------- /examples/external.css: -------------------------------------------------------------------------------- 1 | .foo .section { 2 | color: red; 3 | border: 1pt solid green; 4 | } 5 | 6 | .bar { 7 | color: purple; 8 | } 9 | 10 | .baz { 11 | color: black 12 | } 13 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Index 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/index.js: -------------------------------------------------------------------------------- 1 | const ReactDOM = require('react-dom') 2 | const app = require('./app'); 3 | 4 | ReactDOM.render(app(), document.getElementById('root')) 5 | 6 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./macro') 2 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/empty/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/empty/output.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glortho/styled-import/cf33f478cd507e3b2124bd7b6fbbb8824717c336/macro/__tests__/__fixtures__/empty/output.js -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by array multi of selectors/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport('../../sample.css', ['.foo .section', '.baz']) 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by array multi of selectors/output.js: -------------------------------------------------------------------------------- 1 | const foo = ['color: red;\nborder: 1pt solid green;', 'color: black;']; 2 | 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by array of selectors/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport('../../sample.css', ['.foo .section']) 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by array of selectors/output.js: -------------------------------------------------------------------------------- 1 | const foo = ['color: red;\nborder: 1pt solid green;']; 2 | 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by object multi-key of selectors/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport('../../sample.css', {section: '.foo .section', bar: '.bar'}) 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by object multi-key of selectors/output.js: -------------------------------------------------------------------------------- 1 | const foo = { 2 | 'section': 'color: red;\nborder: 1pt solid green;', 3 | 'bar': 'color: purple;' 4 | }; 5 | 6 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by object of selectors/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport('../../sample.css', {section: '.foo .section'}) 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by object of selectors/output.js: -------------------------------------------------------------------------------- 1 | const foo = { 2 | 'section': 'color: red;\nborder: 1pt solid green;' 3 | }; 4 | 5 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by regex global/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport('../../sample.css', /fo/g) 3 | 4 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by regex global/output.js: -------------------------------------------------------------------------------- 1 | const foo = ['color: red;\nborder: 1pt solid green;', 'text-align: left;']; 2 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by regex/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport('../../sample.css', /foo/) 3 | 4 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by regex/output.js: -------------------------------------------------------------------------------- 1 | const foo = 'color: red;\nborder: 1pt solid green;'; 2 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by string selector/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport('../../sample.css', '.bar') 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports by string selector/output.js: -------------------------------------------------------------------------------- 1 | const foo = 'color: purple;'; 2 | 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports from node_modules stylesheet by string selector/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport('_styled_tester/sample.css', '.bar') 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports from node_modules stylesheet by string selector/output.js: -------------------------------------------------------------------------------- 1 | const foo = 'color: purple;'; 2 | 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports multiple by string selector/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport('../../sample.css', '.foo .section') 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports multiple by string selector/output.js: -------------------------------------------------------------------------------- 1 | const foo = 'color: red;\nborder: 1pt solid green;'; 2 | 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports react by array multi of selectors/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport.react('../../sample.css', ['.foo .section', '.for-react']) 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports react by array multi of selectors/output.js: -------------------------------------------------------------------------------- 1 | const foo = [{ 2 | 'color': 'red', 3 | 'border': '1pt solid green' 4 | }, { 5 | 'textAlign': 'left' 6 | }]; 7 | 8 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports react by array of selectors/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport.react('../../sample.css', ['.foo .section']) 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports react by array of selectors/output.js: -------------------------------------------------------------------------------- 1 | const foo = [{ 2 | 'color': 'red', 3 | 'border': '1pt solid green' 4 | }]; 5 | 6 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports react by object multi-key of selectors/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport.react('../../sample.css', {section: '.foo .section', bar: '.bar'}) 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports react by object multi-key of selectors/output.js: -------------------------------------------------------------------------------- 1 | const foo = { 2 | 'section': { 3 | 'color': 'red', 4 | 'border': '1pt solid green' 5 | }, 6 | 'bar': { 7 | 'color': 'purple' 8 | } 9 | }; 10 | 11 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports react by object of selectors/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport.react('../../sample.css', {section: '.foo .section'}) 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports react by object of selectors/output.js: -------------------------------------------------------------------------------- 1 | const foo = { 2 | 'section': { 3 | 'color': 'red', 4 | 'border': '1pt solid green' 5 | } 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports react by string selector/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport.react('../../sample.css', '.bar') 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports react by string selector/output.js: -------------------------------------------------------------------------------- 1 | const foo = { 2 | 'color': 'purple' 3 | }; 4 | 5 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports react multiple by string selector/code.js: -------------------------------------------------------------------------------- 1 | const styledImport = require('../../../../macro') 2 | const foo = styledImport.react('../../sample.css', '.foo .section') 3 | -------------------------------------------------------------------------------- /macro/__tests__/__fixtures__/imports react multiple by string selector/output.js: -------------------------------------------------------------------------------- 1 | const foo = { 2 | 'color': 'red', 3 | 'border': '1pt solid green' 4 | }; 5 | 6 | -------------------------------------------------------------------------------- /macro/__tests__/index.test.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const pluginTester = require('babel-plugin-tester') 3 | const plugin = require('babel-plugin-macros') 4 | 5 | pluginTester({ 6 | plugin, 7 | fixtures: path.join(__dirname, '__fixtures__') 8 | }) 9 | -------------------------------------------------------------------------------- /macro/__tests__/sample.css: -------------------------------------------------------------------------------- 1 | .foo .section { 2 | color: red; 3 | border: 1pt solid green; 4 | } 5 | 6 | .bar { 7 | color: purple; 8 | } 9 | 10 | .baz { 11 | color: black; 12 | } 13 | 14 | .for-react { 15 | text-align: left; 16 | } 17 | -------------------------------------------------------------------------------- /macro/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const css = require('css'); 4 | 5 | const {createMacro} = require('babel-plugin-macros') 6 | 7 | module.exports = createMacro(styleImportMacro); 8 | 9 | function styleImportMacro({references, state, babel}) { 10 | references.default.forEach(referencePath => { 11 | 12 | const { node } = referencePath.parentPath; 13 | 14 | // if there is a property on the node it means the user is using 15 | // the styledImport.(...) option, for example: 16 | // 17 | // styledImport.react(...) 18 | // 19 | const format = node.property 20 | ? node.property.name 21 | : 'string' 22 | 23 | // TODO: what is the proper way to get arguments when using the property 24 | // format? 25 | const [ cssPathArg, selectorArg ] = node.property 26 | ? referencePath.parentPath.parent.arguments 27 | : referencePath.parentPath.get('arguments').map( arg => arg.node ) 28 | 29 | const cssRules = parseAst(state.file.opts.filename, cssPathArg.value).stylesheet.rules; 30 | 31 | const declarationMethods = getDeclarationMethods(cssRules, babel, { format }); 32 | 33 | const declarations = ( 34 | selectorArg.value ? 35 | declarationMethods.byString(selectorArg.value) : 36 | selectorArg.elements ? 37 | declarationMethods.byArray(selectorArg.elements) : 38 | selectorArg.pattern ? 39 | declarationMethods.byRegex(selectorArg) : 40 | declarationMethods.byObject(selectorArg.properties) 41 | ) 42 | 43 | const fnCallPath = node.property 44 | ? referencePath.parentPath.parentPath 45 | : referencePath.parentPath 46 | fnCallPath.replaceWith(declarations); 47 | }); 48 | } 49 | 50 | const getDeclarationMethods = (cssRules, babel, options = {}) => { 51 | 52 | const stringifyDeclarations = declarations => 53 | declarations.map(item => `${item.property}: ${item.value};`).join('\n') 54 | 55 | const objectifyDeclarations = declarations => 56 | declarations.map(item => babel.types.objectProperty( 57 | babel.types.stringLiteral(toCamelCase(item.property)), 58 | babel.types.stringLiteral(item.value) 59 | )) 60 | 61 | const formatDeclarations = rule => options.format === 'string' 62 | ? babel.types.stringLiteral(stringifyDeclarations(rule.declarations)) 63 | : babel.types.ObjectExpression(objectifyDeclarations(rule.declarations)) 64 | 65 | const byArray = elements => { 66 | const declarations = elements.map( node => { 67 | const rule = cssRules.find( rule => rule.selectors.some( selector => node.value === selector) ) 68 | return rule 69 | ? formatDeclarations(rule) 70 | : babel.types.nullLiteral() 71 | }) 72 | return babel.types.ArrayExpression(declarations) 73 | } 74 | 75 | const byObject = properties => { 76 | const declarations = properties.map(item => { 77 | const key = item.key.name; 78 | const value = item.value.value; 79 | const rule = cssRules 80 | .find( rule => rule.selectors.some( selector => selector === value )) 81 | return babel.types.objectProperty( 82 | babel.types.stringLiteral(key), ( 83 | rule 84 | ? formatDeclarations(rule) 85 | : babel.types.nullLiteral() 86 | ) 87 | ) 88 | }); 89 | return babel.types.ObjectExpression(declarations) 90 | } 91 | 92 | const byString = value => { 93 | const rule = cssRules.find( rule => rule.selectors.some( selector => selector === value )) 94 | return rule 95 | ? formatDeclarations(rule) 96 | : babel.types.nullLiteral() 97 | } 98 | 99 | const byRegex = ({pattern, flags}) => { 100 | const regex = new RegExp(pattern, flags) 101 | if (!~flags.indexOf('g')) { 102 | const rule = cssRules.find( rule => rule.selectors.some( selector => regex.test(selector))) 103 | return rule 104 | ? formatDeclarations(rule) 105 | : babel.types.nullLiteral() 106 | } else { 107 | const declarations = cssRules 108 | .filter( rule => rule.selectors.some( selector => regex.test(selector))) 109 | .map( formatDeclarations ) 110 | return babel.types.ArrayExpression(declarations) 111 | } 112 | } 113 | 114 | return { byRegex, byString, byArray, byObject } 115 | } 116 | 117 | const parseAst = (modulePath, cssPath) => { 118 | 119 | const pathHint = modulePath.charAt(0) 120 | const pathReference = pathHint === '/' 121 | ? path.dirname(modulePath) 122 | : path.join(process.cwd(), path.dirname(modulePath)) 123 | 124 | const cssPathHint = cssPath.charAt(0) 125 | const cssPathReference = ( 126 | cssPathHint === '/' ? 127 | cssPath : 128 | cssPathHint === '.' ? 129 | path.join(pathReference, cssPath) : 130 | require.resolve(cssPath) 131 | ) 132 | const cssString = fs.readFileSync(cssPathReference, 'utf-8') 133 | return css.parse(cssString, {source: cssPathReference}) 134 | } 135 | 136 | const toCamelCase = str => str.replace(/(-.)/g, chars => chars[1].toUpperCase()) 137 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "styled-plus", 3 | "version": "0.2.1", 4 | "description": "Extreme lightweight CSS parser for stealing rules from stylesheets (without adding the stylesheet to your bundle), to compose into Styled Components or anywhere else you might be doing CSS in JS.", 5 | "author": "jed@dataverse.me", 6 | "repository": "https://github.com/glortho/styled-import", 7 | "license": "MIT", 8 | "main": "index.js", 9 | "scripts": { 10 | "copy-test-files": "mkdir node_modules/_styled_tester > /dev/null 2>&1; cp macro/__tests__/sample.css node_modules/_styled_tester > /dev/null 2>&1", 11 | "dev": "./scripts/dev.sh", 12 | "prep": "./scripts/prepublish.sh", 13 | "test": "npm run copy-test-files; jest" 14 | }, 15 | "jest": { 16 | "testMatch": [ 17 | "**/__tests__/**/*.test.js" 18 | ] 19 | }, 20 | "dependencies": {}, 21 | "devDependencies": { 22 | "babel-cli": "^6.26.0", 23 | "babel-core": "^6.26.3", 24 | "babel-loader": "^7.1.5", 25 | "babel-plugin-macros": "^2.4.3", 26 | "babel-plugin-tester": "^5.5.2", 27 | "babel-preset-env": "^1.7.0", 28 | "babel-preset-react": "^6.24.1", 29 | "css": "^2.2.4", 30 | "jest": "^23.6.0", 31 | "react": "^16.6.3", 32 | "react-dom": "^16.6.3", 33 | "styled-components": "^4.1.3", 34 | "webpack": "^4.27.1", 35 | "webpack-cli": "^3.1.2" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /package.npm.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "styled-import", 3 | "version": "0.2.5", 4 | "description": "Extreme lightweight CSS parser for stealing rules from stylesheets (without adding the stylesheet to your bundle), to compose into Styled Components or anywhere else you might be doing CSS in JS.", 5 | "keywords": [ 6 | "babel-plugin-macros" 7 | ], 8 | "main": "index.js", 9 | "author": "jed@dataverse.me", 10 | "repository": "https://github.com/glortho/styled-import", 11 | "license": "MIT", 12 | "scripts": { 13 | "dev": "./scripts/dev.sh" 14 | }, 15 | "devDependencies": { 16 | "babel-plugin-macros": "^2.4.3", 17 | "css": "^2.2.4" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /scripts/dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mv package{,.npm}.json 4 | mv package{.dev,}.json 5 | npm i 6 | -------------------------------------------------------------------------------- /scripts/prepublish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | npm test 4 | mv package{,.dev}.json 5 | mv package{.npm,}.json 6 | npm i 7 | 8 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | mode: 'development', 5 | entry: path.join(__dirname, 'examples', 'index.js'), 6 | output: { 7 | path: path.join(__dirname, 'examples'), 8 | filename: 'bundle.js' 9 | }, 10 | module: { 11 | rules: [ 12 | { 13 | test: /\.m?js$/, 14 | exclude: /(node_modules|bower_components)/, 15 | use: { 16 | loader: 'babel-loader', 17 | options: { 18 | presets: ['babel-preset-env'] 19 | } 20 | } 21 | } 22 | ] 23 | } 24 | }; 25 | --------------------------------------------------------------------------------