Разметка презентации

Описание разметки и примеры для составления презентации в формате Alpha Tessera Base

Файл презентации в Alpha Tessera Base — это текстовый файл, описывающий структуру и содержимое слайдов презентации. Парсер PresentationParser из пакета atessera.markup преобразует такой файл в структурированное представление PresentationContent, которое затем используется шаблоном PresentationTemplate для генерации конечного выходного документа (например, LaTeX+Beamer).

На этой странице подробно разберём синтаксис файла презентации, опишем все возможные типы слайдов и их особенности, а также приведём разнообразные примеры.

Общая структура файла

Файл презентации состоит из двух основных частей:

  1. Глобальные заголовки~— строки, задающие метаданные всей презентации: название, подзаголовок, авторов, дату и тему оформления.
  2. Слайды~— блоки, ограниченные маркерами FRAME BEGIN и FRAME END, каждый из которых соответствует одному слайду презентации.

Глобальные заголовки должны располагаться до первого маркера FRAME BEGIN. Пустые строки между заголовками игнорируются. Весь текст, находящийся вне кадров (после заголовков, между FRAME END и следующим FRAME BEGIN), также игнорируется.

Глобальные заголовки

Каждый глобальный заголовок записывается на отдельной строке и начинается с ключевого слова. Все глобальные заголовки необязательны. Порядок следования не имеет значения.

TITLE — название презентации

TITLE <язык> <текст>
        

Задаёт название презентации. Параметр <язык>~— это двухбуквенный код языка в верхнем регистре (например, EN, RU, DE, FR). Текст названия может содержать пробелы и занимать всю оставшуюся часть строки.

Примеры:

TITLE EN Introduction to Machine Learning
        TITLE RU Введение в машинное обучение
        

SUBTITLE — подзаголовок презентации

SUBTITLE <текст>
        

Задаёт подзаголовок, отображаемый под названием презентации на титульном слайде.

Пример:

SUBTITLE A Practical Guide for Beginners
        

AUTHORS — авторы

AUTHORS <текст>
        

Строка с именами авторов презентации. Формат свободный, обычно имена перечисляются через запятую.

Примеры:

AUTHORS Ivanov I. I., Petrov P. P.
        AUTHORS Prof. Dr. Michael Schmidt
        

DATE — дата

DATE <текст>
        

Дата презентации в свободном формате (например, дата доклада на конференции).

Примеры:

DATE 2025-01-15
        DATE January 2025
        DATE 15.01.2025
        

THEME — тема оформления

THEME <текст>
        

Имя темы оформления LaTeX Beamer (например, Madrid, Copenhagen, Berlin, Warsaw, default).

Примеры:

THEME Madrid
        THEME Copenhagen
        

Полный пример секции глобальных заголовков

TITLE EN Alpha Tessera: Modern Document Processing
        SUBTITLE Tools and Practices for Scientific Publishing
        AUTHORS Michael Pozhidaev
        DATE 2025-06-01
        THEME Warsaw
        

Слайды

Каждый слайд презентации описывается блоком, который начинается строкой FRAME BEGIN и заканчивается строкой FRAME END.

Синтаксис объявления слайда

FRAME BEGIN [тип]
        

где [тип]~— необязательный идентификатор типа содержимого кадра. Если тип не указан или не распознан, по умолчанию используется MARKDOWN.

Регистр букв в названии типа не имеет значения: markdown, Markdown, MARKDOWN~— всё это воспринимается одинаково.

Метаданные слайда

Сразу после FRAME BEGIN могут следовать строки метаданных кадра. Каждая такая строка начинается с одного из ключевых слов:

  • TITLE <текст>~— заголовок слайда
  • SUBTITLE <текст>~— подзаголовок слайда
  • LABEL <текст>~— метка для перекрёстных ссылок (аналог \label в LaTeX)
  • LISTING_LANG <текст>~— язык программирования для кадров типа LISTING (например, java, python, cpp)

Метаданные распознаются до первой строки, которая не соответствует ни одному из ключевых слов метаданных (и не является пустой). Эта строка и все последующие строки до FRAME END считаются исходным содержимым кадра.

Пустые строки до первого метаданного или содержательной строки игнорируются. Однако пустая строка после того, как метаданные уже начались, вызывает переход в режим содержимого, и сама эта пустая строка становится первой строкой исходного содержимого.

Содержимое слайда

Всё, что идёт после метаданных (включая самую первую не-метаданную строку), и до закрывающего FRAME END, является исходным содержимым кадра. Способ интерпретации этого содержимого зависит от типа кадра.

Типы слайдов

Ниже перечислены все поддерживаемые типы кадров с подробным описанием и примерами.

MARKDOWN — упрощённая разметка

Тип по умолчанию. Содержимое слайда интерпретируется как текст в формате Markdown с расширенными возможностями Alpha Tessera.

Базовое форматирование Markdown:

Поддерживаются все стандартные элементы Markdown:

  • Жирный текст: **жирный** или __жирный__
  • Курсив: *курсив* или _курсив_
  • Моноширинный текст: `код`
  • Жирный курсив: ***жирный курсив***
  • ~ Зачёркнутый текст:   ~~зачёркнутый~~
  • Ссылки: [текст ссылки](https://example.com)
  • Изображения: ![альтернативный текст](path/to/image.png)

Заголовки:

Поддерживаются заголовки уровней 1-4 (в LaTeX они проецируются на chapter, section, subsection и subsubsection соответственно):

# Заголовок 1-го уровня
        ## Заголовок 2-го уровня
        ### Заголовок 3-го уровня
        #### Заголовок 4-го уровня
        

Списки:

Неупорядоченные списки — с использованием *, - или +:

* Первый элемент
        * Второй элемент
            * Вложенный элемент
            * Ещё один вложенный
        * Третий элемент
        

Упорядоченные списки:

1. Первый шаг
        2. Второй шаг
           1. Подшаг 2.1
           2. Подшаг 2.2
        3. Третий шаг
        

Цитаты:

> Это цитата.
        > Она может занимать несколько строк.
        >
        > И даже несколько абзацев.
        

Горизонтальная линия:

---
        

Пример простого кадра с Markdown:

FRAME BEGIN MARKDOWN
        TITLE Введение
        SUBTITLE Основные понятия
        LABEL sec:intro
        
        ## Что такое Alpha Tessera?
        
        Alpha Tessera~--- это инструмент для работы с **публикациями** и
        **презентациями**, поддерживающий:
        
        * Чтение материалов в формате Markdown
        * Совместную работу с использованием Git
        * Практики CI/CD для документов
        
        > *Публикация как код*~--- это новая парадигма работы
        > с научными и техническими текстами.
        FRAME END
        

4.2. Внутренние формулы (Inline Math)

Внутри текста Markdown можно вставлять математические формулы, используя синтаксис [$ выражение ]. Формула будет отрендерена как inline LaTeX math (между одинарными $):

Текст с формулой [$x_i] внутри строки.
        Квадратное уравнение [$ax^2 + bx + c = 0] и текст дальше.
        Энергия покоя [$E = mc^2]~--- знаменитое уравнение Эйнштейна.
        

Важно: Между [$ и началом выражения, а также между концом выражения и ] должен быть хотя бы один пробел. Синтаксис регистрозависим: [$ с заглавной S сработает, а строчная не будет воспринята.

Примеры сложных формул:

Вероятностная мера: [$P(A|B) = \frac{P(B|A)P(A)}{P(B)}]
        Сумма ряда: [$\sum_{i=1}^{n} i^2 = \frac{n(n+1)(2n+1)}{6}]
        Гамма-функция Эйлера: [$\Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt]
        

4.3. Блочные формулы (Display Math)

4.3.1. Обычные блочные формулы

Блочная формула без номера записывается как строка, обрамлённая двойными знаками доллара. Такая формула будет отрендерена как $$...$$ в LaTeX:

$$ \frac{d}{dx}e^x = e^x $$
        
        $$ \begin{pmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{pmatrix} $$
        

4.3.2. Нумерованные формулы (с меткой)

Блочная формула может быть снабжена меткой (label) для последующих перекрёстных ссылок. Метка записывается в круглых скобках сразу после закрывающих $$:

$$ \int_{0}^{\infty} e^{-x^2} dx = \frac{\sqrt{\pi}}{2} $$(gaussian-integral)
        

Такая формула будет отрендерена в LaTeX как окружение equation с командой \label{gaussian-integral}:

\begin{equation}
        \label{gaussian-integral}
        \int_{0}^{\infty} e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
        \end{equation}
        

Допустимые символы в метке: буквы латинского алфавита (a-z, A-Z), цифры (0-9), знаки =, _, :, . и -.

$$ \nabla \times \mathbf{E} = -\frac{\partial \mathbf{B}}{\partial t} $$(eq:faraday)
        
        $$ f(x) = \frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{(x-\mu)^2}{2\sigma^2}} $$(normal-dist)
        
        $$ \zeta(s) = \sum_{n=1}^{\infty} \frac{1}{n^s} $$(eq:zeta)
        

4.4. Перекрёстные ссылки

Ссылка на помеченную формулу или другой элемент с меткой записывается в квадратных скобках с символом @ перед именем метки:

  • [@метка]~— обычная ссылка (в LaTeX: \ref{метка})

  • [@@метка]~— ссылка на страницу (в LaTeX: \pageref{метка})

    Как показано в формуле Reference(type=REGULAR, ref=gaussian-integral), значение интеграла Гаусса равно $sqrt{pi}/2$.

    На странице Reference(type=PAGE, ref=eq:faraday) приведён закон электромагнитной индукции Фарадея.

    Доказательство теоремы Пифагора см. в Reference(type=REGULAR, ref=pythagorean-theorem).

4.5. Ссылки на литературу (цитирование)

Ссылка на источник в списке литературы записывается с символом #:

[#ключ]
        

В LaTeX это преобразуется в команду \cite{ключ}.

Пример:

Согласно работе [#knuth1984], алгоритм имеет сложность O(n log n).
        
        Метод был впервые предложен в [#turing1936] и впоследствии развит
        в работах [#shannon1948] и [#kolmogorov1965].
        

4.6. Блоки кода

Блоки кода (fenced code blocks) записываются стандартным образом с тройными обратными кавычками:

```java
        public class HelloWorld {
            public static void main(String[] args) {
                System.out.println("Hello, World!");
            }
        }
        ```
        

После открывающих кавычек можно указать язык программирования для подсветки синтаксиса (например, java, python, cpp, javascript, bash, sql, xml, json, yaml и другие).

4.7. Полный пример кадра с Markdown и формулами

FRAME BEGIN MARKDOWN
        TITLE Математический анализ
        SUBTITLE Производная и интеграл
        LABEL slide:calculus
        
        ## Определение производной
        
        Производная функции [$f(x)] в точке [$x_0] определяется как:
        
        $$ f'(x_0) = \lim_{h \to 0} \frac{f(x_0 + h) - f(x_0)}{h} $$(def:derivative)
        
        ## Основные правила дифференцирования
        
        * Производная константы: [$\frac{d}{dx}c = 0]
        * Производная степенной функции: [$\frac{d}{dx}x^n = nx^{n-1}]
        * Производная экспоненты: [$\frac{d}{dx}e^x = e^x]
        
        Как следует из определения [@def:derivative], все эти правила
        могут быть выведены аналитически (см. также [#fichtenholz1968]).
        
        FRAME END
        

4.8. LATEX — чистый LaTeX

Кадры типа LATEX содержат исходный код на LaTeX, который будет передан в выходной документ без изменений. Это полезно, когда возможностей Markdown недостаточно, и требуется точный контроль над вёрсткой.

FRAME BEGIN LATEX
        TITLE Сложная таблица
        LABEL tab:complex
        
        \begin{table}[h]
        \centering
        \caption{Сравнительный анализ алгоритмов}
        \label{tab:comparison}
        \begin{tabular}{|l|c|c|c|}
        \hline
        \textbf{Алгоритм} & \textbf{Время} & \textbf{Память} & \textbf{Устойчивость} \\
        \hline
        QuickSort  & $O(n \log n)$ & $O(\log n)$ & Нет \\
        MergeSort  & $O(n \log n)$ & $O(n)$      & Да \\
        HeapSort   & $O(n \log n)$ & $O(1)$      & Нет \\
        \hline
        \end{tabular}
        \end{table}
        
        FRAME END
        

Важно: При использовании кадров LATEX вы полностью отвечаете за корректность LaTeX-кода. Парсер не проверяет его синтаксис — он передаётся «как есть».

4.9. LISTING — листинг исходного кода

Кадры типа LISTING предназначены для отображения исходного кода программ с подсветкой синтаксиса. Язык программирования задаётся через метаданное LISTING_LANG.

FRAME BEGIN LISTING
        TITLE Пример на Java
        LISTING_LANG java
        
        public class BinarySearch {
            public static int search(int[] arr, int target) {
                int left = 0;
                int right = arr.length - 1;
        
                while (left <= right) {
                    int mid = left + (right - left) / 2;
        
                    if (arr[mid] == target)
                        return mid;
        
                    if (arr[mid] < target)
                        left = mid + 1;
                    else
                        right = mid - 1;
                }
                return -1;
            }
        }
        
        FRAME END
        

Ещё примеры:

FRAME BEGIN LISTING
        TITLE SQL-запрос
        LISTING_LANG sql
        
        SELECT
            department,
            COUNT(*) AS employee_count,
            AVG(salary) AS avg_salary
        FROM employees
        WHERE hire_date >= '2020-01-01'
        GROUP BY department
        HAVING COUNT(*) > 5
        ORDER BY avg_salary DESC;
        
        FRAME END
        
        FRAME BEGIN LISTING
        TITLE Конфигурация Docker
        LISTING_LANG dockerfile
        
        FROM openjdk:17-slim
        COPY build/libs/*.jar app.jar
        EXPOSE 8080
        ENTRYPOINT ["java", "-jar", "/app.jar"]
        
        FRAME END
        

Поддерживаются, в частности, следующие значения для LISTING_LANG: java, python, cpp, c, javascript, typescript, bash, sql, xml, html, css, json, yaml, dockerfile, ruby, go, rust, scala, kotlin, swift и многие другие (зависят от пакета listings в LaTeX).

4.10. METAPOST — графика MetaPost

Кадры типа METAPOST содержат исходный код на языке MetaPost для создания векторных иллюстраций, диаграмм и графиков.

FRAME BEGIN METAPOST
        TITLE Пример MetaPost: график функции
        LABEL fig:metapost-sine
        
        beginfig(1);
        
        % Настройка координатной сетки
        numeric u;
        u = 1cm;
        
        % Рисование осей
        drawarrow (-2u, 0) -- (8u, 0);
        drawarrow (0, -1.5u) -- (0, 1.5u);
        
        % Подписи осей
        label.bot(btex $x$ etex, (8u, 0));
        label.lft(btex $y$ etex, (0, 1.5u));
        
        % Рисование графика синуса
        draw (-0.5u, 0) for x = 0 step 0.1 until 7:
            .. (x * u, u * sind(x * 180 / 3.14159))
        endfor;
        
        endfig;
        
        FRAME END
        
        FRAME BEGIN METAPOST
        TITLE Блок-схема алгоритма
        
        % Простая блок-схема
        beginfig(1);
        pair a, b, c, d;
        a = (0, 0);
        b = (0, -2cm);
        c = (3cm, -2cm);
        d = (3cm, 0);
        
        draw a -- b -- c -- d -- cycle;
        label(btex Начало etex, (1.5cm, -1cm));
        
        drawarrow (1.5cm, -2cm) -- (1.5cm, -3cm);
        
        endfig;
        
        FRAME END
        

4.11. GNUPLOT — графики и диаграммы

Кадры типа GNUPLOT содержат команды для построения графиков с помощью GNUPlot.

FRAME BEGIN GNUPLOT
        TITLE График нормального распределения
        LABEL fig:normal-dist
        
        set terminal epslatex
        set output 'normal.tex'
        
        set title 'Нормальное распределение'
        set xlabel 'x'
        set ylabel 'f(x)'
        
        set grid
        set key top right
        
        # Функция плотности нормального распределения
        sigma = 1.0
        mu = 0.0
        f(x) = 1.0 / (sigma * sqrt(2 * pi)) * exp(-(x - mu)**2 / (2 * sigma**2))
        
        plot f(x) with lines lw 2 title '$\\mu=0, \\sigma=1$'
        
        FRAME END
        
        FRAME BEGIN GNUPLOT
        TITLE Сравнение алгоритмов сортировки
        
        set terminal epslatex
        set output 'sorting.tex'
        
        set title 'Сравнение времени выполнения'
        set xlabel 'Размер массива (n)'
        set ylabel 'Время (мс)'
        set grid
        
        plot 'data.dat' using 1:2 with lines title 'QuickSort', \
             '' using 1:3 with lines title 'MergeSort', \
             '' using 1:4 with lines title 'BubbleSort'
        
        FRAME END
        

4.12. PLANTUML — диаграммы UML и не только

Кадры типа PLANTUML содержат диаграммы на языке PlantUML.

FRAME BEGIN PLANTUML
        TITLE Диаграмма классов
        LABEL fig:uml-class
        
        @startuml
        class User {
            - id: Long
            - name: String
            - email: String
            + getName(): String
            + getEmail(): String
        }
        
        class Order {
            - id: Long
            - date: Date
            - total: BigDecimal
            + calculateTotal(): BigDecimal
        }
        
        class OrderItem {
            - quantity: int
            - price: BigDecimal
        }
        
        User "1" -- "many" Order : places
        Order "1" -- "many" OrderItem : contains
        @enduml
        
        FRAME END
        
        FRAME BEGIN PLANTUML
        TITLE Диаграмма последовательности
        LABEL fig:seq-diagram
        
        @startuml
        actor User
        participant "Web Server" as WS
        participant "Auth Service" as Auth
        database "Database" as DB
        
        User -> WS: POST /login
        WS -> Auth: validate(credentials)
        Auth -> DB: SELECT user
        DB --> Auth: user data
        Auth --> WS: token
        WS --> User: 200 OK + JWT
        @enduml
        
        FRAME END
        

PlantUML также поддерживает диаграммы деятельности (activity), вариантов использования (use case), состояний (state), компонентов (component), развёртывания (deployment) и многие другие.

4.13. GRAPHVIZ_DOT — графы в формате DOT

Кадры типа GRAPHVIZ_DOT (и его варианты GRAPHVIZ_NEATO, GRAPHVIZ_TWOPI, GRAPHVIZ_CIRCO) содержат описание графа на языке DOT пакета Graphviz. Разные типы соответствуют разным алгоритмам автоматической укладки графа:

  • GRAPHVIZ_DOT~— иерархическая (направленная) укладка

  • GRAPHVIZ_NEATO~— пружинная укладка (spring model)

  • GRAPHVIZ_TWOPI~— радиальная укладка

  • GRAPHVIZ_CIRCO~— круговая укладка

    FRAME BEGIN GRAPHVIZ_DOT TITLE Граф зависимостей модулей LABEL fig:module-deps

    digraph G { rankdir=LR; node [shape=box, style=filled, fillcolor=lightyellow];

      app [label="Application"];
              core [label="Core Library"];
              db [label="Database Module"];
              api [label="REST API"];
              auth [label="Authentication"];
              cache [label="Cache Layer"];
            
              app -> core;
              app -> api;
              api -> auth;
              api -> db;
              core -> cache;
              auth -> db;
            

    }

    FRAME END

    FRAME BEGIN GRAPHVIZ_NEATO TITLE Социальный граф

    graph G { overlap=false; node [shape=circle, style=filled, fillcolor=lightblue];

      Alice -- Bob;
              Alice -- Carol;
              Bob -- Dave;
              Carol -- Dave;
              Carol -- Eve;
              Dave -- Eve;
              Eve -- Frank;
            

    }

    FRAME END

    FRAME BEGIN GRAPHVIZ_CIRCO TITLE Циклическая диаграмма компонентов

    digraph G { layout=circo; node [shape=circle];

      Compiler -> "AST Parser";
              "AST Parser" -> "Code Generator";
              "Code Generator" -> Optimizer;
              Optimizer -> "Linker";
              "Linker" -> Compiler;
            

    }

    FRAME END

4.14. EQUATION — отдельное уравнение

Кадры типа EQUATION предназначены для отображения крупных, самодостаточных математических выражений, которые должны занимать весь слайд.

FRAME BEGIN EQUATION
        TITLE Уравнение Навье-Стокса
        LABEL eq:navier-stokes
        
        \rho \left( \frac{\partial \mathbf{v}}{\partial t}
        + \mathbf{v} \cdot \nabla \mathbf{v} \right)
        = -\nabla p + \mu \nabla^2 \mathbf{v} + \mathbf{f}
        
        FRAME END
        
        FRAME BEGIN EQUATION
        TITLE Тождество Эйлера
        
        e^{i\pi} + 1 = 0
        
        FRAME END
        

5. Продвинутые возможности Markdown в презентациях

5.1. Библиографические записи (BibItem)

В кадрах с Markdown-содержимым можно размещать записи списка литературы (библиографии). Они распознаются по строкам, начинающимся с [#ключ]::

[#knuth1984]: Knuth D. E. Literate Programming // The Computer Journal.~---
        1984.~--- Vol. 27, no. 2.~--- Pp. 97–111.
        
        [#turing1936]: Turing A. M. On Computable Numbers, with an Application to
        the Entscheidungsproblem // Proceedings of the London Mathematical
        Society.~--- 1936.~--- Vol. s2-42, no. 1.~--- Pp. 230-265.
        
        [#shannon1948]: Shannon C. E. A Mathematical Theory of Communication //
        Bell System Technical Journal.~--- 1948.~--- Vol. 27.~--- Pp. 379-423.
        

На такие записи затем можно ссылаться с помощью синтаксиса [#ключ].

Пример кадра со списком литературы:

FRAME BEGIN MARKDOWN
        TITLE Основные источники
        
        [#knuth1984]: Knuth D. E. Literate Programming // The Computer Journal.~---
        1984.~--- Vol. 27, no. 2.~--- Pp. 97–111.
        
        [#turing1936]: Turing A. M. On Computable Numbers, with an Application
        to the Entscheidungsproblem // Proc. London Math. Soc.~--- 1936.~---
        Vol. s2-42.~--- Pp. 230-265.
        
        [#shannon1948]: Shannon C. E. A Mathematical Theory of Communication //
        Bell System Technical Journal.~--- 1948.~--- Vol. 27.~--- Pp. 379-423.
        
        FRAME END
        

5.2. Метки (Label)

Метка (label) может быть размещена в любом месте Markdown-текста с помощью синтаксиса [label:имя]. Она будет преобразована в LaTeX-команду \label{имя}.

## Введение [label:sec:introduction]
        
        Здесь начинается вводная часть.
        

Это позволяет ссылаться не только на формулы, но и на разделы, рисунки, таблицы и другие элементы документа.

5.3. Мультиблоки (MultiBlock)

Мультиблоки — это структура для организации сложного содержимого, которая может состоять из нескольких частей. Они используются для создания окружений, требующих начальных и конечных маркеров.

Синтаксис мультиблоков определяется парсером MultiBlockParser и фабрикой MultiBlockParserFactory. Конкретный синтаксис различается в зависимости от типа мультиблока.

5.4. Расширенные изображения (AdvImage)

Расширенные изображения позволяют указывать дополнительные атрибуты изображения (размер, позиционирование, подпись) через парсер AdvImageBlockParser:

![подпись к рисунку](path/to/image.png){width=80%}
        

5.5. Комбинирование различных элементов

Ниже приведён пример слайда, демонстрирующего совместное использование нескольких возможностей разметки:

FRAME BEGIN MARKDOWN
        TITLE Основная теорема
        SUBTITLE Интегральное исчисление
        LABEL slide:main-theorem
        
        ## Формулировка теоремы
        
        Пусть функция [$f(x)] непрерывна на отрезке [$\lbrack a, b \rbrack].
        Тогда определённый интеграл:
        
        $$ \int_a^b f(x)\,dx = F(b) - F(a) $$(eq:newton-leibniz)
        
        где [$F(x)]~--- первообразная функции [$f(x)], то есть [$F'(x) = f(x)].
        
        > **Историческая справка:** Формула [@eq:newton-leibniz] носит
        > имена Исаака Ньютона и Готфрида Лейбница, которые независимо
        > пришли к ней в конце XVII века  (см. [#newton1687] и [#leibniz1684]).
        
        ## Следствия
        
        1. **Линейность интеграла:**
           [$\int_a^b (\alpha f(x) + \beta g(x))\,dx = \alpha\int_a^b f(x)\,dx + \beta\int_a^b g(x)\,dx]
        
        2. **Интегрирование по частям:**
           [$\int_a^b u\,dv = uv\big|_a^b - \int_a^b v\,du]
        
        FRAME END
        

6. Полный пример файла презентации

Ниже приведён полностью рабочий пример файла презентации, который демонстрирует использование большинства возможностей разметки:

TITLE EN Alpha Tessera Base
        SUBTITLE Инструмент для работы с публикациями и презентациями
        AUTHORS Michael Pozhidaev
        DATE 2025
        THEME Madrid
        
        FRAME BEGIN MARKDOWN
        TITLE Титульный слайд
        SUBTITLE О проекте
        
        # Alpha Tessera Base
        
        **Инструмент для работы с публикациями и презентациями**
        
        * Поддержка формата Markdown
        * Совместная работа через Git
        * Практики CI/CD для документов
        
        FRAME END
        
        FRAME BEGIN MARKDOWN
        TITLE Возможности
        SUBTITLE Обзор функциональности
        
        ## Основные возможности
        
        * Чтение и обработка Markdown с формулами
        * Генерация HTML с SVG-формулами для веба
        * Генерация LaTeX для научных публикаций
        * Генерация презентаций LaTeX Beamer
        * Поддержка MetaPost, GNUPlot, PlantUML, Graphviz
        * Встроенная компиляция в PDF
        
        FRAME END
        
        FRAME BEGIN MARKDOWN
        TITLE Математика в Markdown
        SUBTITLE Внутренние и блочные формулы
        LABEL slide:math
        
        ## Внутренние формулы (inline)
        
        Кинетическая энергия: [$E_k = \frac{mv^2}{2}]
        
        Уравнение Шрёдингера (стационарное):
        [$\hat{H}\Psi = E\Psi]
        
        ## Блочные формулы (display)
        
        Закон всемирного тяготения Ньютона:
        
        $$ F = G \frac{m_1 m_2}{r^2} $$(eq:gravity)
        
        Тензор энергии-импульса в ОТО:
        
        $$ R_{\mu\nu} - \frac{1}{2}R g_{\mu\nu} + \Lambda g_{\mu\nu}
           = \frac{8\pi G}{c^4} T_{\mu\nu} $$(eq:einstein)
        
        Как показано в [@eq:einstein], уравнения Эйнштейна связывают
        геометрию пространства-времени с распределением материи.
        
        FRAME END
        
        FRAME BEGIN LISTING
        TITLE Пример кода: алгоритм Дейкстры
        LISTING_LANG java
        
        import java.util.*;
        
        public class Dijkstra {
            public static int[] shortestPaths(
                    List<List<Edge>> graph, int start) {
                int n = graph.size();
                int[] dist = new int[n];
                Arrays.fill(dist, Integer.MAX_VALUE);
                dist[start] = 0;
        
                PriorityQueue<Node> pq = new PriorityQueue<>();
                pq.add(new Node(start, 0));
        
                while (!pq.isEmpty()) {
                    Node node = pq.poll();
                    int u = node.vertex;
        
                    if (node.dist > dist[u]) continue;
        
                    for (Edge e : graph.get(u)) {
                        int v = e.to;
                        int newDist = dist[u] + e.weight;
                        if (newDist < dist[v]) {
                            dist[v] = newDist;
                            pq.add(new Node(v, newDist));
                        }
                    }
                }
                return dist;
            }
        }
        
        FRAME END
        
        FRAME BEGIN PLANTUML
        TITLE Архитектура системы
        LABEL fig:architecture
        
        @startuml
        package "Alpha Tessera" {
            [Markdown Parser] as MD
            [LaTeX Generator] as TEX
            [HTML Generator] as HTML
            [Presentation Parser] as PRES
        }
        
        package "Внешние инструменты" {
            [GNUPlot] as GP
            [MetaPost] as MP
            [PlantUML] as PUML
            [Graphviz] as GV
            [PdfLaTeX] as PDF
        }
        
        MD --> TEX
        MD --> HTML
        PRES --> TEX
        TEX --> GP
        TEX --> MP
        TEX --> PUML
        TEX --> GV
        TEX --> PDF
        @enduml
        
        FRAME END
        
        FRAME BEGIN GRAPHVIZ_DOT
        TITLE Процесс сборки документа
        LABEL fig:build-pipeline
        
        digraph Pipeline {
            rankdir=TB;
            node [shape=box, style=rounded];
        
            md [label="Исходный\nMarkdown"];
            json [label="Промежуточный\nJSON"];
            tex [label="LaTeX\nдокумент"];
            pdf [label="PDF\nдокумент"];
        
            external [label="Внешние\nресурсы\n(GNUPlot,\nMetaPost,\nPlantUML,\nGraphviz)",
                      shape=folder, style=filled, fillcolor=lightyellow];
        
            md -> json [label="Парсинг"];
            json -> tex [label="Шаблонизация\n(Velocity)"];
            tex -> external [label="Компиляция\nресурсов", style=dashed];
            external -> tex [label="Готовые\nизображения", style=dashed];
            tex -> pdf [label="pdfLaTeX"];
        }
        
        FRAME END
        
        FRAME BEGIN GNUPLOT
        TITLE Сравнение сложности алгоритмов
        
        set terminal epslatex
        set output 'complexity.tex'
        set title 'Асимптотическая сложность'
        set xlabel 'Размер входных данных (n)'
        set ylabel 'Количество операций'
        set grid
        set key top left
        
        set logscale y
        
        plot x**2        title 'O(n^2)'     with lines lw 2, \
             x*log(x)    title 'O(n log n)' with lines lw 2, \
             x           title 'O(n)'       with lines lw 2, \
             log(x)      title 'O(log n)'   with lines lw 2
        
        FRAME END
        
        FRAME BEGIN MARKDOWN
        TITLE Заключение
        
        ## Выводы
        
        Alpha Tessera Base предоставляет **единый инструмент** для:
        
        * Написания научных публикаций
        * Создания презентаций
        * Генерации выходных документов в HTML и PDF
        * Интеграции с современными инструментами разработки
        
        > *Публикация как код* (Publication as Code)~--- это подход,
        > позволяющий применять к документам те же практики,
        > что и к программному коду: контроль версий, рецензирование,
        > автоматическую сборку и тестирование.
        
        FRAME END
        

7. Важные замечания и рекомендации

7.1. Порядок глобальных заголовков и кадров

Глобальные заголовки обязательно должны идти до первого FRAME BEGIN. Если разместить заголовок после начала первого кадра, он будет проигнорирован или, что хуже, воспринят как метаданное кадра (если он внутри кадра и совпадает с ключевыми словами TITLE, SUBTITLE).

7.2. Различие глобальных и кадровых метаданных

Ключевые слова TITLE и SUBTITLE используются и на глобальном уровне, и внутри кадров, но интерпретируются по-разному:

  • Глобальный TITLE EN ...~— название всей презентации
  • Кадровый TITLE ...~— заголовок конкретного слайда

Это два разных контекста, и они не конфликтуют друг с другом.

7.3. Пробелы и пустые строки

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

7.4. Регистр ключевых слов

  • Ключевые слова глобальных заголовков (TITLE, SUBTITLE, AUTHORS, DATE, THEME) чувствительны к регистру и должны записываться заглавными буквами
  • Тип кадра в FRAME BEGIN нечувствителен к регистру
  • Ключевые слова метаданных кадра (TITLE, SUBTITLE, LABEL, LISTING_LANG) чувствительны к регистру

7.5. Экранирование специальных символов

Внутри Markdown-содержимого работают стандартные правила экранирования Markdown:

  • \*~— экранирование звёздочки
  • \_~— экранирование подчёркивания
  • \\~— обратная косая черта
  • \[ и \]~— экранирование квадратных скобок

Внутри LaTeX-кадров действуют правила экранирования LaTeX.

7.6. Совместная работа и CI/CD

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

  • Хранения в системе контроля версий (Git)
  • Совместного редактирования (pull requests, code review)
  • Автоматической сборки в CI/CD-пайплайнах (например, GitHub Actions)
  • Отслеживания изменений (diff между версиями презентации)

Пример файла .github/workflows/main.yml для автоматической сборки:

name: Build presentation
        
        on:
          push:
            paths:
              - 'presentation.txt'
        
        jobs:
          build:
            runs-on: ubuntu-latest
            steps:
              - uses: actions/checkout@v4
              - name: Build presentation
                run: gradle run --args="-i presentation.txt -o slides.pdf"
              - name: Upload PDF
                uses: actions/upload-artifact@v4
                with:
                  name: slides
                  path: slides.pdf
        

7.7. Ограничения

  • Тип кадра по умолчанию — MARKDOWN. Если в FRAME BEGIN указан неизвестный или некорректный тип, он будет silently проигнорирован и заменён на MARKDOWN
  • Имена меток (label) в формулах и перекрёстных ссылках могут содержать только символы: латинские буквы (a-z, A-Z), цифры (0-9), знаки =, _, :, . и -
  • Максимальный уровень заголовков в Markdown — 4 (####). Более глубокие уровни не имеют специальной обработки