Стили
Эндпоинты оформления сайта: собственный CSS (системные данные css) и CSS-переменные темы (css.variables); как слои оформления складываются на странице — Стили и оформление.
Во всех примерах API — https://onpress.pro/api/v2, SITE — id сайта (SITE_ID), OP_TOKEN — токен op_XXXX. Права на всех эндпоинтах страницы — администратор сайта. Как выбирается сайт и в какой форме приходят отказы — Доступ и токен.
Оба имени есть в GET /data/system: у css — methods: ["GET", "PUT", "DELETE"], у css.variables — methods: ["GET", "PATCH", "DELETE"], у обоих deletable: true. DELETE здесь возвращает сайт к оформлению темы. Любая запись без dry_run сбрасывает кэш страниц и сразу собирает заново статические копии страниц — исход в поле ответа rebaked, см. статические копии.
GET /data/css
Отдаёт лист одной записью в items, даже если своего CSS у сайта нет (exists: false, css: ""). Например, узнать размер листа и сколько раз в нём встречаются два класса, не выгружая сам лист:
curl -s -H "Authorization: Bearer $OP_TOKEN" "$API/site/$SITE/data/css?include_css=0&count=.site-header,.opdoc__body"
{
"success": true,
"site_id": "x9HTLHECq",
"name": "css",
"origin": "system",
"writable": true,
"write": { "method": "PUT", "methods": ["PUT", "DELETE"], "at": "/data/css", "dry_run": true, "delete": { "method": "DELETE", "dry_run": true } },
"total": 1,
"items": [{
"css_omitted": "the body was not asked for: repeat without include_css=0 to get it",
"exists": true,
"bytes": 109491,
"lines": 3131,
"sha256": "5aed97061c04f656fb935f1cb5b27bf7345c4d0798695c5ed4c3ef73b8045da6",
"autoload": "off",
"updated_at_gmt": "2026-10-23 15:27:36",
"updated_by": 0,
"source": "codex-rollback",
"stripped": [],
"blocks": [
{ "name": "footer-frame-podval-sajta", "from": 0, "to": 90, "lines": 89, "bytes": 30982 },
{ "name": "header-frame", "from": 92, "to": 1035, "lines": 942, "bytes": 20260 }
],
"blocks_unclosed": [],
"outside_bytes": 0,
"counts": { ".site-header": 127, ".opdoc__body": 210 },
"option": "onpress_custom_css"
}]
}
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
include_css | 0/1 | 1 | 0 — без тела листа, вместо css приходит css_omitted |
count | string | — | до 20 подстрок через запятую — сколько раз встречается каждая (поле counts) |
| Поле записи | Тип | Описание |
|---|---|---|
css | string | лист как есть, без обёртки |
exists, bytes, lines, sha256 | bool, number, number, string | есть ли свой лист, его размер, строки и хеш |
autoload | string | yes (или on) для листов до 64 КБ, no (off) для больших |
updated_at_gmt, updated_by, source | string, number, string | когда, кем и с какой меткой лист записан последний раз; null, если записи не было |
stripped | array | что вырезала очистка при последней записи: rule, count |
blocks | array | куски между строками-сторожами :root{--имя:1} … :root{--имя-end:1}: name, from/to — номера строк маркеров с нуля, lines, bytes |
blocks_unclosed | array | открытые и не закрытые куски: name, from |
outside_bytes | number | непустые байты вне кусков |
counts | object | ответ на count: подстрока → сколько раз |
PUT /data/css
Заменяет лист целиком. Например, проверить лист без записи и увидеть, что вырежет очистка:
curl -s -X PUT "$API/site/$SITE/data/css" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d '{"css": "body{color:red}</style><script>alert(1)</script>", "dry_run": true}'
{
"success": true,
"site_id": "x9HTLHECq",
"option": "onpress_custom_css",
"bytes": 23,
"max_bytes": 262144,
"sha256": "…",
"autoload": "yes",
"stripped": [
{ "rule": "style_close_tag", "count": 1, "reason": "a closing </style> tag ends the style element and lets the rest through as markup", "samples": ["</style>"] },
{ "rule": "script_tag", "count": 2, "reason": "a <script> tag has no place in styles; it is inert inside <style> but not in any other context", "samples": ["<script>", "</script>"] }
],
"warnings": [],
"dry_run": true,
"applied": false,
"css": "body{color:red}alert(1)",
"source": "css"
}
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
css | string | — | весь лист, обязательно; пустая строка допустима |
source | string | node | метка записи, видна в source при чтении |
dry_run | bool | false | вернуть очищенный лист без записи |
flush_cache | bool | true | сбросить весь кэш страниц сайта |
Настоящая запись отвечает applied: true, updated_at_gmt, cache (status: flushed, empty, skipped, failed; dirs) и rebaked — статические копии. Поле source ответа — имя системных данных, как у любой записи в /data/{name}. Очистка вырезает </style>, <script>, адреса javascript: и vbscript:, expression( и управляющие символы, незакрытый /* закрывает, хвостовой перевод строки снимает; о каждом вырезанном говорит stripped.
CSS сайта уходит в браузер как есть, поэтому комментариев /* … */ и кириллицы вне строк в нём быть не должно — такой лист отклоняется целиком, проверка идёт и при dry_run. Пропускаются лицензионные заголовки /*! … */ и строки (content: "/* */", адреса в url(…) в кавычках). Куски размечайте строками-сторожами :root{--имя:1} и :root{--имя-end:1}. Отказ на комментарий выглядит так:
{
"success": false,
"error": "comments_not_allowed",
"message": "site CSS has 1 comment(s) at line(s) 3: code that goes to the browser carries no comments …",
"kind": "css",
"count": 1,
"found": [{ "kind": "block", "line": 3, "text": "/* y */" }]
}
| Код | Статус | Когда | Что делать |
|---|---|---|---|
css_required | 400 | нет поля css | пришлите лист строкой |
wrong_method_for_source | 405 | PATCH вместо PUT | отправьте PUT |
css_too_large | 413 | лист больше 256 КБ; bytes, max_bytes | сократите лист |
comments_not_allowed | 422 | в листе комментарий или кириллица вне строк; места — в found | уберите комментарии, куски размечайте сторожами |
DELETE /data/css
Удаляет лист: сайт возвращается к стилям темы и её CSS-переменным. Например, сначала посмотреть, что удалится:
curl -s -X DELETE "$API/site/$SITE/data/css" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d '{"dry_run": true}'
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
dry_run | bool | false | ничего не удалять, ответить would_clear и bytes |
flush_cache | bool | true | сбросить весь кэш страниц сайта |
Тело необязательно. Настоящее удаление отвечает так:
{ "success": true, "site_id": "x9HTLHECq", "option": "onpress_custom_css", "cleared": true, "cache": { "status": "flushed" }, "rebaked": { "status": "ok", "total": 1, "baked": 1, "static": { "status": "ok", "pages": [{ "id": 7036, "published": true, "url": "/home-next" }] } }, "source": "css" }
GET /data/css.variables
Отдаёт все 66 CSS-переменных темы: по записи в items на переменную, общее — в meta. Например:
curl -s -H "Authorization: Bearer $OP_TOKEN" "$API/site/$SITE/data/css.variables"
{
"success": true,
"site_id": "x9HTLHECq",
"name": "css.variables",
"origin": "system",
"writable": true,
"total": 66,
"meta": {
"theme": "onpress-v2",
"defaults_source": "themes/onpress-v2/assets/css/parts/_variables.css",
"changed": ["color.primary", "color.accent", "color.accent_light", "color.accent_dark", "h2.font", "h2.size", "h2.weight", "h2.line_height", "h2.letter_spacing", "h2.color"],
"stores": { "design": "onpress-sidepanel-design", "typography": "onpress-sidepanel-typography", "tokens": "onpress_design_tokens" },
"css": "html:root{--primary:0 85 255;--primary-light:64 128 255;--primary-dark:0 64 191;}"
},
"items": [
{ "variable": "color.primary", "value": "#0055ff", "default": "#0066ff", "source": "site", "css_var": "--primary-color", "type": "color", "description": "Primary color" },
{ "variable": "h2.size", "value": 40, "default": 36, "source": "site", "css_var": "--h2-fz", "type": "px", "description": "h2: size" }
]
}
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
theme | string | тема сайта | взять значения по умолчанию другой установленной темы |
| Поле | Описание |
|---|---|
variable | имя для записи: color.primary, h2.size |
value, default | значение на сайте и значение темы |
source | default или site — задано на сайте |
css_var | имя CSS-переменной |
type | color, px, int, ratio, em, length, string, enum с values, rgb-channels |
description | что задаёт переменная |
В meta: theme и defaults_source — откуда взяты значения по умолчанию, changed — переменные, заданные на сайте, stores — где они хранятся, css — производные переменные, которые тема выводит сама. Список переменных — Стили и оформление.
PATCH /data/css.variables
Меняет только названные переменные, остальные сохраняют значения. Например, основной цвет и размер H2 с проверкой без записи:
curl -s -X PATCH "$API/site/$SITE/data/css.variables" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d '{"variables": {"color.primary": "#0055ff", "h2.size": 40}, "dry_run": true}'
{
"success": true,
"dry_run": true,
"applied": false,
"site_id": "x9HTLHECq",
"changed": [
{ "variable": "color.primary", "value": "#0055ff", "css_var": "--primary-color", "store": "onpress-sidepanel-design" },
{ "variable": "h2.size", "value": 40, "css_var": "--h2-fz", "store": "onpress-sidepanel-typography" },
{ "variable": "color.accent", "value": "0 85 255", "css_var": "--primary", "store": "onpress_design_tokens", "derived": true }
],
"css": "html:root{--primary:0 85 255;--primary-light:64 128 255;--primary-dark:0 64 191;}",
"source": "css.variables"
}
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
variables | object | — | {имя: значение}, обязательно |
dry_run | bool | false | проверить значения и показать итоговый CSS без записи |
flush_cache | bool | true | сбросить кэш страниц |
theme | string | тема сайта | значения по умолчанию другой темы |
changed — что поменяется: variable, value, css_var, store; derived: true — переменная, выведенная из названной (акцент из основного цвета). Настоящая запись отвечает applied: true, stores, cache и rebaked. Типографика хранится уровнями, поэтому запись одного свойства (h2.size) закрепляет весь уровень h2: остальные его свойства тоже становятся site.
| Код | Статус | Когда | Что делать |
|---|---|---|---|
nothing_to_update | 400 | нет variables | пришлите {"variables": {…}} |
unknown_token | 400 | переменной нет; имя — в token | возьмите имя из GET /data/css.variables |
bad_token_value | 400 | значение не подходит к типу; имя — в token | исправьте значение |
invalid_theme | 400 | такой темы нет | уберите theme |
wrong_method_for_source | 405 | PUT вместо PATCH | отправьте PATCH |
DELETE /data/css.variables
Возвращает переменные к значениям темы: с {"variables": [...]} — только названные, без тела — все. Сброс color.primary снимает и выведенный из него акцент color.accent. Например, вернуть размер H2:
curl -s -X DELETE "$API/site/$SITE/data/css.variables" \
-H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
-d '{"variables": ["h2.size"]}'
{ "success": true, "site_id": "x9HTLHECq", "reset": ["h2.size"], "css": "html:root{--primary:0 85 255;--primary-light:64 128 255;--primary-dark:0 64 191;}", "cache": { "status": "flushed", "dirs": ["…/supercache/test.onpress.pro"] }, "rebaked": { "status": "ok", "total": 1, "baked": 1 }, "source": "css.variables" }
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
variables | string[] | все | имена переменных для сброса |
dry_run | bool | false | ничего не менять, ответить would_change — заданные на сайте переменные из названных, с value и default |
Без тела ответ — reset: "all" и removed_options: сайт возвращается к теме целиком.
| Код | Статус | Когда | Что делать |
|---|---|---|---|
unknown_token | 400 | переменной нет; имя — в token | возьмите имя из GET /data/css.variables |
Статические копии
Страница, которую сайт отдаёт готовым файлом, держит ссылку на файл CSS сайта (его имя меняется вместе с содержимым) и значения CSS-переменных на момент сборки, а сброс кэша страниц её не касается. Поэтому PUT и DELETE /data/css, PATCH и DELETE /data/css.variables после записи собирают заново все такие копии сайта, и новый CSS виден на них сразу, без POST /frames/rebake. Проверка без записи (dry_run) копий не трогает. Сборка — следствие уже состоявшейся записи: её неудача не отменяет запись и не меняет код ответа, только поле rebaked.
Поле rebaked | Смысл |
|---|---|
status | ok — все копии собраны; partial — часть не собралась; failed — ни одна; nothing — копий у сайта нет (reason) |
total | сколько копий у сайта |
baked | сколько собрано и лежит на месте |
skipped, cap | копий больше предела за один вызов (200): сколько осталось, предел |
static.pages[] | по странице: id, published, url, reason — почему копии нет (например, renders_on_request: страница теперь собирается на запросе, копия снята) |
failures[] | пачки страниц, которые не собрались: pages, status, reason |
{ "status": "ok", "total": 1, "baked": 1, "static": { "status": "ok", "pages": [{ "id": 7036, "published": true, "url": "/home-next" }] } }
Сборка идёт пачками по 8 страниц, каждая копия снимается с ответа страницы, поэтому запись на сайте с десятками копий отвечает за несколько секунд.