May 19th, 2021

Учебник по JavaScript: как устроены примеры, движок учебника, Prism.js

Начал читать подраздел 1.1 «Браузерное окружение, спецификации» первого раздела «Документ» второй части «Браузер: документ, события, интерфейсы» учебника по JavaScript.

Все примеры в учебнике с точки зрения стиля оформлены одинаково и выглядят примерно так (это первый пример из обсуждаемого подраздела учебника), картинка-иллюстрация:


Иллюстрация. Оформление примера в учебнике

Код самого примера расположен на сероватом фоне, строки пронумерованы, синтаксические конструкции выделены разным цветом (этот прием называется «подсветкой синтаксиса», по-английски «syntax highlighting»; в википедии по этому поводу есть статьи на русском и английском).

Как видно на иллюстрации, выше и ниже примера идет обычный текст учебника.

Для работы с такой вставкой на HTML-страницу фрагментов кода существует множество библиотек. В частности эти библиотеки помогают с обеспечением подсветки синтаксиса для фрагментов кода на разных языках программирования. Авторы учебника используют для этого библиотеку Prism.js (https://prismjs.com).

В этом можно убедиться, открыв на HTML-странице любого подраздела учебника инструменты разработчика (в моем браузере «Microsoft Edge», работающем на движке «Chromium», это делается с помощью клавиши F12). В меню следует выбрать пункт «Sources» (по-русски «Исходники»). При этом в окне инструментов разработчика слева должна появиться панель обзора ресурсов (по-английски «Navigator pane»), полученных от сервера для конструирования текущей HTML-страницы, с деревом путей к ресурсам (если выбрана вкладка «Page», по-английски «Page tab»). Подробнее тут:

https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/sources/

Итак, в дереве ресурсов папку с файлами библиотеки Prism.js на странице какого-либо подраздела учебника можно найти по следующему пути:

Если в панели обзора ресурсов включена опция «Group by folder» (группировать по папке):
top/wp/./modules/engine/prism
или (если опция «Group by folder» выключена):
top/./modules/engine/prism
Как я понимаю, это «wp» в пути к папке библиотеки Prism.js означает, что авторы учебника используют в своей работе сборщик модулей webpack (статья в википедии, сайт сборщика).

Также эту папку с файлами можно посмотреть в репозитории движка учебника на гитхабе:
https://github.com/javascript-tutorial/engine/tree/master/prism

* * *

На вышеприведенной иллюстрации видно, что в правом верхнем углу примера могут быть (они не всегда есть) две кнопки (слева направо): «выполнить» (кнопка с треугольником как у кнопки «Play» в проигрывателе), «открыть в песочнице» (кнопка с листком бумаги и карандашом).

Кнопка «выполнить» запускает код примера на выполнение прямо на странице учебника.

Кнопка «открыть в песочнице» открывает окно онлайн-редактора, в котором можно поэкспериментировать с кодом примера (изменить его, запустить, запустить измененную версию и тому подобное). В качестве онлайн-редактора («песочницы») используется веб-сервис «Plunker» (https://plnkr.co), созданный специально для экспериментов новичков в программировании (название дословно я бы перевел как «шлёпалка», в том смысле, что новички могут шлёпать туда свои эксперименты сколько угодно и безопасно для окружающих, тот же смысл, что и у «песочницы» в русском языке). Код примера передается в окно онлайн-редактора веб-сервиса «Plunker».

С реализацией кнопок (не только таких, как описано выше) для фрагмента кода из примера тоже помогает библиотека Prism.js, а точнее плагин «Toolbar» к ней (вообще, к этой библиотеке есть десятки разных плагинов, тем оформления, подсветок синтаксиса для разных языков программирования):

https://prismjs.com/plugins/toolbar/

* * *

Устройство HTML-страницы подраздела учебника и то, как HTML-страница связана со скриптами библиотеки Prism.js (и другими скриптами), можно посмотреть в тех же инструментах разработчика, описанных выше (открываю их клавишей F12). Следует выбрать пункт меню «Elements» (по-русски «Элементы страницы»). В открывшемся окне с HTML-исходником текущей HTML-страницы (по-английски «DOM-tree») можно легко отыскать реализацию примера кода на HTML (при наведении мышкой на какой-либо HTML-тег в исходнике этот участок подсвечивается в отображении HTML-страницы, формируемом браузером). Подробнее тут:

https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/css/reference

Пример в учебнике на HTML-странице конструируется с помощью тегов div (слой; всё реализуется множеством слоев, вложенных друг в друга), pre (блок текста, набранного моноширинным шрифтом и с сохранением форматирования), code (атрибут этого тега class используется, чтобы сообщить библиотеке Prism.js название языка программирования для правильной подсветки синтаксиса), a (используется для конструирования кнопок) и span (используется для реализации нумерации строк, а также для разделения семантических единиц кода (или лексем, по-английски «token»), например: ключевые слова, пунктуация, названия функций, строки, комментарии и так далее для дальнейшей их подсветки скриптами из библиотеки Prism.js).

Вот так приблизительно пример с кодом вставляется в HTML при создании страницы подраздела учебника (псевдокод):
...
<div ... class="code-example" ...>
    <div class="codebox code-example__codebox">
        <div class="toolbar codebox__toolbar">
            <!-- реализация кнопок -->
        </div>
        <div class="codebox__code" ...>
            <!-- вывод кода с нумерацией строк и подсветкой синтаксиса -->
        </div>
    </div>
</div>
...

Реализация кнопок:
<!-- реализация кнопок -->
<div class="toolbar__tool">
    <!-- кнопка "выполнить" -->
    <a href="#" title="выполнить" data-action="run" class="toolbar__button toolbar__button_run"></a>
</div>
<div class="toolbar__tool">
    <!-- кнопка "открыть в песочнице" -->
    <a href="#" title="открыть в песочнице" target="_blank" data-action="edit" class="toolbar__button toolbar__button_edit"></a>
</div>

Вся функциональность кнопок написана в скрипте codeBox.js:
https://github.com/javascript-tutorial/engine/blob/master/prism/codeBox.js

Когда читатель учебника открывает HTML-страницу подраздела, запускается функция CodeBox из скрипта (модуля) codeBox.js. Эта функция помещает в HTML-элемент с атрибутом data-action="run" (см. выше, в реализации кнопок, отмечено красным) в событие onclick вызов кода примера на исполнение. При этом код примера хранится в переменной runCode.

Вставка кода на исполнение в событие onclick HTML-элемента (строка 71):
https://github.com/javascript-tutorial/engine/blob/master/prism/codeBox.js#L71

Когда читатель нажимает на кнопку «выполнить» происходит запуск кода по событию onclick HTML-элемента.

Собственно, запуск кода на исполнение (строка 351):
https://github.com/javascript-tutorial/engine/blob/master/prism/codeBox.js#L351
А именно, цитата:
try {
    window["eval"].call(window, runCode);
} catch (e) {
    alert(e.constructor.name + ": " + e.message);
}