nuxt-og-image 6.0.6 → 6.1.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.cjs +4 -4
- package/dist/chunks/tw4.mjs +4 -4
- package/dist/chunks/uno.cjs +2 -2
- package/dist/chunks/uno.mjs +2 -2
- package/dist/cli.cjs +471 -13
- package/dist/cli.mjs +473 -15
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/{DQ3A3fXi.js → BMN50qUN.js} +1 -1
- package/dist/client/_nuxt/Benf5wAR.js +1 -0
- package/dist/client/_nuxt/{BWSU2rm-.js → CUHt7c2i.js} +1 -1
- package/dist/client/_nuxt/D8rANzxA.js +1 -0
- package/dist/client/_nuxt/DDjmUBWb.js +1 -0
- package/dist/client/_nuxt/DVjjsoab.js +3860 -0
- package/dist/client/_nuxt/Dp-uF0ca.js +3 -0
- package/dist/client/_nuxt/IFrameLoader.HTWy4e5S.css +1 -0
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/d1aecffe-1f20-4eff-ae9c-8206db4e03f8.json +1 -0
- package/dist/client/_nuxt/entry.CjxjoX5J.css +2 -0
- package/dist/client/_nuxt/error-404.CvxVKLRw.css +1 -0
- package/dist/client/_nuxt/error-500.9lyObXc1.css +1 -0
- package/dist/client/_nuxt/p4iQRQB2.js +2 -0
- package/dist/client/_nuxt/{pages.JfmTAseD.css → pages.CVzrVadZ.css} +1 -1
- package/dist/client/_nuxt/xGJq_Sw1.js +181 -0
- package/dist/client/debug/index.html +1 -1
- package/dist/client/docs/index.html +1 -1
- package/dist/client/index.html +1 -1
- package/dist/client/templates/index.html +1 -1
- package/dist/module.cjs +2 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +2 -2
- package/dist/runtime/app/utils.js +8 -1
- package/dist/runtime/shared/urlEncoding.js +2 -1
- package/dist/shared/{nuxt-og-image.BM_Slo30.mjs → nuxt-og-image.8sPZ_PD5.mjs} +143 -8
- package/dist/shared/{nuxt-og-image.BuMzAC1A.cjs → nuxt-og-image.CQzMjYCR.cjs} +144 -9
- package/package.json +7 -7
- package/dist/client/_nuxt/BG25oXSp.js +0 -3
- package/dist/client/_nuxt/CAkieT7G.js +0 -1
- package/dist/client/_nuxt/CeFUJIya.js +0 -3860
- package/dist/client/_nuxt/CpLhajTF.js +0 -181
- package/dist/client/_nuxt/DxQS3Z2e.js +0 -1
- package/dist/client/_nuxt/HkJuN7bp.js +0 -1
- package/dist/client/_nuxt/IFrameLoader.D3_OtGCw.css +0 -1
- package/dist/client/_nuxt/PRAc7tB1.js +0 -2
- package/dist/client/_nuxt/builds/meta/6b729f7b-1f0a-4b8a-9835-558aeb415439.json +0 -1
- package/dist/client/_nuxt/entry.Cm_2Fdxn.css +0 -2
- package/dist/client/_nuxt/error-404.D7HOwyLG.css +0 -1
- package/dist/client/_nuxt/error-500.DpzjKi44.css +0 -1
package/dist/chunks/tw4.cjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const promises = require('node:fs/promises');
|
|
4
|
+
const node_url = require('node:url');
|
|
4
5
|
const exsolve = require('exsolve');
|
|
5
6
|
const pathe = require('pathe');
|
|
6
7
|
const cssProvider = require('./css-provider.cjs');
|
|
7
|
-
const module$1 = require('../shared/nuxt-og-image.
|
|
8
|
+
const module$1 = require('../shared/nuxt-og-image.CQzMjYCR.cjs');
|
|
8
9
|
require('node:fs');
|
|
9
10
|
require('@nuxt/kit');
|
|
10
11
|
require('defu');
|
|
@@ -21,7 +22,6 @@ require('@nuxt/devtools-kit');
|
|
|
21
22
|
require('unstorage');
|
|
22
23
|
require('unstorage/drivers/fs-lite');
|
|
23
24
|
require('../../dist/runtime/server/og-image/utils/css.js');
|
|
24
|
-
require('node:url');
|
|
25
25
|
require('magic-string');
|
|
26
26
|
require('strip-literal');
|
|
27
27
|
require('ufo');
|
|
@@ -56,11 +56,11 @@ function createModuleLoader(baseDir) {
|
|
|
56
56
|
return async (id, base) => {
|
|
57
57
|
const resolved = exsolve.resolveModulePath(id, { from: base || baseDir });
|
|
58
58
|
if (resolved) {
|
|
59
|
-
const module2 = await import(resolved).then((m) => m.default || m);
|
|
59
|
+
const module2 = await import(node_url.pathToFileURL(resolved).href).then((m) => m.default || m);
|
|
60
60
|
return { path: resolved, base: pathe.dirname(resolved), module: module2 };
|
|
61
61
|
}
|
|
62
62
|
const relativePath = pathe.join(base || baseDir, id);
|
|
63
|
-
const module = await import(relativePath).then((m) => m.default || m).catch(() => ({}));
|
|
63
|
+
const module = await import(node_url.pathToFileURL(relativePath).href).then((m) => m.default || m).catch(() => ({}));
|
|
64
64
|
return { path: relativePath, base: pathe.dirname(relativePath), module };
|
|
65
65
|
};
|
|
66
66
|
}
|
package/dist/chunks/tw4.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { pathToFileURL } from 'node:url';
|
|
2
3
|
import { resolveModulePath } from 'exsolve';
|
|
3
4
|
import { dirname, join } from 'pathe';
|
|
4
5
|
import { extractVariantBaseClasses, resolveVariantPrefixes } from './css-provider.mjs';
|
|
5
|
-
import { g as resolveVarsDeep, s as simplifyCss, p as postProcessStyles, l as loadLightningCss, e as extractCssVars, b as extractUniversalVars, c as extractPerClassVars, d as extractClassStyles } from '../shared/nuxt-og-image.
|
|
6
|
+
import { g as resolveVarsDeep, s as simplifyCss, p as postProcessStyles, l as loadLightningCss, e as extractCssVars, b as extractUniversalVars, c as extractPerClassVars, d as extractClassStyles } from '../shared/nuxt-og-image.8sPZ_PD5.mjs';
|
|
6
7
|
import 'node:fs';
|
|
7
8
|
import '@nuxt/kit';
|
|
8
9
|
import 'defu';
|
|
@@ -19,7 +20,6 @@ import '@nuxt/devtools-kit';
|
|
|
19
20
|
import 'unstorage';
|
|
20
21
|
import 'unstorage/drivers/fs-lite';
|
|
21
22
|
import '../../dist/runtime/server/og-image/utils/css.js';
|
|
22
|
-
import 'node:url';
|
|
23
23
|
import 'magic-string';
|
|
24
24
|
import 'strip-literal';
|
|
25
25
|
import 'ufo';
|
|
@@ -54,11 +54,11 @@ function createModuleLoader(baseDir) {
|
|
|
54
54
|
return async (id, base) => {
|
|
55
55
|
const resolved = resolveModulePath(id, { from: base || baseDir });
|
|
56
56
|
if (resolved) {
|
|
57
|
-
const module2 = await import(resolved).then((m) => m.default || m);
|
|
57
|
+
const module2 = await import(pathToFileURL(resolved).href).then((m) => m.default || m);
|
|
58
58
|
return { path: resolved, base: dirname(resolved), module: module2 };
|
|
59
59
|
}
|
|
60
60
|
const relativePath = join(base || baseDir, id);
|
|
61
|
-
const module = await import(relativePath).then((m) => m.default || m).catch(() => ({}));
|
|
61
|
+
const module = await import(pathToFileURL(relativePath).href).then((m) => m.default || m).catch(() => ({}));
|
|
62
62
|
return { path: relativePath, base: dirname(relativePath), module };
|
|
63
63
|
};
|
|
64
64
|
}
|
package/dist/chunks/uno.cjs
CHANGED
|
@@ -4,9 +4,10 @@ const promises = require('node:fs/promises');
|
|
|
4
4
|
const defu = require('defu');
|
|
5
5
|
const logger_js = require('../../dist/runtime/logger.js');
|
|
6
6
|
const cssProvider = require('./css-provider.cjs');
|
|
7
|
-
const module$1 = require('../shared/nuxt-og-image.
|
|
7
|
+
const module$1 = require('../shared/nuxt-og-image.CQzMjYCR.cjs');
|
|
8
8
|
require('exsolve');
|
|
9
9
|
require('node:fs');
|
|
10
|
+
require('node:url');
|
|
10
11
|
require('@nuxt/kit');
|
|
11
12
|
require('nuxt-site-config/kit');
|
|
12
13
|
require('ohash');
|
|
@@ -21,7 +22,6 @@ require('@nuxt/devtools-kit');
|
|
|
21
22
|
require('unstorage');
|
|
22
23
|
require('unstorage/drivers/fs-lite');
|
|
23
24
|
require('../../dist/runtime/server/og-image/utils/css.js');
|
|
24
|
-
require('node:url');
|
|
25
25
|
require('magic-string');
|
|
26
26
|
require('strip-literal');
|
|
27
27
|
require('ufo');
|
package/dist/chunks/uno.mjs
CHANGED
|
@@ -2,9 +2,10 @@ import { readFile } from 'node:fs/promises';
|
|
|
2
2
|
import { defu } from 'defu';
|
|
3
3
|
import { logger } from '../../dist/runtime/logger.js';
|
|
4
4
|
import { extractVariantBaseClasses, resolveVariantPrefixes } from './css-provider.mjs';
|
|
5
|
-
import { s as simplifyCss, e as extractCssVars, a as extractPropertyInitialValues, b as extractUniversalVars, c as extractPerClassVars, d as extractClassStyles, p as postProcessStyles, f as extractVarsFromCss, r as resolveExtractedVars } from '../shared/nuxt-og-image.
|
|
5
|
+
import { s as simplifyCss, e as extractCssVars, a as extractPropertyInitialValues, b as extractUniversalVars, c as extractPerClassVars, d as extractClassStyles, p as postProcessStyles, f as extractVarsFromCss, r as resolveExtractedVars } from '../shared/nuxt-og-image.8sPZ_PD5.mjs';
|
|
6
6
|
import 'exsolve';
|
|
7
7
|
import 'node:fs';
|
|
8
|
+
import 'node:url';
|
|
8
9
|
import '@nuxt/kit';
|
|
9
10
|
import 'nuxt-site-config/kit';
|
|
10
11
|
import 'ohash';
|
|
@@ -19,7 +20,6 @@ import '@nuxt/devtools-kit';
|
|
|
19
20
|
import 'unstorage';
|
|
20
21
|
import 'unstorage/drivers/fs-lite';
|
|
21
22
|
import '../../dist/runtime/server/og-image/utils/css.js';
|
|
22
|
-
import 'node:url';
|
|
23
23
|
import 'magic-string';
|
|
24
24
|
import 'strip-literal';
|
|
25
25
|
import 'ufo';
|
package/dist/cli.cjs
CHANGED
|
@@ -40,6 +40,10 @@ const RE_EXCLUDE_OUTPUT = /\.output/;
|
|
|
40
40
|
const RE_EXCLUDE_DATA = /\.data/;
|
|
41
41
|
const RE_EXCLUDE_DIST = /dist/;
|
|
42
42
|
const RE_VUE_OR_SCRIPT = /\.(?:vue|ts|tsx|js|jsx)$/;
|
|
43
|
+
const RE_PASCAL_CASE_STRICT = /^[A-Z]\w*$/;
|
|
44
|
+
const RE_PASCAL_CASE_START = /^[A-Z]/;
|
|
45
|
+
const RE_SCRIPT_SETUP = /<script\s+setup[^>]*>\r?\n?/;
|
|
46
|
+
const RE_PATH_SEPARATOR = /[\\/]|\.\./;
|
|
43
47
|
const DEPRECATED_COMPOSABLE_NAMES = /* @__PURE__ */ new Set([
|
|
44
48
|
"defineOgImageComponent",
|
|
45
49
|
"defineOgImageStatic",
|
|
@@ -204,10 +208,13 @@ function hasChromiumSuffix(filename) {
|
|
|
204
208
|
return RE_CHROMIUM_SUFFIX.test(filename);
|
|
205
209
|
}
|
|
206
210
|
function listTemplates() {
|
|
207
|
-
const templates =
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
+
const templates = [...new Set(
|
|
212
|
+
fs.readdirSync(communityDir).filter((f) => f.endsWith(".vue")).map(getBaseName)
|
|
213
|
+
)];
|
|
214
|
+
p__namespace.intro("Community Templates");
|
|
215
|
+
p__namespace.note(templates.map((t) => `\u2022 ${t}`).join("\n"), "Available");
|
|
216
|
+
p__namespace.log.info("Usage: npx nuxt-og-image eject <template-name>");
|
|
217
|
+
p__namespace.outro("");
|
|
211
218
|
}
|
|
212
219
|
function findTemplateFile(name) {
|
|
213
220
|
const files = fs.readdirSync(communityDir).filter((f) => f.endsWith(".vue"));
|
|
@@ -799,6 +806,439 @@ async function runMigrate(args2) {
|
|
|
799
806
|
}
|
|
800
807
|
p__namespace.outro(dryRun ? "Dry run complete" : "Migration complete!");
|
|
801
808
|
}
|
|
809
|
+
async function runSwitch(args2) {
|
|
810
|
+
const dryRun = args2.includes("--dry-run") || args2.includes("-d");
|
|
811
|
+
const skipConfirm = args2.includes("--yes") || args2.includes("-y");
|
|
812
|
+
const fromIdx = args2.indexOf("--from");
|
|
813
|
+
const toIdx = args2.indexOf("--to");
|
|
814
|
+
const cliFrom = fromIdx !== -1 ? args2[fromIdx + 1] : null;
|
|
815
|
+
const cliTo = toIdx !== -1 ? args2[toIdx + 1] : null;
|
|
816
|
+
const validRenderers = RENDERERS.map((r) => r.name);
|
|
817
|
+
if (cliFrom && !validRenderers.includes(cliFrom)) {
|
|
818
|
+
p__namespace.log.error(`Invalid --from renderer: ${cliFrom}. Must be ${validRenderers.join(", ")}`);
|
|
819
|
+
process.exit(1);
|
|
820
|
+
}
|
|
821
|
+
if (cliTo && !validRenderers.includes(cliTo)) {
|
|
822
|
+
p__namespace.log.error(`Invalid --to renderer: ${cliTo}. Must be ${validRenderers.join(", ")}`);
|
|
823
|
+
process.exit(1);
|
|
824
|
+
}
|
|
825
|
+
p__namespace.intro("Switch OG Image renderer");
|
|
826
|
+
const cwd = process.cwd();
|
|
827
|
+
const dirs = [cwd];
|
|
828
|
+
if (fs.existsSync(pathe.join(cwd, "app")))
|
|
829
|
+
dirs.push(pathe.join(cwd, "app"));
|
|
830
|
+
const layersDir = pathe.join(cwd, "layers");
|
|
831
|
+
if (fs.existsSync(layersDir)) {
|
|
832
|
+
const layerDirs = fs.readdirSync(layersDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => pathe.join(layersDir, d.name));
|
|
833
|
+
dirs.push(...layerDirs);
|
|
834
|
+
}
|
|
835
|
+
const allComponents = [];
|
|
836
|
+
for (const dir of dirs) {
|
|
837
|
+
const components = findOgImageComponents(dir);
|
|
838
|
+
for (const filepath of components) {
|
|
839
|
+
const match = pathe.basename(filepath).match(RE_RENDERER_SUFFIX);
|
|
840
|
+
if (match) {
|
|
841
|
+
allComponents.push({ path: filepath, renderer: match[1] });
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
if (allComponents.length === 0) {
|
|
846
|
+
p__namespace.log.warn("No OG image components with renderer suffixes found.");
|
|
847
|
+
p__namespace.outro("Nothing to do");
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
const currentRenderers = [...new Set(allComponents.map((c) => c.renderer))];
|
|
851
|
+
p__namespace.log.info(`Found ${allComponents.length} component(s) using: ${currentRenderers.join(", ")}`);
|
|
852
|
+
let fromRenderer;
|
|
853
|
+
if (cliFrom) {
|
|
854
|
+
fromRenderer = cliFrom;
|
|
855
|
+
} else if (skipConfirm) {
|
|
856
|
+
if (currentRenderers.length === 1) {
|
|
857
|
+
fromRenderer = currentRenderers[0];
|
|
858
|
+
} else {
|
|
859
|
+
p__namespace.log.error("Multiple renderers detected. Use --from to specify which to migrate.");
|
|
860
|
+
process.exit(1);
|
|
861
|
+
}
|
|
862
|
+
} else {
|
|
863
|
+
const fromSelection = await p__namespace.select({
|
|
864
|
+
message: "Which renderer do you want to migrate from?",
|
|
865
|
+
options: currentRenderers.map((r) => ({
|
|
866
|
+
value: r,
|
|
867
|
+
label: RENDERERS.find((rd) => rd.name === r)?.label || r
|
|
868
|
+
})),
|
|
869
|
+
initialValue: currentRenderers[0]
|
|
870
|
+
});
|
|
871
|
+
if (p__namespace.isCancel(fromSelection)) {
|
|
872
|
+
p__namespace.cancel("Cancelled");
|
|
873
|
+
process.exit(0);
|
|
874
|
+
}
|
|
875
|
+
fromRenderer = fromSelection;
|
|
876
|
+
}
|
|
877
|
+
let toRenderer;
|
|
878
|
+
if (cliTo) {
|
|
879
|
+
toRenderer = cliTo;
|
|
880
|
+
} else if (skipConfirm) {
|
|
881
|
+
toRenderer = fromRenderer === "takumi" ? "satori" : "takumi";
|
|
882
|
+
} else {
|
|
883
|
+
const targetOptions = RENDERERS.filter((r) => r.name !== fromRenderer);
|
|
884
|
+
const toSelection = await p__namespace.select({
|
|
885
|
+
message: "Which renderer do you want to switch to?",
|
|
886
|
+
options: targetOptions.map((r) => ({
|
|
887
|
+
value: r.name,
|
|
888
|
+
label: r.label,
|
|
889
|
+
hint: r.description
|
|
890
|
+
})),
|
|
891
|
+
initialValue: targetOptions[0]?.name
|
|
892
|
+
});
|
|
893
|
+
if (p__namespace.isCancel(toSelection)) {
|
|
894
|
+
p__namespace.cancel("Cancelled");
|
|
895
|
+
process.exit(0);
|
|
896
|
+
}
|
|
897
|
+
toRenderer = toSelection;
|
|
898
|
+
}
|
|
899
|
+
if (fromRenderer === toRenderer) {
|
|
900
|
+
p__namespace.log.warn(`Source and target renderer are the same (${fromRenderer}).`);
|
|
901
|
+
p__namespace.outro("Nothing to do");
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
const toMigrate = allComponents.filter((c) => c.renderer === fromRenderer);
|
|
905
|
+
if (toMigrate.length === 0) {
|
|
906
|
+
p__namespace.log.warn(`No components using ${fromRenderer} renderer found.`);
|
|
907
|
+
p__namespace.outro("Nothing to do");
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
p__namespace.note(
|
|
911
|
+
toMigrate.map((c) => `${pathe.relative(cwd, c.path)} \u2192 ${pathe.basename(c.path).replace(`.${fromRenderer}.vue`, `.${toRenderer}.vue`)}`).join("\n"),
|
|
912
|
+
`Renaming ${toMigrate.length} component(s): ${fromRenderer} \u2192 ${toRenderer}`
|
|
913
|
+
);
|
|
914
|
+
if (dryRun) {
|
|
915
|
+
p__namespace.log.warn("[Dry run mode, no changes will be made]");
|
|
916
|
+
p__namespace.outro("Dry run complete");
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
if (!skipConfirm) {
|
|
920
|
+
const confirmed = await p__namespace.confirm({
|
|
921
|
+
message: `Rename ${toMigrate.length} component(s) from ${fromRenderer} to ${toRenderer}?`,
|
|
922
|
+
initialValue: true
|
|
923
|
+
});
|
|
924
|
+
if (p__namespace.isCancel(confirmed) || !confirmed) {
|
|
925
|
+
p__namespace.cancel("Cancelled");
|
|
926
|
+
process.exit(0);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
const conflicts = [];
|
|
930
|
+
for (const component of toMigrate) {
|
|
931
|
+
const newPath = component.path.replace(`.${fromRenderer}.vue`, `.${toRenderer}.vue`);
|
|
932
|
+
if (fs.existsSync(newPath))
|
|
933
|
+
conflicts.push(`${pathe.basename(component.path)} \u2192 ${pathe.basename(newPath)} (already exists)`);
|
|
934
|
+
}
|
|
935
|
+
if (conflicts.length > 0) {
|
|
936
|
+
p__namespace.log.error("Conflicts detected, aborting:");
|
|
937
|
+
for (const c of conflicts) p__namespace.log.error(` ${c}`);
|
|
938
|
+
process.exit(1);
|
|
939
|
+
}
|
|
940
|
+
for (const component of toMigrate) {
|
|
941
|
+
const newPath = component.path.replace(`.${fromRenderer}.vue`, `.${toRenderer}.vue`);
|
|
942
|
+
fs.renameSync(component.path, newPath);
|
|
943
|
+
p__namespace.log.success(`${pathe.basename(component.path)} \u2192 ${pathe.basename(newPath)}`);
|
|
944
|
+
}
|
|
945
|
+
const hasPkg = fs.existsSync(pathe.join(cwd, "package.json"));
|
|
946
|
+
if (hasPkg) {
|
|
947
|
+
const noFromComponentsRemaining = allComponents.filter((c) => c.renderer === fromRenderer).length === toMigrate.length;
|
|
948
|
+
const detectedPreset = await detectDeploymentTarget(cwd);
|
|
949
|
+
const isEdge = detectedPreset ? EDGE_PRESETS.includes(detectedPreset) : false;
|
|
950
|
+
if (detectedPreset)
|
|
951
|
+
p__namespace.log.info(`Detected deployment target: ${detectedPreset}`);
|
|
952
|
+
const manageDeps = skipConfirm || await p__namespace.confirm({
|
|
953
|
+
message: `Manage dependencies? (install ${toRenderer}, ${noFromComponentsRemaining ? `remove ${fromRenderer}` : "keep existing"})`,
|
|
954
|
+
initialValue: true
|
|
955
|
+
}).then((v) => !p__namespace.isCancel(v) && v);
|
|
956
|
+
if (manageDeps) {
|
|
957
|
+
if (noFromComponentsRemaining) {
|
|
958
|
+
const oldDeps = [.../* @__PURE__ */ new Set([...getRendererDeps(fromRenderer, false), ...getRendererDeps(fromRenderer, true)])];
|
|
959
|
+
const newDeps = /* @__PURE__ */ new Set([...getRendererDeps(toRenderer, false), ...getRendererDeps(toRenderer, true)]);
|
|
960
|
+
const toRemove = oldDeps.filter((d) => !newDeps.has(d));
|
|
961
|
+
if (toRemove.length > 0) {
|
|
962
|
+
const pm = await nypm.detectPackageManager(cwd);
|
|
963
|
+
const spinner2 = p__namespace.spinner();
|
|
964
|
+
spinner2.start(`Removing ${fromRenderer} dependencies...`);
|
|
965
|
+
for (const dep of toRemove) {
|
|
966
|
+
await nypm.removeDependency(dep, { cwd }).catch(() => p__namespace.log.warn(`Could not remove ${dep}, remove manually: ${pm?.name || "npm"} remove ${dep}`));
|
|
967
|
+
}
|
|
968
|
+
spinner2.stop(`Removed ${fromRenderer} dependencies`);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
await installRendererDeps([toRenderer], isEdge);
|
|
972
|
+
}
|
|
973
|
+
const spinner = p__namespace.spinner();
|
|
974
|
+
spinner.start("Running nuxt prepare to update types...");
|
|
975
|
+
const { exec } = await import('tinyexec');
|
|
976
|
+
try {
|
|
977
|
+
await exec("npx", ["nuxi", "prepare"], { nodeOptions: { cwd } });
|
|
978
|
+
spinner.stop("Types updated");
|
|
979
|
+
} catch {
|
|
980
|
+
spinner.stop("Failed to run nuxt prepare");
|
|
981
|
+
p__namespace.log.warn("Run manually: npx nuxt prepare");
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
p__namespace.outro("Renderer switch complete!");
|
|
985
|
+
}
|
|
986
|
+
function readPackageJson(cwd) {
|
|
987
|
+
const pkgPath = pathe.join(cwd, "package.json");
|
|
988
|
+
if (!fs.existsSync(pkgPath))
|
|
989
|
+
return null;
|
|
990
|
+
try {
|
|
991
|
+
return JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
992
|
+
} catch {
|
|
993
|
+
return null;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
function inferRenderer(cwd) {
|
|
997
|
+
const dirs = [cwd];
|
|
998
|
+
if (fs.existsSync(pathe.join(cwd, "app")))
|
|
999
|
+
dirs.push(pathe.join(cwd, "app"));
|
|
1000
|
+
for (const dir of dirs) {
|
|
1001
|
+
const components = findOgImageComponents(dir);
|
|
1002
|
+
for (const filepath of components) {
|
|
1003
|
+
const match = pathe.basename(filepath).match(RE_RENDERER_SUFFIX);
|
|
1004
|
+
if (match)
|
|
1005
|
+
return match[1];
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
const pkg = readPackageJson(cwd);
|
|
1009
|
+
if (pkg) {
|
|
1010
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
1011
|
+
if (allDeps["@takumi-rs/core"] || allDeps["@takumi-rs/wasm"])
|
|
1012
|
+
return "takumi";
|
|
1013
|
+
if (allDeps.satori)
|
|
1014
|
+
return "satori";
|
|
1015
|
+
}
|
|
1016
|
+
return null;
|
|
1017
|
+
}
|
|
1018
|
+
function detectCssFramework(cwd) {
|
|
1019
|
+
const pkg = readPackageJson(cwd);
|
|
1020
|
+
if (!pkg)
|
|
1021
|
+
return "none";
|
|
1022
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
1023
|
+
if (allDeps["@unocss/nuxt"] || allDeps.unocss)
|
|
1024
|
+
return "unocss";
|
|
1025
|
+
if (allDeps["@nuxtjs/tailwindcss"] || allDeps.tailwindcss || allDeps["@nuxt/ui"])
|
|
1026
|
+
return "tailwind";
|
|
1027
|
+
return "none";
|
|
1028
|
+
}
|
|
1029
|
+
const SCRIPT_BLOCK = `<script setup lang="ts">
|
|
1030
|
+
const { title = 'My Page', description = '' } = defineProps<{
|
|
1031
|
+
title?: string
|
|
1032
|
+
description?: string
|
|
1033
|
+
}>()
|
|
1034
|
+
<\/script>`;
|
|
1035
|
+
function getStarterTemplate(renderer, css) {
|
|
1036
|
+
if (renderer === "satori") {
|
|
1037
|
+
return `${SCRIPT_BLOCK}
|
|
1038
|
+
|
|
1039
|
+
<template>
|
|
1040
|
+
<div :style="{ display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', width: '100%', height: '100%', padding: '60px', backgroundColor: 'white', color: '#171717' }">
|
|
1041
|
+
<h1 :style="{ fontSize: '72px', fontWeight: 'bold', margin: 0, lineHeight: 1.1, textAlign: 'center' }">
|
|
1042
|
+
{{ title }}
|
|
1043
|
+
</h1>
|
|
1044
|
+
<p v-if="description" :style="{ fontSize: '32px', opacity: 0.6, marginTop: '16px', textAlign: 'center', maxWidth: '900px' }">
|
|
1045
|
+
{{ description }}
|
|
1046
|
+
</p>
|
|
1047
|
+
</div>
|
|
1048
|
+
</template>
|
|
1049
|
+
`;
|
|
1050
|
+
}
|
|
1051
|
+
if (css === "tailwind" || css === "unocss") {
|
|
1052
|
+
return `${SCRIPT_BLOCK}
|
|
1053
|
+
|
|
1054
|
+
<template>
|
|
1055
|
+
<div class="w-full h-full flex flex-col justify-center items-center p-[60px] bg-white text-neutral-900 dark:bg-neutral-900 dark:text-white">
|
|
1056
|
+
<h1 class="text-[72px] font-bold m-0 leading-tight text-center" style="text-wrap: balance;">
|
|
1057
|
+
{{ title }}
|
|
1058
|
+
</h1>
|
|
1059
|
+
<p v-if="description" class="text-[32px] opacity-60 mt-4 text-center max-w-[900px]">
|
|
1060
|
+
{{ description }}
|
|
1061
|
+
</p>
|
|
1062
|
+
</div>
|
|
1063
|
+
</template>
|
|
1064
|
+
`;
|
|
1065
|
+
}
|
|
1066
|
+
return `${SCRIPT_BLOCK}
|
|
1067
|
+
|
|
1068
|
+
<template>
|
|
1069
|
+
<div class="container">
|
|
1070
|
+
<h1>{{ title }}</h1>
|
|
1071
|
+
<p v-if="description">
|
|
1072
|
+
{{ description }}
|
|
1073
|
+
</p>
|
|
1074
|
+
</div>
|
|
1075
|
+
</template>
|
|
1076
|
+
|
|
1077
|
+
<style scoped>
|
|
1078
|
+
.container {
|
|
1079
|
+
width: 100%;
|
|
1080
|
+
height: 100%;
|
|
1081
|
+
display: flex;
|
|
1082
|
+
flex-direction: column;
|
|
1083
|
+
justify-content: center;
|
|
1084
|
+
align-items: center;
|
|
1085
|
+
padding: 60px;
|
|
1086
|
+
background: white;
|
|
1087
|
+
color: #171717;
|
|
1088
|
+
}
|
|
1089
|
+
h1 {
|
|
1090
|
+
font-size: 72px;
|
|
1091
|
+
font-weight: bold;
|
|
1092
|
+
margin: 0;
|
|
1093
|
+
line-height: 1.1;
|
|
1094
|
+
text-align: center;
|
|
1095
|
+
text-wrap: balance;
|
|
1096
|
+
}
|
|
1097
|
+
p {
|
|
1098
|
+
font-size: 32px;
|
|
1099
|
+
opacity: 0.6;
|
|
1100
|
+
margin-top: 16px;
|
|
1101
|
+
text-align: center;
|
|
1102
|
+
max-width: 900px;
|
|
1103
|
+
}
|
|
1104
|
+
</style>
|
|
1105
|
+
`;
|
|
1106
|
+
}
|
|
1107
|
+
function insertDefineOgImage(filePath, componentName) {
|
|
1108
|
+
if (!fs.existsSync(filePath))
|
|
1109
|
+
return false;
|
|
1110
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
1111
|
+
if (content.includes("defineOgImage"))
|
|
1112
|
+
return false;
|
|
1113
|
+
const call = `defineOgImage('${componentName}', { title: 'Hello' })`;
|
|
1114
|
+
const scriptSetupMatch = content.match(RE_SCRIPT_SETUP);
|
|
1115
|
+
if (scriptSetupMatch) {
|
|
1116
|
+
const insertPos = scriptSetupMatch.index + scriptSetupMatch[0].length;
|
|
1117
|
+
const updated2 = `${content.slice(0, insertPos)}${call}
|
|
1118
|
+
${content.slice(insertPos)}`;
|
|
1119
|
+
fs.writeFileSync(filePath, updated2, "utf-8");
|
|
1120
|
+
return true;
|
|
1121
|
+
}
|
|
1122
|
+
const updated = `<script setup lang="ts">
|
|
1123
|
+
${call}
|
|
1124
|
+
<\/script>
|
|
1125
|
+
|
|
1126
|
+
${content}`;
|
|
1127
|
+
fs.writeFileSync(filePath, updated, "utf-8");
|
|
1128
|
+
return true;
|
|
1129
|
+
}
|
|
1130
|
+
async function runCreate(name, args2) {
|
|
1131
|
+
const cwd = process.cwd();
|
|
1132
|
+
const rendererIdx = args2.indexOf("--renderer");
|
|
1133
|
+
const cliRenderer = rendererIdx !== -1 ? args2[rendererIdx + 1] : null;
|
|
1134
|
+
if (cliRenderer && !RENDERERS.some((r) => r.name === cliRenderer)) {
|
|
1135
|
+
p__namespace.log.error(`Invalid renderer: ${cliRenderer}. Must be ${RENDERERS.map((r) => r.name).join(", ")}`);
|
|
1136
|
+
process.exit(1);
|
|
1137
|
+
}
|
|
1138
|
+
const pathIdx = args2.indexOf("--path");
|
|
1139
|
+
const cliPath = pathIdx !== -1 ? args2[pathIdx + 1] : null;
|
|
1140
|
+
p__namespace.intro("Create OG Image Component");
|
|
1141
|
+
const validateName = (v) => {
|
|
1142
|
+
const trimmed = v?.trim();
|
|
1143
|
+
if (!trimmed)
|
|
1144
|
+
return "Name is required";
|
|
1145
|
+
if (RE_PATH_SEPARATOR.test(trimmed))
|
|
1146
|
+
return 'Name must not contain path separators or ".."';
|
|
1147
|
+
if (!RE_PASCAL_CASE_STRICT.test(trimmed))
|
|
1148
|
+
return "Must be PascalCase (e.g. MyOgImage)";
|
|
1149
|
+
};
|
|
1150
|
+
let componentName = name;
|
|
1151
|
+
if (!componentName) {
|
|
1152
|
+
const input = await p__namespace.text({
|
|
1153
|
+
message: "Component name:",
|
|
1154
|
+
placeholder: "MyOgImage",
|
|
1155
|
+
validate: validateName
|
|
1156
|
+
});
|
|
1157
|
+
if (p__namespace.isCancel(input)) {
|
|
1158
|
+
p__namespace.cancel("Cancelled");
|
|
1159
|
+
process.exit(0);
|
|
1160
|
+
}
|
|
1161
|
+
componentName = input.trim();
|
|
1162
|
+
} else {
|
|
1163
|
+
componentName = componentName.trim();
|
|
1164
|
+
if (!RE_PASCAL_CASE_START.test(componentName))
|
|
1165
|
+
componentName = componentName.charAt(0).toUpperCase() + componentName.slice(1);
|
|
1166
|
+
const err = validateName(componentName);
|
|
1167
|
+
if (err) {
|
|
1168
|
+
p__namespace.log.error(err);
|
|
1169
|
+
process.exit(1);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
let renderer;
|
|
1173
|
+
if (cliRenderer) {
|
|
1174
|
+
renderer = cliRenderer;
|
|
1175
|
+
} else {
|
|
1176
|
+
const inferred = inferRenderer(cwd);
|
|
1177
|
+
if (inferred) {
|
|
1178
|
+
renderer = inferred;
|
|
1179
|
+
p__namespace.log.info(`Inferred renderer: ${renderer}`);
|
|
1180
|
+
} else {
|
|
1181
|
+
const selection = await p__namespace.select({
|
|
1182
|
+
message: "Which renderer?",
|
|
1183
|
+
options: RENDERERS.map((r) => ({
|
|
1184
|
+
value: r.name,
|
|
1185
|
+
label: r.label,
|
|
1186
|
+
hint: r.description
|
|
1187
|
+
})),
|
|
1188
|
+
initialValue: "takumi"
|
|
1189
|
+
});
|
|
1190
|
+
if (p__namespace.isCancel(selection)) {
|
|
1191
|
+
p__namespace.cancel("Cancelled");
|
|
1192
|
+
process.exit(0);
|
|
1193
|
+
}
|
|
1194
|
+
renderer = selection;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
const css = detectCssFramework(cwd);
|
|
1198
|
+
if (css !== "none")
|
|
1199
|
+
p__namespace.log.info(`Detected CSS framework: ${css}`);
|
|
1200
|
+
const baseDir = fs.existsSync(pathe.join(cwd, "app")) ? pathe.join(cwd, "app") : cwd;
|
|
1201
|
+
const outputDir = cliPath ? pathe.resolve(cwd, cliPath) : pathe.resolve(baseDir, "components", "OgImage");
|
|
1202
|
+
if (!outputDir.startsWith(cwd)) {
|
|
1203
|
+
p__namespace.log.error("Output path must be within the project directory");
|
|
1204
|
+
process.exit(1);
|
|
1205
|
+
}
|
|
1206
|
+
if (!fs.existsSync(outputDir))
|
|
1207
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
1208
|
+
const filename = `${componentName}.${renderer}.vue`;
|
|
1209
|
+
const outputPath = pathe.join(outputDir, filename);
|
|
1210
|
+
if (fs.existsSync(outputPath)) {
|
|
1211
|
+
p__namespace.log.error(`File already exists: ${pathe.relative(cwd, outputPath)}`);
|
|
1212
|
+
process.exit(1);
|
|
1213
|
+
}
|
|
1214
|
+
const template = getStarterTemplate(renderer, css);
|
|
1215
|
+
fs.writeFileSync(outputPath, template, "utf-8");
|
|
1216
|
+
p__namespace.log.success(`Created ${pathe.relative(cwd, outputPath)}`);
|
|
1217
|
+
const pagesDir = fs.existsSync(pathe.join(baseDir, "pages")) ? pathe.join(baseDir, "pages") : null;
|
|
1218
|
+
if (pagesDir) {
|
|
1219
|
+
const pageInput = await p__namespace.text({
|
|
1220
|
+
message: "Add defineOgImage to a page? (relative path from pages/, leave empty to skip)",
|
|
1221
|
+
placeholder: "index.vue"
|
|
1222
|
+
});
|
|
1223
|
+
if (!p__namespace.isCancel(pageInput) && pageInput && pageInput.trim()) {
|
|
1224
|
+
let pagePath = pageInput.trim();
|
|
1225
|
+
if (!pagePath.endsWith(".vue"))
|
|
1226
|
+
pagePath += ".vue";
|
|
1227
|
+
const fullPagePath = pathe.resolve(pagesDir, pagePath);
|
|
1228
|
+
if (!fullPagePath.startsWith(pagesDir)) {
|
|
1229
|
+
p__namespace.log.warn("Page path must be within the pages directory");
|
|
1230
|
+
} else if (insertDefineOgImage(fullPagePath, componentName)) {
|
|
1231
|
+
p__namespace.log.success(`Added defineOgImage('${componentName}') to ${pathe.relative(cwd, fullPagePath)}`);
|
|
1232
|
+
} else if (!fs.existsSync(fullPagePath)) {
|
|
1233
|
+
p__namespace.log.warn(`Page not found: ${pathe.relative(cwd, fullPagePath)}`);
|
|
1234
|
+
} else {
|
|
1235
|
+
p__namespace.log.info("Page already has defineOgImage, skipped");
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
p__namespace.log.info(`Usage: defineOgImage('${componentName}', { title: 'Hello' })`);
|
|
1240
|
+
p__namespace.outro("");
|
|
1241
|
+
}
|
|
802
1242
|
async function runEnable(renderer, args2) {
|
|
803
1243
|
const def = RENDERERS.find((r) => r.name === renderer);
|
|
804
1244
|
if (!def) {
|
|
@@ -824,9 +1264,30 @@ async function runEnable(renderer, args2) {
|
|
|
824
1264
|
await installRendererDeps([renderer], isEdge);
|
|
825
1265
|
p__namespace.outro("Done");
|
|
826
1266
|
}
|
|
1267
|
+
function showHelp() {
|
|
1268
|
+
p__namespace.intro("nuxt-og-image CLI");
|
|
1269
|
+
p__namespace.note([
|
|
1270
|
+
"create [name] Scaffold a new OG image component",
|
|
1271
|
+
" Options: --renderer <renderer>, --path <dir>",
|
|
1272
|
+
"list List available community templates",
|
|
1273
|
+
"eject <name> Eject a community template to your project",
|
|
1274
|
+
"switch Switch components between renderers",
|
|
1275
|
+
" Options: --from <renderer>, --to <renderer>, --dry-run, --yes",
|
|
1276
|
+
"enable <renderer> Install dependencies for a renderer (satori, browser, takumi)",
|
|
1277
|
+
" Options: --edge (install wasm versions for edge runtimes)",
|
|
1278
|
+
"migrate v6 Migrate to v6 (component suffixes + new API)",
|
|
1279
|
+
" Options: --dry-run, --yes, --renderer <renderer>"
|
|
1280
|
+
].join("\n"), "Commands");
|
|
1281
|
+
p__namespace.outro("");
|
|
1282
|
+
}
|
|
827
1283
|
const args = process.argv.slice(2);
|
|
828
1284
|
const command = args[0];
|
|
829
|
-
|
|
1285
|
+
const hasHelp = args.includes("--help") || args.includes("-h");
|
|
1286
|
+
if (hasHelp || !command) {
|
|
1287
|
+
showHelp();
|
|
1288
|
+
} else if (command === "create") {
|
|
1289
|
+
runCreate(args[1], args.slice(1));
|
|
1290
|
+
} else if (command === "eject") {
|
|
830
1291
|
const templateName = args[1];
|
|
831
1292
|
if (!templateName) {
|
|
832
1293
|
p__namespace.log.error("Please specify a template name.");
|
|
@@ -845,6 +1306,8 @@ if (command === "eject") {
|
|
|
845
1306
|
process.exit(1);
|
|
846
1307
|
}
|
|
847
1308
|
runMigrate(args);
|
|
1309
|
+
} else if (command === "switch") {
|
|
1310
|
+
runSwitch(args.slice(1));
|
|
848
1311
|
} else if (command === "enable") {
|
|
849
1312
|
const renderer = args[1];
|
|
850
1313
|
if (!renderer) {
|
|
@@ -854,12 +1317,7 @@ if (command === "eject") {
|
|
|
854
1317
|
}
|
|
855
1318
|
runEnable(renderer, args);
|
|
856
1319
|
} else {
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
console.log(" eject <name> Eject a community template to your project");
|
|
861
|
-
console.log(" migrate v6 Migrate to v6 (component suffixes + new API)");
|
|
862
|
-
console.log(" Options: --dry-run, --yes, --renderer <satori|browser|takumi>");
|
|
863
|
-
console.log(" enable <renderer> Install dependencies for a renderer (satori, browser, takumi)");
|
|
864
|
-
console.log(" Options: --edge (install wasm versions for edge runtimes)");
|
|
1320
|
+
p__namespace.log.error(`Unknown command: ${command}`);
|
|
1321
|
+
showHelp();
|
|
1322
|
+
process.exit(1);
|
|
865
1323
|
}
|