Trello Attach Cards

Parse description contents, attach cards those urls are mentioned in the contents

  1. // ==UserScript==
  2. // @name Trello Attach Cards
  3. // @description Parse description contents, attach cards those urls are mentioned in the contents
  4. // @version 1.0.0
  5. // @author Hikerpig
  6. // @copyright 2019 hikerpig (https://github.com/hikerpig)
  7. // @licence MIT
  8. // @match https://trello.com/**/*
  9. // @grant none
  10. // @namespace https://gf.qytechs.cn/users/325041
  11. // ==/UserScript==
  12.  
  13. ;(function() {
  14. 'use strict'
  15.  
  16. const TRELLO_CARD_LINK_PATTERN = /\/c\/([\d\w]+)\/?/
  17.  
  18. /**
  19. * @type MutationObserver
  20. */
  21. let mo
  22.  
  23. let autoAttachBtn
  24.  
  25. function processDesc() {
  26. const desc = document.querySelector('.js-desc')
  27. if (!desc) return
  28. const cardLinks = []
  29. desc.querySelectorAll('a').forEach((ele) => {
  30. const href = ele.href
  31. const matches = TRELLO_CARD_LINK_PATTERN.test(href)
  32. if (matches) {
  33. cardLinks.push({ href })
  34. }
  35. })
  36.  
  37. if (autoAttachBtn) {
  38. autoAttachBtn.remove()
  39. autoAttachBtn = null
  40. }
  41.  
  42. if (cardLinks.length) {
  43. const attachBtn = document.querySelector('.button-link.js-attach')
  44. if (attachBtn) {
  45. autoAttachBtn = document.createElement('div')
  46. autoAttachBtn.classList.add(['button-link'])
  47. autoAttachBtn.textContent = 'Auto Attach Cards'
  48. attachBtn.parentElement.appendChild(autoAttachBtn)
  49.  
  50. autoAttachBtn.onclick = function() {
  51. attachLinks(cardLinks)
  52. }
  53. }
  54. }
  55. }
  56.  
  57. function attachLinks(cardLinks) {
  58. let curLinkIndex = 0
  59. const curAttachHrefs = []
  60. document.querySelectorAll('.trello-card-attachment').forEach((ele) => {
  61. const firstA = ele.querySelector('a')
  62. if (firstA) {
  63. curAttachHrefs.push(firstA.href)
  64. }
  65. })
  66.  
  67. const hrefs = cardLinks.map(o => o.href).filter((href) => {
  68. return curAttachHrefs.indexOf(href) < 0
  69. })
  70.  
  71. function attachNextLink() {
  72. if (!hrefs[curLinkIndex]) return
  73. setTimeout(() => {
  74. const attachBtn = document.querySelector('.button-link.js-attach')
  75. attachBtn.click()
  76.  
  77. setTimeout(() => {
  78. const tryAdd = (retryTimes) => {
  79. const addLinkInput = document.getElementById('addLink')
  80. if (!addLinkInput) {
  81. if (!retryTimes) return
  82. setTimeout(() => {
  83. tryAdd(--retryTimes)
  84. }, 300);
  85. return
  86. }
  87. addLinkInput.value = hrefs[curLinkIndex]
  88. const attachSubmitBtn = document.querySelector('.js-add-attachment-url')
  89. attachSubmitBtn.click()
  90. curLinkIndex++
  91.  
  92. setTimeout(() => {
  93. attachNextLink()
  94. }, 500)
  95. }
  96.  
  97. tryAdd(4)
  98.  
  99. }, 500);
  100. }, 100);
  101. }
  102. attachNextLink()
  103. }
  104.  
  105. function bindOverlayEvents() {
  106. const tabParentEle = document.querySelector('.js-tab-parent')
  107. if (!mo) {
  108. mo = new MutationObserver(mutations => {
  109. let hasCardDetail = false
  110. mutations.forEach(m => {
  111. if (m.addedNodes.length) {
  112. hasCardDetail = true
  113. }
  114. })
  115.  
  116. if (hasCardDetail) {
  117. processDesc()
  118. }
  119. })
  120. }
  121. mo.observe(tabParentEle, { childList: true })
  122. }
  123.  
  124. // ---------------- start -----------------------
  125. processDesc()
  126. bindOverlayEvents()
  127. })()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址