Using JSZip in Observable Framework for reading and creating ZIP archives.
Observable Framework documentation: Library: ZIP Source: https://observablehq.com/framework/lib-zip
To load a ZIP archive, use FileAttachment.
const muybridge = FileAttachment("muybridge.zip").zip();
This returns a promise to a ZipArchive. This uses JSZip under the hood.
muybridge
The filenames property lists the paths of the files contained within the ZIP archive.
muybridge.filenames
To pull out a single file from the archive, use the archive.file method. It returns a FileAttachment which you can use to load the file contents like any other file.
muybridge.file("deer.jpeg").image({width: 320, alt: "A deer"})
That said, if you know the name of the file within the ZIP archive statically, you don’t need to load the ZIP archive; you can simply request the file within the archive directly. The specified file is then extracted from the ZIP archive at build time.
FileAttachment("muybridge/deer.jpeg").image({width: 320, alt: "A deer"})
For images and other media, you can simply use static HTML.
<img src="muybridge/deer.jpeg" width="320" alt="A deer"><img src="muybridge/deer.jpeg" width="320" alt="A deer">
One reason to load a ZIP archive is that you don’t know the files statically — maybe there are lots of files and you don’t want to enumerate them statically, or maybe you expect them to change over time and the ZIP archive is generated by a data loader. For example, maybe you want to display an arbitrary collection of images.
Gallery(await Promise.all(muybridge.filenames.map((f) => muybridge.file(f).image())))
function Gallery(images) {
return html`<div style="
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 1rem;
">${images.map((i) => (i.style = 'width: 100%; height: 100%;', i))}</div>`;
}
To let the user download a ZIP archive, use the download attribute on a link.
<a href="muybridge.zip" download>
<button>download zip</button>
</a>
npx skills add spqw/observable-framework-lib-zip下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer