v1.0
只读模式 group, 分享 评论更多问题 博客标签总是存在一个
This commit is contained in:
87
public/tinymce/classes/html/SaxParser.js
Normal file → Executable file
87
public/tinymce/classes/html/SaxParser.js
Normal file → Executable file
@ -8,6 +8,8 @@
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
/*eslint max-depth:[2, 9] */
|
||||
|
||||
/**
|
||||
* This class parses HTML code using pure JavaScript and executes various events for each item it finds. It will
|
||||
* always execute the events in the right order for tag soup code like <b><p></b></p>. It will also remove elements
|
||||
@ -55,6 +57,45 @@ define("tinymce/html/SaxParser", [
|
||||
], function(Schema, Entities, Tools) {
|
||||
var each = Tools.each;
|
||||
|
||||
/**
|
||||
* Returns the index of the end tag for a specific start tag. This can be
|
||||
* used to skip all children of a parent element from being processed.
|
||||
*
|
||||
* @private
|
||||
* @method findEndTag
|
||||
* @param {tinymce.html.Schema} schema Schema instance to use to match short ended elements.
|
||||
* @param {String} html HTML string to find the end tag in.
|
||||
* @param {Number} startIndex Indext to start searching at should be after the start tag.
|
||||
* @return {Number} Index of the end tag.
|
||||
*/
|
||||
function findEndTag(schema, html, startIndex) {
|
||||
var count = 1, index, matches, tokenRegExp, shortEndedElements;
|
||||
|
||||
shortEndedElements = schema.getShortEndedElements();
|
||||
tokenRegExp = /<([!?\/])?([A-Za-z0-9\-_\:\.]+)((?:\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\/|\s+)>/g;
|
||||
tokenRegExp.lastIndex = index = startIndex;
|
||||
|
||||
while ((matches = tokenRegExp.exec(html))) {
|
||||
index = tokenRegExp.lastIndex;
|
||||
|
||||
if (matches[1] === '/') { // End element
|
||||
count--;
|
||||
} else if (!matches[1]) { // Start element
|
||||
if (matches[2] in shortEndedElements) {
|
||||
continue;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new SaxParser instance.
|
||||
*
|
||||
@ -63,8 +104,10 @@ define("tinymce/html/SaxParser", [
|
||||
* @param {Object} settings Name/value collection of settings. comment, cdata, text, start and end are callbacks.
|
||||
* @param {tinymce.html.Schema} schema HTML Schema class to use when parsing.
|
||||
*/
|
||||
return function(settings, schema) {
|
||||
var self = this, noop = function() {};
|
||||
function SaxParser(settings, schema) {
|
||||
var self = this;
|
||||
|
||||
function noop() {}
|
||||
|
||||
settings = settings || {};
|
||||
self.schema = schema = schema || new Schema();
|
||||
@ -94,7 +137,8 @@ define("tinymce/html/SaxParser", [
|
||||
var validate, elementRule, isValidElement, attr, attribsValue, validAttributesMap, validAttributePatterns;
|
||||
var attributesRequired, attributesDefault, attributesForced;
|
||||
var anyAttributesRequired, selfClosing, tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0;
|
||||
var decode = Entities.decode, fixSelfClosing, filteredAttrs = Tools.makeMap('src,href');
|
||||
var decode = Entities.decode, fixSelfClosing, filteredUrlAttrs = Tools.makeMap('src,href,data,background,formaction,poster');
|
||||
var scriptUriRegExp = /((java|vb)script|mhtml):/i, dataUriRegExp = /^data:/i;
|
||||
|
||||
function processEndTag(name) {
|
||||
var pos, i;
|
||||
@ -160,8 +204,23 @@ define("tinymce/html/SaxParser", [
|
||||
}
|
||||
}
|
||||
|
||||
if (filteredAttrs[name] && !settings.allow_script_urls) {
|
||||
if (/(java|vb)script:/i.test(decodeURIComponent(value.replace(trimRegExp, '')))) {
|
||||
// Block any javascript: urls or non image data uris
|
||||
if (filteredUrlAttrs[name] && !settings.allow_script_urls) {
|
||||
var uri = value.replace(trimRegExp, '');
|
||||
|
||||
try {
|
||||
// Might throw malformed URI sequence
|
||||
uri = decodeURIComponent(uri);
|
||||
} catch (ex) {
|
||||
// Fallback to non UTF-8 decoder
|
||||
uri = unescape(uri);
|
||||
}
|
||||
|
||||
if (scriptUriRegExp.test(uri)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!settings.allow_html_data_urls && dataUriRegExp.test(uri) && !/^data:image\//i.test(uri)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -181,7 +240,7 @@ define("tinymce/html/SaxParser", [
|
||||
'(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE
|
||||
'(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI
|
||||
'(?:\\/([^>]+)>)|' + // End element
|
||||
'(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element
|
||||
'(?:([A-Za-z0-9\\-_\\:\\.]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element
|
||||
')', 'g');
|
||||
|
||||
attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;
|
||||
@ -318,7 +377,13 @@ define("tinymce/html/SaxParser", [
|
||||
}
|
||||
|
||||
// Invalidate element if it's marked as bogus
|
||||
if (attrList.map['data-mce-bogus']) {
|
||||
if ((attr = attrList.map['data-mce-bogus'])) {
|
||||
if (attr === 'all') {
|
||||
index = findEndTag(schema, html, tokenRegExp.lastIndex);
|
||||
tokenRegExp.lastIndex = index;
|
||||
continue;
|
||||
}
|
||||
|
||||
isValidElement = false;
|
||||
}
|
||||
}
|
||||
@ -401,5 +466,9 @@ define("tinymce/html/SaxParser", [
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
SaxParser.findEndTag = findEndTag;
|
||||
|
||||
return SaxParser;
|
||||
});
|
Reference in New Issue
Block a user