simov 8 年之前
父节点
当前提交
59407f9ec0
共有 2 个文件被更改,包括 99 次插入0 次删除
  1. 61 0
      content/content.js
  2. 38 0
      css/content.css

+ 61 - 0
content/content.js

@@ -7,6 +7,7 @@ var state = {
   markdown: '',
   markdown: '',
   raw: window['raw'] || false,
   raw: window['raw'] || false,
   content: window['content'] || {},
   content: window['content'] || {},
+  toc: '',
   getURL: () => chrome.runtime.getURL('/themes/' + state.theme + '.css')
   getURL: () => chrome.runtime.getURL('/themes/' + state.theme + '.css')
 }
 }
 
 
@@ -34,6 +35,10 @@ var oncreate = {
     if (state.content.scroll) {
     if (state.content.scroll) {
       document.body.scrollTop = parseInt(localStorage.getItem('md-' + location.href))
       document.body.scrollTop = parseInt(localStorage.getItem('md-' + location.href))
     }
     }
+    if (state.content.toc && !state.toc) {
+      state.toc = toc()
+      m.redraw()
+    }
     setTimeout(() => Prism.highlightAll(), 20)
     setTimeout(() => Prism.highlightAll(), 20)
   }
   }
 }
 }
@@ -72,6 +77,7 @@ function mount () {
 
 
       if (state.raw) {
       if (state.raw) {
         dom.push(m('pre#markdown', {oncreate: oncreate.markdown}, state.markdown))
         dom.push(m('pre#markdown', {oncreate: oncreate.markdown}, state.markdown))
+        $('body').classList.remove('_toc-left', '_toc-right')
       }
       }
       if (state.theme && !state.raw) {
       if (state.theme && !state.raw) {
         dom.push(m('link#theme [rel="stylesheet"] [type="text/css"]', {
         dom.push(m('link#theme [rel="stylesheet"] [type="text/css"]', {
@@ -84,6 +90,11 @@ function mount () {
             class: /github(-dark)?/.test(state.theme) ? 'markdown-body' : 'markdown-theme'},
             class: /github(-dark)?/.test(state.theme) ? 'markdown-body' : 'markdown-theme'},
             m.trust(state.html))
             m.trust(state.html))
         )
         )
+        if (state.content.toc && state.toc) {
+          dom.push(m.trust(state.toc))
+          // TODO: should be configurable
+          $('body').classList.add('_toc-left')
+        }
       }
       }
 
 
       return (dom.length ? dom : m('div'))
       return (dom.length ? dom : m('div'))
@@ -116,3 +127,53 @@ else {
     window.addEventListener('load', scroll)
     window.addEventListener('load', scroll)
   }
   }
 }
 }
+
+function toc () {
+  // extract all headers
+
+  var headers = []
+
+  function walk (nodes) {
+    nodes.forEach((node) => {
+      var sub = Array.from(node.childNodes)
+      if (sub.length) {
+        walk(sub)
+      }
+      if (/h[1-6]/i.test(node.tagName)) {
+        headers.push({
+          id: node.getAttribute('id'),
+          level: parseInt(node.tagName.replace('H', '')),
+          title: node.innerText
+        })
+      }
+    })
+  }
+
+  walk(Array.from($('body').childNodes))
+
+  // generate TOC
+
+  var link = (header) =>
+    '<a href="#' + header.id + '">' + header.title + '</a>'
+
+  var html = '<div id="_toc"><div id="_ul">'
+
+  headers.forEach((header, index) => {
+    if (index) {
+      var prev = headers[index - 1]
+    }
+    if (!index || prev.level === header.level) {
+      html += link(header)
+    }
+    else if (prev.level > header.level) {
+      html += '</div>' + link(header)
+    }
+    else if (prev.level < header.level) {
+      html += '<div id="_ul">' + link(header)
+    }
+  })
+
+  html += '</div></div>'
+
+  return html
+}

+ 38 - 0
css/content.css

@@ -46,3 +46,41 @@ html, body {
 @media (min-width: 1200px) {
 @media (min-width: 1200px) {
   .markdown-theme { width: 1145px !important; }
   .markdown-theme { width: 1145px !important; }
 }
 }
+
+/*toc*/
+body {
+  display: flex;
+}
+body._toc-left { padding-left: 300px !important; }
+body._toc-right { padding-right: 300px !important; }
+#_toc {
+  position: fixed;
+  top: 0; bottom: 0; left: 0;
+  width: 300px;
+  height: 100%;
+  background: #fafafa;
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+#_toc #_ul {
+  padding: 0 0 0 20px !important;
+  margin: 0 !important;
+}
+#_toc #_ul a {
+  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif !important;
+  font-size: 14px !important;
+  line-height: 17px !important;
+  color: #364149 !important;
+  font-weight: normal !important;
+  font-style: normal !important;
+  text-decoration: none !important;
+  text-transform: none !important;
+  letter-spacing: 0.2px !important;
+  background: none !important;
+  border: 0 !important;
+  padding: 10px 15px !important;
+  display: block !important;
+}
+#_toc #_ul a:hover {
+  text-decoration: underline !important;
+}