ctheme 0.1.1 → 0.1.3

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/DEVELOPMENT.md CHANGED
@@ -55,6 +55,7 @@ Relevant env vars:
55
55
  CTHEME_HOME
56
56
  CTHEME_THEME_DIR
57
57
  CTHEME_SNIPPET_DIR
58
+ CTHEME_SKIP_FONT_BOOTSTRAP
58
59
  ```
59
60
 
60
61
  ## Command Map
@@ -145,6 +146,22 @@ Google Fonts install flow:
145
146
 
146
147
  Do not bundle font files in the repo.
147
148
 
149
+ ### 6. Install Bootstrap
150
+
151
+ `npm install -g ctheme` runs `scripts/postinstall.js`.
152
+
153
+ That script:
154
+
155
+ - runs on macOS only
156
+ - best-effort installs the curated default font pack
157
+ - never hard-fails the package install because of a font download problem
158
+
159
+ Skip it with:
160
+
161
+ ```bash
162
+ CTHEME_SKIP_FONT_BOOTSTRAP=1 npm install -g ctheme
163
+ ```
164
+
148
165
  ## Local Development
149
166
 
150
167
  Install the CLI locally:
package/README.md CHANGED
@@ -18,6 +18,12 @@ From npm:
18
18
  npm install -g ctheme
19
19
  ```
20
20
 
21
+ On macOS, install also preloads the curated default font pack used by the bundled themes. If you want to skip that during install:
22
+
23
+ ```bash
24
+ CTHEME_SKIP_FONT_BOOTSTRAP=1 npm install -g ctheme
25
+ ```
26
+
21
27
  From GitHub:
22
28
 
23
29
  ```bash
@@ -71,7 +77,7 @@ The wizard walks through:
71
77
  - terminal font
72
78
  - UI font
73
79
  - code font
74
- - theme summary before save
80
+ - theme summary with color swatches before save
75
81
  - optional Google Fonts install
76
82
  - optional live apply
77
83
 
@@ -150,6 +156,7 @@ solarized, solarized-dark, velvet
150
156
  ```
151
157
 
152
158
  Bundled themes intentionally vary their font pairings so they do not all feel the same.
159
+ The npm install bootstrap preinstalls the curated font set those presets rely on, so the bundled themes render correctly immediately on macOS.
153
160
 
154
161
  ## Contributing
155
162
 
package/bin/ctheme.js CHANGED
@@ -94,9 +94,9 @@ const BUILTIN_THEMES = [
94
94
  ];
95
95
 
96
96
  const FONT_CHOICES = {
97
- ui: ["Manrope", "Space Grotesk", "Outfit", "Sora", "Plus Jakarta Sans", "Newsreader", "Fraunces"],
98
- code: ["IBM Plex Mono", "Space Mono", "DM Mono", "Source Code Pro", "Fira Code", "JetBrains Mono"],
99
- terminal: ["IBM Plex Mono", "Space Mono", "DM Mono", "Source Code Pro", "Fira Code", "JetBrains Mono"]
97
+ ui: ["Manrope", "Space Grotesk", "Outfit", "Sora", "Plus Jakarta Sans", "Newsreader", "Fraunces", "Bricolage Grotesque", "Urbanist", "Source Sans 3", "IBM Plex Sans", "Instrument Serif", "Syne"],
98
+ code: ["IBM Plex Mono", "Space Mono", "DM Mono", "Source Code Pro", "Fira Code", "JetBrains Mono", "Roboto Mono", "Azeret Mono", "Victor Mono", "Ubuntu Mono"],
99
+ terminal: ["IBM Plex Mono", "Space Mono", "DM Mono", "Source Code Pro", "Fira Code", "JetBrains Mono", "Roboto Mono", "Azeret Mono", "Victor Mono", "Ubuntu Mono"]
100
100
  };
101
101
 
102
102
  const PRESETS = {
@@ -117,7 +117,7 @@ const PRESETS = {
117
117
  cyan: "#39c5cf"
118
118
  },
119
119
  paper: {
120
- fonts: { terminal: "IBM Plex Mono", ui: "Newsreader", code: "IBM Plex Mono" },
120
+ fonts: { terminal: "Source Code Pro", ui: "Newsreader", code: "Source Code Pro" },
121
121
  accent: "#005cc5",
122
122
  bg: "#fff8e8",
123
123
  surface: "#fffdf7",
@@ -149,7 +149,7 @@ const PRESETS = {
149
149
  cyan: "#7dcfff"
150
150
  },
151
151
  mint: {
152
- fonts: { terminal: "JetBrains Mono", ui: "Plus Jakarta Sans", code: "JetBrains Mono" },
152
+ fonts: { terminal: "Roboto Mono", ui: "Plus Jakarta Sans", code: "Roboto Mono" },
153
153
  accent: "#2bb673",
154
154
  bg: "#081411",
155
155
  surface: "#10201b",
@@ -165,7 +165,7 @@ const PRESETS = {
165
165
  cyan: "#5ad1e6"
166
166
  },
167
167
  obsidian: {
168
- fonts: { terminal: "IBM Plex Mono", ui: "Outfit", code: "IBM Plex Mono" },
168
+ fonts: { terminal: "Azeret Mono", ui: "Outfit", code: "Azeret Mono" },
169
169
  accent: "#58a6ff",
170
170
  bg: "#05070a",
171
171
  surface: "#0e131a",
@@ -181,7 +181,7 @@ const PRESETS = {
181
181
  cyan: "#7dd3fc"
182
182
  },
183
183
  glacier: {
184
- fonts: { terminal: "Space Mono", ui: "Space Grotesk", code: "Space Mono" },
184
+ fonts: { terminal: "Space Mono", ui: "Urbanist", code: "Space Mono" },
185
185
  accent: "#7aa2f7",
186
186
  bg: "#0a1220",
187
187
  surface: "#121c2f",
@@ -197,7 +197,7 @@ const PRESETS = {
197
197
  cyan: "#7dcfff"
198
198
  },
199
199
  cobalt: {
200
- fonts: { terminal: "Space Mono", ui: "Sora", code: "Space Mono" },
200
+ fonts: { terminal: "Victor Mono", ui: "Bricolage Grotesque", code: "Victor Mono" },
201
201
  accent: "#4da3ff",
202
202
  bg: "#09111f",
203
203
  surface: "#10203a",
@@ -229,7 +229,7 @@ const PRESETS = {
229
229
  cyan: "#8bd3dd"
230
230
  },
231
231
  lotus: {
232
- fonts: { terminal: "IBM Plex Mono", ui: "Newsreader", code: "IBM Plex Mono" },
232
+ fonts: { terminal: "Ubuntu Mono", ui: "Instrument Serif", code: "Ubuntu Mono" },
233
233
  accent: "#d16d9e",
234
234
  bg: "#fff7f3",
235
235
  surface: "#fffdfb",
@@ -245,7 +245,7 @@ const PRESETS = {
245
245
  cyan: "#4d8ca1"
246
246
  },
247
247
  dune: {
248
- fonts: { terminal: "JetBrains Mono", ui: "Sora", code: "JetBrains Mono" },
248
+ fonts: { terminal: "Fira Code", ui: "Syne", code: "Fira Code" },
249
249
  accent: "#d97706",
250
250
  bg: "#16110c",
251
251
  surface: "#231912",
@@ -261,7 +261,7 @@ const PRESETS = {
261
261
  cyan: "#67e8f9"
262
262
  },
263
263
  forest: {
264
- fonts: { terminal: "IBM Plex Mono", ui: "Newsreader", code: "IBM Plex Mono" },
264
+ fonts: { terminal: "IBM Plex Mono", ui: "IBM Plex Sans", code: "IBM Plex Mono" },
265
265
  accent: "#7ccf7a",
266
266
  bg: "#08100b",
267
267
  surface: "#112016",
@@ -277,7 +277,7 @@ const PRESETS = {
277
277
  cyan: "#6ee7b7"
278
278
  },
279
279
  aurora: {
280
- fonts: { terminal: "Space Mono", ui: "Outfit", code: "Space Mono" },
280
+ fonts: { terminal: "Space Mono", ui: "Urbanist", code: "Space Mono" },
281
281
  accent: "#7c5cff",
282
282
  bg: "#0f0a1f",
283
283
  surface: "#181131",
@@ -293,7 +293,7 @@ const PRESETS = {
293
293
  cyan: "#7bdff2"
294
294
  },
295
295
  espresso: {
296
- fonts: { terminal: "DM Mono", ui: "Fraunces", code: "DM Mono" },
296
+ fonts: { terminal: "Victor Mono", ui: "Instrument Serif", code: "Victor Mono" },
297
297
  accent: "#c67c4e",
298
298
  bg: "#120d0b",
299
299
  surface: "#1d1512",
@@ -325,7 +325,7 @@ const PRESETS = {
325
325
  cyan: "#bde0fe"
326
326
  },
327
327
  neon: {
328
- fonts: { terminal: "Space Mono", ui: "Space Grotesk", code: "Space Mono" },
328
+ fonts: { terminal: "Azeret Mono", ui: "Bricolage Grotesque", code: "Azeret Mono" },
329
329
  accent: "#00f5d4",
330
330
  bg: "#090414",
331
331
  surface: "#130a24",
@@ -341,7 +341,7 @@ const PRESETS = {
341
341
  cyan: "#00bbf9"
342
342
  },
343
343
  harbor: {
344
- fonts: { terminal: "IBM Plex Mono", ui: "Plus Jakarta Sans", code: "IBM Plex Mono" },
344
+ fonts: { terminal: "Roboto Mono", ui: "Plus Jakarta Sans", code: "Roboto Mono" },
345
345
  accent: "#3ba4c9",
346
346
  bg: "#f4f8fb",
347
347
  surface: "#ffffff",
@@ -389,7 +389,7 @@ const PRESETS = {
389
389
  cyan: "#2aa198"
390
390
  },
391
391
  velvet: {
392
- fonts: { terminal: "DM Mono", ui: "Fraunces", code: "DM Mono" },
392
+ fonts: { terminal: "Ubuntu Mono", ui: "Fraunces", code: "Ubuntu Mono" },
393
393
  accent: "#d4a5ff",
394
394
  bg: "#140d18",
395
395
  surface: "#211328",
@@ -912,6 +912,10 @@ function listInstalledFonts() {
912
912
  }
913
913
 
914
914
  function installGoogleFont(family) {
915
+ return installGoogleFontWithOptions(family, {});
916
+ }
917
+
918
+ function installGoogleFontWithOptions(family, options = {}) {
915
919
  const paths = getThemePaths();
916
920
  ensureDir(paths.managedFontDir);
917
921
  const installed = downloadGoogleFontFiles(family, paths.managedFontDir);
@@ -919,13 +923,13 @@ function installGoogleFont(family) {
919
923
  fail(`No installable font files found for ${family}`);
920
924
  }
921
925
 
922
- console.log(`Installed ${family} into ${paths.managedFontDir}`);
923
- for (const file of installed) {
924
- console.log(`- ${file}`);
925
- }
926
- if (!looksMonospaceFamily(family)) {
927
- console.log("Warning: this family looks proportional. It may render poorly in terminal grids.");
926
+ if (!options.quiet) {
927
+ console.log(`Installed ${family} into ${paths.managedFontDir}`);
928
+ for (const file of installed) {
929
+ console.log(`- ${file}`);
930
+ }
928
931
  }
932
+ return installed;
929
933
  }
930
934
 
931
935
  function searchGoogleFonts(query) {
@@ -951,8 +955,7 @@ function searchGoogleFonts(query) {
951
955
  }
952
956
 
953
957
  for (const font of matches) {
954
- const mono = looksMonospaceFamily(font.family) ? "mono-ish" : "proportional";
955
- console.log(`${font.family} (${mono})`);
958
+ console.log(font.family);
956
959
  }
957
960
  }
958
961
 
@@ -993,12 +996,13 @@ function downloadGoogleFontFiles(family, targetDir) {
993
996
  execFileSync("curl", [
994
997
  "-L",
995
998
  "--fail",
999
+ "-sS",
996
1000
  "-H",
997
1001
  "User-Agent: pretty-code",
998
1002
  "--output",
999
1003
  destPath,
1000
1004
  entry.download_url
1001
- ], { stdio: "inherit" });
1005
+ ], { stdio: "pipe" });
1002
1006
  installed.push(destPath);
1003
1007
  }
1004
1008
 
@@ -1209,30 +1213,39 @@ async function promptYesNo(rl, label, defaultValue) {
1209
1213
  }
1210
1214
 
1211
1215
  function installFontsBestEffort(fonts) {
1216
+ const installedFamilies = [];
1212
1217
  for (const family of [...new Set(fonts.filter(Boolean))]) {
1213
1218
  try {
1214
- installGoogleFont(family);
1219
+ installGoogleFontWithOptions(family, { quiet: true });
1220
+ installedFamilies.push(family);
1215
1221
  } catch (error) {
1216
- console.log(`Skipped Google Fonts install for ${family}: ${error instanceof Error ? error.message : String(error)}`);
1222
+ console.log(`Skipped ${family}`);
1217
1223
  }
1218
1224
  }
1225
+ if (installedFamilies.length) {
1226
+ console.log(`Installed fonts: ${installedFamilies.join(", ")}`);
1227
+ }
1219
1228
  }
1220
1229
 
1221
1230
  function printThemeSummary(theme) {
1222
1231
  console.log(` name: ${theme.name}`);
1223
1232
  console.log(` preset: ${theme.preset}`);
1224
- console.log(` accent: ${theme.accent}`);
1225
- console.log(` bg: ${theme.bg}`);
1226
- console.log(` surface: ${theme.surface}`);
1227
- console.log(` surface alt: ${theme.surfaceAlt}`);
1228
- console.log(` text: ${theme.fg}`);
1229
- console.log(` muted: ${theme.muted}`);
1230
- console.log(` dim: ${theme.dim}`);
1233
+ printColorLine("accent", theme.accent);
1234
+ printColorLine("bg", theme.bg);
1235
+ printColorLine("surface", theme.surface);
1236
+ printColorLine("surface alt", theme.surfaceAlt);
1237
+ printColorLine("text", theme.fg);
1238
+ printColorLine("muted", theme.muted);
1239
+ printColorLine("dim", theme.dim);
1231
1240
  console.log(` terminal font: ${theme.fonts.terminal}`);
1232
1241
  console.log(` ui font: ${theme.fonts.ui}`);
1233
1242
  console.log(` code font: ${theme.fonts.code}`);
1234
1243
  }
1235
1244
 
1245
+ function printColorLine(label, hex) {
1246
+ console.log(` ${label}: ${colorBlock(hex, 8)} ${hex}`);
1247
+ }
1248
+
1236
1249
  function writeThemeAssets(paths, name, palette) {
1237
1250
  ensureDir(paths.paletteDir);
1238
1251
  fs.writeFileSync(path.join(paths.paletteDir, `${name}.json`), `${JSON.stringify(palette, null, 2)}\n`, "utf8");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ctheme",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Theme manager for making terminals look better with colors, fonts, and live profile switching",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -21,13 +21,15 @@
21
21
  "files": [
22
22
  "bin",
23
23
  "DEVELOPMENT.md",
24
- "README.md"
24
+ "README.md",
25
+ "scripts"
25
26
  ],
26
27
  "bin": {
27
28
  "ctheme": "bin/ctheme.js"
28
29
  },
29
30
  "scripts": {
30
- "test": "node ./bin/ctheme.js --help"
31
+ "test": "node ./bin/ctheme.js --help",
32
+ "postinstall": "node ./scripts/postinstall.js"
31
33
  },
32
34
  "engines": {
33
35
  "node": ">=18"
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawnSync } = require("child_process");
4
+ const path = require("path");
5
+
6
+ const DEFAULT_FONTS = [
7
+ "Azeret Mono",
8
+ "Bricolage Grotesque",
9
+ "DM Mono",
10
+ "Fira Code",
11
+ "Fraunces",
12
+ "IBM Plex Mono",
13
+ "IBM Plex Sans",
14
+ "Instrument Serif",
15
+ "JetBrains Mono",
16
+ "Newsreader",
17
+ "Outfit",
18
+ "Plus Jakarta Sans",
19
+ "Roboto Mono",
20
+ "Sora",
21
+ "Source Code Pro",
22
+ "Source Sans 3",
23
+ "Space Grotesk",
24
+ "Space Mono",
25
+ "Syne",
26
+ "Ubuntu Mono",
27
+ "Urbanist",
28
+ "Victor Mono"
29
+ ];
30
+
31
+ if (process.env.CTHEME_SKIP_FONT_BOOTSTRAP === "1") {
32
+ console.log("ctheme: skipping default font bootstrap");
33
+ process.exit(0);
34
+ }
35
+
36
+ if (process.platform !== "darwin") {
37
+ console.log("ctheme: skipping default font bootstrap on non-macOS");
38
+ process.exit(0);
39
+ }
40
+
41
+ const cliPath = path.join(__dirname, "..", "bin", "ctheme.js");
42
+ console.log(`ctheme: installing bundled default fonts (${DEFAULT_FONTS.length})`);
43
+
44
+ for (const family of DEFAULT_FONTS) {
45
+ const result = spawnSync(process.execPath, [cliPath, "font", "install", family], {
46
+ stdio: "inherit",
47
+ env: {
48
+ ...process.env,
49
+ CTHEME_SKIP_FONT_BOOTSTRAP: "1"
50
+ }
51
+ });
52
+
53
+ if (result.status !== 0) {
54
+ console.log(`ctheme: skipped ${family}`);
55
+ }
56
+ }
57
+