background.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. // chrome.storage.sync.clear()
  2. // chrome.permissions.getAll((p) => chrome.permissions.remove({origins: p.origins}))
  3. chrome.storage.sync.get((res) => {
  4. var match = '\\.(?:markdown|mdown|mkdn|md|mkd|mdwn|mdtxt|mdtext|text)(?:#.*)?$'
  5. var defaults = {
  6. theme: 'github',
  7. compiler: 'marked',
  8. marked: md.marked.defaults,
  9. remark: md.remark.defaults,
  10. content: {
  11. toc: false,
  12. scroll: true
  13. },
  14. raw: false,
  15. match,
  16. origins: {
  17. 'file://': match
  18. }
  19. }
  20. var options = !Object.keys(res).length ? defaults : res
  21. // v2.2 -> v2.3
  22. if (!options.match || !options.origins) {
  23. options.match = match
  24. options.origins = {
  25. 'file://': match
  26. }
  27. }
  28. // v2.3 -> v2.4
  29. else if (!options.origins['file://']) {
  30. options.origins['file://'] = match
  31. }
  32. // v2.4 -> v2.5
  33. if (!options.compiler) {
  34. options.compiler = options.options
  35. }
  36. if (!options.content) {
  37. options.content = defaults.content
  38. }
  39. // v2.7 -> v2.8
  40. if (!options.marked) {
  41. options.compiler = 'marked'
  42. options.marked = md.marked.defaults
  43. }
  44. // v2.8 -> v2.9
  45. if (!options.remark) {
  46. options.remark = md.remark.defaults
  47. }
  48. if (options.compiler === 'showdown') {
  49. options.compiler = 'remark'
  50. }
  51. chrome.storage.sync.set(options)
  52. // reload extension bug
  53. chrome.permissions.getAll((permissions) => {
  54. var origins = Object.keys(res.origins || {})
  55. chrome.permissions.remove({
  56. origins: permissions.origins
  57. .filter((origin) => (origins.indexOf(origin.slice(0, -2)) === -1))
  58. })
  59. })
  60. })
  61. function parallel (tasks, done) {
  62. var complete = 0, error, result = {}
  63. tasks.forEach((task) => task((err, res) => {
  64. if (error) {
  65. return
  66. }
  67. if (err) {
  68. error = err
  69. done(err)
  70. return
  71. }
  72. if (res) {
  73. Object.keys(res).forEach((key) => {
  74. result[key] = res[key]
  75. })
  76. }
  77. if (++complete === tasks.length) {
  78. done(null, result)
  79. }
  80. }))
  81. }
  82. chrome.tabs.onUpdated.addListener((id, info, tab) => {
  83. if (info.status === 'loading') {
  84. parallel([
  85. (done) => {
  86. chrome.tabs.executeScript(id, {
  87. code: 'JSON.stringify({location, state: window.state})',
  88. runAt: 'document_start'
  89. }, (res) => {
  90. if (chrome.runtime.lastError) {
  91. done(new Error('Origin not allowed'))
  92. return
  93. }
  94. try {
  95. res = JSON.parse(res)
  96. }
  97. catch (err) {
  98. done(new Error('JSON parse error'))
  99. return
  100. }
  101. done(null, res)
  102. })
  103. },
  104. (done) => {
  105. chrome.storage.sync.get((res) => done(null, res))
  106. }
  107. ], (err, res) => {
  108. if (err) {
  109. return
  110. }
  111. var path =
  112. res.origins[res.location.origin] ||
  113. res.origins['*://' + res.location.host] ||
  114. res.origins['*://*']
  115. if (!path) { // v2.2 -> v2.3
  116. return
  117. }
  118. if (!res.state && new RegExp(path).test(res.location.href)) {
  119. chrome.tabs.executeScript(id, {
  120. code: [
  121. 'document.querySelector("pre").style.visibility = "hidden"',
  122. 'var theme = "' + res.theme + '"',
  123. 'var raw = ' + res.raw,
  124. 'var content = ' + JSON.stringify(res.content),
  125. 'var compiler = "' + res.compiler + '"'
  126. ].join(';'), runAt: 'document_start'})
  127. chrome.tabs.insertCSS(id, {file: 'css/content.css', runAt: 'document_start'})
  128. chrome.tabs.insertCSS(id, {file: 'vendor/prism.css', runAt: 'document_start'})
  129. chrome.tabs.executeScript(id, {file: 'vendor/mithril.min.js', runAt: 'document_start'})
  130. chrome.tabs.executeScript(id, {file: 'vendor/prism.js', runAt: 'document_start'})
  131. chrome.tabs.executeScript(id, {file: 'content/content.js', runAt: 'document_start'})
  132. chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
  133. chrome.pageAction.show(tabs[0].id)
  134. })
  135. }
  136. })
  137. }
  138. })
  139. chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
  140. if (req.message === 'markdown') {
  141. md[req.compiler].compile(req.markdown, sendResponse)
  142. }
  143. else if (req.message === 'settings') {
  144. chrome.storage.sync.get((res) => {
  145. sendResponse({
  146. compiler: res.compiler, options: res[res.compiler],
  147. content: res.content, theme: res.theme, raw: res.raw
  148. })
  149. })
  150. }
  151. else if (req.message === 'compiler.name') {
  152. chrome.storage.sync.set({compiler: req.compiler}, sendResponse)
  153. sendMessage({message: 'reload'})
  154. }
  155. else if (req.message === 'compiler.options') {
  156. chrome.storage.sync.set({[req.compiler]: req.options}, sendResponse)
  157. sendMessage({message: 'reload'})
  158. }
  159. else if (req.message === 'content') {
  160. chrome.storage.sync.set({content: req.content}, sendResponse)
  161. sendMessage({message: 'reload'})
  162. }
  163. else if (req.message === 'defaults') {
  164. chrome.storage.sync.set({
  165. theme: 'github',
  166. compiler: 'marked',
  167. marked: md.marked.defaults,
  168. remark: md.remark.defaults,
  169. content: {toc: false, scroll: true},
  170. raw: false
  171. }, sendResponse)
  172. sendMessage({message: 'reload'})
  173. }
  174. else if (req.message === 'theme') {
  175. chrome.storage.sync.set({theme: req.theme}, sendResponse)
  176. sendMessage({message: 'theme', theme: req.theme})
  177. }
  178. else if (req.message === 'raw') {
  179. chrome.storage.sync.set({raw: req.raw}, sendResponse)
  180. sendMessage({message: 'raw', raw: req.raw})
  181. }
  182. else if (req.message === 'advanced') {
  183. chrome.management.getSelf((extension) => {
  184. chrome.tabs.create({url: extension.optionsUrl}, sendResponse)
  185. })
  186. }
  187. else if (req.message === 'origins') {
  188. chrome.storage.sync.get('origins', sendResponse)
  189. }
  190. else if (req.message === 'add') {
  191. chrome.storage.sync.get(['match', 'origins'], (res) => {
  192. res.origins[req.origin] = res.match
  193. chrome.storage.sync.set({origins: res.origins}, sendResponse)
  194. })
  195. }
  196. else if (req.message === 'remove') {
  197. chrome.storage.sync.get('origins', (res) => {
  198. delete res.origins[req.origin]
  199. chrome.storage.sync.set({origins: res.origins}, sendResponse)
  200. })
  201. }
  202. else if (req.message === 'update') {
  203. chrome.storage.sync.get('origins', (res) => {
  204. res.origins[req.origin] = req.match
  205. chrome.storage.sync.set({origins: res.origins}, sendResponse)
  206. })
  207. }
  208. return true
  209. })
  210. function sendMessage (req) {
  211. chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
  212. chrome.tabs.sendMessage(tabs[0].id, req)
  213. })
  214. }