История коммита: добавляем новую опцию в Doxygen
Я использую Doxygen для генерации документации для одной из своих библиотек, libSDL2pp. Однажды, просматривая оную документацию я наткнулся на интересный факт: мой email в сгенерированном HTML был изменён до неузнаваемости, очевидно в целях помешать спам-ботам собирать адреса. Меня такое поведение категорически не устраивало, а в Doxygen не было настройки чтобы его отключить, поэтому я решил её добавить.
Вот так выглядит изменённый email:
То же в HTML (отформатировано для читаемости):
<a href="#" onclick="location.href='mai'+'lto:'+'amd'+'mi'+'3@a'+'md'+'mi3'+'.r'+'u'; return false;">
amdmi<span style="display: none;">.nosp@m.</span>3@am<span style="display: none;">.nosp@m.</span>dmi3.<span style="display: none;">.nosp@m.</span>ru
</a>
Отступление: в начале я как-то не осознал что
<span>
ы вставляемые в адрес должны быть невидимы из-заdisplay: none
, но этот встроенный стиль не работал из-за заголовка Content-Security-Policy у меня на сервере. Это отдельная проблема в Doxygen которую также нужно исправить.
Это прямо серьёзная обфускация! Мне, однако, она совершенно не нужна:
- Я хочу чтобы мой email и читался в виде текста, и работал в качестве ссылки, даже при отключенном javascript.
- Спам меня не сильно беспокоит, даже при том что мой email опубликован в открытом виде на сотнях сайтов и я не использую никаких фильтров, поэтому роботов я не боюсь.
- Так как адрес уже опубликован на других сайтах, прятать его на каком-то одном вообще не имеет смысла.
Поэтому почему бы, подумал я, не добавить возможность отключить это поведение Doxygen.
Начнём с того что найдём в коде место ответственное за обфускацию. Для этого просто поищем по исходникам мусорный текст которые вставляется в адрес. Нужное место находится сразу:
% git clone https://github.com/doxygen/doxygen/ .
% grep -R nosp@m .
./src/htmldocvisitor.cpp: if (*p) m_t << "<span style=\"display: none;\">.nosp@m.</span>";
Итак, мы в функции которая, судя по названию, как-то обрабатывает URLы:
375void HtmlDocVisitor::visit(DocURL *u)
376{
377 if (m_hide) return;
378 if (u->isEmail()) // mail address
379 {
380 QCString url = u->url();
381 // obfuscate the mail address link
382 writeObfuscatedMailAddress(url);
383 const char *p = url.data();
384 // also obfuscate the address as shown on the web page
385 uint size=5;
386 while (*p)
387 {
388 for (uint j=0;j<size && *p;j++)
389 {
390 p = writeUTF8Char(m_t,p);
391 }
392 if (*p) m_t << "<span style=\"display: none;\">.nosp@m.</span>";
393 if (size==5) size=4; else size=5;
394 }
395 m_t << "</a>";
396 }
397 else // web address
398 {
399 m_t << "<a href=\"";
400 m_t << u->url() << "\">";
401 filter(u->url());
402 m_t << "</a>";
403 }
404}
Тут не нужно вникать в алгоритм обфускации, достаточно осмотреться
и увидеть что нам приходит URL (в нашем случае email) в аргументе
url
, с ним производятся какие-то манипуляции и результат выводится
в поток m_t
. Можно заметить что URL передаётся также в функцию
writeObfuscatedMailAddress()
которая ответственна за вывод
открывающего HTML тэга ссылки (<a href="mailto:...">
) и также
обфусцирует в нём email адрес.
Нужно просто обернуть код обфускации в этих двух местах в if
ы
проверяющие соответствующую настройку, в else
ветках которых
выводить неизменённые адреса.
Осталось добавить опцию и научиться получать её значение из кода.
Для последнего я просто поискал [Cc]onfig
в том же исходном файле
и сразу получил пример: Config_getBool(DOT_CLEANUP)
. Теперь можно
найти где определяется DOT_CLEANUP
(а там же и остальные опции).
Обычно это будет #define
или enum
значение в каком-то заголовочном
файле, но в случае Doxygen определение нашлось в .xml:
% grep -R DOT_CLEANUP .
...
./src/config.xml: <option type='bool' id='DOT_CLEANUP' defval='1'>
...
Значит Doxygen строит код обработки опций (а скорее всего, и
документацию по ним) из определений в .xml файле - что-ж, удобно.
Добавляем в этот .xml определение новой опции по аналогии с
существующей, хотя бы той-же DOT_CLEANUP
.
Всё готово, можно собрать Doxygen (cmake . && cmake --build .
после чего получим бинарник в bin/doxygen
) и протестировать новую
опцию. При выключении обфускации сгенерированный HTML выглядит
как ожидается:
<a href="mailto:amdmi3@amdmi3.ru">amdmi3@amdmi3.ru</a>
Можно создавать пулл реквест (упрощённые изменения).
Мои изменения были приняты на следующий день, и должны попасть в
следующий релиз Doxygen 1.9.3
.
На будущее: перед отправкой PR стоит посмотреть на стиль кода принятый в проекте и убедиться что изменения ему соответствуют, чтобы потом не исправить.