initial commit
[namibia] / public / scripts / ckeditor / _source / plugins / htmlwriter / plugin.js
1 /*
2 Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
3 For licensing, see LICENSE.html or http://ckeditor.com/license
4 */
5
6 CKEDITOR.plugins.add( 'htmlwriter' );
7
8 /**
9  * Class used to write HTML data.
10  * @constructor
11  * @example
12  * var writer = new CKEDITOR.htmlWriter();
13  * writer.openTag( 'p' );
14  * writer.attribute( 'class', 'MyClass' );
15  * writer.openTagClose( 'p' );
16  * writer.text( 'Hello' );
17  * writer.closeTag( 'p' );
18  * alert( writer.getHtml() );  "<p class="MyClass">Hello</p>"
19  */
20 CKEDITOR.htmlWriter = CKEDITOR.tools.createClass(
21 {
22         base : CKEDITOR.htmlParser.basicWriter,
23
24         $ : function()
25         {
26                 // Call the base contructor.
27                 this.base();
28
29                 /**
30                  * The characters to be used for each identation step.
31                  * @type String
32                  * @default "\t" (tab)
33                  * @example
34                  * // Use two spaces for indentation.
35                  * editorInstance.dataProcessor.writer.indentationChars = '  ';
36                  */
37                 this.indentationChars = '\t';
38
39                 /**
40                  * The characters to be used to close "self-closing" elements, like "br" or
41                  * "img".
42                  * @type String
43                  * @default " />"
44                  * @example
45                  * // Use HTML4 notation for self-closing elements.
46                  * editorInstance.dataProcessor.writer.selfClosingEnd = '>';
47                  */
48                 this.selfClosingEnd = ' />';
49
50                 /**
51                  * The characters to be used for line breaks.
52                  * @type String
53                  * @default "\n" (LF)
54                  * @example
55                  * // Use CRLF for line breaks.
56                  * editorInstance.dataProcessor.writer.lineBreakChars = '\r\n';
57                  */
58                 this.lineBreakChars = '\n';
59
60                 this.forceSimpleAmpersand = 0;
61
62                 this.sortAttributes = 1;
63
64                 this._.indent = 0;
65                 this._.indentation = '';
66                 // Indicate preformatted block context status. (#5789)
67                 this._.inPre = 0;
68                 this._.rules = {};
69
70                 var dtd = CKEDITOR.dtd;
71
72                 for ( var e in CKEDITOR.tools.extend( {}, dtd.$nonBodyContent, dtd.$block, dtd.$listItem, dtd.$tableContent ) )
73                 {
74                         this.setRules( e,
75                                 {
76                                         indent : 1,
77                                         breakBeforeOpen : 1,
78                                         breakAfterOpen : 1,
79                                         breakBeforeClose : !dtd[ e ][ '#' ],
80                                         breakAfterClose : 1
81                                 });
82                 }
83
84                 this.setRules( 'br',
85                         {
86                                 breakAfterOpen : 1
87                         });
88
89                 this.setRules( 'title',
90                         {
91                                 indent : 0,
92                                 breakAfterOpen : 0
93                         });
94
95                 this.setRules( 'style',
96                         {
97                                 indent : 0,
98                                 breakBeforeClose : 1
99                         });
100
101                 // Disable indentation on <pre>.
102                 this.setRules( 'pre',
103                         {
104                           indent : 0
105                         });
106         },
107
108         proto :
109         {
110                 /**
111                  * Writes the tag opening part for a opener tag.
112                  * @param {String} tagName The element name for this tag.
113                  * @param {Object} attributes The attributes defined for this tag. The
114                  *              attributes could be used to inspect the tag.
115                  * @example
116                  * // Writes "&lt;p".
117                  * writer.openTag( 'p', { class : 'MyClass', id : 'MyId' } );
118                  */
119                 openTag : function( tagName, attributes )
120                 {
121                         var rules = this._.rules[ tagName ];
122
123                         if ( this._.indent )
124                                 this.indentation();
125                         // Do not break if indenting.
126                         else if ( rules && rules.breakBeforeOpen )
127                         {
128                                 this.lineBreak();
129                                 this.indentation();
130                         }
131
132                         this._.output.push( '<', tagName );
133                 },
134
135                 /**
136                  * Writes the tag closing part for a opener tag.
137                  * @param {String} tagName The element name for this tag.
138                  * @param {Boolean} isSelfClose Indicates that this is a self-closing tag,
139                  *              like "br" or "img".
140                  * @example
141                  * // Writes "&gt;".
142                  * writer.openTagClose( 'p', false );
143                  * @example
144                  * // Writes " /&gt;".
145                  * writer.openTagClose( 'br', true );
146                  */
147                 openTagClose : function( tagName, isSelfClose )
148                 {
149                         var rules = this._.rules[ tagName ];
150
151                         if ( isSelfClose )
152                                 this._.output.push( this.selfClosingEnd );
153                         else
154                         {
155                                 this._.output.push( '>' );
156
157                                 if ( rules && rules.indent )
158                                         this._.indentation += this.indentationChars;
159                         }
160
161                         if ( rules && rules.breakAfterOpen )
162                                 this.lineBreak();
163                         tagName == 'pre' && ( this._.inPre = 1 );
164                 },
165
166                 /**
167                  * Writes an attribute. This function should be called after opening the
168                  * tag with {@link #openTagClose}.
169                  * @param {String} attName The attribute name.
170                  * @param {String} attValue The attribute value.
171                  * @example
172                  * // Writes ' class="MyClass"'.
173                  * writer.attribute( 'class', 'MyClass' );
174                  */
175                 attribute : function( attName, attValue )
176                 {
177
178                         if ( typeof attValue == 'string' )
179                         {
180                                 this.forceSimpleAmpersand && ( attValue = attValue.replace( /&amp;/g, '&' ) );
181                                 // Browsers don't always escape special character in attribute values. (#4683, #4719).
182                                 attValue = CKEDITOR.tools.htmlEncodeAttr( attValue );
183                         }
184
185                         this._.output.push( ' ', attName, '="', attValue, '"' );
186                 },
187
188                 /**
189                  * Writes a closer tag.
190                  * @param {String} tagName The element name for this tag.
191                  * @example
192                  * // Writes "&lt;/p&gt;".
193                  * writer.closeTag( 'p' );
194                  */
195                 closeTag : function( tagName )
196                 {
197                         var rules = this._.rules[ tagName ];
198
199                         if ( rules && rules.indent )
200                                 this._.indentation = this._.indentation.substr( this.indentationChars.length );
201
202                         if ( this._.indent )
203                                 this.indentation();
204                         // Do not break if indenting.
205                         else if ( rules && rules.breakBeforeClose )
206                         {
207                                 this.lineBreak();
208                                 this.indentation();
209                         }
210
211                         this._.output.push( '</', tagName, '>' );
212                         tagName == 'pre' && ( this._.inPre = 0 );
213
214                         if ( rules && rules.breakAfterClose )
215                                 this.lineBreak();
216                 },
217
218                 /**
219                  * Writes text.
220                  * @param {String} text The text value
221                  * @example
222                  * // Writes "Hello Word".
223                  * writer.text( 'Hello Word' );
224                  */
225                 text : function( text )
226                 {
227                         if ( this._.indent )
228                         {
229                                 this.indentation();
230                                 !this._.inPre  && ( text = CKEDITOR.tools.ltrim( text ) );
231                         }
232
233                         this._.output.push( text );
234                 },
235
236                 /**
237                  * Writes a comment.
238                  * @param {String} comment The comment text.
239                  * @example
240                  * // Writes "&lt;!-- My comment --&gt;".
241                  * writer.comment( ' My comment ' );
242                  */
243                 comment : function( comment )
244                 {
245                         if ( this._.indent )
246                                 this.indentation();
247
248                         this._.output.push( '<!--', comment, '-->' );
249                 },
250
251                 /**
252                  * Writes a line break. It uses the {@link #lineBreakChars} property for it.
253                  * @example
254                  * // Writes "\n" (e.g.).
255                  * writer.lineBreak();
256                  */
257                 lineBreak : function()
258                 {
259                         if ( !this._.inPre && this._.output.length > 0 )
260                                 this._.output.push( this.lineBreakChars );
261                         this._.indent = 1;
262                 },
263
264                 /**
265                  * Writes the current indentation chars. It uses the
266                  * {@link #indentationChars} property, repeating it for the current
267                  * indentation steps.
268                  * @example
269                  * // Writes "\t" (e.g.).
270                  * writer.indentation();
271                  */
272                 indentation : function()
273                 {
274                         if( !this._.inPre )
275                                 this._.output.push( this._.indentation );
276                         this._.indent = 0;
277                 },
278
279                 /**
280                  * Sets formatting rules for a give element. The possible rules are:
281                  * <ul>
282                  *      <li><b>indent</b>: indent the element contents.</li>
283                  *      <li><b>breakBeforeOpen</b>: break line before the opener tag for this element.</li>
284                  *      <li><b>breakAfterOpen</b>: break line after the opener tag for this element.</li>
285                  *      <li><b>breakBeforeClose</b>: break line before the closer tag for this element.</li>
286                  *      <li><b>breakAfterClose</b>: break line after the closer tag for this element.</li>
287                  * </ul>
288                  *
289                  * All rules default to "false". Each call to the function overrides
290                  * already present rules, leaving the undefined untouched.
291                  *
292                  * By default, all elements available in the {@link CKEDITOR.dtd.$block),
293                  * {@link CKEDITOR.dtd.$listItem} and {@link CKEDITOR.dtd.$tableContent}
294                  * lists have all the above rules set to "true". Additionaly, the "br"
295                  * element has the "breakAfterOpen" set to "true".
296                  * @param {String} tagName The element name to which set the rules.
297                  * @param {Object} rules An object containing the element rules.
298                  * @example
299                  * // Break line before and after "img" tags.
300                  * writer.setRules( 'img',
301                  *     {
302                  *         breakBeforeOpen : true
303                  *         breakAfterOpen : true
304                  *     });
305                  * @example
306                  * // Reset the rules for the "h1" tag.
307                  * writer.setRules( 'h1', {} );
308                  */
309                 setRules : function( tagName, rules )
310                 {
311                         var currentRules = this._.rules[ tagName ];
312
313                         if ( currentRules )
314                                 CKEDITOR.tools.extend( currentRules, rules, true );
315                         else
316                                 this._.rules[ tagName ] = rules;
317                 }
318         }
319 });