notion plugin

add notion outline view

目前为 2023-07-25 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name notion plugin
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.5
  5. // @description add notion outline view
  6. // @author fengxxc
  7. // @match https://www.notion.so/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=notion.so
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. /**
  17. * 一、二、三 级标题的className分别为
  18. * notion-header-block
  19. * notion-sub_header-block
  20. * notion-sub_sub_header-block
  21. */
  22. function getOutlineTokens() {
  23. const headerBlock = document.querySelectorAll('.notion-header-block,.notion-sub_header-block,.notion-sub_sub_header-block')
  24. const tokens = []
  25. for (var i = 0; i < headerBlock.length; i++) {
  26. const id = headerBlock[i].getAttribute('data-block-id').replaceAll('-', '')
  27. // const notranslate = headerBlock[i].querySelector('.notranslate')
  28. const level = headerBlock[i].className.split('sub').length
  29. const header = headerBlock[i].innerText
  30. tokens.push({id, level, header})
  31. }
  32. return tokens
  33. }
  34.  
  35. function getOutlineHTMLs(outlineTokens) {
  36. const pathname = window.location.pathname
  37. return outlineTokens.map(token => (`
  38. <a href="${pathname}#${token.id}" rel="noopener noreferrer" style="display: block; color: inherit; text-decoration: none;">
  39. <div class="notion-focusable" role="button" tabindex="0" style="user-select: none; transition: background 20ms ease-in 0s; cursor: pointer; width: 100%;">
  40. <div style="padding: 6px 2px; font-size: 14px; line-height: 1.3; display: flex; align-items: center; margin-left: ${(token.level-1) * 24}px;">
  41. <div class="notranslate" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis; background-image: linear-gradient(to right, rgba(55, 53, 47, 0.16) 0%, rgba(55, 53, 47, 0.16) 100%); background-repeat: repeat-x; background-position: 0px 100%; background-size: 100% 1px;">
  42. ${token.header}
  43. </div>
  44. </div>
  45. </div>
  46. </a>
  47. `))
  48. }
  49.  
  50. function getOutlineBox(outlineHTMLs) {
  51. return `
  52. <div id="outline_view" style="position: fixed; top: 47px; right: 16px; z-index: 2; background-color: #f0f8ffcc; padding: 9px; height: calc(100% - 47px); overflow-y: auto; max-width: 33%;">
  53. ${outlineHTMLs.join('')}
  54. </div>
  55. `
  56. }
  57.  
  58. let notionFrame = null
  59. let existBox = false
  60. let lastTokenStr = ''
  61. const initInterval = setInterval(() => {
  62. // 内容居左
  63. document.querySelector('.whenContentEditable > main').style.justifyContent = 'left';
  64. notionFrame = notionFrame || document.querySelector('.notion-frame')
  65. if (notionFrame) {
  66. // init completed
  67. // clearInterval(initInterval)
  68. const tokens = getOutlineTokens()
  69. const tokenStr = JSON.stringify(tokens)
  70. if (!existBox) {
  71. notionFrame.insertAdjacentHTML('afterend', getOutlineBox(getOutlineHTMLs(tokens)))
  72. existBox = true
  73. lastTokenStr = tokenStr
  74. } else {
  75. if (lastTokenStr != tokenStr) {
  76. document.querySelector('#outline_view').innerHTML = getOutlineHTMLs(tokens).join('')
  77. lastTokenStr = tokenStr
  78. }
  79. }
  80. }
  81. }, 1000)
  82.  
  83. })();

QingJ © 2025

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