MCPcopy
hub / github.com/garrytan/gstack / modifyStyle

Function modifyStyle

browse/src/cdp-inspector.ts:495–607  ·  view source on GitHub ↗
(
  page: Page,
  selector: string,
  property: string,
  value: string
)

Source from the content-addressed store, hash-verified

493 * Uses CSS.setStyleTexts in headed mode, falls back to inline style in headless.
494 */
495export async function modifyStyle(
496 page: Page,
497 selector: string,
498 property: string,
499 value: string
500): Promise<StyleModification> {
501 // Validate CSS property name
502 if (!/^[a-zA-Z-]+$/.test(property)) {
503 throw new Error(`Invalid CSS property name: ${property}. Only letters and hyphens allowed.`);
504 }
505
506 // Validate CSS value — block data exfiltration patterns
507 const DANGEROUS_CSS = /url\s*\(|expression\s*\(|@import|javascript:|data:/i;
508 if (DANGEROUS_CSS.test(value)) {
509 throw new Error('CSS value rejected: contains potentially dangerous pattern.');
510 }
511
512 let oldValue = '';
513 let source = 'inline';
514 let sourceLine = 0;
515 let method: 'setStyleTexts' | 'inline' = 'inline';
516
517 try {
518 // Try CDP approach first
519 const session = await getOrCreateSession(page);
520 const result = await inspectElement(page, selector);
521 oldValue = result.computedStyles[property] || '';
522
523 // Find the most-specific matching rule that has this property
524 let targetRule: InspectorResult['matchedRules'][0] | null = null;
525 for (const rule of result.matchedRules) {
526 if (rule.userAgent) continue;
527 const hasProp = rule.properties.some(p => p.name === property);
528 if (hasProp && rule.styleSheetId && rule.range) {
529 targetRule = rule;
530 break;
531 }
532 }
533
534 if (targetRule?.styleSheetId && targetRule.range) {
535 // Modify via CSS.setStyleTexts
536 const range = targetRule.range as any;
537
538 // Get current style text
539 const styleText = await session.send('CSS.getStyleSheetText', {
540 styleSheetId: targetRule.styleSheetId,
541 });
542
543 // Build new style text by replacing the property value
544 const currentProps = targetRule.properties;
545 const newPropsText = currentProps
546 .map(p => {
547 if (p.name === property) {
548 return `${p.name}: ${value}`;
549 }
550 return `${p.name}: ${p.value}`;
551 })
552 .join('; ');

Callers 3

handleWriteCommandFunction · 0.90
makeFetchHandlerFunction · 0.90
undoModificationFunction · 0.85

Calls 4

getOrCreateSessionFunction · 0.85
inspectElementFunction · 0.85
pushModificationFunction · 0.85
sendMethod · 0.80

Tested by

no test coverage detected