> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/ru/podrobnye-stati/36-pandora-s-hbox-using-luatex-to-lift-the-lid-of-tex-boxes.md).

# Ящик Пандоры \hbox: использование LuaTeX, чтобы приподнять крышку над коробками TeX

## Введение

Боксы и клей — два ключевых понятия, которые закладывают основу модели и возможностей набора текста в TeX. Продолжая вводный материал в предыдущем посте, [Боксы и клей: краткое, но наглядное введение с использованием LuaTeX](/latex/ru/podrobnye-stati/11-boxes-and-glue-a-brief-but-visual-introduction-using-luatex.md), эта богато иллюстрированная статья рассматривает боксы и клей более подробно. Мы также представляем новый основанный на LuaTeX [проект Overleaf](https://www.overleaf.com/latex/examples/exploring-the-structure-of-tex-boxes-with-luatex/pwdrypmtdbgs) который позволяет вам исследовать глубокую внутреннюю структуру боксов TeX — давая представление, которое поможет вам по-настоящему понять их поведение. Создание проекта Overleaf во многом стало возможным благодаря работе Патрика Гундлаха, поэтому мы выражаем [ему нашу благодарность](#credits-thanks-patrick).

## Почему стоит выбрать LuaTeX?

Во-первых, стоит ещё раз напомнить о различии между LuaTeX и LuaLaTeX:

* LuaTeX — это имя исполняемого механизма набора текста на основе TeX;
* LuaLaTeX обозначает использование макропакета LaTeX с движком LuaTeX.

Это различие крайне важно, потому что в этой статье мы используем встроенные возможности самого движка LuaTeX, а не просто задействуем функции/возможности команд, предоставляемых макропакетом LaTeX.

Читателям, которые не уверены в различии между движком TeX и макропакетом LaTeX, может быть полезно прочитать одну из наших ранее опубликованных статей, [Что в имени: руководство по многочисленным разновидностям TeX](/latex/ru/podrobnye-stati/55-what-s-in-a-name-a-guide-to-the-many-flavours-of-tex.md), в которой эти различия объясняются довольно подробно. В той же статье также обсуждается «TeX» как язык программирования и то, что основанные на TeX механизмы набора текста (например, pdfTeX, XeTeX и LuaTeX) не только различаются своими возможностями и функциональностью, но и имеют вариации в «разновидности» поддерживаемого ими языка TeX. Это подводит нас к нашему выбору LuaTeX. Помимо поддержки языка программирования на основе TeX, LuaTeX также встроен в Lua — предоставляя доступ к простому, но очень мощному традиционному языку программирования. Через Lua и встроенную функциональность LuaTeX вы можете исследовать и контролировать процессы набора текста в LuaTeX так, как ни один другой движок TeX не позволяет, — и это включает возможность исследовать внутренние структуры боксов TeX; поэтому LuaTeX — идеальный (и единственный) выбор для этой статьи и сопровождающего её проекта Overleaf.

### pdfTeX/XeTeX против LuaTeX: в картинках

Следующие *схемы* призваны подчеркнуть важное различие между дизайном pdfTeX/XeTeX и LuaTeX. И pdfTeX, и XeTeX, конечно, позволяют пользователям писать код TeX, который может влиять на поведение набора текста; однако более глубокие внутренние структуры, содержащиеся в этих движках TeX, и низкоуровневые данные, создаваемые в процессе набора текста, в основном недоступны пользовательским командам и макросам. В этом смысле они *относительно* закрытые системы по сравнению с LuaTeX.

#### pdfTeX/XeTeX

![{{{alt}}}](/files/351d6a5d69876c5d3541cb76eb817817f4322333)

#### LuaTeX

LuaTeX вводит новую примитивную команду под названием `\directlua{...}` через которую вы можете писать код, который не только даёт полный доступ к языку Lua, но и позволяет расширять возможности LuaTeX, создавая плагины на таких языках, как C и C++. В Windows такие плагины называются *динамическими библиотеками* (.DLL); в Linux они известны как *разделяемые объектные библиотеки* (.so). Однако настоящая мощь LuaTeX заключается в огромном наборе встроенных функций Lua, которые предоставляют доступ к внутренностям LuaTeX, обеспечивая чрезвычайно сложное управление и программирование набора текста на основе TeX. Набор таких функций называется API (интерфейсом программирования приложений), и именно через API LuaTeX вы используете программы Lua для взаимодействия с его движком набора текста и структурами данных на основе TeX.

![{{{alt}}}](/files/2f5c00d82e246e7802ea33afbc2ecf1502cb1d52)

С помощью `\directlua{...}` команды вы, например, можете получить доступ к низкоуровневым внутренним структурам данных TeX, скрытым от просмотра в других движках TeX. Кроме того, вы можете использовать скрипты Lua для выполнения самых разных вычислений, манипуляций со строками и т. д. и передавать результаты обратно в TeX: возможности почти безграничны. Однако эта статья не предназначена для подробного изложения или учебника по LuaTeX — хотя и велик соблазн привести примеры, демонстрирующие невероятную универсальность этого поразительно мощного движка TeX.

## Боксы и клей: краткое напоминание

Как было введено в статье [Боксы и клей: краткое, но наглядное введение с использованием LuaTeX](https://www.overleaf.com/blog/511-boxes-and-glue-a-brief-but-visual-introduction-using-luatex) боксы и клей — это два ключевых понятия, лежащих в основе возможностей набора текста в TeX. Следующая схема предлагается в качестве очень краткой памятки о поведении горизонтальных и вертикальных типов боксов TeX. Примечание: горизонтальные боксы, конечно, могут содержать текст, набранный на языках с направлением справа налево, таких как арабский или иврит, что означает, что направление роста бокса может быть противоположным тому, что показано для горизонтального бокса на схеме ниже.

![{{{alt}}}](/files/b869a18bc9d1ed2842fc2204ab22c6dd6f1ce70b)

### Примитивы TeX для построения боксов

Сегодня большинство людей готовят документы TeX с помощью макропакета LaTeX, который предназначен для предоставления команд, ограждающих пользователей от большей части низкоуровневого языка TeX — его так называемых *примитивов*— основных команд, встроенных в движки TeX (см. статью [Что в имени: руководство по многочисленным разновидностям TeX](/latex/ru/podrobnye-stati/55-what-s-in-a-name-a-guide-to-the-many-flavours-of-tex.md) для обсуждения примитивов TeX). Коллекция макросов LaTeX предоставляет разнообразные макросы для создания и хранения (сохранения) боксов, но если убрать весь макрокод, то окажется, что существует всего 4 низкоуровневых примитивных команды построения боксов:

Для создания горизонтальных списков:

* \hbox{...}

Для создания и укладки вертикальных списков:

* \vbox{...}
* \vtop{...}
* \vcenter{...}

Мы не будем объяснять, как использовать все эти команды для боксов, потому что в интернете, а также в книгах по TeX/LaTeX, есть множество примеров и учебных материалов — но мы посмотрим, как боксы представлены и хранятся внутри структур данных TeX.

### Клей: гибкие промежутки

Клей, по сути, представляет собой форму промежутка, используемую TeX для размещения/позиционирования объектов по горизонтали или вертикали. Как пользователь TeX, мы можем указать TeX вставить клей фиксированного размера или использовать клей, который является гибким — обладающим ровно той гибкостью, которая нам нужна, чтобы либо растягиваться, либо сжиматься в зависимости от наших требований. Одна из команд TeX для создания клея для горизонтальных промежутков называется `\hskip` и имеет вид

`**\hskip** <natural width> **plus** <amount to stretch> **minus** <amount to shrink>`

`**plus**` и `**minus**` — это ключевые слова TeX, но вам не обязательно использовать их для каждого клея. Если `**plus**` или `**minus**` отсутствуют, то соответствующий `<amount to stretch>` или `<amount to shrink>` считается равным нулю. Например, `\hskip 3pt` вставляет клей фиксированной ширины без компонента растяжения или сжатия.

Пока что думайте о `<amount to stretch>` и `<amount to shrink>` как о наших *рекомендациях* TeX, потому что точная величина растяжения или сжатия будет вычислена TeX.

Чтобы помочь понять эти идеи, вот схема, представляющая клей как пружину.  `<natural width>` — это длина пружины, когда нет ни натяжения (растяжения), ни сжатия.  `<amount to stretch>` и `<amount to shrink>` показаны относительно естественной длины пружины.

![{{{alt}}}](/files/b8e3b532ccf776dc2fc2d81a7f0521e8eeb91570)

#### Пример с \hbox

Предположим, мы хотим создать `\hbox{...}` содержащий только буквы A, B, C и D, и нам нужен бокс шириной 100pt (100 точек TeX). Кроме того, можно безопасно предположить, что суммарная ширина этих четырёх символов намного меньше 100pt, что означает, что TeX нужен какой-то способ заполнить оставшееся пространство внутри бокса: для этого мы используем клей. Однако, поскольку мы не знаем точное количество клея, необходимое для заполнения бокса, рекомендуется добавить несколько гибких клеев и позволить TeX самому вычислить, сколько места им нужно занять. В следующем фрагменте кода обратите внимание на использование «%» для подавления межсловных пробелов, возникающих из символов конца строки.

```
\hbox to100pt{%
A\hskip4pt plus3pt minus 2pt B%
\hskip 0pt plus 2fil C%
\hskip 0pt plus 2fill D%
\hskip 0pt plus 3fill}
```

Получившийся бокс выглядит так (увеличено для наглядности):

![{{{alt}}}](/files/f673e837ee03e586615964a1f1b334798066592f)

Этот `\hbox` покрыт пунктирными рамками (красными), чтобы показать ширину символов (как их видит TeX). Для целей набора текста символы считаются маленькими боксами, а количество клея, необходимое для заполнения этого `\hbox`, определяется (вычисляется) с учётом ширины каждого символа.

Оказывается, TeX не растянул и не сжал клей между A и B (установлен в 4pt), и между B и C клея нет (установлен в 0pt). Однако клей между C и D, а также клей между D и концом бокса, значительно растянулись, потому что у этих клеев наиболее гибкий компонент растяжения — по сути, они поглотили всё растяжение, необходимое для заполнения бокса.

## Назад к LuateX

Пока что мы исследовали боксы и клей и увидели, что LuaTeX позволяет получить доступ к внутренним структурам TeX, скрытым от просмотра в pdfTeX и XeTeX. Пришло время для примера, чтобы сделать это более наглядным, но сначала нам нужно кратко познакомиться с тем, как TeX хранит боксы в своей памяти — начнём с аналогии.

### Как TeX хранит боксы в памяти: аналогия

Предположим, по какой-то причине вам нужно создать модель данных, описывающую физический бокс. Какие данные вы бы выбрали для такого описания? Один из подходов — разделить информацию на две части: данные о самом физическом боксе и данные, представляющие список содержимого бокса. Итак, наша простая модель может выглядеть так:

1. Данные о физическом боксе («метаданные»):

* ширина
* высота
* глубина
* вес
* цвет
* тип (деревянный, пластиковый, картонный)

3. Данные о содержимом бокса: некая форма списка, описывающего элементы, которые он содержит — вероятно, перечисленные в произвольном порядке.

И здесь есть очень близкая аналогия с тем, как TeX хранит боксы.

### Как TeX хранит боксы в памяти: hlists и vlists

Внутри TeX создаёт «контейнеры» под названием *hlists* (горизонтальные списки) и *vlists* (вертикальные списки), которые соответственно представляют hbox'ы и vbox'ы. Эти объекты hlist/vlist предоставляют набор «метаданных» о боксе, а также дают доступ к списку объектов, из которых бокс фактически состоит — этот список называется *списком узлов*. В отличие от физического бокса, куда можно помещать объекты в любом порядке, для TeX порядок содержимого бокса крайне важен — это элементы, которые должны быть набраны. Если у вас есть опыт программирования или компьютерных наук, вас не удивит, что объекты внутри бокса TeX хранятся, при этом сохраняя порядок их создания, с использованием так называемого [двусвязного списка](https://en.wikipedia.org/wiki/Doubly_linked_list). Мы не будем подробнее обсуждать связные списки, поскольку в сети множество учебных материалов, примеров и объяснений.

Понятие узлов и списков узлов — фундаментальный аспект того, как работает TeX, но для целей этой статьи мы дадим лишь краткий обзор. Узлы, по сути, представляют собой своего рода «мини-контейнеры», и (по состоянию на LuaTeX 1.04) существует около 50 различных типов узлов: они отражают внутренние типы данных и компоненты, которые LuaTeX использует для набора текста. Например, существуют узлы для представления глифов (возникающих из «символов»), клея, горизонтальных/вертикальных правил, штрафов, «whatsits», кернинга и так далее. Всё набранное в конечном счёте станет частью огромного списка узлов, и LuaTeX даёт вам прямой доступ к этим внутренним структурам данных. LuaTeX также позволяет вам добавлять, редактировать, дополнять или создавать списки узлов, так что, например, вы можете создавать боксы непосредственно внутри кода Lua, вообще не используя код TeX. Однако писать об этом — дело другого дня.

### Простой пример работы \directlua{...}

Следующий пример создаёт `\hbox` и сохраняет его в регистре боксов 0. Затем мы сообщаем ширину бокса, используя традиционный код TeX, и получаем ту же информацию вторым способом через `\directlua{}`. Здесь мы запускаем небольшой скрипт Lua, который обращается к внутренней области хранения боксов TeX, чтобы получить ширину бокса — разумеется, оба значения идентичны: 2412092sp (sp = scaled point: 65536sp = 1 точка TeX). В конечном счёте в этом крайне простом примере код TeX и код Lua оба обращаются к одним и тем же внутренним структурам данных, чтобы получить ширину бокса, но именно прямой доступ открывает в LuaTeX путь к огромному объёму информации и управления, недоступным в других движках.

![{{{alt}}}](/files/b69865cef5a7f8922c396a0c5b8e5cb7ec73dd10)

```latex
\documentclass{article}
\begin{document}
\setbox0=\hbox{A\hskip 5pt B\hskip 10pt C}
\fontsize{18}{22}\selectfont
\noindent Используя код \TeX{}, бокс 0 имеет ширину \number\wd0\relax \space sp\par
\noindent Мы также можем использовать Lua и вызвать одну из функций Lua\TeX{}, чтобы получить ту же самую
информацию.\vskip10mm
\noindent Из кода Lua бокс 0 имеет ширину
\directlua{
local boxwidth = tex.box[0].width
tex.print(boxwidth.." sp")
}, что, разумеется, идентично значению, полученному из кода \TeX{}.
\end{document}
```

## Собираем всё вместе: проект Overleaf

Мы отметили, что внутри TeX представляет боксы как «контейнеры» под названием hlists/vlists, которые хранят «метаданные» о боксе и обеспечивают доступ к списку компонентов, из которых бокс построен. Используя LuaTeX, вы можете получить доступ к «метаданным» бокса и к списку элементов, содержащихся в боксе TeX: глифам, клею, штрафам, другим боксам и так далее. С помощью скриптов Lua можно исследовать бокс, находящийся в памяти TeX, и построить подробное представление о том, что содержит этот бокс. Подходящее представление бокса TeX и его содержимого достигается с использованием *графов узлов* и мы подготовили [проект Overleaf](https://www.overleaf.com/latex/examples/exploring-the-structure-of-tex-boxes-with-luatex/pwdrypmtdbgs) который делает это, используя отличный скрипт Lua, написанный Патриком Гундлахом (см. благодарности). Мы не будем описывать подробные процессы, необходимые для исследования боксов и генерации графов узлов, — кроме того, что любой программа/скрипт, обрабатывающий боксы TeX, должен быть *рекурсивным* потому что боксы могут быть вложенными: то есть внутри vbox'ов могут быть hbox'ы, внутри hbox'ов — vbox'ы… объединяя все типы боксов на очень глубоком уровне вложенности.

![{{{alt}}}](/files/ae23b69d13c5ae4c9324e82bcbd4f799197e572b)

### Что предоставляет проект?

Он реализует всего 1 команду под названием `\dobox{box command}`, например:

```latex
\dobox{\hbox to100pt{%
A\hskip4pt plus3pt minus 2pt
B\hskip 0pt plus 2fil
C\hskip 0pt plus 2fill
D\hskip 0pt plus 3fill}}
```

Это `\dobox{...}` команда выполняет ряд задач:

1. внутри вашего документа она набирает verbatim-код TeX для вашего бокса;
2. она создаёт SVG-изображение бокса TeX — вы можете встроить его в веб-страницу (как мы сделали в этой записи блога);
3. она создаёт SVG-изображение списка узлов — которое вы также можете встроить в веб-страницы (как мы сделали в этой записи блога);
4. она выводит PDF-графику списка узлов, которая затем импортируется в основной PDF-документ, создаваемый проектом.

Графы узлов могут очень быстро становиться чрезвычайно большими из-за огромного объёма данных, которые LuaTeX должен хранить, чтобы представлять сложные боксы TeX — такие как страница, которая в данный момент строится, или набранная математика. Для более крупных списков узлов импортированное PDF-изображение может быть обрезано границей страницы вашего документа — если вы хотите просмотреть большой граф узлов, вы можете скачать ZIP-файл проекта и извлечь интересующий PDF-график. При загрузке ZIP-файла проекта обязательно выберите «Input and Output Files» в раскрывающемся списке:

![{{{alt}}}](/files/275fa6bf06ca934ba0fdafadf87e597944e0e5b2)

### Графика из проекта Overleaf: краткое описание

Прежде чем мы покажем несколько примеров, стоит сделать несколько замечаний о графике, создаваемой проектом Overleaf, — мы используем тот же `\hbox` пример, упомянутый ранее в статье. Вот он, помещённый в `\dobox{...}` команду:

```latex
\dobox{\hbox to100pt{%
A\hskip4pt plus3pt minus 2pt
B\hskip 0pt plus 2fil
C\hskip 0pt plus 2fill
D\hskip 0pt plus 3fill}}
```

Вот `\hbox` результат, созданный TeX, — для наглядности бокс увеличен, но рамка включена в графику, создаваемую проектом Overleaf.

![{{{alt}}}](/files/072c6f94ef642c171b2dc4e16dac5ab2d305ad9f)

Вот *аннотированная* SVG-диаграмма списка узлов, представляющего указанный выше бокс — аннотации были добавлены, чтобы выделить «метаданные» бокса и список содержащихся в нём объектов: эти аннотации отсутствуют в графике, создаваемой проектом Overleaf.

[![{{{alt}}}](/files/e0d5bc48d1e6213036eef8c930fba973aaa9c9ae)](https://www.filepicker.io/api/file/ZSwIylUR66eFYPMo0suX)

Если посмотреть на раздел «метаданные», можно заметить некоторые незнакомые параметры:

* `glue_set`
* `glue_sign`
* `glue_order`

Эти параметры — это настройки, используемые TeX для вычисления того, насколько клей должен растянуться или сжаться внутри этого бокса, и это лишь один из примеров данных, которые можно легко получить через LuaTeX, но не через другие движки TeX. Обратите внимание, что узлы клея, содержащиеся в компонентах бокса *сохраняют* исходные значения клея, которые мы ввели при создании бокса. Это крайне важно, потому что TeX предоставляет команды `\unhbox`, `\unvbox`, `\unhcopy`, `\unvcopy` которые «распаковывают» содержимое бокса и возвращают его обратно в поток ввода, чтобы оно снова могло участвовать в операциях набора текста. Только когда TeX окончательно выводит (ship out) бокс в PDF- или DVI-файл, `glue_set`, `glue_sign` и `glue_order` применяются к любым клеям, содержащимся в боксе, — чтобы вычислить фактическую величину растяжения или сжатия, необходимую для позиционирования компонентов внутри бокса, а затем сгенерировать соответствующие PDF-данные или DVI-операторы.

Ещё один параметр, указанный в «метаданных», — это `shift`: это значение смещения бокса, возникающее при применении команд TeX:

* `\raise`, `\lower` (применяется к `\hbox`);
* `\moveleft`, `\moveright` (применяется к `\vbox`).

В нашем примере `shift` равен 0pt, потому что мы не смещали `\hbox` из его естественного положения.

Это [проект Overleaf](https://www.overleaf.com/latex/examples/exploring-the-structure-of-tex-boxes-with-luatex/pwdrypmtdbgs) также выводит диаграммы графов узлов в формате PDF: вот ссылка для загрузки [версии PDF-файла](https://www.filepicker.io/api/file/bezigXESC2FSasvjoh8A) графа узлов выше.

### Как проект Overleaf создаёт эти графики?

Проект Overleaf использует возможность запускать программные инструменты и утилиты, установленные на серверах Overleaf, — см. [эту запись блога](/latex/ru/podrobnye-stati/52-using-luatex-to-run-tools-and-utilities-installed-on-overleaf-s-servers.md) для получения дополнительных сведений и примера проекта. Чтобы создать SVG-графику, представляющую бокс TeX, код TeX бокса записывается в небольшой файл, который затем набирается с помощью pdfTeX для создания DVI-файла — обратите внимание, что программа pdfTeX запускается LuaTeX с помощью нескольких строк Lua-скрипта. Этот DVI-файл преобразуется на лету в SVG с использованием `dvisvgm` утилиты — которая поставляется с дистрибутивом TeX Live, установленным на серверах Overleaf. `dvisvgm` запускается с опцией командной строки `-n` чтобы гарантировать, что любой набранный текст преобразуется в линии/кривые, так что корректный вывод SVG-файла не зависит от того, установлены ли шрифты TeX.

Для создания графов узлов мы используем Lua-скрипт под названием `hiviznodelist.lua` который основан на работе Патрика Гундлаха. Этот скрипт записывает так называемый `.gv` (Graphviz)-файл, который представляет собой текстовый файл, содержащий граф узлов, описанный на языке `dot` . `.gv` Файл обрабатывается утилитой под названием `dot` которая выводит диаграмму узлов в форматах PDF и SVG.

### Примеры проекта

Вот ещё несколько примеров с SVG-графикой, созданной с использованием проекта Overleaf. Боксы, содержащие много текста (например, в \vbox), или сложную математику, будут создавать огромные графы узлов — если вы изучаете проект Overleaf, рекомендуется не использовать излишне сложные боксы для демонстрации интересующих вас возможностей.

#### \vbox to 25pt{A}

Этот пример демонстрирует эффект помещения текста непосредственно в `\vbox`: обратите внимание, что структура узлов довольно сложна даже для такого простого бокса. Причина этой сложности в том, что текст, помещённый непосредственно в `\vbox` заставляет TeX выполнять разбиение строк. Вы можете видеть, что `\vbox` имеет ширину 345pt: значение `\hsize` в момент создания этого бокса. Также обратите внимание, что символ «A» содержится в `hlist` , который тоже имеет ширину 345 пунктов, и обратите внимание на большой штраф (10000) вместе с `\parfillskip` и `\rightskip` клеями в конце содержимого бокса. Этот штраф и два элемента клея вставляются в результате действий TeX по разбиению строк. Если вы посмотрите на `glue_set` значение для строки абзаца (`hlist`) содержащей букву «A», вы увидите, что оно чрезвычайно велико (322.500000): почему так? Потому что строка абзаца имеет ширину 345pt, но содержит только `\parindent` и букву «A»: оставшееся пространство должно быть заполнено `\parfillskip` клеем, который должен сильно растянуться, чтобы заполнить оставшееся место в строке.

![{{{alt}}}](/files/a2552008da6ba375613e4e88c4b3a80c1e9ab442)

[![{{{alt}}}](/files/279b29c919a7619f94df6f2a8467167a6c50487a)](https://www.filepicker.io/api/file/pVtHsNGSQ4m09vBZuOpQ)

[Скачать PDF-файл](https://www.filepicker.io/api/file/nBS0uDs2QjqKCKljAm7r)

#### \vbox to 25pt{\hbox{A}}

Очень поучительно сравнить этот пример с предыдущим. Здесь не только граф узлов значительно меньше, но и ширина `\vbox` составляет всего 7.50002pt: ту же ширину, что и символ «A». Причина в том, что «A» был заключён в `\hbox` , который предотвращает `\vbox` запуск TeX на выполнение разбиения строк — важная характеристика боксов, создаваемых с помощью `\vbox`.

![{{{alt}}}](/files/33ad7852ca6ea23851101621d2ff5479f96fd569)

[![{{{alt}}}](/files/8dfef15ac0d3ad3b85644f0a973003fd1f7482ae)](https://www.filepicker.io/api/file/LHepknjnRGOVEdghW4qH)

[Скачать PDF-файл](https://www.filepicker.io/api/file/Yk3uCCQR5ao8Yd3TJCdE)

#### Простая математика: \hbox{$$\displaystyle \int f(x) dx$$}, сложный бокс!

Этот пример демонстрирует, что даже очень простая набранная математика создаёт детальную структуру бокса: набор математических формул порождает *чрезвычайно* сложные структуры данных внутри TeX!

![{{{alt}}}](/files/c9eaede1d6d140b2cadf983be257c8d4e27c1e2e)

[![{{{alt}}}](/files/fbe487442b94b2257004de5c06c36eb043f8ee6a)](https://www.filepicker.io/api/file/oVFNNvCqT0eZP0qS2odk)

[Скачать PDF-файл](https://www.filepicker.io/api/file/D5TepsdaSdeYZvkuSEJt)

## Благодарности: спасибо Патрику!

Выражаем нашу благодарность [Патрику Гундлаху](https://twitter.com/patrickgundlach) который предоставил Overleaf разрешение на использование и распространение модифицированной версии своего Lua-скрипта, `viznodelist.lua`, который обрабатывает боксы TeX и выводит файл (на `dot` языке), который можно обработать для построения графа узлов. В проекте Overleaf есть Lua-скрипт под названием `hiviznodelist.lua`— переименованная и модифицированная версия оригинального кода Патрика, которая доступна на [GitHub](http://gist.github.com/556247). Патрик создал основанную на LuaTeX систему набора текста с открытым исходным кодом под названием [speedata Publisher](https://speedata.github.io/publisher/index.html) которую вы можете скачать и использовать бесплатно — также доступны варианты коммерческой поддержки.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/ru/podrobnye-stati/36-pandora-s-hbox-using-luatex-to-lift-the-lid-of-tex-boxes.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
