Qiita timeline auto more

auto fetch more entries

  1. // ==UserScript==
  2. // @name Qiita timeline auto more
  3. // @namespace https://htsign.hateblo.jp
  4. // @version 0.3.2
  5. // @description auto fetch more entries
  6. // @author htsign
  7. // @match https://qiita.com/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. const queryNodes = function* (path, root = document) {
  12. const result = document.evaluate(path, root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE);
  13. let node;
  14. while ((node = result.iterateNext()) != null) {
  15. yield node;
  16. }
  17. };
  18.  
  19. const listElement = document.querySelector('main');
  20. if (listElement) {
  21. const READMORE_XPATH = './/button[text()="もっと読む"]';
  22.  
  23. const io = new IntersectionObserver((entries, observer) => {
  24. entries
  25. .filter(entry => entry.isIntersecting)
  26. .forEach(({ target }) => {
  27. observer.unobserve(target);
  28. target.click();
  29. });
  30. }, { rootMargin: '100%' });
  31. const mo = new MutationObserver(records => {
  32. const buttons = records
  33. .flatMap(r => [...r.addedNodes])
  34. .flatMap(node => [...queryNodes(READMORE_XPATH, node)]);
  35.  
  36. buttons.forEach(io.observe.bind(io));
  37. });
  38. mo.observe(listElement, { childList: true, subtree: true });
  39.  
  40. const button = document.evaluate(READMORE_XPATH, listElement, null, XPathResult.FIRST_ORDERED_NODE_TYPE)?.singleNodeValue;
  41. if (button) {
  42. io.observe(button);
  43. }
  44. }