projex-cli 0.2.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.
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +321 -0
- package/dist/cli.js.map +1 -0
- package/dist/event-bus.d.ts +35 -0
- package/dist/event-bus.d.ts.map +1 -0
- package/dist/event-bus.js +71 -0
- package/dist/event-bus.js.map +1 -0
- package/dist/events/event-bus.d.ts +35 -0
- package/dist/events/event-bus.d.ts.map +1 -0
- package/dist/events/event-bus.js +71 -0
- package/dist/events/event-bus.js.map +1 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +3 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/types.d.ts +143 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +6 -0
- package/dist/events/types.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/inference/enricher.d.ts +18 -0
- package/dist/inference/enricher.d.ts.map +1 -0
- package/dist/inference/enricher.js +290 -0
- package/dist/inference/enricher.js.map +1 -0
- package/dist/inference/index.d.ts +5 -0
- package/dist/inference/index.d.ts.map +1 -0
- package/dist/inference/index.js +5 -0
- package/dist/inference/index.js.map +1 -0
- package/dist/inference/lifecycle-tracker.d.ts +40 -0
- package/dist/inference/lifecycle-tracker.d.ts.map +1 -0
- package/dist/inference/lifecycle-tracker.js +132 -0
- package/dist/inference/lifecycle-tracker.js.map +1 -0
- package/dist/inference/portfolio-generator.d.ts +44 -0
- package/dist/inference/portfolio-generator.d.ts.map +1 -0
- package/dist/inference/portfolio-generator.js +239 -0
- package/dist/inference/portfolio-generator.js.map +1 -0
- package/dist/inference/project-detector.d.ts +17 -0
- package/dist/inference/project-detector.d.ts.map +1 -0
- package/dist/inference/project-detector.js +127 -0
- package/dist/inference/project-detector.js.map +1 -0
- package/dist/ingestion/github-client.d.ts +56 -0
- package/dist/ingestion/github-client.d.ts.map +1 -0
- package/dist/ingestion/github-client.js +213 -0
- package/dist/ingestion/github-client.js.map +1 -0
- package/dist/ingestion/github-poller.d.ts +41 -0
- package/dist/ingestion/github-poller.d.ts.map +1 -0
- package/dist/ingestion/github-poller.js +121 -0
- package/dist/ingestion/github-poller.js.map +1 -0
- package/dist/ingestion/normalizer.d.ts +41 -0
- package/dist/ingestion/normalizer.d.ts.map +1 -0
- package/dist/ingestion/normalizer.js +173 -0
- package/dist/ingestion/normalizer.js.map +1 -0
- package/dist/integrations/analyzer.d.ts +74 -0
- package/dist/integrations/analyzer.d.ts.map +1 -0
- package/dist/integrations/analyzer.js +287 -0
- package/dist/integrations/analyzer.js.map +1 -0
- package/dist/integrations/index.d.ts +4 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +5 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/injectors.d.ts +60 -0
- package/dist/integrations/injectors.d.ts.map +1 -0
- package/dist/integrations/injectors.js +361 -0
- package/dist/integrations/injectors.js.map +1 -0
- package/dist/integrations/template-generator.d.ts +45 -0
- package/dist/integrations/template-generator.d.ts.map +1 -0
- package/dist/integrations/template-generator.js +187 -0
- package/dist/integrations/template-generator.js.map +1 -0
- package/dist/storage/index.d.ts +2 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +2 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/project-store.d.ts +23 -0
- package/dist/storage/project-store.d.ts.map +1 -0
- package/dist/storage/project-store.js +107 -0
- package/dist/storage/project-store.js.map +1 -0
- package/dist/types.d.ts +143 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portfolio Injectors - Insert generated project cards into portfolio files
|
|
3
|
+
* Supports: HTML, Markdown, React/JSX
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
6
|
+
import { dirname, join } from 'path';
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
/**
|
|
9
|
+
* Base class for portfolio injectors
|
|
10
|
+
*/
|
|
11
|
+
class BaseInjector {
|
|
12
|
+
portfolioPath;
|
|
13
|
+
analysis;
|
|
14
|
+
options;
|
|
15
|
+
constructor(portfolioPath, analysis, options) {
|
|
16
|
+
this.portfolioPath = portfolioPath;
|
|
17
|
+
this.analysis = analysis;
|
|
18
|
+
this.options = options;
|
|
19
|
+
}
|
|
20
|
+
backup(filePath) {
|
|
21
|
+
if (!this.options.createBackup)
|
|
22
|
+
return undefined;
|
|
23
|
+
const backupPath = `${filePath}.backup.${Date.now()}`;
|
|
24
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
25
|
+
writeFileSync(backupPath, content);
|
|
26
|
+
return backupPath;
|
|
27
|
+
}
|
|
28
|
+
gitCommit(files, message) {
|
|
29
|
+
if (!this.options.autoCommit)
|
|
30
|
+
return;
|
|
31
|
+
try {
|
|
32
|
+
for (const file of files) {
|
|
33
|
+
execSync(`git add "${file}"`, { cwd: this.portfolioPath });
|
|
34
|
+
}
|
|
35
|
+
execSync(`git commit -m "${message}"`, { cwd: this.portfolioPath });
|
|
36
|
+
console.log(`[Injector] Committed: ${message}`);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error('[Injector] Git commit failed:', error);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* HTML Portfolio Injector
|
|
45
|
+
*/
|
|
46
|
+
export class HTMLInjector extends BaseInjector {
|
|
47
|
+
async inject(card, projectId) {
|
|
48
|
+
const targetFile = this.findTargetFile();
|
|
49
|
+
if (!targetFile) {
|
|
50
|
+
return {
|
|
51
|
+
success: false,
|
|
52
|
+
file: '',
|
|
53
|
+
message: 'Could not find projects section in HTML files',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const filePath = join(this.portfolioPath, targetFile);
|
|
57
|
+
const backup = this.backup(filePath);
|
|
58
|
+
try {
|
|
59
|
+
let content = readFileSync(filePath, 'utf-8');
|
|
60
|
+
// Find the projects container
|
|
61
|
+
const selector = this.analysis.projectSelector || '.projects';
|
|
62
|
+
const containerPattern = this.findContainerPattern(content, selector);
|
|
63
|
+
if (!containerPattern) {
|
|
64
|
+
return {
|
|
65
|
+
success: false,
|
|
66
|
+
file: targetFile,
|
|
67
|
+
message: `Could not find container matching "${selector}"`,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// Insert the new card
|
|
71
|
+
content = this.insertCard(content, containerPattern, card.html, projectId);
|
|
72
|
+
writeFileSync(filePath, content);
|
|
73
|
+
const commitMsg = this.options.commitMessage || `feat: add project ${projectId}`;
|
|
74
|
+
this.gitCommit([filePath], commitMsg);
|
|
75
|
+
return {
|
|
76
|
+
success: true,
|
|
77
|
+
file: targetFile,
|
|
78
|
+
message: 'Project card injected successfully',
|
|
79
|
+
backup,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
return {
|
|
84
|
+
success: false,
|
|
85
|
+
file: targetFile,
|
|
86
|
+
message: `Injection failed: ${error}`,
|
|
87
|
+
backup,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
findTargetFile() {
|
|
92
|
+
const candidates = ['index.html', 'projects.html', 'portfolio.html', 'work.html'];
|
|
93
|
+
for (const file of candidates) {
|
|
94
|
+
const filePath = join(this.portfolioPath, file);
|
|
95
|
+
if (existsSync(filePath)) {
|
|
96
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
97
|
+
if (/project|portfolio|work/i.test(content)) {
|
|
98
|
+
return file;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return candidates.find(f => existsSync(join(this.portfolioPath, f))) || null;
|
|
103
|
+
}
|
|
104
|
+
findContainerPattern(content, selector) {
|
|
105
|
+
const className = selector.replace('.', '').replace('#', '');
|
|
106
|
+
// Find opening tag with the class/id
|
|
107
|
+
const patterns = [
|
|
108
|
+
new RegExp(`<(div|section|main)[^>]*(?:class|id)=["'][^"']*${className}[^"']*["'][^>]*>`, 'i'),
|
|
109
|
+
new RegExp(`<(div|section|main)[^>]*(?:class|id)="${className}"[^>]*>`, 'i'),
|
|
110
|
+
];
|
|
111
|
+
for (const pattern of patterns) {
|
|
112
|
+
const match = content.match(pattern);
|
|
113
|
+
if (match && match.index !== undefined) {
|
|
114
|
+
const start = match.index + match[0].length;
|
|
115
|
+
// Find the closing tag
|
|
116
|
+
const tagName = match[1];
|
|
117
|
+
const closePattern = new RegExp(`</${tagName}>`, 'gi');
|
|
118
|
+
let depth = 1;
|
|
119
|
+
let pos = start;
|
|
120
|
+
while (depth > 0 && pos < content.length) {
|
|
121
|
+
const openMatch = content.slice(pos).match(new RegExp(`<${tagName}[^>]*>`, 'i'));
|
|
122
|
+
const closeMatch = content.slice(pos).match(closePattern);
|
|
123
|
+
if (!closeMatch)
|
|
124
|
+
break;
|
|
125
|
+
const openPos = openMatch ? openMatch.index : Infinity;
|
|
126
|
+
const closePos = closeMatch.index;
|
|
127
|
+
if (openPos < closePos) {
|
|
128
|
+
depth++;
|
|
129
|
+
pos += openPos + openMatch[0].length;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
depth--;
|
|
133
|
+
if (depth === 0) {
|
|
134
|
+
return { start, end: pos + closePos };
|
|
135
|
+
}
|
|
136
|
+
pos += closePos + closeMatch[0].length;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
insertCard(content, container, cardHtml, projectId) {
|
|
144
|
+
const indent = this.detectIndent(content, container.start);
|
|
145
|
+
const indentedCard = cardHtml
|
|
146
|
+
.split('\n')
|
|
147
|
+
.map((line, i) => i === 0 ? line : indent + line)
|
|
148
|
+
.join('\n');
|
|
149
|
+
// Insert before the closing tag
|
|
150
|
+
const before = content.slice(0, container.end);
|
|
151
|
+
const after = content.slice(container.end);
|
|
152
|
+
return `${before}\n${indent}<!-- projex:${projectId} -->\n${indent}${indentedCard}\n${indent}<!-- /projex:${projectId} -->\n${after}`;
|
|
153
|
+
}
|
|
154
|
+
detectIndent(content, position) {
|
|
155
|
+
const lineStart = content.lastIndexOf('\n', position) + 1;
|
|
156
|
+
const match = content.slice(lineStart, position).match(/^(\s*)/);
|
|
157
|
+
return match ? match[1] + ' ' : ' ';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Markdown Portfolio Injector
|
|
162
|
+
*/
|
|
163
|
+
export class MarkdownInjector extends BaseInjector {
|
|
164
|
+
async inject(card, projectId) {
|
|
165
|
+
const targetFile = this.findTargetFile();
|
|
166
|
+
if (!targetFile) {
|
|
167
|
+
return {
|
|
168
|
+
success: false,
|
|
169
|
+
file: '',
|
|
170
|
+
message: 'Could not find projects section in Markdown files',
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
const filePath = join(this.portfolioPath, targetFile);
|
|
174
|
+
const backup = this.backup(filePath);
|
|
175
|
+
try {
|
|
176
|
+
let content = readFileSync(filePath, 'utf-8');
|
|
177
|
+
// Find the projects section (## Projects, ## Work, etc.)
|
|
178
|
+
const sectionMatch = content.match(/^(##?\s*(?:Projects|Portfolio|Work|My Work)[^\n]*)/mi);
|
|
179
|
+
if (sectionMatch && sectionMatch.index !== undefined) {
|
|
180
|
+
// Find the next section or end of file
|
|
181
|
+
const sectionStart = sectionMatch.index + sectionMatch[0].length;
|
|
182
|
+
const nextSection = content.slice(sectionStart).search(/\n##?\s+[A-Z]/);
|
|
183
|
+
const insertPos = nextSection === -1
|
|
184
|
+
? content.length
|
|
185
|
+
: sectionStart + nextSection;
|
|
186
|
+
// Insert the card
|
|
187
|
+
const markedCard = `\n<!-- projex:${projectId} -->\n${card.markdown}\n<!-- /projex:${projectId} -->\n`;
|
|
188
|
+
content = content.slice(0, insertPos) + markedCard + content.slice(insertPos);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
// Append to end
|
|
192
|
+
content += `\n\n## Projects\n\n<!-- projex:${projectId} -->\n${card.markdown}\n<!-- /projex:${projectId} -->\n`;
|
|
193
|
+
}
|
|
194
|
+
writeFileSync(filePath, content);
|
|
195
|
+
const commitMsg = this.options.commitMessage || `feat: add project ${projectId}`;
|
|
196
|
+
this.gitCommit([filePath], commitMsg);
|
|
197
|
+
return {
|
|
198
|
+
success: true,
|
|
199
|
+
file: targetFile,
|
|
200
|
+
message: 'Project card injected successfully',
|
|
201
|
+
backup,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
return {
|
|
206
|
+
success: false,
|
|
207
|
+
file: targetFile,
|
|
208
|
+
message: `Injection failed: ${error}`,
|
|
209
|
+
backup,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
findTargetFile() {
|
|
214
|
+
const candidates = [
|
|
215
|
+
'README.md',
|
|
216
|
+
'index.md',
|
|
217
|
+
'projects.md',
|
|
218
|
+
'portfolio.md',
|
|
219
|
+
'_pages/projects.md',
|
|
220
|
+
'content/projects.md',
|
|
221
|
+
];
|
|
222
|
+
for (const file of candidates) {
|
|
223
|
+
const filePath = join(this.portfolioPath, file);
|
|
224
|
+
if (existsSync(filePath)) {
|
|
225
|
+
return file;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* React/JSX Portfolio Injector
|
|
233
|
+
*/
|
|
234
|
+
export class ReactInjector extends BaseInjector {
|
|
235
|
+
async inject(card, projectId) {
|
|
236
|
+
// For React, we update a data file rather than injecting JSX directly
|
|
237
|
+
const dataFile = this.findOrCreateDataFile();
|
|
238
|
+
const filePath = join(this.portfolioPath, dataFile);
|
|
239
|
+
const backup = existsSync(filePath) ? this.backup(filePath) : undefined;
|
|
240
|
+
try {
|
|
241
|
+
let projects = [];
|
|
242
|
+
if (existsSync(filePath)) {
|
|
243
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
244
|
+
// Parse existing projects
|
|
245
|
+
const match = content.match(/export\s+(?:const|let)\s+projects\s*=\s*(\[[\s\S]*?\]);/);
|
|
246
|
+
if (match) {
|
|
247
|
+
try {
|
|
248
|
+
// Simple JSON-like parsing (won't work for complex expressions)
|
|
249
|
+
projects = JSON.parse(match[1].replace(/'/g, '"'));
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
projects = [];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// Add new project
|
|
257
|
+
const newProject = {
|
|
258
|
+
id: projectId,
|
|
259
|
+
...this.parseCardToObject(card),
|
|
260
|
+
};
|
|
261
|
+
// Check if already exists
|
|
262
|
+
const existingIndex = projects.findIndex((p) => p.id === projectId);
|
|
263
|
+
if (existingIndex >= 0) {
|
|
264
|
+
projects[existingIndex] = newProject;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
projects.push(newProject);
|
|
268
|
+
}
|
|
269
|
+
// Write data file
|
|
270
|
+
const content = `// Auto-generated by Projex
|
|
271
|
+
export const projects = ${JSON.stringify(projects, null, 2)};
|
|
272
|
+
`;
|
|
273
|
+
writeFileSync(filePath, content);
|
|
274
|
+
const commitMsg = this.options.commitMessage || `feat: add project ${projectId}`;
|
|
275
|
+
this.gitCommit([filePath], commitMsg);
|
|
276
|
+
return {
|
|
277
|
+
success: true,
|
|
278
|
+
file: dataFile,
|
|
279
|
+
message: 'Project data updated successfully',
|
|
280
|
+
backup,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
return {
|
|
285
|
+
success: false,
|
|
286
|
+
file: dataFile,
|
|
287
|
+
message: `Injection failed: ${error}`,
|
|
288
|
+
backup,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
findOrCreateDataFile() {
|
|
293
|
+
const candidates = [
|
|
294
|
+
'src/data/projects.ts',
|
|
295
|
+
'src/data/projects.js',
|
|
296
|
+
'data/projects.ts',
|
|
297
|
+
'data/projects.js',
|
|
298
|
+
'src/lib/projects.ts',
|
|
299
|
+
'lib/projects.ts',
|
|
300
|
+
];
|
|
301
|
+
for (const file of candidates) {
|
|
302
|
+
if (existsSync(join(this.portfolioPath, file))) {
|
|
303
|
+
return file;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// Create new data file
|
|
307
|
+
const newFile = 'src/data/projects.ts';
|
|
308
|
+
const dir = dirname(join(this.portfolioPath, newFile));
|
|
309
|
+
if (!existsSync(dir)) {
|
|
310
|
+
mkdirSync(dir, { recursive: true });
|
|
311
|
+
}
|
|
312
|
+
return newFile;
|
|
313
|
+
}
|
|
314
|
+
parseCardToObject(card) {
|
|
315
|
+
// Extract props from JSX string
|
|
316
|
+
const props = {};
|
|
317
|
+
const patterns = [
|
|
318
|
+
{ key: 'title', pattern: /title="([^"]+)"/ },
|
|
319
|
+
{ key: 'tagline', pattern: /tagline="([^"]+)"/ },
|
|
320
|
+
{ key: 'description', pattern: /description="([^"]+)"/ },
|
|
321
|
+
{ key: 'githubUrl', pattern: /githubUrl="([^"]+)"/ },
|
|
322
|
+
{ key: 'liveUrl', pattern: /liveUrl="([^"]+)"/ },
|
|
323
|
+
];
|
|
324
|
+
for (const { key, pattern } of patterns) {
|
|
325
|
+
const match = card.react.match(pattern);
|
|
326
|
+
if (match) {
|
|
327
|
+
props[key] = match[1];
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
// Extract techStack array
|
|
331
|
+
const techMatch = card.react.match(/techStack=\{(\[[^\]]+\])\}/);
|
|
332
|
+
if (techMatch) {
|
|
333
|
+
try {
|
|
334
|
+
props.techStack = JSON.parse(techMatch[1]);
|
|
335
|
+
}
|
|
336
|
+
catch {
|
|
337
|
+
props.techStack = [];
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return props;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Factory function to create the appropriate injector
|
|
345
|
+
*/
|
|
346
|
+
export function createInjector(portfolioPath, analysis, options) {
|
|
347
|
+
switch (analysis.type) {
|
|
348
|
+
case 'react':
|
|
349
|
+
case 'nextjs':
|
|
350
|
+
case 'gatsby':
|
|
351
|
+
return new ReactInjector(portfolioPath, analysis, options);
|
|
352
|
+
case 'jekyll':
|
|
353
|
+
case 'hugo':
|
|
354
|
+
case 'markdown':
|
|
355
|
+
return new MarkdownInjector(portfolioPath, analysis, options);
|
|
356
|
+
case 'html':
|
|
357
|
+
default:
|
|
358
|
+
return new HTMLInjector(portfolioPath, analysis, options);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=injectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"injectors.js","sourceRoot":"","sources":["../../src/integrations/injectors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template Generator - Creates project cards matching the detected portfolio style
|
|
3
|
+
*/
|
|
4
|
+
import type { Project } from '../events/types.js';
|
|
5
|
+
import type { PortfolioAnalysis } from './analyzer.js';
|
|
6
|
+
export interface GeneratedCard {
|
|
7
|
+
html: string;
|
|
8
|
+
markdown: string;
|
|
9
|
+
react: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class TemplateGenerator {
|
|
12
|
+
private analysis;
|
|
13
|
+
constructor(analysis: PortfolioAnalysis);
|
|
14
|
+
/**
|
|
15
|
+
* Generate a project card in all formats
|
|
16
|
+
*/
|
|
17
|
+
generate(project: Project): GeneratedCard;
|
|
18
|
+
/**
|
|
19
|
+
* Generate HTML card matching detected template
|
|
20
|
+
*/
|
|
21
|
+
private generateHTML;
|
|
22
|
+
/**
|
|
23
|
+
* Fill detected template with project data
|
|
24
|
+
*/
|
|
25
|
+
private fillTemplate;
|
|
26
|
+
/**
|
|
27
|
+
* Generate default HTML card with detected styles
|
|
28
|
+
*/
|
|
29
|
+
private generateDefaultHTML;
|
|
30
|
+
/**
|
|
31
|
+
* Generate Markdown card
|
|
32
|
+
*/
|
|
33
|
+
private generateMarkdown;
|
|
34
|
+
/**
|
|
35
|
+
* Generate React/JSX component
|
|
36
|
+
*/
|
|
37
|
+
private generateReact;
|
|
38
|
+
/**
|
|
39
|
+
* Generate a generic ProjectCard component definition
|
|
40
|
+
*/
|
|
41
|
+
generateProjectCardComponent(): string;
|
|
42
|
+
private escapeRegex;
|
|
43
|
+
private escapeJSX;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=template-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-generator.d.ts","sourceRoot":"","sources":["../../src/integrations/template-generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAkB,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAgB,MAAM,eAAe,CAAC;AAErE,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,QAAQ,CAAoB;gBAExB,QAAQ,EAAE,iBAAiB;IAIvC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa;IAazC;;OAEG;IACH,OAAO,CAAC,YAAY;IAYpB;;OAEG;IACH,OAAO,CAAC,YAAY;IA6CpB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA0B3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAoBxB;;OAEG;IACH,OAAO,CAAC,aAAa;IAarB;;OAEG;IACH,4BAA4B,IAAI,MAAM;IAyCtC,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,SAAS;CAMpB"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template Generator - Creates project cards matching the detected portfolio style
|
|
3
|
+
*/
|
|
4
|
+
export class TemplateGenerator {
|
|
5
|
+
analysis;
|
|
6
|
+
constructor(analysis) {
|
|
7
|
+
this.analysis = analysis;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generate a project card in all formats
|
|
11
|
+
*/
|
|
12
|
+
generate(project) {
|
|
13
|
+
const draft = project.portfolioDraft;
|
|
14
|
+
if (!draft) {
|
|
15
|
+
throw new Error(`Project ${project.id} has no portfolio draft`);
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
html: this.generateHTML(project, draft),
|
|
19
|
+
markdown: this.generateMarkdown(project, draft),
|
|
20
|
+
react: this.generateReact(project, draft),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Generate HTML card matching detected template
|
|
25
|
+
*/
|
|
26
|
+
generateHTML(project, draft) {
|
|
27
|
+
const { cardTemplate } = this.analysis;
|
|
28
|
+
// If we have a detected template, clone and fill it
|
|
29
|
+
if (cardTemplate) {
|
|
30
|
+
return this.fillTemplate(cardTemplate, project, draft);
|
|
31
|
+
}
|
|
32
|
+
// Otherwise use a styled default
|
|
33
|
+
return this.generateDefaultHTML(project, draft);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Fill detected template with project data
|
|
37
|
+
*/
|
|
38
|
+
fillTemplate(template, project, draft) {
|
|
39
|
+
let html = template.html;
|
|
40
|
+
// Common placeholder patterns
|
|
41
|
+
const replacements = {
|
|
42
|
+
// Title patterns
|
|
43
|
+
'{{title}}': draft.title,
|
|
44
|
+
'{{name}}': draft.title,
|
|
45
|
+
'{{project.title}}': draft.title,
|
|
46
|
+
'{{project.name}}': draft.title,
|
|
47
|
+
// Description patterns
|
|
48
|
+
'{{description}}': draft.description,
|
|
49
|
+
'{{summary}}': draft.tagline,
|
|
50
|
+
'{{project.description}}': draft.description,
|
|
51
|
+
// URL patterns
|
|
52
|
+
'{{url}}': draft.githubUrl,
|
|
53
|
+
'{{link}}': draft.githubUrl,
|
|
54
|
+
'{{github}}': draft.githubUrl,
|
|
55
|
+
'{{project.url}}': draft.githubUrl,
|
|
56
|
+
// Tech stack
|
|
57
|
+
'{{tech}}': draft.techStack.join(', '),
|
|
58
|
+
'{{technologies}}': draft.techStack.join(', '),
|
|
59
|
+
'{{stack}}': draft.techStack.join(', '),
|
|
60
|
+
};
|
|
61
|
+
// Apply replacements
|
|
62
|
+
for (const [pattern, value] of Object.entries(replacements)) {
|
|
63
|
+
html = html.replace(new RegExp(this.escapeRegex(pattern), 'gi'), value);
|
|
64
|
+
}
|
|
65
|
+
// Handle tech stack lists
|
|
66
|
+
if (html.includes('{{#each tech}}') || html.includes('{{#tech}}')) {
|
|
67
|
+
const techListHTML = draft.techStack
|
|
68
|
+
.map(tech => `<span class="tech-tag">${tech}</span>`)
|
|
69
|
+
.join('\n');
|
|
70
|
+
html = html.replace(/\{\{#each tech\}\}[\s\S]*?\{\{\/each\}\}/gi, techListHTML);
|
|
71
|
+
html = html.replace(/\{\{#tech\}\}[\s\S]*?\{\{\/tech\}\}/gi, techListHTML);
|
|
72
|
+
}
|
|
73
|
+
return html;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Generate default HTML card with detected styles
|
|
77
|
+
*/
|
|
78
|
+
generateDefaultHTML(project, draft) {
|
|
79
|
+
const { colors, typography, cssVariables } = this.analysis;
|
|
80
|
+
// Build inline styles from detected palette
|
|
81
|
+
const primaryColor = cssVariables['--primary'] || colors.primary[0] || '#0ea5e9';
|
|
82
|
+
const bgColor = cssVariables['--bg-card'] || colors.background[0] || '#1e293b';
|
|
83
|
+
const textColor = cssVariables['--text'] || colors.text[0] || '#f8fafc';
|
|
84
|
+
const font = typography.bodyFont || 'system-ui, sans-serif';
|
|
85
|
+
const techBadges = draft.techStack
|
|
86
|
+
.map(tech => `<span style="display: inline-block; padding: 4px 12px; background: ${primaryColor}22; color: ${primaryColor}; border-radius: 9999px; font-size: 12px; margin: 4px;">${tech}</span>`)
|
|
87
|
+
.join('\n ');
|
|
88
|
+
return `<article class="project-card" style="background: ${bgColor}; border-radius: 12px; padding: 24px; font-family: ${font}; color: ${textColor};">
|
|
89
|
+
<h3 style="margin: 0 0 8px 0; font-size: 20px; font-weight: 600;">${draft.title}</h3>
|
|
90
|
+
<p style="margin: 0 0 16px 0; color: ${textColor}99; font-size: 14px;">${draft.tagline}</p>
|
|
91
|
+
<p style="margin: 0 0 16px 0; line-height: 1.6;">${draft.description}</p>
|
|
92
|
+
<div style="margin-bottom: 16px;">
|
|
93
|
+
${techBadges}
|
|
94
|
+
</div>
|
|
95
|
+
<a href="${draft.githubUrl}" target="_blank" rel="noopener" style="display: inline-flex; align-items: center; color: ${primaryColor}; text-decoration: none; font-weight: 500;">
|
|
96
|
+
View on GitHub →
|
|
97
|
+
</a>
|
|
98
|
+
</article>`;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Generate Markdown card
|
|
102
|
+
*/
|
|
103
|
+
generateMarkdown(project, draft) {
|
|
104
|
+
const techList = draft.techStack.map(t => `\`${t}\``).join(' · ');
|
|
105
|
+
const highlights = draft.highlights.length > 0
|
|
106
|
+
? '\n\n**Highlights:**\n' + draft.highlights.map(h => `- ${h}`).join('\n')
|
|
107
|
+
: '';
|
|
108
|
+
return `### ${draft.title}
|
|
109
|
+
|
|
110
|
+
${draft.tagline}
|
|
111
|
+
|
|
112
|
+
${draft.description}
|
|
113
|
+
|
|
114
|
+
**Tech Stack:** ${techList}
|
|
115
|
+
${highlights}
|
|
116
|
+
|
|
117
|
+
[View on GitHub](${draft.githubUrl})
|
|
118
|
+
|
|
119
|
+
---`;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Generate React/JSX component
|
|
123
|
+
*/
|
|
124
|
+
generateReact(project, draft) {
|
|
125
|
+
const techArray = JSON.stringify(draft.techStack);
|
|
126
|
+
return `<ProjectCard
|
|
127
|
+
title="${this.escapeJSX(draft.title)}"
|
|
128
|
+
tagline="${this.escapeJSX(draft.tagline)}"
|
|
129
|
+
description="${this.escapeJSX(draft.description)}"
|
|
130
|
+
techStack={${techArray}}
|
|
131
|
+
githubUrl="${draft.githubUrl}"
|
|
132
|
+
${draft.liveUrl ? `liveUrl="${draft.liveUrl}"` : ''}
|
|
133
|
+
/>`;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Generate a generic ProjectCard component definition
|
|
137
|
+
*/
|
|
138
|
+
generateProjectCardComponent() {
|
|
139
|
+
const { colors, typography, cssVariables } = this.analysis;
|
|
140
|
+
const primaryColor = cssVariables['--primary'] || colors.primary[0] || '#0ea5e9';
|
|
141
|
+
return `interface ProjectCardProps {
|
|
142
|
+
title: string;
|
|
143
|
+
tagline: string;
|
|
144
|
+
description: string;
|
|
145
|
+
techStack: string[];
|
|
146
|
+
githubUrl: string;
|
|
147
|
+
liveUrl?: string;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function ProjectCard({ title, tagline, description, techStack, githubUrl, liveUrl }: ProjectCardProps) {
|
|
151
|
+
return (
|
|
152
|
+
<article className="project-card bg-surface-800 rounded-xl p-6 hover:bg-surface-700 transition-colors">
|
|
153
|
+
<h3 className="text-xl font-semibold mb-2">{title}</h3>
|
|
154
|
+
<p className="text-surface-400 text-sm mb-4">{tagline}</p>
|
|
155
|
+
<p className="text-surface-200 mb-4">{description}</p>
|
|
156
|
+
<div className="flex flex-wrap gap-2 mb-4">
|
|
157
|
+
{techStack.map((tech) => (
|
|
158
|
+
<span key={tech} className="px-3 py-1 text-xs rounded-full bg-primary-500/20 text-primary-400">
|
|
159
|
+
{tech}
|
|
160
|
+
</span>
|
|
161
|
+
))}
|
|
162
|
+
</div>
|
|
163
|
+
<div className="flex gap-4">
|
|
164
|
+
<a href={githubUrl} target="_blank" rel="noopener" className="text-primary-400 hover:underline">
|
|
165
|
+
GitHub →
|
|
166
|
+
</a>
|
|
167
|
+
{liveUrl && (
|
|
168
|
+
<a href={liveUrl} target="_blank" rel="noopener" className="text-primary-400 hover:underline">
|
|
169
|
+
Live Demo →
|
|
170
|
+
</a>
|
|
171
|
+
)}
|
|
172
|
+
</div>
|
|
173
|
+
</article>
|
|
174
|
+
);
|
|
175
|
+
}`;
|
|
176
|
+
}
|
|
177
|
+
escapeRegex(str) {
|
|
178
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
179
|
+
}
|
|
180
|
+
escapeJSX(str) {
|
|
181
|
+
return str
|
|
182
|
+
.replace(/\\/g, '\\\\')
|
|
183
|
+
.replace(/"/g, '\\"')
|
|
184
|
+
.replace(/\n/g, '\\n');
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=template-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-generator.js","sourceRoot":"","sources":["../../src/integrations/template-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Store - JSON file-based storage for projects
|
|
3
|
+
* Simple MVP storage that can be swapped for a database later.
|
|
4
|
+
*/
|
|
5
|
+
import type { Project, Config } from '../events/types.js';
|
|
6
|
+
export declare class ProjectStore {
|
|
7
|
+
private projects;
|
|
8
|
+
private filePath;
|
|
9
|
+
constructor(config: Config);
|
|
10
|
+
private ensureDataDir;
|
|
11
|
+
private load;
|
|
12
|
+
save(): void;
|
|
13
|
+
getProject(id: string): Project | undefined;
|
|
14
|
+
saveProject(project: Project): void;
|
|
15
|
+
deleteProject(id: string): boolean;
|
|
16
|
+
getAllProjects(): Project[];
|
|
17
|
+
getProjectsByStatus(status: Project['status']): Project[];
|
|
18
|
+
getProjectsNeedingReview(): Project[];
|
|
19
|
+
getApprovedPortfolios(): Project[];
|
|
20
|
+
private serialize;
|
|
21
|
+
private deserialize;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=project-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-store.d.ts","sourceRoot":"","sources":["../../src/storage/project-store.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE1D,qBAAa,YAAY;IACrB,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,QAAQ,CAAS;gBAEb,MAAM,EAAE,MAAM;IAM1B,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,IAAI;IAqBZ,IAAI,IAAI,IAAI;IASZ,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI3C,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAKnC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAMlC,cAAc,IAAI,OAAO,EAAE;IAI3B,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,EAAE;IAIzD,wBAAwB,IAAI,OAAO,EAAE;IAIrC,qBAAqB,IAAI,OAAO,EAAE;IAKlC,OAAO,CAAC,SAAS;IAiBjB,OAAO,CAAC,WAAW;CAgBtB"}
|