additional_plugins/serendipity_event_template_editor/codemirror/parsephphtmlmixed.js
2011-12-13 12:29:05 +01:00

97 lines
3.2 KiB
JavaScript

/*
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, phpParserState = null;
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();
if (parser == PHPParser && phpParserState)
localParser = phpParserState(stream);
else
localParser = parser.make(stream, baseIndent + indentUnit);
return function() {
if (stream.lookAhead(tag, false, false, true)) {
if (parser == PHPParser) phpParserState = localParser.copy();
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, _php = phpParserState;
return function(_stream) {
stream = _stream;
htmlParser = _html(_stream);
localParser = _local && _local(_stream);
phpParserState = _php;
iter.next = _next;
inTag = _inTag;
return iter;
};
}
return iter;
}
return {make: parseMixed, electricChars: "{}/:"};
})();