chromancer
Version:
A powerful command-line interface for automating Chrome browser using Playwright. Perfect for web scraping, automation, testing, and browser workflows.
118 lines (117 loc) • 4.86 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@oclif/core");
const base_js_1 = require("../base.js");
const evaluation_js_1 = require("../utils/evaluation.js");
class Evaluate extends base_js_1.BaseCommand {
static description = 'Execute JavaScript in the page context';
static examples = [
'<%= config.bin %> <%= command.id %> "document.title"',
'<%= config.bin %> <%= command.id %> "document.querySelectorAll(\'a\').length" --return-result',
'<%= config.bin %> <%= command.id %> "localStorage.getItem(\'token\')" --json',
];
static flags = {
...base_js_1.BaseCommand.baseFlags,
'return-result': core_1.Flags.boolean({
description: 'Print the result of the evaluation',
default: true,
}),
json: core_1.Flags.boolean({
description: 'Output result as raw JSON',
default: false,
}),
selector: core_1.Flags.string({
description: 'Evaluate within the context of a specific element',
}),
};
static args = {
script: core_1.Args.string({
description: 'JavaScript code to execute',
required: true,
}),
};
async run() {
const { args, flags } = await this.parse(Evaluate);
await this.connectToChrome(flags.port, flags.host, flags.launch, flags.profile, flags.headless, flags.verbose, flags.keepOpen);
if (!this.page) {
this.error('No page available');
}
try {
this.log(`🔧 Evaluating JavaScript...`);
this.logVerbose('Script to evaluate', { script: args.script });
let result;
if (flags.selector) {
// Evaluate within element context
this.log(`📍 Using element context: ${flags.selector}`);
const element = await this.page.$(flags.selector);
if (!element) {
this.error(`Element not found: ${flags.selector}`);
}
result = await element.evaluate((el, script) => {
// Create a function that has 'el' in scope
const fn = new Function('el', `return ${script}`);
return fn(el);
}, args.script);
}
else {
// Evaluate in page context
result = await (0, evaluation_js_1.safeEvaluate)(this.page, args.script);
}
if (flags['return-result']) {
if (flags.json) {
// Raw JSON output for scripting
console.log(JSON.stringify(result));
}
else {
// Pretty formatted output
this.log('📤 Result:');
if (result === undefined) {
this.log('undefined');
}
else if (result === null) {
this.log('null');
}
else if (typeof result === 'object') {
this.log(JSON.stringify(result, null, 2));
}
else {
this.log(String(result));
}
}
// Log type information if verbose
if (flags.verbose && !flags.json) {
this.logVerbose('Result type', {
type: typeof result,
isArray: Array.isArray(result),
constructor: result?.constructor?.name,
});
}
}
else {
this.log('✅ JavaScript executed successfully');
}
// Log performance metrics if verbose
if (flags.verbose) {
const metrics = await this.page.evaluate(() => {
if (typeof performance !== 'undefined' && performance.memory) {
return {
usedJSHeapSize: Math.round(performance.memory.usedJSHeapSize / 1024 / 1024) + 'MB',
totalJSHeapSize: Math.round(performance.memory.totalJSHeapSize / 1024 / 1024) + 'MB',
};
}
return null;
});
if (metrics) {
this.logVerbose('Memory usage', metrics);
}
}
}
catch (error) {
if (error.name === 'SyntaxError' || error.message.includes('SyntaxError')) {
this.error(`JavaScript syntax error: ${error.message}`);
}
this.error(`Failed to evaluate JavaScript: ${error.message}`);
}
}
}
exports.default = Evaluate;