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 }
 |