GitHub README TOC

Add table of contents(TOC) for README in GitHub.

当前为 2023-04-24 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name GitHub README TOC
  3. // @namespace npm/vite-plugin-monkey
  4. // @version 0.3.0
  5. // @author pacexy <pacexy@gmail.com>
  6. // @description Add table of contents(TOC) for README in GitHub.
  7. // @license MIT
  8. // @icon https://github.com/favicon.ico
  9. // @homepage https://github.com/pacexy/github-readme-toc#readme
  10. // @homepageURL https://github.com/pacexy/github-readme-toc#readme
  11. // @source https://github.com/pacexy/github-readme-toc
  12. // @supportURL https://github.com/pacexy/github-readme-toc/issues
  13. // @match https://github.com/**
  14. // @require https://cdn.jsdelivr.net/npm/react@18.2.0/umd/react.production.min.js
  15. // @require https://cdn.jsdelivr.net/npm/react-dom@18.2.0/umd/react-dom.production.min.js
  16. // ==/UserScript==
  17.  
  18. (e=>{const t=document.createElement("style");t.dataset.source="vite-plugin-monkey",t.textContent=e,document.head.append(t)})(" #github-readme-toc{position:sticky;z-index:30;top:0px!important;padding:24px 0;margin-top:24px;border-top:1px solid var(--color-border-muted)}#github-readme-toc ul{list-style:none;overflow:auto;max-height:100vh;padding-right:8px}#github-readme-toc ul>li{margin-top:8px}#github-readme-toc a{color:var(--color-fg-default)}#github-readme-toc a:hover{color:var(--color-accent-fg);text-decoration:none} ");
  19.  
  20. (function (require$$0, require$$0$1) {
  21. 'use strict';
  22.  
  23. var jsxRuntimeExports = {};
  24. var jsxRuntime = {
  25. get exports() {
  26. return jsxRuntimeExports;
  27. },
  28. set exports(v) {
  29. jsxRuntimeExports = v;
  30. }
  31. };
  32. var reactJsxRuntime_production_min = {};
  33. /**
  34. * @license React
  35. * react-jsx-runtime.production.min.js
  36. *
  37. * Copyright (c) Facebook, Inc. and its affiliates.
  38. *
  39. * This source code is licensed under the MIT license found in the
  40. * LICENSE file in the root directory of this source tree.
  41. */
  42. var f = require$$0, k = Symbol.for("react.element"), l = Symbol.for("react.fragment"), m$1 = Object.prototype.hasOwnProperty, n = f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, p = { key: true, ref: true, __self: true, __source: true };
  43. function q(c, a, g) {
  44. var b, d = {}, e = null, h = null;
  45. void 0 !== g && (e = "" + g);
  46. void 0 !== a.key && (e = "" + a.key);
  47. void 0 !== a.ref && (h = a.ref);
  48. for (b in a)
  49. m$1.call(a, b) && !p.hasOwnProperty(b) && (d[b] = a[b]);
  50. if (c && c.defaultProps)
  51. for (b in a = c.defaultProps, a)
  52. void 0 === d[b] && (d[b] = a[b]);
  53. return { $$typeof: k, type: c, key: e, ref: h, props: d, _owner: n.current };
  54. }
  55. reactJsxRuntime_production_min.Fragment = l;
  56. reactJsxRuntime_production_min.jsx = q;
  57. reactJsxRuntime_production_min.jsxs = q;
  58. (function(module) {
  59. {
  60. module.exports = reactJsxRuntime_production_min;
  61. }
  62. })(jsxRuntime);
  63. var client = {};
  64. var m = require$$0$1;
  65. {
  66. client.createRoot = m.createRoot;
  67. client.hydrateRoot = m.hydrateRoot;
  68. }
  69. const name = "github-readme-toc";
  70. function assert(el) {
  71. if (!el) {
  72. throw new Error("Element not exists");
  73. }
  74. }
  75. function ensureElements() {
  76. var _a;
  77. const container = (_a = document.querySelector(".BorderGrid")) == null ? void 0 : _a.parentElement;
  78. const md = document.querySelector("article.markdown-body");
  79. assert(container);
  80. assert(md);
  81. return { container, md };
  82. }
  83. function getToc() {
  84. return [...ensureElements().md.children].filter((child) => child.tagName.match(/H\d/)).map((heading) => {
  85. var _a;
  86. const depth = Number(heading.tagName.slice(1));
  87. const anchor = heading.querySelector("a.anchor");
  88. return {
  89. depth,
  90. text: (_a = heading.textContent) == null ? void 0 : _a.trim(),
  91. url: anchor == null ? void 0 : anchor.href
  92. };
  93. });
  94. }
  95. const Toc = ({ toc }) => {
  96. return /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { children: toc.map((h, i) => /* @__PURE__ */ jsxRuntimeExports.jsx("li", { style: { paddingLeft: (h.depth - 1) * 16 }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: h.url, children: h.text }) }, i)) });
  97. };
  98. function App() {
  99. const toc = getToc();
  100. return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
  101. /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "h4 mb-3", children: "Table of Contents" }),
  102. /* @__PURE__ */ jsxRuntimeExports.jsx(Toc, { toc })
  103. ] });
  104. }
  105. async function render() {
  106. let root = document.querySelector(`#${name}`);
  107. if (root) {
  108. return;
  109. }
  110. const container = ensureElements().container;
  111. root = document.createElement("div");
  112. root.id = name;
  113. container.append(root);
  114. client.createRoot(root).render(
  115. /* @__PURE__ */ jsxRuntimeExports.jsx(require$$0.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(App, {}) })
  116. );
  117. }
  118. function run() {
  119. render().then(() => {
  120. }).catch((error) => {
  121. });
  122. }
  123. ["pjax:end", "turbo:render"].forEach((e) => {
  124. document.addEventListener(e, () => {
  125. run();
  126. });
  127. });
  128. run();
  129.  
  130. })(React, ReactDOM);