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