X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/74b76ecdb924787d0d0f190bd1e384ddf50b1a16..74b4751a1c110b4c824b14369d3a5eea3ad5816a:/resources/js/code/index.mjs diff --git a/resources/js/code/index.mjs b/resources/js/code/index.mjs index 2b1aa9e74..07dcd53c2 100644 --- a/resources/js/code/index.mjs +++ b/resources/js/code/index.mjs @@ -1,7 +1,6 @@ import {EditorView, keymap} from "@codemirror/view"; -import {copyTextToClipboard} from "../services/clipboard.js" -// Modes +import {copyTextToClipboard} from "../services/clipboard.js" import {viewer, editor} from "./setups.js"; import {createView, updateViewLanguage} from "./views.js"; @@ -46,13 +45,11 @@ function highlightElem(elem) { const ev = createView({ parent: wrapper, doc: content, - extensions: viewer(), + extensions: viewer(wrapper), }); - setMode(ev, langName, content); - window.cm = ev; + setMode(ev, langName, content); elem.remove(); - addCopyIcon(ev); } @@ -61,19 +58,31 @@ function highlightElem(elem) { * @param {EditorView} editorView */ function addCopyIcon(editorView) { - const copyIcon = ``; + const copyIcon = ``; + const checkIcon = ``; const copyButton = document.createElement('button'); copyButton.setAttribute('type', 'button') copyButton.classList.add('cm-copy-button'); copyButton.innerHTML = copyIcon; editorView.dom.appendChild(copyButton); + const notifyTime = 620; + const transitionTime = 60; copyButton.addEventListener('click', event => { copyTextToClipboard(editorView.state.doc.toString()); copyButton.classList.add('success'); + + setTimeout(() => { + copyButton.innerHTML = checkIcon; + }, transitionTime / 2); + setTimeout(() => { copyButton.classList.remove('success'); - }, 240); + }, notifyTime); + + setTimeout(() => { + copyButton.innerHTML = copyIcon; + }, notifyTime + (transitionTime / 2)); }); } @@ -93,17 +102,18 @@ function getTheme() { * @param {HTMLElement} cmContainer * @param {String} content * @param {String} language - * @returns {{wrap: Element, editor: *}} + * @returns {EditorView} */ export function wysiwygView(cmContainer, content, language) { - return CodeMirror(cmContainer, { - value: content, - mode: getMode(language, content), - lineNumbers: true, - lineWrapping: false, - theme: getTheme(), - readOnly: true + const ev = createView({ + parent: cmContainer, + doc: content, + extensions: viewer(cmContainer), }); + + setMode(ev, language, content); + + return ev; } @@ -132,15 +142,29 @@ export function popupEditor(elem, modeSuggestion) { * Create an inline editor to replace the given textarea. * @param {HTMLTextAreaElement} textArea * @param {String} mode - * @returns {CodeMirror3} + * @returns {EditorView} */ export function inlineEditor(textArea, mode) { - return CodeMirror.fromTextArea(textArea, { - mode: getMode(mode, textArea.value), - lineNumbers: true, - lineWrapping: false, - theme: getTheme(), - }); + const content = textArea.value; + const config = { + parent: textArea.parentNode, + doc: content, + extensions: [ + ...editor(textArea.parentElement), + EditorView.updateListener.of((v) => { + if (v.docChanged) { + textArea.value = v.state.doc.toString(); + } + }), + ], + }; + + // Create editor view, hide original input + const ev = createView(config); + setMode(ev, mode, content); + textArea.style.display = 'none'; + + return ev; } /** @@ -188,7 +212,7 @@ export function markdownEditor(elem, onChange, domEventHandlers, keyBindings) { parent: elem.parentNode, doc: content, extensions: [ - ...editor('markdown'), + ...editor(elem.parentElement), EditorView.updateListener.of((v) => { onChange(v); }),