]> BookStack Code Mirror - bookstack/blob - resources/assets/js/code.js
Update search.js
[bookstack] / resources / assets / js / code.js
1 require('codemirror/mode/css/css');
2 require('codemirror/mode/clike/clike');
3 require('codemirror/mode/diff/diff');
4 require('codemirror/mode/go/go');
5 require('codemirror/mode/htmlmixed/htmlmixed');
6 require('codemirror/mode/javascript/javascript');
7 require('codemirror/mode/markdown/markdown');
8 require('codemirror/mode/nginx/nginx');
9 require('codemirror/mode/php/php');
10 require('codemirror/mode/powershell/powershell');
11 require('codemirror/mode/python/python');
12 require('codemirror/mode/ruby/ruby');
13 require('codemirror/mode/shell/shell');
14 require('codemirror/mode/sql/sql');
15 require('codemirror/mode/toml/toml');
16 require('codemirror/mode/xml/xml');
17 require('codemirror/mode/yaml/yaml');
18
19 const CodeMirror = require('codemirror');
20
21 const modeMap = {
22     css: 'css',
23     c: 'clike',
24     java: 'clike',
25     scala: 'clike',
26     kotlin: 'clike',
27     'c++': 'clike',
28     'c#': 'clike',
29     csharp: 'clike',
30     diff: 'diff',
31     go: 'go',
32     html: 'htmlmixed',
33     javascript: 'javascript',
34     json: {name: 'javascript', json: true},
35     js: 'javascript',
36     php: 'php',
37     md: 'markdown',
38     mdown: 'markdown',
39     markdown: 'markdown',
40     nginx: 'nginx',
41     powershell: 'powershell',
42     py: 'python',
43     python: 'python',
44     ruby: 'ruby',
45     rb: 'ruby',
46     shell: 'shell',
47     sh: 'shell',
48     bash: 'shell',
49     toml: 'toml',
50     sql: 'sql',
51     xml: 'xml',
52     yaml: 'yaml',
53     yml: 'yaml',
54 };
55
56 module.exports.highlight = function() {
57     let codeBlocks = document.querySelectorAll('.page-content pre');
58     for (let i = 0; i < codeBlocks.length; i++) {
59         highlightElem(codeBlocks[i]);
60     }
61 };
62
63 function highlightElem(elem) {
64     let innerCodeElem = elem.querySelector('code[class^=language-]');
65     let mode = '';
66     if (innerCodeElem !== null) {
67         let langName = innerCodeElem.className.replace('language-', '');
68         mode = getMode(langName);
69     }
70     elem.innerHTML = elem.innerHTML.replace(/<br\s*[\/]?>/gi ,'\n');
71     let content = elem.textContent;
72
73     CodeMirror(function(elt) {
74         elem.parentNode.replaceChild(elt, elem);
75     }, {
76         value: content,
77         mode:  mode,
78         lineNumbers: true,
79         theme: 'base16-light',
80         readOnly: true
81     });
82 }
83
84 /**
85  * Search for a codemirror code based off a user suggestion
86  * @param suggestion
87  * @returns {string}
88  */
89 function getMode(suggestion) {
90     suggestion = suggestion.trim().replace(/^\./g, '').toLowerCase();
91     return (typeof modeMap[suggestion] !== 'undefined') ? modeMap[suggestion] : '';
92 }
93
94 module.exports.highlightElem = highlightElem;
95
96 module.exports.wysiwygView = function(elem) {
97     let doc = elem.ownerDocument;
98     let codeElem = elem.querySelector('code');
99
100     let lang = (elem.className || '').replace('language-', '');
101     if (lang === '' && codeElem) {
102         lang = (codeElem.className || '').replace('language-', '')
103     }
104
105     elem.innerHTML = elem.innerHTML.replace(/<br\s*[\/]?>/gi ,'\n');
106     let content = elem.textContent;
107     let newWrap = doc.createElement('div');
108     let newTextArea = doc.createElement('textarea');
109
110     newWrap.className = 'CodeMirrorContainer';
111     newWrap.setAttribute('data-lang', lang);
112     newTextArea.style.display = 'none';
113     elem.parentNode.replaceChild(newWrap, elem);
114
115     newWrap.appendChild(newTextArea);
116     newWrap.contentEditable = false;
117     newTextArea.textContent = content;
118
119     let cm = CodeMirror(function(elt) {
120         newWrap.appendChild(elt);
121     }, {
122         value: content,
123         mode:  getMode(lang),
124         lineNumbers: true,
125         theme: 'base16-light',
126         readOnly: true
127     });
128     setTimeout(() => {
129         cm.refresh();
130     }, 300);
131     return {wrap: newWrap, editor: cm};
132 };
133
134 module.exports.popupEditor = function(elem, modeSuggestion) {
135     let content = elem.textContent;
136
137     return CodeMirror(function(elt) {
138         elem.parentNode.insertBefore(elt, elem);
139         elem.style.display = 'none';
140     }, {
141         value: content,
142         mode:  getMode(modeSuggestion),
143         lineNumbers: true,
144         theme: 'base16-light',
145         lineWrapping: true
146     });
147 };
148
149 module.exports.setMode = function(cmInstance, modeSuggestion) {
150       cmInstance.setOption('mode', getMode(modeSuggestion));
151 };
152 module.exports.setContent = function(cmInstance, codeContent) {
153     cmInstance.setValue(codeContent);
154     setTimeout(() => {
155         cmInstance.refresh();
156     }, 10);
157 };
158
159 module.exports.markdownEditor = function(elem) {
160     let content = elem.textContent;
161
162     return CodeMirror(function (elt) {
163         elem.parentNode.insertBefore(elt, elem);
164         elem.style.display = 'none';
165     }, {
166         value: content,
167         mode: "markdown",
168         lineNumbers: true,
169         theme: 'base16-light',
170         lineWrapping: true
171     });
172 };
173
174 module.exports.getMetaKey = function() {
175     let mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault;
176     return mac ? "Cmd" : "Ctrl";
177 };
178