From c8be214ee0a3582614db2c1d9444316b40f04b0e Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 17 Jun 2017 15:07:55 +0100 Subject: [PATCH] Started tinymce code editor components --- resources/assets/js/code.js | 102 ++++++++++++++++++++----- resources/assets/js/pages/page-form.js | 78 ++++++++++++++++++- 2 files changed, 157 insertions(+), 23 deletions(-) diff --git a/resources/assets/js/code.js b/resources/assets/js/code.js index 020c38365..83cb664a1 100644 --- a/resources/assets/js/code.js +++ b/resources/assets/js/code.js @@ -52,31 +52,91 @@ const modeMap = { module.exports.highlight = function() { let codeBlocks = document.querySelectorAll('.page-content pre'); - for (let i = 0; i < codeBlocks.length; i++) { - let innerCodeElem = codeBlocks[i].querySelector('code[class^=language-]'); - let mode = ''; - if (innerCodeElem !== null) { - let langName = innerCodeElem.className.replace('language-', ''); - if (typeof modeMap[langName] !== 'undefined') mode = modeMap[langName]; - } - codeBlocks[i].innerHTML = codeBlocks[i].innerHTML.replace(//gi ,'\n'); - let content = codeBlocks[i].textContent; - console.log('MODE', mode); - - CodeMirror(function(elt) { - codeBlocks[i].parentNode.replaceChild(elt, codeBlocks[i]); - }, { - value: content, - mode: mode, - lineNumbers: true, - theme: 'base16-light', - readOnly: true - }); + highlightElem(codeBlocks[i]); } - }; +function highlightElem(elem) { + let innerCodeElem = elem.querySelector('code[class^=language-]'); + let mode = ''; + if (innerCodeElem !== null) { + let langName = innerCodeElem.className.replace('language-', ''); + if (typeof modeMap[langName] !== 'undefined') mode = modeMap[langName]; + } + elem.innerHTML = elem.innerHTML.replace(//gi ,'\n'); + let content = elem.textContent; + + CodeMirror(function(elt) { + elem.parentNode.replaceChild(elt, elem); + }, { + value: content, + mode: mode, + lineNumbers: true, + theme: 'base16-light', + readOnly: true + }); +} + +module.exports.highlightElem = highlightElem; + +module.exports.wysiwygView = function(elem) { + let doc = elem.ownerDocument; + elem.innerHTML = elem.innerHTML.replace(//gi ,'\n'); + let content = elem.textContent; + let newWrap = doc.createElement('div'); + let newTextArea = doc.createElement('textarea'); + + newWrap.className = 'CodeMirrorContainer'; + newTextArea.style.display = 'none'; + elem.parentNode.replaceChild(newWrap, elem); + + newWrap.appendChild(newTextArea); + newWrap.contentEditable = false; + newTextArea.textContent = content; + + let cm = CodeMirror(function(elt) { + newWrap.appendChild(elt); + }, { + value: content, + mode: '', + lineNumbers: true, + theme: 'base16-light', + readOnly: true + }); + setTimeout(() => { + cm.refresh(); + }, 300); + return newWrap; +}; + +// module.exports.wysiwygEditor = function(elem) { +// let doc = elem.ownerDocument; +// let newWrap = doc.createElement('div'); +// newWrap.className = 'CodeMirrorContainer'; +// let newTextArea = doc.createElement('textarea'); +// newTextArea.style.display = 'none'; +// elem.innerHTML = elem.innerHTML.replace(//gi ,'\n'); +// let content = elem.textContent; +// elem.parentNode.replaceChild(newWrap, elem); +// newWrap.appendChild(newTextArea); +// let cm = CodeMirror(function(elt) { +// newWrap.appendChild(elt); +// }, { +// value: content, +// mode: '', +// lineNumbers: true, +// theme: 'base16-light', +// readOnly: true +// }); +// cm.on('change', event => { +// newTextArea.innerText = cm.getValue(); +// }); +// setTimeout(() => { +// cm.refresh(); +// }, 300); +// }; + module.exports.markdownEditor = function(elem) { let content = elem.textContent; diff --git a/resources/assets/js/pages/page-form.js b/resources/assets/js/pages/page-form.js index 04951b174..871d2b528 100644 --- a/resources/assets/js/pages/page-form.js +++ b/resources/assets/js/pages/page-form.js @@ -1,5 +1,7 @@ "use strict"; +const Code = require('../code'); + /** * Handle pasting images from clipboard. * @param e - event @@ -60,13 +62,85 @@ function registerEditorShortcuts(editor) { editor.addShortcut('meta+shift+E', '', ['FormatBlock', false, 'code']); } + +function codePlugin() { + + function elemIsCodeBlock(elem) { + return elem.className === 'CodeMirrorContainer'; + } + + function showPopup(editor) { + let selectedNode = editor.selection.getNode(); + if (!elemIsCodeBlock(selectedNode)) { + return; + } + + let lang = selectedNode.hasAttribute('data-language') ? selectedNode.getAttribute('data-language') : ''; + let currentCode = selectedNode.querySelector('textarea').textContent; + console.log('SHOW POPUP'); + // TODO - Show custom editor + } + + window.tinymce.PluginManager.add('codeeditor', (editor, url) => { + + let $ = editor.$; + + editor.addButton('codeeditor', { + text: 'Code block', + icon: false, + onclick() { + showPopup(editor); + } + }); + + // Convert + editor.on('PreProcess', function (e) { + $('div.CodeMirrorContainer', e.node). + each((index, elem) => { + let $elem = $(elem); + let code = elem.querySelector('textarea').textContent; + + // $elem.attr('class', $.trim($elem.attr('class'))); + $elem.removeAttr('contentEditable'); + + $elem.empty().append('
').find('pre').first().append($('').each((index, elem) => {
+                    // Needs to be textContent since innerText produces BR:s
+                    elem.textContent = code;
+                }).attr('class', $elem.attr('class')));
+                console.log($elem[0].outerHTML);
+            });
+        });
+
+        editor.on('SetContent', function () {
+            let codeSamples = $('pre').filter((index, elem) => {
+                return elem.contentEditable !== "false";
+            });
+
+            if (codeSamples.length) {
+                editor.undoManager.transact(function () {
+                    codeSamples.each((index, elem) => {
+                        console.log(elem.textContent);
+                        let outerWrap = Code.wysiwygView(elem);
+                        outerWrap.addEventListener('dblclick', () => {
+                            showPopup(editor);
+                        })
+                    });
+                });
+            }
+        });
+
+    });
+}
+
 module.exports = function() {
+    codePlugin();
     let settings = {
         selector: '#html-editor',
         content_css: [
             window.baseUrl('/css/styles.css'),
             window.baseUrl('/libs/material-design-iconic-font/css/material-design-iconic-font.min.css')
         ],
+        branding: false,
         body_class: 'page-content',
         browser_spellcheck: true,
         relative_urls: false,
@@ -78,9 +152,9 @@ module.exports = function() {
         extended_valid_elements: 'pre[*]',
         automatic_uploads: false,
         valid_children: "-div[p|pre|h1|h2|h3|h4|h5|h6|blockquote]",
-        plugins: "image table textcolor paste link autolink fullscreen imagetools code customhr autosave lists codesample",
+        plugins: "image table textcolor paste link autolink fullscreen imagetools code customhr autosave lists codeeditor",
         imagetools_toolbar: 'imageoptions',
-        toolbar: "undo redo | styleselect | bold italic underline strikethrough superscript subscript | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table image-insert link hr | removeformat code fullscreen codesample",
+        toolbar: "undo redo | styleselect | bold italic underline strikethrough superscript subscript | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table image-insert link hr | removeformat code fullscreen codeeditor",
         content_style: "body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}",
         style_formats: [
             {title: "Header Large", format: "h2"},