create-addfox-app 0.1.1-beta.10 → 0.1.1-beta.11
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/README.md +1 -1
- package/dist/cli.js +85 -75
- package/package.json +2 -1
- package/templates/README.md +3 -0
- package/templates/template-preact-js/addfox.config.js +27 -0
- package/templates/template-preact-js/app/background/index.js +8 -0
- package/templates/template-preact-js/app/content/index.js +1 -0
- package/templates/template-preact-js/app/options/App.jsx +5 -0
- package/templates/template-preact-js/app/options/index.jsx +5 -0
- package/templates/template-preact-js/app/popup/App.jsx +23 -0
- package/templates/template-preact-js/app/popup/index.jsx +5 -0
- package/templates/template-preact-js/app/sidepanel/App.jsx +5 -0
- package/templates/template-preact-js/app/sidepanel/index.jsx +5 -0
- package/templates/template-preact-js/package.json +19 -0
- package/templates/template-preact-js/public/icons/icon_128.png +0 -0
- package/templates/template-preact-js/public/welcome.html +19 -0
- package/templates/template-preact-ts/addfox.config.ts +27 -0
- package/templates/template-preact-ts/app/background/index.ts +8 -0
- package/templates/template-preact-ts/app/content/index.ts +1 -0
- package/templates/template-preact-ts/app/options/App.tsx +5 -0
- package/templates/template-preact-ts/app/options/index.tsx +5 -0
- package/templates/template-preact-ts/app/popup/App.tsx +23 -0
- package/templates/template-preact-ts/app/popup/index.tsx +5 -0
- package/templates/template-preact-ts/app/sidepanel/App.tsx +5 -0
- package/templates/template-preact-ts/app/sidepanel/index.tsx +5 -0
- package/templates/template-preact-ts/package.json +21 -0
- package/templates/template-preact-ts/public/icons/icon_128.png +0 -0
- package/templates/template-preact-ts/public/welcome.html +19 -0
- package/templates/template-preact-ts/tsconfig.json +19 -0
- package/templates/template-react-js/addfox.config.js +27 -0
- package/templates/template-react-js/app/background/index.js +8 -0
- package/templates/template-react-js/app/content/index.js +1 -0
- package/templates/template-react-js/app/options/App.jsx +3 -0
- package/templates/template-react-js/app/options/index.jsx +5 -0
- package/templates/template-react-js/app/popup/App.jsx +21 -0
- package/templates/template-react-js/app/popup/index.jsx +5 -0
- package/templates/template-react-js/app/sidepanel/App.jsx +3 -0
- package/templates/template-react-js/app/sidepanel/index.jsx +5 -0
- package/templates/template-react-js/package.json +20 -0
- package/templates/template-react-js/public/icons/icon_128.png +0 -0
- package/templates/template-react-js/public/welcome.html +19 -0
- package/templates/template-react-ts/addfox.config.ts +27 -0
- package/templates/template-react-ts/app/background/index.ts +8 -0
- package/templates/template-react-ts/app/content/index.ts +1 -0
- package/templates/template-react-ts/app/options/App.tsx +3 -0
- package/templates/template-react-ts/app/options/index.tsx +5 -0
- package/templates/template-react-ts/app/popup/App.tsx +21 -0
- package/templates/template-react-ts/app/popup/index.tsx +5 -0
- package/templates/template-react-ts/app/sidepanel/App.tsx +3 -0
- package/templates/template-react-ts/app/sidepanel/index.tsx +5 -0
- package/templates/template-react-ts/package.json +24 -0
- package/templates/template-react-ts/public/icons/icon_128.png +0 -0
- package/templates/template-react-ts/public/welcome.html +19 -0
- package/templates/template-react-ts/tsconfig.json +19 -0
- package/templates/template-solid-js/addfox.config.js +28 -0
- package/templates/template-solid-js/app/background/index.js +8 -0
- package/templates/template-solid-js/app/content/index.js +1 -0
- package/templates/template-solid-js/app/options/App.jsx +3 -0
- package/templates/template-solid-js/app/options/index.jsx +5 -0
- package/templates/template-solid-js/app/popup/App.jsx +26 -0
- package/templates/template-solid-js/app/popup/index.jsx +5 -0
- package/templates/template-solid-js/app/sidepanel/App.jsx +3 -0
- package/templates/template-solid-js/app/sidepanel/index.jsx +5 -0
- package/templates/template-solid-js/package.json +20 -0
- package/templates/template-solid-js/public/icons/icon_128.png +0 -0
- package/templates/template-solid-js/public/welcome.html +19 -0
- package/templates/template-solid-ts/addfox.config.ts +28 -0
- package/templates/template-solid-ts/app/background/index.ts +8 -0
- package/templates/template-solid-ts/app/content/index.ts +1 -0
- package/templates/template-solid-ts/app/options/App.tsx +3 -0
- package/templates/template-solid-ts/app/options/index.tsx +5 -0
- package/templates/template-solid-ts/app/popup/App.tsx +26 -0
- package/templates/template-solid-ts/app/popup/index.tsx +5 -0
- package/templates/template-solid-ts/app/sidepanel/App.tsx +3 -0
- package/templates/template-solid-ts/app/sidepanel/index.tsx +5 -0
- package/templates/template-solid-ts/package.json +22 -0
- package/templates/template-solid-ts/public/icons/icon_128.png +0 -0
- package/templates/template-solid-ts/public/welcome.html +19 -0
- package/templates/template-solid-ts/tsconfig.json +19 -0
- package/templates/template-svelte-js/addfox.config.js +27 -0
- package/templates/template-svelte-js/app/background/index.js +8 -0
- package/templates/template-svelte-js/app/content/index.js +1 -0
- package/templates/template-svelte-js/app/options/App.svelte +4 -0
- package/templates/template-svelte-js/app/options/index.js +4 -0
- package/templates/template-svelte-js/app/popup/App.svelte +24 -0
- package/templates/template-svelte-js/app/popup/index.js +4 -0
- package/templates/template-svelte-js/app/sidepanel/App.svelte +4 -0
- package/templates/template-svelte-js/app/sidepanel/index.js +4 -0
- package/templates/template-svelte-js/package.json +19 -0
- package/templates/template-svelte-js/public/icons/icon_128.png +0 -0
- package/templates/template-svelte-js/public/welcome.html +19 -0
- package/templates/template-svelte-ts/addfox.config.ts +27 -0
- package/templates/template-svelte-ts/app/background/index.ts +8 -0
- package/templates/template-svelte-ts/app/content/index.ts +1 -0
- package/templates/template-svelte-ts/app/options/App.svelte +4 -0
- package/templates/template-svelte-ts/app/options/index.ts +4 -0
- package/templates/template-svelte-ts/app/popup/App.svelte +24 -0
- package/templates/template-svelte-ts/app/popup/index.ts +4 -0
- package/templates/template-svelte-ts/app/sidepanel/App.svelte +4 -0
- package/templates/template-svelte-ts/app/sidepanel/index.ts +4 -0
- package/templates/template-svelte-ts/package.json +21 -0
- package/templates/template-svelte-ts/public/icons/icon_128.png +0 -0
- package/templates/template-svelte-ts/public/welcome.html +19 -0
- package/templates/template-svelte-ts/tsconfig.json +19 -0
- package/templates/template-vanilla-js/addfox.config.js +25 -0
- package/templates/template-vanilla-js/app/background/index.js +8 -0
- package/templates/template-vanilla-js/app/content/index.js +1 -0
- package/templates/template-vanilla-js/app/options/index.js +2 -0
- package/templates/template-vanilla-js/app/popup/index.js +37 -0
- package/templates/template-vanilla-js/app/sidepanel/index.js +2 -0
- package/templates/template-vanilla-js/package.json +15 -0
- package/templates/template-vanilla-js/public/icons/icon_128.png +0 -0
- package/templates/template-vanilla-js/public/welcome.html +19 -0
- package/templates/template-vanilla-ts/addfox.config.ts +25 -0
- package/templates/template-vanilla-ts/app/background/index.ts +8 -0
- package/templates/template-vanilla-ts/app/content/index.ts +1 -0
- package/templates/template-vanilla-ts/app/options/index.ts +2 -0
- package/templates/template-vanilla-ts/app/popup/index.ts +37 -0
- package/templates/template-vanilla-ts/app/sidepanel/index.ts +2 -0
- package/templates/template-vanilla-ts/package.json +17 -0
- package/templates/template-vanilla-ts/public/icons/icon_128.png +0 -0
- package/templates/template-vanilla-ts/public/welcome.html +19 -0
- package/templates/template-vanilla-ts/tsconfig.json +17 -0
- package/templates/template-vue-js/addfox.config.js +27 -0
- package/templates/template-vue-js/app/background/index.js +8 -0
- package/templates/template-vue-js/app/content/index.js +1 -0
- package/templates/template-vue-js/app/options/App.vue +6 -0
- package/templates/template-vue-js/app/options/index.js +5 -0
- package/templates/template-vue-js/app/popup/App.vue +28 -0
- package/templates/template-vue-js/app/popup/index.js +5 -0
- package/templates/template-vue-js/app/sidepanel/App.vue +6 -0
- package/templates/template-vue-js/app/sidepanel/index.js +5 -0
- package/templates/template-vue-js/package.json +20 -0
- package/templates/template-vue-js/public/icons/icon_128.png +0 -0
- package/templates/template-vue-js/public/welcome.html +19 -0
- package/templates/template-vue-ts/addfox.config.ts +27 -0
- package/templates/template-vue-ts/app/background/index.ts +8 -0
- package/templates/template-vue-ts/app/content/index.ts +1 -0
- package/templates/template-vue-ts/app/options/App.vue +6 -0
- package/templates/template-vue-ts/app/options/index.ts +5 -0
- package/templates/template-vue-ts/app/popup/App.vue +26 -0
- package/templates/template-vue-ts/app/popup/index.ts +5 -0
- package/templates/template-vue-ts/app/sidepanel/App.vue +6 -0
- package/templates/template-vue-ts/app/sidepanel/index.ts +5 -0
- package/templates/template-vue-ts/package.json +23 -0
- package/templates/template-vue-ts/public/icons/icon_128.png +0 -0
- package/templates/template-vue-ts/public/welcome.html +19 -0
- package/templates/template-vue-ts/tsconfig.json +19 -0
package/README.md
CHANGED
|
@@ -15,4 +15,4 @@ Interactive scaffolder: generates a addfox-based extension project from options
|
|
|
15
15
|
|
|
16
16
|
## Templates
|
|
17
17
|
|
|
18
|
-
Scaffold templates
|
|
18
|
+
Scaffold templates ship inside this package under **`templates/`** (e.g. `template-vanilla-ts`, `template-react-ts`). They are included in the published npm tarball; the CLI copies the chosen folder into your new project (no remote download). The template’s **`addfox.config`** (including `manifest`) is **preserved**; the CLI only **merges** Rsbuild Less/Sass plugins when those style engines are selected. If no config file exists, a full fallback config is generated.
|
package/dist/cli.js
CHANGED
|
@@ -8,17 +8,16 @@ import prompts from "prompts";
|
|
|
8
8
|
import { blue, cyan, dim, gray, green, lightBlue, magenta, red, trueColor, yellow } from "kolorist";
|
|
9
9
|
import minimist from "minimist";
|
|
10
10
|
import { cp, mkdir } from "node:fs/promises";
|
|
11
|
-
import { gunzipSync } from "node:zlib";
|
|
12
11
|
import { detectPackageManager, getExecCommand, getInstallCommand, getRunCommand } from "@addfox/pkg-manager";
|
|
13
|
-
const GITHUB_REPO = "addfox/addfox";
|
|
14
12
|
const TEMPLATE_BASE = "templates";
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
function getPackageRoot() {
|
|
14
|
+
return external_node_path_resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
15
|
+
}
|
|
16
|
+
function getBundledTemplatesDir() {
|
|
17
|
+
return join(getPackageRoot(), TEMPLATE_BASE);
|
|
18
18
|
}
|
|
19
19
|
function hasLocalTemplate(templateName) {
|
|
20
|
-
|
|
21
|
-
return existsSync(join(repoRoot, TEMPLATE_BASE, templateName));
|
|
20
|
+
return existsSync(join(getBundledTemplatesDir(), templateName));
|
|
22
21
|
}
|
|
23
22
|
const SKIP_TEMPLATE_PATH_PARTS = new Set([
|
|
24
23
|
"node_modules",
|
|
@@ -30,10 +29,9 @@ function shouldCopyLocalTemplatePath(src) {
|
|
|
30
29
|
for (const part of normalized)if (SKIP_TEMPLATE_PATH_PARTS.has(part)) return false;
|
|
31
30
|
return true;
|
|
32
31
|
}
|
|
33
|
-
async function
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
if (!existsSync(templatePath)) return false;
|
|
32
|
+
async function copyBundledTemplate(templateName, destDir) {
|
|
33
|
+
const templatePath = join(getBundledTemplatesDir(), templateName);
|
|
34
|
+
if (!existsSync(templatePath)) throw new Error(`Bundled template "${templateName}" not found under create-addfox-app. Reinstall the package.`);
|
|
37
35
|
await mkdir(destDir, {
|
|
38
36
|
recursive: true
|
|
39
37
|
});
|
|
@@ -41,58 +39,6 @@ async function tryLocalTemplates(templateName, destDir) {
|
|
|
41
39
|
recursive: true,
|
|
42
40
|
filter: (src)=>shouldCopyLocalTemplatePath(src)
|
|
43
41
|
});
|
|
44
|
-
return true;
|
|
45
|
-
}
|
|
46
|
-
function parseTarHeader(buf) {
|
|
47
|
-
if (buf.every((b)=>0 === b)) return null;
|
|
48
|
-
const rawName = buf.subarray(0, 100).toString("utf8").replace(/\0+$/, "");
|
|
49
|
-
const sizeStr = buf.subarray(124, 136).toString("utf8").replace(/\0+$/, "").trim();
|
|
50
|
-
const type = String.fromCharCode(buf[156]);
|
|
51
|
-
const prefix = buf.subarray(345, 500).toString("utf8").replace(/\0+$/, "");
|
|
52
|
-
return {
|
|
53
|
-
name: prefix ? `${prefix}/${rawName}` : rawName,
|
|
54
|
-
size: parseInt(sizeStr, 8) || 0,
|
|
55
|
-
type
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
function extractMatchingFiles(tarBuffer, templatePrefix, destDir) {
|
|
59
|
-
let offset = 0;
|
|
60
|
-
while(offset + 512 <= tarBuffer.length){
|
|
61
|
-
const header = parseTarHeader(tarBuffer.subarray(offset, offset + 512));
|
|
62
|
-
offset += 512;
|
|
63
|
-
if (!header) break;
|
|
64
|
-
const dataBlocks = 512 * Math.ceil(header.size / 512);
|
|
65
|
-
const idx = header.name.indexOf(templatePrefix);
|
|
66
|
-
if (-1 !== idx) {
|
|
67
|
-
const relativePath = header.name.substring(idx + templatePrefix.length).replace(/^\//, "");
|
|
68
|
-
if (relativePath) {
|
|
69
|
-
const destPath = join(destDir, relativePath);
|
|
70
|
-
const isDir = "5" === header.type || relativePath.endsWith("/");
|
|
71
|
-
if (isDir) mkdirSync(destPath, {
|
|
72
|
-
recursive: true
|
|
73
|
-
});
|
|
74
|
-
else if ("0" === header.type || "\0" === header.type) {
|
|
75
|
-
mkdirSync(dirname(destPath), {
|
|
76
|
-
recursive: true
|
|
77
|
-
});
|
|
78
|
-
writeFileSync(destPath, tarBuffer.subarray(offset, offset + header.size));
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
offset += dataBlocks;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
async function downloadTemplate(templateName, destDir, branch = "main") {
|
|
86
|
-
const url = `https://codeload.github.com/${GITHUB_REPO}/tar.gz/${branch}`;
|
|
87
|
-
const templatePrefix = `${TEMPLATE_BASE}/${templateName}/`;
|
|
88
|
-
const response = await fetch(url);
|
|
89
|
-
if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
90
|
-
const compressed = Buffer.from(await response.arrayBuffer());
|
|
91
|
-
const tarBuffer = gunzipSync(compressed);
|
|
92
|
-
mkdirSync(destDir, {
|
|
93
|
-
recursive: true
|
|
94
|
-
});
|
|
95
|
-
extractMatchingFiles(tarBuffer, templatePrefix, destDir);
|
|
96
42
|
}
|
|
97
43
|
const FRAMES = [
|
|
98
44
|
"⠋",
|
|
@@ -295,7 +241,7 @@ function getStylePlugin(engine) {
|
|
|
295
241
|
};
|
|
296
242
|
return null;
|
|
297
243
|
}
|
|
298
|
-
const MINIMAL_MANIFEST = ' name: "My Extension",\n version: "1.0.0",\n manifest_version: 3,\n description: "Browser extension built with addfox",\n permissions: ["
|
|
244
|
+
const MINIMAL_MANIFEST = ' name: "My Extension",\n version: "1.0.0",\n manifest_version: 3,\n description: "Browser extension built with addfox",\n permissions: ["activeTab"],\n icons: {\n "16": "icons/icon_128.png",\n "48": "icons/icon_128.png",\n "128": "icons/icon_128.png",\n },\n action: {\n default_icon: {\n "16": "icons/icon_128.png",\n "48": "icons/icon_128.png",\n "128": "icons/icon_128.png",\n },\n },';
|
|
299
245
|
function generateAddfoxConfig(framework, _language, styleEngine) {
|
|
300
246
|
const importLines = [];
|
|
301
247
|
const fwImport = getFrameworkPluginImport(framework);
|
|
@@ -323,6 +269,67 @@ function generateAddfoxConfig(framework, _language, styleEngine) {
|
|
|
323
269
|
];
|
|
324
270
|
return parts.filter(Boolean).join("\n");
|
|
325
271
|
}
|
|
272
|
+
const MANIFEST_LINE = " manifest: { chromium: manifest, firefox: { ...manifest } },";
|
|
273
|
+
function findMatchingArrayClose(source, openBracketIdx) {
|
|
274
|
+
if ("[" !== source[openBracketIdx]) return -1;
|
|
275
|
+
let depth = 0;
|
|
276
|
+
for(let i = openBracketIdx; i < source.length; i++){
|
|
277
|
+
const c = source[i];
|
|
278
|
+
if ("[" === c) depth++;
|
|
279
|
+
else if ("]" === c) {
|
|
280
|
+
depth--;
|
|
281
|
+
if (0 === depth) return i;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return -1;
|
|
285
|
+
}
|
|
286
|
+
function hasImportFromModule(source, modulePath) {
|
|
287
|
+
return source.includes(`from "${modulePath}"`) || source.includes(`from '${modulePath}'`) || source.includes(`from \`${modulePath}\``);
|
|
288
|
+
}
|
|
289
|
+
function insertImportAfterLastImport(source, importLine) {
|
|
290
|
+
const trimmed = importLine.trim();
|
|
291
|
+
const moduleMatch = /from\s+["']([^"']+)["']/.exec(trimmed);
|
|
292
|
+
if (moduleMatch && hasImportFromModule(source, moduleMatch[1])) return source;
|
|
293
|
+
const lines = source.split("\n");
|
|
294
|
+
let lastImportIdx = -1;
|
|
295
|
+
for(let i = 0; i < lines.length; i++)if (lines[i].trim().startsWith("import ")) lastImportIdx = i;
|
|
296
|
+
if (-1 === lastImportIdx) return `${importLine}\n${source}`;
|
|
297
|
+
const next = [
|
|
298
|
+
...lines
|
|
299
|
+
];
|
|
300
|
+
next.splice(lastImportIdx + 1, 0, importLine);
|
|
301
|
+
return next.join("\n");
|
|
302
|
+
}
|
|
303
|
+
function pluginCallPresent(inner, call) {
|
|
304
|
+
const fn = call.replace(/\(\)$/, "");
|
|
305
|
+
return inner.includes(`${fn}(`);
|
|
306
|
+
}
|
|
307
|
+
function mergeCallsIntoPluginsArray(source, calls) {
|
|
308
|
+
const pluginsIdx = source.indexOf("plugins:");
|
|
309
|
+
if (-1 === pluginsIdx) return addPluginsBlockAfterManifest(source, calls);
|
|
310
|
+
const bracketStart = source.indexOf("[", pluginsIdx);
|
|
311
|
+
if (-1 === bracketStart) return source;
|
|
312
|
+
const bracketEnd = findMatchingArrayClose(source, bracketStart);
|
|
313
|
+
if (-1 === bracketEnd) return source;
|
|
314
|
+
let inner = source.slice(bracketStart + 1, bracketEnd).trim();
|
|
315
|
+
for (const c of calls)if (!pluginCallPresent(inner, c)) inner = inner ? `${inner}, ${c}` : c;
|
|
316
|
+
return source.slice(0, bracketStart + 1) + inner + source.slice(bracketEnd);
|
|
317
|
+
}
|
|
318
|
+
function addPluginsBlockAfterManifest(source, calls) {
|
|
319
|
+
const idx = source.indexOf(MANIFEST_LINE);
|
|
320
|
+
if (-1 === idx) return source;
|
|
321
|
+
const insertPos = idx + MANIFEST_LINE.length;
|
|
322
|
+
return `${source.slice(0, insertPos)}\n plugins: [${calls.join(", ")}],${source.slice(insertPos)}`;
|
|
323
|
+
}
|
|
324
|
+
function mergeScaffoldIntoAddfoxConfig(source, styleEngine) {
|
|
325
|
+
const st = getStylePlugin(styleEngine);
|
|
326
|
+
if (!st) return source;
|
|
327
|
+
let out = insertImportAfterLastImport(source, st.importLine);
|
|
328
|
+
out = mergeCallsIntoPluginsArray(out, [
|
|
329
|
+
st.call
|
|
330
|
+
]);
|
|
331
|
+
return out;
|
|
332
|
+
}
|
|
326
333
|
const UTF8_BOM = "\uFEFF";
|
|
327
334
|
function stripUtf8Bom(text) {
|
|
328
335
|
return text.startsWith(UTF8_BOM) ? text.slice(UTF8_BOM.length) : text;
|
|
@@ -941,21 +948,20 @@ async function main() {
|
|
|
941
948
|
if (!testSelection) process.exit(0);
|
|
942
949
|
const pm = options.packageManager;
|
|
943
950
|
const templateName = getTemplateName(options.framework, options.language);
|
|
944
|
-
const
|
|
945
|
-
const templateLabel =
|
|
946
|
-
const
|
|
951
|
+
const templateReady = hasLocalTemplate(templateName);
|
|
952
|
+
const templateLabel = "Copying template...";
|
|
953
|
+
const TEMPLATE_SPINNER_MIN_MS = 800;
|
|
947
954
|
try {
|
|
948
955
|
await runWithTemplateSpinner(templateLabel, async ()=>{
|
|
949
|
-
await new Promise((
|
|
950
|
-
setImmediate(
|
|
956
|
+
await new Promise((resolveSpinner)=>{
|
|
957
|
+
setImmediate(resolveSpinner);
|
|
951
958
|
});
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
minVisibleMs: LOCAL_TEMPLATE_SPINNER_MIN_MS
|
|
959
|
+
await copyBundledTemplate(templateName, root);
|
|
960
|
+
}, templateReady ? {
|
|
961
|
+
minVisibleMs: TEMPLATE_SPINNER_MIN_MS
|
|
956
962
|
} : void 0);
|
|
957
963
|
} catch (err) {
|
|
958
|
-
console.error(red(`\n Failed to
|
|
964
|
+
console.error(red(`\n Failed to copy template: ${err.message}\n`));
|
|
959
965
|
process.exit(1);
|
|
960
966
|
}
|
|
961
967
|
const useAllEntries = options.entries.includes("__all__");
|
|
@@ -966,7 +972,11 @@ async function main() {
|
|
|
966
972
|
if (!useAllEntries && effectiveEntries.length > 0) filterAppEntries(root, effectiveEntries);
|
|
967
973
|
const configExt = "ts" === options.language ? "ts" : "js";
|
|
968
974
|
const configPath = external_node_path_resolve(root, `addfox.config.${configExt}`);
|
|
969
|
-
|
|
975
|
+
let configContent;
|
|
976
|
+
if (existsSync(configPath)) {
|
|
977
|
+
const existing = readFileSync(configPath, "utf-8");
|
|
978
|
+
configContent = existing.trim().length > 0 && existing.includes("defineConfig") ? mergeScaffoldIntoAddfoxConfig(existing, options.styleEngine) : generateAddfoxConfig(options.framework, options.language, options.styleEngine);
|
|
979
|
+
} else configContent = generateAddfoxConfig(options.framework, options.language, options.styleEngine);
|
|
970
980
|
writeFileSync(configPath, configContent, "utf-8");
|
|
971
981
|
updatePackageName(root, targetDir);
|
|
972
982
|
applyStyleEngine(root, options.framework, options.language, options.styleEngine);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-addfox-app",
|
|
3
|
-
"version": "0.1.1-beta.
|
|
3
|
+
"version": "0.1.1-beta.11",
|
|
4
4
|
"description": "Interactive scaffolder for addfox extension projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
|
+
"templates",
|
|
12
13
|
"LICENSE"
|
|
13
14
|
],
|
|
14
15
|
"dependencies": {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Scaffold templates
|
|
2
|
+
|
|
3
|
+
Templates used by **create-addfox-app**. Each subdirectory (e.g. `template-vanilla-ts`, `template-react-ts`) is a full project skeleton. They live under this package and ship with the published npm tarball; the CLI copies the chosen folder into the new project directory.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { defineConfig } from "addfox";
|
|
2
|
+
import { pluginPreact } from "@rsbuild/plugin-preact";
|
|
3
|
+
|
|
4
|
+
const manifest = {
|
|
5
|
+
name: "My Extension",
|
|
6
|
+
version: "1.0.0",
|
|
7
|
+
manifest_version: 3,
|
|
8
|
+
description: "Browser extension built with addfox",
|
|
9
|
+
permissions: ["activeTab"],
|
|
10
|
+
icons: {
|
|
11
|
+
"16": "icons/icon_128.png",
|
|
12
|
+
"48": "icons/icon_128.png",
|
|
13
|
+
"128": "icons/icon_128.png",
|
|
14
|
+
},
|
|
15
|
+
action: {
|
|
16
|
+
default_icon: {
|
|
17
|
+
"16": "icons/icon_128.png",
|
|
18
|
+
"48": "icons/icon_128.png",
|
|
19
|
+
"128": "icons/icon_128.png",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default defineConfig({
|
|
25
|
+
manifest: { chromium: manifest, firefox: { ...manifest } },
|
|
26
|
+
plugins: [pluginPreact()],
|
|
27
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
function openWelcomePage() {
|
|
2
|
+
chrome.tabs.create({ url: chrome.runtime.getURL("welcome.html") });
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
chrome.runtime.onInstalled.addListener((details) => {
|
|
6
|
+
if (details.reason === "install" || details.reason === "update") openWelcomePage();
|
|
7
|
+
console.log("Extension installed");
|
|
8
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log("Content script loaded");
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { h } from "preact";
|
|
2
|
+
|
|
3
|
+
export default function App() {
|
|
4
|
+
const popupStyle = {
|
|
5
|
+
width: 320,
|
|
6
|
+
minHeight: 200,
|
|
7
|
+
padding: 16,
|
|
8
|
+
boxSizing: "border-box",
|
|
9
|
+
display: "flex",
|
|
10
|
+
flexDirection: "column",
|
|
11
|
+
alignItems: "center",
|
|
12
|
+
justifyContent: "center",
|
|
13
|
+
gap: 12,
|
|
14
|
+
fontFamily: 'system-ui, -apple-system, "Segoe UI", sans-serif',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div style={popupStyle}>
|
|
19
|
+
<img src="/icons/icon_128.png" alt="" width={64} height={64} />
|
|
20
|
+
<div style={{ fontSize: 18, fontWeight: 600 }}>AddFox Preact</div>
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-extension",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "addfox dev",
|
|
8
|
+
"build": "addfox build"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"addfox": "^0.1.1-beta.7",
|
|
12
|
+
"@rsbuild/core": "^1.7.3",
|
|
13
|
+
"@addfox/utils": "^0.1.1-beta.5",
|
|
14
|
+
"preact": "^10.29.0"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@rsbuild/plugin-preact": "^1.7.2"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Welcome - Addfox + Preact</title>
|
|
7
|
+
<style>
|
|
8
|
+
body { font-family: system-ui, sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; margin: 0; background: #fafafa; color: #1a1a1a; }
|
|
9
|
+
h1 { font-size: 1.75rem; font-weight: 700; margin: 0 0 0.5rem; }
|
|
10
|
+
p { font-size: 1rem; color: #666; margin: 0; }
|
|
11
|
+
.welcome-icon { width: 96px; height: 96px; margin-bottom: 1rem; object-fit: contain; border-radius: 12px; }
|
|
12
|
+
</style>
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<img class="welcome-icon" src="/icons/icon_128.png" alt="" width="96" height="96" />
|
|
16
|
+
<h1>Addfox + Preact</h1>
|
|
17
|
+
<p>Your extension is ready. Happy building!</p>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { defineConfig } from "addfox";
|
|
2
|
+
import { pluginPreact } from "@rsbuild/plugin-preact";
|
|
3
|
+
|
|
4
|
+
const manifest = {
|
|
5
|
+
name: "My Extension",
|
|
6
|
+
version: "1.0.0",
|
|
7
|
+
manifest_version: 3,
|
|
8
|
+
description: "Browser extension built with addfox",
|
|
9
|
+
permissions: ["activeTab"],
|
|
10
|
+
icons: {
|
|
11
|
+
"16": "icons/icon_128.png",
|
|
12
|
+
"48": "icons/icon_128.png",
|
|
13
|
+
"128": "icons/icon_128.png",
|
|
14
|
+
},
|
|
15
|
+
action: {
|
|
16
|
+
default_icon: {
|
|
17
|
+
"16": "icons/icon_128.png",
|
|
18
|
+
"48": "icons/icon_128.png",
|
|
19
|
+
"128": "icons/icon_128.png",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default defineConfig({
|
|
25
|
+
manifest: { chromium: manifest, firefox: { ...manifest } },
|
|
26
|
+
plugins: [pluginPreact()],
|
|
27
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
function openWelcomePage() {
|
|
2
|
+
chrome.tabs.create({ url: chrome.runtime.getURL("welcome.html") });
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
chrome.runtime.onInstalled.addListener((details) => {
|
|
6
|
+
if (details.reason === "install" || details.reason === "update") openWelcomePage();
|
|
7
|
+
console.log("Extension installed");
|
|
8
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log("Content script loaded");
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { h } from "preact";
|
|
2
|
+
|
|
3
|
+
export default function App() {
|
|
4
|
+
const popupStyle = {
|
|
5
|
+
width: 320,
|
|
6
|
+
minHeight: 200,
|
|
7
|
+
padding: 16,
|
|
8
|
+
boxSizing: "border-box" as const,
|
|
9
|
+
display: "flex",
|
|
10
|
+
flexDirection: "column" as const,
|
|
11
|
+
alignItems: "center",
|
|
12
|
+
justifyContent: "center",
|
|
13
|
+
gap: 12,
|
|
14
|
+
fontFamily: 'system-ui, -apple-system, "Segoe UI", sans-serif',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div style={popupStyle}>
|
|
19
|
+
<img src="/icons/icon_128.png" alt="" width={64} height={64} />
|
|
20
|
+
<div style={{ fontSize: 18, fontWeight: 600 }}>AddFox Preact</div>
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-extension",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "addfox dev",
|
|
8
|
+
"build": "addfox build"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"addfox": "^0.1.1-beta.7",
|
|
12
|
+
"@rsbuild/core": "^1.7.3",
|
|
13
|
+
"@addfox/utils": "^0.1.1-beta.5",
|
|
14
|
+
"preact": "^10.29.0"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@rsbuild/plugin-preact": "^1.7.2",
|
|
18
|
+
"typescript": "^5.9.3",
|
|
19
|
+
"@types/chrome": "^0.1.38"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Welcome - Addfox + Preact</title>
|
|
7
|
+
<style>
|
|
8
|
+
body { font-family: system-ui, sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; margin: 0; background: #fafafa; color: #1a1a1a; }
|
|
9
|
+
h1 { font-size: 1.75rem; font-weight: 700; margin: 0 0 0.5rem; }
|
|
10
|
+
p { font-size: 1rem; color: #666; margin: 0; }
|
|
11
|
+
.welcome-icon { width: 96px; height: 96px; margin-bottom: 1rem; object-fit: contain; border-radius: 12px; }
|
|
12
|
+
</style>
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<img class="welcome-icon" src="/icons/icon_128.png" alt="" width="96" height="96" />
|
|
16
|
+
<h1>Addfox + Preact</h1>
|
|
17
|
+
<p>Your extension is ready. Happy building!</p>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"resolveJsonModule": true,
|
|
9
|
+
"isolatedModules": true,
|
|
10
|
+
"noEmit": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"types": [
|
|
13
|
+
"chrome"
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
"include": [
|
|
17
|
+
"app"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { defineConfig } from "addfox";
|
|
2
|
+
import { pluginReact } from "@rsbuild/plugin-react";
|
|
3
|
+
|
|
4
|
+
const manifest = {
|
|
5
|
+
name: "My Extension",
|
|
6
|
+
version: "1.0.0",
|
|
7
|
+
manifest_version: 3,
|
|
8
|
+
description: "Browser extension built with addfox",
|
|
9
|
+
permissions: ["activeTab"],
|
|
10
|
+
icons: {
|
|
11
|
+
"16": "icons/icon_128.png",
|
|
12
|
+
"48": "icons/icon_128.png",
|
|
13
|
+
"128": "icons/icon_128.png",
|
|
14
|
+
},
|
|
15
|
+
action: {
|
|
16
|
+
default_icon: {
|
|
17
|
+
"16": "icons/icon_128.png",
|
|
18
|
+
"48": "icons/icon_128.png",
|
|
19
|
+
"128": "icons/icon_128.png",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default defineConfig({
|
|
25
|
+
manifest: { chromium: manifest, firefox: { ...manifest } },
|
|
26
|
+
plugins: [pluginReact()],
|
|
27
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
function openWelcomePage() {
|
|
2
|
+
chrome.tabs.create({ url: chrome.runtime.getURL("welcome.html") });
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
chrome.runtime.onInstalled.addListener((details) => {
|
|
6
|
+
if (details.reason === "install" || details.reason === "update") openWelcomePage();
|
|
7
|
+
console.log("Extension installed");
|
|
8
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log("Content script loaded");
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export default function App() {
|
|
2
|
+
const popupStyle = {
|
|
3
|
+
width: 320,
|
|
4
|
+
minHeight: 200,
|
|
5
|
+
padding: 16,
|
|
6
|
+
boxSizing: "border-box",
|
|
7
|
+
display: "flex",
|
|
8
|
+
flexDirection: "column",
|
|
9
|
+
alignItems: "center",
|
|
10
|
+
justifyContent: "center",
|
|
11
|
+
gap: 12,
|
|
12
|
+
fontFamily: 'system-ui, -apple-system, "Segoe UI", sans-serif',
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div style={popupStyle}>
|
|
17
|
+
<img src="/icons/icon_128.png" alt="" width={64} height={64} />
|
|
18
|
+
<div style={{ fontSize: 18, fontWeight: 600 }}>AddFox React</div>
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|