Skip to content

Commit 7033534

Browse files
hipstersmoothiemrmckeb
authored andcommitted
Add support for PostCSS configs (#33)
1 parent 143b7ea commit 7033534

File tree

6 files changed

+89
-7
lines changed

6 files changed

+89
-7
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"lodash": "^4.17.14",
5353
"postcss": "^7.0.17",
5454
"postcss-icss-selectors": "^2.0.3",
55+
"postcss-load-config": "^2.1.0",
5556
"reserved-words": "^0.1.2",
5657
"sass": "^1.22.4"
5758
},

src/@types/postcss-load.config.d.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
declare module 'postcss-load-config' {
2+
interface PostCSSConfig {
3+
plugins: any[];
4+
options?: any;
5+
}
6+
7+
interface Load {
8+
(context: object, path?: string, options?: object): Promise<PostCSSConfig>;
9+
sync(context: object, path?: string, options?: object): PostCSSConfig;
10+
}
11+
12+
const load: Load;
13+
14+
export = load;
15+
}

src/helpers/DtsSnapshotCreator.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { extractICSS, IICSSExports } from 'icss-utils';
22
import * as postcss from 'postcss';
3-
import * as postcssIcssSelectors from 'postcss-icss-selectors';
43
import * as ts_module from 'typescript/lib/tsserverlibrary';
54
import * as less from 'less';
65
import * as sass from 'sass';
@@ -10,7 +9,6 @@ import { Options } from '../options';
109
import { Logger } from './Logger';
1110

1211
const NOT_CAMELCASE_REGEXP = /[\-_]/;
13-
const processor = postcss(postcssIcssSelectors({ mode: 'local' }));
1412

1513
const classNameToProperty = (className: string) => `'${className}': string;`;
1614
const classNameToNamedExport = (className: string) =>
@@ -39,7 +37,7 @@ const getFilePath = (fileName: string) =>
3937
export class DtsSnapshotCreator {
4038
constructor(private readonly logger: Logger) {}
4139

42-
getClasses(css: string, fileName: string) {
40+
getClasses(processor: postcss.Processor, css: string, fileName: string) {
4341
try {
4442
const fileType = getFileType(fileName);
4543
let transformedCss = '';
@@ -62,7 +60,9 @@ export class DtsSnapshotCreator {
6260

6361
const processedCss = processor.process(transformedCss);
6462

65-
return extractICSS(processedCss.root).icssExports;
63+
return processedCss.root
64+
? extractICSS(processedCss.root).icssExports
65+
: {};
6666
} catch (e) {
6767
this.logger.error(e);
6868
return {};
@@ -97,12 +97,13 @@ export default classes;
9797

9898
getDtsSnapshot(
9999
ts: typeof ts_module,
100+
processor: postcss.Processor,
100101
fileName: string,
101102
scriptSnapshot: ts.IScriptSnapshot,
102103
options: Options,
103104
) {
104105
const css = scriptSnapshot.getText(0, scriptSnapshot.getLength());
105-
const classes = this.getClasses(css, fileName);
106+
const classes = this.getClasses(processor, css, fileName);
106107
const dts = this.createExports(classes, options);
107108
return ts.ScriptSnapshot.fromString(dts);
108109
}

src/helpers/__tests__/DtsSnapshotCreator.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { readFileSync } from 'fs';
22
import { IICSSExports } from 'icss-utils';
33
import { join } from 'path';
4+
import * as postcss from 'postcss';
5+
import * as postcssIcssSelectors from 'postcss-icss-selectors';
46
import { DtsSnapshotCreator } from '../DtsSnapshotCreator';
57

68
const testFileNames = [
@@ -11,6 +13,8 @@ const testFileNames = [
1113
'empty.module.scss',
1214
];
1315

16+
const processor = postcss([postcssIcssSelectors({ mode: 'local' })]);
17+
1418
describe('utils / cssSnapshots', () => {
1519
testFileNames.forEach((fileName) => {
1620
let classes: IICSSExports;
@@ -23,7 +27,11 @@ describe('utils / cssSnapshots', () => {
2327
log: jest.fn(),
2428
error: jest.fn(),
2529
});
26-
classes = dtsSnapshotCreator.getClasses(testFile, fullFileName);
30+
classes = dtsSnapshotCreator.getClasses(
31+
processor,
32+
testFile,
33+
fullFileName,
34+
);
2735
});
2836

2937
describe(`with file '${fileName}'`, () => {

src/index.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,50 @@
11
import * as fs from 'fs';
22
import * as path from 'path';
3+
import * as loadPostCssConfig from 'postcss-load-config';
34
import * as ts_module from 'typescript/lib/tsserverlibrary';
5+
46
import { createMatchers } from './helpers/createMatchers';
57
import { isCSSFn } from './helpers/cssExtensions';
68
import { DtsSnapshotCreator } from './helpers/DtsSnapshotCreator';
79
import { Options } from './options';
810
import { LanguageServiceLogger } from './helpers/Logger';
911

12+
import * as postcss from 'postcss';
13+
import * as postcssIcssSelectors from 'postcss-icss-selectors';
14+
15+
const removePlugin = postcss.plugin('remove-mixins', () => (css) => {
16+
css.walkRules((rule) => {
17+
rule.walkAtRules((atRule) => {
18+
if (atRule.name === 'mixin') {
19+
atRule.remove();
20+
}
21+
});
22+
});
23+
});
24+
25+
function getPostCssConfig(dir: string) {
26+
try {
27+
return loadPostCssConfig.sync({}, dir);
28+
} catch (error) {
29+
return { plugins: [] };
30+
}
31+
}
32+
1033
function init({ typescript: ts }: { typescript: typeof ts_module }) {
1134
let _isCSS: isCSSFn;
35+
1236
function create(info: ts.server.PluginCreateInfo) {
1337
const logger = new LanguageServiceLogger(info);
1438
const dtsSnapshotCreator = new DtsSnapshotCreator(logger);
39+
const postcssConfig = getPostCssConfig(info.project.getCurrentDirectory());
40+
const processor = postcss([
41+
removePlugin(),
42+
...postcssConfig.plugins.filter(
43+
// Postcss mixins plugin might be async and will break the postcss sync output.
44+
(plugin) => !['postcss-mixins'].includes(plugin.postcssPlugin),
45+
),
46+
postcssIcssSelectors({ mode: 'local' }),
47+
]);
1548

1649
// User options for plugin.
1750
const options: Options = info.config.options || {};
@@ -32,6 +65,7 @@ function init({ typescript: ts }: { typescript: typeof ts_module }) {
3265
if (isCSS(fileName)) {
3366
scriptSnapshot = dtsSnapshotCreator.getDtsSnapshot(
3467
ts,
68+
processor,
3569
fileName,
3670
scriptSnapshot,
3771
options,
@@ -58,6 +92,7 @@ function init({ typescript: ts }: { typescript: typeof ts_module }) {
5892
if (isCSS(sourceFile.fileName)) {
5993
scriptSnapshot = dtsSnapshotCreator.getDtsSnapshot(
6094
ts,
95+
processor,
6196
sourceFile.fileName,
6297
scriptSnapshot,
6398
options,

yarn.lock

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ [email protected], core-util-is@~1.0.0:
943943
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
944944
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
945945

946-
cosmiconfig@^5.2.0:
946+
cosmiconfig@^5.0.0, cosmiconfig@^5.2.0:
947947
version "5.2.1"
948948
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
949949
integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
@@ -1698,6 +1698,13 @@ image-size@~0.5.0:
16981698
resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c"
16991699
integrity sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=
17001700

1701+
import-cwd@^2.0.0:
1702+
version "2.1.0"
1703+
resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"
1704+
integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=
1705+
dependencies:
1706+
import-from "^2.1.0"
1707+
17011708
import-fresh@^2.0.0:
17021709
version "2.0.0"
17031710
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
@@ -1706,6 +1713,13 @@ import-fresh@^2.0.0:
17061713
caller-path "^2.0.0"
17071714
resolve-from "^3.0.0"
17081715

1716+
import-from@^2.1.0:
1717+
version "2.1.0"
1718+
resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1"
1719+
integrity sha1-M1238qev/VOqpHHUuAId7ja387E=
1720+
dependencies:
1721+
resolve-from "^3.0.0"
1722+
17091723
import-local@^2.0.0:
17101724
version "2.0.0"
17111725
resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d"
@@ -3240,6 +3254,14 @@ postcss-icss-selectors@^2.0.3:
32403254
lodash "^4.17.4"
32413255
postcss "^6.0.2"
32423256

3257+
postcss-load-config@^2.1.0:
3258+
version "2.1.0"
3259+
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003"
3260+
integrity sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==
3261+
dependencies:
3262+
cosmiconfig "^5.0.0"
3263+
import-cwd "^2.0.0"
3264+
32433265
postcss@^6.0.2:
32443266
version "6.0.23"
32453267
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"

0 commit comments

Comments
 (0)