JSON динамического раздела

Раздел dynamic хранит один JSON-источник и при запуске viewer разворачивает его в корневую страницу и вложенное дерево виртуальных страниц. Источник, контент и Base64-ресурсы встраиваются в экспортированный HTML; внешний JSON endpoint не используется.

Полная структура

{
  "schemaVersion": "1.0",
  "settings": {
    "navigation": {
      "expandedByDefault": false,
      "placement": "toc",
      "showRootInToc": true
    },
    "search": { "enabled": true },
    "toc": {
      "enabled": true,
      "minHeadingLevel": 2,
      "maxHeadingLevel": 4
    }
  },
  "styles": ".dynamic-badge { color: #2563eb; }",
  "scripts": "console.log('Dynamic section page opened');",
  "resources": [
    {
      "id": "logo",
      "contentType": "image/png",
      "encoding": "base64",
      "content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=",
      "fileName": "logo.png"
    }
  ],
  "root": {
    "contentType": "markdown",
    "content": "# Каталог\n\n![Логотип](res://logo)",
    "toc": true,
    "styles": ".dynamic-badge { font-weight: 700; }"
  },
  "pages": [
    {
      "id": "overview",
      "title": "Обзор",
      "slug": "overview",
      "contentType": "markdown",
      "content": "## Введение\n\nОткройте [подробности](ofd-page:details).",
      "hidden": false,
      "searchable": true,
      "toc": true,
      "scripts": "document.getElementById('main-article')?.setAttribute('data-page-ready', 'true');",
      "children": [
        {
          "id": "details",
          "title": "Подробности",
          "slug": "details",
          "contentType": "html",
          "content": "<h2>Подробности</h2><img src=\"res://logo\" alt=\"Логотип\">"
        }
      ]
    }
  ]
}

Обязательные поля

  • schemaVersion должно иметь значение "1.0".
  • resources и pages должны быть массивами, даже если они пусты.
  • root должен содержать contentType и строковое поле content.
  • Каждой странице нужны уникальный id, непустой title, contentType и строковое поле content.

contentType принимает значение html или markdown. Формат каждой страницы выбирается независимо от корня и остальных страниц.

Настройки

  • settings.navigation.expandedByDefault раскрывает навигацию по страницам при первом отображении.
  • settings.navigation.placement принимает toc, header-toc или toc-otp. Эти режимы размещают страницы и заголовки текущей страницы в оглавлении, шапке или панели «На этой странице».
  • settings.navigation.showRootInToc определяет, показывать ли ссылку на основной раздел в оглавлении. Значение по умолчанию — true.
  • settings.search.enabled определяет участие динамического раздела в поиске. Значение по умолчанию — true.
  • settings.toc.enabled задает стандартное поведение оглавления заголовков для корня и страниц. minHeadingLevel и maxHeadingLevel принимают значения от 1 до 6, минимум не может быть больше максимума.

Отсутствующие настройки нормализуются как свернутая навигация в toc с показом основного раздела, включенный поиск и выключенное оглавление заголовков с уровнями от 2 до 4.

Стили и скрипты

Необязательные строки styles и scripts верхнего уровня действуют для корня и всех виртуальных страниц. Объект root и каждая страница могут задать собственные необязательные styles и scripts. Сначала применяется код сохраненного section, затем общий код dynamic section и код конкретной страницы. Стили активны только при открытой странице, скрипты выполняются при каждом ее открытии.

Источники без этих полей остаются корректными источниками схемы 1.0 и работают как раньше.

Страницы и маршруты

slug становится сегментом маршрута страницы. Он может содержать строчные латинские буквы, цифры и одиночные дефисы. Если поле пропущено, значение создается из заголовка. Slug должен быть уникальным среди соседних страниц, а ID страницы — во всем источнике.

children содержит вложенные страницы. Источник может включать не более 2000 страниц с глубиной не более 10 уровней. hidden скрывает страницу из навигации, searchable со значением false исключает только эту страницу из поиска, а toc переопределяет общую настройку оглавления.

Для ссылки на другую виртуальную страницу используйте ofd-page:page-id. Указанный ID должен существовать.

Встроенные ресурсы

Каждому ресурсу нужны уникальный строчный id, непустой MIME contentType, encoding: "base64" и корректное непустое Base64-поле content. Необязательное поле fileName используется при открытии или скачивании файла. ID может содержать латинские буквы, цифры, точки, дефисы и подчеркивания.

Обращайтесь к ресурсу из HTML или Markdown через res://resource-id. Каждый указанный ID должен существовать. Исполняемые MIME-типы, HTML-документы, скрипты, inline event handlers, исполняемые URL и ресурсы, загружаемые через http:, https:, data: или blob:, отклоняются.

Проверка

Редактор показывает ошибки с путем к некорректному полю, например pages[2].content. Перед применением источника проверьте количество страниц, ресурсов и максимальную глубину. Сгенерированные страницы не хранятся как отдельные разделы: для изменения структуры или контента замените JSON.