nuxt-content-assets 1.0.0 → 1.1.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 +40 -19
- package/dist/module.d.ts +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +6 -3
- package/dist/runtime/plugin.mjs +17 -5
- package/dist/runtime/services/assets.d.ts +1 -1
- package/dist/runtime/services/assets.mjs +2 -2
- package/dist/runtime/utils/build.d.ts +8 -0
- package/dist/runtime/utils/build.mjs +12 -0
- package/dist/runtime/utils/index.d.ts +2 -1
- package/dist/runtime/utils/index.mjs +2 -1
- package/dist/runtime/utils/{assert.d.ts → path.d.ts} +8 -0
- package/dist/runtime/utils/{assert.mjs → path.mjs} +8 -1
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -47,16 +47,19 @@ At build time the module [collates and serves](#how-it-works) assets and content
|
|
|
47
47
|
|
|
48
48
|
### Features
|
|
49
49
|
|
|
50
|
+
Built on top of [Nuxt Content](https://github.com/nuxt/content/) and compatible with any Nuxt Content project or theme, including [Docus](https://github.com/nuxt-themes/docus).
|
|
51
|
+
|
|
50
52
|
User experience:
|
|
51
53
|
|
|
52
54
|
- co-locate assets with content files
|
|
53
|
-
-
|
|
55
|
+
- reference assets using relative paths
|
|
56
|
+
- supports any format (image, video, doc)
|
|
54
57
|
|
|
55
58
|
Developer experience:
|
|
56
59
|
|
|
57
|
-
- works
|
|
60
|
+
- works with tags and custom components
|
|
58
61
|
- works in markdown and frontmatter
|
|
59
|
-
- file watching and live
|
|
62
|
+
- file watching and asset live-reload
|
|
60
63
|
- image size injection
|
|
61
64
|
- zero config
|
|
62
65
|
|
|
@@ -147,17 +150,23 @@ If you edit an image, video, embed or iframe source, the content will update imm
|
|
|
147
150
|
|
|
148
151
|
### Image sizing
|
|
149
152
|
|
|
150
|
-
|
|
153
|
+
#### HTML
|
|
154
|
+
|
|
155
|
+
The module is [preconfigured](#image-size) to pass image size hints (by default `style`) to generated `<img>` tags:
|
|
151
156
|
|
|
152
157
|
```html
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
>
|
|
158
|
+
<!-- imageSize: 'style' -->
|
|
159
|
+
<img src="/image.jpg" style="aspect-ratio:640/480">
|
|
160
|
+
|
|
161
|
+
<!-- imageSize: 'attrs' -->
|
|
162
|
+
<img src="/image.jpg" width="640" height="480">
|
|
158
163
|
```
|
|
159
164
|
|
|
160
|
-
|
|
165
|
+
Passing image sizes prevents content jumps on page load.
|
|
166
|
+
|
|
167
|
+
#### Prose components
|
|
168
|
+
|
|
169
|
+
If you use [ProseImg](https://content.nuxtjs.org/api/components/prose) components, you can use `imageSize: 'attrs'` to [hook into these values](demo/components/temp/ProseImg.vue) via Vue's `$attrs` property:
|
|
161
170
|
|
|
162
171
|
```vue
|
|
163
172
|
<template>
|
|
@@ -173,12 +182,22 @@ export default {
|
|
|
173
182
|
</script>
|
|
174
183
|
```
|
|
175
184
|
|
|
176
|
-
|
|
185
|
+
#### Frontmatter
|
|
186
|
+
|
|
187
|
+
If you pass [frontmatter](demo/content/advanced/gallery.md) to [custom components](demo/components/content/ContentImage.vue) configure `imageSize` as `'src'` to encode the size in `src`:
|
|
177
188
|
|
|
178
189
|
```
|
|
179
|
-
:image-
|
|
190
|
+
:image-content{:src="image"}
|
|
180
191
|
```
|
|
181
192
|
|
|
193
|
+
The component will receive the updated path which you can parse and implement as you see fit.
|
|
194
|
+
|
|
195
|
+
```html
|
|
196
|
+
<img class="image-content" src="/image.jpg?width=640&height=480">
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
See demo component [here](demo/components/content/ContentImage.vue).
|
|
200
|
+
|
|
182
201
|
## Configuration
|
|
183
202
|
|
|
184
203
|
The module can be configured in your Nuxt configuration file:
|
|
@@ -205,19 +224,19 @@ You can add one or more image size hints to the generated images:
|
|
|
205
224
|
|
|
206
225
|
```ts
|
|
207
226
|
{
|
|
208
|
-
imageSize: 'attrs
|
|
227
|
+
imageSize: 'style attrs src'
|
|
209
228
|
}
|
|
210
229
|
```
|
|
211
230
|
|
|
212
231
|
Pick from the following switches:
|
|
213
232
|
|
|
214
|
-
| Switch | What it does
|
|
215
|
-
|
|
216
|
-
| `style` | Adds `style="aspect-ratio:..."` to any `<img>` tag
|
|
217
|
-
| `attrs` | Adds `width` and `height` attributes to any `<img>` tag
|
|
218
|
-
| `
|
|
233
|
+
| Switch | What it does |
|
|
234
|
+
| ------- | ------------------------------------------------------------ |
|
|
235
|
+
| `style` | Adds `style="aspect-ratio:..."` to any `<img>` tag |
|
|
236
|
+
| `attrs` | Adds `width` and `height` attributes to any `<img>` tag |
|
|
237
|
+
| `src` | Adds `?width=...&height=...` to `src` attribute (frontmatter only) |
|
|
219
238
|
|
|
220
|
-
Note: if you add `attrs`
|
|
239
|
+
Note: if you add *only* `attrs` include the following CSS in your app:
|
|
221
240
|
|
|
222
241
|
```css
|
|
223
242
|
img {
|
|
@@ -226,6 +245,8 @@ img {
|
|
|
226
245
|
}
|
|
227
246
|
```
|
|
228
247
|
|
|
248
|
+
To disable, pass `false`.
|
|
249
|
+
|
|
229
250
|
### Content extensions
|
|
230
251
|
|
|
231
252
|
This setting tells Nuxt Content to ignore anything that is **not** one of these file extensions:
|
package/dist/module.d.ts
CHANGED
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -51,6 +51,9 @@ function getIgnores(extensions2) {
|
|
|
51
51
|
return `^((?!(${matchTokens(extensions2).join("|")})).)*$`;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
function removeQuery(path) {
|
|
55
|
+
return path.replace(/\?.*$/, "");
|
|
56
|
+
}
|
|
54
57
|
function isExcluded(path) {
|
|
55
58
|
return path.split("/").some((segment) => segment.startsWith(".") || segment.startsWith("_"));
|
|
56
59
|
}
|
|
@@ -59,7 +62,7 @@ function isImage(path) {
|
|
|
59
62
|
return extensions.image.includes(ext);
|
|
60
63
|
}
|
|
61
64
|
function isArticle(path) {
|
|
62
|
-
return path.endsWith(".md");
|
|
65
|
+
return removeQuery(path).endsWith(".md");
|
|
63
66
|
}
|
|
64
67
|
function isAsset(path) {
|
|
65
68
|
return !isArticle(path);
|
|
@@ -131,8 +134,8 @@ function getAssetSizes(srcAbs, hints) {
|
|
|
131
134
|
if (hints.includes("style")) {
|
|
132
135
|
ratio = `${size.width}/${size.height}`;
|
|
133
136
|
}
|
|
134
|
-
if (hints.includes("url")) {
|
|
135
|
-
query =
|
|
137
|
+
if (hints.includes("src") || hints.includes("url")) {
|
|
138
|
+
query = `width=${size.width}&height=${size.height}`;
|
|
136
139
|
}
|
|
137
140
|
} catch (err) {
|
|
138
141
|
warn(`could not read image "${srcAbs}`);
|
package/dist/runtime/plugin.mjs
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import Path from "path";
|
|
2
2
|
import { visit, SKIP, CONTINUE } from "unist-util-visit";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
buildStyle,
|
|
5
|
+
deKey,
|
|
6
|
+
isValidAsset,
|
|
7
|
+
list,
|
|
8
|
+
matchTokens,
|
|
9
|
+
toPath,
|
|
10
|
+
walk,
|
|
11
|
+
removeQuery,
|
|
12
|
+
buildQuery,
|
|
13
|
+
parseQuery
|
|
14
|
+
} from "./utils/index.mjs";
|
|
4
15
|
import { debug, cachePath } from "#nuxt-content-assets";
|
|
5
16
|
import { makeStorage } from "./services/index.mjs";
|
|
6
17
|
async function updateAssets() {
|
|
@@ -51,10 +62,11 @@ const plugin = async (nitro) => {
|
|
|
51
62
|
const filter = (value, key) => !(String(key).startsWith("_") || key === "body");
|
|
52
63
|
walk(file, (value, parent, key) => {
|
|
53
64
|
if (isValidAsset(value)) {
|
|
54
|
-
const { srcAttr, query } = getAsset(value);
|
|
65
|
+
const { srcAttr, query } = getAsset(removeQuery(value));
|
|
55
66
|
if (srcAttr) {
|
|
56
|
-
|
|
57
|
-
|
|
67
|
+
const srcUrl = query ? buildQuery(srcAttr, parseQuery(value), query) : srcAttr;
|
|
68
|
+
parent[key] = srcUrl;
|
|
69
|
+
updated.push(`meta: ${key} to "${srcUrl}"`);
|
|
58
70
|
}
|
|
59
71
|
}
|
|
60
72
|
}, filter);
|
|
@@ -82,7 +94,7 @@ const plugin = async (nitro) => {
|
|
|
82
94
|
}
|
|
83
95
|
if (ratio) {
|
|
84
96
|
if (typeof node.props.style === "string") {
|
|
85
|
-
node.props.style
|
|
97
|
+
node.props.style = buildStyle(node.props.style, `aspect-ratio: ${ratio}`);
|
|
86
98
|
} else {
|
|
87
99
|
node.props.style ||= {};
|
|
88
100
|
node.props.style.aspectRatio = ratio;
|
|
@@ -22,7 +22,7 @@ export declare function getAssetPaths(srcDir: string, srcAbs: string): {
|
|
|
22
22
|
* Get asset image sizes
|
|
23
23
|
*
|
|
24
24
|
* @param srcAbs The absolute path to the asset itself
|
|
25
|
-
* @param hints A list of named image size hints,
|
|
25
|
+
* @param hints A list of named image size hints, one of 'attrs', 'style', or 'src'
|
|
26
26
|
*/
|
|
27
27
|
export declare function getAssetSizes(srcAbs: string, hints: string[]): {
|
|
28
28
|
width: number | undefined;
|
|
@@ -26,8 +26,8 @@ export function getAssetSizes(srcAbs, hints) {
|
|
|
26
26
|
if (hints.includes("style")) {
|
|
27
27
|
ratio = `${size.width}/${size.height}`;
|
|
28
28
|
}
|
|
29
|
-
if (hints.includes("url")) {
|
|
30
|
-
query =
|
|
29
|
+
if (hints.includes("src") || hints.includes("url")) {
|
|
30
|
+
query = `width=${size.width}&height=${size.height}`;
|
|
31
31
|
}
|
|
32
32
|
} catch (err) {
|
|
33
33
|
warn(`could not read image "${srcAbs}`);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a style string by passing multiple independent expressions
|
|
3
|
+
*/
|
|
4
|
+
export declare function buildStyle(...expr: string[]): string;
|
|
5
|
+
/**
|
|
6
|
+
* Build a query string by passing multiple independent expressions
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildQuery(...expr: string[]): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function buildStyle(...expr) {
|
|
2
|
+
return expr.map((expr2) => expr2.replace(/^[; ]+|[; ]+$/g, "")).filter((s) => s).join(";").replace(/\s*;\s*/g, "; ") + ";";
|
|
3
|
+
}
|
|
4
|
+
export function buildQuery(...expr) {
|
|
5
|
+
const output = expr.map((expr2) => expr2.replace(/^[?&]+|&+$/g, "")).filter((s) => s);
|
|
6
|
+
if (output.length) {
|
|
7
|
+
const [first, ...rest] = output;
|
|
8
|
+
const isParam = (expr2) => /^[^?]+=[^=]+$/.test(expr2);
|
|
9
|
+
return !isParam(first) ? rest.length > 0 ? first + (first.includes("?") ? "&" : "?") + rest.join("&") : first : "?" + output.join("&");
|
|
10
|
+
}
|
|
11
|
+
return "";
|
|
12
|
+
}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses the query string from a path
|
|
3
|
+
*/
|
|
4
|
+
export declare function parseQuery(path: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Removes the query string from a path
|
|
7
|
+
*/
|
|
8
|
+
export declare function removeQuery(path: string): string;
|
|
1
9
|
/**
|
|
2
10
|
* Test path to be relative
|
|
3
11
|
*/
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import Path from "path";
|
|
2
2
|
import { extensions } from "../options.mjs";
|
|
3
|
+
export function parseQuery(path) {
|
|
4
|
+
const matches = path.match(/\?.+$/);
|
|
5
|
+
return matches ? matches[0] : "";
|
|
6
|
+
}
|
|
7
|
+
export function removeQuery(path) {
|
|
8
|
+
return path.replace(/\?.*$/, "");
|
|
9
|
+
}
|
|
3
10
|
export function isRelative(path) {
|
|
4
11
|
return !(path.startsWith("http") || Path.isAbsolute(path));
|
|
5
12
|
}
|
|
@@ -11,7 +18,7 @@ export function isImage(path) {
|
|
|
11
18
|
return extensions.image.includes(ext);
|
|
12
19
|
}
|
|
13
20
|
export function isArticle(path) {
|
|
14
|
-
return path.endsWith(".md");
|
|
21
|
+
return removeQuery(path).endsWith(".md");
|
|
15
22
|
}
|
|
16
23
|
export function isAsset(path) {
|
|
17
24
|
return !isArticle(path);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-content-assets",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Enable locally-located assets in Nuxt Content",
|
|
5
5
|
"repository": "davestewart/nuxt-content-assets",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@nuxt/kit": "^3.3.2",
|
|
35
35
|
"debounce": "^1.2.1",
|
|
36
|
-
"glob": "^9.3.2",
|
|
37
36
|
"image-size": "^1.0.2",
|
|
38
37
|
"listhen": "^1.0.4",
|
|
39
38
|
"ohash": "^1.0.0",
|