1
0
Fork
You've already forked sto701c
0
No description
  • OCaml 97.6%
  • CSS 1.5%
  • JavaScript 0.3%
  • Standard ML 0.3%
  • Dune 0.2%
  • Other 0.1%
Find a file
2026年06月22日 10:13:10 +03:00
bin feat: massive update compiler 2026年06月22日 10:13:10 +03:00
lib feat: massive update compiler 2026年06月22日 10:13:10 +03:00
samples feat: massive update compiler 2026年06月22日 10:13:10 +03:00
styles feat: massive update compiler 2026年06月22日 10:13:10 +03:00
tests feat: massive update compiler 2026年06月22日 10:13:10 +03:00
.gitignore feat: woff/woff2 font loading, СТО §5.6 tables, docx media 2026年06月02日 14:12:45 +03:00
dune-project feat: woff/woff2 font loading, СТО §5.6 tables, docx media 2026年06月02日 14:12:45 +03:00
LICENSE feat: first opensource version by standart 2026年05月15日 17:03:00 +03:00
mise.toml feat: support styling with css 2026年05月27日 13:42:29 +03:00
README.md feat: support styling with css 2026年05月27日 13:42:29 +03:00
sto701c.install feat: massive update compiler 2026年06月22日 10:13:10 +03:00
sto701c.opam feat: woff/woff2 font loading, СТО §5.6 tables, docx media 2026年06月02日 14:12:45 +03:00
vite.config.js feat: massive update compiler 2026年06月22日 10:13:10 +03:00

sto701c

Компилятор на OCaml, преобразующий Org-mode, Markdown (CommonMark + GFM) и MDX в PDF и DOCX, оформленные согласно стандарту для учебных текстов.

Оба выходных формата создаются собственными OCaml-писателями — никакие внешние бинарники во время работы не вызываются. Кириллица полностью поддерживается в PDF за счёт встроенных TrueType-шрифтов (по умолчанию DejaVu Serif).

Быстрый старт

mise install
mise run bootstrap
mise run deps
mkdir -p out
mise run run -- -i samples/diploma.md --pdf out/diploma.pdf --docx out/diploma.docx

После выполнения команды в out/ появятся diploma.pdf и diploma.docx. Аргументы после -- передаются в сам CLI sto701c:

mise run run -- -i INPUT.md --pdf OUT.pdf --docx OUT.docx
# ^^ всё справа передаётся программе sto701c

Чтобы собрать все входные примеры из samples/, используйте:

mise run samples

Эта команда создаёт out/org.*, out/md.*, out/mdx.*, out/coursework.*, out/diploma.*, out/nir.* и копирует краткое описание примеров в out/README.md.

Документированный пример

Основной пример для копирования — samples/diploma.md. Он показывает Markdown с YAML-предисловием, полный титульный лист дипломного проекта, подписантов, автоматическую дату и обычное содержимое работы.

Соберите его отдельно:

mkdir -p out
mise run run -- -i samples/diploma.md --pdf out/diploma.pdf --docx out/diploma.docx

Минимальная структура такого файла:

---
title: Технологическое перевооружение производства глифталевых лаков
language: ru
ministry: Министерство науки и высшего образования Российской Федерации
university: Государственный технический университет
cathedra: Кафедра «Химическая технология органических покрытий»
udc: 667.633.26
doc_kind: ДП
subject: Химическая технология высокомолекулярных соединений
doc_code: УНИВЕР 240501.65-008 ДП
approval: Заведующий кафедрой | д-р хим. наук, профессор | И. В. Голиков | auto
supervisor: Руководитель | канд. техн. наук, доцент | М. П. Чагин |
consultant: Консультант по охране труда | канд. техн. наук, доцент | Е. Л. Белороссов |
normcontrol: Нормоконтролер | канд. техн. наук, доцент | М. П. Чагин |
student: | | А. А. Сидоров |
group: ХТЛ-54
year: 2026
---
# Введение

Текст работы начинается после YAML-предисловия.

Формат подписантов: Роль | Степень, звание | Имя | Дата. Дата может быть явной (02.06.2026), автоматической (auto) или пустой для ручного заполнения. Дополнительные пояснения по каждому файлу есть в samples/README.md.

Титульный лист

Титульный лист построен по схеме из 15 модулей на формате A4. Данные передаются через ключевые слова; они работают и в Org, и в YAML-предисловии Markdown/MDX (в YAML ключи записываются строчными буквами).

Ключ Org Ключ YAML Модуль Примечания
#+MINISTRY: ministry 1 верхняя центрированная строка (ведомство)
#+UNIVERSITY: university 1 вторая центрированная строка
#+CATHEDRA: cathedra 1 «Кафедра «...»»
#+UDC: udc 2 индекс УДК, слева сверху
#+APPROVAL: approval 3 блок «ДОПУСКАЕТСЯ К ЗАЩИТЕ» (только ДП/ДР); формат с `
#+GRADING: grading 4 готовая строка оценки (заменяет шаблон)
#+GRADE: grade 4 слово-оценка, подставляется в шаблон
#+DEFENDED_BY: defended_by 4 руководитель, подписавший оценку; формат с `
#+DOC_KIND: doc_kind / kind 4,6,7 ДП·ДР·КП·КР·ПО·ПУ·ПТ·ПП·РГР·РГЗ·ЛР·ОР
#+SUBJECT: subject 6 специальность / дисциплина
#+DOC_CODE: doc_code / code 7 шифр «УНИВЕР 240501.65-008 ДП»
#+AGREED: agreed 8 принудительное «СОГЛАСОВАНО» (для ДП/ДР включается само)
#+SUPERVISOR: supervisor 9 руководитель работы (ДП)
#+CONSULTANT: consultant 10–12 повторяется для каждого консультанта
#+NORMCONTROL: normcontrol 13 нормоконтролёр
#+STUDENT: student 14 строка подписи студента; формат с `
#+GROUP: group 14 «ХТЛ-54»
#+YEAR: year 15 пишется без слова «год»
#+TOPIC: topic / doc_topic 5 заголовок темы (если отличается от #+TITLE:)
#+SIGNATURE_STYLE: signature_style 9–14 slashes (по умолчанию) или inline (___Имя)
#+DATE_STYLE: date_style 9–14 numeric (__.__.____) или verbose («___» __________ 2026)
#+UPPERCASE_TITLE: uppercase_title 5 yes (по умолчанию) или no для длинных тем

Поля #+MINISTRY: / #+UNIVERSITY: / #+CATHEDRA: в Org повторяются — несколько строк подряд объединяются переносами. В YAML тот же эффект достигается разделителем ; , например university: ФГБОУ; высшего образования; «Университет».

Доступные значения #+DOC_KIND:: ДП (дипломный проект), ДР (дипломная работа), КП / КР (курсовой проект/работа), ПО / ПУ / ПТ / ПП (виды практики), РГР / РГЗ (расчётно-графическая работа/задание), ЛР (лабораторная работа), ОР (обзорный реферат), НИР (научно-исследовательская работа).

Формат подписантов с разделителем |: Роль | Степень, звание | Имя Фамилия | ДД.ММ.ГГГГ.

  • Строка подписи формируется автоматически:
    • если имя заполнено, выводится ———————— /Имя Фамилия/ (длинная черта под живую подпись и напечатанное имя в косых чертах для ясности);
    • если имя пустое, ставится более длинная черта и подпись (подпись), чтобы документ можно было подписать от руки.
  • Поле даты принимает три формы:
    • явная дата (02.06.2026);
    • литерал auto — заменяется на сегодняшнюю дату при компиляции документа;
    • пустое значение — выводится как __.__.____ для рукописного заполнения.
  • Поле оценки (#+GRADE: / grade:) подставляется в предложение модуля 4 как ... защищён с оценкой <grade>; если не задано, ставится __________ для рукописного заполнения.

Пустые поля в конце можно опускать; пустые поля внутри строки нужно оставлять между разделителями (Имя | | Фамилия |).

Если ни одно из этих полей не задано, писатель возвращается к простой центрированной странице Title / Subtitle / Authors / Date, так что существующие простые документы продолжают работать без изменений.

Пример (курсовая работа, Org)

#+TITLE: Исследование системы неразрушающего контроля
#+MINISTRY: Министерство науки и высшего образования Российской Федерации
#+UNIVERSITY: Государственный технический университет
#+CATHEDRA: Кафедра «Технология металлов»
#+UDC: 620.179
#+DOC_KIND: КР
#+SUBJECT: Основы технологического контроля
#+DOC_CODE: УНИВЕР 200503.65-007 КР
#+GRADE: отлично
#+DEFENDED_BY: Руководитель | канд. техн. наук, доцент | (личная подпись) Е. Ф. Трофимов | 02.06.2026
#+NORMCONTROL: Нормоконтролер | канд. техн. наук, доцент | (личная подпись) Е. Ф. Трофимов | 02.06.2026
#+STUDENT: | | (личная подпись) А. А. Ушаков | 02.06.2026
#+GROUP: ЭСК-42м
#+YEAR: 2026

Полные примеры — samples/coursework.org и samples/diploma.md.

Решения по оформлению

  • Страница: A4 (×ばつ297 мм), поля слева 30 / справа 10 / сверху 20 / снизу 20 мм.
  • Основной шрифт: Times New Roman, 14 пт, чёрный, одинарный межстрочный интервал. В PDF подставляется DejaVu Serif, потому что TNR не подлежит свободному распространению. Для титульного листа можно подключать TTF через CSS @font-face и применять их через font-family.
  • Абзацный отступ: первая строка 12,5 мм (≈ 5 знаков), единый по всему документу.
  • Нумерация разделов: 1, 1.1, 1.1.1, 1.1.1.1 — до 4 уровней.
  • Заголовки: первая буква заглавная, без точки, без подчёркивания, без переносов.
  • Отбивка заголовков: 3 одинарных межстрочных интервала вокруг заголовков разделов, 2 — вокруг заголовков подразделов.
  • Номера страниц: арабские, в правом верхнем углу; на титульном листе не выводятся.
  • Таблицы: «Таблица N — Заголовок» над таблицей.
  • Рисунки: «Рисунок N — Заголовок» под рисунком, по центру.
  • Структурные ненумерованные заголовки (Содержание, Введение, Заключение, Список используемых источников, Приложение ...) центрируются и не нумеруются.

Инструменты: mise

В проекте используется mise для управления инструментарием OCaml/opam и для запуска задач. Создаётся локальный opam-switch (./_opam/), чтобы системный OCaml не затрагивался.

Первичная настройка

cd sto701c
mise install # ставит ocaml@5.2.1 и opam@2.3.0 из mise.toml
mise run bootstrap
mise run deps

Повседневные команды

Задача Что делает
mise run build dune build в локальном switch
mise run samples Сборка и компиляция samples/* в ./out/
mise run run -- -i FILE.org --pdf out.pdf --docx out.docx Запуск CLI на своём входе
mise run clean dune clean и удаление out/
mise run test Заглушка для dune runtest
mise run fmt dune build @fmt --auto-promote (если установлен ocamlformat)

mise run сам подтягивает версии OCaml/opam проекта, после чего каждая задача оборачивает свою команду в opam exec --switch=. --, чтобы dune и зависимости разрешались относительно локального switch.

CLI

sto701c [-i PATH] [-f org|md|mdx] [--style STYLE.css] [--pdf OUT.pdf] [--docx OUT.docx]
  • -i / --input — путь к входному файлу (- — stdin; по умолчанию).
  • -f / --formatorg, md или mdx. Если не указан, определяется по расширению.
  • --pdf / --docx — нужно указать хотя бы один.
  • --style — путь к CSS-файлу. По умолчанию используется styles/sto701.css, если файл есть. CSS из документа переопределяет файловые настройки. В CSS поддерживается @import с путями относительно файла, где он указан.

CSS-конфигурация

Базовая СТО-разметка лежит в styles/sto701.css. Компилятор берёт оттуда размер страницы, поля и координаты областей титульного листа через @page и вложенные правила вроде title-page header, title-page title, title-page student. Шрифты для PDF можно подключать через @font-face и применять через font-family внутри модулей.

@import "title-page.css";
@import url("fonts.css");
@font-face {
 font-family: "TitleSerif";
 src: url("DejaVuSerif.ttf");
}
@page {
 size: 210mm 297mm;
 margin: 20mm 10mm 20mm 30mm;
 title-page title {
 top: 96mm;
 left: 30mm;
 width: 170mm;
 font-family: "TitleSerif";
 font-size: 18pt;
 font-weight: bold;
 text-transform: uppercase;
 }
}

Примеры

mise run samples
mise run run -- -i my-thesis.org --style styles/sto701.css --pdf thesis.pdf --docx thesis.docx
mise run run -- -i README.md --pdf out.pdf
cat draft.mdx | mise run run -- --pdf draft.pdf --docx draft.docx

Поддерживаемые возможности входа

Org (подмножество, влияющее на экспорт)

  • Ключевые слова документа: #+TITLE, #+SUBTITLE, #+AUTHOR, #+DATE, #+LANGUAGE, #+KEYWORDS, #+OPTIONS, #+MACRO, #+BIBLIOGRAPHY, #+TODO, #+CAPTION, #+NAME, #+ATTR_*.
  • Заголовки с состояниями TODO/DONE/WAITING, приоритетом [#A], тегами :tags:.
  • Списки: маркированные (- / + / *), нумерованные (1. / 1)), описательные (ТЕРМИН :: ОПР), вложенные, чек-боксы ([ ] / [X]).
  • Таблицы с разделителями |---+---| и выравниванием :--: / :-- / --:.
  • Блоки: SRC, EXAMPLE, QUOTE, VERSE, CENTER, EXPORT, COMMENT.
  • Ящики: :PROPERTIES: / :LOGBOOK: / :END:.
  • Определения и ссылки сносок ([fn:NAME]).
  • Строчная разметка: *жирный*, /курсив/, _подчёркнутый_, +зачёркнутый+, ~код~, =verbatim=, нижний _{x} / верхний ^{x} индекс.
  • Математика: $inline$, \(inline\), \[display\], плюс #+BEGIN_EXPORT latex.
  • Ссылки: [[адрес][текст]]; расширения изображений определяются автоматически; префикс file:.
  • Цитирование: [cite:@key].
  • Раскрытие макросов: {{{name(arg)}}} из определений #+MACRO:.
  • Метки/якоря: <<anchor>>.
  • Сырой экспорт: @@latex:...@@, @@ooxml:...@@.

Исполнение блоков Babel сознательно не выполняется.

Markdown (CommonMark + GFM)

  • YAML-предисловие (--- ... ---) с title, author, date, language, keywords и произвольными ключами в meta.custom.
  • ATX-заголовки (#######) и setext-заголовки (подчёркивание === / ---).
  • Абзацы, цитаты (> ...), тематические разделители (--- / *** / ___).
  • Огороженные блоки кода (``` и ~~~) с тегом языка.
  • Списки нумерованные и маркированные, с чек-боксами задач (- [ ] / - [x]).
  • GFM-таблицы с правилом выравнивания (|:--|:--:|--:|).
  • Строчный код (`...`), курсив (* / _), полужирное (** / __), ссылки ([текст](url)), изображения (![alt](src)).

MDX

Обрабатывается как Markdown после удаления всех PascalCase JSX-тегов: <Tag ...>, </Tag> и <Tag .../> удаляются; их содержимое сохраняется как обычный Markdown. По условию задачи компоненты не отображаются в пользовательские рендеры.

Структура проекта

Код разбит на небольшие, узконаправленные модули (ни один не превышает ~240 строк). Внутри lib/ dune использует (include_subdirs unqualified), поэтому каждый .ml становится одноуровневым модулем библиотеки Sto701c независимо от папки.

sto701c/
 mise.toml # инструментарий и задачи
 dune-project # метаданные OCaml-проекта
 bin/
 main.ml # CLI (Cmdliner)
 dune
 lib/
 dune
 core/ # общие типы и проходы
 ast.ml # AST документа
 style.ml # профиль оформления
 title_page.ml # модель титульного листа
 numbering.ml # иерархическая нумерация разделов
 parser/ # все парсеры входов
 inline_ctx.ml # примитивы курсора сканирования
 inline_emph.ml # помощники emphasis / ссылок
 inline_parser.ml # строчная разметка (org + md)
 org/
 org_lexer.ml # построчный токенизатор org
 org_helpers.ml # курсор, атрибуты, разбиение заголовков
 org_tables.ml # таблицы `| ... |`
 org_block_body.ml # сборщик тела #+BEGIN_xxx
 org_blocks.ml # списки + ящики + основной парсер
 org_parser.ml # мета + макросы + точка входа
 md/
 md_front.ml # YAML-предисловие
 md_inline_helpers.ml # детект ATX/setext/fence/table/bullet
 md_blocks.ml # взаимно рекурсивный парсер блоков
 md_parser.ml # точка входа (вкл. срез JSX в MDX)
 writer/
 pdf/ # бэкенд PDF
 pdf_encoding.ml # UTF-8 → Identity-H hex-глифы
 ttf_metrics.ml # минимальный читатель TrueType
 pdf_objects.ml # сборщик PDF-объектов + встраивание шрифтов
 pdf_layout.ml # геометрия, прогоны, разбиение на строки
 pdf_page.ml # состояние страницы + эмиттер строк
 pdf_para.ml # абзац / заголовок / список
 pdf_blocks.ml # код / таблица / рисунок / диспетчер
 pdf_title.ml # титульный лист
 pdf_writer.ml # сериализация + точка входа
 docx/ # бэкенд DOCX
 docx_runs.ml # rPr + строчные → OOXML-прогоны
 docx_blocks.ml # абзацы / списки / таблицы / рисунки
 docx_title.ml # титульный лист
 docx_doc.ml # sectPr + сборка document.xml
 docx_parts.ml # styles/numbering/settings/header xml
 docx_writer.ml # упаковка в zip (точка входа)
 samples/
 sample.org sample.md sample.mdx
 tests/ # заглушка
 out/ # сгенерированные выходы (mise run samples)

Зависимости (ставятся mise run deps)

  • dune 3.x — система сборки
  • camlzip — ZIP-контейнер для DOCX
  • camlpdf — подключён на будущее (текущий PDF-писатель самописный)
  • uutf, uucp — Unicode-утилиты
  • re — регулярные выражения
  • cmdliner — разбор CLI

Ограничения

  • Встроенные изображения отображаются как текст-заглушка (alt) в DOCX и как блоки [caption] в PDF. Встраивание пикселей оставлено на будущее.
  • Рендер таблиц в PDF обрезает слишком длинный текст ячейки до одной строки.
  • LaTeX-математика отображается курсивом, без типографского набора.
  • Стилизация DOCX использует стиль Normal по умолчанию — настройте собственный reference.docx, если нужны дополнительные именованные стили.