Skip to content

Playground: a file panel for themes, kinds, data files and media - #32

Merged
tannevaled merged 1 commit into
mainfrom
feat/playground-files
Oct 22, 2026
Merged

tannevaled merged 1 commit into
mainfrom
feat/playground-files

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

The deck's project, left of the editor: themes, kinds, data files and media, laid out the way the slides command and the VS Code extension read them.

The panel. It is a toolkit.FileTree (go-widgets/toolkit v0.335.0, go-widgets/toolkit#498) over the draft project of the store from #28.

  • Shown: deck.md, slides.yaml, themes/, kinds/, media/.
  • Opening a file edits it in the same editor. The language comes from the extension (Markdown, YAML, HCL, JSON, CSS), and go-slides' diagnostics show for kinds and config files.
  • File operations:
    • rename with F2
    • new file or new folder
    • delete, after a confirmation
    • drag a file onto a folder to move it
    • a context menu, also on Shift+F10
  • WAI-ARIA APG treeview keyboard handling, and Seti icons.

Project menu.

  • New theme from default, gaia or uncover, built with @import. The new theme joins the Theme list.
  • New kind and new data file, both from templates.
  • Each new file is listed in slides.yaml. Renames and deletions are followed there too.

Media. Media dropped or pasted on the editor are stored as bytes in media/, and the deck names them (![](media/x.png)). The deck no longer holds them as data: URIs.

  • Why not blob: URLs from the page: I checked in Chrome. A blob: URL made by the page is refused in the opaque-origin sandbox ("Not allowed to load local resource").
  • What happens instead: the page posts the bytes to the preview, rail and presenter frames. Each frame makes its own blob:null/… URLs and puts them in place of the paths.
  • Sandbox and CSP: the sandbox is unchanged. The only CSP change is adding blob: to media-src and font-src.
  • Save as ▸ HTML page inlines the media as data: URIs.
  • Limits: 8 MiB per file and 64 MiB per project. Usage is shown under the panel.

Project in and out.

  • Download project (.zip).
  • Open project from a .zip, or from a folder. For a folder it uses the File System Access API where available, and <input webkitdirectory> otherwise.
  • The importer refuses:
    • paths outside the project (.., absolute paths, backslashes)
    • symlinks
    • more than 256 files or more than 1024 entries
    • files over 8 MiB (each file is read through a size limit)
    • archives that inflate more than 100× their size
  • Fuzzing: FuzzImportZip, 2.3M runs, no finding.

Share link. When the project holds more than the deck, Share says the link carries only the deck and offers the .zip instead.

Verified.

  • browsertest/files.cjs (added to CI) runs in headless Chrome:
    • a theme made from the menu and picked in the Theme list colours the h1 #4f46e5
    • a kind is applied (invert)
    • a dropped PNG shows as a background through blob:null/… and decodes
    • the project is downloaded as a .zip and reopened from that file with the same files
  • drive.cjs passes, updated for the drop going into media/.
  • slides build deck.md on the exported project, unzipped, builds it with the project theme.

Cost of 20 MiB of media.

Time
Edit reaches the preview, no media 30 ms (median of 7)
Edit reaches the preview, with 20 MiB of media 30 ms (median of 7)
A new document (theme change), media posted again ~270 ms

Load average was about 10–14 during these runs. Both edit rows were measured in the same run.

Not in this PR. The PDF, PPTX and ODP exports from #29 still render the deck alone, without the project's themes, kinds or media. That is a follow-up: exporter.Export has to take the project's files.

🤖 Generated with Claude Code

The deck's project, left of the editor: a go-widgets toolkit.FileTree
(v0.335.0) over the draft project of the store (#28), in the layout the
slides command and the VS Code extension read: deck.md, slides.yaml,
themes/, kinds/, media/.

- A file opens in the editor with its language (Markdown, YAML, HCL, JSON,
  CSS) and its diagnostics; rename (F2), new file or folder, delete with
  confirmation, drag to move, context menu, APG treeview keys, Seti icons.
- The Project menu makes a theme built on default, gaia or uncover
  (@import), a kind and a data file from templates, lists them in
  slides.yaml; project themes join the Theme list.
- Media dropped or pasted on the editor go into media/ as bytes and the
  deck names them (![](media/x.png)) instead of holding a data: URI. The
  preview's opaque-origin frame cannot load a blob: URL made by the page
  (measured), so the page posts the bytes and the frame makes its own blob:
  URLs (media.go); CSP otherwise unchanged (blob: in media-src/font-src).
  Download HTML inlines them. Bounds: 8 MiB a file, 64 MiB a project,
  shown under the panel.
- Download project (.zip) and Open project (.zip or folder: File System
  Access API, else <input webkitdirectory>). The importer refuses paths
  that leave the project, symlinks, >256 files, >1024 entries, oversize
  files (read through a limit), and archives inflating >100x; fuzzed
  (2.3M execs, no finding).
- Share link says the link holds the deck only and offers the .zip.

Verified in headless Chrome (browsertest/files.cjs, added to CI) and with
`slides build deck.md` on an exported, unzipped project. 20 MiB of media:
an edit reaches the preview in 17 ms with and without them; a new
document posts them again in ~270 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tannevaled
tannevaled force-pushed the feat/playground-files branch from 4348374 to afc694e Compare October 22, 2026 17:57
@tannevaled
tannevaled merged commit 1915c07 into main Oct 22, 2026
7 checks passed
@tannevaled
tannevaled deleted the feat/playground-files branch October 22, 2026 18:04
tannevaled added a commit to go-slides/docs that referenced this pull request Oct 22, 2026
)

The Playground page describes the project panel of
go-slides/go-slides.github.io#32: files in the slides command's layout,
New theme / New kind / New data file, media in media/ instead of data:
URIs, Download and Open project (.zip or folder) and its bounds, Share
with a project, and how media reach the sandboxed preview.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant