oscript-ui
oscript-ui

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

Роды документа собирают страницу целиком: объявление типа, голову с заглавием и ресурсами, тело с лендмарками. Обычно их печатает каркас страницы, а свой каркас из них собирают, когда нужна страница без шапки и меню хаба.

Документ, голова и тело#

Документ — корень страницы. Он печатает <!DOCTYPE html> и <html> с языком и темой — это два первых аргумента, — а детьми принимает только голову и тело.

Тема ставится атрибутом data-theme ещё до листа стилей. Иначе страница на мгновение покажется в чужих цветах.

Документ целиком: голова и тело

<!DOCTYPE html>
<html lang="ru" data-theme="тёмная"><head><title>Проекты</title></head><body><main class="wrap"></main></body></html>
HTML = Кит.Документ("ru", "тёмная", Кит.Голова(Кит.Титул("Проекты")), Кит.Тело(Кит.Основное().Вид("полоса"))).Рендер();

Пустой язык не печатается вовсе: lang="" для скринридера хуже, чем отсутствие атрибута.

Голова#

Голова — то, чего человек не видит. В неё кладут только титул, мета, ресурс, стиль и скрипт; заголовок или абзац туда не попадут.

Кодировка стоит в голове первой: до неё браузер читает байты вслепую.

Объявления головы

<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"></head>
HTML = Кит.Голова( Кит.Кодировка("utf-8"), Кит.Мета("viewport", "width=device-width, initial-scale=1")).Рендер();

Свойства карточки ссылки (Open Graph) объявляются отдельной функцией: у них атрибут property, а не name. Адреса в карточке краулер ждёт абсолютными.

Свойства карточки ссылки

<head><meta property="og:title" content="Проекты"><meta property="og:image" content="https://пример.рф/проекты.png"></head>
HTML = Кит.Голова( Кит.МетаСвойство("og:title", "Проекты"), Кит.МетаСвойство("og:image", "https://пример.рф/проекты.png")).Рендер();

Ресурс — лист стилей, иконка вкладки, иконка домашнего экрана. Ресурс без адреса не печатается: <link> в никуда браузер всё равно запросил бы.

Ресурсы: лист стилей и иконка вкладки

<head><link rel="stylesheet" type="text/css" href="/static/app.css"><link rel="icon" type="image/svg+xml" sizes="32x32" href="/static/знак.svg"></head>
HTML = Кит.Голова( Кит.Ресурс("stylesheet", "/static/app.css", "text/css"), Кит.Ресурс("icon", "/static/знак.svg", "image/svg+xml", "32x32"), Кит.Ресурс("icon", "")).Рендер();

Стиль и скрипт#

Стиль — правила, которые должны приехать вместе с разметкой, а не отдельным запросом. Так каркас кладёт токены темы. Правила печатаются как есть: внутри <style> HTML-экранирование не защищает, а ломает.

Палитра инлайном

<style id="токены-темы">:root { --layout-width: 1280px; }</style>
HTML = Кит.Стиль("токены-темы", ":root { --layout-width: 1280px; }").Рендер();

Скрипт кита всегда отложенный (defer): разбор разметки он не останавливает, а порядок исполнения сохраняет. Скрипт без адреса не печатается.

Отложенный скрипт

<script src="/static/app.js" defer></script>
HTML = Кит.Скрипт("/static/app.js").Рендер();

Слово Модуль делает скрипт модулем (дев-сборка 10): с адресом — внешний модуль <script type="module" src>, без адреса — встроенный модуль с текстом, например подсветка блоков кода README рядом с прозой. Такой узел ставят и в тело страницы — в карточку, рядом с тем, что он оживляет. Текст модуля — доверенный код приложения или библиотеки, а не данные: внутри <script> HTML-экранирование не действует, поэтому «</script» и «<!--» в тексте останавливают сборку. Принимается и тег целиком — <script type="module">…</script>, как его отдаёт библиотека подсветки (MarkdownПодсветка.ТегСкрипта() из oscript-md): обёртку кит снимает и печатает свою. Своего nonce у скриптов кита нет — страница со строгой политикой CSP разрешает встроенный модуль своим хешем.

Встроенный модуль — подсветка кода рядом с README

<section class="card"><h2 class="card__title">Описание</h2><div class="card__body"><div class="prose"><pre><code>Сообщить(1);</code></pre></div><script type="module">for (const c of document.querySelectorAll('pre > code')) c.dataset.lang = c.className;</script></div></section>
HTML = Кит.Карточка("Описание", Кит.Проза("<pre><code>Сообщить(1);</code></pre>"), Кит.Скрипт().Модуль("for (const c of document.querySelectorAll('pre > code')) c.dataset.lang = c.className;")) .Рендер();

Лендмарки#

Тело делится на ориентиры, по которым скринридер прыгает одной клавишей: шапка, навигация, основное, подвал. Основное на странице одно — то, ради чего её открыли.

Вид лендмарка — слово .Вид(…) — его оформление в каркасе: «страницы» у шапки и подвала, «полоса» у основного (колонка по центру), «верхняя» у навигации (ряд ходов в шапке). Без вида лендмарк печатается голым тегом.

Страница из лендмарков

<body><header class="top"><nav class="top__nav" aria-label="Основная навигация"></nav></header><main class="wrap"></main><footer class="bottom"></footer></body>
HTML = Кит.Тело( Кит.Шапка( Кит.Навигация().Вид("верхняя").Подпись("Основная навигация")).Вид("страницы"), Кит.Основное().Вид("полоса"), Кит.Подвал().Вид("страницы")).Рендер();

Обратите внимание: подпись у навигации сейчас не печатается. Доступное имя (aria-label) из подписи кит ставит только ряду.

Гайдлайны#

Содержимое экрана

ДелайтеОдин узел «основное» на страницу
Код
HTML = Кит.Тело(
	Кит.Шапка().Вид("страницы"),
	Кит.Основное(Кит.Примечание("Содержимое экрана")).Вид("полоса"),
	Кит.Подвал().Вид("страницы")).Рендер();

Список

Подробности

Не делайтеНесколько «основных»: скринридер не знает, куда прыгать
Код
HTML = Кит.Тело(
	Кит.Основное(Кит.Примечание("Список")).Вид("полоса"),
	Кит.Основное(Кит.Примечание("Подробности")).Вид("полоса")).Рендер();
документ
  голова
    мета
    титул
      текст
  тело
    основное
      примечание
        текст
ДелайтеСвой каркас — только когда каркас страницы не подходит
Код
Документ = Кит.Документ("ru", "",
	Кит.Голова(Кит.Кодировка("utf-8"), Кит.Титул("Печать счёта")),
	Кит.Тело(Кит.Основное(Кит.Примечание("Страница для печати без шапки и меню"))));
HTML = Кит.Код(Документ.Дерево()).Вид("блочный").Рендер();
документ
  голова
  тело
    основное
      примечание
        текст
Не делайтеГолова без кодировки и заглавия
Код
Документ = Кит.Документ("ru", "",
	Кит.Голова(),
	Кит.Тело(Кит.Основное(Кит.Примечание("Вкладка без имени"))));
HTML = Кит.Код(Документ.Дерево()).Вид("блочный").Рендер();

Доступность#

  • Язык документа (lang) задаёт произношение скринридера и переносы слов. Передавайте его всегда.
  • Титул — имя вкладки и первое, что скринридер объявит на странице. Называйте экран, а не приложение.
  • Лендмарки печатаются своими тегами (header, nav, main, footer), поэтому роли им ставить не нужно.

Справка#

Кит.Документ()src/Классы/холст/Кит.os

Документ — корень страницы: объявление типа, <html> и всё, что внутри. В него кладут
голову и тело, больше ничего.

Параметры:
 Язык  - Строка - код языка страницы для атрибута lang.
 Тема  - Строка - значение атрибута data-theme; ставится ДО листа стилей, иначе
         страница мигнёт чужими цветами.
 Р1…Р8 - ЭлементЭкрана - (необязательные) голова и тело.

Возвращаемое значение:
 ЭлементЭкрана

Кит.Голова()src/Классы/холст/Кит.os

Голова документа — то, чего человек не видит: заглавие вкладки, объявления и ресурсы.

Параметры:
 Р1…Р8 - ЭлементЭкрана - (необязательные) титул, мета, ресурсы, стили, скрипты.

Возвращаемое значение:
 ЭлементЭкрана

Кит.Титул()src/Классы/холст/Кит.os

Заглавие вкладки браузера.

Параметры:
 Значение - Строка - текст заглавия (экранируется).

Возвращаемое значение:
 ЭлементЭкрана

Кит.Мета()src/Классы/холст/Кит.os

Объявление «имя — содержание» в голове документа.

Параметры:
 Имя        - Строка - имя объявления (viewport, referrer, color-scheme).
 Содержание - Строка - его значение.

Возвращаемое значение:
 ЭлементЭкрана

Кит.МетаСвойство()src/Классы/холст/Кит.os

Объявление «свойство — содержание» в голове документа: свойства карточки, которую
чужой сервис строит по ссылке на страницу (og:title, og:image и подобные). Объявление
без свойства не печатается.

Параметры:
 Свойство   - Строка - имя свойства (атрибут property).
 Содержание - Строка - его значение.

Возвращаемое значение:
 ЭлементЭкрана

Кит.Кодировка()src/Классы/холст/Кит.os

Объявление кодировки документа. Стоит первым в голове: до него браузер читает байты
вслепую.

Параметры:
 Имя - Строка - имя кодировки.

Возвращаемое значение:
 ЭлементЭкрана

Кит.Ресурс()src/Классы/холст/Кит.os

Ссылка на внешний ресурс: лист стилей, иконка сайта, иконка домашнего экрана.
Ресурс без адреса не печатается вовсе.

Параметры:
 Отношение - Строка - чем ресурс приходится странице (stylesheet, icon).
 Адрес     - Строка - адрес ресурса.
 Тип       - Строка - (необязательный) тип содержимого ресурса.
 Размеры   - Строка - (необязательный) размеры картинки, которые несёт ресурс.

Возвращаемое значение:
 ЭлементЭкрана

Кит.Стиль()src/Классы/холст/Кит.os

Правила оформления прямо в голове документа — то, что обязано приехать вместе
с разметкой, а не отдельным запросом.

Параметры:
 Имя     - Строка - имя блока правил (атрибут id).
 Правила - Строка - ДОВЕРЕННЫЙ CSS: внутри <style> экранирование бесполезно,
           значение обязан провалидировать тот, кто его собрал.

Возвращаемое значение:
 ЭлементЭкрана

ЭлементЭкрана.Модуль()src/Классы/холст/ЭлементЭкрана.os

Скрипт-модуль (дев-сборка 10, ui-каталог-2 П2): узел Кит.Скрипт печатается
<script type="module">. С адресом — внешний модуль; без адреса — встроенный модуль с этим
текстом. Текст — ДОВЕРЕННЫЙ код приложения или библиотеки, а не данные: внутри <script>
HTML-экранирование не действует. Поэтому кит останавливает сборку, если в тексте есть
«</script» или «<!--» — с ними тег закрылся бы раньше времени. Принимается и тег целиком
— <script type="module">…</script>, как его отдаёт библиотека подсветки: обёртку кит
снимает и печатает свою.

Параметры:
 Текст - Строка - (необязательный) код встроенного модуля; пусто — внешний модуль по адресу.

Возвращаемое значение:
 ЭлементЭкрана - этот же элемент.

Кит.Скрипт()src/Классы/холст/Кит.os

Скрипт страницы. Всегда отложенный: разбор разметки он не останавливает. Слово Модуль
(дев-сборка 10) делает его модулем: с адресом — внешний модуль, без адреса — встроенный
модуль с текстом (подсветка кода README и т. п.); такой узел ставят и в тело страницы.

Параметры:
 Адрес - Строка - (необязательный) адрес скрипта; пустой без слова Модуль не печатается.

Возвращаемое значение:
 ЭлементЭкрана

Кит.Тело()src/Классы/холст/Кит.os

Тело документа — всё, что человек видит.

Параметры:
 Р1…Р8 - ЭлементЭкрана, Строка - (необязательные) дети узла; строка — текст.

Возвращаемое значение:
 ЭлементЭкрана

Кит.Шапка()src/Классы/холст/Кит.os

Шапка — верхняя полоса страницы: знак, навигация, учётка. Вид словом: «страницы»
(липкая полоса вверху) | «меню» (полоса с единым меню) | "" (без оформления).

Параметры:
 Р1…Р8 - ЭлементЭкрана, Строка - (необязательные) дети узла; строка — текст.

Возвращаемое значение:
 ЭлементЭкрана

Кит.Основное()src/Классы/холст/Кит.os

Основное — то, ради чего страницу открыли. На странице оно одно. Вид словом: «полоса»
(колонка содержимого по центру) | "" (без оформления).

Параметры:
 Р1…Р8 - ЭлементЭкрана, Строка - (необязательные) дети узла; строка — текст.

Возвращаемое значение:
 ЭлементЭкрана

Кит.Подвал()src/Классы/холст/Кит.os

Подвал — нижняя полоса страницы. Вид словом: «страницы» | "" (без оформления).

Параметры:
 Р1…Р8 - ЭлементЭкрана, Строка - (необязательные) дети узла; строка — текст.

Возвращаемое значение:
 ЭлементЭкрана

Кит.Навигация()src/Классы/холст/Кит.os

Навигация — набор ходов, который скринридер объявляет отдельным ориентиром. Вид словом:
«верхняя» (ряд ходов в шапке страницы) | "" (без оформления).

Параметры:
 Р1…Р8 - ЭлементЭкрана, Строка - (необязательные) дети узла; строка — текст.

Возвращаемое значение:
 ЭлементЭкрана