Поместите xpath к выбранному элементу в расширении боковой панели html

Итак, я пытаюсь разработать расширение для Chrome, которое будет экспортировать список xpaths выбранных элементов со страницы. Однако я не могу вычислить xpath текущего выбранного элемента на панели devtools.

Я попытался использовать getPathTo из этот ответ, но функция не может получить доступ к ссылке на элемент $0.

С помощью этого кода я могу распечатать тег нового выбранного элемента:

chrome.devtools.panels.elements.onSelectionChanged.addListener(function () {
    var expression = "(function(){console.log($0);})()"
    chrome.devtools.inspectedWindow.eval(expression)
});

Но если я попытаюсь:

chrome.devtools.panels.elements.onSelectionChanged.addListener(function () {
    var expression = "(function(){console.log(getPathTo($0));})()"
    chrome.devtools.inspectedWindow.eval(expression)
});

Он жалуется на неопределенную ссылку на $0.

В коде также есть эта функция для установки HTML-кода боковой панели:

chrome.devtools.panels.elements.createSidebarPane(
    "Chrome Extension",
    function (sidebar) {
        sidebar.setPage("sidebar/sidebar.html");
    }
);

И sidebar/sidebar.html — это простая HTML-страница со списком элементов внутри, куда я хочу добавить путь ко всем выбранным элементам и кнопку для копирования списка в буфер обмена. Как я могу использовать ссылку на выбранный элемент внутри функции? Кроме того, как я могу передать результаты на HTML-страницу?


person Gabriel Cardoso    schedule 08.04.2020    source источник
comment
Концептуально оба выражения одинаковы, поэтому наблюдаемое поведение определенно выглядит как ошибка, которую я не могу воспроизвести (код работает для меня), поэтому я предполагаю, что вы не определили getPathTo в контексте страницы, поскольку eval работает в контексте страницы, если только вы указываете иначе, см. документацию.   -  person wOxxOm    schedule 08.04.2020
comment
@wOxxOm Мне действительно тяжело с документацией и отсутствием примеров ... Как определить getPathTo в контексте страницы? Кроме того, если я передаю { useContentScriptContext: true } в качестве параметра для eval, я не вижу ни сообщения об ошибке, ни сообщения в журнале... Похоже, ничего не происходит.   -  person Gabriel Cardoso    schedule 10.04.2020
comment
Я имею в виду отсутствие примеров использования inspectedWindow. Я знаю, что есть страница примеров, но там нет ни одного примера, использующего эту функциональность, и фрагменты кода в документации не очень помогают.   -  person Gabriel Cardoso    schedule 10.04.2020
comment
В документации говорится, что на странице должен быть запущен скрипт содержимого, поэтому я думаю, что у вас его не было.   -  person wOxxOm    schedule 10.04.2020
comment
Вторую часть, сообщение между скриптами, я нашел здесь   -  person Gabriel Cardoso    schedule 14.04.2020


Ответы (1)


chrome.devtools.inspectedWindow.eval запускается в среде вкладки, а не в среде расширения. Веб-страница — это совершенно другой контекст со своими document, DOM, window, глобальными переменными и так далее. Чтобы иметь возможность вызвать getPathTo там, вам нужно поместить его туда.

chrome.devtools.inspectedWindow.eval(`(${() => {
  console.log(getPathTo($0));
  function getPathTo(element) {
    // ...................
    // ..... code
    // ...................
  }
}})()`);

Безопасный подход

По умолчанию eval() запускается в контексте страницы, поэтому на некоторых страницах ваш код может дать сбой, если они переопределяют или искажают стандартные объекты и прототипы. Вместо этого вы можете запустить код в изолированном мире скриптов контента:

chrome.devtools.panels.elements.onSelectionChanged.addListener(() => {
  chrome.tabs.executeScript({
    code: `function getPathTo(element) {
      // ...................
      // ..... code
      // ...................
    }`,
    runAt: 'document_start',
  }, () => {
    chrome.devtools.inspectedWindow.eval(`(${() => {
      console.log(getPathTo($0));
    }})()`, {
      useContentScriptContext: true,
    });
  });
});
person wOxxOm    schedule 10.04.2020