editor.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. "use strict";
  2. function do_insert_data(data) {
  3. const name = 'opennamu_edit_textarea';
  4. const monaco_name = 'opennamu_monaco_editor';
  5. if(!document.getElementById(monaco_name)) {
  6. // https://stackoverflow.com/questions/11076975/insert-text-into-textarea-at-cursor-position-javascript
  7. if(document.selection) {
  8. document.getElementById(name).focus();
  9. let sel = document.selection.createRange();
  10. sel.text = data;
  11. } else if(
  12. document.getElementById(name).selectionStart ||
  13. document.getElementById(name).selectionStart == '0'
  14. ) {
  15. let startPos = document.getElementById(name).selectionStart;
  16. let endPos = document.getElementById(name).selectionEnd;
  17. let myPos = document.getElementById(name).value;
  18. document.getElementById(name).value = myPos.substring(0, startPos) + data + myPos.substring(endPos, myPos.length);
  19. } else {
  20. document.getElementById(name).value += data;
  21. }
  22. } else {
  23. let selection = editor.getSelection();
  24. let id = { major: 1, minor: 1 };
  25. let text = data;
  26. let op = {
  27. identifier: id,
  28. range: selection,
  29. text: text,
  30. forceMoveMarkers: true
  31. };
  32. editor.executeEdits("my-source", [op]);
  33. }
  34. }
  35. // 아직 개편이 더 필요함
  36. function do_paste_image() {
  37. const name = 'opennamu_edit_textarea';
  38. const monaco_name = 'opennamu_monaco_editor';
  39. window.addEventListener('DOMContentLoaded', async function() {
  40. let set = await opennamu_get_main_skin_set("main_css_image_paste");
  41. if(set === 'use') {
  42. let textarea;
  43. if(
  44. document.getElementById(monaco_name) !== null &&
  45. document.getElementById(monaco_name) !== undefined
  46. ) {
  47. textarea = document.getElementById(monaco_name);
  48. } else {
  49. textarea = document.getElementById(name);
  50. }
  51. if(textarea) {
  52. textarea.addEventListener("paste", pasteListener);
  53. }
  54. }
  55. });
  56. }
  57. function pasteListener(e) {
  58. // find file
  59. if(e.clipboardData && e.clipboardData.items) {
  60. const items = e.clipboardData.items;
  61. const formData = new FormData();
  62. let haveImageInClipboard = false;
  63. let file_name = '';
  64. for(let i = 0; i < items.length; i++) {
  65. if(items[i].type.indexOf("image") !== -1) {
  66. const file = items[i].getAsFile();
  67. const customName = prompt("파일 이름 (확장자 제외)");
  68. if(!customName) {
  69. return alert("파일 이름 없음");
  70. }
  71. file_name = customName + ".png";
  72. const customFile = new File([file], file_name, { type: file.type });
  73. formData.append("f_data[]", customFile);
  74. haveImageInClipboard = true;
  75. e.preventDefault();
  76. break;
  77. }
  78. }
  79. if(!haveImageInClipboard) {
  80. return;
  81. }
  82. // send to server
  83. fetch("/upload", {
  84. method: "POST",
  85. body: formData,
  86. }).then((res) => {
  87. if (res.status === 200 || res.status === 201) {
  88. const url = res.url;
  89. alert(
  90. '업로드 완료 : ' +
  91. '[[파일:' + file_name + ']]'
  92. );
  93. } else {
  94. console.error("[ERROR] PasteUpload Fail :", res.statusText);
  95. if(res.status === 400) {
  96. alert("파일 이름 중복");
  97. } else if(res.status === 401) {
  98. alert("권한 부족");
  99. } else {
  100. alert("업로드 실패");
  101. }
  102. }
  103. }).catch((err) => {
  104. console.error("오류 내역 :", JSON.stringify(err), err);
  105. alert("업로드 실패");
  106. });
  107. }
  108. }
  109. function do_stop_exit() {
  110. window.onbeforeunload = function() {
  111. do_monaco_to_textarea();
  112. let data = document.getElementById('opennamu_edit_textarea').value;
  113. let origin = document.getElementById('opennamu_edit_origin').value;
  114. if(data !== origin) {
  115. return '';
  116. }
  117. }
  118. }
  119. function do_stop_exit_release() {
  120. window.onbeforeunload = function () {}
  121. }
  122. function opennamu_edit_turn_off_monaco() {
  123. do_monaco_to_textarea();
  124. document.getElementById('opennamu_edit_textarea').style.display = 'block';
  125. document.getElementById('opennamu_monaco_editor').style.display = 'none';
  126. document.getElementById('opennamu_monaco_editor').remove();
  127. }
  128. function do_monaco_to_textarea() {
  129. if(document.getElementById('opennamu_monaco_editor')) {
  130. try {
  131. document.getElementById('opennamu_edit_textarea').value = window.editor.getValue();
  132. } catch(e) {}
  133. }
  134. }
  135. // https://github.com/microsoft/monaco-editor/issues/568
  136. class PlaceholderContentWidget {
  137. static ID = 'editor.widget.placeholderHint';
  138. constructor(placeholder, editor) {
  139. this.placeholder = placeholder;
  140. this.editor = editor;
  141. // register a listener for editor code changes
  142. editor.onDidChangeModelContent(() => this.onDidChangeModelContent());
  143. // ensure that on initial load the placeholder is shown
  144. this.onDidChangeModelContent();
  145. }
  146. onDidChangeModelContent() {
  147. if (this.editor.getValue() === '') {
  148. this.editor.addContentWidget(this);
  149. } else {
  150. this.editor.removeContentWidget(this);
  151. }
  152. }
  153. getId() {
  154. return PlaceholderContentWidget.ID;
  155. }
  156. getDomNode() {
  157. if (!this.domNode) {
  158. this.domNode = document.createElement('div');
  159. this.domNode.style.width = 'max-content';
  160. this.domNode.textContent = this.placeholder;
  161. this.domNode.style.fontStyle = 'italic';
  162. this.editor.applyFontInfo(this.domNode);
  163. }
  164. return this.domNode;
  165. }
  166. getPosition() {
  167. return {
  168. position: { lineNumber: 1, column: 1 },
  169. preference: [monaco.editor.ContentWidgetPositionPreference.EXACT],
  170. };
  171. }
  172. dispose() {
  173. this.editor.removeContentWidget(this);
  174. }
  175. }
  176. function do_monaco_init(monaco_thema) {
  177. require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.40.0/min/vs' }});
  178. require.config({ 'vs/nls': { availableLanguages: { '*': 'ko' } }});
  179. require(["vs/editor/editor.main"], function () {
  180. window.editor = monaco.editor.create(document.getElementById('opennamu_monaco_editor'), {
  181. value: document.getElementById('opennamu_edit_textarea').value,
  182. language: 'plaintext',
  183. automaticLayout: true,
  184. wordWrap: true,
  185. theme: monaco_thema
  186. });
  187. new PlaceholderContentWidget(document.getElementById('opennamu_edit_textarea').placeholder, window.editor);
  188. });
  189. }