[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.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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;
    });
  }
})();