Виталий Филатов

о тексте, смысле и красоте

Делаем сноски на HTML регулярками

Регулярные выражения — мощный инструмент поиска и замены фрагментов текста. Редактору полезно ими владеть, чтобы при случае не менять что-то руками, а один раз написать умный шаблон. Синтаксис регулярных выражений подробно описан в интернете, поэтому мы сразу перейдём к примеру.

В статье про нейронные сети у меня набралось десять примечаний, которые я решил оформить ссылками, как в Википедии: знак сноски в верхнем регистре со ссылкой на примечание и примечание в конце статьи со ссылкой на сноску.

Было бы лучше, если бы примечание вплывало при наведении на знак сноски, как в Обсидиане, но Эгея не поддерживает сноски вообще. Чтобы не лезть в код движка, я делаю их на чистом HTML, без JS и прочих хитростей

Текст статьи жил в Обсидиане, поэтому ссылки и сноски оформлены в маркдауне:

Текст со сноской[^1]
...
[^1]: Текст примечания на отдельной строке

Эти штуки в скобочках предстояло превратить в HTML:

Текст со сноской <sup><a href="all/ai-talks/#t1" name="n1">[1]</a></sup>
...
<a name="t1"></a>
1. Текст примечания <a href="all/ai-talks/#n1">↩︎</a>

Клик на знак сноски прокручивает страницу до тега <А> с именем «t1», а клик по стрелке — на тег <А> с именем «n1». Из-за особенностей движка в адрес ссылки «href=» приходится добавлять часть адреса страницы. Ссылка-якорь с именем примечания стоит на отдельной строке, чтобы окно браузера прокручивалось ровно до начала абзаца.

Чтобы пройтись по всему тексту и поменять маркдаун на HTML, нужно найти повторяющиеся фрагменты и написать на их основе шаблоны поиска и замены. Фрагменты у нас такие:

[^n] — знак сноски в сплошном тексте
[^n]: Какой-то текст — примечание на отдельной строке

Начнём со строки поиска знака сноски.

n — порядковый номер примечания, всего их десять. Значит, нам нужна регулярка, которая будет искать какое-то число от 1 до 10 в квадратных скобках c ^ в любом месте текста. Получится так:

\[\^(\d{1,2})\](?!:)

Квадратные скобки и ^ — служебные символы, поэтому добавляем перед ними обратный слеш. А перед d — чтобы искать не саму букву, а символ любой цифры. В фигурных скобках указываем, что ищем 1 или 2 цифры. Круглые скобки сохраняют фрагмент строки в переменную — скобочную группу. В конце идёт указание, что строка не должна заканчиваться двоеточием. Это не совсем корректно, ведь знак сноски может стоять где угодно. Но для примера нужна регулярка попроще, так что просто убедимся, что в тексте такого нет.

Теперь напишем строку замены:

&thinsp;<sup><a href="all/ai-talks/#t$1" name="n$1">[$1]</a></sup>

Перед знаком ставим &thinsp; — HTML-код тонкого пробела, чтобы знак сноски не слеплялся со словом слева. $1 — переменная, в которой будет число из знака сноски, от 1 до 10. Единица после $ означает порядковый номер скобочной группы. В этой регулярке она одна, но для обработки примечаний нам потребуются уже две.

Теперь скопируем текст статьи из Обсидиана в Sublime text, откроем режим поиска и замены (Ctrl + H), включим регулярные выражения (Alt + R) и выполним первый набор регулярок.

Найденные регуляркой фрагменты выделены рамкой

Теперь сами примечания. Найдём их в тексте:

\[\^(\d{1,2})\]: (.+?)\n

Первую часть вы уже видели, но теперь мы не исключаем двоеточие. Потом идёт любой текст. Точка означает «любой символ, кроме переноса строки», а «+?» говорит брать символы до первого символа правее. В нашем случае это конец строки \n.

Напишем строку замены:

<a name="t$1"></a>\n$1. $2&nbsp;<a href="all/ai-talks/#n$1">↩︎</a>\n\n

Как видите, порядковый номер сноски $1 удачно стал частью ссылок и порядковым номером примечания, а текст примечания из скобочной группы $2 вставится между номером с точкой и ссылкой на знак сноски. &nbsp; — знак неразрывного пробела, чтобы стрелка не повисала на следующей строке.

Вставим строки в редактор и выполним замену:

Все сноски превратились в HTML

Результат можно посмотреть в коде статьи.

Где и как учиться регуляркам

Регулярки в JavaScript — приятный сайт на русском

Regular-Expressions.info — сайт про регулярки на английском

RegExr — гибкий отладчик регулярок. Можно устанавливать разные параметры поиска (флаги), смотреть, что попадает в скобочные группы, и тестировать строку замены