[SNOLAB] Alt + 123... Searching Results Links List Batch Open

To quickly understand a field, press Alt+1 ...2,3,4...Alt+5 on the search page of Google or Bing to open the search results of the first 2 nth power items and copy the opened ones link. Currently supports: Google, Bing, Zhihu.

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 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             [SNOLAB] Alt + 123... Searching Results Links List Batch Open
// @name:zh          [雪星实验室] Alt + 123... 一键批量打开谷歌必应搜索的前2的n次方项搜索结果
// @namespace        https://userscript.snomiao.com/
// @version          1.1.0
// @description      To quickly understand a field, press Alt+1 ...2,3,4...Alt+5 on the search page of Google or Bing to open the search results of the first 2 nth power items and copy the opened ones link. Currently supports: Google, Bing, Zhihu.
// @description:zh   快速了解一个领域用,在谷歌或必应的搜索页面 按 Alt+1 ...2,3,4... Alt+5  将会打开前2的n次方项的搜索结果,并复制打开的链接。目前支持:谷歌、必应、知乎。
// @author           [email protected]
// @match            *://google.com/*
// @match            *://bing.com/*
// @match            *://youtube.com/*
// @match            *://zhihu.com/*
// @match            *://and-all-searching-results.com/*
// @match            *://*/*
// @grant            none
// @contributionURL  https://snomiao.com/donate
// @supportURL       https://github.com/snomiao/userscript.js/issues
// ==/UserScript==
"use strict";
(() => {
  // ../node_modules/hotkey-mapper/dist/index.mjs
  var { keys } = Object;
  function mapObject(fn, obj) {
    if (arguments.length === 1) {
      return (_obj) => mapObject(fn, _obj);
    }
    let index = 0;
    const objKeys = keys(obj);
    const len = objKeys.length;
    const willReturn = {};
    while (index < len) {
      const key = objKeys[index];
      willReturn[key] = fn(
        obj[key],
        key,
        obj
      );
      index++;
    }
    return willReturn;
  }
  var mapObjIndexed = mapObject;
  function hotkeyMapper(mapping, options) {
    const handler = (event) => {
      if (!event.key)
        throw new Error("Invalid KeyboardEvent");
      if (!event.code)
        throw new Error("Invalid KeyboardEvent");
      const key = event.key?.toLowerCase();
      const code = event.code?.toLowerCase();
      const simp = event.code?.replace(/^(?:Key|Digit|Numpad)/, "").toLowerCase();
      const map = new Proxy(event, {
        get: (target2, p) => Boolean(
          {
            [`${key}Key`]: true,
            [`${code}Key`]: true,
            [`${simp}Key`]: true
          }[p] ?? target2[p]
        )
      });
      const mods = "meta+alt+shift+ctrl";
      mapObjIndexed((fn, hotkey) => {
        const conds = `${mods}+${hotkey.toLowerCase()}`.replace(/win|command|search/, "meta").replace(/control/, "ctrl").split("+").map((key2) => key2.toLowerCase().trim()).map((k, i) => [k, i >= 4 === map[`${k}Key`]]);
        if (!Object.entries(Object.fromEntries(conds)).every(([, ok]) => ok))
          return;
        event.stopPropagation?.();
        event.preventDefault?.();
        return fn(event);
      }, mapping);
    };
    const target = options?.target ?? globalThis;
    target.addEventListener(options?.on ?? "keydown", handler, options);
    return function unload() {
      target.removeEventListener(options?.on ?? "keydown", handler, options);
    };
  }

  // ../ts/$$.ts
  function $$(sel, el = document) {
    return [...el.querySelectorAll(sel)];
  }

  // ../ts/LinksListBatchOpen.user.ts
  globalThis.llboUnload?.();
  globalThis.llboUnload = main();
  function main() {
    console.log("[Links List Batch Open] LOADED");
    const linkAlreadyOpened = /* @__PURE__ */ new Set();
    return hotkeyMapper(
      {
        "alt+1": () => openLinkByCount(2 ** 1),
        "alt+2": () => openLinkByCount(2 ** 2),
        "alt+3": () => openLinkByCount(2 ** 3),
        "alt+4": () => openLinkByCount(2 ** 4),
        "alt+5": () => openLinkByCount(2 ** 5),
        "alt+6": () => openLinkByCount(2 ** 6),
        "alt+7": () => openLinkByCount(2 ** 7),
        "alt+8": () => openLinkByCount(2 ** 8),
        "alt+9": () => openLinkByCount(2 ** 9),
        "alt+shift+1": () => tryCopyLinkByCount(2 ** 1),
        "alt+shift+2": () => tryCopyLinkByCount(2 ** 2),
        "alt+shift+3": () => tryCopyLinkByCount(2 ** 3),
        "alt+shift+4": () => tryCopyLinkByCount(2 ** 4),
        "alt+shift+5": () => tryCopyLinkByCount(2 ** 5),
        "alt+shift+6": () => tryCopyLinkByCount(2 ** 6),
        "alt+shift+7": () => tryCopyLinkByCount(2 ** 7),
        "alt+shift+8": () => tryCopyLinkByCount(2 ** 8),
        "alt+shi  ft+9": () => tryCopyLinkByCount(2 ** 9)
      },
      { capture: true, on: "keydown" }
    );
    function linkOpen(link) {
      if (!linkAlreadyOpened.has(link)) {
        window.open(link);
      }
      linkAlreadyOpened.add(link);
    }
    function openLinkByCount(count = 1) {
      console.log("openLinkByCount", count);
      const links = getLinks(count);
      copyLinks(links);
      links.map((e) => e.link).reverse().map(linkOpen);
    }
  }
  function tryCopyLinkByCount(count = 1) {
    const links = getLinks(count);
    copyLinks(links);
    return links;
  }
  async function copyLinks(links) {
    const md = links.map(markdownLinksGenerate).join("\n\n");
    alert("copied links: " + md);
    await navigator.clipboard.writeText(md);
  }
  function longestCommonSequenceMatrix(m, a, b, x, y) {
    const lcs = longestCommonSequenceMatrix;
    return !x || !y ? "" : a[x - 1] === b[y - 1] ? lcs(m, a, b, x - 1, y - 1) + a[x - 1] : m[y][x - 1] > m[y - 1][x] ? lcs(m, a, b, x - 1, y) : lcs(m, a, b, x, y - 1);
  }
  function longestCommonSequence(a, b) {
    const w = a.length, h = b.length;
    const m = Array(1 + h).fill(0).map(() => Array(1 + w).fill(0));
    for (let y = 0; y < h; y++)
      for (let x = 0; x < w; x++)
        m[1 + y][1 + x] = a[x] === b[y] ? m[y][x] + 1 : Math.max(m[y][1 + x], m[1 + y][x]);
    return longestCommonSequenceMatrix(m, a, b, w, h);
  }
  function elementFeatureList(ele) {
    return [...ele.querySelectorAll("*")].map((e) => e?.tagName + e?.className);
  }
  function featureElementAsk(ele) {
    return !"style script span".toUpperCase().split(" ").includes(ele.tagName);
  }
  function elementListStrengh(ele) {
    return Math.log(1 + (ele.textContent || "").length) * (ele.children.length - 1) * [...ele.children].filter(featureElementAsk).map(elementFeatureList).map((_, i, a) => longestCommonSequence(a[i], a[i + 1] || [])).reduce((\u524D, \u540E) => \u524D + \u540E.length, 0);
  }
  function listElementList() {
    const elements = $$("div,dl,ul,ol,tbody,table,td");
    const sorted = elements.filter((e) => e.children.length > 1).map((element) => {
      const children = [...element.children];
      return {
        element,
        strength: elementListStrengh(element),
        featureList: children.filter(featureElementAsk).map(elementFeatureList)
      };
    });
    return sortBy((a) => -a.strength, sorted);
  }
  function titleLinkElementExtract(e) {
    return e?.querySelector("dd,dt,h1,h2,h3,h4,h5,h6")?.querySelector("a") || [...e?.querySelectorAll("a")]?.filter(
      (e2) => e2.querySelector("dd,dt,h1,h2,h3,h4,h5,h6")
    )?.[0] || e?.querySelector("a");
  }
  function titleLinkExtract(element) {
    return {
      element,
      title: element?.textContent?.replace(/\s+/g, " ").trim(),
      link: element?.href
    };
  }
  function pageMainTitleLinkListExtract() {
    const list = listElementList();
    const filteredList = list.flatMap(
      (father, i, a) => a.some(
        (son, j) => i != j && father.element.contains(son.element) && son.strength > father.strength
      ) ? [] : [father]
    ).flatMap((e, _i, a) => e.strength > a[0].strength * 0.1 ? [e] : []);
    const sortedList = sortBy(
      (a) => a.element.offsetTop * window.outerWidth + a.element.offsetLeft,
      filteredList
    );
    const result = sortedList.map(({ element }) => element).flatMap((e) => [...e?.children]?.map?.(titleLinkElementExtract) || []).flatMap((e) => e ? [e] : []).map(titleLinkExtract).flatMap((e) => e.title ? [e] : []).flatMap((e) => e.link?.match?.(/^http/) ? [e] : []);
    return result;
  }
  function getLinks(\u6570\u91CF = Infinity) {
    return pageMainTitleLinkListExtract().slice(0, \u6570\u91CF);
  }
  function markdownLinksGenerate({ title, link }) {
    return `- [${title}](${link})`;
  }
  function sortBy(sortFn, list) {
    if (arguments.length === 1)
      return (_list) => sortBy(sortFn, _list);
    const clone = [...list];
    return clone.sort((a, b) => {
      const aSortResult = sortFn(a);
      const bSortResult = sortFn(b);
      if (aSortResult === bSortResult)
        return 0;
      return aSortResult < bSortResult ? -1 : 1;
    });
  }
})();