@webstir-io/webstir-frontend 0.1.40 → 0.1.41

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 (138) hide show
  1. package/README.md +124 -60
  2. package/dist/assets/imageOptimizer.js +10 -15
  3. package/dist/assets/precompression.js +1 -1
  4. package/dist/builders/contentBuilder.js +102 -90
  5. package/dist/builders/cssBuilder.js +25 -19
  6. package/dist/builders/htmlBuilder.js +57 -42
  7. package/dist/builders/index.js +1 -1
  8. package/dist/builders/jsBuilder.js +219 -76
  9. package/dist/builders/staticAssetsBuilder.js +27 -9
  10. package/dist/builders/types.d.ts +1 -0
  11. package/dist/cli.d.ts +1 -1
  12. package/dist/cli.js +6 -30
  13. package/dist/config/manifest.js +7 -6
  14. package/dist/config/paths.js +2 -2
  15. package/dist/config/schema.d.ts +8 -0
  16. package/dist/config/schema.js +7 -6
  17. package/dist/config/setup.js +1 -1
  18. package/dist/config/workspace.js +11 -9
  19. package/dist/core/constants.d.ts +1 -1
  20. package/dist/core/constants.js +5 -5
  21. package/dist/core/diagnostics.js +1 -1
  22. package/dist/core/pages.js +4 -4
  23. package/dist/hooks.js +3 -3
  24. package/dist/html/criticalCss.js +6 -3
  25. package/dist/html/htmlSecurity.d.ts +6 -1
  26. package/dist/html/htmlSecurity.js +28 -14
  27. package/dist/html/lazyLoad.js +1 -1
  28. package/dist/html/pageScaffold.js +1 -1
  29. package/dist/html/resourceHints.js +5 -2
  30. package/dist/index.d.ts +2 -0
  31. package/dist/index.js +2 -0
  32. package/dist/inspect.d.ts +2 -0
  33. package/dist/inspect.js +110 -0
  34. package/dist/modes/ssg/metadata.js +4 -4
  35. package/dist/modes/ssg/routing.js +2 -5
  36. package/dist/modes/ssg/seo.js +5 -5
  37. package/dist/modes/ssg/views.js +17 -11
  38. package/dist/operations.js +18 -10
  39. package/dist/pipeline.d.ts +1 -0
  40. package/dist/pipeline.js +6 -1
  41. package/dist/provider.js +28 -24
  42. package/dist/runtime/boundary.d.ts +28 -0
  43. package/dist/runtime/boundary.js +247 -0
  44. package/dist/runtime/index.d.ts +1 -0
  45. package/dist/runtime/index.js +1 -0
  46. package/dist/types.d.ts +52 -0
  47. package/dist/utils/fs.d.ts +11 -10
  48. package/dist/utils/fs.js +48 -20
  49. package/dist/utils/glob.d.ts +8 -0
  50. package/dist/utils/glob.js +21 -0
  51. package/dist/utils/hash.js +1 -2
  52. package/dist/utils/pagePaths.js +2 -2
  53. package/package.json +19 -14
  54. package/scripts/publish.sh +2 -94
  55. package/scripts/update-contract.sh +12 -10
  56. package/src/assets/assetManifest.ts +39 -29
  57. package/src/assets/imageOptimizer.ts +91 -82
  58. package/src/assets/precompression.ts +22 -16
  59. package/src/builders/contentBuilder.ts +1224 -1149
  60. package/src/builders/cssBuilder.ts +466 -417
  61. package/src/builders/htmlBuilder.ts +511 -448
  62. package/src/builders/index.ts +7 -7
  63. package/src/builders/jsBuilder.ts +538 -280
  64. package/src/builders/staticAssetsBuilder.ts +166 -135
  65. package/src/builders/types.ts +7 -6
  66. package/src/cli.ts +66 -90
  67. package/src/config/manifest.ts +16 -14
  68. package/src/config/paths.ts +5 -5
  69. package/src/config/schema.ts +38 -37
  70. package/src/config/setup.ts +7 -7
  71. package/src/config/workspace.ts +118 -116
  72. package/src/config/workspaceManifest.ts +14 -14
  73. package/src/core/constants.ts +62 -62
  74. package/src/core/diagnostics.ts +26 -26
  75. package/src/core/pages.ts +19 -19
  76. package/src/hooks.ts +128 -118
  77. package/src/html/criticalCss.ts +84 -77
  78. package/src/html/htmlSecurity.ts +107 -66
  79. package/src/html/lazyLoad.ts +22 -19
  80. package/src/html/pageScaffold.ts +37 -28
  81. package/src/html/resourceHints.ts +83 -74
  82. package/src/index.ts +2 -0
  83. package/src/inspect.ts +158 -0
  84. package/src/modes/ssg/metadata.ts +53 -51
  85. package/src/modes/ssg/routing.ts +177 -177
  86. package/src/modes/ssg/seo.ts +208 -200
  87. package/src/modes/ssg/validation.ts +31 -25
  88. package/src/modes/ssg/views.ts +257 -238
  89. package/src/operations.ts +105 -95
  90. package/src/pipeline.ts +81 -69
  91. package/src/provider.ts +184 -176
  92. package/src/runtime/boundary.ts +325 -0
  93. package/src/runtime/index.ts +1 -0
  94. package/src/types.ts +107 -48
  95. package/src/utils/changedFile.ts +22 -22
  96. package/src/utils/fs.ts +73 -26
  97. package/src/utils/glob.ts +38 -0
  98. package/src/utils/hash.ts +2 -4
  99. package/src/utils/pagePaths.ts +35 -23
  100. package/src/utils/pathMatch.ts +26 -23
  101. package/tests/add-page-defaults.test.js +44 -39
  102. package/tests/bundlerParity.test.js +252 -0
  103. package/tests/cli.contract.test.js +13 -0
  104. package/tests/content-pages.test.js +108 -13
  105. package/tests/css-app-imports.test.js +22 -11
  106. package/tests/css-page-imports.test.js +26 -13
  107. package/tests/diagnostics.test.js +39 -36
  108. package/tests/features.test.js +48 -43
  109. package/tests/hooks.test.js +58 -42
  110. package/tests/htmlSecurity.test.js +66 -0
  111. package/tests/inspect.test.js +148 -0
  112. package/tests/provider.integration.test.js +71 -20
  113. package/tests/runtime.test.js +493 -0
  114. package/tests/ssg-defaults.test.js +284 -177
  115. package/tests/ssg-guardrails.test.js +51 -51
  116. package/tsconfig.json +3 -10
  117. package/dist/watch/frontendFiles.d.ts +0 -3
  118. package/dist/watch/frontendFiles.js +0 -25
  119. package/dist/watch/hotUpdateTracker.d.ts +0 -51
  120. package/dist/watch/hotUpdateTracker.js +0 -205
  121. package/dist/watch/pipelineHelpers.d.ts +0 -26
  122. package/dist/watch/pipelineHelpers.js +0 -177
  123. package/dist/watch/types.d.ts +0 -27
  124. package/dist/watch/types.js +0 -1
  125. package/dist/watch/watchCoordinator.d.ts +0 -36
  126. package/dist/watch/watchCoordinator.js +0 -551
  127. package/dist/watch/watchDaemon.d.ts +0 -17
  128. package/dist/watch/watchDaemon.js +0 -127
  129. package/dist/watch/watchReporter.d.ts +0 -21
  130. package/dist/watch/watchReporter.js +0 -64
  131. package/scripts/smoke.mjs +0 -35
  132. package/src/watch/frontendFiles.ts +0 -32
  133. package/src/watch/hotUpdateTracker.ts +0 -285
  134. package/src/watch/pipelineHelpers.ts +0 -242
  135. package/src/watch/types.ts +0 -23
  136. package/src/watch/watchCoordinator.ts +0 -666
  137. package/src/watch/watchDaemon.ts +0 -144
  138. package/src/watch/watchReporter.ts +0 -98
package/README.md CHANGED
@@ -1,30 +1,92 @@
1
1
  # @webstir-io/webstir-frontend
2
2
 
3
- Frontend build and publish toolkit for Webstir workspaces. The package bundles the HTML/CSS/JS pipeline, scaffolding helpers, and module provider used by the Webstir CLI and installers.
3
+ HTML-first frontend delivery for Webstir workspaces. This package builds page documents, shared app assets, CSS, and browser-side enhancement scripts for applications that start with server-rendered HTML and selectively add JavaScript where it improves the experience.
4
4
 
5
- ## Status
5
+ ## What It Ships
6
6
 
7
- - Experimental provider for the Webstir ecosystem — pipeline details and configuration surfaces may change between releases.
8
- - Best suited for exploration and demos today; do not rely on it as a hardened production frontend pipeline yet.
7
+ - Multi-page HTML/CSS/JS builds for `src/frontend/**`
8
+ - Publish output with fingerprinted assets under `dist/frontend/**`
9
+ - Watch-mode rebuilds used by the Bun orchestrator
10
+ - Shared app-shell assets such as navigation, refresh, and client enhancement hooks
11
+ - Runtime helpers for boundary-style mount/unmount lifecycles and cleanup scopes
12
+ - SSG as a supported mode, without making static-only delivery the center of the product story
13
+
14
+ Requires Bun **1.3.11** or newer.
15
+
16
+ ## Runtime Model
17
+
18
+ Client code that participates in hot updates should use the boundary runtime instead of relying on module top-level side effects.
19
+
20
+ ```ts
21
+ import { createCleanupScope, defineBoundary } from '@webstir-io/webstir-frontend/runtime';
22
+ ```
23
+
24
+ - `createCleanupScope()` collects cleanup handlers and disposes them in reverse registration order.
25
+ - `defineBoundary()` wraps a page or app region with explicit `mount()` and `unmount()` lifecycle methods.
26
+ - Boundary scopes can mount nested child boundaries with `scope.mountChild(...)`; child boundaries unmount before the parent boundary tears down.
27
+ - Boundaries can opt into hot-state preservation with `snapshotState()` and `restoreState()`; when those hooks are absent, remounts start fresh.
28
+ - `listen()`, `scheduleTimeout()`, `scheduleInterval()`, `trackObserver()`, and `createAbortController()` wrap common side effects so cleanup stays attached to the boundary scope.
29
+ - Boundary code should register DOM listeners, timers, observers, and similar side effects through the cleanup scope so remounts stay deterministic.
30
+
31
+ ## Hot Update Rules
32
+
33
+ Webstir watch mode follows a narrow fallback policy:
34
+
35
+ - CSS edits hot-swap in the browser.
36
+ - JS edits remount only when the module or boundary explicitly opts in.
37
+ - Most content, HTML, and route-shape changes fall back to rebuild + reload.
38
+ - Current exception: the SSG docs-sidebar pilot also remounts on `src/frontend/content/_sidebar.json` edits.
39
+ - Any cleanup failure or declined boundary update falls back to reload.
40
+
41
+ ## Fragment Ownership Decision
42
+
43
+ The current SSG runtime has a working fragment-ownership pilot on the docs sidebar boundary. It now covers the sidebar manifest input (`src/frontend/content/_sidebar.json`) in addition to direct docs page module edits, but owned-fragment HTML replacement is still not justified yet as a general mechanism.
44
+
45
+ Keep reload/remount as the default until the runtime has:
46
+
47
+ - More than one real owned fragment with clear parent/child invalidation rules
48
+ - A stable fragment-to-source mapping for generated HTML updates
49
+ - A lifecycle contract for replacing HTML without duplicating side effects or breaking page state
50
+
51
+ Until then, content and HTML changes should continue to fall back to rebuild + reload.
52
+
53
+ ## HTML-First Workflow
54
+
55
+ The frontend package is designed to pair with the backend runtime rather than replace it:
56
+
57
+ - Build document shells under `build/frontend/pages/**`
58
+ - Publish optimized assets under `dist/frontend/**`
59
+ - Let backend routes or request-time views deliver HTML first
60
+ - Use enhancement scripts for fragment updates, navigation polish, and form handling when JavaScript is available
61
+
62
+ Canonical proof apps in this repo:
63
+
64
+ - [`examples/demos/auth-crud`](../../../examples/demos/auth-crud) for server-handled auth, validation, redirect-after-post, and CRUD flows
65
+ - [`examples/demos/dashboard`](../../../examples/demos/dashboard) for shell-level and panel-level partial refreshes without SPA architecture
9
66
 
10
67
  ## Quick Start
11
68
 
12
- 1. **Install the package**
13
- ```bash
14
- npm install @webstir-io/webstir-frontend
15
- ```
16
- 2. **Run a build**
17
- ```bash
18
- npx webstir-frontend build --workspace /absolute/path/to/workspace
19
- ```
69
+ 1. Install the package
70
+
71
+ ```bash
72
+ bun add @webstir-io/webstir-frontend
73
+ ```
20
74
 
21
- Requires Node.js **20.18.x** or newer.
75
+ 2. Build a workspace
22
76
 
23
- ## Workspace Layout
77
+ ```bash
78
+ bunx webstir-frontend build --workspace /absolute/path/to/workspace
79
+ ```
24
80
 
25
- The provider assumes the standard Webstir workspace shape:
81
+ 3. Publish optimized frontend assets
26
82
 
83
+ ```bash
84
+ bunx webstir-frontend publish --workspace /absolute/path/to/workspace
27
85
  ```
86
+
87
+ ## Workspace Layout
88
+
89
+ ```text
28
90
  workspace/
29
91
  src/frontend/
30
92
  app/
@@ -32,42 +94,44 @@ workspace/
32
94
  images/
33
95
  fonts/
34
96
  media/
35
- frontend.config.json # optional feature flag overrides
36
- webstir.config.mjs # optional hook definitions
37
- build/frontend/... # generated build artifacts
38
- dist/frontend/... # publish-ready assets
39
- .webstir/manifest.json # pipeline manifest emitted on each run
97
+ frontend.config.json # optional feature flags
98
+ webstir.config.mjs # optional hooks
99
+ build/frontend/... # watch/build output
100
+ dist/frontend/... # publish output
101
+ .webstir/manifest.json # pipeline manifest
40
102
  ```
41
103
 
42
104
  ## CLI Commands
43
105
 
44
- Binary name: `webstir-frontend`. All commands require `--workspace` pointing to the absolute workspace root.
106
+ Binary name: `webstir-frontend`. All commands require `--workspace`.
45
107
 
46
108
  | Command | Description | Useful options |
47
- |---------|-------------|----------------|
48
- | `build` | Runs the development pipeline (incremental safe). | `--changed-file <path>` to scope rebuilds. |
49
- | `publish` | Produces optimized assets under `dist/frontend`. | `--mode <bundle\|ssg>` (SSG preview). |
50
- | `rebuild` | Incremental rebuild triggered by a file change. | `--changed-file <path>` to pass the changed file. |
51
- | `add-page <name>` | Scaffolds a page (HTML/CSS/TS) inside `src/frontend/pages`. | |
52
- | `watch-daemon` | Persistent watcher + HMR coordinator. | `--no-auto-start`, `--verbose`, `--hmr-verbose`. |
109
+ | --- | --- | --- |
110
+ | `build` | Runs the development-oriented pipeline. | `--changed-file <path>` to scope rebuilds. |
111
+ | `publish` | Produces optimized frontend assets. | `--mode <bundle\|ssg>` |
112
+ | `rebuild` | Incremental rebuild after a file change. | `--changed-file <path>` |
113
+ | `add-page <name>` | Scaffolds `index.html`, `index.css`, and `index.ts`. | None |
53
114
 
54
- ### Feature Flags
115
+ ## Feature Flags
55
116
 
56
- `frontend.config.json` enables or disables pipeline features:
117
+ `frontend.config.json` controls optional pipeline features:
57
118
 
58
119
  ```jsonc
59
120
  {
60
121
  "features": {
61
122
  "htmlSecurity": true,
123
+ "externalResourceIntegrity": false,
62
124
  "imageOptimization": true,
63
125
  "precompression": false
64
126
  }
65
127
  }
66
128
  ```
67
129
 
68
- ### Lifecycle Hooks
130
+ `externalResourceIntegrity` stays `false` by default so publish does not fetch third-party script or stylesheet URLs just to compute SRI. Enable it only when you explicitly want remote fetches during publish; otherwise, add `integrity` and `crossorigin` attributes yourself for external CDN assets.
131
+
132
+ ## Lifecycle Hooks
69
133
 
70
- Hooks live in `webstir.config.mjs` (or `.js`/`.cjs`) at the workspace root:
134
+ Hooks live in `webstir.config.mjs` (or `.js` / `.cjs`) at the workspace root:
71
135
 
72
136
  ```js
73
137
  export const hooks = {
@@ -78,7 +142,7 @@ export const hooks = {
78
142
  },
79
143
  builders: {
80
144
  assets: {
81
- after({ config }) {
145
+ after() {
82
146
  // custom post-processing
83
147
  }
84
148
  }
@@ -88,8 +152,6 @@ export const hooks = {
88
152
 
89
153
  ## API Usage
90
154
 
91
- The package exports a `ModuleProvider` compatible with `@webstir-io/module-contract`:
92
-
93
155
  ```ts
94
156
  import { frontendProvider } from '@webstir-io/webstir-frontend';
95
157
 
@@ -98,49 +160,51 @@ const result = await frontendProvider.build({
98
160
  env: { WEBSTIR_MODULE_MODE: 'publish' }
99
161
  });
100
162
 
101
- console.log(result.manifest.entryPoints);
102
- ```
163
+ console.log(result.manifest.entryPoints);
164
+ ```
103
165
 
104
- - `frontendProvider.metadata` surfaces id/version compatibility.
105
- - `frontendProvider.resolveWorkspace` returns canonical source/build/test paths.
106
- - `frontendProvider.build` executes the pipeline and returns artifacts + manifest.
166
+ - `frontendProvider.metadata` exposes package and runtime-compatibility metadata
167
+ - `frontendProvider.resolveWorkspace()` returns canonical source/build roots
168
+ - `frontendProvider.build()` executes the pipeline and returns artifacts plus manifest data
169
+ - `inspectFrontendWorkspace()` returns resolved config plus shallow workspace facts without building
107
170
 
108
- ## SSG Preview
171
+ ## SSG Mode
109
172
 
110
- When invoked as:
173
+ SSG is a supported frontend output mode, not a separate product:
111
174
 
112
175
  ```bash
113
- npx webstir-frontend publish --workspace /absolute/path/to/workspace --mode ssg
176
+ bunx webstir-frontend publish --workspace /absolute/path/to/workspace --mode ssg
114
177
  ```
115
178
 
116
- the provider:
179
+ That run:
117
180
 
118
- - Runs the normal publish pipeline to populate `dist/frontend/**`.
119
- - Creates static-friendly `index.html` aliases (root and per-page).
120
- - When `package.json` includes `webstir.moduleManifest.views` with `renderMode: 'ssg'` and `staticPaths`, uses those paths to add additional `index.html` aliases under `dist/frontend/**`.
181
+ - Builds normal publish assets under `dist/frontend/**`
182
+ - Generates `index.html` aliases for document routes
183
+ - Uses `webstir.moduleManifest.views` metadata when present to emit extra static paths
121
184
 
122
185
  ## Maintainer Workflow
123
186
 
124
187
  ```bash
125
- npm install
126
- npm run clean # remove dist artifacts
127
- npm run build # TypeScript → dist/
128
- npm run test # Node --test against compiled output
129
- npm run smoke # scaffolds a temp workspace and runs build/publish
130
- # Release helper (bumps version, pushes tags to trigger release workflow)
131
- npm run release -- patch
188
+ bun install
189
+ bun run clean
190
+ bun run build
191
+ bun run test
192
+ bun run release -- patch
132
193
  ```
133
194
 
134
- GitHub Actions should run `npm ci`, `npm run clean`, `npm run build`, `npm run test`, and `npm run smoke` before publishing. The release workflow publishes to npm with trusted publishing (`id-token: write` + provenance).
195
+ Recommended package validation before release:
135
196
 
136
- CI notes
137
- - Package CI runs clean + build + tests + smoke on PRs and main.
197
+ - `bun run build`
198
+ - `bun run test`
138
199
 
139
200
  ## Troubleshooting
140
201
 
141
- - **“404 Not Found” when installing `@webstir-io/module-contract`** — verify the dependency has been published to npm and re-generate `package-lock.json` against npmjs.
142
- - **“No frontend test files found”** — the `test` script expects files under `tests/**/*.test.js` after build.
143
- - **Missing entry points in manifest** — confirm `build/frontend` contains at least one `.js`/`.mjs` bundle; the provider falls back to `build/app/index.js` and emits a warning if empty.
202
+ - `No frontend test files found`
203
+ The package test script expects compiled tests under `tests/**/*.test.js`.
204
+ - `Missing entry points in manifest`
205
+ Confirm `build/frontend` contains at least one generated JS entry.
206
+ - `SSG output missing a route`
207
+ Check `webstir.moduleManifest.views` for `renderMode: "ssg"` and the expected `staticPaths`.
144
208
 
145
209
  ## Community & Support
146
210
 
@@ -151,7 +215,7 @@ CI notes
151
215
 
152
216
  ## Third-Party Notices
153
217
 
154
- Webstir Frontend depends on third-party libraries and data sets (including `sharp`/libvips and `caniuse-lite`) under their respective licenses. See [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md) for a summary of notable licenses and attribution.
218
+ Webstir Frontend depends on third-party libraries and data sets (including `sharp` / libvips and `caniuse-lite`) under their respective licenses. See [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md) for the attribution summary.
155
219
 
156
220
  ## License
157
221
 
@@ -1,13 +1,9 @@
1
1
  import path from 'node:path';
2
2
  import sharp from 'sharp';
3
- import { glob } from 'glob';
4
3
  import { copy, ensureDir, emptyDir, pathExists, remove } from '../utils/fs.js';
5
4
  import { EXTENSIONS } from '../core/constants.js';
6
- const TRANSCODABLE_EXTENSIONS = new Set([
7
- EXTENSIONS.png,
8
- EXTENSIONS.jpg,
9
- EXTENSIONS.jpeg
10
- ]);
5
+ import { scanGlob } from '../utils/glob.js';
6
+ const TRANSCODABLE_EXTENSIONS = new Set([EXTENSIONS.png, EXTENSIONS.jpg, EXTENSIONS.jpeg]);
11
7
  export async function optimizeImages(sourceDir, destinationDir, files) {
12
8
  if (!(await pathExists(sourceDir))) {
13
9
  await emptyDir(destinationDir);
@@ -15,7 +11,7 @@ export async function optimizeImages(sourceDir, destinationDir, files) {
15
11
  }
16
12
  if (!files || files.length === 0) {
17
13
  await emptyDir(destinationDir);
18
- const allFiles = await glob('**/*', { cwd: sourceDir, nodir: true });
14
+ const allFiles = await scanGlob('**/*', { cwd: sourceDir });
19
15
  await Promise.all(allFiles.map(async (relative) => processImage(sourceDir, destinationDir, relative)));
20
16
  return;
21
17
  }
@@ -40,9 +36,7 @@ function replaceExtension(filePath, extension) {
40
36
  }
41
37
  async function createWebpVariant(sourcePath, destinationPath) {
42
38
  try {
43
- await sharp(sourcePath)
44
- .webp({ quality: 75 })
45
- .toFile(destinationPath);
39
+ await sharp(sourcePath).webp({ quality: 75 }).toFile(destinationPath);
46
40
  }
47
41
  catch {
48
42
  // Ignore failures; fall back to original image only.
@@ -50,9 +44,7 @@ async function createWebpVariant(sourcePath, destinationPath) {
50
44
  }
51
45
  async function createAvifVariant(sourcePath, destinationPath) {
52
46
  try {
53
- await sharp(sourcePath)
54
- .avif({ quality: 45 })
55
- .toFile(destinationPath);
47
+ await sharp(sourcePath).avif({ quality: 45 }).toFile(destinationPath);
56
48
  }
57
49
  catch {
58
50
  // Ignore failures; fall back to original image only.
@@ -79,11 +71,14 @@ async function processImage(sourceDir, destinationDir, relative, incremental = f
79
71
  }
80
72
  await Promise.all([
81
73
  createWebpVariant(sourcePath, replaceExtension(destinationPath, EXTENSIONS.webp)),
82
- createAvifVariant(sourcePath, replaceExtension(destinationPath, EXTENSIONS.avif))
74
+ createAvifVariant(sourcePath, replaceExtension(destinationPath, EXTENSIONS.avif)),
83
75
  ]);
84
76
  }
85
77
  async function removeVariants(destinationPath, includeBase) {
86
- const targets = [replaceExtension(destinationPath, EXTENSIONS.webp), replaceExtension(destinationPath, EXTENSIONS.avif)];
78
+ const targets = [
79
+ replaceExtension(destinationPath, EXTENSIONS.webp),
80
+ replaceExtension(destinationPath, EXTENSIONS.avif),
81
+ ];
87
82
  if (includeBase) {
88
83
  targets.push(destinationPath);
89
84
  }
@@ -3,7 +3,7 @@ import { constants as zlibConstants, createBrotliCompress, createGzip } from 'no
3
3
  export async function createCompressedVariants(filePath) {
4
4
  await Promise.all([
5
5
  compress(filePath, '.br', () => createBrotliCompress({ params: { [zlibConstants.BROTLI_PARAM_QUALITY]: 11 } })),
6
- compress(filePath, '.gz', () => createGzip({ level: zlibConstants.Z_BEST_COMPRESSION }))
6
+ compress(filePath, '.gz', () => createGzip({ level: zlibConstants.Z_BEST_COMPRESSION })),
7
7
  ]);
8
8
  }
9
9
  async function compress(source, extension, factory) {