editor.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // ====================================
  2. // Markdown Editor
  3. // ====================================
  4. if($('#mk-editor').length === 1) {
  5. let codeEditor = ace.edit("codeblock-editor");
  6. codeEditor.setTheme("ace/theme/tomorrow_night");
  7. codeEditor.getSession().setMode("ace/mode/markdown");
  8. codeEditor.setOption('fontSize', '14px');
  9. codeEditor.setOption('hScrollBarAlwaysVisible', false);
  10. codeEditor.setOption('wrap', true);
  11. let modelist = ace.require("ace/ext/modelist");
  12. let vueCodeBlock = new Vue({
  13. el: '#modal-editor-codeblock',
  14. data: {
  15. modes: modelist.modesByName,
  16. modeSelected: 'text'
  17. },
  18. watch: {
  19. modeSelected: (val, oldVal) => {
  20. loadAceMode(val).done(() => {
  21. ace.require("ace/mode/" + val);
  22. codeEditor.getSession().setMode("ace/mode/" + val);
  23. });
  24. }
  25. }
  26. });
  27. var mde = new SimpleMDE({
  28. autofocus: true,
  29. autoDownloadFontAwesome: false,
  30. element: $("#mk-editor").get(0),
  31. placeholder: 'Enter Markdown formatted content here...',
  32. spellChecker: false,
  33. status: false,
  34. toolbar: [{
  35. name: "bold",
  36. action: SimpleMDE.toggleBold,
  37. className: "fa fa-bold",
  38. title: "Bold",
  39. },
  40. {
  41. name: "italic",
  42. action: SimpleMDE.toggleItalic,
  43. className: "fa fa-italic",
  44. title: "Italic",
  45. },
  46. {
  47. name: "strikethrough",
  48. action: SimpleMDE.toggleStrikethrough,
  49. className: "fa fa-strikethrough",
  50. title: "Strikethrough",
  51. },
  52. '|',
  53. {
  54. name: "heading-1",
  55. action: SimpleMDE.toggleHeading1,
  56. className: "fa fa-header fa-header-x fa-header-1",
  57. title: "Big Heading",
  58. },
  59. {
  60. name: "heading-2",
  61. action: SimpleMDE.toggleHeading2,
  62. className: "fa fa-header fa-header-x fa-header-2",
  63. title: "Medium Heading",
  64. },
  65. {
  66. name: "heading-3",
  67. action: SimpleMDE.toggleHeading3,
  68. className: "fa fa-header fa-header-x fa-header-3",
  69. title: "Small Heading",
  70. },
  71. {
  72. name: "quote",
  73. action: SimpleMDE.toggleBlockquote,
  74. className: "fa fa-quote-left",
  75. title: "Quote",
  76. },
  77. '|',
  78. {
  79. name: "unordered-list",
  80. action: SimpleMDE.toggleUnorderedList,
  81. className: "fa fa-list-ul",
  82. title: "Bullet List",
  83. },
  84. {
  85. name: "ordered-list",
  86. action: SimpleMDE.toggleOrderedList,
  87. className: "fa fa-list-ol",
  88. title: "Numbered List",
  89. },
  90. '|',
  91. {
  92. name: "link",
  93. action: (editor) => {
  94. $('#modal-editor-link').slideToggle();
  95. },
  96. className: "fa fa-link",
  97. title: "Insert Link",
  98. },
  99. {
  100. name: "image",
  101. action: (editor) => {
  102. //todo
  103. },
  104. className: "fa fa-image",
  105. title: "Insert Image",
  106. },
  107. '|',
  108. {
  109. name: "inline-code",
  110. action: (editor) => {
  111. if(!editor.codemirror.doc.somethingSelected()) {
  112. return alerts.pushError('Invalid selection','You must select at least 1 character first.');
  113. }
  114. let curSel = editor.codemirror.doc.getSelections();
  115. curSel = _.map(curSel, (s) => {
  116. return '`' + s + '`';
  117. });
  118. editor.codemirror.doc.replaceSelections(curSel);
  119. },
  120. className: "fa fa-terminal",
  121. title: "Inline Code",
  122. },
  123. {
  124. name: "code-block",
  125. action: (editor) => {
  126. $('#modal-editor-codeblock').slideDown(400, () => {
  127. codeEditor.resize();
  128. codeEditor.focus();
  129. });
  130. },
  131. className: "fa fa-code",
  132. title: "Code Block",
  133. },
  134. '|',
  135. {
  136. name: "table",
  137. action: (editor) => {
  138. //todo
  139. },
  140. className: "fa fa-table",
  141. title: "Insert Table",
  142. },
  143. {
  144. name: "horizontal-rule",
  145. action: SimpleMDE.drawHorizontalRule,
  146. className: "fa fa-minus",
  147. title: "Horizontal Rule",
  148. }
  149. ],
  150. shortcuts: {
  151. "toggleBlockquote": null,
  152. "toggleFullScreen": null
  153. }
  154. });
  155. }
  156. //-> Save
  157. $('.btn-edit-save').on('click', (ev) => {
  158. $.ajax(window.location.href, {
  159. data: {
  160. markdown: mde.value()
  161. },
  162. dataType: 'json',
  163. method: 'PUT'
  164. }).then((rData, rStatus, rXHR) => {
  165. if(rData.ok) {
  166. window.location.assign('/' + pageEntryPath);
  167. } else {
  168. alerts.pushError('Something went wrong', rData.error);
  169. }
  170. }, (rXHR, rStatus, err) => {
  171. alerts.pushError('Something went wrong', 'Save operation failed.');
  172. });
  173. });
  174. // ACE - Mode Loader
  175. let modelistLoaded = [];
  176. let loadAceMode = (m) => {
  177. return $.ajax({
  178. url: '/js/ace/mode-' + m + '.js',
  179. dataType: "script",
  180. cache: true,
  181. beforeSend: () => {
  182. if(_.includes(modelistLoaded, m)) {
  183. return false;
  184. }
  185. },
  186. success: () => {
  187. modelistLoaded.push(m);
  188. }
  189. });
  190. }