Привет, Хабр! Нейросети стремительно входят в нашу жизнь, и вот уже Яндекс встроил свою «Алису» прямо в поисковую выдачу. Иногда это удобно, но часто хочется видеть классический список ссылок, а не огромный блок сгенерированного текста, который отодвигает всё остальное вниз.

Я решил вернуть себе контроль над поиском и написал простое браузерное расширение, которое убирает всё лишнее. Назвал его «Bye Bye Alice AI». В этой короткой статье я покажу, как оно устроено.

Задача

Нужно было убрать два основных элемента:

пример поисковой выдачи
пример поисковой выдачи
  1. Большой блок с нейроответом (.FuturisSearchWrapper и .serp-item__futuris-snippet).

  2. Вкладку «Алиса» в навигации.

А также добавить возможность включать и отключать эту функцию.

Как это работает?

Вся магия происходит в нескольких файлах.

1. manifest.json — паспорт расширения

Это главный файл, где мы описываем наше расширение, запрашиваем нужные права (storage для сохранения настроек) и указываем, какие скрипты и где запускать.

{
  "manifest_version": 3,
  "name": "Bye Bye Alice AI",
  "version": "3.0",
  "description": "Removes Yandex AI (Alice) elements from search results and navigation.",
  "permissions": ["storage"],
  "host_permissions": ["*://*.yandex.ru/*"],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["*://*.yandex.ru/search/*"],
      "js": ["remover.js"],
      "run_at": "document_start"
    }
  ],
  "action": {
    "default_popup": "popup.html",
    "default_icon": "icon_inactive.png"
  },
  "icons": {
    "128": "icon128.png"
  }
}

2. remover.js — скрипт-чистильщик

Этот скрипт запускается на страницах поиска Яндекса. Его задача — найти и удалить мешающие блоки.

const SELECTORS_TO_REMOVE = [
  '.FuturisSearchWrapper',
  'a.HeaderNav-Tab[href*="promo=force_neuro"]',
  'li.serp-item.serp-item__futuris-snippet'
];
let isEnabled = true;

/**
 * Находит и удаляет целевые элементы со страницы.
 */
function removeTargetElements() {
  if (!isEnabled) return;
  try {
    SELECTORS_TO_REMOVE.forEach(selector => {
      document.querySelectorAll(selector).forEach(el => el.remove());
    });
  } catch (error) {}
}

/**
 * Блокирует переход по промо-ссылкам.
 * @param {MouseEvent} event - Событие клика.
 */
function blockPromoNavigation(event) {
  if (!isEnabled) return;
  const targetLink = event.target.closest('a');
  if (targetLink && targetLink.href.includes('promo=force_neuro')) {
    event.preventDefault();
    event.stopPropagation();
  }
}

const observer = new MutationObserver(removeTargetElements);

/**
 * Инициализирует MutationObserver для отслеживания изменений в DOM.
 */
function initializeObserver() {
  if (document.body) {
    observer.observe(document.body, {
      childList: true,
      subtree: true,
    });
    removeTargetElements();
  } else {
    setTimeout(initializeObserver, 100);
  }
}

chrome.storage.sync.get('isEnabled', (data) => {
  isEnabled = data.isEnabled !== false;
  if (isEnabled) {
    initializeObserver();
  }
});

chrome.storage.onChanged.addListener((changes, namespace) => {
  if (changes.isEnabled) {
    isEnabled = changes.isEnabled.newValue;
    if (isEnabled) {
      initializeObserver();
    } else {
      observer.disconnect();
    }
  }
});

document.addEventListener('click', blockPromoNavigation, true);

3. popup.html и popup.js — окно настроек

Чтобы пользователь мог сам решать, нужна ему «Алиса» или нет, я добавил простое всплывающее окно с переключателем. Его состояние сохраняется в chrome.storage.

4. background.js — управление иконкой

Маленькая, но важная деталь: иконка расширения меняет цвет в зависимости от того, включена блокировка или нет. Цветная — активна, серая — выключена. Это делается в фоновом скрипте, который следит за изменением настроек.

Результат

Получилось легкое и простое расширение, которое делает ровно одну вещь, но делает ее хорошо. Поиск снова стал чистым и быстрым, а если вдруг понадобится нейросеть — ее можно вернуть одним кликом.

Если вам, как и мне, не хватало такой возможности, можете забрать расширение на GitHub. Проект очень простой, так что может стать отличным примером для тех, кто хочет попробовать написать свое первое расширение.

Спасибо за внимание!

P.S. : Это моя первая статья на Хабре и буду благодарен за карму или/и приглашение