nuxt-content-assets 0.7.0 → 0.9.0-beta

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/dist/module.mjs CHANGED
@@ -1,33 +1,45 @@
1
1
  import * as Fs from 'fs';
2
2
  import * as Path from 'path';
3
3
  import Path__default from 'path';
4
- import { createResolver, defineNuxtModule, addTemplate } from '@nuxt/kit';
4
+ import { useNuxt, createResolver, defineNuxtModule, addPlugin } from '@nuxt/kit';
5
+ import debounce from 'debounce';
5
6
  import getImageSize from 'image-size';
6
- import { hash } from 'ohash';
7
- import glob from 'glob';
8
7
  import { createStorage } from 'unstorage';
9
8
  import githubDriver from 'unstorage/drivers/github';
9
+ import fsDriver from 'unstorage/drivers/fs';
10
+ import { hash } from 'ohash';
11
+ import { listen } from 'listhen';
12
+ import { WebSocketServer, WebSocket } from 'ws';
10
13
 
11
14
  function matchWords(value) {
12
15
  return typeof value === "string" ? value.match(/\w+/g) || [] : [];
13
16
  }
17
+ function toPath(key) {
18
+ return key.replaceAll(":", "/");
19
+ }
20
+ function deKey(path) {
21
+ return path.replace(/^[^:]+:/, "");
22
+ }
14
23
 
15
- const defaults = {
24
+ const defaults$1 = {
16
25
  assetsDir: "/assets/",
17
26
  assetsPattern: "[path]/[file]"
18
27
  };
19
- const imageExtensions = matchWords("png jpg jpeg gif svg webp ico");
20
- const mediaExtensions = matchWords("mp3 m4a wav mp4 mov webm ogg avi flv avchd");
21
- const fileExtensions = matchWords("pdf doc docx xls xlsx ppt pptx odp key");
22
- const extensions = [
23
- ...imageExtensions,
24
- ...mediaExtensions,
25
- ...fileExtensions
26
- ];
28
+ const extensions = {
29
+ image: matchWords("png jpg jpeg gif svg webp ico"),
30
+ media: matchWords("mp3 m4a wav mp4 mov webm ogg avi flv avchd")
31
+ };
27
32
 
28
33
  function isImage(path) {
29
34
  const ext = Path__default.extname(path).substring(1);
30
- return imageExtensions.includes(ext);
35
+ return extensions.image.includes(ext);
36
+ }
37
+ function isArticle(path) {
38
+ return /\.mdx?$/.test(path);
39
+ }
40
+ function isAsset(path) {
41
+ const ext = Path__default.extname(path);
42
+ return !!ext && ext !== ".DS_Store" && !isArticle(path);
31
43
  }
32
44
 
33
45
  const moduleName = "nuxt-content-assets";
@@ -51,10 +63,18 @@ function writeFile(path, data) {
51
63
  createFolder(Path.dirname(path));
52
64
  Fs.writeFileSync(path, text, { encoding: "utf8" });
53
65
  }
66
+ async function writeBlob(path, data) {
67
+ const buffer = Buffer.from(await data.arrayBuffer());
68
+ createFolder(Path.dirname(path));
69
+ Fs.writeFileSync(path, buffer);
70
+ }
54
71
  function copyFile(src, trg) {
55
72
  createFolder(Path.dirname(trg));
56
73
  Fs.copyFileSync(src, trg);
57
74
  }
75
+ function removeFile(src) {
76
+ Fs.rmSync(src);
77
+ }
58
78
  function createFolder(path) {
59
79
  Fs.mkdirSync(path, { recursive: true });
60
80
  }
@@ -65,6 +85,122 @@ function removeFolder(path) {
65
85
  }
66
86
  }
67
87
 
88
+ function getAssetConfig(srcDir, srcAbs, pattern, hints) {
89
+ let width = void 0;
90
+ let height = void 0;
91
+ let ratio = void 0;
92
+ let query = void 0;
93
+ if (hints.length && isImage(srcAbs)) {
94
+ try {
95
+ const size = getImageSize(srcAbs);
96
+ if (hints.includes("style")) {
97
+ ratio = `${size.width}/${size.height}`;
98
+ }
99
+ if (hints.includes("attrs")) {
100
+ width = size.width;
101
+ height = size.height;
102
+ }
103
+ if (hints.includes("url")) {
104
+ query = `?width=${width}&height=${height}`;
105
+ }
106
+ } catch (err) {
107
+ warn(`could not read image "${srcAbs}`);
108
+ }
109
+ }
110
+ const srcRel = Path.relative(srcDir, srcAbs);
111
+ const srcAttr = "/" + srcRel;
112
+ const id = srcRel.replaceAll("/", ":");
113
+ return { id, srcRel, srcAttr, width, height, ratio, query };
114
+ }
115
+
116
+ function makeStorage(source, key = "") {
117
+ const storage = createStorage();
118
+ const options = typeof source === "string" ? { driver: "fs", base: source } : source;
119
+ switch (options.driver) {
120
+ case "fs":
121
+ storage.mount(key, fsDriver({
122
+ ...options,
123
+ ignore: ["[^:]+?\\.md"]
124
+ }));
125
+ break;
126
+ case "github":
127
+ storage.mount(key, githubDriver({
128
+ branch: "main",
129
+ dir: "/",
130
+ ...options
131
+ }));
132
+ break;
133
+ }
134
+ return storage;
135
+ }
136
+ function makeSourceManager(key, source, publicPath, callback) {
137
+ async function onWatch(event, key2) {
138
+ if (isAsset(key2)) {
139
+ const path = event === "update" ? await copyItem(key2) : removeItem(key2);
140
+ if (callback) {
141
+ callback(event, path);
142
+ }
143
+ }
144
+ }
145
+ function getRelSrc(key2) {
146
+ return toPath(key2).replace(/\w+/, "").replace(source.prefix || "", "");
147
+ }
148
+ function getAbsSrc(key2) {
149
+ return Path.join(source.base, getRelSrc(key2));
150
+ }
151
+ function getRelTrg(key2) {
152
+ return Path.join(source.prefix || "", toPath(deKey(key2)));
153
+ }
154
+ function getAbsTrg(key2) {
155
+ return Path.join(publicPath, getRelTrg(key2));
156
+ }
157
+ function removeItem(key2) {
158
+ const absTrg = getAbsTrg(key2);
159
+ removeFile(absTrg);
160
+ return absTrg;
161
+ }
162
+ async function copyItem(key2) {
163
+ const absTrg = getAbsTrg(key2);
164
+ const driver = source.driver;
165
+ if (driver === "fs") {
166
+ const absSrc = getAbsSrc(key2);
167
+ copyFile(absSrc, absTrg);
168
+ } else if (driver === "github") {
169
+ try {
170
+ const data = await storage.getItem(key2);
171
+ if (data) {
172
+ data?.constructor.name === "Blob" ? await writeBlob(absTrg, data) : writeFile(absTrg, data);
173
+ } else {
174
+ warn(`No data for key "${key2}"`);
175
+ }
176
+ } catch (err) {
177
+ warn(err.message);
178
+ }
179
+ }
180
+ return absTrg;
181
+ }
182
+ async function getKeys() {
183
+ const keys = await storage.getKeys();
184
+ return keys.filter(isAsset);
185
+ }
186
+ async function init() {
187
+ const keys = await getKeys();
188
+ const paths = [];
189
+ for (const key2 of keys) {
190
+ const path = await copyItem(key2);
191
+ paths.push(path);
192
+ }
193
+ return paths;
194
+ }
195
+ const storage = makeStorage(source, key);
196
+ storage.watch(onWatch);
197
+ return {
198
+ storage,
199
+ init,
200
+ keys: getKeys
201
+ };
202
+ }
203
+
68
204
  const replacers = {
69
205
  key: (src) => Path__default.dirname(src).split("/").filter((e) => e).shift() || "",
70
206
  path: (src) => Path__default.dirname(src),
@@ -89,67 +225,107 @@ function interpolatePattern(pattern, src, warn = false) {
89
225
  }));
90
226
  }
91
227
 
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}`;
228
+ function createWebSocket() {
229
+ const wss = new WebSocketServer({ noServer: true });
230
+ const serve = (req, socket = req.socket, head = "") => wss.handleUpgrade(req, socket, head, (client) => wss.emit("connection", client, req));
231
+ const broadcast = (data) => {
232
+ data = JSON.stringify(data);
233
+ for (const client of wss.clients) {
234
+ if (client.readyState === WebSocket.OPEN) {
235
+ client.send(data);
102
236
  }
103
- if (hints.includes("attrs")) {
104
- width = size.width;
105
- height = size.height;
237
+ }
238
+ };
239
+ const handlers = [];
240
+ const addHandler = (callback) => {
241
+ handlers.push(callback);
242
+ };
243
+ wss.on("connection", (socket) => {
244
+ socket.addEventListener("message", (event) => {
245
+ let data;
246
+ try {
247
+ data = JSON.parse(event.data || "{}");
248
+ } catch (err) {
106
249
  }
107
- if (hints.includes("url")) {
108
- query = `?width=${width}&height=${height}`;
250
+ if (data) {
251
+ handlers.forEach((callback) => callback(data));
109
252
  }
110
- } catch (err) {
111
- warn(`could not read image "${srcAbs}`);
253
+ });
254
+ });
255
+ return {
256
+ wss,
257
+ serve,
258
+ broadcast,
259
+ addHandler,
260
+ close: () => {
261
+ wss.clients.forEach((client) => client.close());
262
+ return new Promise((resolve) => wss.close(resolve));
112
263
  }
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 };
264
+ };
118
265
  }
119
266
 
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);
267
+ function isObject(data) {
268
+ return data && typeof data === "object" && !Array.isArray(data);
269
+ }
270
+ function makeChannelBroker(ws2) {
271
+ const handlers = [];
272
+ const broadcast = (channel, data) => {
273
+ ws2.broadcast({ channel, data });
274
+ };
275
+ const addHandler = (channel, callback) => {
276
+ handlers.push({ channel, callback });
277
+ };
278
+ ws2.addHandler(function(message) {
279
+ if (isObject(message)) {
280
+ const { channel } = message;
281
+ handlers.filter((handler) => handler.channel === channel || handler.channel === "*").forEach((handler) => handler.callback(message));
146
282
  }
147
- }
148
- return paths;
283
+ });
284
+ return {
285
+ broadcast,
286
+ addHandler
287
+ };
149
288
  }
150
- function getFsAssets(path, extensions) {
151
- const pattern = `${path}/**/*.{${extensions.join(",")}}`;
152
- return glob.globSync(pattern) || [];
289
+ const ws = createWebSocket();
290
+ const broker = makeChannelBroker(ws);
291
+ const defaults = {
292
+ port: {
293
+ port: 4001,
294
+ portRange: [4001, 4040]
295
+ },
296
+ hostname: "localhost",
297
+ showURL: false
298
+ };
299
+ async function setupSocketServer(channel, handler) {
300
+ const nuxt = useNuxt();
301
+ nuxt.hook("nitro:init", async (nitro) => {
302
+ if (!nuxt._socketServer) {
303
+ const { server, url } = await listen(() => "Nuxt Sockets", defaults);
304
+ nuxt._socketServer = server;
305
+ server.on("upgrade", ws.serve);
306
+ nitro.options.runtimeConfig.public.sockets = {
307
+ wsUrl: url.replace("http", "ws")
308
+ };
309
+ nitro.hooks.hook("close", async () => {
310
+ await ws.close();
311
+ await server.close();
312
+ });
313
+ }
314
+ });
315
+ const instance = {
316
+ send(data) {
317
+ broker.broadcast(channel, data);
318
+ return this;
319
+ },
320
+ addHandler(callback) {
321
+ broker.addHandler(channel, callback);
322
+ return this;
323
+ }
324
+ };
325
+ if (handler) {
326
+ instance.addHandler(handler);
327
+ }
328
+ return instance;
153
329
  }
154
330
 
155
331
  const resolve = createResolver(import.meta.url).resolve;
@@ -162,9 +338,7 @@ const module = defineNuxtModule({
162
338
  }
163
339
  },
164
340
  defaults: {
165
- output: `${defaults.assetsDir}/${defaults.assetsPattern}`,
166
- extensions: "",
167
- additionalExtensions: "",
341
+ output: `${defaults$1.assetsDir}/${defaults$1.assetsPattern}`,
168
342
  imageSize: "",
169
343
  debug: false
170
344
  },
@@ -174,37 +348,22 @@ const module = defineNuxtModule({
174
348
  const buildPath = nuxt.options.buildDir;
175
349
  const cachePath = Path.join(buildPath, "content-assets");
176
350
  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
- };
351
+ const indexPath = Path.join(cachePath, "assets.json");
183
352
  if (options.debug) {
184
353
  log("Removing cache folders...");
185
354
  }
186
355
  removeFolder(Path.join(buildPath, "content-cache"));
187
356
  removeFolder(cachePath);
188
- removeFolder(tempPath);
189
357
  (_a = nuxt.options).content || (_a.content = {});
190
358
  if (nuxt.options.content) {
191
359
  (_b = nuxt.options.content).ignores || (_b.ignores = []);
192
360
  }
193
- const output = options.output || defaults.assetsDir;
361
+ nuxt.options.content?.ignores.push("^((?!(mdx?|json|ya?ml|csv)).)*$");
362
+ const output = options.output || defaults$1.assetsDir;
194
363
  const matches = output.match(/([^[]+)(.*)?/);
195
- const assetsDir = matches ? matches[1].replace(/^\/*/, "/").replace(/\/*$/, "") : defaults.assetsDir;
196
- const assetsPattern = (matches ? matches[2] : "") || defaults.assetsPattern;
364
+ const assetsPattern = (matches ? matches[2] : "") || defaults$1.assetsPattern;
197
365
  interpolatePattern(assetsPattern, "", true);
198
366
  const imageFlags = matchWords(options.imageSize);
199
- if (options.extensions?.trim()) {
200
- extensions.splice(0, extensions.length, ...matchWords(options.extensions));
201
- } else if (options.additionalExtensions) {
202
- extensions.push(...matchWords(options.additionalExtensions));
203
- }
204
- if (options.debug) {
205
- log("Preparing sources...");
206
- }
207
- const assets = {};
208
367
  const sources = nuxt.options._layers.map((layer) => layer.config?.content?.sources).reduce((output2, sources2) => {
209
368
  if (sources2) {
210
369
  Object.assign(output2, sources2);
@@ -220,92 +379,71 @@ const module = defineNuxtModule({
220
379
  };
221
380
  }
222
381
  }
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
- }
382
+ addPlugin(resolve("./runtime/sockets/plugin"));
383
+ const socket = nuxt.options.dev ? await setupSocketServer("content-assets") : null;
384
+ function removeAsset(src) {
385
+ const srcRel = Path.relative(publicPath, src);
386
+ delete assets[srcRel];
387
+ saveAssets();
388
+ return "/" + srcRel;
266
389
  }
267
- nuxt.hook("build:before", function() {
268
- if (options.debug) {
269
- dump("assets", assets);
390
+ function updateAsset(src) {
391
+ const {
392
+ srcRel,
393
+ srcAttr,
394
+ width,
395
+ height,
396
+ ratio,
397
+ query
398
+ } = getAssetConfig(publicPath, src, assetsPattern, imageFlags);
399
+ assets[srcRel] = {
400
+ srcRel,
401
+ srcAttr,
402
+ width,
403
+ height,
404
+ ratio,
405
+ query
406
+ };
407
+ saveAssets();
408
+ return srcAttr;
409
+ }
410
+ function watchAsset(event, absTrg) {
411
+ const src = event === "update" ? updateAsset(absTrg) : removeAsset(absTrg);
412
+ if (socket) {
413
+ socket.send({ event, src });
270
414
  }
415
+ }
416
+ const saveAssets = debounce(() => {
417
+ writeFile(indexPath, assets);
418
+ }, 50);
419
+ const assets = {};
420
+ const managers = {};
421
+ for (const [key, source] of Object.entries(sources)) {
271
422
  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
- }
423
+ log(`Creating source "${key}"`);
283
424
  }
284
- if (options.debug) {
285
- if (copied.length) {
286
- list("Copied", copied);
287
- }
288
- if (failed.length) {
289
- list("Failed to copy", failed);
425
+ managers[key] = makeSourceManager(key, source, publicPath, watchAsset);
426
+ }
427
+ nuxt.hook("build:before", async function() {
428
+ for (const [key, manager] of Object.entries(managers)) {
429
+ const paths = await manager.init();
430
+ paths.forEach((path) => updateAsset(path));
431
+ if (options.debug) {
432
+ list(`Copied "${key}" assets`, paths.map((path) => Path.relative(publicPath, path)));
290
433
  }
291
434
  }
292
435
  });
293
- const nitroAssets = Object.entries(assets).reduce((output2, [key, value]) => {
294
- output2[key] = value.config;
295
- return output2;
296
- }, {});
297
436
  const virtualConfig = [
298
- `export const assets = ${JSON.stringify(nitroAssets, null, " ")}`
437
+ // `export const assets = ${JSON.stringify(assets, null, ' ')}`,
438
+ `export const cachePath = '${cachePath}'`
299
439
  ].join("\n");
300
- nuxt.options.alias[`#${moduleName}`] = addTemplate({
301
- filename: `${moduleName}.mjs`,
302
- getContents: () => virtualConfig
303
- }).dst;
304
440
  nuxt.hook("nitro:config", async (config) => {
305
441
  config.plugins || (config.plugins = []);
306
442
  config.plugins.push(pluginPath);
307
443
  config.virtual || (config.virtual = {});
308
- config.virtual[`#${moduleName}`] = virtualConfig;
444
+ config.virtual[`#${moduleName}`] = () => {
445
+ return virtualConfig;
446
+ };
309
447
  config.publicAssets || (config.publicAssets = []);
310
448
  config.publicAssets.push({
311
449
  dir: publicPath
@@ -2,8 +2,8 @@ export declare const defaults: {
2
2
  assetsDir: string;
3
3
  assetsPattern: string;
4
4
  };
5
- export declare const imageExtensions: string[];
6
- export declare const mediaExtensions: string[];
7
- export declare const fileExtensions: string[];
8
- export declare const extensions: string[];
9
5
  export declare const tags: string[];
6
+ export declare const extensions: {
7
+ image: string[];
8
+ media: string[];
9
+ };
@@ -3,12 +3,8 @@ export const defaults = {
3
3
  assetsDir: "/assets/",
4
4
  assetsPattern: "[path]/[file]"
5
5
  };
6
- export const imageExtensions = matchWords("png jpg jpeg gif svg webp ico");
7
- export const mediaExtensions = matchWords("mp3 m4a wav mp4 mov webm ogg avi flv avchd");
8
- export const fileExtensions = matchWords("pdf doc docx xls xlsx ppt pptx odp key");
9
- export const extensions = [
10
- ...imageExtensions,
11
- ...mediaExtensions,
12
- ...fileExtensions
13
- ];
14
6
  export const tags = ["img", "video", "audio", "source", "embed", "iframe", "a"];
7
+ export const extensions = {
8
+ image: matchWords("png jpg jpeg gif svg webp ico"),
9
+ media: matchWords("mp3 m4a wav mp4 mov webm ogg avi flv avchd")
10
+ };
@@ -1,8 +1,20 @@
1
1
  import Path from "path";
2
2
  import { visit } from "unist-util-visit";
3
- import { isValidAsset, walk } from "./utils/index.mjs";
3
+ import { deKey, isValidAsset, toPath, walk } from "./utils/index.mjs";
4
4
  import { tags } from "./options.mjs";
5
- import { assets } from "#nuxt-content-assets";
5
+ import { cachePath } from "#nuxt-content-assets";
6
+ import { makeStorage } from "./services/index.mjs";
7
+ async function updateAssets() {
8
+ assets = await storage.getItem("assets.json");
9
+ }
10
+ const storage = makeStorage(cachePath);
11
+ storage.watch(async (event, key) => {
12
+ if (event === "update" && key === "assets.json") {
13
+ await updateAssets();
14
+ }
15
+ });
16
+ let assets = {};
17
+ void updateAssets();
6
18
  function getAsset(srcDoc, relAsset) {
7
19
  const srcAsset = Path.join(Path.dirname(srcDoc), relAsset);
8
20
  return assets[srcAsset] || {};
@@ -10,7 +22,7 @@ function getAsset(srcDoc, relAsset) {
10
22
  const plugin = async (nitro) => {
11
23
  nitro.hooks.hook("content:file:afterParse", async (file) => {
12
24
  if (file._id.endsWith(".md")) {
13
- const srcDoc = file._id.split(":").join("/");
25
+ const srcDoc = toPath(deKey(file._id));
14
26
  const filter = (value, key) => !(String(key).startsWith("_") || key === "body");
15
27
  walk(file, (value, parent, key) => {
16
28
  if (isValidAsset(value)) {
@@ -1,5 +1,5 @@
1
1
  export type AssetConfig = {
2
- id: string;
2
+ id?: string;
3
3
  srcRel: string;
4
4
  srcAttr: string;
5
5
  width?: number;
@@ -1,7 +1,6 @@
1
1
  import * as Path from "path";
2
2
  import getImageSize from "image-size";
3
3
  import { isImage, warn } from "../utils/index.mjs";
4
- import { interpolatePattern } from "./paths.mjs";
5
4
  export function getAssetConfig(srcDir, srcAbs, pattern, hints) {
6
5
  let width = void 0;
7
6
  let height = void 0;
@@ -24,8 +23,8 @@ export function getAssetConfig(srcDir, srcAbs, pattern, hints) {
24
23
  warn(`could not read image "${srcAbs}`);
25
24
  }
26
25
  }
27
- const srcRel = Path.basename(srcDir) + srcAbs.substring(srcDir.length);
28
- const srcAttr = interpolatePattern(pattern, srcRel);
26
+ const srcRel = Path.relative(srcDir, srcAbs);
27
+ const srcAttr = "/" + srcRel;
29
28
  const id = srcRel.replaceAll("/", ":");
30
29
  return { id, srcRel, srcAttr, width, height, ratio, query };
31
30
  }
@@ -1,10 +1,22 @@
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 {};
1
+ import { WatchEvent, Storage } from 'unstorage';
2
+ import { MountOptions } from '@nuxt/content';
3
+ /**
4
+ * Make a Storage instance
5
+ */
6
+ export declare function makeStorage(source: MountOptions | string, key?: string): Storage;
7
+ export interface SourceManager {
8
+ storage: Storage;
9
+ init: () => Promise<string[]>;
10
+ keys: () => Promise<string[]>;
11
+ }
12
+ /**
13
+ * Make a SourceManager instance
14
+ *
15
+ * Each Source Manager is responsible for mirroring source files to the public folder
16
+ *
17
+ * @param key
18
+ * @param source
19
+ * @param publicPath
20
+ * @param callback
21
+ */
22
+ export declare function makeSourceManager(key: string, source: MountOptions, publicPath: string, callback?: (event: WatchEvent, path: string) => void): SourceManager;