Skip to content

Commit 55041ec

Browse files
fix: refactor file naming error handling
1 parent 33df8a0 commit 55041ec

File tree

3 files changed

+45
-49
lines changed

3 files changed

+45
-49
lines changed

rtl-spec/components/sidebar-file-tree.spec.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ describe('SidebarFileTree component', () => {
9696
) as HTMLInputElement;
9797
await user.type(input, 'tester.js{Enter}');
9898

99-
expect(editorMosaic.files.get('tester.js')).toBe(EditorPresence.Pending);
99+
expect(editorMosaic.files.get('tester.js')).toBe(EditorPresence.Hidden);
100100
});
101101

102-
it('fails to create new editors (file name inside subdir)', async () => {
102+
it('fails to create new editors (file name with path separator)', async () => {
103103
const user = userEvent.setup();
104104
const { container } = render(<SidebarFileTree appState={store} />);
105105
const EDITOR_NEW_NAME = 'subdir/tester.js';
@@ -122,7 +122,7 @@ describe('SidebarFileTree component', () => {
122122
await waitFor(() => {
123123
console.log('store.showErrorDialog: ', store.showErrorDialog);
124124
expect(store.showErrorDialog).toHaveBeenCalledWith(
125-
`Invalid filename "${EDITOR_NEW_NAME}": inside subdir not supported yet`,
125+
`Invalid filename "${EDITOR_NEW_NAME}": filenames cannot include path separators`,
126126
);
127127
});
128128
});
@@ -265,7 +265,7 @@ describe('SidebarFileTree component', () => {
265265
expect(editorMosaic.files.get(EDITOR_NAME)).toBe(EditorPresence.Pending);
266266
});
267267

268-
it('fails if trying to rename an editor to an unsupported name (file inside subdir)', async () => {
268+
it('fails if trying to rename an editor to an unsupported name (file name with path separator)', async () => {
269269
const user = userEvent.setup();
270270
const EDITOR_NAME = 'index.html';
271271
const EDITOR_NEW_NAME = 'msg/data.json';
@@ -288,7 +288,7 @@ describe('SidebarFileTree component', () => {
288288
// Wait for error dialog to be called
289289
await waitFor(() => {
290290
expect(store.showErrorDialog).toHaveBeenCalledWith(
291-
`Invalid filename "${EDITOR_NEW_NAME}": inside subdir not supported yet`,
291+
`Invalid filename "${EDITOR_NEW_NAME}": filenames cannot include path separators`,
292292
);
293293
});
294294

src/renderer/components/sidebar-file-tree.tsx

Lines changed: 7 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ import { ContextMenu2, Tooltip2 } from '@blueprintjs/popover2';
1414
import classNames from 'classnames';
1515
import { observer } from 'mobx-react';
1616

17-
import { EditorId, PACKAGE_NAME } from '../../interfaces';
17+
import { EditorId } from '../../interfaces';
1818
import { EditorPresence } from '../editor-mosaic';
1919
import { AppState } from '../state';
20-
import { isMainEntryPoint, isSupportedFile } from '../utils/editor-utils';
20+
import { isMainEntryPoint } from '../utils/editor-utils';
2121

2222
interface FileTreeProps {
2323
appState: AppState;
@@ -41,7 +41,7 @@ export const SidebarFileTree = observer(
4141
}
4242

4343
public render() {
44-
const { editorMosaic, showErrorDialog } = this.props.appState;
44+
const { editorMosaic } = this.props.appState;
4545
const { files, focusedFile } = editorMosaic;
4646

4747
const fileList: TreeNodeInfo[] = Array.from(files)
@@ -112,19 +112,6 @@ export const SidebarFileTree = observer(
112112
if (e.key === 'Escape') {
113113
e.currentTarget.blur();
114114
} else if (e.key === 'Enter') {
115-
const filename = e.currentTarget.value.trim();
116-
if (filename.includes('/') || filename.includes('\\')) {
117-
await showErrorDialog(
118-
`Invalid filename "${filename}": inside subdir not supported yet`,
119-
);
120-
return;
121-
}
122-
if (!isSupportedFile(filename)) {
123-
await showErrorDialog(
124-
`Invalid filename "${filename}": Must be a file ending in .cjs, .js, .mjs, .html, .css, or .json`,
125-
);
126-
return;
127-
}
128115
this.createEditor(e.currentTarget.value as EditorId);
129116
e.currentTarget.blur();
130117
}
@@ -202,30 +189,6 @@ export const SidebarFileTree = observer(
202189

203190
if (!id) return;
204191

205-
if (id.includes('/') || id.includes('\\')) {
206-
await appState.showErrorDialog(
207-
`Invalid filename "${id}": inside subdir not supported yet`,
208-
);
209-
return;
210-
}
211-
212-
if (
213-
id.endsWith('.json') &&
214-
[PACKAGE_NAME, 'package-lock.json'].includes(id)
215-
) {
216-
await appState.showErrorDialog(
217-
`Cannot add ${PACKAGE_NAME} or package-lock.json as custom files`,
218-
);
219-
return;
220-
}
221-
222-
if (!isSupportedFile(id)) {
223-
await appState.showErrorDialog(
224-
`Invalid filename "${id}": Must be a file ending in .cjs, .js, .mjs, .html, .css, or .json`,
225-
);
226-
return;
227-
}
228-
229192
try {
230193
await appState.editorMosaic.renameFile(editorId, id);
231194

@@ -240,13 +203,13 @@ export const SidebarFileTree = observer(
240203
editorMosaic.remove(editorId);
241204
};
242205

243-
public createEditor = (editorId: EditorId) => {
206+
public createEditor = async (editorId: EditorId) => {
244207
const { appState } = this.props;
245208
try {
246-
appState.editorMosaic.addNewFile(editorId);
247-
appState.editorMosaic.show(editorId);
209+
await appState.editorMosaic.addNewFile(editorId);
210+
await appState.editorMosaic.show(editorId);
248211
} catch (err: any) {
249-
appState.showErrorDialog(err.message);
212+
await appState.showErrorDialog(err.message);
250213
}
251214
};
252215

src/renderer/editor-mosaic.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,18 @@ export class EditorMosaic {
287287
throw new Error(`Cannot add file "${id}": File already exists`);
288288
}
289289

290+
if (id.includes('/') || id.includes('\\')) {
291+
throw new Error(
292+
`Invalid filename "${id}": filenames cannot include path separators`,
293+
);
294+
}
295+
296+
if (!isSupportedFile(id)) {
297+
throw new Error(
298+
`Invalid filename "${id}": Must be a file ending in .cjs, .js, .mjs, .html, .css, or .json`,
299+
);
300+
}
301+
290302
const entryPoint = this.mainEntryPointFile();
291303

292304
if (isMainEntryPoint(id) && entryPoint) {
@@ -308,6 +320,27 @@ export class EditorMosaic {
308320
throw new Error(`Cannot rename file to "${newId}": File already exists`);
309321
}
310322

323+
if (newId.includes('/') || newId.includes('\\')) {
324+
throw new Error(
325+
`Invalid filename "${newId}": filenames cannot include path separators`,
326+
);
327+
}
328+
329+
if (
330+
newId.endsWith('.json') &&
331+
[PACKAGE_NAME, 'package-lock.json'].includes(newId)
332+
) {
333+
throw new Error(
334+
`Cannot add ${PACKAGE_NAME} or package-lock.json as custom files`,
335+
);
336+
}
337+
338+
if (!isSupportedFile(newId)) {
339+
throw new Error(
340+
`Invalid filename "${newId}": Must be a file ending in .cjs, .js, .mjs, .html, .css, or .json`,
341+
);
342+
}
343+
311344
const entryPoint = this.mainEntryPointFile();
312345

313346
if (isMainEntryPoint(newId) && entryPoint !== oldId) {

0 commit comments

Comments
 (0)