Skip to content

Commit 700caec

Browse files
committed
feat(styles): add new stylesheet format - styled-components
1 parent 1464c6a commit 700caec

9 files changed

Lines changed: 129 additions & 16 deletions

File tree

src/config/Config.ts

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,12 @@ export class Config implements IConfig {
5656
}
5757

5858
private setVariables(config) {
59-
// Boolean
60-
6159
this.jsxExt = config.jsxExt ?? this.jsxExt;
6260
this.newJsx = config.newJsx ?? this.newJsx;
6361
this.typescript = config.typescript ?? this.typescript;
6462
this.wrapFolder = config.wrapFolder ?? this.wrapFolder;
65-
this.cssModules = config.cssModules ?? this.cssModules;
6663
this.arrowFunction = config.arrowFunction ?? this.arrowFunction;
6764

68-
// Enum
69-
7065
this.fileNameCase = config.fileNameCase ?? this.fileNameCase;
7166

7267
if (config.styles) {
@@ -108,16 +103,31 @@ export class Config implements IConfig {
108103
if (!this.path || config.path) {
109104
this.path = path.resolve(APP_ROOT, config.path ?? DEFAULT_CONFIG.path);
110105
}
106+
107+
if (this.styles !== 'styled-components') {
108+
this.cssModules = config.cssModules ?? this.cssModules;
109+
} else if (config.cssModules) {
110+
Logger.warn(
111+
chalk =>
112+
`CSS Modules are incompatible with stylesheet format - ${chalk.white(
113+
'styled-components'
114+
)}`
115+
);
116+
}
111117
}
112118

113119
private setFilesExtension() {
114-
const styleExt = this.styles.toLowerCase();
120+
const component = this.typescript ? 'tsx' : `j${this.jsxExt ? 'sx' : 's'}`;
121+
const script = `${this.typescript ? 't' : 'j'}s`;
122+
123+
let style = this.styles.toLowerCase();
124+
if (style === 'styled-components') {
125+
style = script;
126+
} else if (style === 'stylus') {
127+
style = 'styl';
128+
}
115129

116-
this.ext = {
117-
component: this.typescript ? 'tsx' : `j${this.jsxExt ? 'sx' : 's'}`,
118-
script: `${this.typescript ? 't' : 'j'}s`,
119-
style: styleExt === 'stylus' ? 'styl' : styleExt,
120-
};
130+
this.ext = { component, script, style };
121131
}
122132

123133
private setPrefixes() {

src/constants/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export const STYLE_FORMATS: StyleFormats[] = [
2323
'sass',
2424
'less',
2525
'stylus',
26+
'styled-components',
2627
];
2728

2829
export const EXPORT_TYPES: ExportType[] = ['named', 'default'];

src/core/FileGenerateManager.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { config } from '@/config';
22
import { IComponentVariables, IHOCVariables, IHookVariables } from '@/types';
33
import { BarrelTemplate } from '@/core/temlpates/components/BarrelTemplate';
4+
import { StyledComponentsTemplate } from '@/core/temlpates/components/StyledComponentsTemplate';
45
import * as utils from '../utils';
56
import { FileService } from './FileService';
67
import { TemplateGenerator } from './TemplateGenerator';
@@ -57,7 +58,15 @@ export class FileGenerateManager {
5758
fileService.genBarrel(barrelTemplate);
5859
}
5960

60-
const styleTemplate = config.cssModules ? '.root {}' : '';
61+
let styleTemplate = '';
62+
if (config.styles === 'styled-components') {
63+
styleTemplate = templateGenerator.generateTemplate(
64+
StyledComponentsTemplate
65+
);
66+
} else if (config.cssModules) {
67+
styleTemplate = '.root {}';
68+
}
69+
6170
fileService.genStyle(styleTemplate);
6271
}
6372
}

src/core/temlpates/components/ComponentTemplate.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@ export class ComponentTemplate
1414

1515
private getStyleImport() {
1616
const specifiers = [];
17-
const name = `./${this.vars.fileName}.${config.prefixes.style}.${config.ext.style}`;
17+
const isStyled = config.styles === 'styled-components';
18+
const ext = isStyled ? '' : `.${config.ext.style}`;
19+
const name = `./${this.vars.fileName}.${config.prefixes.style}${ext}`;
1820

19-
if (config.cssModules) {
21+
if (isStyled) {
22+
specifiers.push(t.importDefaultSpecifier(t.identifier('Styled')));
23+
} else if (config.cssModules) {
2024
specifiers.push(t.importDefaultSpecifier(t.identifier('styles')));
2125
}
2226

@@ -25,6 +29,19 @@ export class ComponentTemplate
2529

2630
// eslint-disable-next-line class-methods-use-this
2731
private getJsxElement() {
32+
if (config.styles === 'styled-components') {
33+
const memberExpresion = t.jsxMemberExpression(
34+
t.jsxIdentifier('Styled'),
35+
t.jsxIdentifier('Root')
36+
);
37+
38+
return t.jsxElement(
39+
t.jsxOpeningElement(memberExpresion, [], false),
40+
t.jsxClosingElement(memberExpresion),
41+
[]
42+
);
43+
}
44+
2845
const attributes = [];
2946

3047
if (config.cssModules) {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import * as t from '@babel/types';
2+
import { TemplateBase } from '@/core/TemplateBase';
3+
import { Template } from '@/core/TemplateGenerator';
4+
import * as c from '../shared';
5+
6+
export class StyledComponentsTemplate extends TemplateBase implements Template {
7+
// eslint-disable-next-line class-methods-use-this
8+
generateAST(): t.File {
9+
const body: t.Statement[] = [];
10+
11+
body.push(
12+
t.importDeclaration(
13+
[t.importDefaultSpecifier(t.identifier('styled'))],
14+
t.stringLiteral('styled-components')
15+
)
16+
);
17+
18+
body.push(t.emptyStatement());
19+
20+
body.push(
21+
t.exportDefaultDeclaration(
22+
t.objectExpression([
23+
t.objectProperty(
24+
t.identifier('Root'),
25+
t.taggedTemplateExpression(
26+
t.memberExpression(
27+
t.identifier('styled'),
28+
t.identifier('div'),
29+
false
30+
),
31+
t.templateLiteral(
32+
[t.templateElement({ raw: '', cooked: '' }, true)],
33+
[]
34+
)
35+
),
36+
false,
37+
false
38+
),
39+
])
40+
)
41+
);
42+
43+
return c.program(body);
44+
}
45+
}

src/init/questions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export const question = [
1919
type: 'confirm',
2020
name: 'cssModules',
2121
message: 'Use css modules?',
22+
when: values => values.styles !== 'styled-components',
2223
},
2324
{
2425
type: 'confirm',

src/tests/e2e/Component.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,28 @@ describe('Component', () => {
120120

121121
await runGenerator({}, { answers, type });
122122
});
123+
124+
it('should create component: js/styled-components/barrel', async () => {
125+
config.update({
126+
styles: 'styled-components',
127+
jsxExt: false,
128+
});
129+
130+
answers.name = 'js/styled-components/barrel';
131+
answers.barrel = true;
132+
133+
await runGenerator({}, { answers, type });
134+
});
135+
136+
it('should create component: ts/styled-components/barrel', async () => {
137+
config.update({
138+
styles: 'styled-components',
139+
typescript: true,
140+
});
141+
142+
answers.name = 'ts/styled-components/barrel';
143+
answers.barrel = true;
144+
145+
await runGenerator({}, { answers, type });
146+
});
123147
});

src/tests/unit/core/FileService.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ describe('FileService', () => {
109109
it('should create barrel file', () => {
110110
fileServiceMock
111111
.expects('genFile')
112-
.withExactArgs(`${dir}/index.${config.ext.component}`, '', 'barrel');
112+
.withExactArgs(`${dir}/index.${config.ext.script}`, '', 'barrel');
113113
fileService.genBarrel('');
114114

115115
fileServiceMock.verify();

src/types/types.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import { reactHooks } from '@/questions/questionTypes';
22

3-
export type StyleFormats = 'css' | 'scss' | 'sass' | 'less' | 'stylus';
3+
export type StyleFormats =
4+
| 'css'
5+
| 'scss'
6+
| 'sass'
7+
| 'less'
8+
| 'stylus'
9+
| 'styled-components';
410
export type FileNameCase =
511
| 'pascal'
612
| 'camel'

0 commit comments

Comments
 (0)