Add Crawl4AI Assistant Chrome Extension
- Created manifest.json for the Crawl4AI Assistant extension. - Added popup HTML, CSS, and JS files for the extension interface. - Included icons and favicon for the extension. - Implemented functionality for schema capture and code generation. - Updated index.md to reflect the availability of the new extension. - Enhanced LLM Context Builder layout and styles for consistency. - Adjusted global styles for better branding and responsiveness.
This commit is contained in:
BIN
docs/md_v2/apps/crawl4ai-assistant/popup/icons/favicon.ico
Normal file
BIN
docs/md_v2/apps/crawl4ai-assistant/popup/icons/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
BIN
docs/md_v2/apps/crawl4ai-assistant/popup/icons/icon-128.png
Normal file
BIN
docs/md_v2/apps/crawl4ai-assistant/popup/icons/icon-128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
docs/md_v2/apps/crawl4ai-assistant/popup/icons/icon-16.png
Normal file
BIN
docs/md_v2/apps/crawl4ai-assistant/popup/icons/icon-16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
docs/md_v2/apps/crawl4ai-assistant/popup/icons/icon-48.png
Normal file
BIN
docs/md_v2/apps/crawl4ai-assistant/popup/icons/icon-48.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
324
docs/md_v2/apps/crawl4ai-assistant/popup/popup.css
Normal file
324
docs/md_v2/apps/crawl4ai-assistant/popup/popup.css
Normal file
@@ -0,0 +1,324 @@
|
||||
/* Font Face Definitions */
|
||||
@font-face {
|
||||
font-family: 'Dank Mono';
|
||||
src: url('../assets/DankMono-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Dank Mono';
|
||||
src: url('../assets/DankMono-Bold.woff2') format('woff2');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Dank Mono';
|
||||
src: url('../assets/DankMono-Italic.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
:root {
|
||||
--font-primary: 'Dank Mono', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, monospace;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 380px;
|
||||
font-family: var(--font-primary);
|
||||
background: #0a0a0a;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
|
||||
.popup-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #2a2a2a;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
margin: 0 0 4px 0;
|
||||
}
|
||||
|
||||
.header-stats {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.github-stars {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: #999;
|
||||
text-decoration: none;
|
||||
font-size: 13px;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.github-stars:hover {
|
||||
color: #4a9eff;
|
||||
}
|
||||
|
||||
.github-icon {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.mode-selector {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.mode-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding: 16px;
|
||||
background: #1a1a1a;
|
||||
border: 2px solid #2a2a2a;
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mode-button:hover:not(:disabled) {
|
||||
background: #252525;
|
||||
border-color: #4a9eff;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.mode-button:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.mode-button .icon {
|
||||
font-size: 32px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #252525;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.mode-button.schema .icon {
|
||||
background: #1e3a5f;
|
||||
}
|
||||
|
||||
.mode-button.script .icon {
|
||||
background: #3a1e5f;
|
||||
}
|
||||
|
||||
.mode-info h3 {
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.mode-info p {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.active-session {
|
||||
background: #1a1a1a;
|
||||
border: 2px solid #4a9eff;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.active-session.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.session-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #4a9eff;
|
||||
border-radius: 50%;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
}
|
||||
|
||||
.session-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #4a9eff;
|
||||
}
|
||||
|
||||
.session-stats {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin-bottom: 16px;
|
||||
padding: 12px;
|
||||
background: #0a0a0a;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.stat {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.session-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
flex: 1;
|
||||
padding: 10px 16px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.action-button.primary {
|
||||
background: #4a9eff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.action-button.primary:hover:not(:disabled) {
|
||||
background: #3a8eef;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.action-button.primary:disabled {
|
||||
background: #2a4a7f;
|
||||
color: #666;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.action-button.secondary {
|
||||
background: #2a2a2a;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.action-button.secondary:hover {
|
||||
background: #3a3a3a;
|
||||
}
|
||||
|
||||
.instructions {
|
||||
background: #1a1a1a;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.instructions h4 {
|
||||
font-size: 14px;
|
||||
margin-bottom: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.instructions ol {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.instructions li {
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: #ccc;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #2a2a2a;
|
||||
}
|
||||
|
||||
.social-links {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.social-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: #999;
|
||||
text-decoration: none;
|
||||
font-size: 12px;
|
||||
transition: all 0.2s ease;
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
.social-link:hover {
|
||||
color: #0fbbaa;
|
||||
background: #2a2a2a;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.social-link svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
103
docs/md_v2/apps/crawl4ai-assistant/popup/popup.html
Normal file
103
docs/md_v2/apps/crawl4ai-assistant/popup/popup.html
Normal file
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="popup.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="popup-container">
|
||||
<header>
|
||||
<img src="icons/icon-48.png" class="logo" alt="Crawl4AI">
|
||||
<div class="header-content">
|
||||
<h1>Crawl4AI Assistant</h1>
|
||||
<div class="header-stats">
|
||||
<a href="https://github.com/unclecode/crawl4ai" target="_blank" class="github-stars">
|
||||
<svg class="github-icon" viewBox="0 0 16 16" width="16" height="16">
|
||||
<path fill="currentColor" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path>
|
||||
</svg>
|
||||
<span id="stars-count">Loading...</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="mode-selector">
|
||||
<button id="schema-mode" class="mode-button schema">
|
||||
<div class="icon">📊</div>
|
||||
<div class="mode-info">
|
||||
<h3>Schema Builder</h3>
|
||||
<p>Click elements to build extraction schemas</p>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button id="script-mode" class="mode-button script" disabled>
|
||||
<div class="icon">🎯</div>
|
||||
<div class="mode-info">
|
||||
<h3>Script Builder</h3>
|
||||
<p>Coming soon - Build automation scripts</p>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="active-session" class="active-session hidden">
|
||||
<div class="session-header">
|
||||
<span class="status-dot"></span>
|
||||
<span class="session-title">Schema Capture Active</span>
|
||||
</div>
|
||||
<div class="session-stats">
|
||||
<div class="stat">
|
||||
<span class="stat-label">Container:</span>
|
||||
<span id="container-status" class="stat-value">Not selected</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span class="stat-label">Fields:</span>
|
||||
<span id="fields-count" class="stat-value">0</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="session-actions">
|
||||
<button id="generate-code" class="action-button primary" disabled>
|
||||
<span>Generate Code</span>
|
||||
</button>
|
||||
<button id="stop-capture" class="action-button secondary">
|
||||
<span>Stop Capture</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="instructions">
|
||||
<h4>How to use:</h4>
|
||||
<ol>
|
||||
<li>Click "Schema Builder" to start</li>
|
||||
<li>Click on a container element (e.g., product card)</li>
|
||||
<li>Click individual fields inside and name them</li>
|
||||
<li>Generate Python code when done</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<div class="social-links">
|
||||
<a href="https://docs.crawl4ai.com" target="_blank" class="social-link">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<path fill="currentColor" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
||||
</svg>
|
||||
<span>Docs</span>
|
||||
</a>
|
||||
<a href="https://twitter.com/unclecode" target="_blank" class="social-link">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<path fill="currentColor" d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
|
||||
</svg>
|
||||
<span>@unclecode</span>
|
||||
</a>
|
||||
<a href="https://discord.gg/jP8KfhDhyN" target="_blank" class="social-link">
|
||||
<svg viewBox="0 0 24 24" width="16" height="16">
|
||||
<path fill="currentColor" d="M19.27 5.33C17.94 4.71 16.5 4.26 15 4a.09.09 0 00-.07.03c-.18.33-.39.76-.53 1.09a16.09 16.09 0 00-4.8 0c-.14-.34-.35-.76-.54-1.09-.01-.02-.04-.03-.07-.03-1.5.26-2.93.71-4.27 1.33-.01 0-.02.01-.03.02-2.72 4.07-3.47 8.03-3.1 11.95 0 .02.01.04.03.05 1.8 1.32 3.53 2.12 5.24 2.65.03.01.06 0 .07-.02.4-.55.76-1.13 1.07-1.74.02-.04 0-.08-.04-.09-.57-.22-1.11-.48-1.64-.78-.04-.02-.04-.08-.01-.11.11-.08.22-.17.33-.25.02-.02.05-.02.07-.01 3.44 1.57 7.15 1.57 10.55 0 .02-.01.05-.01.07.01.11.09.22.17.33.26.04.03.04.09-.01.11-.52.31-1.07.56-1.64.78-.04.01-.05.06-.04.09.32.61.68 1.19 1.07 1.74.03.01.06.02.09.01 1.72-.53 3.45-1.33 5.25-2.65.02-.01.03-.03.03-.05.44-4.53-.73-8.46-3.1-11.95-.01-.01-.02-.02-.04-.02zM8.52 14.91c-1.03 0-1.89-.95-1.89-2.12s.84-2.12 1.89-2.12c1.06 0 1.9.96 1.89 2.12 0 1.17-.84 2.12-1.89 2.12zm6.97 0c-1.03 0-1.89-.95-1.89-2.12s.84-2.12 1.89-2.12c1.06 0 1.9.96 1.89 2.12 0 1.17-.83 2.12-1.89 2.12z"/>
|
||||
</svg>
|
||||
<span>Discord</span>
|
||||
</a>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="popup.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
112
docs/md_v2/apps/crawl4ai-assistant/popup/popup.js
Normal file
112
docs/md_v2/apps/crawl4ai-assistant/popup/popup.js
Normal file
@@ -0,0 +1,112 @@
|
||||
// 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();
|
||||
});
|
||||
|
||||
// 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 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 });
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user