A self-hosted print studio: images at exact physical sizes, sheet layout with crop marks, tiling, 1:1 PDF. Everything else — image generation, delivery, share links, mail, Telegram — is an optional module that is off by default. This is the neutral public twin of a private tool. Compared to that original: - optional modules behind KLARBILD_MODULES; the default install is print-only - English interface with German as a full second language (1,038 strings); the English sentence is the translation key - no built-in accounts — first boot creates one admin from ADMIN_USERNAME / ADMIN_PASSWORD, or generates a password and logs it once - delivery and backup targets are generic SFTP/FTPS endpoints, off by default - English routes, English identifiers, English comments throughout - two compose files: print-only by default, everything in the full one - AGPL-3.0, CI (build, tests, type check, secret scan), CONTRIBUTING, SECURITY 124 tests green, type check clean, verified end to end against a live instance. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nh4A79bbqT9dcd2inzYUdg
This commit is contained in:
164 files changed
+27190
No files matched your search
@@ -0,0 +1,43 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { summarise } from '../src/lib/printruns.ts';
|
||||
|
||||
/**
|
||||
* The short summary stands in the history list. It arrives cell by cell — two
|
||||
* cells with the same size must not show up there twice.
|
||||
*/
|
||||
|
||||
test('A single size stays as it is', () => {
|
||||
assert.equal(summarise(['13 × 18 cm']), '13 × 18 cm');
|
||||
});
|
||||
|
||||
test('Identical sizes are pulled together', () => {
|
||||
assert.equal(summarise(['10 × 15 cm', '10 × 15 cm']), '10 × 15 cm ×2');
|
||||
});
|
||||
|
||||
test('Existing piece counts are added up, not appended', () => {
|
||||
assert.equal(summarise(['35 × 45 mm ×8', '35 × 45 mm ×4']), '35 × 45 mm ×12');
|
||||
assert.equal(summarise(['10 × 15 cm ×3', '10 × 15 cm']), '10 × 15 cm ×4');
|
||||
});
|
||||
|
||||
test('Different sizes stay side by side, in the order they came in', () => {
|
||||
assert.equal(summarise(['13 × 18 cm', '35 × 45 mm ×8']), '13 × 18 cm, 35 × 45 mm ×8');
|
||||
});
|
||||
|
||||
test('Additions such as (poster) keep the groups apart', () => {
|
||||
assert.equal(summarise(['30 × 40 cm ×2 (poster)', '30 × 40 cm ×1 (poster)']),
|
||||
'30 × 40 cm ×3 (poster)');
|
||||
assert.equal(summarise(['30 × 40 cm (poster)', '30 × 40 cm (oversize)']),
|
||||
'30 × 40 cm (poster), 30 × 40 cm (oversize)');
|
||||
});
|
||||
|
||||
test('An empty list gives something readable', () => {
|
||||
assert.equal(summarise([]), 'Print sheet');
|
||||
});
|
||||
|
||||
test('Very long enumerations are shortened', () => {
|
||||
const many = Array.from({ length: 40 }, (_, i) => `${i + 10} × ${i + 15} cm`);
|
||||
const s = summarise(many);
|
||||
assert.ok(s.length <= 118, `too long: ${s.length}`);
|
||||
assert.ok(s.endsWith('…'));
|
||||
});
|
||||
Reference in new issue
Block a user