editor.component.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. 'use strict'
  2. import SimpleMDE from 'simplemde'
  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. mde = new SimpleMDE({
  46. autofocus: true,
  47. autoDownloadFontAwesome: false,
  48. element: this.$refs.editorTextArea,
  49. placeholder: 'Enter Markdown formatted content here...',
  50. spellChecker: false,
  51. status: false,
  52. toolbar: [
  53. {
  54. name: 'bold',
  55. action: SimpleMDE.toggleBold,
  56. className: 'icon-bold',
  57. title: 'Bold'
  58. },
  59. {
  60. name: 'italic',
  61. action: SimpleMDE.toggleItalic,
  62. className: 'icon-italic',
  63. title: 'Italic'
  64. },
  65. {
  66. name: 'strikethrough',
  67. action: SimpleMDE.toggleStrikethrough,
  68. className: 'icon-strikethrough',
  69. title: 'Strikethrough'
  70. },
  71. '|',
  72. {
  73. name: 'heading-1',
  74. action: SimpleMDE.toggleHeading1,
  75. className: 'icon-header fa-header-x fa-header-1',
  76. title: 'Big Heading'
  77. },
  78. {
  79. name: 'heading-2',
  80. action: SimpleMDE.toggleHeading2,
  81. className: 'icon-header fa-header-x fa-header-2',
  82. title: 'Medium Heading'
  83. },
  84. {
  85. name: 'heading-3',
  86. action: SimpleMDE.toggleHeading3,
  87. className: 'icon-header fa-header-x fa-header-3',
  88. title: 'Small Heading'
  89. },
  90. {
  91. name: 'quote',
  92. action: SimpleMDE.toggleBlockquote,
  93. className: 'icon-quote-left',
  94. title: 'Quote'
  95. },
  96. '|',
  97. {
  98. name: 'unordered-list',
  99. action: SimpleMDE.toggleUnorderedList,
  100. className: 'icon-th-list',
  101. title: 'Bullet List'
  102. },
  103. {
  104. name: 'ordered-list',
  105. action: SimpleMDE.toggleOrderedList,
  106. className: 'icon-list-ol',
  107. title: 'Numbered List'
  108. },
  109. '|',
  110. {
  111. name: 'link',
  112. action: (editor) => {
  113. /* if(!mdeModalOpenState) {
  114. mdeModalOpenState = true;
  115. $('#modal-editor-link').slideToggle();
  116. } */
  117. window.alert('Coming soon!')
  118. },
  119. className: 'icon-link2',
  120. title: 'Insert Link'
  121. },
  122. {
  123. name: 'image',
  124. action: (editor) => {
  125. if (!mdeModalOpenState) {
  126. vueImage.open()
  127. }
  128. },
  129. className: 'icon-image',
  130. title: 'Insert Image'
  131. },
  132. {
  133. name: 'file',
  134. action: (editor) => {
  135. if (!mdeModalOpenState) {
  136. vueFile.open()
  137. }
  138. },
  139. className: 'icon-paper',
  140. title: 'Insert File'
  141. },
  142. {
  143. name: 'video',
  144. action: (editor) => {
  145. if (!mdeModalOpenState) {
  146. vueVideo.open()
  147. }
  148. },
  149. className: 'icon-video-camera2',
  150. title: 'Insert Video Player'
  151. },
  152. '|',
  153. {
  154. name: 'inline-code',
  155. action: (editor) => {
  156. if (!editor.codemirror.doc.somethingSelected()) {
  157. return alerts.pushError('Invalid selection', 'You must select at least 1 character first.')
  158. }
  159. let curSel = editor.codemirror.doc.getSelections()
  160. curSel = _.map(curSel, (s) => {
  161. return '`' + s + '`'
  162. })
  163. editor.codemirror.doc.replaceSelections(curSel)
  164. },
  165. className: 'icon-terminal',
  166. title: 'Inline Code'
  167. },
  168. {
  169. name: 'code-block',
  170. action: (editor) => {
  171. if (!mdeModalOpenState) {
  172. if (mde.codemirror.doc.somethingSelected()) {
  173. vueCodeBlock.initContent = mde.codemirror.doc.getSelection()
  174. }
  175. vueCodeBlock.open()
  176. }
  177. },
  178. className: 'icon-code',
  179. title: 'Code Block'
  180. },
  181. '|',
  182. {
  183. name: 'table',
  184. action: (editor) => {
  185. window.alert('Coming soon!')
  186. // todo
  187. },
  188. className: 'icon-table',
  189. title: 'Insert Table'
  190. },
  191. {
  192. name: 'horizontal-rule',
  193. action: SimpleMDE.drawHorizontalRule,
  194. className: 'icon-minus2',
  195. title: 'Horizontal Rule'
  196. }
  197. ],
  198. shortcuts: {
  199. 'toggleBlockquote': null,
  200. 'toggleFullScreen': null
  201. }
  202. })
  203. // Save
  204. this.$root.$on('editor-save', this.save)
  205. $(window).bind('keydown', (ev) => {
  206. if (ev.ctrlKey || ev.metaKey) {
  207. switch (String.fromCharCode(ev.which).toLowerCase()) {
  208. case 's':
  209. ev.preventDefault()
  210. self.save()
  211. break
  212. }
  213. }
  214. })
  215. this.$store.dispatch('pageLoader/complete')
  216. }
  217. }