@gitpagedocs/cli 1.1.55 → 1.1.58
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 +13 -1
- package/ai/application/run-ai-cli-command.ts +16 -5
- package/ai/core/models/parse-ai-cli-config.ts +78 -0
- package/ai/infrastructure/ai-config-file.ts +77 -8
- package/ai/infrastructure/file-system-adapter.ts +5 -3
- package/ai/presentation/ai-prompts.ts +1 -1
- package/application/report/config-only-reporter.mjs +63 -62
- package/builders/config-orchestrator.mjs +34 -34
- package/builders/project-links.mjs +26 -0
- package/builders/root-config-builder.mjs +11 -16
- package/builders/route-builders.mjs +136 -136
- package/builders/theme-template.mjs +76 -75
- package/builders/version-config-builder.mjs +186 -157
- package/content/docs-en.mjs +26 -24
- package/content/docs-es.mjs +20 -20
- package/content/docs-pt.mjs +20 -20
- package/contracts/doc-versions.mjs +3 -3
- package/contracts/index.mjs +0 -0
- package/data/i18n-langmenu.mjs +35 -35
- package/data/layouts.mjs +20 -0
- package/data/path-mappings.mjs +26 -26
- package/data/route-metas.mjs +93 -93
- package/data/theme-colors.mjs +8 -0
- package/data/urls.mjs +12 -7
- package/package.json +60 -60
- package/presentation/commands/config-clear.ts +23 -0
- package/presentation/commands/diagnostics.ts +1 -1
- package/presentation/commands/run-command.ts +6 -0
- package/presentation/index.ts +1 -1
- package/runtime/output.mjs +35 -35
- package/runtime/workflow.mjs +47 -27
- package/ui/logger.mjs +9 -9
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@ npx @gitpagedocs/cli
|
|
|
27
27
|
| `gitpagedocs password` | Set a documentation access password (writes the public key to `config.json`, prints the private key) |
|
|
28
28
|
| `gitpagedocs deploy` / `pages [actions\|deploy]` | Configure GitHub Pages via Actions + push |
|
|
29
29
|
| `gitpagedocs docs` | Refresh managed regions of README/CONTRIBUTING/SECURITY |
|
|
30
|
+
| `gitpagedocs config clear` | Delete the stored `.gitpagedocsconfig` (wipes saved AI credentials) |
|
|
30
31
|
| `gitpagedocs doctor` · `version` · `update` | Diagnostics / version / update hint |
|
|
31
32
|
| `gitpagedocs mcp start` | Start the MCP server over stdio |
|
|
32
33
|
|
|
@@ -150,7 +151,18 @@ later plain `gitpagedocs` rebuild drops the wiring — re-run `gitpagedocs ai` t
|
|
|
150
151
|
|
|
151
152
|
### `.gitpagedocsconfig` (manual mode)
|
|
152
153
|
|
|
153
|
-
|
|
154
|
+
The file lives in the per-user OS config directory (never inside the repository, so
|
|
155
|
+
the API key cannot be committed by accident) and is written with owner-only
|
|
156
|
+
permissions on POSIX systems:
|
|
157
|
+
|
|
158
|
+
- Windows: `%APPDATA%\gitpagedocs\.gitpagedocsconfig`
|
|
159
|
+
- macOS: `~/Library/Application Support/gitpagedocs/.gitpagedocsconfig`
|
|
160
|
+
- Linux: `$XDG_CONFIG_HOME/gitpagedocs/.gitpagedocsconfig` (or `~/.config/gitpagedocs/.gitpagedocsconfig`)
|
|
161
|
+
|
|
162
|
+
Set `GITPAGEDOCS_CONFIG_DIR` to override the directory; delete the stored file
|
|
163
|
+
and its credentials with `gitpagedocs config clear`; a legacy
|
|
164
|
+
`.gitpagedocsconfig` in the repository root is migrated automatically on the next
|
|
165
|
+
run. You can create/edit this file manually and then run `npx gitpagedocs ai`:
|
|
154
166
|
|
|
155
167
|
```json
|
|
156
168
|
{
|
|
@@ -76,8 +76,15 @@ async function collectFilesWithInteractiveFallback(
|
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
/** Factory seam so tests can inject a deterministic provider (DIP). */
|
|
80
|
+
export type AiProviderFactory = typeof createAiProvider;
|
|
81
|
+
|
|
82
|
+
export async function executeAiRunPlan(
|
|
83
|
+
plan: AiCliRunPlan,
|
|
84
|
+
cwd: string,
|
|
85
|
+
createProvider: AiProviderFactory = createAiProvider,
|
|
86
|
+
): Promise<AiCliRunSummary> {
|
|
87
|
+
const provider = createProvider({
|
|
81
88
|
provider: plan.config.ai.provider,
|
|
82
89
|
model: plan.config.ai.model,
|
|
83
90
|
apiKey: plan.config.ai.apiKey,
|
|
@@ -85,7 +92,7 @@ async function runPlan(plan: AiCliRunPlan, cwd: string): Promise<AiCliRunSummary
|
|
|
85
92
|
});
|
|
86
93
|
|
|
87
94
|
const aiService = new AiCommandService(provider);
|
|
88
|
-
const fileSystem = new FileSystemAdapter();
|
|
95
|
+
const fileSystem = new FileSystemAdapter(cwd);
|
|
89
96
|
|
|
90
97
|
const { files, scanned, skipped } = await collectFilesWithInteractiveFallback(
|
|
91
98
|
fileSystem,
|
|
@@ -131,7 +138,11 @@ export async function runAiCliCommand(options: {
|
|
|
131
138
|
onScaffold?: () => Promise<void>;
|
|
132
139
|
}): Promise<{ summary: AiCliRunSummary; runConfigScaffold: boolean }> {
|
|
133
140
|
const logInfo = options.onInfo ?? (() => undefined);
|
|
134
|
-
const configRepo = new AiConfigFileRepository(
|
|
141
|
+
const configRepo = new AiConfigFileRepository({
|
|
142
|
+
cwd: options.cwd,
|
|
143
|
+
onMigrate: (fromPath, toPath) =>
|
|
144
|
+
logInfo(`[gitpagedocs:ai] Moved configuration from ${fromPath} to ${toPath} (secure user config directory).`),
|
|
145
|
+
});
|
|
135
146
|
|
|
136
147
|
const existingConfig = await configRepo.read();
|
|
137
148
|
const plan = await runAiInteractivePrompt(existingConfig);
|
|
@@ -148,7 +159,7 @@ export async function runAiCliCommand(options: {
|
|
|
148
159
|
await options.onScaffold();
|
|
149
160
|
}
|
|
150
161
|
|
|
151
|
-
const summary = await
|
|
162
|
+
const summary = await executeAiRunPlan(plan, options.cwd);
|
|
152
163
|
return {
|
|
153
164
|
summary,
|
|
154
165
|
runConfigScaffold: plan.runConfigScaffold,
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { AI_MODEL_DEFAULTS, type AiProviderId } from "../../config";
|
|
2
|
+
import type { AiCliConfig } from "./ai-cli-config";
|
|
3
|
+
|
|
4
|
+
const SUPPORTED_PROVIDERS = Object.keys(AI_MODEL_DEFAULTS) as AiProviderId[];
|
|
5
|
+
const SUPPORTED_LANGUAGES: ReadonlyArray<AiCliConfig["ai"]["languages"][number]> = ["pt", "en", "es"];
|
|
6
|
+
|
|
7
|
+
/** Fallbacks for optional fields, mirroring the interactive prompt defaults. */
|
|
8
|
+
const DEFAULT_LANGUAGES: AiCliConfig["ai"]["languages"] = ["en", "pt", "es"];
|
|
9
|
+
const DEFAULT_OUTPUT_DIR = "gitpagedocs/docs";
|
|
10
|
+
const DEFAULT_FILE_PREFIX = "ai-generated";
|
|
11
|
+
|
|
12
|
+
function isString(value: unknown): value is string {
|
|
13
|
+
return typeof value === "string";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function asOptionalString(value: unknown): string | undefined {
|
|
17
|
+
return isString(value) ? value : undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function asStringWithDefault(value: unknown, fallback: string): string {
|
|
21
|
+
return isString(value) ? value : fallback;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function asPaths(value: unknown): string[] {
|
|
25
|
+
return Array.isArray(value) ? value.filter(isString) : [];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function asLanguages(value: unknown): AiCliConfig["ai"]["languages"] {
|
|
29
|
+
const languages = Array.isArray(value)
|
|
30
|
+
? value.filter((language): language is AiCliConfig["ai"]["languages"][number] =>
|
|
31
|
+
SUPPORTED_LANGUAGES.includes(language as AiCliConfig["ai"]["languages"][number]),
|
|
32
|
+
)
|
|
33
|
+
: [];
|
|
34
|
+
return languages.length > 0 ? languages : [...DEFAULT_LANGUAGES];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function asProviderId(value: unknown): AiProviderId | null {
|
|
38
|
+
return isString(value) && SUPPORTED_PROVIDERS.includes(value as AiProviderId)
|
|
39
|
+
? (value as AiProviderId)
|
|
40
|
+
: null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Validate an untrusted `.gitpagedocsconfig` payload. Tolerant by design so
|
|
45
|
+
* hand-edited configs keep working: only the version-1 envelope and a known
|
|
46
|
+
* provider are required; every other field falls back to the interactive
|
|
47
|
+
* prompt defaults. Returns a sanitized {@link AiCliConfig} with only known
|
|
48
|
+
* fields, or `null` when the payload cannot identify a provider.
|
|
49
|
+
*/
|
|
50
|
+
export function parseAiCliConfig(raw: unknown): AiCliConfig | null {
|
|
51
|
+
if (typeof raw !== "object" || raw === null) return null;
|
|
52
|
+
const candidate = raw as Partial<AiCliConfig>;
|
|
53
|
+
if (candidate.version !== 1) return null;
|
|
54
|
+
|
|
55
|
+
const ai = candidate.ai;
|
|
56
|
+
if (typeof ai !== "object" || ai === null) return null;
|
|
57
|
+
const provider = asProviderId(ai.provider);
|
|
58
|
+
if (!provider) return null;
|
|
59
|
+
|
|
60
|
+
const model = asOptionalString(ai.model)?.trim() || AI_MODEL_DEFAULTS[provider];
|
|
61
|
+
const apiKey = asOptionalString(ai.apiKey);
|
|
62
|
+
const baseUrl = asOptionalString(ai.baseUrl);
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
version: 1,
|
|
66
|
+
ai: {
|
|
67
|
+
provider,
|
|
68
|
+
model,
|
|
69
|
+
...(apiKey !== undefined ? { apiKey } : {}),
|
|
70
|
+
...(baseUrl !== undefined ? { baseUrl } : {}),
|
|
71
|
+
paths: asPaths(ai.paths),
|
|
72
|
+
languages: asLanguages(ai.languages),
|
|
73
|
+
outputDir: asStringWithDefault(ai.outputDir, DEFAULT_OUTPUT_DIR),
|
|
74
|
+
filePrefix: asStringWithDefault(ai.filePrefix, DEFAULT_FILE_PREFIX),
|
|
75
|
+
contextPrompt: asStringWithDefault(ai.contextPrompt, ""),
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -1,32 +1,101 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { resolveUserConfigDir } from "@gitpagedocs/tools";
|
|
3
4
|
import {
|
|
4
5
|
AI_CLI_CONFIG_FILENAME,
|
|
5
6
|
type AiCliConfig,
|
|
6
7
|
} from "../core/models/ai-cli-config";
|
|
8
|
+
import { parseAiCliConfig } from "../core/models/parse-ai-cli-config";
|
|
7
9
|
|
|
10
|
+
/** Owner-only directory/file permissions (no-op on Windows, enforced on POSIX). */
|
|
11
|
+
const CONFIG_DIR_MODE = 0o700;
|
|
12
|
+
const CONFIG_FILE_MODE = 0o600;
|
|
13
|
+
|
|
14
|
+
export interface AiConfigFileRepositoryOptions {
|
|
15
|
+
/** Working directory searched for a legacy `<cwd>/.gitpagedocsconfig`. */
|
|
16
|
+
cwd?: string;
|
|
17
|
+
/** Destination directory; defaults to the per-user OS config directory. */
|
|
18
|
+
configDir?: string;
|
|
19
|
+
/** Notified after a legacy config is moved into the user config directory. */
|
|
20
|
+
onMigrate?: (fromPath: string, toPath: string) => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Stores `.gitpagedocsconfig` in the per-user OS config directory
|
|
25
|
+
* (`%APPDATA%\gitpagedocs` on Windows, `~/Library/Application Support/gitpagedocs`
|
|
26
|
+
* on macOS, `$XDG_CONFIG_HOME/gitpagedocs` elsewhere) with owner-only
|
|
27
|
+
* permissions, so the API key never lives inside a repository checkout.
|
|
28
|
+
* A legacy `<cwd>/.gitpagedocsconfig` is migrated automatically on first read.
|
|
29
|
+
*/
|
|
8
30
|
export class AiConfigFileRepository {
|
|
9
|
-
|
|
31
|
+
private readonly cwd: string;
|
|
32
|
+
private readonly configDir: string;
|
|
33
|
+
private readonly onMigrate?: (fromPath: string, toPath: string) => void;
|
|
34
|
+
|
|
35
|
+
constructor(options: AiConfigFileRepositoryOptions = {}) {
|
|
36
|
+
this.cwd = options.cwd ?? process.cwd();
|
|
37
|
+
this.configDir = options.configDir ?? resolveUserConfigDir();
|
|
38
|
+
this.onMigrate = options.onMigrate;
|
|
39
|
+
}
|
|
10
40
|
|
|
11
41
|
getConfigPath(): string {
|
|
42
|
+
return path.join(this.configDir, AI_CLI_CONFIG_FILENAME);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
getLegacyConfigPath(): string {
|
|
12
46
|
return path.join(this.cwd, AI_CLI_CONFIG_FILENAME);
|
|
13
47
|
}
|
|
14
48
|
|
|
15
49
|
async read(): Promise<AiCliConfig | null> {
|
|
50
|
+
const current = await this.readFrom(this.getConfigPath());
|
|
51
|
+
if (current) return current;
|
|
52
|
+
return this.migrateLegacyConfig();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Delete the stored configuration (secure and legacy locations), wiping
|
|
56
|
+
* any saved credentials. Returns the paths that were actually removed. */
|
|
57
|
+
async clear(): Promise<string[]> {
|
|
58
|
+
const removed: string[] = [];
|
|
59
|
+
const candidates = new Set([this.getConfigPath(), this.getLegacyConfigPath()].map((p) => path.resolve(p)));
|
|
60
|
+
for (const configPath of candidates) {
|
|
61
|
+
try {
|
|
62
|
+
await fs.rm(configPath);
|
|
63
|
+
removed.push(configPath);
|
|
64
|
+
} catch {
|
|
65
|
+
// Missing file: nothing to remove at this location.
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return removed;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async write(config: AiCliConfig): Promise<void> {
|
|
16
72
|
const configPath = this.getConfigPath();
|
|
73
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true, mode: CONFIG_DIR_MODE });
|
|
74
|
+
const data = `${JSON.stringify(config, null, 2)}\n`;
|
|
75
|
+
await fs.writeFile(configPath, data, { encoding: "utf-8", mode: CONFIG_FILE_MODE });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private async readFrom(configPath: string): Promise<AiCliConfig | null> {
|
|
17
79
|
try {
|
|
18
80
|
const content = await fs.readFile(configPath, "utf-8");
|
|
19
|
-
|
|
20
|
-
if (!parsed || parsed.version !== 1 || !parsed.ai) return null;
|
|
21
|
-
return parsed as AiCliConfig;
|
|
81
|
+
return parseAiCliConfig(JSON.parse(content));
|
|
22
82
|
} catch {
|
|
23
83
|
return null;
|
|
24
84
|
}
|
|
25
85
|
}
|
|
26
86
|
|
|
27
|
-
async
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
await
|
|
87
|
+
private async migrateLegacyConfig(): Promise<AiCliConfig | null> {
|
|
88
|
+
const legacyPath = this.getLegacyConfigPath();
|
|
89
|
+
if (path.resolve(legacyPath) === path.resolve(this.getConfigPath())) return null;
|
|
90
|
+
const legacy = await this.readFrom(legacyPath);
|
|
91
|
+
if (!legacy) return null;
|
|
92
|
+
try {
|
|
93
|
+
await this.write(legacy);
|
|
94
|
+
await fs.rm(legacyPath, { force: true });
|
|
95
|
+
this.onMigrate?.(legacyPath, this.getConfigPath());
|
|
96
|
+
} catch {
|
|
97
|
+
// Migration is best-effort: keep serving the legacy config on failure.
|
|
98
|
+
}
|
|
99
|
+
return legacy;
|
|
31
100
|
}
|
|
32
101
|
}
|
|
@@ -8,12 +8,14 @@ export interface FilePayload {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export class FileSystemAdapter {
|
|
11
|
+
constructor(private readonly baseDir: string = process.cwd()) {}
|
|
12
|
+
|
|
11
13
|
splitExistingDirectories(targetDirectories: string[]): { existing: string[]; missing: string[] } {
|
|
12
14
|
const existing: string[] = [];
|
|
13
15
|
const missing: string[] = [];
|
|
14
16
|
|
|
15
17
|
for (const targetDirectory of targetDirectories) {
|
|
16
|
-
const absolutePath = path.resolve(
|
|
18
|
+
const absolutePath = path.resolve(this.baseDir, targetDirectory);
|
|
17
19
|
try {
|
|
18
20
|
const stat = statSync(absolutePath);
|
|
19
21
|
if (stat.isDirectory()) {
|
|
@@ -30,7 +32,7 @@ export class FileSystemAdapter {
|
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
async readDirectoryRecursively(targetDirectory: string): Promise<FilePayload[]> {
|
|
33
|
-
const absolutePath = path.resolve(
|
|
35
|
+
const absolutePath = path.resolve(this.baseDir, targetDirectory);
|
|
34
36
|
const resolvedFiles: FilePayload[] = [];
|
|
35
37
|
|
|
36
38
|
try {
|
|
@@ -76,7 +78,7 @@ export class FileSystemAdapter {
|
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
async writeDocumentationOutput(outputContent: string, targetPath: string = "documentation-output.md"): Promise<void> {
|
|
79
|
-
const absoluteDest = path.resolve(
|
|
81
|
+
const absoluteDest = path.resolve(this.baseDir, targetPath);
|
|
80
82
|
await fs.mkdir(path.dirname(absoluteDest), { recursive: true });
|
|
81
83
|
await fs.writeFile(absoluteDest, outputContent, 'utf-8');
|
|
82
84
|
}
|
|
@@ -153,7 +153,7 @@ export async function promptUseExistingConfig(existingConfig: AiCliConfig): Prom
|
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
export async function runAiInteractivePrompt(existingConfig?: AiCliConfig | null): Promise<AiCliRunPlan> {
|
|
156
|
-
intro('
|
|
156
|
+
intro('GitPageDocs AI CLI - interactive mode');
|
|
157
157
|
|
|
158
158
|
if (existingConfig) {
|
|
159
159
|
const existingPlan = await promptUseExistingConfig(existingConfig);
|
|
@@ -1,62 +1,63 @@
|
|
|
1
|
-
/** Config-only command output messages - SRP: single place for all report messages */
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
`
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
lines
|
|
47
|
-
lines.push(...
|
|
48
|
-
lines.push(...
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
1
|
+
/** Config-only command output messages - SRP: single place for all report messages */
|
|
2
|
+
import { resolveRenderingUrl } from "../../builders/project-links.mjs";
|
|
3
|
+
|
|
4
|
+
export function reportConfigOnlySuccess(options) {
|
|
5
|
+
return [`Generated: ${options.outputDir}/ (config-only)`, "No index.html/index.js generated."];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function reportLayoutConfig(options) {
|
|
9
|
+
if (options.useLocalLayoutConfig) {
|
|
10
|
+
return ["Local layouts generated in gitpagedocs/layouts/ (--layoutconfig)."];
|
|
11
|
+
} else {
|
|
12
|
+
return ["Using official remote layouts config by default (no local gitpagedocs/layouts generated)."];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function reportRenderingUrl(options) {
|
|
17
|
+
if (options.githubOwner && options.githubRepo) {
|
|
18
|
+
return [
|
|
19
|
+
`Configured rendering URL: ${resolveRenderingUrl(options.githubOwner, options.githubRepo)}`,
|
|
20
|
+
`Official viewer remains available: https://vidigal-code.github.io/git-page-docs/${options.githubOwner}/${options.githubRepo}?modetheme=light&lang=pt`,
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function reportPushMode() {
|
|
27
|
+
return [
|
|
28
|
+
"Generated: .github/workflows/gitpagedocs-pages.yml",
|
|
29
|
+
"Push mode enabled: committed and pushed gitpagedocs/ + workflow to origin.",
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function reportBuildFlag() {
|
|
34
|
+
return ["`--build` keeps compatibility flag but output remains gitpagedocs/."];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function reportFullOrServeSkipped() {
|
|
38
|
+
return ["External commands were skipped (no prebuilt copy and no local serve spawn)."];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function reportPrebuiltDetected() {
|
|
42
|
+
return ["`prebuilt/` detected, but ignored by config-only generator."];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function reportAll(options, prebuiltDetected) {
|
|
46
|
+
const lines = [];
|
|
47
|
+
lines.push(...reportConfigOnlySuccess(options));
|
|
48
|
+
lines.push(...reportLayoutConfig(options));
|
|
49
|
+
lines.push(...reportRenderingUrl(options));
|
|
50
|
+
if (options.shouldPush) {
|
|
51
|
+
lines.push(...reportPushMode());
|
|
52
|
+
}
|
|
53
|
+
if (options.isBuild) {
|
|
54
|
+
lines.push(...reportBuildFlag());
|
|
55
|
+
}
|
|
56
|
+
if (options.mode === "full" || options.isServe) {
|
|
57
|
+
lines.push(...reportFullOrServeSkipped());
|
|
58
|
+
}
|
|
59
|
+
if (prebuiltDetected) {
|
|
60
|
+
lines.push(...reportPrebuiltDetected());
|
|
61
|
+
}
|
|
62
|
+
return lines;
|
|
63
|
+
}
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
/** Orchestrate build of config artifacts for gitpagedocs */
|
|
2
|
-
|
|
3
|
-
import { LAYOUTS, FALLBACK_LAYOUTS } from "../data/layouts.mjs";
|
|
4
|
-
import { DOCS } from "../content/docs.mjs";
|
|
5
|
-
import { DOC_VERSIONS } from "../data/version-constants.mjs";
|
|
6
|
-
import { buildRootConfig } from "./root-config-builder.mjs";
|
|
7
|
-
import { buildVersionConfig } from "./version-config-builder.mjs";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Build all config artifacts (root, layouts, versions, docs).
|
|
11
|
-
* @param {object} options - { useLocalLayoutConfig, githubOwner, githubRepo, root }
|
|
12
|
-
* @returns {object} { rootConfig, layoutsConfig, fallbackLayoutsConfig, docs, docsHtml, versionConfigs }
|
|
13
|
-
*/
|
|
14
|
-
export function buildConfigArtifacts(options = {}) {
|
|
15
|
-
const root = options.root ?? process.cwd();
|
|
16
|
-
|
|
17
|
-
const rootConfig = buildRootConfig(options);
|
|
18
|
-
const layoutsConfig = { layouts: LAYOUTS };
|
|
19
|
-
const fallbackLayoutsConfig = { layouts: FALLBACK_LAYOUTS };
|
|
20
|
-
|
|
21
|
-
const versionConfigs = {};
|
|
22
|
-
for (const versionId of DOC_VERSIONS) {
|
|
23
|
-
versionConfigs[versionId] = buildVersionConfig(versionId);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
rootConfig,
|
|
28
|
-
layoutsConfig,
|
|
29
|
-
fallbackLayoutsConfig,
|
|
30
|
-
docs: DOCS,
|
|
31
|
-
docsHtml: {},
|
|
32
|
-
versionConfigs,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
1
|
+
/** Orchestrate build of config artifacts for gitpagedocs */
|
|
2
|
+
|
|
3
|
+
import { LAYOUTS, FALLBACK_LAYOUTS } from "../data/layouts.mjs";
|
|
4
|
+
import { DOCS } from "../content/docs.mjs";
|
|
5
|
+
import { DOC_VERSIONS } from "../data/version-constants.mjs";
|
|
6
|
+
import { buildRootConfig } from "./root-config-builder.mjs";
|
|
7
|
+
import { buildVersionConfig } from "./version-config-builder.mjs";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Build all config artifacts (root, layouts, versions, docs).
|
|
11
|
+
* @param {object} options - { useLocalLayoutConfig, githubOwner, githubRepo, root }
|
|
12
|
+
* @returns {object} { rootConfig, layoutsConfig, fallbackLayoutsConfig, docs, docsHtml, versionConfigs }
|
|
13
|
+
*/
|
|
14
|
+
export function buildConfigArtifacts(options = {}) {
|
|
15
|
+
const root = options.root ?? process.cwd();
|
|
16
|
+
|
|
17
|
+
const rootConfig = buildRootConfig(options);
|
|
18
|
+
const layoutsConfig = { layouts: LAYOUTS };
|
|
19
|
+
const fallbackLayoutsConfig = { layouts: FALLBACK_LAYOUTS };
|
|
20
|
+
|
|
21
|
+
const versionConfigs = {};
|
|
22
|
+
for (const versionId of DOC_VERSIONS) {
|
|
23
|
+
versionConfigs[versionId] = buildVersionConfig(versionId, options);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
rootConfig,
|
|
28
|
+
layoutsConfig,
|
|
29
|
+
fallbackLayoutsConfig,
|
|
30
|
+
docs: DOCS,
|
|
31
|
+
docsHtml: {},
|
|
32
|
+
versionConfigs,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Shared derivation of project URLs from CLI options (single source of truth
|
|
2
|
+
* for root and version config builders). */
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_PROJECT_LINK = "https://github.com/Vidigal-code/git-page-docs";
|
|
5
|
+
export const DEFAULT_RENDERING_URL = "https://vidigal-code.github.io/git-page-docs/";
|
|
6
|
+
|
|
7
|
+
export function resolveProjectLink(githubOwner, githubRepo) {
|
|
8
|
+
return githubOwner && githubRepo
|
|
9
|
+
? `https://github.com/${githubOwner}/${githubRepo}`
|
|
10
|
+
: DEFAULT_PROJECT_LINK;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function resolveRenderingUrl(githubOwner, githubRepo) {
|
|
14
|
+
return githubOwner && githubRepo
|
|
15
|
+
? `https://${githubOwner}.github.io/${githubRepo}/`
|
|
16
|
+
: DEFAULT_RENDERING_URL;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function resolveSourceViewerPath(githubOwner, githubRepo) {
|
|
20
|
+
// User repositories use the symbolic HEAD ref so any default branch works
|
|
21
|
+
// (github.com, the trees API and raw.githubusercontent all accept it);
|
|
22
|
+
// the official repository keeps its stable main link.
|
|
23
|
+
return githubOwner && githubRepo
|
|
24
|
+
? `${resolveProjectLink(githubOwner, githubRepo)}/tree/HEAD`
|
|
25
|
+
: `${DEFAULT_PROJECT_LINK}/tree/main`;
|
|
26
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** Build root config for gitpagedocs */
|
|
2
2
|
import { OFFICIAL_LAYOUTS_CONFIG_URL, OFFICIAL_LAYOUTS_TEMPLATES_URL } from "../data/urls.mjs";
|
|
3
|
+
import { resolveProjectLink, resolveRenderingUrl, resolveSourceViewerPath } from "./project-links.mjs";
|
|
3
4
|
import { DOCS } from "../content/docs.mjs";
|
|
4
5
|
import { DOC_VERSIONS } from "../data/version-constants.mjs";
|
|
5
6
|
import { defaultLangMenu } from "../data/i18n-langmenu.mjs";
|
|
@@ -11,16 +12,10 @@ export function buildRootConfig(options = {}) {
|
|
|
11
12
|
const useOfficialLayouts = !useLocalLayoutConfig;
|
|
12
13
|
const githubOwner = options.githubOwner;
|
|
13
14
|
const githubRepo = options.githubRepo;
|
|
14
|
-
const repositorySearchHome = true;
|
|
15
|
-
const renderingUrl =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
: "https://vidigal-code.github.io/git-page-docs/";
|
|
19
|
-
const projectLink =
|
|
20
|
-
githubOwner && githubRepo
|
|
21
|
-
? `https://github.com/${githubOwner}/${githubRepo}`
|
|
22
|
-
: "https://github.com/Vidigal-code/git-page-docs";
|
|
23
|
-
const sourceViewerPath = `${projectLink}/tree/main`;
|
|
15
|
+
const repositorySearchHome = true;
|
|
16
|
+
const renderingUrl = resolveRenderingUrl(githubOwner, githubRepo);
|
|
17
|
+
const projectLink = resolveProjectLink(githubOwner, githubRepo);
|
|
18
|
+
const sourceViewerPath = resolveSourceViewerPath(githubOwner, githubRepo);
|
|
24
19
|
|
|
25
20
|
const versionEntries = DOC_VERSIONS.map((id) => ({
|
|
26
21
|
id,
|
|
@@ -29,12 +24,12 @@ export function buildRootConfig(options = {}) {
|
|
|
29
24
|
PathConfig: `gitpagedocs/docs/versions/${id}/config.json`,
|
|
30
25
|
PreviewProject: "",
|
|
31
26
|
UpdateDate: "",
|
|
32
|
-
branch: "",
|
|
33
|
-
release: "",
|
|
34
|
-
commit: "",
|
|
35
|
-
"source-viewer": true,
|
|
36
|
-
"source-viewer-path": sourceViewerPath,
|
|
37
|
-
}));
|
|
27
|
+
branch: "",
|
|
28
|
+
release: "",
|
|
29
|
+
commit: "",
|
|
30
|
+
"source-viewer": true,
|
|
31
|
+
"source-viewer-path": sourceViewerPath,
|
|
32
|
+
}));
|
|
38
33
|
|
|
39
34
|
const baseSiteConfig = getDefaultSiteConfig(DOCS, projectLink);
|
|
40
35
|
|