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

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

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