├── .changeset ├── README.md └── config.json ├── .github ├── dependabot.yml └── workflows │ ├── build.yml │ └── version.yml ├── .gitignore ├── .nvmrc ├── .yarn └── releases │ └── yarn-3.6.0.cjs ├── .yarnrc.yml ├── CHANGELOG.md ├── README.md ├── example ├── .gitattributes ├── .gitignore ├── README.md ├── package.json ├── src │ ├── AppClient.tsx │ ├── app │ │ ├── App.tsx │ │ └── Component1.tsx │ └── server │ │ ├── AppServer.tsx │ │ └── index.tsx ├── transformer.js ├── tsconfig.json ├── tsconfig.server.json ├── webpack │ ├── config.server.js │ ├── config.ts │ └── transformer.js └── yarn.lock ├── jest.config.json ├── package.json ├── src ├── __tests__ │ ├── baselines.test.ts │ ├── baselines │ │ ├── base │ │ │ ├── issue33.ts.baseline │ │ │ ├── sample1.ts.baseline │ │ │ ├── sample2.ts.baseline │ │ │ ├── sample3.tsx.baseline │ │ │ └── style-objects.ts.baseline │ │ ├── componentIdPrefix │ │ │ ├── issue33.ts.baseline │ │ │ ├── multiple-components.tsx.baseline │ │ │ ├── sample1.ts.baseline │ │ │ ├── sample2.ts.baseline │ │ │ ├── sample3.tsx.baseline │ │ │ └── style-objects.ts.baseline │ │ ├── minification-only │ │ │ ├── issue142.tsx.baseline │ │ │ ├── issue233.ts.baseline │ │ │ ├── issue36-extended.ts.baseline │ │ │ ├── issue36.tsx.baseline │ │ │ ├── issue40.ts.baseline │ │ │ ├── issue44.tsx.baseline │ │ │ ├── minify-css-in-helpers.ts.baseline │ │ │ ├── minify-css-to-use-with-transpilation.ts.baseline │ │ │ ├── minify-css-to-use-without-transpilation.ts.baseline │ │ │ ├── minify-single-line-comments-with-interpolations.ts.baseline │ │ │ ├── simple.ts.baseline │ │ │ └── simple2.ts.baseline │ │ ├── minification │ │ │ ├── issue142.tsx.baseline │ │ │ ├── issue233.ts.baseline │ │ │ ├── issue36-extended.ts.baseline │ │ │ ├── issue36.tsx.baseline │ │ │ ├── issue40.ts.baseline │ │ │ ├── issue44.tsx.baseline │ │ │ ├── minify-css-in-helpers.ts.baseline │ │ │ ├── minify-css-to-use-with-transpilation.ts.baseline │ │ │ ├── minify-css-to-use-without-transpilation.ts.baseline │ │ │ ├── minify-single-line-comments-with-interpolations.ts.baseline │ │ │ ├── simple.ts.baseline │ │ │ └── simple2.ts.baseline │ │ └── ssr │ │ │ ├── issue33.ts.baseline │ │ │ ├── multiple-components.tsx.baseline │ │ │ ├── sample1.ts.baseline │ │ │ ├── sample2.ts.baseline │ │ │ ├── sample3.tsx.baseline │ │ │ └── style-objects.ts.baseline │ ├── componentIdPrefix-baselines.test.ts │ ├── expectTransform.ts │ ├── fixtures │ │ ├── base │ │ │ ├── issue33.ts │ │ │ ├── sample1.ts │ │ │ ├── sample2.ts │ │ │ ├── sample3.tsx │ │ │ └── style-objects.ts │ │ ├── componentIdPrefix │ │ │ └── multiple-components.tsx │ │ ├── minification │ │ │ ├── issue142.tsx │ │ │ ├── issue233.ts │ │ │ ├── issue36-extended.ts │ │ │ ├── issue36.tsx │ │ │ ├── issue40.ts │ │ │ ├── issue44.tsx │ │ │ ├── minify-css-in-helpers.ts │ │ │ ├── minify-css-to-use-with-transpilation.ts │ │ │ ├── minify-css-to-use-without-transpilation.ts │ │ │ ├── minify-single-line-comments-with-interpolations.ts │ │ │ ├── simple.ts │ │ │ └── simple2.ts │ │ └── ssr │ │ │ └── multiple-components.tsx │ ├── minification-only.test.ts │ ├── minification.test.ts │ ├── minify.test.ts │ ├── ssr-baselines.test.ts │ └── themed-styled.ts ├── createTransformer.ts ├── hash.ts ├── index.ts ├── minify.ts ├── models │ └── Options.ts ├── runner.ts └── ts-is-kind.ts ├── tsconfig.json └── yarn.lock /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "master", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "13:00" 8 | open-pull-requests-limit: 10 9 | ignore: 10 | - dependency-name: "@types/node" 11 | versions: 12 | - 14.14.22 13 | - 14.14.25 14 | - 14.14.27 15 | - 14.14.28 16 | - 14.14.30 17 | - 14.14.31 18 | - 14.14.32 19 | - 14.14.33 20 | - 14.14.34 21 | - 14.14.35 22 | - 14.14.36 23 | - 14.14.37 24 | - 14.14.39 25 | - 14.14.41 26 | - 15.0.0 27 | - dependency-name: "@types/react" 28 | versions: 29 | - 17.0.0 30 | - 17.0.1 31 | - 17.0.2 32 | - 17.0.3 33 | - dependency-name: "@types/jest" 34 | versions: 35 | - 26.0.20 36 | - 26.0.21 37 | - 26.0.22 38 | - dependency-name: typescript 39 | versions: 40 | - 4.1.3 41 | - 4.1.4 42 | - 4.1.5 43 | - 4.2.2 44 | - 4.2.3 45 | - dependency-name: y18n 46 | versions: 47 | - 4.0.1 48 | - 4.0.2 49 | - dependency-name: "@types/styled-components" 50 | versions: 51 | - 5.1.7 52 | - 5.1.8 53 | - dependency-name: lodash 54 | versions: 55 | - 4.17.20 56 | - dependency-name: handlebars 57 | versions: 58 | - 4.7.6 59 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: 3 | pull_request: 4 | push: 5 | branches: [main] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: hmarr/debug-action@v2 12 | - uses: actions/checkout@v3 13 | - uses: actions/setup-node@v3 14 | with: 15 | cache: yarn 16 | node-version-file: '.nvmrc' 17 | - name: Install packages 18 | run: yarn --immutable 19 | - name: Build library 20 | run: yarn build 21 | unit: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: hmarr/debug-action@v2 25 | - uses: actions/checkout@v3 26 | - uses: actions/setup-node@v3 27 | with: 28 | cache: yarn 29 | node-version-file: '.nvmrc' 30 | - name: Install packages 31 | run: yarn --immutable 32 | - name: Jest 33 | run: yarn test 34 | -------------------------------------------------------------------------------- /.github/workflows/version.yml: -------------------------------------------------------------------------------- 1 | name: Version or Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | concurrency: ${{ github.workflow }}-${{ github.ref }} 9 | 10 | jobs: 11 | changesets: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: hmarr/debug-action@v2 15 | - uses: actions/checkout@v3 16 | - uses: actions/setup-node@v3 17 | with: 18 | cache: yarn 19 | node-version-file: '.nvmrc' 20 | - name: Install packages 21 | run: yarn --immutable 22 | - name: Build library 23 | run: yarn build 24 | - name: Create Release Pull Request or Publish 25 | uses: changesets/action@v1 26 | with: 27 | version: yarn changeset version 28 | publish: yarn changeset publish 29 | commit: Version package 30 | title: Version package 31 | env: 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | .vscode/ 4 | 5 | .yarn/* 6 | !.yarn/releases 7 | !.yarn/plugins 8 | !.yarn/sdks 9 | !.yarn/versions 10 | !.yarn/patches 11 | .pnp.* 12 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v14 2 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | yarnPath: .yarn/releases/yarn-3.6.0.cjs 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [3.0.0] 4 | 5 | - **breaking change** upgrade to TypeScript 4.8+/5.0+ in #713 6 | - Restore `componentIdPrefix` fallback to getIdFromNode by @roikoren755 in #518 7 | - GitHub Actions setup by @probablyup in #712 8 | - Update README.md by @RockinRonE in #473 9 | 10 | ## [2.0.0] 11 | 12 | - **breaking change** upgrade to TypeScript 4+ and make use of Factory API (#379) 13 | - bugfix in minification of `calc()` (fix #233 in #436) 14 | 15 | ## [1.6.0] 16 | 17 | - namespace prefix to help multiple instances of the library not clash (fix #381 in #395) 18 | 19 | ## [1.5.0] 20 | 21 | - transform anonymous default exports (fix #371 in #367) 22 | - remove deprecated `.extend` transformation pattern (fix #48 in #370) 23 | 24 | ## [1.4.4] 25 | 26 | - bugfix in minification of tabs (fix #142 in #152) 27 | 28 | ## [1.4.3] 29 | 30 | - bugfix in minification (fix #44 in #45) 31 | 32 | ## [1.4.2] 33 | 34 | - another important bugfix in minification (#40 by @Ky6uk, #41) 35 | 36 | ## [1.4.1] 37 | 38 | - important bugfix in minification (#36, #39) 39 | 40 | ## [1.4.0] 41 | 42 | - add experimental support of minification (#14, #35) 43 | - skip emitting empty `withConfig` (#37) 44 | 45 | ## [1.4.0-rc] 46 | 47 | - add experimental support of minification (#14, #35) 48 | 49 | ## [1.3.0] 50 | 51 | - improved detection of component names which fixes issues with jQuery and lodash (#33, #34) 52 | 53 | ## [1.2.0] 54 | 55 | - add support of [style objects](https://www.styled-components.com/docs/advanced#style-objects) (#30, #32) 56 | 57 | ## [1.1.0] 58 | 59 | - component id generation that helps with SSR (great contribution #21 by @fabyo82) 60 | - customizable identifiers of styled-components functions 61 | - display name generation can be turned off 62 | 63 | ## [1.1.0-rc] 64 | 65 | - component id generation that helps with SSR (great contribution #21 by @fabyo82) 66 | - customizable identifiers of `styled-components` functions 67 | - display name generation can be turned off 68 | 69 | ## [1.0.0] 70 | 71 | - The first official release! 72 | - updated `typescript` dependency to support TS 3.0+ (#17, fixed #15) 73 | - remove `ts-is-kind` dependency (#17, fixed #16) 74 | 75 | ## [0.0.7] 76 | 77 | - updated `typescript` dependency to support TS 3.0+ (#17, fixed #15) 78 | - remove `ts-is-kind` dependency (#17, fixed #16) 79 | 80 | [Unreleased]: https://github.com/igorbek/typescript-plugin-styled-components/compare/2.0.0...HEAD 81 | [2.0.0]: https://github.com/igorbek/typescript-plugin-styled-components/compare/1.6.0...2.0.0 82 | [1.6.0]: https://github.com/igorbek/typescript-plugin-styled-components/compare/1.5.0...1.6.0 83 | [1.5.0]: https://github.com/igorbek/typescript-plugin-styled-components/compare/1.4.4...1.5.0 84 | [1.4.4]: https://github.com/igorbek/typescript-plugin-styled-components/compare/1.4.3...1.4.4 85 | [1.4.3]: https://github.com/igorbek/typescript-plugin-styled-components/compare/1.4.2...1.4.3 86 | [1.4.2]: https://github.com/igorbek/typescript-plugin-styled-components/compare/1.4.1...1.4.2 87 | [1.4.1]: https://github.com/igorbek/typescript-plugin-styled-components/compare/1.4.0...1.4.1 88 | [1.4.0]: https://github.com/igorbek/typescript-plugin-styled-components/compare/1.3.0...1.4.0 89 | [1.4.0-rc]: https://github.com/igorbek/typescript-plugin-styled-components/compare/1.3.0...1.4.0-rc 90 | [1.3.0]: https://github.com/igorbek/typescript-plugin-styled-components/compare/1.2.0...1.3.0 91 | [1.2.0]: https://github.com/igorbek/typescript-plugin-styled-components/compare/1.1.0...1.2.0 92 | [1.1.0]: https://github.com/igorbek/typescript-plugin-styled-components/compare/v1.0.0...1.1.0 93 | [1.1.0-rc]: https://github.com/igorbek/typescript-plugin-styled-components/compare/v1.0.0...1.1.0-rc 94 | [1.0.0]: https://github.com/igorbek/typescript-plugin-styled-components/compare/v0.0.7...v1.0.0 95 | [0.0.7]: https://github.com/igorbek/typescript-plugin-styled-components/compare/v0.0.6...v0.0.7 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `typescript-plugin-styled-components` 2 | 3 | This is a TypeScript transformer that improves development experience of [`styled-components`](https://www.styled-components.com/). 4 | 5 | The main purpose is to provide compile-time information of creates styled components, such as names of these components, for the run-time, allowing to operate with proper names of such the components. 6 | 7 | The plugin was mostly inspired by great Babel's plugin [`babel-plugin-styled-components`](https://github.com/styled-components/babel-plugin-styled-components) and partially provides similar functionality for TypeScript users. 8 | 9 | If you like it, consider [![Buy me a coffee](https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png)](https://www.buymeacoffee.com/igorbek) 10 | 11 | Note: This transformer will be useful to you only when you are transpiling your TS code using actual TS compiler, like `tsc` `ts-loader` or `awesome-typescript-loader`. If your TS code is transpiled using [`babel-plugin-transform-typescript`](https://babeljs.io/docs/en/babel-plugin-transform-typescript), you should use [`babel-plugin-styled-components`](https://github.com/styled-components/babel-plugin-styled-components) instead. 12 | 13 | # Installation 14 | 15 | The following command adds the packages to the project as a development-time dependency: 16 | 17 |
yarn add typescript-plugin-styled-components --dev
18 | 19 | # Documentation 20 | 21 | - [Integration with `Webpack`](#Integration-with-Webpack) 22 | - [`awesome-typescript-loader`](#awesome-typescript-loader) 23 | - [`ts-loader`](#ts-loader) 24 | - [Forked process configuration](#Forked-process-configuration) 25 | - [Integration with `Rollup`](#Integration-with-Rollup) 26 | - [TypeScript compiler (CLI)](#TypeScript-compiler-CLI) 27 | - [`ttypescript` compiler](#ttypescript-compiler) 28 | - [API](#API) 29 | - [`createTransformer`](#createTransformer) 30 | - [`Options`](#Options) 31 | - [Notes](#Notes) 32 | 33 | # Integration with `Webpack` 34 | 35 | This section describes how to integrate the plugin into the build/bundling process driven by [**Webpack**](https://webpack.js.org/) and its TypeScript loaders. 36 | 37 | There are two popular TypeScript loaders that support specifying custom transformers: 38 | 39 | - [**awesome-typescript-loader**](https://github.com/s-panferov/awesome-typescript-loader), supports custom transformers since v3.1.3 40 | - [**ts-loader**](https://github.com/TypeStrong/ts-loader), supports custom transformers since v2.2.0 41 | 42 | Both loaders use the same setting `getCustomTransformers` which is an optional function that returns `{ before?: Transformer[], after?: Transformer[] }`. 43 | In order to inject the transformer into compilation, add it to `before` transformers array, like: `{ before: [styledComponentsTransformer] }`. 44 | 45 | ## `awesome-typescript-loader` 46 | 47 | In the `webpack.config.js` file in the section where **awesome-typescript-loader** is configured as a loader: 48 | 49 | ```js 50 | // 1. import default from the plugin module 51 | const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default; 52 | 53 | // 2. create a transformer; 54 | // the factory additionally accepts an options object which described below 55 | const styledComponentsTransformer = createStyledComponentsTransformer(); 56 | 57 | // 3. add getCustomTransformer method to the loader config 58 | var config = { 59 | ... 60 | module: { 61 | rules: [ 62 | { 63 | test: /\.tsx?$/, 64 | loader: 'awesome-typescript-loader', 65 | options: { 66 | ... // other loader's options 67 | getCustomTransformers: () => ({ before: [styledComponentsTransformer] }) 68 | } 69 | } 70 | ] 71 | } 72 | ... 73 | }; 74 | ``` 75 | 76 | Please note, that in the development mode, `awesome-typescript-loader` uses multiple separate processes to speed up compilation. In that mode the above configuration cannot work because functions, which `getCustomTransformers` is, are not transferrable between processes. 77 | To solve this please refer to [Forked process configuration](#forked-process-configuration) section. 78 | 79 | ## `ts-loader` 80 | 81 | In the `webpack.config.js` file in the section where **ts-loader** is configured as a loader: 82 | 83 | ```js 84 | // 1. import default from the plugin module 85 | const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default; 86 | 87 | // 2. create a transformer; 88 | // the factory additionally accepts an options object which described below 89 | const styledComponentsTransformer = createStyledComponentsTransformer(); 90 | 91 | // 3. add getCustomTransformer method to the loader config 92 | var config = { 93 | ... 94 | module: { 95 | rules: [ 96 | { 97 | test: /\.tsx?$/, 98 | loader: 'ts-loader', 99 | options: { 100 | ... // other loader's options 101 | getCustomTransformers: () => ({ before: [styledComponentsTransformer] }) 102 | } 103 | } 104 | ] 105 | } 106 | ... 107 | }; 108 | ``` 109 | 110 | Please note, when `awesome-typescript-loader` is used with `HappyPack` or `thread-loader`, they use multiple separate processes to speed up compilation. In that mode the above configuration cannot work because functions, which `getCustomTransformers` is, are not transferrable between processes. 111 | To solve this please refer to [Forked process configuration](#forked-process-configuration) section. 112 | 113 | ## Forked process configuration 114 | 115 | To configure the transformer for development mode in `awesome-typescript-loader` or `ts-loader` with `HappyPack` or `thread-loader`, you need to make `getCustomTransformers` a resolvable module name instead of the function. Since the configuration is very similar, here's an example: 116 | 117 | ### 1. Move `styledComponentsTransformer` into a separate file 118 | 119 | Let's assume it is in the same folder as your `webpack.config` and has name `webpack.ts-transformers.js`: 120 | ```js 121 | // 1. import default from the plugin module 122 | const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default; 123 | 124 | // 2. create a transformer; 125 | // the factory additionally accepts an options object which described below 126 | const styledComponentsTransformer = createStyledComponentsTransformer(); 127 | 128 | // 3. create getCustomTransformer function 129 | const getCustomTransformers = () => ({ before: [styledComponentsTransformer] }); 130 | 131 | // 4. export getCustomTransformers 132 | module.exports = getCustomTransformers; 133 | ``` 134 | 135 | ### 2. Change the loader's options to point to that file instead of explicit function 136 | 137 | ```diff 138 | -const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default; 139 | -const styledComponentsTransformer = createStyledComponentsTransformer(); 140 | 141 | options: { 142 | ... // other loader's options 143 | - getCustomTransformers: () => ({ before: [styledComponentsTransformer] }) 144 | + getCustomTransformers: path.join(__dirname, './webpack.ts-transformers.js') 145 | } 146 | ``` 147 | 148 | # Integration with `Rollup` 149 | 150 | This section describes how to integrate the plugin into the build/bundling process driven by [**Rollup**](https://rollupjs.org/guide/en/) and its TypeScript loader - [**rollup-plugin-typescript2**](https://github.com/Igorbek/typescript-plugin-styled-components). 151 | 152 | In the `rollup.config.js` file in the section where **rollup-plugin-typescript2** is configured as a loader: 153 | 154 | ```js 155 | // 1. import default from the plugin module 156 | const createStyledComponentsTransformer = require('typescript-plugin-styled-components').default; 157 | 158 | // 2. create a transformer; 159 | // the factory additionally accepts an options object which described below 160 | const styledComponentsTransformer = createStyledComponentsTransformer(); 161 | 162 | // 3. add getCustomTransformer method to the loader config 163 | var config = { 164 | ... 165 | plugins: [ 166 | rollupTypescript({ 167 | ... 168 | transformers: [ 169 | () => ({ 170 | before: [styledComponentsTransformer], 171 | }), 172 | ], 173 | }), 174 | ... 175 | ], 176 | ... 177 | }; 178 | ``` 179 | 180 | # TypeScript compiler (CLI) 181 | 182 | TypeScript command line compiler tool (`tsc`) does not support using of pluggable modules and transformers. 183 | For that reason there are other tools created that do support pluggable transformers. See [`ttypescript` compiler](#ttypescript-compiler) section. 184 | 185 | # `ttypescript` compiler 186 | 187 | The [`ttypescript` compiler](https://github.com/cevek/ttypescript) is a CLI tool that allows to use TypeScript compiler with pluggable transformers. 188 | To use the transformer with that tool you can configure it by updating `tsconfig.json` the following way: 189 | 190 | ```js 191 | { 192 | "compilerOptions": { 193 | "plugins": [ 194 | { 195 | "transform": "typescript-plugin-styled-components", 196 | "type": "config", 197 | 198 | // other typescript-plugin-styled-components options can be added here 199 | "minify": true, 200 | "ssr": true 201 | } 202 | ] 203 | } 204 | } 205 | ``` 206 | 207 | # API 208 | 209 | ## `createTransformer` 210 | 211 | ```ts 212 | function createTransformer(options?: Partial): TransformerFactory; 213 | ``` 214 | 215 | A factory that creates an instance of a TypeScript transformer (which is a factory itself). 216 | 217 | It allows to optionally pass options that allow to tweak transformer's behavior. See `Options` for details. 218 | 219 | ## `Options` 220 | 221 | ```ts 222 | interface Options { 223 | getDisplayName(filename: string, bindingName: string | undefined): string | undefined; 224 | identifiers: CustomStyledIdentifiers; 225 | ssr: boolean; 226 | displayName: boolean; 227 | minify: boolean; 228 | componentIdPrefix: string; 229 | } 230 | ``` 231 | 232 | ### `getDisplayName` 233 | 234 | This method is used to determine component display name from filename and its binding name. 235 | 236 | `filename` is the file name, relative to the project base directory, of the file where the styled component defined. 237 | 238 | `bindingName` is the name that is used in the source code to bind the component. It can be `null` if the component was not bound or assigned. 239 | 240 | Default strategy is to use `bindingName` if it's defined and use inference algorithm from `filename` otherwise. 241 | 242 | Sample: 243 | ```js 244 | function getStyledComponentDisplay(filename, bindingName) { 245 | return bindingName || makePascalCase(filename); 246 | } 247 | ``` 248 | 249 | ### `ssr` 250 | 251 | By adding a unique identifier to every styled component, this plugin avoids checksum mismatches 252 | due to different class generation on the client and on the server. 253 | 254 | This option allows to disable component id generation by setting it to `false`. 255 | 256 | Default value is `true` which means that component id is being injected. 257 | 258 | ### `displayName` 259 | 260 | This option enhances the attached CSS class name on each component with richer output 261 | to help identify your components in the DOM without React DevTools. 262 | 263 | It also adds allows you to see the component's `displayName` in React DevTools. 264 | 265 | To disable `displayName` generation set this option to `false` 266 | 267 | Default value is `true` which means that display name is being injected. 268 | 269 | ### `minify` 270 | 271 | The option allows to turn on minification of inline styles used in styled components. 272 | It is similar to [`babel-plugin-styled-components`](https://github.com/styled-components/babel-plugin-styled-components)'s same option. 273 | The minification is not exactly the same and may produce slightly different results. 274 | 275 | :warning: **Warning**: The minification is an experimental feature, please use with care. 276 | 277 | Default value is `false` which means the minification is not being performed. 278 | 279 | ### `componentIdPrefix` 280 | 281 | To avoid colisions when running more than one insance of typescript-plugin-styled-components at a time, you can add a componentIdPrefix by providing an arbitrary string to this option. 282 | 283 | Default value is `''` which means that no namespacing will happen. 284 | 285 | ### `identifiers` 286 | 287 | This option allows to customize identifiers used by `styled-components` API functions. 288 | 289 | > **Warning**. By providing custom identifiers, predefined ones are not added automatically. 290 | > Make sure you add standard APIs in case you meant to use them. 291 | 292 | ```ts 293 | interface CustomStyledIdentifiers { 294 | styled: string[]; 295 | attrs: string[]; 296 | keyframes: string[]; 297 | css: string[]; 298 | createGlobalStyle: string[]; 299 | extend: string[]; 300 | } 301 | ``` 302 | 303 | - `styled` - list of identifiers of `styled` API (default `['styled']`) 304 | - `attrs` - list of identifiers of `attrs` API (default `['attrs']`) 305 | - `keyframes` - list of identifiers of `keyframes` API (default `['keyframes']`) 306 | - `css` - list of identifiers of `css` API (default `['css']`) 307 | - `createGlobalStyle` - list of identifiers of `createGlobalStyle` API (default `['createGlobalStyle']`) 308 | - `extend` - list of identifiers of `extend` API (default `[]`). Note this API has been deprecated in `styled-components` so starting from `1.5` this option by default has empty set, which means it does not recognize this API by default. 309 | 310 | Example 311 | 312 | ```ts 313 | const styledComponentsTransformer = createStyledComponentsTransformer({ 314 | identifiers: { 315 | styled: ['styled', 'typedStyled'] // typedStyled is an additional identifier of styled API 316 | } 317 | }); 318 | ``` 319 | 320 | # Notes 321 | 322 | Technically, `typescript-plugin-styled-components` is not a TypeScript plugin, since it is only exposed as a TypeScript transformer. 323 | -------------------------------------------------------------------------------- /example/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | 4 | # OS generated files # 5 | ###################### 6 | .AppleDouble/ 7 | .DS_Store 8 | .DS_Store? 9 | ._* 10 | .Spotlight-V100 11 | .Trashes 12 | .idea 13 | *.happypack* 14 | ehthumbs.db 15 | Thumbs.db 16 | npm-debug.log 17 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # typescript-plugin-styled-components SSR example 2 | 3 | ## Getting Started 4 | 5 | - Build `typescript-plugin-styled-components` 6 | 7 | ``` 8 | $ cd .. 9 | ``` 10 | 11 | ``` 12 | $ npm i 13 | ``` 14 | 15 | ``` 16 | $ npm run build 17 | ``` 18 | 19 | - Run example 20 | 21 | ``` 22 | $ cd example 23 | ``` 24 | 25 | ``` 26 | $ npm i 27 | ``` 28 | 29 | ``` 30 | $ npm run dev 31 | ``` 32 | 33 | Note: see [`ttypescript`](https://github.com/cevek/ttypescript) if you want to compile the server without webpack -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-react-ssr-boilerplate", 3 | "version": "2.0.1", 4 | "description": "A starter boilerplate to create comprehensive React apps with TypeScript, Redux, Styled-Components and server-side rendering.", 5 | "author": "sandervispoel ", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/sandervspl/ts-react-ssr-boilerplate" 9 | }, 10 | "license": "MIT", 11 | "scripts": { 12 | "dev": "cross-env NODE_ENV=development webpack-cli --config webpack/config.server.js && node dist/server" 13 | }, 14 | "dependencies": { 15 | "express": "^4.16.4", 16 | "react": "^16.6.0", 17 | "react-dom": "^16.6.0", 18 | "react-router": "^4.3.1", 19 | "react-router-dom": "^4.3.1", 20 | "styled-components": "^4.0.3" 21 | }, 22 | "devDependencies": { 23 | "@types/express": "^4.16.0", 24 | "@types/react": "^16.4.18", 25 | "@types/react-dom": "^16.0.9", 26 | "@types/styled-components": "^4.0.3", 27 | "@types/webpack": "^4.4.17", 28 | "awesome-typescript-loader": "^5.2.1", 29 | "cross-env": "^5.2.0", 30 | "typescript": "^3.1.5", 31 | "webpack": "^4.23.1", 32 | "webpack-cli": "^3.1.2", 33 | "webpack-dev-middleware": "^3.4.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /example/src/AppClient.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | 4 | import App from './app/App'; 5 | import { ThemeProvider } from 'styled-components'; 6 | import { BrowserRouter } from 'react-router-dom' 7 | 8 | const app = document.getElementById('app'); 9 | 10 | ReactDOM.hydrate( 11 | 12 | 13 | 14 | 15 | 16 | , app); 17 | 18 | -------------------------------------------------------------------------------- /example/src/app/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import styled from 'styled-components'; 3 | import { Component1 } from './Component1'; 4 | 5 | const BodyStyle = styled.div` 6 | background: blue; 7 | padding: 20px; 8 | `; 9 | 10 | const Header = styled.h2` 11 | color: yellow; 12 | `; 13 | 14 | class App extends React.Component<{}> { 15 | 16 | render(){ 17 | return ( 18 |
19 | 20 |
Welcome to Typescript Styled Components SSR
21 | 22 |
23 |
24 | ); 25 | } 26 | } 27 | 28 | export default App; 29 | -------------------------------------------------------------------------------- /example/src/app/Component1.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | const Component1Style = styled.div` 5 | background: #fff; 6 | text-align: center; 7 | `; 8 | 9 | const TextStyle = styled.h3` 10 | color: #000; 11 | font-weight: bold; 12 | `; 13 | export const Component1 : React.SFC = () => ( 14 | 15 | SubComponent 16 | 17 | ) -------------------------------------------------------------------------------- /example/src/server/AppServer.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'React' 2 | import { ThemeProvider } from 'styled-components'; 3 | import { StaticRouter } from 'react-router-dom' 4 | import App from '../app/App'; 5 | export const AppServer = (url) => ( 6 | 10 | 11 | 12 | 13 | Test App 14 | 15 | 16 |
17 | 18 | 19 | 20 |
21 |
) -------------------------------------------------------------------------------- /example/src/server/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as express from 'express'; 3 | export const port = process.env.PORT || 3000; 4 | import { ServerStyleSheet } from 'styled-components'; 5 | import { renderToNodeStream } from 'react-dom/server'; 6 | import * as webpack from 'webpack'; 7 | const webpackDevMiddleware = require('webpack-dev-middleware'); 8 | import config from '../../webpack/config'; 9 | import {AppServer} from './AppServer'; 10 | 11 | 12 | const app = express(); 13 | 14 | const compiler = webpack(config); 15 | 16 | app.use(webpackDevMiddleware(compiler, { 17 | publicPath: config.output.publicPath, 18 | historyApiFallback: true, 19 | hot: true, 20 | noInfo: true, 21 | stats: { colors: true }, 22 | })); 23 | 24 | app.get('/', (req, res) => { 25 | res.contentType('text/html'); 26 | res.write(''); 27 | const sheet = new ServerStyleSheet(); 28 | const jsx = sheet.collectStyles() 29 | const stream = sheet.interleaveWithNodeStream(renderToNodeStream(jsx)) 30 | stream.pipe( 31 | res, 32 | { end: false } 33 | ) 34 | 35 | }); 36 | 37 | 38 | 39 | app.listen(port, () => { 40 | console.log(`[${process.env.NODE_ENV}] server running on http://localhost:${port}/`); 41 | }); 42 | -------------------------------------------------------------------------------- /example/transformer.js: -------------------------------------------------------------------------------- 1 | const transformer = '../' -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/", 4 | "sourceMap": true, 5 | "noImplicitAny": false, 6 | "removeComments": false, 7 | "allowUnreachableCode": true, 8 | "pretty": true, 9 | "module": "esnext", 10 | "moduleResolution": "node" , 11 | "target": "es2015", 12 | "jsx": "react", 13 | "baseUrl": "src", 14 | "lib": ["dom", "es6"] 15 | }, 16 | "include": [ 17 | "./webpack/**/*", 18 | "./src/**/*" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /example/tsconfig.server.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | "moduleResolution": "node" , 6 | "plugins": [ 7 | { "transform": "../src", "useSSR": true } 8 | ] 9 | }, 10 | "include": [ 11 | "./webpack/**/*", 12 | "./src/**/*" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /example/webpack/config.server.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const fs = require('fs'); 4 | 5 | const nodeModules = {}; 6 | fs.readdirSync('node_modules') 7 | .filter(function (x) { 8 | return ['.bin'].indexOf(x) === -1; 9 | }) 10 | .forEach(function (mod) { 11 | nodeModules[mod] = 'commonjs ' + mod; 12 | }); 13 | const getTransformer = require('./transformer'); 14 | 15 | 16 | const baseConfig = { 17 | mode: 'development', 18 | devtool: 'eval', 19 | entry: { 20 | server: [ 21 | path.resolve(__dirname, '../', 'src/server/index.tsx'), 22 | ], 23 | }, 24 | output: { 25 | path: path.resolve(__dirname, '..', 'dist'), 26 | publicPath: '/', 27 | filename: '[name].js', 28 | }, 29 | module: { 30 | rules: [ 31 | { 32 | test: /\.tsx?$/, 33 | exclude: /node_modules/, 34 | use: [ { 35 | loader: 'awesome-typescript-loader', 36 | options: { 37 | getCustomTransformers: getTransformer 38 | }, 39 | }], 40 | } 41 | ], 42 | }, 43 | resolve: { 44 | extensions: ['*', '.js', '.ts', '.tsx'] 45 | }, 46 | target: "node", 47 | externals: nodeModules 48 | }; 49 | 50 | module.exports = baseConfig; 51 | 52 | -------------------------------------------------------------------------------- /example/webpack/config.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | 3 | import * as webpack from 'webpack'; 4 | 5 | import * as getTransformer from './transformer'; 6 | 7 | const baseConfig : webpack.Configuration = { 8 | mode: 'development', 9 | devtool: 'eval', 10 | entry: { 11 | app: [path.resolve('src/AppClient.tsx')], 12 | }, 13 | output: { 14 | path: path.resolve('dist'), 15 | publicPath: '/', 16 | filename: '[name].js', 17 | }, 18 | module: { 19 | rules: [ 20 | { 21 | test: /\.tsx?$/, 22 | exclude: /node_modules/, 23 | use: [ { 24 | loader: 'awesome-typescript-loader', 25 | options: { 26 | getCustomTransformers: getTransformer 27 | }, 28 | }], 29 | } 30 | ], 31 | }, 32 | resolve: { 33 | extensions: ['*', '.js', '.ts', '.tsx'] 34 | }, 35 | }; 36 | 37 | export default baseConfig; 38 | 39 | -------------------------------------------------------------------------------- /example/webpack/transformer.js: -------------------------------------------------------------------------------- 1 | 2 | const createStyledComponentsTransformer = require('../../dist').default; 3 | 4 | const styledComponentsTransformer = createStyledComponentsTransformer(); 5 | 6 | module.exports = () => ({ before: [styledComponentsTransformer] }); 7 | 8 | -------------------------------------------------------------------------------- /jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "automock": false, 3 | "globals": { 4 | "ts-jest": { 5 | "tsConfig": "./tsconfig.json" 6 | } 7 | }, 8 | "moduleFileExtensions": [ 9 | "ts", 10 | "tsx", 11 | "js" 12 | ], 13 | "notify": false, 14 | "rootDir": "./", 15 | "testRegex": "\\.test\\.(ts|tsx)$", 16 | "transform": { 17 | "\\.(ts|tsx)$": "ts-jest" 18 | }, 19 | "verbose": true 20 | } 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-plugin-styled-components", 3 | "version": "3.0.0", 4 | "description": "TypeScript transformer for improving the debugging experience of styled-components", 5 | "main": "dist/index.js", 6 | "homepage": "https://github.com/Igorbek/typescript-plugin-styled-components", 7 | "repository": { 8 | "url": "https://github.com/Igorbek/typescript-plugin-styled-components.git", 9 | "type": "git" 10 | }, 11 | "author": "Igor Oleinikov ", 12 | "license": "MIT", 13 | "scripts": { 14 | "build": "tsc", 15 | "build:prod": "tsc --sourceMap false", 16 | "typecheck": "tsc --noEmit", 17 | "test:baselines": "jest --config ./jest.config.json", 18 | "test:watch": "yarn test:baselines -- --watch", 19 | "test": "yarn test:baselines", 20 | "runner": "ts-node ./src/runner.ts" 21 | }, 22 | "typings": "dist/index.d.ts", 23 | "peerDependencies": { 24 | "typescript": "~4.8 || 5" 25 | }, 26 | "devDependencies": { 27 | "@changesets/cli": "^2.26.1", 28 | "@types/jest": "^25.2.1", 29 | "@types/jest-specific-snapshot": "^0.5.4", 30 | "@types/node": "^13.1.2", 31 | "@types/react": "^16.7.22", 32 | "jest": "^24.1.0", 33 | "jest-specific-snapshot": "^2.0.0", 34 | "styled-components": "^5.3.11", 35 | "ts-jest": "24.3.0", 36 | "ts-node": "^8.0.2", 37 | "typescript": "~5.1" 38 | }, 39 | "files": [ 40 | "dist" 41 | ], 42 | "packageManager": "yarn@3.6.0" 43 | } 44 | -------------------------------------------------------------------------------- /src/__tests__/baselines.test.ts: -------------------------------------------------------------------------------- 1 | import createTransformer from '../'; 2 | import { expectBaselineTransforms } from './expectTransform'; 3 | 4 | const transformer = createTransformer({ ssr: false }); 5 | 6 | expectBaselineTransforms(transformer, __dirname + '/fixtures/base', 'baselines/base'); 7 | -------------------------------------------------------------------------------- /src/__tests__/baselines/base/issue33.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue33.ts 1`] = ` 4 | 5 | File: issue33.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | declare const $: any; 10 | declare const jQuery: any; 11 | declare const _: any; 12 | 13 | declare const Button: any; 14 | 15 | const Button1 = Button.extend\` color: red \`; 16 | 17 | const Button2 = $.extend\` color: red \`; 18 | const Button3 = jQuery.extend\` color: red \`; 19 | const Button4 = _.extend\` color: red \`; 20 | 21 | 22 | TypeScript before transform: 23 | 24 | declare const styled: any; 25 | declare const $: any; 26 | declare const jQuery: any; 27 | declare const _: any; 28 | declare const Button: any; 29 | const Button1 = Button.extend \` color: red \`; 30 | const Button2 = $.extend \` color: red \`; 31 | const Button3 = jQuery.extend \` color: red \`; 32 | const Button4 = _.extend \` color: red \`; 33 | 34 | 35 | TypeScript after transform: 36 | 37 | declare const styled: any; 38 | declare const $: any; 39 | declare const jQuery: any; 40 | declare const _: any; 41 | declare const Button: any; 42 | const Button1 = Button.extend \` color: red \`; 43 | const Button2 = $.extend \` color: red \`; 44 | const Button3 = jQuery.extend \` color: red \`; 45 | const Button4 = _.extend \` color: red \`; 46 | 47 | 48 | TypeScript after transpile module: 49 | 50 | const Button1 = Button.extend \` color: red \`; 51 | const Button2 = $.extend \` color: red \`; 52 | const Button3 = jQuery.extend \` color: red \`; 53 | const Button4 = _.extend \` color: red \`; 54 | 55 | 56 | 57 | `; 58 | -------------------------------------------------------------------------------- /src/__tests__/baselines/base/sample1.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`sample1.ts 1`] = ` 4 | 5 | File: sample1.ts 6 | Source code: 7 | 8 | import styled from 'styled-components'; 9 | 10 | const Button = styled.button\` 11 | color: red; 12 | \`; 13 | 14 | declare const nonStyled: any; 15 | 16 | const NonButton = nonStyled.button\` 17 | yo 18 | \`; 19 | 20 | const OtherButton = styled(Button)\` 21 | color: blue; 22 | \`; 23 | 24 | const SuperButton = Button.extend\` 25 | color: super; 26 | \`; 27 | 28 | export default styled.link\` 29 | color: black; 30 | \`; 31 | 32 | export const SmallButton = Button.extend\` 33 | font-size: .7em; 34 | \`; 35 | 36 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' })\` 37 | font-size: .1em; 38 | \`; 39 | 40 | 41 | TypeScript before transform: 42 | 43 | import styled from 'styled-components'; 44 | const Button = styled.button \` 45 | color: red; 46 | \`; 47 | declare const nonStyled: any; 48 | const NonButton = nonStyled.button \` 49 | yo 50 | \`; 51 | const OtherButton = styled(Button) \` 52 | color: blue; 53 | \`; 54 | const SuperButton = Button.extend \` 55 | color: super; 56 | \`; 57 | export default styled.link \` 58 | color: black; 59 | \`; 60 | export const SmallButton = Button.extend \` 61 | font-size: .7em; 62 | \`; 63 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }) \` 64 | font-size: .1em; 65 | \`; 66 | 67 | 68 | TypeScript after transform: 69 | 70 | import styled from 'styled-components'; 71 | const Button = styled.button.withConfig({ displayName: "Button" }) \` 72 | color: red; 73 | \`; 74 | declare const nonStyled: any; 75 | const NonButton = nonStyled.button \` 76 | yo 77 | \`; 78 | const OtherButton = styled(Button).withConfig({ displayName: "OtherButton" }) \` 79 | color: blue; 80 | \`; 81 | const SuperButton = Button.extend \` 82 | color: super; 83 | \`; 84 | export default styled.link \` 85 | color: black; 86 | \`; 87 | export const SmallButton = Button.extend \` 88 | font-size: .7em; 89 | \`; 90 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }).withConfig({ displayName: "MiniButton" }) \` 91 | font-size: .1em; 92 | \`; 93 | 94 | 95 | TypeScript after transpile module: 96 | 97 | import styled from 'styled-components'; 98 | const Button = styled.button.withConfig({ displayName: "Button" }) \` 99 | color: red; 100 | \`; 101 | const NonButton = nonStyled.button \` 102 | yo 103 | \`; 104 | const OtherButton = styled(Button).withConfig({ displayName: "OtherButton" }) \` 105 | color: blue; 106 | \`; 107 | const SuperButton = Button.extend \` 108 | color: super; 109 | \`; 110 | export default styled.link \` 111 | color: black; 112 | \`; 113 | export const SmallButton = Button.extend \` 114 | font-size: .7em; 115 | \`; 116 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }).withConfig({ displayName: "MiniButton" }) \` 117 | font-size: .1em; 118 | \`; 119 | 120 | 121 | 122 | `; 123 | -------------------------------------------------------------------------------- /src/__tests__/baselines/base/sample2.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`sample2.ts 1`] = ` 4 | 5 | File: sample2.ts 6 | Source code: 7 | 8 | import styled from 'styled-components'; 9 | 10 | const styled2 = styled; 11 | const NonButton = styled.button; 12 | const NonStyled = styled\` color: red; \`; 13 | const Link = styled(NonStyled)\` color: red; \`; 14 | 15 | 16 | TypeScript before transform: 17 | 18 | import styled from 'styled-components'; 19 | const styled2 = styled; 20 | const NonButton = styled.button; 21 | const NonStyled = styled \` color: red; \`; 22 | const Link = styled(NonStyled) \` color: red; \`; 23 | 24 | 25 | TypeScript after transform: 26 | 27 | import styled from 'styled-components'; 28 | const styled2 = styled; 29 | const NonButton = styled.button; 30 | const NonStyled = styled \` color: red; \`; 31 | const Link = styled(NonStyled).withConfig({ displayName: "Link" }) \` color: red; \`; 32 | 33 | 34 | TypeScript after transpile module: 35 | 36 | import styled from 'styled-components'; 37 | const styled2 = styled; 38 | const NonButton = styled.button; 39 | const NonStyled = styled \` color: red; \`; 40 | const Link = styled(NonStyled).withConfig({ displayName: "Link" }) \` color: red; \`; 41 | 42 | 43 | 44 | `; 45 | -------------------------------------------------------------------------------- /src/__tests__/baselines/base/sample3.tsx.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`sample3.tsx 1`] = ` 4 | 5 | File: sample3.tsx 6 | Source code: 7 | 8 | import * as React from 'react'; 9 | import styled from '../themed-styled'; 10 | import { SmallButton } from './sample1'; 11 | 12 | interface LabelProps { 13 | size: number; 14 | } 15 | 16 | const CustomLabel = styled.label\` 17 | font-size: \${(props: LabelProps) => props.size + 'px'} 18 | \`; 19 | 20 | const LabeledLink = () => ; 21 | 22 | export default CustomLabel; 23 | 24 | 25 | TypeScript before transform: 26 | 27 | import * as React from 'react'; 28 | import styled from '../themed-styled'; 29 | import { SmallButton } from './sample1'; 30 | interface LabelProps { 31 | size: number; 32 | } 33 | const CustomLabel = styled.label \` 34 | font-size: \${(props: LabelProps) => props.size + 'px'} 35 | \`; 36 | const LabeledLink = () => ; 37 | export default CustomLabel; 38 | 39 | 40 | TypeScript after transform: 41 | 42 | import * as React from 'react'; 43 | import styled from '../themed-styled'; 44 | import { SmallButton } from './sample1'; 45 | interface LabelProps { 46 | size: number; 47 | } 48 | const CustomLabel = styled.label.withConfig({ displayName: "CustomLabel" }) \` 49 | font-size: \${(props: LabelProps) => props.size + 'px'} 50 | \`; 51 | const LabeledLink = () => ; 52 | export default CustomLabel; 53 | 54 | 55 | TypeScript after transpile module: 56 | 57 | import styled from '../themed-styled'; 58 | const CustomLabel = styled.label.withConfig({ displayName: "CustomLabel" }) \` 59 | font-size: \${(props) => props.size + 'px'} 60 | \`; 61 | const LabeledLink = () => />;; 62 | export default CustomLabel; 63 | 64 | 65 | 66 | `; 67 | -------------------------------------------------------------------------------- /src/__tests__/baselines/base/style-objects.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`style-objects.ts 1`] = ` 4 | 5 | File: style-objects.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | const Button = styled.button({ 11 | color: 'red' 12 | }); 13 | 14 | declare const nonStyled: any; 15 | 16 | const NonButton = nonStyled.button({ 17 | color: 'red' 18 | }); 19 | 20 | const OtherButton = styled(Button)({ 21 | color: 'blue' 22 | }); 23 | 24 | const SuperButton = Button.extend({ 25 | color: 'super' 26 | }); 27 | 28 | export default styled.link({ 29 | color: 'black' 30 | }); 31 | 32 | export const SmallButton = Button.extend({ 33 | fontSize: '.7em' 34 | }); 35 | 36 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' })({ 37 | fontSize: '.1em' 38 | }); 39 | 40 | 41 | TypeScript before transform: 42 | 43 | declare const styled: any; 44 | const Button = styled.button({ 45 | color: 'red' 46 | }); 47 | declare const nonStyled: any; 48 | const NonButton = nonStyled.button({ 49 | color: 'red' 50 | }); 51 | const OtherButton = styled(Button)({ 52 | color: 'blue' 53 | }); 54 | const SuperButton = Button.extend({ 55 | color: 'super' 56 | }); 57 | export default styled.link({ 58 | color: 'black' 59 | }); 60 | export const SmallButton = Button.extend({ 61 | fontSize: '.7em' 62 | }); 63 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' })({ 64 | fontSize: '.1em' 65 | }); 66 | 67 | 68 | TypeScript after transform: 69 | 70 | declare const styled: any; 71 | const Button = styled.button.withConfig({ displayName: "Button" })({ 72 | color: 'red' 73 | }); 74 | declare const nonStyled: any; 75 | const NonButton = nonStyled.button({ 76 | color: 'red' 77 | }); 78 | const OtherButton = styled(Button).withConfig({ displayName: "OtherButton" })({ 79 | color: 'blue' 80 | }); 81 | const SuperButton = Button.extend({ 82 | color: 'super' 83 | }); 84 | export default styled.link({ 85 | color: 'black' 86 | }); 87 | export const SmallButton = Button.extend({ 88 | fontSize: '.7em' 89 | }); 90 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }).withConfig({ displayName: "MiniButton" })({ 91 | fontSize: '.1em' 92 | }); 93 | 94 | 95 | TypeScript after transpile module: 96 | 97 | const Button = styled.button.withConfig({ displayName: "Button" })({ 98 | color: 'red' 99 | }); 100 | const NonButton = nonStyled.button({ 101 | color: 'red' 102 | }); 103 | const OtherButton = styled(Button).withConfig({ displayName: "OtherButton" })({ 104 | color: 'blue' 105 | }); 106 | const SuperButton = Button.extend({ 107 | color: 'super' 108 | }); 109 | export default styled.link({ 110 | color: 'black' 111 | }); 112 | export const SmallButton = Button.extend({ 113 | fontSize: '.7em' 114 | }); 115 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }).withConfig({ displayName: "MiniButton" })({ 116 | fontSize: '.1em' 117 | }); 118 | 119 | 120 | 121 | `; 122 | -------------------------------------------------------------------------------- /src/__tests__/baselines/componentIdPrefix/issue33.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue33.ts 1`] = ` 4 | 5 | File: issue33.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | declare const $: any; 10 | declare const jQuery: any; 11 | declare const _: any; 12 | 13 | declare const Button: any; 14 | 15 | const Button1 = Button.extend\` color: red \`; 16 | 17 | const Button2 = $.extend\` color: red \`; 18 | const Button3 = jQuery.extend\` color: red \`; 19 | const Button4 = _.extend\` color: red \`; 20 | 21 | 22 | TypeScript before transform: 23 | 24 | declare const styled: any; 25 | declare const $: any; 26 | declare const jQuery: any; 27 | declare const _: any; 28 | declare const Button: any; 29 | const Button1 = Button.extend \` color: red \`; 30 | const Button2 = $.extend \` color: red \`; 31 | const Button3 = jQuery.extend \` color: red \`; 32 | const Button4 = _.extend \` color: red \`; 33 | 34 | 35 | TypeScript after transform: 36 | 37 | declare const styled: any; 38 | declare const $: any; 39 | declare const jQuery: any; 40 | declare const _: any; 41 | declare const Button: any; 42 | const Button1 = Button.extend \` color: red \`; 43 | const Button2 = $.extend \` color: red \`; 44 | const Button3 = jQuery.extend \` color: red \`; 45 | const Button4 = _.extend \` color: red \`; 46 | 47 | 48 | TypeScript after transpile module: 49 | 50 | const Button1 = Button.extend \` color: red \`; 51 | const Button2 = $.extend \` color: red \`; 52 | const Button3 = jQuery.extend \` color: red \`; 53 | const Button4 = _.extend \` color: red \`; 54 | 55 | 56 | 57 | `; 58 | -------------------------------------------------------------------------------- /src/__tests__/baselines/componentIdPrefix/multiple-components.tsx.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`multiple-components.tsx 1`] = ` 4 | 5 | File: multiple-components.tsx 6 | Source code: 7 | 8 | import styled from 'styled-components'; 9 | 10 | export function createButtons() { 11 | const A = styled.button\` color: red; \`; 12 | const B = styled(A)\` color: blue; \`; 13 | 14 | return { A, B }; 15 | } 16 | 17 | export function createDivs() { 18 | const A = styled.div\` color: green; \`; 19 | const B = styled(A)\` color: yellow; \`; 20 | 21 | return { A, B }; 22 | } 23 | 24 | 25 | TypeScript before transform: 26 | 27 | import styled from 'styled-components'; 28 | export function createButtons() { 29 | const A = styled.button \` color: red; \`; 30 | const B = styled(A) \` color: blue; \`; 31 | return { A, B }; 32 | } 33 | export function createDivs() { 34 | const A = styled.div \` color: green; \`; 35 | const B = styled(A) \` color: yellow; \`; 36 | return { A, B }; 37 | } 38 | 39 | 40 | TypeScript after transform: 41 | 42 | import styled from 'styled-components'; 43 | export function createButtons() { 44 | const A = styled.button.withConfig({ displayName: "test-A", componentId: "test-h2cmto" }) \` color: red; \`; 45 | const B = styled(A).withConfig({ displayName: "test-B", componentId: "test-3cja5" }) \` color: blue; \`; 46 | return { A, B }; 47 | } 48 | export function createDivs() { 49 | const A = styled.div.withConfig({ displayName: "test-A", componentId: "test-1oubriv" }) \` color: green; \`; 50 | const B = styled(A).withConfig({ displayName: "test-B", componentId: "test-lfixbl" }) \` color: yellow; \`; 51 | return { A, B }; 52 | } 53 | 54 | 55 | TypeScript after transpile module: 56 | 57 | import styled from 'styled-components'; 58 | export function createButtons() { 59 | const A = styled.button.withConfig({ displayName: "test-A", componentId: "test-1lfj0gb" }) \` color: red; \`; 60 | const B = styled(A).withConfig({ displayName: "test-B", componentId: "test-kjhsv6" }) \` color: blue; \`; 61 | return { A, B }; 62 | } 63 | export function createDivs() { 64 | const A = styled.div.withConfig({ displayName: "test-A", componentId: "test-wzcq75" }) \` color: green; \`; 65 | const B = styled(A).withConfig({ displayName: "test-B", componentId: "test-6zek9o" }) \` color: yellow; \`; 66 | return { A, B }; 67 | } 68 | 69 | 70 | 71 | `; 72 | -------------------------------------------------------------------------------- /src/__tests__/baselines/componentIdPrefix/sample1.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`sample1.ts 1`] = ` 4 | 5 | File: sample1.ts 6 | Source code: 7 | 8 | import styled from 'styled-components'; 9 | 10 | const Button = styled.button\` 11 | color: red; 12 | \`; 13 | 14 | declare const nonStyled: any; 15 | 16 | const NonButton = nonStyled.button\` 17 | yo 18 | \`; 19 | 20 | const OtherButton = styled(Button)\` 21 | color: blue; 22 | \`; 23 | 24 | const SuperButton = Button.extend\` 25 | color: super; 26 | \`; 27 | 28 | export default styled.link\` 29 | color: black; 30 | \`; 31 | 32 | export const SmallButton = Button.extend\` 33 | font-size: .7em; 34 | \`; 35 | 36 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' })\` 37 | font-size: .1em; 38 | \`; 39 | 40 | 41 | TypeScript before transform: 42 | 43 | import styled from 'styled-components'; 44 | const Button = styled.button \` 45 | color: red; 46 | \`; 47 | declare const nonStyled: any; 48 | const NonButton = nonStyled.button \` 49 | yo 50 | \`; 51 | const OtherButton = styled(Button) \` 52 | color: blue; 53 | \`; 54 | const SuperButton = Button.extend \` 55 | color: super; 56 | \`; 57 | export default styled.link \` 58 | color: black; 59 | \`; 60 | export const SmallButton = Button.extend \` 61 | font-size: .7em; 62 | \`; 63 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }) \` 64 | font-size: .1em; 65 | \`; 66 | 67 | 68 | TypeScript after transform: 69 | 70 | import styled from 'styled-components'; 71 | const Button = styled.button.withConfig({ displayName: "test-Button", componentId: "test-uezo0r" }) \` 72 | color: red; 73 | \`; 74 | declare const nonStyled: any; 75 | const NonButton = nonStyled.button \` 76 | yo 77 | \`; 78 | const OtherButton = styled(Button).withConfig({ displayName: "test-OtherButton", componentId: "test-1x4ml5" }) \` 79 | color: blue; 80 | \`; 81 | const SuperButton = Button.extend \` 82 | color: super; 83 | \`; 84 | export default styled.link.withConfig({ componentId: "test-vba0dl" }) \` 85 | color: black; 86 | \`; 87 | export const SmallButton = Button.extend \` 88 | font-size: .7em; 89 | \`; 90 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }).withConfig({ displayName: "test-MiniButton", componentId: "test-1ktoxg0" }) \` 91 | font-size: .1em; 92 | \`; 93 | 94 | 95 | TypeScript after transpile module: 96 | 97 | import styled from 'styled-components'; 98 | const Button = styled.button.withConfig({ displayName: "test-Button", componentId: "test-1nbxxpw" }) \` 99 | color: red; 100 | \`; 101 | const NonButton = nonStyled.button \` 102 | yo 103 | \`; 104 | const OtherButton = styled(Button).withConfig({ displayName: "test-OtherButton", componentId: "test-17xltiv" }) \` 105 | color: blue; 106 | \`; 107 | const SuperButton = Button.extend \` 108 | color: super; 109 | \`; 110 | export default styled.link.withConfig({ componentId: "test-ep20on" }) \` 111 | color: black; 112 | \`; 113 | export const SmallButton = Button.extend \` 114 | font-size: .7em; 115 | \`; 116 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }).withConfig({ displayName: "test-MiniButton", componentId: "test-am1bk" }) \` 117 | font-size: .1em; 118 | \`; 119 | 120 | 121 | 122 | `; 123 | -------------------------------------------------------------------------------- /src/__tests__/baselines/componentIdPrefix/sample2.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`sample2.ts 1`] = ` 4 | 5 | File: sample2.ts 6 | Source code: 7 | 8 | import styled from 'styled-components'; 9 | 10 | const styled2 = styled; 11 | const NonButton = styled.button; 12 | const NonStyled = styled\` color: red; \`; 13 | const Link = styled(NonStyled)\` color: red; \`; 14 | 15 | 16 | TypeScript before transform: 17 | 18 | import styled from 'styled-components'; 19 | const styled2 = styled; 20 | const NonButton = styled.button; 21 | const NonStyled = styled \` color: red; \`; 22 | const Link = styled(NonStyled) \` color: red; \`; 23 | 24 | 25 | TypeScript after transform: 26 | 27 | import styled from 'styled-components'; 28 | const styled2 = styled; 29 | const NonButton = styled.button; 30 | const NonStyled = styled \` color: red; \`; 31 | const Link = styled(NonStyled).withConfig({ displayName: "test-Link", componentId: "test-1gbt9xq" }) \` color: red; \`; 32 | 33 | 34 | TypeScript after transpile module: 35 | 36 | import styled from 'styled-components'; 37 | const styled2 = styled; 38 | const NonButton = styled.button; 39 | const NonStyled = styled \` color: red; \`; 40 | const Link = styled(NonStyled).withConfig({ displayName: "test-Link", componentId: "test-gbrvon" }) \` color: red; \`; 41 | 42 | 43 | 44 | `; 45 | -------------------------------------------------------------------------------- /src/__tests__/baselines/componentIdPrefix/sample3.tsx.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`sample3.tsx 1`] = ` 4 | 5 | File: sample3.tsx 6 | Source code: 7 | 8 | import * as React from 'react'; 9 | import styled from '../themed-styled'; 10 | import { SmallButton } from './sample1'; 11 | 12 | interface LabelProps { 13 | size: number; 14 | } 15 | 16 | const CustomLabel = styled.label\` 17 | font-size: \${(props: LabelProps) => props.size + 'px'} 18 | \`; 19 | 20 | const LabeledLink = () => ; 21 | 22 | export default CustomLabel; 23 | 24 | 25 | TypeScript before transform: 26 | 27 | import * as React from 'react'; 28 | import styled from '../themed-styled'; 29 | import { SmallButton } from './sample1'; 30 | interface LabelProps { 31 | size: number; 32 | } 33 | const CustomLabel = styled.label \` 34 | font-size: \${(props: LabelProps) => props.size + 'px'} 35 | \`; 36 | const LabeledLink = () => ; 37 | export default CustomLabel; 38 | 39 | 40 | TypeScript after transform: 41 | 42 | import * as React from 'react'; 43 | import styled from '../themed-styled'; 44 | import { SmallButton } from './sample1'; 45 | interface LabelProps { 46 | size: number; 47 | } 48 | const CustomLabel = styled.label.withConfig({ displayName: "test-CustomLabel", componentId: "test-xtd6b" }) \` 49 | font-size: \${(props: LabelProps) => props.size + 'px'} 50 | \`; 51 | const LabeledLink = () => ; 52 | export default CustomLabel; 53 | 54 | 55 | TypeScript after transpile module: 56 | 57 | import styled from '../themed-styled'; 58 | const CustomLabel = styled.label.withConfig({ displayName: "test-CustomLabel", componentId: "test-mqylua" }) \` 59 | font-size: \${(props) => props.size + 'px'} 60 | \`; 61 | const LabeledLink = () => />;; 62 | export default CustomLabel; 63 | 64 | 65 | 66 | `; 67 | -------------------------------------------------------------------------------- /src/__tests__/baselines/componentIdPrefix/style-objects.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`style-objects.ts 1`] = ` 4 | 5 | File: style-objects.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | const Button = styled.button({ 11 | color: 'red' 12 | }); 13 | 14 | declare const nonStyled: any; 15 | 16 | const NonButton = nonStyled.button({ 17 | color: 'red' 18 | }); 19 | 20 | const OtherButton = styled(Button)({ 21 | color: 'blue' 22 | }); 23 | 24 | const SuperButton = Button.extend({ 25 | color: 'super' 26 | }); 27 | 28 | export default styled.link({ 29 | color: 'black' 30 | }); 31 | 32 | export const SmallButton = Button.extend({ 33 | fontSize: '.7em' 34 | }); 35 | 36 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' })({ 37 | fontSize: '.1em' 38 | }); 39 | 40 | 41 | TypeScript before transform: 42 | 43 | declare const styled: any; 44 | const Button = styled.button({ 45 | color: 'red' 46 | }); 47 | declare const nonStyled: any; 48 | const NonButton = nonStyled.button({ 49 | color: 'red' 50 | }); 51 | const OtherButton = styled(Button)({ 52 | color: 'blue' 53 | }); 54 | const SuperButton = Button.extend({ 55 | color: 'super' 56 | }); 57 | export default styled.link({ 58 | color: 'black' 59 | }); 60 | export const SmallButton = Button.extend({ 61 | fontSize: '.7em' 62 | }); 63 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' })({ 64 | fontSize: '.1em' 65 | }); 66 | 67 | 68 | TypeScript after transform: 69 | 70 | declare const styled: any; 71 | const Button = styled.button.withConfig({ displayName: "test-Button", componentId: "test-1qkmci6" })({ 72 | color: 'red' 73 | }); 74 | declare const nonStyled: any; 75 | const NonButton = nonStyled.button({ 76 | color: 'red' 77 | }); 78 | const OtherButton = styled(Button).withConfig({ displayName: "test-OtherButton", componentId: "test-6fha6t" })({ 79 | color: 'blue' 80 | }); 81 | const SuperButton = Button.extend({ 82 | color: 'super' 83 | }); 84 | export default styled.link.withConfig({ componentId: "test-8xjslt" })({ 85 | color: 'black' 86 | }); 87 | export const SmallButton = Button.extend({ 88 | fontSize: '.7em' 89 | }); 90 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }).withConfig({ displayName: "test-MiniButton", componentId: "test-nrep0p" })({ 91 | fontSize: '.1em' 92 | }); 93 | 94 | 95 | TypeScript after transpile module: 96 | 97 | const Button = styled.button.withConfig({ displayName: "test-Button", componentId: "test-1nbxxpw" })({ 98 | color: 'red' 99 | }); 100 | const NonButton = nonStyled.button({ 101 | color: 'red' 102 | }); 103 | const OtherButton = styled(Button).withConfig({ displayName: "test-OtherButton", componentId: "test-17xltiv" })({ 104 | color: 'blue' 105 | }); 106 | const SuperButton = Button.extend({ 107 | color: 'super' 108 | }); 109 | export default styled.link.withConfig({ componentId: "test-ep20on" })({ 110 | color: 'black' 111 | }); 112 | export const SmallButton = Button.extend({ 113 | fontSize: '.7em' 114 | }); 115 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }).withConfig({ displayName: "test-MiniButton", componentId: "test-am1bk" })({ 116 | fontSize: '.1em' 117 | }); 118 | 119 | 120 | 121 | `; 122 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification-only/issue142.tsx.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue142.tsx 1`] = ` 4 | 5 | File: issue142.tsx 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | const Header = styled.div\` 11 | display: flex; 12 | \\t align-items: center; 13 | justify-content: space-between; 14 | \\t \\t font-weight: 600; 15 | padding: 0.8em 1.6em;\\t \\t 16 | background: peachpuff; 17 | \`; 18 | 19 | 20 | TypeScript before transform: 21 | 22 | declare const styled: any; 23 | const Header = styled.div \` 24 | display: flex; 25 | \\t align-items: center; 26 | justify-content: space-between; 27 | \\t \\t font-weight: 600; 28 | padding: 0.8em 1.6em;\\t \\t 29 | background: peachpuff; 30 | \`; 31 | 32 | 33 | TypeScript after transform: 34 | 35 | declare const styled: any; 36 | const Header = styled.div \`display:flex;align-items:center;justify-content:space-between;font-weight:600;padding:0.8em 1.6em;background:peachpuff;\`; 37 | 38 | 39 | TypeScript after transpile module: 40 | 41 | const Header = styled.div \`display:flex;align-items:center;justify-content:space-between;font-weight:600;padding:0.8em 1.6em;background:peachpuff;\`; 42 | 43 | 44 | 45 | `; 46 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification-only/issue233.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue233.ts 1`] = ` 4 | 5 | File: issue233.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | // repro from #233 11 | const ValueCalc = styled.div\` 12 | height: calc(var(--line-height) - 5px); 13 | width: calc(100% - 5px); 14 | \`; 15 | 16 | // another case from #233 17 | styled.div\`--padding-button: calc(var(--padding-button-vertical) - 2px) calc(var(--padding-button-horizontal) - 2px);\` 18 | 19 | // a few more cases 20 | styled.div\` 21 | width: calc( 1%) 22 | width: calc( 1% + var(--a) - calc(2%)) 23 | width: calc( 1% + var(--a) - calc(2%) + calc( 1px + calc(1px + 2px) + var(--a))) 24 | \` 25 | 26 | 27 | TypeScript before transform: 28 | 29 | declare const styled: any; 30 | // repro from #233 31 | const ValueCalc = styled.div \` 32 | height: calc(var(--line-height) - 5px); 33 | width: calc(100% - 5px); 34 | \`; 35 | // another case from #233 36 | styled.div \`--padding-button: calc(var(--padding-button-vertical) - 2px) calc(var(--padding-button-horizontal) - 2px);\`; 37 | // a few more cases 38 | styled.div \` 39 | width: calc( 1%) 40 | width: calc( 1% + var(--a) - calc(2%)) 41 | width: calc( 1% + var(--a) - calc(2%) + calc( 1px + calc(1px + 2px) + var(--a))) 42 | \`; 43 | 44 | 45 | TypeScript after transform: 46 | 47 | declare const styled: any; 48 | // repro from #233 49 | const ValueCalc = styled.div \`height:calc(var(--line-height) - 5px);width:calc(100% - 5px);\`; 50 | // another case from #233 51 | styled.div \`--padding-button:calc(var(--padding-button-vertical) - 2px)calc(var(--padding-button-horizontal) - 2px);\`; 52 | // a few more cases 53 | styled.div \`width:calc( 1%)width:calc( 1% + var(--a) - calc(2%))width:calc( 1% + var(--a) - calc(2%) + calc( 1px + calc(1px + 2px) + var(--a)))\`; 54 | 55 | 56 | TypeScript after transpile module: 57 | 58 | // repro from #233 59 | const ValueCalc = styled.div \`height:calc(var(--line-height) - 5px);width:calc(100% - 5px);\`; 60 | // another case from #233 61 | styled.div \`--padding-button:calc(var(--padding-button-vertical) - 2px)calc(var(--padding-button-horizontal) - 2px);\`; 62 | // a few more cases 63 | styled.div \`width:calc( 1%)width:calc( 1% + var(--a) - calc(2%))width:calc( 1% + var(--a) - calc(2%) + calc( 1px + calc(1px + 2px) + var(--a)))\`; 64 | 65 | 66 | 67 | `; 68 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification-only/issue36-extended.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue36-extended.ts 1`] = ` 4 | 5 | File: issue36-extended.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | export const A = styled.div\` 11 | border: \${'solid'} 10px; 12 | \` 13 | 14 | styled.div\` 15 | border: \${'solid'}// comment here 16 | 10px; 17 | border: solid// comment here 18 | 10px; 19 | \` 20 | 21 | styled.div\` 22 | border: \${'solid'}/* comment here 23 | */10px; 24 | border: \${'solid'}/* comment here 25 | */ 10px; 26 | \` 27 | 28 | 29 | TypeScript before transform: 30 | 31 | declare const styled: any; 32 | export const A = styled.div \` 33 | border: \${'solid'} 10px; 34 | \`; 35 | styled.div \` 36 | border: \${'solid'}// comment here 37 | 10px; 38 | border: solid// comment here 39 | 10px; 40 | \`; 41 | styled.div \` 42 | border: \${'solid'}/* comment here 43 | */10px; 44 | border: \${'solid'}/* comment here 45 | */ 10px; 46 | \`; 47 | 48 | 49 | TypeScript after transform: 50 | 51 | declare const styled: any; 52 | export const A = styled.div \`border:\${'solid'} 10px;\`; 53 | styled.div \`border:\${'solid'} 10px;border:solid 10px;\`; 54 | styled.div \`border:\${'solid'} 10px;border:\${'solid'} 10px;\`; 55 | 56 | 57 | TypeScript after transpile module: 58 | 59 | export const A = styled.div \`border:\${'solid'} 10px;\`; 60 | styled.div \`border:\${'solid'} 10px;border:solid 10px;\`; 61 | styled.div \`border:\${'solid'} 10px;border:\${'solid'} 10px;\`; 62 | 63 | 64 | 65 | `; 66 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification-only/issue36.tsx.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue36.tsx 1`] = ` 4 | 5 | File: issue36.tsx 6 | Source code: 7 | 8 | declare const keyframes: any; 9 | declare const styled: any; 10 | 11 | const rotate360 = keyframes\` 12 | from { 13 | transform: rotate(0deg); 14 | } 15 | to { 16 | transform: rotate(360deg); 17 | } 18 | \`; 19 | 20 | export const StyledDiv = styled.div\` 21 | width: 100px; 22 | height: 100px; 23 | background-color: greenyellow; 24 | animation: \${rotate360} 2s linear infinite; 25 | \`; 26 | 27 | 28 | TypeScript before transform: 29 | 30 | declare const keyframes: any; 31 | declare const styled: any; 32 | const rotate360 = keyframes \` 33 | from { 34 | transform: rotate(0deg); 35 | } 36 | to { 37 | transform: rotate(360deg); 38 | } 39 | \`; 40 | export const StyledDiv = styled.div \` 41 | width: 100px; 42 | height: 100px; 43 | background-color: greenyellow; 44 | animation: \${rotate360} 2s linear infinite; 45 | \`; 46 | 47 | 48 | TypeScript after transform: 49 | 50 | declare const keyframes: any; 51 | declare const styled: any; 52 | const rotate360 = keyframes \`from{transform:rotate(0deg);}to{transform:rotate(360deg);}\`; 53 | export const StyledDiv = styled.div \`width:100px;height:100px;background-color:greenyellow;animation:\${rotate360} 2s linear infinite;\`; 54 | 55 | 56 | TypeScript after transpile module: 57 | 58 | const rotate360 = keyframes \`from{transform:rotate(0deg);}to{transform:rotate(360deg);}\`; 59 | export const StyledDiv = styled.div \`width:100px;height:100px;background-color:greenyellow;animation:\${rotate360} 2s linear infinite;\`; 60 | 61 | 62 | 63 | `; 64 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification-only/issue40.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue40.ts 1`] = ` 4 | 5 | File: issue40.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | styled.div\`padding: 0 0 13px \${'50px'};\` 11 | 12 | 13 | TypeScript before transform: 14 | 15 | declare const styled: any; 16 | styled.div \`padding: 0 0 13px \${'50px'};\`; 17 | 18 | 19 | TypeScript after transform: 20 | 21 | declare const styled: any; 22 | styled.div \`padding:0 0 13px \${'50px'};\`; 23 | 24 | 25 | TypeScript after transpile module: 26 | 27 | styled.div \`padding:0 0 13px \${'50px'};\`; 28 | 29 | 30 | 31 | `; 32 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification-only/issue44.tsx.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue44.tsx 1`] = ` 4 | 5 | File: issue44.tsx 6 | Source code: 7 | 8 | declare const styled: any; 9 | styled.div\` transition: width \${100}ms ease-in;\`; 10 | styled.div\` transition: width \${'100ms'} ease-in;\`; 11 | 12 | 13 | TypeScript before transform: 14 | 15 | declare const styled: any; 16 | styled.div \` transition: width \${100}ms ease-in;\`; 17 | styled.div \` transition: width \${'100ms'} ease-in;\`; 18 | 19 | 20 | TypeScript after transform: 21 | 22 | declare const styled: any; 23 | styled.div \`transition:width \${100}ms ease-in;\`; 24 | styled.div \`transition:width \${'100ms'} ease-in;\`; 25 | 26 | 27 | TypeScript after transpile module: 28 | 29 | styled.div \`transition:width \${100}ms ease-in;\`; 30 | styled.div \`transition:width \${'100ms'} ease-in;\`; 31 | 32 | 33 | 34 | `; 35 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification-only/minify-css-in-helpers.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`minify-css-in-helpers.ts 1`] = ` 4 | 5 | File: minify-css-in-helpers.ts 6 | Source code: 7 | 8 | declare const keyframes: any; 9 | declare const css: any; 10 | declare const createGlobalStyle: any; 11 | 12 | declare const theColor: any; 13 | 14 | const key = keyframes\` 15 | to { 16 | transform: rotate(360deg); 17 | } 18 | \`; 19 | 20 | const color = css\` 21 | color: \${theColor}; 22 | \`; 23 | 24 | const MyRedBody = createGlobalStyle\` 25 | body { 26 | background-color: red; // comments 27 | \${color} // comments 28 | // it will be ignored, but still emitted \${color} 29 | } 30 | \`; 31 | 32 | export {}; 33 | 34 | 35 | TypeScript before transform: 36 | 37 | declare const keyframes: any; 38 | declare const css: any; 39 | declare const createGlobalStyle: any; 40 | declare const theColor: any; 41 | const key = keyframes \` 42 | to { 43 | transform: rotate(360deg); 44 | } 45 | \`; 46 | const color = css \` 47 | color: \${theColor}; 48 | \`; 49 | const MyRedBody = createGlobalStyle \` 50 | body { 51 | background-color: red; // comments 52 | \${color} // comments 53 | // it will be ignored, but still emitted \${color} 54 | } 55 | \`; 56 | export {}; 57 | 58 | 59 | TypeScript after transform: 60 | 61 | declare const keyframes: any; 62 | declare const css: any; 63 | declare const createGlobalStyle: any; 64 | declare const theColor: any; 65 | const key = keyframes \`to{transform:rotate(360deg);}\`; 66 | const color = css \`color:\${theColor};\`; 67 | const MyRedBody = createGlobalStyle \`body{background-color:red;\${color}//\${color}\\n}\`; 68 | export {}; 69 | 70 | 71 | TypeScript after transpile module: 72 | 73 | const key = keyframes \`to{transform:rotate(360deg);}\`; 74 | const color = css \`color:\${theColor};\`; 75 | const MyRedBody = createGlobalStyle \`body{background-color:red;\${color}//\${color}\\n}\`; 76 | export {}; 77 | 78 | 79 | 80 | `; 81 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification-only/minify-css-to-use-with-transpilation.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`minify-css-to-use-with-transpilation.ts 1`] = ` 4 | 5 | File: minify-css-to-use-with-transpilation.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | const Simple = styled.div\` 11 | width: 100%; 12 | \`; 13 | 14 | const Interpolation = styled.div\` 15 | content: " \${props => props.text} "; 16 | \`; 17 | 18 | const SpecialCharacters = styled.div\` 19 | content: " \${props => props.text} ";\\n color: red; 20 | \`; 21 | 22 | const Comment = styled.div\` 23 | // comment 24 | color: red; 25 | \` 26 | 27 | const Parens = styled.div\` 28 | &:hover { 29 | color: blue; 30 | } 31 | \`; 32 | 33 | export {}; 34 | 35 | 36 | TypeScript before transform: 37 | 38 | declare const styled: any; 39 | const Simple = styled.div \` 40 | width: 100%; 41 | \`; 42 | const Interpolation = styled.div \` 43 | content: " \${props => props.text} "; 44 | \`; 45 | const SpecialCharacters = styled.div \` 46 | content: " \${props => props.text} ";\\n color: red; 47 | \`; 48 | const Comment = styled.div \` 49 | // comment 50 | color: red; 51 | \`; 52 | const Parens = styled.div \` 53 | &:hover { 54 | color: blue; 55 | } 56 | \`; 57 | export {}; 58 | 59 | 60 | TypeScript after transform: 61 | 62 | declare const styled: any; 63 | const Simple = styled.div \`width:100%;\`; 64 | const Interpolation = styled.div \`content:" \${props => props.text} ";\`; 65 | const SpecialCharacters = styled.div \`content:" \${props => props.text} ";color:red;\`; 66 | const Comment = styled.div \`color:red;\`; 67 | const Parens = styled.div \`&:hover{color:blue;}\`; 68 | export {}; 69 | 70 | 71 | TypeScript after transpile module: 72 | 73 | const Simple = styled.div \`width:100%;\`; 74 | const Interpolation = styled.div \`content:" \${props => props.text} ";\`; 75 | const SpecialCharacters = styled.div \`content:" \${props => props.text} ";color:red;\`; 76 | const Comment = styled.div \`color:red;\`; 77 | const Parens = styled.div \`&:hover{color:blue;}\`; 78 | export {}; 79 | 80 | 81 | 82 | `; 83 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification-only/minify-css-to-use-without-transpilation.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`minify-css-to-use-without-transpilation.ts 1`] = ` 4 | 5 | File: minify-css-to-use-without-transpilation.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | const Simple = styled.div\` 11 | width: 100%; 12 | \`; 13 | 14 | const Interpolation = styled.div\` 15 | content: "https://test.com/\${props => props.endpoint}"; 16 | \`; 17 | 18 | const SpecialCharacters = styled.div\` 19 | content: " \${props => props.text} ";\\n color: red; 20 | \`; 21 | 22 | const Comment = styled.div\` 23 | width: 100%; 24 | // comment 25 | color: red; 26 | \`; 27 | 28 | const Parens = styled.div\` 29 | &:hover { 30 | color: blue; 31 | } 32 | color: red; 33 | \`; 34 | 35 | const UrlComments = styled.div\` 36 | color: red; 37 | /* // */ 38 | background: red; 39 | /* comment 1 */ 40 | /* comment 2 */ 41 | // comment 3 42 | border: 1px solid green; 43 | \`; 44 | 45 | export {}; 46 | 47 | 48 | TypeScript before transform: 49 | 50 | declare const styled: any; 51 | const Simple = styled.div \` 52 | width: 100%; 53 | \`; 54 | const Interpolation = styled.div \` 55 | content: "https://test.com/\${props => props.endpoint}"; 56 | \`; 57 | const SpecialCharacters = styled.div \` 58 | content: " \${props => props.text} ";\\n color: red; 59 | \`; 60 | const Comment = styled.div \` 61 | width: 100%; 62 | // comment 63 | color: red; 64 | \`; 65 | const Parens = styled.div \` 66 | &:hover { 67 | color: blue; 68 | } 69 | color: red; 70 | \`; 71 | const UrlComments = styled.div \` 72 | color: red; 73 | /* // */ 74 | background: red; 75 | /* comment 1 */ 76 | /* comment 2 */ 77 | // comment 3 78 | border: 1px solid green; 79 | \`; 80 | export {}; 81 | 82 | 83 | TypeScript after transform: 84 | 85 | declare const styled: any; 86 | const Simple = styled.div \`width:100%;\`; 87 | const Interpolation = styled.div \`content:"https://test.com/\${props => props.endpoint}";\`; 88 | const SpecialCharacters = styled.div \`content:" \${props => props.text} ";color:red;\`; 89 | const Comment = styled.div \`width:100%;color:red;\`; 90 | const Parens = styled.div \`&:hover{color:blue;}color:red;\`; 91 | const UrlComments = styled.div \`color:red;background:red;border:1px solid green;\`; 92 | export {}; 93 | 94 | 95 | TypeScript after transpile module: 96 | 97 | const Simple = styled.div \`width:100%;\`; 98 | const Interpolation = styled.div \`content:"https://test.com/\${props => props.endpoint}";\`; 99 | const SpecialCharacters = styled.div \`content:" \${props => props.text} ";color:red;\`; 100 | const Comment = styled.div \`width:100%;color:red;\`; 101 | const Parens = styled.div \`&:hover{color:blue;}color:red;\`; 102 | const UrlComments = styled.div \`color:red;background:red;border:1px solid green;\`; 103 | export {}; 104 | 105 | 106 | 107 | `; 108 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification-only/minify-single-line-comments-with-interpolations.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`minify-single-line-comments-with-interpolations.ts 1`] = ` 4 | 5 | File: minify-single-line-comments-with-interpolations.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | const Test1 = styled.div\` 11 | width: 100%; 12 | // color: \${'red'}; 13 | \` 14 | 15 | const Test2 = styled.div\` 16 | width: 100%; 17 | // color: pale\${'red'}; 18 | \` 19 | 20 | const Test3 = styled.div\` 21 | width: 100%; 22 | // color 23 | \${'red'}; 24 | \` 25 | 26 | const Test4 = styled.div\` 27 | width: 100%; 28 | // color: \${'red'}-blue; 29 | \` 30 | 31 | const Test5 = styled.div\` 32 | width: 100%; 33 | // color: \${'red'}\${'blue'}; 34 | \` 35 | 36 | const Test6 = styled.div\` 37 | background: url("https://google.com"); 38 | width: 100%; 39 | \${'green'} // color: \${'red'}\${'blue'}; 40 | \` 41 | 42 | const Test7 = styled.div\` 43 | background: url("https://google.com"); 44 | width: \${p => p.props.width}; 45 | \${'green'} // color: \${'red'}\${'blue'}; 46 | height: \${p => p.props.height}; 47 | \` 48 | 49 | const Test8 = styled.dev\` 50 | color: /* \${'red'} ... disabled */ blue; 51 | \`; 52 | 53 | const Test9 = styled.dev\` 54 | color: // \${'red'} ... disabled 55 | blue 56 | \`; 57 | 58 | export {} 59 | 60 | TypeScript before transform: 61 | 62 | declare const styled: any; 63 | const Test1 = styled.div \` 64 | width: 100%; 65 | // color: \${'red'}; 66 | \`; 67 | const Test2 = styled.div \` 68 | width: 100%; 69 | // color: pale\${'red'}; 70 | \`; 71 | const Test3 = styled.div \` 72 | width: 100%; 73 | // color 74 | \${'red'}; 75 | \`; 76 | const Test4 = styled.div \` 77 | width: 100%; 78 | // color: \${'red'}-blue; 79 | \`; 80 | const Test5 = styled.div \` 81 | width: 100%; 82 | // color: \${'red'}\${'blue'}; 83 | \`; 84 | const Test6 = styled.div \` 85 | background: url("https://google.com"); 86 | width: 100%; 87 | \${'green'} // color: \${'red'}\${'blue'}; 88 | \`; 89 | const Test7 = styled.div \` 90 | background: url("https://google.com"); 91 | width: \${p => p.props.width}; 92 | \${'green'} // color: \${'red'}\${'blue'}; 93 | height: \${p => p.props.height}; 94 | \`; 95 | const Test8 = styled.dev \` 96 | color: /* \${'red'} ... disabled */ blue; 97 | \`; 98 | const Test9 = styled.dev \` 99 | color: // \${'red'} ... disabled 100 | blue 101 | \`; 102 | export {}; 103 | 104 | 105 | TypeScript after transform: 106 | 107 | declare const styled: any; 108 | const Test1 = styled.div \`width:100%;//\${'red'}\`; 109 | const Test2 = styled.div \`width:100%;//\${'red'}\`; 110 | const Test3 = styled.div \`width:100%;\${'red'};\`; 111 | const Test4 = styled.div \`width:100%;//\${'red'}\`; 112 | const Test5 = styled.div \`width:100%;//\${'red'}\${'blue'}\`; 113 | const Test6 = styled.div \`background:url("https://google.com");width:100%;\${'green'}//\${'red'}\${'blue'}\`; 114 | const Test7 = styled.div \`background:url("https://google.com");width:\${p => p.props.width};\${'green'}//\${'red'}\${'blue'}\\nheight:\${p => p.props.height};\`; 115 | const Test8 = styled.dev \`color:/*\${'red'}*/blue;\`; 116 | const Test9 = styled.dev \`color://\${'red'}\\nblue\`; 117 | export {}; 118 | 119 | 120 | TypeScript after transpile module: 121 | 122 | const Test1 = styled.div \`width:100%;//\${'red'}\`; 123 | const Test2 = styled.div \`width:100%;//\${'red'}\`; 124 | const Test3 = styled.div \`width:100%;\${'red'};\`; 125 | const Test4 = styled.div \`width:100%;//\${'red'}\`; 126 | const Test5 = styled.div \`width:100%;//\${'red'}\${'blue'}\`; 127 | const Test6 = styled.div \`background:url("https://google.com");width:100%;\${'green'}//\${'red'}\${'blue'}\`; 128 | const Test7 = styled.div \`background:url("https://google.com");width:\${p => p.props.width};\${'green'}//\${'red'}\${'blue'}\\nheight:\${p => p.props.height};\`; 129 | const Test8 = styled.dev \`color:/*\${'red'}*/blue;\`; 130 | const Test9 = styled.dev \`color://\${'red'}\\nblue\`; 131 | export {}; 132 | 133 | 134 | 135 | `; 136 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification-only/simple.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`simple.ts 1`] = ` 4 | 5 | File: simple.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | declare const placeholder1: any; 11 | declare const placeholder2: any; 12 | 13 | // splits a line by potential comment starts and joins until one is an actual comment 14 | // \`abc def\` 15 | styled.div\`abc def//ghi//jkl\` 16 | 17 | // ignores comment markers that are inside strings 18 | // \`abc def"//"ghi\\'//\\'jkl\` 19 | styled.div\`abc def"//"ghi\\'//\\'jkl//the end\` 20 | // \`abc def"//"\` 21 | styled.div\`abc def"//"\` 22 | 23 | // ignores comment markers that are inside parantheses 24 | // \`bla (//) bla\` 25 | styled.div\`bla (//) bla//the end\` 26 | 27 | // ignores even unescaped URLs 28 | // \`https://test.com\` 29 | styled.div\`https://test.com// comment//\` 30 | 31 | // removes multi-line comments 32 | // \`this is a test\` 33 | styled.div\`this is a/* ignore me please */test\` 34 | 35 | // joins all lines of code 36 | // \`this is a test\` 37 | styled.div\`this\\nis\\na/* ignore me \\n please */\\ntest\` 38 | 39 | // removes line comments filling an entire line 40 | // \`line one{line:two;}\` 41 | styled.div\`line one { 42 | // remove this comment 43 | line: two; 44 | }\` 45 | 46 | // removes line comments at the end of lines of code 47 | // \`valid line with out comments\` 48 | styled.div\`valid line with // a comment 49 | out comments\` 50 | 51 | // preserves multi-line comments starting with /*! 52 | // \`this is a /*! dont ignore me please */ test\` 53 | styled.div\`this is a /*! dont ignore me please */ test/* but you can ignore me */\` 54 | 55 | // returns the indices of removed placeholders (expressions) 56 | // \`this is some input with \${placeholder1} and //\${placeholder2}\` 57 | styled.div\`this is some\\ninput with \${placeholder1} and // ignored \${placeholder2}\` 58 | 59 | // works with raw escape codes 60 | // \`this\\\\nis\\\\na \\\\ntest\` 61 | styled.div\`this\\\\nis\\\\na/* ignore me \\\\n please */\\\\ntest\` 62 | // \`this\\nis\\na \\ntest\` 63 | styled.div\`this\\nis\\na/* ignore me \\n please */\\ntest\` 64 | // \`this is a test\` 65 | styled.div\`this 66 | is 67 | a/* ignore me \\n please */ 68 | test\` 69 | 70 | // removes spaces around symbols 71 | // \`;:{},;\` 72 | styled.div\`; : { } , ; \` 73 | 74 | // ignores symbols inside strings 75 | // \`;" : "\\' : \\';\` 76 | styled.div\`; " : " \\' : \\' ;\` 77 | 78 | 79 | TypeScript before transform: 80 | 81 | declare const styled: any; 82 | declare const placeholder1: any; 83 | declare const placeholder2: any; 84 | // splits a line by potential comment starts and joins until one is an actual comment 85 | // \`abc def\` 86 | styled.div \`abc def//ghi//jkl\`; 87 | // ignores comment markers that are inside strings 88 | // \`abc def"//"ghi\\'//\\'jkl\` 89 | styled.div \`abc def"//"ghi\\'//\\'jkl//the end\`; 90 | // \`abc def"//"\` 91 | styled.div \`abc def"//"\`; 92 | // ignores comment markers that are inside parantheses 93 | // \`bla (//) bla\` 94 | styled.div \`bla (//) bla//the end\`; 95 | // ignores even unescaped URLs 96 | // \`https://test.com\` 97 | styled.div \`https://test.com// comment//\`; 98 | // removes multi-line comments 99 | // \`this is a test\` 100 | styled.div \`this is a/* ignore me please */test\`; 101 | // joins all lines of code 102 | // \`this is a test\` 103 | styled.div \`this\\nis\\na/* ignore me \\n please */\\ntest\`; 104 | // removes line comments filling an entire line 105 | // \`line one{line:two;}\` 106 | styled.div \`line one { 107 | // remove this comment 108 | line: two; 109 | }\`; 110 | // removes line comments at the end of lines of code 111 | // \`valid line with out comments\` 112 | styled.div \`valid line with // a comment 113 | out comments\`; 114 | // preserves multi-line comments starting with /*! 115 | // \`this is a /*! dont ignore me please */ test\` 116 | styled.div \`this is a /*! dont ignore me please */ test/* but you can ignore me */\`; 117 | // returns the indices of removed placeholders (expressions) 118 | // \`this is some input with \${placeholder1} and //\${placeholder2}\` 119 | styled.div \`this is some\\ninput with \${placeholder1} and // ignored \${placeholder2}\`; 120 | // works with raw escape codes 121 | // \`this\\\\nis\\\\na \\\\ntest\` 122 | styled.div \`this\\\\nis\\\\na/* ignore me \\\\n please */\\\\ntest\`; 123 | // \`this\\nis\\na \\ntest\` 124 | styled.div \`this\\nis\\na/* ignore me \\n please */\\ntest\`; 125 | // \`this is a test\` 126 | styled.div \`this 127 | is 128 | a/* ignore me \\n please */ 129 | test\`; 130 | // removes spaces around symbols 131 | // \`;:{},;\` 132 | styled.div \`; : { } , ; \`; 133 | // ignores symbols inside strings 134 | // \`;" : "\\' : \\';\` 135 | styled.div \`; " : " \\' : \\' ;\`; 136 | 137 | 138 | TypeScript after transform: 139 | 140 | declare const styled: any; 141 | declare const placeholder1: any; 142 | declare const placeholder2: any; 143 | // splits a line by potential comment starts and joins until one is an actual comment 144 | // \`abc def\` 145 | styled.div \`abc def\`; 146 | // ignores comment markers that are inside strings 147 | // \`abc def"//"ghi\\'//\\'jkl\` 148 | styled.div \`abc def"//"ghi'//'jkl\`; 149 | // \`abc def"//"\` 150 | styled.div \`abc def"//"\`; 151 | // ignores comment markers that are inside parantheses 152 | // \`bla (//) bla\` 153 | styled.div \`bla (//)bla\`; 154 | // ignores even unescaped URLs 155 | // \`https://test.com\` 156 | styled.div \`https:\`; 157 | // removes multi-line comments 158 | // \`this is a test\` 159 | styled.div \`this is a test\`; 160 | // joins all lines of code 161 | // \`this is a test\` 162 | styled.div \`this is a test\`; 163 | // removes line comments filling an entire line 164 | // \`line one{line:two;}\` 165 | styled.div \`line one{line:two;}\`; 166 | // removes line comments at the end of lines of code 167 | // \`valid line with out comments\` 168 | styled.div \`valid line with out comments\`; 169 | // preserves multi-line comments starting with /*! 170 | // \`this is a /*! dont ignore me please */ test\` 171 | styled.div \`this is a test\`; 172 | // returns the indices of removed placeholders (expressions) 173 | // \`this is some input with \${placeholder1} and //\${placeholder2}\` 174 | styled.div \`this is some input with \${placeholder1} and//\${placeholder2}\`; 175 | // works with raw escape codes 176 | // \`this\\\\nis\\\\na \\\\ntest\` 177 | styled.div \`this\\\\nis\\\\na \\\\ntest\`; 178 | // \`this\\nis\\na \\ntest\` 179 | styled.div \`this is a test\`; 180 | // \`this is a test\` 181 | styled.div \`this is a test\`; 182 | // removes spaces around symbols 183 | // \`;:{},;\` 184 | styled.div \`;:{},;\`; 185 | // ignores symbols inside strings 186 | // \`;" : "\\' : \\';\` 187 | styled.div \`;" : "' : ';\`; 188 | 189 | 190 | TypeScript after transpile module: 191 | 192 | // splits a line by potential comment starts and joins until one is an actual comment 193 | // \`abc def\` 194 | styled.div \`abc def\`; 195 | // ignores comment markers that are inside strings 196 | // \`abc def"//"ghi\\'//\\'jkl\` 197 | styled.div \`abc def"//"ghi'//'jkl\`; 198 | // \`abc def"//"\` 199 | styled.div \`abc def"//"\`; 200 | // ignores comment markers that are inside parantheses 201 | // \`bla (//) bla\` 202 | styled.div \`bla (//)bla\`; 203 | // ignores even unescaped URLs 204 | // \`https://test.com\` 205 | styled.div \`https:\`; 206 | // removes multi-line comments 207 | // \`this is a test\` 208 | styled.div \`this is a test\`; 209 | // joins all lines of code 210 | // \`this is a test\` 211 | styled.div \`this is a test\`; 212 | // removes line comments filling an entire line 213 | // \`line one{line:two;}\` 214 | styled.div \`line one{line:two;}\`; 215 | // removes line comments at the end of lines of code 216 | // \`valid line with out comments\` 217 | styled.div \`valid line with out comments\`; 218 | // preserves multi-line comments starting with /*! 219 | // \`this is a /*! dont ignore me please */ test\` 220 | styled.div \`this is a test\`; 221 | // returns the indices of removed placeholders (expressions) 222 | // \`this is some input with \${placeholder1} and //\${placeholder2}\` 223 | styled.div \`this is some input with \${placeholder1} and//\${placeholder2}\`; 224 | // works with raw escape codes 225 | // \`this\\\\nis\\\\na \\\\ntest\` 226 | styled.div \`this\\\\nis\\\\na \\\\ntest\`; 227 | // \`this\\nis\\na \\ntest\` 228 | styled.div \`this is a test\`; 229 | // \`this is a test\` 230 | styled.div \`this is a test\`; 231 | // removes spaces around symbols 232 | // \`;:{},;\` 233 | styled.div \`;:{},;\`; 234 | // ignores symbols inside strings 235 | // \`;" : "\\' : \\';\` 236 | styled.div \`;" : "' : ';\`; 237 | 238 | 239 | 240 | `; 241 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification-only/simple2.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`simple2.ts 1`] = ` 4 | 5 | File: simple2.ts 6 | Source code: 7 | 8 | export {} 9 | declare const styled: any; 10 | 11 | // spaces before and after ' " ( ) 12 | styled.div\`a b" c " d\` // \`a b" c "d\` 13 | styled.div\`a b' c ' d\` // \`a b' c 'd\` 14 | styled.div\`a b( c ) d\` // \`a b( c )d\` 15 | styled.div\`a b " c "d\` // \`a b " c "d\` 16 | styled.div\`a b ' c 'd\` // \`a b ' c 'd\` 17 | styled.div\`a b ( c )d\` // \`a b ( c )d\` 18 | 19 | 20 | TypeScript before transform: 21 | 22 | export {}; 23 | declare const styled: any; 24 | // spaces before and after ' " ( ) 25 | styled.div \`a b" c " d\`; // \`a b" c "d\` 26 | styled.div \`a b' c ' d\`; // \`a b' c 'd\` 27 | styled.div \`a b( c ) d\`; // \`a b( c )d\` 28 | styled.div \`a b " c "d\`; // \`a b " c "d\` 29 | styled.div \`a b ' c 'd\`; // \`a b ' c 'd\` 30 | styled.div \`a b ( c )d\`; // \`a b ( c )d\` 31 | 32 | 33 | TypeScript after transform: 34 | 35 | export {}; 36 | declare const styled: any; 37 | // spaces before and after ' " ( ) 38 | styled.div \`a b" c "d\`; // \`a b" c "d\` 39 | styled.div \`a b' c 'd\`; // \`a b' c 'd\` 40 | styled.div \`a b( c )d\`; // \`a b( c )d\` 41 | styled.div \`a b " c "d\`; // \`a b " c "d\` 42 | styled.div \`a b ' c 'd\`; // \`a b ' c 'd\` 43 | styled.div \`a b ( c )d\`; // \`a b ( c )d\` 44 | 45 | 46 | TypeScript after transpile module: 47 | 48 | // spaces before and after ' " ( ) 49 | styled.div \`a b" c "d\`; // \`a b" c "d\` 50 | styled.div \`a b' c 'd\`; // \`a b' c 'd\` 51 | styled.div \`a b( c )d\`; // \`a b( c )d\` 52 | styled.div \`a b " c "d\`; // \`a b " c "d\` 53 | styled.div \`a b ' c 'd\`; // \`a b ' c 'd\` 54 | styled.div \`a b ( c )d\`; // \`a b ( c )d\` 55 | export {}; 56 | 57 | 58 | 59 | `; 60 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification/issue142.tsx.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue142.tsx 1`] = ` 4 | 5 | File: issue142.tsx 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | const Header = styled.div\` 11 | display: flex; 12 | \\t align-items: center; 13 | justify-content: space-between; 14 | \\t \\t font-weight: 600; 15 | padding: 0.8em 1.6em;\\t \\t 16 | background: peachpuff; 17 | \`; 18 | 19 | 20 | TypeScript before transform: 21 | 22 | declare const styled: any; 23 | const Header = styled.div \` 24 | display: flex; 25 | \\t align-items: center; 26 | justify-content: space-between; 27 | \\t \\t font-weight: 600; 28 | padding: 0.8em 1.6em;\\t \\t 29 | background: peachpuff; 30 | \`; 31 | 32 | 33 | TypeScript after transform: 34 | 35 | declare const styled: any; 36 | const Header = styled.div.withConfig({ displayName: "Header" }) \`display:flex;align-items:center;justify-content:space-between;font-weight:600;padding:0.8em 1.6em;background:peachpuff;\`; 37 | 38 | 39 | TypeScript after transpile module: 40 | 41 | const Header = styled.div.withConfig({ displayName: "Header" }) \`display:flex;align-items:center;justify-content:space-between;font-weight:600;padding:0.8em 1.6em;background:peachpuff;\`; 42 | 43 | 44 | 45 | `; 46 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification/issue233.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue233.ts 1`] = ` 4 | 5 | File: issue233.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | // repro from #233 11 | const ValueCalc = styled.div\` 12 | height: calc(var(--line-height) - 5px); 13 | width: calc(100% - 5px); 14 | \`; 15 | 16 | // another case from #233 17 | styled.div\`--padding-button: calc(var(--padding-button-vertical) - 2px) calc(var(--padding-button-horizontal) - 2px);\` 18 | 19 | // a few more cases 20 | styled.div\` 21 | width: calc( 1%) 22 | width: calc( 1% + var(--a) - calc(2%)) 23 | width: calc( 1% + var(--a) - calc(2%) + calc( 1px + calc(1px + 2px) + var(--a))) 24 | \` 25 | 26 | 27 | TypeScript before transform: 28 | 29 | declare const styled: any; 30 | // repro from #233 31 | const ValueCalc = styled.div \` 32 | height: calc(var(--line-height) - 5px); 33 | width: calc(100% - 5px); 34 | \`; 35 | // another case from #233 36 | styled.div \`--padding-button: calc(var(--padding-button-vertical) - 2px) calc(var(--padding-button-horizontal) - 2px);\`; 37 | // a few more cases 38 | styled.div \` 39 | width: calc( 1%) 40 | width: calc( 1% + var(--a) - calc(2%)) 41 | width: calc( 1% + var(--a) - calc(2%) + calc( 1px + calc(1px + 2px) + var(--a))) 42 | \`; 43 | 44 | 45 | TypeScript after transform: 46 | 47 | declare const styled: any; 48 | // repro from #233 49 | const ValueCalc = styled.div.withConfig({ displayName: "ValueCalc" }) \`height:calc(var(--line-height) - 5px);width:calc(100% - 5px);\`; 50 | // another case from #233 51 | styled.div \`--padding-button:calc(var(--padding-button-vertical) - 2px)calc(var(--padding-button-horizontal) - 2px);\`; 52 | // a few more cases 53 | styled.div \`width:calc( 1%)width:calc( 1% + var(--a) - calc(2%))width:calc( 1% + var(--a) - calc(2%) + calc( 1px + calc(1px + 2px) + var(--a)))\`; 54 | 55 | 56 | TypeScript after transpile module: 57 | 58 | // repro from #233 59 | const ValueCalc = styled.div.withConfig({ displayName: "ValueCalc" }) \`height:calc(var(--line-height) - 5px);width:calc(100% - 5px);\`; 60 | // another case from #233 61 | styled.div \`--padding-button:calc(var(--padding-button-vertical) - 2px)calc(var(--padding-button-horizontal) - 2px);\`; 62 | // a few more cases 63 | styled.div \`width:calc( 1%)width:calc( 1% + var(--a) - calc(2%))width:calc( 1% + var(--a) - calc(2%) + calc( 1px + calc(1px + 2px) + var(--a)))\`; 64 | 65 | 66 | 67 | `; 68 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification/issue36-extended.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue36-extended.ts 1`] = ` 4 | 5 | File: issue36-extended.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | export const A = styled.div\` 11 | border: \${'solid'} 10px; 12 | \` 13 | 14 | styled.div\` 15 | border: \${'solid'}// comment here 16 | 10px; 17 | border: solid// comment here 18 | 10px; 19 | \` 20 | 21 | styled.div\` 22 | border: \${'solid'}/* comment here 23 | */10px; 24 | border: \${'solid'}/* comment here 25 | */ 10px; 26 | \` 27 | 28 | 29 | TypeScript before transform: 30 | 31 | declare const styled: any; 32 | export const A = styled.div \` 33 | border: \${'solid'} 10px; 34 | \`; 35 | styled.div \` 36 | border: \${'solid'}// comment here 37 | 10px; 38 | border: solid// comment here 39 | 10px; 40 | \`; 41 | styled.div \` 42 | border: \${'solid'}/* comment here 43 | */10px; 44 | border: \${'solid'}/* comment here 45 | */ 10px; 46 | \`; 47 | 48 | 49 | TypeScript after transform: 50 | 51 | declare const styled: any; 52 | export const A = styled.div.withConfig({ displayName: "A" }) \`border:\${'solid'} 10px;\`; 53 | styled.div \`border:\${'solid'} 10px;border:solid 10px;\`; 54 | styled.div \`border:\${'solid'} 10px;border:\${'solid'} 10px;\`; 55 | 56 | 57 | TypeScript after transpile module: 58 | 59 | export const A = styled.div.withConfig({ displayName: "A" }) \`border:\${'solid'} 10px;\`; 60 | styled.div \`border:\${'solid'} 10px;border:solid 10px;\`; 61 | styled.div \`border:\${'solid'} 10px;border:\${'solid'} 10px;\`; 62 | 63 | 64 | 65 | `; 66 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification/issue36.tsx.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue36.tsx 1`] = ` 4 | 5 | File: issue36.tsx 6 | Source code: 7 | 8 | declare const keyframes: any; 9 | declare const styled: any; 10 | 11 | const rotate360 = keyframes\` 12 | from { 13 | transform: rotate(0deg); 14 | } 15 | to { 16 | transform: rotate(360deg); 17 | } 18 | \`; 19 | 20 | export const StyledDiv = styled.div\` 21 | width: 100px; 22 | height: 100px; 23 | background-color: greenyellow; 24 | animation: \${rotate360} 2s linear infinite; 25 | \`; 26 | 27 | 28 | TypeScript before transform: 29 | 30 | declare const keyframes: any; 31 | declare const styled: any; 32 | const rotate360 = keyframes \` 33 | from { 34 | transform: rotate(0deg); 35 | } 36 | to { 37 | transform: rotate(360deg); 38 | } 39 | \`; 40 | export const StyledDiv = styled.div \` 41 | width: 100px; 42 | height: 100px; 43 | background-color: greenyellow; 44 | animation: \${rotate360} 2s linear infinite; 45 | \`; 46 | 47 | 48 | TypeScript after transform: 49 | 50 | declare const keyframes: any; 51 | declare const styled: any; 52 | const rotate360 = keyframes \`from{transform:rotate(0deg);}to{transform:rotate(360deg);}\`; 53 | export const StyledDiv = styled.div.withConfig({ displayName: "StyledDiv" }) \`width:100px;height:100px;background-color:greenyellow;animation:\${rotate360} 2s linear infinite;\`; 54 | 55 | 56 | TypeScript after transpile module: 57 | 58 | const rotate360 = keyframes \`from{transform:rotate(0deg);}to{transform:rotate(360deg);}\`; 59 | export const StyledDiv = styled.div.withConfig({ displayName: "StyledDiv" }) \`width:100px;height:100px;background-color:greenyellow;animation:\${rotate360} 2s linear infinite;\`; 60 | 61 | 62 | 63 | `; 64 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification/issue40.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue40.ts 1`] = ` 4 | 5 | File: issue40.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | styled.div\`padding: 0 0 13px \${'50px'};\` 11 | 12 | 13 | TypeScript before transform: 14 | 15 | declare const styled: any; 16 | styled.div \`padding: 0 0 13px \${'50px'};\`; 17 | 18 | 19 | TypeScript after transform: 20 | 21 | declare const styled: any; 22 | styled.div \`padding:0 0 13px \${'50px'};\`; 23 | 24 | 25 | TypeScript after transpile module: 26 | 27 | styled.div \`padding:0 0 13px \${'50px'};\`; 28 | 29 | 30 | 31 | `; 32 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification/issue44.tsx.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue44.tsx 1`] = ` 4 | 5 | File: issue44.tsx 6 | Source code: 7 | 8 | declare const styled: any; 9 | styled.div\` transition: width \${100}ms ease-in;\`; 10 | styled.div\` transition: width \${'100ms'} ease-in;\`; 11 | 12 | 13 | TypeScript before transform: 14 | 15 | declare const styled: any; 16 | styled.div \` transition: width \${100}ms ease-in;\`; 17 | styled.div \` transition: width \${'100ms'} ease-in;\`; 18 | 19 | 20 | TypeScript after transform: 21 | 22 | declare const styled: any; 23 | styled.div \`transition:width \${100}ms ease-in;\`; 24 | styled.div \`transition:width \${'100ms'} ease-in;\`; 25 | 26 | 27 | TypeScript after transpile module: 28 | 29 | styled.div \`transition:width \${100}ms ease-in;\`; 30 | styled.div \`transition:width \${'100ms'} ease-in;\`; 31 | 32 | 33 | 34 | `; 35 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification/minify-css-in-helpers.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`minify-css-in-helpers.ts 1`] = ` 4 | 5 | File: minify-css-in-helpers.ts 6 | Source code: 7 | 8 | declare const keyframes: any; 9 | declare const css: any; 10 | declare const createGlobalStyle: any; 11 | 12 | declare const theColor: any; 13 | 14 | const key = keyframes\` 15 | to { 16 | transform: rotate(360deg); 17 | } 18 | \`; 19 | 20 | const color = css\` 21 | color: \${theColor}; 22 | \`; 23 | 24 | const MyRedBody = createGlobalStyle\` 25 | body { 26 | background-color: red; // comments 27 | \${color} // comments 28 | // it will be ignored, but still emitted \${color} 29 | } 30 | \`; 31 | 32 | export {}; 33 | 34 | 35 | TypeScript before transform: 36 | 37 | declare const keyframes: any; 38 | declare const css: any; 39 | declare const createGlobalStyle: any; 40 | declare const theColor: any; 41 | const key = keyframes \` 42 | to { 43 | transform: rotate(360deg); 44 | } 45 | \`; 46 | const color = css \` 47 | color: \${theColor}; 48 | \`; 49 | const MyRedBody = createGlobalStyle \` 50 | body { 51 | background-color: red; // comments 52 | \${color} // comments 53 | // it will be ignored, but still emitted \${color} 54 | } 55 | \`; 56 | export {}; 57 | 58 | 59 | TypeScript after transform: 60 | 61 | declare const keyframes: any; 62 | declare const css: any; 63 | declare const createGlobalStyle: any; 64 | declare const theColor: any; 65 | const key = keyframes \`to{transform:rotate(360deg);}\`; 66 | const color = css \`color:\${theColor};\`; 67 | const MyRedBody = createGlobalStyle \`body{background-color:red;\${color}//\${color}\\n}\`; 68 | export {}; 69 | 70 | 71 | TypeScript after transpile module: 72 | 73 | const key = keyframes \`to{transform:rotate(360deg);}\`; 74 | const color = css \`color:\${theColor};\`; 75 | const MyRedBody = createGlobalStyle \`body{background-color:red;\${color}//\${color}\\n}\`; 76 | export {}; 77 | 78 | 79 | 80 | `; 81 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification/minify-css-to-use-with-transpilation.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`minify-css-to-use-with-transpilation.ts 1`] = ` 4 | 5 | File: minify-css-to-use-with-transpilation.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | const Simple = styled.div\` 11 | width: 100%; 12 | \`; 13 | 14 | const Interpolation = styled.div\` 15 | content: " \${props => props.text} "; 16 | \`; 17 | 18 | const SpecialCharacters = styled.div\` 19 | content: " \${props => props.text} ";\\n color: red; 20 | \`; 21 | 22 | const Comment = styled.div\` 23 | // comment 24 | color: red; 25 | \` 26 | 27 | const Parens = styled.div\` 28 | &:hover { 29 | color: blue; 30 | } 31 | \`; 32 | 33 | export {}; 34 | 35 | 36 | TypeScript before transform: 37 | 38 | declare const styled: any; 39 | const Simple = styled.div \` 40 | width: 100%; 41 | \`; 42 | const Interpolation = styled.div \` 43 | content: " \${props => props.text} "; 44 | \`; 45 | const SpecialCharacters = styled.div \` 46 | content: " \${props => props.text} ";\\n color: red; 47 | \`; 48 | const Comment = styled.div \` 49 | // comment 50 | color: red; 51 | \`; 52 | const Parens = styled.div \` 53 | &:hover { 54 | color: blue; 55 | } 56 | \`; 57 | export {}; 58 | 59 | 60 | TypeScript after transform: 61 | 62 | declare const styled: any; 63 | const Simple = styled.div.withConfig({ displayName: "Simple" }) \`width:100%;\`; 64 | const Interpolation = styled.div.withConfig({ displayName: "Interpolation" }) \`content:" \${props => props.text} ";\`; 65 | const SpecialCharacters = styled.div.withConfig({ displayName: "SpecialCharacters" }) \`content:" \${props => props.text} ";color:red;\`; 66 | const Comment = styled.div.withConfig({ displayName: "Comment" }) \`color:red;\`; 67 | const Parens = styled.div.withConfig({ displayName: "Parens" }) \`&:hover{color:blue;}\`; 68 | export {}; 69 | 70 | 71 | TypeScript after transpile module: 72 | 73 | const Simple = styled.div.withConfig({ displayName: "Simple" }) \`width:100%;\`; 74 | const Interpolation = styled.div.withConfig({ displayName: "Interpolation" }) \`content:" \${props => props.text} ";\`; 75 | const SpecialCharacters = styled.div.withConfig({ displayName: "SpecialCharacters" }) \`content:" \${props => props.text} ";color:red;\`; 76 | const Comment = styled.div.withConfig({ displayName: "Comment" }) \`color:red;\`; 77 | const Parens = styled.div.withConfig({ displayName: "Parens" }) \`&:hover{color:blue;}\`; 78 | export {}; 79 | 80 | 81 | 82 | `; 83 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification/minify-css-to-use-without-transpilation.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`minify-css-to-use-without-transpilation.ts 1`] = ` 4 | 5 | File: minify-css-to-use-without-transpilation.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | const Simple = styled.div\` 11 | width: 100%; 12 | \`; 13 | 14 | const Interpolation = styled.div\` 15 | content: "https://test.com/\${props => props.endpoint}"; 16 | \`; 17 | 18 | const SpecialCharacters = styled.div\` 19 | content: " \${props => props.text} ";\\n color: red; 20 | \`; 21 | 22 | const Comment = styled.div\` 23 | width: 100%; 24 | // comment 25 | color: red; 26 | \`; 27 | 28 | const Parens = styled.div\` 29 | &:hover { 30 | color: blue; 31 | } 32 | color: red; 33 | \`; 34 | 35 | const UrlComments = styled.div\` 36 | color: red; 37 | /* // */ 38 | background: red; 39 | /* comment 1 */ 40 | /* comment 2 */ 41 | // comment 3 42 | border: 1px solid green; 43 | \`; 44 | 45 | export {}; 46 | 47 | 48 | TypeScript before transform: 49 | 50 | declare const styled: any; 51 | const Simple = styled.div \` 52 | width: 100%; 53 | \`; 54 | const Interpolation = styled.div \` 55 | content: "https://test.com/\${props => props.endpoint}"; 56 | \`; 57 | const SpecialCharacters = styled.div \` 58 | content: " \${props => props.text} ";\\n color: red; 59 | \`; 60 | const Comment = styled.div \` 61 | width: 100%; 62 | // comment 63 | color: red; 64 | \`; 65 | const Parens = styled.div \` 66 | &:hover { 67 | color: blue; 68 | } 69 | color: red; 70 | \`; 71 | const UrlComments = styled.div \` 72 | color: red; 73 | /* // */ 74 | background: red; 75 | /* comment 1 */ 76 | /* comment 2 */ 77 | // comment 3 78 | border: 1px solid green; 79 | \`; 80 | export {}; 81 | 82 | 83 | TypeScript after transform: 84 | 85 | declare const styled: any; 86 | const Simple = styled.div.withConfig({ displayName: "Simple" }) \`width:100%;\`; 87 | const Interpolation = styled.div.withConfig({ displayName: "Interpolation" }) \`content:"https://test.com/\${props => props.endpoint}";\`; 88 | const SpecialCharacters = styled.div.withConfig({ displayName: "SpecialCharacters" }) \`content:" \${props => props.text} ";color:red;\`; 89 | const Comment = styled.div.withConfig({ displayName: "Comment" }) \`width:100%;color:red;\`; 90 | const Parens = styled.div.withConfig({ displayName: "Parens" }) \`&:hover{color:blue;}color:red;\`; 91 | const UrlComments = styled.div.withConfig({ displayName: "UrlComments" }) \`color:red;background:red;border:1px solid green;\`; 92 | export {}; 93 | 94 | 95 | TypeScript after transpile module: 96 | 97 | const Simple = styled.div.withConfig({ displayName: "Simple" }) \`width:100%;\`; 98 | const Interpolation = styled.div.withConfig({ displayName: "Interpolation" }) \`content:"https://test.com/\${props => props.endpoint}";\`; 99 | const SpecialCharacters = styled.div.withConfig({ displayName: "SpecialCharacters" }) \`content:" \${props => props.text} ";color:red;\`; 100 | const Comment = styled.div.withConfig({ displayName: "Comment" }) \`width:100%;color:red;\`; 101 | const Parens = styled.div.withConfig({ displayName: "Parens" }) \`&:hover{color:blue;}color:red;\`; 102 | const UrlComments = styled.div.withConfig({ displayName: "UrlComments" }) \`color:red;background:red;border:1px solid green;\`; 103 | export {}; 104 | 105 | 106 | 107 | `; 108 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification/minify-single-line-comments-with-interpolations.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`minify-single-line-comments-with-interpolations.ts 1`] = ` 4 | 5 | File: minify-single-line-comments-with-interpolations.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | const Test1 = styled.div\` 11 | width: 100%; 12 | // color: \${'red'}; 13 | \` 14 | 15 | const Test2 = styled.div\` 16 | width: 100%; 17 | // color: pale\${'red'}; 18 | \` 19 | 20 | const Test3 = styled.div\` 21 | width: 100%; 22 | // color 23 | \${'red'}; 24 | \` 25 | 26 | const Test4 = styled.div\` 27 | width: 100%; 28 | // color: \${'red'}-blue; 29 | \` 30 | 31 | const Test5 = styled.div\` 32 | width: 100%; 33 | // color: \${'red'}\${'blue'}; 34 | \` 35 | 36 | const Test6 = styled.div\` 37 | background: url("https://google.com"); 38 | width: 100%; 39 | \${'green'} // color: \${'red'}\${'blue'}; 40 | \` 41 | 42 | const Test7 = styled.div\` 43 | background: url("https://google.com"); 44 | width: \${p => p.props.width}; 45 | \${'green'} // color: \${'red'}\${'blue'}; 46 | height: \${p => p.props.height}; 47 | \` 48 | 49 | const Test8 = styled.dev\` 50 | color: /* \${'red'} ... disabled */ blue; 51 | \`; 52 | 53 | const Test9 = styled.dev\` 54 | color: // \${'red'} ... disabled 55 | blue 56 | \`; 57 | 58 | export {} 59 | 60 | TypeScript before transform: 61 | 62 | declare const styled: any; 63 | const Test1 = styled.div \` 64 | width: 100%; 65 | // color: \${'red'}; 66 | \`; 67 | const Test2 = styled.div \` 68 | width: 100%; 69 | // color: pale\${'red'}; 70 | \`; 71 | const Test3 = styled.div \` 72 | width: 100%; 73 | // color 74 | \${'red'}; 75 | \`; 76 | const Test4 = styled.div \` 77 | width: 100%; 78 | // color: \${'red'}-blue; 79 | \`; 80 | const Test5 = styled.div \` 81 | width: 100%; 82 | // color: \${'red'}\${'blue'}; 83 | \`; 84 | const Test6 = styled.div \` 85 | background: url("https://google.com"); 86 | width: 100%; 87 | \${'green'} // color: \${'red'}\${'blue'}; 88 | \`; 89 | const Test7 = styled.div \` 90 | background: url("https://google.com"); 91 | width: \${p => p.props.width}; 92 | \${'green'} // color: \${'red'}\${'blue'}; 93 | height: \${p => p.props.height}; 94 | \`; 95 | const Test8 = styled.dev \` 96 | color: /* \${'red'} ... disabled */ blue; 97 | \`; 98 | const Test9 = styled.dev \` 99 | color: // \${'red'} ... disabled 100 | blue 101 | \`; 102 | export {}; 103 | 104 | 105 | TypeScript after transform: 106 | 107 | declare const styled: any; 108 | const Test1 = styled.div.withConfig({ displayName: "Test1" }) \`width:100%;//\${'red'}\`; 109 | const Test2 = styled.div.withConfig({ displayName: "Test2" }) \`width:100%;//\${'red'}\`; 110 | const Test3 = styled.div.withConfig({ displayName: "Test3" }) \`width:100%;\${'red'};\`; 111 | const Test4 = styled.div.withConfig({ displayName: "Test4" }) \`width:100%;//\${'red'}\`; 112 | const Test5 = styled.div.withConfig({ displayName: "Test5" }) \`width:100%;//\${'red'}\${'blue'}\`; 113 | const Test6 = styled.div.withConfig({ displayName: "Test6" }) \`background:url("https://google.com");width:100%;\${'green'}//\${'red'}\${'blue'}\`; 114 | const Test7 = styled.div.withConfig({ displayName: "Test7" }) \`background:url("https://google.com");width:\${p => p.props.width};\${'green'}//\${'red'}\${'blue'}\\nheight:\${p => p.props.height};\`; 115 | const Test8 = styled.dev.withConfig({ displayName: "Test8" }) \`color:/*\${'red'}*/blue;\`; 116 | const Test9 = styled.dev.withConfig({ displayName: "Test9" }) \`color://\${'red'}\\nblue\`; 117 | export {}; 118 | 119 | 120 | TypeScript after transpile module: 121 | 122 | const Test1 = styled.div.withConfig({ displayName: "Test1" }) \`width:100%;//\${'red'}\`; 123 | const Test2 = styled.div.withConfig({ displayName: "Test2" }) \`width:100%;//\${'red'}\`; 124 | const Test3 = styled.div.withConfig({ displayName: "Test3" }) \`width:100%;\${'red'};\`; 125 | const Test4 = styled.div.withConfig({ displayName: "Test4" }) \`width:100%;//\${'red'}\`; 126 | const Test5 = styled.div.withConfig({ displayName: "Test5" }) \`width:100%;//\${'red'}\${'blue'}\`; 127 | const Test6 = styled.div.withConfig({ displayName: "Test6" }) \`background:url("https://google.com");width:100%;\${'green'}//\${'red'}\${'blue'}\`; 128 | const Test7 = styled.div.withConfig({ displayName: "Test7" }) \`background:url("https://google.com");width:\${p => p.props.width};\${'green'}//\${'red'}\${'blue'}\\nheight:\${p => p.props.height};\`; 129 | const Test8 = styled.dev.withConfig({ displayName: "Test8" }) \`color:/*\${'red'}*/blue;\`; 130 | const Test9 = styled.dev.withConfig({ displayName: "Test9" }) \`color://\${'red'}\\nblue\`; 131 | export {}; 132 | 133 | 134 | 135 | `; 136 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification/simple.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`simple.ts 1`] = ` 4 | 5 | File: simple.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | declare const placeholder1: any; 11 | declare const placeholder2: any; 12 | 13 | // splits a line by potential comment starts and joins until one is an actual comment 14 | // \`abc def\` 15 | styled.div\`abc def//ghi//jkl\` 16 | 17 | // ignores comment markers that are inside strings 18 | // \`abc def"//"ghi\\'//\\'jkl\` 19 | styled.div\`abc def"//"ghi\\'//\\'jkl//the end\` 20 | // \`abc def"//"\` 21 | styled.div\`abc def"//"\` 22 | 23 | // ignores comment markers that are inside parantheses 24 | // \`bla (//) bla\` 25 | styled.div\`bla (//) bla//the end\` 26 | 27 | // ignores even unescaped URLs 28 | // \`https://test.com\` 29 | styled.div\`https://test.com// comment//\` 30 | 31 | // removes multi-line comments 32 | // \`this is a test\` 33 | styled.div\`this is a/* ignore me please */test\` 34 | 35 | // joins all lines of code 36 | // \`this is a test\` 37 | styled.div\`this\\nis\\na/* ignore me \\n please */\\ntest\` 38 | 39 | // removes line comments filling an entire line 40 | // \`line one{line:two;}\` 41 | styled.div\`line one { 42 | // remove this comment 43 | line: two; 44 | }\` 45 | 46 | // removes line comments at the end of lines of code 47 | // \`valid line with out comments\` 48 | styled.div\`valid line with // a comment 49 | out comments\` 50 | 51 | // preserves multi-line comments starting with /*! 52 | // \`this is a /*! dont ignore me please */ test\` 53 | styled.div\`this is a /*! dont ignore me please */ test/* but you can ignore me */\` 54 | 55 | // returns the indices of removed placeholders (expressions) 56 | // \`this is some input with \${placeholder1} and //\${placeholder2}\` 57 | styled.div\`this is some\\ninput with \${placeholder1} and // ignored \${placeholder2}\` 58 | 59 | // works with raw escape codes 60 | // \`this\\\\nis\\\\na \\\\ntest\` 61 | styled.div\`this\\\\nis\\\\na/* ignore me \\\\n please */\\\\ntest\` 62 | // \`this\\nis\\na \\ntest\` 63 | styled.div\`this\\nis\\na/* ignore me \\n please */\\ntest\` 64 | // \`this is a test\` 65 | styled.div\`this 66 | is 67 | a/* ignore me \\n please */ 68 | test\` 69 | 70 | // removes spaces around symbols 71 | // \`;:{},;\` 72 | styled.div\`; : { } , ; \` 73 | 74 | // ignores symbols inside strings 75 | // \`;" : "\\' : \\';\` 76 | styled.div\`; " : " \\' : \\' ;\` 77 | 78 | 79 | TypeScript before transform: 80 | 81 | declare const styled: any; 82 | declare const placeholder1: any; 83 | declare const placeholder2: any; 84 | // splits a line by potential comment starts and joins until one is an actual comment 85 | // \`abc def\` 86 | styled.div \`abc def//ghi//jkl\`; 87 | // ignores comment markers that are inside strings 88 | // \`abc def"//"ghi\\'//\\'jkl\` 89 | styled.div \`abc def"//"ghi\\'//\\'jkl//the end\`; 90 | // \`abc def"//"\` 91 | styled.div \`abc def"//"\`; 92 | // ignores comment markers that are inside parantheses 93 | // \`bla (//) bla\` 94 | styled.div \`bla (//) bla//the end\`; 95 | // ignores even unescaped URLs 96 | // \`https://test.com\` 97 | styled.div \`https://test.com// comment//\`; 98 | // removes multi-line comments 99 | // \`this is a test\` 100 | styled.div \`this is a/* ignore me please */test\`; 101 | // joins all lines of code 102 | // \`this is a test\` 103 | styled.div \`this\\nis\\na/* ignore me \\n please */\\ntest\`; 104 | // removes line comments filling an entire line 105 | // \`line one{line:two;}\` 106 | styled.div \`line one { 107 | // remove this comment 108 | line: two; 109 | }\`; 110 | // removes line comments at the end of lines of code 111 | // \`valid line with out comments\` 112 | styled.div \`valid line with // a comment 113 | out comments\`; 114 | // preserves multi-line comments starting with /*! 115 | // \`this is a /*! dont ignore me please */ test\` 116 | styled.div \`this is a /*! dont ignore me please */ test/* but you can ignore me */\`; 117 | // returns the indices of removed placeholders (expressions) 118 | // \`this is some input with \${placeholder1} and //\${placeholder2}\` 119 | styled.div \`this is some\\ninput with \${placeholder1} and // ignored \${placeholder2}\`; 120 | // works with raw escape codes 121 | // \`this\\\\nis\\\\na \\\\ntest\` 122 | styled.div \`this\\\\nis\\\\na/* ignore me \\\\n please */\\\\ntest\`; 123 | // \`this\\nis\\na \\ntest\` 124 | styled.div \`this\\nis\\na/* ignore me \\n please */\\ntest\`; 125 | // \`this is a test\` 126 | styled.div \`this 127 | is 128 | a/* ignore me \\n please */ 129 | test\`; 130 | // removes spaces around symbols 131 | // \`;:{},;\` 132 | styled.div \`; : { } , ; \`; 133 | // ignores symbols inside strings 134 | // \`;" : "\\' : \\';\` 135 | styled.div \`; " : " \\' : \\' ;\`; 136 | 137 | 138 | TypeScript after transform: 139 | 140 | declare const styled: any; 141 | declare const placeholder1: any; 142 | declare const placeholder2: any; 143 | // splits a line by potential comment starts and joins until one is an actual comment 144 | // \`abc def\` 145 | styled.div \`abc def\`; 146 | // ignores comment markers that are inside strings 147 | // \`abc def"//"ghi\\'//\\'jkl\` 148 | styled.div \`abc def"//"ghi'//'jkl\`; 149 | // \`abc def"//"\` 150 | styled.div \`abc def"//"\`; 151 | // ignores comment markers that are inside parantheses 152 | // \`bla (//) bla\` 153 | styled.div \`bla (//)bla\`; 154 | // ignores even unescaped URLs 155 | // \`https://test.com\` 156 | styled.div \`https:\`; 157 | // removes multi-line comments 158 | // \`this is a test\` 159 | styled.div \`this is a test\`; 160 | // joins all lines of code 161 | // \`this is a test\` 162 | styled.div \`this is a test\`; 163 | // removes line comments filling an entire line 164 | // \`line one{line:two;}\` 165 | styled.div \`line one{line:two;}\`; 166 | // removes line comments at the end of lines of code 167 | // \`valid line with out comments\` 168 | styled.div \`valid line with out comments\`; 169 | // preserves multi-line comments starting with /*! 170 | // \`this is a /*! dont ignore me please */ test\` 171 | styled.div \`this is a test\`; 172 | // returns the indices of removed placeholders (expressions) 173 | // \`this is some input with \${placeholder1} and //\${placeholder2}\` 174 | styled.div \`this is some input with \${placeholder1} and//\${placeholder2}\`; 175 | // works with raw escape codes 176 | // \`this\\\\nis\\\\na \\\\ntest\` 177 | styled.div \`this\\\\nis\\\\na \\\\ntest\`; 178 | // \`this\\nis\\na \\ntest\` 179 | styled.div \`this is a test\`; 180 | // \`this is a test\` 181 | styled.div \`this is a test\`; 182 | // removes spaces around symbols 183 | // \`;:{},;\` 184 | styled.div \`;:{},;\`; 185 | // ignores symbols inside strings 186 | // \`;" : "\\' : \\';\` 187 | styled.div \`;" : "' : ';\`; 188 | 189 | 190 | TypeScript after transpile module: 191 | 192 | // splits a line by potential comment starts and joins until one is an actual comment 193 | // \`abc def\` 194 | styled.div \`abc def\`; 195 | // ignores comment markers that are inside strings 196 | // \`abc def"//"ghi\\'//\\'jkl\` 197 | styled.div \`abc def"//"ghi'//'jkl\`; 198 | // \`abc def"//"\` 199 | styled.div \`abc def"//"\`; 200 | // ignores comment markers that are inside parantheses 201 | // \`bla (//) bla\` 202 | styled.div \`bla (//)bla\`; 203 | // ignores even unescaped URLs 204 | // \`https://test.com\` 205 | styled.div \`https:\`; 206 | // removes multi-line comments 207 | // \`this is a test\` 208 | styled.div \`this is a test\`; 209 | // joins all lines of code 210 | // \`this is a test\` 211 | styled.div \`this is a test\`; 212 | // removes line comments filling an entire line 213 | // \`line one{line:two;}\` 214 | styled.div \`line one{line:two;}\`; 215 | // removes line comments at the end of lines of code 216 | // \`valid line with out comments\` 217 | styled.div \`valid line with out comments\`; 218 | // preserves multi-line comments starting with /*! 219 | // \`this is a /*! dont ignore me please */ test\` 220 | styled.div \`this is a test\`; 221 | // returns the indices of removed placeholders (expressions) 222 | // \`this is some input with \${placeholder1} and //\${placeholder2}\` 223 | styled.div \`this is some input with \${placeholder1} and//\${placeholder2}\`; 224 | // works with raw escape codes 225 | // \`this\\\\nis\\\\na \\\\ntest\` 226 | styled.div \`this\\\\nis\\\\na \\\\ntest\`; 227 | // \`this\\nis\\na \\ntest\` 228 | styled.div \`this is a test\`; 229 | // \`this is a test\` 230 | styled.div \`this is a test\`; 231 | // removes spaces around symbols 232 | // \`;:{},;\` 233 | styled.div \`;:{},;\`; 234 | // ignores symbols inside strings 235 | // \`;" : "\\' : \\';\` 236 | styled.div \`;" : "' : ';\`; 237 | 238 | 239 | 240 | `; 241 | -------------------------------------------------------------------------------- /src/__tests__/baselines/minification/simple2.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`simple2.ts 1`] = ` 4 | 5 | File: simple2.ts 6 | Source code: 7 | 8 | export {} 9 | declare const styled: any; 10 | 11 | // spaces before and after ' " ( ) 12 | styled.div\`a b" c " d\` // \`a b" c "d\` 13 | styled.div\`a b' c ' d\` // \`a b' c 'd\` 14 | styled.div\`a b( c ) d\` // \`a b( c )d\` 15 | styled.div\`a b " c "d\` // \`a b " c "d\` 16 | styled.div\`a b ' c 'd\` // \`a b ' c 'd\` 17 | styled.div\`a b ( c )d\` // \`a b ( c )d\` 18 | 19 | 20 | TypeScript before transform: 21 | 22 | export {}; 23 | declare const styled: any; 24 | // spaces before and after ' " ( ) 25 | styled.div \`a b" c " d\`; // \`a b" c "d\` 26 | styled.div \`a b' c ' d\`; // \`a b' c 'd\` 27 | styled.div \`a b( c ) d\`; // \`a b( c )d\` 28 | styled.div \`a b " c "d\`; // \`a b " c "d\` 29 | styled.div \`a b ' c 'd\`; // \`a b ' c 'd\` 30 | styled.div \`a b ( c )d\`; // \`a b ( c )d\` 31 | 32 | 33 | TypeScript after transform: 34 | 35 | export {}; 36 | declare const styled: any; 37 | // spaces before and after ' " ( ) 38 | styled.div \`a b" c "d\`; // \`a b" c "d\` 39 | styled.div \`a b' c 'd\`; // \`a b' c 'd\` 40 | styled.div \`a b( c )d\`; // \`a b( c )d\` 41 | styled.div \`a b " c "d\`; // \`a b " c "d\` 42 | styled.div \`a b ' c 'd\`; // \`a b ' c 'd\` 43 | styled.div \`a b ( c )d\`; // \`a b ( c )d\` 44 | 45 | 46 | TypeScript after transpile module: 47 | 48 | // spaces before and after ' " ( ) 49 | styled.div \`a b" c "d\`; // \`a b" c "d\` 50 | styled.div \`a b' c 'd\`; // \`a b' c 'd\` 51 | styled.div \`a b( c )d\`; // \`a b( c )d\` 52 | styled.div \`a b " c "d\`; // \`a b " c "d\` 53 | styled.div \`a b ' c 'd\`; // \`a b ' c 'd\` 54 | styled.div \`a b ( c )d\`; // \`a b ( c )d\` 55 | export {}; 56 | 57 | 58 | 59 | `; 60 | -------------------------------------------------------------------------------- /src/__tests__/baselines/ssr/issue33.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`issue33.ts 1`] = ` 4 | 5 | File: issue33.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | declare const $: any; 10 | declare const jQuery: any; 11 | declare const _: any; 12 | 13 | declare const Button: any; 14 | 15 | const Button1 = Button.extend\` color: red \`; 16 | 17 | const Button2 = $.extend\` color: red \`; 18 | const Button3 = jQuery.extend\` color: red \`; 19 | const Button4 = _.extend\` color: red \`; 20 | 21 | 22 | TypeScript before transform: 23 | 24 | declare const styled: any; 25 | declare const $: any; 26 | declare const jQuery: any; 27 | declare const _: any; 28 | declare const Button: any; 29 | const Button1 = Button.extend \` color: red \`; 30 | const Button2 = $.extend \` color: red \`; 31 | const Button3 = jQuery.extend \` color: red \`; 32 | const Button4 = _.extend \` color: red \`; 33 | 34 | 35 | TypeScript after transform: 36 | 37 | declare const styled: any; 38 | declare const $: any; 39 | declare const jQuery: any; 40 | declare const _: any; 41 | declare const Button: any; 42 | const Button1 = Button.extend \` color: red \`; 43 | const Button2 = $.extend \` color: red \`; 44 | const Button3 = jQuery.extend \` color: red \`; 45 | const Button4 = _.extend \` color: red \`; 46 | 47 | 48 | TypeScript after transpile module: 49 | 50 | const Button1 = Button.extend \` color: red \`; 51 | const Button2 = $.extend \` color: red \`; 52 | const Button3 = jQuery.extend \` color: red \`; 53 | const Button4 = _.extend \` color: red \`; 54 | 55 | 56 | 57 | `; 58 | -------------------------------------------------------------------------------- /src/__tests__/baselines/ssr/multiple-components.tsx.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`multiple-components.tsx 1`] = ` 4 | 5 | File: multiple-components.tsx 6 | Source code: 7 | 8 | import styled from 'styled-components'; 9 | 10 | export function createButtons() { 11 | const A = styled.button\` color: red; \`; 12 | const B = styled(A)\` color: blue; \`; 13 | 14 | return { A, B }; 15 | } 16 | 17 | export function createDivs() { 18 | const A = styled.div\` color: green; \`; 19 | const B = styled(A)\` color: yellow; \`; 20 | 21 | return { A, B }; 22 | } 23 | 24 | 25 | TypeScript before transform: 26 | 27 | import styled from 'styled-components'; 28 | export function createButtons() { 29 | const A = styled.button \` color: red; \`; 30 | const B = styled(A) \` color: blue; \`; 31 | return { A, B }; 32 | } 33 | export function createDivs() { 34 | const A = styled.div \` color: green; \`; 35 | const B = styled(A) \` color: yellow; \`; 36 | return { A, B }; 37 | } 38 | 39 | 40 | TypeScript after transform: 41 | 42 | import styled from 'styled-components'; 43 | export function createButtons() { 44 | const A = styled.button.withConfig({ displayName: "A", componentId: "sc-hana72" }) \` color: red; \`; 45 | const B = styled(A).withConfig({ displayName: "B", componentId: "sc-ke4nds" }) \` color: blue; \`; 46 | return { A, B }; 47 | } 48 | export function createDivs() { 49 | const A = styled.div.withConfig({ displayName: "A", componentId: "sc-1q7vmnt" }) \` color: green; \`; 50 | const B = styled(A).withConfig({ displayName: "B", componentId: "sc-7q8oop" }) \` color: yellow; \`; 51 | return { A, B }; 52 | } 53 | 54 | 55 | TypeScript after transpile module: 56 | 57 | import styled from 'styled-components'; 58 | export function createButtons() { 59 | const A = styled.button.withConfig({ displayName: "A", componentId: "sc-67koye" }) \` color: red; \`; 60 | const B = styled(A).withConfig({ displayName: "B", componentId: "sc-1svbc9u" }) \` color: blue; \`; 61 | return { A, B }; 62 | } 63 | export function createDivs() { 64 | const A = styled.div.withConfig({ displayName: "A", componentId: "sc-uo2lv8" }) \` color: green; \`; 65 | const B = styled(A).withConfig({ displayName: "B", componentId: "sc-1cxyj9q" }) \` color: yellow; \`; 66 | return { A, B }; 67 | } 68 | 69 | 70 | 71 | `; 72 | -------------------------------------------------------------------------------- /src/__tests__/baselines/ssr/sample1.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`sample1.ts 1`] = ` 4 | 5 | File: sample1.ts 6 | Source code: 7 | 8 | import styled from 'styled-components'; 9 | 10 | const Button = styled.button\` 11 | color: red; 12 | \`; 13 | 14 | declare const nonStyled: any; 15 | 16 | const NonButton = nonStyled.button\` 17 | yo 18 | \`; 19 | 20 | const OtherButton = styled(Button)\` 21 | color: blue; 22 | \`; 23 | 24 | const SuperButton = Button.extend\` 25 | color: super; 26 | \`; 27 | 28 | export default styled.link\` 29 | color: black; 30 | \`; 31 | 32 | export const SmallButton = Button.extend\` 33 | font-size: .7em; 34 | \`; 35 | 36 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' })\` 37 | font-size: .1em; 38 | \`; 39 | 40 | 41 | TypeScript before transform: 42 | 43 | import styled from 'styled-components'; 44 | const Button = styled.button \` 45 | color: red; 46 | \`; 47 | declare const nonStyled: any; 48 | const NonButton = nonStyled.button \` 49 | yo 50 | \`; 51 | const OtherButton = styled(Button) \` 52 | color: blue; 53 | \`; 54 | const SuperButton = Button.extend \` 55 | color: super; 56 | \`; 57 | export default styled.link \` 58 | color: black; 59 | \`; 60 | export const SmallButton = Button.extend \` 61 | font-size: .7em; 62 | \`; 63 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }) \` 64 | font-size: .1em; 65 | \`; 66 | 67 | 68 | TypeScript after transform: 69 | 70 | import styled from 'styled-components'; 71 | const Button = styled.button.withConfig({ displayName: "Button", componentId: "sc-1okqsxw" }) \` 72 | color: red; 73 | \`; 74 | declare const nonStyled: any; 75 | const NonButton = nonStyled.button \` 76 | yo 77 | \`; 78 | const OtherButton = styled(Button).withConfig({ displayName: "OtherButton", componentId: "sc-ce0fkl" }) \` 79 | color: blue; 80 | \`; 81 | const SuperButton = Button.extend \` 82 | color: super; 83 | \`; 84 | export default styled.link.withConfig({ componentId: "sc-vba0dl" }) \` 85 | color: black; 86 | \`; 87 | export const SmallButton = Button.extend \` 88 | font-size: .7em; 89 | \`; 90 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }).withConfig({ displayName: "MiniButton", componentId: "sc-ndnumj" }) \` 91 | font-size: .1em; 92 | \`; 93 | 94 | 95 | TypeScript after transpile module: 96 | 97 | import styled from 'styled-components'; 98 | const Button = styled.button.withConfig({ displayName: "Button", componentId: "sc-13dat8f" }) \` 99 | color: red; 100 | \`; 101 | const NonButton = nonStyled.button \` 102 | yo 103 | \`; 104 | const OtherButton = styled(Button).withConfig({ displayName: "OtherButton", componentId: "sc-1pbo6g5" }) \` 105 | color: blue; 106 | \`; 107 | const SuperButton = Button.extend \` 108 | color: super; 109 | \`; 110 | export default styled.link.withConfig({ componentId: "sc-ep20on" }) \` 111 | color: black; 112 | \`; 113 | export const SmallButton = Button.extend \` 114 | font-size: .7em; 115 | \`; 116 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }).withConfig({ displayName: "MiniButton", componentId: "sc-1cgykmr" }) \` 117 | font-size: .1em; 118 | \`; 119 | 120 | 121 | 122 | `; 123 | -------------------------------------------------------------------------------- /src/__tests__/baselines/ssr/sample2.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`sample2.ts 1`] = ` 4 | 5 | File: sample2.ts 6 | Source code: 7 | 8 | import styled from 'styled-components'; 9 | 10 | const styled2 = styled; 11 | const NonButton = styled.button; 12 | const NonStyled = styled\` color: red; \`; 13 | const Link = styled(NonStyled)\` color: red; \`; 14 | 15 | 16 | TypeScript before transform: 17 | 18 | import styled from 'styled-components'; 19 | const styled2 = styled; 20 | const NonButton = styled.button; 21 | const NonStyled = styled \` color: red; \`; 22 | const Link = styled(NonStyled) \` color: red; \`; 23 | 24 | 25 | TypeScript after transform: 26 | 27 | import styled from 'styled-components'; 28 | const styled2 = styled; 29 | const NonButton = styled.button; 30 | const NonStyled = styled \` color: red; \`; 31 | const Link = styled(NonStyled).withConfig({ displayName: "Link", componentId: "sc-1xlc242" }) \` color: red; \`; 32 | 33 | 34 | TypeScript after transpile module: 35 | 36 | import styled from 'styled-components'; 37 | const styled2 = styled; 38 | const NonButton = styled.button; 39 | const NonStyled = styled \` color: red; \`; 40 | const Link = styled(NonStyled).withConfig({ displayName: "Link", componentId: "sc-z7xxm1" }) \` color: red; \`; 41 | 42 | 43 | 44 | `; 45 | -------------------------------------------------------------------------------- /src/__tests__/baselines/ssr/sample3.tsx.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`sample3.tsx 1`] = ` 4 | 5 | File: sample3.tsx 6 | Source code: 7 | 8 | import * as React from 'react'; 9 | import styled from '../themed-styled'; 10 | import { SmallButton } from './sample1'; 11 | 12 | interface LabelProps { 13 | size: number; 14 | } 15 | 16 | const CustomLabel = styled.label\` 17 | font-size: \${(props: LabelProps) => props.size + 'px'} 18 | \`; 19 | 20 | const LabeledLink = () => ; 21 | 22 | export default CustomLabel; 23 | 24 | 25 | TypeScript before transform: 26 | 27 | import * as React from 'react'; 28 | import styled from '../themed-styled'; 29 | import { SmallButton } from './sample1'; 30 | interface LabelProps { 31 | size: number; 32 | } 33 | const CustomLabel = styled.label \` 34 | font-size: \${(props: LabelProps) => props.size + 'px'} 35 | \`; 36 | const LabeledLink = () => ; 37 | export default CustomLabel; 38 | 39 | 40 | TypeScript after transform: 41 | 42 | import * as React from 'react'; 43 | import styled from '../themed-styled'; 44 | import { SmallButton } from './sample1'; 45 | interface LabelProps { 46 | size: number; 47 | } 48 | const CustomLabel = styled.label.withConfig({ displayName: "CustomLabel", componentId: "sc-1ydgk9x" }) \` 49 | font-size: \${(props: LabelProps) => props.size + 'px'} 50 | \`; 51 | const LabeledLink = () => ; 52 | export default CustomLabel; 53 | 54 | 55 | TypeScript after transpile module: 56 | 57 | import styled from '../themed-styled'; 58 | const CustomLabel = styled.label.withConfig({ displayName: "CustomLabel", componentId: "sc-xc3x4h" }) \` 59 | font-size: \${(props) => props.size + 'px'} 60 | \`; 61 | const LabeledLink = () => />;; 62 | export default CustomLabel; 63 | 64 | 65 | 66 | `; 67 | -------------------------------------------------------------------------------- /src/__tests__/baselines/ssr/style-objects.ts.baseline: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`style-objects.ts 1`] = ` 4 | 5 | File: style-objects.ts 6 | Source code: 7 | 8 | declare const styled: any; 9 | 10 | const Button = styled.button({ 11 | color: 'red' 12 | }); 13 | 14 | declare const nonStyled: any; 15 | 16 | const NonButton = nonStyled.button({ 17 | color: 'red' 18 | }); 19 | 20 | const OtherButton = styled(Button)({ 21 | color: 'blue' 22 | }); 23 | 24 | const SuperButton = Button.extend({ 25 | color: 'super' 26 | }); 27 | 28 | export default styled.link({ 29 | color: 'black' 30 | }); 31 | 32 | export const SmallButton = Button.extend({ 33 | fontSize: '.7em' 34 | }); 35 | 36 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' })({ 37 | fontSize: '.1em' 38 | }); 39 | 40 | 41 | TypeScript before transform: 42 | 43 | declare const styled: any; 44 | const Button = styled.button({ 45 | color: 'red' 46 | }); 47 | declare const nonStyled: any; 48 | const NonButton = nonStyled.button({ 49 | color: 'red' 50 | }); 51 | const OtherButton = styled(Button)({ 52 | color: 'blue' 53 | }); 54 | const SuperButton = Button.extend({ 55 | color: 'super' 56 | }); 57 | export default styled.link({ 58 | color: 'black' 59 | }); 60 | export const SmallButton = Button.extend({ 61 | fontSize: '.7em' 62 | }); 63 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' })({ 64 | fontSize: '.1em' 65 | }); 66 | 67 | 68 | TypeScript after transform: 69 | 70 | declare const styled: any; 71 | const Button = styled.button.withConfig({ displayName: "Button", componentId: "sc-7b7p9e" })({ 72 | color: 'red' 73 | }); 74 | declare const nonStyled: any; 75 | const NonButton = nonStyled.button({ 76 | color: 'red' 77 | }); 78 | const OtherButton = styled(Button).withConfig({ displayName: "OtherButton", componentId: "sc-14ah7t" })({ 79 | color: 'blue' 80 | }); 81 | const SuperButton = Button.extend({ 82 | color: 'super' 83 | }); 84 | export default styled.link.withConfig({ componentId: "sc-8xjslt" })({ 85 | color: 'black' 86 | }); 87 | export const SmallButton = Button.extend({ 88 | fontSize: '.7em' 89 | }); 90 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }).withConfig({ displayName: "MiniButton", componentId: "sc-ad4g7l" })({ 91 | fontSize: '.1em' 92 | }); 93 | 94 | 95 | TypeScript after transpile module: 96 | 97 | const Button = styled.button.withConfig({ displayName: "Button", componentId: "sc-13dat8f" })({ 98 | color: 'red' 99 | }); 100 | const NonButton = nonStyled.button({ 101 | color: 'red' 102 | }); 103 | const OtherButton = styled(Button).withConfig({ displayName: "OtherButton", componentId: "sc-1pbo6g5" })({ 104 | color: 'blue' 105 | }); 106 | const SuperButton = Button.extend({ 107 | color: 'super' 108 | }); 109 | export default styled.link.withConfig({ componentId: "sc-ep20on" })({ 110 | color: 'black' 111 | }); 112 | export const SmallButton = Button.extend({ 113 | fontSize: '.7em' 114 | }); 115 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' }).withConfig({ displayName: "MiniButton", componentId: "sc-1cgykmr" })({ 116 | fontSize: '.1em' 117 | }); 118 | 119 | 120 | 121 | `; 122 | -------------------------------------------------------------------------------- /src/__tests__/componentIdPrefix-baselines.test.ts: -------------------------------------------------------------------------------- 1 | import createTransformer from '..'; 2 | import { expectBaselineTransforms } from './expectTransform'; 3 | 4 | const transformer = createTransformer({ 5 | componentIdPrefix: 'test' 6 | }); 7 | 8 | expectBaselineTransforms(transformer, __dirname + '/fixtures/base', 'baselines/componentIdPrefix'); 9 | expectBaselineTransforms(transformer, __dirname + '/fixtures/componentIdPrefix', 'baselines/componentIdPrefix'); 10 | -------------------------------------------------------------------------------- /src/__tests__/expectTransform.ts: -------------------------------------------------------------------------------- 1 | import 'jest'; 2 | import { addSerializer } from 'jest-specific-snapshot'; 3 | import * as ts from 'typescript'; 4 | import * as fs from 'fs'; 5 | 6 | const printer = ts.createPrinter(); 7 | 8 | interface TransformBaseline { 9 | type: 'transform-baseline'; 10 | filename: string; 11 | content: string; 12 | source: string; 13 | transformed: string; 14 | transpiled: string; 15 | } 16 | 17 | const serializer = { 18 | test: (obj: any): obj is TransformBaseline => obj && obj.type === 'transform-baseline', 19 | print: (obj: TransformBaseline, print: (object: any) => string, indent: (str: string) => string) => ` 20 | File: ${obj.filename} 21 | Source code: 22 | 23 | ${indent(obj.content)} 24 | 25 | TypeScript before transform: 26 | 27 | ${indent(obj.source)} 28 | 29 | TypeScript after transform: 30 | 31 | ${indent(obj.transformed)} 32 | 33 | TypeScript after transpile module: 34 | 35 | ${indent(obj.transpiled)} 36 | 37 | ` 38 | }; 39 | 40 | addSerializer(serializer); 41 | 42 | export function expectTransform(transformer: ts.TransformerFactory, filename: string, path: string, outpath: string) { 43 | const content = fs.readFileSync(path + '/' + filename).toString(); 44 | const sourceFile = ts.createSourceFile(filename, content, ts.ScriptTarget.Latest, /* setParentNodes */ true); 45 | const source = printer.printFile(sourceFile); 46 | const transformedFile = ts.transform(sourceFile, [transformer]).transformed[0]; 47 | const transformed = printer.printFile(transformedFile); 48 | 49 | const transpileOutput = ts.transpileModule(content, { 50 | compilerOptions: { 51 | target: ts.ScriptTarget.Latest 52 | }, 53 | transformers: { 54 | before: [transformer] 55 | } 56 | }) 57 | const transpiled = transpileOutput.outputText 58 | 59 | const snapshot: TransformBaseline = { 60 | type: 'transform-baseline', 61 | filename, 62 | content, 63 | source, 64 | transformed, 65 | transpiled 66 | }; 67 | 68 | expect(snapshot).toMatchSpecificSnapshot(outpath + '/' + filename + '.baseline'); 69 | } 70 | 71 | export function expectBaselineTransforms(transformer: ts.TransformerFactory, path: string, outpath: string) { 72 | const files = fs.readdirSync(path) 73 | .filter(f => f.toLowerCase().endsWith('.tsx') || f.toLowerCase().endsWith('.ts')); 74 | 75 | files.forEach(file => it(file, () => expectTransform(transformer, file, path, outpath))); 76 | } 77 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/base/issue33.ts: -------------------------------------------------------------------------------- 1 | declare const styled: any; 2 | declare const $: any; 3 | declare const jQuery: any; 4 | declare const _: any; 5 | 6 | declare const Button: any; 7 | 8 | const Button1 = Button.extend` color: red `; 9 | 10 | const Button2 = $.extend` color: red `; 11 | const Button3 = jQuery.extend` color: red `; 12 | const Button4 = _.extend` color: red `; 13 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/base/sample1.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const Button = styled.button` 4 | color: red; 5 | `; 6 | 7 | declare const nonStyled: any; 8 | 9 | const NonButton = nonStyled.button` 10 | yo 11 | `; 12 | 13 | const OtherButton = styled(Button)` 14 | color: blue; 15 | `; 16 | 17 | const SuperButton = Button.extend` 18 | color: super; 19 | `; 20 | 21 | export default styled.link` 22 | color: black; 23 | `; 24 | 25 | export const SmallButton = Button.extend` 26 | font-size: .7em; 27 | `; 28 | 29 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' })` 30 | font-size: .1em; 31 | `; 32 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/base/sample2.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const styled2 = styled; 4 | const NonButton = styled.button; 5 | const NonStyled = styled` color: red; `; 6 | const Link = styled(NonStyled)` color: red; `; 7 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/base/sample3.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import styled from '../themed-styled'; 3 | import { SmallButton } from './sample1'; 4 | 5 | interface LabelProps { 6 | size: number; 7 | } 8 | 9 | const CustomLabel = styled.label` 10 | font-size: ${(props: LabelProps) => props.size + 'px'} 11 | `; 12 | 13 | const LabeledLink = () => ; 14 | 15 | export default CustomLabel; 16 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/base/style-objects.ts: -------------------------------------------------------------------------------- 1 | declare const styled: any; 2 | 3 | const Button = styled.button({ 4 | color: 'red' 5 | }); 6 | 7 | declare const nonStyled: any; 8 | 9 | const NonButton = nonStyled.button({ 10 | color: 'red' 11 | }); 12 | 13 | const OtherButton = styled(Button)({ 14 | color: 'blue' 15 | }); 16 | 17 | const SuperButton = Button.extend({ 18 | color: 'super' 19 | }); 20 | 21 | export default styled.link({ 22 | color: 'black' 23 | }); 24 | 25 | export const SmallButton = Button.extend({ 26 | fontSize: '.7em' 27 | }); 28 | 29 | const MiniButton = styled(SmallButton).attrs({ size: 'mini' })({ 30 | fontSize: '.1em' 31 | }); 32 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/componentIdPrefix/multiple-components.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export function createButtons() { 4 | const A = styled.button` color: red; `; 5 | const B = styled(A)` color: blue; `; 6 | 7 | return { A, B }; 8 | } 9 | 10 | export function createDivs() { 11 | const A = styled.div` color: green; `; 12 | const B = styled(A)` color: yellow; `; 13 | 14 | return { A, B }; 15 | } 16 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/minification/issue142.tsx: -------------------------------------------------------------------------------- 1 | declare const styled: any; 2 | 3 | const Header = styled.div` 4 | display: flex; 5 | \t align-items: center; 6 | justify-content: space-between; 7 | \t \t font-weight: 600; 8 | padding: 0.8em 1.6em;\t \t 9 | background: peachpuff; 10 | `; 11 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/minification/issue233.ts: -------------------------------------------------------------------------------- 1 | declare const styled: any; 2 | 3 | // repro from #233 4 | const ValueCalc = styled.div` 5 | height: calc(var(--line-height) - 5px); 6 | width: calc(100% - 5px); 7 | `; 8 | 9 | // another case from #233 10 | styled.div`--padding-button: calc(var(--padding-button-vertical) - 2px) calc(var(--padding-button-horizontal) - 2px);` 11 | 12 | // a few more cases 13 | styled.div` 14 | width: calc( 1%) 15 | width: calc( 1% + var(--a) - calc(2%)) 16 | width: calc( 1% + var(--a) - calc(2%) + calc( 1px + calc(1px + 2px) + var(--a))) 17 | ` 18 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/minification/issue36-extended.ts: -------------------------------------------------------------------------------- 1 | declare const styled: any; 2 | 3 | export const A = styled.div` 4 | border: ${'solid'} 10px; 5 | ` 6 | 7 | styled.div` 8 | border: ${'solid'}// comment here 9 | 10px; 10 | border: solid// comment here 11 | 10px; 12 | ` 13 | 14 | styled.div` 15 | border: ${'solid'}/* comment here 16 | */10px; 17 | border: ${'solid'}/* comment here 18 | */ 10px; 19 | ` 20 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/minification/issue36.tsx: -------------------------------------------------------------------------------- 1 | declare const keyframes: any; 2 | declare const styled: any; 3 | 4 | const rotate360 = keyframes` 5 | from { 6 | transform: rotate(0deg); 7 | } 8 | to { 9 | transform: rotate(360deg); 10 | } 11 | `; 12 | 13 | export const StyledDiv = styled.div` 14 | width: 100px; 15 | height: 100px; 16 | background-color: greenyellow; 17 | animation: ${rotate360} 2s linear infinite; 18 | `; 19 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/minification/issue40.ts: -------------------------------------------------------------------------------- 1 | declare const styled: any; 2 | 3 | styled.div`padding: 0 0 13px ${'50px'};` 4 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/minification/issue44.tsx: -------------------------------------------------------------------------------- 1 | declare const styled: any; 2 | styled.div` transition: width ${100}ms ease-in;`; 3 | styled.div` transition: width ${'100ms'} ease-in;`; 4 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/minification/minify-css-in-helpers.ts: -------------------------------------------------------------------------------- 1 | declare const keyframes: any; 2 | declare const css: any; 3 | declare const createGlobalStyle: any; 4 | 5 | declare const theColor: any; 6 | 7 | const key = keyframes` 8 | to { 9 | transform: rotate(360deg); 10 | } 11 | `; 12 | 13 | const color = css` 14 | color: ${theColor}; 15 | `; 16 | 17 | const MyRedBody = createGlobalStyle` 18 | body { 19 | background-color: red; // comments 20 | ${color} // comments 21 | // it will be ignored, but still emitted ${color} 22 | } 23 | `; 24 | 25 | export {}; 26 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/minification/minify-css-to-use-with-transpilation.ts: -------------------------------------------------------------------------------- 1 | declare const styled: any; 2 | 3 | const Simple = styled.div` 4 | width: 100%; 5 | `; 6 | 7 | const Interpolation = styled.div` 8 | content: " ${props => props.text} "; 9 | `; 10 | 11 | const SpecialCharacters = styled.div` 12 | content: " ${props => props.text} ";\n color: red; 13 | `; 14 | 15 | const Comment = styled.div` 16 | // comment 17 | color: red; 18 | ` 19 | 20 | const Parens = styled.div` 21 | &:hover { 22 | color: blue; 23 | } 24 | `; 25 | 26 | export {}; 27 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/minification/minify-css-to-use-without-transpilation.ts: -------------------------------------------------------------------------------- 1 | declare const styled: any; 2 | 3 | const Simple = styled.div` 4 | width: 100%; 5 | `; 6 | 7 | const Interpolation = styled.div` 8 | content: "https://test.com/${props => props.endpoint}"; 9 | `; 10 | 11 | const SpecialCharacters = styled.div` 12 | content: " ${props => props.text} ";\n color: red; 13 | `; 14 | 15 | const Comment = styled.div` 16 | width: 100%; 17 | // comment 18 | color: red; 19 | `; 20 | 21 | const Parens = styled.div` 22 | &:hover { 23 | color: blue; 24 | } 25 | color: red; 26 | `; 27 | 28 | const UrlComments = styled.div` 29 | color: red; 30 | /* // */ 31 | background: red; 32 | /* comment 1 */ 33 | /* comment 2 */ 34 | // comment 3 35 | border: 1px solid green; 36 | `; 37 | 38 | export {}; 39 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/minification/minify-single-line-comments-with-interpolations.ts: -------------------------------------------------------------------------------- 1 | declare const styled: any; 2 | 3 | const Test1 = styled.div` 4 | width: 100%; 5 | // color: ${'red'}; 6 | ` 7 | 8 | const Test2 = styled.div` 9 | width: 100%; 10 | // color: pale${'red'}; 11 | ` 12 | 13 | const Test3 = styled.div` 14 | width: 100%; 15 | // color 16 | ${'red'}; 17 | ` 18 | 19 | const Test4 = styled.div` 20 | width: 100%; 21 | // color: ${'red'}-blue; 22 | ` 23 | 24 | const Test5 = styled.div` 25 | width: 100%; 26 | // color: ${'red'}${'blue'}; 27 | ` 28 | 29 | const Test6 = styled.div` 30 | background: url("https://google.com"); 31 | width: 100%; 32 | ${'green'} // color: ${'red'}${'blue'}; 33 | ` 34 | 35 | const Test7 = styled.div` 36 | background: url("https://google.com"); 37 | width: ${p => p.props.width}; 38 | ${'green'} // color: ${'red'}${'blue'}; 39 | height: ${p => p.props.height}; 40 | ` 41 | 42 | const Test8 = styled.dev` 43 | color: /* ${'red'} ... disabled */ blue; 44 | `; 45 | 46 | const Test9 = styled.dev` 47 | color: // ${'red'} ... disabled 48 | blue 49 | `; 50 | 51 | export {} -------------------------------------------------------------------------------- /src/__tests__/fixtures/minification/simple.ts: -------------------------------------------------------------------------------- 1 | declare const styled: any; 2 | 3 | declare const placeholder1: any; 4 | declare const placeholder2: any; 5 | 6 | // splits a line by potential comment starts and joins until one is an actual comment 7 | // `abc def` 8 | styled.div`abc def//ghi//jkl` 9 | 10 | // ignores comment markers that are inside strings 11 | // `abc def"//"ghi\'//\'jkl` 12 | styled.div`abc def"//"ghi\'//\'jkl//the end` 13 | // `abc def"//"` 14 | styled.div`abc def"//"` 15 | 16 | // ignores comment markers that are inside parantheses 17 | // `bla (//) bla` 18 | styled.div`bla (//) bla//the end` 19 | 20 | // ignores even unescaped URLs 21 | // `https://test.com` 22 | styled.div`https://test.com// comment//` 23 | 24 | // removes multi-line comments 25 | // `this is a test` 26 | styled.div`this is a/* ignore me please */test` 27 | 28 | // joins all lines of code 29 | // `this is a test` 30 | styled.div`this\nis\na/* ignore me \n please */\ntest` 31 | 32 | // removes line comments filling an entire line 33 | // `line one{line:two;}` 34 | styled.div`line one { 35 | // remove this comment 36 | line: two; 37 | }` 38 | 39 | // removes line comments at the end of lines of code 40 | // `valid line with out comments` 41 | styled.div`valid line with // a comment 42 | out comments` 43 | 44 | // preserves multi-line comments starting with /*! 45 | // `this is a /*! dont ignore me please */ test` 46 | styled.div`this is a /*! dont ignore me please */ test/* but you can ignore me */` 47 | 48 | // returns the indices of removed placeholders (expressions) 49 | // `this is some input with ${placeholder1} and //${placeholder2}` 50 | styled.div`this is some\ninput with ${placeholder1} and // ignored ${placeholder2}` 51 | 52 | // works with raw escape codes 53 | // `this\\nis\\na \\ntest` 54 | styled.div`this\\nis\\na/* ignore me \\n please */\\ntest` 55 | // `this\nis\na \ntest` 56 | styled.div`this\nis\na/* ignore me \n please */\ntest` 57 | // `this is a test` 58 | styled.div`this 59 | is 60 | a/* ignore me \n please */ 61 | test` 62 | 63 | // removes spaces around symbols 64 | // `;:{},;` 65 | styled.div`; : { } , ; ` 66 | 67 | // ignores symbols inside strings 68 | // `;" : "\' : \';` 69 | styled.div`; " : " \' : \' ;` 70 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/minification/simple2.ts: -------------------------------------------------------------------------------- 1 | export {} 2 | declare const styled: any; 3 | 4 | // spaces before and after ' " ( ) 5 | styled.div`a b" c " d` // `a b" c "d` 6 | styled.div`a b' c ' d` // `a b' c 'd` 7 | styled.div`a b( c ) d` // `a b( c )d` 8 | styled.div`a b " c "d` // `a b " c "d` 9 | styled.div`a b ' c 'd` // `a b ' c 'd` 10 | styled.div`a b ( c )d` // `a b ( c )d` 11 | -------------------------------------------------------------------------------- /src/__tests__/fixtures/ssr/multiple-components.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export function createButtons() { 4 | const A = styled.button` color: red; `; 5 | const B = styled(A)` color: blue; `; 6 | 7 | return { A, B }; 8 | } 9 | 10 | export function createDivs() { 11 | const A = styled.div` color: green; `; 12 | const B = styled(A)` color: yellow; `; 13 | 14 | return { A, B }; 15 | } 16 | -------------------------------------------------------------------------------- /src/__tests__/minification-only.test.ts: -------------------------------------------------------------------------------- 1 | import createTransformer from '../'; 2 | import { expectBaselineTransforms } from './expectTransform'; 3 | 4 | const transformer = createTransformer({ displayName: false, ssr: false, minify: true }); 5 | 6 | expectBaselineTransforms(transformer, __dirname + '/fixtures/minification', 'baselines/minification-only'); 7 | -------------------------------------------------------------------------------- /src/__tests__/minification.test.ts: -------------------------------------------------------------------------------- 1 | import createTransformer from '../'; 2 | import { expectBaselineTransforms } from './expectTransform'; 3 | 4 | const transformer = createTransformer({ ssr: false, minify: true }); 5 | 6 | expectBaselineTransforms(transformer, __dirname + '/fixtures/minification', 'baselines/minification'); 7 | -------------------------------------------------------------------------------- /src/__tests__/minify.test.ts: -------------------------------------------------------------------------------- 1 | import { createMinifier } from '../minify'; 2 | 3 | it.skip('debug', () => { 4 | const minifer = createMinifier(); 5 | 6 | move(' w: '); 7 | move(';\n '); 8 | 9 | function move(next: string, last?: boolean) { 10 | console.log({ move: { next, last }, result: minifer(next, last) }); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /src/__tests__/ssr-baselines.test.ts: -------------------------------------------------------------------------------- 1 | import createTransformer from '../'; 2 | import { expectBaselineTransforms } from './expectTransform'; 3 | 4 | const transformer = createTransformer({ 5 | ssr: true 6 | }); 7 | 8 | expectBaselineTransforms(transformer, __dirname + '/fixtures/base', 'baselines/ssr'); 9 | expectBaselineTransforms(transformer, __dirname + '/fixtures/ssr', 'baselines/ssr'); 10 | -------------------------------------------------------------------------------- /src/__tests__/themed-styled.ts: -------------------------------------------------------------------------------- 1 | /* Role: styled-component re-export with builder theme support */ 2 | 3 | // tslint:disable-next-line:import-blacklist 4 | import * as StyledComponentModule from 'styled-components'; 5 | // tslint:disable-next-line:no-duplicate-imports 6 | // tslint:disable-next-line:import-blacklist 7 | import { ThemedStyledComponentsModule, ThemedStyledProps, SimpleInterpolation } from 'styled-components'; 8 | 9 | interface Theme { 10 | color: string; 11 | } 12 | 13 | const { 14 | default: styled, 15 | css, 16 | injectGlobal, 17 | keyframes: keyframesOriginal, 18 | ThemeProvider, 19 | withTheme 20 | } = StyledComponentModule as ThemedStyledComponentsModule as ThemedStyledComponentsModule; 21 | 22 | function keyframes(strings: TemplateStringsArray, ...interpolations: SimpleInterpolation[]): () => string { 23 | let value: string | undefined; 24 | return () => value || (value = keyframesOriginal(strings, ...interpolations)); 25 | } 26 | 27 | export type StyledProps

= ThemedStyledProps; 28 | export default styled; 29 | export { css, injectGlobal, keyframes, withTheme, ThemeProvider }; 30 | -------------------------------------------------------------------------------- /src/createTransformer.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as ts from 'typescript'; 3 | import { 4 | isPropertyAccessExpression, 5 | isCallExpression, 6 | isIdentifier, 7 | isVariableDeclaration, 8 | isExportAssignment, 9 | isTaggedTemplateExpression, 10 | } from './ts-is-kind'; 11 | 12 | import { Options, CustomStyledIdentifiers } from './models/Options'; 13 | import { hash } from './hash'; 14 | import { minifyTemplate } from './minify'; 15 | 16 | /** Detects that a node represents a styled function 17 | * Recognizes the following patterns: 18 | * 19 | * styled.tag 20 | * Component.extend 21 | * styled(Component) 22 | * styled('tag') 23 | * styledFunction.attrs(attributes) 24 | */ 25 | function isStyledFunction( 26 | node: ts.Node, 27 | identifiers: CustomStyledIdentifiers 28 | ): node is ts.PropertyAccessExpression | ts.CallExpression { 29 | if (isPropertyAccessExpression(node)) { 30 | if (isStyledObject(node.expression, identifiers)) { 31 | return true; 32 | } 33 | 34 | if (isStyledExtendIdentifier(node.name.text, identifiers) && isValidComponent(node.expression)) { 35 | return true; 36 | } 37 | 38 | return false; 39 | } 40 | 41 | if (isCallExpression(node) && node.arguments.length === 1) { 42 | if (isStyledObject(node.expression, identifiers)) { 43 | return true; 44 | } 45 | 46 | if (isStyledAttrs(node.expression, identifiers)) { 47 | return true; 48 | } 49 | } 50 | 51 | return false; 52 | } 53 | 54 | function isStyledObjectIdentifier(name: string, { styled: styledIdentifiers = ['styled'] }: CustomStyledIdentifiers) { 55 | return styledIdentifiers.indexOf(name) >= 0; 56 | } 57 | 58 | function isStyledObject(node: ts.Node, identifiers: CustomStyledIdentifiers) { 59 | return node && isIdentifier(node) && isStyledObjectIdentifier(node.text, identifiers); 60 | } 61 | 62 | function isValidComponent(node: ts.Node) { 63 | return node && isIdentifier(node) && isValidComponentName(node.text); 64 | } 65 | 66 | function isLetter(ch: string) { 67 | return ch.toLowerCase() !== ch.toUpperCase(); 68 | } 69 | 70 | function isValidTagName(name: string) { 71 | return isLetter(name[0]) && name[0] === name[0].toLowerCase(); 72 | } 73 | 74 | function isValidComponentName(name: string) { 75 | return isLetter(name[0]) && name[0] === name[0].toUpperCase(); 76 | } 77 | 78 | function isStyledAttrsIdentifier(name: string, { attrs: attrsIdentifiers = ['attrs'] }: CustomStyledIdentifiers) { 79 | return attrsIdentifiers.indexOf(name) >= 0; 80 | } 81 | 82 | function isStyledAttrs(node: ts.Node, identifiers: CustomStyledIdentifiers) { 83 | return ( 84 | node && 85 | isPropertyAccessExpression(node) && 86 | isStyledAttrsIdentifier(node.name.text, identifiers) && 87 | isStyledFunction((node as ts.PropertyAccessExpression).expression, identifiers) 88 | ); 89 | } 90 | 91 | function isStyledKeyframesIdentifier(name: string, { keyframes = ['keyframes'] }: CustomStyledIdentifiers) { 92 | return keyframes.indexOf(name) >= 0; 93 | } 94 | 95 | function isStyledCssIdentifier(name: string, { css = ['css'] }: CustomStyledIdentifiers) { 96 | return css.indexOf(name) >= 0; 97 | } 98 | 99 | function isStyledCreateGlobalStyleIdentifier( 100 | name: string, 101 | { createGlobalStyle = ['createGlobalStyle'] }: CustomStyledIdentifiers 102 | ) { 103 | return createGlobalStyle.indexOf(name) >= 0; 104 | } 105 | 106 | function isStyledExtendIdentifier(name: string, { extend = [] }: CustomStyledIdentifiers) { 107 | return extend.indexOf(name) >= 0; 108 | } 109 | 110 | function isMinifyableStyledFunction(node: ts.Node, identifiers: CustomStyledIdentifiers) { 111 | return ( 112 | isStyledFunction(node, identifiers) || 113 | (isIdentifier(node) && 114 | (isStyledKeyframesIdentifier(node.text, identifiers) || 115 | isStyledCssIdentifier(node.text, identifiers) || 116 | isStyledCreateGlobalStyleIdentifier(node.text, identifiers))) 117 | ); 118 | } 119 | 120 | function defaultGetDisplayName(filename: string, bindingName: string | undefined): string | undefined { 121 | return bindingName; 122 | } 123 | 124 | export function createTransformer(options?: Partial): ts.TransformerFactory; 125 | export function createTransformer({ 126 | getDisplayName = defaultGetDisplayName, 127 | identifiers = {}, 128 | ssr = true, 129 | displayName = true, 130 | minify = false, 131 | componentIdPrefix = '' 132 | }: Partial = {}) { 133 | /** 134 | * Infers display name of a styled component. 135 | * Recognizes the following patterns: 136 | * 137 | * (const|var|let) ComponentName = styled... 138 | * export default styled... 139 | */ 140 | function getDisplayNameFromNode(node: ts.Node, sourceFile: ts.SourceFile): string | undefined { 141 | if (isVariableDeclaration(node) && isIdentifier(node.name)) { 142 | return (componentIdPrefix ? componentIdPrefix + '-' : '') + getDisplayName(sourceFile.fileName, node.name.text); 143 | } 144 | 145 | if (isExportAssignment(node)) { 146 | return getDisplayName(sourceFile.fileName, undefined); 147 | } 148 | 149 | return undefined; 150 | } 151 | 152 | function getIdFromNode( 153 | node: ts.Node, 154 | sourceRoot: string | undefined, 155 | position: number, 156 | sourceFile: ts.SourceFile 157 | ): string | undefined { 158 | if ((isVariableDeclaration(node) && isIdentifier(node.name)) || isExportAssignment(node)) { 159 | const fileName = sourceFile.fileName; 160 | const filePath = sourceRoot 161 | ? path.relative(sourceRoot, fileName).replace(path.sep, path.posix.sep) 162 | : fileName; 163 | return (componentIdPrefix || 'sc') + '-' + hash(`${getDisplayNameFromNode(node, sourceFile)}${filePath}${position}`); 164 | } 165 | return undefined; 166 | } 167 | 168 | const transformer: ts.TransformerFactory = (context) => { 169 | const { sourceRoot } = context.getCompilerOptions(); 170 | 171 | return (sourceFile) => { 172 | let lastComponentPosition = 0; 173 | 174 | const withConfig = (node: ts.Expression, properties: ts.PropertyAssignment[]) => 175 | properties.length > 0 176 | ? context.factory.createCallExpression( 177 | context.factory.createPropertyAccessExpression(node, 'withConfig'), 178 | undefined, 179 | [context.factory.createObjectLiteralExpression(properties)] 180 | ) 181 | : node; 182 | 183 | const createDisplayNameConfig = (displayNameValue: string | undefined) => 184 | displayNameValue 185 | ? [ 186 | context.factory.createPropertyAssignment( 187 | 'displayName', 188 | context.factory.createStringLiteral(displayNameValue) 189 | ), 190 | ] 191 | : []; 192 | const createIdConfig = (componentId: string | undefined) => 193 | componentId 194 | ? [ 195 | context.factory.createPropertyAssignment( 196 | 'componentId', 197 | context.factory.createStringLiteral(componentId) 198 | ), 199 | ] 200 | : []; 201 | 202 | const transformStyledFunction = ( 203 | binding: ts.VariableDeclaration | ts.ExportAssignment, 204 | node: ts.Expression 205 | ) => 206 | withConfig(node, [ 207 | ...(displayName ? createDisplayNameConfig(getDisplayNameFromNode(binding, sourceFile)) : []), 208 | ...(ssr 209 | ? createIdConfig(getIdFromNode(binding, sourceRoot, ++lastComponentPosition, sourceFile)) 210 | : []), 211 | ]); 212 | 213 | const transformTemplateLiteral = (templateLiteral: ts.TemplateLiteral) => 214 | minify ? minifyTemplate(templateLiteral, context.factory) : templateLiteral; 215 | 216 | const transformTaggedTemplateExpression = (node: ts.TaggedTemplateExpression) => 217 | isMinifyableStyledFunction(node.tag, identifiers) 218 | ? context.factory.updateTaggedTemplateExpression( 219 | node, 220 | node.tag, 221 | node.typeArguments, 222 | transformTemplateLiteral(node.template) 223 | ) 224 | : node; 225 | 226 | const transformBindingExpression = ( 227 | binding: ts.VariableDeclaration | ts.ExportAssignment, 228 | node: ts.Expression 229 | ) => { 230 | if (isTaggedTemplateExpression(node) && isStyledFunction(node.tag, identifiers)) { 231 | return context.factory.updateTaggedTemplateExpression( 232 | node, 233 | transformStyledFunction(binding, node.tag), 234 | node.typeArguments, 235 | transformTemplateLiteral(node.template) 236 | ); 237 | } 238 | if (isCallExpression(node) && isStyledFunction(node.expression, identifiers)) { 239 | return context.factory.updateCallExpression( 240 | node, 241 | transformStyledFunction(binding, node.expression), 242 | node.typeArguments, 243 | node.arguments 244 | ); 245 | } 246 | }; 247 | 248 | const updateNode = ( 249 | node: T, 250 | data: D | undefined, 251 | updateFn: (node: T, data: D) => T 252 | ) => (data ? updateFn(node, data) : undefined); 253 | 254 | const updateVariableDeclarationInitializer = (node: ts.VariableDeclaration, initializer: ts.Expression) => 255 | context.factory.updateVariableDeclaration( 256 | node, 257 | node.name, 258 | node.exclamationToken, 259 | node.type, 260 | initializer 261 | ); 262 | 263 | const updateExportAssignmentExpression = (node: ts.ExportAssignment, expression: ts.Expression) => 264 | context.factory.updateExportAssignment(node, node.modifiers, expression); 265 | 266 | const transformNode = (node: ts.Node) => 267 | isVariableDeclaration(node) && node.initializer 268 | ? updateNode( 269 | node, 270 | transformBindingExpression(node, node.initializer), 271 | updateVariableDeclarationInitializer 272 | ) 273 | : isExportAssignment(node) 274 | ? updateNode( 275 | node, 276 | transformBindingExpression(node, node.expression), 277 | updateExportAssignmentExpression 278 | ) 279 | : minify && isTaggedTemplateExpression(node) 280 | ? transformTaggedTemplateExpression(node) 281 | : undefined; 282 | 283 | const visitNode: ts.Visitor = (node) => transformNode(node) || ts.visitEachChild(node, visitNode, context); 284 | 285 | return ts.visitNode(sourceFile, visitNode) as ts.SourceFile; 286 | }; 287 | }; 288 | 289 | return transformer; 290 | } 291 | 292 | export default createTransformer; 293 | -------------------------------------------------------------------------------- /src/hash.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * JS Implementation of MurmurHash2 3 | * 4 | * @author Gary Court 5 | * @see http://github.com/garycourt/murmurhash-js 6 | * @author Austin Appleby 7 | * @see http://sites.google.com/site/murmurhash/ 8 | * 9 | * @param str ASCII only 10 | * @param seed Positive integer only 11 | * @return 32-bit positive integer hash 12 | */ 13 | function murmurhash2_32_gc(str: string, seed: number = 0) { 14 | var l = str.length, 15 | h = seed ^ l, 16 | i = 0, 17 | k; 18 | 19 | while (l >= 4) { 20 | k = 21 | (str.charCodeAt(i) & 0xff) | 22 | ((str.charCodeAt(++i) & 0xff) << 8) | 23 | ((str.charCodeAt(++i) & 0xff) << 16) | 24 | ((str.charCodeAt(++i) & 0xff) << 24); 25 | 26 | k = 27 | (k & 0xffff) * 0x5bd1e995 + 28 | ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16); 29 | k ^= k >>> 24; 30 | k = 31 | (k & 0xffff) * 0x5bd1e995 + 32 | ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16); 33 | 34 | h = 35 | ((h & 0xffff) * 0x5bd1e995 + 36 | ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ 37 | k; 38 | 39 | l -= 4; 40 | ++i; 41 | } 42 | 43 | switch (l) { 44 | case 3: 45 | h ^= (str.charCodeAt(i + 2) & 0xff) << 16; 46 | case 2: 47 | h ^= (str.charCodeAt(i + 1) & 0xff) << 8; 48 | case 1: 49 | h ^= str.charCodeAt(i) & 0xff; 50 | h = 51 | (h & 0xffff) * 0x5bd1e995 + 52 | ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16); 53 | } 54 | 55 | h ^= h >>> 13; 56 | h = 57 | (h & 0xffff) * 0x5bd1e995 + 58 | ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16); 59 | h ^= h >>> 15; 60 | 61 | return h >>> 0; 62 | } 63 | 64 | export function hash(str: string) { 65 | return murmurhash2_32_gc(str).toString(36); 66 | } 67 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import createTransformer from './createTransformer'; 2 | 3 | export { createTransformer }; 4 | export default createTransformer; 5 | -------------------------------------------------------------------------------- /src/minify.ts: -------------------------------------------------------------------------------- 1 | import * as ts from 'typescript'; 2 | import { isNoSubstitutionTemplateLiteral, isTemplateExpression } from './ts-is-kind'; 3 | 4 | type State = ';' | ';$' | 'x' | ' ' | '\n' | '"' | '(' | '\'' | '/' | '//' | ';/' | ';//' | '/$' | '//$' | '/*' | '/**' | ';/*' | ';/**' | '/*$' | '/*$*'; 5 | type StateDataDef = { 6 | ['(']: { count: number } 7 | } 8 | type StateData = K extends keyof StateDataDef ? StateDataDef[K] : void 9 | type StateResult = { [K in State]: K extends keyof StateDataDef ? [K, StateDataDef[K]] : K }[State] 10 | type ReducerResult = { emit?: string; skipEmit?: boolean; state?: StateResult; } | void; 11 | type StateMachine = { 12 | [K in State]: { 13 | next?(ch: string, data: StateData): ReducerResult; 14 | flush?(last: boolean): ReducerResult; 15 | } 16 | }; 17 | 18 | function isSymbol(ch: string) { 19 | return ch == ';' || ch == ':' || ch == '{' || ch == '}' || ch == ','; 20 | } 21 | 22 | function isSpace(ch: string) { 23 | return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; 24 | } 25 | 26 | const stateMachine: StateMachine = { 27 | ';': { 28 | next(ch) { 29 | if (ch == '(') return { state: ['(', {count: 1}]} 30 | if (ch == '\'' || ch == '"') return { state: ch } 31 | if (isSpace(ch)) return { skipEmit: true } 32 | if (ch == '/') return { state: ';/', skipEmit: true } 33 | if (isSymbol(ch)) return; 34 | return { state: 'x' } 35 | }, 36 | flush() { 37 | return { state: ';$' } 38 | } 39 | }, 40 | ';$': { // after placeholder 41 | next(ch) { 42 | if (ch == '(') return { state: ['(', {count: 1}]} 43 | if (ch == '\'' || ch == '"') return { state: ch } 44 | if (isSpace(ch)) return { skipEmit: true, state: ' ' } // we may need a space 45 | if (ch == '/') return { state: '/', skipEmit: true } 46 | if (isSymbol(ch)) return { state: ';' }; 47 | return { state: 'x' } 48 | } 49 | }, 50 | 'x': { 51 | next(ch) { 52 | if (ch == '(') return { state: ['(', {count: 1}]} 53 | if (ch == '\'' || ch == '"') return { state: ch } 54 | if (isSpace(ch)) return { state: ' ', skipEmit: true } 55 | if (ch == '/') return { state: '/', skipEmit: true } 56 | if (isSymbol(ch)) return { state: ';' }; 57 | } 58 | }, 59 | ' ': { // may need space 60 | next(ch) { 61 | if (ch == '(') return { state: ['(', {count: 1}], emit: ' ' + ch} 62 | if (ch == '\'' || ch == '"') return { state: ch, emit: ' ' + ch } 63 | if (isSpace(ch)) return { state: ' ', skipEmit: true } 64 | if (ch == '/') return { state: '/', skipEmit: true } 65 | if (isSymbol(ch)) return { state: ';' }; 66 | return { state: 'x', emit: ' ' + ch }; 67 | }, 68 | flush(last) { 69 | if (!last) return { emit: ' ', state: ';$' }; 70 | } 71 | }, 72 | '\n': { // may need new line 73 | next(ch) { 74 | if (ch == '(') return { state: ['(', {count: 1}], emit: '\n' + ch} 75 | if (ch == '\'' || ch == '"') return { state: ch, emit: '\n' + ch } 76 | if (isSpace(ch)) return { state: '\n', skipEmit: true } 77 | if (ch == '/') return { state: '/', emit: '\n' } 78 | if (isSymbol(ch)) return { state: ';', emit: '\n' + ch }; 79 | return { state: 'x', emit: '\n' + ch }; 80 | } 81 | }, 82 | "'": { 83 | next(ch) { 84 | if (ch == '\'') return { state: ';' }; 85 | } 86 | }, 87 | '"': { 88 | next(ch) { 89 | if (ch == '"') return { state: ';' }; 90 | } 91 | }, 92 | '(': { 93 | next(ch, { count }) { 94 | if (ch == '(') return { state: ['(', { count: count+1 }] } 95 | if (ch == ')') 96 | if (count > 1) 97 | return { state: ['(', { count: count-1 }] } 98 | else 99 | return { state: ';' }; // maybe return ' '? then it'd always add space after 100 | } 101 | }, 102 | '/': { 103 | next(ch) { 104 | if (ch == '/') return { state: '//', skipEmit: true } 105 | if (ch == '*') return { state: '/*', skipEmit: true } 106 | return { state: ';', emit: '/' + ch } 107 | }, 108 | flush() { 109 | return { state: '/$', emit: '/' } 110 | } 111 | }, 112 | '//': { 113 | next(ch) { 114 | if (ch == '\n') return { state: ' ', skipEmit: true } 115 | return { skipEmit: true }; 116 | }, 117 | flush(last) { 118 | if (last) return { skipEmit: true } 119 | return { state: '//$', emit: '//' } 120 | } 121 | }, 122 | ';/': { 123 | next(ch) { 124 | if (ch == '/') return { state: ';//', skipEmit: true } 125 | if (ch == '*') return { state: ';/*', skipEmit: true } 126 | return { state: ';', emit: '/' + ch } 127 | }, 128 | flush() { 129 | return { state: '/$', emit: '/' } 130 | } 131 | }, 132 | ';//': { 133 | next(ch) { 134 | if (ch == '\n') return { state: ';', skipEmit: true } 135 | return { skipEmit: true }; 136 | }, 137 | flush(last) { 138 | if (last) return { skipEmit: true } 139 | return { state: '//$', emit: '//' } 140 | } 141 | }, 142 | '/$': { }, 143 | '//$': { 144 | next(ch) { 145 | if (ch == '\n') return { state: '\n', skipEmit: true } 146 | return { skipEmit: true }; 147 | } 148 | }, 149 | '/*': { 150 | next(ch) { 151 | if (ch == '*') return { state: '/**', skipEmit: true } 152 | return { skipEmit: true }; 153 | }, 154 | flush(last) { 155 | if (last) return { skipEmit: true } 156 | return { state: '/*$', emit: '/*' } 157 | } 158 | }, 159 | '/**': { 160 | next(ch) { 161 | if (ch == '/') return { state: ' ', skipEmit: true } 162 | return { state: '/*', skipEmit: true } 163 | } 164 | }, 165 | ';/*': { 166 | next(ch) { 167 | if (ch == '*') return { state: ';/**', skipEmit: true } 168 | return { skipEmit: true }; 169 | }, 170 | flush(last) { 171 | if (last) return { skipEmit: true } 172 | return { state: '/*$', emit: '/*' } 173 | } 174 | }, 175 | ';/**': { 176 | next(ch) { 177 | if (ch == '/') return { state: ';', skipEmit: true } 178 | return { state: ';/*', skipEmit: true } 179 | } 180 | }, 181 | '/*$': { 182 | next(ch) { 183 | if (ch == '*') return { state: '/*$*', skipEmit: true }; 184 | return { skipEmit: true }; 185 | } 186 | }, 187 | '/*$*': { 188 | next(ch) { 189 | if (ch == '/') return { state: ';', emit: '*/' }; 190 | return { state: '/*$', skipEmit: true } 191 | } 192 | } 193 | }; 194 | 195 | export function createMinifier(): (next: string, last?: boolean) => string { 196 | let state: State = ';'; 197 | let stateData: StateData = undefined as StateData<';'> 198 | 199 | return (next, last = false) => { 200 | let minified = ''; 201 | 202 | function apply(result: ReducerResult, ch?: string) { 203 | if (!result) { 204 | if (ch !== undefined) 205 | minified += ch; 206 | } else { 207 | if (result.state !== undefined) 208 | { 209 | if (typeof result.state === 'string') 210 | state = result.state; 211 | else { 212 | state = result.state[0] 213 | stateData = result.state[1] 214 | } 215 | } 216 | if (result.emit !== undefined) 217 | minified += result.emit; 218 | else if (result.skipEmit !== true && ch !== undefined) 219 | minified += ch; 220 | } 221 | } 222 | 223 | let pos = 0; 224 | let len = next.length; 225 | while (pos < len) { 226 | const ch = next[pos++]; 227 | const reducer = stateMachine[state]; 228 | const prevState = state; 229 | const reducerResult = reducer.next && reducer.next(ch, stateData as any); 230 | apply(reducerResult, ch) 231 | // console.log('next(', { ch, state: prevState }, '): ', reducerResult, ' -> ', { state, minified }); 232 | } 233 | 234 | const reducer = stateMachine[state]; 235 | const prevState = state; 236 | const reducerResult = reducer.flush && reducer.flush(last); 237 | apply(reducerResult); 238 | // console.log('flush', { state: prevState }, '): ', reducerResult, ' -> ', { state, minified }); 239 | 240 | return minified; 241 | } 242 | } 243 | 244 | export function minifyTemplate(templateLiteral: ts.TemplateLiteral, factory: ts.NodeFactory) { 245 | const minifier = createMinifier(); 246 | 247 | if (isNoSubstitutionTemplateLiteral(templateLiteral)) { 248 | const node = factory.createNoSubstitutionTemplateLiteral(minifier(templateLiteral.text, true)); 249 | return node; 250 | } else if (isTemplateExpression(templateLiteral)) { 251 | const head = factory.createTemplateHead(minifier(templateLiteral.head.text)); 252 | const templateSpans = templateLiteral.templateSpans.map(span => factory.createTemplateSpan(span.expression, 253 | span.literal.kind === ts.SyntaxKind.TemplateMiddle 254 | ? factory.createTemplateMiddle(minifier(span.literal.text)) 255 | : factory.createTemplateTail(minifier(span.literal.text, true)))); 256 | const node = factory.createTemplateExpression(head, templateSpans); 257 | return node; 258 | } 259 | 260 | return templateLiteral; 261 | } 262 | -------------------------------------------------------------------------------- /src/models/Options.ts: -------------------------------------------------------------------------------- 1 | export interface Options { 2 | /** 3 | * This method is used to determine component display name from filename and its binding name. 4 | * 5 | * Default strategy is to use `bindingName` if it's defined and use inference algorithm from `filename` otherwise. 6 | */ 7 | getDisplayName(filename: string, bindingName: string | undefined): string | undefined; 8 | 9 | /** 10 | * This option allows to customize identifiers used by `styled-components` API functions. 11 | */ 12 | identifiers: CustomStyledIdentifiers; 13 | 14 | /** 15 | * By adding a unique identifier to every styled component, this plugin avoids checksum mismatches 16 | * due to different class generation on the client and on the server. 17 | * This option allows to disable component id generation by setting it to `false` 18 | * 19 | * @defaultValue `true` 20 | */ 21 | ssr: boolean; 22 | 23 | /** 24 | * This option enhances the attached CSS class name on each component with richer output 25 | * to help identify your components in the DOM without React DevTools. 26 | * It also adds allows you to see the component's `displayName` in React DevTools. 27 | * 28 | * To disable `displayName` generation set this option to `false` 29 | * 30 | * @defaultValue `true` 31 | */ 32 | displayName: boolean; 33 | 34 | /** 35 | * Allow minifying of inline styles in styled functions. 36 | * The minification is an experimental feature, please use with care. 37 | * 38 | * @defaultValue `false` 39 | * @experimental The minification feature is experimental. 40 | */ 41 | minify: boolean; 42 | 43 | /** 44 | * By adding a componentIdPrefix, running multiple instances of typescript-plugin-styled-components 45 | * will not result in clashes caused by the class generation hash. 46 | * 47 | * @defaultValue `''` 48 | */ 49 | componentIdPrefix: string; 50 | } 51 | 52 | export interface CustomStyledIdentifiers { 53 | /** 54 | * Identifiers of `styled` function. 55 | * 56 | * @defaultValue `['styled']` 57 | */ 58 | styled?: string[]; 59 | 60 | /** 61 | * Identifiers of `attrs` function. 62 | * 63 | * @defaultValue `['attrs']` 64 | */ 65 | attrs?: string[]; 66 | 67 | /** 68 | * Identifiers of `keyframes` function. 69 | * 70 | * @defaultValue `['keyframes']` 71 | */ 72 | keyframes?: string[]; 73 | 74 | /** 75 | * Identifiers of `css` function. 76 | * 77 | * @defaultValue `['css']` 78 | */ 79 | css?: string[]; 80 | 81 | /** 82 | * Identifiers of `createGlobalStyle` function. 83 | * 84 | * @defaultValue `['createGlobalStyle']` 85 | */ 86 | createGlobalStyle?: string[]; 87 | 88 | /** 89 | * Identifiers of `extend` function. 90 | * 91 | * @defaultValue `[]` 92 | */ 93 | extend?: string[]; 94 | } 95 | -------------------------------------------------------------------------------- /src/runner.ts: -------------------------------------------------------------------------------- 1 | import * as ts from 'typescript'; 2 | 3 | import createTransformer from './'; 4 | 5 | const sampleTransformer = createTransformer(); 6 | 7 | function main(files: string[]) { 8 | // Normally these would be parsed from tsconfig.json 9 | const options: ts.CompilerOptions = { 10 | skipLibCheck: true, 11 | outDir: 'built', 12 | module: ts.ModuleKind.CommonJS, 13 | noEmitOnError: false, 14 | jsx: ts.JsxEmit.React 15 | }; 16 | 17 | const beforeTransforms = [sampleTransformer]; 18 | const afterTransforms: ts.TransformerFactory[] = []; 19 | 20 | // Do the normal compilation flow 21 | const compilerHost = ts.createCompilerHost(options); 22 | const program = ts.createProgram(files, options, compilerHost); 23 | 24 | const emitResult = program.emit( 25 | undefined, undefined, undefined, undefined, 26 | {before: beforeTransforms, after: afterTransforms}); 27 | } 28 | 29 | const files = process.argv.slice(2); 30 | main(files); 31 | -------------------------------------------------------------------------------- /src/ts-is-kind.ts: -------------------------------------------------------------------------------- 1 | // The source code is kindly borrowed from `ts-is-kind` npm module. 2 | // Original repo: https://github.com/mohsen1/ts-is-kind by @mohsen1 3 | 4 | import * as ts from 'typescript'; 5 | 6 | /** 7 | * Return true if node is `PropertyAccessExpression` 8 | * @param node A TypeScript node 9 | */ 10 | export function isPropertyAccessExpression(node: ts.Node): node is ts.PropertyAccessExpression { 11 | return node.kind === ts.SyntaxKind.PropertyAccessExpression; 12 | } 13 | 14 | /** 15 | * Return true if node is `CallExpression` 16 | * @param node A TypeScript node 17 | */ 18 | export function isCallExpression(node: ts.Node): node is ts.CallExpression { 19 | return node.kind === ts.SyntaxKind.CallExpression; 20 | } 21 | 22 | /** 23 | * Return true if node is `Identifier` 24 | * @param node A TypeScript node 25 | */ 26 | export function isIdentifier(node: ts.Node): node is ts.Identifier { 27 | return node.kind === ts.SyntaxKind.Identifier; 28 | } 29 | 30 | /** 31 | * Return true if node is `VariableDeclaration` 32 | * @param node A TypeScript node 33 | */ 34 | export function isVariableDeclaration(node: ts.Node): node is ts.VariableDeclaration { 35 | return node.kind === ts.SyntaxKind.VariableDeclaration; 36 | } 37 | 38 | /** 39 | * Return true if node is `ExportAssignment` 40 | * @param node A TypeScript node 41 | */ 42 | export function isExportAssignment(node: ts.Node): node is ts.ExportAssignment { 43 | return node.kind === ts.SyntaxKind.ExportAssignment; 44 | } 45 | 46 | /** 47 | * Return true if node is `TaggedTemplateExpression` 48 | * @param node A TypeScript node 49 | */ 50 | export function isTaggedTemplateExpression(node: ts.Node): node is ts.TaggedTemplateExpression { 51 | return node.kind === ts.SyntaxKind.TaggedTemplateExpression; 52 | } 53 | 54 | /** 55 | * Return true if node is `TemplateExpression` 56 | * @param node A TypeScript node 57 | */ 58 | export function isTemplateExpression(node: ts.Node): node is ts.TemplateExpression { 59 | return node.kind === ts.SyntaxKind.TemplateExpression; 60 | } 61 | 62 | /** 63 | * Return true if node is `NoSubstitutionTemplateLiteral` 64 | * @param node A TypeScript node 65 | */ 66 | export function isNoSubstitutionTemplateLiteral(node: ts.Node): node is ts.NoSubstitutionTemplateLiteral { 67 | return node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral; 68 | } 69 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es2015", 5 | /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ 6 | "module": "commonjs", 7 | /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ 8 | // "lib": [], /* Specify library files to be included in the compilation: */ 9 | // "allowJs": true, /* Allow javascript files to be compiled. */ 10 | // "checkJs": true, /* Report errors in .js files. */ 11 | "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 12 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 13 | "sourceMap": true, /* Generates corresponding '.map' file. */ 14 | // "outFile": "./", /* Concatenate and emit output to single file. */ 15 | "outDir": "./dist", /* Redirect output structure to the directory. */ 16 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 17 | // "removeComments": true, /* Do not emit comments to output. */ 18 | // "noEmit": true, /* Do not emit outputs. */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | // "strictNullChecks": true, /* Enable strict null checks. */ 27 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 28 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 29 | 30 | /* Additional Checks */ 31 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 32 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 33 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 34 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 35 | 36 | /* Module Resolution Options */ 37 | "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 38 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 39 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 40 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 41 | // "typeRoots": [], /* List of folders to include type definitions from. */ 42 | // "types": [], /* Type declaration files to be included in compilation. */ 43 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 44 | 45 | /* Source Map Options */ 46 | // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 47 | // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ 48 | //"inlineSourceMap": true, 49 | /* Emit a single file with source maps instead of having a separate file. */ 50 | //"inlineSources": true 51 | /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 52 | 53 | /* Experimental Options */ 54 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 55 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 56 | }, 57 | "exclude": [ 58 | "node_modules", 59 | "src/__tests__", 60 | "src/runner.ts", 61 | "example" 62 | ] 63 | } 64 | --------------------------------------------------------------------------------