Merge pull request #17 from sahiixx/copilot/fix-36accbc4-d072-4df5-aa15-87f145a64780

Fix broken site submodule and implement functional static site generator
This commit is contained in:
Sahiix@1 2025-10-02 09:53:07 +04:00 committed by GitHub
commit 38b58fb636
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 564 additions and 1 deletions

1
site

@ -1 +0,0 @@
Subproject commit f98dac50da2456cb43cead86f999817cd8e93fbe

14
site/.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
# Build output
dist/
# Dependencies
node_modules/
package-lock.json
# Logs
*.log
npm-debug.log*
# OS files
.DS_Store
Thumbs.db

63
site/README.md Normal file
View File

@ -0,0 +1,63 @@
# System Prompts Site Generator
This directory contains a static site generator for the System Prompts repository.
## Quick Start
```bash
# Build the site
npm run build
# Preview locally
npm run preview
# Development mode (build + preview)
npm run dev
```
## Features
- 🔍 Scans the repository for `.txt`, `.json`, and `.md` files
- 📄 Generates individual pages for each file with syntax highlighting
- 📊 Creates an organized index page with statistics
- 🎨 GitHub-inspired dark theme
- 📱 Responsive design
## Project Structure
```
site/
├── package.json # Project dependencies and scripts
├── build.js # Static site generator
├── .gitignore # Git ignore rules
├── README.md # This file
└── dist/ # Generated site (created on build)
├── index.html # Main index page
└── files/ # Individual file pages
```
## How It Works
1. **Scanning**: The build script recursively scans the parent directory for relevant files
2. **Processing**: Each file is processed and converted to an HTML page
3. **Generation**: An index page is created with the directory structure
4. **Output**: All files are written to the `dist/` directory
## Configuration
The build script can be customized by editing `build.js`:
- **EXCLUDED_DIRS**: Directories to skip during scanning
- **INCLUDED_EXTENSIONS**: File extensions to include
- **Styling**: Modify the embedded CSS in the HTML generation functions
## Deployment
The generated `dist/` directory can be deployed to:
- GitHub Pages
- Vercel
- Netlify
- Any static hosting service
See the main [INSTALL.md](../INSTALL.md) for detailed deployment instructions.

468
site/build.js Normal file
View File

@ -0,0 +1,468 @@
const fs = require('fs');
const path = require('path');
// Configuration
const ROOT_DIR = path.join(__dirname, '..');
const DIST_DIR = path.join(__dirname, 'dist');
const FILES_DIR = path.join(DIST_DIR, 'files');
// Directories to exclude from scanning
const EXCLUDED_DIRS = ['.git', 'node_modules', 'site', 'assets'];
// File extensions to include
const INCLUDED_EXTENSIONS = ['.txt', '.json', '.md'];
// Utility function to escape HTML
function escapeHtml(text) {
const map = {
'&': '&',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#039;'
};
return text.replace(/[&<>"']/g, m => map[m]);
}
// Generate HTML for individual file pages
function generateFileHTML(filePath, content, fileInfo) {
const relativePath = path.relative(ROOT_DIR, filePath);
const extension = path.extname(filePath);
const language = extension === '.json' ? 'json' : extension === '.md' ? 'markdown' : 'text';
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${escapeHtml(relativePath)} - System Prompts</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
line-height: 1.6;
background: #0d1117;
color: #c9d1d9;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid #30363d;
}
h1 {
color: #58a6ff;
font-size: 24px;
margin-bottom: 10px;
}
.breadcrumb {
font-size: 14px;
color: #8b949e;
}
.breadcrumb a {
color: #58a6ff;
text-decoration: none;
}
.breadcrumb a:hover {
text-decoration: underline;
}
.file-info {
background: #161b22;
border: 1px solid #30363d;
border-radius: 6px;
padding: 15px;
margin-bottom: 20px;
font-size: 14px;
}
.file-info div {
margin-bottom: 5px;
}
.file-info strong {
color: #8b949e;
margin-right: 10px;
}
pre {
background: #161b22;
border: 1px solid #30363d;
border-radius: 6px;
padding: 20px;
overflow-x: auto;
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
font-size: 14px;
line-height: 1.5;
}
code {
color: #c9d1d9;
}
.back-button {
display: inline-block;
padding: 8px 16px;
background: #21262d;
color: #58a6ff;
text-decoration: none;
border-radius: 6px;
font-size: 14px;
margin-top: 20px;
border: 1px solid #30363d;
}
.back-button:hover {
background: #30363d;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>${escapeHtml(path.basename(filePath))}</h1>
<div class="breadcrumb">
<a href="../index.html">Home</a> / ${escapeHtml(relativePath)}
</div>
</header>
<div class="file-info">
<div><strong>Path:</strong> ${escapeHtml(relativePath)}</div>
<div><strong>Size:</strong> ${fileInfo.size} bytes</div>
<div><strong>Lines:</strong> ${content.split('\\n').length}</div>
</div>
<pre><code class="${language}">${escapeHtml(content)}</code></pre>
<a href="../index.html" class="back-button"> Back to Index</a>
</div>
</body>
</html>`;
}
// Generate HTML for index page
function generateIndexHTML(fileTree, stats) {
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>System Prompts and Models of AI Tools</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
line-height: 1.6;
background: #0d1117;
color: #c9d1d9;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
margin-bottom: 40px;
padding: 40px 20px;
background: linear-gradient(135deg, #1f6feb 0%, #58a6ff 100%);
border-radius: 10px;
color: white;
}
h1 {
font-size: 32px;
margin-bottom: 10px;
}
.subtitle {
font-size: 16px;
opacity: 0.9;
}
.stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 30px;
}
.stat-card {
background: #161b22;
border: 1px solid #30363d;
border-radius: 6px;
padding: 20px;
text-align: center;
}
.stat-number {
font-size: 32px;
font-weight: bold;
color: #58a6ff;
display: block;
margin-bottom: 5px;
}
.stat-label {
font-size: 14px;
color: #8b949e;
}
.file-tree {
background: #161b22;
border: 1px solid #30363d;
border-radius: 6px;
padding: 20px;
}
.directory {
margin-bottom: 20px;
}
.directory-name {
font-size: 18px;
font-weight: bold;
color: #58a6ff;
margin-bottom: 10px;
padding-bottom: 10px;
border-bottom: 1px solid #30363d;
}
.file-list {
list-style: none;
padding-left: 20px;
}
.file-item {
margin: 8px 0;
}
.file-link {
color: #c9d1d9;
text-decoration: none;
display: inline-flex;
align-items: center;
padding: 5px 10px;
border-radius: 4px;
transition: background 0.2s;
}
.file-link:hover {
background: #21262d;
color: #58a6ff;
}
.file-icon {
margin-right: 8px;
}
footer {
margin-top: 40px;
text-align: center;
padding-top: 20px;
border-top: 1px solid #30363d;
color: #8b949e;
font-size: 14px;
}
footer a {
color: #58a6ff;
text-decoration: none;
}
footer a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>📜 System Prompts and Models of AI Tools</h1>
<p class="subtitle">A comprehensive collection of system prompts and configurations</p>
</header>
<div class="stats">
<div class="stat-card">
<span class="stat-number">${stats.totalFiles}</span>
<span class="stat-label">Total Files</span>
</div>
<div class="stat-card">
<span class="stat-number">${stats.totalDirectories}</span>
<span class="stat-label">Directories</span>
</div>
<div class="stat-card">
<span class="stat-number">${Math.round(stats.totalSize / 1024)}KB</span>
<span class="stat-label">Total Size</span>
</div>
</div>
<div class="file-tree">
${generateFileTreeHTML(fileTree)}
</div>
<footer>
<p>Generated from <a href="https://github.com/sahiixx/system-prompts-and-models-of-ai-tools" target="_blank">sahiixx/system-prompts-and-models-of-ai-tools</a></p>
</footer>
</div>
</body>
</html>`;
}
// Generate HTML for file tree
function generateFileTreeHTML(tree) {
let html = '';
const sortedDirs = Object.keys(tree).sort();
for (const dir of sortedDirs) {
const files = tree[dir];
if (files.length === 0) continue;
html += `<div class="directory">
<div class="directory-name">📁 ${escapeHtml(dir)}</div>
<ul class="file-list">`;
const sortedFiles = files.sort((a, b) => a.name.localeCompare(b.name));
for (const file of sortedFiles) {
const icon = file.name.endsWith('.json') ? '📋' : file.name.endsWith('.md') ? '📄' : '📝';
html += `<li class="file-item">
<a href="files/${escapeHtml(file.id)}.html" class="file-link">
<span class="file-icon">${icon}</span>
${escapeHtml(file.name)}
</a>
</li>`;
}
html += `</ul></div>`;
}
return html;
}
// Scan directory recursively
function scanDirectory(dir, baseDir = dir, fileTree = {}, stats = { totalFiles: 0, totalDirectories: 0, totalSize: 0 }) {
const items = fs.readdirSync(dir);
for (const item of items) {
const fullPath = path.join(dir, item);
const relativePath = path.relative(baseDir, fullPath);
// Skip excluded directories
if (EXCLUDED_DIRS.some(excluded => relativePath.startsWith(excluded))) {
continue;
}
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
stats.totalDirectories++;
scanDirectory(fullPath, baseDir, fileTree, stats);
} else if (stat.isFile()) {
const ext = path.extname(fullPath);
if (INCLUDED_EXTENSIONS.includes(ext)) {
const dirName = path.dirname(relativePath);
const displayDir = dirName === '.' ? 'Root' : dirName;
if (!fileTree[displayDir]) {
fileTree[displayDir] = [];
}
stats.totalFiles++;
stats.totalSize += stat.size;
fileTree[displayDir].push({
name: path.basename(fullPath),
path: fullPath,
relativePath: relativePath,
id: Buffer.from(relativePath).toString('base64').replace(/[^a-zA-Z0-9]/g, '_'),
size: stat.size
});
}
}
}
return { fileTree, stats };
}
// Main build function
function build() {
console.log('🚀 Starting build process...\n');
// Clean and create dist directories
if (fs.existsSync(DIST_DIR)) {
fs.rmSync(DIST_DIR, { recursive: true });
}
fs.mkdirSync(DIST_DIR, { recursive: true });
fs.mkdirSync(FILES_DIR, { recursive: true });
console.log('📂 Scanning repository...');
const { fileTree, stats } = scanDirectory(ROOT_DIR);
console.log(`\n📊 Statistics:`);
console.log(` - Total files: ${stats.totalFiles}`);
console.log(` - Total directories: ${stats.totalDirectories}`);
console.log(` - Total size: ${Math.round(stats.totalSize / 1024)}KB\n`);
// Generate individual file pages
console.log('📝 Generating file pages...');
let generatedPages = 0;
for (const dir in fileTree) {
for (const file of fileTree[dir]) {
try {
const content = fs.readFileSync(file.path, 'utf-8');
const html = generateFileHTML(file.path, content, { size: file.size });
const outputPath = path.join(FILES_DIR, `${file.id}.html`);
fs.writeFileSync(outputPath, html);
generatedPages++;
} catch (error) {
console.error(` ⚠️ Error processing ${file.relativePath}: ${error.message}`);
}
}
}
console.log(` ✓ Generated ${generatedPages} file pages`);
// Generate index page
console.log('\n📄 Generating index page...');
const indexHTML = generateIndexHTML(fileTree, stats);
fs.writeFileSync(path.join(DIST_DIR, 'index.html'), indexHTML);
console.log(' ✓ Index page generated');
console.log('\n✨ Build completed successfully!');
console.log(`\n📁 Output directory: ${DIST_DIR}`);
console.log('🌐 Run "npm run preview" to view the site locally\n');
}
// Run build
try {
build();
} catch (error) {
console.error('❌ Build failed:', error);
process.exit(1);
}

19
site/package.json Normal file
View File

@ -0,0 +1,19 @@
{
"name": "system-prompts-site",
"version": "1.0.0",
"description": "Static site generator for System Prompts repository",
"main": "build.js",
"scripts": {
"build": "node build.js",
"preview": "python3 -m http.server 8000 --directory dist 2>/dev/null || python -m http.server 8000 --directory dist",
"dev": "node build.js && npm run preview"
},
"keywords": [
"static-site",
"generator",
"documentation"
],
"author": "",
"license": "ISC",
"dependencies": {}
}