background.js 6.4 KB

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