Add browser extension and shell completions (Milestones 12-13)

M12: Browser Extension
- Chrome/Edge Manifest V3 extension
- Popup UI for saving pages
- Context menu integration (save page/selection/link)
- Background service worker
- Content script for extraction

M13: Shell Completions
- Bash, Zsh, Fish, PowerShell completions
- Dynamic node ID completion
- Dynamic tag completion
- Dynamic graph completion
- Auto-install command (--install)
This commit is contained in:
2026-02-03 11:35:41 +01:00
parent b1c62c5da9
commit f21426fc43
11 changed files with 1248 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
// Content script for Cortex browser extension
// Injected into web pages to extract content
// Extract page content
function extractContent() {
const title = document.title;
// Get selected text
const selection = window.getSelection()?.toString() || '';
// Try to find main content using common selectors
let content = '';
const contentSelectors = [
'article',
'[role="main"]',
'main',
'.post-content',
'.article-content',
'.entry-content',
'.content',
'#content',
];
for (const selector of contentSelectors) {
const el = document.querySelector(selector);
if (el && el.textContent) {
content = el.textContent;
break;
}
}
// Fall back to body content
if (!content) {
content = document.body.textContent || '';
}
// Clean up content
content = content
.replace(/\s+/g, ' ')
.replace(/\n{3,}/g, '\n\n')
.trim()
.slice(0, 100000); // Limit to 100k chars
// Get meta description
const metaDesc = document.querySelector('meta[name="description"]')?.content || '';
// Get author
const author = document.querySelector('meta[name="author"]')?.content ||
document.querySelector('[rel="author"]')?.textContent || '';
// Get published date
const datePublished = document.querySelector('meta[property="article:published_time"]')?.content ||
document.querySelector('time[datetime]')?.getAttribute('datetime') || '';
return {
title,
content,
selection,
excerpt: metaDesc || content.slice(0, 200),
url: window.location.href,
author,
datePublished,
};
}
// Listen for messages from popup or background
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'extract') {
try {
const data = extractContent();
sendResponse(data);
} catch (err) {
sendResponse({ error: err.message });
}
}
return true; // Keep channel open for async response
});
// Make extract function available globally for background script injection
window.__cortexExtract = extractContent;