cb05657f30
Phase 1B audit found 48 files failing `prettier --check`. Auto-apply
via `npx prettier --write resources/js/**/*.{ts,vue,css}` produced
style-only changes:
- consistent quote style
- trailing comma normalization
- spaces around : in v-card style="position: relative" attrs
- explicit ; insertion
No semantic changes. No code-behavior changes. Production-code only;
test files batched separately into `test(frontend):` commit.
Verification:
- npx vitest run → 79/79 files, 614/614 + 3 skipped (no regression).
- npx vue-tsc --noEmit → 0 errors.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
54 lines
2.3 KiB
TypeScript
54 lines
2.3 KiB
TypeScript
/**
|
||
* Pure CSV/Blob-download helpers (Sprint 3 Phase C — extraction из DealsView).
|
||
*
|
||
* Все функции работают через DOM API (`document.createElement('a')`, click,
|
||
* URL.createObjectURL). В jsdom-среде Vitest createObjectURL может быть
|
||
* undefined — функции gracefully no-op'ят, тесты явно мокают через
|
||
* `Object.defineProperty(URL, 'createObjectURL', ...)`.
|
||
*/
|
||
|
||
function csvEscape(value: string): string {
|
||
// CSV-стандарт: значение в кавычках если содержит ; / " / \n; внутри двойные «"».
|
||
if (value.includes(';') || value.includes('"') || value.includes('\n')) {
|
||
return '"' + value.replace(/"/g, '""') + '"';
|
||
}
|
||
return value;
|
||
}
|
||
|
||
export function triggerBlobDownload(blob: Blob, filename: string): void {
|
||
if (typeof URL.createObjectURL !== 'function') return;
|
||
const url = URL.createObjectURL(blob);
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = filename;
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
document.body.removeChild(a);
|
||
setTimeout(() => URL.revokeObjectURL(url), 0);
|
||
}
|
||
|
||
export function triggerCsvDownload(csv: string, filename: string): void {
|
||
// jsdom не реализует URL.createObjectURL; в проде — стандартный browser-flow.
|
||
if (typeof URL.createObjectURL !== 'function') return;
|
||
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
|
||
const url = URL.createObjectURL(blob);
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = filename;
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
document.body.removeChild(a);
|
||
setTimeout(() => URL.revokeObjectURL(url), 0);
|
||
}
|
||
|
||
/**
|
||
* Сборка CSV-строки из массива объектов: header-row + строки + BOM (U+FEFF).
|
||
* BOM нужен чтобы Excel корректно распознавал UTF-8.
|
||
*/
|
||
export function buildCsvString(headers: string[], rows: (string | number)[][]): string {
|
||
const lines = [headers.join(';'), ...rows.map((row) => row.map((v) => csvEscape(String(v))).join(';'))];
|
||
// String.fromCharCode(0xfeff) вместо литерального BOM — иначе ESLint
|
||
// no-irregular-whitespace.
|
||
return String.fromCharCode(0xfeff) + lines.join('\r\n');
|
||
}
|