docs: .gitattributes принудительный LF plus GUIDE Уроки 8 диагностика CRLF-саги (vitest@4 давится на CRLF .mjs)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-06-17 20:15:21 +03:00
parent 7ae53216bf
commit 07f24382e8
2 changed files with 37 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
# Принудительно LF для всех текстовых файлов — навсегда, на всех платформах.
#
# Причина (сага 2026-06-17): CRLF в .mjs ломает transform vitest@4 — фантомный
# «SyntaxError: Invalid or unexpected token» (node/esbuild CRLF терпят, vite — нет).
# Windows git autocrlf при КАЖДОМ касании файла делал тронутые .mjs в рабочем дереве
# CRLF → полный свод краснел 19 файлами без видимой причины. eol=lf снимает это насовсем:
# git хранит и выдаёт LF независимо от core.autocrlf.
* text=auto eol=lf
@@ -322,3 +322,32 @@ Verify-шаги под стеной сдвигают указатель, но GR
**Мета-урок.** При «застряло» — сначала прочитать код пути (средства под рукой в разговорном
режиме), потом действовать. НЕ скатываться в «ждать или спросить владельца», когда можешь сам
диагностировать чтением. Owner видит вердикты в логах — но это не повод не открыть код самому.
## Уроки сессии №8 (2026-06-17) — CRLF ломает vitest@4 (фантомный SyntaxError)
**Симптом.** Полный свод краснеет N файлами с `SyntaxError: Invalid or unexpected token` БЕЗ позиции,
а `node --check`, `esbuild` (даже `--bundle` со всеми импортами) и прямой `node import()` те же файлы
парсят ЧИСТО. Под Claude те же файлы дают `Cannot read properties of undefined (reading 'config')`.
Статикой не воспроизводится — кажется, что «код валиден, а vitest врёт».
**Причина.** Windows git `core.autocrlf` при КАЖДОМ касании файла (merge/checkout) делает тронутые
`.mjs` в рабочем дереве **CRLF**. vitest@4 (vite-transform) давится на `.mjs` с CRLF + шебангом
(`#!/usr/bin/env node`) → `SyntaxError`. node/esbuild CRLF терпят — поэтому ВСЕ статические проверки
молчат. Падают ровно «тронутые git» файлы; нетронутые (LF) проходят. Закоммиченный код при этом LF
и корректен — CRLF живёт только в рабочем дереве (артефакт autocrlf).
**Диагностика (чтобы не потерять часы):**
1. `node --check` / `esbuild` / `node -e "import('./f.mjs')"` зелёные, а vitest красный → подозревай
НЕ синтаксис, а кодировку/переносы.
2. Читай СЫРЬЁ как Buffer (utf8-чтение СРЕЗАЕТ ведущий BOM и не видит CRLF через `charCodeAt`):
`node -e "const b=require('fs').readFileSync('tools/f.mjs'); console.log(b.includes('\r\n'), b.slice(0,3).toString('hex'))"`.
3. Подтверди: конвертни файл CRLF→LF и перепрогони — зелёный = это оно.
**Лечение (насовсем).** `.gitattributes` в корне: `* text=auto eol=lf` (git хранит и выдаёт LF
независимо от `core.autocrlf`). Разовая нормализация рабочего дерева — `node`-скрипт
`...replace(/\r\n/g,'\n')...` по всем `.mjs`, либо `git add --renormalize <безопасные-пути>` (НЕ всё:
`.claude/settings.json` под стеной-off трогать нельзя).
**Мета-урок.** «SyntaxError без позиции» + «статика чистая, vitest красный» = почти всегда
CRLF/кодировка, а не логика. Проверь байты и переносы ПЕРВЫМ делом, а не последним.