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

  1. // ==UserScript==
  2. // @name [SNOLAB] Alt + 123... Searching Results Links List Batch Open
  3. // @name:zh [雪星实验室] Alt + 123... 一键批量打开谷歌必应搜索的前2的n次方项搜索结果
  4. // @namespace snomiao@gmail.com
  5. // @version 1.0.5
  6. // @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.
  7. // @description:zh 快速了解一个领域用,在谷歌或必应的搜索页面 按 Alt+1 ...2,3,4... Alt+5 将会打开前2的n次方项的搜索结果,并复制打开的链接。目前支持:谷歌、必应、知乎。
  8. // @author snomiao
  9. // @match *://google.com/*
  10. // @match *://bing.com/*
  11. // @match *://youtube.com/*
  12. // @match *://zhihu.com/*
  13. // @match *://and-all-searching-results.com/*
  14. // @match *://*/*
  15. // @grant none
  16. // ==/UserScript==
  17.  
  18. /* eslint-disable */
  19.  
  20. // clipboardy/browser
  21. var clipboard = {};
  22. clipboard.write = async (text) => {
  23. await navigator.clipboard.writeText(text);
  24. };
  25. clipboard.read = async () => navigator.clipboard.readText();
  26. clipboard.readSync = () => {
  27. throw new Error("`.readSync()` is not supported in browsers!");
  28. };
  29. clipboard.writeSync = () => {
  30. throw new Error("`.writeSync()` is not supported in browsers!");
  31. };
  32. var browser_default = clipboard;
  33.  
  34. // hotkey-mapper
  35. var { keys } = Object;
  36. function mapObject(fn, obj) {
  37. if (arguments.length === 1) {
  38. return (_obj) => mapObject(fn, _obj);
  39. }
  40. let index = 0;
  41. const objKeys = keys(obj);
  42. const len = objKeys.length;
  43. const willReturn = {};
  44. while (index < len) {
  45. const key = objKeys[index];
  46. willReturn[key] = fn(
  47. obj[key],
  48. key,
  49. obj
  50. );
  51. index++;
  52. }
  53. return willReturn;
  54. }
  55. var mapObjIndexed = mapObject;
  56. function hotkeyMapper(mapping, on = "keydown", options) {
  57. const handler = (event) => {
  58. const mainKey = `${event.code.replace(/^Key/, "").toLowerCase()}Key`;
  59. event[mainKey] = true;
  60. const mods = "meta+alt+shift+ctrl";
  61. mapObjIndexed((fn, hotkey) => {
  62. const conds = `${mods}+${hotkey.toLowerCase()}`.replace(/win|command|search/, "meta").replace(/control/, "ctrl").split("+").map((k, i) => [k, Boolean(i >= 4) === Boolean(event[`${k}Key`])]);
  63. if (!Object.entries(Object.fromEntries(conds)).every(([, ok]) => ok))
  64. return;
  65. event.stopPropagation(), event.preventDefault();
  66. return fn(event);
  67. }, mapping);
  68. };
  69. window.addEventListener(on, handler, options);
  70. return function unload() {
  71. window.removeEventListener(on, handler, options);
  72. };
  73. }
  74.  
  75. // rambda
  76. var cloneList = (list) => Array.prototype.slice.call(list);
  77. function curry(fn, args = []) {
  78. return (..._args) => ((rest) => rest.length >= fn.length ? fn(...rest) : curry(fn, rest))([...args, ..._args]);
  79. }
  80. function adjustFn(index, replaceFn2, list) {
  81. const actualIndex = index < 0 ? list.length + index : index;
  82. if (index >= list.length || actualIndex < 0)
  83. return list;
  84. const clone = cloneList(list);
  85. clone[actualIndex] = replaceFn2(clone[actualIndex]);
  86. return clone;
  87. }
  88. var adjust = curry(adjustFn);
  89. function always(x) {
  90. return (_) => x;
  91. }
  92. var {
  93. isArray
  94. } = Array;
  95. function assocFn(prop2, newValue, obj) {
  96. return Object.assign({}, obj, {
  97. [prop2]: newValue
  98. });
  99. }
  100. var assoc = curry(assocFn);
  101. function _isInteger(n) {
  102. return n << 0 === n;
  103. }
  104. var isInteger = Number.isInteger || _isInteger;
  105. function assocPathFn(path2, newValue, input) {
  106. const pathArrValue = typeof path2 === "string" ? path2.split(".").map((x) => isInteger(Number(x)) ? Number(x) : x) : path2;
  107. if (pathArrValue.length === 0) {
  108. return newValue;
  109. }
  110. const index = pathArrValue[0];
  111. if (pathArrValue.length > 1) {
  112. const condition = typeof input !== "object" || input === null || !input.hasOwnProperty(index);
  113. const nextInput = condition ? isInteger(pathArrValue[1]) ? [] : {} : input[index];
  114. newValue = assocPathFn(Array.prototype.slice.call(pathArrValue, 1), newValue, nextInput);
  115. }
  116. if (isInteger(index) && isArray(input)) {
  117. const arr = cloneList(input);
  118. arr[index] = newValue;
  119. return arr;
  120. }
  121. return assoc(index, newValue, input);
  122. }
  123. var assocPath = curry(assocPathFn);
  124. function clampFn(min, max, input) {
  125. if (min > max) {
  126. throw new Error("min must not be greater than max in clamp(min, max, value)");
  127. }
  128. if (input >= min && input <= max)
  129. return input;
  130. if (input > max)
  131. return max;
  132. if (input < min)
  133. return min;
  134. }
  135. var clamp = curry(clampFn);
  136. var ReduceStopper = class {
  137. constructor(value) {
  138. this.value = value;
  139. }
  140. };
  141. function reduceFn(reducer, acc, list) {
  142. if (!isArray(list)) {
  143. throw new TypeError("reduce: list must be array or iterable");
  144. }
  145. let index = 0;
  146. const len = list.length;
  147. while (index < len) {
  148. acc = reducer(acc, list[index], index, list);
  149. if (acc instanceof ReduceStopper) {
  150. return acc.value;
  151. }
  152. index++;
  153. }
  154. return acc;
  155. }
  156. var reduce = curry(reduceFn);
  157. function _arity(n, fn) {
  158. switch (n) {
  159. case 0:
  160. return function() {
  161. return fn.apply(this, arguments);
  162. };
  163. case 1:
  164. return function(a0) {
  165. return fn.apply(this, arguments);
  166. };
  167. case 2:
  168. return function(a0, a1) {
  169. return fn.apply(this, arguments);
  170. };
  171. case 3:
  172. return function(a0, a1, a2) {
  173. return fn.apply(this, arguments);
  174. };
  175. case 4:
  176. return function(a0, a1, a2, a3) {
  177. return fn.apply(this, arguments);
  178. };
  179. case 5:
  180. return function(a0, a1, a2, a3, a4) {
  181. return fn.apply(this, arguments);
  182. };
  183. case 6:
  184. return function(a0, a1, a2, a3, a4, a5) {
  185. return fn.apply(this, arguments);
  186. };
  187. case 7:
  188. return function(a0, a1, a2, a3, a4, a5, a6) {
  189. return fn.apply(this, arguments);
  190. };
  191. case 8:
  192. return function(a0, a1, a2, a3, a4, a5, a6, a7) {
  193. return fn.apply(this, arguments);
  194. };
  195. case 9:
  196. return function(a0, a1, a2, a3, a4, a5, a6, a7, a8) {
  197. return fn.apply(this, arguments);
  198. };
  199. case 10:
  200. return function(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
  201. return fn.apply(this, arguments);
  202. };
  203. default:
  204. throw new Error("First argument to _arity must be a non-negative integer no greater than ten");
  205. }
  206. }
  207. function _pipe(f, g) {
  208. return function() {
  209. return g.call(this, f.apply(this, arguments));
  210. };
  211. }
  212. function pipe() {
  213. if (arguments.length === 0) {
  214. throw new Error("pipe requires at least one argument");
  215. }
  216. return _arity(arguments[0].length, reduceFn(_pipe, arguments[0], Array.prototype.slice.call(arguments, 1, Infinity)));
  217. }
  218. var {
  219. keys: keys$1
  220. } = Object;
  221. function mapArray(fn, list, isIndexed = false) {
  222. let index = 0;
  223. const willReturn = Array(list.length);
  224. while (index < list.length) {
  225. willReturn[index] = isIndexed ? fn(list[index], index) : fn(list[index]);
  226. index++;
  227. }
  228. return willReturn;
  229. }
  230. function mapObject2(fn, obj) {
  231. if (arguments.length === 1) {
  232. return (_obj) => mapObject2(fn, _obj);
  233. }
  234. let index = 0;
  235. const objKeys = keys$1(obj);
  236. const len = objKeys.length;
  237. const willReturn = {};
  238. while (index < len) {
  239. const key = objKeys[index];
  240. willReturn[key] = fn(obj[key], key, obj);
  241. index++;
  242. }
  243. return willReturn;
  244. }
  245. function map(fn, iterable) {
  246. if (arguments.length === 1)
  247. return (_iterable) => map(fn, _iterable);
  248. if (!iterable) {
  249. throw new Error(INCORRECT_ITERABLE_INPUT);
  250. }
  251. if (isArray(iterable))
  252. return mapArray(fn, iterable);
  253. return mapObject2(fn, iterable);
  254. }
  255. function isFalsy(input) {
  256. return input === void 0 || input === null || Number.isNaN(input) === true;
  257. }
  258. function defaultTo(defaultArgument, input) {
  259. if (arguments.length === 1) {
  260. return (_input) => defaultTo(defaultArgument, _input);
  261. }
  262. return isFalsy(input) ? defaultArgument : input;
  263. }
  264. function type(input) {
  265. if (input === null) {
  266. return "Null";
  267. } else if (input === void 0) {
  268. return "Undefined";
  269. } else if (Number.isNaN(input)) {
  270. return "NaN";
  271. }
  272. const typeResult = Object.prototype.toString.call(input).slice(8, -1);
  273. return typeResult === "AsyncFunction" ? "Promise" : typeResult;
  274. }
  275. function _indexOf(valueToFind, list) {
  276. if (!isArray(list)) {
  277. throw new Error(`Cannot read property 'indexOf' of ${list}`);
  278. }
  279. const typeOfValue = type(valueToFind);
  280. if (!["Object", "Array", "NaN", "RegExp"].includes(typeOfValue))
  281. return list.indexOf(valueToFind);
  282. let index = -1;
  283. let foundIndex = -1;
  284. const {
  285. length
  286. } = list;
  287. while (++index < length && foundIndex === -1) {
  288. if (equals(list[index], valueToFind)) {
  289. foundIndex = index;
  290. }
  291. }
  292. return foundIndex;
  293. }
  294. function _arrayFromIterator(iter) {
  295. const list = [];
  296. let next;
  297. while (!(next = iter.next()).done) {
  298. list.push(next.value);
  299. }
  300. return list;
  301. }
  302. function _equalsSets(a, b) {
  303. if (a.size !== b.size) {
  304. return false;
  305. }
  306. const aList = _arrayFromIterator(a.values());
  307. const bList = _arrayFromIterator(b.values());
  308. const filtered = aList.filter((aInstance) => _indexOf(aInstance, bList) === -1);
  309. return filtered.length === 0;
  310. }
  311. function parseError(maybeError) {
  312. const typeofError = maybeError.__proto__.toString();
  313. if (!["Error", "TypeError"].includes(typeofError))
  314. return [];
  315. return [typeofError, maybeError.message];
  316. }
  317. function parseDate(maybeDate) {
  318. if (!maybeDate.toDateString)
  319. return [false];
  320. return [true, maybeDate.getTime()];
  321. }
  322. function parseRegex(maybeRegex) {
  323. if (maybeRegex.constructor !== RegExp)
  324. return [false];
  325. return [true, maybeRegex.toString()];
  326. }
  327. function equals(a, b) {
  328. if (arguments.length === 1)
  329. return (_b) => equals(a, _b);
  330. const aType = type(a);
  331. if (aType !== type(b))
  332. return false;
  333. if (aType === "Function") {
  334. return a.name === void 0 ? false : a.name === b.name;
  335. }
  336. if (["NaN", "Undefined", "Null"].includes(aType))
  337. return true;
  338. if (aType === "Number") {
  339. if (Object.is(-0, a) !== Object.is(-0, b))
  340. return false;
  341. return a.toString() === b.toString();
  342. }
  343. if (["String", "Boolean"].includes(aType)) {
  344. return a.toString() === b.toString();
  345. }
  346. if (aType === "Array") {
  347. const aClone = Array.from(a);
  348. const bClone = Array.from(b);
  349. if (aClone.toString() !== bClone.toString()) {
  350. return false;
  351. }
  352. let loopArrayFlag = true;
  353. aClone.forEach((aCloneInstance, aCloneIndex) => {
  354. if (loopArrayFlag) {
  355. if (aCloneInstance !== bClone[aCloneIndex] && !equals(aCloneInstance, bClone[aCloneIndex])) {
  356. loopArrayFlag = false;
  357. }
  358. }
  359. });
  360. return loopArrayFlag;
  361. }
  362. const aRegex = parseRegex(a);
  363. const bRegex = parseRegex(b);
  364. if (aRegex[0]) {
  365. return bRegex[0] ? aRegex[1] === bRegex[1] : false;
  366. } else if (bRegex[0])
  367. return false;
  368. const aDate = parseDate(a);
  369. const bDate = parseDate(b);
  370. if (aDate[0]) {
  371. return bDate[0] ? aDate[1] === bDate[1] : false;
  372. } else if (bDate[0])
  373. return false;
  374. const aError = parseError(a);
  375. const bError = parseError(b);
  376. if (aError[0]) {
  377. return bError[0] ? aError[0] === bError[0] && aError[1] === bError[1] : false;
  378. }
  379. if (aType === "Set") {
  380. return _equalsSets(a, b);
  381. }
  382. if (aType === "Object") {
  383. const aKeys = Object.keys(a);
  384. if (aKeys.length !== Object.keys(b).length) {
  385. return false;
  386. }
  387. let loopObjectFlag = true;
  388. aKeys.forEach((aKeyInstance) => {
  389. if (loopObjectFlag) {
  390. const aValue = a[aKeyInstance];
  391. const bValue = b[aKeyInstance];
  392. if (aValue !== bValue && !equals(aValue, bValue)) {
  393. loopObjectFlag = false;
  394. }
  395. }
  396. });
  397. return loopObjectFlag;
  398. }
  399. return false;
  400. }
  401. function prop(propToFind, obj) {
  402. if (arguments.length === 1)
  403. return (_obj) => prop(propToFind, _obj);
  404. if (!obj)
  405. return void 0;
  406. return obj[propToFind];
  407. }
  408. function eqPropsFn(property, objA, objB) {
  409. return equals(prop(property, objA), prop(property, objB));
  410. }
  411. var eqProps = curry(eqPropsFn);
  412. function filterObject(predicate, obj) {
  413. const willReturn = {};
  414. for (const prop2 in obj) {
  415. if (predicate(obj[prop2], prop2, obj)) {
  416. willReturn[prop2] = obj[prop2];
  417. }
  418. }
  419. return willReturn;
  420. }
  421. function filterArray(predicate, list, indexed = false) {
  422. let index = 0;
  423. const len = list.length;
  424. const willReturn = [];
  425. while (index < len) {
  426. const predicateResult = indexed ? predicate(list[index], index) : predicate(list[index]);
  427. if (predicateResult) {
  428. willReturn.push(list[index]);
  429. }
  430. index++;
  431. }
  432. return willReturn;
  433. }
  434. function filter(predicate, iterable) {
  435. if (arguments.length === 1)
  436. return (_iterable) => filter(predicate, _iterable);
  437. if (!iterable) {
  438. throw new Error("Incorrect iterable input");
  439. }
  440. if (isArray(iterable))
  441. return filterArray(predicate, iterable, false);
  442. return filterObject(predicate, iterable);
  443. }
  444. function createPath(path2, delimiter = ".") {
  445. return typeof path2 === "string" ? path2.split(delimiter) : path2;
  446. }
  447. function path(pathInput, obj) {
  448. if (arguments.length === 1)
  449. return (_obj) => path(pathInput, _obj);
  450. if (obj === null || obj === void 0) {
  451. return void 0;
  452. }
  453. let willReturn = obj;
  454. let counter = 0;
  455. const pathArrValue = createPath(pathInput);
  456. while (counter < pathArrValue.length) {
  457. if (willReturn === null || willReturn === void 0) {
  458. return void 0;
  459. }
  460. if (willReturn[pathArrValue[counter]] === null)
  461. return void 0;
  462. willReturn = willReturn[pathArrValue[counter]];
  463. counter++;
  464. }
  465. return willReturn;
  466. }
  467. function ifElseFn(condition, onTrue, onFalse) {
  468. return (...input) => {
  469. const conditionResult = typeof condition === "boolean" ? condition : condition(...input);
  470. if (conditionResult === true) {
  471. return onTrue(...input);
  472. }
  473. return onFalse(...input);
  474. };
  475. }
  476. var ifElse = curry(ifElseFn);
  477. function baseSlice(array, start, end) {
  478. let index = -1;
  479. let {
  480. length
  481. } = array;
  482. end = end > length ? length : end;
  483. if (end < 0) {
  484. end += length;
  485. }
  486. length = start > end ? 0 : end - start >>> 0;
  487. start >>>= 0;
  488. const result = Array(length);
  489. while (++index < length) {
  490. result[index] = array[index + start];
  491. }
  492. return result;
  493. }
  494. function is(targetPrototype, x) {
  495. if (arguments.length === 1)
  496. return (_x) => is(targetPrototype, _x);
  497. return x != null && x.constructor === targetPrototype || x instanceof targetPrototype;
  498. }
  499. function updateFn(index, newValue, list) {
  500. const clone = cloneList(list);
  501. if (index === -1)
  502. return clone.fill(newValue, index);
  503. return clone.fill(newValue, index, index + 1);
  504. }
  505. var update = curry(updateFn);
  506. function maxByFn(compareFn, x, y) {
  507. return compareFn(y) > compareFn(x) ? y : x;
  508. }
  509. var maxBy = curry(maxByFn);
  510. function mergeWithFn(mergeFn, a, b) {
  511. const willReturn = {};
  512. Object.keys(a).forEach((key) => {
  513. if (b[key] === void 0) {
  514. willReturn[key] = a[key];
  515. } else {
  516. willReturn[key] = mergeFn(a[key], b[key]);
  517. }
  518. });
  519. Object.keys(b).forEach((key) => {
  520. if (willReturn[key] !== void 0)
  521. return;
  522. if (a[key] === void 0) {
  523. willReturn[key] = b[key];
  524. } else {
  525. willReturn[key] = mergeFn(a[key], b[key]);
  526. }
  527. });
  528. return willReturn;
  529. }
  530. var mergeWith = curry(mergeWithFn);
  531. function minByFn(compareFn, x, y) {
  532. return compareFn(y) < compareFn(x) ? y : x;
  533. }
  534. var minBy = curry(minByFn);
  535. function ownKeys(object, enumerableOnly) {
  536. var keys2 = Object.keys(object);
  537. if (Object.getOwnPropertySymbols) {
  538. var symbols = Object.getOwnPropertySymbols(object);
  539. enumerableOnly && (symbols = symbols.filter(function(sym) {
  540. return Object.getOwnPropertyDescriptor(object, sym).enumerable;
  541. })), keys2.push.apply(keys2, symbols);
  542. }
  543. return keys2;
  544. }
  545. function _objectSpread2(target) {
  546. for (var i = 1; i < arguments.length; i++) {
  547. var source = null != arguments[i] ? arguments[i] : {};
  548. i % 2 ? ownKeys(Object(source), true).forEach(function(key) {
  549. _defineProperty(target, key, source[key]);
  550. }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function(key) {
  551. Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
  552. });
  553. }
  554. return target;
  555. }
  556. function _defineProperty(obj, key, value) {
  557. if (key in obj) {
  558. Object.defineProperty(obj, key, {
  559. value,
  560. enumerable: true,
  561. configurable: true,
  562. writable: true
  563. });
  564. } else {
  565. obj[key] = value;
  566. }
  567. return obj;
  568. }
  569. function isIterable(input) {
  570. return Array.isArray(input) || type(input) === "Object";
  571. }
  572. function modifyFn(property, fn, iterable) {
  573. if (!isIterable(iterable))
  574. return iterable;
  575. if (iterable[property] === void 0)
  576. return iterable;
  577. if (isArray(iterable)) {
  578. return updateFn(property, fn(iterable[property]), iterable);
  579. }
  580. return _objectSpread2(_objectSpread2({}, iterable), {}, {
  581. [property]: fn(iterable[property])
  582. });
  583. }
  584. var modify = curry(modifyFn);
  585. function modifyPathFn(pathInput, fn, object) {
  586. const path$1 = createPath(pathInput);
  587. if (path$1.length === 1) {
  588. return _objectSpread2(_objectSpread2({}, object), {}, {
  589. [path$1[0]]: fn(object[path$1[0]])
  590. });
  591. }
  592. if (path(path$1, object) === void 0)
  593. return object;
  594. const val = modifyPath(Array.prototype.slice.call(path$1, 1), fn, object[path$1[0]]);
  595. if (val === object[path$1[0]]) {
  596. return object;
  597. }
  598. return assoc(path$1[0], val, object);
  599. }
  600. var modifyPath = curry(modifyPathFn);
  601. function moveFn(fromIndex, toIndex, list) {
  602. if (fromIndex < 0 || toIndex < 0) {
  603. throw new Error("Rambda.move does not support negative indexes");
  604. }
  605. if (fromIndex > list.length - 1 || toIndex > list.length - 1)
  606. return list;
  607. const clone = cloneList(list);
  608. clone[fromIndex] = list[toIndex];
  609. clone[toIndex] = list[fromIndex];
  610. return clone;
  611. }
  612. var move = curry(moveFn);
  613. function multiply(x, y) {
  614. if (arguments.length === 1)
  615. return (_y) => multiply(x, _y);
  616. return x * y;
  617. }
  618. var Identity = (x) => ({
  619. x,
  620. map: (fn) => Identity(fn(x))
  621. });
  622. function overFn(lens, fn, object) {
  623. return lens((x) => Identity(fn(x)))(object).x;
  624. }
  625. var over = curry(overFn);
  626. function pathEqFn(pathToSearch, target, input) {
  627. return equals(path(pathToSearch, input), target);
  628. }
  629. var pathEq = curry(pathEqFn);
  630. function pathOrFn(defaultValue, pathInput, obj) {
  631. return defaultTo(defaultValue, path(pathInput, obj));
  632. }
  633. var pathOr = curry(pathOrFn);
  634. var product = reduce(multiply, 1);
  635. function propEqFn(propToFind, valueToMatch, obj) {
  636. if (!obj)
  637. return false;
  638. return equals(valueToMatch, prop(propToFind, obj));
  639. }
  640. var propEq = curry(propEqFn);
  641. function propIsFn(targetPrototype, property, obj) {
  642. return is(targetPrototype, obj[property]);
  643. }
  644. var propIs = curry(propIsFn);
  645. function propOrFn(defaultValue, property, obj) {
  646. if (!obj)
  647. return defaultValue;
  648. return defaultTo(defaultValue, obj[property]);
  649. }
  650. var propOr = curry(propOrFn);
  651. function propSatisfiesFn(predicate, property, obj) {
  652. return predicate(prop(property, obj));
  653. }
  654. var propSatisfies = curry(propSatisfiesFn);
  655. function replaceFn(pattern, replacer, str) {
  656. return str.replace(pattern, replacer);
  657. }
  658. var replace = curry(replaceFn);
  659. function setFn(lens, replacer, x) {
  660. return over(lens, always(replacer), x);
  661. }
  662. var set = curry(setFn);
  663. function sliceFn(from, to, list) {
  664. return list.slice(from, to);
  665. }
  666. var slice = curry(sliceFn);
  667. function sortBy(sortFn, list) {
  668. if (arguments.length === 1)
  669. return (_list) => sortBy(sortFn, _list);
  670. const clone = cloneList(list);
  671. return clone.sort((a, b) => {
  672. const aSortResult = sortFn(a);
  673. const bSortResult = sortFn(b);
  674. if (aSortResult === bSortResult)
  675. return 0;
  676. return aSortResult < bSortResult ? -1 : 1;
  677. });
  678. }
  679. function take(howMany, listOrString) {
  680. if (arguments.length === 1)
  681. return (_listOrString) => take(howMany, _listOrString);
  682. if (howMany < 0)
  683. return listOrString.slice();
  684. if (typeof listOrString === "string")
  685. return listOrString.slice(0, howMany);
  686. return baseSlice(listOrString, 0, howMany);
  687. }
  688. function whenFn(predicate, whenTrueFn, input) {
  689. if (!predicate(input))
  690. return input;
  691. return whenTrueFn(input);
  692. }
  693. var when = curry(whenFn);
  694. function zipWithFn(fn, x, y) {
  695. return take(x.length > y.length ? y.length : x.length, x).map((xInstance, i) => fn(xInstance, y[i]));
  696. }
  697. var zipWith = curry(zipWithFn);
  698.  
  699. // $$
  700. function $$(sel, el = document) {
  701. return [...el.querySelectorAll(sel)];
  702. }
  703.  
  704. // LinksListBatchOpen
  705. globalThis.llboUnload?.();
  706. globalThis.llboUnload = main();
  707. function main() {
  708. console.log("[\u8C37\u6B4C\u4E00\u952E\u6253\u5F00\u524DN\u9879\u641C\u7D22\u7ED3\u679C] LOADED");
  709. const \u5DF2\u6253\u5F00\u8FC7\u7684\u94FE\u63A5 = {};
  710. return hotkeyMapper(
  711. {
  712. "alt+1": () => openLinkByCount(2 ** 1),
  713. "alt+2": () => openLinkByCount(2 ** 2),
  714. "alt+3": () => openLinkByCount(2 ** 3),
  715. "alt+4": () => openLinkByCount(2 ** 4),
  716. "alt+5": () => openLinkByCount(2 ** 5),
  717. "alt+6": () => openLinkByCount(2 ** 6),
  718. "alt+7": () => openLinkByCount(2 ** 7),
  719. "alt+8": () => openLinkByCount(2 ** 8),
  720. "alt+9": () => openLinkByCount(2 ** 9),
  721. "shift+alt+1": () => tryCopyLinkByCount(2 ** 1),
  722. "shift+alt+2": () => tryCopyLinkByCount(2 ** 2),
  723. "shift+alt+3": () => tryCopyLinkByCount(2 ** 3),
  724. "shift+alt+4": () => tryCopyLinkByCount(2 ** 4),
  725. "shift+alt+5": () => tryCopyLinkByCount(2 ** 5),
  726. "shift+alt+6": () => tryCopyLinkByCount(2 ** 6),
  727. "shift+alt+7": () => tryCopyLinkByCount(2 ** 7),
  728. "shift+alt+8": () => tryCopyLinkByCount(2 ** 8),
  729. "shift+alt+9": () => tryCopyLinkByCount(2 ** 9)
  730. },
  731. void 0,
  732. true
  733. );
  734. function linkOpen(link) {
  735. if (!\u5DF2\u6253\u5F00\u8FC7\u7684\u94FE\u63A5[link]) {
  736. window.open(link);
  737. }
  738. \u5DF2\u6253\u5F00\u8FC7\u7684\u94FE\u63A5[link] = 1;
  739. }
  740. function openLinkByCount(count = 1) {
  741. console.log("openLinkByCount", count);
  742. const links = getLinks(count);
  743. copyLinks(links);
  744. links.map((e) => e.link).reverse().map(linkOpen);
  745. }
  746. }
  747. function tryCopyLinkByCount(count = 1) {
  748. const links = getLinks(count);
  749. copyLinks(links);
  750. return links;
  751. }
  752. async function copyLinks(links) {
  753. const md = links.map(md\u683C\u5F0F\u94FE\u63A5\u751F\u6210).join("\n\n");
  754. alert("copied links: " + md);
  755. await browser_default.write(md);
  756. }
  757. function longestCommonSequenceMatrix(m, a, b, x, y) {
  758. const lcs = longestCommonSequenceMatrix;
  759. 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);
  760. }
  761. function longestCommonSequence(a, b) {
  762. const w = a.length, h = b.length;
  763. const m = Array(1 + h).fill(0).map(() => Array(1 + w).fill(0));
  764. for (let y = 0; y < h; y++)
  765. for (let x = 0; x < w; x++)
  766. m[1 + y][1 + x] = a[x] === b[y] ? m[y][x] + 1 : Math.max(m[y][1 + x], m[1 + y][x]);
  767. return longestCommonSequenceMatrix(m, a, b, w, h);
  768. }
  769. function elementFeatureList(ele) {
  770. return [...ele.querySelectorAll("*")].map((e) => e?.tagName + e?.className);
  771. }
  772. function featureElementAsk(ele) {
  773. return !"style script span".toUpperCase().split(" ").includes(ele.tagName);
  774. }
  775. function elementListStrengh(ele) {
  776. return (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);
  777. }
  778. function listElementList() {
  779. return pipe(
  780. () => $$("div,dl,ul,ol,tbody,table,td"),
  781. filter((e) => e.children.length > 1),
  782. map((element) => ({
  783. element,
  784. strength: elementListStrengh(element),
  785. featureList: pipe(
  786. () => [...element.children],
  787. filter(featureElementAsk),
  788. map(elementFeatureList)
  789. )()
  790. })),
  791. sortBy((a) => -a.strength)
  792. )();
  793. }
  794. function \u6807\u94FE\u5143\u7D20\u63D0\u53D6(e) {
  795. return e?.querySelector("dd,dt,h1,h2,h3,h4,h5,h6")?.querySelector("a") || [...e?.querySelectorAll("a")]?.filter(
  796. (e2) => e2.querySelector("dd,dt,h1,h2,h3,h4,h5,h6")
  797. )?.[0] || e?.querySelector("a");
  798. }
  799. function \u6807\u94FE\u63D0\u53D6(element) {
  800. return {
  801. element,
  802. title: element?.textContent?.replace(/\s+/g, " ").trim(),
  803. link: element?.href
  804. };
  805. }
  806. function \u9875\u4E3B\u6807\u94FE\u5217\u63D0\u53D6() {
  807. return pipe(
  808. () => listElementList(),
  809. (list) => list.flatMap(
  810. (father, i, a) => !a.some((son, j) => i != j && father?.element.contains(son.element)) ? [father] : []
  811. ),
  812. (list) => list.flatMap((e, i, a) => e.strength > a[0].strength * 0.1 ? [e] : []),
  813. sortBy((a) => a.element.offsetTop),
  814. map(({ element }) => element),
  815. (e) => e.flatMap((e2) => [...e2?.children]?.map?.(\u6807\u94FE\u5143\u7D20\u63D0\u53D6) || []),
  816. filter((e) => e),
  817. map(\u6807\u94FE\u63D0\u53D6),
  818. filter(({ title, link }) => title),
  819. filter(({ title, link }) => link?.match?.(/^http/))
  820. )();
  821. }
  822. function getLinks(\u6570\u91CF = Infinity) {
  823. return \u9875\u4E3B\u6807\u94FE\u5217\u63D0\u53D6().slice(0, \u6570\u91CF);
  824. }
  825. function md\u683C\u5F0F\u94FE\u63A5\u751F\u6210({ title, link }) {
  826. return `- [${title}](${link})`;
  827. }