nuxt-content-assets 0.10.1 → 0.10.2

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 CHANGED
@@ -237,9 +237,9 @@ If you want to see what the module does as it runs, set `debug` to true:
237
237
 
238
238
  When Nuxt builds, the module scans all content sources for assets, copies them to an accessible public assets folder, and indexes path and image metadata.
239
239
 
240
- After Nuxt Content has run the parsed content is traversed, and both element attributes and frontmatter properties are checked to see if they resolve to the indexed asset paths.
240
+ After Nuxt Content has run, the parsed content is traversed, and both element attributes and frontmatter properties are checked to see if they resolve to the indexed asset paths.
241
241
 
242
- If they do, then the attribute or property is rewritten with the absolute path. If the asset is an image, then the element or path is optionally updated with size attributes or size query string.
242
+ If they do, then the attribute or property is rewritten with the absolute path. If the asset is an image, then the element or metadata is optionally updated with size attributes or a query string.
243
243
 
244
244
  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.
245
245
 
package/dist/module.json CHANGED
@@ -4,5 +4,5 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.0.0"
6
6
  },
7
- "version": "0.10.1"
7
+ "version": "0.10.2"
8
8
  }
package/dist/module.mjs CHANGED
@@ -12,10 +12,19 @@ import { listen } from 'listhen';
12
12
  import { WebSocketServer, WebSocket } from 'ws';
13
13
 
14
14
  function matchTokens(value) {
15
- const tokens = typeof value === "string" ? value.match(/[^\s,|]+/g) || [] : Array.isArray(value) ? value.filter((value2) => typeof value2 === "string").reduce((output, input) => {
16
- return [...output, ...matchTokens(input)];
17
- }, []) : [];
18
- return Array.from(new Set(tokens));
15
+ let tokens = [];
16
+ if (typeof value === "string") {
17
+ tokens = value.match(/[^\s,|]+/g) || [];
18
+ } else if (Array.isArray(value)) {
19
+ tokens = value.filter((value2) => typeof value2 === "string").reduce((output, input) => {
20
+ return [...output, ...matchTokens(input)];
21
+ }, []);
22
+ } else if (!!value && typeof value === "object") {
23
+ tokens = Object.values(value).reduce((output, value2) => {
24
+ return [...output, ...matchTokens(value2)];
25
+ }, []);
26
+ }
27
+ return tokens.length ? Array.from(new Set(tokens)) : tokens;
19
28
  }
20
29
  function toPath(key) {
21
30
  return key.replaceAll(":", "/");
@@ -53,17 +62,15 @@ function isArticle(path) {
53
62
  return path.endsWith(".md");
54
63
  }
55
64
  function isAsset(path) {
56
- return !isExcluded(path) && !isArticle(path);
65
+ return !isArticle(path);
57
66
  }
58
67
 
59
- const moduleName = "nuxt-content-assets";
60
- const moduleKey = "contentAssets";
61
-
68
+ const label = "[content-assets]";
62
69
  function log(...data) {
63
- console.info(`[${moduleKey}]`, ...data);
70
+ console.info(label, ...data);
64
71
  }
65
72
  function warn(...data) {
66
- console.warn(`[${moduleKey}]`, ...data);
73
+ console.warn(label, ...data);
67
74
  }
68
75
  function list(message, items) {
69
76
  log(`${message}:
@@ -139,6 +146,10 @@ function getAssetSizes(srcAbs, hints) {
139
146
  };
140
147
  }
141
148
 
149
+ function isAssetId(id) {
150
+ const path = toPath(id);
151
+ return !isExcluded(path) && isAsset(path);
152
+ }
142
153
  function makeStorage(source, key = "") {
143
154
  const storage = createStorage();
144
155
  const options = typeof source === "string" ? { driver: "fs", base: source } : source;
@@ -164,7 +175,7 @@ function makeStorage(source, key = "") {
164
175
  }
165
176
  function makeSourceManager(key, source, publicPath, callback) {
166
177
  async function onWatch(event, key2) {
167
- if (isAsset(toPath(key2))) {
178
+ if (isAssetId(key2)) {
168
179
  const path = event === "update" ? await copyItem(key2) : removeItem(key2);
169
180
  if (callback) {
170
181
  callback(event, path);
@@ -210,7 +221,7 @@ function makeSourceManager(key, source, publicPath, callback) {
210
221
  }
211
222
  async function getKeys() {
212
223
  const keys = await storage.getKeys();
213
- return keys.map(toPath).filter(isAsset);
224
+ return keys.filter(isAssetId);
214
225
  }
215
226
  async function init() {
216
227
  const keys = await getKeys();
@@ -230,6 +241,9 @@ function makeSourceManager(key, source, publicPath, callback) {
230
241
  };
231
242
  }
232
243
 
244
+ const moduleName = "nuxt-content-assets";
245
+ const moduleKey = "contentAssets";
246
+
233
247
  function createWebSocket() {
234
248
  const wss = new WebSocketServer({ noServer: true });
235
249
  const serve = (req, socket = req.socket, head = "") => wss.handleUpgrade(req, socket, head, (client) => wss.emit("connection", client, req));
@@ -422,8 +436,10 @@ const module = defineNuxtModule({
422
436
  }
423
437
  }
424
438
  });
439
+ const makeVar = (name, value) => `export const ${name} = ${JSON.stringify(value)};`;
425
440
  const virtualConfig = [
426
- `export const cachePath = '${cachePath}'`
441
+ makeVar("cachePath", cachePath),
442
+ makeVar("debug", options.debug)
427
443
  ].join("\n");
428
444
  nuxt.hook("nitro:config", async (config) => {
429
445
  config.plugins || (config.plugins = []);
@@ -1,7 +1,7 @@
1
1
  import Path from "path";
2
- import { visit } from "unist-util-visit";
3
- import { deKey, isValidAsset, toPath, walk } from "./utils/index.mjs";
4
- import { cachePath } from "#nuxt-content-assets";
2
+ import { visit, SKIP, CONTINUE } from "unist-util-visit";
3
+ import { deKey, isValidAsset, list, matchTokens, toPath, walk } from "./utils/index.mjs";
4
+ import { debug, cachePath } from "#nuxt-content-assets";
5
5
  import { makeStorage } from "./services/index.mjs";
6
6
  async function updateAssets() {
7
7
  assets = await storage.getItem("assets.json");
@@ -14,30 +14,70 @@ storage.watch(async (event, key) => {
14
14
  });
15
15
  let assets = {};
16
16
  void updateAssets();
17
- function getAsset(srcDoc, relAsset) {
18
- const srcAsset = Path.join(Path.dirname(srcDoc), relAsset);
19
- return assets[srcAsset] || {};
20
- }
17
+ const tags = {
18
+ // unlikely to contain assets
19
+ content: matchTokens({
20
+ container: "pre code code-inline",
21
+ 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",
22
+ headers: "h1 h2 h3 h4 h5 h6",
23
+ controls: "input textarea button select optgroup option label legend datalist output",
24
+ media: "map area canvas svg",
25
+ other: "style script noscript template",
26
+ empty: "hr br"
27
+ }),
28
+ // may contain assets
29
+ props: matchTokens({
30
+ content: "main header footer section article aside details dialog summary data object nav blockquote div span p",
31
+ table: "table caption th tr td thead tbody tfoot col colgroup",
32
+ media: "figcaption figure picture",
33
+ form: "form fieldset",
34
+ list: "ul ol li dir dl dt dd",
35
+ formatting: "strong b em i"
36
+ }),
37
+ // assets
38
+ assets: "a img audio source track video embed"
39
+ };
21
40
  const plugin = async (nitro) => {
22
41
  nitro.hooks.hook("content:file:afterParse", async (file) => {
23
- if (file._id.endsWith(".md")) {
24
- const srcDoc = toPath(deKey(file._id));
42
+ const { _id } = file;
43
+ if (_id.endsWith(".md")) {
44
+ const srcDoc = toPath(deKey(_id));
45
+ const srcDir = Path.dirname(srcDoc);
46
+ const updated = [];
47
+ const getAsset = (relAsset) => {
48
+ const srcAsset = Path.join(srcDir, relAsset);
49
+ return assets[srcAsset] || {};
50
+ };
25
51
  const filter = (value, key) => !(String(key).startsWith("_") || key === "body");
26
52
  walk(file, (value, parent, key) => {
27
53
  if (isValidAsset(value)) {
28
- const { srcAttr, query } = getAsset(srcDoc, value);
54
+ const { srcAttr, query } = getAsset(value);
29
55
  if (srcAttr) {
30
56
  parent[key] = srcAttr + (query || "");
57
+ updated.push(`meta: ${key} to "${srcAttr}"`);
31
58
  }
32
59
  }
33
60
  }, filter);
34
61
  visit(file.body, (node) => node.type === "element", (node) => {
35
- for (const [prop, value] of Object.entries(node.props)) {
62
+ const { tag, props } = node;
63
+ const noContent = tags.content.includes(tag);
64
+ if (noContent) {
65
+ return SKIP;
66
+ }
67
+ const noProps = tags.props.includes(tag);
68
+ if (noProps) {
69
+ return CONTINUE;
70
+ }
71
+ if (!props) {
72
+ return CONTINUE;
73
+ }
74
+ for (const [prop, value] of Object.entries(props)) {
36
75
  if (typeof value !== "string") {
37
76
  return;
38
77
  }
39
- const { srcAttr, width, height, ratio } = getAsset(srcDoc, value);
78
+ const { srcAttr, width, height, ratio } = getAsset(value);
40
79
  if (srcAttr) {
80
+ updated.push(`page: ${tag}[${prop}] to "${srcAttr}"`);
41
81
  node.props[prop] = srcAttr;
42
82
  if (width && height) {
43
83
  node.props.width = width;
@@ -52,6 +92,10 @@ const plugin = async (nitro) => {
52
92
  }
53
93
  }
54
94
  });
95
+ if (debug && updated.length) {
96
+ list(`Processed "/${srcDoc}"`, updated);
97
+ console.log();
98
+ }
55
99
  }
56
100
  });
57
101
  };
@@ -2,7 +2,21 @@ import * as Path from "path";
2
2
  import { createStorage } from "unstorage";
3
3
  import githubDriver from "unstorage/drivers/github";
4
4
  import fsDriver from "unstorage/drivers/fs";
5
- import { warn, isAsset, toPath, removeFile, copyFile, writeBlob, writeFile, deKey } from "../utils/index.mjs";
5
+ import {
6
+ warn,
7
+ isAsset,
8
+ toPath,
9
+ removeFile,
10
+ copyFile,
11
+ writeBlob,
12
+ writeFile,
13
+ deKey,
14
+ isExcluded
15
+ } from "../utils/index.mjs";
16
+ function isAssetId(id) {
17
+ const path = toPath(id);
18
+ return !isExcluded(path) && isAsset(path);
19
+ }
6
20
  export function makeStorage(source, key = "") {
7
21
  const storage = createStorage();
8
22
  const options = typeof source === "string" ? { driver: "fs", base: source } : source;
@@ -28,7 +42,7 @@ export function makeStorage(source, key = "") {
28
42
  }
29
43
  export function makeSourceManager(key, source, publicPath, callback) {
30
44
  async function onWatch(event, key2) {
31
- if (isAsset(toPath(key2))) {
45
+ if (isAssetId(key2)) {
32
46
  const path = event === "update" ? await copyItem(key2) : removeItem(key2);
33
47
  if (callback) {
34
48
  callback(event, path);
@@ -74,7 +88,7 @@ export function makeSourceManager(key, source, publicPath, callback) {
74
88
  }
75
89
  async function getKeys() {
76
90
  const keys = await storage.getKeys();
77
- return keys.map(toPath).filter(isAsset);
91
+ return keys.filter(isAssetId);
78
92
  }
79
93
  async function init() {
80
94
  const keys = await getKeys();
@@ -14,7 +14,7 @@ export function isArticle(path) {
14
14
  return path.endsWith(".md");
15
15
  }
16
16
  export function isAsset(path) {
17
- return !isExcluded(path) && !isArticle(path);
17
+ return !isArticle(path);
18
18
  }
19
19
  export function isValidAsset(value) {
20
20
  return typeof value === "string" && isAsset(value) && isRelative(value);
@@ -1,9 +1,9 @@
1
- import { moduleKey } from "../config.mjs";
1
+ const label = "[content-assets]";
2
2
  export function log(...data) {
3
- console.info(`[${moduleKey}]`, ...data);
3
+ console.info(label, ...data);
4
4
  }
5
5
  export function warn(...data) {
6
- console.warn(`[${moduleKey}]`, ...data);
6
+ console.warn(label, ...data);
7
7
  }
8
8
  export function list(message, items) {
9
9
  log(`${message}:
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Tokens may be separated by space, comma or pipe
5
5
  */
6
- export declare function matchTokens(value?: string | unknown[]): string[];
6
+ export declare function matchTokens(value: any): string[];
7
7
  export declare function toPath(key: string): string;
8
8
  export declare function toKey(path: string): any;
9
9
  export declare function deKey(path: string): string;
@@ -1,8 +1,17 @@
1
1
  export function matchTokens(value) {
2
- const tokens = typeof value === "string" ? value.match(/[^\s,|]+/g) || [] : Array.isArray(value) ? value.filter((value2) => typeof value2 === "string").reduce((output, input) => {
3
- return [...output, ...matchTokens(input)];
4
- }, []) : [];
5
- return Array.from(new Set(tokens));
2
+ let tokens = [];
3
+ if (typeof value === "string") {
4
+ tokens = value.match(/[^\s,|]+/g) || [];
5
+ } else if (Array.isArray(value)) {
6
+ tokens = value.filter((value2) => typeof value2 === "string").reduce((output, input) => {
7
+ return [...output, ...matchTokens(input)];
8
+ }, []);
9
+ } else if (!!value && typeof value === "object") {
10
+ tokens = Object.values(value).reduce((output, value2) => {
11
+ return [...output, ...matchTokens(value2)];
12
+ }, []);
13
+ }
14
+ return tokens.length ? Array.from(new Set(tokens)) : tokens;
6
15
  }
7
16
  export function toPath(key) {
8
17
  return key.replaceAll(":", "/");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-content-assets",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "Enable locally-located assets in Nuxt Content",
5
5
  "repository": "davestewart/nuxt-content-assets",
6
6
  "license": "MIT",