popup.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. var state = {
  2. compiler: '',
  3. options: {},
  4. content: {},
  5. theme: '',
  6. themes: [],
  7. raw: false,
  8. tab: '',
  9. tabs: ['theme', 'compiler', 'content'],
  10. compilers: [],
  11. description: {
  12. compiler: {},
  13. content: {
  14. emoji: 'Convert emoji :shortnames: into EmojiOne images',
  15. scroll: 'Remember scroll position',
  16. toc: 'Generate Table of Contents',
  17. mathjax: 'Render MathJax formulas',
  18. }
  19. }
  20. }
  21. var events = {
  22. tab: (e) => {
  23. state.tab = e.target.hash.replace('#tab-', '')
  24. localStorage.setItem('tab', state.tab)
  25. return false
  26. },
  27. compiler: {
  28. name: (e) => {
  29. state.compiler = state.compilers[e.target.selectedIndex]
  30. chrome.runtime.sendMessage({
  31. message: 'popup.compiler.name',
  32. compiler: state.compiler,
  33. }, () => {
  34. chrome.runtime.sendMessage({message: 'popup'}, init)
  35. })
  36. },
  37. options: (e) => {
  38. state.options[e.target.name] = !state.options[e.target.name]
  39. chrome.runtime.sendMessage({
  40. message: 'popup.compiler.options',
  41. compiler: state.compiler,
  42. options: state.options,
  43. })
  44. }
  45. },
  46. content: (e) => {
  47. state.content[e.target.name] = !state.content[e.target.name]
  48. chrome.runtime.sendMessage({
  49. message: 'popup.content',
  50. content: state.content,
  51. })
  52. },
  53. theme: (e) => {
  54. state.theme = state.themes[e.target.selectedIndex]
  55. chrome.runtime.sendMessage({
  56. message: 'popup.theme',
  57. theme: state.theme
  58. })
  59. },
  60. raw: () => {
  61. state.raw = !state.raw
  62. chrome.runtime.sendMessage({
  63. message: 'popup.raw',
  64. raw: state.raw
  65. })
  66. },
  67. defaults: () => {
  68. chrome.runtime.sendMessage({
  69. message: 'popup.defaults'
  70. }, () => {
  71. chrome.runtime.sendMessage({message: 'popup'}, init)
  72. localStorage.removeItem('tab')
  73. state._tabs.activeTabIndex = 0
  74. })
  75. },
  76. advanced: () => {
  77. chrome.runtime.sendMessage({message: 'popup.advanced'})
  78. }
  79. }
  80. var init = (res) => {
  81. state.compiler = res.compiler
  82. state.options = res.options
  83. state.content = res.content
  84. state.theme = res.theme
  85. state.themes = chrome.runtime.getManifest().web_accessible_resources
  86. .filter((file) => file.indexOf('/themes/') === 0)
  87. .map((file) => file.replace(/\/themes\/(.*)\.css/, '$1'))
  88. state.raw = res.raw
  89. state.tab = localStorage.getItem('tab') || 'theme'
  90. state.compilers = res.compilers
  91. state.description.compiler = res.description
  92. m.redraw()
  93. }
  94. chrome.runtime.sendMessage({message: 'popup'}, init)
  95. var oncreate = {
  96. ripple: (vnode) => {
  97. mdc.ripple.MDCRipple.attachTo(vnode.dom)
  98. },
  99. tabs: (vnode) => {
  100. state._tabs = mdc.tabs.MDCTabBar.attachTo(vnode.dom)
  101. setTimeout(() => {
  102. state._tabs.activeTabIndex = state.tabs.indexOf(state.tab)
  103. }, 250)
  104. }
  105. }
  106. var onupdate = (tab, key) => (vnode) => {
  107. var value = tab === 'compiler' ? state.options[key]
  108. : tab === 'content' ? state.content[key]
  109. : null
  110. if (vnode.dom.classList.contains('is-checked') !== value) {
  111. vnode.dom.classList.toggle('is-checked')
  112. }
  113. }
  114. m.mount(document.querySelector('body'), {
  115. view: (vnode) =>
  116. m('#popup',
  117. // raw
  118. m('button.mdc-button mdc-button--raised m-button', {
  119. oncreate: oncreate.ripple,
  120. onclick: events.raw
  121. },
  122. (state.raw ? 'Html' : 'Markdown')
  123. ),
  124. // defaults
  125. m('button.mdc-button mdc-button--raised m-button', {
  126. oncreate: oncreate.ripple,
  127. onclick: events.defaults
  128. },
  129. 'Defaults'
  130. ),
  131. // tabs
  132. m('nav.mdc-tab-bar m-tabs', {
  133. oncreate: oncreate.tabs,
  134. onclick: events.tab
  135. },
  136. state.tabs.map((tab) =>
  137. m('a.mdc-tab', {
  138. href: '#tab-' + tab,
  139. },
  140. tab
  141. )),
  142. m('span.mdc-tab-bar__indicator')
  143. ),
  144. m('.m-panels',
  145. // theme
  146. m('.m-panel', {
  147. class: state.tab === 'theme' ? 'is-active' : ''
  148. },
  149. m('select.mdc-elevation--z2 m-select', {
  150. onchange: events.theme
  151. },
  152. state.themes.map((theme) =>
  153. m('option', {selected: state.theme === theme}, theme)
  154. )
  155. )
  156. ),
  157. // compiler
  158. m('.m-panel', {
  159. class: state.tab === 'compiler' ? 'is-active' : ''
  160. },
  161. m('select.mdc-elevation--z2 m-select', {
  162. onchange: events.compiler.name
  163. },
  164. state.compilers.map((name) =>
  165. m('option', {selected: state.compiler === name}, name)
  166. )
  167. ),
  168. m('.scroll', {
  169. class: Object.keys(state.options)
  170. .filter((key) => typeof state.options[key] === 'boolean')
  171. .length > 8
  172. ? 'max' : ''
  173. },
  174. Object.keys(state.options)
  175. .filter((key) => typeof state.options[key] === 'boolean')
  176. .map((key) =>
  177. m('label.mdc-switch m-switch', {
  178. onupdate: onupdate('compiler', key),
  179. title: state.description.compiler[key]
  180. },
  181. m('input.mdc-switch__native-control', {
  182. type: 'checkbox',
  183. name: key,
  184. checked: state.options[key],
  185. onchange: events.compiler.options
  186. }),
  187. m('.mdc-switch__background', m('.mdc-switch__knob')),
  188. m('span.mdc-switch-label', key)
  189. )
  190. )
  191. )
  192. ),
  193. // content
  194. m('.m-panel', {
  195. class: state.tab === 'content' ? 'is-active' : ''
  196. },
  197. m('.scroll', Object.keys(state.content).map((key) =>
  198. m('label.mdc-switch m-switch', {
  199. onupdate: onupdate('content', key),
  200. title: state.description.content[key]
  201. },
  202. m('input.mdc-switch__native-control', {
  203. type: 'checkbox',
  204. name: key,
  205. checked: state.content[key],
  206. onchange: events.content
  207. }),
  208. m('.mdc-switch__background', m('.mdc-switch__knob')),
  209. m('span.mdc-switch-label', key)
  210. ))
  211. )
  212. )
  213. ),
  214. // advanced options
  215. m('button.mdc-button mdc-button--raised m-button', {
  216. oncreate: oncreate.ripple,
  217. onclick: events.advanced
  218. },
  219. 'Advanced Options'
  220. )
  221. )
  222. })