diff --git a/apps/client/src/views/cuesheet/__tests__/EditableImage.test.ts b/apps/client/src/views/cuesheet/__tests__/EditableImage.test.ts
index 0a2f6ad4f..7b971dd5f 100644
--- a/apps/client/src/views/cuesheet/__tests__/EditableImage.test.ts
+++ b/apps/client/src/views/cuesheet/__tests__/EditableImage.test.ts
@@ -3,20 +3,22 @@ import { describe, expect, test } from 'vitest';
import { isValidImageSource } from '../cuesheet-table/cuesheet-table-elements/EditableImage';
describe('isValidImageSource()', () => {
- test('accepts images hosted elsewhere', () => {
+ test('accepts links to a hosted image', () => {
expect(isValidImageSource('https://example.com/image.png')).toBe(true);
expect(isValidImageSource('http://example.com/image.png')).toBe(true);
});
- test('accepts images served by ontime', () => {
- expect(isValidImageSource('/user/image.png')).toBe(true);
- expect(isValidImageSource('/external/image.png')).toBe(true);
+ test('rejects references to a local file, they would not resolve for our clients', () => {
+ expect(isValidImageSource('/user/image.png')).toBe(false);
+ expect(isValidImageSource('user/image.png')).toBe(false);
+ expect(isValidImageSource('file:///Users/me/image.png')).toBe(false);
+ expect(isValidImageSource('C:\\images\\image.png')).toBe(false);
});
test('rejects values which would not resolve to an image', () => {
expect(isValidImageSource('www.example.com/image.png')).toBe(false);
expect(isValidImageSource('example.com/image.png')).toBe(false);
- expect(isValidImageSource('user/image.png')).toBe(false);
+ expect(isValidImageSource('https://')).toBe(false);
expect(isValidImageSource('some text')).toBe(false);
});
});
diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EditableImage.tsx b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EditableImage.tsx
index bb7a3b28d..fe258fe0e 100644
--- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EditableImage.tsx
+++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EditableImage.tsx
@@ -16,11 +16,16 @@ interface EditableImageProps {
export default memo(EditableImage);
/**
- * An image is either hosted somewhere else
- * or served by ontime itself (eg. a file placed in the user folder)
+ * Images are referenced by link: anything local to the machine running ontime
+ * would not resolve for the clients we serve the cuesheet to
*/
export function isValidImageSource(value: string): boolean {
- return value.startsWith('http://') || value.startsWith('https://') || value.startsWith('/');
+ try {
+ const url = new URL(value);
+ return url.protocol === 'http:' || url.protocol === 'https:';
+ } catch {
+ return false;
+ }
}
function EditableImage({ initialValue, fieldLabel, readOnly, updateValue }: EditableImageProps) {
@@ -73,7 +78,7 @@ function EditableImage({ initialValue, fieldLabel, readOnly, updateValue }: Edit
}
}}
/>
- {isRejected && Use a link (https://...) or a file in ontime (/user/...)}
+ {isRejected && Images are referenced by link (https://...)}
>
);
}