Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/file-selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ function toFilePromises(item: DataTransferItem) {
return fromDirEntry(entry) as any;
}

return fromDataTransferItem(item);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be a breaking change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rolandjitsu I changed this to still call fromDataTransferItem while still getting the functionality I need.

return fromFileEntry(entry);
}

function flatten<T>(items: any[]): T[] {
Expand Down
45 changes: 45 additions & 0 deletions src/file.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,51 @@ describe('toFile()', () => {
expect(fileWithPath.path).toBe(path);
});

it('sets the {relativePath} if provided without overwriting {path}', () => {
const fullPath = '/Users/test/Desktop/test/test.json';
const path = '/test/test.json';
const file = new File([], 'test.json');

// @ts-expect-error
file.path = fullPath;
const fileWithPath = toFileWithPath(file, path);
expect(fileWithPath.path).toBe(fullPath);
expect(fileWithPath.relativePath).toBe(path);
});

test('{relativePath} is enumerable', () => {
const path = '/test/test.json';
const file = new File([], 'test.json');
const fileWithPath = toFileWithPath(file, path);

expect(Object.keys(fileWithPath)).toContain('relativePath');

const keys = [];
for (const key in fileWithPath) {
keys.push(key);
}

expect(keys).toContain('relativePath');
});

it('uses the File {webkitRelativePath} as {relativePath} if it exists', () => {
const name = 'test.json';
const path = 'test/test.json';
const file = new File([], name);
Object.defineProperty(file, 'webkitRelativePath', {
value: path
});
const fileWithPath = toFileWithPath(file);
expect(fileWithPath.relativePath).toBe(path);
});

it('uses the File {name} as {relativePath} if not provided and prefix with forward slash (/)', () => {
const name = 'test.json';
const file = new File([], name);
const fileWithPath = toFileWithPath(file);
expect(fileWithPath.relativePath).toBe('/' + name);
});

it('sets the {type} from extension', () => {
const types = Array.from(COMMON_MIME_TYPES.values());
const files = Array.from(COMMON_MIME_TYPES.keys())
Expand Down
18 changes: 17 additions & 1 deletion src/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ export const COMMON_MIME_TYPES = new Map([

export function toFileWithPath(file: FileWithPath, path?: string): FileWithPath {
const f = withMimeType(file);
const {webkitRelativePath} = file;
if (typeof f.path !== 'string') { // on electron, path is already set to the absolute path
const {webkitRelativePath} = file;
Object.defineProperty(f, 'path', {
value: typeof path === 'string'
? path
Expand All @@ -104,11 +104,27 @@ export function toFileWithPath(file: FileWithPath, path?: string): FileWithPath
});
}

// Always populate a relative path so that even electron apps have access to a relativePath value
Object.defineProperty(f, 'relativePath', {
value: typeof path === 'string'
? path
// If <input webkitdirectory> is set,
// the File will have a {webkitRelativePath} property
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/webkitdirectory
: typeof webkitRelativePath === 'string' && webkitRelativePath.length > 0
? webkitRelativePath
: `/${file.name}`, // prepend forward slash (/) to ensure consistancy when path isn't supplied.
writable: false,
configurable: false,
enumerable: true
})
Comment on lines +108 to +120
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not too different from setting the path. Let's make this block a function and reuse it for setting the path and relativePath.

Also, since the path is relative, /${file.name} should probably be ./${file.name}.


return f;
}

export interface FileWithPath extends File {
readonly path?: string;
readonly relativePath?: string;
}

function withMimeType(file: FileWithPath) {
Expand Down