Сайдбар документации
Левое дерево документации (его выводит вставка onpress/docs-nav) своего хранилища не имеет — оно целиком выводится из страниц:
- пункт — страница, собираемая фреймом документации;
- вложенность — родитель страницы, но только среди таких же страниц: если родитель не страница документации, пункт встаёт в корень;
- порядок —
menu_orderсреди соседей; - подпись — поле
nav_labelстраницы, а без него — её заголовок; - скрытый пункт — страница с меткой скрытия: она опубликована и открывается, но в дереве её нет.
Отсюда два следствия, о которых нужно помнить до первого вызова. Перенос пункта в другую ветку меняет адрес страницы — вложенность и есть родитель. Скрытие раздела с видимыми детьми поднимает детей в корень: скрытый раздел перестаёт быть страницей документации, и его дети оказываются под «чужим» родителем.
Какой фрейм — документация
Фрейм документации определяется по порядку: параметр frame запроса (слаг или id) → опция сайта onpress_docs_frame → первый существующий из слагов docs, obolochka-dokumentaciya. Ответ GET называет его в frame и откуда он взят в frame_source. Неизвестный фрейм в параметре — 404 docs_frame_not_found.
Чтобы страница попала в дерево, опубликуйте её с этим фреймом (frame: "docs") и родителем — страницей документации. Порядок у новой страницы — последним среди соседей.
Короткая подпись
Длинный заголовок страницы («Сборка страницы и статическая копия») в дереве удобно заменить короткой подписью — ключом nav_label во frontmatter:
---
name: "Сборка страницы и статическая копия"
slug: "sborka"
url: "/docs/v2/ru/frames/build/"
frame: "docs"
nav_label: "Сборка и копии"
---
Это свой ключ frontmatter, поэтому публикация предупредит, что он записан как метаполе, — так и должно быть. Заголовок страницы, <title> и хлебные крошки остаются полными.
Прочитать дерево
curl -s -H "Authorization: Bearer $OP_TOKEN" "$API/site/$SITE/docs/sidebar?lang=ru&include_hidden=1" \
| jq '{frame, frame_source, total, hidden_total, tree: [.tree[] | {id, title, url, children: [.children[] | {id, title, hidden}]}]}'
| Параметр | Смысл |
|---|---|
lang | только страницы этого языка — так, как дерево видит посетитель страницы на этом языке. Без параметра в дереве все языки сразу |
include_hidden | включить скрытые пункты с "hidden": true |
statuses | статусы через запятую; по умолчанию publish,draft,private,pending,future — как видит вошедший редактор |
public | то же, что statuses=publish — дерево глазами анонимного посетителя |
frame | фрейм документации явно |
Узел: id, title, slug, status, parent, menu_order, hidden, url (с языковым префиксом), link (null у черновика), lang, children.
Порядок внутри ветки
curl -s -X POST "$API/site/$SITE/docs/sidebar/reorder" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d '{"parent": 6249, "order": [6250, 6251, 6252, 6253]}' | jq '{order, appended, updated}'
{ "order": [6250, 6251, 6252, 6253, 6257], "appended": [6257], "updated": 5 }
parent — id, слаг или путь родителя, 0 — корень. order — пункты ветки в нужном порядке; неназванные встают после названных в прежнем порядке (appended). Пункт из другой ветки — 409 not_a_sibling: перенос между ветками меняет адрес и делается отдельно.
Один пункт: {"id": 6257, "after": 6252} (или before, или position — индекс с нуля).
Перенести, переименовать, поменять статус
curl -s -X PATCH "$API/site/$SITE/docs/sidebar/items/docs~v2~ru~sidebar" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d '{"parent": "/docs/v2/ru/menus/", "position": 0}' | jq '{item, warnings}'
{
"item": { "id": 6265, "parent": { "from": 6249, "to": 6264 }, "url_before": "/docs/v2/ru/sidebar/", "old_paths": [ { "id": 6265, "path": "/docs/v2/ru/sidebar/" } ], "url": "/docs/v2/ru/menus/sidebar/" },
"warnings": ["page #6265 changes its parent: the address /docs/v2/ru/sidebar/ answers 301 to the new one"]
}
{ref} в пути — id, слаг или путь с тильдами вместо слешей. Поля тела:
| Поле | Что делает |
|---|---|
parent | перенести в другую ветку (id, слаг, путь или 0) — меняет адрес страницы и всего её поддерева |
title | переименовать: меняется заголовок страницы, слаг и адрес — нет. Для короткой подписи в дереве используйте nav_label |
status | publish, draft, private, pending, future |
hidden | спрятать или вернуть |
after, before, position | место среди новых соседей |
Прежние адреса страницы и её поддерева API записывает в ответ (old_paths) и в мету страницы; тема v2 отвечает с них перенаправлением 301 на новый адрес, есть ли на сайте своя страница 404 или нет. После переноса проверьте старый адрес запросом без кук. Родитель, который замкнул бы цикл, и главная сайта как родитель отклоняются защитами: пункт встаёт в корень, а warnings объясняет почему. Пустое тело — 400 nothing_to_update.
Спрятать и вернуть
curl -s -X POST "$API/site/$SITE/docs/sidebar/items/docs~v2~ru~staroe/hide" -H "Authorization: Bearer $OP_TOKEN" | jq '{item, warnings}'
curl -s -X POST "$API/site/$SITE/docs/sidebar/items/docs~v2~ru~staroe/show" -H "Authorization: Bearer $OP_TOKEN" | jq .item
Статус и адрес страницы не меняются, страница открывается как раньше — пропадает только пункт. Скрытие раздела с видимыми детьми поднимает детей в корень, ответ предупреждает и называет их число: прячьте ветку целиком или сначала перенесите детей.
Положить дерево целиком
Основной сценарий, когда структура готова: одно дерево — один запрос, в одной транзакции.
curl -s -X PUT "$API/site/$SITE/docs/sidebar" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d '{
"lang": "ru",
"missing": "keep",
"dry_run": true,
"items": [
{ "id": 6249, "children": [
{ "id": 6250 },
{ "id": 6251 },
{ "url": "/docs/v2/ru/pages/", "children": [ 6254, 6255, 6256 ] },
{ "slug": "staroe", "hidden": true }
]}
]
}' | jq '{applied, dry_run, changes, moved, dropped, warnings}'
Пункт — ссылка на существующую страницу (id, slug, url или голое значение) плюс необязательные title, status, hidden, children. Страницы ручка не создаёт — их создаёт публикация.
| Поле | Смысл |
|---|---|
items | дерево, обязательно |
missing | hide (по умолчанию) — страницы документации, которых нет в дереве, скрываются (их id — в dropped); keep — остаются как есть |
lang | языковая ветка, которую заменяет запрос; без него — язык пунктов дерева, а если их несколько — основной язык. missing: "hide" скрывает только страницы этого языка |
dry_run | показать changes, moved, dropped и откатить |
frame | фрейм документации явно |
Весь запрос применяется целиком или не применяется вовсе. Неразрешимая ссылка или страница, указанная дважды, отменяют всё: 409 sidebar_items_unresolved с разбором в errors, где at — координата узла в присланном дереве ("0.1" — второй ребёнок первого корня). Страница, которая ещё не была пунктом документации, становится им: ей ставится фрейм документации, и ответ предупреждает, если до этого у неё был другой фрейм.
Корневые пункты обрабатываются бережно: страница, чей родитель не страница документации, и так рисуется в корне, поэтому её родитель не трогается и адрес не меняется.
changes — что поменялось у каждого пункта (from → to), moved — переезды с адресами до и после, dropped — скрытые, notified — сколько страниц получили событие обновления.
Не используйте PUT дерева там, где разделом управляют несколько человек или агентов: с missing: "hide" он скроет всё, чего нет в вашем дереве. Для правки своей ветки есть reorder и PATCH.
Языки
На многоязычном сайте у каждого языка своё дерево: onpress/docs-nav на странице показывает страницы её языка, GET с lang — ровно их, PUT заменяет дерево одного языка и не трогает остальные.
Коды ошибок
| Код | HTTP | Когда |
|---|---|---|
bad_items | 400 | items не массив |
bad_missing | 400 | missing не hide и не keep |
bad_reorder | 400 | нет ни order, ни id |
bad_status | 400 | статус вне списка; допустимые в allowed |
nothing_to_update | 400 | PATCH с пустым телом |
item_ref_required | 400 | пустая или неразборчивая ссылка на пункт |
page_not_found, not_a_page | 404 | нет такой страницы |
docs_frame_not_found | 404 | названного фрейма документации нет |
page_language_mismatch | 404 | путь с префиксом одного языка, а страница — другого |
ambiguous_page | 409 | слаг у нескольких страниц; кандидаты в candidates |
duplicate_item | 409 | страница в дереве дважды |
not_a_sibling | 409 | в order пункт другой ветки |
sidebar_items_unresolved | 409 | общий отказ PUT: ничего не применено, разбор в errors |
absolute_url_in_path | 422 | в ссылке схема и домен |
parent_not_found | 422 | сегмент пути — не страница |
unknown_language | 422 | lang нет на сайте |