@portosaur/cli 0.1.5 → 0.3.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/bin/porto.mjs +2 -1
- package/package.json +5 -5
- package/src/commands/build.mjs +11 -0
- package/src/commands/dev.mjs +8 -3
- package/src/commands/init.mjs +1 -3
- package/src/commands/serve.mjs +20 -5
- package/src/index.d.ts +1 -1
- package/src/templates/config.yml +4 -4
- package/src/templates/gitignore +1 -1
- package/src/templates/package.json +2 -2
- package/src/utils/paths.mjs +15 -8
- package/src/utils/runner.mjs +64 -42
- package/src/templates/notes/index.mdx +0 -9
package/bin/porto.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portosaur/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "CLI for Portosaur - The static Personal portfolio site generator.",
|
|
5
5
|
"license": "GPL-3.0-only",
|
|
6
6
|
"author": "soymadip",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
],
|
|
17
17
|
"type": "module",
|
|
18
18
|
"bin": {
|
|
19
|
-
"porto": "
|
|
19
|
+
"porto": "bin/porto.mjs"
|
|
20
20
|
},
|
|
21
21
|
"exports": {
|
|
22
22
|
".": {
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
},
|
|
27
27
|
"types": "./src/index.d.ts",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@portosaur/core": "^0.
|
|
30
|
-
"@portosaur/logger": "^0.
|
|
31
|
-
"@portosaur/wizard": "^0.
|
|
29
|
+
"@portosaur/core": "^0.3.0",
|
|
30
|
+
"@portosaur/logger": "^0.3.0",
|
|
31
|
+
"@portosaur/wizard": "^0.3.0",
|
|
32
32
|
"commander": "^13.1.0",
|
|
33
33
|
"js-yaml": "^4.1.1"
|
|
34
34
|
}
|
package/src/commands/build.mjs
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
loadUserConfig,
|
|
13
13
|
generateFavicons,
|
|
14
14
|
generateRobotsTxt,
|
|
15
|
+
getCssVar,
|
|
15
16
|
} from "@portosaur/core";
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -50,11 +51,21 @@ export async function buildCommand(siteDir, extraArgs = []) {
|
|
|
50
51
|
|
|
51
52
|
logger.info("Generating site assets...");
|
|
52
53
|
|
|
54
|
+
const cssFilesToParse = [
|
|
55
|
+
path.join(portoPaths.theme, "css/custom.css"),
|
|
56
|
+
path.join(portoPaths.theme, "css/overrides/variables.css"),
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
const themeColor =
|
|
60
|
+
getCssVar("--ifm-color-primary", cssFilesToParse) || "#3578e5";
|
|
61
|
+
|
|
53
62
|
const faviconRes = await generateFavicons(UserRoot, {
|
|
54
63
|
imagePath: userConfig.home_page?.hero?.profile_pic,
|
|
55
64
|
siteTitle: userConfig.site?.title,
|
|
56
65
|
siteTagline: userConfig.site?.tagline,
|
|
57
66
|
staticDirs: ["static"],
|
|
67
|
+
portoAssetsDir: portoPaths.assets,
|
|
68
|
+
themeColor: themeColor,
|
|
58
69
|
});
|
|
59
70
|
|
|
60
71
|
const configPath = writeConfigShim(UserRoot, portoPaths, {
|
package/src/commands/dev.mjs
CHANGED
|
@@ -41,9 +41,14 @@ export async function devCommand(siteDir, extraArgs = []) {
|
|
|
41
41
|
const watcher = fs.watch(configYamlPath, (eventType) => {
|
|
42
42
|
if (eventType === "change") {
|
|
43
43
|
logger.info(`Detected change in ${configYaml}, reloading...`);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
|
|
45
|
+
// Regenerate the static config shim with the updated values,
|
|
46
|
+
// which triggers Docusaurus' own file watcher to hot-reload.
|
|
47
|
+
try {
|
|
48
|
+
writeConfigShim(UserRoot, portoPaths);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
logger.warn(`Failed to regenerate config: ${err.message}`);
|
|
51
|
+
}
|
|
47
52
|
}
|
|
48
53
|
});
|
|
49
54
|
|
package/src/commands/init.mjs
CHANGED
|
@@ -384,9 +384,7 @@ export async function initCommand(options = {}) {
|
|
|
384
384
|
// to the CLI package to avoid loose dev-mode predictions.
|
|
385
385
|
const isTestProject = looksLikeTestProject(state.projectName);
|
|
386
386
|
|
|
387
|
-
const portoVer = isTestProject
|
|
388
|
-
? "link:@portosaur/cli"
|
|
389
|
-
: porto.version || "0.0.0";
|
|
387
|
+
const portoVer = isTestProject ? "*" : `^${porto.version || "0.0.0"}`;
|
|
390
388
|
|
|
391
389
|
const templateVars = {
|
|
392
390
|
projectName: state.projectName,
|
package/src/commands/serve.mjs
CHANGED
|
@@ -1,27 +1,42 @@
|
|
|
1
1
|
import path from "path";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
runDocusaurus,
|
|
4
|
+
validateProject,
|
|
5
|
+
Paths,
|
|
6
|
+
writeConfigShim,
|
|
7
|
+
} from "../utils/index.mjs";
|
|
3
8
|
import { logger } from "@portosaur/logger";
|
|
4
9
|
|
|
5
10
|
/**
|
|
6
11
|
* Serves the built Portosaur site locally.
|
|
7
|
-
*
|
|
8
|
-
* Note: Docusaurus 'serve' doesn't require a config shim,
|
|
9
|
-
* as it serves the already built static files from the output directory.
|
|
10
12
|
*/
|
|
11
13
|
export async function serveCommand(siteDir, extraArgs = []) {
|
|
12
14
|
const UserRoot = siteDir
|
|
13
15
|
? path.resolve(process.cwd(), siteDir)
|
|
14
16
|
: process.cwd();
|
|
15
17
|
|
|
18
|
+
// Ensure extraArgs is always an array (in case options object is passed)
|
|
19
|
+
const argsArray = Array.isArray(extraArgs) ? extraArgs : [];
|
|
20
|
+
|
|
16
21
|
// ------- Setup -------
|
|
17
22
|
|
|
18
23
|
validateProject(UserRoot);
|
|
19
24
|
|
|
25
|
+
const portoPaths = {
|
|
26
|
+
root: Paths.root,
|
|
27
|
+
assets: path.join(Paths.theme, "assets"),
|
|
28
|
+
theme: path.join(Paths.theme, "theme"),
|
|
29
|
+
plugins: path.join(Paths.theme, "src/plugins"),
|
|
30
|
+
};
|
|
31
|
+
|
|
20
32
|
try {
|
|
21
33
|
logger.info("Serving built site...");
|
|
22
34
|
|
|
35
|
+
// Generate config shim so Docusaurus can locate site configuration
|
|
36
|
+
const configPath = writeConfigShim(UserRoot, portoPaths);
|
|
37
|
+
|
|
23
38
|
// Docusaurus serve looks for the 'build' directory by default.
|
|
24
|
-
await runDocusaurus("serve", UserRoot,
|
|
39
|
+
await runDocusaurus("serve", UserRoot, configPath, argsArray);
|
|
25
40
|
} catch (error) {
|
|
26
41
|
logger.error(`Failed to serve site: ${error.message}`);
|
|
27
42
|
process.exit(1);
|
package/src/index.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export function buildCommand(siteDir?: string, extraArgs?: string[]): void;
|
|
|
41
41
|
/**
|
|
42
42
|
* Serves the built static site locally.
|
|
43
43
|
*/
|
|
44
|
-
export function serveCommand(siteDir?: string): void;
|
|
44
|
+
export function serveCommand(siteDir?: string, extraArgs?: string[]): void;
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
47
|
* Generates the config schema.
|
package/src/templates/config.yml
CHANGED
|
@@ -8,8 +8,8 @@ site:
|
|
|
8
8
|
title: "{{fullName}}"
|
|
9
9
|
tagline: "Short description about you, your passion, your goals etc."
|
|
10
10
|
|
|
11
|
-
favicon: "{{portoRoot}}/
|
|
12
|
-
social_card: "{{portoRoot}}/
|
|
11
|
+
favicon: "{{portoRoot}}/assets/img/svg/icon.svg"
|
|
12
|
+
social_card: "{{portoRoot}}/assets/img/social-card.jpeg"
|
|
13
13
|
|
|
14
14
|
# Auto set if deploying in Github/GitLab Pages
|
|
15
15
|
url: "auto"
|
|
@@ -55,7 +55,7 @@ home_page:
|
|
|
55
55
|
- "skill 1"
|
|
56
56
|
- "skill 2"
|
|
57
57
|
- "skill 3"
|
|
58
|
-
resume: "{{portoRoot}}/
|
|
58
|
+
resume: "{{portoRoot}}/assets/sample-resume.pdf"
|
|
59
59
|
|
|
60
60
|
project_shelf:
|
|
61
61
|
enable: true
|
|
@@ -69,7 +69,7 @@ home_page:
|
|
|
69
69
|
repo: "https://github.com/yourname/project1"
|
|
70
70
|
|
|
71
71
|
- title: "Your Awesome Project 2"
|
|
72
|
-
icon: "{{portoRoot}}/
|
|
72
|
+
icon: "{{portoRoot}}/assets/img/svg/icon.svg"
|
|
73
73
|
bg: "#5c8f2d"
|
|
74
74
|
tags: ["tag1", "tag2", "tag3", "tag4", "tag5", "tag6", "tag7"]
|
|
75
75
|
featured: true
|
package/src/templates/gitignore
CHANGED
package/src/utils/paths.mjs
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
|
|
4
8
|
const srcDir = path.resolve(import.meta.dirname, "../");
|
|
5
9
|
const pkgDir = path.resolve(srcDir, "../");
|
|
6
10
|
|
|
@@ -27,17 +31,20 @@ export const Paths = {
|
|
|
27
31
|
packageJson: path.join(pkgDir, "package.json"),
|
|
28
32
|
|
|
29
33
|
/** Absolute path to the core package. */
|
|
30
|
-
core
|
|
34
|
+
get core() {
|
|
35
|
+
try {
|
|
36
|
+
return path.dirname(require.resolve("@portosaur/core/package.json"));
|
|
37
|
+
} catch {
|
|
38
|
+
return path.resolve(pkgDir, "../core");
|
|
39
|
+
}
|
|
40
|
+
},
|
|
31
41
|
|
|
32
42
|
/** Absolute path to the theme package. */
|
|
33
43
|
get theme() {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (fs.existsSync(localNodeModulesTheme)) {
|
|
39
|
-
return localNodeModulesTheme;
|
|
44
|
+
try {
|
|
45
|
+
return path.dirname(require.resolve("@portosaur/theme/package.json"));
|
|
46
|
+
} catch {
|
|
47
|
+
return path.resolve(pkgDir, "../theme");
|
|
40
48
|
}
|
|
41
|
-
return path.resolve(pkgDir, "../theme");
|
|
42
49
|
},
|
|
43
50
|
};
|
package/src/utils/runner.mjs
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { spawn } from "child_process";
|
|
4
|
+
import { createRequire } from "module";
|
|
5
|
+
import { loadUserConfig, buildDocuConfig } from "@portosaur/core";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
|
-
* Generates a Docusaurus config
|
|
8
|
+
* Generates a static Docusaurus config file by evaluating the Portosaur config
|
|
9
|
+
* at CLI time and serializing the result. This avoids importing @portosaur/core
|
|
10
|
+
* inside Docusaurus' own build/serve runtime.
|
|
11
|
+
*
|
|
7
12
|
* @param {string} UserRoot - The user's project directory.
|
|
8
|
-
* @param {Object} portoPaths - Paths to Portosaur assets and
|
|
13
|
+
* @param {Object} portoPaths - Paths to Portosaur assets and theme.
|
|
9
14
|
* @param {Object} [context={}] - Additional context for config generation.
|
|
10
|
-
* @returns {string} The path to the generated
|
|
15
|
+
* @returns {string} The path to the generated config file.
|
|
11
16
|
*/
|
|
12
17
|
export function writeConfigShim(UserRoot, portoPaths, context = {}) {
|
|
13
18
|
const dotDir = path.join(UserRoot, ".docusaurus", "portosaur");
|
|
@@ -16,35 +21,19 @@ export function writeConfigShim(UserRoot, portoPaths, context = {}) {
|
|
|
16
21
|
fs.mkdirSync(dotDir, { recursive: true });
|
|
17
22
|
}
|
|
18
23
|
|
|
19
|
-
//
|
|
20
|
-
const
|
|
21
|
-
fs.existsSync(path.join(UserRoot, file)),
|
|
22
|
-
);
|
|
23
|
-
if (!configYaml) throw new Error("config.yml not found");
|
|
24
|
-
|
|
25
|
-
const configYamlAbsolute = path
|
|
26
|
-
.resolve(UserRoot, configYaml)
|
|
27
|
-
.replace(/\\/g, "/");
|
|
28
|
-
|
|
29
|
-
// Prepare shim template
|
|
30
|
-
const shimContent = `// Auto-generated by portosaur
|
|
31
|
-
import fs from "fs";
|
|
32
|
-
import yaml from "js-yaml";
|
|
33
|
-
|
|
34
|
-
export default async function getConfig() {
|
|
35
|
-
const { buildDocuConfig } = await import("@portosaur/core");
|
|
36
|
-
const yamlContent = fs.readFileSync("${configYamlAbsolute}", "utf8");
|
|
37
|
-
const rawConf = yaml.load(yamlContent);
|
|
24
|
+
// Load the user's YAML config and evaluate the full Docusaurus config object now.
|
|
25
|
+
const rawConf = loadUserConfig(UserRoot);
|
|
38
26
|
|
|
39
|
-
|
|
40
|
-
portoPaths
|
|
41
|
-
portoRoot:
|
|
42
|
-
|
|
27
|
+
const docuConfig = buildDocuConfig(rawConf, UserRoot, {
|
|
28
|
+
portoPaths,
|
|
29
|
+
portoRoot: path.resolve(portoPaths.root),
|
|
30
|
+
...context,
|
|
43
31
|
});
|
|
44
|
-
}
|
|
45
|
-
`;
|
|
46
32
|
|
|
47
|
-
//
|
|
33
|
+
// Serialize the config as a static export so Docusaurus never needs to
|
|
34
|
+
// dynamically import @portosaur/core during its own build or serve run.
|
|
35
|
+
const shimContent = `// Auto-generated by portosaur — do not edit\nexport default ${JSON.stringify(docuConfig, null, 2)};\n`;
|
|
36
|
+
|
|
48
37
|
const shimPath = path.join(dotDir, "docusaurus.config.js");
|
|
49
38
|
fs.writeFileSync(shimPath, shimContent);
|
|
50
39
|
|
|
@@ -155,27 +144,60 @@ export async function runDocusaurus(
|
|
|
155
144
|
configPath,
|
|
156
145
|
extraArgs = [],
|
|
157
146
|
) {
|
|
158
|
-
const
|
|
159
|
-
"
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
147
|
+
const isBun =
|
|
148
|
+
typeof process !== "undefined" &&
|
|
149
|
+
process.versions &&
|
|
150
|
+
process.versions.bun !== undefined;
|
|
151
|
+
|
|
152
|
+
let bin;
|
|
153
|
+
let args;
|
|
154
|
+
|
|
155
|
+
if (isBun) {
|
|
156
|
+
bin = "bun";
|
|
157
|
+
args = ["run", "--bun", "docusaurus", command, UserRoot];
|
|
158
|
+
} else {
|
|
159
|
+
bin = "node";
|
|
160
|
+
let docusaurusBin;
|
|
161
|
+
try {
|
|
162
|
+
const require = createRequire(import.meta.url);
|
|
163
|
+
docusaurusBin = require.resolve("docusaurus/bin/docusaurus.mjs", {
|
|
164
|
+
paths: [UserRoot],
|
|
165
|
+
});
|
|
166
|
+
} catch (e) {
|
|
167
|
+
docusaurusBin = path.join(
|
|
168
|
+
UserRoot,
|
|
169
|
+
"node_modules",
|
|
170
|
+
"docusaurus",
|
|
171
|
+
"bin",
|
|
172
|
+
"docusaurus.mjs",
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
args = [docusaurusBin, command, UserRoot];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (configPath) {
|
|
179
|
+
args.push("--config", configPath);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
args.push(...extraArgs);
|
|
168
183
|
|
|
169
184
|
// Skip actual execution in test mode
|
|
170
185
|
if (process.env.PORTO_TEST_MODE === "true") {
|
|
171
|
-
console.log(
|
|
186
|
+
console.log(
|
|
187
|
+
`[TEST_MODE] Would run docusaurus ${command} in ${UserRoot} using ${bin}`,
|
|
188
|
+
);
|
|
172
189
|
return Promise.resolve();
|
|
173
190
|
}
|
|
174
191
|
|
|
175
|
-
const
|
|
192
|
+
const childEnv = { ...process.env, FORCE_COLOR: "true" };
|
|
193
|
+
if (command === "build") {
|
|
194
|
+
childEnv.CI = "true";
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const child = spawn(bin, args, {
|
|
176
198
|
stdio: "inherit",
|
|
177
199
|
cwd: UserRoot,
|
|
178
|
-
env:
|
|
200
|
+
env: childEnv,
|
|
179
201
|
});
|
|
180
202
|
|
|
181
203
|
return new Promise((resolve, reject) => {
|