@gitpagedocs/cli 1.1.68 → 1.1.70

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.
Files changed (38) hide show
  1. package/ai/application/ai-command.ts +1 -1
  2. package/ai/application/docs-pattern.ts +9 -5
  3. package/ai/application/resolve-chat-credentials.ts +13 -6
  4. package/ai/core/models/parse-ai-cli-config.ts +6 -8
  5. package/application/home/handler.mjs +3 -1
  6. package/application/ports/cli-runtime-ports.ts +2 -0
  7. package/application/report/config-only-reporter.mjs +2 -5
  8. package/builders/config-orchestrator.mjs +4 -7
  9. package/builders/language-bundles-builder.mjs +4 -4
  10. package/builders/root-config-builder.mjs +1 -1
  11. package/content/docs-en.mjs +4 -4
  12. package/content/docs-es.mjs +4 -4
  13. package/content/docs-pt.mjs +4 -4
  14. package/contracts/doc-versions.mjs +1 -1
  15. package/contracts/langs-paths.mjs +8 -5
  16. package/contracts/layouts-paths.mjs +4 -4
  17. package/contracts/path-segments.d.mts +2 -0
  18. package/contracts/path-segments.mjs +15 -0
  19. package/data/default-site-config.mjs +9 -2
  20. package/data/i18n-langmenu.mjs +3 -0
  21. package/domain/services/layouts-migration.mjs +15 -1
  22. package/home/home-file-writer.mjs +2 -3
  23. package/home/templates.mjs +5 -2
  24. package/infrastructure/home/runtime.mjs +2 -2
  25. package/package.json +3 -3
  26. package/presentation/commands/config-info.ts +44 -9
  27. package/presentation/commands/diagnostics.ts +30 -20
  28. package/presentation/commands/docs.ts +7 -2
  29. package/presentation/commands/pages.ts +4 -2
  30. package/presentation/options/parser.ts +46 -45
  31. package/presentation/ui/prompts.ts +6 -5
  32. package/runtime/doc-path-resolver.mjs +8 -6
  33. package/runtime/exec.mjs +168 -0
  34. package/runtime/git-ops.mjs +22 -20
  35. package/runtime/layouts-migrator.mjs +15 -1
  36. package/runtime/output.mjs +88 -58
  37. package/runtime/workflow.mjs +3 -1
  38. package/start.mjs +8 -6
@@ -77,19 +77,101 @@ async function writeLayoutArtifacts(options) {
77
77
  }
78
78
  }
79
79
 
80
- /** Write the language manifest and one UI-strings bundle per shipped language. */
80
+ /**
81
+ * Write one UI-strings bundle per shipped language. Which ones are on is
82
+ * `site.languages` in config.json, so the 1.1.68 `langs.json` manifest is
83
+ * removed: a stale copy would only mislead.
84
+ */
81
85
  async function writeLanguageArtifacts(root, outputDir, artifacts) {
82
86
  const paths = languageArtifactPaths(outputDir);
83
- await writeJson(root, paths.manifest, artifacts.languageManifest);
87
+ rmSync(path.join(root, paths.legacyManifest), { force: true });
84
88
  for (const [language, bundle] of Object.entries(artifacts.languageBundles)) {
85
89
  await writeJson(root, paths.bundle(language), bundle);
86
90
  }
87
91
  }
88
92
 
93
+ /** Keep only versioned docs output in docs/, removing legacy root language folders. */
94
+ function removeLegacyLanguageDirs(root, outputDir) {
95
+ for (const legacyLanguageDir of SUPPORTED_LANGUAGES) {
96
+ const legacyPath = path.join(root, outputDir, "docs", legacyLanguageDir);
97
+ if (existsSync(legacyPath)) {
98
+ rmSync(legacyPath, { recursive: true, force: true });
99
+ }
100
+ }
101
+ }
102
+
103
+ async function writeVersionConfigs(root, outputDir, versionConfigs) {
104
+ for (const [versionId, versionConfig] of Object.entries(versionConfigs)) {
105
+ await writeJson(root, `${outputDir}/docs/versions/${versionId}/config.json`, versionConfig);
106
+ }
107
+ }
108
+
109
+ async function writeMarkdownDoc(root, outputDir, versionId, docPath, docs) {
110
+ const key = parseDocFileToKey(path.basename(docPath));
111
+ const language = extractLanguageFromPath(docPath);
112
+ const content = key && language ? docs?.[language]?.[key] : undefined;
113
+ if (!content) return;
114
+ const versionedContent = withVersionBadge(content, versionId, language);
115
+ await writeText(root, normalizeToOutputPath(outputDir, docPath), versionedContent);
116
+ }
117
+
118
+ async function writeVersionMarkdownDocs(root, outputDir, versionId, versionConfig, docs) {
119
+ const versionRoutesMd = versionConfig["routes-md"] ?? versionConfig.routes ?? [];
120
+ for (const route of versionRoutesMd) {
121
+ for (const docPath of Object.values(route.path ?? {})) {
122
+ await writeMarkdownDoc(root, outputDir, versionId, docPath, docs);
123
+ }
124
+ }
125
+ }
126
+
127
+ async function writeHtmlDoc(root, outputDir, docPath, docsHtml) {
128
+ const key = parseHtmlFileToKey(path.basename(docPath));
129
+ const language = extractLanguageFromPath(docPath);
130
+ const content = key && language ? docsHtml[key]?.[language] : undefined;
131
+ if (!content) return;
132
+ const normalizedHtmlPath = normalizeToOutputPath(outputDir, docPath);
133
+ await writeText(root, normalizedHtmlPath, content);
134
+ // Backward-compatible alias for tools or users that still expect ".html".
135
+ if (!path.extname(docPath)) {
136
+ await writeText(root, `${normalizedHtmlPath}.html`, content);
137
+ }
138
+ }
139
+
140
+ async function writeVersionHtmlDocs(root, outputDir, versionConfig, docsHtml) {
141
+ const versionRoutesHtml = versionConfig["routes-html"] ?? [];
142
+ for (const route of versionRoutesHtml) {
143
+ if (route.url) continue;
144
+ for (const docPath of Object.values(route.path ?? {})) {
145
+ await writeHtmlDoc(root, outputDir, docPath, docsHtml);
146
+ }
147
+ }
148
+ }
149
+
150
+ /** Ensure version folders always include an index file. */
151
+ async function writeVersionFallbackIndexes(root, outputDir, versionId, docs) {
152
+ for (const language of SUPPORTED_LANGUAGES) {
153
+ const fallbackIndex = docs?.[language]?.index;
154
+ if (!fallbackIndex) continue;
155
+ const versionIndexPath = `${outputDir}/docs/versions/${versionId}/${language}/index.md`;
156
+ if (!existsSync(path.join(root, versionIndexPath))) {
157
+ const versionedFallbackIndex = withVersionBadge(fallbackIndex, versionId, language);
158
+ await writeText(root, versionIndexPath, versionedFallbackIndex);
159
+ }
160
+ }
161
+ }
162
+
163
+ async function writeVersionedDocs(root, outputDir, artifacts) {
164
+ const docsHtml = artifacts.docsHtml ?? {};
165
+ for (const [versionId, versionConfig] of Object.entries(artifacts.versionConfigs)) {
166
+ await writeVersionMarkdownDocs(root, outputDir, versionId, versionConfig, artifacts.docs);
167
+ await writeVersionHtmlDocs(root, outputDir, versionConfig, docsHtml);
168
+ await writeVersionFallbackIndexes(root, outputDir, versionId, artifacts.docs);
169
+ }
170
+ }
171
+
89
172
  export async function writeConfigOnlyOutput(options) {
90
173
  const {
91
174
  root,
92
- pkgRoot,
93
175
  outputDir,
94
176
  artifacts,
95
177
  useLocalLayoutConfig,
@@ -98,13 +180,7 @@ export async function writeConfigOnlyOutput(options) {
98
180
  createThemeTemplate,
99
181
  } = options;
100
182
 
101
- // Keep only versioned docs output in docs/, removing legacy root language folders.
102
- for (const legacyLanguageDir of SUPPORTED_LANGUAGES) {
103
- const legacyPath = path.join(root, outputDir, "docs", legacyLanguageDir);
104
- if (existsSync(legacyPath)) {
105
- rmSync(legacyPath, { recursive: true, force: true });
106
- }
107
- }
183
+ removeLegacyLanguageDirs(root, outputDir);
108
184
 
109
185
  await writeJson(root, `${outputDir}/config.json`, artifacts.rootConfig);
110
186
  await writeLanguageArtifacts(root, outputDir, artifacts);
@@ -117,55 +193,9 @@ export async function writeConfigOnlyOutput(options) {
117
193
  artifacts,
118
194
  createThemeTemplate,
119
195
  });
120
-
121
- for (const [versionId, versionConfig] of Object.entries(artifacts.versionConfigs)) {
122
- await writeJson(root, `${outputDir}/docs/versions/${versionId}/config.json`, versionConfig);
123
- }
196
+ await writeVersionConfigs(root, outputDir, artifacts.versionConfigs);
124
197
 
125
198
  removeLegacySourceViewerFiles(root, outputDir);
126
199
 
127
- for (const [versionId, versionConfig] of Object.entries(artifacts.versionConfigs)) {
128
- const versionRoutesMd = versionConfig["routes-md"] ?? versionConfig.routes ?? [];
129
- for (const route of versionRoutesMd) {
130
- for (const docPath of Object.values(route.path ?? {})) {
131
- const fileName = path.basename(docPath);
132
- const key = parseDocFileToKey(fileName);
133
- const language = extractLanguageFromPath(docPath);
134
- const content = key && language ? artifacts.docs?.[language]?.[key] : undefined;
135
- if (!content) continue;
136
- const versionedContent = withVersionBadge(content, versionId, language);
137
- await writeText(root, normalizeToOutputPath(outputDir, docPath), versionedContent);
138
- }
139
- }
140
-
141
- const versionRoutesHtml = versionConfig["routes-html"] ?? [];
142
- const docsHtml = artifacts.docsHtml ?? {};
143
- for (const route of versionRoutesHtml) {
144
- if (route.url) continue;
145
- for (const docPath of Object.values(route.path ?? {})) {
146
- const fileName = path.basename(docPath);
147
- const key = parseHtmlFileToKey(fileName);
148
- const language = extractLanguageFromPath(docPath);
149
- const content = key && language ? docsHtml[key]?.[language] : undefined;
150
- if (!content) continue;
151
- const normalizedHtmlPath = normalizeToOutputPath(outputDir, docPath);
152
- await writeText(root, normalizedHtmlPath, content);
153
- // Backward-compatible alias for tools or users that still expect ".html".
154
- if (!path.extname(docPath)) {
155
- await writeText(root, `${normalizedHtmlPath}.html`, content);
156
- }
157
- }
158
- }
159
-
160
- // Ensure version folders always include an index file.
161
- for (const language of SUPPORTED_LANGUAGES) {
162
- const fallbackIndex = artifacts.docs?.[language]?.index;
163
- if (!fallbackIndex) continue;
164
- const versionIndexPath = `${outputDir}/docs/versions/${versionId}/${language}/index.md`;
165
- if (!existsSync(path.join(root, versionIndexPath))) {
166
- const versionedFallbackIndex = withVersionBadge(fallbackIndex, versionId, language);
167
- await writeText(root, versionIndexPath, versionedFallbackIndex);
168
- }
169
- }
170
- }
200
+ await writeVersionedDocs(root, outputDir, artifacts);
171
201
  }
@@ -1,6 +1,8 @@
1
+ import { trimSlashes } from "../contracts/path-segments.mjs";
2
+
1
3
  function sanitizeDocsPath(docsPath) {
2
4
  if (!docsPath || typeof docsPath !== "string") return "";
3
- const segment = docsPath.replace(/^\/+|\/+$/g, "").trim();
5
+ const segment = trimSlashes(docsPath).trim();
4
6
  return /^[A-Za-z0-9._-]+$/.test(segment) ? segment : "";
5
7
  }
6
8
 
package/start.mjs CHANGED
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import { spawn } from "child_process";
2
+ import { spawnExecutable } from "./runtime/exec.mjs";
3
3
 
4
4
  const env = { ...process.env, GITPAGEDOCS_REPOSITORY_SEARCH: "true" };
5
5
  // The Next app lives in frontend/, so `next build` emits to frontend/.next —
6
6
  // point `next start` at the same directory (matches `next build frontend`).
7
- const child = spawn("npx", ["next", "start", "frontend"], {
8
- stdio: "inherit",
9
- env,
10
- shell: true,
11
- });
7
+ let child;
8
+ try {
9
+ child = spawnExecutable("npx", ["next", "start", "frontend"], { stdio: "inherit", env });
10
+ } catch (error) {
11
+ console.error(`[gitpagedocs] ${error instanceof Error ? error.message : String(error)}`);
12
+ process.exit(1);
13
+ }
12
14
  child.on("exit", (code) => process.exit(code ?? 0));