* docs: prepare Vendoo 1.41.2 git-ignore boundary hotfix * fix: track native source modules with root-anchored runtime ignores
116 lines
7.3 KiB
JavaScript
116 lines
7.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.1', 'Paketversion ist nicht 1.25.1.');
|
|
assert(index.includes('name="vendoo-build" content="1.25.1"'), 'Build-Metadatum fehlt.');
|
|
assert(index.includes('style.css?v=1.25.1'), 'CSS-Cache-Buster fehlt.');
|
|
assert(index.includes('app.js?v=1.25.1'), 'JS-Cache-Buster fehlt.');
|
|
assert(app.includes("VENDOO_UI_BUILD = '1.25.1'"), 'UI-Buildkennung fehlt.');
|
|
assert(setup.includes('/?build=1.25.1'), '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('grid-template-columns:repeat(auto-fit'), 'Galerie verwendet kein automatisch fließendes Raster.');
|
|
assert(style.includes('container-name:media-card') && style.includes('@container media-card'), 'Galeriekarten skalieren nicht anhand ihrer eigenen Breite.');
|
|
assert(app.includes('class="media-card-open"') && app.includes('data-media-preview'), 'Klickbare Bildfläche fehlt.');
|
|
assert(!app.includes('class="media-card-preview"'), 'Der alte große Vorschau-/Öffnen-Button ist noch vorhanden.');
|
|
assert(app.includes('class="media-action"'), 'Adaptives Galerie-Aktionsdock fehlt.');
|
|
assert(index.match(/data-media-pagination/g)?.length === 2, 'Pagination muss oberhalb und unterhalb der Galerie vorhanden sein.');
|
|
assert(index.match(/data-media-page-jump/g)?.length === 2, 'Direkte Seitenauswahl fehlt oben oder unten.');
|
|
assert(app.includes("root.querySelectorAll('[data-media-page-jump]')"), 'Seitensprung ist nicht angebunden.');
|
|
assert(style.includes('.media-pagination-top') && style.includes('.media-pagination-bottom'), 'Obere/untere Pagination ist nicht gestaltet.');
|
|
|
|
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.1',
|
|
listing_editor_container_responsive: true,
|
|
gallery_card_ux: true,
|
|
adaptive_gallery_grid: true,
|
|
full_image_click_target: true,
|
|
pagination_top_and_bottom: 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 });
|
|
}
|