Skip to content

Commit e232266

Browse files
committed
2 parents 9149d59 + d8298e7 commit e232266

File tree

4 files changed

+175
-1
lines changed

4 files changed

+175
-1
lines changed

CODE_OF_CONDUCT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ representative at an online or offline event.
5959
## Enforcement
6060

6161
Instances of abusive, harassing, or otherwise unacceptable behavior may be
62-
reported to the community leaders responsible for enforcement at [YOUR_PROJECT_CONTACT_EMAIL].
62+
reported to the community leaders responsible for enforcement at {{CONTACT_EMAIL}}.
6363
_All complaints will be reviewed and investigated promptly and fairly_.
6464

6565
All community leaders are obligated to respect the privacy and security of the

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ npm test
3737
# Start building!
3838
```
3939

40+
## Getting Started with Your New Project
41+
42+
After creating a new repository from this template and cloning it to your local machine, run the setup script to personalize your project:
43+
44+
```bash
45+
npm install # if you haven't already
46+
npm run setup
47+
```
48+
49+
This script will guide you through updating the project name, author, and other details.
50+
4051
## Why Choose `js-quality-started`?
4152

4253
Tired of repetitive setup, inconsistent code, and integration headaches? See how `js-quality-started` provides a superior foundation compared to starting from scratch or using basic boilerplates.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"description": "{{PROJECT_DESCRIPTION}}",
55
"main": "src/index.js",
66
"scripts": {
7+
"setup": "node setup.js",
78
"test": "jest",
89
"lint": "eslint .",
910
"lint:fix": "eslint . --fix",

setup.js

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// setup.js
2+
3+
const readline = require('readline');
4+
const fs = require('fs');
5+
const path = require('path');
6+
7+
// Configure readline interface for user input
8+
const rl = readline.createInterface({
9+
input: process.stdin,
10+
output: process.stdout
11+
});
12+
13+
// List of files that need to be modified by the script
14+
const filesToModify = [
15+
'project.json',
16+
'CONTRIBUTING.md',
17+
'LICENSE',
18+
'CODE_OF_CONDUCT.md',
19+
'README.md'
20+
];
21+
22+
/**
23+
* Prompts the user with a question and returns their answer.
24+
* @param {string} query The question to ask the user.
25+
* @returns {Promise<string>} A promise that resolves with the user's answer.
26+
*/
27+
function askQuestion(query) {
28+
return new Promise(resolve => rl.question(query, resolve));
29+
}
30+
31+
/**
32+
* Collects all necessary inputs from the user.
33+
* @returns {Promise<Object>} An object containing all user inputs.
34+
*/
35+
async function getUserInputs() {
36+
console.log('\n--- Project Setup ---');
37+
console.log('Let\'s personalize your new repository.');
38+
console.log('Please provide the following information:');
39+
40+
const inputs = {};
41+
42+
inputs.projectName = await askQuestion('1. Enter the name for your new project (e.g., my-awesome-app): ');
43+
inputs.projectDescription = await askQuestion('2. Enter a short description for your project: ');
44+
inputs.projectKeywords = await askQuestion('3. Enter keywords for your project, separated by commas (e.g., javascript, web, utility): ');
45+
inputs.authorName = await askQuestion('4. Enter the author\'s name (e.g., John Doe or My Company Inc.): ');
46+
inputs.contactEmail = await askQuestion('5. Enter a contact email for your project (e.g., contact@yourproject.com): ');
47+
48+
const currentYear = new Date().getFullYear();
49+
inputs.licenseYear = (await askQuestion(`6. Enter the copyright year (default: ${currentYear}): `)) || currentYear.toString(); // Ensure string for replacement
50+
51+
inputs.githubUsername = await askQuestion('7. Enter your GitHub username or organization name (e.g., octocat): ');
52+
inputs.codecovToken = await askQuestion('8. Enter your Codecov token (optional, leave blank if not using): ');
53+
54+
rl.close(); // Close the readline interface after all questions are asked
55+
return inputs;
56+
}
57+
58+
/**
59+
* Processes each file, replacing placeholders with user inputs.
60+
* @param {Object} inputs An object containing all user inputs.
61+
*/
62+
async function processFiles(inputs) {
63+
for (const file of filesToModify) {
64+
const filePath = path.join(process.cwd(), file); // Assumes script is run from repo root
65+
console.log(`\nProcessing ${file}...`);
66+
67+
try {
68+
let content = fs.readFileSync(filePath, 'utf8');
69+
70+
// --- Generic Replacements (order matters if placeholders overlap) ---
71+
content = content.replace(new RegExp('{{PROJECT_NAME}}', 'g'), inputs.projectName);
72+
content = content.replace(new RegExp('{{PROJECT_DESCRIPTION}}', 'g'), inputs.projectDescription);
73+
content = content.replace(new RegExp('{{AUTHOR_NAME}}', 'g'), inputs.authorName);
74+
content = content.replace(new RegExp('{{CONTACT_EMAIL}}', 'g'), inputs.contactEmail);
75+
content = content.replace(new RegExp('{{LICENSE_YEAR}}', 'g'), inputs.licenseYear);
76+
content = content.replace(new RegExp('{{GITHUB_USERNAME}}', 'g'), inputs.githubUsername);
77+
// Handle optional Codecov token
78+
content = content.replace(new RegExp('{{CODECOV_TOKEN}}', 'g'), inputs.codecovToken || '');
79+
80+
81+
// --- Specific handling for project.json ---
82+
if (file === 'project.json') {
83+
let projectJson = JSON.parse(content);
84+
85+
// Update specific fields that might have been generically replaced but need JSON structure
86+
projectJson.name = inputs.projectName;
87+
projectJson.description = inputs.projectDescription;
88+
projectJson.author = inputs.authorName;
89+
90+
// Handle keywords array: convert comma-separated string to array
91+
if (inputs.projectKeywords) {
92+
projectJson.keywords = inputs.projectKeywords.split(',').map(kw => kw.trim()).filter(kw => kw.length > 0);
93+
} else {
94+
projectJson.keywords = []; // Set to empty array if no keywords provided
95+
}
96+
97+
content = JSON.stringify(projectJson, null, 2); // Pretty print JSON with 2 spaces
98+
}
99+
100+
// --- Specific handling for README.md ---
101+
if (file === 'README.md') {
102+
// Correct the LICENSE link from LICENSE.md to LICENSE
103+
content = content.replace(/\[LICENSE\]\(LICENSE\.md\)/g, '[LICENSE](LICENSE)');
104+
105+
// Update the 'Post-Template Setup' section
106+
// This regex captures the section content up to the next '##' heading or end of file
107+
const postTemplateSetupRegex = /(## Post-Template Setup[\s\S]*?)(?=##|$)/;
108+
const newPostTemplateSetupContent = `## Post-Template Setup\n\nAfter creating your repository from this template, you've successfully run this setup script to personalize your project. You're ready to start building!\n\n*(This section was updated by the setup script.)*`;
109+
110+
if (content.match(postTemplateSetupRegex)) {
111+
content = content.replace(postTemplateSetupRegex, newPostTemplateSetupContent);
112+
} else {
113+
// If the section isn't found (e.g., file was heavily modified), append it
114+
console.warn('Warning: "Post-Template Setup" section not found in README.md. Appending new content.');
115+
content += `\n${newPostTemplateSetupContent}`;
116+
}
117+
}
118+
119+
fs.writeFileSync(filePath, content, 'utf8');
120+
console.log(`Successfully updated ${file}.`);
121+
122+
} catch (error) {
123+
console.error(`Error processing ${file}: ${error.message}`);
124+
if (file === 'project.json' && error instanceof SyntaxError) {
125+
console.error('Make sure project.json is valid JSON before running the script.');
126+
}
127+
}
128+
}
129+
}
130+
131+
/**
132+
* Main function to run the setup script.
133+
*/
134+
async function runSetup() {
135+
try {
136+
const inputs = await getUserInputs();
137+
await processFiles(inputs);
138+
139+
console.log('\n--- Setup Complete! ---');
140+
console.log('Your repository has been successfully personalized.');
141+
console.log('Here are some quick reminders:');
142+
console.log(`- Project Name: ${inputs.projectName}`);
143+
console.log(`- Author: ${inputs.authorName}`);
144+
console.log(`- GitHub Repository: https://github.com/${inputs.githubUsername}/${inputs.projectName}`);
145+
if (inputs.codecovToken) {
146+
console.log(`- Remember to add your Codecov token as a secret named 'CODECOV_TOKEN' in your GitHub repository settings for CI integration.`);
147+
}
148+
console.log('\n- Please review the modified files to ensure everything looks correct and fine-tune as needed.');
149+
console.log('- Don\'t forget to initialize your Git repository if you haven\'t already!');
150+
console.log('\nHappy coding!');
151+
} catch (error) {
152+
console.error('\nAn unexpected error occurred during setup:', error);
153+
process.exit(1); // Exit with an error code
154+
} finally {
155+
if (!rl.closed) {
156+
rl.close(); // Ensure readline interface is closed even on error
157+
}
158+
}
159+
}
160+
161+
// Execute the setup script
162+
runSetup();

0 commit comments

Comments
 (0)