You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

238 lines
6.4 KiB

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