Stack Exchange Formatter

Format contents on Stack Enchange websites such as stackoverflow.com and askubuntu.com for easy saving to Evernote.

目前为 2019-02-24 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Stack Exchange Formatter
  3. // @namespace https://greasyfork.org/en/users/211578
  4. // @version 0.2
  5. // @description Format contents on Stack Enchange websites such as stackoverflow.com and askubuntu.com for easy saving to Evernote.
  6. // @author twchen
  7. // @include https://stackoverflow.com/questions/*
  8. // @include https://*.stackexchange.com/questions/*
  9. // @include https://superuser.com/questions/*
  10. // @include https://serverfault.com/questions/*
  11. // @include https://askubuntu.com/questions/*
  12. // @run-at document-idle
  13. // ==/UserScript==
  14.  
  15. (function () {
  16. "use strict";
  17. const description = document.querySelector("#question .postcell .post-text");
  18. const body = document.body;
  19. let saveDesc = true;
  20. const answersToSave = [];
  21.  
  22. function addLinks() {
  23. const answers = document.querySelectorAll(".answer > .post-layout");
  24. answers.forEach(ans => {
  25. const text = ans.querySelector(".answercell .post-text");
  26. const menu = ans.querySelector(".post-menu");
  27. const saveAnsLink = document.createElement("a");
  28. saveAnsLink.href = "#";
  29. saveAnsLink.text = 'save this answer';
  30. saveAnsLink.onclick = event => {
  31. event.preventDefault();
  32. answersToSave.push(text);
  33. saveDesc = false;
  34. save();
  35. };
  36. const saveQALink = document.createElement('a');
  37. saveQALink.href = '#';
  38. saveQALink.text = 'save this Q&A';
  39. saveQALink.onclick = event => {
  40. event.preventDefault();
  41. answersToSave.push(text);
  42. save();
  43. };
  44. menu.append(saveAnsLink, saveQALink);
  45. });
  46.  
  47. const div = document.createElement('div');
  48. div.classList.add('pl8', 'aside-cta', 'grid--cell');
  49. const chooseLink = document.createElement('a');
  50. chooseLink.href = "#";
  51. chooseLink.classList.add("d-inline-flex", "ai-center", "ws-nowrap", "s-btn", "s-btn__primary");
  52. chooseLink.text = "Save Multiple Answers";
  53. chooseLink.onclick = event => {
  54. event.preventDefault();
  55. startChoosing();
  56. };
  57. div.appendChild(chooseLink);
  58. const header = document.querySelector('#question-header');
  59. header.append(div);
  60. }
  61.  
  62. function startChoosing() {
  63. const votingContainers = document.querySelectorAll('.js-voting-container');
  64. votingContainers.forEach((container, i) => {
  65. const checkbox = document.createElement('input');
  66. checkbox.type = 'checkbox';
  67. checkbox.id = `checkbox${i}`;
  68. checkbox.style.margin = 'auto';
  69. const label = document.createElement('label');
  70. label.htmlFor = `checkbox${i}`;
  71. label.innerText = 'Keep';
  72. label.style.margin = 'auto';
  73. container.prepend(checkbox, label);
  74. });
  75.  
  76. const doneButton = document.createElement('button');
  77. doneButton.innerText = "Done";
  78. Object.assign(doneButton.style, {
  79. position: 'fixed',
  80. right: '2rem',
  81. top: '50%',
  82. zIndex: '100'
  83. });
  84. doneButton.onclick = event => {
  85. event.preventDefault();
  86. doneChoosing();
  87. };
  88. body.appendChild(doneButton);
  89. }
  90.  
  91. function doneChoosing() {
  92. const question = document.querySelector('#question');
  93. const questionCheckbox = question.querySelector('.js-voting-container input[type="checkbox"]');
  94. saveDesc = questionCheckbox.checked;
  95. const answers = document.querySelectorAll(".answer > .post-layout");
  96. answers.forEach(ans => {
  97. const text = ans.querySelector(".answercell .post-text");
  98. const checkbox = ans.querySelector(".js-voting-container input[type='checkbox']");
  99. if (checkbox.checked) {
  100. answersToSave.push(text);
  101. }
  102. });
  103. if (answersToSave.length == 0) {
  104. alert('Choose at least one answer to save!');
  105. } else {
  106. save();
  107. }
  108.  
  109. }
  110.  
  111. function save() {
  112. removeAllChildren(body);
  113. const div = document.createElement("div");
  114. div.style.margin = 'auto';
  115. if (saveDesc) {
  116. div.appendChild(description);
  117. }
  118. answersToSave.forEach(ans => {
  119. const hr = document.createElement("hr");
  120. hr.style.height = '3px';
  121. hr.style.marginTop = '4rem';
  122. div.appendChild(hr);
  123. div.appendChild(ans);
  124. });
  125. body.appendChild(div);
  126. }
  127.  
  128. function removeAllChildren(el) {
  129. while (el.firstChild) {
  130. el.removeChild(el.firstChild);
  131. }
  132. }
  133.  
  134. addLinks();
  135. })();