markdown-xblock 2.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. markdown_xblock/__init__.py +2 -0
  2. markdown_xblock/html.py +335 -0
  3. markdown_xblock/public/plugins/codemirror/LICENSE +21 -0
  4. markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/dialog/dialog.css +32 -0
  5. markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/dialog/dialog.js +155 -0
  6. markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/display/fullscreen.css +6 -0
  7. markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/display/fullscreen.js +41 -0
  8. markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/edit/matchbrackets.js +120 -0
  9. markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/search/search.js +159 -0
  10. markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/search/searchcursor.js +189 -0
  11. markdown_xblock/public/plugins/codemirror/codemirror-4.8/addon/selection/active-line.js +71 -0
  12. markdown_xblock/public/plugins/codemirror/codemirror-4.8/lib/codemirror.css +319 -0
  13. markdown_xblock/public/plugins/codemirror/codemirror-4.8/lib/codemirror.js +7923 -0
  14. markdown_xblock/public/plugins/codemirror/codemirror-4.8/mode/css/css.js +717 -0
  15. markdown_xblock/public/plugins/codemirror/codemirror-4.8/mode/htmlmixed/htmlmixed.js +121 -0
  16. markdown_xblock/public/plugins/codemirror/codemirror-4.8/mode/javascript/javascript.js +684 -0
  17. markdown_xblock/public/plugins/codemirror/codemirror-4.8/mode/markdown/markdown.js +883 -0
  18. markdown_xblock/public/plugins/codemirror/codemirror-4.8/mode/xml/xml.js +384 -0
  19. markdown_xblock/public/plugins/codemirror/langs/en.js +8 -0
  20. markdown_xblock/public/plugins/codemirror/plugin.min.js +1 -0
  21. markdown_xblock/public/plugins/codemirror/source.html +270 -0
  22. markdown_xblock/public/plugins/codesample/css/prism.css +141 -0
  23. markdown_xblock/public/plugins/codesample/js/prism.js +15 -0
  24. markdown_xblock/public/plugins/codesample/plugin.min.js +1 -0
  25. markdown_xblock/public/plugins/image/plugin.min.js +1 -0
  26. markdown_xblock/public/plugins/link/plugin.min.js +1 -0
  27. markdown_xblock/public/plugins/lists/plugin.min.js +1 -0
  28. markdown_xblock/public/plugins/textcolor/plugin.min.js +1 -0
  29. markdown_xblock/public/skin/content.inline.min.css +1 -0
  30. markdown_xblock/public/skin/content.min.css +2 -0
  31. markdown_xblock/public/skin/fonts/icomoon-small.eot +0 -0
  32. markdown_xblock/public/skin/fonts/icomoon-small.svg +175 -0
  33. markdown_xblock/public/skin/fonts/icomoon-small.ttf +0 -0
  34. markdown_xblock/public/skin/fonts/icomoon-small.woff +0 -0
  35. markdown_xblock/public/skin/fonts/icomoon.eot +0 -0
  36. markdown_xblock/public/skin/fonts/icomoon.svg +153 -0
  37. markdown_xblock/public/skin/fonts/icomoon.ttf +0 -0
  38. markdown_xblock/public/skin/fonts/icomoon.woff +0 -0
  39. markdown_xblock/public/skin/fonts/readme.md +1 -0
  40. markdown_xblock/public/skin/img/anchor.gif +0 -0
  41. markdown_xblock/public/skin/img/loader.gif +0 -0
  42. markdown_xblock/public/skin/img/object.gif +0 -0
  43. markdown_xblock/public/skin/img/trans.gif +0 -0
  44. markdown_xblock/public/skin/img/wline.gif +0 -0
  45. markdown_xblock/public/skin/skin.ie7.min.css +1 -0
  46. markdown_xblock/public/skin/skin.json +51 -0
  47. markdown_xblock/public/skin/skin.min.css +1 -0
  48. markdown_xblock/static/css/html.css +15 -0
  49. markdown_xblock/static/css/pygments.css +61 -0
  50. markdown_xblock/static/html/lms.html +1 -0
  51. markdown_xblock/static/html/studio.html +29 -0
  52. markdown_xblock/static/js/html.js +233 -0
  53. markdown_xblock/static/js/tinymce/themes/modern/theme.min.js +1 -0
  54. markdown_xblock/static/js/tinymce/tinymce.js +26801 -0
  55. markdown_xblock/static/js/tinymce/tinymce.min.js +2 -0
  56. markdown_xblock/translations/README.txt +4 -0
  57. markdown_xblock/utils.py +11 -0
  58. markdown_xblock-2.4.0.dist-info/METADATA +158 -0
  59. markdown_xblock-2.4.0.dist-info/RECORD +83 -0
  60. markdown_xblock-2.4.0.dist-info/WHEEL +5 -0
  61. markdown_xblock-2.4.0.dist-info/entry_points.txt +2 -0
  62. markdown_xblock-2.4.0.dist-info/licenses/LICENSE +671 -0
  63. markdown_xblock-2.4.0.dist-info/top_level.txt +5 -0
  64. releasenotes/notes/add-default-css-for-tables-3a53e02e8a350253.yaml +5 -0
  65. releasenotes/notes/add_public_view-d24763b7941dc2b0.yaml +4 -0
  66. releasenotes/notes/custom-css-classes-7984a9c95147d39c.yaml +5 -0
  67. releasenotes/notes/export-md-to-file-ab1528b4c28cb2f0.yaml +5 -0
  68. releasenotes/notes/fix-course-export-b35c78a22be0c6b5.yaml +6 -0
  69. releasenotes/notes/missing-codemirror-files-d64ccb15d0faf640.yaml +6 -0
  70. releasenotes/notes/pypi-release-3e4d5ceb7b6e252a.yaml +7 -0
  71. releasenotes/notes/python-3.12-support-dac839f8d01ac6b9.yaml +4 -0
  72. releasenotes/notes/refactor-ci-36abda8c15250d06.yaml +6 -0
  73. releasenotes/notes/refactor-export-import-49bbf0e8a364f139.yaml +8 -0
  74. releasenotes/notes/remove_py35-0b265861449b1753.yaml +9 -0
  75. releasenotes/notes/safe_mode_replace_escape-40fdb78ec8aa5eff.yaml +7 -0
  76. releasenotes/notes/show_in_read_only_mode-3af39459d5d56b33.yaml +7 -0
  77. requirements/base.txt +9 -0
  78. requirements/dev.txt +2 -0
  79. requirements/reno.txt +1 -0
  80. requirements/test.txt +9 -0
  81. tests/__init__.py +1 -0
  82. tests/test_basics.py +280 -0
  83. var/.placeholder +2 -0
@@ -0,0 +1,384 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ CodeMirror.defineMode("xml", function(config, parserConfig) {
15
+ var indentUnit = config.indentUnit;
16
+ var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
17
+ var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;
18
+ if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
19
+
20
+ var Kludges = parserConfig.htmlMode ? {
21
+ autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
22
+ 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
23
+ 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
24
+ 'track': true, 'wbr': true, 'menuitem': true},
25
+ implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
26
+ 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
27
+ 'th': true, 'tr': true},
28
+ contextGrabbers: {
29
+ 'dd': {'dd': true, 'dt': true},
30
+ 'dt': {'dd': true, 'dt': true},
31
+ 'li': {'li': true},
32
+ 'option': {'option': true, 'optgroup': true},
33
+ 'optgroup': {'optgroup': true},
34
+ 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
35
+ 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
36
+ 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
37
+ 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
38
+ 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
39
+ 'rp': {'rp': true, 'rt': true},
40
+ 'rt': {'rp': true, 'rt': true},
41
+ 'tbody': {'tbody': true, 'tfoot': true},
42
+ 'td': {'td': true, 'th': true},
43
+ 'tfoot': {'tbody': true},
44
+ 'th': {'td': true, 'th': true},
45
+ 'thead': {'tbody': true, 'tfoot': true},
46
+ 'tr': {'tr': true}
47
+ },
48
+ doNotIndent: {"pre": true},
49
+ allowUnquoted: true,
50
+ allowMissing: true,
51
+ caseFold: true
52
+ } : {
53
+ autoSelfClosers: {},
54
+ implicitlyClosed: {},
55
+ contextGrabbers: {},
56
+ doNotIndent: {},
57
+ allowUnquoted: false,
58
+ allowMissing: false,
59
+ caseFold: false
60
+ };
61
+ var alignCDATA = parserConfig.alignCDATA;
62
+
63
+ // Return variables for tokenizers
64
+ var type, setStyle;
65
+
66
+ function inText(stream, state) {
67
+ function chain(parser) {
68
+ state.tokenize = parser;
69
+ return parser(stream, state);
70
+ }
71
+
72
+ var ch = stream.next();
73
+ if (ch == "<") {
74
+ if (stream.eat("!")) {
75
+ if (stream.eat("[")) {
76
+ if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
77
+ else return null;
78
+ } else if (stream.match("--")) {
79
+ return chain(inBlock("comment", "-->"));
80
+ } else if (stream.match("DOCTYPE", true, true)) {
81
+ stream.eatWhile(/[\w\._\-]/);
82
+ return chain(doctype(1));
83
+ } else {
84
+ return null;
85
+ }
86
+ } else if (stream.eat("?")) {
87
+ stream.eatWhile(/[\w\._\-]/);
88
+ state.tokenize = inBlock("meta", "?>");
89
+ return "meta";
90
+ } else {
91
+ type = stream.eat("/") ? "closeTag" : "openTag";
92
+ state.tokenize = inTag;
93
+ return "tag bracket";
94
+ }
95
+ } else if (ch == "&") {
96
+ var ok;
97
+ if (stream.eat("#")) {
98
+ if (stream.eat("x")) {
99
+ ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
100
+ } else {
101
+ ok = stream.eatWhile(/[\d]/) && stream.eat(";");
102
+ }
103
+ } else {
104
+ ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
105
+ }
106
+ return ok ? "atom" : "error";
107
+ } else {
108
+ stream.eatWhile(/[^&<]/);
109
+ return null;
110
+ }
111
+ }
112
+
113
+ function inTag(stream, state) {
114
+ var ch = stream.next();
115
+ if (ch == ">" || (ch == "/" && stream.eat(">"))) {
116
+ state.tokenize = inText;
117
+ type = ch == ">" ? "endTag" : "selfcloseTag";
118
+ return "tag bracket";
119
+ } else if (ch == "=") {
120
+ type = "equals";
121
+ return null;
122
+ } else if (ch == "<") {
123
+ state.tokenize = inText;
124
+ state.state = baseState;
125
+ state.tagName = state.tagStart = null;
126
+ var next = state.tokenize(stream, state);
127
+ return next ? next + " tag error" : "tag error";
128
+ } else if (/[\'\"]/.test(ch)) {
129
+ state.tokenize = inAttribute(ch);
130
+ state.stringStartCol = stream.column();
131
+ return state.tokenize(stream, state);
132
+ } else {
133
+ stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
134
+ return "word";
135
+ }
136
+ }
137
+
138
+ function inAttribute(quote) {
139
+ var closure = function(stream, state) {
140
+ while (!stream.eol()) {
141
+ if (stream.next() == quote) {
142
+ state.tokenize = inTag;
143
+ break;
144
+ }
145
+ }
146
+ return "string";
147
+ };
148
+ closure.isInAttribute = true;
149
+ return closure;
150
+ }
151
+
152
+ function inBlock(style, terminator) {
153
+ return function(stream, state) {
154
+ while (!stream.eol()) {
155
+ if (stream.match(terminator)) {
156
+ state.tokenize = inText;
157
+ break;
158
+ }
159
+ stream.next();
160
+ }
161
+ return style;
162
+ };
163
+ }
164
+ function doctype(depth) {
165
+ return function(stream, state) {
166
+ var ch;
167
+ while ((ch = stream.next()) != null) {
168
+ if (ch == "<") {
169
+ state.tokenize = doctype(depth + 1);
170
+ return state.tokenize(stream, state);
171
+ } else if (ch == ">") {
172
+ if (depth == 1) {
173
+ state.tokenize = inText;
174
+ break;
175
+ } else {
176
+ state.tokenize = doctype(depth - 1);
177
+ return state.tokenize(stream, state);
178
+ }
179
+ }
180
+ }
181
+ return "meta";
182
+ };
183
+ }
184
+
185
+ function Context(state, tagName, startOfLine) {
186
+ this.prev = state.context;
187
+ this.tagName = tagName;
188
+ this.indent = state.indented;
189
+ this.startOfLine = startOfLine;
190
+ if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
191
+ this.noIndent = true;
192
+ }
193
+ function popContext(state) {
194
+ if (state.context) state.context = state.context.prev;
195
+ }
196
+ function maybePopContext(state, nextTagName) {
197
+ var parentTagName;
198
+ while (true) {
199
+ if (!state.context) {
200
+ return;
201
+ }
202
+ parentTagName = state.context.tagName;
203
+ if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
204
+ !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
205
+ return;
206
+ }
207
+ popContext(state);
208
+ }
209
+ }
210
+
211
+ function baseState(type, stream, state) {
212
+ if (type == "openTag") {
213
+ state.tagStart = stream.column();
214
+ return tagNameState;
215
+ } else if (type == "closeTag") {
216
+ return closeTagNameState;
217
+ } else {
218
+ return baseState;
219
+ }
220
+ }
221
+ function tagNameState(type, stream, state) {
222
+ if (type == "word") {
223
+ state.tagName = stream.current();
224
+ setStyle = "tag";
225
+ return attrState;
226
+ } else {
227
+ setStyle = "error";
228
+ return tagNameState;
229
+ }
230
+ }
231
+ function closeTagNameState(type, stream, state) {
232
+ if (type == "word") {
233
+ var tagName = stream.current();
234
+ if (state.context && state.context.tagName != tagName &&
235
+ Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
236
+ popContext(state);
237
+ if (state.context && state.context.tagName == tagName) {
238
+ setStyle = "tag";
239
+ return closeState;
240
+ } else {
241
+ setStyle = "tag error";
242
+ return closeStateErr;
243
+ }
244
+ } else {
245
+ setStyle = "error";
246
+ return closeStateErr;
247
+ }
248
+ }
249
+
250
+ function closeState(type, _stream, state) {
251
+ if (type != "endTag") {
252
+ setStyle = "error";
253
+ return closeState;
254
+ }
255
+ popContext(state);
256
+ return baseState;
257
+ }
258
+ function closeStateErr(type, stream, state) {
259
+ setStyle = "error";
260
+ return closeState(type, stream, state);
261
+ }
262
+
263
+ function attrState(type, _stream, state) {
264
+ if (type == "word") {
265
+ setStyle = "attribute";
266
+ return attrEqState;
267
+ } else if (type == "endTag" || type == "selfcloseTag") {
268
+ var tagName = state.tagName, tagStart = state.tagStart;
269
+ state.tagName = state.tagStart = null;
270
+ if (type == "selfcloseTag" ||
271
+ Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
272
+ maybePopContext(state, tagName);
273
+ } else {
274
+ maybePopContext(state, tagName);
275
+ state.context = new Context(state, tagName, tagStart == state.indented);
276
+ }
277
+ return baseState;
278
+ }
279
+ setStyle = "error";
280
+ return attrState;
281
+ }
282
+ function attrEqState(type, stream, state) {
283
+ if (type == "equals") return attrValueState;
284
+ if (!Kludges.allowMissing) setStyle = "error";
285
+ return attrState(type, stream, state);
286
+ }
287
+ function attrValueState(type, stream, state) {
288
+ if (type == "string") return attrContinuedState;
289
+ if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
290
+ setStyle = "error";
291
+ return attrState(type, stream, state);
292
+ }
293
+ function attrContinuedState(type, stream, state) {
294
+ if (type == "string") return attrContinuedState;
295
+ return attrState(type, stream, state);
296
+ }
297
+
298
+ return {
299
+ startState: function() {
300
+ return {tokenize: inText,
301
+ state: baseState,
302
+ indented: 0,
303
+ tagName: null, tagStart: null,
304
+ context: null};
305
+ },
306
+
307
+ token: function(stream, state) {
308
+ if (!state.tagName && stream.sol())
309
+ state.indented = stream.indentation();
310
+
311
+ if (stream.eatSpace()) return null;
312
+ type = null;
313
+ var style = state.tokenize(stream, state);
314
+ if ((style || type) && style != "comment") {
315
+ setStyle = null;
316
+ state.state = state.state(type || style, stream, state);
317
+ if (setStyle)
318
+ style = setStyle == "error" ? style + " error" : setStyle;
319
+ }
320
+ return style;
321
+ },
322
+
323
+ indent: function(state, textAfter, fullLine) {
324
+ var context = state.context;
325
+ // Indent multi-line strings (e.g. css).
326
+ if (state.tokenize.isInAttribute) {
327
+ if (state.tagStart == state.indented)
328
+ return state.stringStartCol + 1;
329
+ else
330
+ return state.indented + indentUnit;
331
+ }
332
+ if (context && context.noIndent) return CodeMirror.Pass;
333
+ if (state.tokenize != inTag && state.tokenize != inText)
334
+ return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
335
+ // Indent the starts of attribute names.
336
+ if (state.tagName) {
337
+ if (multilineTagIndentPastTag)
338
+ return state.tagStart + state.tagName.length + 2;
339
+ else
340
+ return state.tagStart + indentUnit * multilineTagIndentFactor;
341
+ }
342
+ if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
343
+ var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
344
+ if (tagAfter && tagAfter[1]) { // Closing tag spotted
345
+ while (context) {
346
+ if (context.tagName == tagAfter[2]) {
347
+ context = context.prev;
348
+ break;
349
+ } else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
350
+ context = context.prev;
351
+ } else {
352
+ break;
353
+ }
354
+ }
355
+ } else if (tagAfter) { // Opening tag spotted
356
+ while (context) {
357
+ var grabbers = Kludges.contextGrabbers[context.tagName];
358
+ if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
359
+ context = context.prev;
360
+ else
361
+ break;
362
+ }
363
+ }
364
+ while (context && !context.startOfLine)
365
+ context = context.prev;
366
+ if (context) return context.indent + indentUnit;
367
+ else return 0;
368
+ },
369
+
370
+ electricInput: /<\/[\s\w:]+>$/,
371
+ blockCommentStart: "<!--",
372
+ blockCommentEnd: "-->",
373
+
374
+ configuration: parserConfig.htmlMode ? "html" : "xml",
375
+ helperType: parserConfig.htmlMode ? "html" : "xml"
376
+ };
377
+ });
378
+
379
+ CodeMirror.defineMIME("text/xml", "xml");
380
+ CodeMirror.defineMIME("application/xml", "xml");
381
+ if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
382
+ CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
383
+
384
+ });
@@ -0,0 +1,8 @@
1
+ tinymce.addI18n('en',{
2
+ 'HTML source code': 'HTML source code',
3
+ 'Start search': 'Start search',
4
+ 'Find next': 'Find next',
5
+ 'Find previous': 'Find previous',
6
+ 'Replace': 'Replace',
7
+ 'Replace all': 'Replace all'
8
+ });
@@ -0,0 +1 @@
1
+ tinymce.PluginManager.requireLangPack("codemirror");tinymce.PluginManager.add("codemirror",function(e,r){function o(){e.focus();e.selection.collapse(true);if(e.settings.codemirror.saveCursorPosition){e.selection.setContent('<span style="display: none;" class="CmCaReT">&#x0;</span>')}codemirrorWidth=800;if(e.settings.codemirror.width){codemirrorWidth=e.settings.codemirror.width}codemirrorHeight=550;if(e.settings.codemirror.width){codemirrorHeight=e.settings.codemirror.height}var o={title:"HTML source code",url:r+"/source.html",width:codemirrorWidth,height:codemirrorHeight,resizable:true,maximizable:true,fullScreen:e.settings.codemirror.fullscreen,buttons:[{text:"Ok",subtype:"primary",onclick:function(){var e=document.querySelectorAll(".mce-container-body>iframe")[0];e.contentWindow.submit();i.close()}},{text:"Cancel",onclick:"close"}]};var i=e.windowManager.open(o);if(e.settings.codemirror.fullscreen){i.fullscreen(true)}}e.addButton("code",{title:"Source code",icon:"code",onclick:o});e.addMenuItem("code",{icon:"code",text:"Source code",context:"tools",onclick:o})});
@@ -0,0 +1,270 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <script>
5
+
6
+ /**
7
+ * source.html
8
+ *
9
+ * Copyright 2013-2014 Web Power, www.webpower.nl
10
+ * @author Arjan Haverkamp
11
+ */
12
+
13
+ // Global vars:
14
+ var tinymce, // Reference to TinyMCE
15
+ editor, // Reference to TinyMCE editor
16
+ codemirror, // CodeMirror instance
17
+ chr = 0, // Unused utf-8 character, placeholder for cursor
18
+ isMac = /macintosh|mac os/i.test(navigator.userAgent),
19
+ CMsettings; // CodeMirror settings
20
+
21
+ function inArray(key, arr)
22
+ {
23
+ "use strict";
24
+ arr = '|' + arr.join('|') + '|';
25
+ return arr.indexOf('|'+key+'|') != -1;
26
+ }
27
+
28
+ (function()
29
+ {// Initialise (before load)
30
+ "use strict";
31
+
32
+ tinymce = parent.tinymce;
33
+ editor = tinymce.activeEditor;
34
+ var i, userSettings = editor.settings.codemirror ? editor.settings.codemirror : {};
35
+ CMsettings = {
36
+ path: userSettings.path || 'codemirror-4.8',
37
+ indentOnInit: userSettings.indentOnInit || false,
38
+ config: {// Default config
39
+ mode: 'htmlmixed',
40
+ theme: 'default',
41
+ lineNumbers: true,
42
+ lineWrapping: true,
43
+ indentUnit: 2,
44
+ tabSize: 2,
45
+ indentWithTabs: true,
46
+ matchBrackets: true,
47
+ saveCursorPosition: true,
48
+ styleActiveLine: true
49
+ },
50
+ jsFiles: [// Default JS files
51
+ 'lib/codemirror.js',
52
+ 'addon/edit/matchbrackets.js',
53
+ 'mode/xml/xml.js',
54
+ 'mode/javascript/javascript.js',
55
+ 'mode/css/css.js',
56
+ 'mode/htmlmixed/htmlmixed.js',
57
+ 'addon/dialog/dialog.js',
58
+ 'addon/search/searchcursor.js',
59
+ 'addon/search/search.js',
60
+ 'addon/selection/active-line.js'
61
+ ],
62
+ cssFiles: [// Default CSS files
63
+ 'lib/codemirror.css',
64
+ 'addon/dialog/dialog.css'
65
+ ]
66
+ };
67
+
68
+ if (userSettings.fullscreen) {
69
+ CMsettings.jsFiles.push('addon/display/fullscreen.js');
70
+ CMsettings.cssFiles.push('addon/display/fullscreen.css');
71
+ }
72
+
73
+ // Merge config
74
+ for (i in userSettings.config) {
75
+ CMsettings.config[i] = userSettings.config[i];
76
+ }
77
+
78
+ // Merge jsFiles
79
+ for (i in userSettings.jsFiles) {
80
+ if (!inArray(userSettings.jsFiles[i], CMsettings.jsFiles)) {
81
+ CMsettings.jsFiles.push(userSettings.jsFiles[i]);
82
+ }
83
+ }
84
+
85
+ // Merge cssFiles
86
+ for (i in userSettings.cssFiles) {
87
+ if (!inArray(userSettings.cssFiles[i], CMsettings.cssFiles)) {
88
+ CMsettings.cssFiles.push(userSettings.cssFiles[i]);
89
+ }
90
+ }
91
+
92
+ // Add trailing slash to path
93
+ if (!/\/$/.test(CMsettings.path)) {
94
+ CMsettings.path += '/';
95
+ }
96
+
97
+ // Write stylesheets
98
+ for (i = 0; i < CMsettings.cssFiles.length; i++) {
99
+ document.write('<li'+'nk rel="stylesheet" type="text/css" href="' + CMsettings.path + CMsettings.cssFiles[i] + '" />');
100
+ }
101
+
102
+ // Write JS source files
103
+ for (i = 0; i < CMsettings.jsFiles.length; i++) {
104
+ document.write('<scr'+'ipt type="text/javascript" src="' + CMsettings.path + CMsettings.jsFiles[i] + '"></scr'+'ipt>');
105
+ }
106
+
107
+ // Borrowed from codemirror.js themeChanged function. Sets the theme's class names to the html element.
108
+ // Without this, the background color outside of the codemirror wrapper element remains white.
109
+ // [TMP] commented temporary, cause JS error: Uncaught TypeError: Cannot read property 'replace' of undefined
110
+ if(CMsettings.config.theme) {
111
+ document.documentElement.className += CMsettings.config.theme.replace(/(^|\s)\s*/g, " cm-s-");
112
+ }
113
+
114
+ window.onload = start;
115
+ }());
116
+
117
+ function start()
118
+ {// Initialise (on load)
119
+ "use strict";
120
+
121
+ if (typeof(window.CodeMirror) !== 'function') {
122
+ alert('CodeMirror not found in "' + CMsettings.path + '", aborting...');
123
+ return;
124
+ }
125
+
126
+ // Create legend for keyboard shortcuts for find & replace:
127
+ var head = parent.document.querySelectorAll('.mce-foot')[0],
128
+ div = parent.document.createElement('div'),
129
+ td1 = '<td style="font-size:11px;background:#777;color:#fff;padding:0 4px">',
130
+ td2 = '<td style="font-size:11px;padding-right:5px">';
131
+ div.innerHTML = '<table cellspacing="0" cellpadding="0" style="border-spacing:4px"><tr>' + td1 + (isMac ? '&#8984;-F' : 'Ctrl-F</td>') + td2 + tinymce.translate('Start search') + '</td>' + td1 + (isMac ? '&#8984;-G' : 'Ctrl-G') + '</td>' + td2 + tinymce.translate('Find next') + '</td>' + td1 + (isMac ? '&#8984;-Alt-F' : 'Shift-Ctrl-F') + '</td>' + td2 + tinymce.translate('Find previous') + '</td></tr>' + '<tr>' + td1 + (isMac ? '&#8984;-Alt-F' : 'Shift-Ctrl-F') + '</td>' + td2 + tinymce.translate('Replace') + '</td>' + td1 + (isMac ? 'Shift-&#8984;-Alt-F' : 'Shift-Ctrl-R') +'</td>' + td2 + tinymce.translate('Replace all') + '</td></tr></table>';
132
+ div.style.position = 'absolute';
133
+ div.style.left = div.style.bottom = '5px';
134
+ head.appendChild(div);
135
+
136
+ // Set CodeMirror cursor and bookmark to same position as cursor was in TinyMCE:
137
+ var html = editor.getContent({source_view: true});
138
+
139
+ // [FIX] #6 z-index issue with table panel and source code dialog
140
+ // editor.selection.getBookmark();
141
+
142
+ html = html.replace(/<span\s+style="display: none;"\s+class="CmCaReT"([^>]*)>([^<]*)<\/span>/gm, String.fromCharCode(chr));
143
+ editor.dom.remove(editor.dom.select('.CmCaReT'));
144
+
145
+ // Hide TinyMCE toolbar panels, [FIX] #6 z-index issue with table panel and source code dialog
146
+ // https://github.com/christiaan/tinymce-codemirror/issues/6
147
+ tinymce.each(editor.contextToolbars, function(toolbar) { if (toolbar.panel) { toolbar.panel.hide(); } });
148
+
149
+ CodeMirror.defineInitHook(function(inst)
150
+ {
151
+ // Move cursor to correct position:
152
+ inst.focus();
153
+ var cursor = inst.getSearchCursor(String.fromCharCode(chr), false);
154
+ if (cursor.findNext()) {
155
+ inst.setCursor(cursor.to());
156
+ cursor.replace('');
157
+ }
158
+
159
+ // Indent all code, if so requested:
160
+ if (editor.settings.codemirror.indentOnInit) {
161
+ var last = inst.lineCount();
162
+ inst.operation(function() {
163
+ for (var i = 0; i < last; ++i) {
164
+ inst.indentLine(i);
165
+ }
166
+ });
167
+ }
168
+ });
169
+
170
+ CMsettings.config.value = html;
171
+
172
+ // Instantiante CodeMirror:
173
+ codemirror = CodeMirror(document.body, CMsettings.config);
174
+ codemirror.isDirty = false;
175
+ codemirror.on('change', function(inst) {
176
+ inst.isDirty = true;
177
+ });
178
+ }
179
+
180
+ function findDepth(haystack, needle)
181
+ {
182
+ "use strict";
183
+
184
+ var idx = haystack.indexOf(needle), depth = 0, x;
185
+ for (x = idx -1; x >= 0; x--) {
186
+ switch(haystack.charAt(x)) {
187
+ case '<': depth--; break;
188
+ case '>': depth++; break;
189
+ case '&': depth++; break;
190
+ }
191
+ }
192
+ return depth;
193
+ }
194
+
195
+ // This function is called by plugin.js, when user clicks 'Ok' button
196
+ function submit()
197
+ {
198
+ "use strict";
199
+
200
+ var cc = '&#x0;', isDirty = codemirror.isDirty, doc = codemirror.doc;
201
+
202
+ if (doc.somethingSelected()) {
203
+ // Clear selection:
204
+ doc.setCursor(doc.getCursor());
205
+ }
206
+
207
+ // Insert cursor placeholder (&#x0;)
208
+ doc.replaceSelection(cc);
209
+
210
+ var pos = codemirror.getCursor(),
211
+ curLineHTML = doc.getLine(pos.line);
212
+
213
+ if (findDepth(curLineHTML, cc) !== 0) {
214
+ // Cursor is inside a <tag>, don't set cursor:
215
+ curLineHTML = curLineHTML.replace(cc, '');
216
+ doc.replaceRange(curLineHTML, CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line));
217
+ }
218
+
219
+ // Submit HTML to TinyMCE:
220
+ // [FIX] Cursor position inside JS, style or &nbps;
221
+ // Workaround to fix cursor position if inside script tag
222
+ var code = codemirror.getValue();
223
+ if(code.search(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi) !== -1 || code.search(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi) !== -1)
224
+ {
225
+ editor.setContent(codemirror.getValue().replace(cc, ''));
226
+ }
227
+ else
228
+ {
229
+ editor.setContent(codemirror.getValue().replace(cc, '<span id="CmCaReT"></span>'));
230
+ }
231
+
232
+ editor.isNotDirty = !isDirty;
233
+ if (isDirty) {
234
+ editor.nodeChanged();
235
+ }
236
+
237
+ // Set cursor:
238
+ var el = editor.dom.select('span#CmCaReT')[0];
239
+ if (el) {
240
+ editor.selection.scrollIntoView(el);
241
+ editor.selection.setCursorLocation(el,0);
242
+ editor.dom.remove(el);
243
+ }
244
+ }
245
+
246
+ </script>
247
+ <style type="text/css">
248
+ body {
249
+ margin: 0;
250
+ }
251
+
252
+ .CodeMirror {
253
+ height: 100%;
254
+ font-size: 12px;
255
+ line-height: 18px;
256
+ }
257
+
258
+ .CodeMirror-activeline-background {
259
+ background: #e8f2ff !important;
260
+ }
261
+
262
+ .cm-trailingspace {
263
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QUXCToH00Y1UgAAACFJREFUCNdjPMDBUc/AwNDAAAFMTAwMDA0OP34wQgX/AQBYgwYEx4f9lQAAAABJRU5ErkJggg==);
264
+ background-position: bottom left;
265
+ background-repeat: repeat-x;
266
+ }
267
+ </style>
268
+ </head>
269
+ <body></body>
270
+ </html>