nuxt-og-image 6.7.5 → 6.7.6
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/chunks/tw4.cjs +2 -2
- package/dist/chunks/tw4.mjs +2 -2
- package/dist/chunks/uno.cjs +20 -5
- package/dist/chunks/uno.mjs +19 -5
- package/dist/module.cjs +2 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +2 -2
- package/dist/runtime/app/utils/plugins.js +4 -10
- package/dist/runtime/server/og-image/bindings/browser/chrome-launcher.d.ts +1 -1
- package/dist/runtime/server/og-image/bindings/browser/cloudflare.d.ts +1 -1
- package/dist/runtime/server/og-image/bindings/browser/on-demand.d.ts +1 -1
- package/dist/runtime/server/og-image/bindings/browser/playwright.d.ts +1 -1
- package/dist/runtime/server/og-image/bindings/font-assets/cloudflare.d.ts +1 -1
- package/dist/runtime/server/og-image/bindings/font-assets/cloudflare.js +1 -1
- package/dist/runtime/server/og-image/bindings/font-assets/dev-prerender.d.ts +1 -1
- package/dist/runtime/server/og-image/bindings/font-assets/dev-prerender.js +2 -2
- package/dist/runtime/server/og-image/bindings/font-assets/node.d.ts +1 -1
- package/dist/runtime/server/og-image/bindings/font-assets/node.js +1 -1
- package/dist/runtime/server/og-image/bindings/resvg/node-dev.js +18 -64
- package/dist/runtime/server/og-image/bindings/takumi/node-dev.js +26 -83
- package/dist/runtime/server/og-image/bindings/worker-queue.d.ts +34 -0
- package/dist/runtime/server/og-image/bindings/worker-queue.js +150 -0
- package/dist/runtime/server/og-image/browser/renderer.js +1 -1
- package/dist/runtime/server/og-image/context.d.ts +1 -1
- package/dist/runtime/server/og-image/context.js +2 -3
- package/dist/runtime/server/og-image/core/plugins/imageSrc.js +1 -1
- package/dist/runtime/server/og-image/core/transforms/emojis/local.d.ts +2 -17
- package/dist/runtime/server/og-image/core/transforms/emojis/local.js +1 -1
- package/dist/runtime/server/og-image/devtools.d.ts +1 -1
- package/dist/runtime/server/og-image/devtools.js +1 -1
- package/dist/runtime/server/og-image/fonts.d.ts +1 -1
- package/dist/runtime/server/og-image/templates/html.js +1 -1
- package/dist/runtime/server/plugins/prerender.d.ts +1 -1
- package/dist/runtime/server/plugins/prerender.js +2 -2
- package/dist/runtime/server/routes/__zero-runtime/image.d.ts +1 -1
- package/dist/runtime/server/routes/__zero-runtime/image.js +1 -1
- package/dist/runtime/server/routes/debug.json.d.ts +1 -10
- package/dist/runtime/server/routes/debug.json.js +1 -1
- package/dist/runtime/server/routes/image.d.ts +1 -1
- package/dist/runtime/server/routes/image.js +1 -1
- package/dist/runtime/server/routes/resolve.d.ts +1 -1
- package/dist/runtime/server/routes/resolve.js +1 -1
- package/dist/runtime/server/util/cache.d.ts +1 -6
- package/dist/runtime/server/util/cache.js +2 -2
- package/dist/runtime/server/util/cloudflare.d.ts +1 -1
- package/dist/runtime/server/util/cloudflareAssets.d.ts +1 -1
- package/dist/runtime/server/util/cloudflareAssets.js +1 -1
- package/dist/runtime/server/util/eventHandlers.d.ts +1 -1
- package/dist/runtime/server/util/eventHandlers.js +1 -1
- package/dist/runtime/server/util/fetchLocalAsset.d.ts +1 -1
- package/dist/runtime/server/util/kit.d.ts +7 -3
- package/dist/runtime/server/util/kit.js +4 -18
- package/dist/runtime/server/util/options.js +1 -1
- package/dist/runtime/server/util/query.d.ts +1 -1
- package/dist/runtime/server/utils.d.ts +1 -1
- package/dist/runtime/server/utils.js +1 -1
- package/dist/runtime/types.d.ts +11 -9
- package/dist/shared/{nuxt-og-image.D3mV8OQ9.mjs → nuxt-og-image.BIbfn5xQ.mjs} +111 -83
- package/dist/shared/{nuxt-og-image.Cctpuv4O.cjs → nuxt-og-image.CdpC3njh.cjs} +113 -82
- package/package.json +38 -27
- package/types/virtual.d.ts +15 -0
package/dist/chunks/tw4.cjs
CHANGED
|
@@ -4,17 +4,17 @@ const promises = require('node:fs/promises');
|
|
|
4
4
|
const node_url = require('node:url');
|
|
5
5
|
const exsolve = require('exsolve');
|
|
6
6
|
const pathe = require('pathe');
|
|
7
|
-
const module$1 = require('../shared/nuxt-og-image.
|
|
7
|
+
const module$1 = require('../shared/nuxt-og-image.CdpC3njh.cjs');
|
|
8
8
|
require('node:crypto');
|
|
9
9
|
require('node:fs');
|
|
10
10
|
require('@nuxt/kit');
|
|
11
11
|
require('defu');
|
|
12
12
|
require('fnv1a-64');
|
|
13
13
|
require('nuxt-site-config/kit');
|
|
14
|
+
require('nuxtseo-shared/kit');
|
|
14
15
|
require('pkg-types');
|
|
15
16
|
require('std-env');
|
|
16
17
|
require('oxc-walker');
|
|
17
|
-
require('nuxtseo-shared/kit');
|
|
18
18
|
require('../../dist/runtime/logger.js');
|
|
19
19
|
require('chrome-launcher');
|
|
20
20
|
require('nypm');
|
package/dist/chunks/tw4.mjs
CHANGED
|
@@ -2,17 +2,17 @@ import { readFile } from 'node:fs/promises';
|
|
|
2
2
|
import { pathToFileURL } from 'node:url';
|
|
3
3
|
import { resolveModulePath } from 'exsolve';
|
|
4
4
|
import { dirname, join } from 'pathe';
|
|
5
|
-
import { e as extractVariantBaseClasses, r as resolveVariantPrefixes, h as resolveExtractedVars,
|
|
5
|
+
import { e as extractVariantBaseClasses, r as resolveVariantPrefixes, h as resolveExtractedVars, l as resolveVarsDeep, s as simplifyCss, p as postProcessStyles, m as loadLightningCss, a as extractCssVars, c as extractUniversalVars, d as extractPerClassVars, g as extractVarsFromCss, f as extractClassStyles } from '../shared/nuxt-og-image.BIbfn5xQ.mjs';
|
|
6
6
|
import 'node:crypto';
|
|
7
7
|
import 'node:fs';
|
|
8
8
|
import '@nuxt/kit';
|
|
9
9
|
import 'defu';
|
|
10
10
|
import 'fnv1a-64';
|
|
11
11
|
import 'nuxt-site-config/kit';
|
|
12
|
+
import 'nuxtseo-shared/kit';
|
|
12
13
|
import 'pkg-types';
|
|
13
14
|
import 'std-env';
|
|
14
15
|
import 'oxc-walker';
|
|
15
|
-
import 'nuxtseo-shared/kit';
|
|
16
16
|
import '../../dist/runtime/logger.js';
|
|
17
17
|
import 'chrome-launcher';
|
|
18
18
|
import 'nypm';
|
package/dist/chunks/uno.cjs
CHANGED
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
const promises = require('node:fs/promises');
|
|
4
4
|
const defu = require('defu');
|
|
5
5
|
const logger_js = require('../../dist/runtime/logger.js');
|
|
6
|
-
const module$1 = require('../shared/nuxt-og-image.
|
|
6
|
+
const module$1 = require('../shared/nuxt-og-image.CdpC3njh.cjs');
|
|
7
7
|
require('node:crypto');
|
|
8
8
|
require('node:fs');
|
|
9
9
|
require('node:url');
|
|
10
10
|
require('@nuxt/kit');
|
|
11
11
|
require('fnv1a-64');
|
|
12
12
|
require('nuxt-site-config/kit');
|
|
13
|
+
require('nuxtseo-shared/kit');
|
|
13
14
|
require('pathe');
|
|
14
15
|
require('pkg-types');
|
|
15
16
|
require('std-env');
|
|
16
17
|
require('oxc-walker');
|
|
17
|
-
require('nuxtseo-shared/kit');
|
|
18
18
|
require('chrome-launcher');
|
|
19
19
|
require('nypm');
|
|
20
20
|
require('nuxtseo-shared/devtools');
|
|
@@ -42,6 +42,8 @@ const RE_HEIGHT_ATTR = /\bheight=['"](\d+)['"]/;
|
|
|
42
42
|
const RE_SVG_BODY = /<svg[^>]*>([\s\S]*)<\/svg>/;
|
|
43
43
|
let unoConfig = null;
|
|
44
44
|
let rootDir = null;
|
|
45
|
+
let unocssCorePath;
|
|
46
|
+
let unocssConfigPath;
|
|
45
47
|
let generator = null;
|
|
46
48
|
let pendingGenerator = null;
|
|
47
49
|
let cachedExtracted = null;
|
|
@@ -60,6 +62,15 @@ function clearUnoCache() {
|
|
|
60
62
|
pendingGenerator = null;
|
|
61
63
|
cachedExtracted = null;
|
|
62
64
|
}
|
|
65
|
+
function setUnoModulePaths(options) {
|
|
66
|
+
const nextCorePath = options?.unocssCorePath;
|
|
67
|
+
const nextConfigPath = options?.unocssConfigPath;
|
|
68
|
+
if (nextCorePath === unocssCorePath && nextConfigPath === unocssConfigPath)
|
|
69
|
+
return;
|
|
70
|
+
unocssCorePath = nextCorePath;
|
|
71
|
+
unocssConfigPath = nextConfigPath;
|
|
72
|
+
clearUnoCache();
|
|
73
|
+
}
|
|
63
74
|
async function getGenerator() {
|
|
64
75
|
if (generator)
|
|
65
76
|
return generator;
|
|
@@ -68,17 +79,18 @@ async function getGenerator() {
|
|
|
68
79
|
pendingGenerator = (async () => {
|
|
69
80
|
let loadedConfig;
|
|
70
81
|
try {
|
|
71
|
-
const { loadConfig } = await
|
|
82
|
+
const { loadConfig } = await module$1.importOptionalPeer("@unocss/config", unocssConfigPath, "UnoCSS class extraction with OG images");
|
|
72
83
|
const result = await loadConfig(rootDir || process.cwd());
|
|
73
84
|
loadedConfig = result.config;
|
|
74
85
|
} catch (e) {
|
|
75
|
-
|
|
86
|
+
if (!unoConfig)
|
|
87
|
+
logger_js.logger.warn("[og-image UnoCSS] Failed to load uno.config.ts:", e.message);
|
|
76
88
|
}
|
|
77
89
|
const finalConfig = loadedConfig ? defu.defu(unoConfig || {}, loadedConfig) : unoConfig;
|
|
78
90
|
if (!finalConfig) {
|
|
79
91
|
throw new Error("UnoCSS config not found. Ensure uno.config.ts exists or @unocss/nuxt is loaded.");
|
|
80
92
|
}
|
|
81
|
-
const { createGenerator } = await
|
|
93
|
+
const { createGenerator } = await module$1.importOptionalPeer("@unocss/core", unocssCorePath, "UnoCSS class extraction with OG images");
|
|
82
94
|
generator = await createGenerator(finalConfig);
|
|
83
95
|
return generator;
|
|
84
96
|
})();
|
|
@@ -116,6 +128,7 @@ function resolveUserVars(extracted, rootAttrs) {
|
|
|
116
128
|
return module$1.resolveExtractedVars(extracted, rootAttrs);
|
|
117
129
|
}
|
|
118
130
|
function createUnoProvider(options) {
|
|
131
|
+
setUnoModulePaths(options);
|
|
119
132
|
return {
|
|
120
133
|
name: "unocss",
|
|
121
134
|
async resolveClassesToStyles(classes, context, rootAttrs) {
|
|
@@ -227,6 +240,8 @@ function createUnoProvider(options) {
|
|
|
227
240
|
};
|
|
228
241
|
}
|
|
229
242
|
|
|
243
|
+
exports.importResolvedModule = module$1.importResolvedModule;
|
|
244
|
+
exports.resolveOptionalModulePath = module$1.resolveOptionalModulePath;
|
|
230
245
|
exports.clearUnoCache = clearUnoCache;
|
|
231
246
|
exports.clearUnoUserVarsCache = clearUnoUserVarsCache;
|
|
232
247
|
exports.createUnoProvider = createUnoProvider;
|
package/dist/chunks/uno.mjs
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { defu } from 'defu';
|
|
3
3
|
import { logger } from '../../dist/runtime/logger.js';
|
|
4
|
-
import { e as extractVariantBaseClasses, s as simplifyCss, a as extractCssVars, b as extractPropertyInitialValues, c as extractUniversalVars, d as extractPerClassVars, f as extractClassStyles, p as postProcessStyles, r as resolveVariantPrefixes, g as extractVarsFromCss, h as resolveExtractedVars } from '../shared/nuxt-og-image.
|
|
4
|
+
import { e as extractVariantBaseClasses, s as simplifyCss, a as extractCssVars, b as extractPropertyInitialValues, c as extractUniversalVars, d as extractPerClassVars, f as extractClassStyles, p as postProcessStyles, r as resolveVariantPrefixes, i as importOptionalPeer, g as extractVarsFromCss, h as resolveExtractedVars } from '../shared/nuxt-og-image.BIbfn5xQ.mjs';
|
|
5
|
+
export { j as importResolvedModule, k as resolveOptionalModulePath } from '../shared/nuxt-og-image.BIbfn5xQ.mjs';
|
|
5
6
|
import 'node:crypto';
|
|
6
7
|
import 'node:fs';
|
|
7
8
|
import 'node:url';
|
|
8
9
|
import '@nuxt/kit';
|
|
9
10
|
import 'fnv1a-64';
|
|
10
11
|
import 'nuxt-site-config/kit';
|
|
12
|
+
import 'nuxtseo-shared/kit';
|
|
11
13
|
import 'pathe';
|
|
12
14
|
import 'pkg-types';
|
|
13
15
|
import 'std-env';
|
|
14
16
|
import 'oxc-walker';
|
|
15
|
-
import 'nuxtseo-shared/kit';
|
|
16
17
|
import 'chrome-launcher';
|
|
17
18
|
import 'nypm';
|
|
18
19
|
import 'nuxtseo-shared/devtools';
|
|
@@ -40,6 +41,8 @@ const RE_HEIGHT_ATTR = /\bheight=['"](\d+)['"]/;
|
|
|
40
41
|
const RE_SVG_BODY = /<svg[^>]*>([\s\S]*)<\/svg>/;
|
|
41
42
|
let unoConfig = null;
|
|
42
43
|
let rootDir = null;
|
|
44
|
+
let unocssCorePath;
|
|
45
|
+
let unocssConfigPath;
|
|
43
46
|
let generator = null;
|
|
44
47
|
let pendingGenerator = null;
|
|
45
48
|
let cachedExtracted = null;
|
|
@@ -58,6 +61,15 @@ function clearUnoCache() {
|
|
|
58
61
|
pendingGenerator = null;
|
|
59
62
|
cachedExtracted = null;
|
|
60
63
|
}
|
|
64
|
+
function setUnoModulePaths(options) {
|
|
65
|
+
const nextCorePath = options?.unocssCorePath;
|
|
66
|
+
const nextConfigPath = options?.unocssConfigPath;
|
|
67
|
+
if (nextCorePath === unocssCorePath && nextConfigPath === unocssConfigPath)
|
|
68
|
+
return;
|
|
69
|
+
unocssCorePath = nextCorePath;
|
|
70
|
+
unocssConfigPath = nextConfigPath;
|
|
71
|
+
clearUnoCache();
|
|
72
|
+
}
|
|
61
73
|
async function getGenerator() {
|
|
62
74
|
if (generator)
|
|
63
75
|
return generator;
|
|
@@ -66,17 +78,18 @@ async function getGenerator() {
|
|
|
66
78
|
pendingGenerator = (async () => {
|
|
67
79
|
let loadedConfig;
|
|
68
80
|
try {
|
|
69
|
-
const { loadConfig } = await
|
|
81
|
+
const { loadConfig } = await importOptionalPeer("@unocss/config", unocssConfigPath, "UnoCSS class extraction with OG images");
|
|
70
82
|
const result = await loadConfig(rootDir || process.cwd());
|
|
71
83
|
loadedConfig = result.config;
|
|
72
84
|
} catch (e) {
|
|
73
|
-
|
|
85
|
+
if (!unoConfig)
|
|
86
|
+
logger.warn("[og-image UnoCSS] Failed to load uno.config.ts:", e.message);
|
|
74
87
|
}
|
|
75
88
|
const finalConfig = loadedConfig ? defu(unoConfig || {}, loadedConfig) : unoConfig;
|
|
76
89
|
if (!finalConfig) {
|
|
77
90
|
throw new Error("UnoCSS config not found. Ensure uno.config.ts exists or @unocss/nuxt is loaded.");
|
|
78
91
|
}
|
|
79
|
-
const { createGenerator } = await
|
|
92
|
+
const { createGenerator } = await importOptionalPeer("@unocss/core", unocssCorePath, "UnoCSS class extraction with OG images");
|
|
80
93
|
generator = await createGenerator(finalConfig);
|
|
81
94
|
return generator;
|
|
82
95
|
})();
|
|
@@ -114,6 +127,7 @@ function resolveUserVars(extracted, rootAttrs) {
|
|
|
114
127
|
return resolveExtractedVars(extracted, rootAttrs);
|
|
115
128
|
}
|
|
116
129
|
function createUnoProvider(options) {
|
|
130
|
+
setUnoModulePaths(options);
|
|
117
131
|
return {
|
|
118
132
|
name: "unocss",
|
|
119
133
|
async resolveClassesToStyles(classes, context, rootAttrs) {
|
package/dist/module.cjs
CHANGED
|
@@ -8,11 +8,11 @@ require('@nuxt/kit');
|
|
|
8
8
|
require('defu');
|
|
9
9
|
require('fnv1a-64');
|
|
10
10
|
require('nuxt-site-config/kit');
|
|
11
|
+
require('nuxtseo-shared/kit');
|
|
11
12
|
require('pathe');
|
|
12
13
|
require('pkg-types');
|
|
13
14
|
require('std-env');
|
|
14
|
-
const module$1 = require('./shared/nuxt-og-image.
|
|
15
|
-
require('nuxtseo-shared/kit');
|
|
15
|
+
const module$1 = require('./shared/nuxt-og-image.CdpC3njh.cjs');
|
|
16
16
|
require('../dist/runtime/logger.js');
|
|
17
17
|
require('oxc-walker');
|
|
18
18
|
require('chrome-launcher');
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -6,11 +6,11 @@ import '@nuxt/kit';
|
|
|
6
6
|
import 'defu';
|
|
7
7
|
import 'fnv1a-64';
|
|
8
8
|
import 'nuxt-site-config/kit';
|
|
9
|
+
import 'nuxtseo-shared/kit';
|
|
9
10
|
import 'pathe';
|
|
10
11
|
import 'pkg-types';
|
|
11
12
|
import 'std-env';
|
|
12
|
-
export {
|
|
13
|
-
import 'nuxtseo-shared/kit';
|
|
13
|
+
export { n as default } from './shared/nuxt-og-image.BIbfn5xQ.mjs';
|
|
14
14
|
import '../dist/runtime/logger.js';
|
|
15
15
|
import 'oxc-walker';
|
|
16
16
|
import 'chrome-launcher';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TemplateParamsPlugin } from "@unhead/vue/plugins";
|
|
2
2
|
import { defu } from "defu";
|
|
3
|
-
import {
|
|
4
|
-
import { parseURL
|
|
3
|
+
import { createNitroRouteRuleMatcher } from "nuxtseo-shared/server";
|
|
4
|
+
import { parseURL } from "ufo";
|
|
5
5
|
import { toValue } from "vue";
|
|
6
6
|
import { defineNuxtPlugin, useRequestEvent } from "#app";
|
|
7
7
|
import { withSiteUrl } from "#site-config/app/composables";
|
|
@@ -60,14 +60,8 @@ export const routeRuleOgImage = defineNuxtPlugin((nuxtApp) => {
|
|
|
60
60
|
const path = parseURL(e?.path || "").pathname;
|
|
61
61
|
if (isInternalRoute(path))
|
|
62
62
|
return;
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
);
|
|
66
|
-
const matchedRules = _routeRulesMatcher.matchAll(
|
|
67
|
-
withoutBase(path.split("?")?.[0] || "", ssrContext?.runtimeConfig?.app.baseURL || "")
|
|
68
|
-
).reverse();
|
|
69
|
-
const combinedRules = defu({}, ...matchedRules);
|
|
70
|
-
let routeRules = combinedRules?.ogImage;
|
|
63
|
+
const matchRouteRules = createNitroRouteRuleMatcher(ssrContext?.runtimeConfig || {});
|
|
64
|
+
let routeRules = matchRouteRules(path).ogImage;
|
|
71
65
|
if (typeof routeRules === "undefined")
|
|
72
66
|
return;
|
|
73
67
|
if (routeRules === false) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useRuntimeConfig } from "nitropack/runtime";
|
|
2
1
|
import { withBase } from "ufo";
|
|
2
|
+
import { useRuntimeConfig } from "#nuxtseo/nitro";
|
|
3
3
|
import { getSiteConfig } from "#site-config/server/composables";
|
|
4
4
|
import { getCloudflareAssets } from "../../../util/cloudflareAssets.js";
|
|
5
5
|
import { fetchLocalAsset } from "../../../util/fetchLocalAsset.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
|
-
import { getRequestURL } from "h3";
|
|
3
|
-
import { useRuntimeConfig } from "nitropack/runtime";
|
|
4
2
|
import { join } from "pathe";
|
|
5
3
|
import { withBase } from "ufo";
|
|
4
|
+
import { getRequestURL } from "#nuxtseo/h3";
|
|
5
|
+
import { useRuntimeConfig } from "#nuxtseo/nitro";
|
|
6
6
|
import { buildDir, rootDir } from "#og-image-virtual/build-dir.mjs";
|
|
7
7
|
import { getSiteConfig } from "#site-config/server/composables";
|
|
8
8
|
import { getFetchTimeout } from "../../../util/fetchTimeout.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useRuntimeConfig } from "nitropack/runtime";
|
|
2
1
|
import { withBase } from "ufo";
|
|
2
|
+
import { useRuntimeConfig } from "#nuxtseo/nitro";
|
|
3
3
|
import { getNitroOrigin, getSiteConfig } from "#site-config/server/composables";
|
|
4
4
|
import { getFetchTimeout } from "../../../util/fetchTimeout.js";
|
|
5
5
|
import { fetchWithRedirectValidation } from "../../../util/ssrf.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Worker } from "node:worker_threads";
|
|
2
|
+
import { createWorkerQueue, parseWorkerTimeout } from "../worker-queue.js";
|
|
2
3
|
const workerCode = `
|
|
3
4
|
const { createRequire } = require('node:module')
|
|
4
5
|
const _require = createRequire(process.cwd() + '/')
|
|
@@ -12,78 +13,31 @@ parentPort.on('message', ({ id, svg, options }) => {
|
|
|
12
13
|
// Always slice to create a standard ArrayBuffer \u2014 native addon buffers
|
|
13
14
|
// use external memory that can't be transferred via postMessage
|
|
14
15
|
const ab = png.buffer.slice(png.byteOffset, png.byteOffset + png.byteLength)
|
|
15
|
-
parentPort.postMessage({ id, png: ab }, [ab])
|
|
16
|
+
parentPort.postMessage({ _tag: 'response', id, payload: { _tag: 'success', png: ab } }, [ab])
|
|
16
17
|
} catch (err) {
|
|
17
|
-
parentPort.postMessage({ id, error: err?.message || String(err) })
|
|
18
|
+
parentPort.postMessage({ _tag: 'response', id, payload: { _tag: 'failure', error: err?.message || String(err) } })
|
|
18
19
|
}
|
|
19
20
|
})
|
|
21
|
+
parentPort.postMessage({ _tag: 'ready' })
|
|
20
22
|
`;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
23
|
+
const workerTimeout = parseWorkerTimeout(process.env.NUXT_OG_IMAGE_WORKER_TIMEOUT);
|
|
24
|
+
const workerQueue = createWorkerQueue({
|
|
25
|
+
createWorker: () => new Worker(workerCode, { eval: true }),
|
|
26
|
+
executionTimeout: workerTimeout,
|
|
27
|
+
startupTimeout: workerTimeout,
|
|
28
|
+
label: "resvg"
|
|
29
|
+
});
|
|
30
|
+
function renderPng(svg, options) {
|
|
31
|
+
return workerQueue.enqueue(({ id }) => ({ id, svg, options })).then((result) => {
|
|
32
|
+
if (result._tag === "failure")
|
|
33
|
+
throw new Error(result.error);
|
|
34
|
+
return Buffer.from(result.png);
|
|
35
|
+
});
|
|
34
36
|
}
|
|
35
37
|
const signalKey = Symbol.for("og-image:resvg-worker-cleanup");
|
|
36
38
|
if (!globalThis[signalKey]) {
|
|
37
39
|
globalThis[signalKey] = true;
|
|
38
|
-
process.on("exit",
|
|
39
|
-
}
|
|
40
|
-
function createWorker() {
|
|
41
|
-
const w = new Worker(workerCode, { eval: true });
|
|
42
|
-
w.on("message", ({ id, png, error }) => {
|
|
43
|
-
const p = pending.get(id);
|
|
44
|
-
if (p) {
|
|
45
|
-
clearTimeout(p.timer);
|
|
46
|
-
pending.delete(id);
|
|
47
|
-
if (error)
|
|
48
|
-
p.reject(new Error(error));
|
|
49
|
-
else
|
|
50
|
-
p.resolve(Buffer.from(png));
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
w.on("error", (err) => {
|
|
54
|
-
for (const [id, p] of pending) {
|
|
55
|
-
clearTimeout(p.timer);
|
|
56
|
-
pending.delete(id);
|
|
57
|
-
p.reject(err);
|
|
58
|
-
}
|
|
59
|
-
worker = null;
|
|
60
|
-
});
|
|
61
|
-
w.on("exit", (code) => {
|
|
62
|
-
if (code !== 0) {
|
|
63
|
-
for (const [id, p] of pending) {
|
|
64
|
-
clearTimeout(p.timer);
|
|
65
|
-
pending.delete(id);
|
|
66
|
-
p.reject(new Error(`Resvg worker exited with code ${code}`));
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
worker = null;
|
|
70
|
-
});
|
|
71
|
-
w.unref();
|
|
72
|
-
return w;
|
|
73
|
-
}
|
|
74
|
-
function renderPng(svg, options) {
|
|
75
|
-
return new Promise((resolve, reject) => {
|
|
76
|
-
if (!worker)
|
|
77
|
-
worker = createWorker();
|
|
78
|
-
const id = ++requestId;
|
|
79
|
-
const timer = setTimeout(() => {
|
|
80
|
-
pending.delete(id);
|
|
81
|
-
reject(new Error("resvg worker timed out \u2014 killing worker"));
|
|
82
|
-
killWorker();
|
|
83
|
-
}, 3e4);
|
|
84
|
-
pending.set(id, { resolve, reject, timer });
|
|
85
|
-
worker.postMessage({ id, svg, options });
|
|
86
|
-
});
|
|
40
|
+
process.on("exit", workerQueue.shutdown);
|
|
87
41
|
}
|
|
88
42
|
class ResvgWorkerProxy {
|
|
89
43
|
svg;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Worker } from "node:worker_threads";
|
|
2
|
+
import { createWorkerQueue, parseWorkerTimeout } from "../worker-queue.js";
|
|
2
3
|
import { extractResourceUrls as extractTakumiResourceUrls } from "./resource-urls.js";
|
|
3
4
|
const workerCode = `
|
|
4
5
|
const { createRequire } = require('node:module')
|
|
@@ -30,85 +31,24 @@ parentPort.on('message', async ({ id, type, newFonts, nodes, options }) => {
|
|
|
30
31
|
// Always slice to create a standard ArrayBuffer \u2014 native addon buffers
|
|
31
32
|
// use external memory that can't be transferred via postMessage
|
|
32
33
|
const ab = image.buffer.slice(image.byteOffset, image.byteOffset + image.byteLength)
|
|
33
|
-
parentPort.postMessage({ id, image: ab, fontWarnings }, [ab])
|
|
34
|
+
parentPort.postMessage({ _tag: 'response', id, payload: { _tag: 'success', image: ab, fontWarnings } }, [ab])
|
|
34
35
|
} catch (err) {
|
|
35
|
-
parentPort.postMessage({ id, error: err?.message || String(err) })
|
|
36
|
+
parentPort.postMessage({ _tag: 'response', id, payload: { _tag: 'failure', error: err?.message || String(err) } })
|
|
36
37
|
}
|
|
37
38
|
})
|
|
39
|
+
parentPort.postMessage({ _tag: 'ready' })
|
|
38
40
|
`;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
worker.terminate();
|
|
47
|
-
worker = null;
|
|
48
|
-
for (const [id, p] of pending) {
|
|
49
|
-
clearTimeout(p.timer);
|
|
50
|
-
pending.delete(id);
|
|
51
|
-
p.reject(new Error("Takumi worker terminated"));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
41
|
+
const workerTimeout = parseWorkerTimeout(process.env.NUXT_OG_IMAGE_WORKER_TIMEOUT);
|
|
42
|
+
const workerQueue = createWorkerQueue({
|
|
43
|
+
createWorker: () => new Worker(workerCode, { eval: true }),
|
|
44
|
+
executionTimeout: workerTimeout,
|
|
45
|
+
startupTimeout: workerTimeout,
|
|
46
|
+
label: "takumi"
|
|
47
|
+
});
|
|
54
48
|
const signalKey = Symbol.for("og-image:takumi-worker-cleanup");
|
|
55
49
|
if (!globalThis[signalKey]) {
|
|
56
50
|
globalThis[signalKey] = true;
|
|
57
|
-
process.on("exit",
|
|
58
|
-
}
|
|
59
|
-
function createWorker() {
|
|
60
|
-
workerGeneration++;
|
|
61
|
-
const w = new Worker(workerCode, { eval: true });
|
|
62
|
-
w.on("message", ({ id, image, urls, error, fontWarnings }) => {
|
|
63
|
-
const p = pending.get(id);
|
|
64
|
-
if (p) {
|
|
65
|
-
clearTimeout(p.timer);
|
|
66
|
-
pending.delete(id);
|
|
67
|
-
if (error)
|
|
68
|
-
p.reject(new Error(error));
|
|
69
|
-
else if (urls !== void 0)
|
|
70
|
-
p.resolve(urls);
|
|
71
|
-
else
|
|
72
|
-
p.resolve({ image: Buffer.from(image), fontWarnings });
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
w.on("error", (err) => {
|
|
76
|
-
for (const [id, p] of pending) {
|
|
77
|
-
clearTimeout(p.timer);
|
|
78
|
-
pending.delete(id);
|
|
79
|
-
p.reject(err);
|
|
80
|
-
}
|
|
81
|
-
worker = null;
|
|
82
|
-
});
|
|
83
|
-
w.on("exit", (code) => {
|
|
84
|
-
if (code !== 0) {
|
|
85
|
-
for (const [id, p] of pending) {
|
|
86
|
-
clearTimeout(p.timer);
|
|
87
|
-
pending.delete(id);
|
|
88
|
-
p.reject(new Error(`Takumi worker exited with code ${code}`));
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
worker = null;
|
|
92
|
-
});
|
|
93
|
-
w.unref();
|
|
94
|
-
return w;
|
|
95
|
-
}
|
|
96
|
-
function ensureWorker() {
|
|
97
|
-
if (!worker)
|
|
98
|
-
worker = createWorker();
|
|
99
|
-
}
|
|
100
|
-
function postToWorker(msg, timeoutMs = 3e4) {
|
|
101
|
-
return new Promise((resolve, reject) => {
|
|
102
|
-
ensureWorker();
|
|
103
|
-
const id = ++requestId;
|
|
104
|
-
const timer = setTimeout(() => {
|
|
105
|
-
pending.delete(id);
|
|
106
|
-
reject(new Error("takumi worker timed out \u2014 killing worker"));
|
|
107
|
-
killWorker();
|
|
108
|
-
}, timeoutMs);
|
|
109
|
-
pending.set(id, { resolve, reject, timer });
|
|
110
|
-
worker.postMessage({ id, ...msg });
|
|
111
|
-
});
|
|
51
|
+
process.on("exit", workerQueue.shutdown);
|
|
112
52
|
}
|
|
113
53
|
function extractResourceUrls(nodes) {
|
|
114
54
|
return Promise.resolve(extractTakumiResourceUrls(nodes));
|
|
@@ -130,21 +70,24 @@ class RendererWorkerProxy {
|
|
|
130
70
|
this.loadFont(font);
|
|
131
71
|
}
|
|
132
72
|
render(nodes, options) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
73
|
+
return workerQueue.enqueue(({ id, generation }) => {
|
|
74
|
+
let fontsToSend;
|
|
75
|
+
if (this.syncedGeneration !== generation) {
|
|
76
|
+
fontsToSend = [...this.allFonts];
|
|
77
|
+
this.pendingFonts = [];
|
|
78
|
+
} else {
|
|
79
|
+
fontsToSend = this.pendingFonts.splice(0);
|
|
80
|
+
}
|
|
81
|
+
this.syncedGeneration = generation;
|
|
82
|
+
return { id, type: "render", newFonts: fontsToSend, nodes, options };
|
|
83
|
+
}).then((result) => {
|
|
84
|
+
if (result._tag === "failure")
|
|
85
|
+
throw new Error(result.error);
|
|
143
86
|
if (result.fontWarnings?.length) {
|
|
144
87
|
for (const w of result.fontWarnings)
|
|
145
88
|
console.warn(`[nuxt-og-image] Failed to load font "${w.name}" (weight: ${w.weight}) into takumi renderer: ${w.error}`);
|
|
146
89
|
}
|
|
147
|
-
return result.image;
|
|
90
|
+
return Buffer.from(result.image);
|
|
148
91
|
});
|
|
149
92
|
}
|
|
150
93
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
interface WorkerHandle {
|
|
2
|
+
on: {
|
|
3
|
+
(event: 'message', listener: (message: unknown) => void): WorkerHandle;
|
|
4
|
+
(event: 'error', listener: (error: Error) => void): WorkerHandle;
|
|
5
|
+
(event: 'exit', listener: (code: number) => void): WorkerHandle;
|
|
6
|
+
};
|
|
7
|
+
postMessage: (message: unknown) => void;
|
|
8
|
+
removeAllListeners: () => WorkerHandle;
|
|
9
|
+
terminate: () => Promise<number>;
|
|
10
|
+
unref: () => void;
|
|
11
|
+
}
|
|
12
|
+
interface QueueOptions {
|
|
13
|
+
createWorker: () => WorkerHandle;
|
|
14
|
+
executionTimeout: number;
|
|
15
|
+
startupTimeout: number;
|
|
16
|
+
label: string;
|
|
17
|
+
maxAttempts?: number;
|
|
18
|
+
}
|
|
19
|
+
interface Job<TMessage, TResponse> {
|
|
20
|
+
id: number;
|
|
21
|
+
buildMessage: (context: {
|
|
22
|
+
id: number;
|
|
23
|
+
generation: number;
|
|
24
|
+
}) => TMessage;
|
|
25
|
+
resolve: (response: TResponse) => void;
|
|
26
|
+
reject: (error: Error) => void;
|
|
27
|
+
attempts: number;
|
|
28
|
+
}
|
|
29
|
+
export declare function parseWorkerTimeout(value: string | undefined, fallback?: number): number;
|
|
30
|
+
export declare function createWorkerQueue<TMessage, TResponse>(options: QueueOptions): {
|
|
31
|
+
enqueue: (buildMessage: Job<TMessage, TResponse>["buildMessage"]) => Promise<TResponse>;
|
|
32
|
+
shutdown: () => void;
|
|
33
|
+
};
|
|
34
|
+
export {};
|