rehype-og-card 3.1.13 → 3.1.15

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/index.js CHANGED
@@ -5,9 +5,9 @@ import { restoreBuildCache, restoreOGDataBuildCache, saveBuildCacheFile, saveOGD
5
5
  import { isElement } from "hast-util-is-element";
6
6
  import path from "path";
7
7
  import { visitParents } from "unist-util-visit-parents";
8
- // eslint-disable-next-line no-magic-numbers
8
+ // oxlint-disable-next-line no-magic-numbers
9
9
  const ONE_DAY_MS = 24 * 60 * 60 * 1000;
10
- // eslint-disable-next-line no-magic-numbers
10
+ // oxlint-disable-next-line no-magic-numbers
11
11
  const DEFAULT_CACHE_MAX_AGE_MS = 30 * ONE_DAY_MS;
12
12
  const DEFAULT_OPTIONS = {
13
13
  buildCache: false,
@@ -30,9 +30,8 @@ const DEFAULT_OPTIONS = {
30
30
  * @param options Plugin options.
31
31
  * @returns Transformer function.
32
32
  */
33
- const rehypeOGCard = (options
34
- // eslint-disable-next-line max-lines-per-function, max-statements
35
- ) => {
33
+ // oxlint-disable-next-line max-statements max-lines-per-function
34
+ const rehypeOGCard = (options) => {
36
35
  const mergedOptions = {
37
36
  ...DEFAULT_OPTIONS,
38
37
  ...options
@@ -55,10 +54,10 @@ const rehypeOGCard = (options
55
54
  * Transform function to create OG card from bare links.
56
55
  * @param tree Root node of the HAST tree.
57
56
  */
58
- // eslint-disable-next-line max-lines-per-function
57
+ // oxlint-disable-next-line max-lines-per-function
59
58
  const transform = async (tree) => {
60
59
  const linkCardPromises = [];
61
- // eslint-disable-next-line max-statements, max-lines-per-function
60
+ // oxlint-disable-next-line max-statements, max-lines-per-function
62
61
  visitParents(tree, ["element", "text"], (node, ancestors) => {
63
62
  let anchorNode = null;
64
63
  const isBareLink = node.type === "text" && isValidURL(node.value.trim());
@@ -68,7 +67,7 @@ const rehypeOGCard = (options
68
67
  }
69
68
  else if (mergedOptions.enableSameTextURLConversion && isValidAnchor) {
70
69
  const isSameTextURL =
71
- // eslint-disable-next-line no-magic-numbers
70
+ // oxlint-disable-next-line no-magic-numbers
72
71
  node.children.length === 1 &&
73
72
  node.children[0] &&
74
73
  isTextNode(node.children[0]) &&
@@ -80,7 +79,7 @@ const rehypeOGCard = (options
80
79
  else {
81
80
  return;
82
81
  }
83
- // eslint-disable-next-line no-magic-numbers
82
+ // oxlint-disable-next-line no-magic-numbers
84
83
  const parent = ancestors[ancestors.length - 1];
85
84
  if (!parent)
86
85
  return;
@@ -89,14 +88,14 @@ const rehypeOGCard = (options
89
88
  const shouldSkip = ancestors.some((ancestor) => isElement(ancestor) && ["ul", "ol"].includes(ancestor.tagName));
90
89
  if (shouldSkip)
91
90
  return;
92
- // eslint-disable-next-line no-magic-numbers
91
+ // oxlint-disable-next-line no-magic-numbers
93
92
  const isTheOnlyChild = parent.children.length === 1;
94
93
  if (!isTheOnlyChild)
95
94
  return;
96
95
  const targetURL = new URL(anchorNode.properties.href);
97
96
  if (mergedOptions.excludeDomains.includes(targetURL.hostname))
98
97
  return;
99
- // eslint-disable-next-line jsdoc/require-jsdoc, max-statements, max-lines-per-function
98
+ // oxlint-disable-next-line max-statements max-lines-per-function jsdoc-js/require-jsdoc
100
99
  const linkCardPromise = async () => {
101
100
  let OGData = mergedOptions.buildCache
102
101
  ? await restoreOGDataBuildCache(anchorNode.properties.href, mergedOptions.buildCachePath, mergedOptions.buildCacheMaxAge)
@@ -153,16 +152,16 @@ const rehypeOGCard = (options
153
152
  }
154
153
  const OGCard = createOGCard(OGData, mergedOptions);
155
154
  const { removeParentPTag: shouldRemoveParentPTag } = mergedOptions;
156
- // eslint-disable-next-line no-magic-numbers
155
+ // oxlint-disable-next-line no-magic-numbers
157
156
  const replacementContainer = shouldRemoveParentPTag ? ancestors[ancestors.length - 2] : parent;
158
157
  const replacementTarget = shouldRemoveParentPTag ? parent : node;
159
158
  if (!replacementContainer || !("children" in replacementContainer))
160
159
  return;
161
160
  const index = replacementContainer.children.indexOf(replacementTarget);
162
- // eslint-disable-next-line no-magic-numbers
161
+ // oxlint-disable-next-line no-magic-numbers
163
162
  if (index === -1)
164
163
  return;
165
- // eslint-disable-next-line no-magic-numbers
164
+ // oxlint-disable-next-line no-magic-numbers
166
165
  replacementContainer.children.splice(index, 1, OGCard);
167
166
  };
168
167
  linkCardPromises.push(linkCardPromise());
package/dist/types.d.ts CHANGED
@@ -89,10 +89,10 @@ interface OGCardData {
89
89
  OGImageWidth?: number | undefined;
90
90
  OGImageHeight?: number | undefined;
91
91
  }
92
- declare const cacheIndexSchema: import("arktype/internal/variants/object.ts").ObjectType<{
92
+ declare const parseCacheIndex: import("arktype/internal/variants/object.ts").ObjectType<(In: string) => import("arktype/internal/attributes.ts").To<{
93
93
  [x: string]: {
94
94
  createdAt: number;
95
95
  };
96
- }, {}>;
97
- type CacheIndex = typeof cacheIndexSchema.infer;
98
- export { cacheIndexSchema, type RehypeOGCardOptions, type OGCardData, type CacheIndex };
96
+ }>, {}>;
97
+ type CacheIndex = typeof parseCacheIndex.infer;
98
+ export { parseCacheIndex, type RehypeOGCardOptions, type OGCardData, type CacheIndex };
package/dist/types.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { type } from "arktype";
2
- const cacheIndexSchema = type({
2
+ const parseCacheIndex = type("string.json.parse").to({
3
3
  "[string]": {
4
4
  createdAt: "number"
5
5
  }
6
6
  });
7
- export { cacheIndexSchema };
7
+ export { parseCacheIndex };
@@ -1,5 +1,5 @@
1
- /* eslint-disable max-lines */
2
- import { cacheIndexSchema } from "../types.js";
1
+ /* oxlint-disable max-lines */
2
+ import { parseCacheIndex } from "../types.js";
3
3
  import { checkFileExists, generateFilename } from "./file.js";
4
4
  import fs from "fs/promises";
5
5
  import fsSync from "fs";
@@ -36,10 +36,10 @@ const getCacheIndexLockPath = (directory) => path.join(directory, CACHE_INDEX_LO
36
36
  * @param ms Duration in milliseconds.
37
37
  */
38
38
  const sleepSync = (ms) => {
39
- // eslint-disable-next-line no-magic-numbers
39
+ // oxlint-disable-next-line no-magic-numbers
40
40
  const buffer = new SharedArrayBuffer(4);
41
41
  const view = new Int32Array(buffer);
42
- // eslint-disable-next-line no-magic-numbers
42
+ // oxlint-disable-next-line no-magic-numbers
43
43
  Atomics.wait(view, 0, 0, ms);
44
44
  };
45
45
  /**
@@ -123,8 +123,7 @@ const readCacheIndexSync = (directory) => {
123
123
  const indexPath = getCacheIndexPath(directory);
124
124
  try {
125
125
  const raw = fsSync.readFileSync(indexPath, "utf-8");
126
- const parsed = JSON.parse(raw);
127
- const validated = cacheIndexSchema(parsed);
126
+ const validated = parseCacheIndex(raw);
128
127
  if (validated instanceof type.errors)
129
128
  return {};
130
129
  return validated;
@@ -162,8 +161,7 @@ const readCacheIndex = async (directory) => {
162
161
  return {};
163
162
  try {
164
163
  const raw = await fs.readFile(indexPath, "utf-8");
165
- const parsed = JSON.parse(raw);
166
- const validated = cacheIndexSchema(parsed);
164
+ const validated = parseCacheIndex(raw);
167
165
  if (validated instanceof type.errors)
168
166
  return {};
169
167
  return validated;
@@ -203,7 +201,7 @@ const removeCacheEntrySync = (directory, filename) => {
203
201
  * @param directory Cache directory path.
204
202
  * @param maxAgeMs Cache expiration time in milliseconds.
205
203
  */
206
- // eslint-disable-next-line max-statements, max-lines-per-function
204
+ // oxlint-disable-next-line max-statements, max-lines-per-function
207
205
  const pruneExpiredCacheFilesSync = (directory, maxAgeMs) => {
208
206
  if (maxAgeMs === false)
209
207
  return;
@@ -216,10 +214,10 @@ const pruneExpiredCacheFilesSync = (directory, maxAgeMs) => {
216
214
  const entryPath = path.join(directory, entry.name);
217
215
  if (entry.isDirectory()) {
218
216
  pruneExpiredCacheFilesSync(entryPath, maxAgeMs);
219
- // eslint-disable-next-line no-continue
217
+ // oxlint-disable-next-line no-continue
220
218
  continue;
221
219
  }
222
- // eslint-disable-next-line no-continue
220
+ // oxlint-disable-next-line no-continue
223
221
  if (entry.name === CACHE_INDEX_FILENAME || entry.name === CACHE_INDEX_LOCK_FILENAME)
224
222
  continue;
225
223
  if (entry.name.endsWith(".json")) {
@@ -228,7 +226,7 @@ const pruneExpiredCacheFilesSync = (directory, maxAgeMs) => {
228
226
  const data = JSON.parse(raw);
229
227
  if (typeof data.cachedAt !== "number") {
230
228
  fsSync.rmSync(entryPath, { force: true });
231
- // eslint-disable-next-line no-continue
229
+ // oxlint-disable-next-line no-continue
232
230
  continue;
233
231
  }
234
232
  if (isCacheExpired(data.cachedAt, maxAgeMs)) {
@@ -238,14 +236,14 @@ const pruneExpiredCacheFilesSync = (directory, maxAgeMs) => {
238
236
  catch {
239
237
  fsSync.rmSync(entryPath, { force: true });
240
238
  }
241
- // eslint-disable-next-line no-continue
239
+ // oxlint-disable-next-line no-continue
242
240
  continue;
243
241
  }
244
242
  const cachedAtMs = index[entry.name]?.createdAt;
245
243
  if (typeof cachedAtMs !== "number" || isCacheExpired(cachedAtMs, maxAgeMs)) {
246
244
  removeCacheEntrySync(directory, entry.name);
247
245
  indexUpdated = true;
248
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
246
+ // oxlint-disable-next-line @typescript-eslint/no-dynamic-delete
249
247
  delete index[entry.name];
250
248
  }
251
249
  }
@@ -258,7 +256,7 @@ const pruneExpiredCacheFilesSync = (directory, maxAgeMs) => {
258
256
  * @param serverCachePath Server cache path.
259
257
  * @param buildCachePath Build cache path.
260
258
  */
261
- // eslint-disable-next-line max-statements
259
+ // oxlint-disable-next-line max-statements
262
260
  const saveBuildCacheFile = async (serverCachePath, buildCachePath) => {
263
261
  const serverCacheExists = await checkFileExists(serverCachePath);
264
262
  const buildCacheExists = await checkFileExists(buildCachePath);
@@ -315,9 +313,8 @@ const saveOGDataBuildCache = async (url, OGData, buildCachePath) => {
315
313
  * @param maxAgeMs Cache expiration time in milliseconds.
316
314
  * @returns Restored OG data. If not found, returns `null`.
317
315
  */
318
- const restoreOGDataBuildCache = async (url, buildCachePath, maxAgeMs
319
- // eslint-disable-next-line max-statements
320
- ) => {
316
+ // oxlint-disable-next-line max-statements
317
+ const restoreOGDataBuildCache = async (url, buildCachePath, maxAgeMs) => {
321
318
  const filename = generateFilename(url, false);
322
319
  const savePath = `${path.join(buildCachePath, filename)}.json`;
323
320
  try {
@@ -325,7 +322,6 @@ const restoreOGDataBuildCache = async (url, buildCachePath, maxAgeMs
325
322
  const parsed = JSON.parse(data);
326
323
  if (typeof parsed.cachedAt !== "number") {
327
324
  if (maxAgeMs === false) {
328
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
329
325
  const { cachedAt: __, ...rest } = parsed;
330
326
  return rest;
331
327
  }
@@ -336,7 +332,6 @@ const restoreOGDataBuildCache = async (url, buildCachePath, maxAgeMs
336
332
  await fs.rm(savePath, { force: true });
337
333
  return null;
338
334
  }
339
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
340
335
  const { cachedAt: __, ...rest } = parsed;
341
336
  return rest;
342
337
  }
package/dist/util/file.js CHANGED
@@ -34,7 +34,7 @@ const checkFileExistsSync = (filePath) => {
34
34
  const createDirectorySync = (dir) => {
35
35
  fs.mkdir(dir, { recursive: true }, (error) => {
36
36
  if (error) {
37
- // eslint-disable-next-line no-console
37
+ // oxlint-disable-next-line no-console
38
38
  console.error("[rehype-og-card] Failed to copy files: ", error);
39
39
  }
40
40
  });
@@ -54,7 +54,7 @@ const copyDirectory = (source, destination) => {
54
54
  }
55
55
  fs.cp(source, destination, { recursive: true }, (error) => {
56
56
  if (error) {
57
- // eslint-disable-next-line no-console
57
+ // oxlint-disable-next-line no-console
58
58
  console.error("[rehype-og-card] Failed to copy files: ", error);
59
59
  }
60
60
  });
package/dist/util/hast.js CHANGED
@@ -58,7 +58,7 @@ const createOGCard = (data, options) => {
58
58
  data.OGImageURL
59
59
  ? h("div.og-card-image-container", [
60
60
  h("img.og-card-image", {
61
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
61
+ // oxlint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
62
62
  alt: data.OGImageAlt || data.OGImageURL,
63
63
  decoding: options.decoding,
64
64
  height: data.OGImageHeight,
@@ -21,11 +21,11 @@ const isValidURL = (url) => {
21
21
  * @returns Resolved absolute URL or `undefined` if the raw URL is invalid.
22
22
  */
23
23
  const resolveAbsoluteURL = (rawURL, baseURL) => {
24
- // eslint-disable-next-line no-undefined
24
+ // oxlint-disable-next-line no-undefined
25
25
  if (!rawURL)
26
26
  return undefined;
27
27
  const parsedUrl = URL.parse(rawURL, baseURL);
28
- // eslint-disable-next-line no-undefined
28
+ // oxlint-disable-next-line no-undefined
29
29
  return parsedUrl ? parsedUrl.href : undefined;
30
30
  };
31
31
  /**
@@ -56,13 +56,13 @@ const getOGData = async (url, userAgent) => {
56
56
  description: result.ogDescription,
57
57
  displayURL: url,
58
58
  faviconURL,
59
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
59
+ // oxlint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
60
60
  title: result.ogTitle || url,
61
61
  url
62
62
  };
63
63
  }
64
64
  catch (error) {
65
- // eslint-disable-next-line no-console
65
+ // oxlint-disable-next-line no-console
66
66
  console.error("[rehype-og-card] Error fetching OG data:", error);
67
67
  return null;
68
68
  }
@@ -72,10 +72,10 @@ const getOGData = async (url, userAgent) => {
72
72
  * @param options Options to download image.
73
73
  * @returns Filename of the downloaded image.
74
74
  */
75
- // eslint-disable-next-line max-statements, max-lines-per-function
75
+ // oxlint-disable-next-line max-statements, max-lines-per-function
76
76
  const downloadImage = async (options) => {
77
77
  if (!isValidURL(options.url)) {
78
- // eslint-disable-next-line no-console
78
+ // oxlint-disable-next-line no-console
79
79
  console.error("[rehype-og-card] Invalid thumbnail URL:", options.url);
80
80
  return null;
81
81
  }
@@ -94,7 +94,7 @@ const downloadImage = async (options) => {
94
94
  if (typeof cachedAt === "number" && !isCacheExpired(cachedAt, maxAge))
95
95
  return filename;
96
96
  if (typeof entry !== "undefined") {
97
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
97
+ // oxlint-disable-next-line @typescript-eslint/no-dynamic-delete
98
98
  delete index[filename];
99
99
  await writeCacheIndex(options.directory, index);
100
100
  }
@@ -104,7 +104,7 @@ const downloadImage = async (options) => {
104
104
  headers: {
105
105
  "user-agent": options.userAgent
106
106
  },
107
- // eslint-disable-next-line no-magic-numbers
107
+ // oxlint-disable-next-line no-magic-numbers
108
108
  signal: AbortSignal.timeout(10 * 1000)
109
109
  });
110
110
  if (!response.ok)
@@ -112,7 +112,7 @@ const downloadImage = async (options) => {
112
112
  const contentType = response.headers.get("content-type");
113
113
  const normalizedContentType = contentType?.split(";")[0]?.trim().toLowerCase();
114
114
  if (!normalizedContentType?.startsWith("image/")) {
115
- // eslint-disable-next-line no-console
115
+ // oxlint-disable-next-line no-console
116
116
  console.error("[rehype-og-card] Invalid image content type:", contentType ?? "unknown", "for", options.url);
117
117
  return null;
118
118
  }
@@ -130,7 +130,7 @@ const downloadImage = async (options) => {
130
130
  return filename;
131
131
  }
132
132
  catch (error) {
133
- // eslint-disable-next-line no-console
133
+ // oxlint-disable-next-line no-console
134
134
  console.error("[rehype-og-card] Error downloading image:", error);
135
135
  return null;
136
136
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rehype-og-card",
3
- "version": "3.1.13",
3
+ "version": "3.1.15",
4
4
  "description": "Rehype plugin to convert text links to link cards",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -12,11 +12,11 @@
12
12
  "provenance": true
13
13
  },
14
14
  "scripts": {
15
- "test": "npx vitest",
16
- "lint": "npx eslint ./src/**/*.ts",
17
- "format": "npx prettier --write ./src/**/*",
18
- "format:check": "npx prettier --check ./src/**/*",
19
- "build": "npx tsc",
15
+ "test": "vitest",
16
+ "lint": "oxlint ./src",
17
+ "format": "prettier --write ./src/**/*",
18
+ "format:check": "prettier --check ./src/**/*",
19
+ "build": "tsc",
20
20
  "version": "npm run build && git add .",
21
21
  "ci:version": "changeset version && npm run version",
22
22
  "ci:publish": "npm run build && changeset publish"
@@ -40,20 +40,20 @@
40
40
  },
41
41
  "homepage": "https://github.com/Robot-Inventor/rehype-og-card#readme",
42
42
  "devDependencies": {
43
- "@changesets/changelog-github": "^0.7.0",
44
- "@changesets/cli": "^2.31.1",
45
- "@robot-inventor/eslint-config": "^13.0.0",
46
- "@robot-inventor/tsconfig-base": "^7.1.0",
47
- "@types/node": "^25.9.5",
48
- "eslint": "^10.7.0",
43
+ "@changesets/changelog-github": "^1.0.1",
44
+ "@changesets/cli": "^3.0.3",
45
+ "@robot-inventor/oxlint-config": "^0.2.0",
46
+ "@robot-inventor/tsconfig-base": "^7.2.0",
47
+ "@types/node": "^25.9.6",
49
48
  "hast-util-to-html": "^9.0.5",
49
+ "oxlint": "^1.83.0",
50
50
  "prettier": "^3.9.6",
51
51
  "rehype-stringify": "^10.0.1",
52
52
  "remark-parse": "^11.0.0",
53
53
  "remark-rehype": "^11.1.2",
54
- "typescript": "^6.0.3",
54
+ "typescript": "^7.0.2",
55
55
  "unified": "^11.0.5",
56
- "vitest": "^4.1.10"
56
+ "vitest": "^5.0.0"
57
57
  },
58
58
  "dependencies": {
59
59
  "@types/hast": "^3.0.5",
@@ -63,8 +63,5 @@
63
63
  "node-fetch": "^3.3.2",
64
64
  "open-graph-scraper": "^6.12.0",
65
65
  "unist-util-visit-parents": "^6.0.2"
66
- },
67
- "overrides": {
68
- "zod-validation-error": "^5.0.0"
69
66
  }
70
67
  }