feat: port all template categories to JSON format

- Ported Minimalist templates to JSON (Swiss Grid, Brutalist, etc.)
- Ported Tech templates to JSON (SaaS, Terminal, Cyberpunk, etc.)
- Ported Creative templates to JSON (Art Gallery, Zine, Pop Art, etc.)
- Ported Industrial templates to JSON (Blueprint, Factory, Schematic, etc.)
- Ported Nature templates to JSON (Botanical, Ocean, Mountain, etc.)
- Ported Lifestyle templates to JSON (Cookbook, Travel, Coffee House, etc.)
- Ported Vintage templates to JSON (Art Deco, Medieval, Retro 80s, etc.)
- Updated README.md to reflect the new JSON-based style system (example configuration and contribution workflow)
- Completed migration of over 150 styles to the new architecture
This commit is contained in:
TypoGenie
2026-02-01 18:51:43 +02:00
parent da335734d3
commit a6f664088c
405 changed files with 69134 additions and 5936 deletions

View File

@@ -0,0 +1,81 @@
// Convert TypeScript templates to JSON format for user editing
const fs = require('fs');
const path = require('path');
const sourceDir = path.join(__dirname, '../src/styles/templates');
const outputDir = path.join(__dirname, '../src-tauri/templates');
// Ensure output directory exists
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
// Get all category directories
const categories = fs.readdirSync(sourceDir, { withFileTypes: true })
.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name);
console.log(`Found ${categories.length} categories: ${categories.join(', ')}\n`);
for (const category of categories) {
const categorySourcePath = path.join(sourceDir, category);
const categoryOutputPath = path.join(outputDir, category);
// Create category directory in output
if (!fs.existsSync(categoryOutputPath)) {
fs.mkdirSync(categoryOutputPath, { recursive: true });
}
// Get all template files in category
const templateFiles = fs.readdirSync(categorySourcePath)
.filter(file => file.endsWith('.ts') && file !== 'index.ts');
console.log(`Processing category "${category}" (${templateFiles.length} templates)...`);
for (const file of templateFiles) {
const sourceFile = path.join(categorySourcePath, file);
const content = fs.readFileSync(sourceFile, 'utf8');
// Extract the template object using regex
const templateMatch = content.match(/export\s+const\s+\w+\s*:\s*StyleOption\s*=\s*(\{[\s\S]*?\});\s*$/);
if (templateMatch) {
let templateObj = templateMatch[1];
// Convert template literals to regular strings
templateObj = templateObj.replace(/previewCss:\s*`[\s\S]*?`/, (match) => {
const css = match.replace(/previewCss:\s*`/, '').replace(/`$/, '');
return `previewCss: ${JSON.stringify(css.trim())}`;
});
// Convert single quotes to double quotes for JSON
templateObj = templateObj.replace(/'/g, '"');
// Remove trailing commas
templateObj = templateObj.replace(/,(\s*[}\]])/g, '$1');
// Fix unquoted keys
templateObj = templateObj.replace(/([{,]\s*)(\w+):/g, '$1"$2":');
try {
const template = JSON.parse(templateObj);
// Validate required fields
if (template.id && template.name && template.wordConfig) {
const outputFile = path.join(categoryOutputPath, `${template.id}.json`);
fs.writeFileSync(outputFile, JSON.stringify(template, null, 2));
console.log(`${template.id}.json`);
} else {
console.log(`${file} - missing required fields`);
}
} catch (error) {
console.log(`${file} - parse error: ${error.message}`);
}
} else {
console.log(`${file} - could not extract template`);
}
}
}
console.log('\nDone! Templates converted to JSON format.');
console.log(`Output directory: ${outputDir}`);