🏠 返回首頁 

Greasy Fork is available in English.

ao3 download buttons

Adds download buttons to each work blurb on AO3's works index pages.


安装此脚本?
  1. // ==UserScript==
  2. // @name ao3 download buttons
  3. // @description Adds download buttons to each work blurb on AO3's works index pages.
  4. // @namespace ao3
  5. // @include http*://archiveofourown.org/*works*
  6. // @include http*://archiveofourown.org/*bookmarks*
  7. // @include http*://archiveofourown.org/*readings*
  8. // @include http*://archiveofourown.org/series/*
  9. // @grant none
  10. // @version 2.4
  11. // ==/UserScript==
  12. (function () {
  13. const blurbs = Array.from(document.querySelectorAll('li.blurb'));
  14. if (!blurbs.length) {
  15. return;
  16. }
  17. const style = document.createElement('style');
  18. style.innerHTML = `
  19. .blurb .download.actions {
  20. position: absolute;
  21. right: 0.5em;
  22. top: 2.2em;
  23. white-space: nowrap;
  24. }
  25. .blurb .download .expandable {
  26. position: absolute;
  27. right: calc(100% + 0.5em);
  28. top: -0.5em;
  29. }
  30. .blurb .download .expandable li {
  31. display: inline-block;
  32. margin: 0;
  33. }
  34. @media only screen and (min-width: 800px) {
  35. .blurb .download.actions {
  36. right: 7em;
  37. top: 0.5em;
  38. }
  39. }
  40. `;
  41. document.head.appendChild(style);
  42. blurbs.forEach(blurb => {
  43. let workId;
  44. let title;
  45. try {
  46. const titleLink = blurb.querySelector('.header.module .heading a');
  47. title = titleLink.textContent.trim();
  48. workId = (titleLink.href.match(/\/works\/(\d+)\b/) || [])[1];
  49. } catch (ex) {
  50. }
  51. if (!workId) {
  52. console.log('[ao3 download buttons] - skipping non-downloadable blurb:', blurb);
  53. return;
  54. }
  55. const formats = ['azw3', 'epub', 'mobi', 'pdf', 'html'];
  56. const tuples = formats
  57. .map(ext => [
  58. ext.toUpperCase(),
  59. `/downloads/${workId}/${encodeURIComponent(title)}.${ext}?updated_at=${Date.now()}`
  60. ]);
  61. blurb.innerHTML += `
  62. <div class="download actions" aria-haspopup="true">
  63. <a href="#" class="collapsed">Download</a>
  64. <ul class="expandable secondary hidden">
  65. ${
  66. tuples.map(([label, href]) => `
  67. <li>
  68. <a href=${href}>
  69. ${label}
  70. </a>
  71. </li>
  72. `)
  73. .join('')
  74. }
  75. </ul>
  76. </div>
  77. `;
  78. blurb.querySelector('.download.actions > a').addEventListener('click', ev => {
  79. const button = ev.currentTarget;
  80. button.classList.toggle('collapsed');
  81. button.classList.toggle('expanded');
  82. button.parentNode
  83. .querySelector('.expandable')
  84. .classList.toggle('hidden');
  85. ev.preventDefault();
  86. });
  87. });
  88. })();