✨ New Features: - Click2Crawl: Visual element selection with markdown conversion - Ctrl/Cmd+Click to select multiple elements - Visual text mode for WYSIWYG extraction - Real-time markdown preview with syntax highlighting - Export to .md file or clipboard - Schema Builder Enhancement: Instant data extraction without LLMs - Test schemas directly in browser - See JSON results immediately - Export data or Python code - Cloud deployment ready (coming soon) - Modular Architecture: - Separated into schemaBuilder.js, scriptBuilder.js, click2CrawlBuilder.js - Added contentAnalyzer.js and markdownConverter.js modules - Shared utilities and CSS reset system - Integrated marked.js for markdown rendering 🎨 UI/UX Improvements: - Added edgy cloud announcement banner with seamless shimmer animation - Direct, technical copy: "You don't need Puppeteer. You need Crawl4AI Cloud." - Enhanced feature cards with emojis - Fixed CSS conflicts with targeted reset approach - Improved badge hover effects (red on hover) - Added wrap toggle for code preview 📚 Documentation Updates: - Split extraction diagrams into LLM and no-LLM versions - Updated llms-full.txt with latest content - Added versioned LLM context (v0.1.1) 🔧 Technical Enhancements: - Refactored 3464 lines of monolithic content.js into modules - Added proper event handling and cleanup - Improved z-index management - Better scroll position tracking for badges - Enhanced error handling throughout This release transforms the Chrome Extension from a simple tool into a powerful visual data extraction suite, making web scraping accessible to everyone.
146 lines
4.1 KiB
JavaScript
146 lines
4.1 KiB
JavaScript
// Popup script for Crawl4AI Assistant
|
|
let activeMode = null;
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
// Fetch GitHub stars
|
|
fetchGitHubStars();
|
|
|
|
// Check current state
|
|
chrome.storage.local.get(['captureMode', 'captureStats'], (data) => {
|
|
if (data.captureMode) {
|
|
activeMode = data.captureMode;
|
|
showActiveSession(data.captureStats || {});
|
|
}
|
|
});
|
|
|
|
// Mode buttons
|
|
document.getElementById('schema-mode').addEventListener('click', () => {
|
|
startSchemaCapture();
|
|
});
|
|
|
|
document.getElementById('script-mode').addEventListener('click', () => {
|
|
startScriptCapture();
|
|
});
|
|
|
|
document.getElementById('c2c-mode').addEventListener('click', () => {
|
|
startClick2Crawl();
|
|
});
|
|
|
|
// Session actions
|
|
document.getElementById('generate-code').addEventListener('click', () => {
|
|
generateCode();
|
|
});
|
|
|
|
document.getElementById('stop-capture').addEventListener('click', () => {
|
|
stopCapture();
|
|
});
|
|
});
|
|
|
|
async function fetchGitHubStars() {
|
|
try {
|
|
const response = await fetch('https://api.github.com/repos/unclecode/crawl4ai');
|
|
const data = await response.json();
|
|
const stars = data.stargazers_count;
|
|
|
|
// Format the number (e.g., 1.2k)
|
|
let formattedStars;
|
|
if (stars >= 1000) {
|
|
formattedStars = (stars / 1000).toFixed(1) + 'k';
|
|
} else {
|
|
formattedStars = stars.toString();
|
|
}
|
|
|
|
document.getElementById('stars-count').textContent = `⭐ ${formattedStars}`;
|
|
} catch (error) {
|
|
console.error('Failed to fetch GitHub stars:', error);
|
|
document.getElementById('stars-count').textContent = '⭐ 2k+';
|
|
}
|
|
}
|
|
|
|
function startSchemaCapture() {
|
|
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
|
chrome.tabs.sendMessage(tabs[0].id, {
|
|
action: 'startSchemaCapture'
|
|
}, (response) => {
|
|
if (response && response.success) {
|
|
// Close the popup to let user interact with the page
|
|
window.close();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function startScriptCapture() {
|
|
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
|
chrome.tabs.sendMessage(tabs[0].id, {
|
|
action: 'startScriptCapture'
|
|
}, (response) => {
|
|
if (response && response.success) {
|
|
// Close the popup to let user interact with the page
|
|
window.close();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function startClick2Crawl() {
|
|
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
|
chrome.tabs.sendMessage(tabs[0].id, {
|
|
action: 'startClick2Crawl'
|
|
}, (response) => {
|
|
if (response && response.success) {
|
|
// Close the popup to let user interact with the page
|
|
window.close();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function showActiveSession(stats) {
|
|
document.querySelector('.mode-selector').style.display = 'none';
|
|
document.getElementById('active-session').classList.remove('hidden');
|
|
|
|
updateSessionStats(stats);
|
|
}
|
|
|
|
function updateSessionStats(stats) {
|
|
document.getElementById('container-status').textContent =
|
|
stats.container ? 'Selected ✓' : 'Not selected';
|
|
document.getElementById('fields-count').textContent = stats.fields || 0;
|
|
|
|
// Enable generate button if we have container and fields
|
|
document.getElementById('generate-code').disabled =
|
|
!stats.container || stats.fields === 0;
|
|
}
|
|
|
|
function generateCode() {
|
|
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
|
chrome.tabs.sendMessage(tabs[0].id, {
|
|
action: 'generateCode'
|
|
});
|
|
});
|
|
}
|
|
|
|
function stopCapture() {
|
|
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
|
chrome.tabs.sendMessage(tabs[0].id, {
|
|
action: 'stopCapture'
|
|
}, () => {
|
|
// Reset UI
|
|
document.querySelector('.mode-selector').style.display = 'flex';
|
|
document.getElementById('active-session').classList.add('hidden');
|
|
activeMode = null;
|
|
|
|
// Clear storage
|
|
chrome.storage.local.remove(['captureMode', 'captureStats']);
|
|
});
|
|
});
|
|
}
|
|
|
|
// Listen for stats updates from content script
|
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
if (message.action === 'updateStats') {
|
|
updateSessionStats(message.stats);
|
|
chrome.storage.local.set({ captureStats: message.stats });
|
|
}
|
|
}); |