nuxt-og-image 6.7.7 → 6.8.0
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.mjs +2 -2
- package/dist/chunks/uno.mjs +4 -4
- package/dist/cli.mjs +1 -1
- package/dist/devtools/nuxt.config.ts +4 -1
- package/dist/module.d.mts +10 -0
- package/dist/module.d.ts +10 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +3 -3
- package/dist/runtime/app/client-utils.js +4 -3
- package/dist/runtime/app/utils.js +3 -2
- package/dist/runtime/server/og-image/bindings/satori/harfbuzz.d.ts +4 -0
- package/dist/runtime/server/og-image/bindings/satori/harfbuzz.js +33 -0
- package/dist/runtime/server/og-image/font-subsets.d.ts +3 -11
- package/dist/runtime/server/og-image/font-subsets.js +50 -27
- package/dist/runtime/server/og-image/fonts.d.ts +1 -1
- package/dist/runtime/server/util/eventHandlers.js +3 -3
- package/dist/runtime/shared/urlEncoding.js +2 -1
- package/dist/runtime/shared.d.ts +10 -1
- package/dist/runtime/shared.js +2 -2
- package/dist/runtime/types.d.ts +2 -0
- package/dist/shared/{nuxt-og-image.BMHzg1Vz.mjs → nuxt-og-image.D936Fp6O.mjs} +610 -467
- package/package.json +66 -59
- package/types/virtual.d.ts +18 -0
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { createHash, randomBytes } from 'node:crypto';
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
3
|
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, rmSync } from 'node:fs';
|
|
4
|
-
import {
|
|
4
|
+
import { readFile, mkdir, writeFile, readdir } from 'node:fs/promises';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
|
-
import { resolvePath, useNuxt, addTemplate, updateTemplates, directoryToURL, tryResolveModule, addTypeTemplate, defineNuxtModule, createResolver, addImports, hasNuxtModule, hasNuxtModuleCompatibility, getNuxtModuleVersion, addVitePlugin, addBuildPlugin, addServerHandler, addPlugin, addComponentsDir,
|
|
6
|
+
import { resolvePath, useNuxt, getNuxtVersion, addTemplate, updateTemplates, directoryToURL, tryResolveModule, addTypeTemplate, defineNuxtModule, createResolver, addImports, hasNuxtModule, hasNuxtModuleCompatibility, getNuxtModuleVersion, addVitePlugin, addBuildPlugin, addServerHandler, addPlugin, addComponentsDir, addServerPlugin } from '@nuxt/kit';
|
|
7
7
|
import { defu } from 'defu';
|
|
8
8
|
import { fnv1a64Base36 } from 'fnv1a-64';
|
|
9
9
|
import { installNuxtSiteConfig } from 'nuxt-site-config/kit';
|
|
10
10
|
import { resolveNitroPreset, renderNitroTypeAugmentations, setupNitroRuntimeCompatibility, getNuxtModuleOptions, isNuxtGenerate } from 'nuxtseo-shared/kit';
|
|
11
|
-
import {
|
|
11
|
+
import { join, basename, dirname, relative, isAbsolute, resolve } from 'pathe';
|
|
12
12
|
import { readPackageJSON } from 'pkg-types';
|
|
13
13
|
import { isCI, isAgent, hasTTY } from 'std-env';
|
|
14
|
+
import MagicString from 'magic-string';
|
|
14
15
|
import { parseAndWalk } from 'oxc-walker';
|
|
16
|
+
import { resolveModulePath } from 'exsolve';
|
|
15
17
|
import { logger } from '../../dist/runtime/logger.js';
|
|
16
18
|
import { Launcher } from 'chrome-launcher';
|
|
17
19
|
import { detectPackageManager, addDependency } from 'nypm';
|
|
@@ -19,7 +21,6 @@ import { setupDevToolsUI as setupDevToolsUI$1, setupDevToolsRpc } from 'nuxtseo-
|
|
|
19
21
|
import { createStorage } from 'unstorage';
|
|
20
22
|
import fsDriver from 'unstorage/drivers/fs-lite';
|
|
21
23
|
import { resolveColorMix, GRADIENT_COLOR_SPACE_RE, splitCssDeclarations } from '../../dist/runtime/server/og-image/utils/css.js';
|
|
22
|
-
import MagicString from 'magic-string';
|
|
23
24
|
import { stripLiteral } from 'strip-literal';
|
|
24
25
|
import { parseURL, parseQuery } from 'ufo';
|
|
25
26
|
import { createUnplugin } from 'unplugin';
|
|
@@ -27,9 +28,81 @@ import { parse } from '@vue/compiler-sfc';
|
|
|
27
28
|
import { ofetch } from 'ofetch';
|
|
28
29
|
import { parse as parse$1, walkSync, ELEMENT_NODE as ELEMENT_NODE$2, renderSync } from 'ultrahtml';
|
|
29
30
|
import { RE_MATCH_EMOJIS, getEmojiCodePoint, getEmojiIconNames } from '../../dist/runtime/server/og-image/core/transforms/emojis/emoji-utils.js';
|
|
30
|
-
import { resolveModulePath } from 'exsolve';
|
|
31
31
|
import { p as promptFontsMigration } from './nuxt-og-image.CJa2KCie.mjs';
|
|
32
32
|
|
|
33
|
+
const valueTypes = { i: 127, p: 127, j: 126, f: 125, d: 124 };
|
|
34
|
+
function encodeLength(value) {
|
|
35
|
+
const bytes = [];
|
|
36
|
+
do {
|
|
37
|
+
const byte = value & 127;
|
|
38
|
+
value >>>= 7;
|
|
39
|
+
bytes.push(value ? byte | 128 : byte);
|
|
40
|
+
} while (value);
|
|
41
|
+
return bytes;
|
|
42
|
+
}
|
|
43
|
+
function createHarfBuzzCallbackModule(signature) {
|
|
44
|
+
const type = (character) => {
|
|
45
|
+
const value = valueTypes[character];
|
|
46
|
+
if (value === void 0)
|
|
47
|
+
throw new Error(`Unsupported HarfBuzz callback type: ${character}`);
|
|
48
|
+
return value;
|
|
49
|
+
};
|
|
50
|
+
const params = [...signature.slice(1)].map(type);
|
|
51
|
+
const results = signature[0] === "v" ? [] : [type(signature[0])];
|
|
52
|
+
const functionType = [1, 96, ...encodeLength(params.length), ...params, results.length, ...results];
|
|
53
|
+
return Uint8Array.from([
|
|
54
|
+
0,
|
|
55
|
+
97,
|
|
56
|
+
115,
|
|
57
|
+
109,
|
|
58
|
+
1,
|
|
59
|
+
0,
|
|
60
|
+
0,
|
|
61
|
+
0,
|
|
62
|
+
1,
|
|
63
|
+
...encodeLength(functionType.length),
|
|
64
|
+
...functionType,
|
|
65
|
+
2,
|
|
66
|
+
7,
|
|
67
|
+
1,
|
|
68
|
+
1,
|
|
69
|
+
101,
|
|
70
|
+
1,
|
|
71
|
+
102,
|
|
72
|
+
0,
|
|
73
|
+
0,
|
|
74
|
+
7,
|
|
75
|
+
5,
|
|
76
|
+
1,
|
|
77
|
+
1,
|
|
78
|
+
102,
|
|
79
|
+
0,
|
|
80
|
+
0
|
|
81
|
+
]);
|
|
82
|
+
}
|
|
83
|
+
async function prepareHarfBuzzCallbacks(adapterPath, outputDir) {
|
|
84
|
+
const signatures = /* @__PURE__ */ new Set();
|
|
85
|
+
parseAndWalk(await readFile(adapterPath, "utf8"), adapterPath, {
|
|
86
|
+
enter(node) {
|
|
87
|
+
if (node.type !== "CallExpression" || node.callee.type !== "Identifier" || node.callee.name !== "addFunction")
|
|
88
|
+
return;
|
|
89
|
+
const signature = node.arguments[1];
|
|
90
|
+
if (signature?.type === "Literal" && typeof signature.value === "string")
|
|
91
|
+
signatures.add(signature.value);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
await mkdir(outputDir, { recursive: true });
|
|
95
|
+
const entries = await Promise.all([...signatures].sort().map(async (signature) => {
|
|
96
|
+
const path = join(outputDir, `callback-${signature}.wasm`);
|
|
97
|
+
await writeFile(path, createHarfBuzzCallbackModule(signature));
|
|
98
|
+
return { signature, path };
|
|
99
|
+
}));
|
|
100
|
+
return [
|
|
101
|
+
...entries.map(({ signature, path }) => `import ${signature} from ${JSON.stringify(`${path}?module`)}`),
|
|
102
|
+
`export default { ${entries.map(({ signature }) => signature).join(", ")} }`
|
|
103
|
+
].join("\n");
|
|
104
|
+
}
|
|
105
|
+
|
|
33
106
|
const isUndefinedOrTruthy = (v) => typeof v === "undefined" || v !== false;
|
|
34
107
|
function checkLocalChrome() {
|
|
35
108
|
if (isCI)
|
|
@@ -276,6 +349,36 @@ async function applyNitroPresetCompatibility(nitroConfig, options) {
|
|
|
276
349
|
await applyBinding("sharp"),
|
|
277
350
|
nitroConfig.alias || {}
|
|
278
351
|
);
|
|
352
|
+
if (resolvedCompatibility.satori) {
|
|
353
|
+
const satoriPackage = await readPackageJSON(`${satoriPkgDir}/package.json`);
|
|
354
|
+
if (satoriPackage.dependencies?.harfbuzzjs) {
|
|
355
|
+
const harfbuzzWasmPath = resolveModulePath("harfbuzzjs/hb.wasm", { from: `${satoriPkgDir}/package.json` });
|
|
356
|
+
if (resolvedCompatibility.satori === "wasm" || target.replace(RE_LEGACY_SUFFIX, "") === "netlify-edge") {
|
|
357
|
+
const harfbuzzDir = harfbuzzWasmPath.slice(0, -"hb.wasm".length);
|
|
358
|
+
nitroConfig.virtual["#og-image/harfbuzz-callbacks"] = resolvedCompatibility.satori === "wasm" ? await prepareHarfBuzzCallbacks(`${harfbuzzDir}hbjs.js`, join(useNuxt().options.buildDir, "cache/og-image/harfbuzz")) : "export default undefined";
|
|
359
|
+
Object.assign(nitroConfig.alias, {
|
|
360
|
+
"harfbuzzjs": await resolve.resolvePath("./runtime/server/og-image/bindings/satori/harfbuzz"),
|
|
361
|
+
"#og-image/harfbuzz-factory": `${harfbuzzDir}hb.js`,
|
|
362
|
+
"#og-image/harfbuzz-adapter": `${harfbuzzDir}hbjs.js`
|
|
363
|
+
});
|
|
364
|
+
if (resolvedCompatibility.satori === "wasm") {
|
|
365
|
+
nitroConfig.alias["#og-image/harfbuzz-wasm"] = `${harfbuzzWasmPath}?module`;
|
|
366
|
+
} else {
|
|
367
|
+
const base64 = (await readFile(harfbuzzWasmPath)).toString("base64");
|
|
368
|
+
nitroConfig.virtual["#og-image/harfbuzz-wasm"] = `export default imports => WebAssembly.instantiate(Uint8Array.from(atob(${JSON.stringify(base64)}), c => c.charCodeAt(0)), imports)`;
|
|
369
|
+
}
|
|
370
|
+
} else if (Number.parseInt(getNuxtVersion(useNuxt()), 10) >= 5) {
|
|
371
|
+
const config = nitroConfig;
|
|
372
|
+
config.traceDeps = [.../* @__PURE__ */ new Set([...config.traceDeps || [], "harfbuzzjs*"])];
|
|
373
|
+
} else {
|
|
374
|
+
nitroConfig.externals = nitroConfig.externals || {};
|
|
375
|
+
nitroConfig.externals.traceInclude = [.../* @__PURE__ */ new Set([
|
|
376
|
+
...nitroConfig.externals.traceInclude || [],
|
|
377
|
+
harfbuzzWasmPath
|
|
378
|
+
])];
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
279
382
|
if (Object.values(resolvedCompatibility).includes("wasm")) {
|
|
280
383
|
nitroConfig.experimental = nitroConfig.experimental || {};
|
|
281
384
|
nitroConfig.experimental.wasm = true;
|
|
@@ -334,6 +437,27 @@ async function setupBuildHandler(config, resolve, getDetectedRenderers, getCompa
|
|
|
334
437
|
detectedRenderers: getDetectedRenderers(),
|
|
335
438
|
metadata: getCompatibilityMeta()
|
|
336
439
|
});
|
|
440
|
+
const rollupConfig = nitro.options.rollupConfig ||= { output: {} };
|
|
441
|
+
rollupConfig.plugins = [rollupConfig.plugins, {
|
|
442
|
+
name: "og-image-harfbuzz-worker",
|
|
443
|
+
transform(code, id) {
|
|
444
|
+
if (!nitro.options.alias["#og-image/harfbuzz-factory"] || !id.endsWith("/harfbuzzjs/hb.js"))
|
|
445
|
+
return;
|
|
446
|
+
const transformed = new MagicString(code);
|
|
447
|
+
parseAndWalk(code, id, {
|
|
448
|
+
enter(node) {
|
|
449
|
+
if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && node.id.name === "convertJsFunctionToWasm" && node.init) {
|
|
450
|
+
transformed.prependLeft(node.init.start, 'Module["convertJsFunctionToWasm"] || (');
|
|
451
|
+
transformed.appendRight(node.init.end, ")");
|
|
452
|
+
}
|
|
453
|
+
if (node.type === "VariableDeclarator" && node.id.type === "Identifier" && ["ENVIRONMENT_IS_NODE", "ENVIRONMENT_IS_WEB", "ENVIRONMENT_IS_WORKER"].includes(node.id.name) && node.init) {
|
|
454
|
+
transformed.overwrite(node.init.start, node.init.end, "false");
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
return { code: transformed.toString(), map: transformed.generateMap({ hires: true }).toString() };
|
|
459
|
+
}
|
|
460
|
+
}];
|
|
337
461
|
const target = resolveOgImagePreset(nitro.options);
|
|
338
462
|
const normalizedTarget = target.replace(RE_LEGACY_SUFFIX, "");
|
|
339
463
|
const isEdgePreset = ["cloudflare", "cloudflare-pages", "cloudflare-pages-static", "cloudflare-module", "cloudflare-durable", "vercel-edge", "netlify-edge"].includes(normalizedTarget);
|
|
@@ -2086,8 +2210,7 @@ async function initFontless(options) {
|
|
|
2086
2210
|
{
|
|
2087
2211
|
dev: false,
|
|
2088
2212
|
renderedFontURLs,
|
|
2089
|
-
assetsBaseURL: FONTS_URL_PREFIX
|
|
2090
|
-
callback: (filename, url) => renderedFontURLs.set(filename, url)
|
|
2213
|
+
assetsBaseURL: FONTS_URL_PREFIX
|
|
2091
2214
|
},
|
|
2092
2215
|
faces
|
|
2093
2216
|
),
|
|
@@ -2111,7 +2234,7 @@ async function initFontless(options) {
|
|
|
2111
2234
|
providers
|
|
2112
2235
|
});
|
|
2113
2236
|
options.logger?.debug(`fontless initialized with formats: ['woff', 'ttf'], subsets: ${JSON.stringify(options.fontSubsets || ["latin"])}, priority: ${JSON.stringify(nuxtFontsConfig?.priority || ["google", "bunny", "fontsource"])}`);
|
|
2114
|
-
options.nuxt._ogImageFontless = { resolver,
|
|
2237
|
+
options.nuxt._ogImageFontless = { resolver, providerNames: priority };
|
|
2115
2238
|
}
|
|
2116
2239
|
function persistFontUrlMapping(options) {
|
|
2117
2240
|
if (!options.fontContext?.renderedFontURLs.size)
|
|
@@ -2757,11 +2880,10 @@ function isVue(id, opts = {}) {
|
|
|
2757
2880
|
}
|
|
2758
2881
|
return true;
|
|
2759
2882
|
}
|
|
2760
|
-
const
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
}
|
|
2883
|
+
const VUE_RE = /\.vue(?:\?|$)/;
|
|
2884
|
+
const JS_RE = /\.[cm]?[jt]sx?(?:\?|$)/;
|
|
2885
|
+
const ISLANDS_RE = /components\.islands\.mjs(?:\?|$)/;
|
|
2886
|
+
const COMPOSABLE_CODE_MARKER = "defineOgImage";
|
|
2765
2887
|
const TreeShakeComposablesPlugin = createUnplugin(() => {
|
|
2766
2888
|
const composableNames = [
|
|
2767
2889
|
"defineOgImage",
|
|
@@ -2774,21 +2896,26 @@ const TreeShakeComposablesPlugin = createUnplugin(() => {
|
|
|
2774
2896
|
return {
|
|
2775
2897
|
name: "nuxt-og-image:zero-runtime:transform",
|
|
2776
2898
|
enforce: "pre",
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2899
|
+
transform: {
|
|
2900
|
+
filter: {
|
|
2901
|
+
// @todo re-implement composable tree-shaking for island files
|
|
2902
|
+
id: { include: [VUE_RE, JS_RE], exclude: [ISLANDS_RE] },
|
|
2903
|
+
code: COMPOSABLE_CODE_MARKER
|
|
2904
|
+
},
|
|
2905
|
+
handler(code, id) {
|
|
2906
|
+
if (VUE_RE.test(id) && !isVue(id, { type: ["script"] })) {
|
|
2907
|
+
return;
|
|
2908
|
+
}
|
|
2784
2909
|
if (!COMPOSABLE_RE.test(code)) {
|
|
2785
2910
|
return;
|
|
2786
2911
|
}
|
|
2787
|
-
|
|
2912
|
+
const s = new MagicString(code);
|
|
2913
|
+
for (const match of stripLiteral(code).matchAll(COMPOSABLE_RE_GLOBAL)) {
|
|
2788
2914
|
s.overwrite(match.index, match.index + match[0].length, `${match[1]} import.meta.prerender && ${match[2]}`);
|
|
2789
2915
|
}
|
|
2790
|
-
|
|
2791
|
-
|
|
2916
|
+
if (!s.hasChanged()) {
|
|
2917
|
+
return;
|
|
2918
|
+
}
|
|
2792
2919
|
return {
|
|
2793
2920
|
code: s.toString(),
|
|
2794
2921
|
map: s.generateMap({ hires: true })
|
|
@@ -3304,6 +3431,7 @@ const RE_SVG_ID_ATTR = /\bid="([^"]+)"/g;
|
|
|
3304
3431
|
const RE_SVG_VIEWBOX = /viewBox="([^"]*)"/;
|
|
3305
3432
|
const RE_SVG_BODY = /<svg[^>]*>([\s\S]*)<\/svg>/;
|
|
3306
3433
|
const RE_OG_IMAGE_QUERY$1 = /\?og-image(?:-depth=\d+)?$/;
|
|
3434
|
+
const RE_VUE_ID$1 = /\.vue(?:\?|$)/;
|
|
3307
3435
|
const RE_TEXT_BETWEEN_TAGS = />([^<]*)</g;
|
|
3308
3436
|
const RE_SPECIAL_REGEX_CHARS = /[.*+?^${}()|[\]\\]/g;
|
|
3309
3437
|
const RE_WRAPPER_DIV_START = /^<div>/;
|
|
@@ -3542,419 +3670,424 @@ const AssetTransformPlugin = createUnplugin((options) => {
|
|
|
3542
3670
|
return {
|
|
3543
3671
|
name: "nuxt-og-image:asset-transform",
|
|
3544
3672
|
enforce: "pre",
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
const bounds = getOuterTemplateBounds(code);
|
|
3557
|
-
if (!bounds)
|
|
3558
|
-
return;
|
|
3559
|
-
const s = new MagicString(code);
|
|
3560
|
-
const { templateStart, templateEnd } = bounds;
|
|
3561
|
-
let template = code.slice(templateStart, templateEnd);
|
|
3562
|
-
let hasChanges = false;
|
|
3563
|
-
if (options.emojiSet && RE_MATCH_EMOJIS.test(template)) {
|
|
3564
|
-
if (!emojiIcons) {
|
|
3565
|
-
emojiIcons = options.emojiIcons ?? await import(`@iconify-json/${options.emojiSet}/icons.json`, { with: { type: 'json' } }).then((m) => m.default).catch(() => {
|
|
3566
|
-
return null;
|
|
3567
|
-
});
|
|
3568
|
-
}
|
|
3569
|
-
RE_MATCH_EMOJIS.lastIndex = 0;
|
|
3570
|
-
const allEmojis = /* @__PURE__ */ new Set();
|
|
3571
|
-
for (const match of template.matchAll(RE_MATCH_EMOJIS)) {
|
|
3572
|
-
allEmojis.add(match[0]);
|
|
3673
|
+
transform: {
|
|
3674
|
+
filter: {
|
|
3675
|
+
id: RE_VUE_ID$1
|
|
3676
|
+
},
|
|
3677
|
+
async handler(code, rawId) {
|
|
3678
|
+
const isNested = RE_OG_IMAGE_QUERY$1.test(rawId);
|
|
3679
|
+
if (!isNested) {
|
|
3680
|
+
if (!rawId.endsWith(".vue"))
|
|
3681
|
+
return;
|
|
3682
|
+
if (!options.ogComponentPaths.some((dir) => rawId.startsWith(`${dir}/`) || rawId.startsWith(`${dir}\\`)))
|
|
3683
|
+
return;
|
|
3573
3684
|
}
|
|
3574
|
-
const
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3685
|
+
const id = rawId.replace(RE_OG_IMAGE_QUERY$1, "");
|
|
3686
|
+
if (isNested)
|
|
3687
|
+
options.onNestedTransform?.(id);
|
|
3688
|
+
const bounds = getOuterTemplateBounds(code);
|
|
3689
|
+
if (!bounds)
|
|
3690
|
+
return;
|
|
3691
|
+
const s = new MagicString(code);
|
|
3692
|
+
const { templateStart, templateEnd } = bounds;
|
|
3693
|
+
let template = code.slice(templateStart, templateEnd);
|
|
3694
|
+
let hasChanges = false;
|
|
3695
|
+
if (options.emojiSet && RE_MATCH_EMOJIS.test(template)) {
|
|
3696
|
+
if (!emojiIcons) {
|
|
3697
|
+
emojiIcons = options.emojiIcons ?? await import(`@iconify-json/${options.emojiSet}/icons.json`, { with: { type: 'json' } }).then((m) => m.default).catch(() => {
|
|
3698
|
+
return null;
|
|
3699
|
+
});
|
|
3579
3700
|
}
|
|
3580
|
-
|
|
3581
|
-
|
|
3701
|
+
RE_MATCH_EMOJIS.lastIndex = 0;
|
|
3702
|
+
const allEmojis = /* @__PURE__ */ new Set();
|
|
3703
|
+
for (const match of template.matchAll(RE_MATCH_EMOJIS)) {
|
|
3704
|
+
allEmojis.add(match[0]);
|
|
3582
3705
|
}
|
|
3583
|
-
|
|
3584
|
-
|
|
3706
|
+
const emojiSvgMap = /* @__PURE__ */ new Map();
|
|
3707
|
+
await Promise.all(Array.from(allEmojis, async (emoji) => {
|
|
3708
|
+
let svg = null;
|
|
3709
|
+
if (emojiIcons) {
|
|
3710
|
+
svg = buildEmojiSvg(emoji, emojiIcons, options.emojiSet);
|
|
3711
|
+
}
|
|
3712
|
+
if (!svg) {
|
|
3713
|
+
svg = await fetchEmojiSvg(emoji, options.emojiSet);
|
|
3714
|
+
}
|
|
3715
|
+
if (svg) {
|
|
3716
|
+
emojiSvgMap.set(emoji, svg);
|
|
3717
|
+
}
|
|
3718
|
+
}));
|
|
3719
|
+
if (emojiSvgMap.size > 0) {
|
|
3720
|
+
RE_TEXT_BETWEEN_TAGS.lastIndex = 0;
|
|
3721
|
+
template = template.replace(RE_TEXT_BETWEEN_TAGS, (fullMatch, textContent) => {
|
|
3722
|
+
if (!textContent)
|
|
3723
|
+
return fullMatch;
|
|
3724
|
+
RE_MATCH_EMOJIS.lastIndex = 0;
|
|
3725
|
+
const emojiMatches = [...textContent.matchAll(RE_MATCH_EMOJIS)];
|
|
3726
|
+
if (!emojiMatches.length)
|
|
3727
|
+
return fullMatch;
|
|
3728
|
+
let newTextContent = textContent;
|
|
3729
|
+
for (const match of emojiMatches) {
|
|
3730
|
+
const emoji = match[0];
|
|
3731
|
+
const svg = emojiSvgMap.get(emoji);
|
|
3732
|
+
if (svg) {
|
|
3733
|
+
hasChanges = true;
|
|
3734
|
+
const escaped = emoji.replace(RE_SPECIAL_REGEX_CHARS, "\\$&");
|
|
3735
|
+
newTextContent = newTextContent.replace(new RegExp(escaped, "g"), svg);
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
return `>${newTextContent}<`;
|
|
3739
|
+
});
|
|
3585
3740
|
}
|
|
3586
|
-
}
|
|
3587
|
-
if (
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
newTextContent = newTextContent.replace(new RegExp(escaped, "g"), svg);
|
|
3741
|
+
}
|
|
3742
|
+
if (template.includes("<Icon") || template.includes("<UIcon")) {
|
|
3743
|
+
const prefixes = /* @__PURE__ */ new Set();
|
|
3744
|
+
const iconElements = [];
|
|
3745
|
+
const wrappedTemplate = `<div>${template}</div>`;
|
|
3746
|
+
const doc = parse$1(wrappedTemplate);
|
|
3747
|
+
walkSync(doc, (node, parent, index) => {
|
|
3748
|
+
if (node.type === ELEMENT_NODE$2) {
|
|
3749
|
+
const el = node;
|
|
3750
|
+
if (el.name === "Icon" || el.name === "UIcon") {
|
|
3751
|
+
const iconName = el.attributes.name;
|
|
3752
|
+
if (iconName && !iconName.includes("{")) {
|
|
3753
|
+
const [prefix] = iconName.split(":");
|
|
3754
|
+
if (prefix)
|
|
3755
|
+
prefixes.add(prefix);
|
|
3756
|
+
iconElements.push({ node: el, parent, index });
|
|
3757
|
+
}
|
|
3604
3758
|
}
|
|
3605
3759
|
}
|
|
3606
|
-
return `>${newTextContent}<`;
|
|
3607
3760
|
});
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
const el = node;
|
|
3618
|
-
if (el.name === "Icon" || el.name === "UIcon") {
|
|
3761
|
+
const iconSets = /* @__PURE__ */ new Map();
|
|
3762
|
+
for (const prefix of prefixes) {
|
|
3763
|
+
const icons = await loadIconSet(prefix);
|
|
3764
|
+
if (icons)
|
|
3765
|
+
iconSets.set(prefix, icons);
|
|
3766
|
+
}
|
|
3767
|
+
if (iconElements.length > 0) {
|
|
3768
|
+
let anyReplaced = false;
|
|
3769
|
+
for (const { node: el, parent, index } of iconElements) {
|
|
3619
3770
|
const iconName = el.attributes.name;
|
|
3620
|
-
if (
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3771
|
+
if (!iconName)
|
|
3772
|
+
continue;
|
|
3773
|
+
const [prefix, name] = iconName.split(":");
|
|
3774
|
+
if (!prefix || !name)
|
|
3775
|
+
continue;
|
|
3776
|
+
const icons = iconSets.get(prefix);
|
|
3777
|
+
const iconData = icons?.icons?.[name];
|
|
3778
|
+
let svgHtml;
|
|
3779
|
+
if (iconData) {
|
|
3780
|
+
svgHtml = buildIconSvg(iconData, icons.width || 24, icons.height || 24, el.attributes);
|
|
3781
|
+
} else if (options.cssProvider?.resolveIcon) {
|
|
3782
|
+
const resolved = await options.cssProvider.resolveIcon(prefix, name);
|
|
3783
|
+
if (resolved)
|
|
3784
|
+
svgHtml = buildIconSvg(resolved, resolved.width, resolved.height, el.attributes);
|
|
3785
|
+
}
|
|
3786
|
+
if (!svgHtml)
|
|
3787
|
+
continue;
|
|
3788
|
+
anyReplaced = true;
|
|
3789
|
+
hasChanges = true;
|
|
3790
|
+
const svgDoc = parse$1(svgHtml);
|
|
3791
|
+
if ("children" in parent && Array.isArray(parent.children)) {
|
|
3792
|
+
parent.children[index] = svgDoc.children[0];
|
|
3625
3793
|
}
|
|
3626
3794
|
}
|
|
3795
|
+
if (anyReplaced) {
|
|
3796
|
+
const rendered = renderSync(doc);
|
|
3797
|
+
template = rendered.replace(RE_WRAPPER_DIV_START, "").replace(RE_WRAPPER_DIV_END, "");
|
|
3798
|
+
}
|
|
3627
3799
|
}
|
|
3628
|
-
});
|
|
3629
|
-
const iconSets = /* @__PURE__ */ new Map();
|
|
3630
|
-
for (const prefix of prefixes) {
|
|
3631
|
-
const icons = await loadIconSet(prefix);
|
|
3632
|
-
if (icons)
|
|
3633
|
-
iconSets.set(prefix, icons);
|
|
3634
3800
|
}
|
|
3635
|
-
if (
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
if (!prefix || !name)
|
|
3801
|
+
if (options.cssProvider?.resolveIcon) {
|
|
3802
|
+
const replacements = [];
|
|
3803
|
+
RE_ICON_ELEMENT.lastIndex = 0;
|
|
3804
|
+
let elMatch;
|
|
3805
|
+
while ((elMatch = RE_ICON_ELEMENT.exec(template)) !== null) {
|
|
3806
|
+
const [fullMatch, , attrsStr, classValue] = elMatch;
|
|
3807
|
+
if (!classValue)
|
|
3643
3808
|
continue;
|
|
3644
|
-
const
|
|
3645
|
-
|
|
3646
|
-
let
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3809
|
+
const classes = classValue.split(RE_WHITESPACE).filter(Boolean);
|
|
3810
|
+
let iconPrefix;
|
|
3811
|
+
let iconName;
|
|
3812
|
+
for (const cls of classes) {
|
|
3813
|
+
const im = cls.match(ICON_CLASS_RE);
|
|
3814
|
+
if (im?.[1] && im[2]) {
|
|
3815
|
+
iconPrefix = im[1];
|
|
3816
|
+
iconName = im[2];
|
|
3817
|
+
break;
|
|
3818
|
+
}
|
|
3653
3819
|
}
|
|
3654
|
-
if (!
|
|
3820
|
+
if (!iconPrefix || !iconName)
|
|
3655
3821
|
continue;
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3822
|
+
const resolved = await options.cssProvider.resolveIcon(iconPrefix, iconName);
|
|
3823
|
+
if (!resolved)
|
|
3824
|
+
continue;
|
|
3825
|
+
const attrs = {};
|
|
3826
|
+
RE_HTML_ATTR.lastIndex = 0;
|
|
3827
|
+
let am;
|
|
3828
|
+
while ((am = RE_HTML_ATTR.exec(attrsStr)) !== null) {
|
|
3829
|
+
if (am[1] && am[1] !== "class" && am[1] !== ":style" && am[1] !== "v-bind:style")
|
|
3830
|
+
attrs[am[1]] = am[2] ?? "";
|
|
3661
3831
|
}
|
|
3832
|
+
const otherClasses = classes.filter((c) => !isIconClass(c));
|
|
3833
|
+
if (otherClasses.length > 0)
|
|
3834
|
+
attrs.class = otherClasses.join(" ");
|
|
3835
|
+
const svgHtml = buildIconSvg(resolved, resolved.width, resolved.height, attrs);
|
|
3836
|
+
replacements.push({ from: fullMatch, to: svgHtml });
|
|
3662
3837
|
}
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3838
|
+
for (const { from, to } of replacements) {
|
|
3839
|
+
template = template.replace(from, to);
|
|
3840
|
+
hasChanges = true;
|
|
3666
3841
|
}
|
|
3667
3842
|
}
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
if (!classValue)
|
|
3676
|
-
continue;
|
|
3677
|
-
const classes = classValue.split(RE_WHITESPACE).filter(Boolean);
|
|
3678
|
-
let iconPrefix;
|
|
3679
|
-
let iconName;
|
|
3680
|
-
for (const cls of classes) {
|
|
3681
|
-
const im = cls.match(ICON_CLASS_RE);
|
|
3682
|
-
if (im?.[1] && im[2]) {
|
|
3683
|
-
iconPrefix = im[1];
|
|
3684
|
-
iconName = im[2];
|
|
3685
|
-
break;
|
|
3686
|
-
}
|
|
3687
|
-
}
|
|
3688
|
-
if (!iconPrefix || !iconName)
|
|
3689
|
-
continue;
|
|
3690
|
-
const resolved = await options.cssProvider.resolveIcon(iconPrefix, iconName);
|
|
3691
|
-
if (!resolved)
|
|
3692
|
-
continue;
|
|
3693
|
-
const attrs = {};
|
|
3694
|
-
RE_HTML_ATTR.lastIndex = 0;
|
|
3695
|
-
let am;
|
|
3696
|
-
while ((am = RE_HTML_ATTR.exec(attrsStr)) !== null) {
|
|
3697
|
-
if (am[1] && am[1] !== "class" && am[1] !== ":style" && am[1] !== "v-bind:style")
|
|
3698
|
-
attrs[am[1]] = am[2] ?? "";
|
|
3843
|
+
const rootAttrs = {};
|
|
3844
|
+
const rootAttrMatch = template.match(RE_ROOT_ELEMENT);
|
|
3845
|
+
if (rootAttrMatch?.[2]) {
|
|
3846
|
+
RE_DATA_ATTR.lastIndex = 0;
|
|
3847
|
+
for (const m of rootAttrMatch[2].matchAll(RE_DATA_ATTR)) {
|
|
3848
|
+
if (m[1] && m[2])
|
|
3849
|
+
rootAttrs[`data-${m[1]}`] = m[2];
|
|
3699
3850
|
}
|
|
3700
|
-
const otherClasses = classes.filter((c) => !isIconClass(c));
|
|
3701
|
-
if (otherClasses.length > 0)
|
|
3702
|
-
attrs.class = otherClasses.join(" ");
|
|
3703
|
-
const svgHtml = buildIconSvg(resolved, resolved.width, resolved.height, attrs);
|
|
3704
|
-
replacements.push({ from: fullMatch, to: svgHtml });
|
|
3705
|
-
}
|
|
3706
|
-
for (const { from, to } of replacements) {
|
|
3707
|
-
template = template.replace(from, to);
|
|
3708
|
-
hasChanges = true;
|
|
3709
|
-
}
|
|
3710
|
-
}
|
|
3711
|
-
const rootAttrs = {};
|
|
3712
|
-
const rootAttrMatch = template.match(RE_ROOT_ELEMENT);
|
|
3713
|
-
if (rootAttrMatch?.[2]) {
|
|
3714
|
-
RE_DATA_ATTR.lastIndex = 0;
|
|
3715
|
-
for (const m of rootAttrMatch[2].matchAll(RE_DATA_ATTR)) {
|
|
3716
|
-
if (m[1] && m[2])
|
|
3717
|
-
rootAttrs[`data-${m[1]}`] = m[2];
|
|
3718
3851
|
}
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3852
|
+
if (!rootAttrs["data-theme"] && options.colorPreference)
|
|
3853
|
+
rootAttrs["data-theme"] = options.colorPreference;
|
|
3854
|
+
const hasDynamicDataTheme = !!(rootAttrMatch?.[2] && RE_DYNAMIC_DATA_THEME.test(` ${rootAttrMatch[2]}`));
|
|
3855
|
+
if (options.cssProvider) {
|
|
3856
|
+
options.beforeCssResolve?.();
|
|
3857
|
+
try {
|
|
3858
|
+
const fullCode = code.slice(0, templateStart) + template + code.slice(templateEnd);
|
|
3859
|
+
const result = await transformVueTemplate(fullCode, {
|
|
3860
|
+
resolveStyles: async (classes) => {
|
|
3861
|
+
const supported = classes.filter((cls) => !isUnsupportedClass(cls) && !isIconClass(cls));
|
|
3862
|
+
const unsupported = classes.filter((cls) => isUnsupportedClass(cls));
|
|
3863
|
+
if (unsupported.length > 0) {
|
|
3864
|
+
const componentName2 = id.split("/").pop();
|
|
3865
|
+
logger.warn(`[nuxt-og-image] ${componentName2}: Filtered unsupported classes: ${unsupported.join(", ")}`);
|
|
3866
|
+
}
|
|
3867
|
+
const componentName = id.split("/").pop()?.replace(RE_FILE_EXTENSION, "");
|
|
3868
|
+
if (hasDynamicDataTheme) {
|
|
3869
|
+
const lightAttrs = { ...rootAttrs, "data-theme": "light" };
|
|
3870
|
+
const darkAttrs = { ...rootAttrs, "data-theme": "dark" };
|
|
3871
|
+
const [lightResolved, darkResolved] = await Promise.all([
|
|
3872
|
+
options.cssProvider.resolveClassesToStyles(supported, componentName, lightAttrs),
|
|
3873
|
+
options.cssProvider.resolveClassesToStyles(supported, componentName, darkAttrs)
|
|
3874
|
+
]);
|
|
3875
|
+
return mergeThemePairs(supported, lightResolved, darkResolved);
|
|
3876
|
+
}
|
|
3877
|
+
return options.cssProvider.resolveClassesToStyles(supported, componentName, rootAttrs);
|
|
3734
3878
|
}
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
options.cssProvider.resolveClassesToStyles(supported, componentName, darkAttrs)
|
|
3742
|
-
]);
|
|
3743
|
-
return mergeThemePairs(supported, lightResolved, darkResolved);
|
|
3879
|
+
});
|
|
3880
|
+
if (result) {
|
|
3881
|
+
const newBounds = getOuterTemplateBounds(result.code);
|
|
3882
|
+
if (newBounds) {
|
|
3883
|
+
template = result.code.slice(newBounds.templateStart, newBounds.templateEnd);
|
|
3884
|
+
hasChanges = true;
|
|
3744
3885
|
}
|
|
3745
|
-
return options.cssProvider.resolveClassesToStyles(supported, componentName, rootAttrs);
|
|
3746
|
-
}
|
|
3747
|
-
});
|
|
3748
|
-
if (result) {
|
|
3749
|
-
const newBounds = getOuterTemplateBounds(result.code);
|
|
3750
|
-
if (newBounds) {
|
|
3751
|
-
template = result.code.slice(newBounds.templateStart, newBounds.templateEnd);
|
|
3752
|
-
hasChanges = true;
|
|
3753
3886
|
}
|
|
3887
|
+
} catch (err) {
|
|
3888
|
+
const componentName = id.split("/").pop();
|
|
3889
|
+
logger.warn(`[nuxt-og-image] ${componentName}: CSS template transform failed, using original template`, err.message);
|
|
3754
3890
|
}
|
|
3755
|
-
} catch (err) {
|
|
3756
|
-
const componentName = id.split("/").pop();
|
|
3757
|
-
logger.warn(`[nuxt-og-image] ${componentName}: CSS template transform failed, using original template`, err.message);
|
|
3758
3891
|
}
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
vars.set(name, def[2].trim());
|
|
3769
|
-
}
|
|
3770
|
-
}
|
|
3771
|
-
if (vars.size > 0) {
|
|
3772
|
-
const replacements = [];
|
|
3773
|
-
RE_NON_STYLE_VAR_ATTR.lastIndex = 0;
|
|
3774
|
-
template.replace(RE_NON_STYLE_VAR_ATTR, (match, attr, value) => {
|
|
3775
|
-
const resolved = resolveCssVars(value, vars);
|
|
3776
|
-
if (resolved !== value) {
|
|
3777
|
-
replacements.push({ from: match, to: "", attr, value: resolved });
|
|
3892
|
+
if (template.includes("var(")) {
|
|
3893
|
+
const vars = options.cssProvider?.getVars ? await options.cssProvider.getVars(rootAttrs) : /* @__PURE__ */ new Map();
|
|
3894
|
+
RE_INLINE_STYLE.lastIndex = 0;
|
|
3895
|
+
for (const m of template.matchAll(RE_INLINE_STYLE)) {
|
|
3896
|
+
RE_CSS_VAR_DEF.lastIndex = 0;
|
|
3897
|
+
for (const def of m[1].matchAll(RE_CSS_VAR_DEF)) {
|
|
3898
|
+
const name = `--${def[1]}`;
|
|
3899
|
+
if (!vars.has(name))
|
|
3900
|
+
vars.set(name, def[2].trim());
|
|
3778
3901
|
}
|
|
3779
|
-
return match;
|
|
3780
|
-
});
|
|
3781
|
-
for (const r of replacements) {
|
|
3782
|
-
let value = r.value;
|
|
3783
|
-
if (RE_COLOR_ATTR_NAME.test(r.attr)) {
|
|
3784
|
-
value = await downlevelColor(r.attr, value);
|
|
3785
|
-
}
|
|
3786
|
-
r.to = `${r.attr}="${escapeAttrValue(value)}"`;
|
|
3787
|
-
template = template.replace(r.from, r.to);
|
|
3788
|
-
hasChanges = true;
|
|
3789
3902
|
}
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
const
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
downleveled.push(decl);
|
|
3805
|
-
continue;
|
|
3903
|
+
if (vars.size > 0) {
|
|
3904
|
+
const replacements = [];
|
|
3905
|
+
RE_NON_STYLE_VAR_ATTR.lastIndex = 0;
|
|
3906
|
+
template.replace(RE_NON_STYLE_VAR_ATTR, (match, attr, value) => {
|
|
3907
|
+
const resolved = resolveCssVars(value, vars);
|
|
3908
|
+
if (resolved !== value) {
|
|
3909
|
+
replacements.push({ from: match, to: "", attr, value: resolved });
|
|
3910
|
+
}
|
|
3911
|
+
return match;
|
|
3912
|
+
});
|
|
3913
|
+
for (const r of replacements) {
|
|
3914
|
+
let value = r.value;
|
|
3915
|
+
if (RE_COLOR_ATTR_NAME.test(r.attr)) {
|
|
3916
|
+
value = await downlevelColor(r.attr, value);
|
|
3806
3917
|
}
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3918
|
+
r.to = `${r.attr}="${escapeAttrValue(value)}"`;
|
|
3919
|
+
template = template.replace(r.from, r.to);
|
|
3920
|
+
hasChanges = true;
|
|
3921
|
+
}
|
|
3922
|
+
const styleReplacements = [];
|
|
3923
|
+
RE_STYLE_VAR_ATTR.lastIndex = 0;
|
|
3924
|
+
template.replace(RE_STYLE_VAR_ATTR, (match, styleValue) => {
|
|
3925
|
+
const resolved = resolveCssVars(styleValue, vars);
|
|
3926
|
+
if (resolved !== styleValue)
|
|
3927
|
+
styleReplacements.push({ from: match, content: resolved });
|
|
3928
|
+
return match;
|
|
3929
|
+
});
|
|
3930
|
+
for (const r of styleReplacements) {
|
|
3931
|
+
const declarations = r.content.split(";").filter(Boolean);
|
|
3932
|
+
const downleveled = [];
|
|
3933
|
+
for (const decl of declarations) {
|
|
3934
|
+
const colonIdx = decl.indexOf(":");
|
|
3935
|
+
if (colonIdx === -1) {
|
|
3936
|
+
downleveled.push(decl);
|
|
3937
|
+
continue;
|
|
3938
|
+
}
|
|
3939
|
+
const prop = decl.slice(0, colonIdx).trim();
|
|
3940
|
+
let value = decl.slice(colonIdx + 1).trim();
|
|
3941
|
+
if (RE_COLOR_PROP_NAME.test(prop) && !value.includes("var(")) {
|
|
3942
|
+
value = await downlevelColor(prop, value);
|
|
3943
|
+
if (value.includes("color-mix("))
|
|
3944
|
+
value = resolveColorMix(value);
|
|
3945
|
+
}
|
|
3946
|
+
downleveled.push(`${prop}: ${value}`);
|
|
3813
3947
|
}
|
|
3814
|
-
downleveled.
|
|
3948
|
+
const to = `style="${escapeAttrValue(downleveled.join("; "))}"`;
|
|
3949
|
+
template = template.replace(r.from, to);
|
|
3950
|
+
hasChanges = true;
|
|
3951
|
+
}
|
|
3952
|
+
RE_DYNAMIC_STYLE_VAR.lastIndex = 0;
|
|
3953
|
+
const dynamicReplacements = [];
|
|
3954
|
+
template.replace(RE_DYNAMIC_STYLE_VAR, (match, styleExpr) => {
|
|
3955
|
+
const resolved = resolveCssVars(styleExpr, vars);
|
|
3956
|
+
if (resolved !== styleExpr)
|
|
3957
|
+
dynamicReplacements.push({ from: match, to: `:style="${resolved}"` });
|
|
3958
|
+
return match;
|
|
3959
|
+
});
|
|
3960
|
+
for (const r of dynamicReplacements) {
|
|
3961
|
+
template = template.replace(r.from, r.to);
|
|
3962
|
+
hasChanges = true;
|
|
3815
3963
|
}
|
|
3816
|
-
const to = `style="${escapeAttrValue(downleveled.join("; "))}"`;
|
|
3817
|
-
template = template.replace(r.from, to);
|
|
3818
|
-
hasChanges = true;
|
|
3819
|
-
}
|
|
3820
|
-
RE_DYNAMIC_STYLE_VAR.lastIndex = 0;
|
|
3821
|
-
const dynamicReplacements = [];
|
|
3822
|
-
template.replace(RE_DYNAMIC_STYLE_VAR, (match, styleExpr) => {
|
|
3823
|
-
const resolved = resolveCssVars(styleExpr, vars);
|
|
3824
|
-
if (resolved !== styleExpr)
|
|
3825
|
-
dynamicReplacements.push({ from: match, to: `:style="${resolved}"` });
|
|
3826
|
-
return match;
|
|
3827
|
-
});
|
|
3828
|
-
for (const r of dynamicReplacements) {
|
|
3829
|
-
template = template.replace(r.from, r.to);
|
|
3830
|
-
hasChanges = true;
|
|
3831
3964
|
}
|
|
3832
3965
|
}
|
|
3833
|
-
|
|
3834
|
-
if (!template.includes("data-no-inline")) {
|
|
3835
|
-
RE_IMAGE_SRC.lastIndex = 0;
|
|
3836
|
-
if (RE_IMAGE_SRC.test(template)) {
|
|
3966
|
+
if (!template.includes("data-no-inline")) {
|
|
3837
3967
|
RE_IMAGE_SRC.lastIndex = 0;
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
resolvedPath
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3968
|
+
if (RE_IMAGE_SRC.test(template)) {
|
|
3969
|
+
RE_IMAGE_SRC.lastIndex = 0;
|
|
3970
|
+
const componentDir = dirname(id);
|
|
3971
|
+
const replacements = [];
|
|
3972
|
+
let match;
|
|
3973
|
+
while ((match = RE_IMAGE_SRC.exec(template)) !== null) {
|
|
3974
|
+
const [fullMatch, srcPath, ext] = match;
|
|
3975
|
+
if (!srcPath || !ext)
|
|
3976
|
+
continue;
|
|
3977
|
+
if (srcPath.startsWith("data:") || srcPath.startsWith("http"))
|
|
3978
|
+
continue;
|
|
3979
|
+
let resolvedPath;
|
|
3980
|
+
if (srcPath.startsWith("/")) {
|
|
3981
|
+
resolvedPath = join(options.publicDir, srcPath);
|
|
3982
|
+
} else if (srcPath.startsWith("~/") || srcPath.startsWith("@/")) {
|
|
3983
|
+
resolvedPath = join(options.srcDir, srcPath.slice(2));
|
|
3984
|
+
} else if (!isAbsolute(srcPath)) {
|
|
3985
|
+
resolvedPath = resolve(componentDir, srcPath);
|
|
3986
|
+
} else {
|
|
3987
|
+
continue;
|
|
3988
|
+
}
|
|
3989
|
+
const fileBuffer = await readFile(resolvedPath).catch(() => {
|
|
3990
|
+
return null;
|
|
3991
|
+
});
|
|
3992
|
+
if (!fileBuffer)
|
|
3993
|
+
continue;
|
|
3994
|
+
const mimeType = getMimeType(ext);
|
|
3995
|
+
let dataUri;
|
|
3996
|
+
if (ext === "svg") {
|
|
3997
|
+
const svgContent = fileBuffer.toString("utf-8");
|
|
3998
|
+
dataUri = `data:${mimeType},${encodeURIComponent(svgContent)}`;
|
|
3999
|
+
} else {
|
|
4000
|
+
const base64 = fileBuffer.toString("base64");
|
|
4001
|
+
dataUri = `data:${mimeType};base64,${base64}`;
|
|
4002
|
+
}
|
|
4003
|
+
replacements.push({ from: fullMatch, to: `src="${dataUri}"` });
|
|
4004
|
+
hasChanges = true;
|
|
3856
4005
|
}
|
|
3857
|
-
const
|
|
3858
|
-
|
|
3859
|
-
});
|
|
3860
|
-
if (!fileBuffer)
|
|
3861
|
-
continue;
|
|
3862
|
-
const mimeType = getMimeType(ext);
|
|
3863
|
-
let dataUri;
|
|
3864
|
-
if (ext === "svg") {
|
|
3865
|
-
const svgContent = fileBuffer.toString("utf-8");
|
|
3866
|
-
dataUri = `data:${mimeType},${encodeURIComponent(svgContent)}`;
|
|
3867
|
-
} else {
|
|
3868
|
-
const base64 = fileBuffer.toString("base64");
|
|
3869
|
-
dataUri = `data:${mimeType};base64,${base64}`;
|
|
4006
|
+
for (const { from, to } of replacements) {
|
|
4007
|
+
template = template.replace(from, to);
|
|
3870
4008
|
}
|
|
3871
|
-
replacements.push({ from: fullMatch, to: `src="${dataUri}"` });
|
|
3872
|
-
hasChanges = true;
|
|
3873
|
-
}
|
|
3874
|
-
for (const { from, to } of replacements) {
|
|
3875
|
-
template = template.replace(from, to);
|
|
3876
4009
|
}
|
|
3877
4010
|
}
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
4011
|
+
{
|
|
4012
|
+
const { descriptor } = parse(code);
|
|
4013
|
+
if (descriptor.styles.length > 0) {
|
|
4014
|
+
for (const styleBlock of descriptor.styles) {
|
|
4015
|
+
const rawCss = styleBlock.content;
|
|
4016
|
+
const scopeId = styleBlock.scoped ? rawCss.match(RE_SCOPED_DATA_V)?.[0] ?? null : null;
|
|
4017
|
+
const cleanCss = scopeId ? rawCss.replaceAll(scopeId, "") : rawCss;
|
|
4018
|
+
const simplified = await simplifyCss(cleanCss);
|
|
4019
|
+
const classMap = extractClassStyles(simplified, { skipPrefixes: [] });
|
|
4020
|
+
if (classMap.size > 0) {
|
|
4021
|
+
const wrappedTemplate = `<div>${template}</div>`;
|
|
4022
|
+
const doc = parse$1(wrappedTemplate);
|
|
4023
|
+
walkSync(doc, (node) => {
|
|
4024
|
+
if (node.type !== ELEMENT_NODE$2)
|
|
4025
|
+
return;
|
|
4026
|
+
const el = node;
|
|
4027
|
+
const classAttr = el.attributes?.class;
|
|
4028
|
+
if (!classAttr)
|
|
4029
|
+
return;
|
|
4030
|
+
const elClasses = classAttr.split(RE_WHITESPACE).filter(Boolean);
|
|
4031
|
+
const matchedStyles = {};
|
|
4032
|
+
const consumedClasses = /* @__PURE__ */ new Set();
|
|
4033
|
+
for (const cls of elClasses) {
|
|
4034
|
+
const styles = classMap.get(cls);
|
|
4035
|
+
if (styles) {
|
|
4036
|
+
Object.assign(matchedStyles, styles);
|
|
4037
|
+
consumedClasses.add(cls);
|
|
4038
|
+
}
|
|
3906
4039
|
}
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
}
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
4040
|
+
if (Object.keys(matchedStyles).length === 0)
|
|
4041
|
+
return;
|
|
4042
|
+
const existingStyle = el.attributes?.style || "";
|
|
4043
|
+
const existingProps = {};
|
|
4044
|
+
for (const decl of splitCssDeclarations(existingStyle)) {
|
|
4045
|
+
const [prop, ...valParts] = decl.split(":");
|
|
4046
|
+
const value = valParts.join(":").trim();
|
|
4047
|
+
if (prop?.trim() && value)
|
|
4048
|
+
existingProps[prop.trim()] = value;
|
|
4049
|
+
}
|
|
4050
|
+
const merged = { ...matchedStyles, ...existingProps };
|
|
4051
|
+
el.attributes.style = escapeAttrValue(
|
|
4052
|
+
Object.entries(merged).map(([p, v]) => `${p}:${v}`).join(";")
|
|
4053
|
+
);
|
|
4054
|
+
const remaining = elClasses.filter((c) => !consumedClasses.has(c));
|
|
4055
|
+
if (remaining.length > 0)
|
|
4056
|
+
el.attributes.class = remaining.join(" ");
|
|
4057
|
+
else
|
|
4058
|
+
delete el.attributes.class;
|
|
4059
|
+
if (el.attributes.viewbox) {
|
|
4060
|
+
el.attributes.viewBox = el.attributes.viewbox;
|
|
4061
|
+
delete el.attributes.viewbox;
|
|
4062
|
+
}
|
|
4063
|
+
});
|
|
4064
|
+
template = renderSync(doc).replace(RE_WRAPPER_DIV_START, "").replace(RE_WRAPPER_DIV_END, "");
|
|
4065
|
+
hasChanges = true;
|
|
4066
|
+
}
|
|
3934
4067
|
}
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
4068
|
+
for (const styleBlock of descriptor.styles) {
|
|
4069
|
+
const styleStart = code.indexOf(styleBlock.loc.source) - "<style".length;
|
|
4070
|
+
const fullTagStart = code.lastIndexOf("<style", styleStart + "<style".length);
|
|
4071
|
+
const fullTagEnd = code.indexOf("</style>", styleStart) + "</style>".length;
|
|
4072
|
+
if (fullTagStart >= 0 && fullTagEnd > fullTagStart) {
|
|
4073
|
+
s.remove(fullTagStart, fullTagEnd);
|
|
4074
|
+
}
|
|
3942
4075
|
}
|
|
3943
4076
|
}
|
|
3944
4077
|
}
|
|
4078
|
+
if (options.onFontRequirements) {
|
|
4079
|
+
extractFontRequirementsFromVue(code).then((reqs) => {
|
|
4080
|
+
options.onFontRequirements(id, reqs);
|
|
4081
|
+
});
|
|
4082
|
+
}
|
|
4083
|
+
if (!hasChanges)
|
|
4084
|
+
return;
|
|
4085
|
+
s.overwrite(templateStart, templateEnd, template);
|
|
4086
|
+
return {
|
|
4087
|
+
code: s.toString(),
|
|
4088
|
+
map: s.generateMap({ hires: true })
|
|
4089
|
+
};
|
|
3945
4090
|
}
|
|
3946
|
-
if (options.onFontRequirements) {
|
|
3947
|
-
extractFontRequirementsFromVue(code).then((reqs) => {
|
|
3948
|
-
options.onFontRequirements(id, reqs);
|
|
3949
|
-
});
|
|
3950
|
-
}
|
|
3951
|
-
if (!hasChanges)
|
|
3952
|
-
return;
|
|
3953
|
-
s.overwrite(templateStart, templateEnd, template);
|
|
3954
|
-
return {
|
|
3955
|
-
code: s.toString(),
|
|
3956
|
-
map: s.generateMap({ hires: true })
|
|
3957
|
-
};
|
|
3958
4091
|
}
|
|
3959
4092
|
};
|
|
3960
4093
|
});
|
|
@@ -4145,94 +4278,99 @@ const BUILTIN_COMPONENTS = /* @__PURE__ */ new Set([
|
|
|
4145
4278
|
const MAX_IMPORT_REWRITE_DEPTH = 5;
|
|
4146
4279
|
const RE_OG_IMAGE_QUERY = /\?og-image(?:-depth=(\d+))?$/;
|
|
4147
4280
|
const RE_VUE_IMPORT = /import\s+(\w+)\s+from\s+(['"])(.+?\.vue)\2/g;
|
|
4281
|
+
const RE_VUE_ID = /\.vue(?:\?|$)/;
|
|
4148
4282
|
const ComponentImportRewritePlugin = createUnplugin((options) => {
|
|
4149
4283
|
return {
|
|
4150
4284
|
name: "nuxt-og-image:component-import-rewrite",
|
|
4151
4285
|
enforce: "pre",
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
if (!descriptor.template?.ast) {
|
|
4168
|
-
return;
|
|
4169
|
-
}
|
|
4170
|
-
const usedComponents = /* @__PURE__ */ new Set();
|
|
4171
|
-
walkTemplateAst(descriptor.template.ast.children, (node) => {
|
|
4172
|
-
if (node.type === 1 && !HTML_ELEMENTS.has(node.tag) && !BUILTIN_COMPONENTS.has(node.tag)) {
|
|
4173
|
-
usedComponents.add(node.tag);
|
|
4286
|
+
transform: {
|
|
4287
|
+
filter: {
|
|
4288
|
+
id: RE_VUE_ID
|
|
4289
|
+
},
|
|
4290
|
+
handler(code, rawId) {
|
|
4291
|
+
const depthMatch = rawId.match(RE_OG_IMAGE_QUERY);
|
|
4292
|
+
const currentDepth = depthMatch?.[1] ? Number.parseInt(depthMatch[1]) : 0;
|
|
4293
|
+
if (depthMatch) {
|
|
4294
|
+
if (currentDepth >= MAX_IMPORT_REWRITE_DEPTH)
|
|
4295
|
+
return;
|
|
4296
|
+
} else {
|
|
4297
|
+
if (!rawId.endsWith(".vue"))
|
|
4298
|
+
return;
|
|
4299
|
+
if (!options.ogComponentPaths.some((dir) => rawId.startsWith(`${dir}/`) || rawId.startsWith(`${dir}\\`)))
|
|
4300
|
+
return;
|
|
4174
4301
|
}
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
const components = options.getComponents();
|
|
4180
|
-
const newImports = [];
|
|
4181
|
-
for (const tag of usedComponents) {
|
|
4182
|
-
if (tag === "Icon" || tag === "UIcon")
|
|
4183
|
-
continue;
|
|
4184
|
-
const match = components.find((c) => c.pascalName === tag || c.kebabName === tag);
|
|
4185
|
-
if (match?.filePath && match.filePath.endsWith(".vue")) {
|
|
4186
|
-
newImports.push({ name: tag, filePath: match.filePath });
|
|
4302
|
+
const nextQuery = `?og-image-depth=${currentDepth + 1}`;
|
|
4303
|
+
const { descriptor } = parse(code);
|
|
4304
|
+
if (!descriptor.template?.ast) {
|
|
4305
|
+
return;
|
|
4187
4306
|
}
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
const s = new MagicString(code);
|
|
4193
|
-
const rewritten = /* @__PURE__ */ new Set();
|
|
4194
|
-
const scriptBlock = descriptor.scriptSetup || descriptor.script;
|
|
4195
|
-
if (scriptBlock) {
|
|
4196
|
-
const scriptStart = scriptBlock.loc.start.offset;
|
|
4197
|
-
const scriptContent = scriptBlock.content;
|
|
4198
|
-
for (const m of scriptContent.matchAll(RE_VUE_IMPORT)) {
|
|
4199
|
-
const importName = m[1];
|
|
4200
|
-
if (newImports.some((i) => i.name === importName)) {
|
|
4201
|
-
const source = m[3];
|
|
4202
|
-
const matchStart = scriptStart + m.index + m[0].indexOf(source);
|
|
4203
|
-
s.overwrite(matchStart, matchStart + source.length, `${source}${nextQuery}`);
|
|
4204
|
-
rewritten.add(importName);
|
|
4307
|
+
const usedComponents = /* @__PURE__ */ new Set();
|
|
4308
|
+
walkTemplateAst(descriptor.template.ast.children, (node) => {
|
|
4309
|
+
if (node.type === 1 && !HTML_ELEMENTS.has(node.tag) && !BUILTIN_COMPONENTS.has(node.tag)) {
|
|
4310
|
+
usedComponents.add(node.tag);
|
|
4205
4311
|
}
|
|
4312
|
+
});
|
|
4313
|
+
if (usedComponents.size === 0) {
|
|
4314
|
+
return;
|
|
4206
4315
|
}
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4316
|
+
const components = options.getComponents();
|
|
4317
|
+
const newImports = [];
|
|
4318
|
+
for (const tag of usedComponents) {
|
|
4319
|
+
if (tag === "Icon" || tag === "UIcon")
|
|
4320
|
+
continue;
|
|
4321
|
+
const match = components.find((c) => c.pascalName === tag || c.kebabName === tag);
|
|
4322
|
+
if (match?.filePath && match.filePath.endsWith(".vue")) {
|
|
4323
|
+
newImports.push({ name: tag, filePath: match.filePath });
|
|
4324
|
+
}
|
|
4325
|
+
}
|
|
4326
|
+
if (newImports.length === 0) {
|
|
4327
|
+
return;
|
|
4328
|
+
}
|
|
4329
|
+
const s = new MagicString(code);
|
|
4330
|
+
const rewritten = /* @__PURE__ */ new Set();
|
|
4331
|
+
const scriptBlock = descriptor.scriptSetup || descriptor.script;
|
|
4332
|
+
if (scriptBlock) {
|
|
4333
|
+
const scriptStart = scriptBlock.loc.start.offset;
|
|
4334
|
+
const scriptContent = scriptBlock.content;
|
|
4335
|
+
for (const m of scriptContent.matchAll(RE_VUE_IMPORT)) {
|
|
4336
|
+
const importName = m[1];
|
|
4337
|
+
if (newImports.some((i) => i.name === importName)) {
|
|
4338
|
+
const source = m[3];
|
|
4339
|
+
const matchStart = scriptStart + m.index + m[0].indexOf(source);
|
|
4340
|
+
s.overwrite(matchStart, matchStart + source.length, `${source}${nextQuery}`);
|
|
4341
|
+
rewritten.add(importName);
|
|
4342
|
+
}
|
|
4343
|
+
}
|
|
4344
|
+
}
|
|
4345
|
+
const imports = newImports.filter((i) => !rewritten.has(i.name));
|
|
4346
|
+
if (imports.length === 0) {
|
|
4347
|
+
return {
|
|
4348
|
+
code: s.toString(),
|
|
4349
|
+
map: s.generateMap({ hires: true })
|
|
4350
|
+
};
|
|
4351
|
+
}
|
|
4352
|
+
const importStatements = imports.map((i) => `import ${i.name} from '${i.filePath}${nextQuery}'`).join("\n");
|
|
4353
|
+
if (descriptor.scriptSetup) {
|
|
4354
|
+
const scriptSetupStart = code.indexOf("<script setup");
|
|
4355
|
+
const tagEnd = code.indexOf(">", scriptSetupStart) + 1;
|
|
4356
|
+
s.appendRight(tagEnd, `
|
|
4220
4357
|
${importStatements}`);
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4358
|
+
} else if (descriptor.script) {
|
|
4359
|
+
const scriptStart = code.indexOf("<script");
|
|
4360
|
+
const tagEnd = code.indexOf(">", scriptStart) + 1;
|
|
4361
|
+
s.appendRight(tagEnd, `
|
|
4225
4362
|
${importStatements}`);
|
|
4226
|
-
|
|
4227
|
-
|
|
4363
|
+
} else {
|
|
4364
|
+
s.prepend(`<script setup>
|
|
4228
4365
|
${importStatements}
|
|
4229
4366
|
<\/script>
|
|
4230
4367
|
`);
|
|
4368
|
+
}
|
|
4369
|
+
return {
|
|
4370
|
+
code: s.toString(),
|
|
4371
|
+
map: s.generateMap({ hires: true })
|
|
4372
|
+
};
|
|
4231
4373
|
}
|
|
4232
|
-
return {
|
|
4233
|
-
code: s.toString(),
|
|
4234
|
-
map: s.generateMap({ hires: true })
|
|
4235
|
-
};
|
|
4236
4374
|
}
|
|
4237
4375
|
};
|
|
4238
4376
|
});
|
|
@@ -4948,6 +5086,8 @@ const module$1 = defineNuxtModule({
|
|
|
4948
5086
|
return;
|
|
4949
5087
|
}
|
|
4950
5088
|
const nitroCompatibility = setupNitroRuntimeCompatibility(nuxt);
|
|
5089
|
+
if (nuxt.options.dev && nitroCompatibility._tag === "nitro-v2")
|
|
5090
|
+
nuxt.options.nitro.noExternals ??= false;
|
|
4951
5091
|
const setRuntimeAlias = (id, path) => {
|
|
4952
5092
|
nuxt.options.alias[id] = path;
|
|
4953
5093
|
nuxt.options.nitro.alias ||= {};
|
|
@@ -5284,7 +5424,7 @@ ${familyInfo}`);
|
|
|
5284
5424
|
}
|
|
5285
5425
|
});
|
|
5286
5426
|
if (!nuxt.options.dev) {
|
|
5287
|
-
addBuildPlugin(TreeShakeComposablesPlugin, { server: true, client: true
|
|
5427
|
+
addBuildPlugin(TreeShakeComposablesPlugin, { server: true, client: true });
|
|
5288
5428
|
setRuntimeAlias("#og-image-cache", resolve("./runtime/server/og-image/cache/mock"));
|
|
5289
5429
|
}
|
|
5290
5430
|
}
|
|
@@ -5893,6 +6033,7 @@ export const staticFontCacheDir = ${JSON.stringify(getStaticFontCacheDir(nuxt.op
|
|
|
5893
6033
|
colorPreference = colorModeOptions.fallback;
|
|
5894
6034
|
if (!colorPreference || colorPreference === "system")
|
|
5895
6035
|
colorPreference = "light";
|
|
6036
|
+
const includeTwitter = config.includeTwitter ?? nuxt.options.seo?.automaticTwitterTags ?? true;
|
|
5896
6037
|
const runtimeConfig = {
|
|
5897
6038
|
version,
|
|
5898
6039
|
// binding options
|
|
@@ -5902,6 +6043,7 @@ export const staticFontCacheDir = ${JSON.stringify(getStaticFontCacheDir(nuxt.op
|
|
|
5902
6043
|
publicStoragePath: `root${publicDirAbs.replace(nuxt.options.rootDir, "").replaceAll("/", ":")}`,
|
|
5903
6044
|
defaults: config.defaults,
|
|
5904
6045
|
debug: config.debug,
|
|
6046
|
+
includeTwitter,
|
|
5905
6047
|
// avoid adding credentials
|
|
5906
6048
|
baseCacheKey,
|
|
5907
6049
|
buildCacheDir,
|
|
@@ -5943,6 +6085,7 @@ export const staticFontCacheDir = ${JSON.stringify(getStaticFontCacheDir(nuxt.op
|
|
|
5943
6085
|
...nuxt.options.runtimeConfig.public,
|
|
5944
6086
|
"nuxt-og-image": {
|
|
5945
6087
|
defaults: runtimeConfig.defaults,
|
|
6088
|
+
includeTwitter: runtimeConfig.includeTwitter,
|
|
5946
6089
|
hasServerRuntime: !nuxt.options._generate && !nuxt.options.nitro?.static
|
|
5947
6090
|
}
|
|
5948
6091
|
};
|