Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 17:55:23 +08:00
commit ff43aa6f4d
42 changed files with 4239 additions and 0 deletions

View File

@@ -0,0 +1,290 @@
# CSS Debugging Reference
Advanced CSS debugging workflows and patterns for frontend development.
## Quick Diagnostics
### Check Element Visibility
```bash
# Is element visible?
./browser-eval.js '(() => {
const el = document.querySelector(".target");
const s = getComputedStyle(el);
return {
display: s.display,
visibility: s.visibility,
opacity: s.opacity,
hidden: el.hidden,
height: s.height,
width: s.width,
overflow: s.overflow
};
})()'
```
### Element Not Showing?
Common causes and checks:
```bash
# Check display property
./browser-eval.js 'getComputedStyle(document.querySelector(".target")).display'
# If "none" - element is hidden by CSS
# Check visibility
./browser-eval.js 'getComputedStyle(document.querySelector(".target")).visibility'
# If "hidden" - element takes space but invisible
# Check opacity
./browser-eval.js 'getComputedStyle(document.querySelector(".target")).opacity'
# If "0" - element is transparent
# Check dimensions
./browser-eval.js 'document.querySelector(".target").getBoundingClientRect()'
# If width/height is 0 - element has no size
# Check if off-screen
./browser-eval.js '(() => {
const r = document.querySelector(".target").getBoundingClientRect();
return {
inViewport: r.top >= 0 && r.left >= 0 && r.bottom <= window.innerHeight && r.right <= window.innerWidth,
position: { top: r.top, left: r.left }
};
})()'
```
## Layout Issues
### Flexbox Debugging
```bash
# Check flex container
./browser-eval.js '(() => {
const el = document.querySelector(".flex-container");
const s = getComputedStyle(el);
return {
display: s.display,
flexDirection: s.flexDirection,
justifyContent: s.justifyContent,
alignItems: s.alignItems,
flexWrap: s.flexWrap,
gap: s.gap
};
})()'
# Check flex items
./browser-eval.js '[...document.querySelectorAll(".flex-container > *")].map(el => {
const s = getComputedStyle(el);
return {
flexGrow: s.flexGrow,
flexShrink: s.flexShrink,
flexBasis: s.flexBasis,
alignSelf: s.alignSelf
};
})'
```
### Grid Debugging
```bash
# Check grid container
./browser-eval.js '(() => {
const el = document.querySelector(".grid-container");
const s = getComputedStyle(el);
return {
display: s.display,
gridTemplateColumns: s.gridTemplateColumns,
gridTemplateRows: s.gridTemplateRows,
gap: s.gap,
gridAutoFlow: s.gridAutoFlow
};
})()'
```
### Box Model
```bash
# Full box model breakdown
./browser-eval.js '(() => {
const el = document.querySelector(".target");
const s = getComputedStyle(el);
const r = el.getBoundingClientRect();
return {
content: { width: r.width, height: r.height },
padding: { top: s.paddingTop, right: s.paddingRight, bottom: s.paddingBottom, left: s.paddingLeft },
border: { top: s.borderTopWidth, right: s.borderRightWidth, bottom: s.borderBottomWidth, left: s.borderLeftWidth },
margin: { top: s.marginTop, right: s.marginRight, bottom: s.marginBottom, left: s.marginLeft },
boxSizing: s.boxSizing
};
})()'
```
## Positioning Problems
### Z-Index Stacking
```bash
# Find all positioned elements with z-index
./browser-eval.js '[...document.querySelectorAll("*")].filter(el => {
const s = getComputedStyle(el);
return s.position !== "static" && s.zIndex !== "auto";
}).map(el => ({
selector: el.tagName + (el.id ? "#" + el.id : "") + (el.className ? "." + el.className.split(" ")[0] : ""),
position: getComputedStyle(el).position,
zIndex: getComputedStyle(el).zIndex
})).sort((a, b) => parseInt(b.zIndex) - parseInt(a.zIndex))'
```
### Fixed/Sticky Elements
```bash
# Find fixed/sticky elements
./browser-eval.js '[...document.querySelectorAll("*")].filter(el => {
const pos = getComputedStyle(el).position;
return pos === "fixed" || pos === "sticky";
}).map(el => ({
tag: el.tagName.toLowerCase(),
id: el.id,
class: el.className,
position: getComputedStyle(el).position
}))'
```
## Responsive Issues
### Media Query Testing
```bash
# Test different breakpoints
./browser-resize.js --mobile && ./browser-screenshot.js --output=/tmp/mobile.png
./browser-resize.js --tablet && ./browser-screenshot.js --output=/tmp/tablet.png
./browser-resize.js --desktop && ./browser-screenshot.js --output=/tmp/desktop.png
```
### Check Current Viewport
```bash
./browser-eval.js '({
viewport: { width: window.innerWidth, height: window.innerHeight },
screen: { width: screen.width, height: screen.height },
devicePixelRatio: window.devicePixelRatio
})'
```
## Typography Issues
### Font Not Loading
```bash
# Check computed font
./browser-eval.js 'getComputedStyle(document.querySelector(".text")).fontFamily'
# Check if webfont loaded
./browser-eval.js 'document.fonts.check("16px YourFontName")'
# List all loaded fonts
./browser-eval.js '[...document.fonts].map(f => ({ family: f.family, style: f.style, weight: f.weight, status: f.status }))'
```
### Text Overflow
```bash
# Check text overflow settings
./browser-eval.js '(() => {
const el = document.querySelector(".truncated-text");
const s = getComputedStyle(el);
return {
overflow: s.overflow,
textOverflow: s.textOverflow,
whiteSpace: s.whiteSpace,
width: s.width,
maxWidth: s.maxWidth
};
})()'
```
## Color & Visual
### Check Colors
```bash
# Get all colors used on element
./browser-eval.js '(() => {
const el = document.querySelector(".target");
const s = getComputedStyle(el);
return {
color: s.color,
backgroundColor: s.backgroundColor,
borderColor: s.borderColor,
outlineColor: s.outlineColor
};
})()'
```
### Find Elements by Color
```bash
# Find all elements with a specific background
./browser-eval.js '[...document.querySelectorAll("*")].filter(el =>
getComputedStyle(el).backgroundColor === "rgb(255, 0, 0)"
).map(el => el.tagName + (el.id ? "#" + el.id : ""))'
```
## Performance Concerns
### Large DOM Check
```bash
./browser-eval.js '({
totalElements: document.querySelectorAll("*").length,
deepestNesting: (() => {
let max = 0;
document.querySelectorAll("*").forEach(el => {
let depth = 0, node = el;
while (node.parentElement) { depth++; node = node.parentElement; }
if (depth > max) max = depth;
});
return max;
})()
})'
```
### Reflow Triggers
Watch for properties that cause layout recalculation:
- offsetTop/Left/Width/Height
- scrollTop/Left/Width/Height
- clientTop/Left/Width/Height
- getComputedStyle()
- getBoundingClientRect()
## Animation Debugging
### Check Animations
```bash
./browser-eval.js '(() => {
const el = document.querySelector(".animated");
const s = getComputedStyle(el);
return {
animation: s.animation,
animationName: s.animationName,
animationDuration: s.animationDuration,
animationTimingFunction: s.animationTimingFunction,
animationDelay: s.animationDelay,
transition: s.transition
};
})()'
```
### Force Animation State
```bash
# Pause all animations
./browser-eval.js 'document.querySelectorAll("*").forEach(el => el.style.animationPlayState = "paused")'
# Resume animations
./browser-eval.js 'document.querySelectorAll("*").forEach(el => el.style.animationPlayState = "")'
```
## Common CSS Fixes
### Overflow Scroll Not Working
Check these in order:
1. Parent has defined height
2. `overflow` is set to `scroll` or `auto`
3. Content is actually taller than container
### Element Behind Another
1. Check z-index values
2. Ensure positioned (relative/absolute/fixed)
3. Check stacking context (transform, opacity < 1, etc. create new contexts)
### Flexbox Not Centering
1. Container has height
2. `align-items` for vertical, `justify-content` for horizontal
3. Check `flex-direction` - swaps main/cross axis

View File

@@ -0,0 +1,259 @@
# JavaScript Debugging Reference
Workflows for diagnosing and fixing JavaScript issues in web applications.
## Error Detection
### Capture Runtime Errors
```bash
# Watch for errors in real-time
./browser-console.js --errors --watch
# Inject error capture (run once per page load)
./browser-eval.js 'window.onerror = (msg, src, line, col, err) => {
window.__jsErrors = window.__jsErrors || [];
window.__jsErrors.push({ message: msg, source: src, line, col, stack: err?.stack });
return false;
}'
# Check captured errors
./browser-eval.js 'window.__jsErrors || []'
```
### Unhandled Promise Rejections
```bash
# Capture unhandled rejections
./browser-eval.js 'window.addEventListener("unhandledrejection", e => {
window.__promiseErrors = window.__promiseErrors || [];
window.__promiseErrors.push({ reason: e.reason?.message || String(e.reason) });
})'
# Check promise errors
./browser-eval.js 'window.__promiseErrors || []'
```
## Common Error Types
### TypeError: Cannot read property 'x' of undefined
**Cause**: Accessing property on null/undefined
**Debug**:
```bash
# Check if element exists
./browser-eval.js 'document.querySelector(".my-element")'
# Check if variable/property exists
./browser-eval.js 'typeof window.myApp?.myProperty'
```
### ReferenceError: x is not defined
**Cause**: Variable not in scope or not declared
**Debug**:
```bash
# Check if global exists
./browser-eval.js '"myVariable" in window'
# List all globals matching pattern
./browser-eval.js 'Object.keys(window).filter(k => k.includes("my"))'
```
### SyntaxError
**Cause**: Invalid JavaScript syntax
**Debug**: Check browser console for file and line number
```bash
./browser-console.js --errors
```
## State Inspection
### Check Global Variables
```bash
# List all custom globals (excluding built-ins)
./browser-eval.js '(() => {
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const builtins = new Set(Object.keys(iframe.contentWindow));
iframe.remove();
return Object.keys(window).filter(k => !builtins.has(k) && !k.startsWith("__"));
})()'
```
### Inspect Application State
```bash
# React state (if using React DevTools globals)
./browser-eval.js 'window.__REACT_DEVTOOLS_GLOBAL_HOOK__?.renderers'
# Redux store (if exposed)
./browser-eval.js 'window.__store?.getState()'
# Vue instance (if exposed)
./browser-eval.js 'document.querySelector("#app")?.__vue__?.$data'
```
### Local Storage / Session Storage
```bash
# View localStorage
./browser-eval.js 'Object.fromEntries(Object.entries(localStorage))'
# View sessionStorage
./browser-eval.js 'Object.fromEntries(Object.entries(sessionStorage))'
```
## Event Debugging
### Check Event Listeners
```bash
# Get listeners on element (Chrome only)
./browser-eval.js 'getEventListeners(document.querySelector(".button"))'
# Alternative: Check if onclick exists
./browser-eval.js 'typeof document.querySelector(".button").onclick'
```
### Debug Event Firing
```bash
# Log all click events
./browser-eval.js 'document.addEventListener("click", e => console.log("Click:", e.target.tagName, e.target.className), true)'
# Log all form submissions
./browser-eval.js 'document.addEventListener("submit", e => console.log("Form submit:", e.target.action), true)'
```
### Simulate Events
```bash
# Click element
./browser-eval.js 'document.querySelector(".button").click()'
# Dispatch custom event
./browser-eval.js 'document.querySelector(".target").dispatchEvent(new Event("input", { bubbles: true }))'
# Submit form
./browser-eval.js 'document.querySelector("form").submit()'
```
## Async Debugging
### Track Pending Promises
```bash
# Wrap fetch to log all requests
./browser-eval.js '(() => {
const orig = window.fetch;
window.fetch = (...args) => {
console.log("Fetch:", args[0]);
return orig.apply(window, args);
};
})()'
```
### Debug setTimeout/setInterval
```bash
# List all active timers (approximate)
./browser-eval.js '(() => {
const ids = [];
const id = setTimeout(() => {}, 0);
clearTimeout(id);
for (let i = 1; i < id; i++) {
clearTimeout(i);
clearInterval(i);
}
return `Cleared timers up to ID ${id}`;
})()'
```
## Network-Related JS Issues
### Check if Fetch Failed
```bash
./browser-eval.js 'fetch("/api/data").then(r => ({ status: r.status, ok: r.ok })).catch(e => ({ error: e.message }))'
```
### CORS Errors
Check console for CORS errors:
```bash
./browser-console.js --errors | grep -i cors
```
### API Response Issues
```bash
# Test API and inspect response
./browser-eval.js 'fetch("/api/endpoint").then(r => r.json()).then(d => JSON.stringify(d, null, 2)).catch(e => e.message)'
```
## Module/Import Issues
### Check if Module Loaded
```bash
# Check for module in global scope
./browser-eval.js '"ModuleName" in window'
# Check ES module
./browser-eval.js 'import("./module.js").then(m => Object.keys(m)).catch(e => e.message)'
```
### Script Load Order
```bash
# List all scripts in order
./browser-eval.js '[...document.querySelectorAll("script")].map(s => ({ src: s.src || "(inline)", async: s.async, defer: s.defer }))'
```
## Performance Issues
### Identify Long Tasks
```bash
# Monitor long tasks
./browser-eval.js '(() => {
const observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => console.log("Long task:", entry.duration, "ms"));
});
observer.observe({ entryTypes: ["longtask"] });
return "Long task observer started";
})()'
```
### Memory Leaks
```bash
# Get heap size (Chrome)
./browser-eval.js 'performance.memory ? { usedHeap: Math.round(performance.memory.usedJSHeapSize / 1024 / 1024) + "MB", totalHeap: Math.round(performance.memory.totalJSHeapSize / 1024 / 1024) + "MB" } : "Not available"'
```
## Framework-Specific
### React Debugging
```bash
# Find React components in DOM
./browser-eval.js '(() => {
const reactRoot = document.querySelector("[data-reactroot], #root, #app");
return reactRoot ? "React app found" : "No React root detected";
})()'
# Check for React errors
./browser-console.js --errors | grep -i react
```
### Vue Debugging
```bash
# Check Vue version
./browser-eval.js 'window.Vue?.version || document.querySelector("[data-v-]") ? "Vue detected" : "No Vue"'
```
### Next.js/Nuxt Hydration
```bash
# Check for hydration errors
./browser-console.js --errors | grep -i hydrat
```
## Quick Fixes
### Script Not Running
1. Check if script loaded: `./browser-dom.js "script[src*='filename']"`
2. Check for syntax errors: `./browser-console.js --errors`
3. Check load order: Ensure dependencies load first
### Event Handler Not Working
1. Check element exists when handler attached
2. Verify selector is correct
3. Check for event.preventDefault() or stopPropagation()
### Async Code Not Executing
1. Check if Promise rejects: Add .catch() logging
2. Verify await is in async function
3. Check network requests complete successfully

View File

@@ -0,0 +1,288 @@
# Self-Debugging Workflow
Patterns for Claude and AI agents to verify and fix their own frontend work.
## Core Principle
After making any frontend change, verify it worked:
1. **Screenshot** - Visual verification
2. **Console** - Check for errors
3. **DOM** - Confirm structure
4. **Iterate** - Fix issues and repeat
## Basic Verification Loop
```bash
# After modifying HTML/CSS/JS files:
# 1. Reload the page (if not using hot reload)
./browser-nav.js http://localhost:3000
# 2. Take screenshot to verify visual result
./browser-screenshot.js
# 3. Check for any JavaScript errors
./browser-console.js --errors
# 4. If issues found, fix and repeat
```
## Structured Debugging Protocol
### Phase 1: Initial Assessment
```bash
# Get page summary
./browser-dom.js
# Take baseline screenshot
./browser-screenshot.js --output=/tmp/current-state.png
# Capture any errors
./browser-console.js --errors > /tmp/errors.txt
```
### Phase 2: Make Changes
After editing source files:
```bash
# Force reload (bypass cache)
./browser-eval.js 'location.reload(true)'
# Wait for page load
sleep 2
# Take new screenshot
./browser-screenshot.js --output=/tmp/after-change.png
```
### Phase 3: Verify
```bash
# Check for new errors
./browser-console.js --errors
# Verify element exists (example: new button)
./browser-eval.js 'document.querySelector(".new-button") ? "Found" : "Missing"'
# Verify styling applied
./browser-eval.js 'getComputedStyle(document.querySelector(".new-button")).backgroundColor'
```
### Phase 4: Iterate
If issues found:
1. Identify the problem from screenshot/console
2. Fix the source code
3. Return to Phase 2
## Common Self-Fix Patterns
### CSS Not Applying
**Symptom**: Element exists but looks wrong
**Diagnosis**:
```bash
# Check if styles computed correctly
./browser-eval.js 'getComputedStyle(document.querySelector(".my-element")).cssText.slice(0, 500)'
# Check for conflicting selectors
./browser-eval.js '(() => {
const el = document.querySelector(".my-element");
const sheets = [...document.styleSheets];
const matches = [];
sheets.forEach(sheet => {
try {
[...sheet.cssRules].forEach(rule => {
if (el.matches(rule.selectorText)) matches.push(rule.selectorText);
});
} catch {}
});
return matches;
})()'
```
**Fixes to try**:
1. Increase specificity
2. Check for `!important` overrides
3. Verify selector matches element
### Element Not Visible
**Symptom**: DOM shows element but not visible
**Diagnosis**:
```bash
./browser-eval.js '(() => {
const el = document.querySelector(".my-element");
const s = getComputedStyle(el);
const r = el.getBoundingClientRect();
return {
exists: !!el,
display: s.display,
visibility: s.visibility,
opacity: s.opacity,
width: r.width,
height: r.height,
inViewport: r.top < window.innerHeight && r.bottom > 0
};
})()'
```
**Fixes based on result**:
- `display: none` → Check CSS rules hiding it
- `width/height: 0` → Add dimensions or content
- `opacity: 0` → Check for fade animations
- Not in viewport → Check positioning/scroll
### JavaScript Not Running
**Symptom**: Interactive features don't work
**Diagnosis**:
```bash
# Check for errors
./browser-console.js --errors
# Check if script loaded
./browser-eval.js 'document.querySelectorAll("script").length'
# Check if function exists
./browser-eval.js 'typeof myFunction'
```
**Fixes based on result**:
- Syntax error → Fix the JavaScript
- Script not loaded → Check path/build process
- Function undefined → Check load order, exports
### Layout Broken
**Symptom**: Elements positioned incorrectly
**Diagnosis**:
```bash
# Take screenshot
./browser-screenshot.js
# Check flex/grid container
./browser-eval.js '(() => {
const container = document.querySelector(".container");
const s = getComputedStyle(container);
return { display: s.display, flexDirection: s.flexDirection, gridTemplateColumns: s.gridTemplateColumns };
})()'
```
**Common fixes**:
- Missing `display: flex/grid` on container
- Wrong `flex-direction`
- Missing `width` on flex children
- Grid columns not matching children
## Responsive Verification
### Test All Breakpoints
```bash
# Mobile
./browser-resize.js --mobile
./browser-screenshot.js --output=/tmp/mobile.png
./browser-console.js --errors
# Tablet
./browser-resize.js --tablet
./browser-screenshot.js --output=/tmp/tablet.png
# Desktop
./browser-resize.js --desktop
./browser-screenshot.js --output=/tmp/desktop.png
```
### Compare Screenshots
After each breakpoint, Claude should analyze the screenshot for:
- Layout shifts
- Overlapping elements
- Text overflow
- Hidden/missing elements
- Incorrect spacing
## Interactive Feature Testing
### Form Validation
```bash
# Fill form with test data
./browser-eval.js 'document.querySelector("#email").value = "test@example.com"'
./browser-eval.js 'document.querySelector("#password").value = "test123"'
# Submit and check result
./browser-eval.js 'document.querySelector("form").submit()'
./browser-screenshot.js
./browser-console.js --errors
```
### Click/Hover States
```bash
# Test button click
./browser-eval.js 'document.querySelector(".button").click()'
./browser-screenshot.js
# Check state changed
./browser-eval.js 'document.querySelector(".modal")?.style.display'
```
## Automated Verification Script
For repeated checks, use this pattern:
```bash
#!/bin/bash
# verify-page.sh - Run after changes
URL="${1:-http://localhost:3000}"
OUT_DIR="/tmp/debug-$(date +%s)"
mkdir -p "$OUT_DIR"
echo "Verifying $URL..."
# Navigate
./browser-nav.js "$URL"
sleep 2
# Screenshot
./browser-screenshot.js --output="$OUT_DIR/screenshot.png"
echo "Screenshot: $OUT_DIR/screenshot.png"
# Errors
./browser-console.js --errors > "$OUT_DIR/errors.txt"
if [ -s "$OUT_DIR/errors.txt" ]; then
echo "⚠️ Errors found:"
cat "$OUT_DIR/errors.txt"
else
echo "✓ No JavaScript errors"
fi
# DOM summary
./browser-dom.js > "$OUT_DIR/dom.txt"
echo "DOM summary saved"
echo "Done. Files in $OUT_DIR"
```
## Error Recovery Strategies
### When Screenshot Shows Blank Page
1. Check console for critical errors
2. Verify server is running
3. Check network requests (404, 500)
4. Verify correct URL
### When Console Shows Many Errors
1. Fix first error (often causes cascade)
2. Reload and recheck
3. Address errors in order
### When Element Is "Almost Right"
1. Use picker to select element: `./browser-pick.js "Select the problematic element"`
2. Get full computed styles
3. Compare to expected values
4. Adjust CSS incrementally
## Best Practices
1. **Always screenshot after changes** - Visual verification catches most issues
2. **Check console immediately** - Catch JS errors early
3. **Test responsive early** - Layout issues compound
4. **Verify one change at a time** - Easier to identify what broke
5. **Save debug output** - Reference for comparison
6. **Use the picker for precision** - Get exact selectors from user