├── .babelrc
├── .eslintignore
├── .eslintrc.js
├── .github
├── FUNDING.yml
└── workflows
│ └── ci.yml
├── .gitignore
├── .npmignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── __tests__
├── config.ts
├── files
│ ├── config.json
│ ├── fixtures
│ │ ├── css
│ │ │ ├── css-attributes.css
│ │ │ ├── css-variables.css
│ │ │ ├── style.css
│ │ │ ├── style2.css
│ │ │ └── subdirectory
│ │ │ │ └── style.css
│ │ ├── html
│ │ │ ├── index-with-style.html
│ │ │ └── index.html
│ │ ├── js
│ │ │ ├── complex.js
│ │ │ ├── main.js
│ │ │ └── react.js
│ │ └── pug
│ │ │ └── index.pug
│ ├── issue21
│ │ ├── fixtures
│ │ │ ├── index.html
│ │ │ └── style.css
│ │ └── results
│ │ │ ├── index.html
│ │ │ └── style.css
│ ├── issue70
│ │ ├── fixtures
│ │ │ ├── index.html
│ │ │ └── style.css
│ │ └── results
│ │ │ ├── index.html
│ │ │ └── style.css
│ └── results
│ │ ├── css
│ │ ├── css-attributes-ignore.css
│ │ ├── css-attributes-pre-suffix.css
│ │ ├── css-attributes.css
│ │ ├── css-variables-ignore.css
│ │ ├── css-variables.css
│ │ ├── style-prefix.css
│ │ ├── style-with-config.css
│ │ ├── style.css
│ │ ├── style2.css
│ │ └── subdirectory
│ │ │ └── style.css
│ │ ├── html
│ │ ├── index-with-style.html
│ │ └── index.html
│ │ ├── js
│ │ ├── complex.js
│ │ ├── main.js
│ │ └── react.js
│ │ └── pug
│ │ └── index.pug
├── generateMapping.ts
├── helpers
│ └── reset.ts
├── integration.ts
├── integration_mapping.ts
├── loadMapping.ts
├── processAuto.ts
├── processAutoSync.ts
├── processCss.ts
├── processCssSync.ts
├── processJs.ts
├── processJsSync.ts
├── processPug.ts
├── processPugSync.ts
├── save.ts
└── saveSync.ts
├── docs
├── api
│ ├── config.md
│ ├── loadMapping.md
│ ├── mapping.md
│ ├── processAny.md
│ ├── processAuto.md
│ ├── processCss.md
│ ├── processHtml.md
│ ├── processJs.md
│ └── processPug.md
└── caveats.md
├── global.d.ts
├── jest.config.js
├── jest.setup.js
├── lib
├── Config.ts
├── helper
│ ├── save.ts
│ └── saveSync.ts
├── index.ts
├── mapping
│ ├── generateMapping.ts
│ └── loadMapping.ts
└── process
│ ├── defaults.ts
│ ├── process.ts
│ ├── processSync.ts
│ ├── replaceData.ts
│ └── typeChooser
│ ├── typeChooser.ts
│ └── typeChooserSync.ts
├── package-lock.json
├── package.json
└── tsconfig.json
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "add-module-exports"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | __tests__/files
2 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | browser: true,
4 | es6: true,
5 | jest: true,
6 | },
7 | extends: [
8 | 'plugin:@typescript-eslint/recommended',
9 | 'airbnb-base'
10 | ],
11 | plugins: ['@typescript-eslint'],
12 | parser: '@typescript-eslint/parser',
13 | globals: {
14 | Atomics: 'readonly',
15 | SharedArrayBuffer: 'readonly',
16 | },
17 | parserOptions: {
18 | ecmaVersion: 2018,
19 | sourceType: 'module',
20 | },
21 | settings: {
22 | 'import/resolver': {
23 | node: {
24 | extensions: ['.js', '.ts'],
25 | },
26 | },
27 | },
28 | overrides: [
29 | {
30 | files: ['*.ts', '*.tsx'],
31 | rules: {
32 | 'no-dupe-class-members': 'off',
33 | },
34 | },
35 | ],
36 | rules: {
37 | '@typescript-eslint/explicit-function-return-type': ['warn', {
38 | allowTypedFunctionExpressions: true,
39 | allowExpressions: true,
40 | }],
41 | 'import/extensions': ['error', 'ignorePackages', {
42 | js: 'never',
43 | ts: 'never',
44 | }],
45 | }
46 | };
47 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: jpeer
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Node.js CI
2 | on:
3 | push:
4 | branches:
5 | - main
6 | pull_request:
7 |
8 | jobs:
9 | test:
10 | strategy:
11 | matrix:
12 | node: [12.x, 14.x, 16.x]
13 | os: [ubuntu-latest]
14 | runs-on: ${{ matrix.os }}
15 | steps:
16 | - uses: actions/checkout@v2
17 | - name: Use Node.js ${{ matrix.node }}
18 | uses: actions/setup-node@v1
19 | with:
20 | node-version: ${{ matrix.node }}
21 | - run: npm install
22 | - run: npm test
23 | - name: Coveralls Parallel
24 | uses: coverallsapp/github-action@master
25 | with:
26 | github-token: ${{ secrets.github_token }}
27 | flag-name: run-${{ matrix.test_number }}
28 | parallel: true
29 | finish:
30 | runs-on: ubuntu-latest
31 | needs: test
32 | steps:
33 | - name: Coveralls
34 | uses: coverallsapp/github-action@master
35 | with:
36 | github-token: ${{ secrets.GITHUB_TOKEN }}
37 | parallel-finished: true
38 |
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # modules
2 | node_modules
3 | npm-debug.log
4 |
5 | **/testCache/**
6 | coverage
7 | .vscode
8 | .nyc_output
9 | dest
10 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | coverage/
2 | __tests__/
3 | .travis.yml
4 | lib/
5 | docs
6 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | 4.1.0 - November, 23 2021
2 |
3 | * 7e32f5c Feat: enable optimization from rcs-core by default (closes #80) (#81) (Jan Peer Stöcklmair)
4 | * 6a10373 Chore: add github actions (JPeer264)
5 | * 704d808 4.0.0 (JPeer264)
6 | * 04ecf36 Chore: update babel (JPeer264)
7 | * f5bff64 Feat: move to previous .config instead of .Config.getInstance() (JPeer264)
8 | * 9931075 Chore(deps): bump pug-code-gen from 2.0.2 to 2.0.3 (#72) (dependabot[bot])
9 | * e002f00 Chore(deps): bump lodash from 4.17.15 to 4.17.21 (#73) (dependabot[bot])
10 | * 2c14a98 Chore(deps): bump hosted-git-info from 2.8.5 to 2.8.9 (#74) (dependabot[bot])
11 | * bac2aef Chore(deps): bump ws from 7.2.1 to 7.4.6 (#75) (dependabot[bot])
12 | * 9e03949 Chore(deps): bump postcss from 7.0.35 to 7.0.36 (#76) (dependabot[bot])
13 |
14 | 4.0.0 - June, 22 2021
15 |
16 | * 04ecf36 Chore: update babel (JPeer264)
17 | * f5bff64 Feat: move to previous .config instead of .Config.getInstance() (JPeer264)
18 | * 9931075 Chore(deps): bump pug-code-gen from 2.0.2 to 2.0.3 (#72) (dependabot[bot])
19 | * e002f00 Chore(deps): bump lodash from 4.17.15 to 4.17.21 (#73) (dependabot[bot])
20 | * 2c14a98 Chore(deps): bump hosted-git-info from 2.8.5 to 2.8.9 (#74) (dependabot[bot])
21 | * bac2aef Chore(deps): bump ws from 7.2.1 to 7.4.6 (#75) (dependabot[bot])
22 | * 9e03949 Chore(deps): bump postcss from 7.0.35 to 7.0.36 (#76) (dependabot[bot])
23 |
24 | 4.0.0-rc.3 - January, 07 2021
25 |
26 | * 9f74c0b Feat: use rcs-core mappings (JPeer264)
27 | * adf10d1 Test: add test case for issue 70 (closes #70) (JPeer264)
28 | * 8b68a2a Chore: update rcs-core in dev (JPeer264)
29 | * f1ddcef Docs: add rcs-core to install (JPeer264)
30 | * 3e14683 Docs: move caveats up (JPeer264)
31 | * 7f612f1 Docs: add rcsCore usage (closes #65) (JPeer264)
32 |
33 | 4.0.0-rc.2 - May, 12 2020
34 |
35 | * 265c6c8 Style: remove eslint errors (JPeer264)
36 |
37 | 4.0.0-rc.1 - May, 11 2020
38 |
39 | * a43e6a7 Feat: add caveats (JPeer264)
40 | * d320168 Feat: add support for warning the user about bad lib usage (JPeer264)
41 | * 21af8a5 Feat: ignore files with config file (JPeer264)
42 | * 7fe282c Chore: add funding.yml (Jan Peer Stöcklmair)
43 | * 4ceb812 Feat: add handlebars to html fileExt (JPeer264)
44 |
45 | 4.0.0-rc.0 - February, 20 2020
46 |
47 | * 6fd491e Docs: add plugin notice (JPeer264)
48 | * 5aa9bb5 Refactor: make save and generateMapping promise first (JPeer264)
49 | * 321e95f Refactor: remove lodash.merge (JPeer264)
50 | * 963dbf3 Chore(deps): bump lodash from 4.17.4 to 4.17.15 (#47) (dependabot[bot])
51 | * aa5dee0 Refactor: tests to ts (#61) (Jan Peer Stöcklmair)
52 | * 07e3461 Refactor: add default export to lib index (JPeer264)
53 | * 53a20a1 Chore: add lint-staged and husky (JPeer264)
54 | * 1425784 Chore: add declarations for built files (JPeer264)
55 | * 3341fca Test: fix tests (JPeer264)
56 | * 09114ad Refactor: outsource type from options into own parameter (JPeer264)
57 | * 4173604 Test: add missing tests with tmp dir (JPeer264)
58 | * 894a2d5 Test: speeding up tests by generating proper tmp folders (JPeer264)
59 | * 7bd2910 Fix: remove unnecessary throw (JPeer264)
60 | * 53bcb68 Refactor: make process promise based (JPeer264)
61 | * 04b7a6a Refactor: lib to typescript (#60) (Jan Peer Stöcklmair)
62 | * fa652c1 Chore: update packagelock (JPeer264)
63 | * f3861da Chore: drop Node v6 and v8 support | add v12 support (JPeer264)
64 | * f5c68fa Chore: update npmignore (JPeer264)
65 | * 7b28317 Chore: remove yarn and switch to npm (JPeer264)
66 | * 9a92c13 Chore: update eslint paths (JPeer264)
67 | * 953b48c Test: update wrong path (JPeer264)
68 | * 0992d8f Test: update test files based on new rcs-core nameGenerator library (JPeer264)
69 | * 5477b72 Refactor: remove extended option (JPeer264)
70 | * 96ba334 Test: changing way of error handling in generateMapping (JPeer264)
71 | * 477e4e3 Chore: remove ava config from package.json (JPeer264)
72 | * c3085dc Chore: update to babel 7 (JPeer264)
73 | * c439166 Chore: move to jest (#57) (Jan Peer Stöcklmair)
74 | * 0622182 Chore: fix eslint errors (JPeer264)
75 | * b5fc01e Chore: auto fix eslint (JPeer264)
76 | * a0d1e5d Chore: change to import / export (JPeer264)
77 | * 94373c2 Chore: update eslintrc (JPeer264)
78 | * 862b193 Chore: new deploy method (JPeer264)
79 | * 3da64d6 Chore: change to typescript (JPeer264)
80 | * f4a7fb0 Chore: update rcs-core to 3.0.1 (JPeer264)
81 |
82 | 3.2.8 - February, 13 2020
83 |
84 | * 36cb329 Chore: update rcs-core (JPeer264)
85 |
86 | 3.2.5 - August, 01 2019
87 |
88 | * 5f6bf01 Test: add testcase for #43 (JPeer264)
89 | * 50388ff Chore: update rcs-core to 2.6.2 (JPeer264)
90 |
91 | 3.2.4 - July, 23 2019
92 |
93 | * 912f491 Chore: update rcs-core (JPeer264)
94 |
95 | 3.2.3 - June, 22 2019
96 |
97 | * 13610be Fix: process fill html for sync variant (JPeer264)
98 |
99 | 3.2.2 - June, 22 2019
100 |
101 | * 10b644a Fix: fill library from html files (#41) (Jan Peer Stöcklmair)
102 | * 3a28005 Fix: forgot to pass ignoreCssVariables options (closes #39) (#40) (Jan Peer Stöcklmair)
103 |
104 | 3.2.1 - May, 10 2019
105 |
106 | * ce44c98 Chore: seems like something went wrong with the rcs-core release (JPeer264)
107 |
108 | 3.2.0 - May, 10 2019
109 |
110 | * 0b52450 Feat: css variables support / update rcs-core (closes #37) (JPeer264)
111 |
112 | 3.1.4 - February, 06 2019
113 |
114 | * 4c02258 Chore: update rcs-core (JPeer264)
115 |
116 | 3.1.3 - December, 23 2018
117 |
118 | * 7a16dbb Chore: update rcs-core to 2.4.3 (JPeer264)
119 |
120 | 3.1.2 - December, 16 2018
121 |
122 | * fbb35f2 Chore: update rcs-core (JPeer264)
123 | * abaf6d4 Docs: show how to include rcsrc (#33) (Jan Peer Stöcklmair)
124 |
125 | 3.1.1 - September, 01 2018
126 |
127 | * c05c023 Chore: update rcs-core to 2.4.1 (JPeer264)
128 |
129 | 3.1.0 - August, 28 2018
130 |
131 | * 368693c Feat: rcs.process.pug (closes #22) (#29) (Jan Peer Stöcklmair)
132 |
133 | 3.0.0 - August, 26 2018
134 |
135 | * 10c303b Docs: improve readme (JPeer264)
136 | * 6c5eb44 Test: add tests for html (closes #21) (#28) (Jan Peer Stöcklmair)
137 | * ec8f026 Fix: rename if path is Array and includes just one element (closes #19) (#27) (Jan Peer Stöcklmair)
138 | * d05ba8b Feat: refactor process (#26) (Jan Peer Stöcklmair)
139 | * e0e728e Style: other way of exporting (JPeer264)
140 | * 8e7001f Docs: update to new docs structure (closes #17) (#24) (Jan Peer Stöcklmair)
141 | * 6625141 Feat: add promise functionality (#25) (Jan Peer Stöcklmair)
142 | * f241fd0 Style: consistent code (JPeer264)
143 | * ed9eb26 Test: mocha to ava (#23) (Jan Peer Stöcklmair)
144 |
145 | 2.0.0 - June, 18 2018
146 |
147 | * b9a751d Feat: update rcs-core and add parserOptions in processJs (closes #16) (JPeer264)
148 | * 448747a Style: remove eslint warnings (JPeer264)
149 | * 465aab5 Chore: remove Node 4 support, add v8 and v10 (JPeer264)
150 | * 569dae2 Style: eslint fix (JPeer264)
151 | * f1e5e56 Feat: update to rcs-core@2.0.1 (JPeer264)
152 |
153 | 1.3.5 - April, 26 2018
154 |
155 | * 691303b Chore: update to rcs-core@1.0.5 (JPeer264)
156 |
157 | 1.3.4 - February, 11 2018
158 |
159 | * adb9f09 Chore: update rcs-core to 1.0.4 (closes #14) (#15) (Jan Peer Stöcklmair)
160 |
161 | 1.3.3 - February, 09 2018
162 |
163 | * 6c9b922 Chore: update rcs-core to 1.0.3 (#13) (Jan Peer Stöcklmair)
164 | * 857d458 1.3.2 (JPeer264)
165 | * e5cbea5 Chore: update to newest rcs-core (JPeer264)
166 | * 91f64a2 Style: fix eslint errors (JPeer264)
167 | * e9805bc Chore: add eslint to workflow (JPeer264)
168 |
169 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Jan Peer Stöcklmair
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Rename CSS Selectors (RCS)
2 |
3 | [](https://travis-ci.org/JPeer264/node-rename-css-selectors)
4 | [](https://coveralls.io/github/JPeer264/node-rename-css-selectors?branch=master)
5 |
6 | > **Note:** Please make sure your files are not minified/uglified. Do that after processing it with `rename-css-selectors`
7 |
8 | This module renames all CSS selectors in the given files. It will collect all selectors from the given CSS files. Do not worry about your selectors, `rcs` will do it for you.
9 |
10 | You can also use a config file with the combination of [generateMapping](#generateMapping) and [loadMapping](#loadMapping), if you already had other projects with the same classes. So all your projects have the same minified selector names - always.
11 |
12 | This is a plugin of [rcs-core](https://github.com/JPeer264/node-rcs-core)
13 |
14 | ## Contents
15 |
16 | - [Installation](#installation)
17 | - [Usage](#usage)
18 | - [Methods](#methods)
19 | - [Caveats](#caveats)
20 | - [LICENSE](#license)
21 |
22 | ## Installation
23 |
24 | Install with [npm](https://docs.npmjs.com/cli/install) or [yarn](https://yarnpkg.com/en/docs/install)
25 |
26 | ```sh
27 | npm i rename-css-selectors rcs-core
28 | ```
29 | or
30 | ```sh
31 | yarn add rename-css-selectors rcs-core
32 | ```
33 |
34 | ## Usage
35 |
36 | Async:
37 |
38 | > There are 3 different ways of writing async `rcs` code: callbacks, promises and async/await
39 |
40 | ```js
41 | // you can use every method of `rcs-core` on top
42 | const rcsCore = require('rcs-core');
43 | const rcs = require('rename-css-selectors')
44 |
45 | // if you want to include the .rcsrc config
46 | rcs.config.load();
47 |
48 | // if you have some generated mappings - load them!
49 | // you can also specify the string although it does not exist yet.
50 | rcs.mapping.load('./renaming_map.json');
51 |
52 | // now with rcsCore you could e.g. ignore single variables (optional)
53 | rcsCore.baseLibrary.setExclude(/<%=[\s\S]+%>/);
54 |
55 | // callback
56 | rcs.process.auto(['**/*.js', '**/*.html', '**/*.css'], options, (err) => {
57 | // all css files are now saved, renamed and stored in the selectorLibrary
58 | // also other files are not renamed
59 | // that's it
60 |
61 | // maybe you want to add the new selectors to your previous generated mappings
62 | // do not worry, your old settings are still here, in case you used `rcs.mapping.load`
63 | rcs.mapping.generate('./', { overwrite: true }, (err) => {
64 | // the mapping file is now saved
65 | });
66 | });
67 |
68 | // promise
69 | rcs.process.auto(['**/*.js', '**/*.html', '**/*.css'], options)
70 | .then(() => rcs.mapping.generate('./', { overwrite: true }))
71 | .catch(console.error);
72 |
73 | // async/await
74 | (async () => {
75 | try {
76 | await rcs.process.auto(['**/*.js', '**/*.html', '**/*.css'], options);
77 | await rcs.mapping.generate('./', { overwrite: true });
78 | } catch (err) {
79 | console.error(err);
80 | }
81 | })();
82 | ```
83 |
84 | Sync:
85 |
86 | ```js
87 | const rcs = require('rename-css-selectors');
88 |
89 | rcs.mapping.load('./renaming_map.json');
90 |
91 | try {
92 | rcs.process.autoSync(['**/*.js', '**/*.html', '**/*.css'], options);
93 | rcs.mapping.generateSync('./', { overwrite: true });
94 | } catch (err) {
95 | console.error(err);
96 | }
97 | ```
98 |
99 | ## Methods
100 |
101 | - [rcs.process.auto](docs/api/processAuto.md)
102 | - [rcs.process.css](docs/api/processCss.md)
103 | - [rcs.process.js](docs/api/processJs.md)
104 | - [rcs.process.html](docs/api/processHtml.md)
105 | - [rcs.process.pug](docs/api/processPug.md)
106 | - [rcs.process.any](docs/api/processAny.md)
107 | - [rcs.mapping](docs/api/mapping.md)
108 | - [rcs.config](docs/api/config.md)
109 |
110 | ## Caveats
111 |
112 | Correctly using `rename-css-selectors` on large project means few rules should be followed.
113 | [This document](https://github.com/JPeer264/node-rcs-core/blob/main/docs/caveats.md) explains most of them.
114 |
115 | # LICENSE
116 |
117 | MIT © [Jan Peer Stöcklmair](https://www.jpeer.at)
118 |
--------------------------------------------------------------------------------
/__tests__/config.ts:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import fs from 'fs-extra';
3 | import rcsCore from 'rcs-core';
4 | import rcs from '../lib';
5 |
6 | const testFiles = path.join(process.cwd(), '/__tests__/files');
7 |
8 | beforeEach(() => {
9 | rcsCore.selectorsLibrary.getClassSelector().nameGenerator.setAlphabet('#abcdefghijklmnopqrstuvwxyz');
10 | rcsCore.selectorsLibrary.getIdSelector().nameGenerator.setAlphabet('#abcdefghijklmnopqrstuvwxyz');
11 | rcsCore.selectorsLibrary.reset();
12 | rcsCore.keyframesLibrary.reset();
13 | });
14 |
15 | it('should set the config with package.json', () => {
16 | // include config
17 | rcs.config.load();
18 |
19 | // include new settings
20 | rcsCore.selectorsLibrary.set(['.js', '.any-value']);
21 |
22 | expect(rcsCore.selectorsLibrary.get('js')).toBe('js');
23 | expect(rcsCore.selectorsLibrary.get('any-value')).toBe('a');
24 | });
25 |
26 | it('should set the config with .rcsrc', () => {
27 | const file = '.rcsrc';
28 |
29 | fs.writeFileSync(file, `{
30 | "exclude": [
31 | "flexbox",
32 | "no-js"
33 | ],
34 | "reserve": [
35 | "ad"
36 | ]
37 | }`, {
38 | encoding: 'utf8',
39 | });
40 |
41 | // include config
42 | rcs.config.load();
43 |
44 | // include new settings
45 | rcsCore.selectorsLibrary.set(['.flexbox', '.any-value']);
46 |
47 | expect(rcsCore.selectorsLibrary.get('flexbox')).toBe('flexbox');
48 | expect(rcsCore.selectorsLibrary.get('any-value')).toBe('a');
49 |
50 | fs.removeSync(file);
51 | });
52 |
53 | it('should set the config with package.json', () => {
54 | // include config
55 | rcs.config.load(path.join(testFiles, '/config.json'));
56 |
57 | // include new settings
58 | rcsCore.selectorsLibrary.set(['.own-file', '.any-value']);
59 |
60 | expect(rcsCore.selectorsLibrary.get('own-file')).toBe('own-file');
61 | expect(rcsCore.selectorsLibrary.get('any-value')).toBe('a');
62 | });
63 |
64 | it('should load ignored patterns', () => {
65 | const file = '.rcsrc';
66 |
67 | fs.writeFileSync(file, `{
68 | "ignore": [
69 | "a.js",
70 | "**.min.js"
71 | ]
72 | }`, {
73 | encoding: 'utf8',
74 | });
75 |
76 | // include config
77 | rcs.config.load();
78 |
79 | expect(rcs.config.isIgnored('a.js')).toBe(true);
80 | expect(rcs.config.isIgnored('b.min.js')).toBe(true);
81 | expect(rcs.config.isIgnored('b.js')).toBe(false);
82 |
83 | fs.removeSync(file);
84 | });
85 |
--------------------------------------------------------------------------------
/__tests__/files/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "exclude": [
3 | "own-file",
4 | "no-js"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/__tests__/files/fixtures/css/css-attributes.css:
--------------------------------------------------------------------------------
1 | .selector[class*="block"] {
2 | }
3 |
4 | .block[class*="block"] {
5 | }
6 |
7 | .class[id^="pre-"] {
8 | }
9 |
10 | .another-class[class$="ctor"] {
11 | }
12 |
--------------------------------------------------------------------------------
/__tests__/files/fixtures/css/css-variables.css:
--------------------------------------------------------------------------------
1 | .theme {
2 | --theme-primary: #111;
3 | --theme-secondary: #f0f0f0;
4 | --theme-tertiary: #999;
5 | }
6 |
7 | .theme--variant {
8 | --theme-primary: red;
9 | --theme-secondary: white;
10 | --theme-tertiary: black;
11 | }
12 |
13 | .box {
14 | color: var(--theme-primary);
15 | background-color: var(--theme-secondary);
16 | font-size: 1.2em;
17 | line-height: 1.4;
18 | width: 100%;
19 | max-width: 400px;
20 | padding: 5px;
21 | border: 1px solid var(--theme-tertiary);
22 | margin: 0 0 20px;
23 | }
24 |
25 | .jp-block {
26 | content: 'block';
27 | }
28 |
29 | .jp-block__element {
30 | content: 'block__element';
31 | }
32 |
33 | .jp-block__element--modifier {
34 | content: 'block__element--modifier';
35 | }
36 |
37 | .jp-block--modifier{
38 | content: 'block--modifier';
39 | }
40 |
41 | .jp-pseudo:before {
42 | content: 'before';
43 | }
44 |
45 | .jp-block__element--modifier {
46 | content: 'block__element--modifier';
47 | }
48 |
49 | #id {
50 | content: 'id';
51 | }
52 |
53 | .jp-attribute[src] {
54 | content: 'attribute';
55 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
56 | }
57 |
58 | @media screen and (min-width: .40em) {
59 | #id {
60 | height: .20px;
61 | width: .20em;
62 | }
63 | }
64 |
65 | /**
66 | * a description
67 | */
68 | @media screen and (min-width: 40em)
69 |
70 | {
71 | #id
72 | {
73 | height: .20px;
74 | width: .20em;
75 | }
76 | }
77 |
78 | h1 {
79 | color: red;
80 | }
81 |
82 | .reveal {
83 | content: 'reveal';
84 | color: #eee;
85 | font-size: .5rem;
86 | }
87 |
88 | .js.reveal {
89 | content: 'js reveal';
90 | margin-right: calc(var(--theme-primary, var(--0px)) - var(--theme-secondary, var(--0px)));
91 | margin-bottom: calc(var(--theme-tertiary, var(--0px)) - var(--theme-primary, var(--0px)));
92 | }
93 |
94 | .no-js.reveal {
95 | content: 'js reveal';
96 | }
97 |
98 | .js-reveal {
99 | content: 'js-reveal';
100 | }
101 |
--------------------------------------------------------------------------------
/__tests__/files/fixtures/css/style.css:
--------------------------------------------------------------------------------
1 | .jp-block {
2 | content: 'block';
3 | }
4 |
5 | .jp-block__element {
6 | content: 'block__element';
7 | }
8 |
9 | .jp-block__element--modifier {
10 | content: 'block__element--modifier';
11 | }
12 |
13 | .jp-block--modifier{
14 | content: 'block--modifier';
15 | }
16 |
17 | .jp-pseudo:before {
18 | content: 'before';
19 | }
20 |
21 | .jp-block__element--modifier {
22 | content: 'block__element--modifier';
23 | }
24 |
25 | #id {
26 | content: 'id';
27 | }
28 |
29 | .jp-attribute[src] {
30 | content: 'attribute';
31 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
32 | }
33 |
34 | @media screen and (min-width: .40em) {
35 | #id {
36 | height: .20px;
37 | width: .20em;
38 | }
39 | }
40 |
41 | /**
42 | * a description
43 | */
44 | @media screen and (min-width: 40em)
45 |
46 | {
47 | #id
48 | {
49 | height: .20px;
50 | width: .20em;
51 | }
52 | }
53 |
54 | h1 {
55 | color: red;
56 | }
57 |
58 | .reveal {
59 | content: 'reveal';
60 | color: #eee;
61 | font-size: .5rem;
62 | }
63 |
64 | .js.reveal {
65 | content: 'js reveal';
66 | }
67 |
68 | .no-js.reveal {
69 | content: 'js reveal';
70 | }
71 |
72 | .js-reveal {
73 | content: 'js-reveal';
74 | }
75 |
--------------------------------------------------------------------------------
/__tests__/files/fixtures/css/style2.css:
--------------------------------------------------------------------------------
1 | #id {
2 | content: 'id';
3 | }
4 |
5 | .jp-block__element {
6 | content: 'block__element';
7 | }
8 |
9 | .jp-block__element--modifier {
10 | content: 'block__element--modifier';
11 | }
12 |
13 | .jp-block__element--modifier {
14 | content: 'block__element--modifier';
15 | }
16 |
17 | .jp-block--modifier{
18 | content: 'block--modifier';
19 | }
20 |
21 | .jp-block {
22 | content: 'block';
23 | }
24 |
25 | .jp-pseudo:before {
26 | content: 'before';
27 | }
28 |
--------------------------------------------------------------------------------
/__tests__/files/fixtures/css/subdirectory/style.css:
--------------------------------------------------------------------------------
1 | .jp-block {
2 | content: 'block';
3 | }
4 |
5 | .jp-block__element--modifier {
6 | content: 'block__element--modifier';
7 | }
8 |
9 | .jp-block__element {
10 | content: 'block__element';
11 | }
12 |
13 | .jp-block--modifier{
14 | content: 'block--modifier';
15 | }
16 |
17 | .jp-block__element--modifier {
18 | content: 'block__element--modifier';
19 | }
20 |
21 | .jp-pseudo:before {
22 | content: 'before';
23 | }
24 |
25 | #id {
26 | content: 'id';
27 | }
28 |
--------------------------------------------------------------------------------
/__tests__/files/fixtures/html/index-with-style.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Test Document
6 |
7 |
8 |
9 |
10 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/__tests__/files/fixtures/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Test Document
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/__tests__/files/fixtures/js/complex.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | /**
3 | * Finds the index of the first character
4 | * that's not common between the two given strings.
5 | *
6 | * @return {number} the index of the character where the strings diverge
7 | */
8 | function firstDifferenceIndex(string1, string2) {
9 | var minLen = Math.min(string1.length, string2.length);
10 | for (var i = 0; i < minLen; i++) {
11 | if (string1.charAt(i) !== string2.charAt(i)) {
12 | return i;
13 | }
14 | }
15 | return string1.length === string2.length ? -1 : minLen;
16 | }
17 |
18 | /***/ (function(module, exports) {
19 |
20 | // removed by extract-text-webpack-plugin
21 | module.exports = {"table":"jp-block","key":"jp-pseudo"};
22 |
23 | /***/ }),
24 | /* 523 */
25 | /***/ (function(module, exports, __webpack_require__) {
26 |
27 | var defineProperty = __webpack_require__(531);
28 |
29 | /**
30 | * The base implementation of `assignValue` and `assignMergeValue` without
31 | * value checks.
32 | *
33 | * @private
34 | * @param {Object} object The object to modify.
35 | * @param {string} key The key of the property to assign.
36 | * @param {*} value The value to assign.
37 | */
38 | function baseAssignValue(object, key, value) {
39 | if (key == '__proto__' && defineProperty) {
40 | defineProperty(object, key, {
41 | 'configurable': true,
42 | 'enumerable': true,
43 | 'value': value,
44 | 'writable': true
45 | });
46 | } else {
47 | object[key] = value;
48 | }
49 | }
50 |
51 | module.exports = baseAssignValue;
52 |
53 |
54 | /***/ })
55 |
--------------------------------------------------------------------------------
/__tests__/files/fixtures/js/main.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // jQuery example
3 | $(".jp-block");
4 |
5 | // vanillaJS example
6 | document.getElementsByClassName("jp-block__element");
7 | document.getElementById("jp-block__element--modifier");
8 |
9 | const restSpread = {
10 | weirdFormatting: true,
11 | shouldRest: true,
12 | };
13 |
14 | const extended = { ...restSpread };
15 | const { ...options } = extended;
16 |
--------------------------------------------------------------------------------
/__tests__/files/fixtures/js/react.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import PropTypes from 'prop-types';
3 | import React, { Component } from 'react';
4 | import { bindActionCreators } from 'redux';
5 | import { connect } from 'react-redux';
6 |
7 | import ListView from '../components/ListView';
8 | import eventActions from '../redux/eventsRedux';
9 | import { getAllEvents } from '../selectors';
10 |
11 | class Events extends Component {
12 | componentWillMount() {
13 | this.props.startup();
14 | }
15 |
16 | componentWillReceiveProps(nextProps) {
17 | this.props.events = nextProps.events;
18 | }
19 |
20 | renderEvent() {
21 | if (this.props.events.length === 0) {
22 | return is
;
23 | }
24 |
25 | return ;
26 | }
27 |
28 | render() {
29 | return (
30 |
31 | { this.renderEvent() }
32 |
33 | );
34 | }
35 | }
36 |
37 | Events.propTypes = {
38 | events: PropTypes.arrayOf(PropTypes.shape({
39 | name: PropTypes.string.isRequired,
40 | })),
41 | startup: PropTypes.func.isRequired,
42 | };
43 |
44 | Events.defaultProps = {
45 | events: [
46 | {
47 | name: 'No Event',
48 | },
49 | ],
50 | };
51 |
52 | const mapStateToProps = state => ({
53 | events: getAllEvents(state),
54 | });
55 |
56 | const mapDispatchToProps = dispatch => bindActionCreators({
57 | startup: eventActions.eventsRequest,
58 | }, dispatch);
59 |
60 | export default connect(mapStateToProps, mapDispatchToProps)(Events);
61 |
--------------------------------------------------------------------------------
/__tests__/files/fixtures/pug/index.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | head
3 | meta(charset='UTF-8')
4 | title Test Document
5 | .jp-block
6 | .jp-block__element
7 |
--------------------------------------------------------------------------------
/__tests__/files/issue21/fixtures/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | '
7 |
8 |
9 |
10 |
11 | '
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/__tests__/files/issue21/fixtures/style.css:
--------------------------------------------------------------------------------
1 | .wf-active {
2 | color: red;
3 | }
4 |
5 | .test {
6 | font-weight: bold;
7 | }
8 |
--------------------------------------------------------------------------------
/__tests__/files/issue21/results/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | '
7 |
8 |
9 |
10 |
11 | '
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/__tests__/files/issue21/results/style.css:
--------------------------------------------------------------------------------
1 | .a {
2 | color: red;
3 | }
4 |
5 | .b {
6 | font-weight: bold;
7 | }
8 |
--------------------------------------------------------------------------------
/__tests__/files/issue70/fixtures/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Animals
6 |
7 |
8 |
9 |
10 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/__tests__/files/issue70/fixtures/style.css:
--------------------------------------------------------------------------------
1 | .container {}
2 | .text-center {}
3 | .d-flex {}
4 | .flex-column {}
5 | .justify-content-center {}
6 | .align-items-center {}
7 | .align-content-center {}
8 | .ct-fluid {}
9 |
--------------------------------------------------------------------------------
/__tests__/files/issue70/results/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Animals
6 |
7 |
8 |
9 |
10 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/__tests__/files/issue70/results/style.css:
--------------------------------------------------------------------------------
1 | .a {}
2 | .b {}
3 | .c {}
4 | .d {}
5 | .e {}
6 | .f {}
7 | .g {}
8 | .h {}
9 |
--------------------------------------------------------------------------------
/__tests__/files/results/css/css-attributes-ignore.css:
--------------------------------------------------------------------------------
1 | .prefix-a-suffix[class*="block"] {
2 | }
3 |
4 | .prefix-b-suffix[class*="block"] {
5 | }
6 |
7 | .prefix-c-suffix[id^="prefix-pre-"] {
8 | }
9 |
10 | .prefix-d-suffix[class$="ctor-suffix"] {
11 | }
12 |
--------------------------------------------------------------------------------
/__tests__/files/results/css/css-attributes-pre-suffix.css:
--------------------------------------------------------------------------------
1 | .prefix-tctor-suffix[class*="block"] {
2 | }
3 |
4 | .prefix-tblockn-suffix[class*="block"] {
5 | }
6 |
7 | .prefix-a-suffix[id^="prefix-pre-"] {
8 | }
9 |
10 | .prefix-b-suffix[class$="ctor-suffix"] {
11 | }
12 |
--------------------------------------------------------------------------------
/__tests__/files/results/css/css-attributes.css:
--------------------------------------------------------------------------------
1 | .tctor[class*="block"] {
2 | }
3 |
4 | .tblockn[class*="block"] {
5 | }
6 |
7 | .a[id^="pre-"] {
8 | }
9 |
10 | .b[class$="ctor"] {
11 | }
12 |
--------------------------------------------------------------------------------
/__tests__/files/results/css/css-variables-ignore.css:
--------------------------------------------------------------------------------
1 | .a {
2 | --theme-primary: #111;
3 | --theme-secondary: #f0f0f0;
4 | --theme-tertiary: #999;
5 | }
6 |
7 | .b {
8 | --theme-primary: red;
9 | --theme-secondary: white;
10 | --theme-tertiary: black;
11 | }
12 |
13 | .c {
14 | color: var(--theme-primary);
15 | background-color: var(--theme-secondary);
16 | font-size: 1.2em;
17 | line-height: 1.4;
18 | width: 100%;
19 | max-width: 400px;
20 | padding: 5px;
21 | border: 1px solid var(--theme-tertiary);
22 | margin: 0 0 20px;
23 | }
24 |
25 | .d {
26 | content: 'block';
27 | }
28 |
29 | .e {
30 | content: 'block__element';
31 | }
32 |
33 | .f {
34 | content: 'block__element--modifier';
35 | }
36 |
37 | .g{
38 | content: 'block--modifier';
39 | }
40 |
41 | .h:before {
42 | content: 'before';
43 | }
44 |
45 | .f {
46 | content: 'block__element--modifier';
47 | }
48 |
49 | #a {
50 | content: 'id';
51 | }
52 |
53 | .i[src] {
54 | content: 'attribute';
55 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
56 | }
57 |
58 | @media screen and (min-width: .40em) {
59 | #a {
60 | height: .20px;
61 | width: .20em;
62 | }
63 | }
64 |
65 | /**
66 | * a description
67 | */
68 | @media screen and (min-width: 40em)
69 |
70 | {
71 | #a
72 | {
73 | height: .20px;
74 | width: .20em;
75 | }
76 | }
77 |
78 | h1 {
79 | color: red;
80 | }
81 |
82 | .j {
83 | content: 'reveal';
84 | color: #eee;
85 | font-size: .5rem;
86 | }
87 |
88 | .k.j {
89 | content: 'js reveal';
90 | margin-right: calc(var(--theme-primary, var(--0px)) - var(--theme-secondary, var(--0px)));
91 | margin-bottom: calc(var(--theme-tertiary, var(--0px)) - var(--theme-primary, var(--0px)));
92 | }
93 |
94 | .l.j {
95 | content: 'js reveal';
96 | }
97 |
98 | .m {
99 | content: 'js-reveal';
100 | }
101 |
--------------------------------------------------------------------------------
/__tests__/files/results/css/css-variables.css:
--------------------------------------------------------------------------------
1 | .a {
2 | --a: #111;
3 | --b: #f0f0f0;
4 | --c: #999;
5 | }
6 |
7 | .b {
8 | --a: red;
9 | --b: white;
10 | --c: black;
11 | }
12 |
13 | .c {
14 | color: var(--a);
15 | background-color: var(--b);
16 | font-size: 1.2em;
17 | line-height: 1.4;
18 | width: 100%;
19 | max-width: 400px;
20 | padding: 5px;
21 | border: 1px solid var(--c);
22 | margin: 0 0 20px;
23 | }
24 |
25 | .d {
26 | content: 'block';
27 | }
28 |
29 | .e {
30 | content: 'block__element';
31 | }
32 |
33 | .f {
34 | content: 'block__element--modifier';
35 | }
36 |
37 | .g{
38 | content: 'block--modifier';
39 | }
40 |
41 | .h:before {
42 | content: 'before';
43 | }
44 |
45 | .f {
46 | content: 'block__element--modifier';
47 | }
48 |
49 | #a {
50 | content: 'id';
51 | }
52 |
53 | .i[src] {
54 | content: 'attribute';
55 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
56 | }
57 |
58 | @media screen and (min-width: .40em) {
59 | #a {
60 | height: .20px;
61 | width: .20em;
62 | }
63 | }
64 |
65 | /**
66 | * a description
67 | */
68 | @media screen and (min-width: 40em)
69 |
70 | {
71 | #a
72 | {
73 | height: .20px;
74 | width: .20em;
75 | }
76 | }
77 |
78 | h1 {
79 | color: red;
80 | }
81 |
82 | .j {
83 | content: 'reveal';
84 | color: #eee;
85 | font-size: .5rem;
86 | }
87 |
88 | .k.j {
89 | content: 'js reveal';
90 | margin-right: calc(var(--a, var(--0px)) - var(--b, var(--0px)));
91 | margin-bottom: calc(var(--c, var(--0px)) - var(--a, var(--0px)));
92 | }
93 |
94 | .l.j {
95 | content: 'js reveal';
96 | }
97 |
98 | .m {
99 | content: 'js-reveal';
100 | }
101 |
--------------------------------------------------------------------------------
/__tests__/files/results/css/style-prefix.css:
--------------------------------------------------------------------------------
1 | .prefixed-a {
2 | content: 'block';
3 | }
4 |
5 | .prefixed-b {
6 | content: 'block__element';
7 | }
8 |
9 | .prefixed-c {
10 | content: 'block__element--modifier';
11 | }
12 |
13 | .prefixed-d{
14 | content: 'block--modifier';
15 | }
16 |
17 | .prefixed-e:before {
18 | content: 'before';
19 | }
20 |
21 | .prefixed-c {
22 | content: 'block__element--modifier';
23 | }
24 |
25 | #prefixed-a {
26 | content: 'id';
27 | }
28 |
29 | .prefixed-f[src] {
30 | content: 'attribute';
31 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
32 | }
33 |
34 | @media screen and (min-width: .40em) {
35 | #prefixed-a {
36 | height: .20px;
37 | width: .20em;
38 | }
39 | }
40 |
41 | /**
42 | * a description
43 | */
44 | @media screen and (min-width: 40em)
45 |
46 | {
47 | #prefixed-a
48 | {
49 | height: .20px;
50 | width: .20em;
51 | }
52 | }
53 |
54 | h1 {
55 | color: red;
56 | }
57 |
58 | .prefixed-g {
59 | content: 'reveal';
60 | color: #eee;
61 | font-size: .5rem;
62 | }
63 |
64 | .prefixed-h.prefixed-g {
65 | content: 'js reveal';
66 | }
67 |
68 | .prefixed-i.prefixed-g {
69 | content: 'js reveal';
70 | }
71 |
72 | .prefixed-j {
73 | content: 'js-reveal';
74 | }
75 |
--------------------------------------------------------------------------------
/__tests__/files/results/css/style-with-config.css:
--------------------------------------------------------------------------------
1 | .a {
2 | content: 'block';
3 | }
4 |
5 | .b {
6 | content: 'block__element';
7 | }
8 |
9 | .c {
10 | content: 'block__element--modifier';
11 | }
12 |
13 | .d{
14 | content: 'block--modifier';
15 | }
16 |
17 | .e:before {
18 | content: 'before';
19 | }
20 |
21 | .c {
22 | content: 'block__element--modifier';
23 | }
24 |
25 | #a {
26 | content: 'id';
27 | }
28 |
29 | .f[src] {
30 | content: 'attribute';
31 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
32 | }
33 |
34 | @media screen and (min-width: .40em) {
35 | #a {
36 | height: .20px;
37 | width: .20em;
38 | }
39 | }
40 |
41 | /**
42 | * a description
43 | */
44 | @media screen and (min-width: 40em)
45 |
46 | {
47 | #a
48 | {
49 | height: .20px;
50 | width: .20em;
51 | }
52 | }
53 |
54 | h1 {
55 | color: red;
56 | }
57 |
58 | .g {
59 | content: 'reveal';
60 | color: #eee;
61 | font-size: .5rem;
62 | }
63 |
64 | .js.g {
65 | content: 'js.reveal';
66 | }
67 |
68 | .no-js.g {
69 | content: 'js.reveal';
70 | }
71 |
72 | .h {
73 | content: 'js-reveal';
74 | }
75 |
--------------------------------------------------------------------------------
/__tests__/files/results/css/style.css:
--------------------------------------------------------------------------------
1 | .a {
2 | content: 'block';
3 | }
4 |
5 | .b {
6 | content: 'block__element';
7 | }
8 |
9 | .c {
10 | content: 'block__element--modifier';
11 | }
12 |
13 | .d{
14 | content: 'block--modifier';
15 | }
16 |
17 | .e:before {
18 | content: 'before';
19 | }
20 |
21 | .c {
22 | content: 'block__element--modifier';
23 | }
24 |
25 | #a {
26 | content: 'id';
27 | }
28 |
29 | .f[src] {
30 | content: 'attribute';
31 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
32 | }
33 |
34 | @media screen and (min-width: .40em) {
35 | #a {
36 | height: .20px;
37 | width: .20em;
38 | }
39 | }
40 |
41 | /**
42 | * a description
43 | */
44 | @media screen and (min-width: 40em)
45 |
46 | {
47 | #a
48 | {
49 | height: .20px;
50 | width: .20em;
51 | }
52 | }
53 |
54 | h1 {
55 | color: red;
56 | }
57 |
58 | .g {
59 | content: 'reveal';
60 | color: #eee;
61 | font-size: .5rem;
62 | }
63 |
64 | .h.g {
65 | content: 'js reveal';
66 | }
67 |
68 | .i.g {
69 | content: 'js reveal';
70 | }
71 |
72 | .j {
73 | content: 'js-reveal';
74 | }
75 |
--------------------------------------------------------------------------------
/__tests__/files/results/css/style2.css:
--------------------------------------------------------------------------------
1 | #a {
2 | content: 'id';
3 | }
4 |
5 | .b {
6 | content: 'block__element';
7 | }
8 |
9 | .c {
10 | content: 'block__element--modifier';
11 | }
12 |
13 | .c {
14 | content: 'block__element--modifier';
15 | }
16 |
17 | .d{
18 | content: 'block--modifier';
19 | }
20 |
21 | .a {
22 | content: 'block';
23 | }
24 |
25 | .e:before {
26 | content: 'before';
27 | }
28 |
--------------------------------------------------------------------------------
/__tests__/files/results/css/subdirectory/style.css:
--------------------------------------------------------------------------------
1 | .a {
2 | content: 'block';
3 | }
4 |
5 | .c {
6 | content: 'block__element--modifier';
7 | }
8 |
9 | .b {
10 | content: 'block__element';
11 | }
12 |
13 | .d{
14 | content: 'block--modifier';
15 | }
16 |
17 | .c {
18 | content: 'block__element--modifier';
19 | }
20 |
21 | .e:before {
22 | content: 'before';
23 | }
24 |
25 | #a {
26 | content: 'id';
27 | }
28 |
--------------------------------------------------------------------------------
/__tests__/files/results/html/index-with-style.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Test Document
6 |
7 |
8 |
9 |
10 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/__tests__/files/results/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Test Document
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/__tests__/files/results/js/complex.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | /**
3 | * Finds the index of the first character
4 | * that's not common between the two given strings.
5 | *
6 | * @return {number} the index of the character where the strings diverge
7 | */
8 | function firstDifferenceIndex(string1, string2) {
9 | var minLen = Math.min(string1.length, string2.length);
10 | for (var i = 0; i < minLen; i++) {
11 | if (string1.charAt(i) !== string2.charAt(i)) {
12 | return i;
13 | }
14 | }
15 | return string1.length === string2.length ? -1 : minLen;
16 | }
17 |
18 | /***/ (function(module, exports) {
19 |
20 | // removed by extract-text-webpack-plugin
21 | module.exports = {"table":"a","key":"e"};
22 |
23 | /***/ }),
24 | /* 523 */
25 | /***/ (function(module, exports, __webpack_require__) {
26 |
27 | var defineProperty = __webpack_require__(531);
28 |
29 | /**
30 | * The base implementation of `assignValue` and `assignMergeValue` without
31 | * value checks.
32 | *
33 | * @private
34 | * @param {Object} object The object to modify.
35 | * @param {string} key The key of the property to assign.
36 | * @param {*} value The value to assign.
37 | */
38 | function baseAssignValue(object, key, value) {
39 | if (key == '__proto__' && defineProperty) {
40 | defineProperty(object, key, {
41 | 'configurable': true,
42 | 'enumerable': true,
43 | 'value': value,
44 | 'writable': true
45 | });
46 | } else {
47 | object[key] = value;
48 | }
49 | }
50 |
51 | module.exports = baseAssignValue;
52 |
53 |
54 | /***/ })
55 |
--------------------------------------------------------------------------------
/__tests__/files/results/js/main.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | // jQuery example
3 | $(".a");
4 |
5 | // vanillaJS example
6 | document.getElementsByClassName("b");
7 | document.getElementById("c");
8 |
9 | const restSpread = {
10 | weirdFormatting: true,
11 | shouldRest: true,
12 | };
13 |
14 | const extended = { ...restSpread };
15 | const { ...options } = extended;
16 |
--------------------------------------------------------------------------------
/__tests__/files/results/js/react.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import PropTypes from 'prop-types';
3 | import React, { Component } from 'react';
4 | import { bindActionCreators } from 'redux';
5 | import { connect } from 'react-redux';
6 |
7 | import ListView from '../components/ListView';
8 | import eventActions from '../redux/eventsRedux';
9 | import { getAllEvents } from '../selectors';
10 |
11 | class Events extends Component {
12 | componentWillMount() {
13 | this.props.startup();
14 | }
15 |
16 | componentWillReceiveProps(nextProps) {
17 | this.props.events = nextProps.events;
18 | }
19 |
20 | renderEvent() {
21 | if (this.props.events.length === 0) {
22 | return is
;
23 | }
24 |
25 | return ;
26 | }
27 |
28 | render() {
29 | return (
30 |
31 | { this.renderEvent() }
32 |
33 | );
34 | }
35 | }
36 |
37 | Events.propTypes = {
38 | events: PropTypes.arrayOf(PropTypes.shape({
39 | name: PropTypes.string.isRequired,
40 | })),
41 | startup: PropTypes.func.isRequired,
42 | };
43 |
44 | Events.defaultProps = {
45 | events: [
46 | {
47 | name: 'No Event',
48 | },
49 | ],
50 | };
51 |
52 | const mapStateToProps = state => ({
53 | events: getAllEvents(state),
54 | });
55 |
56 | const mapDispatchToProps = dispatch => bindActionCreators({
57 | startup: eventActions.eventsRequest,
58 | }, dispatch);
59 |
60 | export default connect(mapStateToProps, mapDispatchToProps)(Events);
61 |
--------------------------------------------------------------------------------
/__tests__/files/results/pug/index.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | head
3 | meta(charset!='UTF-8')
4 | title Test Document
5 | .a
6 | .b
7 |
--------------------------------------------------------------------------------
/__tests__/generateMapping.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import path from 'path';
3 | import fs from 'fs-extra';
4 | import json from 'json-extra';
5 |
6 | import reset from './helpers/reset';
7 | import rcs from '../lib';
8 |
9 | let testCwd;
10 | const fixturesCwd = path.join(process.cwd(), '/__tests__/files/fixtures');
11 |
12 | beforeEach(async () => {
13 | testCwd = tmp.dirSync();
14 |
15 | reset();
16 |
17 | await rcs.process.css('**/style*.css', {
18 | newPath: testCwd.name,
19 | cwd: fixturesCwd,
20 | });
21 | });
22 |
23 | afterEach(() => {
24 | testCwd.removeCallback();
25 | });
26 |
27 | test('should create the normal mapping file', (done) => {
28 | rcs.mapping.generate(testCwd.name, (err) => {
29 | const cssMapping = json.readToObjSync(path.join(testCwd.name, '/renaming_map.json'), 'utf8');
30 |
31 | expect(err).toBeFalsy();
32 | expect(cssMapping.selectors['.jp-block']).toBe('a');
33 | expect(cssMapping.selectors['.jp-block__element']).toBe('b');
34 |
35 | done();
36 | });
37 | });
38 |
39 | test('should create the minified mapping file', (done) => {
40 | rcs.mapping.generate(testCwd.name, {
41 | origValues: false,
42 | }, (err) => {
43 | const cssMappingMin = json.readToObjSync(path.join(testCwd.name, '/renaming_map_min.json'), 'utf8');
44 |
45 | expect(err).toBeFalsy();
46 | expect(cssMappingMin.selectors['.a']).toBe('jp-block');
47 | expect(cssMappingMin.selectors['.b']).toBe('jp-block__element');
48 |
49 | done();
50 | });
51 | });
52 |
53 | test('should create the minified mapping file with a custom name', (done) => {
54 | rcs.mapping.generate(testCwd.name, {
55 | origValues: false,
56 | fileName: 'custom-name',
57 | }, (err) => {
58 | const cssMappingMin = json.readToObjSync(path.join(testCwd.name, '/custom-name.json'), 'utf8');
59 |
60 | expect(err).toBeFalsy();
61 | expect(cssMappingMin.selectors['.a']).toBe('jp-block');
62 | expect(cssMappingMin.selectors['.b']).toBe('jp-block__element');
63 |
64 | done();
65 | });
66 | });
67 |
68 | test('should create the minified mapping js file', (done) => {
69 | rcs.mapping.generate(testCwd.name, {
70 | json: false,
71 | }, (err) => {
72 | const cssMapping = fs.readFileSync(path.join(testCwd.name, '/renaming_map.js'), 'utf8');
73 |
74 | expect(err).toBeFalsy();
75 | expect(cssMapping).toMatch(new RegExp(/var CSS_NAME_MAPPING = {/));
76 |
77 | done();
78 | });
79 | });
80 |
81 | test('should overwrite mapping files', (done) => {
82 | rcs.mapping.generate(testCwd.name, (err) => {
83 | rcs.mapping.generate(testCwd.name, { overwrite: true }, (err2) => {
84 | expect(err).toBeFalsy();
85 | expect(err2).toBeFalsy();
86 |
87 | done();
88 | });
89 | });
90 | });
91 |
92 | test('should not overwrite mapping files', async () => {
93 | await expect(rcs.mapping.generate(testCwd.name)).resolves.toBe(undefined);
94 | await expect(rcs.mapping.generate(testCwd.name)).rejects.toBeTruthy();
95 | });
96 |
97 | test('should create the custom names minified mapping file', (done) => {
98 | rcs.mapping.generate(testCwd.name, {
99 | fileName: 'custom-name',
100 | }, (err) => {
101 | const cssMapping = json.readToObjSync(path.join(testCwd.name, '/custom-name.json'), 'utf8');
102 |
103 | expect(err).toBeFalsy();
104 | expect(cssMapping.selectors['.jp-block']).toBe('a');
105 | expect(cssMapping.selectors['.jp-block__element']).toBe('b');
106 |
107 | done();
108 | });
109 | });
110 |
--------------------------------------------------------------------------------
/__tests__/helpers/reset.ts:
--------------------------------------------------------------------------------
1 | import rcsCore from 'rcs-core';
2 |
3 | const reset = (): void => {
4 | rcsCore.keyframesLibrary.setAlphabet('#abcdefghijklmnopqrstuvwxyz');
5 | rcsCore.cssVariablesLibrary.setAlphabet('#abcdefghijklmnopqrstuvwxyz');
6 | rcsCore.selectorsLibrary.setAlphabet('#abcdefghijklmnopqrstuvwxyz');
7 | rcsCore.selectorsLibrary.selectors[0].nameGenerator.reset();
8 | rcsCore.selectorsLibrary.selectors[1].nameGenerator.reset();
9 | rcsCore.keyframesLibrary.nameGenerator.reset();
10 | rcsCore.cssVariablesLibrary.nameGenerator.reset();
11 | rcsCore.selectorsLibrary.reset();
12 | rcsCore.keyframesLibrary.reset();
13 | rcsCore.cssVariablesLibrary.reset();
14 | };
15 |
16 | export default reset;
17 |
--------------------------------------------------------------------------------
/__tests__/integration.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import path from 'path';
3 | import fs from 'fs-extra';
4 | import { minify } from 'html-minifier';
5 |
6 | import rcs from '../lib';
7 | import reset from './helpers/reset';
8 |
9 | let testCwd;
10 | const testFiles = '__tests__/files';
11 | const fixturesCwd = path.join(testFiles, 'fixtures');
12 |
13 | beforeEach(() => {
14 | testCwd = tmp.dirSync();
15 |
16 | reset();
17 | });
18 |
19 | afterEach(() => {
20 | testCwd.removeCallback();
21 | });
22 |
23 | test('issue #19 | detect one file as array', async () => {
24 | await rcs.process.css('**/style.css', {
25 | newPath: testCwd.name,
26 | cwd: fixturesCwd,
27 | });
28 |
29 | await rcs.process.html(['html/index.html'], {
30 | newPath: testCwd.name,
31 | cwd: fixturesCwd,
32 | });
33 |
34 | expect(fs.existsSync(path.join(testCwd.name, '/html/index.html'))).toBe(true);
35 | expect(fs.existsSync(path.join(testCwd.name, '/css/style.css'))).toBe(true);
36 | expect(fs.existsSync(path.join(testCwd.name, '/css/subdirectory/style.css'))).toBe(true);
37 | });
38 |
39 | test('issue #19 | detect one file', async () => {
40 | await rcs.process.css('**/style.css', {
41 | newPath: testCwd.name,
42 | cwd: fixturesCwd,
43 | });
44 |
45 | await rcs.process.html('html/index.html', {
46 | newPath: testCwd.name,
47 | cwd: fixturesCwd,
48 | });
49 |
50 | expect(fs.existsSync(path.join(testCwd.name, '/html/index.html'))).toBe(true);
51 | expect(fs.existsSync(path.join(testCwd.name, '/css/style.css'))).toBe(true);
52 | expect(fs.existsSync(path.join(testCwd.name, '/css/subdirectory/style.css'))).toBe(true);
53 | });
54 |
55 | test('issue #21 | with auto', async () => {
56 | const issueFixture = path.join(testFiles, 'issue21/fixtures');
57 | const issueResults = path.join(testFiles, 'issue21/results');
58 |
59 | await rcs.process.auto(['style.css', 'index.html'], {
60 | newPath: testCwd.name,
61 | cwd: issueFixture,
62 | });
63 |
64 | const newCss = fs.readFileSync(path.join(testCwd.name, '/style.css'), 'utf8');
65 | const newHtml = fs.readFileSync(path.join(testCwd.name, '/index.html'), 'utf8');
66 | const expectedCss = fs.readFileSync(path.join(issueResults, '/style.css'), 'utf8');
67 | const expectedHtml = fs.readFileSync(path.join(issueResults, '/index.html'), 'utf8');
68 |
69 | expect(newCss).toBe(expectedCss);
70 | expect(minify(newHtml, { collapseWhitespace: true }))
71 | .toBe(minify(expectedHtml, { collapseWhitespace: true }));
72 | });
73 |
74 | test('issue #21 | with seperated process functions', async () => {
75 | const issueFixture = path.join(testFiles, 'issue21/fixtures');
76 | const issueResults = path.join(testFiles, 'issue21/results');
77 |
78 | await rcs.process.css('style.css', {
79 | newPath: testCwd.name,
80 | cwd: issueFixture,
81 | });
82 |
83 | await rcs.process.html('index.html', {
84 | newPath: testCwd.name,
85 | cwd: issueFixture,
86 | });
87 |
88 | const newCss = fs.readFileSync(path.join(testCwd.name, '/style.css'), 'utf8');
89 | const newHtml = fs.readFileSync(path.join(testCwd.name, '/index.html'), 'utf8');
90 | const expectedCss = fs.readFileSync(path.join(issueResults, '/style.css'), 'utf8');
91 | const expectedHtml = fs.readFileSync(path.join(issueResults, '/index.html'), 'utf8');
92 |
93 | expect(newCss).toBe(expectedCss);
94 | expect(minify(newHtml, { collapseWhitespace: true }))
95 | .toBe(minify(expectedHtml, { collapseWhitespace: true }));
96 | });
97 |
98 | test('issue #70 | line breaks', async () => {
99 | const issueFixture = path.join(testFiles, 'issue70/fixtures');
100 | const issueResults = path.join(testFiles, 'issue70/results');
101 |
102 | await rcs.process.css('style.css', {
103 | newPath: testCwd.name,
104 | cwd: issueFixture,
105 | });
106 |
107 | await rcs.process.html('index.html', {
108 | newPath: testCwd.name,
109 | cwd: issueFixture,
110 | });
111 |
112 | const newCss = fs.readFileSync(path.join(testCwd.name, '/style.css'), 'utf8');
113 | const newHtml = fs.readFileSync(path.join(testCwd.name, '/index.html'), 'utf8');
114 | const expectedCss = fs.readFileSync(path.join(issueResults, '/style.css'), 'utf8');
115 | const expectedHtml = fs.readFileSync(path.join(issueResults, '/index.html'), 'utf8');
116 |
117 | expect(newCss).toBe(expectedCss);
118 | expect(minify(newHtml, { collapseWhitespace: true }))
119 | .toBe(minify(expectedHtml, { collapseWhitespace: true }));
120 | });
121 |
--------------------------------------------------------------------------------
/__tests__/integration_mapping.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import fs from 'fs-extra';
3 | import path from 'path';
4 | import json from 'json-extra';
5 | import { minify } from 'html-minifier';
6 |
7 | import rcs from '../lib';
8 | import reset from './helpers/reset';
9 |
10 | let testCwd;
11 | const fixturesCwd = './__tests__/files/fixtures';
12 | const resultsCwd = './__tests__/files/results';
13 |
14 | beforeEach(async () => {
15 | testCwd = tmp.dirSync();
16 |
17 | reset();
18 |
19 | await rcs.process.css('**/style*.css', {
20 | newPath: testCwd.name,
21 | cwd: fixturesCwd,
22 | });
23 | await rcs.mapping.generate(testCwd.name);
24 |
25 | reset();
26 | });
27 |
28 | afterEach(() => {
29 | testCwd.removeCallback();
30 | });
31 |
32 | test('should load from an object', async () => {
33 | const cssMapping = json.readToObjSync(path.join(testCwd.name, '/renaming_map.json'), 'utf8');
34 |
35 | rcs.mapping.load(cssMapping);
36 |
37 | await rcs.process.html('**/*.html', {
38 | newPath: testCwd.name,
39 | cwd: fixturesCwd,
40 | });
41 |
42 | const newFile = fs.readFileSync(path.join(testCwd.name, '/html/index.html'), 'utf8');
43 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/html/index.html'), 'utf8');
44 |
45 | expect(minify(newFile, { collapseWhitespace: true }))
46 | .toBe(minify(expectedFile, { collapseWhitespace: true }));
47 | });
48 |
49 | test('should load from a filestring', async () => {
50 | await rcs.mapping.load(path.join(testCwd.name, '/renaming_map.json'));
51 |
52 | await rcs.process.html('**/*.html', {
53 | newPath: testCwd.name,
54 | cwd: fixturesCwd,
55 | });
56 |
57 | const newFile = fs.readFileSync(path.join(testCwd.name, '/html/index.html'), 'utf8');
58 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/html/index.html'), 'utf8');
59 |
60 | expect(minify(newFile, { collapseWhitespace: true }))
61 | .toBe(minify(expectedFile, { collapseWhitespace: true }));
62 | });
63 |
64 | test('should load nothing as it does not exist', async () => {
65 | await rcs.mapping.load(path.join(testCwd.name, '/doesnotexist.json'));
66 |
67 | await rcs.process.html('**/*.html', {
68 | newPath: testCwd.name,
69 | cwd: fixturesCwd,
70 | });
71 |
72 | const newFile = fs.readFileSync(path.join(testCwd.name, '/html/index.html'), 'utf8');
73 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/html/index.html'), 'utf8');
74 |
75 | expect(minify(newFile, { collapseWhitespace: true }))
76 | .not.toBe(minify(expectedFile, { collapseWhitespace: true }));
77 | });
78 |
79 | test('should load from a filestring', async () => {
80 | await rcs.process.css('**/style*.css', {
81 | newPath: testCwd.name,
82 | cwd: fixturesCwd,
83 | });
84 |
85 | await rcs.mapping.generate(testCwd.name, { origValues: false });
86 |
87 | reset();
88 |
89 | await rcs.mapping.load(path.join(testCwd.name, '/renaming_map_min.json'), { origValues: false });
90 |
91 | await rcs.process.html('**/*.html', {
92 | newPath: testCwd.name,
93 | cwd: fixturesCwd,
94 | });
95 |
96 | const newFile = fs.readFileSync(path.join(testCwd.name, '/html/index.html'), 'utf8');
97 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/html/index.html'), 'utf8');
98 |
99 | expect(minify(newFile, { collapseWhitespace: true }))
100 | .toBe(minify(expectedFile, { collapseWhitespace: true }));
101 | });
102 |
--------------------------------------------------------------------------------
/__tests__/loadMapping.ts:
--------------------------------------------------------------------------------
1 | import rcsCore from 'rcs-core';
2 |
3 | import rcs from '../lib';
4 | import reset from './helpers/reset';
5 |
6 | beforeEach(() => {
7 | reset();
8 | });
9 |
10 | test('should load from an object', () => {
11 | rcs.mapping.load({
12 | selectors: {
13 | '.jp-block': 'a-class',
14 | '#compressed': 'b',
15 | },
16 | });
17 |
18 | expect(rcsCore.selectorsLibrary.get('jp-block')).toBe('a-class');
19 | expect(rcsCore.selectorsLibrary.get('#compressed')).toBe('b');
20 | });
21 |
--------------------------------------------------------------------------------
/__tests__/processAuto.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import path from 'path';
3 | import fs from 'fs-extra';
4 | import rcsCore from 'rcs-core';
5 | import { minify } from 'html-minifier';
6 |
7 | import rcs from '../lib';
8 | import reset from './helpers/reset';
9 |
10 | const fixturesCwd = '__tests__/files/fixtures';
11 | const resultsCwd = '__tests__/files/results';
12 |
13 | let testCwd;
14 |
15 | beforeEach(() => {
16 | testCwd = tmp.dirSync();
17 |
18 | reset();
19 | });
20 |
21 | afterEach(() => {
22 | testCwd.removeCallback();
23 | });
24 |
25 | test('should process css files', async () => {
26 | await rcs.process.auto('**/style*.css', {
27 | newPath: testCwd.name,
28 | cwd: fixturesCwd,
29 | });
30 |
31 | const newFile = fs.readFileSync(path.join(testCwd.name, '/css/style.css'), 'utf8');
32 | const newFile2 = fs.readFileSync(path.join(testCwd.name, '/css/style2.css'), 'utf8');
33 | const newFile3 = fs.readFileSync(path.join(testCwd.name, '/css/subdirectory/style.css'), 'utf8');
34 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/css/style.css'), 'utf8');
35 | const expectedFile2 = fs.readFileSync(path.join(resultsCwd, '/css/style2.css'), 'utf8');
36 | const expectedFile3 = fs.readFileSync(path.join(resultsCwd, '/css/subdirectory/style.css'), 'utf8');
37 |
38 | expect(newFile).toBe(expectedFile);
39 | expect(newFile2).toBe(expectedFile2);
40 | expect(newFile3).toBe(expectedFile3);
41 | });
42 |
43 | test('processing | should process all files automatically', async () => {
44 | await rcs.process.auto(['**/*.{js,html}', 'css/style.css'], {
45 | newPath: testCwd.name,
46 | cwd: fixturesCwd,
47 | });
48 |
49 | const newFile = fs.readFileSync(path.join(testCwd.name, '/js/main.js'), 'utf8');
50 | const newFile2 = fs.readFileSync(path.join(testCwd.name, '/css/style.css'), 'utf8');
51 | const newFile3 = fs.readFileSync(path.join(testCwd.name, '/html/index.html'), 'utf8');
52 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/js/main.js'), 'utf8');
53 | const expectedFile2 = fs.readFileSync(path.join(resultsCwd, '/css/style.css'), 'utf8');
54 | const expectedFile3 = fs.readFileSync(path.join(resultsCwd, '/html/index.html'), 'utf8');
55 |
56 | expect(newFile).toBe(expectedFile);
57 | expect(newFile2).toBe(expectedFile2);
58 | expect(minify(newFile3, { collapseWhitespace: true }))
59 | .toBe(minify(expectedFile3, { collapseWhitespace: true }));
60 | });
61 |
62 | test('should process css files as arrays', async () => {
63 | await rcs.process.auto(['**/style.css', '**/style2.css'], {
64 | newPath: testCwd.name,
65 | cwd: fixturesCwd,
66 | });
67 |
68 | const newFile = fs.readFileSync(path.join(testCwd.name, '/css/style.css'), 'utf8');
69 | const newFile2 = fs.readFileSync(path.join(testCwd.name, '/css/style2.css'), 'utf8');
70 | const newFile3 = fs.readFileSync(path.join(testCwd.name, '/css/subdirectory/style.css'), 'utf8');
71 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/css/style.css'), 'utf8');
72 | const expectedFile2 = fs.readFileSync(path.join(resultsCwd, '/css/style2.css'), 'utf8');
73 | const expectedFile3 = fs.readFileSync(path.join(resultsCwd, '/css/subdirectory/style.css'), 'utf8');
74 |
75 | expect(newFile).toBe(expectedFile);
76 | expect(newFile2).toBe(expectedFile2);
77 | expect(newFile3).toBe(expectedFile3);
78 | });
79 |
80 | test('should not overwrite original files', async () => {
81 | await expect((
82 | rcs.process.auto(['**/style.css', '**/style2.css'], {
83 | newPath: fixturesCwd,
84 | cwd: fixturesCwd,
85 | })
86 | )).rejects.toEqual(new Error('File exist and cannot be overwritten. Set the option overwrite to true to overwrite files.'));
87 | });
88 |
89 | test('should fail', async () => {
90 | await expect(rcs.process.auto('path/**/with/nothing/in/it'))
91 | .rejects.toEqual(new Error('No files found'));
92 | });
93 |
94 | test('should process auto file with css variables', async () => {
95 | await rcs.process.auto('css/css-variables.css', {
96 | newPath: testCwd.name,
97 | cwd: fixturesCwd,
98 | });
99 |
100 | const newFile = fs.readFileSync(path.join(testCwd.name, '/css/css-variables.css'), 'utf8');
101 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/css/css-variables.css'), 'utf8');
102 |
103 | expect(newFile).toBe(expectedFile);
104 | });
105 |
106 | test('should not process auto file with css variables', async () => {
107 | await rcs.process.auto('css/css-variables.css', {
108 | newPath: testCwd.name,
109 | cwd: fixturesCwd,
110 | ignoreCssVariables: true,
111 | });
112 |
113 | const newFile = fs.readFileSync(path.join(testCwd.name, '/css/css-variables.css'), 'utf8');
114 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/css/css-variables-ignore.css'), 'utf8');
115 |
116 | expect(newFile).toBe(expectedFile);
117 | });
118 |
119 | test('should fillLibraries from html and css | issue #38', async () => {
120 | await rcs.process.auto(['**/*.{js,html}', 'css/style.css'], {
121 | newPath: testCwd.name,
122 | cwd: fixturesCwd,
123 | });
124 |
125 | const newFile = fs.readFileSync(path.join(testCwd.name, '/html/index-with-style.html'), 'utf8');
126 | const newFile2 = fs.readFileSync(path.join(testCwd.name, '/css/style.css'), 'utf8');
127 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/html/index-with-style.html'), 'utf8');
128 | const expectedFile2 = fs.readFileSync(path.join(resultsCwd, '/css/style.css'), 'utf8');
129 |
130 | expect(minify(newFile, { collapseWhitespace: true }))
131 | .toBe(minify(expectedFile, { collapseWhitespace: true }));
132 | expect(minify(newFile2, { collapseWhitespace: true }))
133 | .toBe(minify(expectedFile2, { collapseWhitespace: true }));
134 | });
135 |
136 | test('should check if optimize has been called', async () => {
137 | const optimizeSpy = jest.spyOn(rcsCore, 'optimize');
138 |
139 | await rcs.process.auto(['**/*.{js,html}', 'css/style.css'], {
140 | newPath: testCwd.name,
141 | cwd: fixturesCwd,
142 | });
143 |
144 | expect(optimizeSpy).toHaveBeenCalledTimes(1);
145 |
146 | optimizeSpy.mockRestore();
147 | });
148 |
149 | test('should check if optimize has been called test', async () => {
150 | const optimizeSpy = jest.spyOn(rcsCore, 'optimize');
151 |
152 | await rcs.process.auto(['**/*.{js,html}', 'css/style.css'], {
153 | newPath: testCwd.name,
154 | cwd: fixturesCwd,
155 | optimize: false,
156 | });
157 |
158 | expect(optimizeSpy).not.toHaveBeenCalled();
159 |
160 | optimizeSpy.mockRestore();
161 | });
162 |
--------------------------------------------------------------------------------
/__tests__/processAutoSync.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import path from 'path';
3 | import fs from 'fs-extra';
4 | import { minify } from 'html-minifier';
5 |
6 | import rcs from '../lib';
7 | import reset from './helpers/reset';
8 |
9 | let testCwd;
10 | const fixturesCwd = '__tests__/files/fixtures';
11 | const resultsCwd = '__tests__/files/results';
12 |
13 | beforeEach(() => {
14 | testCwd = tmp.dirSync();
15 |
16 | reset();
17 | });
18 |
19 | afterEach(() => {
20 | testCwd.removeCallback();
21 | });
22 |
23 | test('should process all files synchronously', () => {
24 | let newFile;
25 | let expectedFile;
26 |
27 | rcs.process.autoSync(['**/*.js', 'css/style.css'], {
28 | newPath: testCwd.name,
29 | cwd: fixturesCwd,
30 | });
31 |
32 | newFile = fs.readFileSync(path.join(testCwd.name, '/js/main.js'), 'utf8');
33 | expectedFile = fs.readFileSync(path.join(resultsCwd, '/js/main.js'), 'utf8');
34 |
35 | expect(newFile).toBe(expectedFile);
36 |
37 | newFile = fs.readFileSync(path.join(testCwd.name, '/css/style.css'), 'utf8');
38 | expectedFile = fs.readFileSync(path.join(resultsCwd, '/css/style.css'), 'utf8');
39 |
40 | expect(newFile).toBe(expectedFile);
41 | });
42 |
43 | test('should fillLibraries from html and css | issue #38', () => {
44 | rcs.process.autoSync(['**/*.{js,html}', 'css/style.css'], {
45 | newPath: testCwd.name,
46 | cwd: fixturesCwd,
47 | });
48 |
49 | const newFile = fs.readFileSync(path.join(testCwd.name, '/html/index-with-style.html'), 'utf8');
50 | const newFile2 = fs.readFileSync(path.join(testCwd.name, '/css/style.css'), 'utf8');
51 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/html/index-with-style.html'), 'utf8');
52 | const expectedFile2 = fs.readFileSync(path.join(resultsCwd, '/css/style.css'), 'utf8');
53 |
54 | expect(minify(newFile, { collapseWhitespace: true }))
55 | .toBe(minify(expectedFile, { collapseWhitespace: true }));
56 | expect(minify(newFile2, { collapseWhitespace: true }))
57 | .toBe(minify(expectedFile2, { collapseWhitespace: true }));
58 | });
59 |
--------------------------------------------------------------------------------
/__tests__/processCss.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import path from 'path';
3 | import fs from 'fs-extra';
4 |
5 | import rcs from '../lib';
6 | import reset from './helpers/reset';
7 |
8 | let testCwd;
9 | const fixturesCwd = '__tests__/files/fixtures';
10 | const resultsCwd = '__tests__/files/results';
11 |
12 | beforeEach(() => {
13 | testCwd = tmp.dirSync();
14 |
15 | reset();
16 | });
17 |
18 | afterEach(() => {
19 | testCwd.removeCallback();
20 | });
21 |
22 | test('should process css files and prefix them', async () => {
23 | await rcs.process.css('**/style*.css', {
24 | newPath: testCwd.name,
25 | cwd: fixturesCwd,
26 | prefix: 'prefixed-',
27 | });
28 |
29 | const newFile = fs.readFileSync(path.join(testCwd.name, '/css/style.css'), 'utf8');
30 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/css/style-prefix.css'), 'utf8');
31 |
32 | expect(newFile).toBe(expectedFile);
33 | });
34 |
35 | test('should process css files with rcs.process.css', async () => {
36 | await rcs.process.css('**/style*.css', {
37 | newPath: testCwd.name,
38 | cwd: fixturesCwd,
39 | });
40 |
41 | const newFile = fs.readFileSync(path.join(testCwd.name, '/css/style.css'), 'utf8');
42 | const newFile2 = fs.readFileSync(path.join(testCwd.name, '/css/style2.css'), 'utf8');
43 | const newFile3 = fs.readFileSync(path.join(testCwd.name, '/css/subdirectory/style.css'), 'utf8');
44 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/css/style.css'), 'utf8');
45 | const expectedFile2 = fs.readFileSync(path.join(resultsCwd, '/css/style2.css'), 'utf8');
46 | const expectedFile3 = fs.readFileSync(path.join(resultsCwd, '/css/subdirectory/style.css'), 'utf8');
47 |
48 | expect(newFile).toBe(expectedFile);
49 | expect(newFile2).toBe(expectedFile2);
50 | expect(newFile3).toBe(expectedFile3);
51 | });
52 |
53 | test('should process css files without options', async () => {
54 | await rcs.process.css(path.join(fixturesCwd, 'css/**/style*.css'));
55 |
56 | const newFile = fs.readFileSync(path.join(process.cwd(), 'rcs', fixturesCwd, '/css/style.css'), 'utf8');
57 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/css/style.css'), 'utf8');
58 |
59 | expect(newFile).toBe(expectedFile);
60 |
61 | fs.removeSync(path.join(process.cwd(), 'rcs'));
62 | });
63 |
64 | test('should replace the selector attributes correctly', async () => {
65 | await rcs.process.css('css/css-attributes.css', {
66 | newPath: testCwd.name,
67 | cwd: fixturesCwd,
68 | });
69 |
70 | expect(fs.readFileSync(path.join(testCwd.name, '/css/css-attributes.css'), 'utf8'))
71 | .toBe(fs.readFileSync(path.join(resultsCwd, '/css/css-attributes.css'), 'utf8'));
72 | });
73 |
74 | test('should replace the selector attributes with pre and suffixes correctly', async () => {
75 | await rcs.process.css('css/css-attributes.css', {
76 | prefix: 'prefix-',
77 | suffix: '-suffix',
78 | newPath: testCwd.name,
79 | cwd: fixturesCwd,
80 | });
81 |
82 | expect(fs.readFileSync(path.join(testCwd.name, '/css/css-attributes.css'), 'utf8'))
83 | .toBe(fs.readFileSync(path.join(resultsCwd, '/css/css-attributes-pre-suffix.css'), 'utf8'));
84 | });
85 |
86 | test('should replace the selector attributes without caring about attribute selectors', async () => {
87 | await rcs.process.css('css/css-attributes.css', {
88 | prefix: 'prefix-',
89 | suffix: '-suffix',
90 | ignoreAttributeSelectors: true,
91 | newPath: testCwd.name,
92 | cwd: fixturesCwd,
93 | });
94 |
95 | expect(fs.readFileSync(path.join(testCwd.name, '/css/css-attributes.css'), 'utf8'))
96 | .toBe(fs.readFileSync(path.join(resultsCwd, '/css/css-attributes-ignore.css'), 'utf8'));
97 | });
98 |
99 | test('should process css file with css variables', async () => {
100 | await rcs.process.css('css/css-variables.css', {
101 | newPath: testCwd.name,
102 | cwd: fixturesCwd,
103 | });
104 |
105 | const newFile = fs.readFileSync(path.join(testCwd.name, '/css/css-variables.css'), 'utf8');
106 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/css/css-variables.css'), 'utf8');
107 |
108 | expect(newFile).toBe(expectedFile);
109 | });
110 |
--------------------------------------------------------------------------------
/__tests__/processCssSync.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import path from 'path';
3 | import fs from 'fs-extra';
4 |
5 | import rcs from '../lib';
6 | import reset from './helpers/reset';
7 |
8 | let testCwd;
9 | const fixturesCwd = '__tests__/files/fixtures';
10 | const resultsCwd = '__tests__/files/results';
11 |
12 | beforeEach(() => {
13 | testCwd = tmp.dirSync();
14 |
15 | reset();
16 | });
17 |
18 | afterEach(() => {
19 | testCwd.removeCallback();
20 | });
21 |
22 | test('should process css files synchornously', () => {
23 | rcs.process.cssSync('**/style*.css', {
24 | newPath: testCwd.name,
25 | cwd: fixturesCwd,
26 | });
27 |
28 | const newFile = fs.readFileSync(path.join(testCwd.name, '/css/style.css'), 'utf8');
29 | const newFile2 = fs.readFileSync(path.join(testCwd.name, '/css/style2.css'), 'utf8');
30 | const newFile3 = fs.readFileSync(path.join(testCwd.name, '/css/subdirectory/style.css'), 'utf8');
31 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/css/style.css'), 'utf8');
32 | const expectedFile2 = fs.readFileSync(path.join(resultsCwd, '/css/style2.css'), 'utf8');
33 | const expectedFile3 = fs.readFileSync(path.join(resultsCwd, '/css/subdirectory/style.css'), 'utf8');
34 |
35 | expect(newFile).toBe(expectedFile);
36 | expect(newFile2).toBe(expectedFile2);
37 | expect(newFile3).toBe(expectedFile3);
38 | });
39 |
40 | test('should process css files as arrays synchornously', () => {
41 | rcs.process.cssSync(['**/style.css', '**/style2.css'], {
42 | newPath: testCwd.name,
43 | cwd: fixturesCwd,
44 | });
45 |
46 | const newFile = fs.readFileSync(path.join(testCwd.name, '/css/style.css'), 'utf8');
47 | const newFile2 = fs.readFileSync(path.join(testCwd.name, '/css/style2.css'), 'utf8');
48 | const newFile3 = fs.readFileSync(path.join(testCwd.name, '/css/subdirectory/style.css'), 'utf8');
49 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/css/style.css'), 'utf8');
50 | const expectedFile2 = fs.readFileSync(path.join(resultsCwd, '/css/style2.css'), 'utf8');
51 | const expectedFile3 = fs.readFileSync(path.join(resultsCwd, '/css/subdirectory/style.css'), 'utf8');
52 |
53 | expect(newFile).toBe(expectedFile);
54 | expect(newFile2).toBe(expectedFile2);
55 | expect(newFile3).toBe(expectedFile3);
56 | });
57 |
--------------------------------------------------------------------------------
/__tests__/processJs.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import path from 'path';
3 | import fs from 'fs-extra';
4 | import rcsCore from 'rcs-core';
5 |
6 | import rcs from '../lib';
7 | import reset from './helpers/reset';
8 |
9 | let testCwd;
10 | const fixturesCwd = '__tests__/files/fixtures';
11 | const resultsCwd = '__tests__/files/results';
12 |
13 | beforeAll(() => {
14 | testCwd = tmp.dirSync();
15 |
16 | reset();
17 |
18 | rcsCore.selectorsLibrary.fillLibrary(fs.readFileSync(path.join(fixturesCwd, '/css/style.css'), 'utf8'));
19 | });
20 |
21 | afterEach(() => {
22 | testCwd.removeCallback();
23 | });
24 |
25 | test('should process js files', async () => {
26 | await rcs.process.js('js/main.js', {
27 | newPath: testCwd.name,
28 | cwd: fixturesCwd,
29 | });
30 |
31 | const newFile = fs.readFileSync(path.join(testCwd.name, '/js/main.js'), 'utf8');
32 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/js/main.js'), 'utf8');
33 |
34 | expect(newFile).toBe(expectedFile);
35 | });
36 |
37 | test('should process jsx files', async () => {
38 | await rcs.process.js('js/react.js', {
39 | newPath: testCwd.name,
40 | cwd: fixturesCwd,
41 | });
42 |
43 | const newFile = fs.readFileSync(path.join(testCwd.name, '/js/react.js'), 'utf8');
44 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/js/react.js'), 'utf8');
45 |
46 | expect(newFile).toBe(expectedFile);
47 | });
48 |
49 | test('should not process jsx files', async () => {
50 | await expect((
51 | rcs.process.js('js/react.js', {
52 | newPath: testCwd.name,
53 | cwd: fixturesCwd,
54 | espreeOptions: {
55 | ecmaFeatures: {
56 | jsx: false,
57 | },
58 | },
59 | })
60 | )).rejects.toBeTruthy();
61 | });
62 |
63 | test('should process complex files', async () => {
64 | await rcs.process.js('js/complex.js', {
65 | newPath: testCwd.name,
66 | cwd: fixturesCwd,
67 | });
68 |
69 | const newFile = fs.readFileSync(path.join(testCwd.name, '/js/complex.js'), 'utf8');
70 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/js/complex.js'), 'utf8');
71 |
72 | expect(newFile).toBe(expectedFile);
73 | });
74 |
75 | test('should not process multiple files', async () => {
76 | await rcs.process.js('js/*.js', {
77 | newPath: testCwd.name,
78 | cwd: fixturesCwd,
79 | espreeOptions: {
80 | ecmaFeatures: {
81 | jsx: true,
82 | },
83 | },
84 | });
85 |
86 | const newFile = fs.readFileSync(path.join(testCwd.name, '/js/complex.js'), 'utf8');
87 | const newFileTwo = fs.readFileSync(path.join(testCwd.name, '/js/main.js'), 'utf8');
88 | const newFileThree = fs.readFileSync(path.join(testCwd.name, '/js/react.js'), 'utf8');
89 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/js/complex.js'), 'utf8');
90 | const expectedFileTwo = fs.readFileSync(path.join(resultsCwd, '/js/main.js'), 'utf8');
91 | const expectedFileThree = fs.readFileSync(path.join(resultsCwd, '/js/react.js'), 'utf8');
92 |
93 | expect(newFile).toBe(expectedFile);
94 | expect(newFileTwo).toBe(expectedFileTwo);
95 | expect(newFileThree).toBe(expectedFileThree);
96 | });
97 |
--------------------------------------------------------------------------------
/__tests__/processJsSync.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import fs from 'fs-extra';
3 | import rcsCore from 'rcs-core';
4 | import path from 'path';
5 |
6 | import rcs from '../lib';
7 | import reset from './helpers/reset';
8 |
9 | let testCwd;
10 | const fixturesCwd = '__tests__/files/fixtures';
11 | const resultsCwd = '__tests__/files/results';
12 |
13 | beforeAll(() => {
14 | testCwd = tmp.dirSync();
15 |
16 | reset();
17 |
18 | rcsCore.selectorsLibrary.fillLibrary(fs.readFileSync(path.join(fixturesCwd, '/css/style.css'), 'utf8'));
19 | });
20 |
21 | afterEach(() => {
22 | testCwd.removeCallback();
23 | });
24 |
25 | test('should process js files', () => {
26 | rcs.process.jsSync('js/main.js', {
27 | newPath: testCwd.name,
28 | cwd: fixturesCwd,
29 | });
30 |
31 | const newFile = fs.readFileSync(path.join(testCwd.name, '/js/main.js'), 'utf8');
32 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/js/main.js'), 'utf8');
33 |
34 | expect(newFile).toBe(expectedFile);
35 | });
36 |
37 | test('should process jsx files', () => {
38 | rcs.process.jsSync('js/react.js', {
39 | newPath: testCwd.name,
40 | cwd: fixturesCwd,
41 | espreeOptions: {
42 | ecmaFeatures: {
43 | jsx: true,
44 | },
45 | },
46 | });
47 |
48 | const newFile = fs.readFileSync(path.join(testCwd.name, '/js/react.js'), 'utf8');
49 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/js/react.js'), 'utf8');
50 |
51 | expect(newFile).toBe(expectedFile);
52 | });
53 |
54 | test('should not process jsx files', () => {
55 | rcs.process.jsSync('js/react.js', {
56 | newPath: testCwd.name,
57 | cwd: fixturesCwd,
58 | });
59 |
60 | const newFile = fs.readFileSync(path.join(testCwd.name, '/js/react.js'), 'utf8');
61 | const expectedFile = fs.readFileSync(path.join(testCwd.name, '/js/react.js'), 'utf8');
62 |
63 | expect(newFile).toBe(expectedFile);
64 | });
65 |
66 | test('should process complex files', () => {
67 | rcs.process.jsSync('js/complex.js', {
68 | newPath: testCwd.name,
69 | cwd: fixturesCwd,
70 | });
71 |
72 | const newFile = fs.readFileSync(path.join(testCwd.name, '/js/complex.js'), 'utf8');
73 | const expectedFile = fs.readFileSync(path.join(testCwd.name, '/js/complex.js'), 'utf8');
74 |
75 | expect(newFile).toBe(expectedFile);
76 | });
77 |
78 | test('should not process multiple files', () => {
79 | rcs.process.jsSync('js/*.js', {
80 | newPath: testCwd.name,
81 | cwd: fixturesCwd,
82 | espreeOptions: {
83 | ecmaFeatures: {
84 | jsx: true,
85 | },
86 | },
87 | });
88 |
89 | const newFile = fs.readFileSync(path.join(testCwd.name, '/js/complex.js'), 'utf8');
90 | const newFileTwo = fs.readFileSync(path.join(testCwd.name, '/js/main.js'), 'utf8');
91 | const newFileThree = fs.readFileSync(path.join(testCwd.name, '/js/react.js'), 'utf8');
92 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/js/complex.js'), 'utf8');
93 | const expectedFileTwo = fs.readFileSync(path.join(resultsCwd, '/js/main.js'), 'utf8');
94 | const expectedFileThree = fs.readFileSync(path.join(resultsCwd, '/js/react.js'), 'utf8');
95 |
96 | expect(newFile).toBe(expectedFile);
97 | expect(newFileTwo).toBe(expectedFileTwo);
98 | expect(newFileThree).toBe(expectedFileThree);
99 | });
100 |
--------------------------------------------------------------------------------
/__tests__/processPug.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import path from 'path';
3 | import fs from 'fs-extra';
4 | import rcsCore from 'rcs-core';
5 |
6 | import rcs from '../lib';
7 | import reset from './helpers/reset';
8 |
9 | let testCwd;
10 | const fixturesCwd = '__tests__/files/fixtures';
11 | const resultsCwd = '__tests__/files/results';
12 |
13 | beforeAll(() => {
14 | testCwd = tmp.dirSync();
15 |
16 | reset();
17 |
18 | rcsCore.selectorsLibrary.fillLibrary(fs.readFileSync(path.join(fixturesCwd, '/css/style.css'), 'utf8'));
19 | });
20 |
21 | afterEach(() => {
22 | testCwd.removeCallback();
23 | });
24 |
25 | test('should process pug files', async () => {
26 | await rcs.process.pug('pug/index.pug', {
27 | newPath: testCwd.name,
28 | cwd: fixturesCwd,
29 | });
30 |
31 | const newFile = fs.readFileSync(path.join(testCwd.name, '/pug/index.pug'), 'utf8');
32 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/pug/index.pug'), 'utf8');
33 |
34 | expect(newFile.trim()).toBe(expectedFile.trim());
35 | });
36 |
--------------------------------------------------------------------------------
/__tests__/processPugSync.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import path from 'path';
3 | import fs from 'fs-extra';
4 | import rcsCore from 'rcs-core';
5 |
6 | import rcs from '../lib';
7 | import reset from './helpers/reset';
8 |
9 | let testCwd;
10 | const fixturesCwd = '__tests__/files/fixtures';
11 | const resultsCwd = '__tests__/files/results';
12 |
13 |
14 | beforeAll(() => {
15 | testCwd = tmp.dirSync();
16 |
17 | reset();
18 |
19 | rcsCore.selectorsLibrary.fillLibrary(fs.readFileSync(path.join(fixturesCwd, '/css/style.css'), 'utf8'));
20 | });
21 |
22 | afterEach(() => {
23 | testCwd.removeCallback();
24 | });
25 |
26 | test('should process pug files', () => {
27 | rcs.process.pugSync('pug/index.pug', {
28 | newPath: testCwd.name,
29 | cwd: fixturesCwd,
30 | });
31 |
32 | const newFile = fs.readFileSync(path.join(testCwd.name, '/pug/index.pug'), 'utf8');
33 | const expectedFile = fs.readFileSync(path.join(resultsCwd, '/pug/index.pug'), 'utf8');
34 |
35 | expect(newFile.trim()).toBe(expectedFile.trim());
36 | });
37 |
--------------------------------------------------------------------------------
/__tests__/save.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import fs from 'fs-extra';
3 | import path from 'path';
4 |
5 | import save from '../lib/helper/save';
6 |
7 | let testCwd;
8 | const testFiles = '__tests__/files';
9 |
10 | beforeEach(() => {
11 | testCwd = tmp.dirSync();
12 | });
13 |
14 | afterEach(() => {
15 | testCwd.removeCallback();
16 | });
17 |
18 |
19 | test('should create a file within a non existing dir', (done) => {
20 | const filePath = path.join(testCwd.name, '/a/non/existing/path/test.txt');
21 |
22 | save(filePath, 'test content', (err) => {
23 | expect(err).not.toBe(undefined);
24 |
25 | expect(fs.existsSync(filePath)).toBe(true);
26 | expect(fs.readFileSync(filePath, 'utf8')).toBe('test content');
27 |
28 | done();
29 | });
30 | });
31 |
32 | test('should not overwrite the same file', async () => {
33 | const filePath = path.join(testFiles, '/config.json');
34 | const filePathTest = path.join(testCwd.name, '/config.json');
35 | const oldFile = fs.readFileSync(filePath, 'utf8');
36 |
37 | await save(filePathTest, 'test content');
38 |
39 | await expect(save(filePathTest, 'test content'))
40 | .rejects
41 | .toEqual(new Error('File exist and cannot be overwritten. Set the option overwrite to true to overwrite files.'));
42 | expect(fs.readFileSync(filePath, 'utf8')).toBe(oldFile);
43 | });
44 |
--------------------------------------------------------------------------------
/__tests__/saveSync.ts:
--------------------------------------------------------------------------------
1 | import tmp from 'tmp';
2 | import fs from 'fs-extra';
3 | import path from 'path';
4 |
5 | import saveSync from '../lib/helper/saveSync';
6 |
7 | let testCwd;
8 | const testFiles = '__tests__/files';
9 |
10 | beforeEach(() => {
11 | testCwd = tmp.dirSync();
12 | });
13 |
14 | afterEach(() => {
15 | testCwd.removeCallback();
16 | });
17 |
18 |
19 | test('saveSync | should save', () => {
20 | const filePath = path.join(testCwd.name, '/config.txt');
21 |
22 | saveSync(filePath, 'test content');
23 |
24 | expect(fs.readFileSync(filePath, 'utf8')).toBe('test content');
25 | });
26 |
27 | test('saveSync | should not overwrite the same file', () => {
28 | const filePath = path.join(testFiles, '/config.json');
29 | const filePathTest = path.join(testCwd.name, '/config.json');
30 | const oldFile = fs.readFileSync(filePath, 'utf8');
31 | let failed = false;
32 |
33 | saveSync(filePathTest, 'test content');
34 |
35 | try {
36 | saveSync(filePathTest, 'test content');
37 |
38 | // if no error is thrown before it should fail here
39 | failed = true;
40 | } catch (e) {
41 | expect(e.message).toBe('File exist and cannot be overwritten. Set the option overwrite to true to overwrite files.');
42 | }
43 |
44 | expect(failed).toBe(false);
45 | expect(fs.readFileSync(filePath, 'utf8')).toBe(oldFile);
46 | });
47 |
--------------------------------------------------------------------------------
/docs/api/config.md:
--------------------------------------------------------------------------------
1 | # Config
2 |
3 | **config.load([pathLocation])**
4 |
5 | > All available configs [here](#rcs-config)
6 |
7 | RCS will lookup first for a `.rcsrc` of the current directory. If there is no such file, it will lookup for a `package.json` with a `"rcsrc": {}` in it. You can also write any path in the parameters and write your own config file. This function is synchronous.
8 |
9 | Parameters:
10 | - pathLocation `` *optional*
11 |
12 | Example:
13 |
14 | ```js
15 | const rcs = require('rename-css-selectors');
16 |
17 | rcs.config.load();
18 | ```
19 |
20 | ## RCS config
21 |
22 | > Just create a `.rcsrc` in your project root or you can add everything in your `package.json` with the value `rcs`
23 |
24 | - [Example](#example)
25 | - [Exclude](#exclude-classes-and-ids)
26 | - [Ignore](#ignore-files)
27 |
28 | ### Example
29 |
30 | The `.rcsrc` or the a own config file:
31 |
32 | ```json
33 | {
34 | "exclude": [
35 | "js",
36 | "flexbox"
37 | ]
38 | }
39 | ```
40 |
41 | The `package.json`:
42 |
43 | ```json
44 | {
45 | "name": "Your application name",
46 | "rcs": {
47 | "exclude": [
48 | "js",
49 | "flexbox"
50 | ]
51 | }
52 | }
53 | ```
54 |
55 | ### Exclude Classes and IDs
56 |
57 | `exclude`
58 |
59 | What if you are using something such as Modernizr and you do not want to minify some selectors?
60 |
61 | Let's exclude 4 classes and id's: `js`, `flexbox`, `canvas` and `svg`
62 |
63 | ```json
64 | {
65 | "exclude": [
66 | "js",
67 | "flexbox",
68 | "canvas",
69 | "svg"
70 | ]
71 | }
72 | ```
73 |
74 | ### Ignore files
75 |
76 | `ignore`
77 |
78 | If you need to ignore some file or some file pattern from processing, this is how to do it using minimatch pattern (glob)
79 | Please notice that filepathes are matched absolutely.
80 |
81 | ```json
82 | {
83 | "ignore": [
84 | "relativeFile.js",
85 | "**/*.min.js",
86 | ]
87 | }
88 | ```
89 |
--------------------------------------------------------------------------------
/docs/api/loadMapping.md:
--------------------------------------------------------------------------------
1 | # loadMapping
2 |
3 | **loadMapping(mapping[, options])**
4 |
5 | > *Note:* If you include a file, it **MUST** be the json generated mapping.
6 |
7 | Loads the previous generated mapping. This ensures that all your projects have all the time the same renamed selectors.
8 |
9 | Parameters:
10 | - mapping ``: can be either a path to the mapping or a mapping object
11 | - options `