astro-opengraph-images 1.18.0-dev.9990 → 1.19.0-dev.10928
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/CHANGELOG.md +7 -0
- package/README.md +9 -10
- package/dist/hook.d.ts +3 -2
- package/dist/hook.d.ts.map +1 -1
- package/dist/hook.js +12 -3
- package/dist/hook.js.map +1 -1
- package/dist/hook.test.d.ts +2 -0
- package/dist/hook.test.d.ts.map +1 -0
- package/dist/hook.test.js +217 -0
- package/dist/hook.test.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integration.d.ts +1 -1
- package/dist/integration.d.ts.map +1 -1
- package/dist/integration.js +2 -1
- package/dist/integration.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/hook.test.ts +277 -0
- package/src/hook.ts +17 -1
- package/src/index.ts +2 -0
- package/src/integration.ts +2 -0
- package/src/types.ts +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.19.0](https://github.com/shepherdjerred/monorepo/compare/astro-opengraph-images-v1.18.0...astro-opengraph-images-v1.19.0) (2026-08-23)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **astro-opengraph-images:** add early path filtering ([#2331](https://github.com/shepherdjerred/monorepo/issues/2331)) ([63bbab7](https://github.com/shepherdjerred/monorepo/commit/63bbab7ed1deb40db3628b63a314dc82af524a5e))
|
|
9
|
+
|
|
3
10
|
## [1.18.0](https://github.com/shepherdjerred/monorepo/compare/astro-opengraph-images-v1.17.4...astro-opengraph-images-v1.18.0) (2026-08-03)
|
|
4
11
|
|
|
5
12
|
|
package/README.md
CHANGED
|
@@ -215,9 +215,9 @@ If you're using this project, [open a PR](https://github.com/shepherdjerred/mono
|
|
|
215
215
|
|
|
216
216
|
## Filtering Pages
|
|
217
217
|
|
|
218
|
-
By default, this integration generates an Open Graph image for every page in your build output. Pass an optional `
|
|
218
|
+
By default, this integration generates an Open Graph image for every page in your build output. Pass an optional `pathFilter` callback to skip pages before their output files are read — for example, the 404 page, utility routes, or sections where images don't apply.
|
|
219
219
|
|
|
220
|
-
The callback receives the
|
|
220
|
+
The `pathFilter` callback receives the page pathname. Return `true` to continue processing the page and `false` to skip it. The callback may be synchronous or return a `Promise<boolean>`.
|
|
221
221
|
|
|
222
222
|
```diff
|
|
223
223
|
import opengraphImages, { presets } from "astro-opengraph-images";
|
|
@@ -228,7 +228,7 @@ The callback receives the same `RenderFunctionInput` as your renderer (pathname,
|
|
|
228
228
|
options: { fonts: [/* ... */] },
|
|
229
229
|
render: presets.blackAndWhite,
|
|
230
230
|
+ // Only generate images for blog posts
|
|
231
|
-
+
|
|
231
|
+
+ pathFilter: ({ pathname }) => pathname.startsWith("/blog/"),
|
|
232
232
|
}),
|
|
233
233
|
],
|
|
234
234
|
});
|
|
@@ -237,16 +237,15 @@ The callback receives the same `RenderFunctionInput` as your renderer (pathname,
|
|
|
237
237
|
More examples:
|
|
238
238
|
|
|
239
239
|
```typescript
|
|
240
|
-
// Exclude utility pages
|
|
241
|
-
|
|
240
|
+
// Exclude utility pages before their HTML is read
|
|
241
|
+
pathFilter: ({ pathname }) => !["/404/", "/"].includes(pathname);
|
|
242
242
|
|
|
243
|
-
// Filter on DOM content
|
|
244
|
-
filter: async ({ document,
|
|
245
|
-
document.querySelector(
|
|
246
|
-
pathname.startsWith("/blog/");
|
|
243
|
+
// Filter on DOM content after Open Graph metadata has been extracted
|
|
244
|
+
filter: async ({ document, type }) =>
|
|
245
|
+
type === "article" && document.querySelector("article") !== null;
|
|
247
246
|
```
|
|
248
247
|
|
|
249
|
-
When `verbose: true` is set on `options`, skipped pages are logged.
|
|
248
|
+
Use `pathFilter` when excluded pages may not have the required Open Graph metadata. The metadata-aware `filter` runs only after the output HTML is read, parsed, and strictly extracted, so it is never called for a page missing any of these required tags: `og:title`, `og:url`, `og:type`, or `og:image`. A missing required tag fails the build before `filter` can return `false`. When `verbose: true` is set on `options`, skipped pages are logged.
|
|
250
249
|
|
|
251
250
|
## Custom Renderers
|
|
252
251
|
|
package/dist/hook.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { AstroBuildDoneHookInput, FilterFunction, IntegrationOptions, RenderFunction } from "./types.ts";
|
|
2
|
-
export declare function buildDoneHook({ logger, pages, options, dir, render, filter, }: AstroBuildDoneHookInput & {
|
|
1
|
+
import type { AstroBuildDoneHookInput, FilterFunction, IntegrationOptions, PathFilterFunction, RenderFunction } from "./types.ts";
|
|
2
|
+
export declare function buildDoneHook({ logger, pages, options, dir, render, filter, pathFilter, }: AstroBuildDoneHookInput & {
|
|
3
3
|
options: IntegrationOptions;
|
|
4
4
|
render: RenderFunction;
|
|
5
5
|
filter: FilterFunction | undefined;
|
|
6
|
+
pathFilter: PathFilterFunction | undefined;
|
|
6
7
|
}): Promise<void>;
|
|
7
8
|
//# sourceMappingURL=hook.d.ts.map
|
package/dist/hook.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,uBAAuB,EACvB,cAAc,EACd,kBAAkB,EAElB,cAAc,EACf,MAAM,YAAY,CAAC;AASpB,wBAAsB,aAAa,CAAC,EAClC,MAAM,EACN,KAAK,EACL,OAAO,EACP,GAAG,EACH,MAAM,EACN,MAAM,
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,uBAAuB,EACvB,cAAc,EACd,kBAAkB,EAElB,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AASpB,wBAAsB,aAAa,CAAC,EAClC,MAAM,EACN,KAAK,EACL,OAAO,EACP,GAAG,EACH,MAAM,EACN,MAAM,EACN,UAAU,GACX,EAAE,uBAAuB,GAAG;IAC3B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,cAAc,GAAG,SAAS,CAAC;IACnC,UAAU,EAAE,kBAAkB,GAAG,SAAS,CAAC;CAC5C,iBAMA"}
|
package/dist/hook.js
CHANGED
|
@@ -6,12 +6,21 @@ import { getFilePath } from "./util.js";
|
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import * as jsdom from "jsdom";
|
|
8
8
|
import path from "node:path";
|
|
9
|
-
export async function buildDoneHook({ logger, pages, options, dir, render, filter, }) {
|
|
9
|
+
export async function buildDoneHook({ logger, pages, options, dir, render, filter, pathFilter, }) {
|
|
10
10
|
logger.info("Generating Open Graph images");
|
|
11
|
-
const promises = pages.map((page) => handlePage({ page, options, render, dir, logger, filter }));
|
|
11
|
+
const promises = pages.map((page) => handlePage({ page, options, render, dir, logger, filter, pathFilter }));
|
|
12
12
|
await Promise.all(promises);
|
|
13
13
|
}
|
|
14
|
-
async function handlePage({ page, options, render, dir, logger, filter, }) {
|
|
14
|
+
async function handlePage({ page, options, render, dir, logger, filter, pathFilter, }) {
|
|
15
|
+
if (pathFilter) {
|
|
16
|
+
const shouldRender = await pathFilter(page);
|
|
17
|
+
if (!shouldRender) {
|
|
18
|
+
if (options.verbose) {
|
|
19
|
+
logger.info(`Skipping page ${page.pathname}.`);
|
|
20
|
+
}
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
15
24
|
// gets the absolute path to the HTML file. E.g. /home/user/project/dist/blog/index.html
|
|
16
25
|
// fileURLToPath() converts the URL to a file path. Without it, the path would start with a leading slash on Windows
|
|
17
26
|
// systems, resulting in an invalid path.
|
package/dist/hook.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook.js","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,MAAM,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"hook.js","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.test.d.ts","sourceRoot":"","sources":["../src/hook.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { access, mkdir, mkdtemp, readFile, rm, writeFile, } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { createElement } from "react";
|
|
6
|
+
import { expect, test } from "vitest";
|
|
7
|
+
import { buildDoneHook } from "./hook.js";
|
|
8
|
+
import { astroOpenGraphImages } from "./integration.js";
|
|
9
|
+
class TestLogger {
|
|
10
|
+
options = {
|
|
11
|
+
destination: {
|
|
12
|
+
write: (message) => {
|
|
13
|
+
void message;
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
level: "silent",
|
|
17
|
+
};
|
|
18
|
+
label = "test";
|
|
19
|
+
fork(_label) {
|
|
20
|
+
return new TestLogger();
|
|
21
|
+
}
|
|
22
|
+
info(message) {
|
|
23
|
+
void message;
|
|
24
|
+
}
|
|
25
|
+
warn(message) {
|
|
26
|
+
void message;
|
|
27
|
+
}
|
|
28
|
+
error(message) {
|
|
29
|
+
void message;
|
|
30
|
+
}
|
|
31
|
+
debug(message) {
|
|
32
|
+
void message;
|
|
33
|
+
}
|
|
34
|
+
flush() {
|
|
35
|
+
void this.label;
|
|
36
|
+
}
|
|
37
|
+
close() {
|
|
38
|
+
void this.label;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
test("an async path filter skips a page before reading its output", async () => {
|
|
42
|
+
const outputDir = await createTempDir();
|
|
43
|
+
let pathFilterCalls = 0;
|
|
44
|
+
let filterCalls = 0;
|
|
45
|
+
let renderCalls = 0;
|
|
46
|
+
const pathFilter = async ({ pathname }) => {
|
|
47
|
+
pathFilterCalls += 1;
|
|
48
|
+
await Promise.resolve();
|
|
49
|
+
return pathname !== "/excluded/";
|
|
50
|
+
};
|
|
51
|
+
const filter = ({ pathname }) => {
|
|
52
|
+
filterCalls += 1;
|
|
53
|
+
return pathname !== "/excluded/";
|
|
54
|
+
};
|
|
55
|
+
const render = () => {
|
|
56
|
+
renderCalls += 1;
|
|
57
|
+
return null;
|
|
58
|
+
};
|
|
59
|
+
const integration = astroOpenGraphImages({
|
|
60
|
+
options: { fonts: testOptions.fonts },
|
|
61
|
+
render,
|
|
62
|
+
filter,
|
|
63
|
+
pathFilter,
|
|
64
|
+
});
|
|
65
|
+
const hook = integration.hooks["astro:build:done"];
|
|
66
|
+
if (hook === undefined) {
|
|
67
|
+
throw new Error("Expected astro:build:done hook");
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
await expect(hook({
|
|
71
|
+
pages: [{ pathname: "/excluded/" }],
|
|
72
|
+
dir: pathToFileURL(`${outputDir}/`),
|
|
73
|
+
assets: new Map(),
|
|
74
|
+
logger: new TestLogger(),
|
|
75
|
+
})).resolves.toBeUndefined();
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
await rm(outputDir, { force: true, recursive: true });
|
|
79
|
+
}
|
|
80
|
+
expect(pathFilterCalls).toBe(1);
|
|
81
|
+
expect(filterCalls).toBe(0);
|
|
82
|
+
expect(renderCalls).toBe(0);
|
|
83
|
+
});
|
|
84
|
+
test("a path-filtered-in page still requires Open Graph metadata", async () => {
|
|
85
|
+
const outputDir = await createOutputDir("accepted", "<html></html>");
|
|
86
|
+
let filterCalls = 0;
|
|
87
|
+
const pathFilter = alwaysPathFilter;
|
|
88
|
+
const filter = () => {
|
|
89
|
+
filterCalls += 1;
|
|
90
|
+
return true;
|
|
91
|
+
};
|
|
92
|
+
const render = emptyRender;
|
|
93
|
+
try {
|
|
94
|
+
await expect(buildDoneHook({
|
|
95
|
+
pages: [{ pathname: "/accepted/" }],
|
|
96
|
+
dir: pathToFileURL(`${outputDir}/`),
|
|
97
|
+
assets: new Map(),
|
|
98
|
+
logger: new TestLogger(),
|
|
99
|
+
options: testOptions,
|
|
100
|
+
render,
|
|
101
|
+
filter,
|
|
102
|
+
pathFilter,
|
|
103
|
+
})).rejects.toThrow("Missing required meta tags");
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
await rm(outputDir, { force: true, recursive: true });
|
|
107
|
+
}
|
|
108
|
+
expect(filterCalls).toBe(0);
|
|
109
|
+
});
|
|
110
|
+
test("an accepted page with Open Graph metadata renders an image", async () => {
|
|
111
|
+
const outputDir = await createOutputDir("rendered", `<!doctype html>
|
|
112
|
+
<html>
|
|
113
|
+
<head>
|
|
114
|
+
<meta property="og:title" content="Rendered page" />
|
|
115
|
+
<meta property="og:url" content="http://example.com/rendered/" />
|
|
116
|
+
<meta property="og:type" content="website" />
|
|
117
|
+
<meta property="og:image" content="http://example.com/rendered/index.png" />
|
|
118
|
+
</head>
|
|
119
|
+
</html>`);
|
|
120
|
+
let filterCalls = 0;
|
|
121
|
+
let renderCalls = 0;
|
|
122
|
+
const pathFilter = alwaysPathFilter;
|
|
123
|
+
const filter = ({ pathname }) => {
|
|
124
|
+
filterCalls += 1;
|
|
125
|
+
return pathname === "/rendered/";
|
|
126
|
+
};
|
|
127
|
+
const render = () => {
|
|
128
|
+
renderCalls += 1;
|
|
129
|
+
return createElement("div");
|
|
130
|
+
};
|
|
131
|
+
try {
|
|
132
|
+
await expect(buildDoneHook({
|
|
133
|
+
pages: [{ pathname: "/rendered/" }],
|
|
134
|
+
dir: pathToFileURL(`${outputDir}/`),
|
|
135
|
+
assets: new Map(),
|
|
136
|
+
logger: new TestLogger(),
|
|
137
|
+
options: testOptions,
|
|
138
|
+
render,
|
|
139
|
+
filter,
|
|
140
|
+
pathFilter,
|
|
141
|
+
})).resolves.toBeUndefined();
|
|
142
|
+
await access(path.join(outputDir, "rendered", "index.png"));
|
|
143
|
+
}
|
|
144
|
+
finally {
|
|
145
|
+
await rm(outputDir, { force: true, recursive: true });
|
|
146
|
+
}
|
|
147
|
+
expect(filterCalls).toBe(1);
|
|
148
|
+
expect(renderCalls).toBe(1);
|
|
149
|
+
});
|
|
150
|
+
test("the metadata-aware filter can skip a valid page", async () => {
|
|
151
|
+
const outputDir = await createOutputDir("metadata-skipped", renderedPageHtml("metadata-skipped"));
|
|
152
|
+
let filterCalls = 0;
|
|
153
|
+
let renderCalls = 0;
|
|
154
|
+
const pathFilter = alwaysPathFilter;
|
|
155
|
+
const filter = ({ title }) => {
|
|
156
|
+
filterCalls += 1;
|
|
157
|
+
expect(title).toBe("Rendered page");
|
|
158
|
+
return false;
|
|
159
|
+
};
|
|
160
|
+
const render = () => {
|
|
161
|
+
renderCalls += 1;
|
|
162
|
+
return createElement("div");
|
|
163
|
+
};
|
|
164
|
+
try {
|
|
165
|
+
await expect(buildDoneHook({
|
|
166
|
+
pages: [{ pathname: "/metadata-skipped/" }],
|
|
167
|
+
dir: pathToFileURL(`${outputDir}/`),
|
|
168
|
+
assets: new Map(),
|
|
169
|
+
logger: new TestLogger(),
|
|
170
|
+
options: testOptions,
|
|
171
|
+
render,
|
|
172
|
+
filter,
|
|
173
|
+
pathFilter,
|
|
174
|
+
})).resolves.toBeUndefined();
|
|
175
|
+
await expect(access(path.join(outputDir, "metadata-skipped", "index.png"))).rejects.toThrow();
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
await rm(outputDir, { force: true, recursive: true });
|
|
179
|
+
}
|
|
180
|
+
expect(filterCalls).toBe(1);
|
|
181
|
+
expect(renderCalls).toBe(0);
|
|
182
|
+
});
|
|
183
|
+
const testOptions = {
|
|
184
|
+
width: 1200,
|
|
185
|
+
height: 630,
|
|
186
|
+
verbose: false,
|
|
187
|
+
fonts: [
|
|
188
|
+
{
|
|
189
|
+
data: await readFile(path.join(import.meta.dirname, "../node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff")),
|
|
190
|
+
name: "Roboto",
|
|
191
|
+
weight: 400,
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
};
|
|
195
|
+
const alwaysPathFilter = () => true;
|
|
196
|
+
const emptyRender = () => null;
|
|
197
|
+
async function createOutputDir(page, html = renderedPageHtml(page)) {
|
|
198
|
+
const outputDir = await createTempDir();
|
|
199
|
+
await mkdir(path.join(outputDir, page), { recursive: true });
|
|
200
|
+
await writeFile(path.join(outputDir, page, "index.html"), html);
|
|
201
|
+
return outputDir;
|
|
202
|
+
}
|
|
203
|
+
async function createTempDir() {
|
|
204
|
+
return await mkdtemp(path.join(tmpdir(), "astro-opengraph-images-"));
|
|
205
|
+
}
|
|
206
|
+
function renderedPageHtml(page) {
|
|
207
|
+
return `<!doctype html>
|
|
208
|
+
<html>
|
|
209
|
+
<head>
|
|
210
|
+
<meta property="og:title" content="Rendered page" />
|
|
211
|
+
<meta property="og:url" content="http://example.com/${page}/" />
|
|
212
|
+
<meta property="og:type" content="website" />
|
|
213
|
+
<meta property="og:image" content="http://example.com/${page}/index.png" />
|
|
214
|
+
</head>
|
|
215
|
+
</html>`;
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=hook.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.test.js","sourceRoot":"","sources":["../src/hook.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getImagePath as importedGetImagePath } from "./util.ts";
|
|
2
2
|
import { astroOpenGraphImages } from "./integration.ts";
|
|
3
|
-
import type { IntegrationInput as _IntegrationInput, IntegrationDefaults as _IntegrationDefaults, PartialIntegrationOptions as _PartialIntegrationOptions, IntegrationOptions as _IntegrationOptions, Page as _Page, AstroBuildDoneHookInput as _AstroBuildDoneHookInput, RenderFunctionInput as _RenderFunctionInput, RenderFunction as _RenderFunction, FilterFunction as _FilterFunction, PageDetails as _PageDetails, SatoriWeight as _SatoriWeight, SatoriFontStyle as _SatoriFontStyle, SatoriFontOptions as _SatoriFontOptions, SatoriOptions as _SatoriOptions } from "./types.ts";
|
|
3
|
+
import type { IntegrationInput as _IntegrationInput, IntegrationDefaults as _IntegrationDefaults, PartialIntegrationOptions as _PartialIntegrationOptions, IntegrationOptions as _IntegrationOptions, Page as _Page, AstroBuildDoneHookInput as _AstroBuildDoneHookInput, RenderFunctionInput as _RenderFunctionInput, RenderFunction as _RenderFunction, FilterFunction as _FilterFunction, PathFilterFunction as _PathFilterFunction, PageDetails as _PageDetails, SatoriWeight as _SatoriWeight, SatoriFontStyle as _SatoriFontStyle, SatoriFontOptions as _SatoriFontOptions, SatoriOptions as _SatoriOptions } from "./types.ts";
|
|
4
4
|
export declare const presets: {
|
|
5
5
|
blackAndWhite: typeof import("./presets/black-and-white.tsx").blackAndWhite;
|
|
6
6
|
gradients: typeof import("./presets/gradients.tsx").gradients;
|
|
@@ -25,6 +25,7 @@ export type AstroBuildDoneHookInput = _AstroBuildDoneHookInput;
|
|
|
25
25
|
export type RenderFunctionInput = _RenderFunctionInput;
|
|
26
26
|
export type RenderFunction = _RenderFunction;
|
|
27
27
|
export type FilterFunction = _FilterFunction;
|
|
28
|
+
export type PathFilterFunction = _PathFilterFunction;
|
|
28
29
|
export type PageDetails = _PageDetails;
|
|
29
30
|
export type SatoriWeight = _SatoriWeight;
|
|
30
31
|
export type SatoriFontStyle = _SatoriFontStyle;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,IAAI,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EACV,gBAAgB,IAAI,iBAAiB,EACrC,mBAAmB,IAAI,oBAAoB,EAC3C,yBAAyB,IAAI,0BAA0B,EACvD,kBAAkB,IAAI,mBAAmB,EACzC,IAAI,IAAI,KAAK,EACb,uBAAuB,IAAI,wBAAwB,EACnD,mBAAmB,IAAI,oBAAoB,EAC3C,cAAc,IAAI,eAAe,EACjC,cAAc,IAAI,eAAe,EACjC,WAAW,IAAI,YAAY,EAC3B,YAAY,IAAI,aAAa,EAC7B,eAAe,IAAI,gBAAgB,EACnC,iBAAiB,IAAI,kBAAkB,EACvC,aAAa,IAAI,cAAc,EAChC,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,OAAO;;;;;;;;;;;;CAAkB,CAAC;AACvC,eAAO,MAAM,YAAY,6BAAuB,CAAC;eAClC,oBAAoB;AAEnC,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AACjD,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAAC;AACvD,MAAM,MAAM,yBAAyB,GAAG,0BAA0B,CAAC;AACnE,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AACrD,MAAM,MAAM,IAAI,GAAG,KAAK,CAAC;AACzB,MAAM,MAAM,uBAAuB,GAAG,wBAAwB,CAAC;AAC/D,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAAC;AACvD,MAAM,MAAM,cAAc,GAAG,eAAe,CAAC;AAC7C,MAAM,MAAM,cAAc,GAAG,eAAe,CAAC;AAC7C,MAAM,MAAM,WAAW,GAAG,YAAY,CAAC;AACvC,MAAM,MAAM,YAAY,GAAG,aAAa,CAAC;AACzC,MAAM,MAAM,eAAe,GAAG,gBAAgB,CAAC;AAC/C,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AACnD,MAAM,MAAM,aAAa,GAAG,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,IAAI,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EACV,gBAAgB,IAAI,iBAAiB,EACrC,mBAAmB,IAAI,oBAAoB,EAC3C,yBAAyB,IAAI,0BAA0B,EACvD,kBAAkB,IAAI,mBAAmB,EACzC,IAAI,IAAI,KAAK,EACb,uBAAuB,IAAI,wBAAwB,EACnD,mBAAmB,IAAI,oBAAoB,EAC3C,cAAc,IAAI,eAAe,EACjC,cAAc,IAAI,eAAe,EACjC,kBAAkB,IAAI,mBAAmB,EACzC,WAAW,IAAI,YAAY,EAC3B,YAAY,IAAI,aAAa,EAC7B,eAAe,IAAI,gBAAgB,EACnC,iBAAiB,IAAI,kBAAkB,EACvC,aAAa,IAAI,cAAc,EAChC,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,OAAO;;;;;;;;;;;;CAAkB,CAAC;AACvC,eAAO,MAAM,YAAY,6BAAuB,CAAC;eAClC,oBAAoB;AAEnC,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AACjD,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAAC;AACvD,MAAM,MAAM,yBAAyB,GAAG,0BAA0B,CAAC;AACnE,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AACrD,MAAM,MAAM,IAAI,GAAG,KAAK,CAAC;AACzB,MAAM,MAAM,uBAAuB,GAAG,wBAAwB,CAAC;AAC/D,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAAC;AACvD,MAAM,MAAM,cAAc,GAAG,eAAe,CAAC;AAC7C,MAAM,MAAM,cAAc,GAAG,eAAe,CAAC;AAC7C,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG,YAAY,CAAC;AACvC,MAAM,MAAM,YAAY,GAAG,aAAa,CAAC;AACzC,MAAM,MAAM,eAAe,GAAG,gBAAgB,CAAC;AAC/C,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AACnD,MAAM,MAAM,aAAa,GAAG,cAAc,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,YAAY,IAAI,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,YAAY,IAAI,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAmBxD,MAAM,CAAC,MAAM,OAAO,GAAG,eAAe,CAAC;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,oBAAoB,CAAC;AACjD,eAAe,oBAAoB,CAAC"}
|
package/dist/integration.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { AstroIntegration } from "astro";
|
|
2
2
|
import type { IntegrationInput } from "./types.ts";
|
|
3
|
-
export declare function astroOpenGraphImages({ options, render, filter, }: IntegrationInput): AstroIntegration;
|
|
3
|
+
export declare function astroOpenGraphImages({ options, render, filter, pathFilter, }: IntegrationInput): AstroIntegration;
|
|
4
4
|
//# sourceMappingURL=integration.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../src/integration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,KAAK,EAGV,gBAAgB,EAEjB,MAAM,YAAY,CAAC;AASpB,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACP,MAAM,EACN,MAAM,
|
|
1
|
+
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../src/integration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,KAAK,EAGV,gBAAgB,EAEjB,MAAM,YAAY,CAAC;AASpB,wBAAgB,oBAAoB,CAAC,EACnC,OAAO,EACP,MAAM,EACN,MAAM,EACN,UAAU,GACX,EAAE,gBAAgB,GAAG,gBAAgB,CAiBrC"}
|
package/dist/integration.js
CHANGED
|
@@ -4,7 +4,7 @@ const defaults = {
|
|
|
4
4
|
height: 630,
|
|
5
5
|
verbose: false,
|
|
6
6
|
};
|
|
7
|
-
export function astroOpenGraphImages({ options, render, filter, }) {
|
|
7
|
+
export function astroOpenGraphImages({ options, render, filter, pathFilter, }) {
|
|
8
8
|
const optionsWithDefaults = { ...defaults, ...options };
|
|
9
9
|
return {
|
|
10
10
|
name: "astro-opengraph-images",
|
|
@@ -15,6 +15,7 @@ export function astroOpenGraphImages({ options, render, filter, }) {
|
|
|
15
15
|
options: optionsWithDefaults,
|
|
16
16
|
render,
|
|
17
17
|
filter,
|
|
18
|
+
pathFilter,
|
|
18
19
|
});
|
|
19
20
|
},
|
|
20
21
|
},
|
package/dist/integration.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.js","sourceRoot":"","sources":["../src/integration.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,QAAQ,GAAwB;IACpC,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,KAAK;CACf,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,EACnC,OAAO,EACP,MAAM,EACN,MAAM,
|
|
1
|
+
{"version":3,"file":"integration.js","sourceRoot":"","sources":["../src/integration.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,QAAQ,GAAwB;IACpC,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,KAAK;CACf,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,EACnC,OAAO,EACP,MAAM,EACN,MAAM,EACN,UAAU,GACO;IACjB,MAAM,mBAAmB,GAAuB,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,EAAE,CAAC;IAE5E,OAAO;QACL,IAAI,EAAE,wBAAwB;QAC9B,KAAK,EAAE;YACL,kBAAkB,EAAE,KAAK,EAAE,KAA8B,EAAE,EAAE;gBAC3D,OAAO,aAAa,CAAC;oBACnB,GAAG,KAAK;oBACR,OAAO,EAAE,mBAAmB;oBAC5B,MAAM;oBACN,MAAM;oBACN,UAAU;iBACX,CAAC,CAAC;YACL,CAAC;SACF;KACF,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export type IntegrationInput = {
|
|
|
4
4
|
options: PartialIntegrationOptions;
|
|
5
5
|
render: RenderFunction;
|
|
6
6
|
filter?: FilterFunction;
|
|
7
|
+
pathFilter?: PathFilterFunction;
|
|
7
8
|
};
|
|
8
9
|
/** When applied to PartialIntegrationOptions this type equals IntegrationOptions */
|
|
9
10
|
export type IntegrationDefaults = {
|
|
@@ -25,6 +26,8 @@ export type IntegrationOptions = PartialIntegrationOptions & IntegrationDefaults
|
|
|
25
26
|
export type Page = {
|
|
26
27
|
pathname: string;
|
|
27
28
|
};
|
|
29
|
+
/** A function that filters pages before their output files are read */
|
|
30
|
+
export type PathFilterFunction = (input: Page) => Promise<boolean> | boolean;
|
|
28
31
|
/** The input Astro passes to the build done hook */
|
|
29
32
|
export type AstroBuildDoneHookInput = Parameters<BaseIntegrationHooks["astro:build:done"]>[0];
|
|
30
33
|
/** The input arguments to a `RenderFunction` */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,yBAAyB,CAAC;IACnC,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"url": "https://github.com/shepherdjerred/monorepo/issues"
|
|
18
18
|
},
|
|
19
19
|
"type": "module",
|
|
20
|
-
"version": "1.
|
|
20
|
+
"version": "1.19.0-dev.10928",
|
|
21
21
|
"imports": {
|
|
22
22
|
"#src/*": "./src/*"
|
|
23
23
|
},
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"lint": "eslint src --cache",
|
|
26
26
|
"build": "PATH=node_modules/@typescript/native/bin:$PATH tsc",
|
|
27
27
|
"watch": "PATH=node_modules/@typescript/native/bin:$PATH tsc -w",
|
|
28
|
-
"test": "vitest src",
|
|
28
|
+
"test": "bun --no-install --bun vitest --config ../../vitest.config.ts run src",
|
|
29
29
|
"typecheck": "PATH=node_modules/@typescript/native/bin:$PATH tsc --noEmit",
|
|
30
30
|
"publish:npm": "bun ../../scripts/publish-npm.ts .",
|
|
31
31
|
"test:ci": "bun ../../scripts/run-ci-test.ts",
|
|
@@ -72,17 +72,17 @@
|
|
|
72
72
|
"@shepherdjerred/eslint-config": "0.3.0",
|
|
73
73
|
"@tsconfig/node24": "^24.0.4",
|
|
74
74
|
"@tsconfig/strictest": "^2.0.8",
|
|
75
|
-
"@types/bun": "
|
|
76
|
-
"@types/jsdom": "^
|
|
75
|
+
"@types/bun": "1.4.0",
|
|
76
|
+
"@types/jsdom": "^30.0.0",
|
|
77
77
|
"@types/node": "^26.1.1",
|
|
78
|
-
"@types/react": "^19.2.
|
|
78
|
+
"@types/react": "^19.2.18",
|
|
79
79
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
80
80
|
"astro": "^7.1.5",
|
|
81
81
|
"eslint": "^10.3.0",
|
|
82
82
|
"jiti": "^2.7.0",
|
|
83
83
|
"typescript": "^6.0.3",
|
|
84
|
-
"vitest": "
|
|
85
|
-
"@vitest/coverage-istanbul": "4.1.
|
|
84
|
+
"vitest": "4.1.10",
|
|
85
|
+
"@vitest/coverage-istanbul": "4.1.10"
|
|
86
86
|
},
|
|
87
87
|
"files": [
|
|
88
88
|
"dist",
|
package/src/hook.test.ts
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import type { AstroIntegrationLogger } from "astro";
|
|
2
|
+
import {
|
|
3
|
+
access,
|
|
4
|
+
mkdir,
|
|
5
|
+
mkdtemp,
|
|
6
|
+
readFile,
|
|
7
|
+
rm,
|
|
8
|
+
writeFile,
|
|
9
|
+
} from "node:fs/promises";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
import { pathToFileURL } from "node:url";
|
|
13
|
+
import { createElement } from "react";
|
|
14
|
+
import { expect, test } from "vitest";
|
|
15
|
+
import { buildDoneHook } from "./hook.ts";
|
|
16
|
+
import { astroOpenGraphImages } from "./integration.ts";
|
|
17
|
+
import type {
|
|
18
|
+
FilterFunction,
|
|
19
|
+
IntegrationOptions,
|
|
20
|
+
PathFilterFunction,
|
|
21
|
+
RenderFunction,
|
|
22
|
+
} from "./types.ts";
|
|
23
|
+
|
|
24
|
+
class TestLogger implements AstroIntegrationLogger {
|
|
25
|
+
readonly options = {
|
|
26
|
+
destination: {
|
|
27
|
+
write: (message: unknown) => {
|
|
28
|
+
void message;
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
level: "silent" as const,
|
|
32
|
+
};
|
|
33
|
+
readonly label = "test";
|
|
34
|
+
|
|
35
|
+
fork(_label: string): TestLogger {
|
|
36
|
+
return new TestLogger();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
info(message: string): void {
|
|
40
|
+
void message;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
warn(message: string): void {
|
|
44
|
+
void message;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
error(message: string): void {
|
|
48
|
+
void message;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
debug(message: string): void {
|
|
52
|
+
void message;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
flush(): void {
|
|
56
|
+
void this.label;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
close(): void {
|
|
60
|
+
void this.label;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
test("an async path filter skips a page before reading its output", async () => {
|
|
65
|
+
const outputDir = await createTempDir();
|
|
66
|
+
let pathFilterCalls = 0;
|
|
67
|
+
let filterCalls = 0;
|
|
68
|
+
let renderCalls = 0;
|
|
69
|
+
|
|
70
|
+
const pathFilter: PathFilterFunction = async ({ pathname }) => {
|
|
71
|
+
pathFilterCalls += 1;
|
|
72
|
+
await Promise.resolve();
|
|
73
|
+
return pathname !== "/excluded/";
|
|
74
|
+
};
|
|
75
|
+
const filter: FilterFunction = ({ pathname }) => {
|
|
76
|
+
filterCalls += 1;
|
|
77
|
+
return pathname !== "/excluded/";
|
|
78
|
+
};
|
|
79
|
+
const render: RenderFunction = () => {
|
|
80
|
+
renderCalls += 1;
|
|
81
|
+
return null;
|
|
82
|
+
};
|
|
83
|
+
const integration = astroOpenGraphImages({
|
|
84
|
+
options: { fonts: testOptions.fonts },
|
|
85
|
+
render,
|
|
86
|
+
filter,
|
|
87
|
+
pathFilter,
|
|
88
|
+
});
|
|
89
|
+
const hook = integration.hooks["astro:build:done"];
|
|
90
|
+
|
|
91
|
+
if (hook === undefined) {
|
|
92
|
+
throw new Error("Expected astro:build:done hook");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
await expect(
|
|
97
|
+
hook({
|
|
98
|
+
pages: [{ pathname: "/excluded/" }],
|
|
99
|
+
dir: pathToFileURL(`${outputDir}/`),
|
|
100
|
+
assets: new Map(),
|
|
101
|
+
logger: new TestLogger(),
|
|
102
|
+
}),
|
|
103
|
+
).resolves.toBeUndefined();
|
|
104
|
+
} finally {
|
|
105
|
+
await rm(outputDir, { force: true, recursive: true });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
expect(pathFilterCalls).toBe(1);
|
|
109
|
+
expect(filterCalls).toBe(0);
|
|
110
|
+
expect(renderCalls).toBe(0);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("a path-filtered-in page still requires Open Graph metadata", async () => {
|
|
114
|
+
const outputDir = await createOutputDir("accepted", "<html></html>");
|
|
115
|
+
let filterCalls = 0;
|
|
116
|
+
const pathFilter = alwaysPathFilter;
|
|
117
|
+
const filter: FilterFunction = () => {
|
|
118
|
+
filterCalls += 1;
|
|
119
|
+
return true;
|
|
120
|
+
};
|
|
121
|
+
const render = emptyRender;
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
await expect(
|
|
125
|
+
buildDoneHook({
|
|
126
|
+
pages: [{ pathname: "/accepted/" }],
|
|
127
|
+
dir: pathToFileURL(`${outputDir}/`),
|
|
128
|
+
assets: new Map(),
|
|
129
|
+
logger: new TestLogger(),
|
|
130
|
+
options: testOptions,
|
|
131
|
+
render,
|
|
132
|
+
filter,
|
|
133
|
+
pathFilter,
|
|
134
|
+
}),
|
|
135
|
+
).rejects.toThrow("Missing required meta tags");
|
|
136
|
+
} finally {
|
|
137
|
+
await rm(outputDir, { force: true, recursive: true });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
expect(filterCalls).toBe(0);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("an accepted page with Open Graph metadata renders an image", async () => {
|
|
144
|
+
const outputDir = await createOutputDir(
|
|
145
|
+
"rendered",
|
|
146
|
+
`<!doctype html>
|
|
147
|
+
<html>
|
|
148
|
+
<head>
|
|
149
|
+
<meta property="og:title" content="Rendered page" />
|
|
150
|
+
<meta property="og:url" content="http://example.com/rendered/" />
|
|
151
|
+
<meta property="og:type" content="website" />
|
|
152
|
+
<meta property="og:image" content="http://example.com/rendered/index.png" />
|
|
153
|
+
</head>
|
|
154
|
+
</html>`,
|
|
155
|
+
);
|
|
156
|
+
let filterCalls = 0;
|
|
157
|
+
let renderCalls = 0;
|
|
158
|
+
const pathFilter = alwaysPathFilter;
|
|
159
|
+
const filter: FilterFunction = ({ pathname }) => {
|
|
160
|
+
filterCalls += 1;
|
|
161
|
+
return pathname === "/rendered/";
|
|
162
|
+
};
|
|
163
|
+
const render: RenderFunction = () => {
|
|
164
|
+
renderCalls += 1;
|
|
165
|
+
return createElement("div");
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
await expect(
|
|
170
|
+
buildDoneHook({
|
|
171
|
+
pages: [{ pathname: "/rendered/" }],
|
|
172
|
+
dir: pathToFileURL(`${outputDir}/`),
|
|
173
|
+
assets: new Map(),
|
|
174
|
+
logger: new TestLogger(),
|
|
175
|
+
options: testOptions,
|
|
176
|
+
render,
|
|
177
|
+
filter,
|
|
178
|
+
pathFilter,
|
|
179
|
+
}),
|
|
180
|
+
).resolves.toBeUndefined();
|
|
181
|
+
await access(path.join(outputDir, "rendered", "index.png"));
|
|
182
|
+
} finally {
|
|
183
|
+
await rm(outputDir, { force: true, recursive: true });
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
expect(filterCalls).toBe(1);
|
|
187
|
+
expect(renderCalls).toBe(1);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test("the metadata-aware filter can skip a valid page", async () => {
|
|
191
|
+
const outputDir = await createOutputDir(
|
|
192
|
+
"metadata-skipped",
|
|
193
|
+
renderedPageHtml("metadata-skipped"),
|
|
194
|
+
);
|
|
195
|
+
let filterCalls = 0;
|
|
196
|
+
let renderCalls = 0;
|
|
197
|
+
const pathFilter = alwaysPathFilter;
|
|
198
|
+
const filter: FilterFunction = ({ title }) => {
|
|
199
|
+
filterCalls += 1;
|
|
200
|
+
expect(title).toBe("Rendered page");
|
|
201
|
+
return false;
|
|
202
|
+
};
|
|
203
|
+
const render: RenderFunction = () => {
|
|
204
|
+
renderCalls += 1;
|
|
205
|
+
return createElement("div");
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
await expect(
|
|
210
|
+
buildDoneHook({
|
|
211
|
+
pages: [{ pathname: "/metadata-skipped/" }],
|
|
212
|
+
dir: pathToFileURL(`${outputDir}/`),
|
|
213
|
+
assets: new Map(),
|
|
214
|
+
logger: new TestLogger(),
|
|
215
|
+
options: testOptions,
|
|
216
|
+
render,
|
|
217
|
+
filter,
|
|
218
|
+
pathFilter,
|
|
219
|
+
}),
|
|
220
|
+
).resolves.toBeUndefined();
|
|
221
|
+
await expect(
|
|
222
|
+
access(path.join(outputDir, "metadata-skipped", "index.png")),
|
|
223
|
+
).rejects.toThrow();
|
|
224
|
+
} finally {
|
|
225
|
+
await rm(outputDir, { force: true, recursive: true });
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
expect(filterCalls).toBe(1);
|
|
229
|
+
expect(renderCalls).toBe(0);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const testOptions: IntegrationOptions = {
|
|
233
|
+
width: 1200,
|
|
234
|
+
height: 630,
|
|
235
|
+
verbose: false,
|
|
236
|
+
fonts: [
|
|
237
|
+
{
|
|
238
|
+
data: await readFile(
|
|
239
|
+
path.join(
|
|
240
|
+
import.meta.dirname,
|
|
241
|
+
"../node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff",
|
|
242
|
+
),
|
|
243
|
+
),
|
|
244
|
+
name: "Roboto",
|
|
245
|
+
weight: 400,
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const alwaysPathFilter: PathFilterFunction = () => true;
|
|
251
|
+
const emptyRender: RenderFunction = () => null;
|
|
252
|
+
|
|
253
|
+
async function createOutputDir(
|
|
254
|
+
page: string,
|
|
255
|
+
html = renderedPageHtml(page),
|
|
256
|
+
): Promise<string> {
|
|
257
|
+
const outputDir = await createTempDir();
|
|
258
|
+
await mkdir(path.join(outputDir, page), { recursive: true });
|
|
259
|
+
await writeFile(path.join(outputDir, page, "index.html"), html);
|
|
260
|
+
return outputDir;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async function createTempDir(): Promise<string> {
|
|
264
|
+
return await mkdtemp(path.join(tmpdir(), "astro-opengraph-images-"));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function renderedPageHtml(page: string): string {
|
|
268
|
+
return `<!doctype html>
|
|
269
|
+
<html>
|
|
270
|
+
<head>
|
|
271
|
+
<meta property="og:title" content="Rendered page" />
|
|
272
|
+
<meta property="og:url" content="http://example.com/${page}/" />
|
|
273
|
+
<meta property="og:type" content="website" />
|
|
274
|
+
<meta property="og:image" content="http://example.com/${page}/index.png" />
|
|
275
|
+
</head>
|
|
276
|
+
</html>`;
|
|
277
|
+
}
|
package/src/hook.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
FilterFunction,
|
|
6
6
|
IntegrationOptions,
|
|
7
7
|
Page,
|
|
8
|
+
PathFilterFunction,
|
|
8
9
|
RenderFunction,
|
|
9
10
|
} from "./types.ts";
|
|
10
11
|
import * as fs from "node:fs/promises";
|
|
@@ -22,14 +23,16 @@ export async function buildDoneHook({
|
|
|
22
23
|
dir,
|
|
23
24
|
render,
|
|
24
25
|
filter,
|
|
26
|
+
pathFilter,
|
|
25
27
|
}: AstroBuildDoneHookInput & {
|
|
26
28
|
options: IntegrationOptions;
|
|
27
29
|
render: RenderFunction;
|
|
28
30
|
filter: FilterFunction | undefined;
|
|
31
|
+
pathFilter: PathFilterFunction | undefined;
|
|
29
32
|
}) {
|
|
30
33
|
logger.info("Generating Open Graph images");
|
|
31
34
|
const promises = pages.map((page) =>
|
|
32
|
-
handlePage({ page, options, render, dir, logger, filter }),
|
|
35
|
+
handlePage({ page, options, render, dir, logger, filter, pathFilter }),
|
|
33
36
|
);
|
|
34
37
|
await Promise.all(promises);
|
|
35
38
|
}
|
|
@@ -41,6 +44,7 @@ type HandlePageInput = {
|
|
|
41
44
|
dir: URL;
|
|
42
45
|
logger: AstroIntegrationLogger;
|
|
43
46
|
filter: FilterFunction | undefined;
|
|
47
|
+
pathFilter: PathFilterFunction | undefined;
|
|
44
48
|
};
|
|
45
49
|
|
|
46
50
|
async function handlePage({
|
|
@@ -50,7 +54,19 @@ async function handlePage({
|
|
|
50
54
|
dir,
|
|
51
55
|
logger,
|
|
52
56
|
filter,
|
|
57
|
+
pathFilter,
|
|
53
58
|
}: HandlePageInput) {
|
|
59
|
+
if (pathFilter) {
|
|
60
|
+
const shouldRender = await pathFilter(page);
|
|
61
|
+
|
|
62
|
+
if (!shouldRender) {
|
|
63
|
+
if (options.verbose) {
|
|
64
|
+
logger.info(`Skipping page ${page.pathname}.`);
|
|
65
|
+
}
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
54
70
|
// gets the absolute path to the HTML file. E.g. /home/user/project/dist/blog/index.html
|
|
55
71
|
// fileURLToPath() converts the URL to a file path. Without it, the path would start with a leading slash on Windows
|
|
56
72
|
// systems, resulting in an invalid path.
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
RenderFunctionInput as _RenderFunctionInput,
|
|
12
12
|
RenderFunction as _RenderFunction,
|
|
13
13
|
FilterFunction as _FilterFunction,
|
|
14
|
+
PathFilterFunction as _PathFilterFunction,
|
|
14
15
|
PageDetails as _PageDetails,
|
|
15
16
|
SatoriWeight as _SatoriWeight,
|
|
16
17
|
SatoriFontStyle as _SatoriFontStyle,
|
|
@@ -31,6 +32,7 @@ export type AstroBuildDoneHookInput = _AstroBuildDoneHookInput;
|
|
|
31
32
|
export type RenderFunctionInput = _RenderFunctionInput;
|
|
32
33
|
export type RenderFunction = _RenderFunction;
|
|
33
34
|
export type FilterFunction = _FilterFunction;
|
|
35
|
+
export type PathFilterFunction = _PathFilterFunction;
|
|
34
36
|
export type PageDetails = _PageDetails;
|
|
35
37
|
export type SatoriWeight = _SatoriWeight;
|
|
36
38
|
export type SatoriFontStyle = _SatoriFontStyle;
|
package/src/integration.ts
CHANGED
|
@@ -17,6 +17,7 @@ export function astroOpenGraphImages({
|
|
|
17
17
|
options,
|
|
18
18
|
render,
|
|
19
19
|
filter,
|
|
20
|
+
pathFilter,
|
|
20
21
|
}: IntegrationInput): AstroIntegration {
|
|
21
22
|
const optionsWithDefaults: IntegrationOptions = { ...defaults, ...options };
|
|
22
23
|
|
|
@@ -29,6 +30,7 @@ export function astroOpenGraphImages({
|
|
|
29
30
|
options: optionsWithDefaults,
|
|
30
31
|
render,
|
|
31
32
|
filter,
|
|
33
|
+
pathFilter,
|
|
32
34
|
});
|
|
33
35
|
},
|
|
34
36
|
},
|
package/src/types.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type IntegrationInput = {
|
|
|
5
5
|
options: PartialIntegrationOptions;
|
|
6
6
|
render: RenderFunction;
|
|
7
7
|
filter?: FilterFunction;
|
|
8
|
+
pathFilter?: PathFilterFunction;
|
|
8
9
|
};
|
|
9
10
|
|
|
10
11
|
/** When applied to PartialIntegrationOptions this type equals IntegrationOptions */
|
|
@@ -36,6 +37,9 @@ export type Page = {
|
|
|
36
37
|
pathname: string;
|
|
37
38
|
};
|
|
38
39
|
|
|
40
|
+
/** A function that filters pages before their output files are read */
|
|
41
|
+
export type PathFilterFunction = (input: Page) => Promise<boolean> | boolean;
|
|
42
|
+
|
|
39
43
|
/** The input Astro passes to the build done hook */
|
|
40
44
|
export type AstroBuildDoneHookInput = Parameters<
|
|
41
45
|
BaseIntegrationHooks["astro:build:done"]
|