nuxt-content-assets 0.6.0 → 0.7.0
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 +67 -41
- package/dist/module.json +1 -1
- package/dist/module.mjs +209 -90
- package/dist/runtime/config.d.ts +2 -0
- package/dist/runtime/config.mjs +2 -0
- package/dist/runtime/options.mjs +3 -3
- package/dist/runtime/plugin.d.ts +3 -2
- package/dist/runtime/plugin.mjs +25 -31
- package/dist/runtime/services/assets.d.ts +18 -0
- package/dist/runtime/services/assets.mjs +31 -0
- package/dist/runtime/services/index.d.ts +3 -0
- package/dist/runtime/services/index.mjs +3 -0
- package/dist/runtime/{utils → services}/paths.d.ts +2 -3
- package/dist/runtime/{utils → services}/paths.mjs +6 -4
- package/dist/runtime/services/sources.d.ts +10 -0
- package/dist/runtime/services/sources.mjs +39 -0
- package/dist/runtime/utils/debug.d.ts +1 -1
- package/dist/runtime/utils/debug.mjs +6 -9
- package/dist/runtime/utils/fs.d.ts +4 -0
- package/dist/runtime/utils/fs.mjs +20 -0
- package/dist/runtime/utils/index.d.ts +3 -4
- package/dist/runtime/utils/index.mjs +3 -4
- package/package.json +13 -8
- package/dist/runtime/utils/content.d.ts +0 -7
- package/dist/runtime/utils/content.mjs +0 -12
- /package/dist/runtime/utils/{assets.d.ts → assert.d.ts} +0 -0
- /package/dist/runtime/utils/{assets.mjs → assert.mjs} +0 -0
- /package/dist/runtime/utils/{config.d.ts → string.d.ts} +0 -0
- /package/dist/runtime/utils/{config.mjs → string.mjs} +0 -0
package/README.md
CHANGED
|
@@ -47,7 +47,13 @@ That's it!
|
|
|
47
47
|
|
|
48
48
|
## Demo
|
|
49
49
|
|
|
50
|
-
To
|
|
50
|
+
To view the demo locally, run:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
npm run dev
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
To view the demo online, visit:
|
|
51
57
|
|
|
52
58
|
- https://stackblitz.com/github/davestewart/nuxt-content-assets?file=demo%2Fapp.vue
|
|
53
59
|
|
|
@@ -55,12 +61,6 @@ You can browse the demo files in:
|
|
|
55
61
|
|
|
56
62
|
- https://github.com/davestewart/nuxt-content-assets/tree/main/demo
|
|
57
63
|
|
|
58
|
-
To run the demo locally, clone the application and from the root, run:
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
npm run demo
|
|
62
|
-
```
|
|
63
|
-
|
|
64
64
|
## Setup
|
|
65
65
|
|
|
66
66
|
Install the dependency:
|
|
@@ -97,7 +97,7 @@ Relative paths are defined by anything not starting with a slash or `http`, for
|
|
|
97
97
|
|
|
98
98
|
```
|
|
99
99
|
image.jpg
|
|
100
|
-
|
|
100
|
+
assets/featured.png
|
|
101
101
|
../assets/cv.pdf
|
|
102
102
|
```
|
|
103
103
|
|
|
@@ -119,20 +119,20 @@ However, you can use relative paths in frontmatter:
|
|
|
119
119
|
---
|
|
120
120
|
title: Portfolio Item 1
|
|
121
121
|
images:
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
-
|
|
122
|
+
- assets/image-1.jpg
|
|
123
|
+
- assets/image-2.jpg
|
|
124
|
+
- assets/image-3.jpg
|
|
125
125
|
---
|
|
126
126
|
```
|
|
127
127
|
|
|
128
128
|
Then pass these to components like so:
|
|
129
129
|
|
|
130
130
|
```markdown
|
|
131
|
-
::gallery{:
|
|
131
|
+
::gallery{:data="images"}
|
|
132
132
|
::
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
> Note: to pass size hints in frontmatter, set the `imageSize` configuration option to `'url'`
|
|
135
|
+
> Note: to pass size hints in frontmatter, set the `imageSize` configuration [option](#image-size) to `'url'`
|
|
136
136
|
|
|
137
137
|
See the [Demo](demo/content/recipes/index.md) for an example.
|
|
138
138
|
|
|
@@ -156,7 +156,7 @@ The module can prevent content jumps by optionally writing image size informatio
|
|
|
156
156
|
<img src="/image.jpg?width=640&height=480" width="640" height="480" style="aspect-ratio:640/480">
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
-
If you use
|
|
159
|
+
If you use [ProseImg](https://content.nuxtjs.org/api/components/prose) components, you can pass these values to your own markup:
|
|
160
160
|
|
|
161
161
|
```vue
|
|
162
162
|
<template>
|
|
@@ -172,7 +172,7 @@ export default {
|
|
|
172
172
|
</script>
|
|
173
173
|
```
|
|
174
174
|
|
|
175
|
-
See the [configuration](#image-size) section to add this, and the [Demo](demo/components/
|
|
175
|
+
See the [configuration](#image-size) section to add this, and the [Demo](demo/components/temp/ProseImg.vue) for an example.
|
|
176
176
|
|
|
177
177
|
### Build
|
|
178
178
|
|
|
@@ -196,7 +196,7 @@ export default defineNuxtConfig({
|
|
|
196
196
|
// where to generate and serve the assets from
|
|
197
197
|
output: 'assets/content/[path]/[file]',
|
|
198
198
|
|
|
199
|
-
//
|
|
199
|
+
// include additional extensions
|
|
200
200
|
additionalExtensions: 'html',
|
|
201
201
|
|
|
202
202
|
// completely replace supported extensions
|
|
@@ -216,38 +216,43 @@ export default defineNuxtConfig({
|
|
|
216
216
|
The output path can be customised using a template string:
|
|
217
217
|
|
|
218
218
|
```
|
|
219
|
-
assets/
|
|
219
|
+
assets/[name]-[hash].[ext]
|
|
220
220
|
```
|
|
221
221
|
|
|
222
|
-
The first part of the path
|
|
222
|
+
The first part of the path is where you want content assets to be served from:
|
|
223
223
|
|
|
224
224
|
```
|
|
225
|
-
assets/
|
|
225
|
+
assets/
|
|
226
226
|
```
|
|
227
227
|
|
|
228
|
-
The optional second part of the path indicates the relative location of each
|
|
228
|
+
The optional second part of the path indicates the relative location of each asset.
|
|
229
229
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
|
233
|
-
|
|
234
|
-
| `[
|
|
235
|
-
| `[
|
|
236
|
-
| `[
|
|
237
|
-
| `[
|
|
230
|
+
The table below shows replacements for the asset `content/posts/2023-01-01/featured.jpg`:
|
|
231
|
+
|
|
232
|
+
| Token | Description | Example |
|
|
233
|
+
|-------------|----------------------------------------------------------------------------------------------------|----------------------------|
|
|
234
|
+
| `[key]` | The config key of the source (see [sources](https://content.nuxtjs.org/api/configuration#sources)) | `content` |
|
|
235
|
+
| `[path]` | The relative path of the source | `content/posts/2023-01-01` |
|
|
236
|
+
| `[folder]` | The relative path of the file's folder | `posts/2023-01-01` |
|
|
237
|
+
| `[file]` | The full filename of the file | `featured.jpg` |
|
|
238
|
+
| `[name]` | The name of the file without the extension | `featured` |
|
|
239
|
+
| `[hash]` | A hash of the absolute source path | `9M00N4l9A0` |
|
|
240
|
+
| `[extname]` | The full extension with the dot | `.jpg` |
|
|
241
|
+
| `[ext]` | The extension without the dot | `jpg` |
|
|
238
242
|
|
|
239
243
|
For example:
|
|
240
244
|
|
|
241
|
-
| Template
|
|
242
|
-
|
|
243
|
-
| `assets/
|
|
244
|
-
| `assets/
|
|
245
|
-
| `
|
|
245
|
+
| Template | Output |
|
|
246
|
+
|------------------------------|------------------------------------------------|
|
|
247
|
+
| `assets/[path]/[file]` | `assets/content/posts/2023-01-01/featured.jpg` |
|
|
248
|
+
| `assets/[folder]/[file]` | `assets/posts/2023-01-01/featured.jpg` |
|
|
249
|
+
| `assets/[name]-[hash].[ext]` | `assets/featured-9M00N4l9A0.jpg` |
|
|
250
|
+
| `assets/[hash].[ext]` | `assets/9M00N4l9A0.jpg` |
|
|
246
251
|
|
|
247
252
|
Note that the module defaults to:
|
|
248
253
|
|
|
249
254
|
```
|
|
250
|
-
/assets/
|
|
255
|
+
/assets/[path]/[file]
|
|
251
256
|
```
|
|
252
257
|
|
|
253
258
|
### Extensions
|
|
@@ -323,30 +328,51 @@ If you want to see what the module does as it runs, set `debug` to true:
|
|
|
323
328
|
|
|
324
329
|
Should you wish to develop the project, the scripts are:
|
|
325
330
|
|
|
331
|
+
Develop the module itself:
|
|
332
|
+
|
|
326
333
|
```bash
|
|
327
334
|
# install dependencies
|
|
328
335
|
npm install
|
|
329
336
|
|
|
330
|
-
#
|
|
331
|
-
npm run dev:prepare
|
|
332
|
-
|
|
333
|
-
# develop with the demo
|
|
337
|
+
# develop (runs using the demo)
|
|
334
338
|
npm run dev
|
|
335
339
|
|
|
336
|
-
# build the demo
|
|
337
|
-
npm run dev:build
|
|
338
|
-
|
|
339
340
|
# run eslint
|
|
340
341
|
npm run lint
|
|
341
342
|
|
|
342
343
|
# run vitest
|
|
343
344
|
npm run test
|
|
344
345
|
npm run test:watch
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Build and check the demo:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
# generate demo type stubs
|
|
352
|
+
npm run demo:prepare
|
|
345
353
|
|
|
354
|
+
# generate the demo output
|
|
355
|
+
npm run demo:generate
|
|
356
|
+
|
|
357
|
+
# serve the demo output
|
|
358
|
+
npm run demo:serve
|
|
359
|
+
|
|
360
|
+
# build the demo
|
|
361
|
+
npm run demo:build
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Make a new release:
|
|
365
|
+
|
|
366
|
+
```bash
|
|
346
367
|
# release new version
|
|
347
368
|
npm run release
|
|
369
|
+
|
|
370
|
+
# dry run the release
|
|
371
|
+
npm run release:dry
|
|
348
372
|
```
|
|
349
373
|
|
|
374
|
+
Make sure to edit changelog and update `package.json` version first!
|
|
375
|
+
|
|
350
376
|
<!-- Badges -->
|
|
351
377
|
[npm-version-src]: https://img.shields.io/npm/v/nuxt-content-assets/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
352
378
|
[npm-version-href]: https://npmjs.com/package/nuxt-content-assets
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import { createResolver, defineNuxtModule, addTemplate } from '@nuxt/kit';
|
|
2
|
-
import getImageSize from 'image-size';
|
|
3
|
-
import glob from 'glob';
|
|
4
1
|
import * as Fs from 'fs';
|
|
5
2
|
import * as Path from 'path';
|
|
6
3
|
import Path__default from 'path';
|
|
4
|
+
import { createResolver, defineNuxtModule, addTemplate } from '@nuxt/kit';
|
|
5
|
+
import getImageSize from 'image-size';
|
|
7
6
|
import { hash } from 'ohash';
|
|
7
|
+
import glob from 'glob';
|
|
8
|
+
import { createStorage } from 'unstorage';
|
|
9
|
+
import githubDriver from 'unstorage/drivers/github';
|
|
8
10
|
|
|
9
11
|
function matchWords(value) {
|
|
10
12
|
return typeof value === "string" ? value.match(/\w+/g) || [] : [];
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
const defaults = {
|
|
14
|
-
assetsDir: "assets/
|
|
15
|
-
assetsPattern: "[
|
|
16
|
+
assetsDir: "/assets/",
|
|
17
|
+
assetsPattern: "[path]/[file]"
|
|
16
18
|
};
|
|
17
19
|
const imageExtensions = matchWords("png jpg jpeg gif svg webp ico");
|
|
18
20
|
const mediaExtensions = matchWords("mp3 m4a wav mp4 mov webm ogg avi flv avchd");
|
|
@@ -28,40 +30,57 @@ function isImage(path) {
|
|
|
28
30
|
return imageExtensions.includes(ext);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
function getSources(sources) {
|
|
32
|
-
return Object.keys(sources).reduce((output, key) => {
|
|
33
|
-
const source = sources[key];
|
|
34
|
-
if (source) {
|
|
35
|
-
const { driver, base } = source;
|
|
36
|
-
if (driver === "fs") {
|
|
37
|
-
output[key] = base;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return output;
|
|
41
|
-
}, {});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
33
|
const moduleName = "nuxt-content-assets";
|
|
45
34
|
const moduleKey = "content-assets";
|
|
46
35
|
|
|
47
36
|
function log(...data) {
|
|
48
37
|
console.info(`[${moduleKey}]`, ...data);
|
|
49
38
|
}
|
|
39
|
+
function warn(...data) {
|
|
40
|
+
console.warn(`[${moduleKey}]`, ...data);
|
|
41
|
+
}
|
|
42
|
+
function list(message, items) {
|
|
43
|
+
log(`${message}:
|
|
44
|
+
|
|
45
|
+
${items.map((item) => ` - ${item}`).join("\n")}
|
|
46
|
+
`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function writeFile(path, data) {
|
|
50
|
+
const text = typeof data === "object" ? JSON.stringify(data, null, " ") : String(data);
|
|
51
|
+
createFolder(Path.dirname(path));
|
|
52
|
+
Fs.writeFileSync(path, text, { encoding: "utf8" });
|
|
53
|
+
}
|
|
54
|
+
function copyFile(src, trg) {
|
|
55
|
+
createFolder(Path.dirname(trg));
|
|
56
|
+
Fs.copyFileSync(src, trg);
|
|
57
|
+
}
|
|
58
|
+
function createFolder(path) {
|
|
59
|
+
Fs.mkdirSync(path, { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
function removeFolder(path) {
|
|
62
|
+
const isDownstream = path.startsWith(Path.resolve());
|
|
63
|
+
if (isDownstream) {
|
|
64
|
+
Fs.rmSync(path, { recursive: true, force: true });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
50
67
|
|
|
51
68
|
const replacers = {
|
|
52
|
-
|
|
69
|
+
key: (src) => Path__default.dirname(src).split("/").filter((e) => e).shift() || "",
|
|
70
|
+
path: (src) => Path__default.dirname(src),
|
|
71
|
+
folder: (src) => Path__default.dirname(src).replace(/[^/]+\//, ""),
|
|
53
72
|
file: (src) => Path__default.basename(src),
|
|
54
73
|
name: (src) => Path__default.basename(src, Path__default.extname(src)),
|
|
55
74
|
extname: (src) => Path__default.extname(src),
|
|
56
75
|
ext: (src) => Path__default.extname(src).substring(1),
|
|
57
76
|
hash: (src) => hash({ src })
|
|
58
77
|
};
|
|
59
|
-
function interpolatePattern(pattern, src,
|
|
78
|
+
function interpolatePattern(pattern, src, warn = false) {
|
|
60
79
|
return Path__default.join(pattern.replace(/\[\w+]/g, (match) => {
|
|
61
80
|
const name = match.substring(1, match.length - 1);
|
|
62
81
|
const fn = replacers[name];
|
|
63
82
|
if (fn) {
|
|
64
|
-
return fn(src
|
|
83
|
+
return fn(src);
|
|
65
84
|
}
|
|
66
85
|
if (warn) {
|
|
67
86
|
log(`Unknown output token ${match}`, true);
|
|
@@ -70,6 +89,69 @@ function interpolatePattern(pattern, src, dir, warn = false) {
|
|
|
70
89
|
}));
|
|
71
90
|
}
|
|
72
91
|
|
|
92
|
+
function getAssetConfig(srcDir, srcAbs, pattern, hints) {
|
|
93
|
+
let width = void 0;
|
|
94
|
+
let height = void 0;
|
|
95
|
+
let ratio = void 0;
|
|
96
|
+
let query = void 0;
|
|
97
|
+
if (hints.length && isImage(srcAbs)) {
|
|
98
|
+
try {
|
|
99
|
+
const size = getImageSize(srcAbs);
|
|
100
|
+
if (hints.includes("style")) {
|
|
101
|
+
ratio = `${size.width}/${size.height}`;
|
|
102
|
+
}
|
|
103
|
+
if (hints.includes("attrs")) {
|
|
104
|
+
width = size.width;
|
|
105
|
+
height = size.height;
|
|
106
|
+
}
|
|
107
|
+
if (hints.includes("url")) {
|
|
108
|
+
query = `?width=${width}&height=${height}`;
|
|
109
|
+
}
|
|
110
|
+
} catch (err) {
|
|
111
|
+
warn(`could not read image "${srcAbs}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const srcRel = Path.basename(srcDir) + srcAbs.substring(srcDir.length);
|
|
115
|
+
const srcAttr = interpolatePattern(pattern, srcRel);
|
|
116
|
+
const id = srcRel.replaceAll("/", ":");
|
|
117
|
+
return { id, srcRel, srcAttr, width, height, ratio, query };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async function getGithubAssets(key, source, tempPath, extensions) {
|
|
121
|
+
const storage = createStorage();
|
|
122
|
+
storage.mount(key, githubDriver({
|
|
123
|
+
repo: source.repo,
|
|
124
|
+
branch: source.branch || "main",
|
|
125
|
+
dir: source.dir || "/",
|
|
126
|
+
ttl: source.ttl || 600
|
|
127
|
+
}));
|
|
128
|
+
const rx = new RegExp(`.${extensions.join("|")}$`);
|
|
129
|
+
const keys = await storage.getKeys();
|
|
130
|
+
const assetKeys = keys.filter((key2) => rx.test(key2));
|
|
131
|
+
const assetItems = await Promise.all(assetKeys.map(async (id) => {
|
|
132
|
+
const data = await storage.getItem(id);
|
|
133
|
+
return { id, data };
|
|
134
|
+
}));
|
|
135
|
+
const prefix = source.prefix || "";
|
|
136
|
+
const paths = [];
|
|
137
|
+
for (const { id, data } of assetItems) {
|
|
138
|
+
if (data) {
|
|
139
|
+
const path = id.replaceAll(":", "/");
|
|
140
|
+
const absPath = Path.join(tempPath, path.replace(key, `${key}/${prefix}`));
|
|
141
|
+
const absFolder = Path.dirname(absPath);
|
|
142
|
+
const buffer = data.constructor.name === "Blob" ? Buffer.from(await data.arrayBuffer()) : typeof data === "object" ? JSON.stringify(data, null, " ") : String(data);
|
|
143
|
+
Fs.mkdirSync(absFolder, { recursive: true });
|
|
144
|
+
Fs.writeFileSync(absPath, buffer);
|
|
145
|
+
paths.push(absPath);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return paths;
|
|
149
|
+
}
|
|
150
|
+
function getFsAssets(path, extensions) {
|
|
151
|
+
const pattern = `${path}/**/*.{${extensions.join(",")}}`;
|
|
152
|
+
return glob.globSync(pattern) || [];
|
|
153
|
+
}
|
|
154
|
+
|
|
73
155
|
const resolve = createResolver(import.meta.url).resolve;
|
|
74
156
|
const module = defineNuxtModule({
|
|
75
157
|
meta: {
|
|
@@ -86,97 +168,134 @@ const module = defineNuxtModule({
|
|
|
86
168
|
imageSize: "",
|
|
87
169
|
debug: false
|
|
88
170
|
},
|
|
89
|
-
setup(options, nuxt) {
|
|
90
|
-
var _a;
|
|
171
|
+
async setup(options, nuxt) {
|
|
172
|
+
var _a, _b;
|
|
91
173
|
const pluginPath = resolve("./runtime/plugin");
|
|
92
174
|
const buildPath = nuxt.options.buildDir;
|
|
93
|
-
const cachePath = Path.
|
|
175
|
+
const cachePath = Path.join(buildPath, "content-assets");
|
|
176
|
+
const publicPath = Path.join(cachePath, "public");
|
|
177
|
+
const tempPath = Path.resolve("node_modules/.nuxt-content-assets");
|
|
178
|
+
const dump = (name, data) => {
|
|
179
|
+
const path = `${cachePath}/debug/${name}.json`;
|
|
180
|
+
log(`Dumping "${Path.relative("", path)}"`);
|
|
181
|
+
writeFile(path, data);
|
|
182
|
+
};
|
|
94
183
|
if (options.debug) {
|
|
95
184
|
log("Removing cache folders...");
|
|
96
185
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return output2;
|
|
104
|
-
}, {});
|
|
105
|
-
if (Object.keys(sources).length === 0 || !sources.content) {
|
|
106
|
-
const content = nuxt.options.srcDir + "/content";
|
|
107
|
-
if (Fs.existsSync(content)) {
|
|
108
|
-
sources.content = content;
|
|
109
|
-
}
|
|
186
|
+
removeFolder(Path.join(buildPath, "content-cache"));
|
|
187
|
+
removeFolder(cachePath);
|
|
188
|
+
removeFolder(tempPath);
|
|
189
|
+
(_a = nuxt.options).content || (_a.content = {});
|
|
190
|
+
if (nuxt.options.content) {
|
|
191
|
+
(_b = nuxt.options.content).ignores || (_b.ignores = []);
|
|
110
192
|
}
|
|
111
193
|
const output = options.output || defaults.assetsDir;
|
|
112
194
|
const matches = output.match(/([^[]+)(.*)?/);
|
|
113
|
-
const assetsDir = matches ? matches[1] : defaults.assetsDir;
|
|
195
|
+
const assetsDir = matches ? matches[1].replace(/^\/*/, "/").replace(/\/*$/, "") : defaults.assetsDir;
|
|
114
196
|
const assetsPattern = (matches ? matches[2] : "") || defaults.assetsPattern;
|
|
115
|
-
interpolatePattern(assetsPattern, "",
|
|
197
|
+
interpolatePattern(assetsPattern, "", true);
|
|
116
198
|
const imageFlags = matchWords(options.imageSize);
|
|
117
199
|
if (options.extensions?.trim()) {
|
|
118
200
|
extensions.splice(0, extensions.length, ...matchWords(options.extensions));
|
|
119
201
|
} else if (options.additionalExtensions) {
|
|
120
202
|
extensions.push(...matchWords(options.additionalExtensions));
|
|
121
203
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
let height = void 0;
|
|
125
|
-
let ratio = void 0;
|
|
126
|
-
let query = void 0;
|
|
127
|
-
if (imageFlags.length && isImage(src)) {
|
|
128
|
-
const size = getImageSize(src);
|
|
129
|
-
if (imageFlags.includes("style")) {
|
|
130
|
-
ratio = `${size.width}/${size.height}`;
|
|
131
|
-
}
|
|
132
|
-
if (imageFlags.includes("attrs")) {
|
|
133
|
-
width = size.width;
|
|
134
|
-
height = size.height;
|
|
135
|
-
}
|
|
136
|
-
if (imageFlags.includes("url")) {
|
|
137
|
-
query = `?width=${width}&height=${height}`;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
const id = Path.join(Path.basename(dir), Path.relative(dir, src)).replaceAll("/", ":");
|
|
141
|
-
const file = interpolatePattern(pattern, src, dir);
|
|
142
|
-
const trg = Path.join(cachePath, assetsDir, file);
|
|
143
|
-
const rel = Path.join("/", assetsDir, file);
|
|
144
|
-
return { id, file, trg, rel, width, height, ratio, query };
|
|
204
|
+
if (options.debug) {
|
|
205
|
+
log("Preparing sources...");
|
|
145
206
|
}
|
|
146
|
-
const publicFolder = Path.join(cachePath, assetsDir);
|
|
147
|
-
const sourceFolders = Object.values(sources);
|
|
148
207
|
const assets = {};
|
|
149
|
-
|
|
150
|
-
(
|
|
208
|
+
const sources = nuxt.options._layers.map((layer) => layer.config?.content?.sources).reduce((output2, sources2) => {
|
|
209
|
+
if (sources2) {
|
|
210
|
+
Object.assign(output2, sources2);
|
|
211
|
+
}
|
|
212
|
+
return output2;
|
|
213
|
+
}, {});
|
|
214
|
+
if (Object.keys(sources).length === 0 || !sources.content) {
|
|
215
|
+
const content = nuxt.options.srcDir + "/content";
|
|
216
|
+
if (Fs.existsSync(content)) {
|
|
217
|
+
sources.content = {
|
|
218
|
+
driver: "fs",
|
|
219
|
+
base: content
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
for (const [key, source] of Object.entries(sources)) {
|
|
224
|
+
const { driver } = source;
|
|
225
|
+
let srcDir = "";
|
|
226
|
+
let paths = [];
|
|
227
|
+
switch (driver) {
|
|
228
|
+
case "fs":
|
|
229
|
+
paths = getFsAssets(source.base, extensions);
|
|
230
|
+
srcDir = source.base;
|
|
231
|
+
break;
|
|
232
|
+
case "github":
|
|
233
|
+
paths = await getGithubAssets(key, source, tempPath, extensions);
|
|
234
|
+
srcDir = Path.join(tempPath, key);
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
if (options.debug) {
|
|
238
|
+
log(`Prepared ${paths.length} paths for source "${key}"`);
|
|
239
|
+
}
|
|
240
|
+
if (paths.length) {
|
|
241
|
+
paths.forEach((src) => {
|
|
242
|
+
const {
|
|
243
|
+
id,
|
|
244
|
+
srcRel,
|
|
245
|
+
srcAttr,
|
|
246
|
+
width,
|
|
247
|
+
height,
|
|
248
|
+
ratio,
|
|
249
|
+
query
|
|
250
|
+
} = getAssetConfig(srcDir, src, assetsPattern, imageFlags);
|
|
251
|
+
nuxt.options.content.ignores.push(id);
|
|
252
|
+
const trg = Path.join(publicPath, assetsDir, srcAttr);
|
|
253
|
+
assets[srcRel] = {
|
|
254
|
+
src,
|
|
255
|
+
trg,
|
|
256
|
+
config: {
|
|
257
|
+
srcAttr: Path.join(assetsDir, srcAttr),
|
|
258
|
+
width,
|
|
259
|
+
height,
|
|
260
|
+
ratio,
|
|
261
|
+
query
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
});
|
|
265
|
+
}
|
|
151
266
|
}
|
|
152
|
-
sourceFolders.forEach((folder) => {
|
|
153
|
-
const pattern = `${folder}/**/*.{${extensions.join(",")}}`;
|
|
154
|
-
const paths = glob.globSync(pattern);
|
|
155
|
-
paths.forEach((src) => {
|
|
156
|
-
const config = getAssetConfig(assetsPattern, src, folder);
|
|
157
|
-
nuxt.options.content.ignores.push(config.id);
|
|
158
|
-
assets[src] = config;
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
267
|
nuxt.hook("build:before", function() {
|
|
162
|
-
Fs.mkdirSync(publicFolder, { recursive: true });
|
|
163
268
|
if (options.debug) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
${
|
|
168
|
-
|
|
269
|
+
dump("assets", assets);
|
|
270
|
+
}
|
|
271
|
+
if (options.debug) {
|
|
272
|
+
log(`Copying ${Object.keys(assets).length} assets...`);
|
|
273
|
+
}
|
|
274
|
+
const copied = [];
|
|
275
|
+
const failed = [];
|
|
276
|
+
for (const [key, { src, trg }] of Object.entries(assets)) {
|
|
277
|
+
if (Fs.existsSync(src)) {
|
|
278
|
+
copyFile(src, trg);
|
|
279
|
+
copied.push(key);
|
|
280
|
+
} else {
|
|
281
|
+
failed.push(key);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if (options.debug) {
|
|
285
|
+
if (copied.length) {
|
|
286
|
+
list("Copied", copied);
|
|
287
|
+
}
|
|
288
|
+
if (failed.length) {
|
|
289
|
+
list("Failed to copy", failed);
|
|
290
|
+
}
|
|
169
291
|
}
|
|
170
|
-
Object.keys(assets).forEach((src) => {
|
|
171
|
-
const { trg } = assets[src];
|
|
172
|
-
const trgFolder = Path.dirname(trg);
|
|
173
|
-
Fs.mkdirSync(trgFolder, { recursive: true });
|
|
174
|
-
Fs.copyFileSync(src, trg);
|
|
175
|
-
});
|
|
176
292
|
});
|
|
293
|
+
const nitroAssets = Object.entries(assets).reduce((output2, [key, value]) => {
|
|
294
|
+
output2[key] = value.config;
|
|
295
|
+
return output2;
|
|
296
|
+
}, {});
|
|
177
297
|
const virtualConfig = [
|
|
178
|
-
`export const assets = ${JSON.stringify(
|
|
179
|
-
`export const sources = ${JSON.stringify(sources)}`
|
|
298
|
+
`export const assets = ${JSON.stringify(nitroAssets, null, " ")}`
|
|
180
299
|
].join("\n");
|
|
181
300
|
nuxt.options.alias[`#${moduleName}`] = addTemplate({
|
|
182
301
|
filename: `${moduleName}.mjs`,
|
|
@@ -189,7 +308,7 @@ ${paths.join("\n")}
|
|
|
189
308
|
config.virtual[`#${moduleName}`] = virtualConfig;
|
|
190
309
|
config.publicAssets || (config.publicAssets = []);
|
|
191
310
|
config.publicAssets.push({
|
|
192
|
-
dir:
|
|
311
|
+
dir: publicPath
|
|
193
312
|
// maxAge: 60 * 60 * 24 * 365 // 1 year
|
|
194
313
|
});
|
|
195
314
|
});
|
package/dist/runtime/options.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { matchWords } from "./utils/
|
|
1
|
+
import { matchWords } from "./utils/string.mjs";
|
|
2
2
|
export const defaults = {
|
|
3
|
-
assetsDir: "assets/
|
|
4
|
-
assetsPattern: "[
|
|
3
|
+
assetsDir: "/assets/",
|
|
4
|
+
assetsPattern: "[path]/[file]"
|
|
5
5
|
};
|
|
6
6
|
export const imageExtensions = matchWords("png jpg jpeg gif svg webp ico");
|
|
7
7
|
export const mediaExtensions = matchWords("mp3 m4a wav mp4 mov webm ogg avi flv avchd");
|
package/dist/runtime/plugin.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type { NitroAppPlugin } from 'nitropack';
|
|
2
|
+
declare const plugin: NitroAppPlugin;
|
|
3
|
+
export default plugin;
|
package/dist/runtime/plugin.mjs
CHANGED
|
@@ -2,49 +2,42 @@ import Path from "path";
|
|
|
2
2
|
import { visit } from "unist-util-visit";
|
|
3
3
|
import { isValidAsset, walk } from "./utils/index.mjs";
|
|
4
4
|
import { tags } from "./options.mjs";
|
|
5
|
-
import { assets
|
|
6
|
-
function
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
const relPath = parts.join("/");
|
|
10
|
-
const absBase = sources[key];
|
|
11
|
-
return Path.join(absBase, relPath);
|
|
5
|
+
import { assets } from "#nuxt-content-assets";
|
|
6
|
+
function getAsset(srcDoc, relAsset) {
|
|
7
|
+
const srcAsset = Path.join(Path.dirname(srcDoc), relAsset);
|
|
8
|
+
return assets[srcAsset] || {};
|
|
12
9
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return assets[absAsset] || {};
|
|
16
|
-
}
|
|
17
|
-
export default defineNitroPlugin(async (nitroApp) => {
|
|
18
|
-
nitroApp.hooks.hook("content:file:afterParse", async (file) => {
|
|
10
|
+
const plugin = async (nitro) => {
|
|
11
|
+
nitro.hooks.hook("content:file:afterParse", async (file) => {
|
|
19
12
|
if (file._id.endsWith(".md")) {
|
|
20
|
-
const
|
|
13
|
+
const srcDoc = file._id.split(":").join("/");
|
|
21
14
|
const filter = (value, key) => !(String(key).startsWith("_") || key === "body");
|
|
22
15
|
walk(file, (value, parent, key) => {
|
|
23
16
|
if (isValidAsset(value)) {
|
|
24
|
-
const {
|
|
25
|
-
if (
|
|
26
|
-
parent[key] =
|
|
17
|
+
const { srcAttr, query } = getAsset(srcDoc, value);
|
|
18
|
+
if (srcAttr) {
|
|
19
|
+
parent[key] = srcAttr + (query || "");
|
|
27
20
|
}
|
|
28
21
|
}
|
|
29
22
|
}, filter);
|
|
30
23
|
visit(file.body, (n) => tags.includes(n.tag), (node) => {
|
|
31
24
|
if (node.props.src) {
|
|
32
|
-
const {
|
|
33
|
-
if (
|
|
34
|
-
node.props.src =
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
25
|
+
const { srcAttr, width, height, ratio } = getAsset(srcDoc, node.props.src);
|
|
26
|
+
if (srcAttr) {
|
|
27
|
+
node.props.src = srcAttr;
|
|
28
|
+
if (width && height) {
|
|
29
|
+
node.props.width = width;
|
|
30
|
+
node.props.height = height;
|
|
31
|
+
}
|
|
32
|
+
if (ratio) {
|
|
33
|
+
node.props.style = `aspect-ratio:${ratio}`;
|
|
34
|
+
}
|
|
42
35
|
}
|
|
43
36
|
} else if (node.tag === "a") {
|
|
44
37
|
if (node.props.href) {
|
|
45
|
-
const {
|
|
46
|
-
if (
|
|
47
|
-
node.props.href =
|
|
38
|
+
const { srcAttr } = getAsset(srcDoc, node.props.href);
|
|
39
|
+
if (srcAttr) {
|
|
40
|
+
node.props.href = srcAttr;
|
|
48
41
|
node.props.target = "_blank";
|
|
49
42
|
}
|
|
50
43
|
}
|
|
@@ -52,4 +45,5 @@ export default defineNitroPlugin(async (nitroApp) => {
|
|
|
52
45
|
});
|
|
53
46
|
}
|
|
54
47
|
});
|
|
55
|
-
}
|
|
48
|
+
};
|
|
49
|
+
export default plugin;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type AssetConfig = {
|
|
2
|
+
id: string;
|
|
3
|
+
srcRel: string;
|
|
4
|
+
srcAttr: string;
|
|
5
|
+
width?: number;
|
|
6
|
+
height?: number;
|
|
7
|
+
ratio?: string;
|
|
8
|
+
query?: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Get config for asset
|
|
12
|
+
*
|
|
13
|
+
* @param srcDir The absolute path to the asset's source folder
|
|
14
|
+
* @param srcAbs The absolute path to the asset itself
|
|
15
|
+
* @param pattern The user-defined pattern to create the public src attribute
|
|
16
|
+
* @param hints A list of named image size hints, i.e. 'style', 'attrs', etc
|
|
17
|
+
*/
|
|
18
|
+
export declare function getAssetConfig(srcDir: string, srcAbs: string, pattern: string, hints: string[]): AssetConfig;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as Path from "path";
|
|
2
|
+
import getImageSize from "image-size";
|
|
3
|
+
import { isImage, warn } from "../utils/index.mjs";
|
|
4
|
+
import { interpolatePattern } from "./paths.mjs";
|
|
5
|
+
export function getAssetConfig(srcDir, srcAbs, pattern, hints) {
|
|
6
|
+
let width = void 0;
|
|
7
|
+
let height = void 0;
|
|
8
|
+
let ratio = void 0;
|
|
9
|
+
let query = void 0;
|
|
10
|
+
if (hints.length && isImage(srcAbs)) {
|
|
11
|
+
try {
|
|
12
|
+
const size = getImageSize(srcAbs);
|
|
13
|
+
if (hints.includes("style")) {
|
|
14
|
+
ratio = `${size.width}/${size.height}`;
|
|
15
|
+
}
|
|
16
|
+
if (hints.includes("attrs")) {
|
|
17
|
+
width = size.width;
|
|
18
|
+
height = size.height;
|
|
19
|
+
}
|
|
20
|
+
if (hints.includes("url")) {
|
|
21
|
+
query = `?width=${width}&height=${height}`;
|
|
22
|
+
}
|
|
23
|
+
} catch (err) {
|
|
24
|
+
warn(`could not read image "${srcAbs}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const srcRel = Path.basename(srcDir) + srcAbs.substring(srcDir.length);
|
|
28
|
+
const srcAttr = interpolatePattern(pattern, srcRel);
|
|
29
|
+
const id = srcRel.replaceAll("/", ":");
|
|
30
|
+
return { id, srcRel, srcAttr, width, height, ratio, query };
|
|
31
|
+
}
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* Interpolate assets path pattern
|
|
3
3
|
*
|
|
4
4
|
* @param pattern A path pattern with tokens
|
|
5
|
-
* @param src The
|
|
6
|
-
* @param dir The absolute path to its containing folder
|
|
5
|
+
* @param src The relative path to a src asset
|
|
7
6
|
* @param warn An optional flag to warn for unknown tokens
|
|
8
7
|
*/
|
|
9
|
-
export declare function interpolatePattern(pattern: string, src: string,
|
|
8
|
+
export declare function interpolatePattern(pattern: string, src: string, warn?: boolean): string;
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import Path from "path";
|
|
2
2
|
import { hash } from "ohash";
|
|
3
|
-
import { log } from "
|
|
3
|
+
import { log } from "../utils/index.mjs";
|
|
4
4
|
const replacers = {
|
|
5
|
-
|
|
5
|
+
key: (src) => Path.dirname(src).split("/").filter((e) => e).shift() || "",
|
|
6
|
+
path: (src) => Path.dirname(src),
|
|
7
|
+
folder: (src) => Path.dirname(src).replace(/[^/]+\//, ""),
|
|
6
8
|
file: (src) => Path.basename(src),
|
|
7
9
|
name: (src) => Path.basename(src, Path.extname(src)),
|
|
8
10
|
extname: (src) => Path.extname(src),
|
|
9
11
|
ext: (src) => Path.extname(src).substring(1),
|
|
10
12
|
hash: (src) => hash({ src })
|
|
11
13
|
};
|
|
12
|
-
export function interpolatePattern(pattern, src,
|
|
14
|
+
export function interpolatePattern(pattern, src, warn = false) {
|
|
13
15
|
return Path.join(pattern.replace(/\[\w+]/g, (match) => {
|
|
14
16
|
const name = match.substring(1, match.length - 1);
|
|
15
17
|
const fn = replacers[name];
|
|
16
18
|
if (fn) {
|
|
17
|
-
return fn(src
|
|
19
|
+
return fn(src);
|
|
18
20
|
}
|
|
19
21
|
if (warn) {
|
|
20
22
|
log(`Unknown output token ${match}`, true);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type GithubOptions = {
|
|
2
|
+
repo: string;
|
|
3
|
+
branch?: string;
|
|
4
|
+
dir?: string;
|
|
5
|
+
prefix?: string;
|
|
6
|
+
ttl?: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function getGithubAssets(key: string, source: GithubOptions, tempPath: string, extensions: string[]): Promise<string[]>;
|
|
9
|
+
export declare function getFsAssets(path: string, extensions: string[]): string[];
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as Fs from "fs";
|
|
2
|
+
import * as Path from "path";
|
|
3
|
+
import glob from "glob";
|
|
4
|
+
import { createStorage } from "unstorage";
|
|
5
|
+
import githubDriver from "unstorage/drivers/github";
|
|
6
|
+
export async function getGithubAssets(key, source, tempPath, extensions) {
|
|
7
|
+
const storage = createStorage();
|
|
8
|
+
storage.mount(key, githubDriver({
|
|
9
|
+
repo: source.repo,
|
|
10
|
+
branch: source.branch || "main",
|
|
11
|
+
dir: source.dir || "/",
|
|
12
|
+
ttl: source.ttl || 600
|
|
13
|
+
}));
|
|
14
|
+
const rx = new RegExp(`.${extensions.join("|")}$`);
|
|
15
|
+
const keys = await storage.getKeys();
|
|
16
|
+
const assetKeys = keys.filter((key2) => rx.test(key2));
|
|
17
|
+
const assetItems = await Promise.all(assetKeys.map(async (id) => {
|
|
18
|
+
const data = await storage.getItem(id);
|
|
19
|
+
return { id, data };
|
|
20
|
+
}));
|
|
21
|
+
const prefix = source.prefix || "";
|
|
22
|
+
const paths = [];
|
|
23
|
+
for (const { id, data } of assetItems) {
|
|
24
|
+
if (data) {
|
|
25
|
+
const path = id.replaceAll(":", "/");
|
|
26
|
+
const absPath = Path.join(tempPath, path.replace(key, `${key}/${prefix}`));
|
|
27
|
+
const absFolder = Path.dirname(absPath);
|
|
28
|
+
const buffer = data.constructor.name === "Blob" ? Buffer.from(await data.arrayBuffer()) : typeof data === "object" ? JSON.stringify(data, null, " ") : String(data);
|
|
29
|
+
Fs.mkdirSync(absFolder, { recursive: true });
|
|
30
|
+
Fs.writeFileSync(absPath, buffer);
|
|
31
|
+
paths.push(absPath);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return paths;
|
|
35
|
+
}
|
|
36
|
+
export function getFsAssets(path, extensions) {
|
|
37
|
+
const pattern = `${path}/**/*.{${extensions.join(",")}}`;
|
|
38
|
+
return glob.globSync(pattern) || [];
|
|
39
|
+
}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Fs from "fs";
|
|
3
|
-
import { moduleKey } from "../../config";
|
|
1
|
+
import { moduleKey } from "../config.mjs";
|
|
4
2
|
export function log(...data) {
|
|
5
3
|
console.info(`[${moduleKey}]`, ...data);
|
|
6
4
|
}
|
|
7
5
|
export function warn(...data) {
|
|
8
6
|
console.warn(`[${moduleKey}]`, ...data);
|
|
9
7
|
}
|
|
10
|
-
export function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Fs.writeFileSync(path, JSON.stringify(data, null, " "), { encoding: "utf8" });
|
|
8
|
+
export function list(message, items) {
|
|
9
|
+
log(`${message}:
|
|
10
|
+
|
|
11
|
+
${items.map((item) => ` - ${item}`).join("\n")}
|
|
12
|
+
`);
|
|
16
13
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function writeFile(path: string, data: null | string | number | boolean | object): void;
|
|
2
|
+
export declare function copyFile(src: string, trg: string): void;
|
|
3
|
+
export declare function createFolder(path: string): void;
|
|
4
|
+
export declare function removeFolder(path: string): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as Path from "path";
|
|
2
|
+
import * as Fs from "fs";
|
|
3
|
+
export function writeFile(path, data) {
|
|
4
|
+
const text = typeof data === "object" ? JSON.stringify(data, null, " ") : String(data);
|
|
5
|
+
createFolder(Path.dirname(path));
|
|
6
|
+
Fs.writeFileSync(path, text, { encoding: "utf8" });
|
|
7
|
+
}
|
|
8
|
+
export function copyFile(src, trg) {
|
|
9
|
+
createFolder(Path.dirname(trg));
|
|
10
|
+
Fs.copyFileSync(src, trg);
|
|
11
|
+
}
|
|
12
|
+
export function createFolder(path) {
|
|
13
|
+
Fs.mkdirSync(path, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
export function removeFolder(path) {
|
|
16
|
+
const isDownstream = path.startsWith(Path.resolve());
|
|
17
|
+
if (isDownstream) {
|
|
18
|
+
Fs.rmSync(path, { recursive: true, force: true });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./config.mjs";
|
|
3
|
-
export * from "./content.mjs";
|
|
1
|
+
export * from "./assert.mjs";
|
|
4
2
|
export * from "./debug.mjs";
|
|
3
|
+
export * from "./fs.mjs";
|
|
4
|
+
export * from "./string.mjs";
|
|
5
5
|
export * from "./object.mjs";
|
|
6
|
-
export * from "./paths.mjs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-content-assets",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Enable locally-located assets in Nuxt Content",
|
|
5
5
|
"repository": "davestewart/nuxt-content-assets",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,22 +19,24 @@
|
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
21
|
"dev": "nuxi dev demo",
|
|
22
|
-
"dev:build": "nuxi build demo",
|
|
23
|
-
"dev:prepare": "nuxt-module-build --stub && nuxi prepare demo",
|
|
24
22
|
"build": "nuxt-module-build",
|
|
25
|
-
"release": "npm run lint && npm run test && npm run build && npm publish && git push --follow-tags",
|
|
26
|
-
"release:dry": "npm run lint && npm run test && npm run build && npm publish --dry-run",
|
|
27
|
-
"release:old": "npm run lint && npm run test && npm run build && changelogen --release && npm publish && git push --follow-tags",
|
|
28
23
|
"lint": "eslint .",
|
|
29
24
|
"test": "vitest run",
|
|
30
|
-
"test:watch": "vitest watch"
|
|
25
|
+
"test:watch": "vitest watch",
|
|
26
|
+
"demo:prepare": "nuxt-module-build --stub && nuxi prepare demo",
|
|
27
|
+
"demo:generate": "nuxt generate demo",
|
|
28
|
+
"demo:serve": "npx serve demo/dist",
|
|
29
|
+
"demo:build": "nuxi build demo",
|
|
30
|
+
"release": "npm run lint && npm run test && npm run build && npm publish && git push --follow-tags",
|
|
31
|
+
"release:dry": "npm run lint && npm run test && npm run build && npm publish --dry-run"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
34
|
"@nuxt/kit": "^3.3.2",
|
|
34
35
|
"glob": "^9.3.2",
|
|
35
36
|
"image-size": "^1.0.2",
|
|
36
37
|
"ohash": "^1.0.0",
|
|
37
|
-
"unist-util-visit": "^4.1.2"
|
|
38
|
+
"unist-util-visit": "^4.1.2",
|
|
39
|
+
"unstorage": "^1.4.1"
|
|
38
40
|
},
|
|
39
41
|
"peerDependencies": {
|
|
40
42
|
"@nuxt/content": "latest"
|
|
@@ -49,5 +51,8 @@
|
|
|
49
51
|
"eslint": "^8.36.0",
|
|
50
52
|
"nuxt": "^3.3.2",
|
|
51
53
|
"vitest": "^0.29.7"
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=14.0.0"
|
|
52
57
|
}
|
|
53
58
|
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export function getSources(sources) {
|
|
2
|
-
return Object.keys(sources).reduce((output, key) => {
|
|
3
|
-
const source = sources[key];
|
|
4
|
-
if (source) {
|
|
5
|
-
const { driver, base } = source;
|
|
6
|
-
if (driver === "fs") {
|
|
7
|
-
output[key] = base;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
return output;
|
|
11
|
-
}, {});
|
|
12
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|