Как устроен документ

Редактор разделяет настройки на два уровня: документ целиком и отдельные разделы внутри него. Это важно, потому что стили, скрипты, переменные, языки и экспорт работают по-разному в зависимости от уровня.

Уровень документа

На уровне документа хранятся общие параметры всего итогового HTML-файла: название документа, заголовок экспортированного файла, язык документа, логотип, фавикон, Open Graph-поля, настройки шапки и подвала, цветовые схемы, поиск, переключатель языков и другие глобальные опции.

Здесь же находятся ресурсы, которые относятся ко всему документу сразу: переменные, список поддерживаемых языков контента, пользовательские стили и пользовательские скрипты.

При экспорте document CSS вставляется прямо в <head> итогового файла, а document JavaScript добавляется перед закрывающим </body>. Такой код работает глобально и может влиять на все страницы, меню, шапку, подвал и любые элементы интерфейса чтения.

Если в документе заданы внешние CSS- или JS-файлы, они не встраиваются внутрь HTML, а подключаются как обычные <link> и <script src>. Это удобно для CDN и аналитики, но для работы таких файлов нужен доступ к сети и стабильный внешний URL.

Минификация document CSS и document scripts выполняется во время экспорта. В редакторе код не исполняется как в готовом экспортированном файле: итоговое поведение нужно проверять именно в экспортированном HTML.

Типы разделов

page — основной тип раздела для контента, который должен открываться прямо внутри документа: инструкции, explanation, onboarding, release notes, tutorial, policy, knowledge base article и любые страницы с текстом, изображениями, примерами, поиском, оглавлением, локальными стилями, section scripts и мультиязычностью.

link нужен не для контента, а для маршрутизации читателя. Используйте его, когда сам материал должен открываться по URL: внешний сайт, внешняя документация, страница поддержки, GitHub, форма, отдельный сервис или даже другой разделенный документ.

related нужен для переиспользования shared page-раздела в нескольких местах. Используйте его, когда одна и та же страница должна появляться в нескольких документах: общая установка, требования, блок безопасности, единые условия интеграции, FAQ или типовой onboarding. Вы обновляете источник один раз, а related-разделы получают тот же контент, section styles, section scripts и поведение оглавления.

api используйте для структурированной API Reference по C#-коду: пространства имен, классы, структуры, интерфейсы, records, enums, delegates, конструкторы, методы, свойства, индексаторы, поля, параметры методов и XML summary. Такой раздел подходит для SDK, библиотек, внутренних платформ, game tools и plugin APIs, где reference нужно регулярно собирать из исходников и держать синхронной с кодом.

dynamic используйте для встроенного JSON-источника, который описывает корневую страницу, вложенные страницы и переиспользуемые Base64-ресурсы. Содержимое каждой страницы может иметь тип html или markdown. Экспортированный viewer создает эти страницы во время выполнения. Ресурсы подключаются через res://resource-id; внешний JSON и внешние ресурсы страниц не поддерживаются.

Подготовка API-раздела

API-раздел в One File Docs принимает JSON. Рабочий процесс простой: извлеките описание API из C#-исходников во внешний JSON-файл, затем загрузите этот файл в раздел типа api.

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

  • CSharpApiExtractor — основной Roslyn-based extractor, который сканирует .cs-файлы и строит JSON-описание public API.
  • CSharpApiExtractorGUI — desktop GUI-оболочка для того же extraction workflow, ориентированная на более простой ручной экспорт и работу с несколькими проектами без программирования.

CSharpApiExtractor читает .cs-файлы напрямую, не требует разбора .csproj, берет summary из комментариев /// и формирует JSON с описанием public API. Отдельно он собирает undocumented items в список MissedItems, чтобы было проще контролировать качество reference-документации.

CSharpApiExtractor выбирайте для автоматической сборки: CI/CD, регулярные релизы, несколько пакетов и сценарии, где JSON должен обновляться вместе с кодом.

CSharpApiExtractorGUI выбирайте для ручной работы: редкие обновления, разовый экспорт, несколько project-конфигураций и случаи, когда JSON удобнее собрать через desktop-интерфейс.

Если reference — только часть документа, размещайте справку в api-разделе, а guides, tutorials, migration notes и integration walkthroughs оформляйте как обычные page-разделы рядом.

Структура разделов

Разделы образуют дерево. У каждого раздела есть заголовок, внутренний ID, тип, позиция в иерархии и, при необходимости, родительский раздел. Именно из ID собираются пути и якоря внутри экспортированного файла и HTML.

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

Для многоязычных документов у раздела можно указать конкретный язык или режим all. Тогда экспортированный файл покажет только подходящие страницы для выбранного языка.

Внутренняя перелинковка

Внутренние ссылки строятся на основе ID разделов и id якорей внутри контента. Поэтому перед перелинковкой сначала проверьте, что у нужной страницы задан понятный и стабильный ID в настройках раздела.

Чтобы сослаться на другой раздел, используйте обычную ссылку с hash-путем вида #section-id. Если раздел вложенный, путь будет составным: #parent-id/child-id.

Если ссылка должна вести не просто на страницу, а сразу к конкретному месту внутри нее, добавьте anchor после пути раздела: #section-id/anchor-id или #parent-id/child-id/anchor-id.

Якорь внутри страницы можно получить несколькими способами: задать id у заголовка или другого HTML-элемента вручную, использовать anchor-вставку в визуальном редакторе, либо включить генерацию оглавления, чтобы экспортированный файл сам проставил id у заголовков h1, h2 и h3.

Практически это выглядит так: ссылка #installation откроет страницу раздела, а ссылка #installation/system-requirements откроет ту же страницу и прокрутит экспортированный файл к якорю system-requirements.

Такую ссылку можно поставить прямо в контент page-раздела через обычный диалог вставки ссылки. Если нужен отдельный пункт меню, создайте раздел типа link и укажите тот же внутренний hash-адрес в поле URL.

Стили и скрипты документа

Document-level custom code нужен для общих правил: брендовые цвета, типографика, общие UI-правки интерфейса чтения, глобальные обработчики событий, счетчики, интеграции и общие хелперы.

Этот код подставляется в экспорт уже после сборки итогового файла. Поэтому document CSS может переопределять встроенные стили One File Docs, а document scripts могут обращаться к глобальному JavaScript API через window.OneFileDocsViewer.

В document CSS и scripts работают переменные документа и шаблонные условия. Если в коде есть {{productName}} или блоки вида {% if productName %}...{% endif %}, при экспорте они будут сначала раскрыты, а уже потом вставлены в HTML.

Стили и скрипты разделов

У каждого раздела можно задать собственные CSS, JavaScript, а также списки внешних CSS- и JS-файлов. Эти настройки действуют только на экспортированный файл и не являются глобальными настройками всего документа.

Section CSS работает как активный стиль текущей страницы. Когда пользователь открывает раздел, экспортированный файл записывает его CSS в отдельный <style id="active-section-custom-css">. При переходе в другой раздел это содержимое заменяется, а если CSS у нового раздела нет, стиль удаляется.

Внешние CSS-файлы раздела подключаются только на время просмотра этого раздела. При переключении страницы экспортированный файл удаляет предыдущие section stylesheet links и добавляет новые.

Section scripts выполняются при рендеринге раздела. Это значит, что один и тот же скрипт запускается заново каждый раз, когда пользователь снова открывает страницу. Если код добавляет обработчики событий, таймеры или DOM-узлы, его лучше писать идемпотентно, чтобы повторный вход в раздел не создавал дубликаты.

Внешние JS-файлы раздела тоже подключаются динамически при открытии страницы и снимаются при переходе на другую. Для сложной логики это полезно, когда код нужен только на одном экране, а не во всем документе.

Во время работы section scripts экспортированный файл генерирует события начала и завершения через API. Это позволяет привязывать аналитику, отладку и собственные интеграции к моменту показа конкретной страницы.

Что учитывать на практике

  • Document custom code используйте для правил, которые должны жить во всем HTML-файле.
  • Section custom code используйте для локальной логики конкретной страницы.
  • Если нужен офлайн-результат одним файлом, не полагайтесь на внешние CSS и JS URL.
  • Если section script изменяет DOM, рассчитывайте на повторный запуск при повторном открытии раздела.
  • Если нужно переиспользование поведения и оформления, выносите страницу в shared-раздел и подключайте ее через related.
  • Пользовательские стили и скрипты доступны только на Pro и применяются именно при экспорте.