JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.1
[ckeditor.git] / _source / core / htmlparser / filter.js
1 /*\r
2 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
3 For licensing, see LICENSE.html or http://ckeditor.com/license\r
4 */\r
5 \r
6 (function()\r
7 {\r
8         CKEDITOR.htmlParser.filter = CKEDITOR.tools.createClass(\r
9         {\r
10                 $ : function( rules )\r
11                 {\r
12                         this._ =\r
13                         {\r
14                                 elementNames : [],\r
15                                 attributeNames : [],\r
16                                 elements : { $length : 0 },\r
17                                 attributes : { $length : 0 }\r
18                         };\r
19 \r
20                         if ( rules )\r
21                                 this.addRules( rules, 10 );\r
22                 },\r
23 \r
24                 proto :\r
25                 {\r
26                         addRules : function( rules, priority )\r
27                         {\r
28                                 if ( typeof priority != 'number' )\r
29                                         priority = 10;\r
30 \r
31                                 // Add the elementNames.\r
32                                 addItemsToList( this._.elementNames, rules.elementNames, priority );\r
33 \r
34                                 // Add the attributeNames.\r
35                                 addItemsToList( this._.attributeNames, rules.attributeNames, priority );\r
36 \r
37                                 // Add the elements.\r
38                                 addNamedItems( this._.elements, rules.elements, priority );\r
39 \r
40                                 // Add the attributes.\r
41                                 addNamedItems( this._.attributes, rules.attributes, priority );\r
42 \r
43                                 // Add the text.\r
44                                 this._.text = transformNamedItem( this._.text, rules.text, priority ) || this._.text;\r
45 \r
46                                 // Add the comment.\r
47                                 this._.comment = transformNamedItem( this._.comment, rules.comment, priority ) || this._.comment;\r
48 \r
49                                 // Add root fragment.\r
50                                 this._.root = transformNamedItem( this._.root, rules.root, priority ) || this._.root;\r
51                         },\r
52 \r
53                         onElementName : function( name )\r
54                         {\r
55                                 return filterName( name, this._.elementNames );\r
56                         },\r
57 \r
58                         onAttributeName : function( name )\r
59                         {\r
60                                 return filterName( name, this._.attributeNames );\r
61                         },\r
62 \r
63                         onText : function( text )\r
64                         {\r
65                                 var textFilter = this._.text;\r
66                                 return textFilter ? textFilter.filter( text ) : text;\r
67                         },\r
68 \r
69                         onComment : function( commentText, comment )\r
70                         {\r
71                                 var textFilter = this._.comment;\r
72                                 return textFilter ? textFilter.filter( commentText, comment ) : commentText;\r
73                         },\r
74 \r
75                         onFragment : function( element )\r
76                         {\r
77                                 var rootFilter = this._.root;\r
78                                 return rootFilter ? rootFilter.filter( element ) : element;\r
79                         },\r
80 \r
81                         onElement : function( element )\r
82                         {\r
83                                 // We must apply filters set to the specific element name as\r
84                                 // well as those set to the generic $ name. So, add both to an\r
85                                 // array and process them in a small loop.\r
86                                 var filters = [ this._.elements[ '^' ], this._.elements[ element.name ], this._.elements.$ ],\r
87                                         filter, ret;\r
88 \r
89                                 for ( var i = 0 ; i < 3 ; i++ )\r
90                                 {\r
91                                         filter = filters[ i ];\r
92                                         if ( filter )\r
93                                         {\r
94                                                 ret = filter.filter( element, this );\r
95 \r
96                                                 if ( ret === false )\r
97                                                         return null;\r
98 \r
99                                                 if ( ret && ret != element )\r
100                                                         return this.onNode( ret );\r
101 \r
102                                                 // The non-root element has been dismissed by one of the filters.\r
103                                                 if ( element.parent && !element.name )\r
104                                                         break;\r
105                                         }\r
106                                 }\r
107 \r
108                                 return element;\r
109                         },\r
110 \r
111                         onNode : function( node )\r
112                         {\r
113                                 var type = node.type;\r
114 \r
115                                 return type == CKEDITOR.NODE_ELEMENT ? this.onElement( node ) :\r
116                                         type == CKEDITOR.NODE_TEXT ? new CKEDITOR.htmlParser.text( this.onText( node.value ) ) :\r
117                                         type == CKEDITOR.NODE_COMMENT ? new CKEDITOR.htmlParser.comment( this.onComment( node.value ) ):\r
118                                         null;\r
119                         },\r
120 \r
121                         onAttribute : function( element, name, value )\r
122                         {\r
123                                 var filter = this._.attributes[ name ];\r
124 \r
125                                 if ( filter )\r
126                                 {\r
127                                         var ret = filter.filter( value, element, this );\r
128 \r
129                                         if ( ret === false )\r
130                                                 return false;\r
131 \r
132                                         if ( typeof ret != 'undefined' )\r
133                                                 return ret;\r
134                                 }\r
135 \r
136                                 return value;\r
137                         }\r
138                 }\r
139         });\r
140 \r
141         function filterName( name, filters )\r
142         {\r
143                 for ( var i = 0 ; name && i < filters.length ; i++ )\r
144                 {\r
145                         var filter = filters[ i ];\r
146                         name = name.replace( filter[ 0 ], filter[ 1 ] );\r
147                 }\r
148                 return name;\r
149         }\r
150 \r
151         function addItemsToList( list, items, priority )\r
152         {\r
153                 if( typeof items == 'function' )\r
154                         items = [ items ];\r
155 \r
156                 var i, j,\r
157                         listLength = list.length,\r
158                         itemsLength = items && items.length;\r
159 \r
160                 if ( itemsLength )\r
161                 {\r
162                         // Find the index to insert the items at.\r
163                         for ( i = 0 ; i < listLength && list[ i ].pri < priority ; i++ )\r
164                         { /*jsl:pass*/ }\r
165 \r
166                         // Add all new items to the list at the specific index.\r
167                         for ( j = itemsLength - 1 ; j >= 0 ; j-- )\r
168                         {\r
169                                 var item = items[ j ];\r
170                                 if ( item )\r
171                                 {\r
172                                         item.pri = priority;\r
173                                         list.splice( i, 0, item );\r
174                                 }\r
175                         }\r
176                 }\r
177         }\r
178 \r
179         function addNamedItems( hashTable, items, priority )\r
180         {\r
181                 if ( items )\r
182                 {\r
183                         for ( var name in items )\r
184                         {\r
185                                 var current = hashTable[ name ];\r
186 \r
187                                 hashTable[ name ] =\r
188                                         transformNamedItem(\r
189                                                 current,\r
190                                                 items[ name ],\r
191                                                 priority );\r
192 \r
193                                 if ( !current )\r
194                                         hashTable.$length++;\r
195                         }\r
196                 }\r
197         }\r
198 \r
199         function transformNamedItem( current, item, priority )\r
200         {\r
201                 if ( item )\r
202                 {\r
203                         item.pri = priority;\r
204 \r
205                         if ( current )\r
206                         {\r
207                                 // If the current item is not an Array, transform it.\r
208                                 if ( !current.splice )\r
209                                 {\r
210                                         if ( current.pri > priority )\r
211                                                 current = [ item, current ];\r
212                                         else\r
213                                                 current = [ current, item ];\r
214 \r
215                                         current.filter = callItems;\r
216                                 }\r
217                                 else\r
218                                         addItemsToList( current, item, priority );\r
219 \r
220                                 return current;\r
221                         }\r
222                         else\r
223                         {\r
224                                 item.filter = item;\r
225                                 return item;\r
226                         }\r
227                 }\r
228         }\r
229 \r
230         function callItems( currentEntry )\r
231         {\r
232                 var isObject = ( typeof currentEntry == 'object' );\r
233 \r
234                 for ( var i = 0 ; i < this.length ; i++ )\r
235                 {\r
236                         var item = this[ i ],\r
237                                 ret = item.apply( window, arguments );\r
238 \r
239                         if ( typeof ret != 'undefined' )\r
240                         {\r
241                                 if ( ret === false )\r
242                                         return false;\r
243 \r
244                                 if ( isObject && ret != currentEntry )\r
245                                         return ret;\r
246                         }\r
247                 }\r
248 \r
249                 return null;\r
250         }\r
251 })();\r
252 \r
253 // "entities" plugin\r
254 /*\r
255 {\r
256         text : function( text )\r
257         {\r
258                 // TODO : Process entities.\r
259                 return text.toUpperCase();\r
260         }\r
261 };\r
262 */\r