release: v0.19.0

Release v0.19.0. See the `## [0.19.0] — 2026-09-29` section of
[CHANGELOG.md](https://github.com/ralksta/immich-folio/blob/dev/CHANGELOG.md)
for the full list.

Highlights: client proofing links (#683), custom content pages (#738),
asset picker search (#740), concurrent-edit detection (#742), env-locked
settings (#739), an accessibility baseline (#741), three security fixes
with advisories (#737, #755, #759), and a pre-release quality pass
(#780–#797).

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: ralksta <ralksta@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Ralf <rohlenbo79@gmail.com>
Co-authored-by: Paul Thies <110185070+ImScheinox@users.noreply.github.com>
Co-authored-by: lancetm714 <108419425+lancetm714@users.noreply.github.com>
Co-authored-by: Lance Martin <lancetaylor95@gmail.com>
This commit is contained in:
Ralksta
2026-09-29 22:50:30 +02:00
committed by GitHub
parent 5f251923f0
commit ad8b09700b
297 changed files with 19398 additions and 1800 deletions

View File

@@ -0,0 +1,52 @@
import { describe, it, expect } from 'vitest';
import { baseName, formatExport } from '../proofExport';
const picks = [
{ position: 3, fileName: 'IMG_0412.JPG', takenAt: '2026-05-01T10:00:00' },
{ position: 7, fileName: 'IMG_0412.CR3' },
{ position: 9, fileName: 'wedding "first", look.jpg' },
];
describe('baseName', () => {
it('drops only the last extension', () => {
expect(baseName('IMG_0412.JPG')).toBe('IMG_0412');
expect(baseName('a.b.tif')).toBe('a.b');
expect(baseName('.hidden')).toBe('.hidden');
expect(baseName('noext')).toBe('noext');
});
});
describe('formatExport', () => {
it('lists de-duplicated base names for a Lightroom filter', () => {
expect(formatExport(picks, 'lightroom')).toBe('IMG_0412, wedding "first", look');
});
it('lists full names one per line', () => {
expect(formatExport(picks, 'txt')).toBe(
'IMG_0412.JPG\nIMG_0412.CR3\nwedding "first", look.jpg\n',
);
expect(formatExport([], 'txt')).toBe('');
});
it('writes RFC 4180 CSV', () => {
expect(formatExport(picks, 'csv').split('\r\n')).toEqual([
'position,file_name,taken_at',
'3,IMG_0412.JPG,2026-05-01T10:00:00',
'7,IMG_0412.CR3,',
'9,"wedding ""first"", look.jpg",',
'',
]);
});
it('never lets a file name become a spreadsheet formula', () => {
const csv = formatExport([{ position: 1, fileName: '=HYPERLINK("x")' }], 'csv');
expect(csv).toContain(`"'=HYPERLINK(""x"")"`);
});
it('also neutralises names starting with a tab or carriage return', () => {
for (const name of ['\t=1+1', '\r=1+1']) {
const row = formatExport([{ position: 1, fileName: name }], 'csv').split('\r\n')[1];
expect(row).toMatch(/^1,"?'/);
}
});
});