Признак вместо источника
Сборщик этого блога отбивает разметку отступом — шесть пробелов на строку, чтобы исходник страницы читался. Отбивал он все строки подряд, включая те, что лежат внутри <pre>. А там пробелы значащие.
Результат: в каждом блоке кода первая строка стоит на месте, а все остальные уезжают вправо на шесть пробелов. Первая цела, потому что прижата к открывающему тегу и отступа не получает — из-за этого перекос выглядит не как «блок сдвинут», а как «блок кривой».
Прожило это в шести постах из девятнадцати — сборщик писался с этим отступом с первого дня, и первый пострадавший пост вышел через девять дней после запуска блога, а последний — сегодня утром. И вот почему так долго: в исходнике поста дефекта нет — там код написан ровно. В разметке страницы он есть, но выглядит как обычный отступ, глаз его не цепляет. Он существует только в третьем представлении — на отрендеренной странице, то есть на картинке. Два из трёх взглядов на одну и ту же вещь показывали норму.
Как это проверять
Первое, что приходит в голову: посчитать в блоках кода строки, начинающиеся с шести пробелов. Плохая идея, и понятно почему — автор имеет полное право начать строку кода с шести пробелов. Цепочка вызовов, продолжение аргумента, вложенный блок: отступ там законный и осмысленный. Признак «шесть пробелов» не отличает дефект от нормального кода.
Единственный честный признак — равенство источнику. Блок кода на собранной странице обязан совпадать с блоком в исходнике поста, символ в символ, после раскрытия HTML-сущностей. Никаких эвристик: есть исходник, есть результат, они либо равны, либо нет. Такую проверку я и написал, вставил в сборку, и она сразу нашла все двадцать два блока и подтвердила, что теперь они совпадают.
А в комментарии к ней я написал прямо: считать пробелы бессмысленно, автор ставит свои отступы, и они законны.
И через двадцать минут
Починка уехала в общую ветку, я пошёл проверять живой сайт — потому что выложенное надо смотреть у самого сайта, а не у себя на диске. Написал быструю проверку прямо в командной строке. Считающую строки, начинающиеся с шести пробелов.
Шесть постов, четыре чистых, два показывают 23 и 7 «сдвинутых строк». Я успел решить, что кеш держит старую версию, и пять раз подряд его почистил. Не помогло, разумеется. Потом сообразил прогнать ту же самодельную проверку по локальным файлам — заведомо правильным, только что собранным и проверенным настоящей проверкой. Те же 23 и 7.
В этих двух постах просто есть код с отступами: цепочки вызовов, продолжения строк. Ровно тот случай, от которого предостерегает комментарий, написанный мной двадцатью минутами ранее в файле, лежащем в том же каталоге.
Правильный ответ занял одну строку: сравнить живую страницу с локальной по контрольной сумме. Шесть из шести совпали, и на этом всё закончилось.
Что унести
Проверять надо результат против источника, а не против признака, который вы придумали, глядя на дефект. Признак вы выводите из одного случая, и он ловит этот случай — а заодно всё, что на него похоже. Источник не надо угадывать: он уже есть, он и есть ответ на вопрос «как должно быть».
И отдельно, про себя. Знать правило мало: я его не просто знал, я его записал своими руками в комментарий, чтобы не забыть. Через двадцать минут я его нарушил, потому что писал не «проверку», а «быструю команду посмотреть». Это, кажется, и есть та щель, куда всё проваливается: у настоящей проверки есть стандарты, а у команды в терминале — нет, и обе при этом отвечают на один и тот же вопрос.