aboutsummaryrefslogtreecommitdiff
path: root/packages/create-astro/src/actions/shared.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/create-astro/src/actions/shared.ts')
-rw-r--r--packages/create-astro/src/actions/shared.ts59
1 files changed, 59 insertions, 0 deletions
diff --git a/packages/create-astro/src/actions/shared.ts b/packages/create-astro/src/actions/shared.ts
new file mode 100644
index 000000000..da19677d0
--- /dev/null
+++ b/packages/create-astro/src/actions/shared.ts
@@ -0,0 +1,59 @@
+import fs from 'node:fs';
+
+// Some existing files and directories can be safely ignored when checking if a directory is a valid project directory.
+// https://github.com/facebook/create-react-app/blob/d960b9e38c062584ff6cfb1a70e1512509a966e7/packages/create-react-app/createReactApp.js#L907-L934
+const VALID_PROJECT_DIRECTORY_SAFE_LIST = [
+ '.DS_Store',
+ '.git',
+ '.gitkeep',
+ '.gitattributes',
+ '.gitignore',
+ '.gitlab-ci.yml',
+ '.hg',
+ '.hgcheck',
+ '.hgignore',
+ '.idea',
+ '.npmignore',
+ '.travis.yml',
+ '.yarn',
+ '.yarnrc.yml',
+ 'docs',
+ 'LICENSE',
+ 'mkdocs.yml',
+ 'Thumbs.db',
+ /\.iml$/,
+ /^npm-debug\.log/,
+ /^yarn-debug\.log/,
+ /^yarn-error\.log/,
+];
+
+export function isEmpty(dirPath: string) {
+ if (!fs.existsSync(dirPath)) {
+ return true;
+ }
+
+ const conflicts = fs.readdirSync(dirPath).filter((content) => {
+ return !VALID_PROJECT_DIRECTORY_SAFE_LIST.some((safeContent) => {
+ return typeof safeContent === 'string' ? content === safeContent : safeContent.test(content);
+ });
+ });
+
+ return conflicts.length === 0;
+}
+
+function isValidName(projectName: string) {
+ return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(projectName);
+}
+
+export function toValidName(projectName: string) {
+ if (isValidName(projectName)) return projectName;
+
+ return projectName
+ .trim()
+ .toLowerCase()
+ .replace(/\s+/g, '-')
+ .replace(/^[._]/, '')
+ .replace(/[^a-z\d\-~]+/g, '-')
+ .replace(/^-+/, '')
+ .replace(/-+$/, '');
+}