content.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. var $ = document.querySelector.bind(document)
  2. var state = {
  3. theme,
  4. raw,
  5. content,
  6. compiler,
  7. html: '',
  8. markdown: '',
  9. toc: ''
  10. }
  11. chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
  12. if (req.message === 'reload') {
  13. location.reload(true)
  14. }
  15. else if (req.message === 'theme') {
  16. state.theme = req.theme
  17. m.redraw()
  18. }
  19. else if (req.message === 'raw') {
  20. state.raw = req.raw
  21. m.redraw()
  22. }
  23. })
  24. var oncreate = {
  25. markdown: () => {
  26. scroll()
  27. },
  28. html: () => {
  29. scroll()
  30. if (state.content.toc && !state.toc) {
  31. state.toc = toc()
  32. m.redraw()
  33. }
  34. setTimeout(() => Prism.highlightAll(), 20)
  35. }
  36. }
  37. function mount () {
  38. $('pre').style.display = 'none'
  39. var md = $('pre').innerText
  40. m.mount($('body'), {
  41. oninit: () => {
  42. ;((done) => {
  43. if (document.charset === 'UTF-8') {
  44. done()
  45. return
  46. }
  47. m.request({method: 'GET', url: location.href,
  48. deserialize: (body) => {
  49. done(body)
  50. return body
  51. }
  52. })
  53. })((data) => {
  54. state.markdown = data || md
  55. chrome.runtime.sendMessage({
  56. message: 'markdown',
  57. compiler: state.compiler,
  58. markdown: state.markdown
  59. }, (res) => {
  60. state.html = res.html
  61. m.redraw()
  62. })
  63. })
  64. },
  65. view: () => {
  66. var dom = []
  67. if (state.raw) {
  68. dom.push(m('pre#_markdown', {oncreate: oncreate.markdown}, state.markdown))
  69. $('body').classList.remove('_toc-left', '_toc-right')
  70. }
  71. else {
  72. if (state.theme) {
  73. dom.push(m('link#_theme [rel="stylesheet"] [type="text/css"]', {
  74. href: chrome.runtime.getURL('/themes/' + state.theme + '.css')
  75. }))
  76. }
  77. if (state.html) {
  78. dom.push(m('#_html', {oncreate: oncreate.html,
  79. class: /github(-dark)?/.test(state.theme) ? 'markdown-body' : 'markdown-theme'},
  80. m.trust(state.html)
  81. ))
  82. if (state.content.toc && state.toc) {
  83. dom.push(m.trust(state.toc))
  84. $('body').classList.add('_toc-left')
  85. }
  86. }
  87. }
  88. return (dom.length ? dom : m('div'))
  89. }
  90. })
  91. }
  92. function scroll () {
  93. if (state.content.scroll) {
  94. $('body').scrollTop = parseInt(localStorage.getItem('md-' + location.href))
  95. }
  96. else if (location.hash) {
  97. $('body').scrollTop = $(location.hash) && $(location.hash).offsetTop
  98. setTimeout(() => {
  99. $('body').scrollTop = $(location.hash) && $(location.hash).offsetTop
  100. }, 100)
  101. }
  102. }
  103. scroll.init = () => {
  104. if (state.content.scroll) {
  105. var timeout = null
  106. window.addEventListener('scroll', () => {
  107. clearTimeout(timeout)
  108. timeout = setTimeout(() => {
  109. localStorage.setItem('md-' + location.href, $('body').scrollTop)
  110. }, 100)
  111. })
  112. }
  113. setTimeout(scroll, 100)
  114. }
  115. if (document.readyState === 'complete') {
  116. mount()
  117. scroll.init()
  118. }
  119. else {
  120. window.addEventListener('DOMContentLoaded', mount)
  121. window.addEventListener('load', scroll.init)
  122. }
  123. var toc = (
  124. link = (header) => '<a href="#' + header.id + '">' + header.title + '</a>') =>
  125. Array.from($('#_html').childNodes)
  126. .filter((node) => /h[1-6]/i.test(node.tagName))
  127. .map((node) => ({
  128. id: node.getAttribute('id'),
  129. level: parseInt(node.tagName.replace('H', '')),
  130. title: node.innerText
  131. }))
  132. .reduce((html, header, index, headers) => {
  133. if (index) {
  134. var prev = headers[index - 1]
  135. }
  136. if (!index || prev.level === header.level) {
  137. html += link(header)
  138. }
  139. else if (prev.level > header.level) {
  140. while (prev.level-- > header.level) {
  141. html += '</div>'
  142. }
  143. html += link(header)
  144. }
  145. else if (prev.level < header.level) {
  146. html += '<div id="_ul">' + link(header)
  147. }
  148. return html
  149. }, '<div id="_toc"><div id="_ul">') + '</div></div>'