UNPKG

chromancer

Version:

A powerful command-line interface for automating Chrome browser using Playwright. Perfect for web scraping, automation, testing, and browser workflows.

164 lines (163 loc) 6.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("@oclif/core"); const base_js_1 = require("../../base.js"); class TabsFocus extends base_js_1.BaseCommand { static description = 'Focus a specific tab by URL or title pattern'; static examples = [ '<%= config.bin %> <%= command.id %> "example.com"', '<%= config.bin %> <%= command.id %> "My Document" --title', '<%= config.bin %> <%= command.id %> "github.com" --exact', '<%= config.bin %> <%= command.id %> --interactive', ]; static flags = { ...base_js_1.BaseCommand.baseFlags, title: core_1.Flags.boolean({ description: 'Search by title instead of URL', default: false, }), exact: core_1.Flags.boolean({ description: 'Require exact match instead of partial', default: false, }), interactive: core_1.Flags.boolean({ char: 'i', description: 'Interactively select from matching tabs', default: false, }), }; static args = { pattern: core_1.Args.string({ description: 'Pattern to match against URL or title', required: false, }), }; async run() { const { args, flags } = await this.parse(TabsFocus); await this.connectToChrome(flags.port, flags.host, flags.launch, flags.profile, flags.headless, flags.verbose, flags.keepOpen); if (!this.browser) { this.error('No browser available'); } try { const context = this.browser.contexts()[0]; const pages = context.pages(); if (pages.length === 0) { this.log('No tabs available'); return; } // Get tab information with search field const tabsInfo = await Promise.all(pages.map(async (page, index) => { const url = page.url(); const title = await page.title(); const searchField = flags.title ? title : url; return { index, page, title: title || 'Untitled', url, searchField, isActive: page === this.page, }; })); let matchingTabs = tabsInfo; // Filter by pattern if provided if (args.pattern && !flags.interactive) { const pattern = args.pattern.toLowerCase(); matchingTabs = tabsInfo.filter(tab => { const field = tab.searchField.toLowerCase(); return flags.exact ? field === pattern : field.includes(pattern); }); if (matchingTabs.length === 0) { this.error(`No tabs found matching "${args.pattern}" in ${flags.title ? 'title' : 'URL'}`); } } // Select target tab let targetTab; if (flags.interactive || matchingTabs.length > 1) { // Interactive selection or multiple matches const choices = matchingTabs.map(tab => ({ name: `${tab.isActive ? '▶ ' : ' '}[${tab.index}] ${tab.title} - ${tab.url}`, value: tab, short: `[${tab.index}] ${tab.title}`, })); const inquirer = await Promise.resolve().then(() => __importStar(require('inquirer'))); const { selected } = await inquirer.default.prompt([ { type: 'list', name: 'selected', message: matchingTabs.length > 1 ? `Found ${matchingTabs.length} matching tabs. Select one:` : 'Select tab to focus:', choices, pageSize: 10, }, ]); targetTab = selected; } else if (matchingTabs.length === 1) { targetTab = matchingTabs[0]; } else { this.error('No pattern provided. Use --interactive flag or provide a search pattern'); } // Check if already on target tab if (targetTab.isActive) { this.log('Already focused on selected tab'); return; } // Focus the target tab await targetTab.page.bringToFront(); this.page = targetTab.page; this.log(`🎯 Focused tab [${targetTab.index}]`); this.log(` Title: ${targetTab.title}`); this.log(` URL: ${targetTab.url}`); if (flags.verbose) { this.logVerbose('Focus operation details', { pattern: args.pattern, searchField: flags.title ? 'title' : 'url', matchesFound: matchingTabs.length, selectedIndex: targetTab.index, }); } } catch (error) { this.error(`Failed to focus tab: ${error.message}`); } } } exports.default = TabsFocus;