Skip to content

Commit 3bb0a60

Browse files
committed
Initial commit
0 parents  commit 3bb0a60

15 files changed

+4405
-0
lines changed

.editorconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# editorconfig.org
2+
root = true
3+
4+
[*]
5+
charset = utf-8
6+
end_of_line = lf
7+
indent_size = 2
8+
indent_style = space
9+
insert_final_newline = true
10+
max_line_length = 80
11+
trim_trailing_whitespace = true

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/.vscode
2+
/lib
3+
/node_modules
4+
npm-debug.log
5+
yarn-error.log

package.json

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"name": "typescript-css-modules",
3+
"version": "1.0.0",
4+
"main": "lib/index.js",
5+
"repository": "[email protected]:mrmckeb/typescript-css-modules.git",
6+
"author": "Brody McKee <[email protected]>",
7+
"license": "MIT",
8+
"description": "CSS modules support for TypeScript",
9+
"keywords": [
10+
"css",
11+
"modules",
12+
"plugin",
13+
"postcss",
14+
"sass",
15+
"typescript"
16+
],
17+
"scripts": {
18+
"build": "tsc",
19+
"test": "jest"
20+
},
21+
"husky": {
22+
"hooks": {
23+
"pre-commit": "pretty-quick --staged"
24+
}
25+
},
26+
"jest": {
27+
"preset": "ts-jest",
28+
"testEnvironment": "node"
29+
},
30+
"prettier": {
31+
"arrowParens": "always",
32+
"singleQuote": true,
33+
"trailingComma": "all"
34+
},
35+
"dependencies": {
36+
"icss-utils": "^4.0.0",
37+
"postcss": "^7.0.5",
38+
"postcss-icss-selectors": "^2.0.3"
39+
},
40+
"devDependencies": {
41+
"@types/jest": "^23.3.9",
42+
"@types/node": "^10.12.6",
43+
"husky": "^1.1.3",
44+
"jest": "^23.6.0",
45+
"prettier": "^1.15.2",
46+
"pretty-quick": "^1.8.0",
47+
"ts-jest": "^23.10.4",
48+
"tslint": "^5.11.0",
49+
"typescript": "^3.1.6"
50+
},
51+
"peerDependencies": {
52+
"typescript": "^3.0.0"
53+
}
54+
}

src/@types/icss-utils.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
declare module 'icss-utils' {
2+
import { Root } from 'postcss';
3+
interface IICSSExports {
4+
[exportName: string]: string;
5+
}
6+
export const extractICSS: (
7+
css: Root,
8+
removeRules?: boolean,
9+
) => {
10+
icssExports: IICSSExports;
11+
};
12+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
declare module 'postcss-icss-selectors' {
2+
import { Plugin } from 'postcss';
3+
const plugin: Plugin<{ mode: 'local' | 'global' }>;
4+
export = plugin;
5+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { isCSS, isRelativeCSS } from '../cssExtensions';
2+
3+
describe('utils / cssExtensions', () => {
4+
describe('isCSS', () => {
5+
it('should match CSS module extensions', () => {
6+
expect(isCSS('./myfile.module.scss')).toBe(true);
7+
expect(isCSS('./myfile.module.sass')).toBe(true);
8+
expect(isCSS('./myfile.module.css')).toBe(true);
9+
});
10+
11+
it('should not match non-CSS module extensions', () => {
12+
expect(isCSS('./myfile.module.s')).toBe(false);
13+
expect(isCSS('./myfile.scss')).toBe(false);
14+
expect(isCSS('./myfile.sass')).toBe(false);
15+
expect(isCSS('./myfile.css')).toBe(false);
16+
});
17+
});
18+
19+
describe('isRelativeCSS', () => {
20+
it('should match relative CSS modules', () => {
21+
expect(isRelativeCSS('./myfile.module.css')).toBe(true);
22+
expect(isRelativeCSS('../folder/myfile.module.css')).toBe(true);
23+
});
24+
25+
it('should not match non-relative CSS modules', () => {
26+
expect(isRelativeCSS('myfile.module.css')).toBe(false);
27+
});
28+
});
29+
});
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { readFileSync } from 'fs';
2+
import { IICSSExports } from 'icss-utils';
3+
import { join } from 'path';
4+
import { createExports, getClasses } from '../cssSnapshots';
5+
6+
describe('utils / cssSnapshots', () => {
7+
let classesA: IICSSExports;
8+
let classesB: IICSSExports;
9+
10+
beforeAll(() => {
11+
const testFileA = readFileSync(
12+
join(__dirname, 'fixtures/testA.module.css'),
13+
'utf8',
14+
);
15+
const testFileB = readFileSync(
16+
join(__dirname, 'fixtures/testB.module.scss'),
17+
'utf8',
18+
);
19+
classesA = getClasses(testFileA);
20+
classesB = getClasses(testFileB);
21+
});
22+
23+
describe('getClasses', () => {
24+
it('should return an object matching expected CSS classes', () => {
25+
expect(classesA).toEqual({
26+
ClassB: 'file__ClassB---2bPVi',
27+
childA: 'file__childA---1hjQD',
28+
childB: 'file__childB---pq4Ks',
29+
'class-c': 'file__class-c---DZ1TD',
30+
classA: 'file__classA---2xcnJ',
31+
nestedChild: 'file__nestedChild---2d15b',
32+
parent: 'file__parent---1ATMj',
33+
});
34+
expect(classesB).toEqual({
35+
'local-class': 'file__local-class---3KegX',
36+
'local-class-2': 'file__local-class-2---2h6qz',
37+
'local-class-inside-global': 'file__local-class-inside-global---2xH_Y',
38+
'local-class-inside-local': 'file__local-class-inside-local---QdL6b',
39+
});
40+
});
41+
});
42+
43+
describe('createExports', () => {
44+
it('should create an exports file', () => {
45+
const exportsA = createExports(classesA);
46+
const exportsB = createExports(classesB);
47+
// tslint:disable max-line-length
48+
expect(exportsA).toMatchInlineSnapshot(
49+
`"export const classA: string;export const ClassB: string;export const class-c: string;export const parent: string;export const childA: string;export const childB: string;export const nestedChild: string;"`,
50+
);
51+
expect(exportsB).toMatchInlineSnapshot(
52+
`"export const local-class-inside-global: string;export const local-class: string;export const local-class-2: string;export const local-class-inside-local: string;"`,
53+
);
54+
// tslint:enable max-line-length
55+
});
56+
});
57+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
.classA {
2+
}
3+
4+
.ClassB {
5+
}
6+
7+
.class-c {
8+
}
9+
10+
.parent {
11+
.childA {
12+
}
13+
.childB {
14+
.nestedChild {
15+
}
16+
}
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
:global .global-class {
2+
}
3+
4+
:global(.global-class-2) {
5+
.local-class-inside-global {
6+
}
7+
}
8+
9+
:local .local-class {
10+
}
11+
12+
:local(.local-class-2) {
13+
.local-class-inside-local {
14+
}
15+
}

src/helpers/cssExtensions.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const isRelative = (fileName: string) => /^\.\.?($|[\\/])/.test(fileName);
2+
3+
export const isCSS = (fileName: string) =>
4+
/\.module\.(sa|sc|c)ss$/.test(fileName);
5+
6+
export const isRelativeCSS = (fileName: string) =>
7+
isCSS(fileName) && isRelative(fileName);

0 commit comments

Comments
 (0)