editor.component.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. 'use strict'
  2. /* global FuseBox */
  3. import filesize from 'filesize.js'
  4. import $ from 'jquery'
  5. let mde
  6. export default {
  7. name: 'editor',
  8. props: ['currentPath'],
  9. filters: {
  10. filesize(v) {
  11. return this._.toUpper(filesize(v))
  12. }
  13. },
  14. data() {
  15. return {}
  16. },
  17. methods: {
  18. save() {
  19. let self = this
  20. this.$http.put(window.location.href, {
  21. markdown: mde.value()
  22. }).then(resp => {
  23. return resp.json()
  24. }).then(resp => {
  25. if (resp.ok) {
  26. window.location.assign('/' + self.currentPath)
  27. } else {
  28. self.$store.dispatch('alert', {
  29. style: 'red',
  30. icon: 'square-cross',
  31. msg: resp.msg
  32. })
  33. }
  34. }).catch(err => {
  35. self.$store.dispatch('alert', {
  36. style: 'red',
  37. icon: 'square-cross',
  38. msg: 'Error: ' + err.body.msg
  39. })
  40. })
  41. }
  42. },
  43. mounted() {
  44. let self = this
  45. FuseBox.import('/js/simplemde/simplemde.min.js', (SimpleMDE) => {
  46. mde = new SimpleMDE({
  47. autofocus: true,
  48. autoDownloadFontAwesome: false,
  49. element: this.$refs.editorTextArea,
  50. placeholder: 'Enter Markdown formatted content here...',
  51. spellChecker: false,
  52. status: false,
  53. toolbar: [
  54. {
  55. name: 'bold',
  56. action: SimpleMDE.toggleBold,
  57. className: 'icon-bold',
  58. title: 'Bold'
  59. },
  60. {
  61. name: 'italic',
  62. action: SimpleMDE.toggleItalic,
  63. className: 'icon-italic',
  64. title: 'Italic'
  65. },
  66. {
  67. name: 'strikethrough',
  68. action: SimpleMDE.toggleStrikethrough,
  69. className: 'icon-strikethrough',
  70. title: 'Strikethrough'
  71. },
  72. '|',
  73. {
  74. name: 'heading-1',
  75. action: SimpleMDE.toggleHeading1,
  76. className: 'icon-header fa-header-x fa-header-1',
  77. title: 'Big Heading'
  78. },
  79. {
  80. name: 'heading-2',
  81. action: SimpleMDE.toggleHeading2,
  82. className: 'icon-header fa-header-x fa-header-2',
  83. title: 'Medium Heading'
  84. },
  85. {
  86. name: 'heading-3',
  87. action: SimpleMDE.toggleHeading3,
  88. className: 'icon-header fa-header-x fa-header-3',
  89. title: 'Small Heading'
  90. },
  91. {
  92. name: 'quote',
  93. action: SimpleMDE.toggleBlockquote,
  94. className: 'icon-quote-left',
  95. title: 'Quote'
  96. },
  97. '|',
  98. {
  99. name: 'unordered-list',
  100. action: SimpleMDE.toggleUnorderedList,
  101. className: 'icon-th-list',
  102. title: 'Bullet List'
  103. },
  104. {
  105. name: 'ordered-list',
  106. action: SimpleMDE.toggleOrderedList,
  107. className: 'icon-list-ol',
  108. title: 'Numbered List'
  109. },
  110. '|',
  111. {
  112. name: 'link',
  113. action: (editor) => {
  114. /* if(!mdeModalOpenState) {
  115. mdeModalOpenState = true;
  116. $('#modal-editor-link').slideToggle();
  117. } */
  118. window.alert('Coming soon!')
  119. },
  120. className: 'icon-link2',
  121. title: 'Insert Link'
  122. },
  123. {
  124. name: 'image',
  125. action: (editor) => {
  126. // if (!mdeModalOpenState) {
  127. // vueImage.open()
  128. // }
  129. },
  130. className: 'icon-image',
  131. title: 'Insert Image'
  132. },
  133. {
  134. name: 'file',
  135. action: (editor) => {
  136. // if (!mdeModalOpenState) {
  137. // vueFile.open()
  138. // }
  139. },
  140. className: 'icon-paper',
  141. title: 'Insert File'
  142. },
  143. {
  144. name: 'video',
  145. action: (editor) => {
  146. // if (!mdeModalOpenState) {
  147. // vueVideo.open()
  148. // }
  149. },
  150. className: 'icon-video-camera2',
  151. title: 'Insert Video Player'
  152. },
  153. '|',
  154. {
  155. name: 'inline-code',
  156. action: (editor) => {
  157. if (!editor.codemirror.doc.somethingSelected()) {
  158. return self.$store.dispatch('alert', {
  159. style: 'orange',
  160. icon: 'marquee',
  161. msg: 'Invalid selection. Select at least 1 character.'
  162. })
  163. }
  164. let curSel = editor.codemirror.doc.getSelections()
  165. curSel = self._.map(curSel, (s) => {
  166. return '`' + s + '`'
  167. })
  168. editor.codemirror.doc.replaceSelections(curSel)
  169. },
  170. className: 'icon-terminal',
  171. title: 'Inline Code'
  172. },
  173. {
  174. name: 'code-block',
  175. action: (editor) => {
  176. // if (!mdeModalOpenState) {
  177. // if (mde.codemirror.doc.somethingSelected()) {
  178. // vueCodeBlock.initContent = mde.codemirror.doc.getSelection()
  179. // }
  180. // vueCodeBlock.open()
  181. // }
  182. },
  183. className: 'icon-code',
  184. title: 'Code Block'
  185. },
  186. '|',
  187. {
  188. name: 'table',
  189. action: (editor) => {
  190. window.alert('Coming soon!')
  191. // todo
  192. },
  193. className: 'icon-table',
  194. title: 'Insert Table'
  195. },
  196. {
  197. name: 'horizontal-rule',
  198. action: SimpleMDE.drawHorizontalRule,
  199. className: 'icon-minus2',
  200. title: 'Horizontal Rule'
  201. }
  202. ],
  203. shortcuts: {
  204. 'toggleBlockquote': null,
  205. 'toggleFullScreen': null
  206. }
  207. })
  208. // Save
  209. this.$root.$on('editor-save', this.save)
  210. $(window).bind('keydown', (ev) => {
  211. if (ev.ctrlKey || ev.metaKey) {
  212. switch (String.fromCharCode(ev.which).toLowerCase()) {
  213. case 's':
  214. ev.preventDefault()
  215. self.save()
  216. break
  217. }
  218. }
  219. })
  220. this.$store.dispatch('pageLoader/complete')
  221. })
  222. }
  223. }