Skip to content

Commit 6c19189

Browse files
committed
feat: support directory names for index components
1 parent b243830 commit 6c19189

11 files changed

Lines changed: 160 additions & 53 deletions

File tree

‎README.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,16 @@ Controls whether Props and State declarations use type aliases or interfaces in
111111

112112
Controls whether TypeScript component snippets name their props type `Props` or derive it from the component name, for example `ButtonProps`.
113113

114+
### `componentNameSource`
115+
116+
**Type:** `string`
117+
118+
**Default:** `filename`
119+
120+
**Allowed values:** `filename`, `directoryForIndex`
121+
122+
Controls how component snippets derive their name. `directoryForIndex` uses the parent directory for an `index.*` file, so `Button/index.tsx` becomes `Button`; other filenames still use their basename.
123+
114124
### `componentWrapper`
115125

116126
**Type:** `string`

‎docs/Snippets.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Snippet bodies preserve the spacing shown below; spaces inside braces and parent
77

88
_TypeScript_ has own components and own snippets. Use search or just type `ts` before every component snippet.
99

10+
Component snippets use the current filename by default. Set `componentNameSource` to `directoryForIndex` to use the parent directory for `index.*` files.
11+
1012
I.E. `tsrcc`
1113

1214
<br>

‎package.json‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@
132132
],
133133
"scope": "application"
134134
},
135+
"reactSnippets.settings.componentNameSource": {
136+
"type": "string",
137+
"markdownDescription": "Controls whether component snippets use the filename or use the parent directory name for `index.*` files.",
138+
"default": "filename",
139+
"enum": [
140+
"filename",
141+
"directoryForIndex"
142+
],
143+
"scope": "application"
144+
},
135145
"reactSnippets.settings.componentWrapper": {
136146
"type": "string",
137147
"markdownDescription": "Controls whether component snippets wrap their content in a React fragment or a `div`.",

‎src/helpers/extensionConfig.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { workspace } from 'vscode';
22

33
import {
4+
ComponentNameSource,
45
ComponentWrapper,
56
DEFAULT_GENERATION_SETTINGS,
67
GenerationSettings,
@@ -33,6 +34,10 @@ const extensionConfig = (): ExtensionSettings => {
3334
'typescriptPropsNaming',
3435
DEFAULT_GENERATION_SETTINGS.typescriptPropsNaming,
3536
),
37+
componentNameSource: config.get<ComponentNameSource>(
38+
'componentNameSource',
39+
DEFAULT_GENERATION_SETTINGS.componentNameSource,
40+
),
3641
componentWrapper: config.get<ComponentWrapper>(
3742
'componentWrapper',
3843
DEFAULT_GENERATION_SETTINGS.componentWrapper,

‎src/helpers/snippetPlaceholders.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,25 @@ const propsPlaceholders = {
1111
},
1212
} as const;
1313

14+
const componentNamePlaceholders = {
15+
filename: Mappings.FileName,
16+
directoryForIndex: Mappings.DirectoryNameForIndex,
17+
} as const;
18+
1419
export const replaceSnippetPlaceholders = (
1520
snippetString: string,
1621
settings: GenerationSettings,
1722
): string => {
1823
const {
24+
componentNameSource,
1925
componentWrapper,
2026
typescriptPropsNaming,
2127
typescriptPropsStatePrefix,
2228
} = settings;
2329
const propsPlaceholder =
2430
propsPlaceholders[typescriptPropsNaming][typescriptPropsStatePrefix];
31+
const componentNamePlaceholder =
32+
componentNamePlaceholders[componentNameSource];
2533
const propsName =
2634
typescriptPropsNaming === 'component'
2735
? Mappings.ComponentProps
@@ -39,6 +47,7 @@ export const replaceSnippetPlaceholders = (
3947
.replaceAll(Placeholders.TypeProps, propsPlaceholder)
4048
.replaceAll(Placeholders.TypeState, statePlaceholder)
4149
.replaceAll(Placeholders.ComponentProps, propsName)
50+
.replaceAll(Placeholders.ComponentName, componentNamePlaceholder)
4251
.replaceAll(Placeholders.FileName, Mappings.FileName)
4352
.replaceAll(Placeholders.ComponentWrapper, componentWrapperPlaceholder)
4453
.replaceAll(Placeholders.FirstTab, Mappings.FirstTab)

‎src/sourceSnippets/components.ts‎

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const reactClassComponent: ComponentsSnippet = {
4444
body: [
4545
...reactComponent,
4646
'',
47-
`export default class ${Placeholders.FileName} extends Component {`,
47+
`export default class ${Placeholders.ComponentName} extends Component {`,
4848
...innerComponentReturn,
4949
'}',
5050
'',
@@ -58,7 +58,7 @@ const reactClassExportComponent: ComponentsSnippet = {
5858
body: [
5959
...reactComponent,
6060
'',
61-
`export class ${Placeholders.FileName} extends Component {`,
61+
`export class ${Placeholders.ComponentName} extends Component {`,
6262
...innerComponentReturn,
6363
'}',
6464
...exportDefault,
@@ -72,7 +72,7 @@ const reactFunctionalExportComponent: ComponentsSnippet = {
7272
body: [
7373
...react,
7474
'',
75-
`function ${Placeholders.FileName}() {`,
75+
`function ${Placeholders.ComponentName}() {`,
7676
...innerComponent,
7777
'}',
7878
...exportDefault,
@@ -86,7 +86,7 @@ const reactFunctionalComponent: ComponentsSnippet = {
8686
body: [
8787
...react,
8888
'',
89-
`export default function ${Placeholders.FileName}() {`,
89+
`export default function ${Placeholders.ComponentName}() {`,
9090
...innerComponent,
9191
'}',
9292
'',
@@ -100,11 +100,11 @@ const reactFunctionalComponentWithPropTypes: ComponentsSnippet = {
100100
body: [
101101
...reactPropTypes,
102102
'',
103-
`function ${Placeholders.FileName}(props) {`,
103+
`function ${Placeholders.ComponentName}(props) {`,
104104
...innerComponent,
105105
'}',
106106
'',
107-
`${Placeholders.FileName}.propTypes = {}`,
107+
`${Placeholders.ComponentName}.propTypes = {}`,
108108
...exportDefault,
109109
'',
110110
],
@@ -118,7 +118,7 @@ const reactArrowFunctionExportComponent: ComponentsSnippet = {
118118
body: [
119119
...react,
120120
'',
121-
`const ${Placeholders.FileName} = () => {`,
121+
`const ${Placeholders.ComponentName} = () => {`,
122122
...innerComponent,
123123
'}',
124124
...exportDefault,
@@ -133,7 +133,7 @@ const reactArrowFunctionComponent: ComponentsSnippet = {
133133
body: [
134134
...react,
135135
'',
136-
`export const ${Placeholders.FileName} = () => {`,
136+
`export const ${Placeholders.ComponentName} = () => {`,
137137
...innerComponent,
138138
'}',
139139
'',
@@ -148,11 +148,11 @@ const reactArrowFunctionComponentWithPropTypes: ComponentsSnippet = {
148148
body: [
149149
...reactPropTypes,
150150
'',
151-
`const ${Placeholders.FileName} = props => {`,
151+
`const ${Placeholders.ComponentName} = props => {`,
152152
...innerComponent,
153153
'}',
154154
'',
155-
`${Placeholders.FileName}.propTypes = {}`,
155+
`${Placeholders.ComponentName}.propTypes = {}`,
156156
...exportDefault,
157157
],
158158
description:
@@ -166,7 +166,7 @@ const reactClassExportComponentWithPropTypes: ComponentsSnippet = {
166166
"import PropTypes from 'prop-types'",
167167
...reactComponent,
168168
'',
169-
`export class ${Placeholders.FileName} extends Component {`,
169+
`export class ${Placeholders.ComponentName} extends Component {`,
170170
' static propTypes = {}',
171171
'',
172172
...innerComponentReturn,
@@ -182,7 +182,7 @@ const reactClassPureComponent: ComponentsSnippet = {
182182
body: [
183183
...reactPureComponent,
184184
'',
185-
`export default class ${Placeholders.FileName} extends PureComponent {`,
185+
`export default class ${Placeholders.ComponentName} extends PureComponent {`,
186186
...innerComponentReturn,
187187
'}',
188188
'',
@@ -196,7 +196,7 @@ const reactClassExportPureComponent: ComponentsSnippet = {
196196
body: [
197197
...reactPureComponent,
198198
'',
199-
`export class ${Placeholders.FileName} extends PureComponent {`,
199+
`export class ${Placeholders.ComponentName} extends PureComponent {`,
200200
...innerComponentReturn,
201201
'}',
202202
...exportDefault,
@@ -212,7 +212,7 @@ const reactClassPureComponentWithPropTypes: ComponentsSnippet = {
212212
"import PropTypes from 'prop-types'",
213213
...reactPureComponent,
214214
'',
215-
`export default class ${Placeholders.FileName} extends PureComponent {`,
215+
`export default class ${Placeholders.ComponentName} extends PureComponent {`,
216216
' static propTypes = {}',
217217
'',
218218
...innerComponentReturn,
@@ -228,7 +228,7 @@ const reactFunctionMemoComponent: ComponentsSnippet = {
228228
body: [
229229
...reactWithMemo,
230230
'',
231-
`const ${Placeholders.FileName} = memo(() => {`,
231+
`const ${Placeholders.ComponentName} = memo(() => {`,
232232
...innerComponent,
233233
'})',
234234
...exportDefault,
@@ -243,11 +243,11 @@ const reactFunctionMemoComponentWithPropTypes: ComponentsSnippet = {
243243
"import PropTypes from 'prop-types'",
244244
...reactWithMemo,
245245
'',
246-
`const ${Placeholders.FileName} = memo((props) => {`,
246+
`const ${Placeholders.ComponentName} = memo((props) => {`,
247247
...innerComponent,
248248
'})',
249249
'',
250-
`${Placeholders.FileName}.propTypes = {}`,
250+
`${Placeholders.ComponentName}.propTypes = {}`,
251251
...exportDefault,
252252
],
253253
description:
@@ -261,7 +261,7 @@ const reactClassComponentPropTypes: ComponentsSnippet = {
261261
"import PropTypes from 'prop-types'",
262262
...reactComponent,
263263
'',
264-
`export default class ${Placeholders.FileName} extends Component {`,
264+
`export default class ${Placeholders.ComponentName} extends Component {`,
265265
` static propTypes = {${Placeholders.SecondTab}: ${Placeholders.ThirdTab}}`,
266266
'',
267267
...innerComponentReturn,
@@ -278,7 +278,7 @@ const reactClassComponentRedux: ComponentsSnippet = {
278278
body: [
279279
...reactComponentWithReduxConnect,
280280
'',
281-
`export class ${Placeholders.FileName} extends Component {`,
281+
`export class ${Placeholders.ComponentName} extends Component {`,
282282
...innerComponentReturn,
283283
'}',
284284
...reduxComponentExport,
@@ -294,7 +294,7 @@ const reactClassComponentReduxPropTypes: ComponentsSnippet = {
294294
"import PropTypes from 'prop-types'",
295295
...reactComponentWithReduxConnect,
296296
'',
297-
`export class ${Placeholders.FileName} extends Component {`,
297+
`export class ${Placeholders.ComponentName} extends Component {`,
298298
' static propTypes = {',
299299
` ${Placeholders.SecondTab}: ${Placeholders.ThirdTab}`,
300300
' }',
@@ -313,7 +313,7 @@ const reactFunctionalComponentRedux: ComponentsSnippet = {
313313
body: [
314314
...reactWithReduxConnect,
315315
'',
316-
`export const ${Placeholders.FileName} = (props) => {`,
316+
`export const ${Placeholders.ComponentName} = (props) => {`,
317317
...innerComponent,
318318
'}',
319319
...reduxComponentExport,
@@ -329,11 +329,11 @@ const reactFunctionalComponentReduxPropTypes: ComponentsSnippet = {
329329
"import PropTypes from 'prop-types'",
330330
...reactWithReduxConnect,
331331
'',
332-
`export const ${Placeholders.FileName} = (props) => {`,
332+
`export const ${Placeholders.ComponentName} = (props) => {`,
333333
...innerComponent,
334334
'}',
335335
'',
336-
`${Placeholders.FileName}.propTypes = {`,
336+
`${Placeholders.ComponentName}.propTypes = {`,
337337
` ${Placeholders.SecondTab}: PropTypes.${Placeholders.ThirdTab}`,
338338
'}',
339339
...reduxComponentExport,

‎src/sourceSnippets/reactNative.ts‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const reactNativeComponent: ReactNativeSnippet = {
6262
"import { Text, View } from 'react-native'",
6363
...reactComponent,
6464
'',
65-
`export default class ${Placeholders.FileName} extends Component {`,
65+
`export default class ${Placeholders.ComponentName} extends Component {`,
6666
...reactNativeComponentReturn,
6767
'}',
6868
],
@@ -75,7 +75,7 @@ const reactNativeComponentWithStyles: ReactNativeSnippet = {
7575
"import { Text, StyleSheet, View } from 'react-native'",
7676
...reactComponent,
7777
'',
78-
`export default class ${Placeholders.FileName} extends Component {`,
78+
`export default class ${Placeholders.ComponentName} extends Component {`,
7979
...reactNativeComponentReturn,
8080
'}',
8181
'',
@@ -90,7 +90,7 @@ const reactNativeComponentExport: ReactNativeSnippet = {
9090
"import { Text, View } from 'react-native'",
9191
...reactComponent,
9292
'',
93-
`export class ${Placeholders.FileName} extends Component {`,
93+
`export class ${Placeholders.ComponentName} extends Component {`,
9494
...reactNativeComponentReturn,
9595
'}',
9696
...exportDefault,
@@ -104,7 +104,7 @@ const reactNativePureComponent: ReactNativeSnippet = {
104104
"import { Text, View } from 'react-native'",
105105
...reactPureComponent,
106106
'',
107-
`export default class ${Placeholders.FileName} extends PureComponent {`,
107+
`export default class ${Placeholders.ComponentName} extends PureComponent {`,
108108
...reactNativeComponentReturn,
109109
'}',
110110
],
@@ -117,7 +117,7 @@ const reactNativePureComponentExport: ReactNativeSnippet = {
117117
"import { Text, View } from 'react-native'",
118118
...reactPureComponent,
119119
'',
120-
`export class ${Placeholders.FileName} extends PureComponent {`,
120+
`export class ${Placeholders.ComponentName} extends PureComponent {`,
121121
...reactNativeComponentReturn,
122122
'}',
123123
...exportDefault,
@@ -131,7 +131,7 @@ const reactNativeFunctionalExportComponent: ReactNativeSnippet = {
131131
"import { View, Text } from 'react-native'",
132132
...react,
133133
'',
134-
`const ${Placeholders.FileName} = () => {`,
134+
`const ${Placeholders.ComponentName} = () => {`,
135135
...reactNativeReturn,
136136
'}',
137137
...exportDefault,
@@ -145,7 +145,7 @@ const reactNativeFunctionalExportComponentWithStyles: ReactNativeSnippet = {
145145
"import { StyleSheet, Text, View } from 'react-native'",
146146
...react,
147147
'',
148-
`const ${Placeholders.FileName} = () => {`,
148+
`const ${Placeholders.ComponentName} = () => {`,
149149
...reactNativeReturn,
150150
'}',
151151
...exportDefault,
@@ -161,7 +161,7 @@ const reactNativeFunctionalComponent: ReactNativeSnippet = {
161161
"import { View, Text } from 'react-native'",
162162
...react,
163163
'',
164-
`export default function ${Placeholders.FileName}() {`,
164+
`export default function ${Placeholders.ComponentName}() {`,
165165
...reactNativeReturn,
166166
'}',
167167
],
@@ -174,7 +174,7 @@ const reactNativeFunctionalComponentWithStyles: ReactNativeSnippet = {
174174
"import { StyleSheet, Text, View } from 'react-native'",
175175
...react,
176176
'',
177-
`export default function ${Placeholders.FileName}() {`,
177+
`export default function ${Placeholders.ComponentName}() {`,
178178
...reactNativeReturn,
179179
'}',
180180
'',
@@ -189,7 +189,7 @@ const reactNativeExtendedFunctional: ReactNativeSnippet = {
189189
"import React, { useState, useEffect } from 'react'",
190190
"import { View, SafeAreaView, Text, StyleSheet } from 'react-native'",
191191
'',
192-
`const ${Placeholders.FileName} = ({ \${2:props} }) => {`,
192+
`const ${Placeholders.ComponentName} = ({ \${2:props} }) => {`,
193193
' const [${3:state}, ${4:setState}] = useState(${5:initialState})',
194194
'',
195195
' useEffect(() => {',
@@ -213,7 +213,7 @@ const reactNativeExtendedFunctional: ReactNativeSnippet = {
213213
' },',
214214
'})',
215215
'',
216-
`export default ${Placeholders.FileName}`,
216+
`export default ${Placeholders.ComponentName}`,
217217
],
218218
description:
219219
'React Native functional component with useState, useEffect, SafeAreaView and basic styling',

0 commit comments

Comments
 (0)