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

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

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