Files
cv-site/tests/inspect-structure.js
T
juanatsap 2c372eee49 feat: add social links to footer and optional company logo toggle
**Social Links in Footer (Page 2):**
- Replace address/phone with LinkedIn, GitHub, and Behance links
- Maintain email@ link
- All links are clickable and open in new tabs
- Footer displays social media profiles prominently

**Company Logo Toggle Feature:**
- Add "Show logos" toggle switch in top action bar
- Toggle displays company logos (48x48px) to the left of each experience item
- LinkedIn-style layout when logos are shown
- Logos hidden by default, optional display via toggle
- Graceful fallback: missing logos don't break layout (onerror handler)
- Logos directory created at static/images/logos/ with README

**Technical Implementation:**
- New CSS file: logo-toggle.css for toggle switch and logo layout
- JavaScript: toggleLogos() function for show/hide functionality
- Template updates: experience items now support flex layout with logos
- Action bar grid updated to accommodate 4 columns
- Logo display uses CSS class `.show-logos` on `.cv-paper`
- Print CSS: logos hidden in PDF exports by default

**User Experience:**
- Clean toggle switch UI with smooth animations
- Mobile responsive design
- Accessibility: proper ARIA labels for toggle
- Optional feature that doesn't clutter default view
- Professional LinkedIn-style appearance when enabled

Logos can be added to static/images/logos/ directory using filenames
from the companyLogo field in CV JSON data.
2025-11-05 12:15:43 +00:00

99 lines
3.1 KiB
JavaScript

const { chromium } = require('playwright');
async function inspectStructure() {
const browser = await chromium.launch();
const page = await browser.newPage();
console.log('\n=== INSPECTING OLD SITE (localhost:3000) ===\n');
await page.goto('http://localhost:3000', { waitUntil: 'networkidle' });
// Get all class names
const classes = await page.evaluate(() => {
const allElements = document.querySelectorAll('*');
const classSet = new Set();
allElements.forEach(el => {
if (el.className && typeof el.className === 'string') {
el.className.split(' ').forEach(cls => {
if (cls.trim()) classSet.add(cls.trim());
});
}
});
return Array.from(classSet).sort();
});
console.log('All classes found:');
console.log(classes.filter(c => c.includes('badge') || c.includes('title') || c.includes('cv') || c.includes('sidebar')).join('\n'));
// Get main structure
const structure = await page.evaluate(() => {
const getStructure = (el, depth = 0) => {
if (depth > 3) return null;
const tag = el.tagName.toLowerCase();
const classes = el.className || '';
const id = el.id || '';
return {
tag,
classes,
id,
children: Array.from(el.children).map(child => getStructure(child, depth + 1)).filter(Boolean)
};
};
return getStructure(document.body);
});
console.log('\n\nMain structure:');
console.log(JSON.stringify(structure, null, 2).substring(0, 5000));
// Find elements with "badge" or "title" in their classes
const badgeElements = await page.$$eval('[class*="badge"], [class*="title"]', elements =>
elements.slice(0, 20).map(el => ({
tag: el.tagName,
class: el.className,
text: el.textContent?.substring(0, 100),
computedStyles: (() => {
const computed = window.getComputedStyle(el);
return {
fontSize: computed.fontSize,
fontWeight: computed.fontWeight,
color: computed.color,
backgroundColor: computed.backgroundColor,
padding: computed.padding,
height: computed.height
};
})()
}))
);
console.log('\n\nBadge/Title elements:');
console.log(JSON.stringify(badgeElements, null, 2));
console.log('\n\n=== INSPECTING NEW SITE (localhost:1999) ===\n');
await page.goto('http://localhost:1999', { waitUntil: 'networkidle' });
const newBadgeElements = await page.$$eval('[class*="badge"], [class*="title"]', elements =>
elements.slice(0, 20).map(el => ({
tag: el.tagName,
class: el.className,
text: el.textContent?.substring(0, 100),
computedStyles: (() => {
const computed = window.getComputedStyle(el);
return {
fontSize: computed.fontSize,
fontWeight: computed.fontWeight,
color: computed.color,
backgroundColor: computed.backgroundColor,
padding: computed.padding,
height: computed.height
};
})()
}))
);
console.log('Badge/Title elements:');
console.log(JSON.stringify(newBadgeElements, null, 2));
await browser.close();
}
inspectStructure().catch(console.error);