stackscan 0.1.6 → 0.1.9

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/dist/add.js CHANGED
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(add_exports);
36
36
  var import_fs_extra = __toESM(require("fs-extra"));
37
37
  var import_path = __toESM(require("path"));
38
38
  var import_chalk = __toESM(require("chalk"));
39
- var BASE_DIR = import_path.default.join(process.cwd(), "stackscan");
39
+ var BASE_DIR = import_path.default.join(process.cwd(), "public", "stackscan");
40
40
  async function add(sourcePath) {
41
41
  let absoluteSourcePath = import_path.default.resolve(sourcePath);
42
42
  if (!import_fs_extra.default.existsSync(absoluteSourcePath)) {
@@ -71,7 +71,7 @@ async function add(sourcePath) {
71
71
  import_fs_extra.default.mkdirSync(targetDir, { recursive: true });
72
72
  }
73
73
  import_fs_extra.default.copyFileSync(absoluteSourcePath, targetFile);
74
- console.log(import_chalk.default.green(`\u2705 Added project "${pkg.name}" to stackscan/${folderName}`));
74
+ console.log(import_chalk.default.green(`\u2705 Added project "${pkg.name}" to public/stackscan/${folderName}`));
75
75
  } catch (error) {
76
76
  console.error(import_chalk.default.red(`\u274C Error processing ${sourcePath}:`), error);
77
77
  process.exit(1);
package/dist/add.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  add
3
- } from "./chunk-IFEEO473.mjs";
3
+ } from "./chunk-ACCTMJVS.mjs";
4
4
  import "./chunk-EOKQCSHI.mjs";
5
5
  export {
6
6
  add
@@ -0,0 +1,158 @@
1
+ import {
2
+ techMap
3
+ } from "./chunk-LSUI3VI4.mjs";
4
+ import {
5
+ copyAssets,
6
+ generateMarkdown
7
+ } from "./chunk-UJM3S22V.mjs";
8
+ import {
9
+ simple_icons_hex_default
10
+ } from "./chunk-EH2SEQZP.mjs";
11
+
12
+ // src/scan.ts
13
+ import fs from "fs";
14
+ import path from "path";
15
+ var BASE_DIR = path.join(process.cwd(), "stackscan");
16
+ var SKIPPED_TECHS = [
17
+ "react-dom"
18
+ ];
19
+ async function scan(options = {}) {
20
+ console.log("\u{1F680} Starting Scan...");
21
+ if (options.color) {
22
+ console.log(`\u{1F3A8} Color mode: ${options.color}`);
23
+ }
24
+ if (!fs.existsSync(BASE_DIR)) {
25
+ console.log(`Creating stackscan directory at: ${BASE_DIR}`);
26
+ fs.mkdirSync(BASE_DIR, { recursive: true });
27
+ console.log('Please place your project folders inside "stackscan/" and run this command again.');
28
+ process.exit(0);
29
+ }
30
+ const entries = fs.readdirSync(BASE_DIR, { withFileTypes: true });
31
+ const projectDirs = entries.filter((dirent) => dirent.isDirectory() && dirent.name !== "input" && dirent.name !== "output");
32
+ if (projectDirs.length === 0) {
33
+ console.log('\u26A0\uFE0F No project directories found in "stackscan/".');
34
+ return;
35
+ }
36
+ console.log(`Found ${projectDirs.length} projects to process.
37
+ `);
38
+ const allProjects = [];
39
+ const allTechs = [];
40
+ for (const dir of projectDirs) {
41
+ const projectPath = path.join(BASE_DIR, dir.name);
42
+ const packageJsonPath = path.join(projectPath, "package.json");
43
+ if (fs.existsSync(packageJsonPath)) {
44
+ try {
45
+ const content = fs.readFileSync(packageJsonPath, "utf-8");
46
+ const pkg = JSON.parse(content);
47
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
48
+ const detectedTechs = [];
49
+ Object.keys(allDeps).forEach((dep) => {
50
+ if (SKIPPED_TECHS.includes(dep)) return;
51
+ if (techMap[dep]) {
52
+ const tech = techMap[dep];
53
+ let color = null;
54
+ if (options.color === "white") color = "#FFFFFF";
55
+ else if (options.color === "black") color = "#000000";
56
+ else if (options.color && options.color.startsWith("#")) color = options.color;
57
+ else {
58
+ const depSlug = dep.toLowerCase();
59
+ const nameSlug = tech.name.toLowerCase();
60
+ const nameSlugNoSpaces = tech.name.toLowerCase().replace(/\s+/g, "");
61
+ const hex = simple_icons_hex_default[depSlug] || simple_icons_hex_default[nameSlug] || simple_icons_hex_default[nameSlugNoSpaces];
62
+ if (hex) color = `#${hex}`;
63
+ }
64
+ detectedTechs.push({
65
+ name: tech.name,
66
+ slug: dep,
67
+ logo: tech.logo,
68
+ // Raw path for resolution
69
+ color
70
+ });
71
+ }
72
+ });
73
+ let uniqueTechs = Array.from(new Set(detectedTechs.map((t) => t.slug))).map((slug) => detectedTechs.find((t) => t.slug === slug));
74
+ const seenLogos = /* @__PURE__ */ new Set();
75
+ uniqueTechs = uniqueTechs.filter((t) => {
76
+ if (seenLogos.has(t.logo)) {
77
+ return false;
78
+ }
79
+ seenLogos.add(t.logo);
80
+ return true;
81
+ });
82
+ const assetsDir = path.join(process.cwd(), "public", "assets", "logos");
83
+ if (options.copyAssets !== false) {
84
+ await copyAssets(uniqueTechs, assetsDir, { colorMode: options.color });
85
+ }
86
+ const techsWithUrls = uniqueTechs.map((t) => ({
87
+ ...t,
88
+ logo: `https://raw.githubusercontent.com/benjamindotdev/stackscan/main/public/assets/logos/${t.logo}`,
89
+ relativePath: `./public/assets/logos/${t.logo}`
90
+ }));
91
+ allTechs.push(...techsWithUrls);
92
+ fs.writeFileSync(
93
+ path.join(projectPath, "stack.json"),
94
+ JSON.stringify(techsWithUrls, null, 2)
95
+ );
96
+ const mdContent = generateMarkdown(techsWithUrls);
97
+ fs.writeFileSync(path.join(projectPath, "stack.md"), mdContent);
98
+ allProjects.push({
99
+ name: dir.name,
100
+ techs: techsWithUrls
101
+ });
102
+ console.log(`\u2705 ${dir.name.padEnd(20)} -> stack.json (${uniqueTechs.length} techs)`);
103
+ } catch (err) {
104
+ console.error(`\u274C Error processing ${dir.name}:`, err.message);
105
+ }
106
+ } else {
107
+ console.warn(`\u26A0\uFE0F Skipping "${dir.name}": No package.json found.`);
108
+ }
109
+ }
110
+ if (allProjects.length > 0) {
111
+ updateRootReadme(allProjects);
112
+ }
113
+ console.log("\n\u2728 Sync complete.");
114
+ }
115
+ function updateRootReadme(projects) {
116
+ const readmePath = path.join(process.cwd(), "README.md");
117
+ if (!fs.existsSync(readmePath)) {
118
+ console.log("\u26A0\uFE0F No root README.md found to update.");
119
+ return;
120
+ }
121
+ let readmeContent = fs.readFileSync(readmePath, "utf-8");
122
+ const startMarker = "<!-- STACKSYNC_START -->";
123
+ const endMarker = "<!-- STACKSYNC_END -->";
124
+ let newSection = `${startMarker}
125
+ ## My Projects
126
+
127
+ `;
128
+ for (const p of projects) {
129
+ newSection += `### ${p.name}
130
+ `;
131
+ newSection += `<p>
132
+ `;
133
+ for (const t of p.techs) {
134
+ const src = t.relativePath || t.logo;
135
+ newSection += ` <img src="${src}" alt="${t.name}" height="25" style="margin-right: 10px;" />
136
+ `;
137
+ }
138
+ newSection += `</p>
139
+
140
+ `;
141
+ }
142
+ newSection += `${endMarker}`;
143
+ if (readmeContent.includes(startMarker) && readmeContent.includes(endMarker)) {
144
+ const regex = new RegExp(`${startMarker}[\\s\\S]*?${endMarker}`);
145
+ readmeContent = readmeContent.replace(regex, newSection);
146
+ console.log(`\u{1F4DD} Updated root README.md with ${projects.length} projects.`);
147
+ } else {
148
+ readmeContent += `
149
+
150
+ ${newSection}`;
151
+ console.log(`\u{1F4DD} Appended projects to root README.md.`);
152
+ }
153
+ fs.writeFileSync(readmePath, readmeContent);
154
+ }
155
+
156
+ export {
157
+ scan
158
+ };
@@ -0,0 +1,49 @@
1
+ // src/add.ts
2
+ import fs from "fs-extra";
3
+ import path from "path";
4
+ import chalk from "chalk";
5
+ var BASE_DIR = path.join(process.cwd(), "public", "stackscan");
6
+ async function add(sourcePath) {
7
+ let absoluteSourcePath = path.resolve(sourcePath);
8
+ if (!fs.existsSync(absoluteSourcePath)) {
9
+ console.error(chalk.red(`\u274C Path not found: ${sourcePath}`));
10
+ process.exit(1);
11
+ }
12
+ if (fs.statSync(absoluteSourcePath).isDirectory()) {
13
+ absoluteSourcePath = path.join(absoluteSourcePath, "package.json");
14
+ if (!fs.existsSync(absoluteSourcePath)) {
15
+ console.error(chalk.red(`\u274C No package.json found in directory: ${sourcePath}`));
16
+ process.exit(1);
17
+ }
18
+ }
19
+ try {
20
+ const content = fs.readFileSync(absoluteSourcePath, "utf-8");
21
+ const pkg = JSON.parse(content);
22
+ if (!pkg.name) {
23
+ console.error(chalk.red(`\u274C No "name" field found in ${sourcePath}`));
24
+ process.exit(1);
25
+ }
26
+ const baseFolderName = pkg.name.replace(/^@/, "").replace(/\//g, "-");
27
+ let folderName = baseFolderName;
28
+ let targetDir = path.join(BASE_DIR, folderName);
29
+ let counter = 1;
30
+ while (fs.existsSync(targetDir)) {
31
+ folderName = `${baseFolderName}-${counter}`;
32
+ targetDir = path.join(BASE_DIR, folderName);
33
+ counter++;
34
+ }
35
+ const targetFile = path.join(targetDir, "package.json");
36
+ if (!fs.existsSync(targetDir)) {
37
+ fs.mkdirSync(targetDir, { recursive: true });
38
+ }
39
+ fs.copyFileSync(absoluteSourcePath, targetFile);
40
+ console.log(chalk.green(`\u2705 Added project "${pkg.name}" to public/stackscan/${folderName}`));
41
+ } catch (error) {
42
+ console.error(chalk.red(`\u274C Error processing ${sourcePath}:`), error);
43
+ process.exit(1);
44
+ }
45
+ }
46
+
47
+ export {
48
+ add
49
+ };
@@ -0,0 +1,158 @@
1
+ import {
2
+ techMap
3
+ } from "./chunk-LSUI3VI4.mjs";
4
+ import {
5
+ copyAssets,
6
+ generateMarkdown
7
+ } from "./chunk-UJM3S22V.mjs";
8
+ import {
9
+ simple_icons_hex_default
10
+ } from "./chunk-EH2SEQZP.mjs";
11
+
12
+ // src/scan.ts
13
+ import fs from "fs";
14
+ import path from "path";
15
+ var BASE_DIR = path.join(process.cwd(), "public", "stackscan");
16
+ var SKIPPED_TECHS = [
17
+ "react-dom"
18
+ ];
19
+ async function scan(options = {}) {
20
+ console.log("\u{1F680} Starting Scan...");
21
+ if (options.color) {
22
+ console.log(`\u{1F3A8} Color mode: ${options.color}`);
23
+ }
24
+ if (!fs.existsSync(BASE_DIR)) {
25
+ console.log(`Creating stackscan directory at: ${BASE_DIR}`);
26
+ fs.mkdirSync(BASE_DIR, { recursive: true });
27
+ console.log('Please place your project folders inside "public/stackscan/" and run this command again.');
28
+ process.exit(0);
29
+ }
30
+ const entries = fs.readdirSync(BASE_DIR, { withFileTypes: true });
31
+ const projectDirs = entries.filter((dirent) => dirent.isDirectory() && dirent.name !== "input" && dirent.name !== "output");
32
+ if (projectDirs.length === 0) {
33
+ console.log('\u26A0\uFE0F No project directories found in "public/stackscan/".');
34
+ return;
35
+ }
36
+ console.log(`Found ${projectDirs.length} projects to process.
37
+ `);
38
+ const allProjects = [];
39
+ const allTechs = [];
40
+ for (const dir of projectDirs) {
41
+ const projectPath = path.join(BASE_DIR, dir.name);
42
+ const packageJsonPath = path.join(projectPath, "package.json");
43
+ if (fs.existsSync(packageJsonPath)) {
44
+ try {
45
+ const content = fs.readFileSync(packageJsonPath, "utf-8");
46
+ const pkg = JSON.parse(content);
47
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
48
+ const detectedTechs = [];
49
+ Object.keys(allDeps).forEach((dep) => {
50
+ if (SKIPPED_TECHS.includes(dep)) return;
51
+ if (techMap[dep]) {
52
+ const tech = techMap[dep];
53
+ let color = null;
54
+ if (options.color === "white") color = "#FFFFFF";
55
+ else if (options.color === "black") color = "#000000";
56
+ else if (options.color && options.color.startsWith("#")) color = options.color;
57
+ else {
58
+ const depSlug = dep.toLowerCase();
59
+ const nameSlug = tech.name.toLowerCase();
60
+ const nameSlugNoSpaces = tech.name.toLowerCase().replace(/\s+/g, "");
61
+ const hex = simple_icons_hex_default[depSlug] || simple_icons_hex_default[nameSlug] || simple_icons_hex_default[nameSlugNoSpaces];
62
+ if (hex) color = `#${hex}`;
63
+ }
64
+ detectedTechs.push({
65
+ name: tech.name,
66
+ slug: dep,
67
+ logo: tech.logo,
68
+ // Raw path for resolution
69
+ color
70
+ });
71
+ }
72
+ });
73
+ let uniqueTechs = Array.from(new Set(detectedTechs.map((t) => t.slug))).map((slug) => detectedTechs.find((t) => t.slug === slug));
74
+ const seenLogos = /* @__PURE__ */ new Set();
75
+ uniqueTechs = uniqueTechs.filter((t) => {
76
+ if (seenLogos.has(t.logo)) {
77
+ return false;
78
+ }
79
+ seenLogos.add(t.logo);
80
+ return true;
81
+ });
82
+ const assetsDir = path.join(process.cwd(), "public", "assets", "logos");
83
+ if (options.copyAssets !== false) {
84
+ await copyAssets(uniqueTechs, assetsDir, { colorMode: options.color });
85
+ }
86
+ const techsWithUrls = uniqueTechs.map((t) => ({
87
+ ...t,
88
+ logo: `https://raw.githubusercontent.com/benjamindotdev/stackscan/main/public/assets/logos/${t.logo}`,
89
+ relativePath: `./public/assets/logos/${t.logo}`
90
+ }));
91
+ allTechs.push(...techsWithUrls);
92
+ fs.writeFileSync(
93
+ path.join(projectPath, "stack.json"),
94
+ JSON.stringify(techsWithUrls, null, 2)
95
+ );
96
+ const mdContent = generateMarkdown(techsWithUrls);
97
+ fs.writeFileSync(path.join(projectPath, "stack.md"), mdContent);
98
+ allProjects.push({
99
+ name: dir.name,
100
+ techs: techsWithUrls
101
+ });
102
+ console.log(`\u2705 ${dir.name.padEnd(20)} -> stack.json (${uniqueTechs.length} techs)`);
103
+ } catch (err) {
104
+ console.error(`\u274C Error processing ${dir.name}:`, err.message);
105
+ }
106
+ } else {
107
+ console.warn(`\u26A0\uFE0F Skipping "${dir.name}": No package.json found.`);
108
+ }
109
+ }
110
+ if (allProjects.length > 0) {
111
+ updateRootReadme(allProjects);
112
+ }
113
+ console.log("\n\u2728 Sync complete.");
114
+ }
115
+ function updateRootReadme(projects) {
116
+ const readmePath = path.join(process.cwd(), "README.md");
117
+ if (!fs.existsSync(readmePath)) {
118
+ console.log("\u26A0\uFE0F No root README.md found to update.");
119
+ return;
120
+ }
121
+ let readmeContent = fs.readFileSync(readmePath, "utf-8");
122
+ const startMarker = "<!-- STACKSYNC_START -->";
123
+ const endMarker = "<!-- STACKSYNC_END -->";
124
+ let newSection = `${startMarker}
125
+ ## My Projects
126
+
127
+ `;
128
+ for (const p of projects) {
129
+ newSection += `### ${p.name}
130
+ `;
131
+ newSection += `<p>
132
+ `;
133
+ for (const t of p.techs) {
134
+ const src = t.relativePath || t.logo;
135
+ newSection += ` <img src="${src}" alt="${t.name}" height="25" style="margin-right: 10px;" />
136
+ `;
137
+ }
138
+ newSection += `</p>
139
+
140
+ `;
141
+ }
142
+ newSection += `${endMarker}`;
143
+ if (readmeContent.includes(startMarker) && readmeContent.includes(endMarker)) {
144
+ const regex = new RegExp(`${startMarker}[\\s\\S]*?${endMarker}`);
145
+ readmeContent = readmeContent.replace(regex, newSection);
146
+ console.log(`\u{1F4DD} Updated root README.md with ${projects.length} projects.`);
147
+ } else {
148
+ readmeContent += `
149
+
150
+ ${newSection}`;
151
+ console.log(`\u{1F4DD} Appended projects to root README.md.`);
152
+ }
153
+ fs.writeFileSync(readmePath, readmeContent);
154
+ }
155
+
156
+ export {
157
+ scan
158
+ };
@@ -0,0 +1,158 @@
1
+ import {
2
+ techMap
3
+ } from "./chunk-LSUI3VI4.mjs";
4
+ import {
5
+ copyAssets,
6
+ generateMarkdown
7
+ } from "./chunk-UJM3S22V.mjs";
8
+ import {
9
+ simple_icons_hex_default
10
+ } from "./chunk-EH2SEQZP.mjs";
11
+
12
+ // src/sync.ts
13
+ import fs from "fs";
14
+ import path from "path";
15
+ var BASE_DIR = path.join(process.cwd(), "stackscan");
16
+ var SKIPPED_TECHS = [
17
+ "react-dom"
18
+ ];
19
+ async function sync(options = {}) {
20
+ console.log("\u{1F680} Starting Sync...");
21
+ if (options.color) {
22
+ console.log(`\u{1F3A8} Color mode: ${options.color}`);
23
+ }
24
+ if (!fs.existsSync(BASE_DIR)) {
25
+ console.log(`Creating stackscan directory at: ${BASE_DIR}`);
26
+ fs.mkdirSync(BASE_DIR, { recursive: true });
27
+ console.log('Please place your project folders inside "stackscan/" and run this command again.');
28
+ process.exit(0);
29
+ }
30
+ const entries = fs.readdirSync(BASE_DIR, { withFileTypes: true });
31
+ const projectDirs = entries.filter((dirent) => dirent.isDirectory() && dirent.name !== "input" && dirent.name !== "output");
32
+ if (projectDirs.length === 0) {
33
+ console.log('\u26A0\uFE0F No project directories found in "stackscan/".');
34
+ return;
35
+ }
36
+ console.log(`Found ${projectDirs.length} projects to process.
37
+ `);
38
+ const allProjects = [];
39
+ const allTechs = [];
40
+ for (const dir of projectDirs) {
41
+ const projectPath = path.join(BASE_DIR, dir.name);
42
+ const packageJsonPath = path.join(projectPath, "package.json");
43
+ if (fs.existsSync(packageJsonPath)) {
44
+ try {
45
+ const content = fs.readFileSync(packageJsonPath, "utf-8");
46
+ const pkg = JSON.parse(content);
47
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
48
+ const detectedTechs = [];
49
+ Object.keys(allDeps).forEach((dep) => {
50
+ if (SKIPPED_TECHS.includes(dep)) return;
51
+ if (techMap[dep]) {
52
+ const tech = techMap[dep];
53
+ let color = null;
54
+ if (options.color === "white") color = "#FFFFFF";
55
+ else if (options.color === "black") color = "#000000";
56
+ else if (options.color && options.color.startsWith("#")) color = options.color;
57
+ else {
58
+ const depSlug = dep.toLowerCase();
59
+ const nameSlug = tech.name.toLowerCase();
60
+ const nameSlugNoSpaces = tech.name.toLowerCase().replace(/\s+/g, "");
61
+ const hex = simple_icons_hex_default[depSlug] || simple_icons_hex_default[nameSlug] || simple_icons_hex_default[nameSlugNoSpaces];
62
+ if (hex) color = `#${hex}`;
63
+ }
64
+ detectedTechs.push({
65
+ name: tech.name,
66
+ slug: dep,
67
+ logo: tech.logo,
68
+ // Raw path for resolution
69
+ color
70
+ });
71
+ }
72
+ });
73
+ let uniqueTechs = Array.from(new Set(detectedTechs.map((t) => t.slug))).map((slug) => detectedTechs.find((t) => t.slug === slug));
74
+ const seenLogos = /* @__PURE__ */ new Set();
75
+ uniqueTechs = uniqueTechs.filter((t) => {
76
+ if (seenLogos.has(t.logo)) {
77
+ return false;
78
+ }
79
+ seenLogos.add(t.logo);
80
+ return true;
81
+ });
82
+ const assetsDir = path.join(process.cwd(), "public", "assets", "logos");
83
+ if (options.copyAssets !== false) {
84
+ await copyAssets(uniqueTechs, assetsDir, { colorMode: options.color });
85
+ }
86
+ const techsWithUrls = uniqueTechs.map((t) => ({
87
+ ...t,
88
+ logo: `https://raw.githubusercontent.com/benjamindotdev/stackscan/main/public/assets/logos/${t.logo}`,
89
+ relativePath: `./public/assets/logos/${t.logo}`
90
+ }));
91
+ allTechs.push(...techsWithUrls);
92
+ fs.writeFileSync(
93
+ path.join(projectPath, "stack.json"),
94
+ JSON.stringify(techsWithUrls, null, 2)
95
+ );
96
+ const mdContent = generateMarkdown(techsWithUrls);
97
+ fs.writeFileSync(path.join(projectPath, "stack.md"), mdContent);
98
+ allProjects.push({
99
+ name: dir.name,
100
+ techs: techsWithUrls
101
+ });
102
+ console.log(`\u2705 ${dir.name.padEnd(20)} -> stack.json (${uniqueTechs.length} techs)`);
103
+ } catch (err) {
104
+ console.error(`\u274C Error processing ${dir.name}:`, err.message);
105
+ }
106
+ } else {
107
+ console.warn(`\u26A0\uFE0F Skipping "${dir.name}": No package.json found.`);
108
+ }
109
+ }
110
+ if (allProjects.length > 0) {
111
+ updateRootReadme(allProjects);
112
+ }
113
+ console.log("\n\u2728 Sync complete.");
114
+ }
115
+ function updateRootReadme(projects) {
116
+ const readmePath = path.join(process.cwd(), "README.md");
117
+ if (!fs.existsSync(readmePath)) {
118
+ console.log("\u26A0\uFE0F No root README.md found to update.");
119
+ return;
120
+ }
121
+ let readmeContent = fs.readFileSync(readmePath, "utf-8");
122
+ const startMarker = "<!-- STACKSYNC_START -->";
123
+ const endMarker = "<!-- STACKSYNC_END -->";
124
+ let newSection = `${startMarker}
125
+ ## My Projects
126
+
127
+ `;
128
+ for (const p of projects) {
129
+ newSection += `### ${p.name}
130
+ `;
131
+ newSection += `<p>
132
+ `;
133
+ for (const t of p.techs) {
134
+ const src = t.relativePath || t.logo;
135
+ newSection += ` <img src="${src}" alt="${t.name}" height="25" style="margin-right: 10px;" />
136
+ `;
137
+ }
138
+ newSection += `</p>
139
+
140
+ `;
141
+ }
142
+ newSection += `${endMarker}`;
143
+ if (readmeContent.includes(startMarker) && readmeContent.includes(endMarker)) {
144
+ const regex = new RegExp(`${startMarker}[\\s\\S]*?${endMarker}`);
145
+ readmeContent = readmeContent.replace(regex, newSection);
146
+ console.log(`\u{1F4DD} Updated root README.md with ${projects.length} projects.`);
147
+ } else {
148
+ readmeContent += `
149
+
150
+ ${newSection}`;
151
+ console.log(`\u{1F4DD} Appended projects to root README.md.`);
152
+ }
153
+ fs.writeFileSync(readmePath, readmeContent);
154
+ }
155
+
156
+ export {
157
+ sync
158
+ };