231 lines
6.8 KiB
JavaScript
231 lines
6.8 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const fs = require('fs')
|
|
const path = require('path')
|
|
|
|
// Paths
|
|
const peopleImagesDir = path.join(__dirname, '../public/images/people')
|
|
const peopleComponentsDir = path.join(__dirname, '../src/components/people')
|
|
const peopleAppDir = path.join(__dirname, '../src/app/people')
|
|
|
|
// Function to parse markdown frontmatter
|
|
function parseFrontmatter(content) {
|
|
const frontmatterRegex = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/
|
|
const match = content.match(frontmatterRegex)
|
|
|
|
if (!match) return null
|
|
|
|
const frontmatter = {}
|
|
const body = match[2].trim()
|
|
|
|
// Parse YAML-like frontmatter
|
|
const lines = match[1].split('\n')
|
|
let currentKey = null
|
|
|
|
for (const line of lines) {
|
|
const trimmed = line.trim()
|
|
if (!trimmed) continue
|
|
|
|
if (trimmed.includes(':') && !trimmed.startsWith(' ')) {
|
|
const [key, ...valueParts] = trimmed.split(':')
|
|
const value = valueParts.join(':').trim()
|
|
currentKey = key.trim()
|
|
|
|
if (value) {
|
|
if (value.startsWith('[') && value.endsWith(']')) {
|
|
// Array value
|
|
frontmatter[currentKey] = value.slice(1, -1).split(',').map(v => v.trim())
|
|
} else if (value.startsWith('{') && value.endsWith('}')) {
|
|
// Object value - parse simple key-value pairs
|
|
const obj = {}
|
|
const objContent = value.slice(1, -1)
|
|
const pairs = objContent.split(',')
|
|
for (const pair of pairs) {
|
|
const [k, v] = pair.split(':').map(s => s.trim())
|
|
if (k && v) {
|
|
obj[k] = v
|
|
}
|
|
}
|
|
frontmatter[currentKey] = obj
|
|
} else {
|
|
frontmatter[currentKey] = value
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return { frontmatter, body }
|
|
}
|
|
|
|
// Function to convert name to component name
|
|
function nameToComponentName(name) {
|
|
return name.replace(/\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, '')
|
|
}
|
|
|
|
// Function to convert name to function name
|
|
function nameToFunctionName(name) {
|
|
return 'People_' + nameToComponentName(name)
|
|
}
|
|
|
|
// Function to generate people component
|
|
function generatePeopleComponent(personData) {
|
|
const { name, role, imageUrl, linkedinUrl, description } = personData
|
|
const functionName = nameToFunctionName(name)
|
|
|
|
return `import { PersonTemplate } from '@/components/PersonTemplate'
|
|
|
|
export const data = [
|
|
{
|
|
name: '${name}',
|
|
role: '${role}',
|
|
imageUrl: '${imageUrl}',
|
|
xUrl: '#',
|
|
linkedinUrl: '${linkedinUrl || '#'}',
|
|
},
|
|
]
|
|
|
|
const biography = \`
|
|
<p class="text-lg/7">
|
|
${description || `${name} is a valued member of our team, bringing expertise and dedication to their role as ${role}.`}
|
|
</p>
|
|
\`
|
|
|
|
export function ${functionName}() {
|
|
return <PersonTemplate personData={data[0]} biography={biography} />
|
|
}
|
|
`
|
|
}
|
|
|
|
// Function to generate page component
|
|
function generatePageComponent(personData) {
|
|
const { name } = personData
|
|
const functionName = nameToFunctionName(name)
|
|
const componentName = nameToComponentName(name)
|
|
const pageFunctionName = name.replace(/\s+/g, '') + 'Page'
|
|
|
|
return `import { CallToAction } from '@/components/CallToAction'
|
|
import { Faqs } from '@/components/Faqs'
|
|
import { Footer } from '@/components/Footer'
|
|
import { Header_darkbg } from '@/components/Header_darkbg'
|
|
import { ${functionName} } from '@/components/people/People_${componentName}'
|
|
|
|
export default function ${pageFunctionName}() {
|
|
return (
|
|
<>
|
|
<Header_darkbg />
|
|
<main>
|
|
<${functionName} />
|
|
<CallToAction />
|
|
<Faqs />
|
|
</main>
|
|
<Footer />
|
|
</>
|
|
)
|
|
}
|
|
`
|
|
}
|
|
|
|
// Main function
|
|
function main() {
|
|
console.log('🔍 Scanning for people data...')
|
|
|
|
if (!fs.existsSync(peopleImagesDir)) {
|
|
console.log('❌ People images directory not found')
|
|
return
|
|
}
|
|
|
|
const peopleDirectories = fs.readdirSync(peopleImagesDir)
|
|
.filter(dir => {
|
|
const dirPath = path.join(peopleImagesDir, dir)
|
|
return fs.statSync(dirPath).isDirectory() && dir !== '_index.md'
|
|
})
|
|
|
|
console.log(`✅ Found ${peopleDirectories.length} people directories`)
|
|
|
|
let generatedCount = 0
|
|
let updatedCount = 0
|
|
|
|
for (const personDir of peopleDirectories) {
|
|
try {
|
|
const indexPath = path.join(peopleImagesDir, personDir, 'index.md')
|
|
|
|
if (!fs.existsSync(indexPath)) {
|
|
console.log(`⚠️ No index.md found for ${personDir}`)
|
|
continue
|
|
}
|
|
|
|
const content = fs.readFileSync(indexPath, 'utf8')
|
|
const parsed = parseFrontmatter(content)
|
|
|
|
if (!parsed) {
|
|
console.log(`⚠️ Could not parse frontmatter for ${personDir}`)
|
|
continue
|
|
}
|
|
|
|
const { frontmatter, body } = parsed
|
|
|
|
// Find the actual image file
|
|
const imageExtensions = ['jpg', 'jpeg', 'png']
|
|
let actualImagePath = frontmatter.extra?.imgPath
|
|
|
|
if (!actualImagePath) {
|
|
// Try to find the image file with different extensions
|
|
for (const ext of imageExtensions) {
|
|
const imagePath = path.join(peopleImagesDir, personDir, `${personDir}.${ext}`)
|
|
if (fs.existsSync(imagePath)) {
|
|
actualImagePath = `${personDir}.${ext}`
|
|
break
|
|
}
|
|
}
|
|
// Fallback to jpg if no image found
|
|
actualImagePath = actualImagePath || `${personDir}.jpg`
|
|
}
|
|
|
|
// Extract person data
|
|
const personData = {
|
|
name: frontmatter.title || personDir.replace(/_/g, ' '),
|
|
role: frontmatter.description || 'Team Member',
|
|
imageUrl: `/images/people/${personDir}/${actualImagePath}`,
|
|
linkedinUrl: frontmatter.extra?.socialLinks?.LinkedIn || '#',
|
|
description: body || `${frontmatter.title} is a valued member of our team.`
|
|
}
|
|
|
|
// Generate component
|
|
const componentName = nameToComponentName(personData.name)
|
|
const componentPath = path.join(peopleComponentsDir, `People_${componentName}.tsx`)
|
|
|
|
if (!fs.existsSync(componentPath)) {
|
|
const componentContent = generatePeopleComponent(personData)
|
|
fs.writeFileSync(componentPath, componentContent, 'utf8')
|
|
console.log(`✅ Generated component: People_${componentName}.tsx`)
|
|
generatedCount++
|
|
}
|
|
|
|
// Update page.tsx
|
|
const pagePath = path.join(peopleAppDir, personDir, 'page.tsx')
|
|
|
|
if (fs.existsSync(pagePath)) {
|
|
const pageContent = generatePageComponent(personData)
|
|
fs.writeFileSync(pagePath, pageContent, 'utf8')
|
|
console.log(`✅ Updated page: ${personDir}/page.tsx`)
|
|
updatedCount++
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error(`❌ Error processing ${personDir}:`, error.message)
|
|
}
|
|
}
|
|
|
|
console.log(`\n🎉 Generation complete!`)
|
|
console.log(` - Generated ${generatedCount} new components`)
|
|
console.log(` - Updated ${updatedCount} page files`)
|
|
console.log(`\n📝 Run 'npm run generate-people-data' to update the data registry`)
|
|
}
|
|
|
|
// Run the script
|
|
if (require.main === module) {
|
|
main()
|
|
}
|
|
|
|
module.exports = { main }
|