mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-05-14 04:32:21 +00:00
Finished off main functionality of custom tinymce code editor
This commit is contained in:
parent
c8be214ee0
commit
968e7b8b72
10 changed files with 204 additions and 57 deletions
resources
assets
lang/en
views
|
@ -62,7 +62,7 @@ function highlightElem(elem) {
|
||||||
let mode = '';
|
let mode = '';
|
||||||
if (innerCodeElem !== null) {
|
if (innerCodeElem !== null) {
|
||||||
let langName = innerCodeElem.className.replace('language-', '');
|
let langName = innerCodeElem.className.replace('language-', '');
|
||||||
if (typeof modeMap[langName] !== 'undefined') mode = modeMap[langName];
|
mode = getMode(langName);
|
||||||
}
|
}
|
||||||
elem.innerHTML = elem.innerHTML.replace(/<br\s*[\/]?>/gi ,'\n');
|
elem.innerHTML = elem.innerHTML.replace(/<br\s*[\/]?>/gi ,'\n');
|
||||||
let content = elem.textContent;
|
let content = elem.textContent;
|
||||||
|
@ -78,16 +78,35 @@ function highlightElem(elem) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for a codemirror code based off a user suggestion
|
||||||
|
* @param suggestion
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function getMode(suggestion) {
|
||||||
|
suggestion = suggestion.trim().replace(/^\./g, '').toLowerCase();
|
||||||
|
return (typeof modeMap[suggestion] !== 'undefined') ? modeMap[suggestion] : '';
|
||||||
|
}
|
||||||
|
|
||||||
module.exports.highlightElem = highlightElem;
|
module.exports.highlightElem = highlightElem;
|
||||||
|
|
||||||
module.exports.wysiwygView = function(elem) {
|
module.exports.wysiwygView = function(elem) {
|
||||||
let doc = elem.ownerDocument;
|
let doc = elem.ownerDocument;
|
||||||
|
let codeElem = elem.querySelector('code');
|
||||||
|
|
||||||
|
let lang = (elem.className || '').replace('language-', '');
|
||||||
|
if (lang === '' && codeElem) {
|
||||||
|
console.log(codeElem.className);
|
||||||
|
lang = (codeElem.className || '').replace('language-', '')
|
||||||
|
}
|
||||||
|
|
||||||
elem.innerHTML = elem.innerHTML.replace(/<br\s*[\/]?>/gi ,'\n');
|
elem.innerHTML = elem.innerHTML.replace(/<br\s*[\/]?>/gi ,'\n');
|
||||||
let content = elem.textContent;
|
let content = elem.textContent;
|
||||||
let newWrap = doc.createElement('div');
|
let newWrap = doc.createElement('div');
|
||||||
let newTextArea = doc.createElement('textarea');
|
let newTextArea = doc.createElement('textarea');
|
||||||
|
|
||||||
newWrap.className = 'CodeMirrorContainer';
|
newWrap.className = 'CodeMirrorContainer';
|
||||||
|
newWrap.setAttribute('data-lang', lang);
|
||||||
newTextArea.style.display = 'none';
|
newTextArea.style.display = 'none';
|
||||||
elem.parentNode.replaceChild(newWrap, elem);
|
elem.parentNode.replaceChild(newWrap, elem);
|
||||||
|
|
||||||
|
@ -99,7 +118,7 @@ module.exports.wysiwygView = function(elem) {
|
||||||
newWrap.appendChild(elt);
|
newWrap.appendChild(elt);
|
||||||
}, {
|
}, {
|
||||||
value: content,
|
value: content,
|
||||||
mode: '',
|
mode: getMode(lang),
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
theme: 'base16-light',
|
theme: 'base16-light',
|
||||||
readOnly: true
|
readOnly: true
|
||||||
|
@ -107,50 +126,47 @@ module.exports.wysiwygView = function(elem) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
cm.refresh();
|
cm.refresh();
|
||||||
}, 300);
|
}, 300);
|
||||||
return newWrap;
|
return {wrap: newWrap, editor: cm};
|
||||||
};
|
};
|
||||||
|
|
||||||
// module.exports.wysiwygEditor = function(elem) {
|
module.exports.popupEditor = function(elem, modeSuggestion) {
|
||||||
// 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(/<br\s*[\/]?>/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;
|
let content = elem.textContent;
|
||||||
|
|
||||||
let cm = CodeMirror(function(elt) {
|
return CodeMirror(function(elt) {
|
||||||
elem.parentNode.insertBefore(elt, elem);
|
elem.parentNode.insertBefore(elt, elem);
|
||||||
elem.style.display = 'none';
|
elem.style.display = 'none';
|
||||||
}, {
|
}, {
|
||||||
value: content,
|
value: content,
|
||||||
mode: "markdown",
|
mode: getMode(modeSuggestion),
|
||||||
|
lineNumbers: true,
|
||||||
|
theme: 'base16-light',
|
||||||
|
lineWrapping: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.setMode = function(cmInstance, modeSuggestion) {
|
||||||
|
cmInstance.setOption('mode', getMode(modeSuggestion));
|
||||||
|
};
|
||||||
|
module.exports.setContent = function(cmInstance, codeContent) {
|
||||||
|
cmInstance.setValue(codeContent);
|
||||||
|
setTimeout(() => {
|
||||||
|
cmInstance.refresh();
|
||||||
|
}, 10);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.markdownEditor = function(elem) {
|
||||||
|
let content = elem.textContent;
|
||||||
|
|
||||||
|
return CodeMirror(function (elt) {
|
||||||
|
elem.parentNode.insertBefore(elt, elem);
|
||||||
|
elem.style.display = 'none';
|
||||||
|
}, {
|
||||||
|
value: content,
|
||||||
|
mode: "markdown",
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
theme: 'base16-light',
|
theme: 'base16-light',
|
||||||
lineWrapping: true
|
lineWrapping: true
|
||||||
});
|
});
|
||||||
return cm;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -58,11 +58,14 @@ function registerEditorShortcuts(editor) {
|
||||||
// Other block shortcuts
|
// Other block shortcuts
|
||||||
editor.addShortcut('meta+q', '', ['FormatBlock', false, 'blockquote']);
|
editor.addShortcut('meta+q', '', ['FormatBlock', false, 'blockquote']);
|
||||||
editor.addShortcut('meta+d', '', ['FormatBlock', false, 'p']);
|
editor.addShortcut('meta+d', '', ['FormatBlock', false, 'p']);
|
||||||
editor.addShortcut('meta+e', '', ['FormatBlock', false, 'pre']);
|
editor.addShortcut('meta+e', '', ['codeeditor', false, 'pre']);
|
||||||
editor.addShortcut('meta+shift+E', '', ['FormatBlock', false, 'code']);
|
editor.addShortcut('meta+shift+E', '', ['FormatBlock', false, 'code']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and enable our custom code plugin
|
||||||
|
*/
|
||||||
function codePlugin() {
|
function codePlugin() {
|
||||||
|
|
||||||
function elemIsCodeBlock(elem) {
|
function elemIsCodeBlock(elem) {
|
||||||
|
@ -71,14 +74,35 @@ function codePlugin() {
|
||||||
|
|
||||||
function showPopup(editor) {
|
function showPopup(editor) {
|
||||||
let selectedNode = editor.selection.getNode();
|
let selectedNode = editor.selection.getNode();
|
||||||
|
|
||||||
if (!elemIsCodeBlock(selectedNode)) {
|
if (!elemIsCodeBlock(selectedNode)) {
|
||||||
|
let providedCode = editor.selection.getNode().textContent;
|
||||||
|
window.vues['code-editor'].open(providedCode, '', (code, lang) => {
|
||||||
|
let wrap = document.createElement('div');
|
||||||
|
wrap.innerHTML = `<pre><code class="language-${lang}"></code></pre>`;
|
||||||
|
wrap.querySelector('code').innerText = code;
|
||||||
|
editor.formatter.toggle('pre');
|
||||||
|
let node = editor.selection.getNode();
|
||||||
|
editor.dom.setHTML(node, wrap.querySelector('pre').innerHTML);
|
||||||
|
editor.fire('SetContent');
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let lang = selectedNode.hasAttribute('data-language') ? selectedNode.getAttribute('data-language') : '';
|
let lang = selectedNode.hasAttribute('data-lang') ? selectedNode.getAttribute('data-lang') : '';
|
||||||
let currentCode = selectedNode.querySelector('textarea').textContent;
|
let currentCode = selectedNode.querySelector('textarea').textContent;
|
||||||
console.log('SHOW POPUP');
|
|
||||||
// TODO - Show custom editor
|
window.vues['code-editor'].open(currentCode, lang, (code, lang) => {
|
||||||
|
let editorElem = selectedNode.querySelector('.CodeMirror');
|
||||||
|
let cmInstance = editorElem.CodeMirror;
|
||||||
|
if (cmInstance) {
|
||||||
|
Code.setContent(cmInstance, code);
|
||||||
|
Code.setMode(cmInstance, lang);
|
||||||
|
}
|
||||||
|
let textArea = selectedNode.querySelector('textarea');
|
||||||
|
if (textArea) textArea.textContent = code;
|
||||||
|
selectedNode.setAttribute('data-lang', lang);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
window.tinymce.PluginManager.add('codeeditor', (editor, url) => {
|
window.tinymce.PluginManager.add('codeeditor', (editor, url) => {
|
||||||
|
@ -88,9 +112,11 @@ function codePlugin() {
|
||||||
editor.addButton('codeeditor', {
|
editor.addButton('codeeditor', {
|
||||||
text: 'Code block',
|
text: 'Code block',
|
||||||
icon: false,
|
icon: false,
|
||||||
onclick() {
|
cmd: 'codeeditor'
|
||||||
showPopup(editor);
|
});
|
||||||
}
|
|
||||||
|
editor.addCommand('codeeditor', () => {
|
||||||
|
showPopup(editor);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Convert
|
// Convert
|
||||||
|
@ -98,32 +124,33 @@ function codePlugin() {
|
||||||
$('div.CodeMirrorContainer', e.node).
|
$('div.CodeMirrorContainer', e.node).
|
||||||
each((index, elem) => {
|
each((index, elem) => {
|
||||||
let $elem = $(elem);
|
let $elem = $(elem);
|
||||||
let code = elem.querySelector('textarea').textContent;
|
let textArea = elem.querySelector('textarea');
|
||||||
|
let code = textArea.textContent;
|
||||||
|
let lang = elem.getAttribute('data-lang');
|
||||||
|
|
||||||
// $elem.attr('class', $.trim($elem.attr('class')));
|
// $elem.attr('class', $.trim($elem.attr('class')));
|
||||||
$elem.removeAttr('contentEditable');
|
$elem.removeAttr('contentEditable');
|
||||||
|
let $pre = $('<pre></pre>');
|
||||||
$elem.empty().append('<pre></pre>').find('pre').first().append($('<code></code>').each((index, elem) => {
|
$pre.append($('<code></code>').each((index, elem) => {
|
||||||
// Needs to be textContent since innerText produces BR:s
|
// Needs to be textContent since innerText produces BR:s
|
||||||
elem.textContent = code;
|
elem.textContent = code;
|
||||||
}).attr('class', $elem.attr('class')));
|
}).attr('class', `language-${lang}`));
|
||||||
console.log($elem[0].outerHTML);
|
$elem.replaceWith($pre);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.on('SetContent', function () {
|
editor.on('SetContent', function () {
|
||||||
let codeSamples = $('pre').filter((index, elem) => {
|
let codeSamples = $('body > pre').filter((index, elem) => {
|
||||||
return elem.contentEditable !== "false";
|
return elem.contentEditable !== "false";
|
||||||
});
|
});
|
||||||
|
|
||||||
if (codeSamples.length) {
|
if (codeSamples.length) {
|
||||||
editor.undoManager.transact(function () {
|
editor.undoManager.transact(function () {
|
||||||
codeSamples.each((index, elem) => {
|
codeSamples.each((index, elem) => {
|
||||||
console.log(elem.textContent);
|
let editDetails = Code.wysiwygView(elem);
|
||||||
let outerWrap = Code.wysiwygView(elem);
|
editDetails.wrap.addEventListener('dblclick', () => {
|
||||||
outerWrap.addEventListener('dblclick', () => {
|
showPopup(editor, editDetails.wrap, editDetails.editor);
|
||||||
showPopup(editor);
|
});
|
||||||
})
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -154,7 +181,7 @@ module.exports = function() {
|
||||||
valid_children: "-div[p|pre|h1|h2|h3|h4|h5|h6|blockquote]",
|
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 codeeditor",
|
plugins: "image table textcolor paste link autolink fullscreen imagetools code customhr autosave lists codeeditor",
|
||||||
imagetools_toolbar: 'imageoptions',
|
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 codeeditor",
|
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",
|
||||||
content_style: "body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}",
|
content_style: "body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}",
|
||||||
style_formats: [
|
style_formats: [
|
||||||
{title: "Header Large", format: "h2"},
|
{title: "Header Large", format: "h2"},
|
||||||
|
@ -163,14 +190,14 @@ module.exports = function() {
|
||||||
{title: "Header Tiny", format: "h5"},
|
{title: "Header Tiny", format: "h5"},
|
||||||
{title: "Paragraph", format: "p", exact: true, classes: ''},
|
{title: "Paragraph", format: "p", exact: true, classes: ''},
|
||||||
{title: "Blockquote", format: "blockquote"},
|
{title: "Blockquote", format: "blockquote"},
|
||||||
{title: "Code Block", icon: "code", format: "pre"},
|
{title: "Code Block", icon: "code", cmd: 'codeeditor'},
|
||||||
{title: "Inline Code", icon: "code", inline: "code"},
|
{title: "Inline Code", icon: "code", inline: "code"},
|
||||||
{title: "Callouts", items: [
|
{title: "Callouts", items: [
|
||||||
{title: "Success", block: 'p', exact: true, attributes : {'class' : 'callout success'}},
|
{title: "Success", block: 'p', exact: true, attributes : {'class' : 'callout success'}},
|
||||||
{title: "Info", block: 'p', exact: true, attributes : {'class' : 'callout info'}},
|
{title: "Info", block: 'p', exact: true, attributes : {'class' : 'callout info'}},
|
||||||
{title: "Warning", block: 'p', exact: true, attributes : {'class' : 'callout warning'}},
|
{title: "Warning", block: 'p', exact: true, attributes : {'class' : 'callout warning'}},
|
||||||
{title: "Danger", block: 'p', exact: true, attributes : {'class' : 'callout danger'}}
|
{title: "Danger", block: 'p', exact: true, attributes : {'class' : 'callout danger'}}
|
||||||
]}
|
]},
|
||||||
],
|
],
|
||||||
style_formats_merge: false,
|
style_formats_merge: false,
|
||||||
formats: {
|
formats: {
|
||||||
|
|
39
resources/assets/js/vues/code-editor.js
Normal file
39
resources/assets/js/vues/code-editor.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
const codeLib = require('../code');
|
||||||
|
|
||||||
|
const methods = {
|
||||||
|
show() {
|
||||||
|
if (!this.editor) this.editor = codeLib.popupEditor(this.$refs.editor, this.language);
|
||||||
|
this.$refs.overlay.style.display = 'flex';
|
||||||
|
},
|
||||||
|
hide() {
|
||||||
|
this.$refs.overlay.style.display = 'none';
|
||||||
|
},
|
||||||
|
updateEditorMode(language) {
|
||||||
|
codeLib.setMode(this.editor, language);
|
||||||
|
},
|
||||||
|
open(code, language, callback) {
|
||||||
|
this.show();
|
||||||
|
this.updateEditorMode(language);
|
||||||
|
this.language = language;
|
||||||
|
codeLib.setContent(this.editor, code);
|
||||||
|
this.code = code;
|
||||||
|
this.callback = callback;
|
||||||
|
},
|
||||||
|
save() {
|
||||||
|
if (!this.callback) return;
|
||||||
|
this.callback(this.editor.getValue(), this.language);
|
||||||
|
this.hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
editor: null,
|
||||||
|
language: '',
|
||||||
|
code: '',
|
||||||
|
callback: null
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
methods,
|
||||||
|
data
|
||||||
|
};
|
|
@ -7,12 +7,15 @@ function exists(id) {
|
||||||
let vueMapping = {
|
let vueMapping = {
|
||||||
'search-system': require('./search'),
|
'search-system': require('./search'),
|
||||||
'entity-dashboard': require('./entity-search'),
|
'entity-dashboard': require('./entity-search'),
|
||||||
|
'code-editor': require('./code-editor')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.vues = {};
|
||||||
|
|
||||||
Object.keys(vueMapping).forEach(id => {
|
Object.keys(vueMapping).forEach(id => {
|
||||||
if (exists(id)) {
|
if (exists(id)) {
|
||||||
let config = vueMapping[id];
|
let config = vueMapping[id];
|
||||||
config.el = '#' + id;
|
config.el = '#' + id;
|
||||||
new Vue(config);
|
window.vues[id] = new Vue(config);
|
||||||
}
|
}
|
||||||
});
|
});
|
|
@ -248,6 +248,10 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
-webkit-font-variant-ligatures: contextual;
|
-webkit-font-variant-ligatures: contextual;
|
||||||
font-variant-ligatures: contextual;
|
font-variant-ligatures: contextual;
|
||||||
|
&:after {
|
||||||
|
content: none;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.CodeMirror-wrap pre {
|
.CodeMirror-wrap pre {
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
|
@ -467,3 +467,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
||||||
.image-picker .none {
|
.image-picker .none {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#code-editor .CodeMirror {
|
||||||
|
height: 400px;
|
||||||
|
}
|
|
@ -135,6 +135,21 @@ pre {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
border: 1px solid #DDD;
|
border: 1px solid #DDD;
|
||||||
|
padding-left: 31px;
|
||||||
|
position: relative;
|
||||||
|
padding-top: 3px;
|
||||||
|
padding-bottom: 3px;
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 29px;
|
||||||
|
left: 0;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #DDD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,6 +197,7 @@ pre code {
|
||||||
border: 0;
|
border: 0;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
display: block;
|
display: block;
|
||||||
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Text colors
|
* Text colors
|
||||||
|
|
|
@ -20,5 +20,13 @@ return [
|
||||||
'image_preview' => 'Image Preview',
|
'image_preview' => 'Image Preview',
|
||||||
'image_upload_success' => 'Image uploaded successfully',
|
'image_upload_success' => 'Image uploaded successfully',
|
||||||
'image_update_success' => 'Image details successfully updated',
|
'image_update_success' => 'Image details successfully updated',
|
||||||
'image_delete_success' => 'Image successfully deleted'
|
'image_delete_success' => 'Image successfully deleted',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Code editor
|
||||||
|
*/
|
||||||
|
'code_editor' => 'Edit Code',
|
||||||
|
'code_language' => 'Code Language',
|
||||||
|
'code_content' => 'Code Content',
|
||||||
|
'code_save' => 'Save Code',
|
||||||
];
|
];
|
29
resources/views/components/code-editor.blade.php
Normal file
29
resources/views/components/code-editor.blade.php
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<div id="code-editor">
|
||||||
|
<div class="overlay" ref="overlay" v-cloak @click="hide()">
|
||||||
|
<div class="popup-body" @click.stop>
|
||||||
|
|
||||||
|
<div class="popup-header primary-background">
|
||||||
|
<div class="popup-title">{{ trans('components.code_editor') }}</div>
|
||||||
|
<button class="popup-close neg corner-button button" @click="hide()">x</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="padded">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="code-editor-language">{{ trans('components.code_language') }}</label>
|
||||||
|
<input @keypress.enter="save()" id="code-editor-language" type="text" @input="updateEditorMode(language)" v-model="language">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="code-editor-content">{{ trans('components.code_content') }}</label>
|
||||||
|
<textarea ref="editor" v-model="code"></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="button" class="button pos" @click="save()">{{ trans('components.code_save') }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -21,6 +21,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@include('components.image-manager', ['imageType' => 'gallery', 'uploaded_to' => $page->id])
|
@include('components.image-manager', ['imageType' => 'gallery', 'uploaded_to' => $page->id])
|
||||||
|
@include('components.code-editor')
|
||||||
@include('components.entity-selector-popup')
|
@include('components.entity-selector-popup')
|
||||||
|
|
||||||
@stop
|
@stop
|
Loading…
Add table
Add a link
Reference in a new issue