Files
vendoo/tools/verify-release-1.25.0.mjs
Masterluke77andGitHub 6f48827f4d Vendoo 1.41.2 – Git Ignore Boundary & Module Tracking Hotfix (#18)
* docs: prepare Vendoo 1.41.2 git-ignore boundary hotfix

* fix: track native source modules with root-anchored runtime ignores
2026-07-09 17:09:00 +02:00

106 lines
6.3 KiB
JavaScript

import { readFileSync, mkdtempSync, mkdirSync, rmSync, existsSync } from 'node:fs';
import { resolve, join } from 'node:path';
import { tmpdir } from 'node:os';
import sharp from 'sharp';
import { renderImageVersion, normalizeEditorOperations } from '../lib/image-editor.mjs';
const root = resolve(import.meta.dirname, '..');
const read = path => readFileSync(resolve(root, path), 'utf8');
const assert = (condition, message) => { if (!condition) throw new Error(message); };
const index = read('public/index.html');
const app = read('public/app.js');
const style = read('public/style.css');
const server = read('server.mjs');
const db = read('lib/db.mjs');
const jobs = read('lib/ai-flux-prompt-jobs.mjs');
const router = read('lib/ai-router.mjs');
const setup = read('setup.ps1');
const packageJson = JSON.parse(read('package.json'));
assert(packageJson.version === '1.25.0', 'Paketversion ist nicht 1.25.0.');
assert(index.includes('name="vendoo-build" content="1.25.0"'), 'Build-Metadatum fehlt.');
assert(index.includes('style.css?v=1.25.0'), 'CSS-Cache-Buster fehlt.');
assert(index.includes('app.js?v=1.25.0'), 'JS-Cache-Buster fehlt.');
assert(app.includes("VENDOO_UI_BUILD = '1.25.0'"), 'UI-Buildkennung fehlt.');
assert(setup.includes('/?build=1.25.0'), 'Windows-Start-Cache-Buster fehlt.');
assert(style.includes('container-name:listing-editor'), 'Inhaltsbreitenabhängiger Listing-Editor fehlt.');
assert(style.includes('@container listing-editor (max-width: 760px)'), 'Listing-Editor-Container-Breakpoint fehlt.');
assert(style.includes('.detail-description-pane .ql-toolbar.ql-snow'), 'Responsive WYSIWYG-Toolbar fehlt.');
assert(style.includes('Broad width hardening for all primary workspaces'), 'Globale Breitenhärtung fehlt.');
assert(index.includes('id="smart-copy-modal"'), 'Smart-Copy-Modal fehlt.');
assert(app.includes('function openSmartCopyModal'), 'Smart-Copy-Modalsteuerung fehlt.');
assert(app.includes('renderSmartCopyLauncher'), 'Smart-Copy-Einstieg fehlt.');
assert(!style.includes('.vd-button.is-loading { animation: vd-publish-spin'), 'Gesamter Publish-Button rotiert weiterhin.');
assert(app.includes("button.textContent = index === 0 ? 'Wird geladen …' : '…'"), 'Ruhiger Publish-Ladestatus fehlt.');
assert(index.includes('id="flux-prompt-lab"'), 'FLUX Prompt Lab fehlt.');
assert(index.includes('id="flux-prompt-lab-ai"'), 'AI-Prompt-Aktion fehlt.');
assert(server.includes("app.post('/api/flux-prompt/improve'"), 'Prompt-Verbesserungs-API fehlt.');
assert(router.includes('export async function generateText'), 'Provider-Routing für Text fehlt.');
for (const file of ['lib/ai-claude.mjs','lib/ai-openai.mjs','lib/ai-openrouter.mjs','lib/ai-local.mjs']) {
assert(read(file).includes('export async function generateText'), `${file}: Textgenerierung fehlt.`);
}
assert(index.includes('id="flux-history-page-size"'), 'FLUX-Bildpagination fehlt.');
assert(index.includes('id="flux-history-pagination"') || index.includes('class="flux-history-pagination"'), 'FLUX-Bild-Paginierungsleiste fehlt.');
assert(db.includes('export function paginateFluxImages'), 'Serverseitige FLUX-Bildpagination fehlt.');
assert(server.includes('paginateFluxImages'), 'FLUX-Bildpagination ist nicht angebunden.');
assert(jobs.includes('Math.min(15, Number(pageSize)'), 'Job-Center ist nicht auf maximal 15 begrenzt.');
assert(index.includes('<option value="5">5 / Seite</option><option value="10" selected>10 / Seite</option><option value="15">15 / Seite</option>'), 'Job-Seitengrößen 5/10/15 fehlen.');
assert(style.includes('.media-card-favorite-toggle'), 'Galerie-Favoriten-Overlay fehlt.');
assert(style.includes('.media-card-select input:checked + span::after') && app.includes('<span aria-hidden="true"></span></label>'), 'Galerie-Auswahlfeld ist nicht sauber gestaltet.');
assert(style.includes('.media-card-actions { display:grid'), 'Galerie-Aktionsraster fehlt.');
assert(app.includes('class="media-card-preview"'), 'Galerie-Vorschauaktion fehlt.');
const extensionFiles = ['extension/content.js', 'extensions/content.js', 'extensions/chrome/content.js', 'extensions/edge/content.js', 'extensions/firefox/content.js'];
for (const file of extensionFiles) {
const content = read(file);
assert(content.includes('function isLikelyTitleField(el)'), `${file}: Vinted-Titelfeldschutz fehlt.`);
}
const temp = mkdtempSync(join(tmpdir(), 'vendoo-125-bg-'));
try {
const uploadRoot = join(temp, 'uploads');
mkdirSync(join(uploadRoot, 'verification'), { recursive: true });
const source = join(uploadRoot, 'verification', 'source.png');
const image = Buffer.from('<svg width="360" height="260" xmlns="http://www.w3.org/2000/svg"><rect width="360" height="260" fill="#f2eee8"/><rect x="80" y="45" width="200" height="170" rx="28" fill="#d8c7b4"/><rect x="120" y="75" width="120" height="110" rx="18" fill="#356a5d"/></svg>');
await sharp(image).png().toFile(source);
const render = async sensitivity => renderImageVersion({
uploadRoot,
sourcePath: 'verification/source.png',
rootPath: 'verification/source.png',
context: 'verification',
operations: normalizeEditorOperations({ remove_background: true, background_sensitivity: sensitivity, format: 'png' }),
});
const low = await render(5);
const high = await render(90);
const countTransparent = async filename => {
const raw = await sharp(join(uploadRoot, filename)).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
let count = 0;
for (let i = 3; i < raw.data.length; i += raw.info.channels) if (raw.data[i] < 32) count += 1;
return count;
};
const lowTransparent = await countTransparent(low.filename);
const highTransparent = await countTransparent(high.filename);
assert(highTransparent > lowTransparent, 'Hintergrundintensität reagiert nicht.');
console.log(JSON.stringify({
ok: true,
release: '1.25.0',
listing_editor_container_responsive: true,
gallery_card_ux: true,
smart_copy_modal: true,
publish_refresh_without_button_spin: true,
flux_history_pagination: [5,10,15],
flux_job_pagination: [5,10,15],
flux_prompt_lab_providers: ['claude','openai','openrouter','local'],
background_sensitivity: { low_transparent_pixels: lowTransparent, high_transparent_pixels: highTransparent },
vinted_title_guard_preserved: true,
}, null, 2));
} finally {
rmSync(temp, { recursive: true, force: true });
}