github-codewiki-jumper

One click jump from GitHub to CodeWiki, DeepWiki and Zread

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name               github-codewiki-jumper
// @name:zh-CN         GitHub 代码百科跳转助手
// @namespace          https://github.com/qixing-jk/github-codewiki-jumper
// @version            1.2.6
// @author             qixing-jk
// @description        One click jump from GitHub to CodeWiki, DeepWiki and Zread
// @description:zh-CN  一键从 GitHub仓库 跳转到 CodeWiki, DeepWiki 和 Zread
// @match              *://github.com/*
// ==/UserScript==

(function () {
  'use strict';

  const JUMPER_CONTAINER_ID = "jumper-buttons-container";
  const INJECTION_SELECTOR = '[class*="SidebarSection-module__sidebarSection"].hide-sm.hide-md';
  const SIDEBAR_SELECTOR = 'div[class*="CodeViewSidebar-module__borderGrid"]';
  const normalizeRepositoryName = (value) => {
    const parts = value == null ? void 0 : value.trim().split("/").map((part) => part.trim());
    if (!parts || parts.length !== 2 || parts.some((part) => !part)) {
      return null;
    }
    return parts.join("/");
  };
  const getRepositoryNameFromPath = () => {
    const [owner, repository] = window.location.pathname.split("/").filter(Boolean);
    if (!owner || !repository) {
      return null;
    }
    try {
      return normalizeRepositoryName(`${decodeURIComponent(owner)}/${decodeURIComponent(repository)}`);
    } catch {
      return null;
    }
  };
  const getRepositoryName = () => {
    var _a, _b;
    const candidates = [
      (_a = document.querySelector('meta[name="current-repo-nwo"]')) == null ? void 0 : _a.getAttribute("content"),
      (_b = document.querySelector('meta[name="octolytics-dimension-repository_nwo"]')) == null ? void 0 : _b.getAttribute("content"),
      getRepositoryNameFromPath()
    ];
    for (const candidate of candidates) {
      const repositoryName = normalizeRepositoryName(candidate);
      if (repositoryName) {
        return repositoryName;
      }
    }
    return null;
  };
  const buildRepositoryPath = (repositoryName) => {
    const normalizedRepositoryName = normalizeRepositoryName(repositoryName);
    if (!normalizedRepositoryName) {
      return null;
    }
    return `/${normalizedRepositoryName.split("/").map((part) => encodeURIComponent(part)).join("/")}`;
  };
  const buildDeepWikiUrl = (pathname) => {
    return `https://deepwiki.com${pathname}`;
  };
  const buildCodeWikiUrl = (hostname, pathname) => {
    return `https://codewiki.google/${hostname}${pathname}`;
  };
  const buildZReadUrl = (pathname) => {
    return `https://zread.ai${pathname}`;
  };
  const deepWikiIconUrl = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='110%20110%20460%20500'%3e%3cpath%20style='fill:%2321c19a'%20class=''%20d='M418.73,332.37c9.84-5.68,22.07-5.68,31.91,0l25.49,14.71c.82.48,1.69.8,2.58,1.06.19.06.37.11.55.16.87.21,1.76.34,2.65.35.04,0,.08.02.13.02.1,0,.19-.03.29-.04.83-.02,1.64-.13,2.45-.32.14-.03.28-.05.42-.09.87-.24,1.7-.59,2.5-1.03.08-.04.17-.06.25-.1l50.97-29.43c3.65-2.11,5.9-6.01,5.9-10.22v-58.86c0-4.22-2.25-8.11-5.9-10.22l-50.97-29.43c-3.65-2.11-8.15-2.11-11.81,0l-50.97,29.43c-.08.04-.13.11-.2.16-.78.48-1.51,1.02-2.15,1.66-.1.1-.18.21-.28.31-.57.6-1.08,1.26-1.51,1.97-.07.12-.15.22-.22.34-.44.77-.77,1.6-1.03,2.47-.05.19-.1.37-.14.56-.22.89-.37,1.81-.37,2.76v29.43c0,11.36-6.11,21.95-15.95,27.63-9.84,5.68-22.06,5.68-31.91,0l-25.49-14.71c-.82-.48-1.69-.8-2.57-1.06-.19-.06-.37-.11-.56-.16-.88-.21-1.76-.34-2.65-.34-.13,0-.26.02-.4.02-.84.02-1.66.13-2.47.32-.13.03-.27.05-.4.09-.87.24-1.71.6-2.51,1.04-.08.04-.16.06-.24.1l-50.97,29.43c-3.65,2.11-5.9,6.01-5.9,10.22v58.86c0,4.22,2.25,8.11,5.9,10.22l50.97,29.43c.08.04.17.06.24.1.8.44,1.64.79,2.5,1.03.14.04.28.06.42.09.81.19,1.62.3,2.45.32.1,0,.19.04.29.04.04,0,.08-.02.13-.02.89,0,1.77-.13,2.65-.35.19-.04.37-.1.56-.16.88-.26,1.75-.59,2.58-1.06l25.49-14.71c9.84-5.68,22.06-5.68,31.91,0,9.84,5.68,15.95,16.27,15.95,27.63v29.43c0,.95.15,1.87.37,2.76.05.19.09.37.14.56.25.86.59,1.69,1.03,2.47.07.12.15.22.22.34.43.71.94,1.37,1.51,1.97.1.1.18.21.28.31.65.63,1.37,1.18,2.15,1.66.07.04.13.11.2.16l50.97,29.43c1.83,1.05,3.86,1.58,5.9,1.58s4.08-.53,5.9-1.58l50.97-29.43c3.65-2.11,5.9-6.01,5.9-10.22v-58.86c0-4.22-2.25-8.11-5.9-10.22l-50.97-29.43c-.08-.04-.16-.06-.24-.1-.8-.44-1.64-.8-2.51-1.04-.13-.04-.26-.05-.39-.09-.82-.2-1.65-.31-2.49-.33-.13,0-.25-.02-.38-.02-.89,0-1.78.13-2.66.35-.18.04-.36.1-.54.15-.88.26-1.75.59-2.58,1.07l-25.49,14.72c-9.84,5.68-22.07,5.68-31.9,0-9.84-5.68-15.95-16.27-15.95-27.63s6.11-21.95,15.95-27.63Z'%3e%3c/path%3e%3cpath%20style='fill:%233969ca'%20d='M141.09,317.65l50.97,29.43c1.83,1.05,3.86,1.58,5.9,1.58s4.08-.53,5.9-1.58l50.97-29.43c.08-.04.13-.11.2-.16.78-.48,1.51-1.02,2.15-1.66.1-.1.18-.21.28-.31.57-.6,1.08-1.26,1.51-1.97.07-.12.15-.22.22-.34.44-.77.77-1.6,1.03-2.47.05-.19.1-.37.14-.56.22-.89.37-1.81.37-2.76v-29.43c0-11.36,6.11-21.95,15.96-27.63s22.06-5.68,31.91,0l25.49,14.71c.82.48,1.69.8,2.57,1.06.19.06.37.11.56.16.87.21,1.76.34,2.64.35.04,0,.09.02.13.02.1,0,.19-.04.29-.04.83-.02,1.65-.13,2.45-.32.14-.03.28-.05.41-.09.87-.24,1.71-.6,2.51-1.04.08-.04.16-.06.24-.1l50.97-29.43c3.65-2.11,5.9-6.01,5.9-10.22v-58.86c0-4.22-2.25-8.11-5.9-10.22l-50.97-29.43c-3.65-2.11-8.15-2.11-11.81,0l-50.97,29.43c-.08.04-.13.11-.2.16-.78.48-1.51,1.02-2.15,1.66-.1.1-.18.21-.28.31-.57.6-1.08,1.26-1.51,1.97-.07.12-.15.22-.22.34-.44.77-.77,1.6-1.03,2.47-.05.19-.1.37-.14.56-.22.89-.37,1.81-.37,2.76v29.43c0,11.36-6.11,21.95-15.95,27.63-9.84,5.68-22.07,5.68-31.91,0l-25.49-14.71c-.82-.48-1.69-.8-2.58-1.06-.19-.06-.37-.11-.55-.16-.88-.21-1.76-.34-2.65-.35-.13,0-.26.02-.4.02-.83.02-1.66.13-2.47.32-.13.03-.27.05-.4.09-.87.24-1.71.6-2.51,1.04-.08.04-.16.06-.24.1l-50.97,29.43c-3.65,2.11-5.9,6.01-5.9,10.22v58.86c0,4.22,2.25,8.11,5.9,10.22Z'%3e%3c/path%3e%3cpath%20style='fill:%230294de'%20class=''%20d='M396.88,484.35l-50.97-29.43c-.08-.04-.17-.06-.24-.1-.8-.44-1.64-.79-2.51-1.03-.14-.04-.27-.06-.41-.09-.81-.19-1.64-.3-2.47-.32-.13,0-.26-.02-.39-.02-.89,0-1.78.13-2.66.35-.18.04-.36.1-.54.15-.88.26-1.76.59-2.58,1.07l-25.49,14.72c-9.84,5.68-22.06,5.68-31.9,0-9.84-5.68-15.96-16.27-15.96-27.63v-29.43c0-.95-.15-1.87-.37-2.76-.05-.19-.09-.37-.14-.56-.25-.86-.59-1.69-1.03-2.47-.07-.12-.15-.22-.22-.34-.43-.71-.94-1.37-1.51-1.97-.1-.1-.18-.21-.28-.31-.65-.63-1.37-1.18-2.15-1.66-.07-.04-.13-.11-.2-.16l-50.97-29.43c-3.65-2.11-8.15-2.11-11.81,0l-50.97,29.43c-3.65,2.11-5.9,6.01-5.9,10.22v58.86c0,4.22,2.25,8.11,5.9,10.22l50.97,29.43c.08.04.17.06.25.1.8.44,1.63.79,2.5,1.03.14.04.29.06.43.09.8.19,1.61.3,2.43.32.1,0,.2.04.3.04.04,0,.09-.02.13-.02.88,0,1.77-.13,2.64-.34.19-.04.37-.1.56-.16.88-.26,1.75-.59,2.57-1.06l25.49-14.71c9.84-5.68,22.06-5.68,31.91,0,9.84,5.68,15.95,16.27,15.95,27.63v29.43c0,.95.15,1.87.37,2.76.05.19.09.37.14.56.25.86.59,1.69,1.03,2.47.07.12.15.22.22.34.43.71.94,1.37,1.51,1.97.1.1.18.21.28.31.65.63,1.37,1.18,2.15,1.66.07.04.13.11.2.16l50.97,29.43c1.83,1.05,3.86,1.58,5.9,1.58s4.08-.53,5.9-1.58l50.97-29.43c3.65-2.11,5.9-6.01,5.9-10.22v-58.86c0-4.22-2.25-8.11-5.9-10.22Z'%3e%3c/path%3e%3c/svg%3e";
  const codeWikiIconUrl = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20fill='none'%20viewBox='-20%20-20%20320%20320'%3e%3cpath%20fill='%23007af4'%20d='M119.166%204.013a56.1%2056.1%200%200%201%2041.668%200l113.289%2045.316c7.836%203.135%207.836%2014.228%200%2017.363L206.34%2093.805c-4.694%201.877-4.694%208.521%200%2010.399l67.782%2027.114c7.837%203.134%207.836%2014.227%200%2017.362l-67.781%2027.113c-4.694%201.877-4.694%208.522%200%2010.399l67.781%2027.113c7.837%203.134%207.836%2014.228%200%2017.362l-113.289%2045.317a56.1%2056.1%200%200%201-41.667%200L5.877%20230.667c-7.836-3.134-7.836-14.227%200-17.362l67.78-27.113c4.695-1.877%204.695-8.522%200-10.399L5.878%20148.68c-7.836-3.135-7.836-14.228%200-17.362l67.782-27.114c4.694-1.878%204.694-8.522%200-10.4L5.879%2066.693c-7.837-3.135-7.837-14.228%200-17.363z'/%3e%3cpath%20fill='url(%23a)'%20d='M119.166%204.013a56.1%2056.1%200%200%201%2041.668%200l113.289%2045.316c7.836%203.135%207.836%2014.228%200%2017.363L206.34%2093.805c-4.694%201.877-4.694%208.521%200%2010.399l67.782%2027.114c7.837%203.134%207.836%2014.227%200%2017.362l-67.781%2027.113c-4.694%201.877-4.694%208.522%200%2010.399l67.781%2027.113c7.837%203.134%207.836%2014.228%200%2017.362l-113.289%2045.317a56.1%2056.1%200%200%201-41.667%200L5.877%20230.667c-7.836-3.134-7.836-14.227%200-17.362l67.78-27.113c4.695-1.877%204.695-8.522%200-10.399L5.878%20148.68c-7.836-3.135-7.836-14.228%200-17.362l67.782-27.114c4.694-1.878%204.694-8.522%200-10.4L5.879%2066.693c-7.837-3.135-7.837-14.228%200-17.363z'/%3e%3cpath%20fill='url(%23b)'%20d='M119.166%204.013a56.1%2056.1%200%200%201%2041.668%200l113.289%2045.316c7.836%203.135%207.836%2014.228%200%2017.363L206.34%2093.805c-4.694%201.877-4.694%208.521%200%2010.399l67.782%2027.114c7.837%203.134%207.836%2014.227%200%2017.362l-67.781%2027.113c-4.694%201.877-4.694%208.522%200%2010.399l67.781%2027.113c7.837%203.134%207.836%2014.228%200%2017.362l-113.289%2045.317a56.1%2056.1%200%200%201-41.667%200L5.877%20230.667c-7.836-3.134-7.836-14.227%200-17.362l67.78-27.113c4.695-1.877%204.695-8.522%200-10.399L5.878%20148.68c-7.836-3.135-7.836-14.228%200-17.362l67.782-27.114c4.694-1.878%204.694-8.522%200-10.4L5.879%2066.693c-7.837-3.135-7.837-14.228%200-17.363z'/%3e%3cpath%20fill='url(%23c)'%20d='M119.167%204.012a56.1%2056.1%200%200%201%2041.667%200L274.123%2049.33c7.836%203.134%207.836%2014.226%200%2017.36L206.34%2093.806c-4.694%201.877-4.694%208.521%200%2010.399l67.782%2027.114c7.836%203.134%207.836%2014.228%200%2017.362l-67.781%2027.113c-4.693%201.878-4.693%208.522%200%2010.399l67.781%2027.113c7.836%203.135%207.836%2014.228%200%2017.362l-113.288%2045.317a56.1%2056.1%200%200%201-41.668%200L5.877%20230.667c-7.836-3.134-7.836-14.227%200-17.362l67.78-27.113c4.694-1.877%204.694-8.521%200-10.399L5.877%20148.68c-7.836-3.134-7.836-14.227%200-17.362l67.783-27.114c4.693-1.878%204.693-8.522%200-10.4L5.878%2066.692c-7.836-3.135-7.836-14.227%200-17.361z'/%3e%3cdefs%3e%3clinearGradient%20id='a'%20x1='82.447'%20x2='127.557'%20y1='259.773'%20y2='161.773'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='.206'%20stop-color='%2308b962'/%3e%3cstop%20offset='.987'%20stop-color='%2308b962'%20stop-opacity='0'/%3e%3c/linearGradient%3e%3clinearGradient%20id='b'%20x1='99.558'%20x2='150.891'%20y1='43.553'%20y2='139.996'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='%23f94543'/%3e%3cstop%20offset='1'%20stop-color='%23f94543'%20stop-opacity='0'/%3e%3c/linearGradient%3e%3cradialGradient%20id='c'%20cx='0'%20cy='0'%20r='1'%20gradientTransform='matrix(438.114%200%200%20438.11%2011.9%20139.972)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='%23fabc12'/%3e%3cstop%20offset='.423'%20stop-color='%23fabc12'%20stop-opacity='0'/%3e%3c/radialGradient%3e%3c/defs%3e%3c/svg%3e";
  const zreadIconUrl = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20aria-hidden='true'%20viewBox='0%200%2032%2032'%20version='1.1'%20width='24'%20height='24'%20data-view-component='true'%3e%3cpath%20d='M9.91922%203.2002H4.47922C3.77229%203.2002%203.19922%203.77327%203.19922%204.4802V9.9202C3.19922%2010.6271%203.77229%2011.2002%204.47922%2011.2002H9.91922C10.6261%2011.2002%2011.1992%2010.6271%2011.1992%209.9202V4.4802C11.1992%203.77327%2010.6261%203.2002%209.91922%203.2002Z'%20fill='%23000000'%3e%3c/path%3e%3cpath%20d='M9.91922%2020.7998H4.47922C3.77229%2020.7998%203.19922%2021.3729%203.19922%2022.0798V27.5198C3.19922%2028.2267%203.77229%2028.7998%204.47922%2028.7998H9.91922C10.6261%2028.7998%2011.1992%2028.2267%2011.1992%2027.5198V22.0798C11.1992%2021.3729%2010.6261%2020.7998%209.91922%2020.7998Z'%20fill='%23000000'%3e%3c/path%3e%3cpath%20d='M27.5208%203.2002H22.0808C21.3739%203.2002%2020.8008%203.77327%2020.8008%204.4802V9.9202C20.8008%2010.6271%2021.3739%2011.2002%2022.0808%2011.2002H27.5208C28.2277%2011.2002%2028.8008%2010.6271%2028.8008%209.9202V4.4802C28.8008%203.77327%2028.2277%203.2002%2027.5208%203.2002Z'%20fill='%23000000'%3e%3c/path%3e%3cpath%20d='M8%2024L24%208L8%2024Z'%20fill='%23000000'%3e%3c/path%3e%3cpath%20d='M8%2024L24%208'%20stroke='%23000000'%20stroke-width='2'%20stroke-linecap='round'%3e%3c/path%3e%3c/svg%3e";
  const zreadIconDarkUrl = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20aria-hidden='true'%20viewBox='0%200%2032%2032'%20version='1.1'%20width='24'%20height='24'%20data-view-component='true'%3e%3cpath%20d='M9.91922%203.2002H4.47922C3.77229%203.2002%203.19922%203.77327%203.19922%204.4802V9.9202C3.19922%2010.6271%203.77229%2011.2002%204.47922%2011.2002H9.91922C10.6261%2011.2002%2011.1992%2010.6271%2011.1992%209.9202V4.4802C11.1992%203.77327%2010.6261%203.2002%209.91922%203.2002Z'%20fill='%23b8b8b8'%3e%3c/path%3e%3cpath%20d='M9.91922%2020.7998H4.47922C3.77229%2020.7998%203.19922%2021.3729%203.19922%2022.0798V27.5198C3.19922%2028.2267%203.77229%2028.7998%204.47922%2028.7998H9.91922C10.6261%2028.7998%2011.1992%2028.2267%2011.1992%2027.5198V22.0798C11.1992%2021.3729%2010.6261%2020.7998%209.91922%2020.7998Z'%20fill='%23b8b8b8'%3e%3c/path%3e%3cpath%20d='M27.5208%203.2002H22.0808C21.3739%203.2002%2020.8008%203.77327%2020.8008%204.4802V9.9202C20.8008%2010.6271%2021.3739%2011.2002%2022.0808%2011.2002H27.5208C28.2277%2011.2002%2028.8008%2010.6271%2028.8008%209.9202V4.4802C28.8008%203.77327%2028.2277%203.2002%2027.5208%203.2002Z'%20fill='%23b8b8b8'%3e%3c/path%3e%3cpath%20d='M8%2024L24%208L8%2024Z'%20fill='%23b8b8b8'%3e%3c/path%3e%3cpath%20d='M8%2024L24%208'%20stroke='%23b8b8b8'%20stroke-width='2'%20stroke-linecap='round'%3e%3c/path%3e%3c/svg%3e";
  const isDarkMode = () => {
    var _a;
    const html = document.documentElement;
    if ((html == null ? void 0 : html.getAttribute("data-color-mode")) === "dark") {
      return true;
    }
    if ((html == null ? void 0 : html.classList.contains("dark")) || (html == null ? void 0 : html.classList.contains("color-mode-dark"))) {
      return true;
    }
    const media = (_a = window.matchMedia) == null ? void 0 : _a.call(window, "(prefers-color-scheme: dark)");
    return !!(media == null ? void 0 : media.matches);
  };
  const getZreadIcon = () => isDarkMode() ? zreadIconDarkUrl : zreadIconUrl;
  const createButtonsContainer = () => {
    const container = document.createElement("div");
    container.id = JUMPER_CONTAINER_ID;
    container.setAttribute("translate", "no");
    container.classList.add("notranslate");
    return container;
  };
  const createLink = (url, text, iconUrl) => {
    const link = document.createElement("a");
    link.href = url;
    link.target = "_blank";
    link.classList.add("Link", "Link--muted");
    link.style.display = "inline-flex";
    link.style.alignItems = "center";
    link.style.whiteSpace = "nowrap";
    link.style.gap = "8px";
    const img = document.createElement("img");
    img.src = iconUrl;
    img.style.width = "16px";
    img.style.height = "16px";
    img.style.flexShrink = "0";
    img.style.display = "block";
    link.appendChild(img);
    link.appendChild(document.createTextNode(text));
    return link;
  };
  const addButtons = () => {
    var _a;
    const repositoryName = getRepositoryName();
    if (!repositoryName) {
      return;
    }
    const repositoryPath = buildRepositoryPath(repositoryName);
    if (!repositoryPath) {
      return;
    }
    const targetElement = document.querySelector(INJECTION_SELECTOR);
    if (!targetElement || document.getElementById(JUMPER_CONTAINER_ID)) {
      return;
    }
    const urlx = new URL(window.location.href);
    const buttonsContainer = createButtonsContainer();
    for (const link of [
      createLink(buildDeepWikiUrl(repositoryPath), "DeepWiki", deepWikiIconUrl),
      createLink(buildCodeWikiUrl(urlx.hostname, repositoryPath), "CodeWiki", codeWikiIconUrl),
      createLink(buildZReadUrl(repositoryPath), "Zread", getZreadIcon())
    ]) {
      const div = document.createElement("div");
      div.classList.add("mt-2");
      div.appendChild(link);
      buttonsContainer.appendChild(div);
    }
    const sidebar = document.querySelector(SIDEBAR_SELECTOR);
    const reportRow = (_a = sidebar == null ? void 0 : sidebar.querySelector('a[href*="/contact/report-content"]')) == null ? void 0 : _a.closest(".mt-2");
    if (reportRow) {
      reportRow.insertAdjacentElement("afterend", buttonsContainer);
      return;
    }
    targetElement.appendChild(buttonsContainer);
  };
  let injectTimer;
  const shouldInjectButtons = () => {
    return !!document.querySelector(INJECTION_SELECTOR) && !document.getElementById(JUMPER_CONTAINER_ID);
  };
  const scheduleInjection = (delay = 200) => {
    if (injectTimer) {
      clearTimeout(injectTimer);
    }
    injectTimer = setTimeout(() => {
      injectTimer = void 0;
      if (shouldInjectButtons()) {
        addButtons();
      }
    }, delay);
  };
  const observeSidebar = () => {
    const observer = new MutationObserver(() => {
      if (shouldInjectButtons()) {
        scheduleInjection(0);
      }
    });
    observer.observe(document.documentElement, {
      childList: true,
      subtree: true
    });
  };
  const setupNavigationListeners = () => {
    const handleNavigation = () => {
      scheduleInjection();
    };
    document.addEventListener("turbo:load", handleNavigation);
    document.addEventListener("turbo:render", handleNavigation);
    document.addEventListener("pjax:end", handleNavigation);
    window.addEventListener("popstate", handleNavigation);
    observeSidebar();
    scheduleInjection(0);
  };
  setupNavigationListeners();
  addButtons();

})();