nuxt-content-assets 1.4.2 → 1.4.4
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.
- package/README.md +73 -46
- package/cache/nuxt.config.ts +1 -0
- package/cache/public/.gitignore +2 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +63 -28
- package/dist/runtime/assets/public.d.ts +2 -1
- package/dist/runtime/assets/public.mjs +19 -6
- package/dist/runtime/utils/config.d.ts +1 -0
- package/dist/runtime/utils/config.mjs +2 -0
- package/dist/runtime/utils/fs.d.ts +2 -0
- package/dist/runtime/utils/fs.mjs +12 -0
- package/dist/runtime/utils/path.d.ts +6 -1
- package/dist/runtime/utils/path.mjs +5 -3
- package/package.json +16 -8
package/README.md
CHANGED
|
@@ -155,11 +155,16 @@ If you delete an asset, it will be greyed out in the browser until you replace t
|
|
|
155
155
|
|
|
156
156
|
If you edit an image, video, embed or iframe source, the content will update immediately, which is useful if you're looking to get that design just right!
|
|
157
157
|
|
|
158
|
+
> [!NOTE]
|
|
159
|
+
> Live reload does not currently work with Nuxt Image (see Issue [#77](https://github.com/davestewart/nuxt-content-assets/issues/77)).
|
|
160
|
+
>
|
|
161
|
+
> If you need to iterate on image design, consider disabling Nuxt Image in development.
|
|
162
|
+
|
|
158
163
|
### Image sizing
|
|
159
164
|
|
|
160
165
|
#### HTML
|
|
161
166
|
|
|
162
|
-
The module
|
|
167
|
+
The module can pass image size hints to generated `<img>` tags:
|
|
163
168
|
|
|
164
169
|
```html
|
|
165
170
|
<!-- imageSize: 'style' -->
|
|
@@ -169,7 +174,10 @@ The module is [preconfigured](#image-size) to pass image size hints (by default
|
|
|
169
174
|
<img src="/image.jpg" width="640" height="480">
|
|
170
175
|
```
|
|
171
176
|
|
|
172
|
-
|
|
177
|
+
Turning this on prevents content jumps as your page loads.
|
|
178
|
+
|
|
179
|
+
> [!CAUTION]
|
|
180
|
+
> Don't use `imageSize: 'src'` in conjunction with Nuxt Image as it prevents the IPX module from correctly serving images, which causes static site generation to fail
|
|
173
181
|
|
|
174
182
|
#### Prose components
|
|
175
183
|
|
|
@@ -207,27 +215,17 @@ See playground component [here](playground/components/content/ContentImage.vue).
|
|
|
207
215
|
|
|
208
216
|
### Nuxt Image
|
|
209
217
|
|
|
210
|
-
|
|
218
|
+
[Nuxt Image](https://image.nuxtjs.org/) is supported by adding Nuxt Content Asset's cache folder as a Nuxt Layer:
|
|
211
219
|
|
|
212
220
|
```ts
|
|
213
221
|
// nuxt.config.ts
|
|
214
222
|
export default defineNuxtConfig({
|
|
215
|
-
modules: [
|
|
216
|
-
// Nuxt Image should be placed before Nuxt Content Assets
|
|
217
|
-
'@nuxt/image',
|
|
218
|
-
'nuxt-content-assets',
|
|
219
|
-
'@nuxt/content',
|
|
220
|
-
],
|
|
221
|
-
|
|
222
223
|
extends: [
|
|
223
|
-
|
|
224
|
-
'.nuxt/content-assets',
|
|
224
|
+
'node_modules/nuxt-content-assets/cache',
|
|
225
225
|
],
|
|
226
226
|
}
|
|
227
227
|
```
|
|
228
228
|
|
|
229
|
-
> Note that the new Layers setup enables Nuxt Image to load images from both the project's `public` folder and from `content`.
|
|
230
|
-
|
|
231
229
|
To serve all images as Nuxt Image images, create a `ProseImg` component like so:
|
|
232
230
|
|
|
233
231
|
```vue
|
|
@@ -239,7 +237,6 @@ To serve all images as Nuxt Image images, create a `ProseImg` component like so:
|
|
|
239
237
|
|
|
240
238
|
See the playground folder for both the [global](playground/components/temp/ProseImg.vue) and a [per image](playground/components/content/NuxtImg.ts) solution.
|
|
241
239
|
|
|
242
|
-
|
|
243
240
|
## Configuration
|
|
244
241
|
|
|
245
242
|
The module has the following options:
|
|
@@ -248,11 +245,11 @@ The module has the following options:
|
|
|
248
245
|
// nuxt.config.ts
|
|
249
246
|
export default defineNuxtConfig({
|
|
250
247
|
contentAssets: {
|
|
251
|
-
// inject image
|
|
248
|
+
// inject image size hints into the rendered html
|
|
252
249
|
imageSize: 'style',
|
|
253
250
|
|
|
254
251
|
// treat these extensions as content
|
|
255
|
-
contentExtensions: '
|
|
252
|
+
contentExtensions: 'mdx? csv ya?ml json',
|
|
256
253
|
|
|
257
254
|
// output debug messages
|
|
258
255
|
debug: false,
|
|
@@ -262,7 +259,11 @@ export default defineNuxtConfig({
|
|
|
262
259
|
|
|
263
260
|
### Image size
|
|
264
261
|
|
|
265
|
-
|
|
262
|
+
> [!Note]
|
|
263
|
+
>
|
|
264
|
+
> Since `v1.4.1` image size hints are now opt-in. This was done to maximise compatibiility with Nuxt Image.
|
|
265
|
+
|
|
266
|
+
You can add one _or more_ image size hints to the generated images:
|
|
266
267
|
|
|
267
268
|
```ts
|
|
268
269
|
{
|
|
@@ -277,7 +278,6 @@ Pick from the following switches:
|
|
|
277
278
|
| `'style'` | Adds `style="aspect-ratio:..."` to any `<img>` tag |
|
|
278
279
|
| `'attrs'` | Adds `width` and `height` attributes to any `<img>` tag |
|
|
279
280
|
| `'src'` | Adds `?width=...&height=...` to `src` attribute (frontmatter only) |
|
|
280
|
-
| `false` | Disable image size hints |
|
|
281
281
|
|
|
282
282
|
Note: if you add *only* `attrs`, include the following CSS in your app:
|
|
283
283
|
|
|
@@ -290,15 +290,20 @@ img {
|
|
|
290
290
|
|
|
291
291
|
### Content extensions
|
|
292
292
|
|
|
293
|
+
> [!NOTE]
|
|
293
294
|
> Generally, you shouldn't need to touch this setting
|
|
294
295
|
|
|
295
|
-
This setting tells Nuxt Content to ignore anything that is **not** one of
|
|
296
|
+
This setting tells Nuxt Content to ignore anything that is **not** one of the supported content types:
|
|
296
297
|
|
|
297
298
|
```
|
|
298
|
-
|
|
299
|
+
mdx? csv ya?ml json
|
|
299
300
|
```
|
|
300
301
|
|
|
301
|
-
This way, you can use any **other** file type as an asset, without needing to explicitly configure
|
|
302
|
+
This way, you can use any **other** file type as an asset, without needing to explicitly configure Nuxt Content's [ignores](https://content.nuxt.com/get-started/configuration#ignores) list.
|
|
303
|
+
|
|
304
|
+
Without this, Nuxt Content would warn about unsupported file types:
|
|
305
|
+
|
|
306
|
+
> [WARN] .jpg files are not supported, "content:path:to:some-asset.jpg" falling back to raw content
|
|
302
307
|
|
|
303
308
|
### Debug
|
|
304
309
|
|
|
@@ -312,65 +317,85 @@ If you want to see what the module does as it runs, set `debug` to true:
|
|
|
312
317
|
|
|
313
318
|
## How it works
|
|
314
319
|
|
|
315
|
-
When Nuxt builds, the module scans all content sources for assets, copies them to
|
|
320
|
+
When Nuxt builds, the module scans all content sources for assets, copies them to a temporary layer folder (`nuxt_modules/nuxt-content-assets/cache`), and indexes path and image metadata.
|
|
316
321
|
|
|
317
|
-
After Nuxt Content has run, the parsed content is traversed, and both element attributes and frontmatter properties are checked to see if they resolve to the indexed asset paths.
|
|
322
|
+
After Nuxt Content has run, the parsed content (`.nuxt/content-cache`) is traversed, and both element attributes and frontmatter properties are checked to see if they resolve to the previously-indexed asset paths.
|
|
318
323
|
|
|
319
|
-
If they do, then the attribute or property is rewritten with the absolute path. If the asset is an image, then the element or metadata is optionally updated with size attributes or a query string.
|
|
324
|
+
If they do, then the attribute or property in Nuxt Content's cache is rewritten with the absolute path. If the asset is an image, then the element or metadata is optionally updated with size attributes or a query string.
|
|
320
325
|
|
|
321
326
|
Finally, Nitro serves the site, and any requests made to the transformed asset paths should be picked up and the *copied* asset served by the browser.
|
|
322
327
|
|
|
323
|
-
In development,
|
|
328
|
+
In development, a watch process propagates asset changes to the cache, updates the asset index, and notifies the browser via web sockets to refresh any loaded images.
|
|
329
|
+
|
|
330
|
+
If Nuxt Image is used, the `_ipx/` endpoint serves images directly from the cache's public folder.
|
|
324
331
|
|
|
325
332
|
## Development
|
|
326
333
|
|
|
327
|
-
Should you wish to develop the project, the
|
|
334
|
+
Should you wish to develop the project, you'll work with the following entities:
|
|
335
|
+
|
|
336
|
+
- [src](./src)<br>The module code itself
|
|
337
|
+
- [playground](./playground)<br>A standalone Nuxt app that reads the live module code
|
|
338
|
+
- [scripts](package.json)<br>A set of scripts to develop and publish the module
|
|
328
339
|
|
|
329
|
-
|
|
340
|
+
### Setup
|
|
341
|
+
|
|
342
|
+
To set up the project, run each of these scripts once:
|
|
330
343
|
|
|
331
344
|
```bash
|
|
332
345
|
# install dependencies
|
|
333
346
|
npm install
|
|
334
347
|
|
|
335
|
-
#
|
|
336
|
-
npm run dev:
|
|
337
|
-
|
|
338
|
-
# develop (runs the playground app)
|
|
339
|
-
npm run dev
|
|
340
|
-
|
|
341
|
-
# run eslint
|
|
342
|
-
npm run lint
|
|
348
|
+
# copy the cache folder to the playground's node_modules (workaround required in development)
|
|
349
|
+
npm run dev:setup
|
|
343
350
|
|
|
344
|
-
# run
|
|
345
|
-
npm run
|
|
346
|
-
npm run test:watch
|
|
351
|
+
# generate types for the module and playground (re-run if you install new packages)
|
|
352
|
+
npm run dev:prepare
|
|
347
353
|
```
|
|
348
354
|
|
|
349
|
-
|
|
355
|
+
### Development
|
|
356
|
+
|
|
357
|
+
To develop the module, utilise the supplied playground app:
|
|
350
358
|
|
|
351
359
|
```bash
|
|
360
|
+
# compile the module, run and serve the playground
|
|
361
|
+
npm run dev
|
|
362
|
+
|
|
352
363
|
# generate the playground
|
|
353
364
|
npm run dev:generate
|
|
354
365
|
|
|
355
366
|
# build the playground
|
|
356
367
|
npm run dev:build
|
|
357
368
|
|
|
358
|
-
# serve the generated
|
|
369
|
+
# serve the generated/built playground
|
|
359
370
|
npm run dev:preview
|
|
360
371
|
```
|
|
361
372
|
|
|
362
|
-
|
|
373
|
+
Check your code quality using these tools:
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
# lint your code with eslint
|
|
377
|
+
npm run lint
|
|
378
|
+
|
|
379
|
+
# runs tests with vitest
|
|
380
|
+
npm run test
|
|
381
|
+
npm run test:watch
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Publishing
|
|
385
|
+
|
|
386
|
+
> [!IMPORTANT]
|
|
387
|
+
> Before publishing, be sure to update the [version](package.json) and [changelog](CHANGELOG.md)!
|
|
388
|
+
|
|
389
|
+
To build and publish, run following scripts as required:
|
|
363
390
|
|
|
364
391
|
```bash
|
|
365
|
-
# dry
|
|
392
|
+
# lint, test, build, and dry-run publish
|
|
366
393
|
npm run release:dry
|
|
367
394
|
|
|
368
|
-
#
|
|
395
|
+
# lint, test, build and publish
|
|
369
396
|
npm run release
|
|
370
397
|
```
|
|
371
398
|
|
|
372
|
-
Make sure to edit changelog and update `package.json` version before releasing!
|
|
373
|
-
|
|
374
399
|
## Maintenance
|
|
375
400
|
|
|
376
401
|
This module was created using the Nuxt [Module Builder](https://github.com/nuxt/module-builder) command:
|
|
@@ -385,6 +410,8 @@ This created the module code from the starter template found here:
|
|
|
385
410
|
|
|
386
411
|
Both [Nuxi](https://github.com/nuxt/cli) and the module's dependencies and scripts are updated fairly regularly, so from time to time this module may need to be updated to keep in sync. So far, this has meant just updating the dependencies and scripts, which are found in the starter template code mentioned above.
|
|
387
412
|
|
|
413
|
+
Note that the build/release scripts are slightly modified from the originals; build is now separated, and release now doesn't use [changelogen](https://github.com/unjs/changelogen), or automatically add tags and push to GitHub.
|
|
414
|
+
|
|
388
415
|
<!-- Badges -->
|
|
389
416
|
[npm-version-src]: https://img.shields.io/npm/v/nuxt-content-assets/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
390
417
|
[npm-version-href]: https://npmjs.com/package/nuxt-content-assets
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default {}
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import Fs from 'fs';
|
|
1
|
+
import * as Fs from 'fs';
|
|
2
|
+
import Fs__default from 'fs';
|
|
2
3
|
import Path from 'crosspath';
|
|
3
4
|
import { useNuxt, createResolver, defineNuxtModule, addPlugin } from '@nuxt/kit';
|
|
4
5
|
import { visit, SKIP, CONTINUE } from 'unist-util-visit';
|
|
@@ -36,6 +37,8 @@ function deKey(path) {
|
|
|
36
37
|
const extensions = {
|
|
37
38
|
// used to get image size
|
|
38
39
|
image: matchTokens("png jpg jpeg gif svg webp ico"),
|
|
40
|
+
// used to recognise content
|
|
41
|
+
content: matchTokens("md mdx json yml yaml csv"),
|
|
39
42
|
// unused for now
|
|
40
43
|
media: matchTokens("mp3 m4a wav mp4 mov webm ogg avi flv avchd")
|
|
41
44
|
};
|
|
@@ -47,15 +50,17 @@ function makeIgnores(extensions2) {
|
|
|
47
50
|
function removeQuery(path) {
|
|
48
51
|
return path.replace(/\?.*$/, "");
|
|
49
52
|
}
|
|
53
|
+
function getExt(path) {
|
|
54
|
+
return Path.extname(removeQuery(path)).substring(1);
|
|
55
|
+
}
|
|
50
56
|
function isExcluded(path) {
|
|
51
57
|
return path.split("/").some((segment) => segment.startsWith(".") || segment.startsWith("_"));
|
|
52
58
|
}
|
|
53
59
|
function isImage(path) {
|
|
54
|
-
|
|
55
|
-
return extensions.image.includes(ext);
|
|
60
|
+
return extensions.image.includes(getExt(path));
|
|
56
61
|
}
|
|
57
62
|
function isArticle(path) {
|
|
58
|
-
return
|
|
63
|
+
return extensions.content.includes(getExt(path));
|
|
59
64
|
}
|
|
60
65
|
function isAsset(path) {
|
|
61
66
|
return !isArticle(path);
|
|
@@ -153,35 +158,47 @@ function buildQuery(...expr) {
|
|
|
153
158
|
}
|
|
154
159
|
|
|
155
160
|
function readFile(path, asJson = false) {
|
|
156
|
-
const text =
|
|
161
|
+
const text = Fs__default.readFileSync(path, { encoding: "utf8" });
|
|
157
162
|
return asJson ? JSON.parse(text) : text;
|
|
158
163
|
}
|
|
159
164
|
function writeFile(path, data) {
|
|
160
165
|
const text = typeof data === "object" ? JSON.stringify(data, null, " ") : String(data);
|
|
161
166
|
createFolder(Path.dirname(path));
|
|
162
|
-
|
|
167
|
+
Fs__default.writeFileSync(path, text, { encoding: "utf8" });
|
|
163
168
|
}
|
|
164
169
|
async function writeBlob(path, data) {
|
|
165
170
|
const buffer = Buffer.from(await data.arrayBuffer());
|
|
166
171
|
createFolder(Path.dirname(path));
|
|
167
|
-
|
|
172
|
+
Fs__default.writeFileSync(path, buffer);
|
|
168
173
|
}
|
|
169
174
|
function copyFile(src, trg) {
|
|
170
175
|
createFolder(Path.dirname(trg));
|
|
171
|
-
|
|
176
|
+
Fs__default.copyFileSync(src, trg);
|
|
172
177
|
}
|
|
173
178
|
function removeFile(src) {
|
|
174
|
-
|
|
179
|
+
Fs__default.rmSync(src);
|
|
175
180
|
}
|
|
176
181
|
function createFolder(path) {
|
|
177
|
-
|
|
182
|
+
Fs__default.mkdirSync(path, { recursive: true });
|
|
178
183
|
}
|
|
179
184
|
function removeFolder(path) {
|
|
180
185
|
const isDownstream = path.startsWith(Path.resolve());
|
|
181
186
|
if (isDownstream) {
|
|
182
|
-
|
|
187
|
+
Fs__default.rmSync(path, { recursive: true, force: true });
|
|
183
188
|
}
|
|
184
189
|
}
|
|
190
|
+
function removeEntry(path) {
|
|
191
|
+
if (Fs__default.existsSync(path)) {
|
|
192
|
+
if (isFile(path)) {
|
|
193
|
+
removeFile(path);
|
|
194
|
+
} else {
|
|
195
|
+
removeFolder(path);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function isFile(path) {
|
|
200
|
+
return Fs__default.lstatSync(path).isFile();
|
|
201
|
+
}
|
|
185
202
|
|
|
186
203
|
function createWebSocket() {
|
|
187
204
|
const wss = new WebSocketServer({ noServer: true });
|
|
@@ -390,22 +407,23 @@ function makeSourceManager(key, source, publicPath, callback) {
|
|
|
390
407
|
}
|
|
391
408
|
|
|
392
409
|
function makeAssetsManager(publicPath, shouldWatch = true) {
|
|
393
|
-
const
|
|
394
|
-
const
|
|
410
|
+
const assetsKey = "assets.json";
|
|
411
|
+
const assetsPath = Path.join(publicPath, "..");
|
|
412
|
+
const storage = makeSourceStorage(assetsPath);
|
|
395
413
|
if (shouldWatch) {
|
|
396
414
|
void storage.watch(async (event, key) => {
|
|
397
|
-
if (event === "update" && key ===
|
|
415
|
+
if (event === "update" && key === assetsKey) {
|
|
398
416
|
await load();
|
|
399
417
|
}
|
|
400
418
|
});
|
|
401
419
|
}
|
|
402
420
|
const assets = {};
|
|
403
421
|
async function load() {
|
|
404
|
-
const data = await storage.getItem(
|
|
422
|
+
const data = await storage.getItem(assetsKey);
|
|
405
423
|
Object.assign(assets, data || {});
|
|
406
424
|
}
|
|
407
425
|
const save = debounce(function() {
|
|
408
|
-
void storage.setItem(
|
|
426
|
+
void storage.setItem(assetsKey, assets);
|
|
409
427
|
}, 50);
|
|
410
428
|
function resolveAsset(content, relAsset, registerContent = false) {
|
|
411
429
|
const srcDir = Path.dirname(content._file);
|
|
@@ -447,8 +465,19 @@ function makeAssetsManager(publicPath, shouldWatch = true) {
|
|
|
447
465
|
}
|
|
448
466
|
return asset;
|
|
449
467
|
}
|
|
468
|
+
const init = () => {
|
|
469
|
+
if (Fs.existsSync(publicPath)) {
|
|
470
|
+
const names = Fs.readdirSync(publicPath);
|
|
471
|
+
for (const name of names) {
|
|
472
|
+
if (!/^\.git(ignore|keep)$/.test(name)) {
|
|
473
|
+
removeEntry(Path.join(publicPath, name));
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
};
|
|
450
478
|
void load();
|
|
451
479
|
return {
|
|
480
|
+
init,
|
|
452
481
|
setAsset,
|
|
453
482
|
getAsset,
|
|
454
483
|
removeAsset,
|
|
@@ -521,24 +550,29 @@ const meta = {
|
|
|
521
550
|
const module = defineNuxtModule({
|
|
522
551
|
meta,
|
|
523
552
|
defaults: {
|
|
524
|
-
imageSize: "
|
|
525
|
-
contentExtensions: "
|
|
553
|
+
imageSize: "",
|
|
554
|
+
contentExtensions: "mdx? csv ya?ml json",
|
|
526
555
|
debug: false
|
|
527
556
|
},
|
|
528
557
|
async setup(options, nuxt) {
|
|
529
558
|
const buildPath = nuxt.options.buildDir;
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
559
|
+
const modulesPath = nuxt.options.modulesDir.find((path) => Fs.existsSync(`${path}/nuxt-content-assets/cache`)) || "";
|
|
560
|
+
if (!modulesPath) {
|
|
561
|
+
warn("Unable to find cache folder!");
|
|
562
|
+
if (nuxt.options.srcDir.endsWith("/playground")) {
|
|
563
|
+
warn('Run "npm run dev:setup" to generate a new cache folder');
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
const cachePath = modulesPath ? Path.resolve(modulesPath, "nuxt-content-assets/cache") : Path.resolve(buildPath, "content-assets");
|
|
567
|
+
const publicPath = Path.join(cachePath, "public");
|
|
568
|
+
const contentPath = Path.join(buildPath, "content-cache");
|
|
533
569
|
const isDev = !!nuxt.options.dev;
|
|
534
570
|
const isDebug = !!options.debug;
|
|
535
571
|
if (isDebug) {
|
|
536
|
-
log("
|
|
572
|
+
log("Cleaning content-cache");
|
|
573
|
+
log(`Cache path: "${Path.relative(".", cachePath)}"`);
|
|
537
574
|
}
|
|
538
|
-
|
|
539
|
-
removeFolder(assetsPath);
|
|
540
|
-
createFolder(`${assetsPath}/public`);
|
|
541
|
-
writeFile(`${assetsPath}/nuxt.config.ts`, "export default {}");
|
|
575
|
+
removeEntry(contentPath);
|
|
542
576
|
const { contentExtensions } = options;
|
|
543
577
|
if (contentExtensions) {
|
|
544
578
|
nuxt.options.content ||= {};
|
|
@@ -550,7 +584,7 @@ const module = defineNuxtModule({
|
|
|
550
584
|
}
|
|
551
585
|
const imageSizes = matchTokens(options.imageSize);
|
|
552
586
|
const sources = Array.from(nuxt.options._layers).map((layer) => layer.config?.content?.sources).reduce((output, sources2) => {
|
|
553
|
-
if (sources2) {
|
|
587
|
+
if (sources2 && !Array.isArray(sources2)) {
|
|
554
588
|
Object.assign(output, sources2);
|
|
555
589
|
}
|
|
556
590
|
return output;
|
|
@@ -565,6 +599,7 @@ const module = defineNuxtModule({
|
|
|
565
599
|
}
|
|
566
600
|
}
|
|
567
601
|
const assets = makeAssetsManager(publicPath, isDev);
|
|
602
|
+
assets.init();
|
|
568
603
|
function onAssetChange(event, absTrg) {
|
|
569
604
|
let src = "";
|
|
570
605
|
let width;
|
|
@@ -577,7 +612,7 @@ const module = defineNuxtModule({
|
|
|
577
612
|
if (oldAsset) {
|
|
578
613
|
if (oldAsset.width !== newAsset.width || oldAsset.height !== newAsset.height) {
|
|
579
614
|
newAsset.content.forEach(async (id) => {
|
|
580
|
-
const path = Path.join(contentPath, toPath(id));
|
|
615
|
+
const path = Path.join(contentPath, "parsed", toPath(id));
|
|
581
616
|
rewriteContent(path, newAsset);
|
|
582
617
|
});
|
|
583
618
|
}
|
|
@@ -3,10 +3,11 @@ import type { ParsedContent, AssetConfig } from '../../types';
|
|
|
3
3
|
* Manages the public assets
|
|
4
4
|
*/
|
|
5
5
|
export declare function makeAssetsManager(publicPath: string, shouldWatch?: boolean): {
|
|
6
|
+
init: () => void;
|
|
6
7
|
setAsset: (path: string) => AssetConfig;
|
|
7
8
|
getAsset: (path: string) => AssetConfig | undefined;
|
|
8
9
|
removeAsset: (path: string) => AssetConfig | undefined;
|
|
9
|
-
resolveAsset: (content: ParsedContent, relAsset: string, registerContent?: boolean) => AssetConfig
|
|
10
|
+
resolveAsset: (content: ParsedContent, relAsset: string, registerContent?: boolean) => Partial<AssetConfig>;
|
|
10
11
|
dispose: () => Promise<void>;
|
|
11
12
|
};
|
|
12
13
|
/**
|
|
@@ -1,26 +1,28 @@
|
|
|
1
|
+
import * as Fs from "fs";
|
|
1
2
|
import Path from "crosspath";
|
|
2
3
|
import getImageSize from "image-size";
|
|
3
4
|
import debounce from "debounce";
|
|
4
5
|
import { hash } from "ohash";
|
|
5
6
|
import { makeSourceStorage } from "./source.mjs";
|
|
6
|
-
import { isImage, warn, log } from "../utils/index.mjs";
|
|
7
|
+
import { isImage, warn, log, removeEntry } from "../utils/index.mjs";
|
|
7
8
|
export function makeAssetsManager(publicPath, shouldWatch = true) {
|
|
8
|
-
const
|
|
9
|
-
const
|
|
9
|
+
const assetsKey = "assets.json";
|
|
10
|
+
const assetsPath = Path.join(publicPath, "..");
|
|
11
|
+
const storage = makeSourceStorage(assetsPath);
|
|
10
12
|
if (shouldWatch) {
|
|
11
13
|
void storage.watch(async (event, key) => {
|
|
12
|
-
if (event === "update" && key ===
|
|
14
|
+
if (event === "update" && key === assetsKey) {
|
|
13
15
|
await load();
|
|
14
16
|
}
|
|
15
17
|
});
|
|
16
18
|
}
|
|
17
19
|
const assets = {};
|
|
18
20
|
async function load() {
|
|
19
|
-
const data = await storage.getItem(
|
|
21
|
+
const data = await storage.getItem(assetsKey);
|
|
20
22
|
Object.assign(assets, data || {});
|
|
21
23
|
}
|
|
22
24
|
const save = debounce(function() {
|
|
23
|
-
void storage.setItem(
|
|
25
|
+
void storage.setItem(assetsKey, assets);
|
|
24
26
|
}, 50);
|
|
25
27
|
function resolveAsset(content, relAsset, registerContent = false) {
|
|
26
28
|
const srcDir = Path.dirname(content._file);
|
|
@@ -62,8 +64,19 @@ export function makeAssetsManager(publicPath, shouldWatch = true) {
|
|
|
62
64
|
}
|
|
63
65
|
return asset;
|
|
64
66
|
}
|
|
67
|
+
const init = () => {
|
|
68
|
+
if (Fs.existsSync(publicPath)) {
|
|
69
|
+
const names = Fs.readdirSync(publicPath);
|
|
70
|
+
for (const name of names) {
|
|
71
|
+
if (!/^\.git(ignore|keep)$/.test(name)) {
|
|
72
|
+
removeEntry(Path.join(publicPath, name));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
65
77
|
void load();
|
|
66
78
|
return {
|
|
79
|
+
init,
|
|
67
80
|
setAsset,
|
|
68
81
|
getAsset,
|
|
69
82
|
removeAsset,
|
|
@@ -2,6 +2,8 @@ import { matchTokens } from "./string.mjs";
|
|
|
2
2
|
export const extensions = {
|
|
3
3
|
// used to get image size
|
|
4
4
|
image: matchTokens("png jpg jpeg gif svg webp ico"),
|
|
5
|
+
// used to recognise content
|
|
6
|
+
content: matchTokens("md mdx json yml yaml csv"),
|
|
5
7
|
// unused for now
|
|
6
8
|
media: matchTokens("mp3 m4a wav mp4 mov webm ogg avi flv avchd")
|
|
7
9
|
};
|
|
@@ -5,3 +5,5 @@ export declare function copyFile(src: string, trg: string): void;
|
|
|
5
5
|
export declare function removeFile(src: string): void;
|
|
6
6
|
export declare function createFolder(path: string): void;
|
|
7
7
|
export declare function removeFolder(path: string): void;
|
|
8
|
+
export declare function removeEntry(path: string): void;
|
|
9
|
+
export declare function isFile(path: string): any;
|
|
@@ -30,3 +30,15 @@ export function removeFolder(path) {
|
|
|
30
30
|
Fs.rmSync(path, { recursive: true, force: true });
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
export function removeEntry(path) {
|
|
34
|
+
if (Fs.existsSync(path)) {
|
|
35
|
+
if (isFile(path)) {
|
|
36
|
+
removeFile(path);
|
|
37
|
+
} else {
|
|
38
|
+
removeFolder(path);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function isFile(path) {
|
|
43
|
+
return Fs.lstatSync(path).isFile();
|
|
44
|
+
}
|
|
@@ -6,6 +6,11 @@ export declare function parseQuery(path: string): string;
|
|
|
6
6
|
* Removes the query string from a path
|
|
7
7
|
*/
|
|
8
8
|
export declare function removeQuery(path: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Gets the extension of a path
|
|
11
|
+
* @param path
|
|
12
|
+
*/
|
|
13
|
+
export declare function getExt(path: string): string;
|
|
9
14
|
/**
|
|
10
15
|
* Test path to be relative
|
|
11
16
|
*/
|
|
@@ -20,7 +25,7 @@ export declare function isExcluded(path: string): boolean;
|
|
|
20
25
|
*/
|
|
21
26
|
export declare function isImage(path: string): boolean;
|
|
22
27
|
/**
|
|
23
|
-
* Test path is markdown
|
|
28
|
+
* Test path is markdown or data
|
|
24
29
|
*/
|
|
25
30
|
export declare function isArticle(path: string): boolean;
|
|
26
31
|
/**
|
|
@@ -7,6 +7,9 @@ export function parseQuery(path) {
|
|
|
7
7
|
export function removeQuery(path) {
|
|
8
8
|
return path.replace(/\?.*$/, "");
|
|
9
9
|
}
|
|
10
|
+
export function getExt(path) {
|
|
11
|
+
return Path.extname(removeQuery(path)).substring(1);
|
|
12
|
+
}
|
|
10
13
|
export function isRelative(path) {
|
|
11
14
|
return !(path.startsWith("http") || Path.isAbsolute(path));
|
|
12
15
|
}
|
|
@@ -14,11 +17,10 @@ export function isExcluded(path) {
|
|
|
14
17
|
return path.split("/").some((segment) => segment.startsWith(".") || segment.startsWith("_"));
|
|
15
18
|
}
|
|
16
19
|
export function isImage(path) {
|
|
17
|
-
|
|
18
|
-
return extensions.image.includes(ext);
|
|
20
|
+
return extensions.image.includes(getExt(path));
|
|
19
21
|
}
|
|
20
22
|
export function isArticle(path) {
|
|
21
|
-
return
|
|
23
|
+
return extensions.content.includes(getExt(path));
|
|
22
24
|
}
|
|
23
25
|
export function isAsset(path) {
|
|
24
26
|
return !isArticle(path);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-content-assets",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.4",
|
|
4
4
|
"description": "Enable locally-located assets in Nuxt Content",
|
|
5
5
|
"repository": "davestewart/nuxt-content-assets",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,16 +15,23 @@
|
|
|
15
15
|
"main": "./dist/module.cjs",
|
|
16
16
|
"types": "./dist/types.d.ts",
|
|
17
17
|
"files": [
|
|
18
|
+
"cache",
|
|
18
19
|
"dist"
|
|
19
20
|
],
|
|
20
21
|
"scripts": {
|
|
22
|
+
"dev:setup": "cpy cache playground/node_modules/nuxt-content-assets && cpy \"cache/**\" playground/.nuxt/content-assets",
|
|
23
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare",
|
|
24
|
+
|
|
21
25
|
"dev": "nuxi dev playground",
|
|
22
|
-
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
23
26
|
"dev:generate": "nuxi generate playground",
|
|
24
27
|
"dev:build": "nuxi build playground",
|
|
25
28
|
"dev:preview": "nuxi preview playground",
|
|
26
|
-
|
|
27
|
-
"
|
|
29
|
+
|
|
30
|
+
"build": "nuxt-module-build build",
|
|
31
|
+
"release:setup": "npm run lint && npm run test && npm run build",
|
|
32
|
+
"release:dry": "npm run release:setup && npm publish --dry-run",
|
|
33
|
+
"release": "npm run release:setup && npm publish",
|
|
34
|
+
|
|
28
35
|
"lint": "eslint .",
|
|
29
36
|
"test": "vitest run",
|
|
30
37
|
"test:watch": "vitest watch"
|
|
@@ -44,18 +51,19 @@
|
|
|
44
51
|
"@nuxt/content": "^2.0.0"
|
|
45
52
|
},
|
|
46
53
|
"devDependencies": {
|
|
47
|
-
"@types/node": "^20.12.4",
|
|
48
54
|
"@nuxt/devtools": "latest",
|
|
49
55
|
"@nuxt/eslint-config": "^0.2.0",
|
|
50
56
|
"@nuxt/module-builder": "^0.5.5",
|
|
51
57
|
"@nuxt/schema": "^3.11.2",
|
|
52
58
|
"@nuxt/test-utils": "^3.12.0",
|
|
59
|
+
"@types/debounce": "^1.2.1",
|
|
60
|
+
"@types/node": "^20.12.4",
|
|
61
|
+
"@types/ws": "^8.5.10",
|
|
53
62
|
"changelogen": "^0.5.5",
|
|
63
|
+
"cpy-cli": "^5.0.0",
|
|
54
64
|
"eslint": "^8.57.0",
|
|
55
65
|
"nuxt": "^3.11.2",
|
|
56
|
-
"vitest": "^1.4.0"
|
|
57
|
-
"@types/debounce": "^1.2.1",
|
|
58
|
-
"@types/ws": "^8.5.10"
|
|
66
|
+
"vitest": "^1.4.0"
|
|
59
67
|
},
|
|
60
68
|
"engines": {
|
|
61
69
|
"node": ">=16.0.0"
|