Notion Tags

Makes Notion better - #tags decoration

  1. // ==UserScript==
  2. // @name Notion Tags
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.5
  5. // @description Makes Notion better - #tags decoration
  6. // @author Andreas Huttenrauch
  7. // @match https://www.notion.so/*
  8. // @grant GM_log
  9. // @grant GM_addStyle
  10. // @run-at document-end
  11. // ==/UserScript==
  12.  
  13. var debug = false;
  14.  
  15. LOG ("starting up");
  16. GM_addStyle('div.gwstagblock { }');
  17. GM_addStyle('div.gwstagblock tag { padding: 1px 5px; font-weight: bold; background: red; border-radius: 5px; color: white; }');
  18.  
  19. // create an observer instance
  20. var observer = new MutationObserver(function(mutations) {
  21. mutations.forEach(function(mutation) {
  22. var target = false;
  23. if ( mutation.target.nodeName == "DIV" ) target = mutation.target;
  24. else target = mutation.target.parentElement;
  25. if ( target.getAttribute("contentEditable") == "true" ) target = target.parentElement;
  26. if ( ! target ) return;
  27. findtags(target);
  28. });
  29. });
  30. var config = { characterData: true, attributes: false, childList: true, subtree: true };
  31. var mutgt = document.body;
  32. observer.observe(mutgt, config);
  33. var lastBlock = false;
  34.  
  35. function findtags(elm) {
  36. elm = elm || document;
  37. //if ( typeof elm.querySelectorAll !== 'function' ) return;
  38. var blocks = elm.querySelectorAll("div[contenteditable='true']");
  39. blocks.forEach(function(el) {
  40. var s = el.textContent
  41. if ( s.indexOf("#") != -1 || el.classList.contains("gwstagblock")) {
  42. markuptags(el);
  43. }
  44. })
  45. }
  46.  
  47. function replaceTags(text, html) {
  48. var matches = text.match(/(?:^|\s)(#[^\n\s\t]+)/g);
  49. if ( matches ) {
  50. for (var i=0; i<matches.length; i++) {
  51. var word = matches[i].trim();
  52. if ( html.indexOf('<tag>'+word+'</tag>') == -1 ) {
  53. html = html.replace(word, '<tag>'+word+'</tag>');
  54. }
  55. }
  56. }
  57. matches = html.match(/<tag>([^#].*?)<\/tag>/g);
  58. if ( matches ) {
  59. for (i=0; i<matches.length; i++) {
  60. html = html.replace('<tag>'+matches[i]+'</tag>', matches[i]);
  61. }
  62. }
  63. return html;
  64. }
  65.  
  66. function removeTags(html) {
  67. var matches = html.match(/<tag>(.*?)<\/tag>/g);
  68. if ( matches ) {
  69. for (var i=0; i<matches.length; i++) {
  70. html = html.replace('<tag>'+matches[i]+'</tag>', matches[i]);
  71. }
  72. }
  73. return html;
  74. }
  75.  
  76. function lostFocusEvent() {
  77. if (document.activeElement === lastBlock) return;
  78. document.removeEventListener('keyup', lostFocusEvent);
  79. document.removeEventListener('click', lostFocusEvent);
  80. markuptags(lastBlock);
  81. }
  82.  
  83. function markuptags(element) {
  84. var isFocused = (document.activeElement === element);
  85. var text = element.textContent;
  86. var html = element.innerHTML;
  87. if ( isFocused ) {
  88. var untagged = removeTags(html);
  89. if ( untagged != html ) {
  90. element.innerHTML = untagged;
  91. }
  92. lastBlock = element;
  93. document.addEventListener('keyup', lostFocusEvent);
  94. document.addEventListener('click', lostFocusEvent);
  95. return;
  96. }
  97. var tagged = replaceTags(text, element.innerHTML);
  98. if ( element.innerHTML == tagged ) return;
  99. element.innerHTML = tagged;
  100. if ( text.indexOf("#") != -1 ) {
  101. if ( ! element.classList.contains("gwstagblock") ) {
  102. LOG("markuptags found: "+text);
  103. element.classList.add("gwstagblock");
  104. }
  105. } else if ( element.classList.contains("gwstagblock") ) {
  106. LOG("removing tag from: "+text);
  107. element.classList.remove("gwstagblock");
  108. }
  109. }
  110.  
  111. function LOG(...args) {
  112. if (!debug) return
  113. console.log('[Notion UserScript]', ...args)
  114. }
  115.  
  116.  

QingJ © 2025

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