zedx 0.1.0 → 0.2.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # zedx
2
2
 
3
- Boilerplate generator for Zed extensions.
3
+ Boilerplate generator for [Zed Editor](https://zed.dev/) extensions.
4
4
 
5
5
  ## Installation
6
6
 
@@ -16,9 +16,9 @@ zedx
16
16
 
17
17
  # Bump extension version
18
18
  # Run inside extension dir
19
- zedx bump patch # 1.2.3 → 1.2.4
20
- zedx bump minor # 1.2.3 → 1.3.0
21
- zedx bump major # 1.2.3 → 2.0.0
19
+ zedx version patch # 1.2.3 → 1.2.4
20
+ zedx version minor # 1.2.3 → 1.3.0
21
+ zedx version major # 1.2.3 → 2.0.0
22
22
  ```
23
23
 
24
24
  ### Supported extension types:
@@ -1,2 +1,2 @@
1
- import type { ExtensionOptions } from "./types/index.js";
1
+ import type { ExtensionOptions } from './types/index.js';
2
2
  export declare function generateExtension(options: ExtensionOptions, targetDir: string): Promise<void>;
package/dist/generator.js CHANGED
@@ -1,37 +1,37 @@
1
- import fs from "fs-extra";
2
- import path from "path";
3
- import { fileURLToPath } from "url";
4
- import ejs from "ejs";
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import ejs from 'ejs';
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = path.dirname(__filename);
7
- const isDev = __dirname.includes("/src/");
8
- const PROJECT_ROOT = isDev ? path.join(__dirname, "..") : __dirname;
9
- const TEMPLATE_DIR = path.join(PROJECT_ROOT, "templates");
7
+ const isDev = __dirname.includes('/src/');
8
+ const PROJECT_ROOT = isDev ? path.join(__dirname, '..') : __dirname;
9
+ const TEMPLATE_DIR = path.join(PROJECT_ROOT, 'templates');
10
10
  async function renderTemplate(templatePath, data) {
11
- const template = await fs.readFile(templatePath, "utf-8");
11
+ const template = await fs.readFile(templatePath, 'utf-8');
12
12
  return ejs.render(template, data);
13
13
  }
14
14
  export async function generateExtension(options, targetDir) {
15
15
  await fs.ensureDir(targetDir);
16
- const extToml = await renderTemplate(path.join(TEMPLATE_DIR, "base/extension.toml.ejs"), options);
17
- await fs.writeFile(path.join(targetDir, "extension.toml"), extToml);
18
- const licensePath = path.join(TEMPLATE_DIR, "base/licenses", options.license);
19
- let licenseContent = await fs.readFile(licensePath, "utf-8");
20
- licenseContent = licenseContent.replaceAll("{{YEAR}}", new Date().getFullYear().toString());
21
- licenseContent = licenseContent.replaceAll("{{AUTHOR}}", options.author);
22
- await fs.writeFile(path.join(targetDir, "LICENSE"), licenseContent);
16
+ const extToml = await renderTemplate(path.join(TEMPLATE_DIR, 'base/extension.toml.ejs'), options);
17
+ await fs.writeFile(path.join(targetDir, 'extension.toml'), extToml);
18
+ const licensePath = path.join(TEMPLATE_DIR, 'base/licenses', options.license);
19
+ let licenseContent = await fs.readFile(licensePath, 'utf-8');
20
+ licenseContent = licenseContent.replaceAll('{{YEAR}}', new Date().getFullYear().toString());
21
+ licenseContent = licenseContent.replaceAll('{{AUTHOR}}', options.author);
22
+ await fs.writeFile(path.join(targetDir, 'LICENSE'), licenseContent);
23
23
  await generateTheme(options, targetDir);
24
24
  }
25
25
  async function generateTheme(options, targetDir) {
26
- const themeDir = path.join(targetDir, "themes");
26
+ const themeDir = path.join(targetDir, 'themes');
27
27
  await fs.ensureDir(themeDir);
28
- const appearance = options.appearance || "dark";
29
- const appearances = appearance === "both" ? ["dark", "light"] : [appearance];
28
+ const appearance = options.appearance || 'dark';
29
+ const appearances = appearance === 'both' ? ['dark', 'light'] : [appearance];
30
30
  const themeData = {
31
31
  ...options,
32
- themeName: options.themeName || "My Theme",
33
- appearances,
32
+ themeName: options.themeName || 'My Theme',
33
+ appearances
34
34
  };
35
- const themeJson = await renderTemplate(path.join(TEMPLATE_DIR, "theme/theme.json.ejs"), themeData);
35
+ const themeJson = await renderTemplate(path.join(TEMPLATE_DIR, 'theme/theme.json.ejs'), themeData);
36
36
  await fs.writeFile(path.join(themeDir, `${options.id}.json`), themeJson);
37
37
  }
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
+ #!/usr/bin/env node
1
2
  export {};
package/dist/index.js CHANGED
@@ -1,18 +1,19 @@
1
- import path from "path";
2
- import * as p from "@clack/prompts";
3
- import color from "picocolors";
4
- import { Command } from "commander";
5
- import fs from "fs-extra";
6
- import { promptUser, promptThemeDetails } from "./prompts.js";
7
- import { generateExtension } from "./generator.js";
1
+ #!/usr/bin/env node
2
+ import path from 'path';
3
+ import * as p from '@clack/prompts';
4
+ import color from 'picocolors';
5
+ import { Command } from 'commander';
6
+ import fs from 'fs-extra';
7
+ import { promptUser, promptThemeDetails } from './prompts.js';
8
+ import { generateExtension } from './generator.js';
8
9
  function bumpVersion(version, type) {
9
- const [major, minor, patch] = version.split(".").map(Number);
10
+ const [major, minor, patch] = version.split('.').map(Number);
10
11
  switch (type) {
11
- case "major":
12
+ case 'major':
12
13
  return `${major + 1}.0.0`;
13
- case "minor":
14
+ case 'minor':
14
15
  return `${major}.${minor + 1}.0`;
15
- case "patch":
16
+ case 'patch':
16
17
  return `${major}.${minor}.${patch + 1}`;
17
18
  }
18
19
  }
@@ -21,15 +22,15 @@ function getCallerDir() {
21
22
  }
22
23
  async function bumpExtensionVersion(type) {
23
24
  const callerDir = getCallerDir();
24
- const tomlPath = path.join(callerDir, "extension.toml");
25
+ const tomlPath = path.join(callerDir, 'extension.toml');
25
26
  if (!(await fs.pathExists(tomlPath))) {
26
- p.log.error(color.red("No extension.toml found in current directory."));
27
+ p.log.error(color.red('No extension.toml found in current directory.'));
27
28
  process.exit(1);
28
29
  }
29
- const content = await fs.readFile(tomlPath, "utf-8");
30
+ const content = await fs.readFile(tomlPath, 'utf-8');
30
31
  const versionMatch = content.match(/version\s*=\s*"(\d+\.\d+\.\d+)"/);
31
32
  if (!versionMatch) {
32
- p.log.error(color.red("Could not find version in extension.toml"));
33
+ p.log.error(color.red('Could not find version in extension.toml'));
33
34
  process.exit(1);
34
35
  }
35
36
  const currentVersion = versionMatch[1];
@@ -40,14 +41,14 @@ async function bumpExtensionVersion(type) {
40
41
  }
41
42
  async function main() {
42
43
  const program = new Command();
43
- program.name("zedx").description("Boilerplate generator for Zed extensions");
44
+ program.name('zedx').description('Boilerplate generator for Zed Editor extensions.');
44
45
  program
45
- .command("bump")
46
- .description("Bump the version of the extension")
47
- .argument("<type>", "Version bump type: major, minor, or patch")
46
+ .command('version')
47
+ .description('Bump the version of the extension')
48
+ .argument('<type>', 'Version bump type: major, minor, or patch')
48
49
  .action(async (type) => {
49
- if (!["major", "minor", "patch"].includes(type)) {
50
- p.log.error(color.red("Invalid bump type. Use: major, minor, or patch"));
50
+ if (!['major', 'minor', 'patch'].includes(type)) {
51
+ p.log.error(color.red('Invalid bump type. Use: major, minor, or patch'));
51
52
  process.exit(1);
52
53
  }
53
54
  await bumpExtensionVersion(type);
@@ -59,11 +60,14 @@ async function main() {
59
60
  Object.assign(options, themeDetails);
60
61
  const targetDir = path.join(getCallerDir(), options.id);
61
62
  await generateExtension(options, targetDir);
62
- // Final success message
63
- p.outro(`${color.green("✓")} ${color.bold("Extension created successfully!")}\n\n` +
64
- `Location: ${color.yellow(targetDir)}\n`);
65
- p.note(`Open Zed and install theme as dev extension: Extensions > Install Dev Extension`, "Next steps");
66
- p.outro(`More info: ${color.underline(color.yellow("https://zed.dev/docs/extensions/developing-extensions"))}`);
63
+ p.outro(`${color.green('✓')} ${color.bold('Extension created successfully!')}\n` +
64
+ `${color.gray('─'.repeat(40))}\n` +
65
+ `${color.dim('Location:')} ${color.cyan(targetDir)}`);
66
+ p.outro(`${color.yellow('⚡')} ${color.bold('Next steps')}\n\n` +
67
+ ` ${color.gray('1.')} Open Zed\n` +
68
+ ` ${color.gray('2.')} ${color.white('Extensions > Install Dev Extension')}\n` +
69
+ ` ${color.gray('3.')} Select ${color.cyan(options.id)} folder\n\n` +
70
+ `${color.dim('Learn more:')} ${color.underline(color.blue('https://zed.dev/docs/extensions/developing-extensions'))}`);
67
71
  return;
68
72
  }
69
73
  program.parse(process.argv);
package/dist/prompts.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { ExtensionOptions } from "./types/index.js";
1
+ import type { ExtensionOptions } from './types/index.js';
2
2
  export declare function promptUser(): Promise<ExtensionOptions>;
3
3
  export declare function promptThemeDetails(): Promise<{
4
4
  themeName: string;
5
- appearance: "light" | "dark" | "both";
5
+ appearance: 'light' | 'dark' | 'both';
6
6
  }>;
package/dist/prompts.js CHANGED
@@ -1,79 +1,80 @@
1
- import * as p from "@clack/prompts";
2
- import color from "picocolors";
1
+ import * as p from '@clack/prompts';
2
+ import color from 'picocolors';
3
3
  export async function promptUser() {
4
- p.intro(color.bgBlue(" zedx "));
5
- const nameDefault = "my-zed-extension";
4
+ p.intro(`${color.bgBlue(color.bold(' zedx '))} ${color.blue('Boilerplate generator for Zed Editor extensions.')}`);
5
+ const nameDefault = 'my-zed-extension';
6
6
  const name = await p.text({
7
- message: "Project name:",
8
- placeholder: nameDefault,
7
+ message: 'Project name:',
8
+ placeholder: nameDefault
9
9
  });
10
10
  if (p.isCancel(name)) {
11
- p.cancel("Cancelled.");
11
+ p.cancel('Cancelled.');
12
12
  process.exit(0);
13
13
  }
14
14
  const nameValue = name || nameDefault;
15
- const idDefault = nameValue.toLowerCase().replace(/\s+/g, "-");
15
+ const idDefault = nameValue.toLowerCase().replace(/\s+/g, '-');
16
16
  const id = await p.text({
17
- message: "Extension ID:",
17
+ message: 'Extension ID:',
18
18
  placeholder: idDefault,
19
19
  validate: (value) => {
20
- if (value && value.includes(" "))
21
- return "ID cannot contain spaces";
20
+ if (value && value.includes(' '))
21
+ return 'ID cannot contain spaces';
22
22
  if (value && value !== value.toLowerCase())
23
- return "ID must be lowercase";
24
- },
23
+ return 'ID must be lowercase';
24
+ }
25
25
  });
26
26
  if (p.isCancel(id)) {
27
- p.cancel("Cancelled.");
27
+ p.cancel('Cancelled.');
28
28
  process.exit(0);
29
29
  }
30
30
  const idValue = id || idDefault;
31
- const descriptionDefault = "A Zed theme";
31
+ const descriptionDefault = 'A Zed theme';
32
32
  const description = await p.text({
33
- message: "Description:",
34
- placeholder: descriptionDefault,
33
+ message: 'Description:',
34
+ placeholder: descriptionDefault
35
35
  });
36
36
  if (p.isCancel(description)) {
37
- p.cancel("Cancelled.");
37
+ p.cancel('Cancelled.');
38
38
  process.exit(0);
39
39
  }
40
40
  const descriptionValue = description || descriptionDefault;
41
41
  const author = await p.text({
42
- message: "Author name:",
42
+ message: 'Author name:',
43
+ placeholder: 'name <username@example.com>',
43
44
  validate: (value) => {
44
45
  if (!value || value.length === 0)
45
- return "Author is required";
46
- },
46
+ return 'Author is required';
47
+ }
47
48
  });
48
49
  if (p.isCancel(author)) {
49
- p.cancel("Cancelled.");
50
+ p.cancel('Cancelled.');
50
51
  process.exit(0);
51
52
  }
52
- const repositoryDefault = `https://github.com/${author ?? ""}/zed-theme.git`;
53
+ const repositoryDefault = `https://github.com/username/zed-theme.git`;
53
54
  const repository = await p.text({
54
- message: "GitHub repository URL:",
55
- initialValue: repositoryDefault,
55
+ message: 'GitHub repository URL:',
56
+ initialValue: repositoryDefault
56
57
  });
57
58
  if (p.isCancel(repository)) {
58
- p.cancel("Cancelled.");
59
+ p.cancel('Cancelled.');
59
60
  process.exit(0);
60
61
  }
61
62
  const repositoryValue = repository || repositoryDefault;
62
63
  const license = await p.select({
63
- message: "License:",
64
+ message: 'License:',
64
65
  options: [
65
- { value: "Apache-2.0", label: "Apache 2.0" },
66
- { value: "BSD-2-Clause", label: "BSD 2-Clause" },
67
- { value: "BSD-3-Clause", label: "BSD 3-Clause" },
68
- { value: "GPL-3.0", label: "GNU GPLv3" },
69
- { value: "LGPL-3.0", label: "GNU LGPLv3" },
70
- { value: "MIT", label: "MIT" },
71
- { value: "Zlib", label: "zlib" },
66
+ { value: 'Apache-2.0', label: 'Apache 2.0' },
67
+ { value: 'BSD-2-Clause', label: 'BSD 2-Clause' },
68
+ { value: 'BSD-3-Clause', label: 'BSD 3-Clause' },
69
+ { value: 'GPL-3.0', label: 'GNU GPLv3' },
70
+ { value: 'LGPL-3.0', label: 'GNU LGPLv3' },
71
+ { value: 'MIT', label: 'MIT' },
72
+ { value: 'Zlib', label: 'zlib' }
72
73
  ],
73
- initialValue: "MIT",
74
+ initialValue: 'MIT'
74
75
  });
75
76
  if (p.isCancel(license)) {
76
- p.cancel("Cancelled.");
77
+ p.cancel('Cancelled.');
77
78
  process.exit(0);
78
79
  }
79
80
  const options = {
@@ -83,34 +84,34 @@ export async function promptUser() {
83
84
  author: String(author),
84
85
  repository: repositoryValue,
85
86
  license: license,
86
- types: ["theme"],
87
+ types: ['theme']
87
88
  };
88
89
  return options;
89
90
  }
90
91
  export async function promptThemeDetails() {
91
92
  const themeName = await p.text({
92
- message: "Theme name:",
93
- placeholder: "My Theme",
93
+ message: 'Theme name:',
94
+ placeholder: 'My Theme'
94
95
  });
95
96
  if (p.isCancel(themeName)) {
96
- p.cancel("Cancelled.");
97
+ p.cancel('Cancelled.');
97
98
  process.exit(0);
98
99
  }
99
100
  const appearance = await p.select({
100
- message: "Appearance:",
101
+ message: 'Appearance:',
101
102
  options: [
102
- { value: "dark", label: "Dark" },
103
- { value: "light", label: "Light" },
104
- { value: "both", label: "Both (Dark & Light)" },
103
+ { value: 'dark', label: 'Dark' },
104
+ { value: 'light', label: 'Light' },
105
+ { value: 'both', label: 'Both (Dark & Light)' }
105
106
  ],
106
- initialValue: "dark",
107
+ initialValue: 'dark'
107
108
  });
108
109
  if (p.isCancel(appearance)) {
109
- p.cancel("Cancelled.");
110
+ p.cancel('Cancelled.');
110
111
  process.exit(0);
111
112
  }
112
113
  return {
113
114
  themeName: String(themeName),
114
- appearance: appearance,
115
+ appearance: appearance
115
116
  };
116
117
  }
package/package.json CHANGED
@@ -1,53 +1,53 @@
1
1
  {
2
- "name": "zedx",
3
- "version": "0.1.0",
4
- "description": "Boilerplate generator for Zed extensions",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "bin": {
8
- "zedx": "dist/index.js"
9
- },
10
- "files": [
11
- "dist"
12
- ],
13
- "scripts": {
14
- "build": "tsc && cp -r src/templates dist/",
15
- "start": "node dist/index.js",
16
- "dev": "tsx src/index.ts"
17
- },
18
- "keywords": [
19
- "zed",
20
- "zed-editor",
21
- "extension",
22
- "boilerplate",
23
- "scaffold"
24
- ],
25
- "author": "Taha Nejad <taha@noiserandom.com>",
26
- "repository": {
27
- "type": "git",
28
- "url": "https://github.com/tahayvr/zedx.git"
29
- },
30
- "homepage": "https://github.com/tahayvr/zedx#readme",
31
- "license": "Apache-2.0",
32
- "publishConfig": {
33
- "access": "public"
34
- },
35
- "engines": {
36
- "node": ">=18"
37
- },
38
- "devDependencies": {
39
- "@types/ejs": "^3.1.5",
40
- "@types/fs-extra": "^11.0.4",
41
- "@types/node": "^25.2.3",
42
- "tsx": "^4.21.0",
43
- "typescript": "^5.9.3"
44
- },
45
- "dependencies": {
46
- "@clack/prompts": "^0.10.1",
47
- "commander": "^14.0.3",
48
- "ejs": "^4.0.1",
49
- "fs-extra": "^11.3.3",
50
- "picocolors": "^1.1.1"
51
- },
52
- "packageManager": "pnpm@10.30.0+sha512.2b5753de015d480eeb88f5b5b61e0051f05b4301808a82ec8b840c9d2adf7748eb352c83f5c1593ca703ff1017295bc3fdd3119abb9686efc96b9fcb18200937"
2
+ "name": "zedx",
3
+ "version": "0.2.0",
4
+ "description": "Boilerplate generator for Zed Edittor extensions.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "zedx": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc && cp -r src/templates dist/",
15
+ "start": "node dist/index.js",
16
+ "dev": "tsx src/index.ts"
17
+ },
18
+ "keywords": [
19
+ "zed",
20
+ "zed-editor",
21
+ "extension",
22
+ "boilerplate",
23
+ "scaffold"
24
+ ],
25
+ "author": "Taha Nejad <taha@noiserandom.com>",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/tahayvr/zedx.git"
29
+ },
30
+ "homepage": "https://github.com/tahayvr/zedx#readme",
31
+ "license": "Apache-2.0",
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "engines": {
36
+ "node": ">=18"
37
+ },
38
+ "devDependencies": {
39
+ "@types/ejs": "^3.1.5",
40
+ "@types/fs-extra": "^11.0.4",
41
+ "@types/node": "^25.2.3",
42
+ "tsx": "^4.21.0",
43
+ "typescript": "^5.9.3"
44
+ },
45
+ "dependencies": {
46
+ "@clack/prompts": "^0.10.1",
47
+ "commander": "^14.0.3",
48
+ "ejs": "^4.0.1",
49
+ "fs-extra": "^11.3.3",
50
+ "picocolors": "^1.1.1"
51
+ },
52
+ "packageManager": "pnpm@10.30.0+sha512.2b5753de015d480eeb88f5b5b61e0051f05b4301808a82ec8b840c9d2adf7748eb352c83f5c1593ca703ff1017295bc3fdd3119abb9686efc96b9fcb18200937"
53
53
  }