JIRA Links

Turn JIRA ticket names into links

  1. // ==UserScript==
  2. // @name JIRA Links
  3. // @author Nik Rolls
  4. // @description Turn JIRA ticket names into links
  5. // @match *://*/*
  6. // @require https://greasyfork.org/scripts/395037-monkeyconfig-modern/code/MonkeyConfig%20Modern.js?version=764968
  7. // @grant GM_getMetadata
  8. // @grant GM_getValue
  9. // @grant GM_setValue
  10. // @grant GM_registerMenuCommand
  11. // @grant GM_addStyle
  12. // @namespace https://greasyfork.org/users/503103
  13. // @version 0.0.1.20200429221337
  14. // ==/UserScript==
  15.  
  16. (function() {
  17. 'use strict';
  18. const cfg = new MonkeyConfig({
  19. menuCommand: true,
  20. params: {
  21. domain: {
  22. label: "Your JIRA domain",
  23. type: 'text'
  24. },
  25. prefix: {
  26. label: "Ticket name prefix<br/><small>eg: if your ticket IDs look like<br/>'AB-1234', the prefix would be<br/>'AB'.</small>",
  27. type: 'text'
  28. }
  29. }
  30. });
  31. let interval = null;
  32. document.addEventListener('visibilitychange', detectVisibility);
  33. detectVisibility();
  34. function detectVisibility() {
  35. if (document.visibilityState === 'visible') {
  36. startWatching();
  37. } else {
  38. stopWatching();
  39. }
  40. }
  41. function startWatching() {
  42. if (cfg.get('domain') && cfg.get('prefix')) {
  43. augmentLinks();
  44. interval = window.setInterval(augmentLinks, 1000);
  45. }
  46. }
  47. function stopWatching() {
  48. if (interval) {
  49. window.clearInterval(interval);
  50. }
  51. }
  52. function augmentLinks() {
  53. const domain = cfg.get('domain').toLowerCase();
  54. const prefix = cfg.get('prefix').replace(/[^A-Za-z]/g, '').toUpperCase();
  55. const items = document.evaluate(`/html/body//*[not(self::style or self::script or self::a or self::input or self::textarea or boolean(@contenteditable)) and
  56. text()[contains(.,"${prefix}-") or contains(.,"${prefix}_")]]`, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  57. for (var i = 0; i < items.snapshotLength; i++) {
  58. const item = items.snapshotItem(i);
  59. console.log(item);
  60. const pattern = new RegExp(`(?<!<a[^>]+>)\\b(${prefix}(?:-|_)(\\d+))([\\b\\W])`, 'g');
  61. if (!item.closest('a') && !item.closest('[contenteditable]') && item.innerHTML.match(pattern)) {
  62. item.innerHTML = item.innerHTML.replace(pattern, `<a href="https://${domain}/secure/QuickSearch.jspa?searchString=$2">$1</a>$3`);
  63. }
  64. }
  65. }
  66. })();