Перейти к содержимому

Playground

Пишите презентацию в браузере и смотрите, как слайды следуют за текстом: go-slides, скомпилированный в WebAssembly, с автодополнением, справкой и примерами.

Открыть Playground →

Playground (онлайн-редактор go-slides) — это сам go-slides v0.20.2, скомпилированный в WebAssembly и работающий в вашем браузере. Набирайте презентацию слева; слайды появляются справа. Ничего не отправляется на сервер: ни презентация, ни ссылка для обмена.

Интерфейс Playground (лента, справка, сообщения) говорит на языке страницы: откройте /ru/playground/ для русского, и так же для двенадцати языков этого сайта. Переключатель языка на странице меняет его, а ваш выбор сохраняется в этом браузере; ссылка, в которой указан язык, всегда главнее. Примеры презентаций остаются на английском. Украинский, русский, китайский, японский и корейский рисуются подмножеством Noto Sans (от 0,06 до 2,3 МиБ), которое страница загружает только для этих языков.

Что в ней есть

  • Живой предпросмотр каждого слайда, отрисовываемый вне потока страницы (Web Worker), так что набор текста никогда его не ждёт. Щёлкните слайд — и редактор перейдёт к его строке; переместите курсор — и предпросмотр прокрутится к его слайду.

  • Показ: сама презентация, с управлением с клавиатуры, экранным пультом и переходами.

  • Режим докладчика: Present (или p в показе) открывает его во втором окне: текущий слайд, следующий шаг, заметки докладчика (<!-- comments --> презентации), часы и таймер. Стрелки, пробел, Home и End работают в любом из окон, и каждое следует за другим, в том числе когда вы правите презентацию. Если окно не открывается, разрешите всплывающие окна для сайта. Режим обзора (o) есть только в скачанной странице.

  • Автодополнение по мере набора: ключи директив (точечные _ — в комментариях), значения kind, theme, size, paginate, а также функции шаблонов и поля данных внутри {{ }}.

  • Справка о том, что под курсором: директива, kind (что он задаёт), функция шаблона. Панель справки также ссылается на эти страницы. Начиная с v0.16.0 справка по директивам следует языку интерфейса и доступна на 11 языках.

  • Проблемы на своей строке: ошибки шаблонов, YAML и HCL подсвечиваются в редакторе и перечисляются под ним, а предпросмотр сохраняет последнюю презентацию, которая отрисовалась.

  • Примеры: приветственная презентация, шаблоны, порождающие слайды, kinds (типы слайдов), front matter на HCL, темы и точечные директивы, а также математика, изображения и фоны (![bg], разделённый ![bg left:40%], фильтры).

  • Файлы: панель слева от редактора — это проект презентации в том виде, в каком его читают команда и расширение VS Code: deck.md, slides.yaml, themes/, kinds/, media/.

    • Щёлкните файл, чтобы править его. Редактор раскрашивает его по языку (Markdown, YAML, HCL, JSON, CSS) и отмечает его проблемы.
    • Правая кнопка мыши (или Shift+F10) — New File, New Folder, Rename (F2), Delete (с подтверждением) и New theme / New kind. Перетащите файл на папку, чтобы переместить его. Клавиатура следует шаблону дерева WAI-ARIA, включая поиск по набору.
    • Project ▸ New theme создаёт themes/my-gaia.css (или на основе default, uncover): @import встроенной темы и добавленные вами правила. Она попадает в список тем. New kind и New data file тоже начинаются с шаблонов. Каждый файл перечисляется в slides.yaml, так что slides build deck.md его находит.
    • Project ▸ Download project (.zip) сохраняет всё. В распакованном виде его собирает slides build deck.md. Open project принимает .zip или папку обратно. Архив, выходящий за пределы своей папки (.., абсолютные пути), содержащий больше 256 файлов, файл больше 8 МиБ или раздувающийся более чем в 100 раз, отклоняется.
    • Всё хранится в этом браузере вместе с черновиком. Проект может занимать до 64 МиБ, а строка под файлами показывает, сколько использовано.
  • Медиа: перетащите или вставьте изображение, видео или звук в редактор — и он попадёт в media/, а презентация назовёт его: ![](media/photo.png). Перетащите файлы на папку панели, чтобы положить их туда. Презентация остаётся маленькой и читаемой, и ничего не загружается. Изолированная среда предпросмотра загружает их, не открываясь шире (страница передаёт ей байты). Save as ▸ HTML page кладёт их в страницу. Изображения https: тоже работают, но браузер загружает их с их сервера, который при этом видит ваш адрес. Предпросмотр не отправляет referrer.

  • Изменяемые панели: панель файлов, редактор, миниатюры слайдов, предпросмотр и справка разделены полосами, которые можно перетаскивать (над полосой указатель превращается в курсор изменения размера). Место достаётся панели рядом с полосой, остальные сохраняют размер. Двойной щелчок по полосе или Enter на ней закрывает панель и возвращает её обратно. С клавиатуры F6 перемещается между полосами, стрелки сдвигают полосу на 16 px, Home и End доводят предыдущую панель до наименьшего и наибольшего размера, а Escape возвращает в редактор. Вкладка View по-прежнему отключает панели. Заданные вами размеры сохраняются в этом браузере вместе с черновиком; размеры по умолчанию (190, 168 и 280 px, остальное делят редактор и предпросмотр в пропорции 6 к 5) никогда не сохраняются.

  • Закрытие панели: у каждой панели в заголовке есть маленькая кнопка × с подсказкой. Остальные делят её место, а панель возвращается с прежней шириной. Чтобы открыть её снова, используйте её переключатель на вкладке View (он есть у каждой панели). Редактор и предпросмотр можно закрыть по отдельности, но не оба сразу: последний отказывается, его кнопка неактивна, а подсказка объясняет почему. С клавиатуры F6, затем Tab или Shift+Tab ведут к кнопке ×, а Enter или пробел закрывает панель; клавиатура возвращается в редактор. Какие панели открыты, сохраняется в этом браузере вместе с размерами (Versions, GitHub и редактор тем, открытые для задачи, запускаются закрытыми).

  • Format: вкладка Format правит Markdown за вас, и каждое нажатие — один шаг отмены.

    • Text: Bold, Italic, Strikethrough и Inline code работают с выделением или словом под курсором и переключаются (Ctrl+B, Ctrl+I, Ctrl+Shift+X и Ctrl+E; Cmd на Mac). Кнопка показывается нажатой, когда курсор внутри её разметки. В Markdown нет подчёркивания: Underline (Ctrl+U) оборачивает текст в <u>…</u> — тег, который сохраняет разрешённый по умолчанию список HTML Marp, так что он работает и при выключенном сыром HTML.
    • Paragraph: Heading 1–3 (Ctrl+Alt+1..3), маркированный список (Ctrl+Shift+8), нумерованный (Ctrl+Shift+7) и цитата работают с выделенными строками и переключаются. Горизонтальная черта — это тег <hr>: ---, *** и ___ в Marp каждый начинали бы новый слайд.
    • Table: сетка выбирает столбцы и строки. С курсором в таблице вы добавляете или удаляете строку или столбец и выравниваете столбец (:--, :-:, --:); после каждой правки таблица перезаписывается выровненной.
    • Slide text слева, по центру или справа записывает блок <style scoped> в текущий слайд. В Marp нет синтаксиса выравнивания, а атрибут style не проходит через разрешённый по умолчанию список HTML, но блок scoped проходит, так что это работает при выключенном сыром HTML и видно в предпросмотре, HTML-странице и PDF.
    • Link (Ctrl+K) записывает [text](url) с выделенным url.
  • Подсветка ключей front matter на любой глубине, в YAML (в том числе в отображениях {a: 1}) и в HCL.

  • Выбор темы: default, gaia, uncover, темы проекта (themes/*.css) и темы, которые определяет презентация (/* @theme name */ в <style>). Он записывает theme: в front matter, YAML или HCL, так что ссылка для обмена его сохраняет, и следует за front matter при её правке.

  • Предпросмотр сохраняет своё место по мере набора: заменяются только изменившиеся слайды, а смена темы заново открывает предпросмотр на том же слайде.

  • Ссылка для обмена: презентация путешествует в самой ссылке (в её части #, сжатая), так что открытие ссылки открывает презентацию. Ссылки несут до 64 КиБ в сжатом виде, и только презентацию: когда в проекте больше (темы, kinds, медиа), Share сообщает об этом и предлагает .zip.

  • Save as:

    • HTML-страница, такая же, какую пишет slides deck.md;
    • PDF (векторный, с выделяемым текстом и оглавлением);
    • редактируемая презентация PowerPoint или OpenDocument.

    Они создаются в вашем браузере тем же кодом, что slides --pdf, --pptx и --odp: PDF презентации из 100 слайдов в тесте производительности побайтно совпадает с PDF команды. Первый экспорт скачивает движок экспорта (около 5 МиБ, один раз; браузер хранит его до следующего обновления) с индикатором хода и компилирует его по мере поступления. Затем он скачивает только те шрифты, которые рисуют ваши слайды. При скорости 3 МБ/с первый PDF приветственной презентации готов менее чем за 3 секунды. Презентация из 100 слайдов после этого занимает около 3 секунд. Изображение https: включается, только если его сервер это позволяет (CORS); изображения data: включаются всегда.

  • Ваш черновик сохраняется:

    • Презентация сохраняется в этом браузере по мере набора (IndexedDB, только для этого сайта) и возвращается при перезагрузке. Ничего никуда не отправляется. Текстовые файлы проекта (темы, kinds, данные, slides.yaml) сохраняются так же, даже если вы закрываете вкладку сразу после набора; медиа сохраняются по мере перетаскивания.
    • Ссылка для обмена открывает свою презентацию и сохраняет ваш черновик: Draft ▸ Restore my draft возвращает его.
    • Пример, Draft ▸ Reset to the example (с подтверждением) и другая вкладка его тоже никогда не стирают: Draft ▸ Restore replaced возвращает его обратно.
    • Draft ▸ Forget my drafts стирает всё сохранённое.

Каждый экспорт отрисовывает тот проект, который показывает предпросмотр: его slides.yaml, темы, kinds, файлы данных и медиа, причём медиа — внутри документа.

Изображения в виде файлов (--images у slides) в браузере не создаются: используйте команду или расширение VS Code.

Редактор тем

Главная ▸ Стиль ▸ Редактор тем открывает панель, которая редактирует одну из тем проекта с помощью элементов управления, а предпросмотр следует за изменениями. Тема хранится как папка пакета, theme-src/<name>/; таблица, которую читают предпросмотр и экспорт, themes/<name>.css, компилируется из неё: то, что вы видите, и есть то, что вы экспортируете. Импортированный пакет темы (Импортировать… в панели, Добавить медиа… или перетаскивание) сохраняет там свои файлы, так что его можно редактировать.

  • Палитра: цвета фона, текста, заголовков, акцента и ссылок. Выберите цвет или введите его (#1a2b3c, rgb(), hsl() или название).
  • Типографика: шрифты текста, заголовков и кода с их размерами и насыщенностью. Шрифты — общие и распространённые, а также те, что вы добавите (Добавить шрифт…: .woff2, .woff, .ttf или .otf).
  • Логотип: изображение (.svg, .png), его место (угол или весь фон) и размер. Номер страницы и колонтитул: где стоит номер страницы, а также размеры и выравнивание.
  • Сведения: то, что говорит theme.hcl: версия, описание, авторы, лицензия, сайт, базовая тема (extends) и нужная версия go-slides.
  • Контраст (WCAG): для каждого текста на его фоне — коэффициент и его уровень, AA или AAA, либо «Не проходит», в реальном времени. Заголовки считаются крупным текстом (для AA достаточно 3:1; обычному тексту нужно 4,5:1).

Править CSS показывает таблицу стилей темы в редакторе. Элементы управления пишут только внутрь блока, обрамлённого двумя комментариями gsta:visual, и перечитывают его, когда вы правите его значения вручную. То, что вы пишете вне блока, не затрагивается никогда. Если вы добавите в блок то, что элементы управления показать не могут, они перестанут писать, и панель сообщит об этом; Восстановить блок переписывает его из имеющихся в нём значений и больше ничего.

Импортировать… открывает .gsta.xz или отдельный .css. Пакет проверяется так, как его проверяет slides theme verify, с теми же ограничениями: небезопасный пакет (путь, выходящий за его пределы, ссылка, скрипт в SVG, внешний url(), несовпавшая контрольная сумма) отклоняется с кодом theme.* в «Проблемах», и ничего не меняется. В отдельной таблице стилей @import "gaia"; становится базовой темой (extends), потому что пакет указывает свою основу именно там. У добавленного шрифта лицензия LicenseRef-unspecified, пока вы не укажете её в «Сведениях».

Экспортировать .gsta.xz собирает пакет в вашем браузере и перечитывает его так, как это делает slides theme verify, поэтому файл его проходит; Экспортировать CSS скачивает скомпилированную таблицу. Ничего не отправляется. Каждая правка — это шаг Отмены (подряд идущие правки одного элемента — один шаг), и заменённое сохраняется как версия; Сохранить версию сохраняет тему и её версию под её именем в панели «Версии».

Отмена, повтор и версии

Undo и Redo (отмена и повтор) находятся на вкладке Home, а также на Ctrl+Z, Ctrl+Shift+Z и Ctrl+Y (Cmd на Mac). Они отменяют последнюю правку показанного файла (у каждого файла своя история), а затем последнюю операцию над всем проектом: выбранный пример, Reset, открытый .zip или папку, восстановленный черновик, удалённый или переименованный файл или папку, восстановленную версию. Redo возвращает всё таким, каким оно было, когда нажали Undo.

Версии хранят весь проект в этом браузере, ничего никуда не отправляя. Одна сохраняется вскоре после того, как вы перестали печатать (не чаще раза в 2 минуты), перед каждой операцией над всем проектом, при каждом экспорте и создании ссылки для обмена. Save version… сохраняет одну под именем. Home ▸ Versions открывает панель Versions:

  • Preview показывает версию в предпросмотре.
  • Compare with now показывает изменения каждого файла построчно, в одном столбце или рядом; F7 и Shift+F7 переходят между изменениями.
  • Restore возвращает версию; Undo отменяет восстановление.
  • Delete удаляет версию.

Что хранится: 20 новейших автоматических версий, затем по одной в час за сутки и по одной в день за месяц. Именованные версии хранятся, пока вы их не удалите (не более 50). Все версии вместе занимают не более 96 MiB, а файлы, которые не менялись, хранятся один раз. Когда хранилище браузера заполнено, первыми удаляются самые старые автоматические версии.

GitHub

Home ▸ History ▸ GitHub открывает панель, которая загружает папку презентации из репозитория GitHub и отправляет ваши изменения обратно как pull request. Заполните:

  • Репозиторий (владелец/имя);
  • Ветка (пусто: по умолчанию);
  • Папка (пусто: корень): в папке должен быть deck.md.

Над этими полями панель показывает git-фрейм: небольшую панель, в которой вы выбираете forge, вводите токен (скрыт), отмечаете Запомнить на этом устройстве и нажимаете Подключиться (или Войти через GitLab) либо Отключиться. Фрейм — это страница другого сайта, go-slides-usercontent.github.io, встроенная в playground: страница playground никогда не видит ваш токен.

Токен — это персональный токен доступа с тонкой настройкой (создать), ограниченный выбранными репозиториями, с правами Contents чтение и запись и Pull requests чтение и запись (Metadata чтение подразумевается). Затем:

  • Загрузить заменяет проект папкой из GitHub. Undo возвращает всё назад, а проект в прежнем виде сохраняется как версия «С GitHub».
  • Предложить изменения… запрашивает заголовок, создаёт новую ветку slides/<заголовок>-<дата-время> и открывает pull request. Она никогда не пишет в существующую ветку или в ветку по умолчанию. Открыть pull request переходит к нему.
  • Проверить изменения сравнивает более новую версию на GitHub с вашей в окне Compare. Взять их загружает её.

Для GitHub прокси не используется: фрейм обращается к нему напрямую.

Токен вводится во фрейме и остаётся на его сайте. Страница playground не может его прочитать (фрейм — другой origin, со своим хранилищем), никакая команда, которую страница может отправить, его не возвращает, а Content Security Policy страницы вообще не разрешает ей соединений с GitHub или GitLab. Фрейм отправляет токен только на api.github.com (или gitlab.com). Его никогда не сохраняют в черновике, версиях, ссылках для общего доступа и экспорте, и он никогда не попадает в предпросмотр слайдов и в воркер рендеринга. Запомнить на этом устройстве хранит его в собственном localStorage фрейма, на go-slides-usercontent.github.io, а не в хранилище playground, до Отключиться (или Forget my drafts).

Если вы пользовались более ранней версией: токен, который она хранила в собственном хранилище страницы playground, удаляется при первом открытии этой версии, и панель сообщает об этом. Введите его во фрейме заново (и отметьте «Запомнить», если хотите его сохранить).

Предложить изменения… — это запись, поэтому фрейм сначала спрашивает вас: он показывает заголовок, репозиторий и число файлов и ждёт, пока вы нажмёте его собственную кнопку Разрешить (не дольше двух минут, по одному предложению за раз). До вашего нажатия ничего не записывается.

Остаются два риска, потому что они присущи странице, которая встраивает фрейм. Скрипт, внедрённый в страницу playground, может прочитать nonce фрейма и отправлять команды фрейма: прочитать загруженную папку или запросить предложение (которое вам всё равно нужно разрешить во фрейме). И он может нарисовать поддельную панель поверх фрейма и сам запросить ваш токен: если фрейм выглядит странно или находится не там, где должен, не вводите токен. Ни то, ни другое не позволяет ему прочитать токен, который хранит фрейм. Выбирайте токен, ограниченный нужными репозиториями. Для команд режим собственного сервера (скоро) хранит токены на сервере.

GitLab.com

В панели есть список forge: GitHub и GitLab.com. Для GitLab укажите персональный токен доступа с областью api или нажмите Войти через GitLab (код авторизации OAuth с PKCE, без секрета). Вход открывает небольшое окно сайта фрейма и возвращается к нему; страница playground, в которой вы работаете, не покидается. Его токены остаются только в памяти фрейма (никогда не запоминаются на устройстве, даже с Запомнить на этом устройстве), сами обновляются до истечения срока, а Отключиться отзывает их в GitLab. Вход, начатый не фреймом, или повторно использованная ссылка отклоняется. Вход доступен, когда приложение GitLab этого сайта зарегистрировано; до тех пор пользуйтесь персональным токеном доступа.

Запросы идут только на api.github.com и gitlab.com и только из фрейма: страница playground не делает их и не отправляет referrer.

Почему api? Таблица областей GitLab говорит о write_repository: «Does not support API authentication». Она нужна только для git по HTTP, который GitLab отдаёт без CORS, поэтому браузер не может ею пользоваться. Предложения идут через REST API, которому нужна api, «complete read and write access to the API». Украденный токен api может всё, что его пользователь может делать через API, во всех проектах, до которых этот пользователь дотягивается. Выбирайте токен доступа проекта или группы, ограниченный репозиториями презентаций, или отдельную учётную запись GitLab, которая лишь участник проектов презентаций.

Безопасность

Презентация показывается в iframe, изолированном без источника страницы: он не может обратиться ни к Playground, ни к его хранилищу, не отправляет форм и никуда не переходит. Его страница несёт политику Content Security Policy, которая запускает только её собственные скрипты. Сырой HTML в презентации следует списку разрешённого Marp, как это по умолчанию делает slides. Отрисовка, длящаяся дольше 5 секунд (шаблон, ушедший в цикл), останавливается.

Окно докладчика сохраняет эту изоляцию. Его открывает сам Playground, и оно показывает презентацию в iframe, изолированном так же. Два iframe не могут делить хранилище, поэтому Playground передаёт номер слайда между ними в сообщениях. Ни один фрейм, запускающий презентацию, не получает источник Playground.

Медиа проекта попадают в изолированные фреймы как байты в сообщении, и каждый фрейм делает из них собственные URL blob: в своём источнике. URL blob:, созданный Playground, там не загружается, а политика фреймов получает только blob: для медиа и шрифтов.

Playground можно раздавать со своей машины за входом по паролю: см. Самостоятельный хостинг.

Размер и скорость

Модуль занимает 8,8 МиБ в том виде, в каком его отдаёт GitHub Pages (gzip; Pages не отдаёт brotli). Он скачивается один раз с индикатором хода, затем кэшируется браузером до следующего развёртывания. На Apple M4 Max с Chrome 155, измерено на живой странице, редактор готов через 2,1 с после открытия страницы, из которых 1,5 с — загрузка, а первые слайды появляются на 2,4 с. Изменение презентации из 100 слайдов в тесте производительности доходит до предпросмотра примерно за 30 мс: go-slides отрисовывает только изменившиеся слайды, и в предпросмотре заменяются только они.

Created on by tannevaled

Modified on by tannevaled