debian-django-ckeditor/ckeditor/static/ckeditor/ckeditor/_source/core/htmlparser/filter.js

289 lines
6.4 KiB
JavaScript

/*
Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/
(function()
{
CKEDITOR.htmlParser.filter = CKEDITOR.tools.createClass(
{
$ : function( rules )
{
this._ =
{
elementNames : [],
attributeNames : [],
elements : { $length : 0 },
attributes : { $length : 0 }
};
if ( rules )
this.addRules( rules, 10 );
},
proto :
{
addRules : function( rules, priority )
{
if ( typeof priority != 'number' )
priority = 10;
// Add the elementNames.
addItemsToList( this._.elementNames, rules.elementNames, priority );
// Add the attributeNames.
addItemsToList( this._.attributeNames, rules.attributeNames, priority );
// Add the elements.
addNamedItems( this._.elements, rules.elements, priority );
// Add the attributes.
addNamedItems( this._.attributes, rules.attributes, priority );
// Add the text.
this._.text = transformNamedItem( this._.text, rules.text, priority ) || this._.text;
// Add the comment.
this._.comment = transformNamedItem( this._.comment, rules.comment, priority ) || this._.comment;
// Add root fragment.
this._.root = transformNamedItem( this._.root, rules.root, priority ) || this._.root;
},
onElementName : function( name )
{
return filterName( name, this._.elementNames );
},
onAttributeName : function( name )
{
return filterName( name, this._.attributeNames );
},
onText : function( text )
{
var textFilter = this._.text;
return textFilter ? textFilter.filter( text ) : text;
},
onComment : function( commentText, comment )
{
var textFilter = this._.comment;
return textFilter ? textFilter.filter( commentText, comment ) : commentText;
},
onFragment : function( element )
{
var rootFilter = this._.root;
return rootFilter ? rootFilter.filter( element ) : element;
},
onElement : function( element )
{
// We must apply filters set to the specific element name as
// well as those set to the generic $ name. So, add both to an
// array and process them in a small loop.
var filters = [ this._.elements[ '^' ], this._.elements[ element.name ], this._.elements.$ ],
filter, ret;
for ( var i = 0 ; i < 3 ; i++ )
{
filter = filters[ i ];
if ( filter )
{
ret = filter.filter( element, this );
if ( ret === false )
return null;
if ( ret && ret != element )
return this.onNode( ret );
// The non-root element has been dismissed by one of the filters.
if ( element.parent && !element.name )
break;
}
}
return element;
},
onNode : function( node )
{
var type = node.type;
return type == CKEDITOR.NODE_ELEMENT ? this.onElement( node ) :
type == CKEDITOR.NODE_TEXT ? new CKEDITOR.htmlParser.text( this.onText( node.value ) ) :
type == CKEDITOR.NODE_COMMENT ? new CKEDITOR.htmlParser.comment( this.onComment( node.value ) ):
null;
},
onAttribute : function( element, name, value )
{
var filter = this._.attributes[ name ];
if ( filter )
{
var ret = filter.filter( value, element, this );
if ( ret === false )
return false;
if ( typeof ret != 'undefined' )
return ret;
}
return value;
}
}
});
function filterName( name, filters )
{
for ( var i = 0 ; name && i < filters.length ; i++ )
{
var filter = filters[ i ];
name = name.replace( filter[ 0 ], filter[ 1 ] );
}
return name;
}
function addItemsToList( list, items, priority )
{
if ( typeof items == 'function' )
items = [ items ];
var i, j,
listLength = list.length,
itemsLength = items && items.length;
if ( itemsLength )
{
// Find the index to insert the items at.
for ( i = 0 ; i < listLength && list[ i ].pri < priority ; i++ )
{ /*jsl:pass*/ }
// Add all new items to the list at the specific index.
for ( j = itemsLength - 1 ; j >= 0 ; j-- )
{
var item = items[ j ];
if ( item )
{
item.pri = priority;
list.splice( i, 0, item );
}
}
}
}
function addNamedItems( hashTable, items, priority )
{
if ( items )
{
for ( var name in items )
{
var current = hashTable[ name ];
hashTable[ name ] =
transformNamedItem(
current,
items[ name ],
priority );
if ( !current )
hashTable.$length++;
}
}
}
function transformNamedItem( current, item, priority )
{
if ( item )
{
item.pri = priority;
if ( current )
{
// If the current item is not an Array, transform it.
if ( !current.splice )
{
if ( current.pri > priority )
current = [ item, current ];
else
current = [ current, item ];
current.filter = callItems;
}
else
addItemsToList( current, item, priority );
return current;
}
else
{
item.filter = item;
return item;
}
}
}
// Invoke filters sequentially on the array, break the iteration
// when it doesn't make sense to continue anymore.
function callItems( currentEntry )
{
var isNode = currentEntry.type
|| currentEntry instanceof CKEDITOR.htmlParser.fragment;
for ( var i = 0 ; i < this.length ; i++ )
{
// Backup the node info before filtering.
if ( isNode )
{
var orgType = currentEntry.type,
orgName = currentEntry.name;
}
var item = this[ i ],
ret = item.apply( window, arguments );
if ( ret === false )
return ret;
// We're filtering node (element/fragment).
if ( isNode )
{
// No further filtering if it's not anymore
// fitable for the subsequent filters.
if ( ret && ( ret.name != orgName
|| ret.type != orgType ) )
{
return ret;
}
}
// Filtering value (nodeName/textValue/attrValue).
else
{
// No further filtering if it's not
// any more values.
if ( typeof ret != 'string' )
return ret;
}
ret != undefined && ( currentEntry = ret );
}
return currentEntry;
}
})();
// "entities" plugin
/*
{
text : function( text )
{
// TODO : Process entities.
return text.toUpperCase();
}
};
*/