A Chrome extension that allows you to easily copy articles with formatting and automatically insert them into Gmail compose. Features configurable selectors for different websites and intelligent field detection.
- One-click article extraction from any website
- Automatic Gmail integration with compose window pre-filling
- Default recipient auto-fill - set default email addresses per site
- Configurable selectors for different websites
- Interactive XPath picker for selecting article elements directly from the active page
- Dynamic content picker for copying any hovered page element to the clipboard without adding a site rule
- CSS and XPath selector support for article extraction
- Stable rule editing with reduced flicker, caret preservation, and automatic focus on newly added site rules
- Intelligent field detection for To, Subject, and Body fields
- Enhanced stability with multiple fallback selectors
- Comprehensive debugging tools for troubleshooting
- JSON import/export of site configurations
- Tracing spans & events for diagnostics (
tracing.js) - Automatic clipboard copy with configurable modes
- Toast notifications for copy success/failure
- Responsive image best-fit sizing in Gmail body
- Download or clone this repository
- Open Chrome and navigate to
chrome://extensions/ - Enable Developer mode (toggle in top right)
- Click "Load unpacked" and select the extension folder
- Pin the extension to your toolbar for easy access
- Open Side Panel: Click the extension icon and choose "Open side panel" (or use Chrome side panel toggle and select the extension).
- Click the extension icon to open the configuration popup
- Add site configurations:
- Name: Friendly name for the site
- Host Pattern: Regular expression matching the site URL
- Selectors: CSS selectors or XPath selectors for article content (multiple selectors supported)
- Use Pick next to a selector to hover elements on the active page and click one to save a unique indexed XPath.
- New site rules automatically focus the Name field, and edits are saved without refreshing the card on every keystroke.
// Habr.com
Name: Habr
Host Pattern: habr\.com
Selectors: [data-test-id="article-body"]
// Medium
Name: Medium
Host Pattern: medium\.com
Selectors: article, .postArticle-content
// Dev.to
Name: Dev.To
Host Pattern: dev\.to
Selectors: .crayons-article__main- Open side panel to configure sites (instead of popup)
- Navigate to an article on a configured website
- Click "Send Article to Gmail" button (appears on supported sites)
- Gmail compose window opens with:
- To field: Pre-filled with configured email
- Subject: Article title
- Body: Article content with source link
- Optional: Clipboard already contains the copied content (HTML or plain text per settings)
Open the popup Settings section to toggle:
- Enable automatic clipboard copy (on by default)
- Copy as plain text only (disables HTML flavor)
- Show toast notifications (success/failure feedback)
Use Pick Content in the popup or side panel when you want to copy page content without creating a site configuration:
- Open the target page in the active tab.
- Click
Pick Content. - Hover the element you want to copy.
- Click the highlighted element to copy it to the clipboard.
- Press
Escto cancel picker mode.
The copied payload preserves HTML formatting by default, includes a plain text clipboard flavor when available, converts relative URLs inside the selected HTML to absolute URLs, and respects the Copy as plain text only setting.
UI Buttons (Side Panel/Popup):
- Click
Exportto downloadsiteConfigs.jsonbackup. - Click
Importand choose a previously exported file to replace all configs. - Validation ensures each config has
hostPatternandselectors(backwards compatible with legacytoEmail).
Console Commands (Side Panel/Popup):
Open side panel, press F12, open the Console tab, then use:
// List all configs in table format
UAS_CONFIG_LIST()
// Export to console and clipboard
UAS_CONFIG_EXPORT()
// Import from JSON string or array
UAS_CONFIG_IMPORT('[{"name":"Site","hostPattern":"example\\.com","selectors":[".article"]}]')
// Export from old extension version (all storage)
UAS_EXPORT_OLD()For Old Extension Versions (Manual Migration):
Export from old version console:
chrome.storage.local.get({ siteConfigs: [] }, d => {
console.table(d.siteConfigs);
console.log(JSON.stringify(d.siteConfigs, null, 2));
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(JSON.stringify(d.siteConfigs, null, 2));
console.log('Copied to clipboard');
}
});Import into old version console:
chrome.storage.local.set({ siteConfigs: [
/* paste your JSON array here */
]}, () => {
console.log('Imported');
location.reload();
});The extension emits lightweight spans/events for key actions (extraction, clipboard copy, Gmail insertion). In DevTools console:
UAS_TRACE_DUMP(); // table of recent spans/eventsBackground trace buffer accessible:
chrome.runtime.sendMessage({type:'UAS_TRACE_GET'}, r => console.log(r.traces));Inserted article images are auto-adjusted to fit Gmail compose width (max-width:100%; height:auto;).
Open Gmail and press F12 to access developer console, then use:
// Analyze all Gmail elements
UAS_DEBUG.checkGmailElements();
// Test To field population
UAS_DEBUG.testToField('your-email@example.com');
// Test Subject field population
UAS_DEBUG.testSubjectField('Your Subject');
// Force content insertion
UAS_DEBUG.forceInsert();
// Check storage contents
UAS_DEBUG.checkStorage();- Open Gmail and developer console (F12)
- Run element analysis:
UAS_DEBUG.checkGmailElements();
- Look for To field candidates in the output
- Test field population:
UAS_DEBUG.testToField('test@example.com');
- Check if compose window is fully loaded
- Refresh Gmail page after saving article
- Try opening Gmail in a new tab instead of popup
- Run debug analysis to identify correct selectors
The extension uses multiple strategies to find Gmail fields:
To Field Selectors:
input[aria-label*="To" i]- By aria-labeldiv[role="combobox"][aria-label*="To" i]- Modern Gmail elementsinput[type="email"]- By field type- Contextual analysis of parent elements
Subject Field Selectors:
input[name="subject"]andinput[name="subjectbox"]input[aria-label*="Subject" i]- By aria-labeldiv.aoT input- Gmail-specific selectors
Body Field Detection:
- Size and visibility validation
- Exclusion of To/Subject fields
- Multiple contenteditable selectors
- Initial wait for compose elements to load
- MutationObserver for DOM changes
- Periodic checks as fallback
- Element validation (size, visibility, context)
|-- manifest.json # Extension manifest
|-- background.js # Service worker
|-- content_script_gmail.js # Gmail integration
|-- content_script_article.js # Article extraction
|-- popup.html # Configuration interface
|-- popup.js # Configuration logic
|-- debug.js # Debug utilities
|-- style.css # Popup styles
|-- test_gmail.html # Testing tool
`-- icon128.png # Extension icon
| Issue | Solution |
|---|---|
| Fields not populating | Run UAS_DEBUG.checkGmailElements() to identify selectors |
| Content insertion fails | Check element size validation and visibility |
| Extension not detecting article | Verify site configuration and selectors |
- Added
Pick Contentin the popup and side panel for copying any hovered page element without adding a site configuration. - Reused the existing picker highlight model while keeping dynamic copy separate from saved XPath selector rules.
- Preserved rich HTML clipboard output by default, with plain text mode and toast notifications following the existing settings.
- Reduced flicker while typing in site rules by ignoring storage refreshes caused by the current edit session.
- Kept the text cursor stable when editing fields and selectors.
- Focus now moves to the new rule's Name field after clicking
Add Site. - Site card titles update live while editing the Name field.
- Added a
Pickaction for selector fields that highlights page elements and inserts a unique indexed XPath on click. - Added XPath support to article extraction while keeping existing CSS selectors compatible.
- Fixed rule focus restoration so duplicate selector or host values no longer move editing focus to another rule.
- Refreshed side panel and popup UI with cleaner config cards, sticky tools, site count, search clear, duplicate site, and empty states.
- Fixed filtered config edits so search results no longer overwrite the full saved site list.
- Fixed Gmail pending article cleanup so stored article data is cleared only after successful body insertion.
- Improved Gmail compose body detection for the
?fs=1&tf=cmcompose popup and retry flow.
- Replaced popup with Chrome side panel (
sidepanel.html). - Updated manifest to include
side_panelentry. - Maintains all previous settings & functionality.
- Added JSON import/export of site configurations.
- Integrated tracing module (
tracing.js) with spans/events. - Automatic clipboard copy (HTML+plain text) with settings to disable and plain-text-only mode.
- Toast notifications for clipboard success/failure.
- Responsive best-fit image sizing in Gmail compose body.
- Added user settings persistence (
userSettings). - Minor UI enhancements in popup.
- Extended selectors for all Gmail fields (15+ for To field)
- Improved field population logic with focus and event triggers
- Enhanced debugging with element analysis
- Better waiting mechanisms for Gmail loading
- Multiple selector fallbacks
- MutationObserver for DOM changes
- Enhanced logging and debugging
- Improved timing and delays
- Basic article extraction
- Gmail compose integration
- Configurable site selectors
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
If you encounter issues:
- Check the troubleshooting guide above
- Use the debug console commands
- Open an issue with debug output
- Include Chrome version and Gmail interface language
Made for productivity and automation