nuxt-content-assets 1.1.1 → 1.2.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 +2 -0
- package/dist/module.d.ts +19 -1
- package/dist/module.json +4 -3
- package/dist/module.mjs +350 -168
- package/dist/runtime/assets/public.d.ts +41 -0
- package/dist/runtime/assets/public.mjs +111 -0
- package/dist/runtime/{services/sources.d.ts → assets/source.d.ts} +4 -4
- package/dist/runtime/{services/sources.mjs → assets/source.mjs} +4 -14
- package/dist/runtime/content/parsed.d.ts +5 -0
- package/dist/runtime/content/parsed.mjs +32 -0
- package/dist/runtime/content/plugin.mjs +65 -0
- package/dist/runtime/sockets/factory.d.ts +5 -1
- package/dist/runtime/sockets/factory.mjs +3 -10
- package/dist/runtime/sockets/plugin.d.ts +3 -0
- package/dist/runtime/sockets/plugin.mjs +31 -8
- package/dist/runtime/sockets/setup.d.ts +1 -1
- package/dist/runtime/sockets/setup.mjs +15 -2
- package/dist/runtime/utils/config.d.ts +11 -0
- package/dist/runtime/utils/config.mjs +12 -0
- package/dist/runtime/utils/content.d.ts +16 -0
- package/dist/runtime/utils/content.mjs +43 -0
- package/dist/runtime/utils/index.d.ts +2 -0
- package/dist/runtime/utils/index.mjs +2 -0
- package/dist/runtime/utils/object.d.ts +7 -3
- package/dist/runtime/utils/object.mjs +5 -2
- package/dist/runtime/utils/path.mjs +1 -1
- package/dist/types.d.ts +1 -5
- package/package.json +2 -4
- package/dist/runtime/config.d.ts +0 -2
- package/dist/runtime/config.mjs +0 -2
- package/dist/runtime/options.d.ts +0 -10
- package/dist/runtime/options.mjs +0 -18
- package/dist/runtime/plugin.mjs +0 -121
- package/dist/runtime/services/assets.d.ts +0 -25
- package/dist/runtime/services/assets.mjs +0 -23
- package/dist/runtime/services/index.d.ts +0 -3
- package/dist/runtime/services/index.mjs +0 -3
- package/dist/runtime/services/paths.d.ts +0 -8
- package/dist/runtime/services/paths.mjs +0 -26
- package/dist/runtime/sockets/composable.d.ts +0 -2
- package/dist/runtime/sockets/composable.mjs +0 -12
- /package/dist/runtime/{plugin.d.ts → content/plugin.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -283,6 +283,8 @@ If they do, then the attribute or property is rewritten with the absolute path.
|
|
|
283
283
|
|
|
284
284
|
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.
|
|
285
285
|
|
|
286
|
+
In development, file watching propagates asset changes to the public folder, updates related cached content, and notifies the browser via web sockets to refresh any loaded images.
|
|
287
|
+
|
|
286
288
|
## Development
|
|
287
289
|
|
|
288
290
|
Should you wish to develop the project, the scripts are:
|
package/dist/module.d.ts
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
2
|
|
|
3
3
|
interface ModuleOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Image size hints
|
|
6
|
+
*
|
|
7
|
+
* @example 'attrs style url'
|
|
8
|
+
* @default 'style'
|
|
9
|
+
*/
|
|
4
10
|
imageSize?: string | string[] | false;
|
|
5
|
-
|
|
11
|
+
/**
|
|
12
|
+
* List of content extensions; anything else as an asset
|
|
13
|
+
*
|
|
14
|
+
* @example 'md'
|
|
15
|
+
* @default 'md csv ya?ml json'
|
|
16
|
+
*/
|
|
17
|
+
contentExtensions?: string | string[];
|
|
18
|
+
/**
|
|
19
|
+
* Display debug messages
|
|
20
|
+
*
|
|
21
|
+
* @example true
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
6
24
|
debug?: boolean;
|
|
7
25
|
}
|
|
8
26
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
|
package/dist/module.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"
|
|
2
|
+
"moduleName": "nuxt-content-assets",
|
|
3
|
+
"moduleKey": "contentAssets",
|
|
4
4
|
"compatibility": {
|
|
5
5
|
"nuxt": "^3.0.0"
|
|
6
6
|
},
|
|
7
|
-
"
|
|
7
|
+
"name": "nuxt-content-assets",
|
|
8
|
+
"version": "1.2.0"
|
|
8
9
|
}
|
package/dist/module.mjs
CHANGED
|
@@ -2,14 +2,15 @@ import * as Fs from 'fs';
|
|
|
2
2
|
import * as Path from 'path';
|
|
3
3
|
import Path__default from 'path';
|
|
4
4
|
import { useNuxt, createResolver, defineNuxtModule, addPlugin } from '@nuxt/kit';
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
5
|
+
import { visit, SKIP, CONTINUE } from 'unist-util-visit';
|
|
6
|
+
import { listen } from 'listhen';
|
|
7
|
+
import { WebSocketServer, WebSocket } from 'ws';
|
|
8
8
|
import githubDriver from 'unstorage/drivers/github';
|
|
9
9
|
import fsDriver from 'unstorage/drivers/fs';
|
|
10
|
+
import { createStorage } from 'unstorage';
|
|
11
|
+
import getImageSize from 'image-size';
|
|
12
|
+
import debounce from 'debounce';
|
|
10
13
|
import 'ohash';
|
|
11
|
-
import { listen } from 'listhen';
|
|
12
|
-
import { WebSocketServer, WebSocket } from 'ws';
|
|
13
14
|
|
|
14
15
|
function matchTokens(value) {
|
|
15
16
|
let tokens = [];
|
|
@@ -33,22 +34,16 @@ function deKey(path) {
|
|
|
33
34
|
return path.replace(/^[^:]+:/, "");
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
const defaults = {
|
|
37
|
-
// inject image size into the rendered html
|
|
38
|
-
imageSize: "style",
|
|
39
|
-
// treat these extensions as content
|
|
40
|
-
contentExtensions: "md csv ya?ml json",
|
|
41
|
-
// output debug messages
|
|
42
|
-
debug: false
|
|
43
|
-
};
|
|
44
37
|
const extensions = {
|
|
45
38
|
// used to get image size
|
|
46
39
|
image: matchTokens("png jpg jpeg gif svg webp ico"),
|
|
47
40
|
// unused for now
|
|
48
41
|
media: matchTokens("mp3 m4a wav mp4 mov webm ogg avi flv avchd")
|
|
49
42
|
};
|
|
50
|
-
function
|
|
51
|
-
|
|
43
|
+
function makeIgnores(extensions2) {
|
|
44
|
+
const matched = matchTokens(extensions2);
|
|
45
|
+
const ignored = matched.join("|");
|
|
46
|
+
return `[^:]+\\.(?!(${ignored})$)`;
|
|
52
47
|
}
|
|
53
48
|
|
|
54
49
|
function removeQuery(path) {
|
|
@@ -68,6 +63,73 @@ function isAsset(path) {
|
|
|
68
63
|
return !isArticle(path);
|
|
69
64
|
}
|
|
70
65
|
|
|
66
|
+
function walk(node, callback, filter) {
|
|
67
|
+
function visit(node2, callback2, parent, key) {
|
|
68
|
+
if (filter) {
|
|
69
|
+
const result = filter(node2, key);
|
|
70
|
+
if (result === false) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (Array.isArray(node2)) {
|
|
75
|
+
node2.forEach((value, index) => {
|
|
76
|
+
visit(value, callback2, node2, index);
|
|
77
|
+
});
|
|
78
|
+
} else if (isObject(node2)) {
|
|
79
|
+
Object.keys(node2).forEach((key2) => {
|
|
80
|
+
visit(node2[key2], callback2, node2, key2);
|
|
81
|
+
});
|
|
82
|
+
} else {
|
|
83
|
+
callback2(node2, parent, key);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
visit(node, callback, { node }, "node");
|
|
87
|
+
}
|
|
88
|
+
function isObject(data) {
|
|
89
|
+
return data && typeof data === "object" && !Array.isArray(data);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function walkMeta(content, callback) {
|
|
93
|
+
walk(content, callback, (value, key) => !(String(key).startsWith("_") || key === "body"));
|
|
94
|
+
}
|
|
95
|
+
function walkBody(content, callback) {
|
|
96
|
+
visit(content.body, (node) => node.type === "element", (node) => {
|
|
97
|
+
const { tag, props } = node;
|
|
98
|
+
const excluded = tags.exclude.includes(tag);
|
|
99
|
+
if (excluded) {
|
|
100
|
+
return SKIP;
|
|
101
|
+
}
|
|
102
|
+
const included = tags.include.includes(tag);
|
|
103
|
+
if (included || !props) {
|
|
104
|
+
return CONTINUE;
|
|
105
|
+
}
|
|
106
|
+
callback(node);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
const tags = {
|
|
110
|
+
// unlikely to contain assets
|
|
111
|
+
exclude: matchTokens({
|
|
112
|
+
container: "pre code code-inline",
|
|
113
|
+
formatting: "acronym abbr address bdi bdo big center cite del dfn font ins kbd mark meter progress q rp rt ruby s samp small strike sub sup time tt u var wbr",
|
|
114
|
+
headers: "h1 h2 h3 h4 h5 h6",
|
|
115
|
+
controls: "input textarea button select optgroup option label legend datalist output",
|
|
116
|
+
media: "map area canvas svg",
|
|
117
|
+
other: "style script noscript template",
|
|
118
|
+
empty: "hr br"
|
|
119
|
+
}),
|
|
120
|
+
// may contain assets
|
|
121
|
+
include: matchTokens({
|
|
122
|
+
content: "main header footer section article aside details dialog summary data object nav blockquote div span p",
|
|
123
|
+
table: "table caption th tr td thead tbody tfoot col colgroup",
|
|
124
|
+
media: "figcaption figure picture",
|
|
125
|
+
form: "form fieldset",
|
|
126
|
+
list: "ul ol li dir dl dt dd",
|
|
127
|
+
formatting: "strong b em i"
|
|
128
|
+
}),
|
|
129
|
+
// assets
|
|
130
|
+
assets: "a img audio source track video embed"
|
|
131
|
+
};
|
|
132
|
+
|
|
71
133
|
const label = "[content-assets]";
|
|
72
134
|
function log(...data) {
|
|
73
135
|
console.info(label, ...data);
|
|
@@ -82,6 +144,20 @@ ${items.map((item) => ` - ${item}`).join("\n")}
|
|
|
82
144
|
`);
|
|
83
145
|
}
|
|
84
146
|
|
|
147
|
+
function buildQuery(...expr) {
|
|
148
|
+
const output = expr.map((expr2) => expr2.replace(/^[?&]+|&+$/g, "")).filter((s) => s);
|
|
149
|
+
if (output.length) {
|
|
150
|
+
const [first, ...rest] = output;
|
|
151
|
+
const isParam = (expr2) => /^[^?]+=[^=]+$/.test(expr2);
|
|
152
|
+
return !isParam(first) ? rest.length > 0 ? first + (first.includes("?") ? "&" : "?") + rest.join("&") : first : "?" + output.join("&");
|
|
153
|
+
}
|
|
154
|
+
return "";
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function readFile(path, asJson = false) {
|
|
158
|
+
const text = Fs.readFileSync(path, { encoding: "utf8" });
|
|
159
|
+
return asJson ? JSON.parse(text) : text;
|
|
160
|
+
}
|
|
85
161
|
function writeFile(path, data) {
|
|
86
162
|
const text = typeof data === "object" ? JSON.stringify(data, null, " ") : String(data);
|
|
87
163
|
createFolder(Path.dirname(path));
|
|
@@ -109,32 +185,117 @@ function removeFolder(path) {
|
|
|
109
185
|
}
|
|
110
186
|
}
|
|
111
187
|
|
|
112
|
-
function
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
const
|
|
188
|
+
function createWebSocket() {
|
|
189
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
190
|
+
const serve = (req, socket = req.socket, head = "") => wss.handleUpgrade(req, socket, head, (client) => wss.emit("connection", client, req));
|
|
191
|
+
const broadcast = (data) => {
|
|
192
|
+
data = JSON.stringify(data);
|
|
193
|
+
for (const client of wss.clients) {
|
|
194
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
195
|
+
client.send(data);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
const handlers = [];
|
|
200
|
+
const addHandler = (callback) => {
|
|
201
|
+
handlers.push(callback);
|
|
202
|
+
};
|
|
203
|
+
wss.on("connection", (socket) => {
|
|
204
|
+
socket.addEventListener("message", (event) => {
|
|
205
|
+
let data;
|
|
206
|
+
try {
|
|
207
|
+
data = JSON.parse(event.data || "{}");
|
|
208
|
+
} catch (err) {
|
|
209
|
+
}
|
|
210
|
+
if (data) {
|
|
211
|
+
handlers.forEach((callback) => callback(data));
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
});
|
|
116
215
|
return {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
216
|
+
wss,
|
|
217
|
+
serve,
|
|
218
|
+
broadcast,
|
|
219
|
+
addHandler,
|
|
220
|
+
close: () => {
|
|
221
|
+
wss.clients.forEach((client) => client.close());
|
|
222
|
+
return new Promise((resolve) => wss.close(resolve));
|
|
223
|
+
}
|
|
120
224
|
};
|
|
121
225
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
226
|
+
|
|
227
|
+
function makeChannelBroker(ws2) {
|
|
228
|
+
const handlers = [];
|
|
229
|
+
const broadcast = (channel, data) => {
|
|
230
|
+
ws2.broadcast({ channel, data });
|
|
231
|
+
};
|
|
232
|
+
const addHandler = (channel, callback) => {
|
|
233
|
+
handlers.push({ channel, callback });
|
|
234
|
+
};
|
|
235
|
+
ws2.addHandler(function(message) {
|
|
236
|
+
if (isObject(message)) {
|
|
237
|
+
const { channel } = message;
|
|
238
|
+
handlers.filter((handler) => handler.channel === channel || handler.channel === "*").forEach((handler) => handler.callback(message));
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
return {
|
|
242
|
+
broadcast,
|
|
243
|
+
addHandler
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const ws = createWebSocket();
|
|
247
|
+
const broker = makeChannelBroker(ws);
|
|
248
|
+
async function setupSocketServer(channel, handler) {
|
|
249
|
+
const nuxt = useNuxt();
|
|
250
|
+
nuxt.hook("nitro:init", async (nitro) => {
|
|
251
|
+
if (!nuxt._socketServer) {
|
|
252
|
+
const defaults = nuxt.options.runtimeConfig.content.watch.ws;
|
|
253
|
+
const port = defaults.port.port;
|
|
254
|
+
const { server, url } = await listen(() => "Nuxt Content Assets", {
|
|
255
|
+
hostname: defaults.hostname,
|
|
256
|
+
port: {
|
|
257
|
+
port: port + 1,
|
|
258
|
+
portRange: [
|
|
259
|
+
port + 1,
|
|
260
|
+
port + 40
|
|
261
|
+
]
|
|
262
|
+
},
|
|
263
|
+
showURL: false
|
|
264
|
+
});
|
|
265
|
+
nuxt._socketServer = server;
|
|
266
|
+
server.on("upgrade", ws.serve);
|
|
267
|
+
const wsUrl = url.replace("http", "ws");
|
|
268
|
+
log(`Websocket listening on "${wsUrl}"`);
|
|
269
|
+
nitro.options.runtimeConfig.public.sockets = {
|
|
270
|
+
wsUrl
|
|
271
|
+
};
|
|
272
|
+
nitro.hooks.hook("close", async () => {
|
|
273
|
+
await ws.close();
|
|
274
|
+
await server.close();
|
|
275
|
+
});
|
|
128
276
|
}
|
|
277
|
+
});
|
|
278
|
+
const instance = {
|
|
279
|
+
send(data) {
|
|
280
|
+
broker.broadcast(channel, data);
|
|
281
|
+
return this;
|
|
282
|
+
},
|
|
283
|
+
addHandler(callback) {
|
|
284
|
+
broker.addHandler(channel, callback);
|
|
285
|
+
return this;
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
if (handler) {
|
|
289
|
+
instance.addHandler(handler);
|
|
129
290
|
}
|
|
130
|
-
return
|
|
291
|
+
return instance;
|
|
131
292
|
}
|
|
132
293
|
|
|
133
294
|
function isAssetId(id) {
|
|
134
295
|
const path = toPath(id);
|
|
135
296
|
return !isExcluded(path) && isAsset(path);
|
|
136
297
|
}
|
|
137
|
-
function
|
|
298
|
+
function makeSourceStorage(source, key = "") {
|
|
138
299
|
const storage = createStorage();
|
|
139
300
|
const options = typeof source === "string" ? { driver: "fs", base: source } : source;
|
|
140
301
|
switch (options.driver) {
|
|
@@ -216,7 +377,7 @@ function makeSourceManager(key, source, publicPath, callback) {
|
|
|
216
377
|
}
|
|
217
378
|
return paths;
|
|
218
379
|
}
|
|
219
|
-
const storage =
|
|
380
|
+
const storage = makeSourceStorage(source, key);
|
|
220
381
|
storage.watch(onWatch);
|
|
221
382
|
return {
|
|
222
383
|
storage,
|
|
@@ -225,141 +386,159 @@ function makeSourceManager(key, source, publicPath, callback) {
|
|
|
225
386
|
};
|
|
226
387
|
}
|
|
227
388
|
|
|
228
|
-
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
const broadcast = (data) => {
|
|
235
|
-
data = JSON.stringify(data);
|
|
236
|
-
for (const client of wss.clients) {
|
|
237
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
238
|
-
client.send(data);
|
|
239
|
-
}
|
|
389
|
+
function makeAssetsManager(publicPath) {
|
|
390
|
+
const indexKey = "assets.json";
|
|
391
|
+
const storage = makeSourceStorage(Path.join(publicPath, ".."));
|
|
392
|
+
storage.watch(async (event, key) => {
|
|
393
|
+
if (event === "update" && key === indexKey) {
|
|
394
|
+
await load();
|
|
240
395
|
}
|
|
241
|
-
};
|
|
242
|
-
const handlers = [];
|
|
243
|
-
const addHandler = (callback) => {
|
|
244
|
-
handlers.push(callback);
|
|
245
|
-
};
|
|
246
|
-
wss.on("connection", (socket) => {
|
|
247
|
-
socket.addEventListener("message", (event) => {
|
|
248
|
-
let data;
|
|
249
|
-
try {
|
|
250
|
-
data = JSON.parse(event.data || "{}");
|
|
251
|
-
} catch (err) {
|
|
252
|
-
}
|
|
253
|
-
if (data) {
|
|
254
|
-
handlers.forEach((callback) => callback(data));
|
|
255
|
-
}
|
|
256
|
-
});
|
|
257
396
|
});
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
397
|
+
const assets = {};
|
|
398
|
+
async function load() {
|
|
399
|
+
const data = await storage.getItem(indexKey);
|
|
400
|
+
Object.assign(assets, data || {});
|
|
401
|
+
}
|
|
402
|
+
const save = debounce(function() {
|
|
403
|
+
storage.setItem(indexKey, assets);
|
|
404
|
+
}, 50);
|
|
405
|
+
function resolveAsset(content, relAsset, registerContent = false) {
|
|
406
|
+
const srcDir = Path.dirname(content._file);
|
|
407
|
+
const srcAsset = Path.join(srcDir, relAsset);
|
|
408
|
+
const asset = assets[srcAsset];
|
|
409
|
+
if (asset && registerContent) {
|
|
410
|
+
const { _id } = content;
|
|
411
|
+
if (!asset.content.includes(_id)) {
|
|
412
|
+
asset.content.push(_id);
|
|
413
|
+
save();
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return asset || {};
|
|
417
|
+
}
|
|
418
|
+
function setAsset(path) {
|
|
419
|
+
const { srcRel, srcAttr } = getAssetPaths(publicPath, path);
|
|
420
|
+
const { width, height } = getAssetSize(path);
|
|
421
|
+
const oldAsset = assets[srcRel];
|
|
422
|
+
const newAsset = {
|
|
423
|
+
srcAttr,
|
|
424
|
+
content: oldAsset?.content || [],
|
|
425
|
+
width,
|
|
426
|
+
height
|
|
427
|
+
};
|
|
428
|
+
assets[srcRel] = newAsset;
|
|
429
|
+
save();
|
|
430
|
+
return newAsset;
|
|
431
|
+
}
|
|
432
|
+
function getAsset(path) {
|
|
433
|
+
const { srcRel } = getAssetPaths(publicPath, path);
|
|
434
|
+
return srcRel ? { ...assets[srcRel] } : void 0;
|
|
435
|
+
}
|
|
436
|
+
function removeAsset(path) {
|
|
437
|
+
const { srcRel } = getAssetPaths(publicPath, path);
|
|
438
|
+
const asset = assets[srcRel];
|
|
439
|
+
if (asset) {
|
|
440
|
+
delete assets[srcRel];
|
|
441
|
+
save();
|
|
266
442
|
}
|
|
443
|
+
return asset;
|
|
444
|
+
}
|
|
445
|
+
void load();
|
|
446
|
+
return {
|
|
447
|
+
setAsset,
|
|
448
|
+
getAsset,
|
|
449
|
+
removeAsset,
|
|
450
|
+
resolveAsset
|
|
267
451
|
};
|
|
268
452
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
function makeChannelBroker(ws2) {
|
|
274
|
-
const handlers = [];
|
|
275
|
-
const broadcast = (channel, data) => {
|
|
276
|
-
ws2.broadcast({ channel, data });
|
|
277
|
-
};
|
|
278
|
-
const addHandler = (channel, callback) => {
|
|
279
|
-
handlers.push({ channel, callback });
|
|
280
|
-
};
|
|
281
|
-
ws2.addHandler(function(message) {
|
|
282
|
-
if (isObject(message)) {
|
|
283
|
-
const { channel } = message;
|
|
284
|
-
handlers.filter((handler) => handler.channel === channel || handler.channel === "*").forEach((handler) => handler.callback(message));
|
|
285
|
-
}
|
|
286
|
-
});
|
|
453
|
+
function getAssetPaths(srcDir, srcAbs) {
|
|
454
|
+
const srcRel = Path.relative(srcDir, srcAbs);
|
|
455
|
+
const srcAttr = "/" + srcRel;
|
|
287
456
|
return {
|
|
288
|
-
|
|
289
|
-
|
|
457
|
+
srcRel,
|
|
458
|
+
srcAttr
|
|
290
459
|
};
|
|
291
460
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
wsUrl
|
|
310
|
-
};
|
|
311
|
-
nitro.hooks.hook("close", async () => {
|
|
312
|
-
await ws.close();
|
|
313
|
-
await server.close();
|
|
314
|
-
});
|
|
461
|
+
function getAssetSize(srcAbs) {
|
|
462
|
+
if (isImage(srcAbs)) {
|
|
463
|
+
try {
|
|
464
|
+
return getImageSize(srcAbs);
|
|
465
|
+
} catch (err) {
|
|
466
|
+
warn(`could not read image "${srcAbs}`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return {};
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function rewriteContent(path, asset) {
|
|
473
|
+
const { parsed } = readFile(path, true);
|
|
474
|
+
const { srcAttr, width, height } = asset;
|
|
475
|
+
walkMeta(parsed, (value, parent, key) => {
|
|
476
|
+
if (value.startsWith(srcAttr)) {
|
|
477
|
+
parent[key] = parent[key].replace(/width=\d+&height=\d+/, `width=${width}&height=${height}`);
|
|
315
478
|
}
|
|
316
479
|
});
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
480
|
+
walkBody(parsed, function(node) {
|
|
481
|
+
const { tag, props } = node;
|
|
482
|
+
if (tag === "img" && props?.src?.startsWith(srcAttr)) {
|
|
483
|
+
props.src = buildQuery(srcAttr, `time=${Date.now()}`);
|
|
484
|
+
if (props.width) {
|
|
485
|
+
props.width = width;
|
|
486
|
+
}
|
|
487
|
+
if (props.height) {
|
|
488
|
+
props.height = height;
|
|
489
|
+
}
|
|
490
|
+
if (props.style) {
|
|
491
|
+
const ratio = `${width}/${height}`;
|
|
492
|
+
if (typeof props.style === "string") {
|
|
493
|
+
props.style = props.style.replace(/aspect-ratio: \d+\/\d+/, `aspect-ratio: ${ratio}`);
|
|
494
|
+
} else if (props.style.aspectRatio) {
|
|
495
|
+
props.style.aspectRatio = ratio;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
325
498
|
}
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
return instance;
|
|
499
|
+
});
|
|
500
|
+
writeFile(path, { module: true, parsed });
|
|
501
|
+
return parsed;
|
|
331
502
|
}
|
|
332
503
|
|
|
333
504
|
const resolve = createResolver(import.meta.url).resolve;
|
|
505
|
+
const meta = {
|
|
506
|
+
moduleName: "nuxt-content-assets",
|
|
507
|
+
moduleKey: "contentAssets",
|
|
508
|
+
compatibility: {
|
|
509
|
+
nuxt: "^3.0.0"
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
const defaults = {
|
|
513
|
+
imageSize: "style",
|
|
514
|
+
contentExtensions: "md csv ya?ml json",
|
|
515
|
+
debug: false
|
|
516
|
+
};
|
|
334
517
|
const module = defineNuxtModule({
|
|
335
|
-
meta
|
|
336
|
-
name: moduleName,
|
|
337
|
-
configKey: moduleKey,
|
|
338
|
-
compatibility: {
|
|
339
|
-
nuxt: "^3.0.0"
|
|
340
|
-
}
|
|
341
|
-
},
|
|
518
|
+
meta,
|
|
342
519
|
defaults,
|
|
343
520
|
async setup(options, nuxt) {
|
|
344
521
|
var _a, _b;
|
|
345
|
-
const pluginPath = resolve("./runtime/plugin");
|
|
346
522
|
const buildPath = nuxt.options.buildDir;
|
|
347
|
-
const
|
|
348
|
-
const publicPath = Path.join(
|
|
349
|
-
const
|
|
523
|
+
const assetsPath = Path.join(buildPath, "content-assets");
|
|
524
|
+
const publicPath = Path.join(assetsPath, "public");
|
|
525
|
+
const contentPath = Path.join(buildPath, "content-cache/parsed");
|
|
350
526
|
if (options.debug) {
|
|
351
527
|
log("Removing cache folders...");
|
|
352
528
|
}
|
|
353
529
|
removeFolder(Path.join(buildPath, "content-cache"));
|
|
354
|
-
removeFolder(
|
|
355
|
-
|
|
356
|
-
if (
|
|
357
|
-
(
|
|
530
|
+
removeFolder(assetsPath);
|
|
531
|
+
const { contentExtensions } = options;
|
|
532
|
+
if (contentExtensions) {
|
|
533
|
+
(_a = nuxt.options).content || (_a.content = {});
|
|
534
|
+
if (nuxt.options.content) {
|
|
535
|
+
(_b = nuxt.options.content).ignores || (_b.ignores = []);
|
|
536
|
+
}
|
|
537
|
+
const ignores = makeIgnores(contentExtensions);
|
|
538
|
+
nuxt.options.content?.ignores.push(ignores);
|
|
358
539
|
}
|
|
359
|
-
const ignores = getIgnores(options.contentExtensions);
|
|
360
|
-
nuxt.options.content?.ignores.push(ignores);
|
|
361
540
|
const imageFlags = matchTokens(options.imageSize);
|
|
362
|
-
const sources = nuxt.options._layers.map((layer) => layer.config?.content?.sources).reduce((output, sources2) => {
|
|
541
|
+
const sources = Array.from(nuxt.options._layers).map((layer) => layer.config?.content?.sources).reduce((output, sources2) => {
|
|
363
542
|
if (sources2) {
|
|
364
543
|
Object.assign(output, sources2);
|
|
365
544
|
}
|
|
@@ -374,31 +553,33 @@ const module = defineNuxtModule({
|
|
|
374
553
|
};
|
|
375
554
|
}
|
|
376
555
|
}
|
|
377
|
-
|
|
378
|
-
const { srcRel, srcAttr } = getAssetPaths(publicPath, src);
|
|
379
|
-
const { width, height } = getAssetSizes(src);
|
|
380
|
-
assets[srcRel] = {
|
|
381
|
-
srcAttr,
|
|
382
|
-
width,
|
|
383
|
-
height
|
|
384
|
-
};
|
|
385
|
-
saveAssets();
|
|
386
|
-
return srcAttr;
|
|
387
|
-
}
|
|
388
|
-
function removeAsset(src) {
|
|
389
|
-
const { srcRel, srcAttr } = getAssetPaths(publicPath, src);
|
|
390
|
-
delete assets[srcRel];
|
|
391
|
-
saveAssets();
|
|
392
|
-
return srcAttr;
|
|
393
|
-
}
|
|
394
|
-
const saveAssets = debounce(() => {
|
|
395
|
-
writeFile(indexPath, assets);
|
|
396
|
-
}, 50);
|
|
397
|
-
const assets = {};
|
|
556
|
+
const assets = makeAssetsManager(publicPath);
|
|
398
557
|
function onAssetChange(event, absTrg) {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
558
|
+
let src = "";
|
|
559
|
+
let width;
|
|
560
|
+
let height;
|
|
561
|
+
if (event === "update") {
|
|
562
|
+
const oldAsset = isImage(absTrg) && imageFlags.length ? assets.getAsset(absTrg) : null;
|
|
563
|
+
const newAsset = assets.setAsset(absTrg);
|
|
564
|
+
width = newAsset.width;
|
|
565
|
+
height = newAsset.height;
|
|
566
|
+
if (oldAsset) {
|
|
567
|
+
if (oldAsset.width !== newAsset.width || oldAsset.height !== newAsset.height) {
|
|
568
|
+
newAsset.content.forEach(async (id) => {
|
|
569
|
+
const path = Path.join(contentPath, toPath(id));
|
|
570
|
+
rewriteContent(path, newAsset);
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
src = newAsset.srcAttr;
|
|
575
|
+
} else {
|
|
576
|
+
const asset = assets.removeAsset(absTrg);
|
|
577
|
+
if (asset) {
|
|
578
|
+
src = asset.srcAttr;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
if (src && socket) {
|
|
582
|
+
socket.send({ event, src, width, height });
|
|
402
583
|
}
|
|
403
584
|
}
|
|
404
585
|
addPlugin(resolve("./runtime/sockets/plugin"));
|
|
@@ -413,15 +594,16 @@ const module = defineNuxtModule({
|
|
|
413
594
|
nuxt.hook("build:before", async function() {
|
|
414
595
|
for (const [key, manager] of Object.entries(managers)) {
|
|
415
596
|
const paths = await manager.init();
|
|
416
|
-
paths.forEach((path) =>
|
|
597
|
+
paths.forEach((path) => assets.setAsset(path));
|
|
417
598
|
if (options.debug) {
|
|
418
599
|
list(`Copied "${key}" assets`, paths.map((path) => Path.relative(publicPath, path)));
|
|
419
600
|
}
|
|
420
601
|
}
|
|
421
602
|
});
|
|
603
|
+
const pluginPath = resolve("./runtime/content/plugin");
|
|
422
604
|
const makeVar = (name, value) => `export const ${name} = ${JSON.stringify(value)};`;
|
|
423
605
|
const virtualConfig = [
|
|
424
|
-
makeVar("
|
|
606
|
+
makeVar("publicPath", publicPath),
|
|
425
607
|
makeVar("imageFlags", imageFlags),
|
|
426
608
|
makeVar("debug", options.debug)
|
|
427
609
|
].join("\n");
|
|
@@ -429,7 +611,7 @@ const module = defineNuxtModule({
|
|
|
429
611
|
config.plugins || (config.plugins = []);
|
|
430
612
|
config.plugins.push(pluginPath);
|
|
431
613
|
config.virtual || (config.virtual = {});
|
|
432
|
-
config.virtual[`#${moduleName}`] = () => {
|
|
614
|
+
config.virtual[`#${meta.moduleName}`] = () => {
|
|
433
615
|
return virtualConfig;
|
|
434
616
|
};
|
|
435
617
|
config.publicAssets || (config.publicAssets = []);
|