summaryrefslogtreecommitdiffstats
path: root/media/CodeMirror-0.62
diff options
context:
space:
mode:
Diffstat (limited to 'media/CodeMirror-0.62')
-rw-r--r--media/CodeMirror-0.62/LICENSE23
-rw-r--r--media/CodeMirror-0.62/bigtest.html1296
-rw-r--r--media/CodeMirror-0.62/contrib/lua/LICENSE32
-rw-r--r--media/CodeMirror-0.62/contrib/lua/css/luacolors.css59
-rw-r--r--media/CodeMirror-0.62/contrib/lua/index.html68
-rw-r--r--media/CodeMirror-0.62/contrib/lua/js/parselua.js253
-rw-r--r--media/CodeMirror-0.62/contrib/php/LICENSE37
-rw-r--r--media/CodeMirror-0.62/contrib/php/css/phpcolors.css110
-rw-r--r--media/CodeMirror-0.62/contrib/php/index.html292
-rw-r--r--media/CodeMirror-0.62/contrib/php/js/parsephp.js371
-rw-r--r--media/CodeMirror-0.62/contrib/php/js/parsephphtmlmixed.js90
-rw-r--r--media/CodeMirror-0.62/contrib/php/js/tokenizephp.js1007
-rw-r--r--media/CodeMirror-0.62/contrib/python/LICENSE32
-rw-r--r--media/CodeMirror-0.62/contrib/python/css/pythoncolors.css54
-rw-r--r--media/CodeMirror-0.62/contrib/python/index.html141
-rw-r--r--media/CodeMirror-0.62/contrib/python/js/parsepython.js544
-rw-r--r--media/CodeMirror-0.62/css/csscolors.css47
-rw-r--r--media/CodeMirror-0.62/css/docs.css46
-rw-r--r--media/CodeMirror-0.62/css/jscolors.css55
-rw-r--r--media/CodeMirror-0.62/css/people.jpgbin14122 -> 0 bytes
-rw-r--r--media/CodeMirror-0.62/css/sparqlcolors.css39
-rw-r--r--media/CodeMirror-0.62/css/survexcolors.css71
-rw-r--r--media/CodeMirror-0.62/css/xmlcolors.css51
-rw-r--r--media/CodeMirror-0.62/csstest.html60
-rw-r--r--media/CodeMirror-0.62/highlight.html82
-rw-r--r--media/CodeMirror-0.62/htmltest.html53
-rw-r--r--media/CodeMirror-0.62/index.html182
-rw-r--r--media/CodeMirror-0.62/js/codemirror.js298
-rw-r--r--media/CodeMirror-0.62/js/editor.js1303
-rw-r--r--media/CodeMirror-0.62/js/highlight.js68
-rw-r--r--media/CodeMirror-0.62/js/mirrorframe.js81
-rw-r--r--media/CodeMirror-0.62/js/parsecss.js155
-rw-r--r--media/CodeMirror-0.62/js/parsedummy.js32
-rw-r--r--media/CodeMirror-0.62/js/parsehtmlmixed.js74
-rw-r--r--media/CodeMirror-0.62/js/parsejavascript.js341
-rw-r--r--media/CodeMirror-0.62/js/parsesparql.js162
-rw-r--r--media/CodeMirror-0.62/js/parsesurvex.js107
-rw-r--r--media/CodeMirror-0.62/js/parsexml.js292
-rw-r--r--media/CodeMirror-0.62/js/select.js583
-rw-r--r--media/CodeMirror-0.62/js/stringstream.js140
-rw-r--r--media/CodeMirror-0.62/js/tokenize.js57
-rw-r--r--media/CodeMirror-0.62/js/tokenizejavascript.js175
-rw-r--r--media/CodeMirror-0.62/js/undo.js403
-rw-r--r--media/CodeMirror-0.62/js/util.js115
-rw-r--r--media/CodeMirror-0.62/jstest.html56
-rw-r--r--media/CodeMirror-0.62/manual.html622
-rw-r--r--media/CodeMirror-0.62/mixedtest.html52
-rw-r--r--media/CodeMirror-0.62/sparqltest.html41
-rw-r--r--media/CodeMirror-0.62/story.html652
49 files changed, 0 insertions, 10904 deletions
diff --git a/media/CodeMirror-0.62/LICENSE b/media/CodeMirror-0.62/LICENSE
deleted file mode 100644
index 44ceed6..0000000
--- a/media/CodeMirror-0.62/LICENSE
+++ /dev/null
@@ -1,23 +0,0 @@
- Copyright (c) 2007-2009 Marijn Haverbeke
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any
- damages arising from the use of this software.
-
- Permission is granted to anyone to use this software for any
- purpose, including commercial applications, and to alter it and
- redistribute it freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must
- not claim that you wrote the original software. If you use this
- software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
-
- 2. Altered source versions must be plainly marked as such, and must
- not be misrepresented as being the original software.
-
- 3. This notice may not be removed or altered from any source
- distribution.
-
- Marijn Haverbeke
- marijnh at gmail
diff --git a/media/CodeMirror-0.62/bigtest.html b/media/CodeMirror-0.62/bigtest.html
deleted file mode 100644
index 04ebcda..0000000
--- a/media/CodeMirror-0.62/bigtest.html
+++ /dev/null
@@ -1,1296 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <script src="js/codemirror.js" type="text/javascript"></script>
- <title>CodeMirror: JavaScript demonstration</title>
- <link rel="stylesheet" type="text/css" href="css/docs.css"/>
- </head>
- <body style="padding: 20px;">
-
-<p>This page demonstrates <a href="index.html">CodeMirror</a>'s
-JavaScript parser. Note that the ugly buttons at the top are not are
-not part of CodeMirror proper -- they demonstrate the way it can be
-embedded in a web-application.</p>
-
-<div class="border">
-<textarea id="code" cols="120" rows="30">
-/* The Editor object manages the content of the editable frame. It
- * catches events, colours nodes, and indents lines. This file also
- * holds some functions for transforming arbitrary DOM structures into
- * plain sequences of &lt;span> and &lt;br> elements
- */
-
-// Make sure a string does not contain two consecutive 'collapseable'
-// whitespace characters.
-function makeWhiteSpace(n) {
- var buffer = [], nb = true;
- for (; n > 0; n--) {
- buffer.push((nb || n == 1) ? nbsp : " ");
- nb = !nb;
- }
- return buffer.join("");
-}
-
-// Create a set of white-space characters that will not be collapsed
-// by the browser, but will not break text-wrapping either.
-function fixSpaces(string) {
- if (string.charAt(0) == " ") string = nbsp + string.slice(1);
- return string.replace(/[\t \u00a0]{2,}/g, function(s) {return makeWhiteSpace(s.length);});
-}
-
-function cleanText(text) {
- return text.replace(/\u00a0/g, " ").replace(/\u200b/g, "");
-}
-
-// Create a SPAN node with the expected properties for document part
-// spans.
-function makePartSpan(value, doc) {
- var text = value;
- if (value.nodeType == 3) text = value.nodeValue;
- else value = doc.createTextNode(text);
-
- var span = doc.createElement("SPAN");
- span.isPart = true;
- span.appendChild(value);
- span.currentText = text;
- return span;
-}
-
-// On webkit, when the last BR of the document does not have text
-// behind it, the cursor can not be put on the line after it. This
-// makes pressing enter at the end of the document occasionally do
-// nothing (or at least seem to do nothing). To work around it, this
-// function makes sure the document ends with a span containing a
-// zero-width space character. The traverseDOM iterator filters such
-// character out again, so that the parsers won't see them. This
-// function is called from a few strategic places to make sure the
-// zwsp is restored after the highlighting process eats it.
-var webkitLastLineHack = webkit ?
- function(container) {
- var last = container.lastChild;
- if (!last || !last.isPart || last.textContent != "\u200b")
- container.appendChild(makePartSpan("\u200b", container.ownerDocument));
- } : function() {};
-
-var Editor = (function(){
- // The HTML elements whose content should be suffixed by a newline
- // when converting them to flat text.
- var newlineElements = {"P": true, "DIV": true, "LI": true};
-
- function asEditorLines(string) {
- return fixSpaces(string.replace(/\t/g, " ").replace(/\u00a0/g, " ")).replace(/\r\n?/g, "\n").split("\n");
- }
-
- // Helper function for traverseDOM. Flattens an arbitrary DOM node
- // into an array of textnodes and &lt;br> tags.
- function simplifyDOM(root) {
- var doc = root.ownerDocument;
- var result = [];
- var leaving = true;
-
- function simplifyNode(node) {
- if (node.nodeType == 3) {
- var text = node.nodeValue = fixSpaces(node.nodeValue.replace(/[\r\u200b]/g, "").replace(/\n/g, " "));
- if (text.length) leaving = false;
- result.push(node);
- }
- else if (node.nodeName == "BR" &amp;&amp; node.childNodes.length == 0) {
- leaving = true;
- result.push(node);
- }
- else {
- forEach(node.childNodes, simplifyNode);
- if (!leaving &amp;&amp; newlineElements.hasOwnProperty(node.nodeName)) {
- leaving = true;
- result.push(doc.createElement("BR"));
- }
- }
- }
-
- simplifyNode(root);
- return result;
- }
-
- // Creates a MochiKit-style iterator that goes over a series of DOM
- // nodes. The values it yields are strings, the textual content of
- // the nodes. It makes sure that all nodes up to and including the
- // one whose text is being yielded have been 'normalized' to be just
- // &lt;span> and &lt;br> elements.
- // See the story.html file for some short remarks about the use of
- // continuation-passing style in this iterator.
- function traverseDOM(start){
- function yield(value, c){cc = c; return value;}
- function push(fun, arg, c){return function(){return fun(arg, c);};}
- function stop(){cc = stop; throw StopIteration;};
- var cc = push(scanNode, start, stop);
- var owner = start.ownerDocument;
- var nodeQueue = [];
-
- // Create a function that can be used to insert nodes after the
- // one given as argument.
- function pointAt(node){
- var parent = node.parentNode;
- var next = node.nextSibling;
- return function(newnode) {
- parent.insertBefore(newnode, next);
- };
- }
- var point = null;
-
- // Insert a normalized node at the current point. If it is a text
- // node, wrap it in a &lt;span>, and give that span a currentText
- // property -- this is used to cache the nodeValue, because
- // directly accessing nodeValue is horribly slow on some browsers.
- // The dirty property is used by the highlighter to determine
- // which parts of the document have to be re-highlighted.
- function insertPart(part){
- var text = "\n";
- if (part.nodeType == 3) {
- select.snapshotChanged();
- part = makePartSpan(part, owner);
- text = part.currentText;
- }
- part.dirty = true;
- nodeQueue.push(part);
- point(part);
- return text;
- }
-
- // Extract the text and newlines from a DOM node, insert them into
- // the document, and yield the textual content. Used to replace
- // non-normalized nodes.
- function writeNode(node, c){
- var toYield = [];
- forEach(simplifyDOM(node), function(part) {
- toYield.push(insertPart(part));
- });
- return yield(toYield.join(""), c);
- }
-
- // Check whether a node is a normalized &lt;span> element.
- function partNode(node){
- if (node.isPart &amp;&amp; node.childNodes.length == 1 &amp;&amp; node.firstChild.nodeType == 3) {
- node.currentText = node.firstChild.nodeValue;
- return !/[\n\t\r]/.test(node.currentText);
- }
- return false;
- }
-
- // Handle a node. Add its successor to the continuation if there
- // is one, find out whether the node is normalized. If it is,
- // yield its content, otherwise, normalize it (writeNode will take
- // care of yielding).
- function scanNode(node, c){
- if (node.nextSibling)
- c = push(scanNode, node.nextSibling, c);
-
- if (partNode(node)){
- nodeQueue.push(node);
- return yield(node.currentText, c);
- }
- else if (node.nodeName == "BR") {
- nodeQueue.push(node);
- return yield("\n", c);
- }
- else {
- point = pointAt(node);
- removeElement(node);
- return writeNode(node, c);
- }
- }
-
- // MochiKit iterators are objects with a next function that
- // returns the next value or throws StopIteration when there are
- // no more values.
- return {next: function(){return cc();}, nodes: nodeQueue};
- }
-
- // Determine the text size of a processed node.
- function nodeSize(node) {
- if (node.nodeName == "BR")
- return 1;
- else
- return node.currentText.length;
- }
-
- // Search backwards through the top-level nodes until the next BR or
- // the start of the frame.
- function startOfLine(node) {
- while (node &amp;&amp; node.nodeName != "BR") node = node.previousSibling;
- return node;
- }
- function endOfLine(node, container) {
- if (!node) node = container.firstChild;
- else if (node.nodeName == "BR") node = node.nextSibling;
-
- while (node &amp;&amp; node.nodeName != "BR") node = node.nextSibling;
- return node;
- }
-
- // Replace all DOM nodes in the current selection with new ones.
- // Needed to prevent issues in IE where the old DOM nodes can be
- // pasted back into the document, still holding their old undo
- // information.
- function scrubPasted(container, start, start2) {
- var end = select.selectionTopNode(container, true),
- doc = container.ownerDocument;
- if (start != null &amp;&amp; start.parentNode != container) start = start2;
- if (start === false) start = null;
- if (start == end || !end || !container.firstChild) return;
-
- var clear = traverseDOM(start ? start.nextSibling : container.firstChild);
- while (end.parentNode == container) try{clear.next();}catch(e){break;}
- forEach(clear.nodes, function(node) {
- var newNode = node.nodeName == "BR" ? doc.createElement("BR") : makePartSpan(node.currentText, doc);
- container.replaceChild(newNode, node);
- });
- }
-
- // Client interface for searching the content of the editor. Create
- // these by calling CodeMirror.getSearchCursor. To use, call
- // findNext on the resulting object -- this returns a boolean
- // indicating whether anything was found, and can be called again to
- // skip to the next find. Use the select and replace methods to
- // actually do something with the found locations.
- function SearchCursor(editor, string, fromCursor) {
- this.editor = editor;
- this.history = editor.history;
- this.history.commit();
-
- // Are we currently at an occurrence of the search string?
- this.atOccurrence = false;
- // The object stores a set of nodes coming after its current
- // position, so that when the current point is taken out of the
- // DOM tree, we can still try to continue.
- this.fallbackSize = 15;
- var cursor;
- // Start from the cursor when specified and a cursor can be found.
- if (fromCursor &amp;&amp; (cursor = select.cursorPos(this.editor.container))) {
- this.line = cursor.node;
- this.offset = cursor.offset;
- }
- else {
- this.line = null;
- this.offset = 0;
- }
- this.valid = !!string;
-
- // Create a matcher function based on the kind of string we have.
- var target = string.split("\n"), self = this;;
- this.matches = (target.length == 1) ?
- // For one-line strings, searching can be done simply by calling
- // indexOf on the current line.
- function() {
- var match = cleanText(self.history.textAfter(self.line).slice(self.offset)).indexOf(string);
- if (match > -1)
- return {from: {node: self.line, offset: self.offset + match},
- to: {node: self.line, offset: self.offset + match + string.length}};
- } :
- // Multi-line strings require internal iteration over lines, and
- // some clunky checks to make sure the first match ends at the
- // end of the line and the last match starts at the start.
- function() {
- var firstLine = cleanText(self.history.textAfter(self.line).slice(self.offset));
- var match = firstLine.lastIndexOf(target[0]);
- if (match == -1 || match != firstLine.length - target[0].length)
- return false;
- var startOffset = self.offset + match;
-
- var line = self.history.nodeAfter(self.line);
- for (var i = 1; i &lt; target.length - 1; i++) {
- if (cleanText(self.history.textAfter(line)) != target[i])
- return false;
- line = self.history.nodeAfter(line);
- }
-
- if (cleanText(self.history.textAfter(line)).indexOf(target[target.length - 1]) != 0)
- return false;
-
- return {from: {node: self.line, offset: startOffset},
- to: {node: line, offset: target[target.length - 1].length}};
- };
- }
-
- SearchCursor.prototype = {
- findNext: function() {
- if (!this.valid) return false;
- this.atOccurrence = false;
- var self = this;
-
- // Go back to the start of the document if the current line is
- // no longer in the DOM tree.
- if (this.line &amp;&amp; !this.line.parentNode) {
- this.line = null;
- this.offset = 0;
- }
-
- // Set the cursor's position one character after the given
- // position.
- function saveAfter(pos) {
- if (self.history.textAfter(pos.node).length &lt; pos.offset) {
- self.line = pos.node;
- self.offset = pos.offset + 1;
- }
- else {
- self.line = self.history.nodeAfter(pos.node);
- self.offset = 0;
- }
- }
-
- while (true) {
- var match = this.matches();
- // Found the search string.
- if (match) {
- this.atOccurrence = match;
- saveAfter(match.from);
- return true;
- }
- this.line = this.history.nodeAfter(this.line);
- this.offset = 0;
- // End of document.
- if (!this.line) {
- this.valid = false;
- return false;
- }
- }
- },
-
- select: function() {
- if (this.atOccurrence) {
- select.setCursorPos(this.editor.container, this.atOccurrence.from, this.atOccurrence.to);
- select.scrollToCursor(this.editor.container);
- }
- },
-
- replace: function(string) {
- if (this.atOccurrence) {
- var end = this.editor.replaceRange(this.atOccurrence.from, this.atOccurrence.to, string);
- this.line = end.node;
- this.offset = end.offset;
- this.atOccurrence = false;
- }
- }
- };
-
- // The Editor object is the main inside-the-iframe interface.
- function Editor(options) {
- this.options = options;
- window.indentUnit = options.indentUnit;
- this.parent = parent;
- this.doc = document;
- var container = this.container = this.doc.body;
- this.win = window;
- this.history = new History(container, options.undoDepth, options.undoDelay,
- this, options.onChange);
- var self = this;
-
- if (!Editor.Parser)
- throw "No parser loaded.";
- if (options.parserConfig &amp;&amp; Editor.Parser.configure)
- Editor.Parser.configure(options.parserConfig);
-
- if (!options.readOnly)
- select.setCursorPos(container, {node: null, offset: 0});
-
- this.dirty = [];
- if (options.content)
- this.importCode(options.content);
- else // FF acts weird when the editable document is completely empty
- container.appendChild(this.doc.createElement("BR"));
-
- if (!options.readOnly) {
- if (options.continuousScanning !== false) {
- this.scanner = this.documentScanner(options.linesPerPass);
- this.delayScanning();
- }
-
- function setEditable() {
- // In IE, designMode frames can not run any scripts, so we use
- // contentEditable instead.
- if (document.body.contentEditable != undefined &amp;&amp; internetExplorer)
- document.body.contentEditable = "true";
- else
- document.designMode = "on";
-
- document.documentElement.style.borderWidth = "0";
- if (!options.textWrapping)
- container.style.whiteSpace = "nowrap";
- }
-
- // If setting the frame editable fails, try again when the user
- // focus it (happens when the frame is not visible on
- // initialisation, in Firefox).
- try {
- setEditable();
- }
- catch(e) {
- var focusEvent = addEventHandler(document, "focus", function() {
- focusEvent();
- setEditable();
- }, true);
- }
-
- addEventHandler(document, "keydown", method(this, "keyDown"));
- addEventHandler(document, "keypress", method(this, "keyPress"));
- addEventHandler(document, "keyup", method(this, "keyUp"));
-
- function cursorActivity() {self.cursorActivity(false);}
- addEventHandler(document.body, "mouseup", cursorActivity);
- addEventHandler(document.body, "paste", function(event) {
- cursorActivity();
- if (internetExplorer) {
- var text = null;
- try {text = window.clipboardData.getData("Text");}catch(e){}
- if (text != null) {
- self.replaceSelection(text);
- event.stop();
- }
- else {
- var start = select.selectionTopNode(self.container, true),
- start2 = start &amp;&amp; start.previousSibling;
- setTimeout(function(){scrubPasted(self.container, start, start2);}, 0);
- }
- }
- });
- addEventHandler(document.body, "cut", cursorActivity);
-
- if (this.options.autoMatchParens)
- addEventHandler(document.body, "click", method(this, "scheduleParenBlink"));
- }
- }
-
- function isSafeKey(code) {
- return (code >= 16 &amp;&amp; code &lt;= 18) || // shift, control, alt
- (code >= 33 &amp;&amp; code &lt;= 40); // arrows, home, end
- }
-
- Editor.prototype = {
- // Import a piece of code into the editor.
- importCode: function(code) {
- this.history.push(null, null, asEditorLines(code));
- this.history.reset();
- },
-
- // Extract the code from the editor.
- getCode: function() {
- if (!this.container.firstChild)
- return "";
-
- var accum = [];
- select.markSelection(this.win);
- forEach(traverseDOM(this.container.firstChild), method(accum, "push"));
- webkitLastLineHack(this.container);
- select.selectMarked();
- return cleanText(accum.join(""));
- },
-
- checkLine: function(node) {
- if (node === false || !(node == null || node.parentNode == this.container))
- throw parent.CodeMirror.InvalidLineHandle;
- },
-
- cursorPosition: function(start) {
- if (start == null) start = true;
- var pos = select.cursorPos(this.container, start);
- if (pos) return {line: pos.node, character: pos.offset};
- else return {line: null, character: 0};
- },
-
- firstLine: function() {
- return null;
- },
-
- lastLine: function() {
- if (this.container.lastChild) return startOfLine(this.container.lastChild);
- else return null;
- },
-
- nextLine: function(line) {
- this.checkLine(line);
- var end = endOfLine(line, this.container);
- return end || false;
- },
-
- prevLine: function(line) {
- this.checkLine(line);
- if (line == null) return false;
- return startOfLine(line.previousSibling);
- },
-
- selectLines: function(startLine, startOffset, endLine, endOffset) {
- this.checkLine(startLine);
- var start = {node: startLine, offset: startOffset}, end = null;
- if (endOffset !== undefined) {
- this.checkLine(endLine);
- end = {node: endLine, offset: endOffset};
- }
- select.setCursorPos(this.container, start, end);
- select.scrollToCursor(this.container);
- },
-
- lineContent: function(line) {
- this.checkLine(line);
- var accum = [];
- for (line = line ? line.nextSibling : this.container.firstChild;
- line &amp;&amp; line.nodeName != "BR"; line = line.nextSibling)
- accum.push(nodeText(line));
- return cleanText(accum.join(""));
- },
-
- setLineContent: function(line, content) {
- this.history.commit();
- this.replaceRange({node: line, offset: 0},
- {node: line, offset: this.history.textAfter(line).length},
- content);
- this.addDirtyNode(line);
- this.scheduleHighlight();
- },
-
- insertIntoLine: function(line, position, content) {
- var before = null;
- if (position == "end") {
- before = endOfLine(line, this.container);
- }
- else {
- for (var cur = line ? line.nextSibling : this.container.firstChild; cur; cur = cur.nextSibling) {
- if (position == 0) {
- before = cur;
- break;
- }
- var text = (cur.innerText || cur.textContent || cur.nodeValue || "");
- if (text.length > position) {
- before = cur.nextSibling;
- content = text.slice(0, position) + content + text.slice(position);
- removeElement(cur);
- break;
- }
- position -= text.length;
- }
- }
-
- var lines = asEditorLines(content), doc = this.container.ownerDocument;
- for (var i = 0; i &lt; lines.length; i++) {
- if (i > 0) this.container.insertBefore(doc.createElement("BR"), before);
- this.container.insertBefore(makePartSpan(lines[i], doc), before);
- }
- this.addDirtyNode(line);
- this.scheduleHighlight();
- },
-
- // Retrieve the selected text.
- selectedText: function() {
- var h = this.history;
- h.commit();
-
- var start = select.cursorPos(this.container, true),
- end = select.cursorPos(this.container, false);
- if (!start || !end) return "";
-
- if (start.node == end.node)
- return h.textAfter(start.node).slice(start.offset, end.offset);
-
- var text = [h.textAfter(start.node).slice(start.offset)];
- for (pos = h.nodeAfter(start.node); pos != end.node; pos = h.nodeAfter(pos))
- text.push(h.textAfter(pos));
- text.push(h.textAfter(end.node).slice(0, end.offset));
- return cleanText(text.join("\n"));
- },
-
- // Replace the selection with another piece of text.
- replaceSelection: function(text) {
- this.history.commit();
- var start = select.cursorPos(this.container, true),
- end = select.cursorPos(this.container, false);
- if (!start || !end) return;
-
- end = this.replaceRange(start, end, text);
- select.setCursorPos(this.container, start, end);
- },
-
- replaceRange: function(from, to, text) {
- var lines = asEditorLines(text);
- lines[0] = this.history.textAfter(from.node).slice(0, from.offset) + lines[0];
- var lastLine = lines[lines.length - 1];
- lines[lines.length - 1] = lastLine + this.history.textAfter(to.node).slice(to.offset);
- var end = this.history.nodeAfter(to.node);
- this.history.push(from.node, end, lines);
- return {node: this.history.nodeBefore(end),
- offset: lastLine.length};
- },
-
- getSearchCursor: function(string, fromCursor) {
- return new SearchCursor(this, string, fromCursor);
- },
-
- // Re-indent the whole buffer
- reindent: function() {
- if (this.container.firstChild)
- this.indentRegion(null, this.container.lastChild);
- },
-
- grabKeys: function(eventHandler, filter) {
- this.frozen = eventHandler;
- this.keyFilter = filter;
- },
- ungrabKeys: function() {
- this.frozen = "leave";
- this.keyFilter = null;
- },
-
- // Intercept enter and tab, and assign their new functions.
- keyDown: function(event) {
- if (this.frozen == "leave") this.frozen = null;
- if (this.frozen &amp;&amp; (!this.keyFilter || this.keyFilter(event.keyCode))) {
- event.stop();
- this.frozen(event);
- return;
- }
-
- var code = event.keyCode;
- // Don't scan when the user is typing.
- this.delayScanning();
- // Schedule a paren-highlight event, if configured.
- if (this.options.autoMatchParens)
- this.scheduleParenBlink();
-
- if (code == 13) { // enter
- if (event.ctrlKey) {
- this.reparseBuffer();
- }
- else {
- select.insertNewlineAtCursor(this.win);
- this.indentAtCursor();
- select.scrollToCursor(this.container);
- }
- event.stop();
- }
- else if (code == 9 &amp;&amp; this.options.tabMode != "default") { // tab
- this.handleTab(!event.ctrlKey &amp;&amp; !event.shiftKey);
- event.stop();
- }
- else if (code == 32 &amp;&amp; event.shiftKey &amp;&amp; this.options.tabMode == "default") { // space
- this.handleTab(true);
- event.stop();
- }
- else if ((code == 219 || code == 221) &amp;&amp; event.ctrlKey) {
- this.blinkParens(event.shiftKey);
- event.stop();
- }
- else if (event.metaKey &amp;&amp; (code == 37 || code == 39)) { // Meta-left/right
- var cursor = select.selectionTopNode(this.container);
- if (cursor === false || !this.container.firstChild) return;
-
- if (code == 37) select.focusAfterNode(startOfLine(cursor), this.container);
- else {
- end = endOfLine(cursor, this.container);
- select.focusAfterNode(end ? end.previousSibling : this.container.lastChild, this.container);
- }
- event.stop();
- }
- else if (event.ctrlKey || event.metaKey) {
- if ((event.shiftKey &amp;&amp; code == 90) || code == 89) { // shift-Z, Y
- select.scrollToNode(this.history.redo());
- event.stop();
- }
- else if (code == 90 || code == 8) { // Z, backspace
- select.scrollToNode(this.history.undo());
- event.stop();
- }
- else if (code == 83 &amp;&amp; this.options.saveFunction) { // S
- this.options.saveFunction();
- event.stop();
- }
- }
- },
-
- // Check for characters that should re-indent the current line,
- // and prevent Opera from handling enter and tab anyway.
- keyPress: function(event) {
- var electric = /indent|default/.test(this.options.tabMode) &amp;&amp; Editor.Parser.electricChars;
- // Hack for Opera, and Firefox on OS X, in which stopping a
- // keydown event does not prevent the associated keypress event
- // from happening, so we have to cancel enter and tab again
- // here.
- if ((this.frozen &amp;&amp; (!this.keyFilter || this.keyFilter(event.keyCode))) ||
- event.code == 13 || (event.code == 9 &amp;&amp; this.options.tabMode != "default") ||
- (event.keyCode == 32 &amp;&amp; event.shiftKey &amp;&amp; this.options.tabMode == "default"))
- event.stop();
- else if (electric &amp;&amp; electric.indexOf(event.character) != -1)
- this.parent.setTimeout(method(this, "indentAtCursor"), 0);
- },
-
- // Mark the node at the cursor dirty when a non-safe key is
- // released.
- keyUp: function(event) {
- this.cursorActivity(isSafeKey(event.keyCode));
- },
-
- // Indent the line following a given &lt;br>, or null for the first
- // line. If given a &lt;br> element, this must have been highlighted
- // so that it has an indentation method. Returns the whitespace
- // element that has been modified or created (if any).
- indentLineAfter: function(start, direction) {
- // whiteSpace is the whitespace span at the start of the line,
- // or null if there is no such node.
- var whiteSpace = start ? start.nextSibling : this.container.firstChild;
- if (whiteSpace &amp;&amp; !hasClass(whiteSpace, "whitespace"))
- whiteSpace = null;
-
- // Sometimes the start of the line can influence the correct
- // indentation, so we retrieve it.
- var firstText = whiteSpace ? whiteSpace.nextSibling : (start ? start.nextSibling : this.container.firstChild);
- var nextChars = (start &amp;&amp; firstText &amp;&amp; firstText.currentText) ? firstText.currentText : "";
-
- // Ask the lexical context for the correct indentation, and
- // compute how much this differs from the current indentation.
- var newIndent = 0, curIndent = whiteSpace ? whiteSpace.currentText.length : 0;
- if (direction != null &amp;&amp; this.options.tabMode == "shift")
- newIndent = direction ? curIndent + indentUnit : Math.max(0, curIndent - indentUnit)
- else if (start)
- newIndent = start.indentation(nextChars, curIndent, direction);
- else if (Editor.Parser.firstIndentation)
- newIndent = Editor.Parser.firstIndentation(nextChars, curIndent, direction);
- var indentDiff = newIndent - curIndent;
-
- // If there is too much, this is just a matter of shrinking a span.
- if (indentDiff &lt; 0) {
- if (newIndent == 0) {
- if (firstText) select.snapshotMove(whiteSpace.firstChild, firstText.firstChild, 0);
- removeElement(whiteSpace);
- whiteSpace = null;
- }
- else {
- select.snapshotMove(whiteSpace.firstChild, whiteSpace.firstChild, indentDiff, true);
- whiteSpace.currentText = makeWhiteSpace(newIndent);
- whiteSpace.firstChild.nodeValue = whiteSpace.currentText;
- }
- }
- // Not enough...
- else if (indentDiff > 0) {
- // If there is whitespace, we grow it.
- if (whiteSpace) {
- whiteSpace.currentText = makeWhiteSpace(newIndent);
- whiteSpace.firstChild.nodeValue = whiteSpace.currentText;
- }
- // Otherwise, we have to add a new whitespace node.
- else {
- whiteSpace = makePartSpan(makeWhiteSpace(newIndent), this.doc);
- whiteSpace.className = "whitespace";
- if (start) insertAfter(whiteSpace, start);
- else this.container.insertBefore(whiteSpace, this.container.firstChild);
- }
- if (firstText) select.snapshotMove(firstText.firstChild, whiteSpace.firstChild, curIndent, false, true);
- }
- if (indentDiff != 0) this.addDirtyNode(start);
- return whiteSpace;
- },
-
- // Re-highlight the selected part of the document.
- highlightAtCursor: function() {
- var pos = select.selectionTopNode(this.container, true);
- var to = select.selectionTopNode(this.container, false);
- if (pos === false || to === false) return;
-
- select.markSelection(this.win);
- if (this.highlight(pos, endOfLine(to, this.container), true, 20) === false)
- return false;
- select.selectMarked();
- return true;
- },
-
- // When tab is pressed with text selected, the whole selection is
- // re-indented, when nothing is selected, the line with the cursor
- // is re-indented.
- handleTab: function(direction) {
- if (this.options.tabMode == "spaces") {
- select.insertTabAtCursor(this.win);
- }
- else if (!select.somethingSelected(this.win)) {
- this.indentAtCursor(direction);
- }
- else {
- var start = select.selectionTopNode(this.container, true),
- end = select.selectionTopNode(this.container, false);
- if (start === false || end === false) return;
- this.indentRegion(start, end, direction);
- }
- },
-
- // Delay (or initiate) the next paren blink event.
- scheduleParenBlink: function() {
- if (this.parenEvent) this.parent.clearTimeout(this.parenEvent);
- var self = this;
- this.parenEvent = this.parent.setTimeout(function(){self.blinkParens();}, 300);
- },
-
- // Take the token before the cursor. If it contains a character in
- // '()[]{}', search for the matching paren/brace/bracket, and
- // highlight them in green for a moment, or red if no proper match
- // was found.
- blinkParens: function(jump) {
- // Clear the event property.
- if (this.parenEvent) this.parent.clearTimeout(this.parenEvent);
- this.parenEvent = null;
-
- // Extract a 'paren' from a piece of text.
- function paren(node) {
- if (node.currentText) {
- var match = node.currentText.match(/^[\s\u00a0]*([\(\)\[\]{}])[\s\u00a0]*$/);
- return match &amp;&amp; match[1];
- }
- }
- // Determine the direction a paren is facing.
- function forward(ch) {
- return /[\(\[\{]/.test(ch);
- }
-
- var ch, self = this, cursor = select.selectionTopNode(this.container, true);
- if (!cursor || !this.highlightAtCursor()) return;
- cursor = select.selectionTopNode(this.container, true);
- if (!(cursor &amp;&amp; ((ch = paren(cursor)) || (cursor = cursor.nextSibling) &amp;&amp; (ch = paren(cursor)))))
- return;
- // We only look for tokens with the same className.
- var className = cursor.className, dir = forward(ch), match = matching[ch];
-
- // Since parts of the document might not have been properly
- // highlighted, and it is hard to know in advance which part we
- // have to scan, we just try, and when we find dirty nodes we
- // abort, parse them, and re-try.
- function tryFindMatch() {
- var stack = [], ch, ok = true;;
- for (var runner = cursor; runner; runner = dir ? runner.nextSibling : runner.previousSibling) {
- if (runner.className == className &amp;&amp; runner.nodeName == "SPAN" &amp;&amp; (ch = paren(runner))) {
- if (forward(ch) == dir)
- stack.push(ch);
- else if (!stack.length)
- ok = false;
- else if (stack.pop() != matching[ch])
- ok = false;
- if (!stack.length) break;
- }
- else if (runner.dirty || runner.nodeName != "SPAN" &amp;&amp; runner.nodeName != "BR") {
- return {node: runner, status: "dirty"};
- }
- }
- return {node: runner, status: runner &amp;&amp; ok};
- }
- // Temporarily give the relevant nodes a colour.
- function blink(node, ok) {
- node.style.fontWeight = "bold";
- node.style.color = ok ? "#8F8" : "#F88";
- self.parent.setTimeout(function() {node.style.fontWeight = ""; node.style.color = "";}, 500);
- }
-
- while (true) {
- var found = tryFindMatch();
- if (found.status == "dirty") {
- this.highlight(found.node, 1);
- // Needed because in some corner cases a highlight does not
- // reach a node.
- found.node.dirty = false;
- continue;
- }
- else {
- blink(cursor, found.status);
- if (found.node) {
- blink(found.node, found.status);
- if (jump) select.focusAfterNode(found.node.previousSibling, this.container);
- }
- break;
- }
- }
- },
-
- // Adjust the amount of whitespace at the start of the line that
- // the cursor is on so that it is indented properly.
- indentAtCursor: function(direction) {
- if (!this.container.firstChild) return;
- // The line has to have up-to-date lexical information, so we
- // highlight it first.
- if (!this.highlightAtCursor()) return;
- var cursor = select.selectionTopNode(this.container, false);
- // If we couldn't determine the place of the cursor,
- // there's nothing to indent.
- if (cursor === false)
- return;
- var lineStart = startOfLine(cursor);
- var whiteSpace = this.indentLineAfter(lineStart, direction);
- if (cursor == lineStart &amp;&amp; whiteSpace)
- cursor = whiteSpace;
- // This means the indentation has probably messed up the cursor.
- if (cursor == whiteSpace)
- select.focusAfterNode(cursor, this.container);
- },
-
- // Indent all lines whose start falls inside of the current
- // selection.
- indentRegion: function(start, end, direction) {
- var current = (start = startOfLine(start)), before = start &amp;&amp; startOfLine(start.previousSibling);
- if (end.nodeName != "BR") end = endOfLine(end, this.container);
-
- do {
- if (current) this.highlight(before, current, true);
- this.indentLineAfter(current, direction);
- before = current;
- current = endOfLine(current, this.container);
- } while (current != end);
- select.setCursorPos(this.container, {node: start, offset: 0}, {node: end, offset: 0});
- },
-
- // Find the node that the cursor is in, mark it as dirty, and make
- // sure a highlight pass is scheduled.
- cursorActivity: function(safe) {
- if (internetExplorer) {
- this.container.createTextRange().execCommand("unlink");
- this.selectionSnapshot = select.selectionCoords(this.win);
- }
-
- var activity = this.options.cursorActivity;
- if (!safe || activity) {
- var cursor = select.selectionTopNode(this.container, false);
- if (cursor === false || !this.container.firstChild) return;
- cursor = cursor || this.container.firstChild;
- if (activity) activity(cursor);
- if (!safe) {
- this.scheduleHighlight();
- this.addDirtyNode(cursor);
- }
- }
- },
-
- reparseBuffer: function() {
- forEach(this.container.childNodes, function(node) {node.dirty = true;});
- if (this.container.firstChild)
- this.addDirtyNode(this.container.firstChild);
- },
-
- // Add a node to the set of dirty nodes, if it isn't already in
- // there.
- addDirtyNode: function(node) {
- node = node || this.container.firstChild;
- if (!node) return;
-
- for (var i = 0; i &lt; this.dirty.length; i++)
- if (this.dirty[i] == node) return;
-
- if (node.nodeType != 3)
- node.dirty = true;
- this.dirty.push(node);
- },
-
- // Cause a highlight pass to happen in options.passDelay
- // milliseconds. Clear the existing timeout, if one exists. This
- // way, the passes do not happen while the user is typing, and
- // should as unobtrusive as possible.
- scheduleHighlight: function() {
- // Timeouts are routed through the parent window, because on
- // some browsers designMode windows do not fire timeouts.
- var self = this;
- this.parent.clearTimeout(this.highlightTimeout);
- this.highlightTimeout = this.parent.setTimeout(function(){self.highlightDirty();}, this.options.passDelay);
- },
-
- // Fetch one dirty node, and remove it from the dirty set.
- getDirtyNode: function() {
- while (this.dirty.length > 0) {
- var found = this.dirty.pop();
- // IE8 sometimes throws an unexplainable 'invalid argument'
- // exception for found.parentNode
- try {
- // If the node has been coloured in the meantime, or is no
- // longer in the document, it should not be returned.
- while (found &amp;&amp; found.parentNode != this.container)
- found = found.parentNode
- if (found &amp;&amp; (found.dirty || found.nodeType == 3))
- return found;
- } catch (e) {}
- }
- return null;
- },
-
- // Pick dirty nodes, and highlight them, until
- // options.linesPerPass lines have been highlighted. The highlight
- // method will continue to next lines as long as it finds dirty
- // nodes. It returns an object indicating the amount of lines
- // left, and information about the place where it stopped. If
- // there are dirty nodes left after this function has spent all
- // its lines, it shedules another highlight to finish the job.
- highlightDirty: function(force) {
- // Prevent FF from raising an error when it is firing timeouts
- // on a page that's no longer loaded.
- if (!window.select) return;
-
- var lines = force ? Infinity : this.options.linesPerPass;
- if (!this.options.readOnly) select.markSelection(this.win);
- var start;
- while (lines > 0 &amp;&amp; (start = this.getDirtyNode())){
- var result = this.highlight(start, lines);
- if (result) {
- lines = result.left;
- if (result.node &amp;&amp; result.dirty)
- this.addDirtyNode(result.node);
- }
- }
- if (!this.options.readOnly) select.selectMarked();
- if (start)
- this.scheduleHighlight();
- return this.dirty.length == 0;
- },
-
- // Creates a function that, when called through a timeout, will
- // continuously re-parse the document.
- documentScanner: function(linesPer) {
- var self = this, pos = null;
- return function() {
- // If the current node is no longer in the document... oh
- // well, we start over.
- if (pos &amp;&amp; pos.parentNode != self.container)
- pos = null;
- select.markSelection(self.win);
- var result = self.highlight(pos, linesPer, true);
- select.selectMarked();
- var newPos = result ? (result.node &amp;&amp; result.node.nextSibling) : null;
- pos = (pos == newPos) ? null : newPos;
- self.delayScanning();
- };
- },
-
- // Starts the continuous scanning process for this document after
- // a given interval.
- delayScanning: function() {
- if (this.scanner) {
- this.parent.clearTimeout(this.documentScan);
- this.documentScan = this.parent.setTimeout(this.scanner, this.options.continuousScanning);
- }
- },
-
- // The function that does the actual highlighting/colouring (with
- // help from the parser and the DOM normalizer). Its interface is
- // rather overcomplicated, because it is used in different
- // situations: ensuring that a certain line is highlighted, or
- // highlighting up to X lines starting from a certain point. The
- // 'from' argument gives the node at which it should start. If
- // this is null, it will start at the beginning of the document.
- // When a number of lines is given with the 'target' argument, it
- // will highlight no more than that amount of lines. If this
- // argument holds a DOM node, it will highlight until it reaches
- // that node. If at any time it comes across a 'clean' line (no
- // dirty nodes), it will stop, except when 'cleanLines' is true.
- highlight: function(from, target, cleanLines, maxBacktrack){
- var container = this.container, self = this, active = this.options.activeTokens;
- var lines = (typeof target == "number" ? target : null);
-
- if (!container.firstChild)
- return;
- // Backtrack to the first node before from that has a partial
- // parse stored.
- while (from &amp;&amp; (!from.parserFromHere || from.dirty)) {
- from = from.previousSibling;
- if (maxBacktrack != null &amp;&amp; from.nodeName == "BR" &amp;&amp; (--maxBacktrack) &lt; 0)
- return false;
- }
- // If we are at the end of the document, do nothing.
- if (from &amp;&amp; !from.nextSibling)
- return;
-
- // Check whether a part (&lt;span> node) and the corresponding token
- // match.
- function correctPart(token, part){
- return !part.reduced &amp;&amp; part.currentText == token.value &amp;&amp; part.className == token.style;
- }
- // Shorten the text associated with a part by chopping off
- // characters from the front. Note that only the currentText
- // property gets changed. For efficiency reasons, we leave the
- // nodeValue alone -- we set the reduced flag to indicate that
- // this part must be replaced.
- function shortenPart(part, minus){
- part.currentText = part.currentText.substring(minus);
- part.reduced = true;
- }
- // Create a part corresponding to a given token.
- function tokenPart(token){
- var part = makePartSpan(token.value, self.doc);
- part.className = token.style;
- return part;
- }
-
- function maybeTouch(node) {
- if (node) {
- if (node.nextSibling != node.oldNextSibling) {
- self.history.touch(node);
- node.oldNextSibling = node.nextSibling;
- }
- }
- else {
- if (self.container.firstChild != self.container.oldFirstChild) {
- self.history.touch(node);
- self.container.oldFirstChild = self.container.firstChild;
- }
- }
- }
-
- // Get the token stream. If from is null, we start with a new
- // parser from the start of the frame, otherwise a partial parse
- // is resumed.
- var traversal = traverseDOM(from ? from.nextSibling : container.firstChild),
- stream = stringStream(traversal),
- parsed = from ? from.parserFromHere(stream) : Editor.Parser.make(stream);
-
- // parts is an interface to make it possible to 'delay' fetching
- // the next DOM node until we are completely done with the one
- // before it. This is necessary because often the next node is
- // not yet available when we want to proceed past the current
- // one.
- var parts = {
- current: null,
- // Fetch current node.
- get: function(){
- if (!this.current)
- this.current = traversal.nodes.shift();
- return this.current;
- },
- // Advance to the next part (do not fetch it yet).
- next: function(){
- this.current = null;
- },
- // Remove the current part from the DOM tree, and move to the
- // next.
- remove: function(){
- container.removeChild(this.get());
- this.current = null;
- },
- // Advance to the next part that is not empty, discarding empty
- // parts.
- getNonEmpty: function(){
- var part = this.get();
- // Allow empty nodes when they are alone on a line, needed
- // for the FF cursor bug workaround (see select.js,
- // insertNewlineAtCursor).
- while (part &amp;&amp; part.nodeName == "SPAN" &amp;&amp; part.currentText == "") {
- var old = part;
- this.remove();
- part = this.get();
- // Adjust selection information, if any. See select.js for details.
- select.snapshotMove(old.firstChild, part &amp;&amp; (part.firstChild || part), 0);
- }
- return part;
- }
- };
-
- var lineDirty = false, prevLineDirty = true, lineNodes = 0;
-
- // This forEach loops over the tokens from the parsed stream, and
- // at the same time uses the parts object to proceed through the
- // corresponding DOM nodes.
- forEach(parsed, function(token){
- var part = parts.getNonEmpty();
-
- if (token.value == "\n"){
- // The idea of the two streams actually staying synchronized
- // is such a long shot that we explicitly check.
- if (part.nodeName != "BR")
- throw "Parser out of sync. Expected BR.";
-
- if (part.dirty || !part.indentation) lineDirty = true;
- maybeTouch(from);
- from = part;
-
- // Every &lt;br> gets a copy of the parser state and a lexical
- // context assigned to it. The first is used to be able to
- // later resume parsing from this point, the second is used
- // for indentation.
- part.parserFromHere = parsed.copy();
- part.indentation = token.indentation;
- part.dirty = false;
-
- // If the target argument wasn't an integer, go at least
- // until that node.
- if (lines == null &amp;&amp; part == target) throw StopIteration;
-
- // A clean line with more than one node means we are done.
- // Throwing a StopIteration is the way to break out of a
- // MochiKit forEach loop.
- if ((lines != null &amp;&amp; --lines &lt;= 0) || (!lineDirty &amp;&amp; !prevLineDirty &amp;&amp; lineNodes > 1 &amp;&amp; !cleanLines))
- throw StopIteration;
- prevLineDirty = lineDirty; lineDirty = false; lineNodes = 0;
- parts.next();
- }
- else {
- if (part.nodeName != "SPAN")
- throw "Parser out of sync. Expected SPAN.";
- if (part.dirty)
- lineDirty = true;
- lineNodes++;
-
- // If the part matches the token, we can leave it alone.
- if (correctPart(token, part)){
- part.dirty = false;
- parts.next();
- }
- // Otherwise, we have to fix it.
- else {
- lineDirty = true;
- // Insert the correct part.
- var newPart = tokenPart(token);
- container.insertBefore(newPart, part);
- if (active) active(newPart, token, self);
- var tokensize = token.value.length;
- var offset = 0;
- // Eat up parts until the text for this token has been
- // removed, adjusting the stored selection info (see
- // select.js) in the process.
- while (tokensize > 0) {
- part = parts.get();
- var partsize = part.currentText.length;
- select.snapshotReplaceNode(part.firstChild, newPart.firstChild, tokensize, offset);
- if (partsize > tokensize){
- shortenPart(part, tokensize);
- tokensize = 0;
- }
- else {
- tokensize -= partsize;
- offset += partsize;
- parts.remove();
- }
- }
- }
- }
- });
- maybeTouch(from);
- webkitLastLineHack(this.container);
-
- // The function returns some status information that is used by
- // hightlightDirty to determine whether and where it has to
- // continue.
- return {left: lines,
- node: parts.getNonEmpty(),
- dirty: lineDirty};
- }
- };
-
- return Editor;
-})();
-
- addEventHandler(window, "load", function() {
- var CodeMirror = window.frameElement.CodeMirror;
- CodeMirror.editor = new Editor(CodeMirror.options);
- this.parent.setTimeout(method(CodeMirror, "init"), 0);
- });
-</textarea>
-</div>
-
-<script type="text/javascript">
- var textarea = document.getElementById('code');
- var editor = new CodeMirror(CodeMirror.replace(textarea), {
- height: "750px",
- width: "100%",
- content: textarea.value,
- parserfile: ["tokenizejavascript.js", "parsejavascript.js"],
- stylesheet: "css/jscolors.css",
- path: "js/",
- autoMatchParens: true,
- initCallback: function(editor){editor.win.document.body.lastChild.scrollIntoView();}
- });
-</script>
-
- </body>
-</html>
diff --git a/media/CodeMirror-0.62/contrib/lua/LICENSE b/media/CodeMirror-0.62/contrib/lua/LICENSE
deleted file mode 100644
index 1af1908..0000000
--- a/media/CodeMirror-0.62/contrib/lua/LICENSE
+++ /dev/null
@@ -1,32 +0,0 @@
-Copyright (c) 2009, Franciszek Wawrzak
-All rights reserved.
-
-This software is provided for use in connection with the
-CodeMirror suite of modules and utilities, hosted and maintained
-at http://marijn.haverbeke.nl/codemirror/.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
- copyright notice, this list of conditions and the
- following disclaimer.
-
-* Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
diff --git a/media/CodeMirror-0.62/contrib/lua/css/luacolors.css b/media/CodeMirror-0.62/contrib/lua/css/luacolors.css
deleted file mode 100644
index 6df44b5..0000000
--- a/media/CodeMirror-0.62/contrib/lua/css/luacolors.css
+++ /dev/null
@@ -1,59 +0,0 @@
-.editbox {
- margin: .4em;
- padding: 0;
- font-family: monospace;
- font-size: 10pt;
- color: black;
-}
-
-pre.code, .editbox {
- color: #666666;
-}
-
-.editbox p {
- margin: 0;
-}
-
-span.lua-comment {
- color: #BB9977;
-}
-
-span.lua-keyword {
- font-weight: bold;
- color: blue;
-}
-
-span.lua-string {
- color: #AA2222;
-}
-
-span.lua-stdfunc {
- font-weight: bold;
- color: #077;
-}
-span.lua-customfunc {
- font-weight: bold;
- color: #0AA;
-}
-
-
-span.lua-identifier {
- color: black;
-}
-
-span.lua-number {
- color: #3A3;
-}
-
-span.lua-token {
- color: #151;
-}
-
-span.lua-error {
- color: #FFF;
- background-color: #F00;
-}
-
-
-
-
diff --git a/media/CodeMirror-0.62/contrib/lua/index.html b/media/CodeMirror-0.62/contrib/lua/index.html
deleted file mode 100644
index 03a3229..0000000
--- a/media/CodeMirror-0.62/contrib/lua/index.html
+++ /dev/null
@@ -1,68 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <script src="../../js/codemirror.js" type="text/javascript"></script>
- <title>CodeMirror: Lua demonstration</title>
- </head>
- <body style="padding: 20px;">
-
-<p>This page demonstrates <a href="../../index.html">CodeMirror</a>'s
-Lua parser. Written by <a href="http://francio.pl/">Franciszek
-Wawrzak</a>, released under a BSD-style <a
-href="LICENSE">license</a>.</p>
-
-<div style="border: 1px solid black; padding: 0px;">
-<textarea id="code" cols="120" rows="30">
---[[
-example useless code to show lua syntax highlighting
-this is multiline comment
-]]
-
-function blahblahblah(x)
-
- local table = {
- "asd" = 123,
- "x" = 0.34,
- }
- if x ~= 3 then
- print( x )
- elseif x == "string"
- my_custom_function( 0x34 )
- else
- unknown_function( "some string" )
- end
-
- --single line comment
-
-end
-
-function blablabla3()
-
- for k,v in ipairs( table ) do
- --abcde..
- y=[=[
- x=[[
- x is a multi line string
- ]]
- but its definition is iside a highest level string!
- ]=]
- print(" \"\" ")
- --this marks a parser error:
- s = [== asdasdasd]]
-
- s = math.sin( x )
- end
-
-end
-</textarea>
-</div>
-
-<script type="text/javascript">
- var editor = CodeMirror.fromTextArea('code', {
- height: "350px",
- parserfile: "../contrib/lua/js/parselua.js",
- stylesheet: "css/luacolors.css",
- path: "../../js/"
- });
-</script>
- </body>
-</html>
diff --git a/media/CodeMirror-0.62/contrib/lua/js/parselua.js b/media/CodeMirror-0.62/contrib/lua/js/parselua.js
deleted file mode 100644
index 2bc891b..0000000
--- a/media/CodeMirror-0.62/contrib/lua/js/parselua.js
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- Simple parser for LUA
- Written for Lua 5.1, based on parsecss and other parsers.
- features: highlights keywords, strings, comments (no leveling supported! ("[==[")),tokens, basic indenting
-
- to make this parser highlight your special functions pass table with this functions names to parserConfig argument of creator,
-
- parserConfig: ["myfunction1","myfunction2"],
- */
-
-
-function findFirstRegexp(words) {
- return new RegExp("^(?:" + words.join("|") + ")", "i");
-}
-
-function matchRegexp(words) {
- return new RegExp("^(?:" + words.join("|") + ")$", "i");
-}
-
-
-
-var luaCustomFunctions= matchRegexp([]);
-
-function configureLUA(parserConfig){
- if(parserConfig)
- luaCustomFunctions= matchRegexp(parserConfig);
-}
-
-
-//long list of standard functions from lua manual
-var luaStdFunctions = matchRegexp([
-"_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load","loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require","select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall",
-
-"coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield",
-
-"debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable","debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable","debug.setupvalue","debug.traceback",
-
-"close","flush","lines","read","seek","setvbuf","write",
-
-"io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin","io.stdout","io.tmpfile","io.type","io.write",
-
-"math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg","math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max","math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh","math.sqrt","math.tan","math.tanh",
-
-"os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale","os.time","os.tmpname",
-
-"package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload","package.seeall",
-
-"string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub","string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper",
-
-"table.concat","table.insert","table.maxn","table.remove","table.sort"
-]);
-
-
-
- var luaKeywords = matchRegexp(["and","break","elseif","false","nil","not","or","return",
- "true","function", "end", "if", "then", "else", "do",
- "while", "repeat", "until", "for", "in", "local" ]);
-
- var luaIndentKeys = matchRegexp(["function", "if","repeat","for","while", "[\(]", "{"]);
- var luaUnindentKeys = matchRegexp(["end", "until", "[\)]", "}"]);
-
- var luaUnindentKeys2 = findFirstRegexp(["end", "until", "[\)]", "}"]);
- var luaMiddleKeys = findFirstRegexp(["else","elseif"]);
-
-
-
-var LUAParser = Editor.Parser = (function() {
- var tokenizeLUA = (function() {
- function normal(source, setState) {
- var ch = source.next();
-
- if (ch == "-" && source.equals("-")) {
- source.next();
- setState(inSLComment);
- return null;
- }
- else if (ch == "\"" || ch == "'") {
- setState(inString(ch));
- return null;
- }
- if (ch == "[" && (source.equals("[") || source.equals("="))) {
- var level = 0;
- while(source.equals("=")){
- level ++;
- source.next();
- }
- if(! source.equals("[") )
- return "lua-error";
- setState(inMLSomething(level,"lua-string"));
- return null;
- }
-
- else if (ch == "=") {
- if (source.equals("="))
- source.next();
- return "lua-token";
- }
-
- else if (ch == ".") {
- if (source.equals("."))
- source.next();
- if (source.equals("."))
- source.next();
- return "lua-token";
- }
-
- else if (ch == "+" || ch == "-" || ch == "*" || ch == "/" || ch == "%" || ch == "^" || ch == "#" ) {
- return "lua-token";
- }
- else if (ch == ">" || ch == "<" || ch == "(" || ch == ")" || ch == "{" || ch == "}" || ch == "[" ) {
- return "lua-token";
- }
- else if (ch == "]" || ch == ";" || ch == ":" || ch == ",") {
- return "lua-token";
- }
- else if (source.equals("=") && (ch == "~" || ch == "<" || ch == ">")) {
- source.next();
- return "lua-token";
- }
-
- else if (/\d/.test(ch)) {
- source.nextWhileMatches(/[\w.%]/);
- return "lua-number";
- }
- else {
- source.nextWhileMatches(/[\w\\\-_.]/);
- return "lua-identifier";
- }
- }
-
-function inSLComment(source, setState) {
- var start = true;
- var count=0;
- while (!source.endOfLine()) {
- var ch = source.next();
- var level = 0;
- if ((ch =="[") && start)
- while(source.equals("=")){
- source.next();
- level++;
- }
- if (source.equals("[")){
- setState(inMLSomething(level,"lua-comment"));
- return null;
- }
- start = false;
- }
- setState(normal);
- return "lua-comment";
-
- }
-
- function inMLSomething(level,what) {
- //wat sholud be "lua-string" or "lua-comment", level is the number of "=" in opening mark.
- return function(source, setState){
- var dashes = 0;
- while (!source.endOfLine()) {
- var ch = source.next();
- if (dashes == level+1 && ch == "]" ) {
- setState(normal);
- break;
- }
- if (dashes == 0)
- dashes = (ch == "]") ? 1:0;
- else
- dashes = (ch == "=") ? dashes + 1 : 0;
- }
- return what;
- }
- }
-
-
- function inString(quote) {
- return function(source, setState) {
- var escaped = false;
- while (!source.endOfLine()) {
- var ch = source.next();
- if (ch == quote && !escaped)
- break;
- escaped = !escaped && ch == "\\";
- }
- if (!escaped)
- setState(normal);
- return "lua-string";
- };
- }
-
- return function(source, startState) {
- return tokenizer(source, startState || normal);
- };
- })();
-
- function indentLUA(indentDepth, base) {
- return function(nextChars) {
-
- var closing = (luaUnindentKeys2.test(nextChars) || luaMiddleKeys.test(nextChars));
-
-
- return base + ( indentUnit * (indentDepth - (closing?1:0)) );
- };
- }
-
-
-function parseLUA(source,basecolumn) {
- basecolumn = basecolumn || 0;
-
- var tokens = tokenizeLUA(source);
- var indentDepth = 0;
-
- var iter = {
- next: function() {
- var token = tokens.next(), style = token.style, content = token.content;
-
-
-
- if (style == "lua-identifier" && luaKeywords.test(content)){
- token.style = "lua-keyword";
- }
- if (style == "lua-identifier" && luaStdFunctions.test(content)){
- token.style = "lua-stdfunc";
- }
- if (style == "lua-identifier" && luaCustomFunctions.test(content)){
- token.style = "lua-customfunc";
- }
-
- if (luaIndentKeys.test(content))
- indentDepth++;
- else if (luaUnindentKeys.test(content))
- indentDepth--;
-
-
- if (content == "\n")
- token.indentation = indentLUA( indentDepth, basecolumn);
-
- return token;
- },
-
- copy: function() {
- var _tokenState = tokens.state, _indentDepth = indentDepth;
- return function(source) {
- tokens = tokenizeLUA(source, _tokenState);
-
- indentDepth = _indentDepth;
- return iter;
- };
- }
- };
- return iter;
- }
-
- return {make: parseLUA, configure:configureLUA, electricChars: "delf})"}; //en[d] els[e] unti[l] elsei[f] // this should be taken from Keys keywords
-})();
-
diff --git a/media/CodeMirror-0.62/contrib/php/LICENSE b/media/CodeMirror-0.62/contrib/php/LICENSE
deleted file mode 100644
index ce4c5e4..0000000
--- a/media/CodeMirror-0.62/contrib/php/LICENSE
+++ /dev/null
@@ -1,37 +0,0 @@
-Copyright (c) 2008-2009, Yahoo! Inc.
-All rights reserved.
-
-This software is provided for use in connection with the
-CodeMirror suite of modules and utilities, hosted and maintained
-at http://marijn.haverbeke.nl/codemirror/.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
- copyright notice, this list of conditions and the
- following disclaimer.
-
-* Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
-
-* Neither the name of Yahoo! Inc. nor the names of its
- contributors may be used to endorse or promote products
- derived from this software without specific prior
- written permission of Yahoo! Inc.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
diff --git a/media/CodeMirror-0.62/contrib/php/css/phpcolors.css b/media/CodeMirror-0.62/contrib/php/css/phpcolors.css
deleted file mode 100644
index 1dd1aec..0000000
--- a/media/CodeMirror-0.62/contrib/php/css/phpcolors.css
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
-The copyrights embodied in the content of this file are licensed by
-Yahoo! Inc. under the BSD (revised) open source license
-
-@author Dan Vlad Dascalescu <dandv@yahoo-inc.com>
-*/
-
-.editbox {
- margin: .4em;
- padding: 0;
- font-family: monospace;
- font-size: 10pt;
-}
-
-/*We should define specific styles for every element of the syntax.
- the setting below will cause some annoying color to show through if we missed
- defining a style for a token. This is also the "color" of the whitespace and
- of the cursor.
-*/
-pre.code, .editbox {
- color: red;
-}
-
-.editbox p {
- margin: 0;
-}
-
-span.php-punctuation {
- color: blue;
-}
-
-span.php-keyword {
- color: #770088;
- font-weight: bold;
-}
-
-span.php-operator {
- color: blue;
-}
-
-/* __FILE__ etc.; http://php.net/manual/en/reserved.php */
-span.php-compile-time-constant {
- color: #776088;
- font-weight: bold;
-}
-
-/* output of get_defined_constants(). Differs from http://php.net/manual/en/reserved.constants.php */
-span.php-predefined-constant {
- color: darkgreen;
- font-weight: bold;
-}
-
-/* PHP reserved "language constructs"... echo() etc.; http://php.net/manual/en/reserved.php */
-span.php-reserved-language-construct {
- color: green;
- font-weight: bold;
-}
-
-/* PHP built-in functions: glob(), chr() etc.; output of get_defined_functions()["internal"] */
-span.php-predefined-function {
- color: green;
-}
-
-/* PHP predefined classes: PDO, Exception etc.; output of get_declared_classes() and different from http://php.net/manual/en/reserved.classes.php */
-span.php-predefined-class {
- color: green;
-}
-
-span.php-atom {
- color: #228811;
-}
-
-/* class, interface, namespace or function names, but not $variables */
-span.php-t_string {
- color: black;
-}
-
-span.php-variable {
- color: black;
- font-weight: bold;
-}
-
-
-span.js-localvariable {
- color: #004499;
-}
-
-span.php-comment {
- color: #AA7700;
- font-stretch: condensed;
-/* font-style: italic; This causes line height to slightly change, getting line numbers out of sync */
-}
-
-span.php-string-single-quoted {
- color: #AA2222;
-}
-/* double quoted strings allow interpolation */
-span.php-string-double-quoted {
- color: #AA2222;
- font-weight: bold;
-}
-
-span.syntax-error {
- background-color: red;
-}
-
-span.deprecated {
- font-size: smaller;
-}
diff --git a/media/CodeMirror-0.62/contrib/php/index.html b/media/CodeMirror-0.62/contrib/php/index.html
deleted file mode 100644
index f35f5d2..0000000
--- a/media/CodeMirror-0.62/contrib/php/index.html
+++ /dev/null
@@ -1,292 +0,0 @@
-<!--
-Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
-The copyrights embodied in the content of this file are licensed by
-Yahoo! Inc. under the BSD (revised) open source license
-
-@author Dan Vlad Dascalescu <dandv@yahoo-inc.com>
-
--->
-
-
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <script src="../../js/codemirror.js" type="text/javascript"></script>
- <title>CodeMirror: PHP+HTML+JavaScript+CSS mixed-mode demonstration</title>
- <link rel="stylesheet" type="text/css" href="../../css/docs.css"/>
- </head>
- <body style="padding: 20px;">
-
- <p>This is a complex demonstration of the <b>PHP+HTML+JavaScript+CSS mixed-mode
- syntax highlight</b> capabilities of <a href="../../index.html">CodeMirror</a>.
- &lt;?php ... ?> tags use the PHP parser, &lt;script> tags use the JavaScript
- parser, and &lt;style> tags use the CSS parser. The rest of the content is
- parsed using the XML parser in HTML mode.</p>
-
- <p>Features of the PHP parser:
- <ul>
- <li>special "deprecated" style for PHP4 keywords like 'var'
- <li>support for PHP 5.3 keywords: 'namespace', 'use'
- <li>911 predefined constants, 1301 predefined functions, 105 predeclared classes
- from a typical PHP installation in a LAMP environment
- <li>new feature: syntax error flagging, thus enabling strict parsing of:
- <ol>
- <li>function definitions with explicitly or implicitly typed arguments and default values
- <li>modifiers (public, static etc.) applied to method and member definitions
- <li>foreach(array_expression as $key [=> $value]) loops
- </ol>
- <li>differentiation between single-quoted strings and double-quoted interpolating strings
- </ul>
- </p>
-
- <div style="border: 1px solid black; padding: 3px; background-color: #F8F8F8">
- <textarea id="code" cols="120" rows="30">
-The "root" parser is XML in HTML mode.
-Next, we can switch into PHP mode, for example. This is
-<?php echo 'text output by';
-?>
-PHP. </b>
-On the line above, we just had an XML syntax error due to the </b> tag not being opened.
-
-<?xml version='1.0' encoding='UTF-8' standalone='yes'?> HTML text will follow
-<html>
- <head>
- <title>Similarly, the 'script' tag will switch to the JavaScript parser:</title>
- <script type="text/javascript">
- // Press enter inside the object and your new line will be suitably
- // indented.
- var keyBindings = {
- enter: "newline-and-indent",
- tab: "reindent-selection",
- ctrl_enter: "reparse-buffer",
- ctrl_z: "undo",
- ctrl_y: "redo",
- ctrl_backspace: "undo-for-safari-which-stupidly-enough-blocks-ctrl-z"
- };
-
- // Press tab on the next line and the wrong indentation will be fixed.
- var regex = /foo|bar/i;
-
- function example(x) {
- // Local variables get a different colour than global ones.
- var y = 44.4;
- return x + y - z;
- }
- </script>
- <style>
- /* Some example CSS */
-
- @import url("something.css");
-
- body {
- margin: 0;
- padding: 3em 6em;
- font-family: tahoma, arial, sans-serif;
- color: #000;
- }
-
- #navigation a {
- font-weight: bold;
- text-decoration: none !important;
- }
-
- h1 {
- font-size: 2.5em;
- }
-
- h1:before, h2:before {
- content: "::";
- }
-
- code {
- font-family: courier, monospace;
- font-size: 80%;
- color: #418A8A;
- }
- </style>
- </head>
-
- <body>
-
- The PHP code below contains some deliberate errors. Play with the editor by fixing them
- and observing how the highlight changes.
-
- <?php
- namespace A;
- namespace A::B::C;
- namespace A::::B;
- namespace A::B::C::;
- namespace A::B::C::D x;
- self::range($row['lft'], $row['rgt'])); // error: extra ')'
- $a = (b() + 4) 5 foo; // error: missing operators
- self::$var;
- $parent = self::range($max + 1, $max + 1);
- $row[attributes][$attribute_name] = $attribute_value;
- $row[attributes()][$attribute_name] = $attribute_value;
- $row[attributes(5)][$attribute_name] = $attribute_value;
- $row[$attributes()][$attribute_name] = $attribute_value;
- abstract class 5 extends foo implements echo {
- private function domainObjectBuilder() {
- return $this->use_domain_object_builder
- ? $this->domain()->objectBuilder()
- : null;
- }
-
- const $myconst = 'some string';
- $array[myconst] = 4;
- // this is a single-line C++-style comment
- # this is a single-line shell-style comment
- private var $a = __FILE__;
- protected static $b = timezone_transitions_get('some parameter here');
- global $g = isset("string");
- static $s = hash_update_file; // warning: predefined function non-call
- function mike ($var) $foo;
- mike(A::func(param));
- func($b $c); // error: function parameters must be comma-separated
- foo bar; // error: no operator
- $baz $quux; // error: no operator
- public abstract function loadPageXML(util_FilePath $filename, $merge=0+$foo, $x, $y=3) {
- $newrow[$key] = $val;
- $newresult[] = $row;
- $state = $row['c'] == 1;
- $attribute_values[$attribute_name] = null;
- $row['attributes'][$attribute_name] = $attribute_value;
- $result[$row['element']][$row['attribute']] = $row['value'];
- $sql = "multiline string
-line2 is special - it'll interpolate variables like $state and method calls
-{$this->cache->add($key, 5)} and maybe \"more\"
-
-line5";
- $sql = 'multiline string
-single quoting means no \'interpolation\' like "$start" or method call
-{$this->cache->add($key, 5)} will happen
-
-line5';
- $bitpattern = 1 << 2;
- $bitpattern <<= 3;
- $incorrect = <<< 5 EOSTRING // FIXME: CodeMirror update bug: add a letter before 5 and notice that syntax is not updated until EOF, even with continuousScanning: 500
-error: the identifier must conform to the identifier rules
-EOSTRING;
- $sql = <<< EOSQL
- SELECT attribute, element, value
- FROM attribute_values
- WHERE dimension = ?
-EOSQL;
- $this->lr_cache->add($key, self::range($row['lft'], $row['rgt']));
- $composite_string = <<<EOSTRING
-some lines here
-EOSTRING
-. 'something extra';
- $page_lft = ($domain->name() == 'page') ? $start + 1 : $page_start + 1;
- echo "This is class foo";
- echo "a = ".$this ->a[2+3*$array["foo"]]."";
- echo "b = {$this->b}"; // FIXME: highlight interpolation in strings
- }
- final function makecoffee error($types = array("cappuccino"), $coffeeMaker = NULL) {
- $out_of_way_amount = $max - $child->left() + 1;
- $absolute_pos = $child->left() - $move->width();
- $varfunc(1, 'x');
- $varfunc(1, 'x') + foo() - 5;
- $funcarray[$i]('param1', $param2);
- $lr[$domain_name] = $this->get_left_and_right($domain,
- $dimension_name,
- $element_name);
- $domain_list = is_null($domain) ?
- r3_Domain::names() :
- array($domain->name());
- foreach (r3_Domain::names() as $domain_name) {
- $placeholders = 'distance LIKE '
- . implode(array_fill(1, $num_distances, '?'),
- ' OR distance LIKE ');
-
- }
- return $this->target*$this->trans+myfunc(__METHOD__);
- /*
- echo 'This is a test'; /* This comment will cause a problem */
- */
- }
- switch( $type ) {
- case "r3core_AddTemplateToTargetEvent":
- $this->notifyAddTemplateToTarget( $genevent );
- break;
- case "r3core_GenerateTargetEvent" $this:
- for($i=0; $i<=this->method(); $i++) {
- echo 'Syntax "highlighting"';
- }
- try {
- foreach($array xor $loader->parse_fn($filename) as $key => value) {
- namespace r3;
- }
- } catch( Exception $e ) {
- /** restore the backup
- */
- $this->loadAll($tmp, $event, true);
- // `php -l` doesn't complain at all at this (it assumes string constants):
- this + makes * no - sense;
- }
-
- break;
-
- default moo:
- throw new r3_util_Exception( get_class( $genevent ) . " does not map" );
- }
-
-
- };
-
- ?>
-
- <r3:cphp>
- php("works", $here, 2);
- </r3:cphp>
-
- <r4:cphp>
- class foo {
- // a comment
- var $a;
- var $b;
- };
- </r4:cphp>
-
- <h1>This is an <?php # echo 'simple';?> example.</h1>
- <p>The header above will say 'This is an example'.</p>
- <h1>This is an <?php // echo 'simple';?> example.</h1>
-
- <?php echo; ?>
- <body>
-
-<?php echo "<html>
- <head>
- <script>
- var foo = 'bar';
- </script>
- <style>
- span.test {font-family: arial, 'lucida console', sans-serif}
- </style>
- </head>
- <body>
- <!-- comment -->
- </body>
-</html>"; ?>
-
-</body>
-</html>
-
-
- </textarea>
- </div>
-
- <script type="text/javascript">
- var editor = CodeMirror.fromTextArea('code', {
- height: "350px",
- parserfile: ["parsexml.js", "parsecss.js", "tokenizejavascript.js", "parsejavascript.js",
- "../contrib/php/js/tokenizephp.js", "../contrib/php/js/parsephp.js",
- "../contrib/php/js/parsephphtmlmixed.js"],
- stylesheet: ["../../css/xmlcolors.css", "../../css/jscolors.css", "../../css/csscolors.css", "css/phpcolors.css"],
- path: "../../js/",
- continuousScanning: 500
- });
- </script>
-
-
- </body>
-</html>
diff --git a/media/CodeMirror-0.62/contrib/php/js/parsephp.js b/media/CodeMirror-0.62/contrib/php/js/parsephp.js
deleted file mode 100644
index 92d1e27..0000000
--- a/media/CodeMirror-0.62/contrib/php/js/parsephp.js
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
-Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
-The copyrights embodied in the content of this file are licensed by
-Yahoo! Inc. under the BSD (revised) open source license
-
-@author Dan Vlad Dascalescu <dandv@yahoo-inc.com>
-
-
-Parse function for PHP. Makes use of the tokenizer from tokenizephp.js.
-Based on parsejavascript.js by Marijn Haverbeke.
-
-
-Features:
- + special "deprecated" style for PHP4 keywords like 'var'
- + support for PHP 5.3 keywords: 'namespace', 'use'
- + 911 predefined constants, 1301 predefined functions, 105 predeclared classes
- from a typical PHP installation in a LAMP environment
- + new feature: syntax error flagging, thus enabling strict parsing of:
- + function definitions with explicitly or implicitly typed arguments and default values
- + modifiers (public, static etc.) applied to method and member definitions
- + foreach(array_expression as $key [=> $value]) loops
- + differentiation between single-quoted strings and double-quoted interpolating strings
-
-*/
-
-
-// add the Array.indexOf method for JS engines that don't support it (e.g. IE)
-// code from https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Objects/Array/IndexOf
-if (!Array.prototype.indexOf)
-{
- Array.prototype.indexOf = function(elt /*, from*/)
- {
- var len = this.length;
-
- var from = Number(arguments[1]) || 0;
- from = (from < 0)
- ? Math.ceil(from)
- : Math.floor(from);
- if (from < 0)
- from += len;
-
- for (; from < len; from++)
- {
- if (from in this &&
- this[from] === elt)
- return from;
- }
- return -1;
- };
-};
-
-
-var PHPParser = Editor.Parser = (function() {
- // Token types that can be considered to be atoms, part of operator expressions
- var atomicTypes = {
- "atom": true, "number": true, "variable": true, "string": true
- };
- // Constructor for the lexical context objects.
- function PHPLexical(indented, column, type, align, prev, info) {
- // indentation at start of this line
- this.indented = indented;
- // column at which this scope was opened
- this.column = column;
- // type of scope ('stat' (statement), 'form' (special form), '[', '{', or '(')
- this.type = type;
- // '[', '{', or '(' blocks that have any text after their opening
- // character are said to be 'aligned' -- any lines below are
- // indented all the way to the opening character.
- if (align != null)
- this.align = align;
- // Parent scope, if any.
- this.prev = prev;
- this.info = info;
- };
-
- // PHP indentation rules
- function indentPHP(lexical) {
- return function(firstChars) {
- var firstChar = firstChars && firstChars.charAt(0), type = lexical.type;
- var closing = firstChar == type;
- if (type == "form" && firstChar == "{")
- return lexical.indented;
- else if (type == "stat" || type == "form")
- return lexical.indented + indentUnit;
- else if (lexical.info == "switch" && !closing)
- return lexical.indented + (/^(?:case|default)\b/.test(firstChars) ? indentUnit : 2 * indentUnit);
- else if (lexical.align)
- return lexical.column - (closing ? 1 : 0);
- else
- return lexical.indented + (closing ? 0 : indentUnit);
- };
- };
-
- // The parser-iterator-producing function itself.
- function parsePHP(input, basecolumn) {
- // Wrap the input in a token stream
- var tokens = tokenizePHP(input);
- // The parser state. cc is a stack of actions that have to be
- // performed to finish the current statement. For example we might
- // know that we still need to find a closing parenthesis and a
- // semicolon. Actions at the end of the stack go first. It is
- // initialized with an infinitely looping action that consumes
- // whole statements.
- var cc = [statements];
- // The lexical scope, used mostly for indentation.
- var lexical = new PHPLexical((basecolumn || 0) - indentUnit, 0, "block", false);
- // Current column, and the indentation at the start of the current
- // line. Used to create lexical scope objects.
- var column = 0;
- var indented = 0;
- // Variables which are used by the mark, cont, and pass functions
- // below to communicate with the driver loop in the 'next' function.
- var consume, marked;
-
- // The iterator object.
- var parser = {next: next, copy: copy};
-
- // parsing is accomplished by calling next() repeatedly
- function next(){
- // Start by performing any 'lexical' actions (adjusting the
- // lexical variable), or the operations below will be working
- // with the wrong lexical state.
- while(cc[cc.length - 1].lex)
- cc.pop()();
-
- // Fetch the next token.
- var token = tokens.next();
-
- // Adjust column and indented.
- if (token.type == "whitespace" && column == 0)
- indented = token.value.length;
- column += token.value.length;
- if (token.content == "\n"){
- indented = column = 0;
- // If the lexical scope's align property is still undefined at
- // the end of the line, it is an un-aligned scope.
- if (!("align" in lexical))
- lexical.align = false;
- // Newline tokens get an indentation function associated with
- // them.
- token.indentation = indentPHP(lexical);
- }
- // No more processing for meaningless tokens.
- if (token.type == "whitespace" || token.type == "comment"
- || token.type == "string_not_terminated" )
- return token;
- // When a meaningful token is found and the lexical scope's
- // align is undefined, it is an aligned scope.
- if (!("align" in lexical))
- lexical.align = true;
-
- // Execute actions until one 'consumes' the token and we can
- // return it. 'marked' is used to change the style of the current token.
- while(true) {
- consume = marked = false;
- // Take and execute the topmost action.
- var action = cc.pop();
- action(token);
-
- if (consume){
- if (marked)
- token.style = marked;
- // Here we differentiate between local and global variables.
- return token;
- }
- }
- return 1; // Firebug workaround for http://code.google.com/p/fbug/issues/detail?id=1239#c1
- }
-
- // This makes a copy of the parser state. It stores all the
- // stateful variables in a closure, and returns a function that
- // will restore them when called with a new input stream. Note
- // that the cc array has to be copied, because it is contantly
- // being modified. Lexical objects are not mutated, so they can
- // be shared between runs of the parser.
- function copy(){
- var _lexical = lexical, _cc = cc.concat([]), _tokenState = tokens.state;
-
- return function copyParser(input){
- lexical = _lexical;
- cc = _cc.concat([]); // copies the array
- column = indented = 0;
- tokens = tokenizePHP(input, _tokenState);
- return parser;
- };
- }
-
- // Helper function for pushing a number of actions onto the cc
- // stack in reverse order.
- function push(fs){
- for (var i = fs.length - 1; i >= 0; i--)
- cc.push(fs[i]);
- }
- // cont and pass are used by the action functions to add other
- // actions to the stack. cont will cause the current token to be
- // consumed, pass will leave it for the next action.
- function cont(){
- push(arguments);
- consume = true;
- }
- function pass(){
- push(arguments);
- consume = false;
- }
- // Used to change the style of the current token.
- function mark(style){
- marked = style;
- }
- // Add a lyer of style to the current token, for example syntax-error
- function mark_add(style){
- marked = marked + ' ' + style;
- }
-
- // Push a new lexical context of the given type.
- function pushlex(type, info) {
- var result = function pushlexing() {
- lexical = new PHPLexical(indented, column, type, null, lexical, info)
- };
- result.lex = true;
- return result;
- }
- // Pop off the current lexical context.
- function poplex(){
- lexical = lexical.prev;
- }
- poplex.lex = true;
- // The 'lex' flag on these actions is used by the 'next' function
- // to know they can (and have to) be ran before moving on to the
- // next token.
-
- // Creates an action that discards tokens until it finds one of
- // the given type. This will ignore (and recover from) syntax errors.
- function expect(wanted){
- return function expecting(token){
- if (token.type == wanted) cont(); // consume the token
- else {
- cont(arguments.callee); // continue expecting() - call itself
- }
- };
- }
-
- // Require a specific token type, or one of the tokens passed in the 'wanted' array
- // Used to detect blatant syntax errors. 'execute' is used to pass extra code
- // to be executed if the token is matched. For example, a '(' match could
- // 'execute' a cont( compasep(funcarg), require(")") )
- function require(wanted, execute){
- return function requiring(token){
- var ok;
- var type = token.type;
- if (typeof(wanted) == "string")
- ok = (type == wanted) -1;
- else
- ok = wanted.indexOf(type);
- if (ok >= 0) {
- if (execute && typeof(execute[ok]) == "function")
- execute[ok](token);
- cont(); // just consume the token
- }
- else {
- if (!marked) mark(token.style);
- mark_add("syntax-error");
- cont(arguments.callee);
- }
- };
- }
-
- // Looks for a statement, and then calls itself.
- function statements(token){
- return pass(statement, statements);
- }
- // Dispatches various types of statements based on the type of the current token.
- function statement(token){
- var type = token.type;
- if (type == "keyword a") cont(pushlex("form"), expression, statement, poplex);
- else if (type == "keyword b") cont(pushlex("form"), statement, poplex);
- else if (type == "{") cont(pushlex("}"), block, poplex);
- else if (type == "function") funcdef();
- // technically, "class implode {...}" is correct, but we'll flag that as an error because it overrides a predefined function
- else if (type == "class") cont(require("t_string"), expect("{"), pushlex("}"), block, poplex);
- else if (type == "foreach") cont(pushlex("form"), require("("), pushlex(")"), expression, require("as"), require("variable"), /* => $value */ expect(")"), poplex, statement, poplex);
- else if (type == "for") cont(pushlex("form"), require("("), pushlex(")"), expression, require(";"), expression, require(";"), expression, require(")"), poplex, statement, poplex);
- // public final function foo(), protected static $bar;
- else if (type == "modifier") cont(require(["modifier", "variable", "function"], [null, null, funcdef]));
- else if (type == "switch") cont(pushlex("form"), require("("), expression, require(")"), pushlex("}", "switch"), require([":", "{"]), block, poplex, poplex);
- else if (type == "case") cont(expression, require(":"));
- else if (type == "default") cont(require(":"));
- else if (type == "catch") cont(pushlex("form"), require("("), require("t_string"), require("variable"), require(")"), statement, poplex);
- else if (type == "const") cont(require("t_string")); // 'const static x=5' is a syntax error
- // technically, "namespace implode {...}" is correct, but we'll flag that as an error because it overrides a predefined function
- else if (type == "namespace") cont(namespacedef, require(";"));
- // $variables may be followed by operators, () for variable function calls, or [] subscripts
- else pass(pushlex("stat"), expression, require(";"), poplex);
- }
- // Dispatch expression types.
- function expression(token){
- var type = token.type;
- if (atomicTypes.hasOwnProperty(type)) cont(maybeoperator);
- else if (type == "<<<") cont(require("string"), maybeoperator); // heredoc/nowdoc
- else if (type == "t_string") cont(maybe_double_colon, maybeoperator);
- else if (type == "keyword c") cont(expression);
- // function call or parenthesized expression: $a = ($b + 1) * 2;
- else if (type == "(") cont(pushlex(")"), commasep(expression), require(")"), poplex, maybeoperator);
- else if (type == "operator") cont(expression);
- }
- // Called for places where operators, function calls, or subscripts are
- // valid. Will skip on to the next action if none is found.
- function maybeoperator(token){
- var type = token.type;
- if (type == "operator") {
- if (token.content == "?") cont(expression, require(":"), expression); // ternary operator
- else cont(expression);
- }
- else if (type == "(") cont(pushlex(")"), expression, commasep(expression), require(")"), poplex, maybeoperator /* $varfunc() + 3 */);
- else if (type == "[") cont(pushlex("]"), expression, require("]"), maybeoperator /* for multidimensional arrays, or $func[$i]() */, poplex);
- }
- // A regular use of the double colon to specify a class, as in self::func() or myclass::$var;
- // Differs from `namespace` or `use` in that only one class can be the parent; chains (A::B::$var) are a syntax error.
- function maybe_double_colon(token) {
- if (token.type == "t_double_colon")
- // A::$var, A::func(), A::const
- cont(require(["t_string", "variable"]), maybeoperator);
- else {
- // a t_string wasn't followed by ::, such as in a function call: foo()
- pass(expression)
- }
- }
- // the declaration or definition of a function
- function funcdef() {
- cont(require("t_string"), require("("), pushlex(")"), commasep(funcarg), require(")"), poplex, block);
- }
- // Parses a comma-separated list of the things that are recognized
- // by the 'what' argument.
- function commasep(what){
- function proceed(token) {
- if (token.type == ",") cont(what, proceed);
- };
- return function commaSeparated() {
- pass(what, proceed);
- };
- }
- // Look for statements until a closing brace is found.
- function block(token) {
- if (token.type == "}") cont();
- else pass(statement, block);
- }
- function maybedefaultparameter(token){
- if (token.content == "=") cont(expression);
- }
- // support for default arguments: http://us.php.net/manual/en/functions.arguments.php#functions.arguments.default
- function funcarg(token){
- // function foo(myclass $obj) {...}
- if (token.type == "t_string") cont(require("variable"), maybedefaultparameter);
- // function foo($string) {...}
- else if (token.type == "variable") cont(maybedefaultparameter);
- }
-
- // A namespace definition or use
- function maybe_double_colon_def(token) {
- if (token.type == "t_double_colon")
- cont(namespacedef);
- }
- function namespacedef(token) {
- pass(require("t_string"), maybe_double_colon_def);
- }
-
- return parser;
- }
-
- return {make: parsePHP, electricChars: "{}:"};
-
-})();
diff --git a/media/CodeMirror-0.62/contrib/php/js/parsephphtmlmixed.js b/media/CodeMirror-0.62/contrib/php/js/parsephphtmlmixed.js
deleted file mode 100644
index ee4418d..0000000
--- a/media/CodeMirror-0.62/contrib/php/js/parsephphtmlmixed.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
-The copyrights embodied in the content of this file are licensed by
-Yahoo! Inc. under the BSD (revised) open source license
-
-@author Dan Vlad Dascalescu <dandv@yahoo-inc.com>
-
-Based on parsehtmlmixed.js by Marijn Haverbeke.
-*/
-
-var PHPHTMLMixedParser = Editor.Parser = (function() {
- if (!(PHPParser && CSSParser && JSParser && XMLParser))
- throw new Error("PHP, CSS, JS, and XML parsers must be loaded for PHP+HTML mixed mode to work.");
- XMLParser.configure({useHTMLKludges: true});
-
- function parseMixed(stream) {
- var htmlParser = XMLParser.make(stream), localParser = null, inTag = false;
- var iter = {next: top, copy: copy};
-
- function top() {
- var token = htmlParser.next();
- if (token.content == "<")
- inTag = true;
- else if (token.style == "xml-tagname" && inTag === true)
- inTag = token.content.toLowerCase();
- else if (token.type == "xml-processing") {
- // dispatch on PHP
- if (token.content == "<?php")
- iter.next = local(PHPParser, "?>");
- }
- // "xml-processing" tokens are ignored, because they should be handled by a specific local parser
- else if (token.content == ">") {
- if (inTag == "script")
- iter.next = local(JSParser, "</script");
- else if (inTag == "style")
- iter.next = local(CSSParser, "</style");
- inTag = false;
- }
- return token;
- }
- function local(parser, tag) {
- var baseIndent = htmlParser.indentation();
- localParser = parser.make(stream, baseIndent + indentUnit);
- return function() {
- if (stream.lookAhead(tag, false, false, true)) {
- localParser = null;
- iter.next = top;
- return top(); // pass the ending tag to the enclosing parser
- }
-
- var token = localParser.next();
- var lt = token.value.lastIndexOf("<"), sz = Math.min(token.value.length - lt, tag.length);
- if (lt != -1 && token.value.slice(lt, lt + sz).toLowerCase() == tag.slice(0, sz) &&
- stream.lookAhead(tag.slice(sz), false, false, true)) {
- stream.push(token.value.slice(lt));
- token.value = token.value.slice(0, lt);
- }
-
- if (token.indentation) {
- var oldIndent = token.indentation;
- token.indentation = function(chars) {
- if (chars == "</")
- return baseIndent;
- else
- return oldIndent(chars);
- }
- }
-
- return token;
- };
- }
-
- function copy() {
- var _html = htmlParser.copy(), _local = localParser && localParser.copy(),
- _next = iter.next, _inTag = inTag;
- return function(_stream) {
- stream = _stream;
- htmlParser = _html(_stream);
- localParser = _local && _local(_stream);
- iter.next = _next;
- inTag = _inTag;
- return iter;
- };
- }
- return iter;
- }
-
- return {make: parseMixed, electricChars: "{}/:"};
-
-})();
diff --git a/media/CodeMirror-0.62/contrib/php/js/tokenizephp.js b/media/CodeMirror-0.62/contrib/php/js/tokenizephp.js
deleted file mode 100644
index c851741..0000000
--- a/media/CodeMirror-0.62/contrib/php/js/tokenizephp.js
+++ /dev/null
@@ -1,1007 +0,0 @@
-/*
-Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
-The copyrights embodied in the content of this file are licensed by
-Yahoo! Inc. under the BSD (revised) open source license
-
-@author Vlad Dan Dascalescu <dandv@yahoo-inc.com>
-
-
-Tokenizer for PHP code
-
-References:
- + http://php.net/manual/en/reserved.php
- + http://php.net/tokens
- + get_defined_constants(), get_defined_functions(), get_declared_classes()
- executed on a realistic (not vanilla) PHP installation with typical LAMP modules.
- Specifically, the PHP bundled with the Uniform Web Server (www.uniformserver.com).
-
-*/
-
-
-// add the forEach method for JS engines that don't support it (e.g. IE)
-// code from https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Objects:Array:forEach
-if (!Array.prototype.forEach)
-{
- Array.prototype.forEach = function(fun /*, thisp*/)
- {
- var len = this.length;
- if (typeof fun != "function")
- throw new TypeError();
-
- var thisp = arguments[1];
- for (var i = 0; i < len; i++)
- {
- if (i in this)
- fun.call(thisp, this[i], i, this);
- }
- };
-}
-
-
-var tokenizePHP = (function() {
- /* A map of PHP's reserved words (keywords, predefined classes, functions and
- constants. Each token has a type ('keyword', 'operator' etc.) and a style.
- The style corresponds to the CSS span class in phpcolors.css.
-
- Keywords can be of three types:
- a - takes an expression and forms a statement - e.g. if
- b - takes just a statement - e.g. else
- c - takes an optinoal expression, but no statement - e.g. return
- This distinction gives the parser enough information to parse
- correct code correctly (we don't care that much how we parse
- incorrect code).
-
- Reference: http://us.php.net/manual/en/reserved.php
- */
- var keywords = function(){
- function token(type, style){
- return {type: type, style: style};
- }
- var result = {};
-
- // for each(var element in ["...", "..."]) can pick up elements added to
- // Array.prototype, so we'll use the loop structure below. See also
- // http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for_each...in
-
- // keywords that take an expression and form a statement
- ["if", "elseif", "while", "declare"].forEach(function(element, index, array) {
- result[element] = token("keyword a", "php-keyword");
- });
-
- // keywords that take just a statement
- ["do", "else", "try" ].forEach(function(element, index, array) {
- result[element] = token("keyword b", "php-keyword");
- });
-
- // keywords that take an optional expression, but no statement
- ["return", "break", "continue", // the expression is optional
- "new", "clone", "throw" // the expression is mandatory
- ].forEach(function(element, index, array) {
- result[element] = token("keyword c", "php-keyword");
- });
-
- ["__CLASS__", "__DIR__", "__FILE__", "__FUNCTION__", "__METHOD__", "__NAMESPACE__"].forEach(function(element, index, array) {
- result[element] = token("atom", "php-compile-time-constant");
- });
-
- ["true", "false", "null"].forEach(function(element, index, array) {
- result[element] = token("atom", "php-atom");
- });
-
- ["and", "or", "xor", "instanceof"].forEach(function(element, index, array) {
- result[element] = token("operator", "php-keyword php-operator");
- });
-
- ["class", "interface"].forEach(function(element, index, array) {
- result[element] = token("class", "php-keyword");
- });
- ["namespace", "use", "extends", "implements"].forEach(function(element, index, array) {
- result[element] = token("namespace", "php-keyword");
- });
-
- // reserved "language constructs"... http://php.net/manual/en/reserved.php
- [ "die", "echo", "empty", "exit", "eval", "include", "include_once", "isset",
- "list", "require", "require_once", "return", "print", "unset",
- "array" // a keyword rather, but mandates a parenthesized parameter list
- ].forEach(function(element, index, array) {
- result[element] = token("t_string", "php-reserved-language-construct");
- });
-
- result["switch"] = token("switch", "php-keyword");
- result["case"] = token("case", "php-keyword");
- result["default"] = token("default", "php-keyword");
- result["catch"] = token("catch", "php-keyword");
- result["function"] = token("function", "php-keyword");
-
- // http://php.net/manual/en/control-structures.alternative-syntax.php must be followed by a ':'
- ["endif", "endwhile", "endfor", "endforeach", "endswitch", "enddeclare"].forEach(function(element, index, array) {
- result[element] = token("default", "php-keyword");
- });
-
- result["const"] = token("const", "php-keyword");
-
- ["abstract", "final", "private", "protected", "public", "global", "static"].forEach(function(element, index, array) {
- result[element] = token("modifier", "php-keyword");
- });
- result["var"] = token("modifier", "php-keyword deprecated");
-
- result["foreach"] = token("foreach", "php-keyword");
- result["as"] = token("as", "php-keyword");
- result["for"] = token("for", "php-keyword");
-
- // PHP built-in functions - output of get_defined_functions()["internal"]
- [ "zend_version", "func_num_args", "func_get_arg", "func_get_args", "strlen",
- "strcmp", "strncmp", "strcasecmp", "strncasecmp", "each", "error_reporting",
- "define", "defined", "get_class", "get_parent_class", "method_exists",
- "property_exists", "class_exists", "interface_exists", "function_exists",
- "get_included_files", "get_required_files", "is_subclass_of", "is_a",
- "get_class_vars", "get_object_vars", "get_class_methods", "trigger_error",
- "user_error", "set_error_handler", "restore_error_handler",
- "set_exception_handler", "restore_exception_handler", "get_declared_classes",
- "get_declared_interfaces", "get_defined_functions", "get_defined_vars",
- "create_function", "get_resource_type", "get_loaded_extensions",
- "extension_loaded", "get_extension_funcs", "get_defined_constants",
- "debug_backtrace", "debug_print_backtrace", "bcadd", "bcsub", "bcmul", "bcdiv",
- "bcmod", "bcpow", "bcsqrt", "bcscale", "bccomp", "bcpowmod", "jdtogregorian",
- "gregoriantojd", "jdtojulian", "juliantojd", "jdtojewish", "jewishtojd",
- "jdtofrench", "frenchtojd", "jddayofweek", "jdmonthname", "easter_date",
- "easter_days", "unixtojd", "jdtounix", "cal_to_jd", "cal_from_jd",
- "cal_days_in_month", "cal_info", "variant_set", "variant_add", "variant_cat",
- "variant_sub", "variant_mul", "variant_and", "variant_div", "variant_eqv",
- "variant_idiv", "variant_imp", "variant_mod", "variant_or", "variant_pow",
- "variant_xor", "variant_abs", "variant_fix", "variant_int", "variant_neg",
- "variant_not", "variant_round", "variant_cmp", "variant_date_to_timestamp",
- "variant_date_from_timestamp", "variant_get_type", "variant_set_type",
- "variant_cast", "com_create_guid", "com_event_sink", "com_print_typeinfo",
- "com_message_pump", "com_load_typelib", "com_get_active_object", "ctype_alnum",
- "ctype_alpha", "ctype_cntrl", "ctype_digit", "ctype_lower", "ctype_graph",
- "ctype_print", "ctype_punct", "ctype_space", "ctype_upper", "ctype_xdigit",
- "strtotime", "date", "idate", "gmdate", "mktime", "gmmktime", "checkdate",
- "strftime", "gmstrftime", "time", "localtime", "getdate", "date_create",
- "date_parse", "date_format", "date_modify", "date_timezone_get",
- "date_timezone_set", "date_offset_get", "date_time_set", "date_date_set",
- "date_isodate_set", "timezone_open", "timezone_name_get",
- "timezone_name_from_abbr", "timezone_offset_get", "timezone_transitions_get",
- "timezone_identifiers_list", "timezone_abbreviations_list",
- "date_default_timezone_set", "date_default_timezone_get", "date_sunrise",
- "date_sunset", "date_sun_info", "filter_input", "filter_var",
- "filter_input_array", "filter_var_array", "filter_list", "filter_has_var",
- "filter_id", "ftp_connect", "ftp_login", "ftp_pwd", "ftp_cdup", "ftp_chdir",
- "ftp_exec", "ftp_raw", "ftp_mkdir", "ftp_rmdir", "ftp_chmod", "ftp_alloc",
- "ftp_nlist", "ftp_rawlist", "ftp_systype", "ftp_pasv", "ftp_get", "ftp_fget",
- "ftp_put", "ftp_fput", "ftp_size", "ftp_mdtm", "ftp_rename", "ftp_delete",
- "ftp_site", "ftp_close", "ftp_set_option", "ftp_get_option", "ftp_nb_fget",
- "ftp_nb_get", "ftp_nb_continue", "ftp_nb_put", "ftp_nb_fput", "ftp_quit",
- "hash", "hash_file", "hash_hmac", "hash_hmac_file", "hash_init", "hash_update",
- "hash_update_stream", "hash_update_file", "hash_final", "hash_algos", "iconv",
- "ob_iconv_handler", "iconv_get_encoding", "iconv_set_encoding", "iconv_strlen",
- "iconv_substr", "iconv_strpos", "iconv_strrpos", "iconv_mime_encode",
- "iconv_mime_decode", "iconv_mime_decode_headers", "json_encode", "json_decode",
- "odbc_autocommit", "odbc_binmode", "odbc_close", "odbc_close_all",
- "odbc_columns", "odbc_commit", "odbc_connect", "odbc_cursor",
- "odbc_data_source", "odbc_execute", "odbc_error", "odbc_errormsg", "odbc_exec",
- "odbc_fetch_array", "odbc_fetch_object", "odbc_fetch_row", "odbc_fetch_into",
- "odbc_field_len", "odbc_field_scale", "odbc_field_name", "odbc_field_type",
- "odbc_field_num", "odbc_free_result", "odbc_gettypeinfo", "odbc_longreadlen",
- "odbc_next_result", "odbc_num_fields", "odbc_num_rows", "odbc_pconnect",
- "odbc_prepare", "odbc_result", "odbc_result_all", "odbc_rollback",
- "odbc_setoption", "odbc_specialcolumns", "odbc_statistics", "odbc_tables",
- "odbc_primarykeys", "odbc_columnprivileges", "odbc_tableprivileges",
- "odbc_foreignkeys", "odbc_procedures", "odbc_procedurecolumns", "odbc_do",
- "odbc_field_precision", "preg_match", "preg_match_all", "preg_replace",
- "preg_replace_callback", "preg_split", "preg_quote", "preg_grep",
- "preg_last_error", "session_name", "session_module_name", "session_save_path",
- "session_id", "session_regenerate_id", "session_decode", "session_register",
- "session_unregister", "session_is_registered", "session_encode",
- "session_start", "session_destroy", "session_unset",
- "session_set_save_handler", "session_cache_limiter", "session_cache_expire",
- "session_set_cookie_params", "session_get_cookie_params",
- "session_write_close", "session_commit", "spl_classes", "spl_autoload",
- "spl_autoload_extensions", "spl_autoload_register", "spl_autoload_unregister",
- "spl_autoload_functions", "spl_autoload_call", "class_parents",
- "class_implements", "spl_object_hash", "iterator_to_array", "iterator_count",
- "iterator_apply", "constant", "bin2hex", "sleep", "usleep", "flush",
- "wordwrap", "htmlspecialchars", "htmlentities", "html_entity_decode",
- "htmlspecialchars_decode", "get_html_translation_table", "sha1", "sha1_file",
- "md5", "md5_file", "crc32", "iptcparse", "iptcembed", "getimagesize",
- "image_type_to_mime_type", "image_type_to_extension", "phpinfo", "phpversion",
- "phpcredits", "php_logo_guid", "php_real_logo_guid", "php_egg_logo_guid",
- "zend_logo_guid", "php_sapi_name", "php_uname", "php_ini_scanned_files",
- "strnatcmp", "strnatcasecmp", "substr_count", "strspn", "strcspn", "strtok",
- "strtoupper", "strtolower", "strpos", "stripos", "strrpos", "strripos",
- "strrev", "hebrev", "hebrevc", "nl2br", "basename", "dirname", "pathinfo",
- "stripslashes", "stripcslashes", "strstr", "stristr", "strrchr", "str_shuffle",
- "str_word_count", "str_split", "strpbrk", "substr_compare", "strcoll",
- "substr", "substr_replace", "quotemeta", "ucfirst", "ucwords", "strtr",
- "addslashes", "addcslashes", "rtrim", "str_replace", "str_ireplace",
- "str_repeat", "count_chars", "chunk_split", "trim", "ltrim", "strip_tags",
- "similar_text", "explode", "implode", "setlocale", "localeconv", "soundex",
- "levenshtein", "chr", "ord", "parse_str", "str_pad", "chop", "strchr",
- "sprintf", "printf", "vprintf", "vsprintf", "fprintf", "vfprintf", "sscanf",
- "fscanf", "parse_url", "urlencode", "urldecode", "rawurlencode",
- "rawurldecode", "http_build_query", "unlink", "exec", "system",
- "escapeshellcmd", "escapeshellarg", "passthru", "shell_exec", "proc_open",
- "proc_close", "proc_terminate", "proc_get_status", "rand", "srand",
- "getrandmax", "mt_rand", "mt_srand", "mt_getrandmax", "getservbyname",
- "getservbyport", "getprotobyname", "getprotobynumber", "getmyuid", "getmygid",
- "getmypid", "getmyinode", "getlastmod", "base64_decode", "base64_encode",
- "convert_uuencode", "convert_uudecode", "abs", "ceil", "floor", "round", "sin",
- "cos", "tan", "asin", "acos", "atan", "atan2", "sinh", "cosh", "tanh", "pi",
- "is_finite", "is_nan", "is_infinite", "pow", "exp", "log", "log10", "sqrt",
- "hypot", "deg2rad", "rad2deg", "bindec", "hexdec", "octdec", "decbin",
- "decoct", "dechex", "base_convert", "number_format", "fmod", "ip2long",
- "long2ip", "getenv", "putenv", "microtime", "gettimeofday", "uniqid",
- "quoted_printable_decode", "convert_cyr_string", "get_current_user",
- "set_time_limit", "get_cfg_var", "magic_quotes_runtime",
- "set_magic_quotes_runtime", "get_magic_quotes_gpc", "get_magic_quotes_runtime",
- "import_request_variables", "error_log", "error_get_last", "call_user_func",
- "call_user_func_array", "call_user_method", "call_user_method_array",
- "serialize", "unserialize", "var_dump", "var_export", "debug_zval_dump",
- "print_r", "memory_get_usage", "memory_get_peak_usage",
- "register_shutdown_function", "register_tick_function",
- "unregister_tick_function", "highlight_file", "show_source",
- "highlight_string", "php_strip_whitespace", "ini_get", "ini_get_all",
- "ini_set", "ini_alter", "ini_restore", "get_include_path", "set_include_path",
- "restore_include_path", "setcookie", "setrawcookie", "header", "headers_sent",
- "headers_list", "connection_aborted", "connection_status", "ignore_user_abort",
- "parse_ini_file", "is_uploaded_file", "move_uploaded_file", "gethostbyaddr",
- "gethostbyname", "gethostbynamel", "intval", "floatval", "doubleval", "strval",
- "gettype", "settype", "is_null", "is_resource", "is_bool", "is_long",
- "is_float", "is_int", "is_integer", "is_double", "is_real", "is_numeric",
- "is_string", "is_array", "is_object", "is_scalar", "is_callable", "ereg",
- "ereg_replace", "eregi", "eregi_replace", "split", "spliti", "join",
- "sql_regcase", "dl", "pclose", "popen", "readfile", "rewind", "rmdir", "umask",
- "fclose", "feof", "fgetc", "fgets", "fgetss", "fread", "fopen", "fpassthru",
- "ftruncate", "fstat", "fseek", "ftell", "fflush", "fwrite", "fputs", "mkdir",
- "rename", "copy", "tempnam", "tmpfile", "file", "file_get_contents",
- "file_put_contents", "stream_select", "stream_context_create",
- "stream_context_set_params", "stream_context_set_option",
- "stream_context_get_options", "stream_context_get_default",
- "stream_filter_prepend", "stream_filter_append", "stream_filter_remove",
- "stream_socket_client", "stream_socket_server", "stream_socket_accept",
- "stream_socket_get_name", "stream_socket_recvfrom", "stream_socket_sendto",
- "stream_socket_enable_crypto", "stream_socket_shutdown",
- "stream_copy_to_stream", "stream_get_contents", "fgetcsv", "fputcsv", "flock",
- "get_meta_tags", "stream_set_write_buffer", "set_file_buffer",
- "set_socket_blocking", "stream_set_blocking", "socket_set_blocking",
- "stream_get_meta_data", "stream_get_line", "stream_wrapper_register",
- "stream_register_wrapper", "stream_wrapper_unregister",
- "stream_wrapper_restore", "stream_get_wrappers", "stream_get_transports",
- "get_headers", "stream_set_timeout", "socket_set_timeout", "socket_get_status",
- "realpath", "fsockopen", "pfsockopen", "pack", "unpack", "get_browser",
- "crypt", "opendir", "closedir", "chdir", "getcwd", "rewinddir", "readdir",
- "dir", "scandir", "glob", "fileatime", "filectime", "filegroup", "fileinode",
- "filemtime", "fileowner", "fileperms", "filesize", "filetype", "file_exists",
- "is_writable", "is_writeable", "is_readable", "is_executable", "is_file",
- "is_dir", "is_link", "stat", "lstat", "chown", "chgrp", "chmod", "touch",
- "clearstatcache", "disk_total_space", "disk_free_space", "diskfreespace",
- "mail", "ezmlm_hash", "openlog", "syslog", "closelog",
- "define_syslog_variables", "lcg_value", "metaphone", "ob_start", "ob_flush",
- "ob_clean", "ob_end_flush", "ob_end_clean", "ob_get_flush", "ob_get_clean",
- "ob_get_length", "ob_get_level", "ob_get_status", "ob_get_contents",
- "ob_implicit_flush", "ob_list_handlers", "ksort", "krsort", "natsort",
- "natcasesort", "asort", "arsort", "sort", "rsort", "usort", "uasort", "uksort",
- "shuffle", "array_walk", "array_walk_recursive", "count", "end", "prev",
- "next", "reset", "current", "key", "min", "max", "in_array", "array_search",
- "extract", "compact", "array_fill", "array_fill_keys", "range",
- "array_multisort", "array_push", "array_pop", "array_shift", "array_unshift",
- "array_splice", "array_slice", "array_merge", "array_merge_recursive",
- "array_keys", "array_values", "array_count_values", "array_reverse",
- "array_reduce", "array_pad", "array_flip", "array_change_key_case",
- "array_rand", "array_unique", "array_intersect", "array_intersect_key",
- "array_intersect_ukey", "array_uintersect", "array_intersect_assoc",
- "array_uintersect_assoc", "array_intersect_uassoc", "array_uintersect_uassoc",
- "array_diff", "array_diff_key", "array_diff_ukey", "array_udiff",
- "array_diff_assoc", "array_udiff_assoc", "array_diff_uassoc",
- "array_udiff_uassoc", "array_sum", "array_product", "array_filter",
- "array_map", "array_chunk", "array_combine", "array_key_exists", "pos",
- "sizeof", "key_exists", "assert", "assert_options", "version_compare",
- "str_rot13", "stream_get_filters", "stream_filter_register",
- "stream_bucket_make_writeable", "stream_bucket_prepend",
- "stream_bucket_append", "stream_bucket_new", "output_add_rewrite_var",
- "output_reset_rewrite_vars", "sys_get_temp_dir", "token_get_all", "token_name",
- "readgzfile", "gzrewind", "gzclose", "gzeof", "gzgetc", "gzgets", "gzgetss",
- "gzread", "gzopen", "gzpassthru", "gzseek", "gztell", "gzwrite", "gzputs",
- "gzfile", "gzcompress", "gzuncompress", "gzdeflate", "gzinflate", "gzencode",
- "ob_gzhandler", "zlib_get_coding_type", "libxml_set_streams_context",
- "libxml_use_internal_errors", "libxml_get_last_error", "libxml_clear_errors",
- "libxml_get_errors", "dom_import_simplexml", "simplexml_load_file",
- "simplexml_load_string", "simplexml_import_dom", "wddx_serialize_value",
- "wddx_serialize_vars", "wddx_packet_start", "wddx_packet_end", "wddx_add_vars",
- "wddx_deserialize", "xml_parser_create", "xml_parser_create_ns",
- "xml_set_object", "xml_set_element_handler", "xml_set_character_data_handler",
- "xml_set_processing_instruction_handler", "xml_set_default_handler",
- "xml_set_unparsed_entity_decl_handler", "xml_set_notation_decl_handler",
- "xml_set_external_entity_ref_handler", "xml_set_start_namespace_decl_handler",
- "xml_set_end_namespace_decl_handler", "xml_parse", "xml_parse_into_struct",
- "xml_get_error_code", "xml_error_string", "xml_get_current_line_number",
- "xml_get_current_column_number", "xml_get_current_byte_index",
- "xml_parser_free", "xml_parser_set_option", "xml_parser_get_option",
- "utf8_encode", "utf8_decode", "xmlwriter_open_uri", "xmlwriter_open_memory",
- "xmlwriter_set_indent", "xmlwriter_set_indent_string",
- "xmlwriter_start_comment", "xmlwriter_end_comment",
- "xmlwriter_start_attribute", "xmlwriter_end_attribute",
- "xmlwriter_write_attribute", "xmlwriter_start_attribute_ns",
- "xmlwriter_write_attribute_ns", "xmlwriter_start_element",
- "xmlwriter_end_element", "xmlwriter_full_end_element",
- "xmlwriter_start_element_ns", "xmlwriter_write_element",
- "xmlwriter_write_element_ns", "xmlwriter_start_pi", "xmlwriter_end_pi",
- "xmlwriter_write_pi", "xmlwriter_start_cdata", "xmlwriter_end_cdata",
- "xmlwriter_write_cdata", "xmlwriter_text", "xmlwriter_write_raw",
- "xmlwriter_start_document", "xmlwriter_end_document",
- "xmlwriter_write_comment", "xmlwriter_start_dtd", "xmlwriter_end_dtd",
- "xmlwriter_write_dtd", "xmlwriter_start_dtd_element",
- "xmlwriter_end_dtd_element", "xmlwriter_write_dtd_element",
- "xmlwriter_start_dtd_attlist", "xmlwriter_end_dtd_attlist",
- "xmlwriter_write_dtd_attlist", "xmlwriter_start_dtd_entity",
- "xmlwriter_end_dtd_entity", "xmlwriter_write_dtd_entity",
- "xmlwriter_output_memory", "xmlwriter_flush", "gd_info", "imagearc",
- "imageellipse", "imagechar", "imagecharup", "imagecolorat",
- "imagecolorallocate", "imagepalettecopy", "imagecreatefromstring",
- "imagecolorclosest", "imagecolordeallocate", "imagecolorresolve",
- "imagecolorexact", "imagecolorset", "imagecolortransparent",
- "imagecolorstotal", "imagecolorsforindex", "imagecopy", "imagecopymerge",
- "imagecopymergegray", "imagecopyresized", "imagecreate",
- "imagecreatetruecolor", "imageistruecolor", "imagetruecolortopalette",
- "imagesetthickness", "imagefilledarc", "imagefilledellipse",
- "imagealphablending", "imagesavealpha", "imagecolorallocatealpha",
- "imagecolorresolvealpha", "imagecolorclosestalpha", "imagecolorexactalpha",
- "imagecopyresampled", "imagegrabwindow", "imagegrabscreen", "imagerotate",
- "imageantialias", "imagesettile", "imagesetbrush", "imagesetstyle",
- "imagecreatefrompng", "imagecreatefromgif", "imagecreatefromjpeg",
- "imagecreatefromwbmp", "imagecreatefromxbm", "imagecreatefromgd",
- "imagecreatefromgd2", "imagecreatefromgd2part", "imagepng", "imagegif",
- "imagejpeg", "imagewbmp", "imagegd", "imagegd2", "imagedestroy",
- "imagegammacorrect", "imagefill", "imagefilledpolygon", "imagefilledrectangle",
- "imagefilltoborder", "imagefontwidth", "imagefontheight", "imageinterlace",
- "imageline", "imageloadfont", "imagepolygon", "imagerectangle",
- "imagesetpixel", "imagestring", "imagestringup", "imagesx", "imagesy",
- "imagedashedline", "imagettfbbox", "imagettftext", "imageftbbox",
- "imagefttext", "imagepsloadfont", "imagepsfreefont", "imagepsencodefont",
- "imagepsextendfont", "imagepsslantfont", "imagepstext", "imagepsbbox",
- "imagetypes", "jpeg2wbmp", "png2wbmp", "image2wbmp", "imagelayereffect",
- "imagecolormatch", "imagexbm", "imagefilter", "imageconvolution",
- "mb_convert_case", "mb_strtoupper", "mb_strtolower", "mb_language",
- "mb_internal_encoding", "mb_http_input", "mb_http_output", "mb_detect_order",
- "mb_substitute_character", "mb_parse_str", "mb_output_handler",
- "mb_preferred_mime_name", "mb_strlen", "mb_strpos", "mb_strrpos", "mb_stripos",
- "mb_strripos", "mb_strstr", "mb_strrchr", "mb_stristr", "mb_strrichr",
- "mb_substr_count", "mb_substr", "mb_strcut", "mb_strwidth", "mb_strimwidth",
- "mb_convert_encoding", "mb_detect_encoding", "mb_list_encodings",
- "mb_convert_kana", "mb_encode_mimeheader", "mb_decode_mimeheader",
- "mb_convert_variables", "mb_encode_numericentity", "mb_decode_numericentity",
- "mb_send_mail", "mb_get_info", "mb_check_encoding", "mb_regex_encoding",
- "mb_regex_set_options", "mb_ereg", "mb_eregi", "mb_ereg_replace",
- "mb_eregi_replace", "mb_split", "mb_ereg_match", "mb_ereg_search",
- "mb_ereg_search_pos", "mb_ereg_search_regs", "mb_ereg_search_init",
- "mb_ereg_search_getregs", "mb_ereg_search_getpos", "mb_ereg_search_setpos",
- "mbregex_encoding", "mbereg", "mberegi", "mbereg_replace", "mberegi_replace",
- "mbsplit", "mbereg_match", "mbereg_search", "mbereg_search_pos",
- "mbereg_search_regs", "mbereg_search_init", "mbereg_search_getregs",
- "mbereg_search_getpos", "mbereg_search_setpos", "mysql_connect",
- "mysql_pconnect", "mysql_close", "mysql_select_db", "mysql_query",
- "mysql_unbuffered_query", "mysql_db_query", "mysql_list_dbs",
- "mysql_list_tables", "mysql_list_fields", "mysql_list_processes",
- "mysql_error", "mysql_errno", "mysql_affected_rows", "mysql_insert_id",
- "mysql_result", "mysql_num_rows", "mysql_num_fields", "mysql_fetch_row",
- "mysql_fetch_array", "mysql_fetch_assoc", "mysql_fetch_object",
- "mysql_data_seek", "mysql_fetch_lengths", "mysql_fetch_field",
- "mysql_field_seek", "mysql_free_result", "mysql_field_name",
- "mysql_field_table", "mysql_field_len", "mysql_field_type",
- "mysql_field_flags", "mysql_escape_string", "mysql_real_escape_string",
- "mysql_stat", "mysql_thread_id", "mysql_client_encoding", "mysql_ping",
- "mysql_get_client_info", "mysql_get_host_info", "mysql_get_proto_info",
- "mysql_get_server_info", "mysql_info", "mysql_set_charset", "mysql",
- "mysql_fieldname", "mysql_fieldtable", "mysql_fieldlen", "mysql_fieldtype",
- "mysql_fieldflags", "mysql_selectdb", "mysql_freeresult", "mysql_numfields",
- "mysql_numrows", "mysql_listdbs", "mysql_listtables", "mysql_listfields",
- "mysql_db_name", "mysql_dbname", "mysql_tablename", "mysql_table_name",
- "mysqli_affected_rows", "mysqli_autocommit", "mysqli_change_user",
- "mysqli_character_set_name", "mysqli_close", "mysqli_commit", "mysqli_connect",
- "mysqli_connect_errno", "mysqli_connect_error", "mysqli_data_seek",
- "mysqli_debug", "mysqli_disable_reads_from_master", "mysqli_disable_rpl_parse",
- "mysqli_dump_debug_info", "mysqli_enable_reads_from_master",
- "mysqli_enable_rpl_parse", "mysqli_embedded_server_end",
- "mysqli_embedded_server_start", "mysqli_errno", "mysqli_error",
- "mysqli_stmt_execute", "mysqli_execute", "mysqli_fetch_field",
- "mysqli_fetch_fields", "mysqli_fetch_field_direct", "mysqli_fetch_lengths",
- "mysqli_fetch_array", "mysqli_fetch_assoc", "mysqli_fetch_object",
- "mysqli_fetch_row", "mysqli_field_count", "mysqli_field_seek",
- "mysqli_field_tell", "mysqli_free_result", "mysqli_get_charset",
- "mysqli_get_client_info", "mysqli_get_client_version", "mysqli_get_host_info",
- "mysqli_get_proto_info", "mysqli_get_server_info", "mysqli_get_server_version",
- "mysqli_get_warnings", "mysqli_init", "mysqli_info", "mysqli_insert_id",
- "mysqli_kill", "mysqli_set_local_infile_default",
- "mysqli_set_local_infile_handler", "mysqli_master_query",
- "mysqli_more_results", "mysqli_multi_query", "mysqli_next_result",
- "mysqli_num_fields", "mysqli_num_rows", "mysqli_options", "mysqli_ping",
- "mysqli_prepare", "mysqli_report", "mysqli_query", "mysqli_real_connect",
- "mysqli_real_escape_string", "mysqli_real_query", "mysqli_rollback",
- "mysqli_rpl_parse_enabled", "mysqli_rpl_probe", "mysqli_rpl_query_type",
- "mysqli_select_db", "mysqli_set_charset", "mysqli_stmt_attr_get",
- "mysqli_stmt_attr_set", "mysqli_stmt_field_count", "mysqli_stmt_init",
- "mysqli_stmt_prepare", "mysqli_stmt_result_metadata",
- "mysqli_stmt_send_long_data", "mysqli_stmt_bind_param",
- "mysqli_stmt_bind_result", "mysqli_stmt_fetch", "mysqli_stmt_free_result",
- "mysqli_stmt_get_warnings", "mysqli_stmt_insert_id", "mysqli_stmt_reset",
- "mysqli_stmt_param_count", "mysqli_send_query", "mysqli_slave_query",
- "mysqli_sqlstate", "mysqli_ssl_set", "mysqli_stat",
- "mysqli_stmt_affected_rows", "mysqli_stmt_close", "mysqli_stmt_data_seek",
- "mysqli_stmt_errno", "mysqli_stmt_error", "mysqli_stmt_num_rows",
- "mysqli_stmt_sqlstate", "mysqli_store_result", "mysqli_stmt_store_result",
- "mysqli_thread_id", "mysqli_thread_safe", "mysqli_use_result",
- "mysqli_warning_count", "mysqli_bind_param", "mysqli_bind_result",
- "mysqli_client_encoding", "mysqli_escape_string", "mysqli_fetch",
- "mysqli_param_count", "mysqli_get_metadata", "mysqli_send_long_data",
- "mysqli_set_opt", "pdo_drivers", "socket_select", "socket_create",
- "socket_create_listen", "socket_accept", "socket_set_nonblock",
- "socket_set_block", "socket_listen", "socket_close", "socket_write",
- "socket_read", "socket_getsockname", "socket_getpeername", "socket_connect",
- "socket_strerror", "socket_bind", "socket_recv", "socket_send",
- "socket_recvfrom", "socket_sendto", "socket_get_option", "socket_set_option",
- "socket_shutdown", "socket_last_error", "socket_clear_error", "socket_getopt",
- "socket_setopt", "eaccelerator_put", "eaccelerator_get", "eaccelerator_rm",
- "eaccelerator_gc", "eaccelerator_lock", "eaccelerator_unlock",
- "eaccelerator_caching", "eaccelerator_optimizer", "eaccelerator_clear",
- "eaccelerator_clean", "eaccelerator_info", "eaccelerator_purge",
- "eaccelerator_cached_scripts", "eaccelerator_removed_scripts",
- "eaccelerator_list_keys", "eaccelerator_encode", "eaccelerator_load",
- "_eaccelerator_loader_file", "_eaccelerator_loader_line",
- "eaccelerator_set_session_handlers", "_eaccelerator_output_handler",
- "eaccelerator_cache_page", "eaccelerator_rm_page", "eaccelerator_cache_output",
- "eaccelerator_cache_result", "xdebug_get_stack_depth",
- "xdebug_get_function_stack", "xdebug_print_function_stack",
- "xdebug_get_declared_vars", "xdebug_call_class", "xdebug_call_function",
- "xdebug_call_file", "xdebug_call_line", "xdebug_var_dump", "xdebug_debug_zval",
- "xdebug_debug_zval_stdout", "xdebug_enable", "xdebug_disable",
- "xdebug_is_enabled", "xdebug_break", "xdebug_start_trace", "xdebug_stop_trace",
- "xdebug_get_tracefile_name", "xdebug_get_profiler_filename",
- "xdebug_dump_aggr_profiling_data", "xdebug_clear_aggr_profiling_data",
- "xdebug_memory_usage", "xdebug_peak_memory_usage", "xdebug_time_index",
- "xdebug_start_error_collection", "xdebug_stop_error_collection",
- "xdebug_get_collected_errors", "xdebug_start_code_coverage",
- "xdebug_stop_code_coverage", "xdebug_get_code_coverage",
- "xdebug_get_function_count", "xdebug_dump_superglobals",
- "_" // alias for gettext()
- ].forEach(function(element, index, array) {
- result[element] = token("t_string", "php-predefined-function");
- });
-
- // output of get_defined_constants(). Differs significantly from http://php.net/manual/en/reserved.constants.php
- [ "E_ERROR", "E_RECOVERABLE_ERROR", "E_WARNING", "E_PARSE", "E_NOTICE",
- "E_STRICT", "E_CORE_ERROR", "E_CORE_WARNING", "E_COMPILE_ERROR",
- "E_COMPILE_WARNING", "E_USER_ERROR", "E_USER_WARNING", "E_USER_NOTICE",
- "E_ALL", "TRUE", "FALSE", "NULL", "ZEND_THREAD_SAFE", "PHP_VERSION", "PHP_OS",
- "PHP_SAPI", "DEFAULT_INCLUDE_PATH", "PEAR_INSTALL_DIR", "PEAR_EXTENSION_DIR",
- "PHP_EXTENSION_DIR", "PHP_PREFIX", "PHP_BINDIR", "PHP_LIBDIR", "PHP_DATADIR",
- "PHP_SYSCONFDIR", "PHP_LOCALSTATEDIR", "PHP_CONFIG_FILE_PATH",
- "PHP_CONFIG_FILE_SCAN_DIR", "PHP_SHLIB_SUFFIX", "PHP_EOL", "PHP_EOL",
- "PHP_INT_MAX", "PHP_INT_SIZE", "PHP_OUTPUT_HANDLER_START",
- "PHP_OUTPUT_HANDLER_CONT", "PHP_OUTPUT_HANDLER_END", "UPLOAD_ERR_OK",
- "UPLOAD_ERR_INI_SIZE", "UPLOAD_ERR_FORM_SIZE", "UPLOAD_ERR_PARTIAL",
- "UPLOAD_ERR_NO_FILE", "UPLOAD_ERR_NO_TMP_DIR", "UPLOAD_ERR_CANT_WRITE",
- "UPLOAD_ERR_EXTENSION", "CAL_GREGORIAN", "CAL_JULIAN", "CAL_JEWISH",
- "CAL_FRENCH", "CAL_NUM_CALS", "CAL_DOW_DAYNO", "CAL_DOW_SHORT", "CAL_DOW_LONG",
- "CAL_MONTH_GREGORIAN_SHORT", "CAL_MONTH_GREGORIAN_LONG",
- "CAL_MONTH_JULIAN_SHORT", "CAL_MONTH_JULIAN_LONG", "CAL_MONTH_JEWISH",
- "CAL_MONTH_FRENCH", "CAL_EASTER_DEFAULT", "CAL_EASTER_ROMAN",
- "CAL_EASTER_ALWAYS_GREGORIAN", "CAL_EASTER_ALWAYS_JULIAN",
- "CAL_JEWISH_ADD_ALAFIM_GERESH", "CAL_JEWISH_ADD_ALAFIM",
- "CAL_JEWISH_ADD_GERESHAYIM", "CLSCTX_INPROC_SERVER", "CLSCTX_INPROC_HANDLER",
- "CLSCTX_LOCAL_SERVER", "CLSCTX_REMOTE_SERVER", "CLSCTX_SERVER", "CLSCTX_ALL",
- "VT_NULL", "VT_EMPTY", "VT_UI1", "VT_I1", "VT_UI2", "VT_I2", "VT_UI4", "VT_I4",
- "VT_R4", "VT_R8", "VT_BOOL", "VT_ERROR", "VT_CY", "VT_DATE", "VT_BSTR",
- "VT_DECIMAL", "VT_UNKNOWN", "VT_DISPATCH", "VT_VARIANT", "VT_INT", "VT_UINT",
- "VT_ARRAY", "VT_BYREF", "CP_ACP", "CP_MACCP", "CP_OEMCP", "CP_UTF7", "CP_UTF8",
- "CP_SYMBOL", "CP_THREAD_ACP", "VARCMP_LT", "VARCMP_EQ", "VARCMP_GT",
- "VARCMP_NULL", "NORM_IGNORECASE", "NORM_IGNORENONSPACE", "NORM_IGNORESYMBOLS",
- "NORM_IGNOREWIDTH", "NORM_IGNOREKANATYPE", "DISP_E_DIVBYZERO",
- "DISP_E_OVERFLOW", "DISP_E_BADINDEX", "MK_E_UNAVAILABLE", "INPUT_POST",
- "INPUT_GET", "INPUT_COOKIE", "INPUT_ENV", "INPUT_SERVER", "INPUT_SESSION",
- "INPUT_REQUEST", "FILTER_FLAG_NONE", "FILTER_REQUIRE_SCALAR",
- "FILTER_REQUIRE_ARRAY", "FILTER_FORCE_ARRAY", "FILTER_NULL_ON_FAILURE",
- "FILTER_VALIDATE_INT", "FILTER_VALIDATE_BOOLEAN", "FILTER_VALIDATE_FLOAT",
- "FILTER_VALIDATE_REGEXP", "FILTER_VALIDATE_URL", "FILTER_VALIDATE_EMAIL",
- "FILTER_VALIDATE_IP", "FILTER_DEFAULT", "FILTER_UNSAFE_RAW",
- "FILTER_SANITIZE_STRING", "FILTER_SANITIZE_STRIPPED",
- "FILTER_SANITIZE_ENCODED", "FILTER_SANITIZE_SPECIAL_CHARS",
- "FILTER_SANITIZE_EMAIL", "FILTER_SANITIZE_URL", "FILTER_SANITIZE_NUMBER_INT",
- "FILTER_SANITIZE_NUMBER_FLOAT", "FILTER_SANITIZE_MAGIC_QUOTES",
- "FILTER_CALLBACK", "FILTER_FLAG_ALLOW_OCTAL", "FILTER_FLAG_ALLOW_HEX",
- "FILTER_FLAG_STRIP_LOW", "FILTER_FLAG_STRIP_HIGH", "FILTER_FLAG_ENCODE_LOW",
- "FILTER_FLAG_ENCODE_HIGH", "FILTER_FLAG_ENCODE_AMP",
- "FILTER_FLAG_NO_ENCODE_QUOTES", "FILTER_FLAG_EMPTY_STRING_NULL",
- "FILTER_FLAG_ALLOW_FRACTION", "FILTER_FLAG_ALLOW_THOUSAND",
- "FILTER_FLAG_ALLOW_SCIENTIFIC", "FILTER_FLAG_SCHEME_REQUIRED",
- "FILTER_FLAG_HOST_REQUIRED", "FILTER_FLAG_PATH_REQUIRED",
- "FILTER_FLAG_QUERY_REQUIRED", "FILTER_FLAG_IPV4", "FILTER_FLAG_IPV6",
- "FILTER_FLAG_NO_RES_RANGE", "FILTER_FLAG_NO_PRIV_RANGE", "FTP_ASCII",
- "FTP_TEXT", "FTP_BINARY", "FTP_IMAGE", "FTP_AUTORESUME", "FTP_TIMEOUT_SEC",
- "FTP_AUTOSEEK", "FTP_FAILED", "FTP_FINISHED", "FTP_MOREDATA", "HASH_HMAC",
- "ICONV_IMPL", "ICONV_VERSION", "ICONV_MIME_DECODE_STRICT",
- "ICONV_MIME_DECODE_CONTINUE_ON_ERROR", "ODBC_TYPE", "ODBC_BINMODE_PASSTHRU",
- "ODBC_BINMODE_RETURN", "ODBC_BINMODE_CONVERT", "SQL_ODBC_CURSORS",
- "SQL_CUR_USE_DRIVER", "SQL_CUR_USE_IF_NEEDED", "SQL_CUR_USE_ODBC",
- "SQL_CONCURRENCY", "SQL_CONCUR_READ_ONLY", "SQL_CONCUR_LOCK",
- "SQL_CONCUR_ROWVER", "SQL_CONCUR_VALUES", "SQL_CURSOR_TYPE",
- "SQL_CURSOR_FORWARD_ONLY", "SQL_CURSOR_KEYSET_DRIVEN", "SQL_CURSOR_DYNAMIC",
- "SQL_CURSOR_STATIC", "SQL_KEYSET_SIZE", "SQL_FETCH_FIRST", "SQL_FETCH_NEXT",
- "SQL_CHAR", "SQL_VARCHAR", "SQL_LONGVARCHAR", "SQL_DECIMAL", "SQL_NUMERIC",
- "SQL_BIT", "SQL_TINYINT", "SQL_SMALLINT", "SQL_INTEGER", "SQL_BIGINT",
- "SQL_REAL", "SQL_FLOAT", "SQL_DOUBLE", "SQL_BINARY", "SQL_VARBINARY",
- "SQL_LONGVARBINARY", "SQL_DATE", "SQL_TIME", "SQL_TIMESTAMP",
- "PREG_PATTERN_ORDER", "PREG_SET_ORDER", "PREG_OFFSET_CAPTURE",
- "PREG_SPLIT_NO_EMPTY", "PREG_SPLIT_DELIM_CAPTURE", "PREG_SPLIT_OFFSET_CAPTURE",
- "PREG_GREP_INVERT", "PREG_NO_ERROR", "PREG_INTERNAL_ERROR",
- "PREG_BACKTRACK_LIMIT_ERROR", "PREG_RECURSION_LIMIT_ERROR",
- "PREG_BAD_UTF8_ERROR", "DATE_ATOM", "DATE_COOKIE", "DATE_ISO8601",
- "DATE_RFC822", "DATE_RFC850", "DATE_RFC1036", "DATE_RFC1123", "DATE_RFC2822",
- "DATE_RFC3339", "DATE_RSS", "DATE_W3C", "SUNFUNCS_RET_TIMESTAMP",
- "SUNFUNCS_RET_STRING", "SUNFUNCS_RET_DOUBLE", "LIBXML_VERSION",
- "LIBXML_DOTTED_VERSION", "LIBXML_NOENT", "LIBXML_DTDLOAD", "LIBXML_DTDATTR",
- "LIBXML_DTDVALID", "LIBXML_NOERROR", "LIBXML_NOWARNING", "LIBXML_NOBLANKS",
- "LIBXML_XINCLUDE", "LIBXML_NSCLEAN", "LIBXML_NOCDATA", "LIBXML_NONET",
- "LIBXML_COMPACT", "LIBXML_NOXMLDECL", "LIBXML_NOEMPTYTAG", "LIBXML_ERR_NONE",
- "LIBXML_ERR_WARNING", "LIBXML_ERR_ERROR", "LIBXML_ERR_FATAL",
- "CONNECTION_ABORTED", "CONNECTION_NORMAL", "CONNECTION_TIMEOUT", "INI_USER",
- "INI_PERDIR", "INI_SYSTEM", "INI_ALL", "PHP_URL_SCHEME", "PHP_URL_HOST",
- "PHP_URL_PORT", "PHP_URL_USER", "PHP_URL_PASS", "PHP_URL_PATH",
- "PHP_URL_QUERY", "PHP_URL_FRAGMENT", "M_E", "M_LOG2E", "M_LOG10E", "M_LN2",
- "M_LN10", "M_PI", "M_PI_2", "M_PI_4", "M_1_PI", "M_2_PI", "M_SQRTPI",
- "M_2_SQRTPI", "M_LNPI", "M_EULER", "M_SQRT2", "M_SQRT1_2", "M_SQRT3", "INF",
- "NAN", "INFO_GENERAL", "INFO_CREDITS", "INFO_CONFIGURATION", "INFO_MODULES",
- "INFO_ENVIRONMENT", "INFO_VARIABLES", "INFO_LICENSE", "INFO_ALL",
- "CREDITS_GROUP", "CREDITS_GENERAL", "CREDITS_SAPI", "CREDITS_MODULES",
- "CREDITS_DOCS", "CREDITS_FULLPAGE", "CREDITS_QA", "CREDITS_ALL",
- "HTML_SPECIALCHARS", "HTML_ENTITIES", "ENT_COMPAT", "ENT_QUOTES",
- "ENT_NOQUOTES", "STR_PAD_LEFT", "STR_PAD_RIGHT", "STR_PAD_BOTH",
- "PATHINFO_DIRNAME", "PATHINFO_BASENAME", "PATHINFO_EXTENSION",
- "PATHINFO_FILENAME", "CHAR_MAX", "LC_CTYPE", "LC_NUMERIC", "LC_TIME",
- "LC_COLLATE", "LC_MONETARY", "LC_ALL", "SEEK_SET", "SEEK_CUR", "SEEK_END",
- "LOCK_SH", "LOCK_EX", "LOCK_UN", "LOCK_NB", "STREAM_NOTIFY_CONNECT",
- "STREAM_NOTIFY_AUTH_REQUIRED", "STREAM_NOTIFY_AUTH_RESULT",
- "STREAM_NOTIFY_MIME_TYPE_IS", "STREAM_NOTIFY_FILE_SIZE_IS",
- "STREAM_NOTIFY_REDIRECTED", "STREAM_NOTIFY_PROGRESS", "STREAM_NOTIFY_FAILURE",
- "STREAM_NOTIFY_COMPLETED", "STREAM_NOTIFY_RESOLVE",
- "STREAM_NOTIFY_SEVERITY_INFO", "STREAM_NOTIFY_SEVERITY_WARN",
- "STREAM_NOTIFY_SEVERITY_ERR", "STREAM_FILTER_READ", "STREAM_FILTER_WRITE",
- "STREAM_FILTER_ALL", "STREAM_CLIENT_PERSISTENT", "STREAM_CLIENT_ASYNC_CONNECT",
- "STREAM_CLIENT_CONNECT", "STREAM_CRYPTO_METHOD_SSLv2_CLIENT",
- "STREAM_CRYPTO_METHOD_SSLv3_CLIENT", "STREAM_CRYPTO_METHOD_SSLv23_CLIENT",
- "STREAM_CRYPTO_METHOD_TLS_CLIENT", "STREAM_CRYPTO_METHOD_SSLv2_SERVER",
- "STREAM_CRYPTO_METHOD_SSLv3_SERVER", "STREAM_CRYPTO_METHOD_SSLv23_SERVER",
- "STREAM_CRYPTO_METHOD_TLS_SERVER", "STREAM_SHUT_RD", "STREAM_SHUT_WR",
- "STREAM_SHUT_RDWR", "STREAM_PF_INET", "STREAM_PF_INET6", "STREAM_PF_UNIX",
- "STREAM_IPPROTO_IP", "STREAM_IPPROTO_TCP", "STREAM_IPPROTO_UDP",
- "STREAM_IPPROTO_ICMP", "STREAM_IPPROTO_RAW", "STREAM_SOCK_STREAM",
- "STREAM_SOCK_DGRAM", "STREAM_SOCK_RAW", "STREAM_SOCK_SEQPACKET",
- "STREAM_SOCK_RDM", "STREAM_PEEK", "STREAM_OOB", "STREAM_SERVER_BIND",
- "STREAM_SERVER_LISTEN", "FILE_USE_INCLUDE_PATH", "FILE_IGNORE_NEW_LINES",
- "FILE_SKIP_EMPTY_LINES", "FILE_APPEND", "FILE_NO_DEFAULT_CONTEXT",
- "PSFS_PASS_ON", "PSFS_FEED_ME", "PSFS_ERR_FATAL", "PSFS_FLAG_NORMAL",
- "PSFS_FLAG_FLUSH_INC", "PSFS_FLAG_FLUSH_CLOSE", "CRYPT_SALT_LENGTH",
- "CRYPT_STD_DES", "CRYPT_EXT_DES", "CRYPT_MD5", "CRYPT_BLOWFISH",
- "DIRECTORY_SEPARATOR", "PATH_SEPARATOR", "GLOB_BRACE", "GLOB_MARK",
- "GLOB_NOSORT", "GLOB_NOCHECK", "GLOB_NOESCAPE", "GLOB_ERR", "GLOB_ONLYDIR",
- "LOG_EMERG", "LOG_ALERT", "LOG_CRIT", "LOG_ERR", "LOG_WARNING", "LOG_NOTICE",
- "LOG_INFO", "LOG_DEBUG", "LOG_KERN", "LOG_USER", "LOG_MAIL", "LOG_DAEMON",
- "LOG_AUTH", "LOG_SYSLOG", "LOG_LPR", "LOG_NEWS", "LOG_UUCP", "LOG_CRON",
- "LOG_AUTHPRIV", "LOG_PID", "LOG_CONS", "LOG_ODELAY", "LOG_NDELAY",
- "LOG_NOWAIT", "LOG_PERROR", "EXTR_OVERWRITE", "EXTR_SKIP", "EXTR_PREFIX_SAME",
- "EXTR_PREFIX_ALL", "EXTR_PREFIX_INVALID", "EXTR_PREFIX_IF_EXISTS",
- "EXTR_IF_EXISTS", "EXTR_REFS", "SORT_ASC", "SORT_DESC", "SORT_REGULAR",
- "SORT_NUMERIC", "SORT_STRING", "SORT_LOCALE_STRING", "CASE_LOWER",
- "CASE_UPPER", "COUNT_NORMAL", "COUNT_RECURSIVE", "ASSERT_ACTIVE",
- "ASSERT_CALLBACK", "ASSERT_BAIL", "ASSERT_WARNING", "ASSERT_QUIET_EVAL",
- "STREAM_USE_PATH", "STREAM_IGNORE_URL", "STREAM_ENFORCE_SAFE_MODE",
- "STREAM_REPORT_ERRORS", "STREAM_MUST_SEEK", "STREAM_URL_STAT_LINK",
- "STREAM_URL_STAT_QUIET", "STREAM_MKDIR_RECURSIVE", "IMAGETYPE_GIF",
- "IMAGETYPE_JPEG", "IMAGETYPE_PNG", "IMAGETYPE_SWF", "IMAGETYPE_PSD",
- "IMAGETYPE_BMP", "IMAGETYPE_TIFF_II", "IMAGETYPE_TIFF_MM", "IMAGETYPE_JPC",
- "IMAGETYPE_JP2", "IMAGETYPE_JPX", "IMAGETYPE_JB2", "IMAGETYPE_SWC",
- "IMAGETYPE_IFF", "IMAGETYPE_WBMP", "IMAGETYPE_JPEG2000", "IMAGETYPE_XBM",
- "T_INCLUDE", "T_INCLUDE_ONCE", "T_EVAL", "T_REQUIRE", "T_REQUIRE_ONCE",
- "T_LOGICAL_OR", "T_LOGICAL_XOR", "T_LOGICAL_AND", "T_PRINT", "T_PLUS_EQUAL",
- "T_MINUS_EQUAL", "T_MUL_EQUAL", "T_DIV_EQUAL", "T_CONCAT_EQUAL", "T_MOD_EQUAL",
- "T_AND_EQUAL", "T_OR_EQUAL", "T_XOR_EQUAL", "T_SL_EQUAL", "T_SR_EQUAL",
- "T_BOOLEAN_OR", "T_BOOLEAN_AND", "T_IS_EQUAL", "T_IS_NOT_EQUAL",
- "T_IS_IDENTICAL", "T_IS_NOT_IDENTICAL", "T_IS_SMALLER_OR_EQUAL",
- "T_IS_GREATER_OR_EQUAL", "T_SL", "T_SR", "T_INC", "T_DEC", "T_INT_CAST",
- "T_DOUBLE_CAST", "T_STRING_CAST", "T_ARRAY_CAST", "T_OBJECT_CAST",
- "T_BOOL_CAST", "T_UNSET_CAST", "T_NEW", "T_EXIT", "T_IF", "T_ELSEIF", "T_ELSE",
- "T_ENDIF", "T_LNUMBER", "T_DNUMBER", "T_STRING", "T_STRING_VARNAME",
- "T_VARIABLE", "T_NUM_STRING", "T_INLINE_HTML", "T_CHARACTER",
- "T_BAD_CHARACTER", "T_ENCAPSED_AND_WHITESPACE", "T_CONSTANT_ENCAPSED_STRING",
- "T_ECHO", "T_DO", "T_WHILE", "T_ENDWHILE", "T_FOR", "T_ENDFOR", "T_FOREACH",
- "T_ENDFOREACH", "T_DECLARE", "T_ENDDECLARE", "T_AS", "T_SWITCH", "T_ENDSWITCH",
- "T_CASE", "T_DEFAULT", "T_BREAK", "T_CONTINUE", "T_FUNCTION", "T_CONST",
- "T_RETURN", "T_USE", "T_GLOBAL", "T_STATIC", "T_VAR", "T_UNSET", "T_ISSET",
- "T_EMPTY", "T_CLASS", "T_EXTENDS", "T_INTERFACE", "T_IMPLEMENTS",
- "T_OBJECT_OPERATOR", "T_DOUBLE_ARROW", "T_LIST", "T_ARRAY", "T_CLASS_C",
- "T_FUNC_C", "T_METHOD_C", "T_LINE", "T_FILE", "T_COMMENT", "T_DOC_COMMENT",
- "T_OPEN_TAG", "T_OPEN_TAG_WITH_ECHO", "T_CLOSE_TAG", "T_WHITESPACE",
- "T_START_HEREDOC", "T_END_HEREDOC", "T_DOLLAR_OPEN_CURLY_BRACES",
- "T_CURLY_OPEN", "T_PAAMAYIM_NEKUDOTAYIM", "T_DOUBLE_COLON", "T_ABSTRACT",
- "T_CATCH", "T_FINAL", "T_INSTANCEOF", "T_PRIVATE", "T_PROTECTED", "T_PUBLIC",
- "T_THROW", "T_TRY", "T_CLONE", "T_HALT_COMPILER", "FORCE_GZIP",
- "FORCE_DEFLATE", "XML_ELEMENT_NODE", "XML_ATTRIBUTE_NODE", "XML_TEXT_NODE",
- "XML_CDATA_SECTION_NODE", "XML_ENTITY_REF_NODE", "XML_ENTITY_NODE",
- "XML_PI_NODE", "XML_COMMENT_NODE", "XML_DOCUMENT_NODE",
- "XML_DOCUMENT_TYPE_NODE", "XML_DOCUMENT_FRAG_NODE", "XML_NOTATION_NODE",
- "XML_HTML_DOCUMENT_NODE", "XML_DTD_NODE", "XML_ELEMENT_DECL_NODE",
- "XML_ATTRIBUTE_DECL_NODE", "XML_ENTITY_DECL_NODE", "XML_NAMESPACE_DECL_NODE",
- "XML_LOCAL_NAMESPACE", "XML_ATTRIBUTE_CDATA", "XML_ATTRIBUTE_ID",
- "XML_ATTRIBUTE_IDREF", "XML_ATTRIBUTE_IDREFS", "XML_ATTRIBUTE_ENTITY",
- "XML_ATTRIBUTE_NMTOKEN", "XML_ATTRIBUTE_NMTOKENS", "XML_ATTRIBUTE_ENUMERATION",
- "XML_ATTRIBUTE_NOTATION", "DOM_PHP_ERR", "DOM_INDEX_SIZE_ERR",
- "DOMSTRING_SIZE_ERR", "DOM_HIERARCHY_REQUEST_ERR", "DOM_WRONG_DOCUMENT_ERR",
- "DOM_INVALID_CHARACTER_ERR", "DOM_NO_DATA_ALLOWED_ERR",
- "DOM_NO_MODIFICATION_ALLOWED_ERR", "DOM_NOT_FOUND_ERR",
- "DOM_NOT_SUPPORTED_ERR", "DOM_INUSE_ATTRIBUTE_ERR", "DOM_INVALID_STATE_ERR",
- "DOM_SYNTAX_ERR", "DOM_INVALID_MODIFICATION_ERR", "DOM_NAMESPACE_ERR",
- "DOM_INVALID_ACCESS_ERR", "DOM_VALIDATION_ERR", "XML_ERROR_NONE",
- "XML_ERROR_NO_MEMORY", "XML_ERROR_SYNTAX", "XML_ERROR_NO_ELEMENTS",
- "XML_ERROR_INVALID_TOKEN", "XML_ERROR_UNCLOSED_TOKEN",
- "XML_ERROR_PARTIAL_CHAR", "XML_ERROR_TAG_MISMATCH",
- "XML_ERROR_DUPLICATE_ATTRIBUTE", "XML_ERROR_JUNK_AFTER_DOC_ELEMENT",
- "XML_ERROR_PARAM_ENTITY_REF", "XML_ERROR_UNDEFINED_ENTITY",
- "XML_ERROR_RECURSIVE_ENTITY_REF", "XML_ERROR_ASYNC_ENTITY",
- "XML_ERROR_BAD_CHAR_REF", "XML_ERROR_BINARY_ENTITY_REF",
- "XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF", "XML_ERROR_MISPLACED_XML_PI",
- "XML_ERROR_UNKNOWN_ENCODING", "XML_ERROR_INCORRECT_ENCODING",
- "XML_ERROR_UNCLOSED_CDATA_SECTION", "XML_ERROR_EXTERNAL_ENTITY_HANDLING",
- "XML_OPTION_CASE_FOLDING", "XML_OPTION_TARGET_ENCODING",
- "XML_OPTION_SKIP_TAGSTART", "XML_OPTION_SKIP_WHITE", "XML_SAX_IMPL", "IMG_GIF",
- "IMG_JPG", "IMG_JPEG", "IMG_PNG", "IMG_WBMP", "IMG_XPM", "IMG_COLOR_TILED",
- "IMG_COLOR_STYLED", "IMG_COLOR_BRUSHED", "IMG_COLOR_STYLEDBRUSHED",
- "IMG_COLOR_TRANSPARENT", "IMG_ARC_ROUNDED", "IMG_ARC_PIE", "IMG_ARC_CHORD",
- "IMG_ARC_NOFILL", "IMG_ARC_EDGED", "IMG_GD2_RAW", "IMG_GD2_COMPRESSED",
- "IMG_EFFECT_REPLACE", "IMG_EFFECT_ALPHABLEND", "IMG_EFFECT_NORMAL",
- "IMG_EFFECT_OVERLAY", "GD_BUNDLED", "IMG_FILTER_NEGATE",
- "IMG_FILTER_GRAYSCALE", "IMG_FILTER_BRIGHTNESS", "IMG_FILTER_CONTRAST",
- "IMG_FILTER_COLORIZE", "IMG_FILTER_EDGEDETECT", "IMG_FILTER_GAUSSIAN_BLUR",
- "IMG_FILTER_SELECTIVE_BLUR", "IMG_FILTER_EMBOSS", "IMG_FILTER_MEAN_REMOVAL",
- "IMG_FILTER_SMOOTH", "PNG_NO_FILTER", "PNG_FILTER_NONE", "PNG_FILTER_SUB",
- "PNG_FILTER_UP", "PNG_FILTER_AVG", "PNG_FILTER_PAETH", "PNG_ALL_FILTERS",
- "MB_OVERLOAD_MAIL", "MB_OVERLOAD_STRING", "MB_OVERLOAD_REGEX", "MB_CASE_UPPER",
- "MB_CASE_LOWER", "MB_CASE_TITLE", "MYSQL_ASSOC", "MYSQL_NUM", "MYSQL_BOTH",
- "MYSQL_CLIENT_COMPRESS", "MYSQL_CLIENT_SSL", "MYSQL_CLIENT_INTERACTIVE",
- "MYSQL_CLIENT_IGNORE_SPACE", "MYSQLI_READ_DEFAULT_GROUP",
- "MYSQLI_READ_DEFAULT_FILE", "MYSQLI_OPT_CONNECT_TIMEOUT",
- "MYSQLI_OPT_LOCAL_INFILE", "MYSQLI_INIT_COMMAND", "MYSQLI_CLIENT_SSL",
- "MYSQLI_CLIENT_COMPRESS", "MYSQLI_CLIENT_INTERACTIVE",
- "MYSQLI_CLIENT_IGNORE_SPACE", "MYSQLI_CLIENT_NO_SCHEMA",
- "MYSQLI_CLIENT_FOUND_ROWS", "MYSQLI_STORE_RESULT", "MYSQLI_USE_RESULT",
- "MYSQLI_ASSOC", "MYSQLI_NUM", "MYSQLI_BOTH",
- "MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH", "MYSQLI_STMT_ATTR_CURSOR_TYPE",
- "MYSQLI_CURSOR_TYPE_NO_CURSOR", "MYSQLI_CURSOR_TYPE_READ_ONLY",
- "MYSQLI_CURSOR_TYPE_FOR_UPDATE", "MYSQLI_CURSOR_TYPE_SCROLLABLE",
- "MYSQLI_STMT_ATTR_PREFETCH_ROWS", "MYSQLI_NOT_NULL_FLAG",
- "MYSQLI_PRI_KEY_FLAG", "MYSQLI_UNIQUE_KEY_FLAG", "MYSQLI_MULTIPLE_KEY_FLAG",
- "MYSQLI_BLOB_FLAG", "MYSQLI_UNSIGNED_FLAG", "MYSQLI_ZEROFILL_FLAG",
- "MYSQLI_AUTO_INCREMENT_FLAG", "MYSQLI_TIMESTAMP_FLAG", "MYSQLI_SET_FLAG",
- "MYSQLI_NUM_FLAG", "MYSQLI_PART_KEY_FLAG", "MYSQLI_GROUP_FLAG",
- "MYSQLI_TYPE_DECIMAL", "MYSQLI_TYPE_TINY", "MYSQLI_TYPE_SHORT",
- "MYSQLI_TYPE_LONG", "MYSQLI_TYPE_FLOAT", "MYSQLI_TYPE_DOUBLE",
- "MYSQLI_TYPE_NULL", "MYSQLI_TYPE_TIMESTAMP", "MYSQLI_TYPE_LONGLONG",
- "MYSQLI_TYPE_INT24", "MYSQLI_TYPE_DATE", "MYSQLI_TYPE_TIME",
- "MYSQLI_TYPE_DATETIME", "MYSQLI_TYPE_YEAR", "MYSQLI_TYPE_NEWDATE",
- "MYSQLI_TYPE_ENUM", "MYSQLI_TYPE_SET", "MYSQLI_TYPE_TINY_BLOB",
- "MYSQLI_TYPE_MEDIUM_BLOB", "MYSQLI_TYPE_LONG_BLOB", "MYSQLI_TYPE_BLOB",
- "MYSQLI_TYPE_VAR_STRING", "MYSQLI_TYPE_STRING", "MYSQLI_TYPE_CHAR",
- "MYSQLI_TYPE_INTERVAL", "MYSQLI_TYPE_GEOMETRY", "MYSQLI_TYPE_NEWDECIMAL",
- "MYSQLI_TYPE_BIT", "MYSQLI_RPL_MASTER", "MYSQLI_RPL_SLAVE", "MYSQLI_RPL_ADMIN",
- "MYSQLI_NO_DATA", "MYSQLI_DATA_TRUNCATED", "MYSQLI_REPORT_INDEX",
- "MYSQLI_REPORT_ERROR", "MYSQLI_REPORT_STRICT", "MYSQLI_REPORT_ALL",
- "MYSQLI_REPORT_OFF", "AF_UNIX", "AF_INET", "AF_INET6", "SOCK_STREAM",
- "SOCK_DGRAM", "SOCK_RAW", "SOCK_SEQPACKET", "SOCK_RDM", "MSG_OOB",
- "MSG_WAITALL", "MSG_PEEK", "MSG_DONTROUTE", "SO_DEBUG", "SO_REUSEADDR",
- "SO_KEEPALIVE", "SO_DONTROUTE", "SO_LINGER", "SO_BROADCAST", "SO_OOBINLINE",
- "SO_SNDBUF", "SO_RCVBUF", "SO_SNDLOWAT", "SO_RCVLOWAT", "SO_SNDTIMEO",
- "SO_RCVTIMEO", "SO_TYPE", "SO_ERROR", "SOL_SOCKET", "SOMAXCONN",
- "PHP_NORMAL_READ", "PHP_BINARY_READ", "SOCKET_EINTR", "SOCKET_EBADF",
- "SOCKET_EACCES", "SOCKET_EFAULT", "SOCKET_EINVAL", "SOCKET_EMFILE",
- "SOCKET_EWOULDBLOCK", "SOCKET_EINPROGRESS", "SOCKET_EALREADY",
- "SOCKET_ENOTSOCK", "SOCKET_EDESTADDRREQ", "SOCKET_EMSGSIZE",
- "SOCKET_EPROTOTYPE", "SOCKET_ENOPROTOOPT", "SOCKET_EPROTONOSUPPORT",
- "SOCKET_ESOCKTNOSUPPORT", "SOCKET_EOPNOTSUPP", "SOCKET_EPFNOSUPPORT",
- "SOCKET_EAFNOSUPPORT", "SOCKET_EADDRINUSE", "SOCKET_EADDRNOTAVAIL",
- "SOCKET_ENETDOWN", "SOCKET_ENETUNREACH", "SOCKET_ENETRESET",
- "SOCKET_ECONNABORTED", "SOCKET_ECONNRESET", "SOCKET_ENOBUFS", "SOCKET_EISCONN",
- "SOCKET_ENOTCONN", "SOCKET_ESHUTDOWN", "SOCKET_ETOOMANYREFS",
- "SOCKET_ETIMEDOUT", "SOCKET_ECONNREFUSED", "SOCKET_ELOOP",
- "SOCKET_ENAMETOOLONG", "SOCKET_EHOSTDOWN", "SOCKET_EHOSTUNREACH",
- "SOCKET_ENOTEMPTY", "SOCKET_EPROCLIM", "SOCKET_EUSERS", "SOCKET_EDQUOT",
- "SOCKET_ESTALE", "SOCKET_EREMOTE", "SOCKET_EDISCON", "SOCKET_SYSNOTREADY",
- "SOCKET_VERNOTSUPPORTED", "SOCKET_NOTINITIALISED", "SOCKET_HOST_NOT_FOUND",
- "SOCKET_TRY_AGAIN", "SOCKET_NO_RECOVERY", "SOCKET_NO_DATA",
- "SOCKET_NO_ADDRESS", "SOL_TCP", "SOL_UDP", "EACCELERATOR_VERSION",
- "EACCELERATOR_SHM_AND_DISK", "EACCELERATOR_SHM", "EACCELERATOR_SHM_ONLY",
- "EACCELERATOR_DISK_ONLY", "EACCELERATOR_NONE", "XDEBUG_TRACE_APPEND",
- "XDEBUG_TRACE_COMPUTERIZED", "XDEBUG_TRACE_HTML", "XDEBUG_CC_UNUSED",
- "XDEBUG_CC_DEAD_CODE", "STDIN", "STDOUT", "STDERR",
- ].forEach(function(element, index, array) {
- result[element] = token("atom", "php-predefined-constant");
- });
-
- // PHP declared classes - output of get_declared_classes(). Differs from http://php.net/manual/en/reserved.classes.php
- [ "stdClass", "Exception", "ErrorException", "COMPersistHelper", "com_exception",
- "com_safearray_proxy", "variant", "com", "dotnet", "ReflectionException",
- "Reflection", "ReflectionFunctionAbstract", "ReflectionFunction",
- "ReflectionParameter", "ReflectionMethod", "ReflectionClass",
- "ReflectionObject", "ReflectionProperty", "ReflectionExtension", "DateTime",
- "DateTimeZone", "LibXMLError", "__PHP_Incomplete_Class", "php_user_filter",
- "Directory", "SimpleXMLElement", "DOMException", "DOMStringList",
- "DOMNameList", "DOMImplementationList", "DOMImplementationSource",
- "DOMImplementation", "DOMNode", "DOMNameSpaceNode", "DOMDocumentFragment",
- "DOMDocument", "DOMNodeList", "DOMNamedNodeMap", "DOMCharacterData", "DOMAttr",
- "DOMElement", "DOMText", "DOMComment", "DOMTypeinfo", "DOMUserDataHandler",
- "DOMDomError", "DOMErrorHandler", "DOMLocator", "DOMConfiguration",
- "DOMCdataSection", "DOMDocumentType", "DOMNotation", "DOMEntity",
- "DOMEntityReference", "DOMProcessingInstruction", "DOMStringExtend",
- "DOMXPath", "RecursiveIteratorIterator", "IteratorIterator", "FilterIterator",
- "RecursiveFilterIterator", "ParentIterator", "LimitIterator",
- "CachingIterator", "RecursiveCachingIterator", "NoRewindIterator",
- "AppendIterator", "InfiniteIterator", "RegexIterator",
- "RecursiveRegexIterator", "EmptyIterator", "ArrayObject", "ArrayIterator",
- "RecursiveArrayIterator", "SplFileInfo", "DirectoryIterator",
- "RecursiveDirectoryIterator", "SplFileObject", "SplTempFileObject",
- "SimpleXMLIterator", "LogicException", "BadFunctionCallException",
- "BadMethodCallException", "DomainException", "InvalidArgumentException",
- "LengthException", "OutOfRangeException", "RuntimeException",
- "OutOfBoundsException", "OverflowException", "RangeException",
- "UnderflowException", "UnexpectedValueException", "SplObjectStorage",
- "XMLReader", "XMLWriter", "mysqli_sql_exception", "mysqli_driver", "mysqli",
- "mysqli_warning", "mysqli_result", "mysqli_stmt", "PDOException", "PDO",
- "PDOStatement", "PDORow"
- ].forEach(function(element, index, array) {
- result[element] = token("t_string", "php-predefined-class");
- });
-
- return result;
-
- }();
-
- // Helper regexps
- var isOperatorChar = /[+*&%\/=<>!?.|-]/;
- var isHexDigit = /[0-9A-Fa-f]/;
- var isWordChar = /[\w\$_]/;
-
- // Wrapper around phpToken that helps maintain parser state (whether
- // we are inside of a multi-line comment)
- function phpTokenState(inside) {
- return function(source, setState) {
- var newInside = inside;
- var type = phpToken(inside, source, function(c) {newInside = c;});
- if (newInside != inside)
- setState(phpTokenState(newInside));
- return type;
- };
- }
-
- // The token reader, inteded to be used by the tokenizer from
- // tokenize.js (through phpTokenState). Advances the source stream
- // over a token, and returns an object containing the type and style
- // of that token.
- function phpToken(inside, source, setInside) {
- function readHexNumber(){
- source.next(); // skip the 'x'
- source.nextWhileMatches(isHexDigit);
- return {type: "number", style: "php-atom"};
- }
-
- function readNumber() {
- source.nextWhileMatches(/[0-9]/);
- if (source.equals(".")){
- source.next();
- source.nextWhileMatches(/[0-9]/);
- }
- if (source.equals("e") || source.equals("E")){
- source.next();
- if (source.equals("-"))
- source.next();
- source.nextWhileMatches(/[0-9]/);
- }
- return {type: "number", style: "php-atom"};
- }
- // Read a word and look it up in the keywords array. If found, it's a
- // keyword of that type; otherwise it's a PHP T_STRING.
- function readWord() {
- source.nextWhileMatches(isWordChar);
- var word = source.get();
- var known = keywords.hasOwnProperty(word) && keywords.propertyIsEnumerable(word) && keywords[word];
- // since we called get(), tokenize::take won't get() anything. Thus, we must set token.content
- return known ? {type: known.type, style: known.style, content: word} :
- {type: "t_string", style: "php-t_string", content: word};
- }
- function readVariable() {
- source.nextWhileMatches(isWordChar);
- var word = source.get();
- // in PHP, '$this' is a reserved word, but 'this' isn't. You can have function this() {...}
- if (word == "$this")
- return {type: "variable", style: "php-keyword", content: word};
- else
- return {type: "variable", style: "php-variable", content: word};
- }
-
- // Advance the stream until the given character (not preceded by a
- // backslash) is encountered, or the end of the line is reached.
- function nextUntilUnescaped(source, end) {
- var escaped = false;
- var next;
- while(!source.endOfLine()){
- var next = source.next();
- if (next == end && !escaped)
- return false;
- escaped = next == "\\";
- }
- return escaped;
- }
-
- function readSingleLineComment() {
- // read until the end of the line or until ?>, which terminates single-line comments
- // `<?php echo 1; // comment ?> foo` will display "1 foo"
- while(!source.lookAhead("?>") && !source.endOfLine())
- source.next();
- return {type: "comment", style: "php-comment"};
- }
- /* For multi-line comments, we want to return a comment token for
- every line of the comment, but we also want to return the newlines
- in them as regular newline tokens. We therefore need to save a
- state variable ("inside") to indicate whether we are inside a
- multi-line comment.
- */
-
- function readMultilineComment(start){
- var newInside = "/*";
- var maybeEnd = (start == "*");
- while (true) {
- if (source.endOfLine())
- break;
- var next = source.next();
- if (next == "/" && maybeEnd){
- newInside = null;
- break;
- }
- maybeEnd = (next == "*");
- }
- setInside(newInside);
- return {type: "comment", style: "php-comment"};
- }
-
- // similar to readMultilineComment and nextUntilUnescaped
- // unlike comments, strings are not stopped by ?>
- function readMultilineString(start){
- var newInside = start;
- var escaped = false;
- while (true) {
- if (source.endOfLine())
- break;
- var next = source.next();
- if (next == start && !escaped){
- newInside = null; // we're outside of the string now
- break;
- }
- escaped = (next == "\\");
- }
- setInside(newInside);
- return {
- type: newInside == null? "string" : "string_not_terminated",
- style: (start == "'"? "php-string-single-quoted" : "php-string-double-quoted")
- };
- }
-
- // http://php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc
- // See also 'nowdoc' on the page. Heredocs are not interrupted by the '?>' token.
- function readHeredoc(identifier){
- var token = {};
- if (identifier == "<<<") {
- // on our first invocation after reading the <<<, we must determine the closing identifier
- if (source.equals("'")) {
- // nowdoc
- source.nextWhileMatches(isWordChar);
- identifier = "'" + source.get() + "'";
- source.next(); // consume the closing "'"
- } else if (source.matches(/[A-Za-z_]/)) {
- // heredoc
- source.nextWhileMatches(isWordChar);
- identifier = source.get();
- } else {
- // syntax error
- setInside(null);
- return { type: "error", style: "syntax-error" };
- }
- setInside(identifier);
- token.type = "string_not_terminated";
- token.style = identifier.charAt(0) == "'"? "php-string-single-quoted" : "php-string-double-quoted";
- token.content = identifier;
- } else {
- token.style = identifier.charAt(0) == "'"? "php-string-single-quoted" : "php-string-double-quoted";
- // consume a line of heredoc and check if it equals the closing identifier plus an optional semicolon
- if (source.lookAhead(identifier, true) && (source.lookAhead(";\n") || source.endOfLine())) {
- // the closing identifier can only appear at the beginning of the line
- // note that even whitespace after the ";" is forbidden by the PHP heredoc syntax
- token.type = "string";
- token.content = source.get(); // don't get the ";" if there is one
- setInside(null);
- } else {
- token.type = "string_not_terminated";
- source.nextWhileMatches(/[^\n]/);
- token.content = source.get();
- }
- }
- return token;
- }
-
- function readOperator() {
- source.nextWhileMatches(isOperatorChar);
- return {type: "operator", style: "php-operator"};
- }
- function readStringSingleQuoted() {
- var endBackSlash = nextUntilUnescaped(source, "'", false);
- setInside(endBackSlash ? "'" : null);
- return {type: "string", style: "php-string-single-quoted"};
- }
- function readStringDoubleQuoted() {
- var endBackSlash = nextUntilUnescaped(source, "\"", false);
- setInside(endBackSlash ? "\"": null);
- return {type: "string", style: "php-string-double-quoted"};
- }
-
- // Fetch the next token. Dispatches on first character in the
- // stream, or first two characters when the first is a slash.
- switch (inside) {
- case null:
- case false: break;
- case "'":
- case "\"": return readMultilineString(inside);
- case "/*": return readMultilineComment(source.next());
- default: return readHeredoc(inside);
- }
- var ch = source.next();
- if (ch == "'" || ch == "\"")
- return readMultilineString(ch)
- else if (ch == "#")
- return readSingleLineComment();
- else if (ch == "$")
- return readVariable();
- else if (ch == ":" && source.equals(":")) {
- source.next();
- // the T_DOUBLE_COLON can only follow a T_STRING (class name)
- return {type: "t_double_colon", style: "php-operator"}
- }
- // with punctuation, the type of the token is the symbol itself
- else if (/[\[\]{}\(\),;:]/.test(ch)) {
- return {type: ch, style: "php-punctuation"};
- }
- else if (ch == "0" && (source.equals("x") || source.equals("X")))
- return readHexNumber();
- else if (/[0-9]/.test(ch))
- return readNumber();
- else if (ch == "/") {
- if (source.equals("*"))
- { source.next(); return readMultilineComment(ch); }
- else if (source.equals("/"))
- return readSingleLineComment();
- else
- return readOperator();
- }
- else if (ch == "<") {
- if (source.lookAhead("<<", true)) {
- setInside("<<<");
- return {type: "<<<", style: "php-punctuation"};
- }
- else
- return readOperator();
- }
- else if (isOperatorChar.test(ch))
- return readOperator();
- else
- return readWord();
- }
-
- // The external interface to the tokenizer.
- return function(source, startState) {
- return tokenizer(source, startState || phpTokenState(false, true));
- };
-})();
diff --git a/media/CodeMirror-0.62/contrib/python/LICENSE b/media/CodeMirror-0.62/contrib/python/LICENSE
deleted file mode 100644
index c237889..0000000
--- a/media/CodeMirror-0.62/contrib/python/LICENSE
+++ /dev/null
@@ -1,32 +0,0 @@
-Copyright (c) 2009, Timothy Farrell
-All rights reserved.
-
-This software is provided for use in connection with the
-CodeMirror suite of modules and utilities, hosted and maintained
-at http://marijn.haverbeke.nl/codemirror/.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
- copyright notice, this list of conditions and the
- following disclaimer.
-
-* Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
diff --git a/media/CodeMirror-0.62/contrib/python/css/pythoncolors.css b/media/CodeMirror-0.62/contrib/python/css/pythoncolors.css
deleted file mode 100644
index a642a6a..0000000
--- a/media/CodeMirror-0.62/contrib/python/css/pythoncolors.css
+++ /dev/null
@@ -1,54 +0,0 @@
-.editbox {
- padding: .4em;
- margin: 0;
- font-family: monospace;
- font-size: 10pt;
- line-height: 1.1em;
- color: black;
-}
-
-pre.code, .editbox {
- color: #666666;
-}
-
-.editbox p {
- margin: 0;
-}
-
-span.py-delimiter, span.py-special {
- color: #666666;
-}
-
-span.py-operator {
- color: #666666;
-}
-
-span.py-error {
- background-color: #660000;
- color: #FFFFFF;
-}
-
-span.py-keyword {
- color: #770088;
- font-weight: bold;
-}
-
-span.py-literal {
- color: #228811;
-}
-
-span.py-identifier, span.py-func {
- color: black;
-}
-
-span.py-type, span.py-decorator {
- color: #0000FF;
-}
-
-span.py-comment {
- color: #AA7700;
-}
-
-span.py-string, span.py-bytes, span.py-raw, span.py-unicode {
- color: #AA2222;
-}
diff --git a/media/CodeMirror-0.62/contrib/python/index.html b/media/CodeMirror-0.62/contrib/python/index.html
deleted file mode 100644
index 31d2f0a..0000000
--- a/media/CodeMirror-0.62/contrib/python/index.html
+++ /dev/null
@@ -1,141 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
- <script src="../../js/codemirror.js" type="text/javascript"></script>
- <title>CodeMirror: Python demonstration</title>
- <style type="text/css">
- .CodeMirror-line-numbers {
- width: 2.2em;
- color: #aaa;
- background-color: #eee;
- text-align: right;
- padding: .4em;
- margin: 0;
- font-family: monospace;
- font-size: 10pt;
- line-height: 1.1em;
- }
- </style>
-</head>
-<body style="padding: 20px;">
-<p>
- This is a simple demonstration of the Python syntax highlighting module
- for <a href="index.html">CodeMirror</a>.
-</p>
-<p>
- Features of this parser include:
-</p>
-<ul>
- <li>Token-based syntax highlighting - currently very little lexical analysis happens. Few lexical errors will be detected.</li>
- <li>Use the normal indentation mode to enforce regular indentation, otherwise the "shift" indentation mode will give you more flexibility.</li>
- <li>Parser Options:
- <ul>
- <li>pythonVersion (Integer) - 2 or 3 to indicate which version of Python to parse. Default = 2</li>
- <li>strictErrors (Bool) - true to highlight errors that may not be Python errors but cause confusion for this parser. Default = true</li>
- </ul>
- </li>
-</ul>
-<p>Written by Timothy Farrell (<a href="LICENSE">license</a>). Special
-thanks to Adam Brand and Marijn Haverbeke for their help in debugging
-and providing for this parser.</p>
-
-<div style="border: 1px solid black; padding: 0px;">
-<textarea id="code" cols="100" rows="20" style="width:100%">
-# Literals
-1234
-0.0e101
-.123
-0b01010011100
-0o01234567
-0x0987654321abcdef
-# Error Literals
-.0b000
-0.0e
-0e
-
-# String Literals
-'For\''
-"God\""
-"""so loved
-the world"""
-'''that he gave
-his only begotten\' '''
-'that whosoever believeth \
-in him'
-''
-
-# Identifiers
-__a__
-a.b
-a.b.c
-# Error Identifiers
-a.
-
-# Operators
-+ - * / % & | ^ ~ < >
-== != <= >= <> << >> // **
-and or not in is
-
-# Delimiters
-() [] {} , : ` = ; @ . # At-signs and periods require context
-+= -= *= /= %= &= |= ^=
-//= >>= <<= **=
-
-# Keywords
-as assert break class continue def del elif else except
-finally for from global if import lambda pass raise
-return try while with yield
-
-# Python 2 Keywords (otherwise Identifiers)
-exec print
-
-# Python 3 Keywords (otherwise Identifiers)
-nonlocal
-
-# Types
-bool classmethod complex dict enumerate float frozenset int list object
-property reversed set slice staticmethod str super tuple type
-
-# Python 2 Types (otherwise Identifiers)
-basestring buffer file long unicode xrange
-
-# Python 3 Types (otherwise Identifiers)
-bytearray bytes filter map memoryview open range zip
-
-# Example Strict Errors
-def doesNothing():
- pass # indentUnit is set to 4 but this line is indented 3
-
-# Some Example code
-import os
-from package import ParentClass
-
-@nonsenseDecorator
-def doesNothing():
- pass
-
-class ExampleClass(ParentClass):
- @staticmethod
- def example(inputStr):
- a = list(inputStr)
- a.reverse()
- return ''.join(a)
-
- def __init__(self, mixin = 'Hello'):
- self.mixin = mixin
-
-</textarea>
-</div>
-
-<script type="text/javascript">
- var editor = CodeMirror.fromTextArea('code', {
- parserfile: ["../contrib/python/js/parsepython.js"],
- stylesheet: "css/pythoncolors.css",
- path: "../../js/",
- lineNumbers: true,
- textWrapping: false,
- indentUnit: 4,
- parserConfig: {'pythonVersion': 2, 'strictErrors': true}
- });
-</script>
-</body>
-</html>
diff --git a/media/CodeMirror-0.62/contrib/python/js/parsepython.js b/media/CodeMirror-0.62/contrib/python/js/parsepython.js
deleted file mode 100644
index 4847c76..0000000
--- a/media/CodeMirror-0.62/contrib/python/js/parsepython.js
+++ /dev/null
@@ -1,544 +0,0 @@
-var PythonParser = Editor.Parser = (function() {
- function wordRegexp(words) {
- return new RegExp("^(?:" + words.join("|") + ")$");
- }
- var DELIMITERCLASS = 'py-delimiter';
- var LITERALCLASS = 'py-literal';
- var ERRORCLASS = 'py-error';
- var OPERATORCLASS = 'py-operator';
- var IDENTIFIERCLASS = 'py-identifier';
- var STRINGCLASS = 'py-string';
- var BYTESCLASS = 'py-bytes';
- var UNICODECLASS = 'py-unicode';
- var RAWCLASS = 'py-raw';
- var NORMALCONTEXT = 'normal';
- var STRINGCONTEXT = 'string';
- var singleOperators = '+-*/%&|^~<>';
- var doubleOperators = wordRegexp(['==', '!=', '\\<=', '\\>=', '\\<\\>',
- '\\<\\<', '\\>\\>', '\\/\\/', '\\*\\*']);
- var singleDelimiters = '()[]{}@,:.`=;';
- var doubleDelimiters = ['\\+=', '\\-=', '\\*=', '/=', '%=', '&=', '\\|=',
- '\\^='];
- var tripleDelimiters = wordRegexp(['//=','\\>\\>=','\\<\\<=','\\*\\*=']);
- var singleStarters = singleOperators + singleDelimiters + '=!';
- var doubleStarters = '=<>*/';
- var identifierStarters = /[_A-Za-z]/;
-
- var wordOperators = wordRegexp(['and', 'or', 'not', 'is', 'in']);
- var commonkeywords = ['as', 'assert', 'break', 'class', 'continue',
- 'def', 'del', 'elif', 'else', 'except', 'finally',
- 'for', 'from', 'global', 'if', 'import',
- 'lambda', 'pass', 'raise', 'return',
- 'try', 'while', 'with', 'yield'];
- var commontypes = ['bool', 'classmethod', 'complex', 'dict', 'enumerate',
- 'float', 'frozenset', 'int', 'list', 'object',
- 'property', 'reversed', 'set', 'slice', 'staticmethod',
- 'str', 'super', 'tuple', 'type'];
- var py2 = {'types': ['basestring', 'buffer', 'file', 'long', 'unicode',
- 'xrange'],
- 'keywords': ['exec', 'print'],
- 'version': 2 };
- var py3 = {'types': ['bytearray', 'bytes', 'filter', 'map', 'memoryview',
- 'open', 'range', 'zip'],
- 'keywords': ['nonlocal'],
- 'version': 3};
-
- var py, keywords, types, stringStarters, stringTypes, config;
-
- function configure(conf) {
- if (!conf.hasOwnProperty('pythonVersion')) {
- conf.pythonVersion = 2;
- }
- if (!conf.hasOwnProperty('strictErrors')) {
- conf.strictErrors = true;
- }
- if (conf.pythonVersion != 2 && conf.pythonVersion != 3) {
- alert('CodeMirror: Unknown Python Version "' +
- conf.pythonVersion +
- '", defaulting to Python 2.x.');
- conf.pythonVersion = 2;
- }
- if (conf.pythonVersion == 3) {
- py = py3;
- stringStarters = /[\'\"rbRB]/;
- stringTypes = /[rb]/;
- doubleDelimiters.push('\\-\\>');
- } else {
- py = py2;
- stringStarters = /['"RUru]/;
- stringTypes = /[ru]/;
- }
- config = conf;
- keywords = wordRegexp(commonkeywords.concat(py.keywords));
- types = wordRegexp(commontypes.concat(py.types));
- doubleDelimiters = wordRegexp(doubleDelimiters);
- }
-
- var tokenizePython = (function() {
- function normal(source, setState) {
- var stringDelim, threeStr, temp, type, word, possible = {};
- var ch = source.next();
-
- function filterPossible(token, styleIfPossible) {
- if (!possible.style && !possible.content) {
- return token;
- } else if (typeof(token) == STRINGCONTEXT) {
- token = {content: source.get(), style: token};
- }
- if (possible.style || styleIfPossible) {
- token.style = styleIfPossible ? styleIfPossible : possible.style;
- }
- if (possible.content) {
- token.content = possible.content + token.content;
- }
- possible = {};
- return token;
- }
-
- // Handle comments
- if (ch == '#') {
- while (!source.endOfLine()) {
- source.next();
- }
- return 'py-comment';
- }
- // Handle special chars
- if (ch == '\\') {
- if (source.peek() != '\n') {
- var whitespace = true;
- while (!source.endOfLine()) {
- if(!(/\s/.test(source.next()))) {
- whitespace = false;
- }
- }
- if (!whitespace) {
- return ERRORCLASS;
- }
- }
- return 'py-special';
- }
- // Handle operators and delimiters
- if (singleStarters.indexOf(ch) != -1) {
- if (doubleStarters.indexOf(source.peek()) != -1) {
- temp = ch + source.peek();
- // It must be a double delimiter or operator or triple delimiter
- if (doubleOperators.test(temp)) {
- source.next();
- if (tripleDelimiters.test(temp + source.peek())) {
- source.next();
- return DELIMITERCLASS;
- } else {
- return OPERATORCLASS;
- }
- } else if (doubleDelimiters.test(temp)) {
- source.next();
- return DELIMITERCLASS;
- }
- }
- // It must be a single delimiter or operator
- if (singleOperators.indexOf(ch) != -1) {
- return OPERATORCLASS;
- } else if (singleDelimiters.indexOf(ch) != -1) {
- if (ch == '@' && /\w/.test(source.peek())) {
- possible = {style:'py-decorator',
- content: source.get()};
- ch = source.next();
- } else if (ch == '.' && /\d/.test(source.peek())) {
- possible = {style:LITERALCLASS,
- content: source.get()};
- ch = source.next();
- } else {
- return DELIMITERCLASS;
- }
- } else {
- return ERRORCLASS;
- }
- }
- // Handle number literals
- if (/\d/.test(ch)) {
- if (ch === '0' && !source.endOfLine()) {
- switch (source.peek()) {
- case 'o':
- case 'O':
- source.next();
- source.nextWhileMatches(/[0-7]/);
- return filterPossible(LITERALCLASS, ERRORCLASS);
- case 'x':
- case 'X':
- source.next();
- source.nextWhileMatches(/[0-9A-Fa-f]/);
- return filterPossible(LITERALCLASS, ERRORCLASS);
- case 'b':
- case 'B':
- source.next();
- source.nextWhileMatches(/[01]/);
- return filterPossible(LITERALCLASS, ERRORCLASS);
- }
- }
- source.nextWhileMatches(/\d/);
- if (source.peek() == '.') {
- source.next();
- source.nextWhileMatches(/\d/);
- }
- // Grab an exponent
- if (source.peek().toLowerCase() == 'e') {
- source.next();
- if (source.peek() == '+' || source.peek() == '-') {
- source.next();
- }
- if (/\d/.test(source.peek())) {
- source.nextWhileMatches(/\d/);
- } else {
- return filterPossible(ERRORCLASS);
- }
- }
- // Grab a complex number
- if (source.peek().toLowerCase() == 'j') {
- source.next();
- }
-
- return filterPossible(LITERALCLASS);
- }
- // Handle strings
- if (stringStarters.test(ch)) {
- var peek = source.peek();
- var stringType = STRINGCLASS;
- if ((stringTypes.test(ch)) && (peek == '"' || peek == "'")) {
- switch (ch.toLowerCase()) {
- case 'b':
- stringType = BYTESCLASS;
- break;
- case 'r':
- stringType = RAWCLASS;
- break;
- case 'u':
- stringType = UNICODECLASS;
- break;
- }
- ch = source.next();
- stringDelim = ch;
- if (source.peek() != stringDelim) {
- setState(inString(stringType, stringDelim));
- return null;
- } else {
- source.next();
- if (source.peek() == stringDelim) {
- source.next();
- threeStr = stringDelim + stringDelim + stringDelim;
- setState(inString(stringType, threeStr));
- return null;
- } else {
- return stringType;
- }
- }
- } else if (ch == "'" || ch == '"') {
- stringDelim = ch;
- if (source.peek() != stringDelim) {
- setState(inString(stringType, stringDelim));
- return null;
- } else {
- source.next();
- if (source.peek() == stringDelim) {
- source.next();
- threeStr = stringDelim + stringDelim + stringDelim;
- setState(inString(stringType, threeStr));
- return null;
- } else {
- return stringType;
- }
- }
- }
- }
- // Handle Identifier
- if (identifierStarters.test(ch)) {
- source.nextWhileMatches(/[\w\d]/);
- word = source.get();
- if (wordOperators.test(word)) {
- type = OPERATORCLASS;
- } else if (keywords.test(word)) {
- type = 'py-keyword';
- } else if (types.test(word)) {
- type = 'py-type';
- } else {
- type = IDENTIFIERCLASS;
- while (source.peek() == '.') {
- source.next();
- if (identifierStarters.test(source.peek())) {
- source.nextWhileMatches(/[\w\d]/);
- } else {
- type = ERRORCLASS;
- break;
- }
- }
- word = word + source.get();
- }
- return filterPossible({style: type, content: word});
- }
-
- // Register Dollar sign and Question mark as errors. Always!
- if (/\$\?/.test(ch)) {
- return filterPossible(ERRORCLASS);
- }
-
- return filterPossible(ERRORCLASS);
- }
-
- function inString(style, terminator) {
- return function(source, setState) {
- var matches = [];
- var found = false;
- while (!found && !source.endOfLine()) {
- var ch = source.next(), newMatches = [];
- // Skip escaped characters
- if (ch == '\\') {
- if (source.peek() == '\n') {
- break;
- }
- ch = source.next();
- ch = source.next();
- }
- if (ch == terminator.charAt(0)) {
- matches.push(terminator);
- }
- for (var i = 0; i < matches.length; i++) {
- var match = matches[i];
- if (match.charAt(0) == ch) {
- if (match.length == 1) {
- setState(normal);
- found = true;
- break;
- } else {
- newMatches.push(match.slice(1));
- }
- }
- }
- matches = newMatches;
- }
- return style;
- };
- }
-
- return function(source, startState) {
- return tokenizer(source, startState || normal);
- };
- })();
-
- function parsePython(source) {
- if (!keywords) {
- configure({});
- }
-
- var tokens = tokenizePython(source);
- var lastToken = null;
- var column = 0;
- var context = {prev: null,
- endOfScope: false,
- startNewScope: false,
- level: 0,
- next: null,
- type: NORMALCONTEXT
- };
-
- function pushContext(level, type) {
- type = type ? type : NORMALCONTEXT;
- context = {prev: context,
- endOfScope: false,
- startNewScope: false,
- level: level,
- next: null,
- type: type
- };
- }
-
- function popContext(remove) {
- remove = remove ? remove : false;
- if (context.prev) {
- if (remove) {
- context = context.prev;
- context.next = null;
- } else {
- context.prev.next = context;
- context = context.prev;
- }
- }
- }
-
- function indentPython(context) {
- var temp;
- return function(nextChars, currentLevel, direction) {
- if (direction === null || direction === undefined) {
- if (nextChars) {
- while (context.next) {
- context = context.next;
- }
- }
- return context.level;
- }
- else if (direction === true) {
- if (currentLevel == context.level) {
- if (context.next) {
- return context.next.level;
- } else {
- return context.level;
- }
- } else {
- temp = context;
- while (temp.prev && temp.prev.level > currentLevel) {
- temp = temp.prev;
- }
- return temp.level;
- }
- } else if (direction === false) {
- if (currentLevel > context.level) {
- return context.level;
- } else if (context.prev) {
- temp = context;
- while (temp.prev && temp.prev.level >= currentLevel) {
- temp = temp.prev;
- }
- if (temp.prev) {
- return temp.prev.level;
- } else {
- return temp.level;
- }
- }
- }
- return context.level;
- };
- }
-
- var iter = {
- next: function() {
- var token = tokens.next();
- var type = token.style;
- var content = token.content;
-
- if (lastToken) {
- if (lastToken.content == 'def' && type == IDENTIFIERCLASS) {
- token.style = 'py-func';
- }
- if (lastToken.content == '\n') {
- var tempCtx = context;
- // Check for a different scope
- if (type == 'whitespace' && context.type == NORMALCONTEXT) {
- if (token.value.length < context.level) {
- while (token.value.length < context.level) {
- popContext();
- }
-
- if (token.value.length != context.level) {
- context = tempCtx;
- if (config.strictErrors) {
- token.style = ERRORCLASS;
- }
- } else {
- context.next = null;
- }
- }
- } else if (context.level !== 0 &&
- context.type == NORMALCONTEXT) {
- while (0 !== context.level) {
- popContext();
- }
-
- if (context.level !== 0) {
- context = tempCtx;
- if (config.strictErrors) {
- token.style = ERRORCLASS;
- }
- }
- }
- }
- }
-
- // Handle Scope Changes
- switch(type) {
- case STRINGCLASS:
- case BYTESCLASS:
- case RAWCLASS:
- case UNICODECLASS:
- if (context.type !== STRINGCONTEXT) {
- pushContext(context.level + 1, STRINGCONTEXT);
- }
- break;
- default:
- if (context.type === STRINGCONTEXT) {
- popContext(true);
- }
- break;
- }
- switch(content) {
- case '.':
- case '@':
- // These delimiters don't appear by themselves
- if (content !== token.value) {
- token.style = ERRORCLASS;
- }
- break;
- case ':':
- // Colons only delimit scope inside a normal scope
- if (context.type === NORMALCONTEXT) {
- context.startNewScope = context.level+indentUnit;
- }
- break;
- case '(':
- case '[':
- case '{':
- // These start a sequence scope
- pushContext(column + content.length, 'sequence');
- break;
- case ')':
- case ']':
- case '}':
- // These end a sequence scope
- popContext(true);
- break;
- case 'pass':
- case 'return':
- // These end a normal scope
- if (context.type === NORMALCONTEXT) {
- context.endOfScope = true;
- }
- break;
- case '\n':
- // Reset our column
- column = 0;
- // Make any scope changes
- if (context.endOfScope) {
- context.endOfScope = false;
- popContext();
- } else if (context.startNewScope !== false) {
- var temp = context.startNewScope;
- context.startNewScope = false;
- pushContext(temp, NORMALCONTEXT);
- }
- // Newlines require an indentation function wrapped in a closure for proper context.
- token.indentation = indentPython(context);
- break;
- }
-
- // Keep track of current column for certain scopes.
- if (content != '\n') {
- column += token.value.length;
- }
-
- lastToken = token;
- return token;
- },
-
- copy: function() {
- var _context = context, _tokenState = tokens.state;
- return function(source) {
- tokens = tokenizePython(source, _tokenState);
- context = _context;
- return iter;
- };
- }
- };
- return iter;
- }
-
- return {make: parsePython,
- electricChars: "",
- configure: configure};
-})();
diff --git a/media/CodeMirror-0.62/css/csscolors.css b/media/CodeMirror-0.62/css/csscolors.css
deleted file mode 100644
index 100c93f..0000000
--- a/media/CodeMirror-0.62/css/csscolors.css
+++ /dev/null
@@ -1,47 +0,0 @@
-.editbox {
- margin: .4em;
- padding: 0;
- font-family: monospace;
- font-size: 10pt;
- color: black;
-}
-
-pre.code, .editbox {
- color: #666666;
-}
-
-.editbox p {
- margin: 0;
-}
-
-span.css-at {
- color: #770088;
-}
-
-span.css-unit {
- color: #228811;
-}
-
-span.css-value {
- color: #770088;
-}
-
-span.css-identifier {
- color: black;
-}
-
-span.css-important {
- color: #0000FF;
-}
-
-span.css-colorcode {
- color: #004499;
-}
-
-span.css-comment {
- color: #AA7700;
-}
-
-span.css-string {
- color: #AA2222;
-}
diff --git a/media/CodeMirror-0.62/css/docs.css b/media/CodeMirror-0.62/css/docs.css
deleted file mode 100644
index c86b7d7..0000000
--- a/media/CodeMirror-0.62/css/docs.css
+++ /dev/null
@@ -1,46 +0,0 @@
-body {
- margin: 0;
- padding: 3em 6em;
- color: black;
- max-width: 50em;
-}
-
-h1 {
- font-size: 22pt;
-}
-
-.underline {
- border-bottom: 3px solid #C44;
-}
-
-h2 {
- font-size: 14pt;
-}
-
-p.rel {
- padding-left: 2em;
- text-indent: -2em;
-}
-
-div.border {
- border: 1px solid black;
- padding: 3px;
-}
-
-code {
- font-family: courier, monospace;
- font-size: 90%;
- color: #144;
-}
-
-pre.code {
- margin: 1.1em 12px;
- border: 1px solid #CCCCCC;
- color: black;
- padding: .4em;
- font-family: courier, monospace;
-}
-
-.warn {
- color: #C00;
-}
diff --git a/media/CodeMirror-0.62/css/jscolors.css b/media/CodeMirror-0.62/css/jscolors.css
deleted file mode 100644
index 3067628..0000000
--- a/media/CodeMirror-0.62/css/jscolors.css
+++ /dev/null
@@ -1,55 +0,0 @@
-.editbox {
- margin: .4em;
- padding: 0;
- font-family: monospace;
- font-size: 10pt;
- color: black;
-}
-
-pre.code, .editbox {
- color: #666666;
-}
-
-.editbox p {
- margin: 0;
-}
-
-span.js-punctuation {
- color: #666666;
-}
-
-span.js-operator {
- color: #666666;
-}
-
-span.js-keyword {
- color: #770088;
-}
-
-span.js-atom {
- color: #228811;
-}
-
-span.js-variable {
- color: black;
-}
-
-span.js-variabledef {
- color: #0000FF;
-}
-
-span.js-localvariable {
- color: #004499;
-}
-
-span.js-property {
- color: black;
-}
-
-span.js-comment {
- color: #AA7700;
-}
-
-span.js-string {
- color: #AA2222;
-}
diff --git a/media/CodeMirror-0.62/css/people.jpg b/media/CodeMirror-0.62/css/people.jpg
deleted file mode 100644
index 7347895..0000000
--- a/media/CodeMirror-0.62/css/people.jpg
+++ /dev/null
Binary files differ
diff --git a/media/CodeMirror-0.62/css/sparqlcolors.css b/media/CodeMirror-0.62/css/sparqlcolors.css
deleted file mode 100644
index 78d8ae0..0000000
--- a/media/CodeMirror-0.62/css/sparqlcolors.css
+++ /dev/null
@@ -1,39 +0,0 @@
-.editbox {
- margin: .4em;
- padding: 0;
- font-family: monospace;
- font-size: 10pt;
- color: black;
-}
-
-.editbox p {
- margin: 0;
-}
-
-span.sp-keyword {
- color: #708;
-}
-
-span.sp-prefixed {
- color: #5d1;
-}
-
-span.sp-var {
- color: #00c;
-}
-
-span.sp-comment {
- color: #a70;
-}
-
-span.sp-literal {
- color: #a22;
-}
-
-span.sp-uri {
- color: #292;
-}
-
-span.sp-operator {
- color: #088;
-}
diff --git a/media/CodeMirror-0.62/css/survexcolors.css b/media/CodeMirror-0.62/css/survexcolors.css
deleted file mode 100644
index d54a198..0000000
--- a/media/CodeMirror-0.62/css/survexcolors.css
+++ /dev/null
@@ -1,71 +0,0 @@
-.editbox {
- margin: .4em;
- padding: 0;
- font-family: monospace;
- font-size: 10pt;
- color: black;
-}
-
-
-pre.code, .editbox {
- color: #666666;
-}
-
-.editbox p {
- margin: 0;
-}
-
-span.svx-command {
- color: red;
-}
-span.svx-begin, span.svx-end {
- color: #990000;
-}
-span.svx-comment {
- color: blue;
-}
-span.svx-measure {
- color: green;
-}
-span.svx-station {
- color: #009900;
-}
-span.svx-string {
- color: blue;
-}
-span.svx-word {
- color: black;
-}
-
-
-span.css-at {
- color: #770088;
-}
-
-span.css-unit {
- color: #228811;
-}
-
-span.css-value {
- color: #770088;
-}
-
-span.css-identifier {
- color: black;
-}
-
-span.css-important {
- color: #0000FF;
-}
-
-span.css-colorcode {
- color: #004499;
-}
-
-span.css-comment {
- color: #AA7700;
-}
-
-span.css-string {
- color: #AA2222;
-}
diff --git a/media/CodeMirror-0.62/css/xmlcolors.css b/media/CodeMirror-0.62/css/xmlcolors.css
deleted file mode 100644
index aa26579..0000000
--- a/media/CodeMirror-0.62/css/xmlcolors.css
+++ /dev/null
@@ -1,51 +0,0 @@
-.editbox {
- margin: .4em;
- padding: 0;
- font-family: monospace;
- font-size: 10pt;
- color: black;
-}
-
-.editbox p {
- margin: 0;
-}
-
-span.xml-tagname {
- color: #A0B;
-}
-
-span.xml-attribute {
- color: #281;
-}
-
-span.xml-punctuation {
- color: black;
-}
-
-span.xml-attname {
- color: #00F;
-}
-
-span.xml-comment {
- color: #A70;
-}
-
-span.xml-cdata {
- color: #48A;
-}
-
-span.xml-processing {
- color: #999;
-}
-
-span.xml-entity {
- color: #A22;
-}
-
-span.xml-error {
- color: #F00;
-}
-
-span.xml-text {
- color: black;
-}
diff --git a/media/CodeMirror-0.62/csstest.html b/media/CodeMirror-0.62/csstest.html
deleted file mode 100644
index cb031a0..0000000
--- a/media/CodeMirror-0.62/csstest.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <script src="js/codemirror.js" type="text/javascript"></script>
- <title>CodeMirror: CSS demonstration</title>
- <link rel="stylesheet" type="text/css" href="css/docs.css"/>
- </head>
- <body style="padding: 20px;">
-
-<p>Demonstration of <a href="index.html">CodeMirror</a>'s CSS
-highlighter.</p>
-
-<div class="border">
-<textarea id="code" cols="120" rows="30">
-/* Some example CSS */
-
-@import url("something.css");
-
-body {
- margin: 0;
- padding: 3em 6em;
- font-family: tahoma, arial, sans-serif;
- color: #000;
-}
-
-#navigation a {
- font-weight: bold;
- text-decoration: none !important;
-}
-
-h1 {
- font-size: 2.5em;
-}
-
-h2 {
- font-size: 1.7em;
-}
-
-h1:before, h2:before {
- content: "::";
-}
-
-code {
- font-family: courier, monospace;
- font-size: 80%;
- color: #418A8A;
-}
-</textarea>
-</div>
-
-<script type="text/javascript">
- var editor = CodeMirror.fromTextArea('code', {
- height: "350px",
- parserfile: "parsecss.js",
- stylesheet: "css/csscolors.css",
- path: "js/"
- });
-</script>
-
- </body>
-</html>
diff --git a/media/CodeMirror-0.62/highlight.html b/media/CodeMirror-0.62/highlight.html
deleted file mode 100644
index 6f1dd34..0000000
--- a/media/CodeMirror-0.62/highlight.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <script src="js/highlight.js" type="text/javascript"></script>
- <script src="js/stringstream.js" type="text/javascript"></script>
- <script src="js/tokenize.js" type="text/javascript"></script>
- <script src="js/tokenizejavascript.js" type="text/javascript"></script>
- <script src="js/parsejavascript.js" type="text/javascript"></script>
- <title>CodeMirror: String highlight demonstration</title>
- <link rel="stylesheet" type="text/css" href="css/jscolors.css"/>
- </head>
- <body style="padding: 20px;">
-
-<div style="border: 1px solid black; padding: .4em;">
-<textarea id="code" cols="120" rows="20" style="border-width: 0">
-// Demo for running a CodeMirror parser over a piece of code without
-// creating an actual editor.
-
-(function(){
- function normaliseString(string) {
- var tab = "";
- for (var i = 0; i &lt; indentUnit; i++) tab += " ";
-
- string = string.replace(/\t/g, tab).replace(/\u00a0/g, " ").replace(/\r\n?/g, "\n");
- var pos = 0, parts = [], lines = string.split("\n");
- for (var line = 0; line &lt; lines.length; line++) {
- if (line != 0) parts.push("\n");
- parts.push(lines[line]);
- }
-
- return {
- next: function() {
- if (pos &lt; parts.length) return parts[pos++];
- else throw StopIteration;
- }
- };
- }
-
- window.highlightText = function(string, output, parser) {
- var parser = (parser || Editor.Parser).make(stringStream(normaliseString(string)));
- try {
- while (true) {
- var token = parser.next();
- var span = document.createElement("SPAN");
- span.className = token.style;
- span.appendChild(document.createTextNode(token.value));
- output.appendChild(span);
- }
- }
- catch (e) {
- if (e != StopIteration) throw e;
- }
- }
-})();
-</textarea>
-</div>
-
-<button onclick="highlight()">Run highlighter</button>
-
-<div>
-<div id="numbers" style="float: left; width: 2em; margin-right: .5em; text-align: right; font-family: monospace; color: #CCC;"></div>
-<pre id="output" style="font-family: monospace"></pre>
-</div>
-
-<script type="text/javascript">
- // Simple hack to demonstrate adding line numbers. Just pass the DOM node as
- // the second argument to highlightText when you don't need those
- function highlight() {
- var lineNo = 1, output = document.getElementById("output"), numbers = document.getElementById("numbers");
- output.innerHTML = numbers.innerHTML = "";
-
- function addLine(line) {
- numbers.appendChild(document.createTextNode(String(lineNo++)));
- numbers.appendChild(document.createElement("BR"));
- for (var i = 0; i < line.length; i++) output.appendChild(line[i]);
- output.appendChild(document.createElement("BR"));
- }
- highlightText(document.getElementById("code").value, addLine);
- }
-</script>
-
- </body>
-</html>
diff --git a/media/CodeMirror-0.62/htmltest.html b/media/CodeMirror-0.62/htmltest.html
deleted file mode 100644
index a737522..0000000
--- a/media/CodeMirror-0.62/htmltest.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <script src="js/codemirror.js" type="text/javascript"></script>
- <title>CodeMirror: HTML/XML demonstration</title>
- <link rel="stylesheet" type="text/css" href="css/docs.css"/>
- <style type="text/css">
- .CodeMirror-line-numbers {
- width: 2.2em;
- color: #aaa;
- background-color: #eee;
- text-align: right;
- padding-right: .3em;
- font-size: 10pt;
- font-family: monospace;
- padding-top: .4em;
- }
- </style>
- </head>
- <body style="padding: 20px;">
-
-<p>This is a simple demonstration of the XML/HTML indentation module
-for <a href="index.html">CodeMirror</a>. The <a
-href="js/parsexml.js">javascript</a> file contains some comments with
-more information.</p>
-
-<div style="border: 1px solid black; padding: 0px;">
-<textarea id="code" cols="120" rows="30">
-&lt;html style="color: green"&gt;
- &lt;!-- this is a comment --&gt;
- &lt;head&gt;
- &lt;title&gt;HTML Example&lt;/title&gt;
- &lt;/head&gt;
- &lt;body&gt;
- The indentation tries to be &lt;em&gt;somewhat &amp;quot;do what
- I mean&amp;quot;&lt;/em&gt;... but might not match your style.
- &lt;/body&gt;
-&lt;/html&gt;
-</textarea>
-</div>
-
-<script type="text/javascript">
- var editor = CodeMirror.fromTextArea('code', {
- height: "350px",
- parserfile: "parsexml.js",
- stylesheet: "css/xmlcolors.css",
- path: "js/",
- continuousScanning: 500,
- lineNumbers: true,
- textWrapping: false
- });
-</script>
- </body>
-</html>
diff --git a/media/CodeMirror-0.62/index.html b/media/CodeMirror-0.62/index.html
deleted file mode 100644
index 58356bd..0000000
--- a/media/CodeMirror-0.62/index.html
+++ /dev/null
@@ -1,182 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CodeMirror: In-browser code editing</title>
-
- <link rel="stylesheet" type="text/css" href="css/docs.css"/>
- <style type="text/css">
- div.top {text-align: center;}
- div.top h1 {margin-bottom: 0;}
- div.top h2 {margin-top: 0; margin-bottom: 1.5em;}
- div.donate span {cursor: pointer; text-decoration: underline;}
- div.donate {font-size: 70%; margin-top: 1em; width: 155px; padding: 10px; border: 1px solid #c44;}
- </style>
- </head>
- <body>
-
-<div class="top">
- <h1>CodeMirror</h1>
- <h2 class="underline">In-browser code editing made almost bearable</h2>
-</div>
-<div style="float: right; padding-left: 10px;">
- <form action="https://www.paypal.com/cgi-bin/webscr" method="post" id="paypal">
- <input type="hidden" name="cmd" value="_s-xclick"/>
- <input type="hidden" name="hosted_button_id" value="3701544"/>
- </form>
- <img src="css/people.jpg" alt=""/><br/>
- <div class="donate">
- Make a donation:
- <ul style="margin: 0 2em; padding: 0">
- <li><span onclick="document.getElementById('paypal').submit();">Paypal</span></li>
- <li><span onclick="document.getElementById('bankinfo').style.display = 'block';">Bank</span></li>
- </ul>
- <div id="bankinfo" style="display: none; font-size: 80%;">
- Bank: <i>Rabobank</i><br/>
- Country: <i>Netherlands</i><br/>
- SWIFT: <i>RABONL2U</i><br/>
- Account: <i>147850770</i><br/>
- Name: <i>Marijn Haverbeke</i><br/>
- IBAN: <i>NL26 RABO 0147 8507 70</i>
- </div>
- </div>
-</div>
-
-<p>CodeMirror is a JavaScript library that can be used to create a
-relatively pleasant editor interface for code-like content &#x2015;
-computer programs, HTML markup, and similar. If a parser has been
-written for the language you are editing (see below for a list of
-supported languages), the code will be coloured, and the editor will
-help you with indentation.</p>
-
-<p>To get a look at CodeMirror, see the test pages for the various
-parsers...</p>
-
-<ul>
- <li><a href="jstest.html">JavaScript</a></li>
- <li><a href="htmltest.html">XML/HTML</a></li>
- <li><a href="csstest.html">CSS</a></li>
- <li><a href="sparqltest.html">SPARQL</a></li>
- <li><a href="mixedtest.html">HTML mixed-mode</a></li>
- <li><a href="contrib/php/index.html">HTML+PHP mixed-mode</a> (courtesy of <a href="contrib/php/LICENSE">Yahoo!</a>)</li>
- <li><a href="contrib/python/index.html">Python</a> (courtesy of <a href="contrib/python/LICENSE">Timothy Farrell</a>)</li>
- <li><a href="contrib/lua/index.html">Lua</a> (courtesy of <a href="http://francio.pl/">Franciszek Wawrzak</a>)</li>
- <li><a href="http://stuff.hantl.cz/ruby-in-codemirror/">Ruby</a> (by Michal Hantl, <a href="http://github.com/hakunin/ruby-in-codemirror/tree/master">unfinished</a>)</li>
-</ul>
-
-<p>Or take a look at some real-world uses of the system...</p>
-
-<ul>
- <li><a href="http://github.com/darwin/firerainbow">FireRainbow: syntax colouring for Firebug</a></li>
- <li><a href="http://dev.freebaseapps.com/">Freebase's Acre IDE</a></li>
- <li><a href="http://kml-samples.googlecode.com/svn/trunk/interactive/index.html">Google Earth KML sampler</a></li>
- <li><a href="http://eloquentjavascript.net/chapter1.html">Eloquent JavaScript's console</a></li>
- <li><a href="http://demo.qooxdoo.org/current/playground/#Hello_World">The qooxdoo playground</a></li>
- <li><a href="http://billmill.org/static/canvastutorial/index.html">A cool tutorial about the &lt;canvas> element</a></li>
- <li><a href="http://orc.csres.utexas.edu/tryorc.shtml">An online IDE for the Orc programming language</a></li>
- <li><a href="http://code.google.com/apis/ajax/playground">Google's API playground</a></li>
-</ul>
-
-<h2>Releases</h2>
-
-<p class="rel"><em>30-05-2009</em>: <a
-href="http://marijn.haverbeke.nl/codemirror/codemirror-0.62.zip">Version
-0.62</a>: Introduces <a href="contrib/python/index.html">Python</a>
-and <a href="contrib/lua/index.html">Lua</a> parsers. Add
-<code>setParser</code> (on-the-fly mode changing) and
-<code>clearHistory</code> methods. Make parsing passes time-based
-instead of lines-based (see the <code>passTime</code> option).</p>
-
-<p class="rel"><em>04-03-2009</em>: <a
-href="http://marijn.haverbeke.nl/codemirror/codemirror-0.61.zip">Version
-0.61</a>: Add line numbers support (see <code>lineNumbers</code>
-option in <a href="manual.html">manual</a>). Support a mode where tab
-'shifts' indentation instead of resetting it (see
-<code>tabMode="shift"</code>). Add <code>indentUnit</code> option to
-configure indentation depths. Make it possible to grab the editor's
-keyboard input, which is useful when popping up dialogs (see
-<code>grabKeys</code>/<code>ungrabKeys</code>). Fix a lot of small
-bugs, among which the various issues related to pasting in Internet
-Explorer.</p>
-
-<p class="rel"><em>29-12-2008</em>: <a
-href="http://marijn.haverbeke.nl/codemirror/codemirror-0.60.zip">Version
-0.60</a>: This release makes lots of internal changes, so test before
-you upgrade. More robust selection-preservation on IE, allowing styles
-with different font sizes. New <code>activeTokens</code> and
-<code>cursorActivity</code> callbacks, and a more powerful, line-based
-interface for inspecting and manipulating the content of the editor
-(see <a href="manual.html">manual</a>). Fixes the
-<code>replaceSelection</code> problem in IE, and a lot of other,
-smaller issues.</p>
-
-<p class="rel"><em>28-09-2008</em>: <a
-href="http://marijn.haverbeke.nl/codemirror/codemirror-0.58.zip">Version
-0.58</a>: Add parsers for SPARQL and HTML-mixed-mode (nests CSS and JS
-parsers). Also: bracket highlighting, a 'dumb tabs' mode, an
-<code>onChange</code> callback, and heaps of bugfixes. See the manual
-for details on the new features.</p>
-
-<p class="rel"><em>04-07-2008</em>: <a
-href="http://marijn.haverbeke.nl/codemirror/codemirror-0.57.zip">Version
-0.57</a>: A CSS parser and a nice tokenizer framework, bugfixes in the
-XML parser, a few browser-issue workarounds, one of which should fix
-the age-old Firefox cursor-showing-on-wrong line bug.</p>
-
-<h2 id="supported">Supported browsers</h2>
-
-<p>At this time, the following browsers are supported:</p>
-
-<ul>
- <li>Firefox 1.5 or higher</li>
- <li>Internet Explorer 6 or higher</li>
- <li>Safari 3 or higher</li>
- <li>Opera 9.52 or higher</li>
- <li>Chrome</li>
-</ul>
-
-<p>Making it work on other browsers that have decent support for the
-W3C DOM model should not be too hard, but I am not actively testing
-against those.</p>
-
-<h2>Getting the code</h2>
-
-<p>All of CodeMirror is released under a <a
-href="LICENSE">zlib-style</a> license. To get it, you can download the
-<a href="http://marijn.haverbeke.nl/codemirror/codemirror.zip">latest
-release</a> or the current <a
-href="http://marijn.haverbeke.nl/codemirror/codemirror-latest.zip">development
-snapshot</a> as zip files, or use the <a
-href="http://www.darcs.net/">darcs</a> version control system to get
-the repository:</p>
-
-<pre class="code">darcs get http://marijn.haverbeke.nl/codemirror</pre>
-
-<p>This second method is recommended if you are planning to hack on
-CodeMirror &#x2015; it makes it easy to record your patches and share them
-with me. To see the repository online, visit the <a
-href="http://marijn.haverbeke.nl/darcsweb.cgi?r=CodeMirror">CodeMirror
-darcsweb</a>.</p>
-
-<h2>Support</h2>
-
-<p>There is a <a
-href="http://groups.google.com/group/codemirror">Google group</a> (a
-sort of mailing list/newsgroup thingy) for discussion and news related
-to CodeMirror. You can also e-mail me directly: <a
-href="mailto:marijnh@gmail.com">Marijn Haverbeke</a>.</p>
-
-<h2>Documentation</h2>
-
-<ul>
- <li>The <a href="manual.html">manual</a> is all most users will need
- to read (or skim).</li>
- <li>If you're interested in working on the code, <a
- href="story.html">this document</a> about CodeMirror's architecture
- will be useful.</li>
- <li>The <a
- href="http://marijn.haverbeke.nl/darcsweb.cgi?r=CodeMirror;a=tree">source
- code</a> is, for the most part, rather well commented, so if all
- else fails, you can try reading it.</li>
-</ul>
-
- </body>
-</html>
diff --git a/media/CodeMirror-0.62/js/codemirror.js b/media/CodeMirror-0.62/js/codemirror.js
deleted file mode 100644
index aac55f5..0000000
--- a/media/CodeMirror-0.62/js/codemirror.js
+++ /dev/null
@@ -1,298 +0,0 @@
-/* CodeMirror main module
- *
- * Implements the CodeMirror constructor and prototype, which take care
- * of initializing the editor frame, and providing the outside interface.
- */
-
-// The CodeMirrorConfig object is used to specify a default
-// configuration. If you specify such an object before loading this
-// file, the values you put into it will override the defaults given
-// below. You can also assign to it after loading.
-var CodeMirrorConfig = window.CodeMirrorConfig || {};
-
-var CodeMirror = (function(){
- function setDefaults(object, defaults) {
- for (var option in defaults) {
- if (!object.hasOwnProperty(option))
- object[option] = defaults[option];
- }
- }
- function forEach(array, action) {
- for (var i = 0; i < array.length; i++)
- action(array[i]);
- }
-
- // These default options can be overridden by passing a set of
- // options to a specific CodeMirror constructor. See manual.html for
- // their meaning.
- setDefaults(CodeMirrorConfig, {
- stylesheet: "",
- path: "",
- parserfile: [],
- basefiles: ["util.js", "stringstream.js", "select.js", "undo.js", "editor.js", "tokenize.js"],
- iframeClass: null,
- passDelay: 200,
- passTime: 50,
- continuousScanning: false,
- saveFunction: null,
- onChange: null,
- undoDepth: 50,
- undoDelay: 800,
- disableSpellcheck: true,
- textWrapping: true,
- readOnly: false,
- width: "100%",
- height: "300px",
- autoMatchParens: false,
- parserConfig: null,
- tabMode: "indent", // or "spaces", "default", "shift"
- reindentOnLoad: false,
- activeTokens: null,
- cursorActivity: null,
- lineNumbers: false,
- indentUnit: 2
- });
-
- function wrapLineNumberDiv(place) {
- return function(node) {
- var container = document.createElement("DIV"),
- nums = document.createElement("DIV"),
- scroller = document.createElement("DIV");
- container.style.position = "relative";
- nums.style.position = "absolute";
- nums.style.height = "100%";
- if (nums.style.setExpression) {
- try {nums.style.setExpression("height", "this.previousSibling.offsetHeight + 'px'");}
- catch(e) {} // Seems to throw 'Not Implemented' on some IE8 versions
- }
- nums.style.top = "0px";
- nums.style.overflow = "hidden";
- place(container);
- container.appendChild(node);
- container.appendChild(nums);
- scroller.className = "CodeMirror-line-numbers";
- nums.appendChild(scroller);
- }
- }
-
- function applyLineNumbers(frame) {
- var win = frame.contentWindow, doc = win.document,
- nums = frame.nextSibling, scroller = nums.firstChild;
-
- var nextNum = 1, barWidth = null;
- function sizeBar() {
- if (nums.offsetWidth != barWidth) {
- barWidth = nums.offsetWidth;
- nums.style.left = "-" + (frame.parentNode.style.marginLeft = barWidth + "px");
- }
- }
- function update() {
- var diff = 20 + Math.max(doc.body.offsetHeight, frame.offsetHeight) - scroller.offsetHeight;
- for (var n = Math.ceil(diff / 10); n > 0; n--) {
- var div = document.createElement("DIV");
- div.appendChild(document.createTextNode(nextNum++));
- scroller.appendChild(div);
- }
- nums.scrollTop = doc.body.scrollTop || doc.documentElement.scrollTop || 0;
- }
- sizeBar();
- update();
- win.addEventHandler(win, "scroll", update);
- setInterval(sizeBar, 500);
- }
-
- function CodeMirror(place, options) {
- // Backward compatibility for deprecated options.
- if (options.dumbTabs) options.tabMode = "spaces";
- else if (options.normalTab) options.tabMode = "default";
-
- // Use passed options, if any, to override defaults.
- this.options = options = options || {};
- setDefaults(options, CodeMirrorConfig);
-
- var frame = this.frame = document.createElement("IFRAME");
- if (options.iframeClass) frame.className = options.iframeClass;
- frame.frameBorder = 0;
- frame.src = "javascript:false;";
- frame.style.border = "0";
- frame.style.width = options.width;
- frame.style.height = options.height;
- // display: block occasionally suppresses some Firefox bugs, so we
- // always add it, redundant as it sounds.
- frame.style.display = "block";
-
- if (place.appendChild) {
- var node = place;
- place = function(n){node.appendChild(n);};
- }
- if (options.lineNumbers) place = wrapLineNumberDiv(place);
- place(frame);
-
- // Link back to this object, so that the editor can fetch options
- // and add a reference to itself.
- frame.CodeMirror = this;
- this.win = frame.contentWindow;
-
- if (typeof options.parserfile == "string")
- options.parserfile = [options.parserfile];
- if (typeof options.stylesheet == "string")
- options.stylesheet = [options.stylesheet];
-
- var html = ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><html><head>"];
- forEach(options.stylesheet, function(file) {
- html.push("<link rel=\"stylesheet\" type=\"text/css\" href=\"" + file + "\"/>");
- });
- forEach(options.basefiles.concat(options.parserfile), function(file) {
- html.push("<script type=\"text/javascript\" src=\"" + options.path + file + "\"></script>");
- });
- html.push("</head><body style=\"border-width: 0;\" class=\"editbox\" spellcheck=\"" +
- (options.disableSpellcheck ? "false" : "true") + "\"></body></html>");
-
- var doc = this.win.document;
- doc.open();
- doc.write(html.join(""));
- doc.close();
- }
-
- CodeMirror.prototype = {
- init: function() {
- if (this.options.initCallback) this.options.initCallback(this);
- if (this.options.lineNumbers) applyLineNumbers(this.frame);
- if (this.options.reindentOnLoad) this.reindent();
- },
-
- getCode: function() {return this.editor.getCode();},
- setCode: function(code) {this.editor.importCode(code);},
- selection: function() {return this.editor.selectedText();},
- reindent: function() {this.editor.reindent();},
- reindentSelection: function() {this.editor.reindentSelection(null);},
-
- focus: function() {
- this.win.focus();
- if (this.editor.selectionSnapshot) // IE hack
- this.win.select.selectCoords(this.win, this.editor.selectionSnapshot);
- },
- replaceSelection: function(text) {
- this.focus();
- this.editor.replaceSelection(text);
- return true;
- },
- replaceChars: function(text, start, end) {
- this.editor.replaceChars(text, start, end);
- },
- getSearchCursor: function(string, fromCursor) {
- return this.editor.getSearchCursor(string, fromCursor);
- },
-
- undo: function() {this.editor.history.undo();},
- redo: function() {this.editor.history.redo();},
- historySize: function() {return this.editor.history.historySize();},
- clearHistory: function() {this.editor.history.clear();},
-
- grabKeys: function(callback, filter) {this.editor.grabKeys(callback, filter);},
- ungrabKeys: function() {this.editor.ungrabKeys();},
-
- setParser: function(name) {this.editor.setParser(name);},
-
- cursorPosition: function(start) {
- if (this.win.select.ie_selection) this.focus();
- return this.editor.cursorPosition(start);
- },
- firstLine: function() {return this.editor.firstLine();},
- lastLine: function() {return this.editor.lastLine();},
- nextLine: function(line) {return this.editor.nextLine(line);},
- prevLine: function(line) {return this.editor.prevLine(line);},
- lineContent: function(line) {return this.editor.lineContent(line);},
- setLineContent: function(line, content) {this.editor.setLineContent(line, content);},
- insertIntoLine: function(line, position, content) {this.editor.insertIntoLine(line, position, content);},
- selectLines: function(startLine, startOffset, endLine, endOffset) {
- this.win.focus();
- this.editor.selectLines(startLine, startOffset, endLine, endOffset);
- },
- nthLine: function(n) {
- var line = this.firstLine();
- for (; n > 1 && line !== false; n--)
- line = this.nextLine(line);
- return line;
- },
- lineNumber: function(line) {
- var num = 0;
- while (line !== false) {
- num++;
- line = this.prevLine(line);
- }
- return num;
- },
-
- // Old number-based line interface
- jumpToLine: function(n) {
- this.selectLines(this.nthLine(n), 0);
- this.win.focus();
- },
- currentLine: function() {
- return this.lineNumber(this.cursorPosition().line);
- }
- };
-
- CodeMirror.InvalidLineHandle = {toString: function(){return "CodeMirror.InvalidLineHandle";}};
-
- CodeMirror.replace = function(element) {
- if (typeof element == "string")
- element = document.getElementById(element);
- return function(newElement) {
- element.parentNode.replaceChild(newElement, element);
- };
- };
-
- CodeMirror.fromTextArea = function(area, options) {
- if (typeof area == "string")
- area = document.getElementById(area);
-
- options = options || {};
- if (area.style.width && options.width == null)
- options.width = area.style.width;
- if (area.style.height && options.height == null)
- options.height = area.style.height;
- if (options.content == null) options.content = area.value;
-
- if (area.form) {
- function updateField() {
- area.value = mirror.getCode();
- }
- if (typeof area.form.addEventListener == "function")
- area.form.addEventListener("submit", updateField, false);
- else
- area.form.attachEvent("onsubmit", updateField);
- }
-
- function insert(frame) {
- if (area.nextSibling)
- area.parentNode.insertBefore(frame, area.nextSibling);
- else
- area.parentNode.appendChild(frame);
- }
-
- area.style.display = "none";
- var mirror = new CodeMirror(insert, options);
- return mirror;
- };
-
- CodeMirror.isProbablySupported = function() {
- // This is rather awful, but can be useful.
- var match;
- if (window.opera)
- return Number(window.opera.version()) >= 9.52;
- else if (/Apple Computers, Inc/.test(navigator.vendor) && (match = navigator.userAgent.match(/Version\/(\d+(?:\.\d+)?)\./)))
- return Number(match[1]) >= 3;
- else if (document.selection && window.ActiveXObject && (match = navigator.userAgent.match(/MSIE (\d+(?:\.\d*)?)\b/)))
- return Number(match[1]) >= 6;
- else if (match = navigator.userAgent.match(/gecko\/(\d{8})/i))
- return Number(match[1]) >= 20050901;
- else if (match = navigator.userAgent.match(/AppleWebKit\/(\d+)/))
- return Number(match[1]) >= 525;
- else
- return null;
- };
-
- return CodeMirror;
-})();
diff --git a/media/CodeMirror-0.62/js/editor.js b/media/CodeMirror-0.62/js/editor.js
deleted file mode 100644
index e580ccb..0000000
--- a/media/CodeMirror-0.62/js/editor.js
+++ /dev/null
@@ -1,1303 +0,0 @@
-/* The Editor object manages the content of the editable frame. It
- * catches events, colours nodes, and indents lines. This file also
- * holds some functions for transforming arbitrary DOM structures into
- * plain sequences of <span> and <br> elements
- */
-
-// Make sure a string does not contain two consecutive 'collapseable'
-// whitespace characters.
-function makeWhiteSpace(n) {
- var buffer = [], nb = true;
- for (; n > 0; n--) {
- buffer.push((nb || n == 1) ? nbsp : " ");
- nb = !nb;
- }
- return buffer.join("");
-}
-
-// Create a set of white-space characters that will not be collapsed
-// by the browser, but will not break text-wrapping either.
-function fixSpaces(string) {
- if (string.charAt(0) == " ") string = nbsp + string.slice(1);
- return string.replace(/\t/g, function(){return makeWhiteSpace(indentUnit);})
- .replace(/[ \u00a0]{2,}/g, function(s) {return makeWhiteSpace(s.length);});
-}
-
-function cleanText(text) {
- return text.replace(/\u00a0/g, " ").replace(/\u200b/g, "");
-}
-
-// Create a SPAN node with the expected properties for document part
-// spans.
-function makePartSpan(value, doc) {
- var text = value;
- if (value.nodeType == 3) text = value.nodeValue;
- else value = doc.createTextNode(text);
-
- var span = doc.createElement("SPAN");
- span.isPart = true;
- span.appendChild(value);
- span.currentText = text;
- return span;
-}
-
-// On webkit, when the last BR of the document does not have text
-// behind it, the cursor can not be put on the line after it. This
-// makes pressing enter at the end of the document occasionally do
-// nothing (or at least seem to do nothing). To work around it, this
-// function makes sure the document ends with a span containing a
-// zero-width space character. The traverseDOM iterator filters such
-// character out again, so that the parsers won't see them. This
-// function is called from a few strategic places to make sure the
-// zwsp is restored after the highlighting process eats it.
-var webkitLastLineHack = webkit ?
- function(container) {
- var last = container.lastChild;
- if (!last || !last.isPart || last.textContent != "\u200b")
- container.appendChild(makePartSpan("\u200b", container.ownerDocument));
- } : function() {};
-
-var Editor = (function(){
- // The HTML elements whose content should be suffixed by a newline
- // when converting them to flat text.
- var newlineElements = {"P": true, "DIV": true, "LI": true};
-
- function asEditorLines(string) {
- var tab = makeWhiteSpace(indentUnit);
- return map(string.replace(/\t/g, tab).replace(/\u00a0/g, " ").replace(/\r\n?/g, "\n").split("\n"), fixSpaces);
- }
-
- // Helper function for traverseDOM. Flattens an arbitrary DOM node
- // into an array of textnodes and <br> tags.
- function simplifyDOM(root) {
- var doc = root.ownerDocument;
- var result = [];
- var leaving = true;
-
- function simplifyNode(node) {
- if (node.nodeType == 3) {
- var text = node.nodeValue = fixSpaces(node.nodeValue.replace(/[\r\u200b]/g, "").replace(/\n/g, " "));
- if (text.length) leaving = false;
- result.push(node);
- }
- else if (node.nodeName == "BR" && node.childNodes.length == 0) {
- leaving = true;
- result.push(node);
- }
- else {
- forEach(node.childNodes, simplifyNode);
- if (!leaving && newlineElements.hasOwnProperty(node.nodeName)) {
- leaving = true;
- result.push(doc.createElement("BR"));
- }
- }
- }
-
- simplifyNode(root);
- return result;
- }
-
- // Creates a MochiKit-style iterator that goes over a series of DOM
- // nodes. The values it yields are strings, the textual content of
- // the nodes. It makes sure that all nodes up to and including the
- // one whose text is being yielded have been 'normalized' to be just
- // <span> and <br> elements.
- // See the story.html file for some short remarks about the use of
- // continuation-passing style in this iterator.
- function traverseDOM(start){
- function yield(value, c){cc = c; return value;}
- function push(fun, arg, c){return function(){return fun(arg, c);};}
- function stop(){cc = stop; throw StopIteration;};
- var cc = push(scanNode, start, stop);
- var owner = start.ownerDocument;
- var nodeQueue = [];
-
- // Create a function that can be used to insert nodes after the
- // one given as argument.
- function pointAt(node){
- var parent = node.parentNode;
- var next = node.nextSibling;
- return function(newnode) {
- parent.insertBefore(newnode, next);
- };
- }
- var point = null;
-
- // Insert a normalized node at the current point. If it is a text
- // node, wrap it in a <span>, and give that span a currentText
- // property -- this is used to cache the nodeValue, because
- // directly accessing nodeValue is horribly slow on some browsers.
- // The dirty property is used by the highlighter to determine
- // which parts of the document have to be re-highlighted.
- function insertPart(part){
- var text = "\n";
- if (part.nodeType == 3) {
- select.snapshotChanged();
- part = makePartSpan(part, owner);
- text = part.currentText;
- }
- part.dirty = true;
- nodeQueue.push(part);
- point(part);
- return text;
- }
-
- // Extract the text and newlines from a DOM node, insert them into
- // the document, and yield the textual content. Used to replace
- // non-normalized nodes.
- function writeNode(node, c){
- var toYield = [];
- forEach(simplifyDOM(node), function(part) {
- toYield.push(insertPart(part));
- });
- return yield(toYield.join(""), c);
- }
-
- // Check whether a node is a normalized <span> element.
- function partNode(node){
- if (node.isPart && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
- node.currentText = node.firstChild.nodeValue;
- return !/[\n\t\r]/.test(node.currentText);
- }
- return false;
- }
-
- // Handle a node. Add its successor to the continuation if there
- // is one, find out whether the node is normalized. If it is,
- // yield its content, otherwise, normalize it (writeNode will take
- // care of yielding).
- function scanNode(node, c){
- if (node.nextSibling)
- c = push(scanNode, node.nextSibling, c);
-
- if (partNode(node)){
- nodeQueue.push(node);
- return yield(node.currentText, c);
- }
- else if (node.nodeName == "BR") {
- nodeQueue.push(node);
- return yield("\n", c);
- }
- else {
- point = pointAt(node);
- removeElement(node);
- return writeNode(node, c);
- }
- }
-
- // MochiKit iterators are objects with a next function that
- // returns the next value or throws StopIteration when there are
- // no more values.
- return {next: function(){return cc();}, nodes: nodeQueue};
- }
-
- // Determine the text size of a processed node.
- function nodeSize(node) {
- if (node.nodeName == "BR")
- return 1;
- else
- return node.currentText.length;
- }
-
- // Search backwards through the top-level nodes until the next BR or
- // the start of the frame.
- function startOfLine(node) {
- while (node && node.nodeName != "BR") node = node.previousSibling;
- return node;
- }
- function endOfLine(node, container) {
- if (!node) node = container.firstChild;
- else if (node.nodeName == "BR") node = node.nextSibling;
-
- while (node && node.nodeName != "BR") node = node.nextSibling;
- return node;
- }
-
- function time() {return new Date().getTime();}
-
- // Replace all DOM nodes in the current selection with new ones.
- // Needed to prevent issues in IE where the old DOM nodes can be
- // pasted back into the document, still holding their old undo
- // information.
- function scrubPasted(container, start, start2) {
- var end = select.selectionTopNode(container, true),
- doc = container.ownerDocument;
- if (start != null && start.parentNode != container) start = start2;
- if (start === false) start = null;
- if (start == end || !end || !container.firstChild) return;
-
- var clear = traverseDOM(start ? start.nextSibling : container.firstChild);
- while (end.parentNode == container) try{clear.next();}catch(e){break;}
- forEach(clear.nodes, function(node) {
- var newNode = node.nodeName == "BR" ? doc.createElement("BR") : makePartSpan(node.currentText, doc);
- container.replaceChild(newNode, node);
- });
- }
-
- // Client interface for searching the content of the editor. Create
- // these by calling CodeMirror.getSearchCursor. To use, call
- // findNext on the resulting object -- this returns a boolean
- // indicating whether anything was found, and can be called again to
- // skip to the next find. Use the select and replace methods to
- // actually do something with the found locations.
- function SearchCursor(editor, string, fromCursor) {
- this.editor = editor;
- this.history = editor.history;
- this.history.commit();
-
- // Are we currently at an occurrence of the search string?
- this.atOccurrence = false;
- // The object stores a set of nodes coming after its current
- // position, so that when the current point is taken out of the
- // DOM tree, we can still try to continue.
- this.fallbackSize = 15;
- var cursor;
- // Start from the cursor when specified and a cursor can be found.
- if (fromCursor && (cursor = select.cursorPos(this.editor.container))) {
- this.line = cursor.node;
- this.offset = cursor.offset;
- }
- else {
- this.line = null;
- this.offset = 0;
- }
- this.valid = !!string;
-
- // Create a matcher function based on the kind of string we have.
- var target = string.split("\n"), self = this;
- this.matches = (target.length == 1) ?
- // For one-line strings, searching can be done simply by calling
- // indexOf on the current line.
- function() {
- var match = cleanText(self.history.textAfter(self.line).slice(self.offset)).indexOf(string);
- if (match > -1)
- return {from: {node: self.line, offset: self.offset + match},
- to: {node: self.line, offset: self.offset + match + string.length}};
- } :
- // Multi-line strings require internal iteration over lines, and
- // some clunky checks to make sure the first match ends at the
- // end of the line and the last match starts at the start.
- function() {
- var firstLine = cleanText(self.history.textAfter(self.line).slice(self.offset));
- var match = firstLine.lastIndexOf(target[0]);
- if (match == -1 || match != firstLine.length - target[0].length)
- return false;
- var startOffset = self.offset + match;
-
- var line = self.history.nodeAfter(self.line);
- for (var i = 1; i < target.length - 1; i++) {
- if (cleanText(self.history.textAfter(line)) != target[i])
- return false;
- line = self.history.nodeAfter(line);
- }
-
- if (cleanText(self.history.textAfter(line)).indexOf(target[target.length - 1]) != 0)
- return false;
-
- return {from: {node: self.line, offset: startOffset},
- to: {node: line, offset: target[target.length - 1].length}};
- };
- }
-
- SearchCursor.prototype = {
- findNext: function() {
- if (!this.valid) return false;
- this.atOccurrence = false;
- var self = this;
-
- // Go back to the start of the document if the current line is
- // no longer in the DOM tree.
- if (this.line && !this.line.parentNode) {
- this.line = null;
- this.offset = 0;
- }
-
- // Set the cursor's position one character after the given
- // position.
- function saveAfter(pos) {
- if (self.history.textAfter(pos.node).length < pos.offset) {
- self.line = pos.node;
- self.offset = pos.offset + 1;
- }
- else {
- self.line = self.history.nodeAfter(pos.node);
- self.offset = 0;
- }
- }
-
- while (true) {
- var match = this.matches();
- // Found the search string.
- if (match) {
- this.atOccurrence = match;
- saveAfter(match.from);
- return true;
- }
- this.line = this.history.nodeAfter(this.line);
- this.offset = 0;
- // End of document.
- if (!this.line) {
- this.valid = false;
- return false;
- }
- }
- },
-
- select: function() {
- if (this.atOccurrence) {
- select.setCursorPos(this.editor.container, this.atOccurrence.from, this.atOccurrence.to);
- select.scrollToCursor(this.editor.container);
- }
- },
-
- replace: function(string) {
- if (this.atOccurrence) {
- var end = this.editor.replaceRange(this.atOccurrence.from, this.atOccurrence.to, string);
- this.line = end.node;
- this.offset = end.offset;
- this.atOccurrence = false;
- }
- }
- };
-
- // The Editor object is the main inside-the-iframe interface.
- function Editor(options) {
- this.options = options;
- window.indentUnit = options.indentUnit;
- this.parent = parent;
- this.doc = document;
- var container = this.container = this.doc.body;
- this.win = window;
- this.history = new History(container, options.undoDepth, options.undoDelay,
- this, options.onChange);
- var self = this;
-
- if (!Editor.Parser)
- throw "No parser loaded.";
- if (options.parserConfig && Editor.Parser.configure)
- Editor.Parser.configure(options.parserConfig);
-
- if (!options.readOnly)
- select.setCursorPos(container, {node: null, offset: 0});
-
- this.dirty = [];
- if (options.content)
- this.importCode(options.content);
- else // FF acts weird when the editable document is completely empty
- container.appendChild(this.doc.createElement("BR"));
-
- if (!options.readOnly) {
- if (options.continuousScanning !== false) {
- this.scanner = this.documentScanner(options.passTime);
- this.delayScanning();
- }
-
- function setEditable() {
- // In IE, designMode frames can not run any scripts, so we use
- // contentEditable instead.
- if (document.body.contentEditable != undefined && internetExplorer)
- document.body.contentEditable = "true";
- else
- document.designMode = "on";
-
- document.documentElement.style.borderWidth = "0";
- if (!options.textWrapping)
- container.style.whiteSpace = "nowrap";
- }
-
- // If setting the frame editable fails, try again when the user
- // focus it (happens when the frame is not visible on
- // initialisation, in Firefox).
- try {
- setEditable();
- }
- catch(e) {
- var focusEvent = addEventHandler(document, "focus", function() {
- focusEvent();
- setEditable();
- }, true);
- }
-
- addEventHandler(document, "keydown", method(this, "keyDown"));
- addEventHandler(document, "keypress", method(this, "keyPress"));
- addEventHandler(document, "keyup", method(this, "keyUp"));
-
- function cursorActivity() {self.cursorActivity(false);}
- addEventHandler(document.body, "mouseup", cursorActivity);
- addEventHandler(document.body, "paste", function(event) {
- cursorActivity();
- if (internetExplorer) {
- var text = null;
- try {text = window.clipboardData.getData("Text");}catch(e){}
- if (text != null) {
- self.replaceSelection(text);
- event.stop();
- }
- else {
- var start = select.selectionTopNode(self.container, true),
- start2 = start && start.previousSibling;
- setTimeout(function(){scrubPasted(self.container, start, start2);}, 0);
- }
- }
- });
- addEventHandler(document.body, "cut", cursorActivity);
-
- if (this.options.autoMatchParens)
- addEventHandler(document.body, "click", method(this, "scheduleParenBlink"));
- }
- else if (!options.textWrapping) {
- container.style.whiteSpace = "nowrap";
- }
- }
-
- function isSafeKey(code) {
- return (code >= 16 && code <= 18) || // shift, control, alt
- (code >= 33 && code <= 40); // arrows, home, end
- }
-
- Editor.prototype = {
- // Import a piece of code into the editor.
- importCode: function(code) {
- this.history.push(null, null, asEditorLines(code));
- this.history.reset();
- },
-
- // Extract the code from the editor.
- getCode: function() {
- if (!this.container.firstChild)
- return "";
-
- var accum = [];
- select.markSelection(this.win);
- forEach(traverseDOM(this.container.firstChild), method(accum, "push"));
- webkitLastLineHack(this.container);
- select.selectMarked();
- return cleanText(accum.join(""));
- },
-
- checkLine: function(node) {
- if (node === false || !(node == null || node.parentNode == this.container))
- throw parent.CodeMirror.InvalidLineHandle;
- },
-
- cursorPosition: function(start) {
- if (start == null) start = true;
- var pos = select.cursorPos(this.container, start);
- if (pos) return {line: pos.node, character: pos.offset};
- else return {line: null, character: 0};
- },
-
- firstLine: function() {
- return null;
- },
-
- lastLine: function() {
- if (this.container.lastChild) return startOfLine(this.container.lastChild);
- else return null;
- },
-
- nextLine: function(line) {
- this.checkLine(line);
- var end = endOfLine(line, this.container);
- return end || false;
- },
-
- prevLine: function(line) {
- this.checkLine(line);
- if (line == null) return false;
- return startOfLine(line.previousSibling);
- },
-
- selectLines: function(startLine, startOffset, endLine, endOffset) {
- this.checkLine(startLine);
- var start = {node: startLine, offset: startOffset}, end = null;
- if (endOffset !== undefined) {
- this.checkLine(endLine);
- end = {node: endLine, offset: endOffset};
- }
- select.setCursorPos(this.container, start, end);
- select.scrollToCursor(this.container);
- },
-
- lineContent: function(line) {
- this.checkLine(line);
- var accum = [];
- for (line = line ? line.nextSibling : this.container.firstChild;
- line && line.nodeName != "BR"; line = line.nextSibling)
- accum.push(nodeText(line));
- return cleanText(accum.join(""));
- },
-
- setLineContent: function(line, content) {
- this.history.commit();
- this.replaceRange({node: line, offset: 0},
- {node: line, offset: this.history.textAfter(line).length},
- content);
- this.addDirtyNode(line);
- this.scheduleHighlight();
- },
-
- insertIntoLine: function(line, position, content) {
- var before = null;
- if (position == "end") {
- before = endOfLine(line, this.container);
- }
- else {
- for (var cur = line ? line.nextSibling : this.container.firstChild; cur; cur = cur.nextSibling) {
- if (position == 0) {
- before = cur;
- break;
- }
- var text = (cur.innerText || cur.textContent || cur.nodeValue || "");
- if (text.length > position) {
- before = cur.nextSibling;
- content = text.slice(0, position) + content + text.slice(position);
- removeElement(cur);
- break;
- }
- position -= text.length;
- }
- }
-
- var lines = asEditorLines(content), doc = this.container.ownerDocument;
- for (var i = 0; i < lines.length; i++) {
- if (i > 0) this.container.insertBefore(doc.createElement("BR"), before);
- this.container.insertBefore(makePartSpan(lines[i], doc), before);
- }
- this.addDirtyNode(line);
- this.scheduleHighlight();
- },
-
- // Retrieve the selected text.
- selectedText: function() {
- var h = this.history;
- h.commit();
-
- var start = select.cursorPos(this.container, true),
- end = select.cursorPos(this.container, false);
- if (!start || !end) return "";
-
- if (start.node == end.node)
- return h.textAfter(start.node).slice(start.offset, end.offset);
-
- var text = [h.textAfter(start.node).slice(start.offset)];
- for (var pos = h.nodeAfter(start.node); pos != end.node; pos = h.nodeAfter(pos))
- text.push(h.textAfter(pos));
- text.push(h.textAfter(end.node).slice(0, end.offset));
- return cleanText(text.join("\n"));
- },
-
- // Replace the selection with another piece of text.
- replaceSelection: function(text) {
- this.history.commit();
- var start = select.cursorPos(this.container, true),
- end = select.cursorPos(this.container, false);
- if (!start || !end) return;
-
- end = this.replaceRange(start, end, text);
- select.setCursorPos(this.container, start, end);
- },
-
- replaceRange: function(from, to, text) {
- var lines = asEditorLines(text);
- lines[0] = this.history.textAfter(from.node).slice(0, from.offset) + lines[0];
- var lastLine = lines[lines.length - 1];
- lines[lines.length - 1] = lastLine + this.history.textAfter(to.node).slice(to.offset);
- var end = this.history.nodeAfter(to.node);
- this.history.push(from.node, end, lines);
- return {node: this.history.nodeBefore(end),
- offset: lastLine.length};
- },
-
- getSearchCursor: function(string, fromCursor) {
- return new SearchCursor(this, string, fromCursor);
- },
-
- // Re-indent the whole buffer
- reindent: function() {
- if (this.container.firstChild)
- this.indentRegion(null, this.container.lastChild);
- },
-
- reindentSelection: function(direction) {
- if (!select.somethingSelected(this.win)) {
- this.indentAtCursor(direction);
- }
- else {
- var start = select.selectionTopNode(this.container, true),
- end = select.selectionTopNode(this.container, false);
- if (start === false || end === false) return;
- this.indentRegion(start, end, direction);
- }
- },
-
- grabKeys: function(eventHandler, filter) {
- this.frozen = eventHandler;
- this.keyFilter = filter;
- },
- ungrabKeys: function() {
- this.frozen = "leave";
- this.keyFilter = null;
- },
-
- setParser: function(name) {
- Editor.Parser = window[name];
- if (this.container.firstChild) {
- forEach(this.container.childNodes, function(n) {
- if (n.nodeType != 3) n.dirty = true;
- });
- this.addDirtyNode(this.firstChild);
- this.scheduleHighlight();
- }
- },
-
- // Intercept enter and tab, and assign their new functions.
- keyDown: function(event) {
- if (this.frozen == "leave") this.frozen = null;
- if (this.frozen && (!this.keyFilter || this.keyFilter(event.keyCode))) {
- event.stop();
- this.frozen(event);
- return;
- }
-
- var code = event.keyCode;
- // Don't scan when the user is typing.
- this.delayScanning();
- // Schedule a paren-highlight event, if configured.
- if (this.options.autoMatchParens)
- this.scheduleParenBlink();
-
- // The variouschecks for !altKey are there because AltGr sets both
- // ctrlKey and altKey to true, and should not be recognised as
- // Control.
- if (code == 13) { // enter
- if (event.ctrlKey && !event.altKey) {
- this.reparseBuffer();
- }
- else {
- select.insertNewlineAtCursor(this.win);
- this.indentAtCursor();
- select.scrollToCursor(this.container);
- }
- event.stop();
- }
- else if (code == 9 && this.options.tabMode != "default") { // tab
- this.handleTab(!event.ctrlKey && !event.shiftKey);
- event.stop();
- }
- else if (code == 32 && event.shiftKey && this.options.tabMode == "default") { // space
- this.handleTab(true);
- event.stop();
- }
- else if (code == 36 && !event.shiftKey) { // home
- if (this.home())
- event.stop();
- }
- else if ((code == 219 || code == 221) && event.ctrlKey && !event.altKey) { // [, ]
- this.blinkParens(event.shiftKey);
- event.stop();
- }
- else if (event.metaKey && !event.shiftKey && (code == 37 || code == 39)) { // Meta-left/right
- var cursor = select.selectionTopNode(this.container);
- if (cursor === false || !this.container.firstChild) return;
-
- if (code == 37) select.focusAfterNode(startOfLine(cursor), this.container);
- else {
- var end = endOfLine(cursor, this.container);
- select.focusAfterNode(end ? end.previousSibling : this.container.lastChild, this.container);
- }
- event.stop();
- }
- else if ((event.ctrlKey || event.metaKey) && !event.altKey) {
- if ((event.shiftKey && code == 90) || code == 89) { // shift-Z, Y
- select.scrollToNode(this.history.redo());
- event.stop();
- }
- else if (code == 90 || code == 8) { // Z, backspace
- select.scrollToNode(this.history.undo());
- event.stop();
- }
- else if (code == 83 && this.options.saveFunction) { // S
- this.options.saveFunction();
- event.stop();
- }
- }
- },
-
- // Check for characters that should re-indent the current line,
- // and prevent Opera from handling enter and tab anyway.
- keyPress: function(event) {
- var electric = /indent|default/.test(this.options.tabMode) && Editor.Parser.electricChars;
- // Hack for Opera, and Firefox on OS X, in which stopping a
- // keydown event does not prevent the associated keypress event
- // from happening, so we have to cancel enter and tab again
- // here.
- if ((this.frozen && (!this.keyFilter || this.keyFilter(event.keyCode))) ||
- event.code == 13 || (event.code == 9 && this.options.tabMode != "default") ||
- (event.keyCode == 32 && event.shiftKey && this.options.tabMode == "default"))
- event.stop();
- else if (electric && electric.indexOf(event.character) != -1)
- this.parent.setTimeout(method(this, "indentAtCursor"), 0);
- },
-
- // Mark the node at the cursor dirty when a non-safe key is
- // released.
- keyUp: function(event) {
- this.cursorActivity(isSafeKey(event.keyCode));
- },
-
- // Indent the line following a given <br>, or null for the first
- // line. If given a <br> element, this must have been highlighted
- // so that it has an indentation method. Returns the whitespace
- // element that has been modified or created (if any).
- indentLineAfter: function(start, direction) {
- // whiteSpace is the whitespace span at the start of the line,
- // or null if there is no such node.
- var whiteSpace = start ? start.nextSibling : this.container.firstChild;
- if (whiteSpace && !hasClass(whiteSpace, "whitespace"))
- whiteSpace = null;
-
- // Sometimes the start of the line can influence the correct
- // indentation, so we retrieve it.
- var firstText = whiteSpace ? whiteSpace.nextSibling : (start ? start.nextSibling : this.container.firstChild);
- var nextChars = (start && firstText && firstText.currentText) ? firstText.currentText : "";
-
- // Ask the lexical context for the correct indentation, and
- // compute how much this differs from the current indentation.
- var newIndent = 0, curIndent = whiteSpace ? whiteSpace.currentText.length : 0;
- if (direction != null && this.options.tabMode == "shift")
- newIndent = direction ? curIndent + indentUnit : Math.max(0, curIndent - indentUnit)
- else if (start)
- newIndent = start.indentation(nextChars, curIndent, direction);
- else if (Editor.Parser.firstIndentation)
- newIndent = Editor.Parser.firstIndentation(nextChars, curIndent, direction);
- var indentDiff = newIndent - curIndent;
-
- // If there is too much, this is just a matter of shrinking a span.
- if (indentDiff < 0) {
- if (newIndent == 0) {
- if (firstText) select.snapshotMove(whiteSpace.firstChild, firstText.firstChild, 0);
- removeElement(whiteSpace);
- whiteSpace = null;
- }
- else {
- select.snapshotMove(whiteSpace.firstChild, whiteSpace.firstChild, indentDiff, true);
- whiteSpace.currentText = makeWhiteSpace(newIndent);
- whiteSpace.firstChild.nodeValue = whiteSpace.currentText;
- }
- }
- // Not enough...
- else if (indentDiff > 0) {
- // If there is whitespace, we grow it.
- if (whiteSpace) {
- whiteSpace.currentText = makeWhiteSpace(newIndent);
- whiteSpace.firstChild.nodeValue = whiteSpace.currentText;
- }
- // Otherwise, we have to add a new whitespace node.
- else {
- whiteSpace = makePartSpan(makeWhiteSpace(newIndent), this.doc);
- whiteSpace.className = "whitespace";
- if (start) insertAfter(whiteSpace, start);
- else this.container.insertBefore(whiteSpace, this.container.firstChild);
- }
- if (firstText) select.snapshotMove(firstText.firstChild, whiteSpace.firstChild, curIndent, false, true);
- }
- if (indentDiff != 0) this.addDirtyNode(start);
- return whiteSpace;
- },
-
- // Re-highlight the selected part of the document.
- highlightAtCursor: function() {
- var pos = select.selectionTopNode(this.container, true);
- var to = select.selectionTopNode(this.container, false);
- if (pos === false || to === false) return;
-
- select.markSelection(this.win);
- if (this.highlight(pos, endOfLine(to, this.container), true, 20) === false)
- return false;
- select.selectMarked();
- return true;
- },
-
- // When tab is pressed with text selected, the whole selection is
- // re-indented, when nothing is selected, the line with the cursor
- // is re-indented.
- handleTab: function(direction) {
- if (this.options.tabMode == "spaces")
- select.insertTabAtCursor(this.win);
- else
- this.reindentSelection(direction);
- },
-
- home: function() {
- var cur = select.selectionTopNode(this.container, true), start = cur;
- if (cur === false || !(!cur || cur.isPart || cur.nodeName == "BR") || !this.container.firstChild)
- return false;
-
- while (cur && cur.nodeName != "BR") cur = cur.previousSibling;
- var next = cur ? cur.nextSibling : this.container.firstChild;
- if (next && next != start && next.isPart && hasClass(next, "whitespace"))
- select.focusAfterNode(next, this.container);
- else
- select.focusAfterNode(cur, this.container);
- return true;
- },
-
- // Delay (or initiate) the next paren blink event.
- scheduleParenBlink: function() {
- if (this.parenEvent) this.parent.clearTimeout(this.parenEvent);
- var self = this;
- this.parenEvent = this.parent.setTimeout(function(){self.blinkParens();}, 300);
- },
-
- // Take the token before the cursor. If it contains a character in
- // '()[]{}', search for the matching paren/brace/bracket, and
- // highlight them in green for a moment, or red if no proper match
- // was found.
- blinkParens: function(jump) {
- if (!window.select) return;
- // Clear the event property.
- if (this.parenEvent) this.parent.clearTimeout(this.parenEvent);
- this.parenEvent = null;
-
- // Extract a 'paren' from a piece of text.
- function paren(node) {
- if (node.currentText) {
- var match = node.currentText.match(/^[\s\u00a0]*([\(\)\[\]{}])[\s\u00a0]*$/);
- return match && match[1];
- }
- }
- // Determine the direction a paren is facing.
- function forward(ch) {
- return /[\(\[\{]/.test(ch);
- }
-
- var ch, self = this, cursor = select.selectionTopNode(this.container, true);
- if (!cursor || !this.highlightAtCursor()) return;
- cursor = select.selectionTopNode(this.container, true);
- if (!(cursor && ((ch = paren(cursor)) || (cursor = cursor.nextSibling) && (ch = paren(cursor)))))
- return;
- // We only look for tokens with the same className.
- var className = cursor.className, dir = forward(ch), match = matching[ch];
-
- // Since parts of the document might not have been properly
- // highlighted, and it is hard to know in advance which part we
- // have to scan, we just try, and when we find dirty nodes we
- // abort, parse them, and re-try.
- function tryFindMatch() {
- var stack = [], ch, ok = true;;
- for (var runner = cursor; runner; runner = dir ? runner.nextSibling : runner.previousSibling) {
- if (runner.className == className && runner.nodeName == "SPAN" && (ch = paren(runner))) {
- if (forward(ch) == dir)
- stack.push(ch);
- else if (!stack.length)
- ok = false;
- else if (stack.pop() != matching[ch])
- ok = false;
- if (!stack.length) break;
- }
- else if (runner.dirty || runner.nodeName != "SPAN" && runner.nodeName != "BR") {
- return {node: runner, status: "dirty"};
- }
- }
- return {node: runner, status: runner && ok};
- }
- // Temporarily give the relevant nodes a colour.
- function blink(node, ok) {
- node.style.fontWeight = "bold";
- node.style.color = ok ? "#8F8" : "#F88";
- self.parent.setTimeout(function() {node.style.fontWeight = ""; node.style.color = "";}, 500);
- }
-
- while (true) {
- var found = tryFindMatch();
- if (found.status == "dirty") {
- this.highlight(found.node, endOfLine(found.node));
- // Needed because in some corner cases a highlight does not
- // reach a node.
- found.node.dirty = false;
- continue;
- }
- else {
- blink(cursor, found.status);
- if (found.node) {
- blink(found.node, found.status);
- if (jump) select.focusAfterNode(found.node.previousSibling, this.container);
- }
- break;
- }
- }
- },
-
- // Adjust the amount of whitespace at the start of the line that
- // the cursor is on so that it is indented properly.
- indentAtCursor: function(direction) {
- if (!this.container.firstChild) return;
- // The line has to have up-to-date lexical information, so we
- // highlight it first.
- if (!this.highlightAtCursor()) return;
- var cursor = select.selectionTopNode(this.container, false);
- // If we couldn't determine the place of the cursor,
- // there's nothing to indent.
- if (cursor === false)
- return;
- var lineStart = startOfLine(cursor);
- var whiteSpace = this.indentLineAfter(lineStart, direction);
- if (cursor == lineStart && whiteSpace)
- cursor = whiteSpace;
- // This means the indentation has probably messed up the cursor.
- if (cursor == whiteSpace)
- select.focusAfterNode(cursor, this.container);
- },
-
- // Indent all lines whose start falls inside of the current
- // selection.
- indentRegion: function(start, end, direction) {
- var current = (start = startOfLine(start)), before = start && startOfLine(start.previousSibling);
- if (end.nodeName != "BR") end = endOfLine(end, this.container);
-
- do {
- var next = endOfLine(current, this.container);
- if (current) this.highlight(before, next, true);
- this.indentLineAfter(current, direction);
- before = current;
- current = next;
- } while (current != end);
- select.setCursorPos(this.container, {node: start, offset: 0}, {node: end, offset: 0});
- },
-
- // Find the node that the cursor is in, mark it as dirty, and make
- // sure a highlight pass is scheduled.
- cursorActivity: function(safe) {
- if (internetExplorer) {
- this.container.createTextRange().execCommand("unlink");
- this.selectionSnapshot = select.selectionCoords(this.win);
- }
-
- var activity = this.options.cursorActivity;
- if (!safe || activity) {
- var cursor = select.selectionTopNode(this.container, false);
- if (cursor === false || !this.container.firstChild) return;
- cursor = cursor || this.container.firstChild;
- if (activity) activity(cursor);
- if (!safe) {
- this.scheduleHighlight();
- this.addDirtyNode(cursor);
- }
- }
- },
-
- reparseBuffer: function() {
- forEach(this.container.childNodes, function(node) {node.dirty = true;});
- if (this.container.firstChild)
- this.addDirtyNode(this.container.firstChild);
- },
-
- // Add a node to the set of dirty nodes, if it isn't already in
- // there.
- addDirtyNode: function(node) {
- node = node || this.container.firstChild;
- if (!node) return;
-
- for (var i = 0; i < this.dirty.length; i++)
- if (this.dirty[i] == node) return;
-
- if (node.nodeType != 3)
- node.dirty = true;
- this.dirty.push(node);
- },
-
- // Cause a highlight pass to happen in options.passDelay
- // milliseconds. Clear the existing timeout, if one exists. This
- // way, the passes do not happen while the user is typing, and
- // should as unobtrusive as possible.
- scheduleHighlight: function() {
- // Timeouts are routed through the parent window, because on
- // some browsers designMode windows do not fire timeouts.
- var self = this;
- this.parent.clearTimeout(this.highlightTimeout);
- this.highlightTimeout = this.parent.setTimeout(function(){self.highlightDirty();}, this.options.passDelay);
- },
-
- // Fetch one dirty node, and remove it from the dirty set.
- getDirtyNode: function() {
- while (this.dirty.length > 0) {
- var found = this.dirty.pop();
- // IE8 sometimes throws an unexplainable 'invalid argument'
- // exception for found.parentNode
- try {
- // If the node has been coloured in the meantime, or is no
- // longer in the document, it should not be returned.
- while (found && found.parentNode != this.container)
- found = found.parentNode
- if (found && (found.dirty || found.nodeType == 3))
- return found;
- } catch (e) {}
- }
- return null;
- },
-
- // Pick dirty nodes, and highlight them, until options.passTime
- // milliseconds have gone by. The highlight method will continue
- // to next lines as long as it finds dirty nodes. It returns
- // information about the place where it stopped. If there are
- // dirty nodes left after this function has spent all its lines,
- // it shedules another highlight to finish the job.
- highlightDirty: function(force) {
- // Prevent FF from raising an error when it is firing timeouts
- // on a page that's no longer loaded.
- if (!window.select) return;
-
- if (!this.options.readOnly) select.markSelection(this.win);
- var start, endTime = force ? null : time() + this.options.passTime;
- while (time() < endTime && (start = this.getDirtyNode())) {
- var result = this.highlight(start, endTime);
- if (result && result.node && result.dirty)
- this.addDirtyNode(result.node);
- }
- if (!this.options.readOnly) select.selectMarked();
- if (start) this.scheduleHighlight();
- return this.dirty.length == 0;
- },
-
- // Creates a function that, when called through a timeout, will
- // continuously re-parse the document.
- documentScanner: function(passTime) {
- var self = this, pos = null;
- return function() {
- // FF timeout weirdness workaround.
- if (!window.select) return;
- // If the current node is no longer in the document... oh
- // well, we start over.
- if (pos && pos.parentNode != self.container)
- pos = null;
- select.markSelection(self.win);
- var result = self.highlight(pos, time() + passTime, true);
- select.selectMarked();
- var newPos = result ? (result.node && result.node.nextSibling) : null;
- pos = (pos == newPos) ? null : newPos;
- self.delayScanning();
- };
- },
-
- // Starts the continuous scanning process for this document after
- // a given interval.
- delayScanning: function() {
- if (this.scanner) {
- this.parent.clearTimeout(this.documentScan);
- this.documentScan = this.parent.setTimeout(this.scanner, this.options.continuousScanning);
- }
- },
-
- // The function that does the actual highlighting/colouring (with
- // help from the parser and the DOM normalizer). Its interface is
- // rather overcomplicated, because it is used in different
- // situations: ensuring that a certain line is highlighted, or
- // highlighting up to X milliseconds starting from a certain
- // point. The 'from' argument gives the node at which it should
- // start. If this is null, it will start at the beginning of the
- // document. When a timestamp is given with the 'target' argument,
- // it will stop highlighting at that time. If this argument holds
- // a DOM node, it will highlight until it reaches that node. If at
- // any time it comes across two 'clean' lines (no dirty nodes), it
- // will stop, except when 'cleanLines' is true. maxBacktrack is
- // the maximum number of lines to backtrack to find an existing
- // parser instance. This is used to give up in situations where a
- // highlight would take too long and freeze the browser interface.
- highlight: function(from, target, cleanLines, maxBacktrack){
- var container = this.container, self = this, active = this.options.activeTokens;
- var endTime = (typeof target == "number" ? target : null);
-
- if (!container.firstChild)
- return;
- // Backtrack to the first node before from that has a partial
- // parse stored.
- while (from && (!from.parserFromHere || from.dirty)) {
- if (maxBacktrack != null && from.nodeName == "BR" && (--maxBacktrack) < 0)
- return false;
- from = from.previousSibling;
- }
- // If we are at the end of the document, do nothing.
- if (from && !from.nextSibling)
- return;
-
- // Check whether a part (<span> node) and the corresponding token
- // match.
- function correctPart(token, part){
- return !part.reduced && part.currentText == token.value && part.className == token.style;
- }
- // Shorten the text associated with a part by chopping off
- // characters from the front. Note that only the currentText
- // property gets changed. For efficiency reasons, we leave the
- // nodeValue alone -- we set the reduced flag to indicate that
- // this part must be replaced.
- function shortenPart(part, minus){
- part.currentText = part.currentText.substring(minus);
- part.reduced = true;
- }
- // Create a part corresponding to a given token.
- function tokenPart(token){
- var part = makePartSpan(token.value, self.doc);
- part.className = token.style;
- return part;
- }
-
- function maybeTouch(node) {
- if (node) {
- if (lineDirty || node.nextSibling != node.oldNextSibling)
- self.history.touch(node);
- node.oldNextSibling = node.nextSibling;
- }
- else {
- if (lineDirty || self.container.firstChild != self.container.oldFirstChild)
- self.history.touch(node);
- self.container.oldFirstChild = self.container.firstChild;
- }
- }
-
- // Get the token stream. If from is null, we start with a new
- // parser from the start of the frame, otherwise a partial parse
- // is resumed.
- var traversal = traverseDOM(from ? from.nextSibling : container.firstChild),
- stream = stringStream(traversal),
- parsed = from ? from.parserFromHere(stream) : Editor.Parser.make(stream);
-
- // parts is an interface to make it possible to 'delay' fetching
- // the next DOM node until we are completely done with the one
- // before it. This is necessary because often the next node is
- // not yet available when we want to proceed past the current
- // one.
- var parts = {
- current: null,
- // Fetch current node.
- get: function(){
- if (!this.current)
- this.current = traversal.nodes.shift();
- return this.current;
- },
- // Advance to the next part (do not fetch it yet).
- next: function(){
- this.current = null;
- },
- // Remove the current part from the DOM tree, and move to the
- // next.
- remove: function(){
- container.removeChild(this.get());
- this.current = null;
- },
- // Advance to the next part that is not empty, discarding empty
- // parts.
- getNonEmpty: function(){
- var part = this.get();
- // Allow empty nodes when they are alone on a line, needed
- // for the FF cursor bug workaround (see select.js,
- // insertNewlineAtCursor).
- while (part && part.nodeName == "SPAN" && part.currentText == "") {
- var old = part;
- this.remove();
- part = this.get();
- // Adjust selection information, if any. See select.js for details.
- select.snapshotMove(old.firstChild, part && (part.firstChild || part), 0);
- }
- return part;
- }
- };
-
- var lineDirty = false, prevLineDirty = true, lineNodes = 0;
-
- // This forEach loops over the tokens from the parsed stream, and
- // at the same time uses the parts object to proceed through the
- // corresponding DOM nodes.
- forEach(parsed, function(token){
- var part = parts.getNonEmpty();
-
- if (token.value == "\n"){
- // The idea of the two streams actually staying synchronized
- // is such a long shot that we explicitly check.
- if (part.nodeName != "BR")
- throw "Parser out of sync. Expected BR.";
-
- if (part.dirty || !part.indentation) lineDirty = true;
- maybeTouch(from);
- from = part;
-
- // Every <br> gets a copy of the parser state and a lexical
- // context assigned to it. The first is used to be able to
- // later resume parsing from this point, the second is used
- // for indentation.
- part.parserFromHere = parsed.copy();
- part.indentation = token.indentation;
- part.dirty = false;
-
- // If the target argument wasn't an integer, go at least
- // until that node.
- if (endTime == null && part == target) throw StopIteration;
-
- // A clean line with more than one node means we are done.
- // Throwing a StopIteration is the way to break out of a
- // MochiKit forEach loop.
- if ((endTime != null && time() >= endTime) || (!lineDirty && !prevLineDirty && lineNodes > 1 && !cleanLines))
- throw StopIteration;
- prevLineDirty = lineDirty; lineDirty = false; lineNodes = 0;
- parts.next();
- }
- else {
- if (part.nodeName != "SPAN")
- throw "Parser out of sync. Expected SPAN.";
- if (part.dirty)
- lineDirty = true;
- lineNodes++;
-
- // If the part matches the token, we can leave it alone.
- if (correctPart(token, part)){
- part.dirty = false;
- parts.next();
- }
- // Otherwise, we have to fix it.
- else {
- lineDirty = true;
- // Insert the correct part.
- var newPart = tokenPart(token);
- container.insertBefore(newPart, part);
- if (active) active(newPart, token, self);
- var tokensize = token.value.length;
- var offset = 0;
- // Eat up parts until the text for this token has been
- // removed, adjusting the stored selection info (see
- // select.js) in the process.
- while (tokensize > 0) {
- part = parts.get();
- var partsize = part.currentText.length;
- select.snapshotReplaceNode(part.firstChild, newPart.firstChild, tokensize, offset);
- if (partsize > tokensize){
- shortenPart(part, tokensize);
- tokensize = 0;
- }
- else {
- tokensize -= partsize;
- offset += partsize;
- parts.remove();
- }
- }
- }
- }
- });
- maybeTouch(from);
- webkitLastLineHack(this.container);
-
- // The function returns some status information that is used by
- // hightlightDirty to determine whether and where it has to
- // continue.
- return {node: parts.getNonEmpty(),
- dirty: lineDirty};
- }
- };
-
- return Editor;
-})();
-
-addEventHandler(window, "load", function() {
- var CodeMirror = window.frameElement.CodeMirror;
- CodeMirror.editor = new Editor(CodeMirror.options);
- this.parent.setTimeout(method(CodeMirror, "init"), 0);
-});
diff --git a/media/CodeMirror-0.62/js/highlight.js b/media/CodeMirror-0.62/js/highlight.js
deleted file mode 100644
index f0de59c..0000000
--- a/media/CodeMirror-0.62/js/highlight.js
+++ /dev/null
@@ -1,68 +0,0 @@
-// Minimal framing needed to use CodeMirror-style parsers to highlight
-// code. Load this along with tokenize.js, stringstream.js, and your
-// parser. Then call highlightText, passing a string as the first
-// argument, and as the second argument either a callback function
-// that will be called with an array of SPAN nodes for every line in
-// the code, or a DOM node to which to append these spans, and
-// optionally (not needed if you only loaded one parser) a parser
-// object.
-
-// Stuff from util.js that the parsers are using.
-var StopIteration = {toString: function() {return "StopIteration"}};
-
-var Editor = {};
-var indentUnit = 2;
-
-(function(){
- function normaliseString(string) {
- var tab = "";
- for (var i = 0; i < indentUnit; i++) tab += " ";
-
- string = string.replace(/\t/g, tab).replace(/\u00a0/g, " ").replace(/\r\n?/g, "\n");
- var pos = 0, parts = [], lines = string.split("\n");
- for (var line = 0; line < lines.length; line++) {
- if (line != 0) parts.push("\n");
- parts.push(lines[line]);
- }
-
- return {
- next: function() {
- if (pos < parts.length) return parts[pos++];
- else throw StopIteration;
- }
- };
- }
-
- window.highlightText = function(string, callback, parser) {
- var parser = (parser || Editor.Parser).make(stringStream(normaliseString(string)));
- var line = [];
- if (callback.nodeType == 1) {
- var node = callback;
- callback = function(line) {
- for (var i = 0; i < line.length; i++)
- node.appendChild(line[i]);
- node.appendChild(document.createElement("BR"));
- };
- }
-
- try {
- while (true) {
- var token = parser.next();
- if (token.value == "\n") {
- callback(line);
- line = [];
- }
- else {
- var span = document.createElement("SPAN");
- span.className = token.style;
- span.appendChild(document.createTextNode(token.value));
- line.push(span);
- }
- }
- }
- catch (e) {
- if (e != StopIteration) throw e;
- }
- if (line.length) callback(line);
- }
-})();
diff --git a/media/CodeMirror-0.62/js/mirrorframe.js b/media/CodeMirror-0.62/js/mirrorframe.js
deleted file mode 100644
index 7f6ad1a..0000000
--- a/media/CodeMirror-0.62/js/mirrorframe.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Demonstration of embedding CodeMirror in a bigger application. The
- * interface defined here is a mess of prompts and confirms, and
- * should probably not be used in a real project.
- */
-
-function MirrorFrame(place, options) {
- this.home = document.createElement("DIV");
- if (place.appendChild)
- place.appendChild(this.home);
- else
- place(this.home);
-
- var self = this;
- function makeButton(name, action) {
- var button = document.createElement("INPUT");
- button.type = "button";
- button.value = name;
- self.home.appendChild(button);
- button.onclick = function(){self[action].call(self);};
- }
-
- makeButton("Search", "search");
- makeButton("Replace", "replace");
- makeButton("Current line", "line");
- makeButton("Jump to line", "jump");
- makeButton("Insert constructor", "macro");
- makeButton("Indent all", "reindent");
-
- this.mirror = new CodeMirror(this.home, options);
-}
-
-MirrorFrame.prototype = {
- search: function() {
- var text = prompt("Enter search term:", "");
- if (!text) return;
-
- var first = true;
- do {
- var cursor = this.mirror.getSearchCursor(text, first);
- first = false;
- while (cursor.findNext()) {
- cursor.select();
- if (!confirm("Search again?"))
- return;
- }
- } while (confirm("End of document reached. Start over?"));
- },
-
- replace: function() {
- // This is a replace-all, but it is possible to implement a
- // prompting replace.
- var from = prompt("Enter search string:", ""), to;
- if (from) to = prompt("What should it be replaced with?", "");
- if (to == null) return;
-
- var cursor = this.mirror.getSearchCursor(from, false);
- while (cursor.findNext())
- cursor.replace(to);
- },
-
- jump: function() {
- var line = prompt("Jump to line:", "");
- if (line && !isNaN(Number(line)))
- this.mirror.jumpToLine(Number(line));
- },
-
- line: function() {
- alert("The cursor is currently at line " + this.mirror.currentLine());
- this.mirror.focus();
- },
-
- macro: function() {
- var name = prompt("Name your constructor:", "");
- if (name)
- this.mirror.replaceSelection("function " + name + "() {\n \n}\n\n" + name + ".prototype = {\n \n};\n");
- },
-
- reindent: function() {
- this.mirror.reindent();
- }
-};
diff --git a/media/CodeMirror-0.62/js/parsecss.js b/media/CodeMirror-0.62/js/parsecss.js
deleted file mode 100644
index 4f90d59..0000000
--- a/media/CodeMirror-0.62/js/parsecss.js
+++ /dev/null
@@ -1,155 +0,0 @@
-/* Simple parser for CSS */
-
-var CSSParser = Editor.Parser = (function() {
- var tokenizeCSS = (function() {
- function normal(source, setState) {
- var ch = source.next();
- if (ch == "@") {
- source.nextWhileMatches(/\w/);
- return "css-at";
- }
- else if (ch == "/" && source.equals("*")) {
- setState(inCComment);
- return null;
- }
- else if (ch == "<" && source.equals("!")) {
- setState(inSGMLComment);
- return null;
- }
- else if (ch == "=") {
- return "css-compare";
- }
- else if (source.equals("=") && (ch == "~" || ch == "|")) {
- source.next();
- return "css-compare";
- }
- else if (ch == "\"" || ch == "'") {
- setState(inString(ch));
- return null;
- }
- else if (ch == "#") {
- source.nextWhileMatches(/\w/);
- return "css-hash";
- }
- else if (ch == "!") {
- source.nextWhileMatches(/[ \t]/);
- source.nextWhileMatches(/\w/);
- return "css-important";
- }
- else if (/\d/.test(ch)) {
- source.nextWhileMatches(/[\w.%]/);
- return "css-unit";
- }
- else if (/[,.+>*\/]/.test(ch)) {
- return "css-select-op";
- }
- else if (/[;{}:\[\]]/.test(ch)) {
- return "css-punctuation";
- }
- else {
- source.nextWhileMatches(/[\w\\\-_]/);
- return "css-identifier";
- }
- }
-
- function inCComment(source, setState) {
- var maybeEnd = false;
- while (!source.endOfLine()) {
- var ch = source.next();
- if (maybeEnd && ch == "/") {
- setState(normal);
- break;
- }
- maybeEnd = (ch == "*");
- }
- return "css-comment";
- }
-
- function inSGMLComment(source, setState) {
- var dashes = 0;
- while (!source.endOfLine()) {
- var ch = source.next();
- if (dashes >= 2 && ch == ">") {
- setState(normal);
- break;
- }
- dashes = (ch == "-") ? dashes + 1 : 0;
- }
- return "css-comment";
- }
-
- function inString(quote) {
- return function(source, setState) {
- var escaped = false;
- while (!source.endOfLine()) {
- var ch = source.next();
- if (ch == quote && !escaped)
- break;
- escaped = !escaped && ch == "\\";
- }
- if (!escaped)
- setState(normal);
- return "css-string";
- };
- }
-
- return function(source, startState) {
- return tokenizer(source, startState || normal);
- };
- })();
-
- function indentCSS(inBraces, inRule, base) {
- return function(nextChars) {
- if (!inBraces || /^\}/.test(nextChars)) return base;
- else if (inRule) return base + indentUnit * 2;
- else return base + indentUnit;
- };
- }
-
- // This is a very simplistic parser -- since CSS does not really
- // nest, it works acceptably well, but some nicer colouroing could
- // be provided with a more complicated parser.
- function parseCSS(source, basecolumn) {
- basecolumn = basecolumn || 0;
- var tokens = tokenizeCSS(source);
- var inBraces = false, inRule = false;
-
- var iter = {
- next: function() {
- var token = tokens.next(), style = token.style, content = token.content;
-
- if (style == "css-identifier" && inRule)
- token.style = "css-value";
- if (style == "css-hash")
- token.style = inRule ? "css-colorcode" : "css-identifier";
-
- if (content == "\n")
- token.indentation = indentCSS(inBraces, inRule, basecolumn);
-
- if (content == "{")
- inBraces = true;
- else if (content == "}")
- inBraces = inRule = false;
- else if (inBraces && content == ";")
- inRule = false;
- else if (inBraces && style != "css-comment" && style != "whitespace")
- inRule = true;
-
- return token;
- },
-
- copy: function() {
- var _inBraces = inBraces, _inRule = inRule, _tokenState = tokens.state;
- return function(source) {
- tokens = tokenizeCSS(source, _tokenState);
- inBraces = _inBraces;
- inRule = _inRule;
- return iter;
- };
- }
- };
- return iter;
- }
-
- return {make: parseCSS, electricChars: "}"};
-})();
diff --git a/media/CodeMirror-0.62/js/parsedummy.js b/media/CodeMirror-0.62/js/parsedummy.js
deleted file mode 100644
index 9e63caa..0000000
--- a/media/CodeMirror-0.62/js/parsedummy.js
+++ /dev/null
@@ -1,32 +0,0 @@
-var DummyParser = Editor.Parser = (function() {
- function tokenizeDummy(source) {
- while (!source.endOfLine()) source.next();
- return "text";
- }
- function parseDummy(source) {
- function indentTo(n) {return function() {return n;}}
- source = tokenizer(source, tokenizeDummy);
- var space = 0;
-
- var iter = {
- next: function() {
- var tok = source.next();
- if (tok.type == "whitespace") {
- if (tok.value == "\n") tok.indentation = indentTo(space);
- else space = tok.value.length;
- }
- return tok;
- },
- copy: function() {
- var _space = space;
- return function(_source) {
- space = _space;
- source = tokenizer(_source, tokenizeDummy);
- return iter;
- };
- }
- };
- return iter;
- }
- return {make: parseDummy};
-})();
diff --git a/media/CodeMirror-0.62/js/parsehtmlmixed.js b/media/CodeMirror-0.62/js/parsehtmlmixed.js
deleted file mode 100644
index ed1a608..0000000
--- a/media/CodeMirror-0.62/js/parsehtmlmixed.js
+++ /dev/null
@@ -1,74 +0,0 @@
-var HTMLMixedParser = Editor.Parser = (function() {
- if (!(CSSParser && JSParser && XMLParser))
- throw new Error("CSS, JS, and XML parsers must be loaded for HTML mixed mode to work.");
- XMLParser.configure({useHTMLKludges: true});
-
- function parseMixed(stream) {
- var htmlParser = XMLParser.make(stream), localParser = null, inTag = false;
- var iter = {next: top, copy: copy};
-
- function top() {
- var token = htmlParser.next();
- if (token.content == "<")
- inTag = true;
- else if (token.style == "xml-tagname" && inTag === true)
- inTag = token.content.toLowerCase();
- else if (token.content == ">") {
- if (inTag == "script")
- iter.next = local(JSParser, "</script");
- else if (inTag == "style")
- iter.next = local(CSSParser, "</style");
- inTag = false;
- }
- return token;
- }
- function local(parser, tag) {
- var baseIndent = htmlParser.indentation();
- localParser = parser.make(stream, baseIndent + indentUnit);
- return function() {
- if (stream.lookAhead(tag, false, false, true)) {
- localParser = null;
- iter.next = top;
- return top();
- }
-
- var token = localParser.next();
- var lt = token.value.lastIndexOf("<"), sz = Math.min(token.value.length - lt, tag.length);
- if (lt != -1 && token.value.slice(lt, lt + sz).toLowerCase() == tag.slice(0, sz) &&
- stream.lookAhead(tag.slice(sz), false, false, true)) {
- stream.push(token.value.slice(lt));
- token.value = token.value.slice(0, lt);
- }
-
- if (token.indentation) {
- var oldIndent = token.indentation;
- token.indentation = function(chars) {
- if (chars == "</")
- return baseIndent;
- else
- return oldIndent(chars);
- }
- }
-
- return token;
- };
- }
-
- function copy() {
- var _html = htmlParser.copy(), _local = localParser && localParser.copy(),
- _next = iter.next, _inTag = inTag;
- return function(_stream) {
- stream = _stream;
- htmlParser = _html(_stream);
- localParser = _local && _local(_stream);
- iter.next = _next;
- inTag = _inTag;
- return iter;
- };
- }
- return iter;
- }
-
- return {make: parseMixed, electricChars: "{}/:"};
-
-})();
diff --git a/media/CodeMirror-0.62/js/parsejavascript.js b/media/CodeMirror-0.62/js/parsejavascript.js
deleted file mode 100644
index 756639a..0000000
--- a/media/CodeMirror-0.62/js/parsejavascript.js
+++ /dev/null
@@ -1,341 +0,0 @@
-/* Parse function for JavaScript. Makes use of the tokenizer from
- * tokenizejavascript.js. Note that your parsers do not have to be
- * this complicated -- if you don't want to recognize local variables,
- * in many languages it is enough to just look for braces, semicolons,
- * parentheses, etc, and know when you are inside a string or comment.
- *
- * See manual.html for more info about the parser interface.
- */
-
-var JSParser = Editor.Parser = (function() {
- // Token types that can be considered to be atoms.
- var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
- // Constructor for the lexical context objects.
- function JSLexical(indented, column, type, align, prev, info) {
- // indentation at start of this line
- this.indented = indented;
- // column at which this scope was opened
- this.column = column;
- // type of scope ('vardef', 'stat' (statement), 'form' (special form), '[', '{', or '(')
- this.type = type;
- // '[', '{', or '(' blocks that have any text after their opening
- // character are said to be 'aligned' -- any lines below are
- // indented all the way to the opening character.
- if (align != null)
- this.align = align;
- // Parent scope, if any.
- this.prev = prev;
- this.info = info;
- }
-
- // My favourite JavaScript indentation rules.
- function indentJS(lexical) {
- return function(firstChars) {
- var firstChar = firstChars && firstChars.charAt(0), type = lexical.type;
- var closing = firstChar == type;
- if (type == "vardef")
- return lexical.indented + 4;
- else if (type == "form" && firstChar == "{")
- return lexical.indented;
- else if (type == "stat" || type == "form")
- return lexical.indented + indentUnit;
- else if (lexical.info == "switch" && !closing)
- return lexical.indented + (/^(?:case|default)\b/.test(firstChars) ? indentUnit : 2 * indentUnit);
- else if (lexical.align)
- return lexical.column - (closing ? 1 : 0);
- else
- return lexical.indented + (closing ? 0 : indentUnit);
- };
- }
-
- // The parser-iterator-producing function itself.
- function parseJS(input, basecolumn) {
- // Wrap the input in a token stream
- var tokens = tokenizeJavaScript(input);
- // The parser state. cc is a stack of actions that have to be
- // performed to finish the current statement. For example we might
- // know that we still need to find a closing parenthesis and a
- // semicolon. Actions at the end of the stack go first. It is
- // initialized with an infinitely looping action that consumes
- // whole statements.
- var cc = [statements];
- // Context contains information about the current local scope, the
- // variables defined in that, and the scopes above it.
- var context = null;
- // The lexical scope, used mostly for indentation.
- var lexical = new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false);
- // Current column, and the indentation at the start of the current
- // line. Used to create lexical scope objects.
- var column = 0;
- var indented = 0;
- // Variables which are used by the mark, cont, and pass functions
- // below to communicate with the driver loop in the 'next'
- // function.
- var consume, marked;
-
- // The iterator object.
- var parser = {next: next, copy: copy};
-
- function next(){
- // Start by performing any 'lexical' actions (adjusting the
- // lexical variable), or the operations below will be working
- // with the wrong lexical state.
- while(cc[cc.length - 1].lex)
- cc.pop()();
-
- // Fetch a token.
- var token = tokens.next();
-
- // Adjust column and indented.
- if (token.type == "whitespace" && column == 0)
- indented = token.value.length;
- column += token.value.length;
- if (token.content == "\n"){
- indented = column = 0;
- // If the lexical scope's align property is still undefined at
- // the end of the line, it is an un-aligned scope.
- if (!("align" in lexical))
- lexical.align = false;
- // Newline tokens get an indentation function associated with
- // them.
- token.indentation = indentJS(lexical);
- }
- // No more processing for meaningless tokens.
- if (token.type == "whitespace" || token.type == "comment")
- return token;
- // When a meaningful token is found and the lexical scope's
- // align is undefined, it is an aligned scope.
- if (!("align" in lexical))
- lexical.align = true;
-
- // Execute actions until one 'consumes' the token and we can
- // return it.
- while(true) {
- consume = marked = false;
- // Take and execute the topmost action.
- cc.pop()(token.type, token.content);
- if (consume){
- // Marked is used to change the style of the current token.
- if (marked)
- token.style = marked;
- // Here we differentiate between local and global variables.
- else if (token.type == "variable" && inScope(token.content))
- token.style = "js-localvariable";
- return token;
- }
- }
- }
-
- // This makes a copy of the parser state. It stores all the
- // stateful variables in a closure, and returns a function that
- // will restore them when called with a new input stream. Note
- // that the cc array has to be copied, because it is contantly
- // being modified. Lexical objects are not mutated, and context
- // objects are not mutated in a harmful way, so they can be shared
- // between runs of the parser.
- function copy(){
- var _context = context, _lexical = lexical, _cc = cc.concat([]), _tokenState = tokens.state;
-
- return function copyParser(input){
- context = _context;
- lexical = _lexical;
- cc = _cc.concat([]); // copies the array
- column = indented = 0;
- tokens = tokenizeJavaScript(input, _tokenState);
- return parser;
- };
- }
-
- // Helper function for pushing a number of actions onto the cc
- // stack in reverse order.
- function push(fs){
- for (var i = fs.length - 1; i >= 0; i--)
- cc.push(fs[i]);
- }
- // cont and pass are used by the action functions to add other
- // actions to the stack. cont will cause the current token to be
- // consumed, pass will leave it for the next action.
- function cont(){
- push(arguments);
- consume = true;
- }
- function pass(){
- push(arguments);
- consume = false;
- }
- // Used to change the style of the current token.
- function mark(style){
- marked = style;
- }
-
- // Push a new scope. Will automatically link the current scope.
- function pushcontext(){
- context = {prev: context, vars: {"this": true, "arguments": true}};
- }
- // Pop off the current scope.
- function popcontext(){
- context = context.prev;
- }
- // Register a variable in the current scope.
- function register(varname){
- if (context){
- mark("js-variabledef");
- context.vars[varname] = true;
- }
- }
- // Check whether a variable is defined in the current scope.
- function inScope(varname){
- var cursor = context;
- while (cursor) {
- if (cursor.vars[varname])
- return true;
- cursor = cursor.prev;
- }
- return false;
- }
-
- // Push a new lexical context of the given type.
- function pushlex(type, info) {
- var result = function(){
- lexical = new JSLexical(indented, column, type, null, lexical, info)
- };
- result.lex = true;
- return result;
- }
- // Pop off the current lexical context.
- function poplex(){
- lexical = lexical.prev;
- }
- poplex.lex = true;
- // The 'lex' flag on these actions is used by the 'next' function
- // to know they can (and have to) be ran before moving on to the
- // next token.
-
- // Creates an action that discards tokens until it finds one of
- // the given type.
- function expect(wanted){
- return function expecting(type){
- if (type == wanted) cont();
- else cont(arguments.callee);
- };
- }
-
- // Looks for a statement, and then calls itself.
- function statements(type){
- return pass(statement, statements);
- }
- // Dispatches various types of statements based on the type of the
- // current token.
- function statement(type){
- if (type == "var") cont(pushlex("vardef"), vardef1, expect(";"), poplex);
- else if (type == "keyword a") cont(pushlex("form"), expression, statement, poplex);
- else if (type == "keyword b") cont(pushlex("form"), statement, poplex);
- else if (type == "{") cont(pushlex("}"), block, poplex);
- else if (type == "function") cont(functiondef);
- else if (type == "for") cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), poplex, statement, poplex);
- else if (type == "variable") cont(pushlex("stat"), maybelabel);
- else if (type == "switch") cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), block, poplex, poplex);
- else if (type == "case") cont(expression, expect(":"));
- else if (type == "default") cont(expect(":"));
- else if (type == "catch") cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), statement, poplex, popcontext);
- else pass(pushlex("stat"), expression, expect(";"), poplex);
- }
- // Dispatch expression types.
- function expression(type){
- if (atomicTypes.hasOwnProperty(type)) cont(maybeoperator);
- else if (type == "function") cont(functiondef);
- else if (type == "keyword c") cont(expression);
- else if (type == "(") cont(pushlex(")"), expression, expect(")"), poplex, maybeoperator);
- else if (type == "operator") cont(expression);
- else if (type == "[") cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
- else if (type == "{") cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
- }
- // Called for places where operators, function calls, or
- // subscripts are valid. Will skip on to the next action if none
- // is found.
- function maybeoperator(type){
- if (type == "operator") cont(expression);
- else if (type == "(") cont(pushlex(")"), expression, commasep(expression, ")"), poplex, maybeoperator);
- else if (type == ".") cont(property, maybeoperator);
- else if (type == "[") cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
- }
- // When a statement starts with a variable name, it might be a
- // label. If no colon follows, it's a regular statement.
- function maybelabel(type){
- if (type == ":") cont(poplex, statement);
- else pass(maybeoperator, expect(";"), poplex);
- }
- // Property names need to have their style adjusted -- the
- // tokenizer thinks they are variables.
- function property(type){
- if (type == "variable") {mark("js-property"); cont();}
- }
- // This parses a property and its value in an object literal.
- function objprop(type){
- if (type == "variable") mark("js-property");
- if (atomicTypes.hasOwnProperty(type)) cont(expect(":"), expression);
- }
- // Parses a comma-separated list of the things that are recognized
- // by the 'what' argument.
- function commasep(what, end){
- function proceed(type) {
- if (type == ",") cont(what, proceed);
- else if (type == end) cont();
- else cont(expect(end));
- };
- return function commaSeparated(type) {
- if (type == end) cont();
- else pass(what, proceed);
- };
- }
- // Look for statements until a closing brace is found.
- function block(type){
- if (type == "}") cont();
- else pass(statement, block);
- }
- // Variable definitions are split into two actions -- 1 looks for
- // a name or the end of the definition, 2 looks for an '=' sign or
- // a comma.
- function vardef1(type, value){
- if (type == "variable"){register(value); cont(vardef2);}
- else cont();
- }
- function vardef2(type, value){
- if (value == "=") cont(expression, vardef2);
- else if (type == ",") cont(vardef1);
- }
- // For loops.
- function forspec1(type){
- if (type == "var") cont(vardef1, forspec2);
- else if (type == ";") pass(forspec2);
- else if (type == "variable") cont(formaybein);
- else pass(forspec2);
- }
- function formaybein(type, value){
- if (value == "in") cont(expression);
- else cont(maybeoperator, forspec2);
- }
- function forspec2(type, value){
- if (type == ";") cont(forspec3);
- else if (value == "in") cont(expression);
- else cont(expression, expect(";"), forspec3);
- }
- function forspec3(type) {
- if (type == ")") pass();
- else cont(expression);
- }
- // A function definition creates a new context, and the variables
- // in its argument list have to be added to this context.
- function functiondef(type, value){
- if (type == "variable"){register(value); cont(functiondef);}
- else if (type == "(") cont(pushcontext, commasep(funarg, ")"), statement, popcontext);
- }
- function funarg(type, value){
- if (type == "variable"){register(value); cont();}
- }
-
- return parser;
- }
-
- return {make: parseJS, electricChars: "{}:"};
-})();
diff --git a/media/CodeMirror-0.62/js/parsesparql.js b/media/CodeMirror-0.62/js/parsesparql.js
deleted file mode 100644
index 4b1dcaf..0000000
--- a/media/CodeMirror-0.62/js/parsesparql.js
+++ /dev/null
@@ -1,162 +0,0 @@
-var SparqlParser = Editor.Parser = (function() {
- function wordRegexp(words) {
- return new RegExp("^(?:" + words.join("|") + ")$", "i");
- }
- var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri",
- "isblank", "isliteral", "union", "a"]);
- var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe",
- "ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional",
- "graph", "by", "asc", "desc", ]);
- var operatorChars = /[*+\-<>=&|]/;
-
- var tokenizeSparql = (function() {
- function normal(source, setState) {
- var ch = source.next();
- if (ch == "$" || ch == "?") {
- source.nextWhileMatches(/[\w\d]/);
- return "sp-var";
- }
- else if (ch == "<" && !source.matches(/[\s\u00a0=]/)) {
- source.nextWhileMatches(/[^\s\u00a0>]/);
- if (source.equals(">")) source.next();
- return "sp-uri";
- }
- else if (ch == "\"" || ch == "'") {
- setState(inLiteral(ch));
- return null;
- }
- else if (/[{}\(\),\.;\[\]]/.test(ch)) {
- return "sp-punc";
- }
- else if (ch == "#") {
- while (!source.endOfLine()) source.next();
- return "sp-comment";
- }
- else if (operatorChars.test(ch)) {
- source.nextWhileMatches(operatorChars);
- return "sp-operator";
- }
- else if (ch == ":") {
- source.nextWhileMatches(/[\w\d\._\-]/);
- return "sp-prefixed";
- }
- else {
- source.nextWhileMatches(/[_\w\d]/);
- if (source.equals(":")) {
- source.next();
- source.nextWhileMatches(/[\w\d_\-]/);
- return "sp-prefixed";
- }
- var word = source.get(), type;
- if (ops.test(word))
- type = "sp-operator";
- else if (keywords.test(word))
- type = "sp-keyword";
- else
- type = "sp-word";
- return {style: type, content: word};
- }
- }
-
- function inLiteral(quote) {
- return function(source, setState) {
- var escaped = false;
- while (!source.endOfLine()) {
- var ch = source.next();
- if (ch == quote && !escaped) {
- setState(normal);
- break;
- }
- escaped = !escaped && ch == "\\";
- }
- return "sp-literal";
- };
- }
-
- return function(source, startState) {
- return tokenizer(source, startState || normal);
- };
- })();
-
- function indentSparql(context) {
- return function(nextChars) {
- var firstChar = nextChars && nextChars.charAt(0);
- if (/[\]\}]/.test(firstChar))
- while (context && context.type == "pattern") context = context.prev;
-
- var closing = context && firstChar == matching[context.type];
- if (!context)
- return 0;
- else if (context.type == "pattern")
- return context.col;
- else if (context.align)
- return context.col - (closing ? context.width : 0);
- else
- return context.indent + (closing ? 0 : indentUnit);
- }
- }
-
- function parseSparql(source) {
- var tokens = tokenizeSparql(source);
- var context = null, indent = 0, col = 0;
- function pushContext(type, width) {
- context = {prev: context, indent: indent, col: col, type: type, width: width};
- }
- function popContext() {
- context = context.prev;
- }
-
- var iter = {
- next: function() {
- var token = tokens.next(), type = token.style, content = token.content, width = token.value.length;
-
- if (content == "\n") {
- token.indentation = indentSparql(context);
- indent = col = 0;
- if (context && context.align == null) context.align = false;
- }
- else if (type == "whitespace" && col == 0) {
- indent = width;
- }
- else if (type != "sp-comment" && context && context.align == null) {
- context.align = true;
- }
-
- if (content != "\n") col += width;
-
- if (/[\[\{\(]/.test(content)) {
- pushContext(content, width);
- }
- else if (/[\]\}\)]/.test(content)) {
- while (context && context.type == "pattern")
- popContext();
- if (context && content == matching[context.type])
- popContext();
- }
- else if (content == "." && context && context.type == "pattern") {
- popContext();
- }
- else if ((type == "sp-word" || type == "sp-prefixed" || type == "sp-uri" || type == "sp-var" || type == "sp-literal") &&
- context && /[\{\[]/.test(context.type)) {
- pushContext("pattern", width);
- }
-
- return token;
- },
-
- copy: function() {
- var _context = context, _indent = indent, _col = col, _tokenState = tokens.state;
- return function(source) {
- tokens = tokenizeSparql(source, _tokenState);
- context = _context;
- indent = _indent;
- col = _col;
- return iter;
- };
- }
- };
- return iter;
- }
-
- return {make: parseSparql, electricChars: "}]"};
-})();
diff --git a/media/CodeMirror-0.62/js/parsesurvex.js b/media/CodeMirror-0.62/js/parsesurvex.js
deleted file mode 100644
index 941b347..0000000
--- a/media/CodeMirror-0.62/js/parsesurvex.js
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Simple parser for Survex files (based on the CSS example) */
-
-// The tokenizer breaks up the text into convincing chunks (I think the white-space is parser automatically)
-var SVXParser = Editor.Parser = (function() {
- var tokenizeSVX = (function() {
- function normal(source, setState) {
- var ch = source.next();
-
- if (ch == ";") {
- source.nextWhile(matcher(/[^\n]/));
- return "svx-comment";
- }
- else if (ch == "*") {
- source.nextWhile(matcher(/\w/));
- return "svx-command";
- }
- else if (ch == "\"" || ch == "'") {
- var escaped = false;
- while (!source.endOfLine()) {
- var nch = source.next();
- if (nch == ch && !escaped)
- break;
- escaped = !escaped && nch == "\\";
- }
- return "svx-string";
- }
- else if (/[\d\-+.]/.test(ch)) {
- source.nextWhile(matcher(/[\d.]/));
- return "svx-measure";
- }
- else {
- source.nextWhile(matcher(/\S/));
- return "svx-word";
- }
- }
-
- return function(source, startState) {
- return tokenizer(source, startState || normal);
- };
- })();
-
- // survex doesn't have indentation; but you get double linefeeds if you leave this out.
- function indentSVX() {
- return function(nextChars) {
- return 0;
- };
- }
-
- // Then this simple parser fixes up the obvious errors made by the tokenizer (which could only operate on characters)
- // A very fancy upgrade could make it capable of handling the *data commands which make it accept different orderings of
- // the parameters -- though this may be a challenge because the whole file needs reparsing when that happens -- don't
- // know how optimized the basic code is to be able to call for such to happen when a formatting command like this changes.
- function parseSVX(source, basecolumn) {
- basecolumn = basecolumn || 0;
- var tokens = tokenizeSVX(source);
- var inCommand = false;
- var ntokeninline = -1;
-
- var iter = {
- next: function() {
- var token = tokens.next(), style = token.style, content = token.content;
-
- if (content == "\n") {
- ntokeninline = -1;
- inCommand = false;
- token.indentation = indentSVX();
- }
- else if (style != "whitespace")
- ntokeninline += 1;
-
- if (style == "svx-command") {
- inCommand = (ntokeninline == 0);
- if (!inCommand)
- token.style = "svx-word";
- else if (content == "*begin")
- token.style = "svx-begin";
- else if (content == "*end")
- token.style = "svx-end";
- }
-
- if (!inCommand && style == "svx-measure") {
- if (ntokeninline < 2)
- token.style = "svx-word";
- }
- if (!inCommand && style == "svx-word" && (ntokeninline == 4)) {
- if (content == "down" || content == "up")
- token.style = "svx-measure";
- }
-
- return token;
- },
-
- copy: function() {
- var _inCommand = inCommand, _tokenState = tokens.state, _ntokeninline = ntokeninline;
- return function(source) {
- tokens = tokenizeSVX(source, _tokenState);
- inCommand = _inCommand;
- ntokeninline = _ntokeninline;
- return iter;
- };
- }
- };
- return iter;
- }
-
- return {make: parseSVX};
-})();
diff --git a/media/CodeMirror-0.62/js/parsexml.js b/media/CodeMirror-0.62/js/parsexml.js
deleted file mode 100644
index 95a8099..0000000
--- a/media/CodeMirror-0.62/js/parsexml.js
+++ /dev/null
@@ -1,292 +0,0 @@
-/* This file defines an XML parser, with a few kludges to make it
- * useable for HTML. autoSelfClosers defines a set of tag names that
- * are expected to not have a closing tag, and doNotIndent specifies
- * the tags inside of which no indentation should happen (see Config
- * object). These can be disabled by passing the editor an object like
- * {useHTMLKludges: false} as parserConfig option.
- */
-
-var XMLParser = Editor.Parser = (function() {
- var Kludges = {
- autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true,
- "meta": true, "col": true, "frame": true, "base": true, "area": true},
- doNotIndent: {"pre": true, "!cdata": true}
- };
- var NoKludges = {autoSelfClosers: {}, doNotIndent: {"!cdata": true}};
- var UseKludges = Kludges;
- var alignCDATA = false;
-
- // Simple stateful tokenizer for XML documents. Returns a
- // MochiKit-style iterator, with a state property that contains a
- // function encapsulating the current state. See tokenize.js.
- var tokenizeXML = (function() {
- function inText(source, setState) {
- var ch = source.next();
- if (ch == "<") {
- if (source.equals("!")) {
- source.next();
- if (source.equals("[")) {
- if (source.lookAhead("[CDATA[", true)) {
- setState(inBlock("xml-cdata", "]]>"));
- return null;
- }
- else {
- return "xml-text";
- }
- }
- else if (source.lookAhead("--", true)) {
- setState(inBlock("xml-comment", "-->"));
- return null;
- }
- else {
- return "xml-text";
- }
- }
- else if (source.equals("?")) {
- source.next();
- source.nextWhileMatches(/[\w\._\-]/);
- setState(inBlock("xml-processing", "?>"));
- return "xml-processing";
- }
- else {
- if (source.equals("/")) source.next();
- setState(inTag);
- return "xml-punctuation";
- }
- }
- else if (ch == "&") {
- while (!source.endOfLine()) {
- if (source.next() == ";")
- break;
- }
- return "xml-entity";
- }
- else {
- source.nextWhileMatches(/[^&<\n]/);
- return "xml-text";
- }
- }
-
- function inTag(source, setState) {
- var ch = source.next();
- if (ch == ">") {
- setState(inText);
- return "xml-punctuation";
- }
- else if (/[?\/]/.test(ch) && source.equals(">")) {
- source.next();
- setState(inText);
- return "xml-punctuation";
- }
- else if (ch == "=") {
- return "xml-punctuation";
- }
- else if (/[\'\"]/.test(ch)) {
- setState(inAttribute(ch));
- return null;
- }
- else {
- source.nextWhileMatches(/[^\s\u00a0=<>\"\'\/?]/);
- return "xml-name";
- }
- }
-
- function inAttribute(quote) {
- return function(source, setState) {
- while (!source.endOfLine()) {
- if (source.next() == quote) {
- setState(inTag);
- break;
- }
- }
- return "xml-attribute";
- };
- }
-
- function inBlock(style, terminator) {
- return function(source, setState) {
- while (!source.endOfLine()) {
- if (source.lookAhead(terminator, true)) {
- setState(inText);
- break;
- }
- source.next();
- }
- return style;
- };
- }
-
- return function(source, startState) {
- return tokenizer(source, startState || inText);
- };
- })();
-
- // The parser. The structure of this function largely follows that of
- // parseJavaScript in parsejavascript.js (there is actually a bit more
- // shared code than I'd like), but it is quite a bit simpler.
- function parseXML(source) {
- var tokens = tokenizeXML(source);
- var cc = [base];
- var tokenNr = 0, indented = 0;
- var currentTag = null, context = null;
- var consume, marked;
-
- function push(fs) {
- for (var i = fs.length - 1; i >= 0; i--)
- cc.push(fs[i]);
- }
- function cont() {
- push(arguments);
- consume = true;
- }
- function pass() {
- push(arguments);
- consume = false;
- }
-
- function mark(style) {
- marked = style;
- }
- function expect(text) {
- return function(style, content) {
- if (content == text) cont();
- else mark("xml-error") || cont(arguments.callee);
- };
- }
-
- function pushContext(tagname, startOfLine) {
- var noIndent = UseKludges.doNotIndent.hasOwnProperty(tagname) || (context && context.noIndent);
- context = {prev: context, name: tagname, indent: indented, startOfLine: startOfLine, noIndent: noIndent};
- }
- function popContext() {
- context = context.prev;
- }
- function computeIndentation(baseContext) {
- return function(nextChars, current) {
- var context = baseContext;
- if (context && context.noIndent)
- return current;
- if (alignCDATA && /<!\[CDATA\[/.test(nextChars))
- return 0;
- if (context && /^<\//.test(nextChars))
- context = context.prev;
- while (context && !context.startOfLine)
- context = context.prev;
- if (context)
- return context.indent + indentUnit;
- else
- return 0;
- };
- }
-
- function base() {
- return pass(element, base);
- }
- var harmlessTokens = {"xml-text": true, "xml-entity": true, "xml-comment": true, "xml-processing": true};
- function element(style, content) {
- if (content == "<") cont(tagname, attributes, endtag(tokenNr == 1));
- else if (content == "</") cont(closetagname, expect(">"));
- else if (style == "xml-cdata") {
- if (!context || context.name != "!cdata") pushContext("!cdata");
- if (/\]\]>$/.test(content)) popContext();
- cont();
- }
- else if (harmlessTokens.hasOwnProperty(style)) cont();
- else mark("xml-error") || cont();
- }
- function tagname(style, content) {
- if (style == "xml-name") {
- currentTag = content.toLowerCase();
- mark("xml-tagname");
- cont();
- }
- else {
- currentTag = null;
- pass();
- }
- }
- function closetagname(style, content) {
- if (style == "xml-name" && context && content.toLowerCase() == context.name) {
- popContext();
- mark("xml-tagname");
- }
- else {
- mark("xml-error");
- }
- cont();
- }
- function endtag(startOfLine) {
- return function(style, content) {
- if (content == "/>" || (content == ">" && UseKludges.autoSelfClosers.hasOwnProperty(currentTag))) cont();
- else if (content == ">") pushContext(currentTag, startOfLine) || cont();
- else mark("xml-error") || cont(arguments.callee);
- };
- }
- function attributes(style) {
- if (style == "xml-name") mark("xml-attname") || cont(attribute, attributes);
- else pass();
- }
- function attribute(style, content) {
- if (content == "=") cont(value);
- else if (content == ">" || content == "/>") pass(endtag);
- else pass();
- }
- function value(style) {
- if (style == "xml-attribute") cont(value);
- else pass();
- }
-
- return {
- indentation: function() {return indented;},
-
- next: function(){
- var token = tokens.next();
- if (token.style == "whitespace" && tokenNr == 0)
- indented = token.value.length;
- else
- tokenNr++;
- if (token.content == "\n") {
- indented = tokenNr = 0;
- token.indentation = computeIndentation(context);
- }
-
- if (token.style == "whitespace" || token.type == "xml-comment")
- return token;
-
- while(true){
- consume = marked = false;
- cc.pop()(token.style, token.content);
- if (consume){
- if (marked)
- token.style = marked;
- return token;
- }
- }
- },
-
- copy: function(){
- var _cc = cc.concat([]), _tokenState = tokens.state, _context = context;
- var parser = this;
-
- return function(input){
- cc = _cc.concat([]);
- tokenNr = indented = 0;
- context = _context;
- tokens = tokenizeXML(input, _tokenState);
- return parser;
- };
- }
- };
- }
-
- return {
- make: parseXML,
- electricChars: "/",
- configure: function(config) {
- if (config.useHTMLKludges != null)
- UseKludges = config.useHTMLKludges ? Kludges : NoKludges;
- if (config.alignCDATA)
- alignCDATA = config.alignCDATA;
- }
- };
-})();
diff --git a/media/CodeMirror-0.62/js/select.js b/media/CodeMirror-0.62/js/select.js
deleted file mode 100644
index 4a11c54..0000000
--- a/media/CodeMirror-0.62/js/select.js
+++ /dev/null
@@ -1,583 +0,0 @@
-/* Functionality for finding, storing, and restoring selections
- *
- * This does not provide a generic API, just the minimal functionality
- * required by the CodeMirror system.
- */
-
-// Namespace object.
-var select = {};
-
-(function() {
- select.ie_selection = document.selection && document.selection.createRangeCollection;
-
- // Find the 'top-level' (defined as 'a direct child of the node
- // passed as the top argument') node that the given node is
- // contained in. Return null if the given node is not inside the top
- // node.
- function topLevelNodeAt(node, top) {
- while (node && node.parentNode != top)
- node = node.parentNode;
- return node;
- }
-
- // Find the top-level node that contains the node before this one.
- function topLevelNodeBefore(node, top) {
- while (!node.previousSibling && node.parentNode != top)
- node = node.parentNode;
- return topLevelNodeAt(node.previousSibling, top);
- }
-
- // Used to prevent restoring a selection when we do not need to.
- var currentSelection = null;
-
- var fourSpaces = "\u00a0\u00a0\u00a0\u00a0";
-
- select.snapshotChanged = function() {
- if (currentSelection) currentSelection.changed = true;
- };
-
- // This is called by the code in editor.js whenever it is replacing
- // a text node. The function sees whether the given oldNode is part
- // of the current selection, and updates this selection if it is.
- // Because nodes are often only partially replaced, the length of
- // the part that gets replaced has to be taken into account -- the
- // selection might stay in the oldNode if the newNode is smaller
- // than the selection's offset. The offset argument is needed in
- // case the selection does move to the new object, and the given
- // length is not the whole length of the new node (part of it might
- // have been used to replace another node).
- select.snapshotReplaceNode = function(from, to, length, offset) {
- if (!currentSelection) return;
- currentSelection.changed = true;
-
- function replace(point) {
- if (from == point.node) {
- if (length && point.offset > length) {
- point.offset -= length;
- }
- else {
- point.node = to;
- point.offset += (offset || 0);
- }
- }
- }
- replace(currentSelection.start);
- replace(currentSelection.end);
- };
-
- select.snapshotMove = function(from, to, distance, relative, ifAtStart) {
- if (!currentSelection) return;
- currentSelection.changed = true;
-
- function move(point) {
- if (from == point.node && (!ifAtStart || point.offset == 0)) {
- point.node = to;
- if (relative) point.offset = Math.max(0, point.offset + distance);
- else point.offset = distance;
- }
- }
- move(currentSelection.start);
- move(currentSelection.end);
- };
-
- // Most functions are defined in two ways, one for the IE selection
- // model, one for the W3C one.
- if (select.ie_selection) {
- function selectionNode(win, start) {
- var range = win.document.selection.createRange();
- range.collapse(start);
-
- function nodeAfter(node) {
- var found = null;
- while (!found && node) {
- found = node.nextSibling;
- node = node.parentNode;
- }
- return nodeAtStartOf(found);
- }
-
- function nodeAtStartOf(node) {
- while (node && node.firstChild) node = node.firstChild;
- return {node: node, offset: 0};
- }
-
- var containing = range.parentElement();
- if (!isAncestor(win.document.body, containing)) return null;
- if (!containing.firstChild) return nodeAtStartOf(containing);
-
- var working = range.duplicate();
- working.moveToElementText(containing);
- working.collapse(true);
- for (var cur = containing.firstChild; cur; cur = cur.nextSibling) {
- if (cur.nodeType == 3) {
- var size = cur.nodeValue.length;
- working.move("character", size);
- }
- else {
- working.moveToElementText(cur);
- working.collapse(false);
- }
-
- var dir = range.compareEndPoints("StartToStart", working);
- if (dir == 0) return nodeAfter(cur);
- if (dir == 1) continue;
- if (cur.nodeType != 3) return nodeAtStartOf(cur);
-
- working.setEndPoint("StartToEnd", range);
- return {node: cur, offset: size - working.text.length};
- }
- return nodeAfter(containing);
- }
-
- select.markSelection = function(win) {
- currentSelection = null;
- var sel = win.document.selection;
- if (!sel) return;
- var start = selectionNode(win, true),
- end = selectionNode(win, false);
- if (!start || !end) return;
- currentSelection = {start: start, end: end, window: win, changed: false};
- };
-
- select.selectMarked = function() {
- if (!currentSelection || !currentSelection.changed) return;
-
- function makeRange(point) {
- var range = currentSelection.window.document.body.createTextRange();
- var node = point.node;
- if (!node) {
- range.moveToElementText(currentSelection.window.document.body);
- range.collapse(false);
- }
- else if (node.nodeType == 3) {
- range.moveToElementText(node.parentNode);
- var offset = point.offset;
- while (node.previousSibling) {
- node = node.previousSibling;
- offset += (node.innerText || "").length;
- }
- range.move("character", offset);
- }
- else {
- range.moveToElementText(node);
- range.collapse(true);
- }
- return range;
- }
-
- var start = makeRange(currentSelection.start), end = makeRange(currentSelection.end);
- start.setEndPoint("StartToEnd", end);
- start.select();
- };
-
- // Get the top-level node that one end of the cursor is inside or
- // after. Note that this returns false for 'no cursor', and null
- // for 'start of document'.
- select.selectionTopNode = function(container, start) {
- var selection = container.ownerDocument.selection;
- if (!selection) return false;
-
- var range = selection.createRange();
- range.collapse(start);
- var around = range.parentElement();
- if (around && isAncestor(container, around)) {
- // Only use this node if the selection is not at its start.
- var range2 = range.duplicate();
- range2.moveToElementText(around);
- if (range.compareEndPoints("StartToStart", range2) == -1)
- return topLevelNodeAt(around, container);
- }
- // Fall-back hack
- try {range.pasteHTML("<span id='xxx-temp-xxx'></span>");}
- catch (e) {return false;}
-
- var temp = container.ownerDocument.getElementById("xxx-temp-xxx");
- if (temp) {
- var result = topLevelNodeBefore(temp, container);
- removeElement(temp);
- return result;
- }
- return false;
- };
-
- // Place the cursor after this.start. This is only useful when
- // manually moving the cursor instead of restoring it to its old
- // position.
- select.focusAfterNode = function(node, container) {
- var range = container.ownerDocument.body.createTextRange();
- range.moveToElementText(node || container);
- range.collapse(!node);
- range.select();
- };
-
- select.somethingSelected = function(win) {
- var sel = win.document.selection;
- return sel && (sel.createRange().text != "");
- };
-
- function insertAtCursor(window, html) {
- var selection = window.document.selection;
- if (selection) {
- var range = selection.createRange();
- range.pasteHTML(html);
- range.collapse(false);
- range.select();
- }
- }
-
- // Used to normalize the effect of the enter key, since browsers
- // do widely different things when pressing enter in designMode.
- select.insertNewlineAtCursor = function(window) {
- insertAtCursor(window, "<br>");
- };
-
- select.insertTabAtCursor = function(window) {
- insertAtCursor(window, fourSpaces);
- };
-
- // Get the BR node at the start of the line on which the cursor
- // currently is, and the offset into the line. Returns null as
- // node if cursor is on first line.
- select.cursorPos = function(container, start) {
- var selection = container.ownerDocument.selection;
- if (!selection) return null;
-
- var topNode = select.selectionTopNode(container, start);
- while (topNode && topNode.nodeName != "BR")
- topNode = topNode.previousSibling;
-
- var range = selection.createRange(), range2 = range.duplicate();
- range.collapse(start);
- if (topNode) {
- range2.moveToElementText(topNode);
- range2.collapse(false);
- }
- else {
- // When nothing is selected, we can get all kinds of funky errors here.
- try { range2.moveToElementText(container); }
- catch (e) { return null; }
- range2.collapse(true);
- }
- range.setEndPoint("StartToStart", range2);
-
- return {node: topNode, offset: range.text.length};
- };
-
- select.setCursorPos = function(container, from, to) {
- function rangeAt(pos) {
- var range = container.ownerDocument.body.createTextRange();
- if (!pos.node) {
- range.moveToElementText(container);
- range.collapse(true);
- }
- else {
- range.moveToElementText(pos.node);
- range.collapse(false);
- }
- range.move("character", pos.offset);
- return range;
- }
-
- var range = rangeAt(from);
- if (to && to != from)
- range.setEndPoint("EndToEnd", rangeAt(to));
- range.select();
- }
-
- // Make sure the cursor is visible.
- select.scrollToCursor = function(container) {
- var selection = container.ownerDocument.selection;
- if (!selection) return null;
- selection.createRange().scrollIntoView();
- };
-
- select.scrollToNode = function(node) {
- if (!node) return;
- node.scrollIntoView();
- };
-
- // Some hacks for storing and re-storing the selection when the editor loses and regains focus.
- select.selectionCoords = function (win) {
- var selection = win.document.selection;
- if (!selection) return null;
- var start = selection.createRange(), end = start.duplicate();
- start.collapse(true);
- end.collapse(false);
-
- var body = win.document.body;
- return {start: {x: start.boundingLeft + body.scrollLeft - 1,
- y: start.boundingTop + body.scrollTop},
- end: {x: end.boundingLeft + body.scrollLeft - 1,
- y: end.boundingTop + body.scrollTop}};
- };
-
- // Restore a stored selection.
- select.selectCoords = function(win, coords) {
- if (!coords) return;
-
- var range1 = win.document.body.createTextRange(), range2 = range1.duplicate();
- // This can fail for various hard-to-handle reasons.
- try {
- range1.moveToPoint(coords.start.x, coords.start.y);
- range2.moveToPoint(coords.end.x, coords.end.y);
- range1.setEndPoint("EndToStart", range2);
- range1.select();
- } catch(e) {alert(e.message);}
- };
- }
- // W3C model
- else {
- // Store start and end nodes, and offsets within these, and refer
- // back to the selection object from those nodes, so that this
- // object can be updated when the nodes are replaced before the
- // selection is restored.
- select.markSelection = function (win) {
- var selection = win.getSelection();
- if (!selection || selection.rangeCount == 0)
- return (currentSelection = null);
- var range = selection.getRangeAt(0);
-
- currentSelection = {
- start: {node: range.startContainer, offset: range.startOffset},
- end: {node: range.endContainer, offset: range.endOffset},
- window: win,
- changed: false
- };
-
- // We want the nodes right at the cursor, not one of their
- // ancestors with a suitable offset. This goes down the DOM tree
- // until a 'leaf' is reached (or is it *up* the DOM tree?).
- function normalize(point){
- while (point.node.nodeType != 3 && point.node.nodeName != "BR") {
- var newNode = point.node.childNodes[point.offset] || point.node.nextSibling;
- point.offset = 0;
- while (!newNode && point.node.parentNode) {
- point.node = point.node.parentNode;
- newNode = point.node.nextSibling;
- }
- point.node = newNode;
- if (!newNode)
- break;
- }
- }
-
- normalize(currentSelection.start);
- normalize(currentSelection.end);
- };
-
- select.selectMarked = function () {
- if (!currentSelection || !currentSelection.changed) return;
- var win = currentSelection.window, range = win.document.createRange();
-
- function setPoint(point, which) {
- if (point.node) {
- // Some magic to generalize the setting of the start and end
- // of a range.
- if (point.offset == 0)
- range["set" + which + "Before"](point.node);
- else
- range["set" + which](point.node, point.offset);
- }
- else {
- range.setStartAfter(win.document.body.lastChild || win.document.body);
- }
- }
-
- setPoint(currentSelection.end, "End");
- setPoint(currentSelection.start, "Start");
- selectRange(range, win);
- };
-
- // Helper for selecting a range object.
- function selectRange(range, window) {
- var selection = window.getSelection();
- selection.removeAllRanges();
- selection.addRange(range);
- };
- function selectionRange(window) {
- var selection = window.getSelection();
- if (!selection || selection.rangeCount == 0)
- return false;
- else
- return selection.getRangeAt(0);
- }
-
- // Finding the top-level node at the cursor in the W3C is, as you
- // can see, quite an involved process.
- select.selectionTopNode = function(container, start) {
- var range = selectionRange(container.ownerDocument.defaultView);
- if (!range) return false;
-
- var node = start ? range.startContainer : range.endContainer;
- var offset = start ? range.startOffset : range.endOffset;
- // Work around (yet another) bug in Opera's selection model.
- if (window.opera && !start && range.endContainer == container && range.endOffset == range.startOffset + 1 &&
- container.childNodes[range.startOffset] && container.childNodes[range.startOffset].nodeName == "BR")
- offset--;
-
- // For text nodes, we look at the node itself if the cursor is
- // inside, or at the node before it if the cursor is at the
- // start.
- if (node.nodeType == 3){
- if (offset > 0)
- return topLevelNodeAt(node, container);
- else
- return topLevelNodeBefore(node, container);
- }
- // Occasionally, browsers will return the HTML node as
- // selection. If the offset is 0, we take the start of the frame
- // ('after null'), otherwise, we take the last node.
- else if (node.nodeName == "HTML") {
- return (offset == 1 ? null : container.lastChild);
- }
- // If the given node is our 'container', we just look up the
- // correct node by using the offset.
- else if (node == container) {
- return (offset == 0) ? null : node.childNodes[offset - 1];
- }
- // In any other case, we have a regular node. If the cursor is
- // at the end of the node, we use the node itself, if it is at
- // the start, we use the node before it, and in any other
- // case, we look up the child before the cursor and use that.
- else {
- if (offset == node.childNodes.length)
- return topLevelNodeAt(node, container);
- else if (offset == 0)
- return topLevelNodeBefore(node, container);
- else
- return topLevelNodeAt(node.childNodes[offset - 1], container);
- }
- };
-
- select.focusAfterNode = function(node, container) {
- var win = container.ownerDocument.defaultView,
- range = win.document.createRange();
- range.setStartBefore(container.firstChild || container);
- // In Opera, setting the end of a range at the end of a line
- // (before a BR) will cause the cursor to appear on the next
- // line, so we set the end inside of the start node when
- // possible.
- if (node && !node.firstChild)
- range.setEndAfter(node);
- else if (node)
- range.setEnd(node, node.childNodes.length);
- else
- range.setEndBefore(container.firstChild || container);
- range.collapse(false);
- selectRange(range, win);
- };
-
- select.somethingSelected = function(win) {
- var range = selectionRange(win);
- return range && !range.collapsed;
- };
-
- function insertNodeAtCursor(window, node) {
- var range = selectionRange(window);
- if (!range) return;
-
- range.deleteContents();
- range.insertNode(node);
- webkitLastLineHack(window.document.body);
- range = window.document.createRange();
- range.selectNode(node);
- range.collapse(false);
- selectRange(range, window);
- }
-
- select.insertNewlineAtCursor = function(window) {
- insertNodeAtCursor(window, window.document.createElement("BR"));
- };
-
- select.insertTabAtCursor = function(window) {
- insertNodeAtCursor(window, window.document.createTextNode(fourSpaces));
- };
-
- select.cursorPos = function(container, start) {
- var range = selectionRange(window);
- if (!range) return;
-
- var topNode = select.selectionTopNode(container, start);
- while (topNode && topNode.nodeName != "BR")
- topNode = topNode.previousSibling;
-
- range = range.cloneRange();
- range.collapse(start);
- if (topNode)
- range.setStartAfter(topNode);
- else
- range.setStartBefore(container);
- return {node: topNode, offset: range.toString().length};
- };
-
- select.setCursorPos = function(container, from, to) {
- var win = container.ownerDocument.defaultView,
- range = win.document.createRange();
-
- function setPoint(node, offset, side) {
- if (!node)
- node = container.firstChild;
- else
- node = node.nextSibling;
-
- if (!node)
- return;
-
- if (offset == 0) {
- range["set" + side + "Before"](node);
- return true;
- }
-
- var backlog = []
- function decompose(node) {
- if (node.nodeType == 3)
- backlog.push(node);
- else
- forEach(node.childNodes, decompose);
- }
- while (true) {
- while (node && !backlog.length) {
- decompose(node);
- node = node.nextSibling;
- }
- var cur = backlog.shift();
- if (!cur) return false;
-
- var length = cur.nodeValue.length;
- if (length >= offset) {
- range["set" + side](cur, offset);
- return true;
- }
- offset -= length;
- }
- }
-
- to = to || from;
- if (setPoint(to.node, to.offset, "End") && setPoint(from.node, from.offset, "Start"))
- selectRange(range, win);
- };
-
- select.scrollToNode = function(element) {
- if (!element) return;
- var doc = element.ownerDocument, body = doc.body, win = doc.defaultView, html = doc.documentElement;
-
- // In Opera, BR elements *always* have a scrollTop property of zero. Go Opera.
- while (element && !element.offsetTop)
- element = element.previousSibling;
-
- var y = 0, pos = element;
- while (pos && pos.offsetParent) {
- y += pos.offsetTop;
- pos = pos.offsetParent;
- }
-
- var screen_y = y - (body.scrollTop || html.scrollTop || 0);
- if (screen_y < 0 || screen_y > win.innerHeight - 30)
- win.scrollTo(body.scrollLeft || html.scrollLeft || 0, y);
- };
-
- select.scrollToCursor = function(container) {
- select.scrollToNode(select.selectionTopNode(container, true) || container.firstChild);
- };
- }
-})();
diff --git a/media/CodeMirror-0.62/js/stringstream.js b/media/CodeMirror-0.62/js/stringstream.js
deleted file mode 100644
index 6d9355f..0000000
--- a/media/CodeMirror-0.62/js/stringstream.js
+++ /dev/null
@@ -1,140 +0,0 @@
-/* String streams are the things fed to parsers (which can feed them
- * to a tokenizer if they want). They provide peek and next methods
- * for looking at the current character (next 'consumes' this
- * character, peek does not), and a get method for retrieving all the
- * text that was consumed since the last time get was called.
- *
- * An easy mistake to make is to let a StopIteration exception finish
- * the token stream while there are still characters pending in the
- * string stream (hitting the end of the buffer while parsing a
- * token). To make it easier to detect such errors, the strings throw
- * an exception when this happens.
- */
-
-// Make a string stream out of an iterator that returns strings. This
-// is applied to the result of traverseDOM (see codemirror.js), and
-// the resulting stream is fed to the parser.
-window.stringStream = function(source){
- // String that's currently being iterated over.
- var current = "";
- // Position in that string.
- var pos = 0;
- // Accumulator for strings that have been iterated over but not
- // get()-ed yet.
- var accum = "";
- // Make sure there are more characters ready, or throw
- // StopIteration.
- function ensureChars() {
- while (pos == current.length) {
- accum += current;
- current = ""; // In case source.next() throws
- pos = 0;
- try {current = source.next();}
- catch (e) {
- if (e != StopIteration) throw e;
- else return false;
- }
- }
- return true;
- }
-
- return {
- // Return the next character in the stream.
- peek: function() {
- if (!ensureChars()) return null;
- return current.charAt(pos);
- },
- // Get the next character, throw StopIteration if at end, check
- // for unused content.
- next: function() {
- if (!ensureChars()) {
- if (accum.length > 0)
- throw "End of stringstream reached without emptying buffer ('" + accum + "').";
- else
- throw StopIteration;
- }
- return current.charAt(pos++);
- },
- // Return the characters iterated over since the last call to
- // .get().
- get: function() {
- var temp = accum;
- accum = "";
- if (pos > 0){
- temp += current.slice(0, pos);
- current = current.slice(pos);
- pos = 0;
- }
- return temp;
- },
- // Push a string back into the stream.
- push: function(str) {
- current = current.slice(0, pos) + str + current.slice(pos);
- },
- lookAhead: function(str, consume, skipSpaces, caseInsensitive) {
- function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
- str = cased(str);
- var found = false;
-
- var _accum = accum, _pos = pos;
- if (skipSpaces) this.nextWhileMatches(/[\s\u00a0]/);
-
- while (true) {
- var end = pos + str.length, left = current.length - pos;
- if (end <= current.length) {
- found = str == cased(current.slice(pos, end));
- pos = end;
- break;
- }
- else if (str.slice(0, left) == cased(current.slice(pos))) {
- accum += current; current = "";
- try {current = source.next();}
- catch (e) {break;}
- pos = 0;
- str = str.slice(left);
- }
- else {
- break;
- }
- }
-
- if (!(found && consume)) {
- current = accum.slice(_accum.length) + current;
- pos = _pos;
- accum = _accum;
- }
-
- return found;
- },
-
- // Utils built on top of the above
- more: function() {
- return this.peek() !== null;
- },
- applies: function(test) {
- var next = this.peek();
- return (next !== null && test(next));
- },
- nextWhile: function(test) {
- var next;
- while ((next = this.peek()) !== null && test(next))
- this.next();
- },
- matches: function(re) {
- var next = this.peek();
- return (next !== null && re.test(next));
- },
- nextWhileMatches: function(re) {
- var next;
- while ((next = this.peek()) !== null && re.test(next))
- this.next();
- },
- equals: function(ch) {
- return ch === this.peek();
- },
- endOfLine: function() {
- var next = this.peek();
- return next == null || next == "\n";
- }
- };
-};
diff --git a/media/CodeMirror-0.62/js/tokenize.js b/media/CodeMirror-0.62/js/tokenize.js
deleted file mode 100644
index 071970c..0000000
--- a/media/CodeMirror-0.62/js/tokenize.js
+++ /dev/null
@@ -1,57 +0,0 @@
-// A framework for simple tokenizers. Takes care of newlines and
-// white-space, and of getting the text from the source stream into
-// the token object. A state is a function of two arguments -- a
-// string stream and a setState function. The second can be used to
-// change the tokenizer's state, and can be ignored for stateless
-// tokenizers. This function should advance the stream over a token
-// and return a string or object containing information about the next
-// token, or null to pass and have the (new) state be called to finish
-// the token. When a string is given, it is wrapped in a {style, type}
-// object. In the resulting object, the characters consumed are stored
-// under the content property. Any whitespace following them is also
-// automatically consumed, and added to the value property. (Thus,
-// content is the actual meaningful part of the token, while value
-// contains all the text it spans.)
-
-function tokenizer(source, state) {
- // Newlines are always a separate token.
- function isWhiteSpace(ch) {
- // The messy regexp is because IE's regexp matcher is of the
- // opinion that non-breaking spaces are no whitespace.
- return ch != "\n" && /^[\s\u00a0]*$/.test(ch);
- }
-
- var tokenizer = {
- state: state,
-
- take: function(type) {
- if (typeof(type) == "string")
- type = {style: type, type: type};
-
- type.content = (type.content || "") + source.get();
- if (!/\n$/.test(type.content))
- source.nextWhile(isWhiteSpace);
- type.value = type.content + source.get();
- return type;
- },
-
- next: function () {
- if (!source.more()) throw StopIteration;
-
- var type;
- if (source.equals("\n")) {
- source.next();
- return this.take("whitespace");
- }
-
- if (source.applies(isWhiteSpace))
- type = "whitespace";
- else
- while (!type)
- type = this.state(source, function(s) {tokenizer.state = s;});
-
- return this.take(type);
- }
- };
- return tokenizer;
-}
diff --git a/media/CodeMirror-0.62/js/tokenizejavascript.js b/media/CodeMirror-0.62/js/tokenizejavascript.js
deleted file mode 100644
index f55dfce..0000000
--- a/media/CodeMirror-0.62/js/tokenizejavascript.js
+++ /dev/null
@@ -1,175 +0,0 @@
-/* Tokenizer for JavaScript code */
-
-var tokenizeJavaScript = (function() {
- // Advance the stream until the given character (not preceded by a
- // backslash) is encountered, or the end of the line is reached.
- function nextUntilUnescaped(source, end) {
- var escaped = false;
- var next;
- while (!source.endOfLine()) {
- var next = source.next();
- if (next == end && !escaped)
- return false;
- escaped = !escaped && next == "\\";
- }
- return escaped;
- }
-
- // A map of JavaScript's keywords. The a/b/c keyword distinction is
- // very rough, but it gives the parser enough information to parse
- // correct code correctly (we don't care that much how we parse
- // incorrect code). The style information included in these objects
- // is used by the highlighter to pick the correct CSS style for a
- // token.
- var keywords = function(){
- function result(type, style){
- return {type: type, style: "js-" + style};
- }
- // keywords that take a parenthised expression, and then a
- // statement (if)
- var keywordA = result("keyword a", "keyword");
- // keywords that take just a statement (else)
- var keywordB = result("keyword b", "keyword");
- // keywords that optionally take an expression, and form a
- // statement (return)
- var keywordC = result("keyword c", "keyword");
- var operator = result("operator", "keyword");
- var atom = result("atom", "atom");
- return {
- "if": keywordA, "while": keywordA, "with": keywordA,
- "else": keywordB, "do": keywordB, "try": keywordB, "finally": keywordB,
- "return": keywordC, "break": keywordC, "continue": keywordC, "new": keywordC, "delete": keywordC, "throw": keywordC,
- "in": operator, "typeof": operator, "instanceof": operator,
- "var": result("var", "keyword"), "function": result("function", "keyword"), "catch": result("catch", "keyword"),
- "for": result("for", "keyword"), "switch": result("switch", "keyword"),
- "case": result("case", "keyword"), "default": result("default", "keyword"),
- "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom
- };
- }();
-
- // Some helper regexps
- var isOperatorChar = /[+\-*&%\/=<>!?|]/;
- var isHexDigit = /[0-9A-Fa-f]/;
- var isWordChar = /[\w\$_]/;
-
- // Wrapper around jsToken that helps maintain parser state (whether
- // we are inside of a multi-line comment and whether the next token
- // could be a regular expression).
- function jsTokenState(inside, regexp) {
- return function(source, setState) {
- var newInside = inside;
- var type = jsToken(inside, regexp, source, function(c) {newInside = c;});
- var newRegexp = type.type == "operator" || type.type == "keyword c" || type.type.match(/^[\[{}\(,;:]$/);
- if (newRegexp != regexp || newInside != inside)
- setState(jsTokenState(newInside, newRegexp));
- return type;
- };
- }
-
- // The token reader, inteded to be used by the tokenizer from
- // tokenize.js (through jsTokenState). Advances the source stream
- // over a token, and returns an object containing the type and style
- // of that token.
- function jsToken(inside, regexp, source, setInside) {
- function readHexNumber(){
- source.next(); // skip the 'x'
- source.nextWhileMatches(isHexDigit);
- return {type: "number", style: "js-atom"};
- }
-
- function readNumber() {
- source.nextWhileMatches(/[0-9]/);
- if (source.equals(".")){
- source.next();
- source.nextWhileMatches(/[0-9]/);
- }
- if (source.equals("e") || source.equals("E")){
- source.next();
- if (source.equals("-"))
- source.next();
- source.nextWhileMatches(/[0-9]/);
- }
- return {type: "number", style: "js-atom"};
- }
- // Read a word, look it up in keywords. If not found, it is a
- // variable, otherwise it is a keyword of the type found.
- function readWord() {
- source.nextWhileMatches(isWordChar);
- var word = source.get();
- var known = keywords.hasOwnProperty(word) && keywords.propertyIsEnumerable(word) && keywords[word];
- return known ? {type: known.type, style: known.style, content: word} :
- {type: "variable", style: "js-variable", content: word};
- }
- function readRegexp() {
- nextUntilUnescaped(source, "/");
- source.nextWhileMatches(/[gi]/);
- return {type: "regexp", style: "js-string"};
- }
- // Mutli-line comments are tricky. We want to return the newlines
- // embedded in them as regular newline tokens, and then continue
- // returning a comment token for every line of the comment. So
- // some state has to be saved (inside) to indicate whether we are
- // inside a /* */ sequence.
- function readMultilineComment(start){
- var newInside = "/*";
- var maybeEnd = (start == "*");
- while (true) {
- if (source.endOfLine())
- break;
- var next = source.next();
- if (next == "/" && maybeEnd){
- newInside = null;
- break;
- }
- maybeEnd = (next == "*");
- }
- setInside(newInside);
- return {type: "comment", style: "js-comment"};
- }
- function readOperator() {
- source.nextWhileMatches(isOperatorChar);
- return {type: "operator", style: "js-operator"};
- }
- function readString(quote) {
- var endBackSlash = nextUntilUnescaped(source, quote);
- setInside(endBackSlash ? quote : null);
- return {type: "string", style: "js-string"};
- }
-
- // Fetch the next token. Dispatches on first character in the
- // stream, or first two characters when the first is a slash.
- if (inside == "\"" || inside == "'")
- return readString(inside);
- var ch = source.next();
- if (inside == "/*")
- return readMultilineComment(ch);
- else if (ch == "\"" || ch == "'")
- return readString(ch);
- // with punctuation, the type of the token is the symbol itself
- else if (/[\[\]{}\(\),;\:\.]/.test(ch))
- return {type: ch, style: "js-punctuation"};
- else if (ch == "0" && (source.equals("x") || source.equals("X")))
- return readHexNumber();
- else if (/[0-9]/.test(ch))
- return readNumber();
- else if (ch == "/"){
- if (source.equals("*"))
- { source.next(); return readMultilineComment(ch); }
- else if (source.equals("/"))
- { nextUntilUnescaped(source, null); return {type: "comment", style: "js-comment"};}
- else if (regexp)
- return readRegexp();
- else
- return readOperator();
- }
- else if (isOperatorChar.test(ch))
- return readOperator();
- else
- return readWord();
- }
-
- // The external interface to the tokenizer.
- return function(source, startState) {
- return tokenizer(source, startState || jsTokenState(false, true));
- };
-})();
diff --git a/media/CodeMirror-0.62/js/undo.js b/media/CodeMirror-0.62/js/undo.js
deleted file mode 100644
index 1930cfb..0000000
--- a/media/CodeMirror-0.62/js/undo.js
+++ /dev/null
@@ -1,403 +0,0 @@
-/**
- * Storage and control for undo information within a CodeMirror
- * editor. 'Why on earth is such a complicated mess required for
- * that?', I hear you ask. The goal, in implementing this, was to make
- * the complexity of storing and reverting undo information depend
- * only on the size of the edited or restored content, not on the size
- * of the whole document. This makes it necessary to use a kind of
- * 'diff' system, which, when applied to a DOM tree, causes some
- * complexity and hackery.
- *
- * In short, the editor 'touches' BR elements as it parses them, and
- * the History stores these. When nothing is touched in commitDelay
- * milliseconds, the changes are committed: It goes over all touched
- * nodes, throws out the ones that did not change since last commit or
- * are no longer in the document, and assembles the rest into zero or
- * more 'chains' -- arrays of adjacent lines. Links back to these
- * chains are added to the BR nodes, while the chain that previously
- * spanned these nodes is added to the undo history. Undoing a change
- * means taking such a chain off the undo history, restoring its
- * content (text is saved per line) and linking it back into the
- * document.
- */
-
-// A history object needs to know about the DOM container holding the
-// document, the maximum amount of undo levels it should store, the
-// delay (of no input) after which it commits a set of changes, and,
-// unfortunately, the 'parent' window -- a window that is not in
-// designMode, and on which setTimeout works in every browser.
-function History(container, maxDepth, commitDelay, editor, onChange) {
- this.container = container;
- this.maxDepth = maxDepth; this.commitDelay = commitDelay;
- this.editor = editor; this.parent = editor.parent;
- this.onChange = onChange;
- // This line object represents the initial, empty editor.
- var initial = {text: "", from: null, to: null};
- // As the borders between lines are represented by BR elements, the
- // start of the first line and the end of the last one are
- // represented by null. Since you can not store any properties
- // (links to line objects) in null, these properties are used in
- // those cases.
- this.first = initial; this.last = initial;
- // Similarly, a 'historyTouched' property is added to the BR in
- // front of lines that have already been touched, and 'firstTouched'
- // is used for the first line.
- this.firstTouched = false;
- // History is the set of committed changes, touched is the set of
- // nodes touched since the last commit.
- this.history = []; this.redoHistory = []; this.touched = [];
-}
-
-History.prototype = {
- // Schedule a commit (if no other touches come in for commitDelay
- // milliseconds).
- scheduleCommit: function() {
- var self = this;
- this.parent.clearTimeout(this.commitTimeout);
- this.commitTimeout = this.parent.setTimeout(function(){self.tryCommit();}, this.commitDelay);
- },
-
- // Mark a node as touched. Null is a valid argument.
- touch: function(node) {
- this.setTouched(node);
- this.scheduleCommit();
- },
-
- // Undo the last change.
- undo: function() {
- // Make sure pending changes have been committed.
- this.commit();
-
- if (this.history.length) {
- // Take the top diff from the history, apply it, and store its
- // shadow in the redo history.
- var item = this.history.pop();
- this.redoHistory.push(this.updateTo(item, "applyChain"));
- if (this.onChange) this.onChange();
- return this.chainNode(item);
- }
- },
-
- // Redo the last undone change.
- redo: function() {
- this.commit();
- if (this.redoHistory.length) {
- // The inverse of undo, basically.
- var item = this.redoHistory.pop();
- this.addUndoLevel(this.updateTo(item, "applyChain"));
- if (this.onChange) this.onChange();
- return this.chainNode(item);
- }
- },
-
- clear: function() {
- this.history = [];
- this.redoHistory = [];
- },
-
- // Ask for the size of the un/redo histories.
- historySize: function() {
- return {undo: this.history.length, redo: this.redoHistory.length};
- },
-
- // Push a changeset into the document.
- push: function(from, to, lines) {
- var chain = [];
- for (var i = 0; i < lines.length; i++) {
- var end = (i == lines.length - 1) ? to : this.container.ownerDocument.createElement("BR");
- chain.push({from: from, to: end, text: cleanText(lines[i])});
- from = end;
- }
- this.pushChains([chain], from == null && to == null);
- },
-
- pushChains: function(chains, doNotHighlight) {
- this.commit(doNotHighlight);
- this.addUndoLevel(this.updateTo(chains, "applyChain"));
- this.redoHistory = [];
- },
-
- // Retrieve a DOM node from a chain (for scrolling to it after undo/redo).
- chainNode: function(chains) {
- for (var i = 0; i < chains.length; i++) {
- var start = chains[i][0], node = start && (start.from || start.to);
- if (node) return node;
- }
- },
-
- // Clear the undo history, make the current document the start
- // position.
- reset: function() {
- this.history = []; this.redoHistory = [];
- },
-
- textAfter: function(br) {
- return this.after(br).text;
- },
-
- nodeAfter: function(br) {
- return this.after(br).to;
- },
-
- nodeBefore: function(br) {
- return this.before(br).from;
- },
-
- // Commit unless there are pending dirty nodes.
- tryCommit: function() {
- if (!window.History) return; // Stop when frame has been unloaded
- if (this.editor.highlightDirty()) this.commit();
- else this.scheduleCommit();
- },
-
- // Check whether the touched nodes hold any changes, if so, commit
- // them.
- commit: function(doNotHighlight) {
- this.parent.clearTimeout(this.commitTimeout);
- // Make sure there are no pending dirty nodes.
- if (!doNotHighlight) this.editor.highlightDirty(true);
- // Build set of chains.
- var chains = this.touchedChains(), self = this;
-
- if (chains.length) {
- this.addUndoLevel(this.updateTo(chains, "linkChain"));
- this.redoHistory = [];
- if (this.onChange) this.onChange();
- }
- },
-
- // [ end of public interface ]
-
- // Update the document with a given set of chains, return its
- // shadow. updateFunc should be "applyChain" or "linkChain". In the
- // second case, the chains are taken to correspond the the current
- // document, and only the state of the line data is updated. In the
- // first case, the content of the chains is also pushed iinto the
- // document.
- updateTo: function(chains, updateFunc) {
- var shadows = [], dirty = [];
- for (var i = 0; i < chains.length; i++) {
- shadows.push(this.shadowChain(chains[i]));
- dirty.push(this[updateFunc](chains[i]));
- }
- if (updateFunc == "applyChain")
- this.notifyDirty(dirty);
- return shadows;
- },
-
- // Notify the editor that some nodes have changed.
- notifyDirty: function(nodes) {
- forEach(nodes, method(this.editor, "addDirtyNode"))
- this.editor.scheduleHighlight();
- },
-
- // Link a chain into the DOM nodes (or the first/last links for null
- // nodes).
- linkChain: function(chain) {
- for (var i = 0; i < chain.length; i++) {
- var line = chain[i];
- if (line.from) line.from.historyAfter = line;
- else this.first = line;
- if (line.to) line.to.historyBefore = line;
- else this.last = line;
- }
- },
-
- // Get the line object after/before a given node.
- after: function(node) {
- return node ? node.historyAfter : this.first;
- },
- before: function(node) {
- return node ? node.historyBefore : this.last;
- },
-
- // Mark a node as touched if it has not already been marked.
- setTouched: function(node) {
- if (node) {
- if (!node.historyTouched) {
- this.touched.push(node);
- node.historyTouched = true;
- }
- }
- else {
- this.firstTouched = true;
- }
- },
-
- // Store a new set of undo info, throw away info if there is more of
- // it than allowed.
- addUndoLevel: function(diffs) {
- this.history.push(diffs);
- if (this.history.length > this.maxDepth)
- this.history.shift();
- },
-
- // Build chains from a set of touched nodes.
- touchedChains: function() {
- var self = this;
-
- // The temp system is a crummy hack to speed up determining
- // whether a (currently touched) node has a line object associated
- // with it. nullTemp is used to store the object for the first
- // line, other nodes get it stored in their historyTemp property.
- var nullTemp = null;
- function temp(node) {return node ? node.historyTemp : nullTemp;}
- function setTemp(node, line) {
- if (node) node.historyTemp = line;
- else nullTemp = line;
- }
-
- function buildLine(node) {
- var text = [];
- for (var cur = node ? node.nextSibling : self.container.firstChild;
- cur && cur.nodeName != "BR"; cur = cur.nextSibling)
- if (cur.currentText) text.push(cur.currentText);
- return {from: node, to: cur, text: cleanText(text.join(""))};
- }
-
- // Filter out unchanged lines and nodes that are no longer in the
- // document. Build up line objects for remaining nodes.
- var lines = [];
- if (self.firstTouched) self.touched.push(null);
- forEach(self.touched, function(node) {
- if (node && node.parentNode != self.container) return;
-
- if (node) node.historyTouched = false;
- else self.firstTouched = false;
-
- var line = buildLine(node), shadow = self.after(node);
- if (!shadow || shadow.text != line.text || shadow.to != line.to) {
- lines.push(line);
- setTemp(node, line);
- }
- });
-
- // Get the BR element after/before the given node.
- function nextBR(node, dir) {
- var link = dir + "Sibling", search = node[link];
- while (search && search.nodeName != "BR")
- search = search[link];
- return search;
- }
-
- // Assemble line objects into chains by scanning the DOM tree
- // around them.
- var chains = []; self.touched = [];
- forEach(lines, function(line) {
- // Note that this makes the loop skip line objects that have
- // been pulled into chains by lines before them.
- if (!temp(line.from)) return;
-
- var chain = [], curNode = line.from, safe = true;
- // Put any line objects (referred to by temp info) before this
- // one on the front of the array.
- while (true) {
- var curLine = temp(curNode);
- if (!curLine) {
- if (safe) break;
- else curLine = buildLine(curNode);
- }
- chain.unshift(curLine);
- setTemp(curNode, null);
- if (!curNode) break;
- safe = self.after(curNode);
- curNode = nextBR(curNode, "previous");
- }
- curNode = line.to; safe = self.before(line.from);
- // Add lines after this one at end of array.
- while (true) {
- if (!curNode) break;
- var curLine = temp(curNode);
- if (!curLine) {
- if (safe) break;
- else curLine = buildLine(curNode);
- }
- chain.push(curLine);
- setTemp(curNode, null);
- safe = self.before(curNode);
- curNode = nextBR(curNode, "next");
- }
- chains.push(chain);
- });
-
- return chains;
- },
-
- // Find the 'shadow' of a given chain by following the links in the
- // DOM nodes at its start and end.
- shadowChain: function(chain) {
- var shadows = [], next = this.after(chain[0].from), end = chain[chain.length - 1].to;
- while (true) {
- shadows.push(next);
- var nextNode = next.to;
- if (!nextNode || nextNode == end)
- break;
- else
- next = nextNode.historyAfter || this.before(end);
- // (The this.before(end) is a hack -- FF sometimes removes
- // properties from BR nodes, in which case the best we can hope
- // for is to not break.)
- }
- return shadows;
- },
-
- // Update the DOM tree to contain the lines specified in a given
- // chain, link this chain into the DOM nodes.
- applyChain: function(chain) {
- // Some attempt is made to prevent the cursor from jumping
- // randomly when an undo or redo happens. It still behaves a bit
- // strange sometimes.
- var cursor = select.cursorPos(this.container, false), self = this;
-
- // Remove all nodes in the DOM tree between from and to (null for
- // start/end of container).
- function removeRange(from, to) {
- var pos = from ? from.nextSibling : self.container.firstChild;
- while (pos != to) {
- var temp = pos.nextSibling;
- removeElement(pos);
- pos = temp;
- }
- }
-
- var start = chain[0].from, end = chain[chain.length - 1].to;
- // Clear the space where this change has to be made.
- removeRange(start, end);
-
- // Insert the content specified by the chain into the DOM tree.
- for (var i = 0; i < chain.length; i++) {
- var line = chain[i];
- // The start and end of the space are already correct, but BR
- // tags inside it have to be put back.
- if (i > 0)
- self.container.insertBefore(line.from, end);
-
- // Add the text.
- var node = makePartSpan(fixSpaces(line.text), this.container.ownerDocument);
- self.container.insertBefore(node, end);
- // See if the cursor was on this line. Put it back, adjusting
- // for changed line length, if it was.
- if (cursor && cursor.node == line.from) {
- var cursordiff = 0;
- var prev = this.after(line.from);
- if (prev && i == chain.length - 1) {
- // Only adjust if the cursor is after the unchanged part of
- // the line.
- for (var match = 0; match < cursor.offset &&
- line.text.charAt(match) == prev.text.charAt(match); match++);
- if (cursor.offset > match)
- cursordiff = line.text.length - prev.text.length;
- }
- select.setCursorPos(this.container, {node: line.from, offset: Math.max(0, cursor.offset + cursordiff)});
- }
- // Cursor was in removed line, this is last new line.
- else if (cursor && (i == chain.length - 1) && cursor.node && cursor.node.parentNode != this.container) {
- select.setCursorPos(this.container, {node: line.from, offset: line.text.length});
- }
- }
-
- // Anchor the chain in the DOM tree.
- this.linkChain(chain);
- return start;
- }
-};
diff --git a/media/CodeMirror-0.62/js/util.js b/media/CodeMirror-0.62/js/util.js
deleted file mode 100644
index f552767..0000000
--- a/media/CodeMirror-0.62/js/util.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/* A few useful utility functions. */
-
-var internetExplorer = document.selection && window.ActiveXObject && /MSIE/.test(navigator.userAgent);
-var webkit = /AppleWebKit/.test(navigator.userAgent);
-
-// Capture a method on an object.
-function method(obj, name) {
- return function() {obj[name].apply(obj, arguments);};
-}
-
-// The value used to signal the end of a sequence in iterators.
-var StopIteration = {toString: function() {return "StopIteration"}};
-
-// Apply a function to each element in a sequence.
-function forEach(iter, f) {
- if (iter.next) {
- try {while (true) f(iter.next());}
- catch (e) {if (e != StopIteration) throw e;}
- }
- else {
- for (var i = 0; i < iter.length; i++)
- f(iter[i]);
- }
-}
-
-// Map a function over a sequence, producing an array of results.
-function map(iter, f) {
- var accum = [];
- forEach(iter, function(val) {accum.push(f(val));});
- return accum;
-}
-
-// Create a predicate function that tests a string againsts a given
-// regular expression. No longer used but might be used by 3rd party
-// parsers.
-function matcher(regexp){
- return function(value){return regexp.test(value);};
-}
-
-// Test whether a DOM node has a certain CSS class. Much faster than
-// the MochiKit equivalent, for some reason.
-function hasClass(element, className){
- var classes = element.className;
- return classes && new RegExp("(^| )" + className + "($| )").test(classes);
-}
-
-// Insert a DOM node after another node.
-function insertAfter(newNode, oldNode) {
- var parent = oldNode.parentNode;
- parent.insertBefore(newNode, oldNode.nextSibling);
- return newNode;
-}
-
-function removeElement(node) {
- if (node.parentNode)
- node.parentNode.removeChild(node);
-}
-
-function clearElement(node) {
- while (node.firstChild)
- node.removeChild(node.firstChild);
-}
-
-// Check whether a node is contained in another one.
-function isAncestor(node, child) {
- while (child = child.parentNode) {
- if (node == child)
- return true;
- }
- return false;
-}
-
-// The non-breaking space character.
-var nbsp = "\u00a0";
-var matching = {"{": "}", "[": "]", "(": ")",
- "}": "{", "]": "[", ")": "("};
-
-// Standardize a few unportable event properties.
-function normalizeEvent(event) {
- if (!event.stopPropagation) {
- event.stopPropagation = function() {this.cancelBubble = true;};
- event.preventDefault = function() {this.returnValue = false;};
- }
- if (!event.stop) {
- event.stop = function() {
- this.stopPropagation();
- this.preventDefault();
- };
- }
-
- if (event.type == "keypress") {
- event.code = (event.charCode == null) ? event.keyCode : event.charCode;
- event.character = String.fromCharCode(event.code);
- }
- return event;
-}
-
-// Portably register event handlers.
-function addEventHandler(node, type, handler, removeFunc) {
- function wrapHandler(event) {
- handler(normalizeEvent(event || window.event));
- }
- if (typeof node.addEventListener == "function") {
- node.addEventListener(type, wrapHandler, false);
- if (removeFunc) return function() {node.removeEventListener(type, wrapHandler, false);};
- }
- else {
- node.attachEvent("on" + type, wrapHandler);
- if (removeFunc) return function() {node.detachEvent("on" + type, wrapHandler);};
- }
-}
-
-function nodeText(node) {
- return node.innerText || node.textContent || node.nodeValue || "";
-}
diff --git a/media/CodeMirror-0.62/jstest.html b/media/CodeMirror-0.62/jstest.html
deleted file mode 100644
index 13879a7..0000000
--- a/media/CodeMirror-0.62/jstest.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <script src="js/codemirror.js" type="text/javascript"></script>
- <script src="js/mirrorframe.js" type="text/javascript"></script>
- <title>CodeMirror: JavaScript demonstration</title>
- <link rel="stylesheet" type="text/css" href="css/docs.css"/>
- </head>
- <body style="padding: 20px;">
-
-<p>This page demonstrates <a href="index.html">CodeMirror</a>'s
-JavaScript parser. Note that the ugly buttons at the top are not are
-not part of CodeMirror proper -- they demonstrate the way it can be
-embedded in a web-application.</p>
-
-<div class="border">
-<textarea id="code" cols="120" rows="30">
-// Here you see some JavaScript code. Mess around with it to get
-// acquainted with CodeMirror's features.
-
-// Press enter inside the object and your new line will be suitably
-// indented.
-var keyBindings = {
- enter: "newline-and-indent",
- tab: "reindent-selection",
- ctrl_z: "undo",
- ctrl_y: "redo",
- ctrl_backspace: "undo-for-safari (which blocks ctrl-z)",
- ctrl-bracket: "highlight-brackets",
- ctrl-shift-bracket: "jump-to-matching-bracket"
-};
-
-// Press tab on the next line and the wrong indentation will be fixed.
- var regex = /foo|bar/i;
-
-function example(x) {
- // Local variables get a different colour than global ones.
- var y = 44.4;
- return x + y - z;
-}
-</textarea>
-</div>
-
-<script type="text/javascript">
- var textarea = document.getElementById('code');
- var editor = new MirrorFrame(CodeMirror.replace(textarea), {
- height: "350px",
- content: textarea.value,
- parserfile: ["tokenizejavascript.js", "parsejavascript.js"],
- stylesheet: "css/jscolors.css",
- path: "js/",
- autoMatchParens: true
- });
-</script>
-
- </body>
-</html>
diff --git a/media/CodeMirror-0.62/manual.html b/media/CodeMirror-0.62/manual.html
deleted file mode 100644
index cc8131f..0000000
--- a/media/CodeMirror-0.62/manual.html
+++ /dev/null
@@ -1,622 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CodeMirror user manual</title>
- <link rel="stylesheet" type="text/css" href="css/docs.css"/>
- </head>
- <body>
- <h1 class="underline">CodeMirror user manual</h1>
-
- <h2>Contents</h2>
-
- <ul>
- <li><a href="#useage">Basic Useage</a></li>
- <li><a href="#configuration">Configuration</a></li>
- <li><a href="#parsers">Parsers</a></li>
- <li><a href="#programming">Programming Interface</a></li>
- <li><a href="#writeparser">Writing a Parser</a></li>
- </ul>
-
- <h2 id="useage">Basic Usage</h2>
-
- <p>Inside the editor, the tab key is used to re-indent the current
- selection (or the current line when nothing is selected), and
- pressing enter will, apart from inserting a line break,
- automatically indent the new line. Pressing control-enter will
- cause the whole buffer to be re-coloured, which can be helpful
- when some colouring has become out-of-date without the editor
- noticing it.</p>
-
- <p>The editor sports an undo/redo system, accessible with
- control-z (undo) and control-y (redo). Safari will not allow
- client scripts to capture control-z presses, but you can use
- control-backspace instead on that browser.</p>
-
- <p>The key-combination control-[ triggers a paren-blink: If the
- cursor is directly after a '(', ')', '[', ']', '{', or '}', the
- editor looks for the matching character, and highlights these
- characters for a moment. There is an option to enable this to
- happen any time the user types something or moves the cursor.</p>
-
- <p>To use CodeMirror in a document, you should add a script tag to
- load <a href="js/codemirror.js"><code>codemirror.js</code></a>. This
- adds two objects to your environment, <code>CodeMirror</code> and
- <code>CodeMirrorConfig</code>. The first is the interface to the
- editor, the second can be used to configure it. (Note that this is
- the only name-space pollution you can expect from CodeMirror --
- all other cruft is kept inside the IFRAMEs that it creates when
- you open an editor.)</p>
-
- <p>To add an editor to a document, you must choose a place, a
- parser, and a style-sheet for it. For example, to append an
- XML editor to the body of the document, you do:</p>
-
- <pre class="code">var editor = new CodeMirror(document.body, {
- parserfile: "parsexml.js",
- stylesheet: "xmlcolors.css"
-});</pre>
-
- <p>The first argument to the <code>CodeMirror</code> constructor
- can be a DOM node, in which case the editor gets appended to that
- node, or a function, which will be called with the IFRAME node as
- argument, and which is expected to place that node somewhere in
- the document.</p>
-
- <p>The second (optional) argument is an object that specifies
- options. A set of default options (see below) is present in the
- <code>CodeMirrorConfig</code> object, but each instance of the
- editor can be given a set of specific options to override these
- defaults. In this case, we specified that the parser should be
- loaded from the <a
- href="js/parsexml.js"><code>"parsexml.js"</code></a> file, and
- that <a href="css/xmlcolors.css"><code>"xmlcolors.css"</code></a>
- should be used to specify the colours of the code.</p>
-
- <p>Another example:</p>
-
- <pre class="code">var editor = new CodeMirror(CodeMirror.replace("inputfield"), {
- parserfile: ["tokenizejavascript.js", "parsejavascript.js"],
- path: "lib/codemirror/js/",
- stylesheet: "lib/codemirror/css/jscolors.css",
- content: document.getElementById("inputfield").value
-});</pre>
-
- <p>Here we use the utility function
- <code>CodeMirror.replace</code> to create a function that will
- replace a node in the current document (given either directly or
- by ID) with the editor. We also select the JavaScript parser this
- time, and give a <code>path</code> option to tell the editor that
- its files are not located in the same directory as the current
- HTML page, but in <code>"lib/codemirror/"</code>.</p>
-
- <p>There is a function
- <code>CodeMirror.isProbablySupported()</code> that causes some
- 1998-style browser detection to happen, returning
- <code>false</code> if CodeMirror is probably not supported on the
- browser, <code>true</code> if it probably is, and
- <code>null</code> if it has no idea. As the name suggests, this is
- not something you can rely on, but it's usually better than
- nothing.</p>
-
- <p>Another utility function, <code>CodeMirror.fromTextArea</code>,
- will, given a textarea node or the id of such a node, hide the
- textarea and replace it with a CodeMirror frame. If the textarea
- was part of a form, an <code>onsubmit</code> handler will be
- registered with this form, which will load the content of the
- editor into the textarea, so that it can be submitted as normal.
- This function optionally takes a configuration object as second
- argument.</p>
-
- <pre class="code">var editor = CodeMirror.fromTextArea("inputfield", {
- parserfile: ["tokenizejavascript.js", "parsejavascript.js"],
- path: "lib/codemirror/js/",
- stylesheet: "lib/codemirror/css/jscolors.css"
-});</pre>
-
- <p>The reason that the script path has to be configured is that
- CodeMirror will load in a bunch of extra files when an editor is
- created (the parser script, among others). To be able to do this,
- it has to know where to find them. These are all the JavaScript
- files that are part of CodeMirror itself:</p>
-
- <dl>
- <dt><a href="js/codemirror.js"><code>codemirror.js</code></a></dt>
- <dd>Main interface, takes care of default configuration and the
- definition of editor frames. Include this in your HTML
- document.</dd>
- <dt><a href="js/editor.js"><code>editor.js</code></a></dt> <dd>The
- code that takes care of reacting to user input, colouring text,
- and indenting lines.</dd>
- <dt><a href="js/util.js"><code>util.js</code></a></dt> <dd>A few
- generic utility functions.</dd>
- <dt><a
- href="js/undo.js"><code>undo.js</code></a></dt>
- <dd>Implements the undo history for the editor.</dd>
- <dt><a
- href="js/stringstream.js"><code>stringstream.js</code></a></dt>
- <dd>Objects for wrapping the textual input to the parser.</dd>
- <dt><a href="js/select.js"><code>select.js</code></a></dt> <dd>Some
- helper utilities for working with selected text and cursor
- positions.</dd>
- <dt><a href="js/tokenize.js"><code>tokenize.js</code></a></dt>
- <dd>Helper framework for writing tokenisers.</dd>
- </dl>
-
- <p>Most of these are rather full of comments, which can be useful
- when you are trying to figure out how they work, but wastes a lot
- of bandwidth in a production system. Take a look at the
- description of the <code>basefiles</code> option below if you want
- to concatenate and minimise the library.</p>
-
- <p>Apart from these, there are files that implement the various
- parsers. These all start with either <code>parse</code> or
- <code>tokenize</code>.</p>
-
- <h2 id="configuration">Configuration</h2>
-
- <p>There are three ways to configure CodeMirror:</p>
-
- <ul>
- <li>If you define a global <code>CodeMirrorConfig</code> object
- before loading <a
- href="js/codemirror.js"><code>codemirror.js</code></a>, the
- configuration options in that object will override the
- defaults.</li>
- <li>By assigning to the properties of the
- <code>CodeMirrorConfig</code> object, configuration defaults can
- be overridden after loading <a
- href="js/codemirror.js"><code>codemirror.js</code></a>.</li>
- <li>The <code>CodeMirror</code> constructor can be given a second
- argument, an object, which will override some options for just
- that editor. Options not mentioned in this object will default to
- the values in the <code>CodeMirrorConfig</code> object.</li>
- </ul>
-
- <p>The options that can be specified are these (most have sensible
- defaults specified in <a
- href="js/codemirror.js"><code>codemirror.js</code></a>):</p>
-
- <dl>
-
- <dt><code>stylesheet</code></dt><dd>The file name of the style-sheet
- that should be used to colour the code in the editor frame. See <a
- href="css/jscolors.css"><code>jscolors.css</code></a> for an
- example.</dd>
-
- <dt><code>path</code></dt><dd>The path that is prefixed to
- script file names when they are loaded into an IFRAME. (Note that
- this is not applied to the style-sheet file name.)</dd>
-
- <dt><code>parserfile</code></dt><dd>A file name string, or an
- array of strings that name the files containing the parser. See
- below for the interface that such a parser should
- implement.</dd>
-
- <dt><code>basefiles</code></dt><dd>An array of strings naming
- the files containing the base CodeMirror functionality. Defaults
- to <code>["util.js", "stringstream.js", "select.js", "undo.js",
- "editor.js", "tokenize.js"]</code>, but if you put them all into
- a single file to reduce latency, or add some functionality, you
- might have to adjust that.</dd>
-
- <dt><code>iframeClass</code></dt><dd>Set this to a string to
- give the IFRAME node created for the editor a custom CSS class.
- Defaults to <code>null</code>.</dd>
-
- <dt><code>passDelay</code></dt><dd>Gives the amount of
- milliseconds between colouring passes. Defaults to 200.</dd>
-
- <dt><code>passTime</code></dt><dd>Specifies the maximum amount
- of time that the highlighter will spend in one shot. Setting
- this too high will cause the editor to 'freeze' the browser for
- noticeable intervals. Defaults to 50.</dd>
-
- <dt><code>continuousScanning</code></dt><dd>Configure continuous
- scanning of the document. When <code>false</code>, scanning is
- disabled. When set to a number, say <code>N</code>, a
- 'background' process will scan the document for
- <code>passTime</code> (see above) milliseconds every
- <code>N</code> milliseconds, regardless of whether anything
- changed. This makes sure non-local changes propagate through the
- document, and will help keep everything consistent. It does add
- extra processing cost, even for an idle editor. Default value is
- <code>false</code>.</dd>
-
- <dt><code>autoMatchParens</code></dt><dd>When <code>true</code>,
- will cause parens to be matched every time a key is pressed or
- the user clicks on the document. Defaults to <code>false</code>.
- Might be expensive for big documents.</dd>
-
- <dt><code>saveFunction</code></dt><dd>If given a function
- value, that function will be invoked when the user presses
- control-s. You should advise your Opera users to use
- control-shift-s instead, since plain control-s will bring up the
- 'save page' dialog. Defaults to <code>null</code>.</dd>
-
- <dt><code>undoDepth</code></dt><dd>Maximum length of the undo
- history. Default is 50.</dd>
-
- <dt><code>onChange</code></dt><dd>An optional function of zero
- arguments that gets called whenever the document is changed.
- Happens at undo-commit time, not instantaniously.</dd>
-
- <dt><code>undoDelay</code></dt><dd>When nothing is done in the
- editor for this amount of milliseconds, pending changes get
- added to the undo history. Setting this lower will give the undo
- functionality a finer granularity. Defaults to 800.</dd>
-
- <dt><code>width</code>, <code>height</code></dt><dd>The size of
- the editor frame, given as a style-sheet quantities (for example
- <code>"600px"</code> or <code>"100%"</code>).</dd>
-
- <dt><code>disableSpellcheck</code></dt><dd>Should the editor
- disable spell-checking on browsers that support it (Firefox 2+).
- Default is <code>true</code>, since for most code spell-checking
- is useless.</dd>
-
- <dt><code>textWrapping</code></dt><dd>Can be used to disable or
- enable text-wrapping in the editor frame. Default is
- <code>true</code>.</dd>
-
- <dt><code>lineNumbers</code></dt><dd>Show line numbers to the
- left of the editor. This requires you to specify a style for the
- <code>CodeMirror-line-numbers</code> CSS class (in the outer
- document) to configure the width, font, colors, etcetera for the
- line-number DIV. You have to make sure that lines in the
- numbering element have the same height as lines in the editor.
- This is most easily done by giving them both the same font and
- an absolute ('pt' or 'px') font size. This option defaults to
- <code>false</code>. When enabling this, you have to disable
- <code>textWrapping</code>, since the line numbers don't take
- wrapped lines into account.</dd>
-
- <dt><code>indentUnit</code></dt><dd>An integer that specifies
- the amount of spaces one 'level' of indentation should add.
- Default is <code>2</code>.</dd>
-
- <dt><code>tabMode</code></dt><dd>Determines what the effect of
- pressing tab is. Possibilities are:
- <dl>
- <dt><code>"indent"</code></dt><dd>The default. Causes tab to
- adjust the indentation of the selection or current line using
- the parser's rules.</dd>
- <dt><code>"spaces"</code></dt><dd>Pressing tab simply inserts
- four spaces.</dd>
- <dt><code>"default"</code></dt><dd>CodeMirror does not
- interfere with the tab key, but leaves it to the browser to
- handle it. Binds shift-space to regular indentation
- behaviour.</dd>
- <dt><code>"shift"</code></dt><dd>Pressing tab indents the
- current line (or selection) one <code>indentUnit</code>
- deeper, pressing shift-tab or ctrl-tab (whichever your browser
- does not interfere with), un-indents it.</dd>
- </dl></dd>
-
- <dt><code>reindentOnLoad</code></dt><dd>When <code>true</code>,
- this causes the content of the editor to be reindented
- immediately when the editor loads. Defaults to
- <code>false</code>.</dd>
-
- <dt><code>readOnly</code></dt><dd>When set to <code>true</code>,
- the document is not editable.</dd>
-
- <dt><code>initCallback</code></dt><dd>If set to a function, this
- will be called (with the editor object as its argument) after
- the editor has finished initialising.</dd>
-
- <dt><code>cursorActivity</code></dt><dd>A function that is
- called every time the cursor moves, with the top-level node that
- the cursor is inside or next to as an argument. Can be used to
- have some controls react to the context of the cursor.</dd>
-
- <dt><code>activeTokens</code></dt><dd>Can be set to a function
- that will be called with <code>(spanNode, tokenObject,
- editor)</code> arguments whenever a new token node is being
- added to the document. Can be used to do things like add event
- handlers to nodes. Should <em>not</em> change the DOM structure
- of the node (so no turning the span into a link), since this
- will greatly confuse the editor.</dd>
-
- <dt id="parserConfig"><code>parserConfig</code></dt><dd>An
- object value that is passed along to the parser to configure it.
- What this object should look like depends on the parser
- used.</dd>
-
- <dt><code>content</code></dt><dd>The starting content of the
- editor. You'll probably not want to provide a global default for
- this, but add it to the <code>options</code> object passed to
- individual editors as they are created.</dd>
-
- </dl>
-
- <h2 id="parsers">Parsers</h2>
-
- <p>(If you want to use a CodeMirror parser to highlight a piece of
- text, without creating an editor, see <a
- href="highlight.html">this example</a>, and the <code><a
- href="js/highlight.js">highlight.js</a></code> script.)</p>
-
- <p>The following parsers come with the distribution of CodeMirror:</p>
-
- <dl>
- <dt><code><a href="js/parsexml.js">parsexml.js</a></code> (<a
- href="htmltest.html">demo</a>)</dt><dd>A HTML/XML parser. Takes
- a <code>useHTMLKludges</code> configuration option (see the
- <code><a href="#parserConfig">parserConfig</a></code> option
- above), which specifies whether the content of the editor is
- HTML or XML, and things like self-closing tags (<code>br</code>,
- <code>img</code>) exist. This defaults to <code>true</code>.
- Example colours for the styles that this parser uses are defined
- in <code><a
- href="css/xmlcolors.css">css/xmlcolors.css</a></code>.</dd>
-
- <dt><code><a
- href="js/tokenizejavascript.js">tokenizejavascript.js</a></code>,
- <code><a
- href="js/parsejavascript.js">parseejavascript.js</a></code> (<a
- href="jstest.html">demo</a>)</dt><dd>The JavaScript parser.
- Example colours in <code><a
- href="css/jscolors.css">css/jscolors.css</a></code></dd>
-
- <dt><code><a href="js/parsecss.js">parsecss.js</a></code> (<a
- href="csstest.html">demo</a>)</dt><dd>A CSS parser. Styles in
- <code><a
- href="css/csscolors.css">css/csscolors.css</a></code></dd>
-
- <dt><code><a
- href="js/parsehtmlmixed.js">parsehtmlmixed.js</a></code> (<a
- href="mixedtest.html">demo</a>)</dt><dd>A mixed-mode HTML
- parser. Requires the XML, JavaScript, and CSS parsers to also be
- loaded, so your <code>parserfile</code> option looks something
- like <code>["parsexml.js", "parsecss.js",
- "tokenizejavascript.js", "parsejavascript.js",
- "parsehtmlmixed.js"]</code>.</dd>
-
- <dt><code><a href="js/parsesparql.js">parsesparql.js</a></code>
- (<a href="sparqltest.html">demo</a>)</dt><dd>Parses the <a
- href="http://en.wikipedia.org/wiki/SPARQL">SPARQL</a> query
- language. Example styles in <code><a
- href="css/sparqlcolors.css">css/sparqlcolors.css</a></code></dd>
-
- <dt><code><a
- href="js/parsedummy.js">parsedummy.js</a></code></dt><dd>A
- 'dummy' parser to make it possible to edit plain text, or
- documents for which no suitable parser exists.</dd>
-
- <dt><code><a
- href="contrib/php/js/parsephp.js">contrib/php/js/parsephp.js</a></code>
- (<a href="contrib/php/index.html">demo</a>)</dt><dd>PHP
- parser.</dd>
-
- <dt><code><a
- href="contrib/python/js/parsepython.js">contrib/python/js/parsepython.js</a></code>
- (<a href="contrib/python/index.html">demo</a>)</dt><dd>Python
- parser.</dd>
-
- <dt><code><a href="contrib/lua/js/parselua.js">contrib/lua/js/parselua.js</a></code>
- (<a href="contrib/lua/index.html">demo</a>)</dt><dd>Lua
- parser.</dd>
-
- </dl>
-
- <h2 id="programming">Programming Interface</h2>
-
- <p>To be as flexible as possible, CodeMirror implements a very
- plain editable field, without any accompanying buttons, bells, and
- whistles. <code>CodeMirror</code> objects do, however, provide a
- number of methods that make it possible to add extra functionality
- around the editor. <a
- href="js/mirrorframe.js"><code>mirrorframe.js</code></a> provides a
- basic example of their usage.</p>
-
- <dl>
-
- <dt><code>getCode()</code> &#8594;
- <code>string</code></dt><dd>Returns the current content of the
- editor, as a string.</dd>
-
- <dt><code>setCode(string)</code></dt><dd>Replaces the current
- content of the editor with the given value.</dd>
-
- <dt><code>focus()</code></dt><dd>Gives focus to the editor
- frame.</dd>
-
- <dt><code>currentLine()</code> &#8594;
- <code>number</code></dt><dd>Returns the line on which the cursor
- is currently sitting. <span class="warn">(Deprecated, see the
- line-based interface below)</span></dd>
-
- <dt><code>jumpToLine(number)</code></dt><dd>Moves the cursor to
- the start of the given line. <span
- class="warn">(Deprecated)</span></dd>
-
- <dt><code>selection()</code> &#8594;
- <code>string</code></dt><dd>Returns the text that is currently
- selected in the editor.</dd>
-
- <dt><code>replaceSelection(string)</code></dt><dd>Replaces the
- currently selected text with the given string. Will also cause
- the editor frame to gain focus.</dd>
-
- <dt><code>reindent()</code></dt><dd>Automatically re-indent the
- whole document.</dd>
-
- <dt><code>reindentSelection()</code></dt><dd>Automatically
- re-indent the selected lines.</dd>
-
- <dt><code>getSearchCursor(string, atCursor)</code> &#8594;
- <code>cursor</code></dt><dd>The first argument indicates the
- string that should be searched for, and the second indicates
- whether searching should start at the cursor (<code>true</code>)
- or at the start of the document (<code>false</code>). Returns an
- object that provides an interface for searching. Call its
- <code>findNext()</code> method to search for an occurrence of
- the given string. This returns <code>true</code> if something is
- found, or <code>false</code> if the end of document is reached.
- When an occurrence has been found, you can call
- <code>select()</code> to select it, or
- <code>replace(string)</code> to replace it with a given string.
- Note that letting the user change the document, or
- programmatically changing it in any way except for calling
- <code>replace</code> on the cursor itself, might cause a cursor
- object to skip back to the beginning of the document.</dd>
-
- <dt><code>undo()</code></dt><dd>Undo one changeset, if available.</dd>
- <dt><code>redo()</code></dt><dd>Redo one changeset, if available.</dd>
- <dt><code>historySize() &#8594; object</code></dt><dd>Get a
- <code>{undo, redo}</code> object holding the sizes of the undo
- and redo histories.</dd>
- <dt><code>clearHistory()</code></dt><dd>Drop all history
- information.</dd>
-
- <dt><code>grabKeys(callback, filter)</code></dt><dd>Route
- keyboard input in the editor to a callback function. This
- function is given a slightly normalised (see
- <code>normalizeEvent</code> in <a
- href="js/util.js"><code>util.js</code></a>) <code>keydown</code>
- event object. If a second argument is given, this will be used
- to determine which events to apply the callback to. It should
- take a key code (as in <code>event.keyCode</code>), and return a
- boolean, where <code>true</code> means the event should be
- routed to the callback, and <code>false</code> leaves the key to
- perform its normal behaviour.</dd>
- <dt><code>ungrabKeys()</code></dt><dd>Revert the effect of
- <code>grabKeys</code>.</dd>
-
- <dt><code>setParser(name)</code></dt><dd>Change the active
- parser. To use this you'll have to load more than one parser
- (put the one you want to use as default at the end of the list).
- Then call this function with a string containing the name of the
- parser you want to switch to (see the parser script file to find
- the name, it'll be something like <code>CSSParser</code>).</dd>
- </dl>
-
- <p>For detailed interaction with the content of the editor,
- CodeMirror exposes a line-oriented interface, which allows you to
- inspect and manipulate the document line by line. Line handles
- should be considered opaque (they are in fact the <code>BR</code>
- nodes at the start of the line), except that the value
- <code>false</code> (but <em>not</em> <code>null</code>) always
- denotes an invalid value. Since changing the document might cause
- some line handles to become invalid, every function that takes
- them as argument can throw
- <code>CodeMirror.InvalidLineHandle</code>. These are the relevant
- methods:</p>
-
- <dl>
- <dt><code>cursorPosition(start)</code> &#8594;
- <code>object</code></dt><dd>Retrieve a <code>{line,
- character}</code> object representing the cursor position.
- <code>start</code> defaults to <code>true</code> and determines
- if the startpoint or the endpoint of the selection is used.</dd>
- <dt><code>firstLine()</code> &#8594;
- <code>handle</code></dt><dd>Get the first line of the
- document.</dd>
- <dt><code>lastLine()</code> &#8594;
- <code>handle</code></dt><dd>The last line.</dd>
- <dt><code>nextLine(handle)</code> &#8594;
- <code>handle</code></dt><dd>Get the line after the given one, or
- <code>false</code> if that was the last line.</dd>
- <dt><code>prevLine(handle)</code> &#8594;
- <code>handle</code></dt><dd>Find the line before the given one,
- return <code>false</code> if that was the first line.</dd>
- <dt><code>nthLine(number)</code> &#8594;
- <code>handle</code></dt><dd>Find the Nth line of the document.
- Note that the first line counts as one, not zero. Returns
- <code>false</code> if there is no such line.</dd>
- <dt><code>lineContent(handle)</code> &#8594;
- <code>string</code></dt><dd>Retrieve the content of the
- line.</dd>
- <dt><code>setLineContent(handle, string)</code></dt><dd>Replace
- the content of the line with the given string.</dd>
- <dt><code>lineNumber(handle)</code> &#8594;
- <code>number</code></dt><dd>Ask which line of the document
- (1-based) the given line is.</dd>
- <dt><code>selectLines(startHandle, startOffset,
- endHandle, endOffset)</code></dt><dd>Move the selection to a
- specific point. <code>endHandle</code> and
- <code>endOffset</code> can be omitted to just place the cursor
- somewhere without selecting any text.</dd>
- <dt><code>insertIntoLine(handle, position,
- text)</code></dt><dd>Insert a piece of text into a line.
- <code>position</code> can be an integer, specifying the position
- in the line where the text should be inserted, or the string
- <code>"end"</code>, for the end of the line.</dd>
- </dl>
-
- <h2 id="writeparser">Writing a Parser</h2>
-
- <p>A parser is implemented by one or more files (see
- <code>parserfile</code> above) which, when loaded, add a
- <code>Parser</code> object to the <code>Editor</code> object
- defined by <a href="js/editor.js"><code>editor.js</code></a>. This
- object must support the following interface:</p>
-
- <dl>
-
- <dt><code>make(stream)</code></dt><dd>A function that, given a
- string stream (see <a
- href="js/stringstream.js"><code>stringstream.js</code></a>),
- creates a parser. The behaviour of this parser is described
- below.</dd>
-
- <dt><code>electricChars</code></dt><dd>An optional string
- containing the characters that, when typed, should cause the
- indentation of the current line to be recomputed (for example
- <code>"{}"</code> for c-like languages).</dd>
-
- <dt><code>configure(object)</code></dt><dd>An optional function
- that can be used to configure the parser. If it exists, and an
- editor is given a <code>parserConfig</code> option, it will be
- called with the value of that option.</dd>
-
- <dt><code>firstIndentation(chars, current,
- direction)</code></dt><dd>An optional function that is used to
- determine the proper indentation of the first line of a
- document. When not provided, <code>0</code> is used.</dd>
- </dl>
-
- <p>When the <code>make</code> method is called with a string
- stream, it should return a MochiKit-style iterator: an object with
- a <code>next</code> method, which will raise
- <code>StopIteration</code> when it is at its end (see <a
- href="http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/">this</a>
- for details). This iterator, when called, will consume input from
- the string stream, and produce a token object.</p>
-
- <p>Token objects represent a single significant piece of the text
- that is being edited. A token object must have a
- <code>value</code> property holding the text it stands for, and a
- <code>style</code> property with the CSS class that should be used
- to colour this element. This can be anything, except that any
- whitespace at the start of a line should <em>always</em> have
- class <code>"whitespace"</code>: The editor must be able to
- recognize these when it indents lines. Furthermore, each newline
- character <em>must</em> have its own separate token, which has an
- <code>indentation</code> property holding a function that can be
- used to determine the proper indentation level for the next line.
- This function optionally takes the text in the first token of the
- next line, the current indentation of the line, and the
- 'direction' of the indentation as arguments, which it can use to
- adjust the indentation level. The direction argument is only
- useful for modes in which lines do not have a fixed indentation,
- and can be modified by multiple tab presses. It is
- <code>null</code> for 'default' indentations (like what happens
- when the user presses enter), <code>true</code> for regular tab
- presses, and <code>false</code> for control-tab or shift-tab.</p>
-
- <p>So far this should be pretty easy. The hard part is that this
- iterator must also have a <code>copy</code> method. This method,
- called without arguments, returns a function representing the
- current state of the parser. When this state function is later
- called with a string stream as its argument, it returns a parser
- object that resumes parsing using the old state and the new input
- stream. It may assume that only one parser is active at a time,
- and can clobber the state of the old parser if it wants.</p>
-
- <p>For examples, see <a
- href="js/parsejavascript.js"><code>parsejavascript.js</code></a>,
- <a href="js/parsexml.js"><code>parsexml.js</code></a>, and <a
- href="js/parsecss.js"><code>parsecss.js</code></a>.</p>
-
- </body>
-</html>
diff --git a/media/CodeMirror-0.62/mixedtest.html b/media/CodeMirror-0.62/mixedtest.html
deleted file mode 100644
index 46d25da..0000000
--- a/media/CodeMirror-0.62/mixedtest.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <script src="js/codemirror.js" type="text/javascript"></script>
- <title>CodeMirror: HTML mixed-mode demonstration</title>
- <link rel="stylesheet" type="text/css" href="css/docs.css"/>
- </head>
- <body style="padding: 20px;">
-
-<p>This is a simple demonstration of the HTML mixed-mode indentation
-module for <a href="index.html">CodeMirror</a>. Script tags use the JS
-parser, style tags use the CSS parser.</p>
-
-<div style="border: 1px solid black; padding: 3px;">
-<textarea id="code" cols="120" rows="30">
-&lt;html>
- &lt;head>
- &lt;title>HTML Example&lt;/title>
- &lt;script type="text/javascript">
- function foo(bar, baz) {
- alert("quux");
- return bar + baz + 1;
- }
- &lt;/script>
- &lt;style type="text/css">
- div.border {
- border: 1px solid black;
- padding: 3px;
- }
- #foo code {
- font-family: courier, monospace;
- font-size: 80%;
- color: #448888;
- }
- &lt;/style>
- &lt;/head>
- &lt;body>
- &lt;p>Duh&lt;/p>
- &lt;/body>
-&lt;/html>
-</textarea>
-</div>
-
-<script type="text/javascript">
- var editor = CodeMirror.fromTextArea('code', {
- height: "350px",
- parserfile: ["parsexml.js", "parsecss.js", "tokenizejavascript.js", "parsejavascript.js", "parsehtmlmixed.js"],
- stylesheet: ["css/xmlcolors.css", "css/jscolors.css", "css/csscolors.css"],
- path: "js/"
- });
-</script>
- </body>
-</html>
diff --git a/media/CodeMirror-0.62/sparqltest.html b/media/CodeMirror-0.62/sparqltest.html
deleted file mode 100644
index 5d65c93..0000000
--- a/media/CodeMirror-0.62/sparqltest.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <script src="js/codemirror.js" type="text/javascript"></script>
- <title>CodeMirror: Sparql demonstration</title>
- <link rel="stylesheet" type="text/css" href="css/docs.css"/>
- </head>
- <body style="padding: 20px;">
-
-<p>Demonstration of <a href="index.html">CodeMirror</a>'s Sparql
-highlighter.</p>
-
-<div class="border">
-<textarea id="code" cols="120" rows="30">
-PREFIX a: &lt;http://www.w3.org/2000/10/annotation-ns#>
-PREFIX dc: &lt;http://purl.org/dc/elements/1.1/>
-PREFIX foaf: &lt;http://xmlns.com/foaf/0.1/>
-
-# Comment!
-
-SELECT ?given ?family
-WHERE {
- ?annot a:annotates &lt;http://www.w3.org/TR/rdf-sparql-query/> .
- ?annot dc:creator ?c .
- OPTIONAL {?c foaf:given ?given ;
- foaf:family ?family } .
- FILTER isBlank(?c)
-}
-</textarea>
-</div>
-
-<script type="text/javascript">
- var editor = CodeMirror.fromTextArea('code', {
- height: "250px",
- parserfile: "parsesparql.js",
- stylesheet: "css/sparqlcolors.css",
- path: "js/"
- });
-</script>
-
- </body>
-</html>
diff --git a/media/CodeMirror-0.62/story.html b/media/CodeMirror-0.62/story.html
deleted file mode 100644
index d845858..0000000
--- a/media/CodeMirror-0.62/story.html
+++ /dev/null
@@ -1,652 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>Implementing a syntax-higlighting JavaScript editor in JavaScript</title>
- <style type="text/css">
- body {
- padding: 3em 6em;
- max-width: 50em;
- }
- h1 {
- text-align: center;
- margin: 0;
- }
- h2 {
- font-size: 130%;
- }
- code {
- font-family: courier, monospace;
- font-size: 80%;
- color: #144;
- }
- p {
- margin: 1em 0;
- }
- pre.code {
- margin: 1.1em 12px;
- border: 1px solid #CCCCCC;
- padding: .4em;
- font-family: courier, monospace;
- }
- </style>
- <link rel="stylesheet" type="text/css" href="css/jscolors.css"/>
- </head>
- <body>
- <h1 style="font-size: 180%;">Implementing a syntax-higlighting JavaScript editor in JavaScript</h1>
- <h1 style="font-size: 110%;">or</h1>
- <h1 style="font-size: 130%; margin-bottom: 3em;">A brutal odyssey to the dark side of the DOM tree</h1>
-
- <p style="font-size: 80%">
- <b>Topic</b>: JavaScript, advanced browser weirdness, cool programming techniques<br/>
- <b>Audience</b>: Programmers, especially JavaScript programmers<br/>
- <b>Author</b>: Marijn Haverbeke<br/>
- <b>Date</b>: May 24th 2007
- </p>
-
- <p style="color: #811; font-size: 90%; font-style: italic">Note: some of the details given here no
- longer apply to the current <a
- href="http://marijn.haverbeke.nl/codemirror">CodeMirror</a>
- codebase, which has evolved quite a bit in the meantime.</p>
-
- <p>In one of his (very informative) <a
- href="http://www.learnwebdesignonline.com/videos/programming/javascript/yahoo-douglas-crockford">video
- lectures</a>, Douglas Crockford remarks that writing JavaScript
- for the web is 'programming in a hostile environment'. I had done
- my fair share of weird workarounds, and even occasonally gave up
- an on idea entirely because browsers just wouldn't support it, but
- before this project I never really realized just how powerless a
- programmer can be in the face of buggy, incompatible, and poorly
- designed platforms.</p>
-
- <p>The plan was not ridiculously ambitious. I wanted to 'enhance' a
- textarea to the point where writing code in it is pleasant. This meant
- automatic indentation and, if possible at all, syntax highlighting.</p>
-
- <p>In this document I describe the story of implementing this, for your
- education and amusement. A demonstration of the resulting program,
- along with the source code, can be found at <a
- href="http://marijn.haverbeke.nl/codemirror">my website</a>.</p>
-
- <h2>Take one: Only indentation</h2>
-
- <p>The very first attempt merely added auto-indentation to a textarea
- element. It would scan backwards through the content of the area,
- starting from the cursor, until it had enough information to decide
- how to indent the current line. It took me a while to figure out a
- decent model for indenting JavaScript code, but in the end this seems
- to work:</p>
-
- <ul>
- <li>Code that sits inside a block is indented one unit (generally two
- spaces) more than the statement or brace that opened the block.</li>
- <li>A statement that is continued to the next line is indented one unit
- more than the line that starts the statement.</li>
- <li>When dealing with lists of arguments or the content of array and
- object literals there are two possible models. If there is any text
- directly after the opening brace, bracket, or parenthesis,
- subsequent lines are aligned with this opening character. If the
- opening character is followed by a newline (optionally with whitespace
- or comments before it), the next line is indented one unit further
- than the line that started the list.</li>
- <li>And, obviously, if a statement follows another statement it is
- indented the same amount as the one before it.</li>
- </ul>
-
- <p>When scanning backwards through code one has to take string values,
- comments, and regular expressions (which are delimited by slashes)
- into account, because braces and semicolons and such are not
- significant when they appear inside them. Single-line ('//') comments
- turned out to be rather inefficient to check for when doing a
- backwards scan, since every time you encounter a newline you have to
- go on to the next newline to determine whether this line ends in a
- comment or not. Regular expressions are even worse &#x2015; without
- contextual information they are impossible to distinguish from the
- division operator, and I didn't get them working in this first
- version.</p>
-
- <p>To find out which line to indent, and to make sure that adding or
- removing whitespace doesn't cause the cursor to jump in strange ways,
- it is necessary to determine which text the user has selected. Even
- though I was working with just a simple textarea at this point, this
- was already a bit of a headache.</p>
-
- <p>On W3C-standards-respecting browsers, textarea nodes have
- <code>selectionStart</code> and <code>selectionEnd</code>
- properties which nicely give you the amount of characters before
- the start and end of the selection. Great!</p>
-
- <p>Then, there is Internet Explorer. Internet Explorer also has an API
- for looking at and manipulating selections. It gives you information
- such as a detailed map of the space the selected lines take up on the
- screen, in pixels, and of course the text inside the selection. It
- does, however, not give you much of a clue on where the selection is
- located in the document.</p>
-
- <p>After some experimentation I managed to work out an elaborate
- method for getting something similar to the
- <code>selectionStart</code> and <code>selectionEnd</code> values
- in other browsers. It worked like this:</p>
-
- <ul>
- <li>Get the <code>TextRange</code> object corresponding to the selection.</li>
- <li>Record the length of the text inside it.</li>
- <li>Make another <code>TextRange</code> that covers the whole textarea element.</li>
- <li>Set the start of the first <code>TextRange</code> to the start of the second one.</li>
- <li>Again get the length of the text in the first object.</li>
- <li>Now <code>selectionEnd</code> is the second length, and <code>selectionStart</code> is
- the second minus the first one.</li>
- </ul>
-
- <p>That seemed to work, but when resetting the selection after modifying
- the content of the textarea I ran into another interesting feature of
- these <code>TextRange</code>s: You can move their endpoints by a given number of
- characters, which is useful when trying to set a cursor at the Nth
- character of a textarea, but in this context, newlines are <em>not</em>
- considered to be characters, so you'll always end up one character too
- far for every newline you passed. Of course, you can count newlines
- and compensate for this (though it is still not possible to position
- the cursor right in front of a newline). Sheesh.</p>
-
- <p>After ragging on Internet Explorer for a while, let us move on and rag
- on Firefox a bit. It turns out that, in Firefox, getting and setting
- the text content of a DOM element is unexplainably expensive,
- especially when there is a lot of text involved. As soon as I tried to
- use my indentation code to indent itself (some 400 lines), I found
- myself waiting for over four seconds every time I pressed enter. That
- seemed a little slow.</p>
-
- <h2>designMode it is</h2>
-
- <p>The solution was obvious: Since the text inside a textarea can only be
- manipulated as one single big string, I had to spread it out over
- multiple nodes. How do you spread editable content over multiple
- nodes? Right! <code>designMode</code> or <code>contentEditable</code>.</p>
-
- <p>Now I wasn't entirely naive about <code>designMode</code>, I had been looking
- into writing a non-messy WYSIWYG editor before, and at that time I had
- concluded two things:</p>
-
- <ul>
- <li>It is impossible to prevent the user from inserting whichever HTML
- junk he wants into the document.</li>
- <li>In Internet Explorer, it is extemely hard to get a good view
- on what nodes the user has selected.</li>
- </ul>
-
- <p>Basically, the good folks at Microsoft designed a really bad interface
- for putting editable documents in pages, and the other browsers, not
- wanting to be left behind, more or less copied that. And there isn't
- much hope for a better way to do this appearing anytime soon. Wise
- people probably use a Flash movie or (God forbid) a Java applet for
- these kind of things, though those are not without drawbacks either.</p>
-
- <p>Anyway, seeing how using an editable document would also make syntax
- highlighting possible, I foolishly went ahead. There is something
- perversely fascinating about trying to build a complicated system on a
- lousy, unsuitable platform.</p>
-
- <h2>A parser</h2>
-
- <p>How does one do decent syntax highlighting? A very simple scanning can
- tell the difference between strings, comments, keywords, and other
- code. But this time I wanted to actually be able to recognize regular
- expressions, so that I didn't have any blatant incorrect behaviour
- anymore.</p>
-
- <p>That brought me to the idea of doing a serious parse on the code. This
- would not only make detecting regular expressions much easier, it
- would also give me detailed information about the code, which can be
- used to determine proper indentation levels, and to make subtle
- distinctions in colouring, for example the difference between variable
- names and property names.</p>
-
- <p>And hey, when we're parsing the whole thing, it would even be possible
- to make a distinction between local and global variables, and colour
- them differently. If you've ever programmed JavaScript you can
- probably imagine how useful this would be &#x2015; it is ridiculously easy
- to accidentally create global instead of local variables. I don't
- consider myself a JavaScript rookie anymore, but it was (embarrasingly
- enough) only this week that I realized that my habit of typing <code>for
- (name in object) ...</code> was creating a global variable <code>name</code>, and that
- I should be typing <code>for (var name in object) ...</code> instead.</p>
-
- <p>Re-parsing all the code the user has typed in every time he hits a key
- is obviously not feasible. So how does one combine on-the-fly
- highlighting with a serious parser? One option would be to split the
- code into top-level statements (functions, variable definitions, etc.)
- and parse these separately. This is horribly clunky though, especially
- considering the fact that modern JavaScripters often put all the code
- in a file in a single big object or function to prevent namespace
- pollution.</p>
-
- <p>I have always liked continuation-passing style and generators. So the
- idea I came up with is this: An interruptable, resumable parser. This
- is a parser that does not run through a whole document at once, but
- parses on-demand, a little bit at a time. At any moment you can create
- a copy of its current state, which can be resumed later. You start
- parsing at the top of the code, and keep going as long as you like,
- but throughout the document, for example at every end of line, you
- store a copy of the current parser state. Later on, when line 106
- changes, you grab the interrupted parser that was stored at the end of
- line 105, and use it to re-parse line 106. It still knows exactly what
- the context was at that point, which local variables were defined,
- which unfinished statements were encountered, and so on.</p>
-
- <p>But that, unfortunately, turned out to be not quite as easy as it
- sounds.</p>
-
- <h2>The DOM nodes underfoot</h2>
-
- <p>Of course, when working inside an editable frame we don't just
- have to deal with text. The code will be represented by some kind
- of DOM tree. My first idea was to set the <code>white-space:
- pre</code> style for the frame and try to work with mostly text,
- with the occasional coloured <code>span</code> element. It turned
- out that support for <code>white-space: pre</code> in browsers,
- especially in editable frames, is so hopelessly glitchy that this
- was unworkable.</p>
-
- <p>Next I tried a series of <code>div</code> elements, one per
- line, with <code>span</code> elements inside them. This seemed to
- nicely reflect the structure of the code in a shallowly
- hierarchical way. I soon realized, however, that my code would be
- much more straightfoward when using no hierarchy whatsoever
- &#x2015; a series of <code>span</code>s, with <code>br</code> tags
- at the end of every line. This way, the DOM nodes form a flat
- sequence that corresponds to the sequence of the text &#x2015;
- just extract text from <code>span</code> nodes and substitute
- newlines for <code>br</code> nodes.</p>
-
- <p>It would be a shame if the editor would fall apart as soon as
- someone pastes some complicated HTML into it. I wanted it to be
- able to deal with whatever mess it finds. This means using some
- kind of HTML-normalizer that takes arbitrary HTML and flattens it
- into a series of <code>br</code>s and <code>span</code> elements
- that contain a single text node. Just like the parsing process, it
- would be best if this did not have to done to the entire buffer
- every time something changes.</p>
-
- <p>It took some banging my head against my keyboard, but I found a very
- nice way to model this. It makes heavy use of generators, for which I
- used <a href="http://www.mochikit.com">MochiKit</a>'s iterator
- framework. Bob Ippolito explains the concepts in this library very
- well in his <a
- href="http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/">blog
- post</a> about it. (Also notice some of the dismissive comments at the
- bottom of that post. They say "I don't think I really want to learn
- this, so I'll make up some silly reason to condemn it.")</p>
-
- <p>The highlighting process consists of the following elements:
- normalizing the DOM tree, extracting the text from the DOM tree,
- tokenizing this text, parsing the tokens, and finally adjusting the
- DOM nodes to reflect the structure of the code.</p>
-
- <p>The first two, I put into a single generator. It scans the DOM
- tree, fixing anything that is not a simple top-level
- <code>span</code> or <code>br</code>, and it produces the text
- content of the nodes (or a newline in case of a <code>br</code>)
- as its output &#x2015; each time it is called, it yields a string.
- Continuation passing style was a good way to model this process in
- an iterator, which has to be processed one step at a time. Look at
- this simplified version:</p>
-
- <pre class="code"><span class="js-keyword">function</span> <span class="js-variable">traverseDOM</span>(<span class="js-variabledef">start</span>){
- <span class="js-keyword">var</span> <span class="js-variabledef">cc</span> = <span class="js-keyword">function</span>(){<span class="js-variable">scanNode</span>(<span class="js-localvariable">start</span>, <span class="js-variable">stop</span>);};
- <span class="js-keyword">function</span> <span class="js-variabledef">stop</span>(){
- <span class="js-localvariable">cc</span> = <span class="js-localvariable">stop</span>;
- <span class="js-keyword">throw</span> <span class="js-variable">StopIteration</span>;
- }
- <span class="js-keyword">function</span> <span class="js-variabledef">yield</span>(<span class="js-variabledef">value</span>, <span class="js-variabledef">c</span>){
- <span class="js-localvariable">cc</span> = <span class="js-localvariable">c</span>;
- <span class="js-keyword">return</span> <span class="js-localvariable">value</span>;
- }
-
- <span class="js-keyword">function</span> <span class="js-variabledef">scanNode</span>(<span class="js-variabledef">node</span>, <span class="js-variabledef">c</span>){
- <span class="js-keyword">if</span> (<span class="js-localvariable">node</span>.<span class="js-property">nextSibling</span>)
- <span class="js-keyword">var</span> <span class="js-variabledef">nextc</span> = <span class="js-keyword">function</span>(){<span class="js-localvariable">scanNode</span>(<span class="js-localvariable">node</span>.<span class="js-property">nextSibling</span>, <span class="js-localvariable">c</span>);};
- <span class="js-keyword">else</span>
- <span class="js-keyword">var</span> <span class="js-variabledef">nextc</span> = <span class="js-localvariable">c</span>;
-
- <span class="js-keyword">if</span> (<span class="js-comment">/* node is proper span element */</span>)
- <span class="js-keyword">return</span> <span class="js-localvariable">yield</span>(<span class="js-localvariable">node</span>.<span class="js-property">firstChild</span>.<span class="js-property">nodeValue</span>, <span class="js-localvariable">nextc</span>);
- <span class="js-keyword">else</span> <span class="js-keyword">if</span> (<span class="js-comment">/* node is proper br element */</span>)
- <span class="js-keyword">return</span> <span class="js-localvariable">yield</span>(<span class="js-string">&quot;\n&quot;</span>, <span class="js-localvariable">nextc</span>);
- <span class="js-keyword">else</span>
- <span class="js-comment">/* flatten node, yield its textual content */</span>;
- }
-
- <span class="js-keyword">return</span> {<span class="js-property">next</span>: <span class="js-keyword">function</span>(){<span class="js-keyword">return</span> <span class="js-localvariable">cc</span>();}};
-}</pre>
-
- <p>The variable <code>c</code> stands for 'continuation', and <code>cc</code> for 'current
- continuation' &#x2015; that last variable is used to store the function to
- continue with, when yielding a value to the outside world. Every time
- control leaves this function, it has to make sure that <code>cc</code> is set to
- a suitable value, which is what <code>yield</code> and <code>stop</code> take care of.</p>
-
- <p>The object that is returned contains a <code>next</code> method, which is
- MochiKit's idea of an iterator, and the initial continuation just
- throws a <code>StopIteration</code>, which is how MochiKit signals that an
- iterator has reached its end.</p>
-
- <p>The first lines of <code>scanNode</code> extend the continuation with the task of
- scanning the next node, if there is a next node. The rest of the
- function decides what kind of value to <code>yield</code>. Note that this is a
- rather trivial example of this technique, since the process of going
- through these nodes is basically linear (it was much, much more
- complex in earlier versions), but still the trick with the
- continuations makes the code shorter and, for those in the know,
- clearer than the equivalent 'storing the iterator state in variables'
- approach.</p>
-
- <p>The next iterator that the input passes through is the
- tokenizer. Well, actually, there is another iterator in between
- that isolates the tokenizer from the fact that the DOM traversal
- yields a bunch of separate strings, and presents them as a single
- character stream (with a convenient <code>peek</code> operation),
- but this is not a very interesting one. What the tokenizer returns
- is a stream of token objects, each of which has a
- <code>value</code>, its textual content, a <code>type</code>, like
- <code>"variable"</code>, <code>"operator"</code>, or just itself,
- <code>"{"</code> for example, in the case of significant
- punctuation or special keywords. They also have a
- <code>style</code>, which is used later by the highlighter to give
- their <code>span</code> elements a class name (the parser will
- still adjust this in some cases).</p>
-
- <p>At first I assumed the parser would have to talk back to the
- tokenizer about the current context, in order to be able to
- distinguish those accursed regular expressions from divisions, but
- it seems that regular expressions are only allowed if the previous
- (non-whitespace, non-comment) token was either an operator, a
- keyword like <code>new</code> or <code>throw</code>, or a specific
- kind of punctuation (<code>"[{}(,;:"</code>) that indicates a new
- expression can be started here. This made things considerably
- easier, since the 'regexp or no regexp' question could stay
- entirely within the tokenizer.</p>
-
- <p>The next step, then, is the parser. It does not do a very
- thorough job because, firstly, it has to be fast, and secondly, it
- should not go to pieces when fed an incorrect program. So only
- superficial constructs are recognized, keywords that resemble each
- other in syntax, such as <code>while</code> and <code>if</code>,
- are treated in precisely the same way, as are <code>try</code> and
- <code>else</code> &#x2015; the parser doesn't mind if an
- <code>else</code> appears without an <code>if</code>. Stuff that
- binds variables, <code>var</code>, <code>function</code>, and
- <code>catch</code> to be precise, is treated with more care,
- because the parser wants to know about local variables.</p>
-
- <p>Inside the parser, three kinds of context are stored. Firstly, a set
- of known local variables, which is used to adjust the style of
- variable tokens. Every time the parser enters a function, a new set of
- variables is created. If there was already such a set (entering an
- inner function), a pointer to the old one is stored in the new one. At
- the end of the function, the current variable set is 'popped' off and
- the previous one is restored.</p>
-
- <p>The second kind of context is the lexical context, this keeps track of
- whether we are inside a statement, block, or list. Like the variable
- context, it also forms a stack of contexts, with each one containing a
- pointer to the previous ones so that they can be popped off again when
- they are finished. This information is used for indentation. Every
- time the parser encounters a newline token, it attaches the current
- lexical context and a 'copy' of itself (more about that later) to this
- token.</p>
-
- <p>The third context is a continuation context. This parser does not use
- straight continuation style, instead it uses a stack of actions that
- have to be performed. These actions are simple functions, a kind of
- minilanguage, they act on tokens, and decide what kind of new actions
- should be pushed onto the stack. Here are some examples:</p>
-
-<pre class="code"><span class="js-keyword">function</span> <span class="js-variable">expression</span>(<span class="js-variabledef">type</span>){
- <span class="js-keyword">if</span> (<span class="js-localvariable">type</span> in <span class="js-variable">atomicTypes</span>) <span class="js-variable">cont</span>(<span class="js-variable">maybeoperator</span>);
- <span class="js-keyword">else</span> <span class="js-keyword">if</span> (<span class="js-localvariable">type</span> == <span class="js-string">&quot;function&quot;</span>) <span class="js-variable">cont</span>(<span class="js-variable">functiondef</span>);
- <span class="js-keyword">else</span> <span class="js-keyword">if</span> (<span class="js-localvariable">type</span> == <span class="js-string">&quot;(&quot;</span>) <span class="js-variable">cont</span>(<span class="js-variable">pushlex</span>(<span class="js-string">&quot;list&quot;</span>), <span class="js-variable">expression</span>, <span class="js-variable">expect</span>(<span class="js-string">&quot;)&quot;</span>), <span class="js-variable">poplex</span>);
- <span class="js-keyword">else</span> <span class="js-keyword">if</span> (<span class="js-localvariable">type</span> == <span class="js-string">&quot;operator&quot;</span>) <span class="js-variable">cont</span>(<span class="js-variable">expression</span>);
- <span class="js-keyword">else</span> <span class="js-keyword">if</span> (<span class="js-localvariable">type</span> == <span class="js-string">&quot;[&quot;</span>) <span class="js-variable">cont</span>(<span class="js-variable">pushlex</span>(<span class="js-string">&quot;list&quot;</span>), <span class="js-variable">commasep</span>(<span class="js-variable">expression</span>), <span class="js-variable">expect</span>(<span class="js-string">&quot;]&quot;</span>), <span class="js-variable">poplex</span>);
- <span class="js-keyword">else</span> <span class="js-keyword">if</span> (<span class="js-localvariable">type</span> == <span class="js-string">&quot;{&quot;</span>) <span class="js-variable">cont</span>(<span class="js-variable">pushlex</span>(<span class="js-string">&quot;list&quot;</span>), <span class="js-variable">commasep</span>(<span class="js-variable">objprop</span>), <span class="js-variable">expect</span>(<span class="js-string">&quot;}&quot;</span>), <span class="js-variable">poplex</span>);
- <span class="js-keyword">else</span> <span class="js-keyword">if</span> (<span class="js-localvariable">type</span> == <span class="js-string">&quot;keyword c&quot;</span>) <span class="js-variable">cont</span>(<span class="js-variable">expression</span>);
-}
-
-<span class="js-keyword">function</span> <span class="js-variable">block</span>(<span class="js-variabledef">type</span>){
- <span class="js-keyword">if</span> (<span class="js-localvariable">type</span> == <span class="js-string">&quot;}&quot;</span>) <span class="js-variable">cont</span>();
- <span class="js-keyword">else</span> <span class="js-variable">pass</span>(<span class="js-variable">statement</span>, <span class="js-variable">block</span>);
-}</pre>
-
- <p>The function <code>cont</code> (for continue), will push the actions it is given
- onto the stack (in reverse order, so that the first one will be popped
- first). Actions such as <code>pushlex</code> and <code>poplex</code> merely adjust the
- lexical environment, while others, such as <code>expression</code> itself, do
- actual parsing. <code>pass</code>, as seen in <code>block</code>, is similar to <code>cont</code>, but
- it does not 'consume' the current token, so the next action will again
- see this same token. In <code>block</code>, this happens when the function
- determines that we are not at the end of the block yet, so it pushes
- the <code>statement</code> function which will interpret the current token as the
- start of a statement.</p>
-
- <p>These actions are called by a 'driver' function, which filters out the
- whitespace and comments, so that the parser actions do not have to
- think about those, and keeps track of some things like the indentation
- of the current line and the column at which the current token ends,
- which are stored in the lexical context and used for indentation.
- After calling an action, if the action called <code>cont</code>, this driver
- function will return the current token, if <code>pass</code> (or nothing) was
- called, it will immediately continue with the next action.</p>
-
- <p>This goes to show that it is viable to write a quite elaborate
- minilanguage in a macro-less language like JavaScript. I don't think
- it would be possible to do something like this without closures (or
- similarly powerful abstraction) though, I've certainly never seen
- anything like it in Java code.</p>
-
- <p>The way a 'copy' of the parser was produced shows a nice usage
- of closures. Like with the DOM transformer shown above, most of
- the local state of the parser is held in a closure produced by
- calling <code>parse(stream)</code>. The function
- <code>copy</code>, which is local to the parser function, produces
- a new closure, with copies of all the relevant variables:</p>
-
-<pre class="code"><span class="js-keyword">function</span> <span class="js-variable">copy</span>(){
- <span class="js-keyword">var</span> <span class="js-variabledef">_context</span> = <span class="js-variable">context</span>, <span class="js-variabledef">_lexical</span> = <span class="js-variable">lexical</span>, <span class="js-variabledef">_actions</span> = <span class="js-variable">copyArray</span>(<span class="js-variable">actions</span>);
-
- <span class="js-keyword">return</span> <span class="js-keyword">function</span>(<span class="js-variabledef">_tokens</span>){
- <span class="js-variable">context</span> = <span class="js-localvariable">_context</span>;
- <span class="js-variable">lexical</span> = <span class="js-localvariable">_lexical</span>;
- <span class="js-variable">actions</span> = <span class="js-variable">copyArray</span>(<span class="js-localvariable">_actions</span>);
- <span class="js-variable">tokens</span> = <span class="js-localvariable">_tokens</span>;
- <span class="js-keyword">return</span> <span class="js-variable">parser</span>;
- };
-}</pre>
-
- <p>Where <code>parser</code> is the object that contains the <code>next</code> (driver)
- function, and a reference to this <code>copy</code> function. When the function
- that <code>copy</code> produces is called with a token stream as argument, it
- updates the local variables in the parser closure, and returns the
- corresponding iterator object.</p>
-
- <p>Moving on, we get to the last stop in this chain of generators, the
- actual highlighter. You can view this one as taking two streams as
- input, on the one hand there is the stream of tokens from the parser,
- and on the other hand there is the DOM tree as left by the DOM
- transformer. If everything went correctly, these two should be
- synchronized. The highlighter can look at the current token, see if
- the <code>span</code> in the DOM tree corresponds to it (has the same text
- content, and the correct class), and if not it can chop up the DOM
- nodes to conform to the tokens.</p>
-
- <p>Every time the parser yields a newline token, the highligher
- encounters a <code>br</code> element in the DOM stream. It takes the copy of the
- parser and the lexical context from this token and attaches them to
- the DOM node. This way, a new highlighting process can be started from
- that node by re-starting the copy of the parser with a new token
- stream, which reads tokens from the DOM nodes starting at that <code>br</code>
- element, and the indentation code can use the lexical context
- information to determine the correct indentation at that point.</p>
-
- <h2>Selection woes</h2>
-
- <p>All the above can be done using the DOM interface that all major
- browsers have in common, and which is relatively free of weird bugs
- and abberrations. However, when the user is typing in new code, this
- must also be highlighted. For this to happen, the program must know
- where the cursor currently is, and because it mucks up the DOM tree,
- it has to restore this cursor position after doing the highlighting.</p>
-
- <p>Re-highlighting always happens per line, because the copy of the
- parser is stored only at the end of lines. Doing this every time the
- user presses a key is terribly slow and obnoxious, so what I did was
- keep a list of 'dirty' nodes, and as soon as the user didn't type
- anyting for 300 milliseconds the program starts re-highlighting these
- nodes. If it finds more than ten lines must be re-parsed, it does only
- ten and waits another 300 milliseconds before it continues, this way
- the browser never freezes up entirely.</p>
-
- <p>As mentioned earlier, Internet Explorer's selection model is not the
- most practical one. My attempts to build a wrapper that makes it look
- like the W3C model all stranded. In the end I came to the conclusion
- that I only needed two operations:</p>
-
- <ul>
- <li>Creating a selection 'snapshot' that can be restored after
- highlighting, in such a way that it still works if some of the nodes
- that were selected are replaced by other nodes with the same
- size but a different structure.</li>
- <li>Finding the top-level node around or before the cursor, to mark it
- dirty or to insert indentation whitespace at the start of that line.</li>
- </ul>
-
- <p>It turns out that the pixel-based selection model that Internet
- Explorer uses, which always seemed completely ludricrous to me, is
- perfect for the first case. Since the DOM transformation (generally)
- does not change the position of things, storing the pixel offsets of
- the selection makes it possible to restore that same selection, never
- mind what happened to the underlying DOM structure.</p>
-
- <p>[Later addition: Note that this, due to the very random design
- of the <a
- href="http://msdn2.microsoft.com/en-us/library/ms535872(VS.85).aspx#">TextRange
- interface</a>, only really works when the whole selection falls
- within the visible part of the document.]</p>
-
- <p>Doing the same with the W3C selection model is a lot harder. What I
- ended up with was this:</p>
-
- <ul>
- <li>Create an object pointing to the nodes at the start and end of the
- selection, and the offset within those nodes. This is basically the
- information that the <code>Range</code> object gives you.</li>
- <li>Make references from these nodes back to that object.</li>
- <li>When replacing (part of) a node with another one, check for such a
- reference, and when it is present, check whether this new node will
- get the selection. If it does, move the reference from the old to the
- new node, if it does not, adjust the offset in the selection object to
- reflect the fact that part of the old node has been replaced.</li>
- </ul>
-
- <p>Now in the second case (getting the top-level node at the
- cursor) the Internet Explorer cheat does not work. In the W3C
- model this is rather easy, you have to do some creative parent-
- and sibling-pointer following to arrive at the correct top-level
- node, but nothing weird. In Internet Explorer, all we have to go
- on is the <code>parentElement</code> method on a
- <code>TextRange</code>, which gives the first element that
- completely envelops the selection. If the cursor is inside a text
- node, this is good, that text node tells us where we are. If the
- cursor is between nodes, for example between two <code>br</code>
- nodes, you get to top-level node itself back, which is remarkably
- useless. In cases like this I stoop to a rather ugly hack (which
- fortunately turned out to be acceptably fast) &#x2015; I create a
- temporary empty <code>span</code> with an ID inside the selection,
- get a reference to this <code>span</code> by ID, take its
- <code>previousSibling</code>, and remove it again.</p>
-
- <p>Unfortunately, Opera's selection implementation is buggy, and it
- will give wildly incorrect <code>Range</code> objects when the cursor
- is between two nodes. This is a bit of a showstopper, and until I find
- a workaround for that or it gets fixed, the highlighter doesn't work
- properly in Opera.</p>
-
- <p>Also, when one presses enter in a <code>designMode</code>
- document in Firefox or Opera, a <code>br</code> tag is inserted.
- In Internet Explorer, pressing enter causes some maniacal gnome to
- come out and start wrapping all the content before and after the
- cursor in <code>p</code> tags. I suppose there is something to be
- said for that, in principle, though if you saw the tag soup of
- <code>font</code>s and nested paragraphs Internet Explorer
- generates you would soon enough forget all about principle.
- Anyway, getting unwanted <code>p</code> tags slowed the
- highlighter down terribly &#x2015; it had to overhaul the whole
- DOM tree to remove them again, every time the user pressed enter.
- Fortunately I could fix this by capturing the enter presses and
- manually inserting a <code>br</code> tag at the cursor.</p>
-
- <p>On the subject of Internet Explorer's tag soup, here is an interesting
- anecdote: One time, when testing the effect that modifying the content
- of a selection had, I inspected the DOM tree and found a <code>"/B"</code>
- element. This was not a closing tag, there are no closing tags in the
- DOM tree, just elements. The <code>nodeName</code> of this element was actually
- <code>"/B"</code>. That was when I gave up any notions of ever understanding the
- profound mystery that is Internet Explorer.</p>
-
- <h2>Closing thoughts</h2>
-
- <p>Well, I despaired at times, but I did end up with a working JavaScript
- editor. I did not keep track of the amount of time I wasted on this,
- but I would estimate it to be around fifty hours. Finding workarounds
- for browser bugs can be a terribly nonlinear process. I just spent
- half a day working on a weird glitch in Firefox that caused the cursor
- in the editable frame to be displayed 3/4 line too high when it was at
- the very end of the document. Then I found out that setting the
- style.display of the iframe to "block" fixed this (why not?). I'm
- amazed how often issues that seem hopeless do turn out to be
- avoidable, even if it takes hours of screwing around and some truly
- non-obvious ideas.</p>
-
- <p>For a lot of things, JavaScript + DOM elements are a surprisingly
- powerful platform. Simple interactive documents and forms can be
- written in browsers with very little effort, generally less than with
- most 'traditional' platforms (Java, Win32, things like WxWidgets).
- Libraries like Dojo (and a similar monster I once wrote myself) even
- make complex, composite widgets workable. However, when applications
- go sufficiently beyond the things that browsers were designed for, the
- available APIs do not give enough control, are nonstandard and buggy,
- and are often poorly designed. Because of this, writing such
- applications, when it is even possible, is <em>painful</em> process.</p>
-
- <p>And who likes pain? Sure, when finding that crazy workaround,
- subdueing the damn browser, and getting everything to work, there
- is a certain macho thrill. But one can't help wondering how much
- easier things like preventing the user from pasting pictures in
- his source code would be on another platform. Maybe something like
- Silverlight or whatever other new browser plugin gizmos people are
- pushing these days will become the way to solve things like this
- in the future. But, personally, I would prefer for those browser
- companies to put some real effort into things like cleaning up and
- standardising shady things like <code>designMode</code>, fixing
- their bugs, and getting serious about ECMAScript 4.</p>
-
- <p>Which is probably not realistically going to happen anytime soon.</p>
-
- <hr/>
-
- <p>Some interesting projects similar to this:</p>
-
- <ul>
- <li><a href="http://gpl.internetconnection.net/vi/">vi clone</a></li>
- <li><a href="http://robrohan.com/projects/9ne/">Emacs clone</a></li>
- <li><a href="http://codepress.sourceforge.net/">CodePress</a></li>
- <li><a href="http://www.codeide.com">CodeIDE</a></li>
- <li><a href="http://www.cdolivet.net/editarea">EditArea</a></li>
- </ul>
-
- <hr/>
-
- <p>If you have any remarks, criticism, or hints related to the
- above, drop me an e-mail at <a
- href="mailto:marijnh@gmail.com">marijnh@gmail.com</a>. If you say
- something generally interesting, I'll include your reaction here
- at the bottom of this page.</p>
-
- </body>
-</html>