zone5 0.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +258 -0
  3. package/dist/cli/index.js +33 -0
  4. package/dist/cli/index2.js +238 -0
  5. package/dist/cli/index3.js +53 -0
  6. package/dist/cli/templates/.zone5.toml +4 -0
  7. package/dist/cli/templates/app.css +3 -0
  8. package/dist/cli/templates/layout.svelte +15 -0
  9. package/dist/cli/templates/layout.ts +1 -0
  10. package/dist/components/Zone5.svelte +153 -0
  11. package/dist/components/Zone5.svelte.d.ts +12 -0
  12. package/dist/components/Zone5Img.svelte +103 -0
  13. package/dist/components/Zone5Img.svelte.d.ts +10 -0
  14. package/dist/components/Zone5Lightbox.svelte +131 -0
  15. package/dist/components/Zone5Lightbox.svelte.d.ts +12 -0
  16. package/dist/components/Zone5Provider.svelte +68 -0
  17. package/dist/components/Zone5Provider.svelte.d.ts +9 -0
  18. package/dist/components/atoms/Button.svelte +40 -0
  19. package/dist/components/atoms/Button.svelte.d.ts +13 -0
  20. package/dist/components/atoms/CloseButton.svelte +18 -0
  21. package/dist/components/atoms/CloseButton.svelte.d.ts +9 -0
  22. package/dist/components/atoms/NextButton.svelte +19 -0
  23. package/dist/components/atoms/NextButton.svelte.d.ts +10 -0
  24. package/dist/components/atoms/PrevButton.svelte +19 -0
  25. package/dist/components/atoms/PrevButton.svelte.d.ts +10 -0
  26. package/dist/components/atoms/index.d.ts +4 -0
  27. package/dist/components/atoms/index.js +5 -0
  28. package/dist/components/constants.d.ts +17 -0
  29. package/dist/components/constants.js +17 -0
  30. package/dist/components/index.d.ts +6 -0
  31. package/dist/components/index.js +7 -0
  32. package/dist/components/portal.d.ts +4 -0
  33. package/dist/components/portal.js +26 -0
  34. package/dist/components/types.d.ts +7 -0
  35. package/dist/components/types.js +1 -0
  36. package/dist/config.d.ts +51 -0
  37. package/dist/config.js +56 -0
  38. package/dist/index.d.ts +6 -0
  39. package/dist/index.js +4 -0
  40. package/dist/module.d.ts +19 -0
  41. package/dist/processor/blurhash.d.ts +7 -0
  42. package/dist/processor/blurhash.js +37 -0
  43. package/dist/processor/color.d.ts +5 -0
  44. package/dist/processor/color.js +32 -0
  45. package/dist/processor/config.d.ts +12 -0
  46. package/dist/processor/config.js +9 -0
  47. package/dist/processor/exif/converters.d.ts +7 -0
  48. package/dist/processor/exif/converters.js +38 -0
  49. package/dist/processor/exif/defaults.d.ts +17 -0
  50. package/dist/processor/exif/defaults.js +17 -0
  51. package/dist/processor/exif/exif.d.ts +34 -0
  52. package/dist/processor/exif/exif.js +43 -0
  53. package/dist/processor/exif/index.d.ts +1 -0
  54. package/dist/processor/exif/index.js +1 -0
  55. package/dist/processor/exif/types.d.ts +4 -0
  56. package/dist/processor/exif/types.js +1 -0
  57. package/dist/processor/file.d.ts +3 -0
  58. package/dist/processor/file.js +28 -0
  59. package/dist/processor/index.d.ts +27 -0
  60. package/dist/processor/index.js +70 -0
  61. package/dist/processor/variants.d.ts +13 -0
  62. package/dist/processor/variants.js +83 -0
  63. package/dist/remark.d.ts +5 -0
  64. package/dist/remark.js +268 -0
  65. package/dist/stores/index.d.ts +1 -0
  66. package/dist/stores/index.js +1 -0
  67. package/dist/stores/registry.svelte.d.ts +22 -0
  68. package/dist/stores/registry.svelte.js +100 -0
  69. package/dist/test-setup.d.ts +9 -0
  70. package/dist/test-setup.js +25 -0
  71. package/dist/vite.d.ts +2 -0
  72. package/dist/vite.js +158 -0
  73. package/package.json +144 -5
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Christian Wygoda
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,258 @@
1
+ # Zone5
2
+
3
+ Image gallery system for SvelteKit with optimized image processing, lightbox functionality, and MDX support.
4
+
5
+ ## Features
6
+
7
+ - 🖼️ Optimized image processing with variants, blurhash, and color extraction
8
+ - 🔍 Lightbox component with keyboard navigation
9
+ - 📝 MDX integration for markdown-based galleries
10
+ - 🎨 Tailwind CSS 4 support
11
+ - ⚡ Vite plugin for automatic image processing
12
+ - 🛠️ CLI tool for quick project scaffolding
13
+
14
+ ## CLI Tool
15
+
16
+ The `zone5` CLI tool helps you quickly create a new SvelteKit gallery project:
17
+
18
+ ```bash
19
+ npx zone5 create <input-folder> <output-folder> [options]
20
+ ```
21
+
22
+ ### Options
23
+
24
+ - `-m, --mode <type>` - How to handle images: copy, link, or move (default: copy)
25
+ - `-p, --package-manager <pm>` - Package manager: npm, pnpm, yarn, bun, or skip (default: npm)
26
+ - `--no-interactive` - Skip prompts and use defaults
27
+
28
+ ### Example
29
+
30
+ ```bash
31
+ npx zone5 create ./my-photos ./my-gallery --package-manager pnpm
32
+ ```
33
+
34
+ ## Usage in SvelteKit Projects
35
+
36
+ ### Installation
37
+
38
+ ```bash
39
+ npm install zone5
40
+ ```
41
+
42
+ ### Basic Setup
43
+
44
+ 1. Add the Vite plugin to your `vite.config.ts`:
45
+
46
+ ```typescript
47
+ import { sveltekit } from '@sveltejs/kit/vite';
48
+ import { zone5 } from 'zone5/vite';
49
+ import { defineConfig } from 'vite';
50
+
51
+ export default defineConfig({
52
+ plugins: [zone5(), sveltekit()],
53
+ });
54
+ ```
55
+
56
+ 2. Wrap your layout with `Zone5Provider`:
57
+
58
+ ```svelte
59
+ <script>
60
+ import { Zone5Provider } from 'zone5/components';
61
+ </script>
62
+
63
+ <Zone5Provider>
64
+ <slot />
65
+ </Zone5Provider>
66
+ ```
67
+
68
+ 3. Create a `.zone5.toml` config file:
69
+
70
+ ```toml
71
+ [base]
72
+ root = "src/routes"
73
+ cache = ".zone5"
74
+ namespace = "@zone5"
75
+
76
+ [processor]
77
+ widths = [400, 800, 1200, 1600, 2400]
78
+ ```
79
+
80
+ ### Using in Components
81
+
82
+ ```svelte
83
+ <script>
84
+ import { Zone5 } from 'zone5/components';
85
+
86
+ import image1 from './photo1.jpg?z5';
87
+ import image2 from './photo2.jpg?z5';
88
+ </script>
89
+
90
+ <Zone5 images={[image1, image2]} />
91
+ ```
92
+
93
+ ### Using in Markdown/MDX
94
+
95
+ Add the remark plugin to your `svelte.config.js`:
96
+
97
+ ```javascript
98
+ import { remarkZ5Images } from 'zone5/remark';
99
+ import { mdsvex } from 'mdsvex';
100
+
101
+ export default {
102
+ preprocess: [
103
+ mdsvex({
104
+ extensions: ['.md'],
105
+ remarkPlugins: [remarkZ5Images],
106
+ }),
107
+ ],
108
+ };
109
+ ```
110
+
111
+ Then simply reference images with the `?z5` query parameter:
112
+
113
+ ```markdown
114
+ ![Mountain view](./mountains.jpg?z5)
115
+ ![Beach sunset](./beach.jpg?z5)
116
+ ```
117
+
118
+ ## Development
119
+
120
+ ### Prerequisites
121
+
122
+ - Node.js 18+
123
+ - pnpm (recommended package manager)
124
+
125
+ ### Getting Started
126
+
127
+ ```bash
128
+ # Install dependencies
129
+ pnpm install
130
+
131
+ # Run development server
132
+ pnpm dev
133
+
134
+ # Run tests in watch mode
135
+ pnpm test --watch
136
+
137
+ # Type check
138
+ pnpm check
139
+ ```
140
+
141
+ ### Project Structure
142
+
143
+ ```
144
+ src/
145
+ ├── lib/ # Main library code
146
+ │ ├── components/ # Svelte components
147
+ │ ├── processor/ # Image processing pipeline
148
+ │ ├── vite.ts # Vite plugin
149
+ │ ├── remark.ts # Remark MDX plugin
150
+ │ └── config.ts # Configuration loader
151
+ ├── cli/ # CLI tool
152
+ └── routes/ # Demo/documentation site
153
+ ```
154
+
155
+ ### Testing
156
+
157
+ The project uses a comprehensive test suite organized by purpose:
158
+
159
+ #### `pnpm test` - Unit Tests (⚡ ~2.7s)
160
+
161
+ Fast unit tests for core functionality:
162
+
163
+ - Component tests (portal)
164
+ - Processor tests (blurhash, color, variants, exif)
165
+ - Remark plugin tests
166
+
167
+ **Use this during development** for quick feedback on code changes.
168
+
169
+ To run a single test file:
170
+
171
+ ```bash
172
+ pnpm vitest src/lib/processor/blurhash.test.ts
173
+ ```
174
+
175
+ #### `pnpm test:ui` - Integration UI Tests
176
+
177
+ Playwright tests on the local project (currently placeholder for future tests).
178
+
179
+ #### `pnpm test:cli` - CLI Integration Tests (~47.8s)
180
+
181
+ Integration tests for CLI functionality:
182
+
183
+ - Project creation and configuration
184
+ - Package manager support (npm, pnpm, yarn, bun)
185
+ - Template file generation
186
+ - Utility functions
187
+
188
+ **Run this before committing** CLI-related changes.
189
+
190
+ #### `pnpm test:e2e` - End-to-End Tests (~24.1s)
191
+
192
+ Playwright E2E tests that validate the complete workflow:
193
+
194
+ - Creates a new project using the CLI
195
+ - Builds the generated project
196
+ - Tests the lightbox UI functionality
197
+ - Validates Tailwind CSS integration
198
+
199
+ **Run this to verify** the complete user experience.
200
+
201
+ #### `pnpm test:all` - All Tests (~74.6s)
202
+
203
+ Runs all test suites in sequence: unit → CLI → E2E.
204
+
205
+ **Run this before releases** to ensure everything works together.
206
+
207
+ ### Build Commands
208
+
209
+ ```bash
210
+ pnpm dev # Watch mode for development (full demo site)
211
+ pnpm build # Build the package (runs svelte-package + CLI build + publint)
212
+ pnpm build:cli # Build just the CLI tool
213
+ pnpm build:watch # Build the package in watch mode
214
+ pnpm check # Type checking with svelte-check
215
+ pnpm check:watch # Type checking in watch mode
216
+ pnpm lint # Run ESLint
217
+ ```
218
+
219
+ ### Architecture Overview
220
+
221
+ Zone5 consists of four main components:
222
+
223
+ 1. **Image Processor** (`src/lib/processor/`) - Uses Sharp to generate image variants, extract EXIF data, create blurhashes, and determine dominant colors. Results are cached in `.zone5/` directory.
224
+
225
+ 2. **Vite Plugin** (`src/lib/vite.ts`) - Intercepts `.jpg?z5` imports at build time, processes images, and serves them during development.
226
+
227
+ 3. **Remark Plugin** (`src/lib/remark.ts`) - Transforms markdown images with `?z5` query parameters into Zone5 Svelte components.
228
+
229
+ 4. **Component System** (`src/lib/components/`) - Svelte 5 components with a centralized registry for managing lightbox state and navigation across multiple galleries.
230
+
231
+ See [CLAUDE.md](./CLAUDE.md) for detailed architecture documentation.
232
+
233
+ ### Contributing
234
+
235
+ 1. Make your changes
236
+ 2. Run `pnpm test` to ensure unit tests pass
237
+ 3. Run `pnpm check` to verify types
238
+ 4. Run `pnpm lint` to check code style
239
+ 5. If you changed the CLI, run `pnpm test:cli`
240
+ 6. Before submitting, run `pnpm test:all` to validate everything
241
+
242
+ **Commit Messages:**
243
+
244
+ This project uses [Conventional Commits](https://www.conventionalcommits.org/). Commit messages are validated via Husky hooks.
245
+
246
+ Format: `<type>: <description>`
247
+
248
+ Valid types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`
249
+
250
+ Examples:
251
+
252
+ - `feat: add lightbox keyboard navigation`
253
+ - `fix: resolve EXIF parsing error`
254
+ - `docs: update installation instructions`
255
+
256
+ ## License
257
+
258
+ MIT
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ import { Command as s } from "commander";
3
+ import { readFileSync as c } from "node:fs";
4
+ import { dirname as l, join as d } from "node:path";
5
+ import { fileURLToPath as g } from "node:url";
6
+ import n from "picocolors";
7
+ import { createProject as f } from "./index2.js";
8
+ const u = l(g(import.meta.url)), k = JSON.parse(c(d(u, "../../package.json"), "utf-8")), t = new s();
9
+ t.name("zone5").description("Image gallery system for SvelteKit").version(k.version);
10
+ t.command("create").description("Create a new SvelteKit project with zone5 image processing").argument("<input-folder>", "Path to folder containing images").argument("<output-folder>", "Path where the new project will be created").option("-m, --mode <type>", "How to handle images: copy, link, or move", "copy").option(
11
+ "-p, --package-manager <pm>",
12
+ "Package manager to use: npm, pnpm, yarn, bun, or skip to not install",
13
+ "npm"
14
+ ).option("--no-interactive", "Skip prompts and use defaults").action(async (a, i, p) => {
15
+ const { mode: e, packageManager: o, interactive: m } = p;
16
+ ["copy", "link", "move"].includes(e) || (console.error(n.red(`Error: Invalid mode "${e}". Must be one of: copy, link, move`)), process.exit(1)), ["npm", "pnpm", "yarn", "bun", "skip"].includes(o) || (console.error(
17
+ n.red(
18
+ `Error: Invalid package manager "${o}". Must be one of: npm, pnpm, yarn, bun, skip`
19
+ )
20
+ ), process.exit(1));
21
+ try {
22
+ await f({
23
+ inputFolder: a,
24
+ outputFolder: i,
25
+ mode: e,
26
+ packageManager: o,
27
+ interactive: m
28
+ });
29
+ } catch (r) {
30
+ console.error(n.red("Error:"), r instanceof Error ? r.message : String(r)), process.exit(1);
31
+ }
32
+ });
33
+ t.parse();
@@ -0,0 +1,238 @@
1
+ import f from "fs-extra";
2
+ import { execSync as C } from "node:child_process";
3
+ import { mkdir as h, writeFile as p, copyFile as j, symlink as x, rename as S } from "node:fs/promises";
4
+ import { dirname as $, join as n, resolve as w, basename as u } from "node:path";
5
+ import { fileURLToPath as z } from "node:url";
6
+ import D from "ora";
7
+ import l from "picocolors";
8
+ import I from "prompts";
9
+ import { pathExists as k, isDirectory as b, findImagesRecursive as J } from "./index3.js";
10
+ const T = $(z(import.meta.url)), g = n(T, "templates");
11
+ async function X(e) {
12
+ const { inputFolder: i, outputFolder: o, mode: s, packageManager: a, interactive: d } = e, c = w(i), r = w(o);
13
+ console.log(l.bold(`
14
+ 🖼️ zone5
15
+ `));
16
+ const t = D("Validating input folder...").start();
17
+ if (!await k(c))
18
+ throw t.fail(`Input folder does not exist: ${c}`), new Error("Input folder not found");
19
+ if (!await b(c))
20
+ throw t.fail(`Input path is not a directory: ${c}`), new Error("Input path must be a directory");
21
+ t.text = "Scanning for images...";
22
+ const m = await J(c);
23
+ if (m.length === 0)
24
+ throw t.fail("No images found in input folder"), new Error("No images found");
25
+ if (t.succeed(`Found ${l.cyan(m.length.toString())} images`), await k(r))
26
+ throw t.fail(`Output folder already exists: ${r}`), new Error("Output folder must not exist");
27
+ if (d) {
28
+ const { confirmed: y } = await I({
29
+ type: "confirm",
30
+ name: "confirmed",
31
+ message: `Create project at ${l.cyan(r)} with ${l.cyan(m.length.toString())} images (mode: ${l.yellow(s)})?`,
32
+ initial: !0
33
+ });
34
+ y || (console.log(l.dim("Cancelled")), process.exit(0));
35
+ }
36
+ t.start("Creating SvelteKit project..."), await P(r), t.succeed("Created SvelteKit project"), t.start("Adding dependencies to package.json..."), await L(r), t.succeed("Added dependencies to package.json"), a === "skip" ? t.info("Skipped dependency installation") : (t.start("Installing dependencies..."), await N(r, a), t.succeed("Installed dependencies")), t.start(
37
+ `${s === "copy" ? "Copying" : s === "link" ? "Linking" : "Moving"} images...`
38
+ );
39
+ const v = n(r, "src", "routes");
40
+ if (await f.ensureDir(v), await E(m, c, v, s), t.succeed(
41
+ `${s === "copy" ? "Copied" : s === "link" ? "Linked" : "Moved"} ${m.length} images`
42
+ ), t.start("Generating gallery page..."), await F(v, m), t.succeed("Generated gallery page"), t.start("Adding template files..."), await A(r), t.succeed("Added template files"), t.start("Configuring Vite..."), await M(r), t.succeed("Configured Vite"), t.start("Configuring Svelte..."), await R(r), t.succeed("Configured Svelte"), t.start("Configuring Tailwind..."), await Z(r), t.succeed("Configured Tailwind"), t.start("Creating zone5 config..."), await _(r), t.succeed("Created zone5 config"), a !== "skip" && (t.start("Running svelte-kit sync..."), await O(r, a), t.succeed("Ran svelte-kit sync")), console.log(l.green(`
43
+ ✓ Project created successfully!
44
+ `)), console.log("Next steps:"), console.log(l.cyan(` cd ${u(r)}`)), a === "skip")
45
+ console.log(l.cyan(" npm install # or your preferred package manager")), console.log(l.cyan(" npm run dev"));
46
+ else {
47
+ const y = a === "npm" ? "npm run dev" : `${a} dev`;
48
+ console.log(l.cyan(` ${y}`));
49
+ }
50
+ console.log();
51
+ }
52
+ async function P(e) {
53
+ await h(e, { recursive: !0 });
54
+ const i = {
55
+ name: u(e),
56
+ version: "0.0.1",
57
+ private: !0,
58
+ type: "module",
59
+ scripts: {
60
+ dev: "vite dev",
61
+ build: "vite build",
62
+ preview: "vite preview"
63
+ },
64
+ devDependencies: {},
65
+ dependencies: {}
66
+ };
67
+ await p(n(e, "package.json"), JSON.stringify(i, null, " ")), await f.ensureDir(n(e, "src", "routes")), await f.ensureDir(n(e, "static")), await p(n(e, "src", "app.html"), `<!doctype html>
68
+ <html lang="en">
69
+ <head>
70
+ <meta charset="utf-8" />
71
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
72
+ %sveltekit.head%
73
+ </head>
74
+ <body data-sveltekit-preload-data="hover">
75
+ <div style="display: contents">%sveltekit.body%</div>
76
+ </body>
77
+ </html>
78
+ `);
79
+ }
80
+ async function L(e) {
81
+ const i = n(e, "package.json"), o = JSON.parse(await f.readFile(i, "utf-8"));
82
+ o.devDependencies = {
83
+ "@lucide/svelte": "^0.553.0",
84
+ "@sveltejs/adapter-static": "^3.0.0",
85
+ "@sveltejs/kit": "^2.0.0",
86
+ "@sveltejs/vite-plugin-svelte": "^6.0.0",
87
+ "@tailwindcss/vite": "^4.0.0",
88
+ zone5: "latest",
89
+ mdsvex: "^0.12.0",
90
+ svelte: "^5.0.0",
91
+ tailwindcss: "^4.0.0",
92
+ typescript: "^5.0.0",
93
+ vite: "^7.0.0"
94
+ };
95
+ const s = process.env.ZONE5_LOCAL_PATH;
96
+ if (s) {
97
+ const a = w(s);
98
+ o.devDependencies.zone5 = `file:${a}`;
99
+ }
100
+ await p(i, JSON.stringify(o, null, " "));
101
+ }
102
+ async function N(e, i) {
103
+ C((() => {
104
+ switch (i) {
105
+ case "npm":
106
+ return "npm install";
107
+ case "pnpm":
108
+ return "pnpm install";
109
+ case "yarn":
110
+ return "yarn install";
111
+ case "bun":
112
+ return "bun install";
113
+ }
114
+ })(), {
115
+ cwd: e,
116
+ stdio: "pipe"
117
+ }), await p(n(e, "svelte.config.js"), `import adapter from '@sveltejs/adapter-static';
118
+
119
+ /** @type {import('@sveltejs/kit').Config} */
120
+ const config = {
121
+ kit: {
122
+ adapter: adapter()
123
+ }
124
+ };
125
+
126
+ export default config;
127
+ `), await p(n(e, "vite.config.ts"), `import { sveltekit } from '@sveltejs/vite-plugin-svelte';
128
+ import { defineConfig } from 'vite';
129
+
130
+ export default defineConfig({
131
+ plugins: [sveltekit()]
132
+ });
133
+ `);
134
+ const d = {
135
+ extends: "./.svelte-kit/tsconfig.json",
136
+ compilerOptions: {
137
+ allowJs: !0,
138
+ checkJs: !0,
139
+ esModuleInterop: !0,
140
+ forceConsistentCasingInFileNames: !0,
141
+ resolveJsonModule: !0,
142
+ skipLibCheck: !0,
143
+ sourceMap: !0,
144
+ strict: !0,
145
+ moduleResolution: "bundler"
146
+ }
147
+ };
148
+ await p(n(e, "tsconfig.json"), JSON.stringify(d, null, " "));
149
+ }
150
+ async function O(e, i) {
151
+ C((() => {
152
+ switch (i) {
153
+ case "npm":
154
+ return "npx svelte-kit sync";
155
+ case "pnpm":
156
+ return "pnpm exec svelte-kit sync";
157
+ case "yarn":
158
+ return "yarn svelte-kit sync";
159
+ case "bun":
160
+ return "bunx svelte-kit sync";
161
+ }
162
+ })(), {
163
+ cwd: e,
164
+ stdio: "pipe"
165
+ });
166
+ }
167
+ async function E(e, i, o, s) {
168
+ for (const { path: a, relativePath: d } of e) {
169
+ const c = n(o, u(d));
170
+ s === "copy" ? await j(a, c) : s === "link" ? await x(a, c) : s === "move" && await S(a, c);
171
+ }
172
+ }
173
+ async function F(e, i) {
174
+ const s = `# Photo Gallery
175
+
176
+ ${i.map(({ relativePath: a }) => {
177
+ const d = u(a);
178
+ return `![${d.replace(/\.[^.]+$/, "")}](./${d}?z5)`;
179
+ }).join(`
180
+ `)}
181
+ `;
182
+ await p(n(e, "+page.md"), s);
183
+ }
184
+ async function A(e) {
185
+ const i = n(g, "layout.svelte"), o = n(e, "src", "routes", "+layout.svelte");
186
+ await f.copy(i, o);
187
+ const s = n(g, "app.css"), a = n(e, "src", "app.css");
188
+ await f.copy(s, a);
189
+ const d = n(g, "layout.ts"), c = n(e, "src", "routes", "+layout.ts");
190
+ await f.copy(d, c);
191
+ }
192
+ async function M(e) {
193
+ const i = n(e, "vite.config.ts");
194
+ await p(i, `import { sveltekit } from '@sveltejs/kit/vite';
195
+ import tailwindcss from '@tailwindcss/vite';
196
+ import { zone5 } from 'zone5/vite';
197
+ import { defineConfig } from 'vite';
198
+
199
+ export default defineConfig({
200
+ plugins: [tailwindcss(), zone5(), sveltekit()]
201
+ });
202
+ `);
203
+ }
204
+ async function R(e) {
205
+ const i = n(e, "svelte.config.js");
206
+ await p(i, `import adapter from '@sveltejs/adapter-static';
207
+ import { mdsvex } from 'mdsvex';
208
+ import { remarkZ5Images } from 'zone5/remark';
209
+
210
+ /** @type {import('@sveltejs/kit').Config} */
211
+ const config = {
212
+ extensions: ['.svelte', '.md'],
213
+ preprocess: [
214
+ mdsvex({
215
+ extensions: ['.md'],
216
+ remarkPlugins: [remarkZ5Images]
217
+ })
218
+ ],
219
+ kit: {
220
+ adapter: adapter()
221
+ }
222
+ };
223
+
224
+ export default config;
225
+ `);
226
+ }
227
+ async function Z(e) {
228
+ await p(n(e, "tailwind.config.ts"), `/** @type {import('tailwindcss').Config} */
229
+ export default {};
230
+ `);
231
+ }
232
+ async function _(e) {
233
+ const i = n(g, ".zone5.toml"), o = n(e, ".zone5.toml");
234
+ await f.copy(i, o);
235
+ }
236
+ export {
237
+ X as createProject
238
+ };
@@ -0,0 +1,53 @@
1
+ import { constants as o } from "node:fs";
2
+ import { access as c, stat as f, readdir as u } from "node:fs/promises";
3
+ import { join as p, extname as h } from "node:path";
4
+ const m = /* @__PURE__ */ new Set([
5
+ ".jpg",
6
+ ".jpeg",
7
+ ".png",
8
+ ".webp",
9
+ ".avif",
10
+ ".gif",
11
+ ".tiff",
12
+ ".tif",
13
+ ".heic",
14
+ ".heif"
15
+ ]);
16
+ async function I(t) {
17
+ try {
18
+ return await c(t, o.F_OK), !0;
19
+ } catch {
20
+ return !1;
21
+ }
22
+ }
23
+ async function x(t) {
24
+ try {
25
+ return (await f(t)).isDirectory();
26
+ } catch {
27
+ return !1;
28
+ }
29
+ }
30
+ function l(t) {
31
+ const a = h(t).toLowerCase();
32
+ return m.has(a);
33
+ }
34
+ async function g(t, a = t) {
35
+ const r = await u(t, { withFileTypes: !0 }), i = [];
36
+ for (const e of r) {
37
+ const s = p(t, e.name);
38
+ if (e.isFile() && l(e.name)) {
39
+ const n = s.replace(a + "/", "");
40
+ i.push({ path: s, relativePath: n });
41
+ } else if (e.isDirectory()) {
42
+ const n = await g(s, a);
43
+ i.push(...n);
44
+ }
45
+ }
46
+ return i.sort((e, s) => e.relativePath.localeCompare(s.relativePath));
47
+ }
48
+ export {
49
+ g as findImagesRecursive,
50
+ x as isDirectory,
51
+ l as isImage,
52
+ I as pathExists
53
+ };
@@ -0,0 +1,4 @@
1
+ # Zone5 Configuration
2
+
3
+ [processor]
4
+ variants = [640, 768, 1280, 1920, 2560]
@@ -0,0 +1,3 @@
1
+ @import 'tailwindcss';
2
+
3
+ @source '../node_modules/zone5/dist';
@@ -0,0 +1,15 @@
1
+ <script lang="ts">
2
+ import { Zone5Provider } from 'zone5/components';
3
+
4
+ import '../app.css';
5
+
6
+ const { children } = $props();
7
+ </script>
8
+
9
+ <Zone5Provider>
10
+ <div class="min-h-screen bg-gray-50">
11
+ <main class="container mx-auto px-4 py-8">
12
+ {@render children()}
13
+ </main>
14
+ </div>
15
+ </Zone5Provider>
@@ -0,0 +1 @@
1
+ export const prerender = true;