Skip to content

Commit 30dba60

Browse files
Add support for uploading/downloading WEBP images (#242)
* Add support for uploading/downloading WEBP images * Add test file * Add test entries * Update Playwright Snapshots
1 parent 490516f commit 30dba60

File tree

5 files changed

+28
-9
lines changed

5 files changed

+28
-9
lines changed

src/pages/files.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ import { LabIcon, closeIcon, downloadIcon } from '@jupyterlab/ui-components';
1313

1414
/**
1515
* File type icons mapping function. We currently implement four common file types:
16-
* 1. Image files (PNG, JPEG/JPG) (binary)
16+
* 1. Image files (PNG, JPEG/JPG, WEBP) (binary)
1717
* 2. CSV/TSV files (text)
1818
* @param fileName - the name of the file to determine the icon for.
1919
* @param fileType - the MIME type of the file to determine the icon for.
2020
* @returns A LabIcon representing the file type icon.
2121
*/
2222
const getFileIcon = (fileName: string, fileType: string): LabIcon => {
2323
const extension = fileName.split('.').pop()?.toLowerCase() || '';
24-
if (fileType.startsWith('image/') || ['png', 'jpg', 'jpeg'].includes(extension)) {
24+
if (fileType.startsWith('image/') || ['png', 'jpg', 'jpeg', 'webp'].includes(extension)) {
2525
return EverywhereIcons.imageIcon;
2626
}
2727
if (
@@ -36,14 +36,20 @@ const getFileIcon = (fileName: string, fileType: string): LabIcon => {
3636
};
3737

3838
/**
39-
* Checks if the file type is supported (PNG, JPG/JPEG, or CSV/TSV).
39+
* Checks if the file type is supported (PNG, JPG/JPEG, WEBP, or CSV/TSV).
4040
* @param file - The file to check
4141
* @returns True if the file type is supported, false otherwise.
4242
*/
4343
const isSupportedFileType = (file: File): boolean => {
44-
const supportedMimeTypes = ['image/png', 'image/jpeg', 'text/csv', 'text/tab-separated-values'];
44+
const supportedMimeTypes = [
45+
'image/png',
46+
'image/jpeg',
47+
'image/webp',
48+
'text/csv',
49+
'text/tab-separated-values'
50+
];
4551
const extension = file.name.split('.').pop()?.toLowerCase() || '';
46-
const supportedExtensions = ['png', 'jpg', 'jpeg', 'csv', 'tsv'];
52+
const supportedExtensions = ['png', 'jpg', 'jpeg', 'webp', 'csv', 'tsv'];
4753
return supportedMimeTypes.includes(file.type) || supportedExtensions.includes(extension);
4854
};
4955

@@ -77,7 +83,7 @@ const FileUploader = React.forwardRef<IFileUploaderRef, IFileUploaderProps>((pro
7783
if (supportedFiles.length === 0) {
7884
await showErrorMessage(
7985
'Unsupported file type',
80-
'Please upload only PNG, JPG/JPEG, or CSV/TSV files.'
86+
'Please upload only PNG, JPG/JPEG, WEBP, or CSV/TSV files.'
8187
);
8288
return;
8389
}
@@ -137,7 +143,7 @@ const FileUploader = React.forwardRef<IFileUploaderRef, IFileUploaderProps>((pro
137143
multiple
138144
onChange={handleInputChange}
139145
style={{ display: 'none' }}
140-
accept=".png,.jpg,.jpeg,.csv,.tsv,image/png,image/jpeg,text/csv,text/tab-separated-values"
146+
accept=".png,.jpg,.jpeg,.webp,.csv,.tsv,image/png,image/jpeg,image/webp,text/csv,text/tab-separated-values"
141147
/>
142148
);
143149
});
@@ -247,6 +253,9 @@ function FilesApp(props: IFilesAppProps) {
247253
if (ext === 'jpg' || ext === 'jpeg') {
248254
return 'image/jpeg';
249255
}
256+
if (ext === 'webp') {
257+
return 'image/webp';
258+
}
250259
if (ext === 'csv') {
251260
return 'text/csv';
252261
}

src/types/images.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@ declare module '*.jpg' {
1212
const value: string;
1313
export default value;
1414
}
15+
16+
declare module '*.webp' {
17+
const value: string;
18+
export default value;
19+
}

ui-tests/test-files/c-flower.webp

32.3 KB
Loading

ui-tests/tests/jupytereverywhere.spec.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,15 +354,16 @@ test.describe('Files', () => {
354354
await expect(page).toHaveURL(/\/lab\/files\/$/);
355355
});
356356

357-
test('Should upload two files and display their thumbnails', async ({ page }) => {
357+
test('Should upload three files and display their thumbnails', async ({ page }) => {
358358
await page.locator('.jp-SideBar').getByTitle('Files').click();
359359

360360
await page.locator('.je-FileTile').first().click(); // the first tile will always be the "add new" one
361361

362362
const jpgPath = path.resolve(__dirname, '../test-files/a-image.jpg');
363363
const csvPath = path.resolve(__dirname, '../test-files/b-dataset.csv');
364+
const webpPath = path.resolve(__dirname, '../test-files/c-flower.webp');
364365

365-
await page.setInputFiles('input[type="file"]', [jpgPath, csvPath]);
366+
await page.setInputFiles('input[type="file"]', [jpgPath, csvPath, webpPath]);
366367

367368
// Wait some time for thumbnails to appear as the files
368369
// are being uploaded to the contents manager
@@ -372,13 +373,17 @@ test.describe('Files', () => {
372373
await page
373374
.locator('.je-FileTile-label', { hasText: 'b-dataset.csv' })
374375
.waitFor({ state: 'visible' });
376+
await page
377+
.locator('.je-FileTile-label', { hasText: 'c-flower.webp' })
378+
.waitFor({ state: 'visible' });
375379

376380
expect(await page.locator('.je-FilesApp-grid').screenshot()).toMatchSnapshot(
377381
'uploaded-files-grid.png'
378382
);
379383

380384
await expect(page.locator('.je-FileTile-label', { hasText: 'a-image.jpg' })).toBeVisible();
381385
await expect(page.locator('.je-FileTile-label', { hasText: 'b-dataset.csv' })).toBeVisible();
386+
await expect(page.locator('.je-FileTile-label', { hasText: 'c-flower.webp' })).toBeVisible();
382387
});
383388

384389
test('Hovering a file tile shows close and download actions', async ({ page }) => {
1.03 KB
Loading

0 commit comments

Comments
 (0)