Перейти до вмісту

Playground

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

Відкрити Playground →

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

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

Що в ньому є

  • Живий попередній перегляд кожного слайда, що рендериться поза потоком сторінки (Web Worker), тож набір тексту ніколи його не чекає. Клацніть слайд, щоб перемістити редактор до його рядка; перемістіть курсор — і попередній перегляд прокрутиться до його слайда.

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

  • Вигляд доповідача: Present (або p у показі) відкриває його в другому вікні: поточний слайд, наступний крок, нотатки доповідача (<!-- comments --> презентації), годинник і таймер. Клавіші стрілок, Space, Home і End працюють у будь-якому вікні, і кожне слідує за іншим, також коли ви редагуєте презентацію. Якщо вікно не відкривається, дозвольте спливні вікна для сайту. Вигляд огляду (o) є лише в завантаженій сторінці.

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

  • Довідка про те, що під курсором: директиву, kind (що він встановлює), функцію шаблону. Панель довідки також містить посилання на ці сторінки. Починаючи з v0.16.0 довідка про директиви відповідає мові інтерфейсу, 11 мовами.

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

  • Приклади: вітальна презентація, шаблони, що генерують слайди, kinds слайдів, front matter у HCL, теми й spot-директиви, а також математика, зображення та фони (![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 редагує Markdown за вас, і кожне натискання — це один крок Undo.

    • Текст: 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.
    • Абзац: Heading 1–3 (Ctrl+Alt+1..3), марковані списки (Ctrl+Shift+8), нумерація (Ctrl+Shift+7) і цитата працюють на виділених рядках і перемикаються. Горизонтальна лінія — це тег <hr>: ---, *** і ___ кожен починав би новий слайд у Marp.
    • Таблиця: сітка вибирає стовпці й рядки. На курсорі в таблиці ви додаєте або видаляєте рядок чи стовпець і вирівнюєте стовпець (:--, :-:, --:); таблиця переписується вирівняною після кожної правки.
    • 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) у браузері не створюються: скористайтеся командою або розширенням 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 можна обслуговувати з вашої власної машини, за входом: див. Self-hosting.

Розмір і швидкість

Модуль має 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