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.

218 lines
5.4 KiB

  1. 'use strict'
  2. /* global $, Vue, _, filesize, SimpleMDE, alerts, vueImage, vueFile, vueVideo, vueCodeBlock */
  3. // ====================================
  4. // Markdown Editor
  5. // ====================================
  6. if ($('#mk-editor').length === 1) {
  7. let mdeModalOpenState = false
  8. let mdeCurrentEditor = null // eslint-disable-line no-unused-vars
  9. Vue.filter('filesize', (v) => {
  10. return _.toUpper(filesize(v))
  11. })
  12. /* eslint-disable spaced-comment */
  13. //=include editor-image.js
  14. //=include editor-file.js
  15. //=include editor-video.js
  16. //=include editor-codeblock.js
  17. /* eslint-enable spaced-comment */
  18. var mde = new SimpleMDE({
  19. autofocus: true,
  20. autoDownloadFontAwesome: false,
  21. element: $('#mk-editor').get(0),
  22. placeholder: 'Enter Markdown formatted content here...',
  23. spellChecker: false,
  24. status: false,
  25. toolbar: [
  26. {
  27. name: 'bold',
  28. action: SimpleMDE.toggleBold,
  29. className: 'icon-bold',
  30. title: 'Bold'
  31. },
  32. {
  33. name: 'italic',
  34. action: SimpleMDE.toggleItalic,
  35. className: 'icon-italic',
  36. title: 'Italic'
  37. },
  38. {
  39. name: 'strikethrough',
  40. action: SimpleMDE.toggleStrikethrough,
  41. className: 'icon-strikethrough',
  42. title: 'Strikethrough'
  43. },
  44. '|',
  45. {
  46. name: 'heading-1',
  47. action: SimpleMDE.toggleHeading1,
  48. className: 'icon-header fa-header-x fa-header-1',
  49. title: 'Big Heading'
  50. },
  51. {
  52. name: 'heading-2',
  53. action: SimpleMDE.toggleHeading2,
  54. className: 'icon-header fa-header-x fa-header-2',
  55. title: 'Medium Heading'
  56. },
  57. {
  58. name: 'heading-3',
  59. action: SimpleMDE.toggleHeading3,
  60. className: 'icon-header fa-header-x fa-header-3',
  61. title: 'Small Heading'
  62. },
  63. {
  64. name: 'quote',
  65. action: SimpleMDE.toggleBlockquote,
  66. className: 'icon-quote-left',
  67. title: 'Quote'
  68. },
  69. '|',
  70. {
  71. name: 'unordered-list',
  72. action: SimpleMDE.toggleUnorderedList,
  73. className: 'icon-th-list',
  74. title: 'Bullet List'
  75. },
  76. {
  77. name: 'ordered-list',
  78. action: SimpleMDE.toggleOrderedList,
  79. className: 'icon-list-ol',
  80. title: 'Numbered List'
  81. },
  82. '|',
  83. {
  84. name: 'link',
  85. action: (editor) => {
  86. /* if(!mdeModalOpenState) {
  87. mdeModalOpenState = true;
  88. $('#modal-editor-link').slideToggle();
  89. } */
  90. },
  91. className: 'icon-link2',
  92. title: 'Insert Link'
  93. },
  94. {
  95. name: 'image',
  96. action: (editor) => {
  97. if (!mdeModalOpenState) {
  98. vueImage.open()
  99. }
  100. },
  101. className: 'icon-image',
  102. title: 'Insert Image'
  103. },
  104. {
  105. name: 'file',
  106. action: (editor) => {
  107. if (!mdeModalOpenState) {
  108. vueFile.open()
  109. }
  110. },
  111. className: 'icon-paper',
  112. title: 'Insert File'
  113. },
  114. {
  115. name: 'video',
  116. action: (editor) => {
  117. if (!mdeModalOpenState) {
  118. vueVideo.open()
  119. }
  120. },
  121. className: 'icon-video-camera2',
  122. title: 'Insert Video Player'
  123. },
  124. '|',
  125. {
  126. name: 'inline-code',
  127. action: (editor) => {
  128. if (!editor.codemirror.doc.somethingSelected()) {
  129. return alerts.pushError('Invalid selection', 'You must select at least 1 character first.')
  130. }
  131. let curSel = editor.codemirror.doc.getSelections()
  132. curSel = _.map(curSel, (s) => {
  133. return '`' + s + '`'
  134. })
  135. editor.codemirror.doc.replaceSelections(curSel)
  136. },
  137. className: 'icon-terminal',
  138. title: 'Inline Code'
  139. },
  140. {
  141. name: 'code-block',
  142. action: (editor) => {
  143. if (!mdeModalOpenState) {
  144. mdeModalOpenState = true
  145. if (mde.codemirror.doc.somethingSelected()) {
  146. vueCodeBlock.initContent = mde.codemirror.doc.getSelection()
  147. }
  148. vueCodeBlock.open()
  149. }
  150. },
  151. className: 'icon-code',
  152. title: 'Code Block'
  153. },
  154. '|',
  155. {
  156. name: 'table',
  157. action: (editor) => {
  158. // todo
  159. },
  160. className: 'icon-table',
  161. title: 'Insert Table'
  162. },
  163. {
  164. name: 'horizontal-rule',
  165. action: SimpleMDE.drawHorizontalRule,
  166. className: 'icon-minus2',
  167. title: 'Horizontal Rule'
  168. }
  169. ],
  170. shortcuts: {
  171. 'toggleBlockquote': null,
  172. 'toggleFullScreen': null
  173. }
  174. })
  175. // -> Save
  176. let saveCurrentDocument = (ev) => {
  177. $.ajax(window.location.href, {
  178. data: {
  179. markdown: mde.value()
  180. },
  181. dataType: 'json',
  182. method: 'PUT'
  183. }).then((rData, rStatus, rXHR) => {
  184. if (rData.ok) {
  185. window.location.assign('/' + pageEntryPath) // eslint-disable-line no-undef
  186. } else {
  187. alerts.pushError('Something went wrong', rData.error)
  188. }
  189. }, (rXHR, rStatus, err) => {
  190. alerts.pushError('Something went wrong', 'Save operation failed.')
  191. })
  192. }
  193. $('.btn-edit-save, .btn-create-save').on('click', (ev) => {
  194. saveCurrentDocument(ev)
  195. })
  196. $(window).bind('keydown', (ev) => {
  197. if (ev.ctrlKey || ev.metaKey) {
  198. switch (String.fromCharCode(ev.which).toLowerCase()) {
  199. case 's':
  200. ev.preventDefault()
  201. saveCurrentDocument(ev)
  202. break
  203. }
  204. }
  205. })
  206. }