🏠 Home 

Save citations to your library

Save all citations of a paper to your library


Install this script?
  1. // ==UserScript==
  2. // @name Save citations to your library
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description Save all citations of a paper to your library
  6. // @author yusanshi
  7. // @license MIT
  8. // @match https://scholar.google.com/scholar?*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=google.com
  10. // @require https://cdn.jsdelivr.net/gh/uzairfarooq/arrive@77ff92c058598997e7da9789376b7a666a6d40db/src/arrive.js
  11. // @grant GM.setValue
  12. // @grant GM.getValue
  13. // ==/UserScript==
  14. const sleepTime = 1000;
  15. const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
  16. const work = async (targetLibrary) => {
  17. await document.arrive('#gs_res_ccl_mid > div.gs_r.gs_or.gs_scl', {
  18. onceOnly: true,
  19. existing: true,
  20. });
  21. // Process the current page
  22. for (const e of document.querySelectorAll(
  23. '#gs_res_ccl_mid > div.gs_r.gs_or.gs_scl'
  24. )) {
  25. e.scrollIntoView();
  26. e.querySelector('div.gs_fl a.gs_or_sav span.gs_or_btn_lbl').click();
  27. await sleep(sleepTime);
  28. await document.arrive('#gs_md_albl-d.gs_vis div.gs_ldb_lbc', {
  29. onceOnly: true,
  30. existing: true,
  31. });
  32. let temp = [
  33. ...document.querySelectorAll('#gs_md_albl-d.gs_vis div.gs_ldb_lbc'),
  34. ].filter((a) => a.textContent === targetLibrary);
  35. if (temp.length === 0) {
  36. // create a new library
  37. document
  38. .querySelector('#gs_md_albl-d.gs_vis form span.gs_ldb_new_lb')
  39. .click();
  40. document.querySelector(
  41. '#gs_md_albl-d.gs_vis #gs_lbd_new_txt input'
  42. ).value = targetLibrary;
  43. } else {
  44. // select the old library
  45. temp = temp[0].querySelector('a');
  46. temp.scrollIntoView();
  47. if (!temp.classList.contains('gs_sel')) {
  48. temp.click();
  49. }
  50. }
  51. await sleep(sleepTime);
  52. document.querySelector('#gs_lbd_apl > span.gs_wr > span').click();
  53. await sleep(sleepTime);
  54. }
  55. const nextPage = document.querySelector(
  56. '#gs_n > center > table > tbody > tr > td > span.gs_ico_nav_current'
  57. ).parentElement.nextElementSibling;
  58. if (nextPage.innerText.trim() !== '') {
  59. nextPage.querySelector('a').click();
  60. }
  61. };
  62. (async function () {
  63. 'use strict';
  64. document.body.insertAdjacentHTML(
  65. 'beforeend',
  66. `<div
  67. style="
  68. position: fixed;
  69. bottom: 30px;
  70. right: 30px;
  71. background: rgba(240, 240, 240, 0.9);
  72. z-index: 1;
  73. padding: 5px;
  74. border: 1px solid #ccc;
  75. border-radius: 6px;
  76. display: flex;
  77. align-items: center;
  78. "
  79. >
  80. <label>Target library</label>
  81. <input type="text" id="targetLibrary" style="margin-left:6px;margin-right:10px" />
  82. <label>Current paper</label>
  83. <input type="text" id="currentPaper" style="margin-left:6px;margin-right:10px" />
  84. <input
  85. type="checkbox"
  86. id="running"
  87. style="width: 16px; height: 16px"
  88. />
  89. </div>
  90. `
  91. );
  92. await document.arrive('#targetLibrary', {
  93. onceOnly: true,
  94. existing: true,
  95. });
  96. await document.arrive('#currentPaper', {
  97. onceOnly: true,
  98. existing: true,
  99. });
  100. await document.arrive('#running', {
  101. onceOnly: true,
  102. existing: true,
  103. });
  104. const targetLibraryInput = document.querySelector('#targetLibrary');
  105. const currentPaperInput = document.querySelector('#currentPaper');
  106. const runningCheckbox = document.querySelector('#running');
  107. targetLibraryInput.addEventListener('input', () => {
  108. GM.setValue('targetLibrary', targetLibraryInput.value.trim());
  109. });
  110. currentPaperInput.addEventListener('input', () => {
  111. GM.setValue('currentPaper', currentPaperInput.value.trim());
  112. });
  113. runningCheckbox.addEventListener('change', () => {
  114. GM.setValue('running', runningCheckbox.checked ? 'on' : 'off');
  115. });
  116. const targetLibrary = await GM.getValue('targetLibrary', '');
  117. const currentPaper = await GM.getValue('currentPaper', '');
  118. const running = await GM.getValue('running', 'off');
  119. targetLibraryInput.value = targetLibrary;
  120. currentPaperInput.value = currentPaper;
  121. runningCheckbox.checked = running === 'on';
  122. const params = new URL(window.location.href).searchParams;
  123. if (
  124. targetLibrary !== '' &&
  125. params.get('cites') === currentPaper &&
  126. params.get('q') === null &&
  127. running === 'on'
  128. ) {
  129. work(targetLibrary);
  130. }
  131. })();