create-alistt69-kit 0.1.11 → 0.1.13
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/LICENSE +20 -20
- package/README.md +123 -123
- package/bin/index.js +24 -24
- package/package.json +44 -44
- package/src/core/apply-features.js +14 -14
- package/src/core/collect-project-info.js +170 -170
- package/src/core/copy-base-template.js +11 -11
- package/src/core/create-project.js +99 -99
- package/src/core/install-dependencies.js +27 -27
- package/src/core/parse-cli-args.js +122 -122
- package/src/core/prepare-target-directory.js +69 -69
- package/src/core/render-project-readme.js +188 -188
- package/src/core/replace-tokens.js +45 -45
- package/src/core/restore-special-files.js +18 -18
- package/src/features/autoprefixer/files/postcss.config.cjs +4 -4
- package/src/features/autoprefixer/index.js +18 -18
- package/src/features/define-feature.js +32 -32
- package/src/features/eslint/files/eslint.config.mjs +133 -133
- package/src/features/eslint/index.js +29 -29
- package/src/features/index.js +24 -24
- package/src/features/react-router/files/src/app/App.tsx +20 -20
- package/src/features/react-router/files/src/app/layouts/app/index.tsx +36 -36
- package/src/features/react-router/files/src/app/providers/router/config/router.tsx +13 -13
- package/src/features/react-router/files/src/pages/error/index.ts +1 -1
- package/src/features/react-router/files/src/pages/error/lazy.ts +3 -3
- package/src/features/react-router/files/src/pages/error/page.tsx +7 -7
- package/src/features/react-router/files/src/pages/main/index.ts +1 -1
- package/src/features/react-router/files/src/pages/main/lazy.ts +3 -3
- package/src/features/react-router/files/src/pages/main/page.tsx +7 -7
- package/src/features/react-router/index.js +18 -18
- package/src/features/stylelint/files/stylelint.config.mjs +13 -13
- package/src/features/stylelint/index.js +23 -23
- package/src/templates/base/.editorconfig +11 -11
- package/src/templates/base/README.md +2 -2
- package/src/templates/base/babel.config.json +12 -12
- package/src/templates/base/gitignore +27 -27
- package/src/templates/base/package.json +48 -48
- package/src/templates/base/public/index.html +12 -12
- package/src/templates/base/src/app/App.tsx +17 -17
- package/src/templates/base/src/index.tsx +16 -16
- package/src/templates/base/src/styles/index.scss +13 -13
- package/src/templates/base/tsconfig.json +25 -25
- package/src/utils/console-format.js +11 -11
- package/src/utils/package-json.js +96 -96
- package/src/utils/package-manager.js +22 -22
|
@@ -1,189 +1,189 @@
|
|
|
1
|
-
import { writeFile } from 'node:fs/promises';
|
|
2
|
-
import { resolve } from 'node:path';
|
|
3
|
-
|
|
4
|
-
import { featuresById } from '../features/index.js';
|
|
5
|
-
import { readPackageJson } from '../utils/package-json.js';
|
|
6
|
-
import { getRunScriptCommand } from '../utils/package-manager.js';
|
|
7
|
-
|
|
8
|
-
const defaultTooling = [
|
|
9
|
-
{
|
|
10
|
-
title: 'React',
|
|
11
|
-
docs: 'https://react.dev/',
|
|
12
|
-
description: 'UI library',
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
title: 'TypeScript',
|
|
16
|
-
docs: 'https://www.typescriptlang.org/',
|
|
17
|
-
description: 'Static typing',
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
title: 'Webpack',
|
|
21
|
-
docs: 'https://webpack.js.org/',
|
|
22
|
-
description: 'Bundling and build pipeline',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
title: 'SCSS Modules',
|
|
26
|
-
docs: 'https://github.com/css-modules/css-modules',
|
|
27
|
-
description: 'Scoped styling',
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
title: 'SVGR',
|
|
31
|
-
docs: 'https://react-svgr.com/',
|
|
32
|
-
description: 'SVGs as React components',
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
title: 'Webpack Bundle Analyzer',
|
|
36
|
-
docs: 'https://github.com/webpack-contrib/webpack-bundle-analyzer',
|
|
37
|
-
description: 'Bundle size inspection',
|
|
38
|
-
},
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
const scriptDescriptions = {
|
|
42
|
-
dev: 'Start development server',
|
|
43
|
-
start: 'Start development server',
|
|
44
|
-
build: 'Build for production',
|
|
45
|
-
'build:dev': 'Build in development mode',
|
|
46
|
-
'build:prod': 'Build in production mode',
|
|
47
|
-
typecheck: 'Run TypeScript type check',
|
|
48
|
-
lint: 'Run ESLint',
|
|
49
|
-
'lint:fix': 'Run ESLint with autofix',
|
|
50
|
-
'lint:styles': 'Run Stylelint',
|
|
51
|
-
'lint:styles:fix': 'Run Stylelint with autofix',
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
function formatMarkdownList(items, fallback = '- None') {
|
|
55
|
-
if (items.length === 0) {
|
|
56
|
-
return fallback;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return items.join('\n');
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function formatDefaultTooling() {
|
|
63
|
-
return formatMarkdownList(
|
|
64
|
-
defaultTooling.map(({ title, docs, description }) => (
|
|
65
|
-
`- [${title}](${docs}) — ${description}`
|
|
66
|
-
)),
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function formatFeatureList(selectedFeatureIds) {
|
|
71
|
-
if (selectedFeatureIds.length === 0) {
|
|
72
|
-
return '- None';
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return selectedFeatureIds
|
|
76
|
-
.map((featureId) => {
|
|
77
|
-
const feature = featuresById.get(featureId);
|
|
78
|
-
|
|
79
|
-
if (!feature) {
|
|
80
|
-
return `- ${featureId}`;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return feature.hint
|
|
84
|
-
? `- ${feature.title} — ${feature.hint}`
|
|
85
|
-
: `- ${feature.title}`;
|
|
86
|
-
})
|
|
87
|
-
.join('\n');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function formatScripts(packageManager, scripts) {
|
|
91
|
-
const entries = Object.entries(scripts);
|
|
92
|
-
|
|
93
|
-
if (entries.length === 0) {
|
|
94
|
-
return '_No scripts available._';
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return entries
|
|
98
|
-
.map(([scriptName]) => {
|
|
99
|
-
const command = getRunScriptCommand(packageManager, scriptName);
|
|
100
|
-
const description = scriptDescriptions[scriptName] ?? 'Project script';
|
|
101
|
-
|
|
102
|
-
return `- \`${command}\` — ${description}`;
|
|
103
|
-
})
|
|
104
|
-
.join('\n');
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function formatQuickStart({
|
|
108
|
-
projectName,
|
|
109
|
-
packageManager,
|
|
110
|
-
shouldInstallDependencies,
|
|
111
|
-
}) {
|
|
112
|
-
const steps = [`cd ${projectName}`];
|
|
113
|
-
|
|
114
|
-
if (!shouldInstallDependencies) {
|
|
115
|
-
steps.push(packageManager === 'yarn' ? 'yarn' : `${packageManager} install`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
steps.push(getRunScriptCommand(packageManager, 'start'));
|
|
119
|
-
|
|
120
|
-
return [
|
|
121
|
-
shouldInstallDependencies
|
|
122
|
-
? 'Dependencies are already installed.'
|
|
123
|
-
: 'Install dependencies first, then start the development server.',
|
|
124
|
-
'',
|
|
125
|
-
'```bash',
|
|
126
|
-
...steps,
|
|
127
|
-
'```',
|
|
128
|
-
].join('\n');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function formatProjectStructure() {
|
|
132
|
-
return [
|
|
133
|
-
'- `public/` — static assets and HTML template',
|
|
134
|
-
'- `src/` — application source code',
|
|
135
|
-
'- `src/app/` — app bootstrap, providers, entry-level setup',
|
|
136
|
-
'- `src/styles/` — global styles and shared styling layer',
|
|
137
|
-
'- `config/build/` — split webpack configuration',
|
|
138
|
-
].join('\n');
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export async function renderProjectReadme({
|
|
142
|
-
projectPath,
|
|
143
|
-
projectName,
|
|
144
|
-
selectedFeatureIds,
|
|
145
|
-
packageManager,
|
|
146
|
-
shouldInstallDependencies,
|
|
147
|
-
}) {
|
|
148
|
-
const packageJson = await readPackageJson(projectPath);
|
|
149
|
-
|
|
150
|
-
const readmeContent = [
|
|
151
|
-
`# ${projectName}`,
|
|
152
|
-
'',
|
|
153
|
-
'Created with `create-alistt69-kit`.',
|
|
154
|
-
'',
|
|
155
|
-
'## Overview',
|
|
156
|
-
'',
|
|
157
|
-
'Starter project based on React + TypeScript + Webpack with optional tooling selected during scaffolding.',
|
|
158
|
-
'',
|
|
159
|
-
'## Included by default',
|
|
160
|
-
'',
|
|
161
|
-
formatDefaultTooling(),
|
|
162
|
-
'',
|
|
163
|
-
'## Selected optional features',
|
|
164
|
-
'',
|
|
165
|
-
formatFeatureList(selectedFeatureIds),
|
|
166
|
-
'',
|
|
167
|
-
'## Quick start',
|
|
168
|
-
'',
|
|
169
|
-
formatQuickStart({
|
|
170
|
-
projectName,
|
|
171
|
-
packageManager,
|
|
172
|
-
shouldInstallDependencies,
|
|
173
|
-
}),
|
|
174
|
-
'',
|
|
175
|
-
'## Project structure',
|
|
176
|
-
'',
|
|
177
|
-
formatProjectStructure(),
|
|
178
|
-
'',
|
|
179
|
-
'## Available scripts',
|
|
180
|
-
'',
|
|
181
|
-
formatScripts(packageManager, packageJson.scripts ?? {}),
|
|
182
|
-
].join('\n');
|
|
183
|
-
|
|
184
|
-
await writeFile(
|
|
185
|
-
resolve(projectPath, 'README.md'),
|
|
186
|
-
`${readmeContent}\n`,
|
|
187
|
-
'utf8',
|
|
188
|
-
);
|
|
1
|
+
import { writeFile } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
import { featuresById } from '../features/index.js';
|
|
5
|
+
import { readPackageJson } from '../utils/package-json.js';
|
|
6
|
+
import { getRunScriptCommand } from '../utils/package-manager.js';
|
|
7
|
+
|
|
8
|
+
const defaultTooling = [
|
|
9
|
+
{
|
|
10
|
+
title: 'React',
|
|
11
|
+
docs: 'https://react.dev/',
|
|
12
|
+
description: 'UI library',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
title: 'TypeScript',
|
|
16
|
+
docs: 'https://www.typescriptlang.org/',
|
|
17
|
+
description: 'Static typing',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
title: 'Webpack',
|
|
21
|
+
docs: 'https://webpack.js.org/',
|
|
22
|
+
description: 'Bundling and build pipeline',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
title: 'SCSS Modules',
|
|
26
|
+
docs: 'https://github.com/css-modules/css-modules',
|
|
27
|
+
description: 'Scoped styling',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
title: 'SVGR',
|
|
31
|
+
docs: 'https://react-svgr.com/',
|
|
32
|
+
description: 'SVGs as React components',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
title: 'Webpack Bundle Analyzer',
|
|
36
|
+
docs: 'https://github.com/webpack-contrib/webpack-bundle-analyzer',
|
|
37
|
+
description: 'Bundle size inspection',
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const scriptDescriptions = {
|
|
42
|
+
dev: 'Start development server',
|
|
43
|
+
start: 'Start development server',
|
|
44
|
+
build: 'Build for production',
|
|
45
|
+
'build:dev': 'Build in development mode',
|
|
46
|
+
'build:prod': 'Build in production mode',
|
|
47
|
+
typecheck: 'Run TypeScript type check',
|
|
48
|
+
lint: 'Run ESLint',
|
|
49
|
+
'lint:fix': 'Run ESLint with autofix',
|
|
50
|
+
'lint:styles': 'Run Stylelint',
|
|
51
|
+
'lint:styles:fix': 'Run Stylelint with autofix',
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function formatMarkdownList(items, fallback = '- None') {
|
|
55
|
+
if (items.length === 0) {
|
|
56
|
+
return fallback;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return items.join('\n');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function formatDefaultTooling() {
|
|
63
|
+
return formatMarkdownList(
|
|
64
|
+
defaultTooling.map(({ title, docs, description }) => (
|
|
65
|
+
`- [${title}](${docs}) — ${description}`
|
|
66
|
+
)),
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function formatFeatureList(selectedFeatureIds) {
|
|
71
|
+
if (selectedFeatureIds.length === 0) {
|
|
72
|
+
return '- None';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return selectedFeatureIds
|
|
76
|
+
.map((featureId) => {
|
|
77
|
+
const feature = featuresById.get(featureId);
|
|
78
|
+
|
|
79
|
+
if (!feature) {
|
|
80
|
+
return `- ${featureId}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return feature.hint
|
|
84
|
+
? `- ${feature.title} — ${feature.hint}`
|
|
85
|
+
: `- ${feature.title}`;
|
|
86
|
+
})
|
|
87
|
+
.join('\n');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function formatScripts(packageManager, scripts) {
|
|
91
|
+
const entries = Object.entries(scripts);
|
|
92
|
+
|
|
93
|
+
if (entries.length === 0) {
|
|
94
|
+
return '_No scripts available._';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return entries
|
|
98
|
+
.map(([scriptName]) => {
|
|
99
|
+
const command = getRunScriptCommand(packageManager, scriptName);
|
|
100
|
+
const description = scriptDescriptions[scriptName] ?? 'Project script';
|
|
101
|
+
|
|
102
|
+
return `- \`${command}\` — ${description}`;
|
|
103
|
+
})
|
|
104
|
+
.join('\n');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function formatQuickStart({
|
|
108
|
+
projectName,
|
|
109
|
+
packageManager,
|
|
110
|
+
shouldInstallDependencies,
|
|
111
|
+
}) {
|
|
112
|
+
const steps = [`cd ${projectName}`];
|
|
113
|
+
|
|
114
|
+
if (!shouldInstallDependencies) {
|
|
115
|
+
steps.push(packageManager === 'yarn' ? 'yarn' : `${packageManager} install`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
steps.push(getRunScriptCommand(packageManager, 'start'));
|
|
119
|
+
|
|
120
|
+
return [
|
|
121
|
+
shouldInstallDependencies
|
|
122
|
+
? 'Dependencies are already installed.'
|
|
123
|
+
: 'Install dependencies first, then start the development server.',
|
|
124
|
+
'',
|
|
125
|
+
'```bash',
|
|
126
|
+
...steps,
|
|
127
|
+
'```',
|
|
128
|
+
].join('\n');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function formatProjectStructure() {
|
|
132
|
+
return [
|
|
133
|
+
'- `public/` — static assets and HTML template',
|
|
134
|
+
'- `src/` — application source code',
|
|
135
|
+
'- `src/app/` — app bootstrap, providers, entry-level setup',
|
|
136
|
+
'- `src/styles/` — global styles and shared styling layer',
|
|
137
|
+
'- `config/build/` — split webpack configuration',
|
|
138
|
+
].join('\n');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export async function renderProjectReadme({
|
|
142
|
+
projectPath,
|
|
143
|
+
projectName,
|
|
144
|
+
selectedFeatureIds,
|
|
145
|
+
packageManager,
|
|
146
|
+
shouldInstallDependencies,
|
|
147
|
+
}) {
|
|
148
|
+
const packageJson = await readPackageJson(projectPath);
|
|
149
|
+
|
|
150
|
+
const readmeContent = [
|
|
151
|
+
`# ${projectName}`,
|
|
152
|
+
'',
|
|
153
|
+
'Created with `create-alistt69-kit`.',
|
|
154
|
+
'',
|
|
155
|
+
'## Overview',
|
|
156
|
+
'',
|
|
157
|
+
'Starter project based on React + TypeScript + Webpack with optional tooling selected during scaffolding.',
|
|
158
|
+
'',
|
|
159
|
+
'## Included by default',
|
|
160
|
+
'',
|
|
161
|
+
formatDefaultTooling(),
|
|
162
|
+
'',
|
|
163
|
+
'## Selected optional features',
|
|
164
|
+
'',
|
|
165
|
+
formatFeatureList(selectedFeatureIds),
|
|
166
|
+
'',
|
|
167
|
+
'## Quick start',
|
|
168
|
+
'',
|
|
169
|
+
formatQuickStart({
|
|
170
|
+
projectName,
|
|
171
|
+
packageManager,
|
|
172
|
+
shouldInstallDependencies,
|
|
173
|
+
}),
|
|
174
|
+
'',
|
|
175
|
+
'## Project structure',
|
|
176
|
+
'',
|
|
177
|
+
formatProjectStructure(),
|
|
178
|
+
'',
|
|
179
|
+
'## Available scripts',
|
|
180
|
+
'',
|
|
181
|
+
formatScripts(packageManager, packageJson.scripts ?? {}),
|
|
182
|
+
].join('\n');
|
|
183
|
+
|
|
184
|
+
await writeFile(
|
|
185
|
+
resolve(projectPath, 'README.md'),
|
|
186
|
+
`${readmeContent}\n`,
|
|
187
|
+
'utf8',
|
|
188
|
+
);
|
|
189
189
|
}
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import { readFile, readdir, stat, writeFile } from 'node:fs/promises';
|
|
2
|
-
import { resolve } from 'node:path';
|
|
3
|
-
|
|
4
|
-
const replaceTokensInFile = async (filePath, tokens) => {
|
|
5
|
-
const fileContent = await readFile(filePath, 'utf8');
|
|
6
|
-
|
|
7
|
-
let updatedContent = fileContent;
|
|
8
|
-
|
|
9
|
-
for (const [token, value] of Object.entries(tokens)) {
|
|
10
|
-
updatedContent = updatedContent.replaceAll(token, value);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
await writeFile(filePath, updatedContent, 'utf8');
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const replaceTokensRecursively = async (targetPath, tokens) => {
|
|
17
|
-
const targetStat = await stat(targetPath);
|
|
18
|
-
|
|
19
|
-
if (targetStat.isFile()) {
|
|
20
|
-
await replaceTokensInFile(targetPath, tokens);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (!targetStat.isDirectory()) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const entries = await readdir(targetPath, { withFileTypes: true });
|
|
29
|
-
|
|
30
|
-
for (const entry of entries) {
|
|
31
|
-
const entryPath = resolve(targetPath, entry.name);
|
|
32
|
-
|
|
33
|
-
if (entry.isDirectory()) {
|
|
34
|
-
await replaceTokensRecursively(entryPath, tokens);
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (entry.isFile()) {
|
|
39
|
-
await replaceTokensInFile(entryPath, tokens);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export async function replaceTokens(targetDirPath, tokens) {
|
|
45
|
-
await replaceTokensRecursively(targetDirPath, tokens);
|
|
1
|
+
import { readFile, readdir, stat, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
const replaceTokensInFile = async (filePath, tokens) => {
|
|
5
|
+
const fileContent = await readFile(filePath, 'utf8');
|
|
6
|
+
|
|
7
|
+
let updatedContent = fileContent;
|
|
8
|
+
|
|
9
|
+
for (const [token, value] of Object.entries(tokens)) {
|
|
10
|
+
updatedContent = updatedContent.replaceAll(token, value);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
await writeFile(filePath, updatedContent, 'utf8');
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const replaceTokensRecursively = async (targetPath, tokens) => {
|
|
17
|
+
const targetStat = await stat(targetPath);
|
|
18
|
+
|
|
19
|
+
if (targetStat.isFile()) {
|
|
20
|
+
await replaceTokensInFile(targetPath, tokens);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!targetStat.isDirectory()) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const entries = await readdir(targetPath, { withFileTypes: true });
|
|
29
|
+
|
|
30
|
+
for (const entry of entries) {
|
|
31
|
+
const entryPath = resolve(targetPath, entry.name);
|
|
32
|
+
|
|
33
|
+
if (entry.isDirectory()) {
|
|
34
|
+
await replaceTokensRecursively(entryPath, tokens);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (entry.isFile()) {
|
|
39
|
+
await replaceTokensInFile(entryPath, tokens);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export async function replaceTokens(targetDirPath, tokens) {
|
|
45
|
+
await replaceTokensRecursively(targetDirPath, tokens);
|
|
46
46
|
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { access, rename } from 'node:fs/promises';
|
|
2
|
-
import { resolve } from 'node:path';
|
|
3
|
-
|
|
4
|
-
async function renameIfExists(fromPath, toPath) {
|
|
5
|
-
try {
|
|
6
|
-
await access(fromPath);
|
|
7
|
-
} catch {
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
await rename(fromPath, toPath);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export async function restoreSpecialFiles(projectPath) {
|
|
15
|
-
await renameIfExists(
|
|
16
|
-
resolve(projectPath, 'gitignore'),
|
|
17
|
-
resolve(projectPath, '.gitignore'),
|
|
18
|
-
);
|
|
1
|
+
import { access, rename } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
async function renameIfExists(fromPath, toPath) {
|
|
5
|
+
try {
|
|
6
|
+
await access(fromPath);
|
|
7
|
+
} catch {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
await rename(fromPath, toPath);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function restoreSpecialFiles(projectPath) {
|
|
15
|
+
await renameIfExists(
|
|
16
|
+
resolve(projectPath, 'gitignore'),
|
|
17
|
+
resolve(projectPath, '.gitignore'),
|
|
18
|
+
);
|
|
19
19
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
plugins: [
|
|
3
|
-
require('autoprefixer'),
|
|
4
|
-
],
|
|
1
|
+
module.exports = {
|
|
2
|
+
plugins: [
|
|
3
|
+
require('autoprefixer'),
|
|
4
|
+
],
|
|
5
5
|
};
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { dirname, resolve } from 'node:path';
|
|
2
|
-
import { fileURLToPath } from 'node:url';
|
|
3
|
-
|
|
4
|
-
import { defineFeature } from '../define-feature.js';
|
|
5
|
-
|
|
6
|
-
const currentFilePath = fileURLToPath(import.meta.url);
|
|
7
|
-
const currentDirPath = dirname(currentFilePath);
|
|
8
|
-
|
|
9
|
-
export const autoprefixerFeature = defineFeature({
|
|
10
|
-
id: 'autoprefixer',
|
|
11
|
-
title: 'Autoprefixer',
|
|
12
|
-
hint: 'PostCSS vendor prefixes',
|
|
13
|
-
packageJson: {
|
|
14
|
-
devDependencies: {
|
|
15
|
-
autoprefixer: '^10.4.21',
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
copyFiles: resolve(currentDirPath, 'files'),
|
|
1
|
+
import { dirname, resolve } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
|
|
4
|
+
import { defineFeature } from '../define-feature.js';
|
|
5
|
+
|
|
6
|
+
const currentFilePath = fileURLToPath(import.meta.url);
|
|
7
|
+
const currentDirPath = dirname(currentFilePath);
|
|
8
|
+
|
|
9
|
+
export const autoprefixerFeature = defineFeature({
|
|
10
|
+
id: 'autoprefixer',
|
|
11
|
+
title: 'Autoprefixer',
|
|
12
|
+
hint: 'PostCSS vendor prefixes',
|
|
13
|
+
packageJson: {
|
|
14
|
+
devDependencies: {
|
|
15
|
+
autoprefixer: '^10.4.21',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
copyFiles: resolve(currentDirPath, 'files'),
|
|
19
19
|
});
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import { cp } from 'node:fs/promises';
|
|
2
|
-
|
|
3
|
-
import { patchPackageJson } from '../utils/package-json.js';
|
|
4
|
-
|
|
5
|
-
export function defineFeature({
|
|
6
|
-
id,
|
|
7
|
-
title,
|
|
8
|
-
hint,
|
|
9
|
-
packageJson,
|
|
10
|
-
apply,
|
|
11
|
-
copyFiles,
|
|
12
|
-
}) {
|
|
13
|
-
return {
|
|
14
|
-
id,
|
|
15
|
-
title,
|
|
16
|
-
hint,
|
|
17
|
-
async applyFeature(context) {
|
|
18
|
-
if (packageJson) {
|
|
19
|
-
await patchPackageJson(context.projectPath, packageJson);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (copyFiles) {
|
|
23
|
-
await cp(copyFiles, context.projectPath, {
|
|
24
|
-
recursive: true,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (apply) {
|
|
29
|
-
await apply(context);
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
};
|
|
1
|
+
import { cp } from 'node:fs/promises';
|
|
2
|
+
|
|
3
|
+
import { patchPackageJson } from '../utils/package-json.js';
|
|
4
|
+
|
|
5
|
+
export function defineFeature({
|
|
6
|
+
id,
|
|
7
|
+
title,
|
|
8
|
+
hint,
|
|
9
|
+
packageJson,
|
|
10
|
+
apply,
|
|
11
|
+
copyFiles,
|
|
12
|
+
}) {
|
|
13
|
+
return {
|
|
14
|
+
id,
|
|
15
|
+
title,
|
|
16
|
+
hint,
|
|
17
|
+
async applyFeature(context) {
|
|
18
|
+
if (packageJson) {
|
|
19
|
+
await patchPackageJson(context.projectPath, packageJson);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (copyFiles) {
|
|
23
|
+
await cp(copyFiles, context.projectPath, {
|
|
24
|
+
recursive: true,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (apply) {
|
|
29
|
+
await apply(context);
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
33
|
}
|