source: branches/2.2/filemanager/tp/ckeditor/_source/plugins/htmldataprocessor/plugin.js @ 3019

Revision 3019, 10.9 KB checked in by amuller, 14 years ago (diff)

Ticket #1135 - Corrigindo CSS e adicionando filemanager

Line 
1/*
2Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
3For licensing, see LICENSE.html or http://ckeditor.com/license
4*/
5
6(function()
7{
8        // Regex to scan for   at the end of blocks, which are actually placeholders.
9        // Safari transforms the   to \xa0. (#4172)
10        var tailNbspRegex = /^[\t\r\n ]*(?: |\xa0)$/;
11
12        var protectedSourceMarker = '{cke_protected}';
13
14
15        // Return the last non-space child node of the block (#4344).
16        function lastNoneSpaceChild( block )
17        {
18                var lastIndex = block.children.length,
19                        last = block.children[ lastIndex - 1 ];
20                while(  last && last.type == CKEDITOR.NODE_TEXT && !CKEDITOR.tools.trim( last.value ) )
21                        last = block.children[ --lastIndex ];
22                return last;
23        }
24
25        function trimFillers( block, fromSource )
26        {
27                // If the current node is a block, and if we're converting from source or
28                // we're not in IE then search for and remove any tailing BR node.
29                //
30                // Also, any   at the end of blocks are fillers, remove them as well.
31                // (#2886)
32                var children = block.children, lastChild = lastNoneSpaceChild( block );
33                if ( lastChild )
34                {
35                        if ( ( fromSource || !CKEDITOR.env.ie ) && lastChild.type == CKEDITOR.NODE_ELEMENT && lastChild.name == 'br' )
36                                children.pop();
37                        if ( lastChild.type == CKEDITOR.NODE_TEXT && tailNbspRegex.test( lastChild.value ) )
38                                children.pop();
39                }
40        }
41
42        function blockNeedsExtension( block )
43        {
44                var lastChild = lastNoneSpaceChild( block );
45                return !lastChild || lastChild.type == CKEDITOR.NODE_ELEMENT && lastChild.name == 'br';
46        }
47
48        function extendBlockForDisplay( block )
49        {
50                trimFillers( block, true );
51
52                if ( blockNeedsExtension( block ) )
53                {
54                        if ( CKEDITOR.env.ie )
55                                block.add( new CKEDITOR.htmlParser.text( '\xa0' ) );
56                        else
57                                block.add( new CKEDITOR.htmlParser.element( 'br', {} ) );
58                }
59        }
60
61        function extendBlockForOutput( block )
62        {
63                trimFillers( block );
64
65                if ( blockNeedsExtension( block ) )
66                        block.add( new CKEDITOR.htmlParser.text( '\xa0' ) );
67        }
68
69        var dtd = CKEDITOR.dtd;
70
71        // Find out the list of block-like tags that can contain <br>.
72        var blockLikeTags = CKEDITOR.tools.extend( {}, dtd.$block, dtd.$listItem, dtd.$tableContent );
73        for ( var i in blockLikeTags )
74        {
75                if ( ! ( 'br' in dtd[i] ) )
76                        delete blockLikeTags[i];
77        }
78        // We just avoid filler in <pre> right now.
79        // TODO: Support filler for <pre>, line break is also occupy line height.
80        delete blockLikeTags.pre;
81        var defaultDataFilterRules =
82        {
83                attributeNames :
84                [
85                        // Event attributes (onXYZ) must not be directly set. They can become
86                        // active in the editing area (IE|WebKit).
87                        [ ( /^on/ ), '_cke_pa_on' ]
88                ]
89        };
90
91        var defaultDataBlockFilterRules = { elements : {} };
92
93        for ( i in blockLikeTags )
94                defaultDataBlockFilterRules.elements[ i ] = extendBlockForDisplay;
95
96        var defaultHtmlFilterRules =
97                {
98                        elementNames :
99                        [
100                                // Remove the "cke:" namespace prefix.
101                                [ ( /^cke:/ ), '' ],
102
103                                // Ignore <?xml:namespace> tags.
104                                [ ( /^\?xml:namespace$/ ), '' ]
105                        ],
106
107                        attributeNames :
108                        [
109                                // Attributes saved for changes and protected attributes.
110                                [ ( /^_cke_(saved|pa)_/ ), '' ],
111
112                                // All "_cke" attributes are to be ignored.
113                                [ ( /^_cke.*/ ), '' ]
114                        ],
115
116                        elements :
117                        {
118                                $ : function( element )
119                                {
120                                        // Remove duplicated attributes - #3789.
121                                        var attribs = element.attributes;
122
123                                        if ( attribs )
124                                        {
125                                                var attributeNames = [ 'name', 'href', 'src' ],
126                                                        savedAttributeName;
127                                                for ( var i = 0 ; i < attributeNames.length ; i++ )
128                                                {
129                                                        savedAttributeName = '_cke_saved_' + attributeNames[ i ];
130                                                        savedAttributeName in attribs && ( delete attribs[ attributeNames[ i ] ] );
131                                                }
132                                        }
133                                },
134
135                                embed : function( element )
136                                {
137                                        var parent = element.parent;
138
139                                        // If the <embed> is child of a <object>, copy the width
140                                        // and height attributes from it.
141                                        if ( parent && parent.name == 'object' )
142                                        {
143                                                var parentWidth = parent.attributes.width,
144                                                        parentHeight = parent.attributes.height;
145                                                parentWidth && ( element.attributes.width = parentWidth );
146                                                parentHeight && ( element.attributes.height = parentHeight );
147                                        }
148                                },
149                                // Restore param elements into self-closing.
150                                param : function( param )
151                                {
152                                        param.children = [];
153                                        param.isEmpty = true;
154                                        return param;
155                                },
156
157                                // Remove empty link but not empty anchor.(#3829)
158                                a : function( element )
159                                {
160                                        if ( !( element.children.length ||
161                                                        element.attributes.name ||
162                                                        element.attributes._cke_saved_name ) )
163                                        {
164                                                return false;
165                                        }
166                                }
167                        },
168
169                        attributes :
170                        {
171                                'class' : function( value, element )
172                                {
173                                        // Remove all class names starting with "cke_".
174                                        return CKEDITOR.tools.ltrim( value.replace( /(?:^|\s+)cke_[^\s]*/g, '' ) ) || false;
175                                }
176                        },
177
178                        comment : function( contents )
179                        {
180                                if ( contents.substr( 0, protectedSourceMarker.length ) == protectedSourceMarker )
181                                        return new CKEDITOR.htmlParser.cdata( decodeURIComponent( contents.substr( protectedSourceMarker.length ) ) );
182
183                                return contents;
184                        }
185                };
186
187        var defaultHtmlBlockFilterRules = { elements : {} };
188
189        for ( i in blockLikeTags )
190                defaultHtmlBlockFilterRules.elements[ i ] = extendBlockForOutput;
191
192        if ( CKEDITOR.env.ie )
193        {
194                // IE outputs style attribute in capital letters. We should convert
195                // them back to lower case.
196                defaultHtmlFilterRules.attributes.style = function( value, element )
197                {
198                        return value.toLowerCase();
199                };
200        }
201
202        var protectAttributeRegex = /<(?:a|area|img|input).*?\s((?:href|src|name)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+)))/gi;
203
204        function protectAttributes( html )
205        {
206                return html.replace( protectAttributeRegex, '$& _cke_saved_$1' );
207        }
208
209        var protectStyleTagsRegex = /<(style)(?=[ >])[^>]*>[^<]*<\/\1>/gi;
210        var encodedTagsRegex = /<cke:encoded>([^<]*)<\/cke:encoded>/gi;
211        var protectElementNamesRegex = /(<\/?)((?:object|embed|param).*?>)/gi;
212        var protectSelfClosingRegex = /<cke:param(.*?)\/>/gi;
213
214        function protectStyleTagsMatch( match )
215        {
216                return '<cke:encoded>' + encodeURIComponent( match ) + '</cke:encoded>';
217        }
218
219        function protectStyleTags( html )
220        {
221                return html.replace( protectStyleTagsRegex, protectStyleTagsMatch );
222        }
223        function protectElementsNames( html )
224        {
225                return html.replace( protectElementNamesRegex, '$1cke:$2');
226        }
227        function protectSelfClosingElements( html )
228        {
229                return html.replace( protectSelfClosingRegex, '<cke:param$1></cke:param>' );
230        }
231
232        function unprotectEncodedTagsMatch( match, encoded )
233        {
234                return decodeURIComponent( encoded );
235        }
236
237        function unprotectEncodedTags( html )
238        {
239                return html.replace( encodedTagsRegex, unprotectEncodedTagsMatch );
240        }
241
242        function protectSource( data, protectRegexes )
243        {
244                var protectedHtml = [],
245                        tempRegex = /<\!--\{cke_temp\}(\d*?)-->/g;
246                var regexes =
247                        [
248                                // First of any other protection, we must protect all comments
249                                // to avoid loosing them (of course, IE related).
250                                (/<!--[\s\S]*?-->/g),
251
252                                // Script tags will also be forced to be protected, otherwise
253                                // IE will execute them.
254                                /<script[\s\S]*?<\/script>/gi,
255
256                                // <noscript> tags (get lost in IE and messed up in FF).
257                                /<noscript[\s\S]*?<\/noscript>/gi
258                        ]
259                        .concat( protectRegexes );
260
261                for ( var i = 0 ; i < regexes.length ; i++ )
262                {
263                        data = data.replace( regexes[i], function( match )
264                                {
265                                        match = match.replace( tempRegex,               // There could be protected source inside another one. (#3869).
266                                                function( $, id )
267                                                {
268                                                        return protectedHtml[ id ];
269                                                }
270                                        );
271                                        return  '<!--{cke_temp}' + ( protectedHtml.push( match ) - 1 ) + '-->';
272                                });
273                }
274                data = data.replace( tempRegex, function( $, id )
275                        {
276                                return '<!--' + protectedSourceMarker +
277                                                encodeURIComponent( protectedHtml[ id ] ).replace( /--/g, '%2D%2D' ) +
278                                                '-->';
279                        }
280                );
281                return data;
282        }
283
284        CKEDITOR.plugins.add( 'htmldataprocessor',
285        {
286                requires : [ 'htmlwriter' ],
287
288                init : function( editor )
289                {
290                        var dataProcessor = editor.dataProcessor = new CKEDITOR.htmlDataProcessor( editor );
291
292                        dataProcessor.writer.forceSimpleAmpersand = editor.config.forceSimpleAmpersand;
293
294                        dataProcessor.dataFilter.addRules( defaultDataFilterRules );
295                        dataProcessor.dataFilter.addRules( defaultDataBlockFilterRules );
296                        dataProcessor.htmlFilter.addRules( defaultHtmlFilterRules );
297                        dataProcessor.htmlFilter.addRules( defaultHtmlBlockFilterRules );
298                }
299        });
300
301        CKEDITOR.htmlDataProcessor = function( editor )
302        {
303                this.editor = editor;
304
305                this.writer = new CKEDITOR.htmlWriter();
306                this.dataFilter = new CKEDITOR.htmlParser.filter();
307                this.htmlFilter = new CKEDITOR.htmlParser.filter();
308        };
309
310        CKEDITOR.htmlDataProcessor.prototype =
311        {
312                toHtml : function( data, fixForBody )
313                {
314                        // The source data is already HTML, but we need to clean
315                        // it up and apply the filter.
316
317                        data = protectSource( data, this.editor.config.protectedSource );
318
319                        // Before anything, we must protect the URL attributes as the
320                        // browser may changing them when setting the innerHTML later in
321                        // the code.
322                        data = protectAttributes( data );
323
324                        // IE remvoes style tags from innerHTML. (#3710).
325                        if ( CKEDITOR.env.ie )
326                                data = protectStyleTags( data );
327
328                        // Certain elements has problem to go through DOM operation, protect
329                        // them by prefixing 'cke' namespace.(#3591)
330                        data = protectElementsNames( data );
331
332                        // All none-IE browsers ignore self-closed custom elements,
333                        // protecting them into open-close.(#3591)
334                        data = protectSelfClosingElements( data );
335
336                        // Call the browser to help us fixing a possibly invalid HTML
337                        // structure.
338                        var div = document.createElement( 'div' );
339                        // Add fake character to workaround IE comments bug. (#3801)
340                        div.innerHTML = 'a' + data;
341                        data = div.innerHTML.substr( 1 );
342
343                        if ( CKEDITOR.env.ie )
344                                data = unprotectEncodedTags( data );
345
346                        // Now use our parser to make further fixes to the structure, as
347                        // well as apply the filter.
348                        var fragment = CKEDITOR.htmlParser.fragment.fromHtml( data, fixForBody ),
349                                writer = new CKEDITOR.htmlParser.basicWriter();
350
351                        fragment.writeHtml( writer, this.dataFilter );
352
353                        return writer.getHtml( true );
354                },
355
356                toDataFormat : function( html, fixForBody )
357                {
358                        var writer = this.writer,
359                                fragment = CKEDITOR.htmlParser.fragment.fromHtml( html, fixForBody );
360
361                        writer.reset();
362
363                        fragment.writeHtml( writer, this.htmlFilter );
364
365                        return writer.getHtml( true );
366                }
367        };
368})();
369
370/**
371 * Whether to force using "&" instead of "&amp;amp;" in elements attributes
372 * values. It's not recommended to change this setting for compliance with the
373 * W3C XHTML 1.0 standards
374 * (<a href="http://www.w3.org/TR/xhtml1/#C_12">C.12, XHTML 1.0</a>).
375 * @type Boolean
376 * @default false
377 * @example
378 * config.forceSimpleAmpersand = false;
379 */
380CKEDITOR.config.forceSimpleAmpersand = false;
Note: See TracBrowser for help on using the repository browser.