add people
This commit is contained in:
		
							
								
								
									
										230
									
								
								scripts/generate-all-people.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								scripts/generate-all-people.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,230 @@
 | 
			
		||||
#!/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 }
 | 
			
		||||
							
								
								
									
										127
									
								
								scripts/generate-people-data.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								scripts/generate-people-data.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,127 @@
 | 
			
		||||
#!/usr/bin/env node
 | 
			
		||||
 | 
			
		||||
const fs = require('fs')
 | 
			
		||||
const path = require('path')
 | 
			
		||||
 | 
			
		||||
// Paths
 | 
			
		||||
const peopleComponentsDir = path.join(__dirname, '../src/components/people')
 | 
			
		||||
const peopleDataFile = path.join(__dirname, '../src/lib/peopleData.ts')
 | 
			
		||||
 | 
			
		||||
// Function to get all People_*.tsx files
 | 
			
		||||
function getPeopleComponents() {
 | 
			
		||||
  if (!fs.existsSync(peopleComponentsDir)) {
 | 
			
		||||
    console.log('People components directory not found')
 | 
			
		||||
    return []
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const files = fs.readdirSync(peopleComponentsDir)
 | 
			
		||||
  return files
 | 
			
		||||
    .filter(file => file.startsWith('People_') && file.endsWith('.tsx'))
 | 
			
		||||
    .map(file => {
 | 
			
		||||
      const componentName = file.replace('.tsx', '')
 | 
			
		||||
      const importName = componentName.toLowerCase().replace('people_', '')
 | 
			
		||||
      return {
 | 
			
		||||
        fileName: file,
 | 
			
		||||
        componentName,
 | 
			
		||||
        importName,
 | 
			
		||||
        importPath: `@/components/people/${componentName}`
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Function to generate the peopleData.ts content
 | 
			
		||||
function generatePeopleDataContent(components) {
 | 
			
		||||
  const imports = components
 | 
			
		||||
    .map(comp => `import { data as ${comp.importName}Data } from '${comp.importPath}'`)
 | 
			
		||||
    .join('\n')
 | 
			
		||||
 | 
			
		||||
  const dynamicImports = components
 | 
			
		||||
    .map(comp => `    () => import('${comp.importPath}'),`)
 | 
			
		||||
    .join('\n')
 | 
			
		||||
 | 
			
		||||
  const syncDataPush = components
 | 
			
		||||
    .map(comp => `
 | 
			
		||||
  try {
 | 
			
		||||
    allPeopleData.push(...${comp.importName}Data)
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error('Error loading ${comp.importName} data:', error)
 | 
			
		||||
  }`)
 | 
			
		||||
    .join('\n')
 | 
			
		||||
 | 
			
		||||
  return `// This file is auto-generated by scripts/generate-people-data.js
 | 
			
		||||
// When new people components are added, run: npm run generate-people-data
 | 
			
		||||
 | 
			
		||||
export interface PersonData {
 | 
			
		||||
  name: string
 | 
			
		||||
  role: string
 | 
			
		||||
  imageUrl: string
 | 
			
		||||
  xUrl: string
 | 
			
		||||
  linkedinUrl: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Function to dynamically get all people data
 | 
			
		||||
export async function getAllPeopleData(): Promise<PersonData[]> {
 | 
			
		||||
  const allPeopleData: PersonData[] = []
 | 
			
		||||
 | 
			
		||||
  // Auto-generated list of all people components
 | 
			
		||||
  const peopleComponents = [
 | 
			
		||||
${dynamicImports}
 | 
			
		||||
  ]
 | 
			
		||||
 | 
			
		||||
  for (const importComponent of peopleComponents) {
 | 
			
		||||
    try {
 | 
			
		||||
      const module = await importComponent()
 | 
			
		||||
      if (module.data && Array.isArray(module.data)) {
 | 
			
		||||
        allPeopleData.push(...module.data)
 | 
			
		||||
      }
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.error('Error loading people data:', error)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return allPeopleData
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Synchronous version using static imports for immediate data access
 | 
			
		||||
${imports}
 | 
			
		||||
 | 
			
		||||
export function getAllPeopleDataSync(): PersonData[] {
 | 
			
		||||
  const allPeopleData: PersonData[] = []
 | 
			
		||||
${syncDataPush}
 | 
			
		||||
 | 
			
		||||
  return allPeopleData
 | 
			
		||||
}
 | 
			
		||||
`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Main function
 | 
			
		||||
function main() {
 | 
			
		||||
  console.log('🔍 Scanning for people components...')
 | 
			
		||||
  
 | 
			
		||||
  const components = getPeopleComponents()
 | 
			
		||||
  
 | 
			
		||||
  if (components.length === 0) {
 | 
			
		||||
    console.log('❌ No people components found')
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  console.log(`✅ Found ${components.length} people component(s):`)
 | 
			
		||||
  components.forEach(comp => {
 | 
			
		||||
    console.log(`   - ${comp.componentName}`)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  console.log('📝 Generating peopleData.ts...')
 | 
			
		||||
  
 | 
			
		||||
  const content = generatePeopleDataContent(components)
 | 
			
		||||
  fs.writeFileSync(peopleDataFile, content, 'utf8')
 | 
			
		||||
  
 | 
			
		||||
  console.log('✅ Successfully updated src/lib/peopleData.ts')
 | 
			
		||||
  console.log('\n🎉 All people components will now automatically appear on the people page!')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Run the script
 | 
			
		||||
if (require.main === module) {
 | 
			
		||||
  main()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = { main, getPeopleComponents, generatePeopleDataContent }
 | 
			
		||||
		Reference in New Issue
	
	Block a user