]> BookStack Code Mirror - bookstack/blobdiff - resources/assets/js/code.js
Adds overflow:auto to popup content to allow it to scroll in lower res.
[bookstack] / resources / assets / js / code.js
index ef6bca2e2c3fa66f1a066d636b621f474832ae1f..8a5a7a022d1b617d14f1106d794eaf8f2d8bfc8a 100644 (file)
@@ -1,5 +1,6 @@
 require('codemirror/mode/css/css');
 require('codemirror/mode/clike/clike');
+require('codemirror/mode/diff/diff');
 require('codemirror/mode/go/go');
 require('codemirror/mode/htmlmixed/htmlmixed');
 require('codemirror/mode/javascript/javascript');
@@ -26,6 +27,7 @@ const modeMap = {
     'c++': 'clike',
     'c#': 'clike',
     csharp: 'clike',
+    diff: 'diff',
     go: 'go',
     html: 'htmlmixed',
     javascript: 'javascript',
@@ -42,6 +44,7 @@ const modeMap = {
     ruby: 'ruby',
     rb: 'ruby',
     shell: 'shell',
+    sh: 'shell',
     bash: 'shell',
     toml: 'toml',
     sql: 'sql',
@@ -50,13 +53,20 @@ const modeMap = {
     yml: 'yaml',
 };
 
-module.exports.highlight = function() {
-    let codeBlocks = document.querySelectorAll('.page-content pre');
+/**
+ * Highlight pre elements on a page
+ */
+function highlight() {
+    let codeBlocks = document.querySelectorAll('.page-content pre, .comment-box .content pre');
     for (let i = 0; i < codeBlocks.length; i++) {
         highlightElem(codeBlocks[i]);
     }
-};
+}
 
+/**
+ * Add code highlighting to a single element.
+ * @param {HTMLElement} elem
+ */
 function highlightElem(elem) {
     let innerCodeElem = elem.querySelector('code[class^=language-]');
     let mode = '';
@@ -65,7 +75,7 @@ function highlightElem(elem) {
         mode = getMode(langName);
     }
     elem.innerHTML = elem.innerHTML.replace(/<br\s*[\/]?>/gi ,'\n');
-    let content = elem.textContent;
+    let content = elem.textContent.trim();
 
     CodeMirror(function(elt) {
         elem.parentNode.replaceChild(elt, elem);
@@ -73,7 +83,7 @@ function highlightElem(elem) {
         value: content,
         mode:  mode,
         lineNumbers: true,
-        theme: 'base16-light',
+        theme: getTheme(),
         readOnly: true
     });
 }
@@ -88,15 +98,26 @@ function getMode(suggestion) {
     return (typeof modeMap[suggestion] !== 'undefined') ? modeMap[suggestion] : '';
 }
 
-module.exports.highlightElem = highlightElem;
+/**
+ * Ge the theme to use for CodeMirror instances.
+ * @returns {*|string}
+ */
+function getTheme() {
+    return window.codeTheme || 'base16-light';
+}
 
-module.exports.wysiwygView = function(elem) {
+/**
+ * Create a CodeMirror instance for showing inside the WYSIWYG editor.
+ *  Manages a textarea element to hold code content.
+ * @param {HTMLElement} elem
+ * @returns {{wrap: Element, editor: *}}
+ */
+function wysiwygView(elem) {
     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-', '')
     }
 
@@ -120,16 +141,22 @@ module.exports.wysiwygView = function(elem) {
         value: content,
         mode:  getMode(lang),
         lineNumbers: true,
-        theme: 'base16-light',
+        theme: getTheme(),
         readOnly: true
     });
     setTimeout(() => {
         cm.refresh();
     }, 300);
     return {wrap: newWrap, editor: cm};
-};
+}
 
-module.exports.popupEditor = function(elem, modeSuggestion) {
+/**
+ * Create a CodeMirror instance to show in the WYSIWYG pop-up editor
+ * @param {HTMLElement} elem
+ * @param {String} modeSuggestion
+ * @returns {*}
+ */
+function popupEditor(elem, modeSuggestion) {
     let content = elem.textContent;
 
     return CodeMirror(function(elt) {
@@ -139,22 +166,38 @@ module.exports.popupEditor = function(elem, modeSuggestion) {
         value: content,
         mode:  getMode(modeSuggestion),
         lineNumbers: true,
-        theme: 'base16-light',
+        theme: getTheme(),
         lineWrapping: true
     });
-};
+}
 
-module.exports.setMode = function(cmInstance, modeSuggestion) {
+/**
+ * Set the mode of a codemirror instance.
+ * @param cmInstance
+ * @param modeSuggestion
+ */
+function setMode(cmInstance, modeSuggestion) {
       cmInstance.setOption('mode', getMode(modeSuggestion));
-};
-module.exports.setContent = function(cmInstance, codeContent) {
+}
+
+/**
+ * Set the content of a cm instance.
+ * @param cmInstance
+ * @param codeContent
+ */
+function setContent(cmInstance, codeContent) {
     cmInstance.setValue(codeContent);
     setTimeout(() => {
         cmInstance.refresh();
     }, 10);
-};
+}
 
-module.exports.markdownEditor = function(elem) {
+/**
+ * Get a CodeMirror instace to use for the markdown editor.
+ * @param {HTMLElement} elem
+ * @returns {*}
+ */
+function markdownEditor(elem) {
     let content = elem.textContent;
 
     return CodeMirror(function (elt) {
@@ -164,9 +207,27 @@ module.exports.markdownEditor = function(elem) {
         value: content,
         mode: "markdown",
         lineNumbers: true,
-        theme: 'base16-light',
+        theme: getTheme(),
         lineWrapping: true
     });
+}
 
-};
+/**
+ * Get the 'meta' key dependant on the user's system.
+ * @returns {string}
+ */
+function getMetaKey() {
+    let mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault;
+    return mac ? "Cmd" : "Ctrl";
+}
 
+module.exports = {
+    highlight: highlight,
+    highlightElem: highlightElem,
+    wysiwygView: wysiwygView,
+    popupEditor: popupEditor,
+    setMode: setMode,
+    setContent: setContent,
+    markdownEditor: markdownEditor,
+    getMetaKey: getMetaKey,
+};
\ No newline at end of file