create-stylelint 0.7.0 → 1.0.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.
Files changed (2) hide show
  1. package/package.json +16 -14
  2. package/src/index.mjs +102 -148
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-stylelint",
3
- "version": "0.7.0",
3
+ "version": "1.0.0",
4
4
  "description": "The npm init script for Stylelint.",
5
5
  "keywords": [
6
6
  "stylelint",
@@ -19,11 +19,13 @@
19
19
  ],
20
20
  "license": "MIT",
21
21
  "author": "stylelint",
22
- "main": "create-stylelint.mjs",
22
+ "type": "module",
23
+ "exports": "./create-stylelint.mjs",
23
24
  "bin": {
24
25
  "create-stylelint": "./create-stylelint.mjs"
25
26
  },
26
27
  "files": [
28
+ "create-stylelint.mjs",
27
29
  "src"
28
30
  ],
29
31
  "scripts": {
@@ -48,27 +50,27 @@
48
50
  ]
49
51
  },
50
52
  "dependencies": {
51
- "@inquirer/confirm": "^5.1.18",
52
- "cosmiconfig": "^9.0.0",
53
- "execa": "^9.6.0",
54
- "ora": "^9.0.0",
53
+ "@clack/prompts": "^1.2.0",
54
+ "cosmiconfig": "^9.0.1",
55
+ "execa": "^9.6.1",
55
56
  "picocolors": "^1.1.1",
56
- "semver": "^7.7.2",
57
+ "semver": "^7.7.4",
57
58
  "strip-indent": "^4.1.0",
58
- "which-pm-runs": "^1.1.0"
59
+ "which-pm-runs": "^2.0.0"
59
60
  },
60
61
  "devDependencies": {
61
62
  "@stylelint/npm-package-json-lint-config": "^5.1.0",
62
- "@stylelint/prettier-config": "^3.0.0",
63
+ "@stylelint/prettier-config": "^4.0.0",
63
64
  "@stylelint/remark-preset": "^5.1.1",
65
+ "@types/node": "^25.5.0",
64
66
  "@types/which-pm-runs": "^1.0.2",
65
- "eslint": "^9.36.0",
66
- "eslint-config-stylelint": "^25.0.0",
67
+ "eslint": "^10.1.0",
68
+ "eslint-config-stylelint": "^27.0.0",
67
69
  "npm-run-all": "^4.1.5",
68
- "prettier": "^3.6.2",
70
+ "prettier": "^3.8.1",
69
71
  "remark-cli": "^12.0.1",
70
- "typescript": "^5.9.2",
71
- "vitest": "^3.2.4"
72
+ "typescript": "^6.0.2",
73
+ "vitest": "^4.1.1"
72
74
  },
73
75
  "optionalDependencies": {
74
76
  "@rollup/rollup-darwin-x64": "*",
package/src/index.mjs CHANGED
@@ -1,17 +1,17 @@
1
- /* eslint no-console: 'off' */
2
1
  /* eslint n/no-process-exit: 'off' */
3
2
 
4
3
  import * as fs from 'node:fs';
5
4
  import * as path from 'node:path';
6
5
  import process from 'node:process';
7
6
 
8
- import confirm from '@inquirer/confirm';
7
+ import { cancel, confirm, intro, isCancel, log, note, outro, spinner } from '@clack/prompts';
9
8
  import { cosmiconfig } from 'cosmiconfig';
10
- import detectPackageManager from 'which-pm-runs';
11
9
  import { execa } from 'execa';
12
- import ora from 'ora';
13
10
  import pc from 'picocolors';
14
11
  import stripIndent from 'strip-indent';
12
+ // @ts-expect-error - TS2595: 'whichPMRuns' can only be imported by using a default import.
13
+ // Need to wait for a `@types/which-pm-runs` new version.
14
+ import { whichPMRuns } from 'which-pm-runs';
15
15
 
16
16
  const DEFAULT_CONFIG_FILE = 'stylelint.config.mjs';
17
17
  const DEFAULT_CONFIG_CONTENT = `/** @type {import("stylelint").Config} */
@@ -21,186 +21,140 @@ export default {
21
21
 
22
22
  const ADD_COMMAND = 'add -D stylelint stylelint-config-standard';
23
23
 
24
- async function getExistingConfigInDirectory() {
25
- const explorer = cosmiconfig('stylelint');
26
- const result = await explorer.search();
27
-
28
- return result;
29
- }
30
-
31
- /**
32
- * @param {fs.PathLike} dir
33
- */
34
- function directoryHasPackageJson(dir) {
35
- return fs.readdirSync(dir).some((file) => file === 'package.json');
36
- }
24
+ export async function main() {
25
+ const pkgManager = whichPMRuns()?.name ?? 'npm';
26
+ const cwd = './';
37
27
 
38
- /**
39
- * @param {string} pkgManager
40
- * @return {string} The command
41
- */
42
- function getExecuteCommand(pkgManager) {
43
- switch (pkgManager) {
44
- case 'npm':
45
- return 'npx';
46
- case 'bun':
47
- return 'bunx';
48
- case 'pnpm':
49
- case 'yarn':
50
- return `${pkgManager} dlx`;
51
- default:
52
- throw new Error(`"${pkgManager}" package manager is not supported`);
53
- }
54
- }
28
+ intro(pc.bgGreen(pc.white(' create-stylelint ')));
55
29
 
56
- /**
57
- * @param {string} errorMessage
58
- */
59
- function cancelSetup(errorMessage = '') {
60
- console.error(
30
+ note(
61
31
  stripIndent(`
62
- ${pc.red(pc.bold('Setup canceled!'))}
63
- `),
64
- );
32
+ Create a ${pc.cyan(DEFAULT_CONFIG_FILE)} file containing:
65
33
 
66
- if (errorMessage) {
67
- console.error(
68
- stripIndent(`${errorMessage}
69
- `),
70
- );
71
- }
34
+ ${DEFAULT_CONFIG_CONTENT.split('\n').join('\n\t\t\t ')}
72
35
 
73
- process.exit(1);
74
- }
36
+ Add the related dependencies using:
75
37
 
76
- /**
77
- * @param {string} pkgManager
78
- */
79
- async function showPrompt(pkgManager) {
80
- console.info(
81
- stripIndent(`
82
- We'll create a ${pc.cyan(DEFAULT_CONFIG_FILE)} file containing:
83
- `),
38
+ ${pkgManager} ${ADD_COMMAND}
39
+ `).trim(),
40
+ 'This tool will:',
84
41
  );
85
42
 
86
- console.info(
87
- pc.dim(
88
- DEFAULT_CONFIG_CONTENT.split('\n')
89
- .map((line) => ` ${line}`)
90
- .join('\n'),
91
- ),
92
- );
43
+ const shouldContinue = await confirm({ message: 'Continue?' });
93
44
 
94
- console.info(
95
- stripIndent(`
96
- Then add the related dependencies using:
45
+ if (isCancel(shouldContinue) || !shouldContinue) {
46
+ cancel('Canceled');
47
+ process.exit(0);
48
+ }
97
49
 
98
- ${pc.dim(`${pkgManager} ${ADD_COMMAND}`)}
99
- `),
100
- );
50
+ const configSpinner = spinner();
101
51
 
102
- let proceed;
52
+ configSpinner.start('Creating config');
103
53
 
104
54
  try {
105
- proceed = await confirm({
106
- message: 'Continue?',
107
- });
108
- } catch (error) {
109
- if (error instanceof Error && error.name === 'ExitPromptError') {
110
- // silence
111
- } else {
112
- throw error;
113
- }
114
- }
55
+ const existingConfig = await getExistingConfigInDirectory();
115
56
 
116
- if (!proceed) {
117
- cancelSetup();
118
- }
119
- }
57
+ if (existingConfig !== null) {
58
+ const basename = path.basename(existingConfig.filepath);
59
+ const failureMessage =
60
+ basename === 'package.json'
61
+ ? `A ${pc.cyan('stylelint')} entry in ${pc.cyan('package.json')} already exists.`
62
+ : `A ${pc.cyan(basename)} file already exists.`;
120
63
 
121
- /**
122
- * @param {string} cwd
123
- * @param {string} pkgManager
124
- */
125
- async function createConfig(cwd, pkgManager) {
126
- const spinner = ora('Creating config...').start();
127
- const existingConfig = await getExistingConfigInDirectory();
128
-
129
- if (existingConfig !== null) {
130
- const basename = path.basename(existingConfig.filepath);
131
- const failureMessage =
132
- basename === 'package.json'
133
- ? 'A "stylelint" config in "package.json" already exists.'
134
- : `A "${basename}" config already exists.`;
135
-
136
- spinner.fail();
137
- cancelSetup(`${failureMessage} Remove it and then try again.`);
138
- }
64
+ throw new Error(`${failureMessage} Remove it and then try again.`);
65
+ }
139
66
 
140
- if (!directoryHasPackageJson(cwd)) {
141
- spinner.fail();
142
- cancelSetup(`A "package.json" was not found. Run "${pkgManager} init" and then try again.`);
143
- }
67
+ if (!directoryHasPackageJson(cwd)) {
68
+ throw new Error(
69
+ `A ${pc.cyan('package.json')} was not found. Run ${pc.cyan(`${pkgManager} init`)} and then try again.`,
70
+ );
71
+ }
144
72
 
145
- try {
146
73
  fs.writeFileSync(DEFAULT_CONFIG_FILE, `${DEFAULT_CONFIG_CONTENT}\n`);
74
+ configSpinner.stop('Created config file');
147
75
  } catch (error) {
148
- spinner.fail();
149
- cancelSetup(error instanceof Error ? error.message : String(error));
76
+ handleError(configSpinner, error);
150
77
  }
151
78
 
152
- spinner.succeed('Created config file');
153
- }
79
+ const depsSpinner = spinner();
154
80
 
155
- /**
156
- * @param {string} cwd
157
- * @param {string} pkgManager
158
- */
159
- async function addDependencies(cwd, pkgManager) {
160
- const spinner = ora('Adding dependencies...').start();
81
+ depsSpinner.start('Adding dependencies');
161
82
 
162
83
  try {
163
- await execa(pkgManager, [...ADD_COMMAND.split(' ')], {
164
- cwd,
165
- });
84
+ await execa(pkgManager, [...ADD_COMMAND.split(' ')], { cwd });
85
+ depsSpinner.stop('Added dependencies');
166
86
  } catch (error) {
167
- spinner.fail();
168
- cancelSetup(error instanceof Error ? error.message : String(error));
87
+ handleError(depsSpinner, error);
169
88
  }
170
89
 
171
- spinner.succeed('Added dependencies');
172
- }
90
+ log.success('Stylelint is ready!');
173
91
 
174
- /**
175
- * @param {string} pkgManager
176
- */
177
- function showNextSteps(pkgManager) {
178
- console.info(
92
+ note(
179
93
  stripIndent(`
180
- ${pc.green(pc.bold('Setup complete!'))}
181
-
182
- Lint your CSS files with:
94
+ Lint your CSS files:
183
95
 
184
96
  ${pc.dim(`${getExecuteCommand(pkgManager)} stylelint "**/*.css"`)}
185
97
 
186
- Next steps? Customize your config: ${pc.underline(
187
- pc.blue('https://stylelint.io/user-guide/customize'),
188
- )}
98
+ Customize your config:
189
99
 
190
- If you benefit from Stylelint, please consider sponsoring the project at:
100
+ - ${pc.underline(pc.cyan('https://stylelint.io/user-guide/customize'))}
101
+ `).trim(),
102
+ 'Next steps:',
103
+ );
191
104
 
192
- - ${pc.underline(pc.blue('https://github.com/sponsors/stylelint'))}
193
- - ${pc.underline(pc.blue('https://opencollective.com/stylelint'))}
194
- `),
105
+ log.message(
106
+ stripIndent(`
107
+ ${pc.dim('Support Stylelint:')}
108
+
109
+ ${pc.dim(`- ${pc.underline(pc.cyan('https://github.com/sponsors/stylelint'))}`)}
110
+ ${pc.dim(`- ${pc.underline(pc.cyan('https://opencollective.com/stylelint'))}`)}
111
+ `).trim(),
195
112
  );
113
+
114
+ outro(pc.green('Done!'));
196
115
  }
197
116
 
198
- export async function main() {
199
- const pkgManager = detectPackageManager()?.name ?? 'npm';
200
- const cwd = './';
117
+ async function getExistingConfigInDirectory() {
118
+ const explorer = cosmiconfig('stylelint');
119
+ const result = await explorer.search();
120
+
121
+ return result;
122
+ }
201
123
 
202
- await showPrompt(pkgManager);
203
- await createConfig(cwd, pkgManager);
204
- await addDependencies(cwd, pkgManager);
205
- showNextSteps(pkgManager);
124
+ /**
125
+ * @param {fs.PathLike} dir
126
+ */
127
+ function directoryHasPackageJson(dir) {
128
+ return fs.readdirSync(dir).some((file) => file === 'package.json');
129
+ }
130
+
131
+ /**
132
+ * @param {ReturnType<typeof spinner>} s
133
+ * @param {unknown} error
134
+ * @returns {never}
135
+ */
136
+ function handleError(s, error) {
137
+ const message = error instanceof Error ? error.message : String(error);
138
+
139
+ s.error(message);
140
+ cancel('Canceled');
141
+ process.exit(1);
142
+ }
143
+
144
+ /**
145
+ * @param {string} pkgManager
146
+ * @return {string} The command
147
+ */
148
+ function getExecuteCommand(pkgManager) {
149
+ switch (pkgManager) {
150
+ case 'npm':
151
+ return 'npx';
152
+ case 'bun':
153
+ return 'bunx';
154
+ case 'pnpm':
155
+ case 'yarn':
156
+ return `${pkgManager} dlx`;
157
+ default:
158
+ throw new Error(`${pc.cyan(pkgManager)} package manager is not supported`);
159
+ }
206
160
  }