@docubook/cli 0.2.4 → 0.2.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docubook/cli",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "DocuBook CLI tool that helps you initialize, update, and deploy documentation directly from your terminal.",
5
5
  "type": "module",
6
6
  "files": [
@@ -9,6 +9,104 @@ import { detectPackageManager, getPackageManagerInfo, getPackageManagerVersion }
9
9
  import { getAvailableTemplates, getTemplate, getDefaultTemplate } from "../utils/templateDetect.js";
10
10
  import { execSync } from "child_process";
11
11
  import ora from "ora";
12
+ import fs from "fs";
13
+ import os from "os";
14
+ import path from "path";
15
+
16
+ // Helpers to show changelog once per installed version. Stores shown versions under
17
+ // $HOME/.docubook_cli_seen_changelogs.json as a map: { "@docubook/cli": ["1.2.3"] }
18
+ const _CHANGELOG_STORE = path.join(os.homedir(), ".docubook_cli_seen_changelogs.json");
19
+ function _readChangelogStore() {
20
+ try {
21
+ const raw = fs.readFileSync(_CHANGELOG_STORE, "utf8");
22
+ return JSON.parse(raw || "{}");
23
+ } catch {
24
+ return {};
25
+ }
26
+ }
27
+ function _writeChangelogStore(obj) {
28
+ try {
29
+ fs.writeFileSync(_CHANGELOG_STORE, JSON.stringify(obj, null, 2), { mode: 0o600 });
30
+ } catch {
31
+ // non-fatal
32
+ }
33
+ }
34
+
35
+ async function _fetchChangelogFromGitHub(version) {
36
+ // Fetch CHANGELOG.md from the CLI release tag format: cli-v0.2.5
37
+ const repo = "DocuBook/docubook";
38
+ const bare = version.replace(/^v/, "");
39
+ const tag = `cli-v${bare}`;
40
+
41
+ const candidates = [
42
+ `https://raw.githubusercontent.com/${repo}/${tag}/CHANGELOG.md`,
43
+ `https://raw.githubusercontent.com/${repo}/${tag}/CHANGELOG.MD`,
44
+ // Fallback to main branch
45
+ `https://raw.githubusercontent.com/${repo}/main/CHANGELOG.md`,
46
+ ];
47
+
48
+ for (const url of candidates) {
49
+ try {
50
+ const res = await fetch(url);
51
+ if (res && res.ok) return await res.text();
52
+ } catch {
53
+ // ignore and try next
54
+ }
55
+ }
56
+ return null;
57
+ }
58
+
59
+ function _extractVersionSection(changelogText, version) {
60
+ if (!changelogText) return null;
61
+ const lines = changelogText.split(/\r?\n/);
62
+ // Look for headings that include the version (e.g. "## v1.2.3" or "## 1.2.3")
63
+ const headerRe = new RegExp(`^#{1,3}\\s*(?:v)?${version.replace(/\./g, "\\.")}(?:\\b|\\D)`, "i");
64
+ let start = -1;
65
+ for (let i = 0; i < lines.length; i++) {
66
+ if (headerRe.test(lines[i])) {
67
+ start = i;
68
+ break;
69
+ }
70
+ }
71
+ if (start === -1) return changelogText.slice(0, 2000); // fallback: return beginning of changelog
72
+
73
+ let end = lines.length;
74
+ for (let j = start + 1; j < lines.length; j++) {
75
+ // Match the next version heading (level 2, ## but not ###)
76
+ if (/^##\s*(?!#)/.test(lines[j])) {
77
+ end = j;
78
+ break;
79
+ }
80
+ }
81
+ return lines.slice(start, end).join("\n");
82
+ }
83
+
84
+ async function showChangelogOnce(pkgName, version) {
85
+ try {
86
+ const store = _readChangelogStore();
87
+ const seen = Array.isArray(store[pkgName]) ? store[pkgName] : [];
88
+ if (seen.includes(version)) return;
89
+
90
+ const changelog = await _fetchChangelogFromGitHub(version);
91
+ if (!changelog) return;
92
+
93
+ const section = _extractVersionSection(changelog, version);
94
+ if (!section) return;
95
+
96
+ // Print a concise changelog section
97
+ console.log("\n=== DocuBook CLI changelog (new) ===\n");
98
+ console.log(section.trim());
99
+ console.log("\nFor full changelog, visit:");
100
+ console.log(` https://github.com/DocuBook/docubook/blob/main/CHANGELOG.md\n`);
101
+
102
+ // Mark as shown
103
+ store[pkgName] = Array.from(new Set([...seen, version]));
104
+ _writeChangelogStore(store);
105
+ } catch {
106
+ // silent on any error - changelog is a nicety
107
+ }
108
+ }
109
+
12
110
 
13
111
  /**
14
112
  * Initializes the CLI program
@@ -59,6 +157,12 @@ export function initializeProgram(version) {
59
157
  try {
60
158
  execSync(cmd, { stdio: "inherit" });
61
159
  console.log(`Successfully updated to ${latest}`);
160
+ // Try to show changelog for the newly installed version once
161
+ try {
162
+ await showChangelogOnce(pkgName, latest);
163
+ } catch {
164
+ // non-fatal
165
+ }
62
166
  } catch (installErr) {
63
167
  // If install fails, provide a helpful message
64
168
  console.error(`Update failed: ${installErr.message || installErr}`);
@@ -73,6 +177,16 @@ export function initializeProgram(version) {
73
177
  }
74
178
  });
75
179
 
180
+ // Expose a `version` subcommand: `docubook version`
181
+ program
182
+ .command('version')
183
+ .description('Print the DocuBook CLI version')
184
+ .action(() => {
185
+ console.log(`DocuBook CLI ${version}`);
186
+ console.log("Run 'docubook update' to check for updates.");
187
+ process.exit(0);
188
+ });
189
+
76
190
  // Default behavior (create project)
77
191
  program
78
192
  .argument("[directory]", "The name of the project directory")
package/src/index.js CHANGED
@@ -14,9 +14,9 @@ const packageJsonPath = path.join(__dirname, '..', 'package.json');
14
14
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
15
15
  const VERSION = packageJson.version;
16
16
 
17
- // Handle --version / -V early to print custom output
17
+ // Handle --version / -v early to print custom output
18
18
  const args = process.argv.slice(2);
19
- if (args.includes('--version') || args.includes('-V')) {
19
+ if (args.includes('--version') || args.includes('-v')) {
20
20
  console.log(`DocuBook CLI ${VERSION}`);
21
21
  console.log("Run 'docubook update' to check for updates.");
22
22
  process.exit(0);
package/src/tui/ascii.js CHANGED
@@ -62,7 +62,7 @@ export function createWelcomeBanner(version) {
62
62
  const logoMid = `${colors.cyan}${colors.bright}▌>_▐${colors.reset}`
63
63
  const logoBot = `${colors.cyan}▙▄▄▟${colors.reset}`
64
64
 
65
- const title = `${colors.cyan}${colors.bright}DocuBook${colors.reset} v${version}`
65
+ const title = `${colors.cyan}${colors.bright}DocuBook CLI${colors.reset} v${version}`
66
66
  const subtitle = `${colors.gray}Initialize, build, and deploy docs from terminal.${colors.reset}`
67
67
 
68
68
  const tip = `${colors.gray}Visit our documentation.${colors.reset}`
@@ -103,16 +103,8 @@ export function createBoxedMessage(title, content, color = colors.green) {
103
103
  const reset = "\x1b[0m";
104
104
  const termWidth = process.stdout.columns || 80;
105
105
 
106
- // 1. Tentukan total lebar box (termasuk border)
107
106
  const boxWidth = Math.min(80, termWidth - 4);
108
-
109
- // 2. width adalah panjang garis horizontal (─) di atas dan bawah
110
- // Total lebar box adalah width + 2 (untuk karakter pojok ┌ dan ┐)
111
107
  const width = boxWidth - 2;
112
-
113
- // 3. inner adalah ruang bersih di dalam box untuk teks (tanpa padding spasi)
114
- // Kita beri padding 2 spasi di kiri dan 2 spasi di kanan (total 4)
115
- // Jadi: 1(│) + 2(spasi) + inner + 2(spasi) + 1(│) = width + 2
116
108
  const inner = (width + 2) - 6;
117
109
 
118
110
  const centerTitle = () => {
@@ -126,16 +118,11 @@ export function createBoxedMessage(title, content, color = colors.green) {
126
118
 
127
119
  const pad = (text = "") => {
128
120
  const len = stringWidth(text);
129
- // Tambahkan spasi hingga tepat mengisi 'inner'
130
121
  return text + " ".repeat(Math.max(0, inner - len));
131
122
  };
132
123
 
133
124
  const lines = [];
134
-
135
- // Header
136
125
  lines.push(`${color}┌${centerTitle()}┐${reset}`);
137
-
138
- // Padding atas (opsional)
139
126
  lines.push(`${color}│${reset} ${pad("")} ${color}│${reset}`);
140
127
 
141
128
  const items = typeof content === "string"
@@ -145,15 +132,10 @@ export function createBoxedMessage(title, content, color = colors.green) {
145
132
  for (const line of items) {
146
133
  const wrapped = wrapText(line, inner);
147
134
  wrapped.forEach((w) => {
148
- // Pastikan struktur: │ + spasi(2) + konten + spasi(2) + │
149
135
  lines.push(`${color}│${reset} ${pad(w)} ${color}│${reset}`);
150
136
  });
151
137
  }
152
-
153
- // Padding bawah (opsional)
154
138
  lines.push(`${color}│${reset} ${pad("")} ${color}│${reset}`);
155
-
156
- // Footer
157
139
  lines.push(`${color}└${"─".repeat(width)}┘${reset}`);
158
140
 
159
141
  return "\n" + lines.join("\n") + "\n";
@@ -1,32 +1,6 @@
1
- import { execSync } from "child_process";
2
1
  import fs from "fs";
3
2
  import path from "path";
4
3
 
5
- /**
6
- * Gets the version of the specified package manager
7
- * @param {string} pm - Package manager name
8
- * @returns {string|null} Version string or null if not installed
9
- */
10
- export function getPackageManagerVersion(pm) {
11
- try {
12
- return execSync(`${pm} --version`).toString().trim();
13
- } catch {
14
- return null;
15
- }
16
- }
17
-
18
- /**
19
- * Detects the default package manager from user environment
20
- * @returns {string} Default package manager name
21
- */
22
- export function detectDefaultPackageManager() {
23
- const userAgent = process.env.npm_config_user_agent || "";
24
- if (userAgent.includes("pnpm")) return "pnpm";
25
- if (userAgent.includes("yarn")) return "yarn";
26
- if (userAgent.includes("bun")) return "bun";
27
- return "npm";
28
- }
29
-
30
4
  /**
31
5
  * Updates postcss config file extension for Bun compatibility
32
6
  * @param {string} projectPath - Path to the project directory
package/templates.json CHANGED
@@ -16,6 +16,23 @@
16
16
  ],
17
17
  "url": "https://github.com/DocuBook/docubook/tree/main/packages/template/nextjs-vercel"
18
18
  },
19
+ {
20
+ "id": "nextjs-docker",
21
+ "name": "nextjs-docker",
22
+ "description": "Modern documentation with Next.js standalone and Docker deployment",
23
+ "features": [
24
+ "Next.js 16",
25
+ "React 19",
26
+ "TypeScript",
27
+ "Tailwind CSS",
28
+ "MDX Support",
29
+ "Dark Mode",
30
+ "Search (Algolia)",
31
+ "Responsive Design",
32
+ "Docker Deployment"
33
+ ],
34
+ "url": "https://github.com/DocuBook/docubook/tree/main/packages/template/nextjs-docker"
35
+ },
19
36
  {
20
37
  "id": "react-router",
21
38
  "name": "react-router",