mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-17 16:37:43 +00:00
feat(electron): restore bmp/avif background image support
This commit is contained in:
parent
9b58b883af
commit
0286cd3b5d
4 changed files with 45 additions and 2 deletions
|
|
@ -70,6 +70,39 @@ test('importImage copies a valid image and returns an opaque id', async () => {
|
|||
}
|
||||
});
|
||||
|
||||
test('importImage accepts avif and bmp (restored legacy formats)', async () => {
|
||||
const cache = load();
|
||||
const sourceDir = fsModule.realpathSync.native(
|
||||
await fs.mkdtemp(path.join(os.tmpdir(), 'sp-src-')),
|
||||
);
|
||||
try {
|
||||
const avif = await mkPng(sourceDir, 'bg.avif', Buffer.from('fakeavif'));
|
||||
const avifResult = await cache.importImage(avif);
|
||||
assert.ok(avifResult);
|
||||
assert.equal(avifResult.mimeType, 'image/avif');
|
||||
|
||||
const bmp = await mkPng(sourceDir, 'bg.bmp', Buffer.from('fakebmp'));
|
||||
const bmpResult = await cache.importImage(bmp);
|
||||
assert.ok(bmpResult);
|
||||
assert.equal(bmpResult.mimeType, 'image/bmp');
|
||||
} finally {
|
||||
await fs.rm(sourceDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test('importImage rejects svg (scriptable format deliberately excluded)', async () => {
|
||||
const cache = load();
|
||||
const sourceDir = fsModule.realpathSync.native(
|
||||
await fs.mkdtemp(path.join(os.tmpdir(), 'sp-src-')),
|
||||
);
|
||||
try {
|
||||
const svg = await mkPng(sourceDir, 'bg.svg', Buffer.from('<svg></svg>'));
|
||||
assert.equal(await cache.importImage(svg), null);
|
||||
} finally {
|
||||
await fs.rm(sourceDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test('importImage returns null for a path inside userData (no laundering)', async () => {
|
||||
const cache = load();
|
||||
const evilPath = await mkPng(userDataDir, 'planted.png');
|
||||
|
|
|
|||
|
|
@ -33,12 +33,17 @@ import { assertPathOutside } from './file-path-guard';
|
|||
|
||||
const MAX_IMAGE_BYTES = 5 * 1024 * 1024;
|
||||
|
||||
// SVG is deliberately excluded: it is a scriptable format (can embed
|
||||
// <script>/event handlers) and inlining it as a data URL would reintroduce an
|
||||
// XSS surface, so the cache only accepts raster formats.
|
||||
const MIME_BY_EXT: Record<string, string> = {
|
||||
png: 'image/png',
|
||||
jpg: 'image/jpeg',
|
||||
jpeg: 'image/jpeg',
|
||||
gif: 'image/gif',
|
||||
webp: 'image/webp',
|
||||
bmp: 'image/bmp',
|
||||
avif: 'image/avif',
|
||||
};
|
||||
|
||||
const ID_RE = /^[a-f0-9]{32}$/;
|
||||
|
|
|
|||
|
|
@ -272,7 +272,12 @@ export const initLocalFileSyncAdapter = (): void => {
|
|||
buttonLabel: 'Select',
|
||||
properties: ['openFile'],
|
||||
filters: [
|
||||
{ name: 'Images', extensions: ['png', 'jpg', 'jpeg', 'gif', 'webp'] },
|
||||
{
|
||||
name: 'Images',
|
||||
// Keep in sync with MIME_BY_EXT in image-cache.ts (svg excluded
|
||||
// on purpose — scriptable format).
|
||||
extensions: ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'avif'],
|
||||
},
|
||||
],
|
||||
})) as unknown as { canceled: boolean; filePaths: string[] };
|
||||
if (canceled || !filePaths[0]) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<input
|
||||
#fileInput
|
||||
type="file"
|
||||
accept="image/png,image/jpeg,image/gif,image/webp"
|
||||
accept="image/png,image/jpeg,image/gif,image/webp,image/bmp,image/avif"
|
||||
hidden
|
||||
(change)="onFileSelected($event)"
|
||||
/>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue