Skip to content

Commit 8d732a1

Browse files
committed
feat(casing): add support for transforming classnames
1 parent 4fd4054 commit 8d732a1

8 files changed

+116
-14
lines changed

lib/cli.ts

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import yargs from "yargs";
2-
import { SassError } from "node-sass";
32

4-
import { fileToClassNames, Aliases } from "./sass/file-to-class-names";
3+
import { parse, Aliases, NAME_FORMATS, NameFormat } from "./sass";
54

6-
const { _: files, includePaths, aliases } = yargs
5+
const nameFormatDefault: NameFormat = "camel";
6+
7+
const { _: files, includePaths, aliases, nameFormat } = yargs
78
.demandOption("_")
8-
.option("aliases", { coerce: (obj): Aliases => obj })
9+
.option("aliases", { coerce: (obj): Aliases => obj, alias: "a" })
10+
.option("nameFormat", {
11+
choices: NAME_FORMATS,
12+
default: nameFormatDefault,
13+
alias: "n"
14+
})
915
.option("includePaths", { array: true, string: true }).argv;
1016

11-
fileToClassNames(files[0], { includePaths, aliases })
12-
.then(console.log)
13-
.catch((err: SassError) => {
14-
console.error(err.message);
15-
console.error(`${err.file}[${err.line}:${err.column}]`);
16-
});
17+
parse(files[0], { includePaths, aliases, nameFormat });
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
import { fileToClassNames } from "../file-to-class-names";
22

33
describe("fileToClassNames", () => {
4-
test("converts a file path to an array of class names", async () => {
4+
test("it converts a file path to an array of class names (default camel cased)", async () => {
55
const result = await fileToClassNames(`${__dirname}/style.scss`);
6+
7+
expect(result).toEqual(["someStyles", "nestedClass", "nestedAnother"]);
8+
});
9+
10+
test("it converts a file path to an array of class names with kebab as the name format", async () => {
11+
const result = await fileToClassNames(`${__dirname}/style.scss`, {
12+
nameFormat: "kebab"
13+
});
14+
15+
expect(result).toEqual(["some-styles", "nested-class", "nested-another"]);
16+
});
17+
18+
test("it converts a file path to an array of class names with param as the name format", async () => {
19+
const result = await fileToClassNames(`${__dirname}/style.scss`, {
20+
nameFormat: "param"
21+
});
22+
623
expect(result).toEqual(["some-styles", "nested-class", "nested-another"]);
724
});
825
});

lib/sass/file-to-class-names.ts

+33-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import sass from "node-sass";
2+
import camelcase from "camelcase";
3+
import paramcase from "param-case";
4+
25
import { sourceToClassNames } from "./source-to-class-names";
36

47
export type ClassName = string;
@@ -8,11 +11,16 @@ export interface Aliases {
811
[index: string]: string;
912
}
1013

14+
export type NameFormat = "camel" | "kebab" | "param";
15+
1116
export interface Options {
1217
includePaths?: string[];
1318
aliases?: Aliases;
19+
nameFormat?: NameFormat;
1420
}
1521

22+
export const NAME_FORMATS: NameFormat[] = ["camel", "kebab", "param"];
23+
1624
const importer = (aliases: Aliases) => (url: string) => {
1725
if (url in aliases) {
1826
return {
@@ -25,8 +33,14 @@ const importer = (aliases: Aliases) => (url: string) => {
2533

2634
export const fileToClassNames = (
2735
file: string,
28-
{ includePaths = [], aliases = {} }: Options = {}
36+
{
37+
includePaths = [],
38+
aliases = {},
39+
nameFormat = "camel"
40+
}: Options = {} as Options
2941
) => {
42+
const transformer = classNameTransformer(nameFormat);
43+
3044
return new Promise<ClassNames>((resolve, reject) => {
3145
sass.render(
3246
{
@@ -41,9 +55,26 @@ export const fileToClassNames = (
4155
}
4256

4357
sourceToClassNames(result.css).then(({ exportTokens }) => {
44-
resolve(Object.keys(exportTokens));
58+
const classNames = Object.keys(exportTokens);
59+
const transformedClassNames = classNames.map(transformer);
60+
61+
resolve(transformedClassNames);
4562
});
4663
}
4764
);
4865
});
4966
};
67+
68+
interface Transformer {
69+
(value: string): string;
70+
}
71+
72+
const classNameTransformer = (nameFormat: NameFormat): Transformer => {
73+
switch (nameFormat) {
74+
case "kebab":
75+
case "param":
76+
return paramcase;
77+
case "camel":
78+
return camelcase;
79+
}
80+
};

lib/sass/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { Aliases, NameFormat, NAME_FORMATS } from "./file-to-class-names";
2+
export { parse } from "./parse";

lib/sass/parse.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { SassError } from "node-sass";
2+
3+
import { Options, fileToClassNames } from "./file-to-class-names";
4+
5+
export const parse = (file: string, options: Options): void => {
6+
fileToClassNames(file, options)
7+
.then(console.log)
8+
.catch((err: SassError) => {
9+
console.error(err.message);
10+
console.error(`${err.file}[${err.line}:${err.column}]`);
11+
});
12+
};

package.json

+7
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,19 @@
55
"main": "index.js",
66
"author": "Spencer Miskoviak <smiskoviak@gmail.com>",
77
"license": "MIT",
8+
"scripts": {
9+
"test": "jest"
10+
},
811
"devDependencies": {
12+
"@types/camelcase": "^4.1.0",
913
"@types/jest": "^24.0.0",
1014
"@types/node-sass": "^3.10.32",
15+
"@types/param-case": "^1.1.2",
1116
"@types/yargs": "^12.0.8",
17+
"camelcase": "^5.0.0",
1218
"jest": "^24.1.0",
1319
"node-sass": "^4.11.0",
20+
"param-case": "^2.1.1",
1421
"ts-jest": "^23.10.5",
1522
"typescript": "^3.3.3"
1623
},

tsconfig.json

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
"module": "commonjs",
55
"strict": true,
66
"esModuleInterop": true,
7-
"skipLibCheck": true
7+
"skipLibCheck": true,
8+
"baseUrl": ".",
9+
"paths": {
10+
"css-modules-loader-core": [
11+
"./typings/css-modules-loader-core/index.d.ts"
12+
]
13+
}
814
}
915
}

yarn.lock

+26
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@
117117
lodash "^4.17.10"
118118
to-fast-properties "^2.0.0"
119119

120+
"@types/camelcase@^4.1.0":
121+
version "4.1.0"
122+
resolved "https://registry.yarnpkg.com/@types/camelcase/-/camelcase-4.1.0.tgz#e054f7986f31658d49936261b5cd4588ef29d1ee"
123+
120124
"@types/jest@^24.0.0":
121125
version "24.0.0"
122126
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.0.tgz#848492026c327b3548d92be0352a545c36a21e8a"
@@ -131,6 +135,12 @@
131135
version "10.12.24"
132136
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.24.tgz#b13564af612a22a20b5d95ca40f1bffb3af315cf"
133137

138+
"@types/param-case@^1.1.2":
139+
version "1.1.2"
140+
resolved "https://registry.yarnpkg.com/@types/param-case/-/param-case-1.1.2.tgz#e1fac15b59c7d9cd8c2dd15962c7ad3cf960325f"
141+
dependencies:
142+
param-case "*"
143+
134144
"@types/yargs@^12.0.8":
135145
version "12.0.8"
136146
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.8.tgz#0b45bf0607a5509b921335658d87489c12955176"
@@ -1948,6 +1958,10 @@ loud-rejection@^1.0.0:
19481958
currently-unhandled "^0.4.1"
19491959
signal-exit "^3.0.0"
19501960

1961+
lower-case@^1.1.1:
1962+
version "1.1.4"
1963+
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
1964+
19511965
lru-cache@^4.0.1:
19521966
version "4.1.5"
19531967
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
@@ -2144,6 +2158,12 @@ nice-try@^1.0.4:
21442158
version "1.0.5"
21452159
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
21462160

2161+
no-case@^2.2.0:
2162+
version "2.3.2"
2163+
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
2164+
dependencies:
2165+
lower-case "^1.1.1"
2166+
21472167
node-gyp@^3.8.0:
21482168
version "3.8.0"
21492169
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c"
@@ -2410,6 +2430,12 @@ p-try@^2.0.0:
24102430
version "2.0.0"
24112431
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1"
24122432

2433+
param-case@*, param-case@^2.1.1:
2434+
version "2.1.1"
2435+
resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
2436+
dependencies:
2437+
no-case "^2.2.0"
2438+
24132439
parse-json@^2.2.0:
24142440
version "2.2.0"
24152441
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"

0 commit comments

Comments
 (0)