Skip to content

Руководство по подаче работ ​

В этом руководстве описаны два способа подачи работ, поддерживаемые Papex, и приведён полный справочник по подаче исходного пакета вместе с его манифестом papex.json и инструментарием XeLaTeX.


1. Обзор ​

Papex предлагает два входа подачи для разных сценариев работы:

СпособТочка входаАудиторияОсобенности
Подача через формуВеб-страница «Подать → Форма» / POST /api/papersЭпизодические авторыЗаполнение названия, аннотации, авторов и т. д. в браузере; прямая загрузка PDF полного текста (≤50 МБ)
Загрузка исходного пакетаВеб-страница «Подать → Исходный пакет» / POST /api/submit/archiveАвторы на LaTeXУпакуйте свои исходники с манифестом papex.json в tar.gz; платформа создаёт работу, связывает цитирования и собирает PDF автоматически

Оба способа используют одну и ту же логику приёма (createSubmission + addCitation). Они отличаются лишь источником метаданных и тем, как создаются тело/PDF.

Не хотите работать с командной строкой? Вы также можете использовать встроенный модуль Онлайн-авторинг, чтобы визуально редактировать papex.json, писать тело работы и «экспортировать tar.gz» или «опубликовать в один клик» прямо в браузере — архив, который он создаёт, полностью эквивалентен загрузке исходного пакета.


2. Способ 1: Подача через форму ​

Нажмите Подать в верхней навигации, выберите вкладку Форма, заполните поля и нажмите «Подать работу»:

  • Название, Аннотация
  • Основная категория (обязательно, код из дерева категорий, напр. cs.LG), Дополнительные категории (через запятую, необязательно)
  • Авторы (добавьте сколько нужно; порядок — это порядок авторов)
  • Загрузить PDF (необязательно): перетащите или выберите PDF (≤50 МБ); платформа сохраняет его и автоматически связывает ссылки. DOI (необязательно), Лицензия (по умолчанию CC-BY-4.0), Примечание к версии (необязательно)

Работа затем попадает в очередь рецензирования. Подача через форму отправляется как multipart/form-data: meta — это JSON-строка метаданных, pdf — необязательный PDF-файл.

http
POST /api/papers
Content-Type: multipart/form-data; boundary=...

--boundary
Content-Disposition: form-data; name="meta"

{"title":"…","abstract":"…","primaryCategoryId":"cs.LG","secondaryCategoryIds":["stat.ML"],"authors":[{"name":"Ming Zhang","order":0}],"doi":"","license":"CC-BY-4.0","comments":"","basePaperId":null}
--boundary
Content-Disposition: form-data; name="pdf"; filename="paper.pdf"
Content-Type: application/pdf

<binary PDF data>
--boundary--

PDF необязателен. При наличии конечная точка сохраняет его для версии работы, разбирает тело, связывает внутренние цитирования и возвращает { pdfUrl, pages, referencesExtracted, referencesLinked }. Веб-форма отправляет это автоматически; API-клиенты могут также отправлять обычный JSON (без pdf).


3. Способ 2: Загрузка исходного пакета ​

Загрузка исходного пакета — это сценарий для авторов: вы пишете работу на LaTeX, описываете метаданные и ссылки в структурированном papex.json, упаковываете всё в tar.gz и загружаете за один шаг. Серверная часть выполняет «распаковка → проверка → приём →

связывание цитирований → сборка PDF» end to end.

3.1 Структура пакета ​

Рекомендуемая, хотя и минимальная, структура пакета:

my-paper.tar.gz
├── papex.json            # обязательно: манифест работы (метаданные + разделы + ссылки)
├── papex-template.tex    # основной документ (используйте предоставленный в репозитории papex-template.tex)
├── papex.cls             # класс документа (необязательно; сервер копирует из PAPEX_LATEX_DIR, если отсутствует)
├── references.bib        # необязательно: написанный вручную BibTeX; иначе автоматически генерируется из ссылок
└── sections/             # разделы тела (.tex-фрагменты, на которые ссылаются по порядку из papex.json)
    ├── 00-intro.tex
    ├── 01-related.tex
    └── …

Пакет должен содержать papex.json; иначе загрузка отклоняется (HTTP 400).

3.2 Справочник полей papex.json ​

Полная JSON-схема находится в papex-latex/papex.schema.json. Ключевые поля и их назначения:

ПолеТипОбязательноПримечания / цель в БД
paper.idstring (YYMM.NNNNN)нетЕсли совпадает с вашей (или админской) существующей работой → подаётся как новая версия; иначе назначается новый ID работы
paper.titlestringда→ papers.title / paper_versions.title
paper.abstractstringда→ paper_versions.abstract
paper.keywordsstring[]нетОтображается после аннотации в PDF (отдельно не хранится)
paper.primaryCategoryIdstringда→ papers.primaryCategoryId; должна существовать в таблице категорий, иначе 400
paper.secondaryCategoryIdsstring[]нет→ paper_categories (не основные)
paper.doistringнет→ paper_versions.doi, также записывается в граф цитирований (target_doi)
paper.licensestringнет→ paper_versions.license, по умолчанию CC-BY-4.0
paper.versionNotestringнет→ paper_versions.comments
paper.subtitlestringнетОтображается под названием в PDF
paper.venuestringнетОтображается в блоке названия (напр. конференция/журнал)
authors[].namestringда→ authors + paper_authors (по order)
authors[].orcidstringнетСноска об авторе
authors[].emailstringнетИспользуется как контакт ответственного автора
authors[].affiliationstringнетСтрока → разрешается в affiliations.id через findOrCreateAffiliation
authors[].correspondingbooleanнетСноска «Ответственный автор»
authors[].equalContributionbooleanнетСноска «Равный вклад»
authors[].footnotestringнетСвободная сноска
references[].keystringдаBibTeX-ключ цитирования
references[].doi / arxivIdstringнетРазрешается во внутреннюю работу через resolveTarget; иначе url/title попадают в citations
references[].url / title / authors / year / venuestringнетЗаполняют citations и автогенерируемый references.bib
sections[]string[]даУпорядоченный список путей к .tex разделов; используется только LaTeX, не хранится в таблицах
appendices[]string[]нетУпорядоченный список путей к .tex приложений
acknowledgments / fundingstringнетОтображается в разделе благодарностей/финансирования PDF
buildobjectнетПараметры сборки: style (numeric/authoryear), fontset (fandol/windows/mac/ubuntu), passthrough (поля, освобождённые от экранирования) и т. д.

Отличие от подачи через форму: papex.json использует affiliation как строку вместо числового affiliationId; слой отображения ищет или создаёт строку affiliations. Также добавляются специфичные для LaTeX поля sections, references, appendices, build.

3.3 Инструментарий XeLaTeX (papex-latex/) ​

Специальный инструментарий XeLaTeX поставляется в papex-latex/:

papex-latex/
├── papex.cls              # класс документа (ctex + authblk + biblatex, CJK+английский, макросы метаданных, колонтитулы)
├── papex-template.tex     # основной документ, автоматически \input сгенерированных _papex_*.tex и разделов
├── papex-build.py         # сборщик без зависимостей (только стандартная библиотека; опционально jsonschema)
├── papex.schema.json      # контракт манифеста draft-07
├── latexmkrc              # необязательная конфигурация latexmk
├── README.md              # использование инструментария
└── example/               # полный пример пакета (китайская работа + 5 разделов + приложение)

Ключевые особенности papex.cls

  • CJK + английский: основан на ctex (scheme=plain), по умолчанию fontset=fandol (поставляется с TeX Live, компилируется на сервере «из коробки»); локально переключается через windows / mac / ubuntu.
  • Авторы/аффилиации: authblk с общими аффилиациями, сносками ответственного автора и равного вклада.
  • Ссылки: biblatex + biber, выбор numeric / authoryear.
  • Макросы метаданных: \papexPaperId (ID работы над названием), \papexSubtitle, \papexVenue, \papexDoi (автоссылка doi.org), \papexVersionNote, \papexKeywords (после аннотации), \papexLicense (нижний колонтитул), \papexRunningTitle (верхний колонтитул).
  • Независимость от бренда: без формулировок preprints / arXiv, в соответствии с «свободным от arXiv» соглашением о продукте.

Процесс papex-build.py

  1. Прочитать papex.json (ввод может быть каталогом / одним json / .tar.gz).
  2. Проверить (предпочтительно jsonschema, иначе встроенные проверки).
  3. Экранировать текстовые поля (title / abstract / authors / affiliation / keywords / acknowledgments …), генерируя _papex_meta.tex, _papex_abstract.tex, _papex_sections.tex, _papex_backmatter.tex, _papex_appendices.tex и references.bib (пропускается, если архив уже содержит references.bib).
  4. Скомпилировать через latexmk -xelatex (--emit-only выдаёт только промежуточные файлы, --validate только проверяет).
  5. Файлы разделов .tex пишутся автором вручную и поддерживают полный LaTeX (включая математику); они не экранируются. Используйте build.passthrough, чтобы освободить текстовые поля JSON от экранирования.

3.4 Локальный предпросмотр и сборка ​

bash
# перейти в пример пакета
cd papex-latex/example

# выдать только промежуточные .tex/.bib (TeX не нужен — полезно для проверки экранирования/структуры)
python3 ../papex-build.py . --emit-only

# проверить только papex.json
python3 ../papex-build.py . --validate

# сгенерировать и скомпилировать PDF (требуется локальный TeX Live)
python3 ../papex-build.py .

Упаковка и подача:

bash
tar -czf my-paper.tar.gz papex.json papex-template.tex references.bib sections/

3.5 Загрузка на сайте ​

  1. После входа нажмите Подать в верхней навигации и выберите вкладку Исходный пакет.
  2. Перетащите tar.gz в зону сброса или нажмите для выбора файла (только .tar.gz / .tgz, ≤ 50 МБ).
  3. Нажмите «Загрузить и подать»; платформа возвращает ID работы и версию с примечаниями об обработке (напр. PDF собирается в фоне).
  4. Нажмите «Перейти к работе», чтобы открыть созданную страницу работы.

4. Сквозная обработка (серверная часть) ​

После загрузки сервер обрабатывает пакет следующим образом (исходный код в src/lib/latex/):

author ──tar.gz──> POST /api/submit/archive (multipart: file)
                         │
                         ▼
                  ① распаковка (tar.ts)
                     gunzip + парсер ustar/GNU/PAX без зависимостей, защита от обхода путей
                         │
                         ▼
                  ② чтение papex.json → coerceManifest() проверяет обязательные поля
                         │
                         ▼
                  ③ mapToCreatePaperInput()
                     · primaryCategoryId должна существовать (иначе 400)
                     · строка affiliation → affiliations.id (findOrCreateAffiliation)
                     · paper.id совпадает с собственной/привилегированной работой → новая версия
                         │
                         ▼
                  ④ createSubmission() принимает (повторно использует существующую транзакцию)
                         │
                         ▼
                  ⑤ mapReferencesToCitations() → addCitation() связывает граф цитирований
                         │
                         ▼
                  ⑥ опциональная сборка XeLaTeX (серверный latexmk)
                     → savePdfBuffer() сохраняет → обновляет paper_versions.pdfUrl
                     (отсутствие latexmk → только предупреждение, приём не затрагивается)
                         │
                         ▼
                 возвращает { paperId, version, warnings, pdfUrl? }

Ключевые модули

ФайлОтветственность
src/lib/latex/tar.tsgunzip + parseTar без зависимостей (ustar / длинные имена GNU / расширенные заголовки PAX), writeEntries с защитой от обхода путей
src/lib/latex/papex-json.tsтипы PapexManifest, coerceManifest, mapToCreatePaperInput, mapReferencesToCitations
src/lib/latex/papex-archive.tsоркестрация processSubmissionArchive; buildAndStorePdf проверяет latexmk и компилирует/сохраняет PDF
src/app/api/submit/archive/route.tsпринимает multipart/form-data file (≤50 МБ), аутентифицирует, сопоставляет ошибки с HTTP-статусом

Сопоставление кодов ошибок (HTTP)

Внутренняя ошибкаHTTPЗначение
MANIFEST_MISSING400В архиве отсутствует papex.json
MANIFEST_JSON_INVALID400papex.json не является корректным JSON
MANIFEST_INVALID:…400Отсутствует обязательное поле (title/abstract/primaryCategoryId/authors/sections)
CATEGORY_NOT_FOUND:cs.X400Код категории не существует
ARCHIVE_PARSE_FAILED / ARCHIVE_EMPTY400Архив повреждён или пуст
FORBIDDEN403Нет прав подавать новую версию этой работы
PAPER_NOT_FOUND404Заявленная целевая работа для новой версии не существует
прочее500Внутренняя ошибка (вкл. ID_GENERATION_FAILED)

5. Справочник API ​

POST /api/papers ​

Конечная точка подачи через форму. Запрос — multipart/form-data (см. Раздел 2): поле meta — JSON-строка метаданных, поле pdf — необязательный PDF-файл (≤50 МБ). Требуется аутентификация. Возвращает { paperId, version }, а при загрузке PDF — дополнительно pdf: { pdfUrl, pages, referencesExtracted, referencesLinked }. API-клиенты также могут отправлять обычный JSON (без pdf).

POST /api/submit/archive ​

Конечная точка исходного пакета.

  • Аутентификация: требуется (cookie).

  • Запрос: multipart/form-data, поле file — это tar.gz (≤ 50 МБ).

  • Успех (201):

    json
    {
      "paperId": "2608.00007",
      "version": 1,
      "warnings": [],
      "pdfUrl": "https://…/api/papers/2608.00007/pdf/1"
    }
  • Ошибка: JSON с соответствующим сообщением об ошибке; коды состояний согласно таблице ошибок.


6. Развёртывание и эксплуатация ​

  • TeX Live: серверу нужен texlive (с xelatex, biber, latexmk) и collection-langchinese, чтобы были доступны шрифты fandol.
  • Переменные окружения:
    • PAPEX_LATEX_BIN: путь к latexmk (по умолчанию PATH).
    • PAPEX_LATEX_DIR: каталог с papex.cls; копируется, когда архив его не содержит.
  • Песочница и ресурсы: запускайте компиляцию LaTeX в изолированной среде с ограничениями CPU/памяти/таймаута и отключите \write18 (shell-escape) и сетевой доступ, чтобы вредоносные исходники не могли выполнять команды.
  • Асинхронность: компиляция медленная; в production предпочтительна очередь асинхронных задач (вернуть paperId сразу, обратный вызов для обновления pdfUrl, когда PDF будет готов), чтобы не блокировать запрос.
  • Деградация при отсутствии: если latexmk недоступен, processSubmissionArchive записывает warnings и пропускает сборку PDF; приём и связывание цитирований продолжают работать.
  • Хранение PDF: повторно использует savePdfBuffer (потоковый маршрут /api/papers/{id}/pdf/{version}); новый слой хранения не нужен.

7. Безопасность ​

  • Обход путей: writeEntries проверяет реальный путь каждой записи через path.relative, отклоняя .. и абсолютные пути; parseTar удаляет начальный ./.
  • Ограничение размера: маршрут ограничивает file до ≤ 50 МБ.
  • Злоупотребление ресурсами: компиляция имеет лимиты таймаута/ресурсов; рассмотрите ограничение частоты по пользователям.
  • shell-escape: команда компиляции не передаёт -shell-escape, не позволяя исходникам выполнять системные команды.

8. Часто задаваемые вопросы ​

В: Дублирует ли исходный пакет данные подачи через форму? Нет. Оба используют одну и ту же логику приёма; отличается только источник метаданных.

В: Обязательно ли использовать шаблон XeLaTeX?papex.cls и papex-template.tex определяют итоговую вёрстку PDF; вы пишете только файлы разделов .tex и papex.json. Если архив не содержит papex.cls, сервер использует тот, что из PAPEX_LATEX_DIR.

В: Могу ли я использовать математику, рисунки, свои команды в разделах? Да. Файлы разделов .tex пишутся вручную и поддерживают полный LaTeX, без экранирования. Поместите свои команды преамбулы в файлы разделов или papex-template.tex.

В: Я не вижу PDF сразу после подачи? Если TeX Live не настроен на сервере, pdfUrl пуст, и страница сообщает «PDF собирается в фоне». Настройте его и повторите подачу; в production используйте вместе с очередью асинхронных задач.

В: Как подать новую версию работы? Укажите paper.id в papex.json равным вашему существующему ID работы (и у вас должно быть право подачи для неё); платформа примет её как новую версию.

В: Как цитирования связываются автоматически?doi / arxivId из массива references разрешаются во внутренние работы через resolveTarget, и создаётся ребро цитирования; прочие записи сохраняются как url / title в графе цитирований.

Papex is open source under the Apache-2.0 license.