+/*\r
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.\r
+For licensing, see LICENSE.html or http://ckeditor.com/license\r
+*/\r
+\r
+CKEDITOR.plugins.add( 'htmlwriter' );\r
+\r
+/**\r
+ * Class used to write HTML data.\r
+ * @constructor\r
+ * @example\r
+ * var writer = new CKEDITOR.htmlWriter();\r
+ * writer.openTag( 'p' );\r
+ * writer.attribute( 'class', 'MyClass' );\r
+ * writer.openTagClose( 'p' );\r
+ * writer.text( 'Hello' );\r
+ * writer.closeTag( 'p' );\r
+ * alert( writer.getHtml() ); "<p class="MyClass">Hello</p>"\r
+ */\r
+CKEDITOR.htmlWriter = CKEDITOR.tools.createClass(\r
+{\r
+ base : CKEDITOR.htmlParser.basicWriter,\r
+\r
+ $ : function()\r
+ {\r
+ // Call the base contructor.\r
+ this.base();\r
+\r
+ /**\r
+ * The characters to be used for each identation step.\r
+ * @type String\r
+ * @default "\t" (tab)\r
+ * @example\r
+ * // Use two spaces for indentation.\r
+ * editorInstance.dataProcessor.writer.indentationChars = ' ';\r
+ */\r
+ this.indentationChars = '\t';\r
+\r
+ /**\r
+ * The characters to be used to close "self-closing" elements, like "br" or\r
+ * "img".\r
+ * @type String\r
+ * @default " />"\r
+ * @example\r
+ * // Use HTML4 notation for self-closing elements.\r
+ * editorInstance.dataProcessor.writer.selfClosingEnd = '>';\r
+ */\r
+ this.selfClosingEnd = ' />';\r
+\r
+ /**\r
+ * The characters to be used for line breaks.\r
+ * @type String\r
+ * @default "\n" (LF)\r
+ * @example\r
+ * // Use CRLF for line breaks.\r
+ * editorInstance.dataProcessor.writer.lineBreakChars = '\r\n';\r
+ */\r
+ this.lineBreakChars = '\n';\r
+\r
+ this.forceSimpleAmpersand = false;\r
+\r
+ this.sortAttributes = true;\r
+\r
+ this._.indent = false;\r
+ this._.indentation = '';\r
+ this._.rules = {};\r
+\r
+ var dtd = CKEDITOR.dtd;\r
+\r
+ for ( var e in CKEDITOR.tools.extend( {}, dtd.$block, dtd.$listItem, dtd.$tableContent ) )\r
+ {\r
+ this.setRules( e,\r
+ {\r
+ indent : true,\r
+ breakBeforeOpen : true,\r
+ breakAfterOpen : true,\r
+ breakBeforeClose : !dtd[ e ][ '#' ],\r
+ breakAfterClose : true\r
+ });\r
+ }\r
+ this.setRules( 'br',\r
+ {\r
+ breakAfterOpen : true\r
+ });\r
+ // Disable indentation on <pre>.\r
+ this.setRules( 'pre',\r
+ {\r
+ indent: false\r
+ } );\r
+ },\r
+\r
+ proto :\r
+ {\r
+ /**\r
+ * Writes the tag opening part for a opener tag.\r
+ * @param {String} tagName The element name for this tag.\r
+ * @param {Object} attributes The attributes defined for this tag. The\r
+ * attributes could be used to inspect the tag.\r
+ * @example\r
+ * // Writes "<p".\r
+ * writer.openTag( 'p', { class : 'MyClass', id : 'MyId' } );\r
+ */\r
+ openTag : function( tagName, attributes )\r
+ {\r
+ var rules = this._.rules[ tagName ];\r
+\r
+ if ( this._.indent )\r
+ this.indentation();\r
+ // Do not break if indenting.\r
+ else if ( rules && rules.breakBeforeOpen )\r
+ {\r
+ this.lineBreak();\r
+ this.indentation();\r
+ }\r
+\r
+ this._.output.push( '<', tagName );\r
+ },\r
+\r
+ /**\r
+ * Writes the tag closing part for a opener tag.\r
+ * @param {String} tagName The element name for this tag.\r
+ * @param {Boolean} isSelfClose Indicates that this is a self-closing tag,\r
+ * like "br" or "img".\r
+ * @example\r
+ * // Writes ">".\r
+ * writer.openTagClose( 'p', false );\r
+ * @example\r
+ * // Writes " />".\r
+ * writer.openTagClose( 'br', true );\r
+ */\r
+ openTagClose : function( tagName, isSelfClose )\r
+ {\r
+ var rules = this._.rules[ tagName ];\r
+\r
+ if ( isSelfClose )\r
+ this._.output.push( this.selfClosingEnd );\r
+ else\r
+ {\r
+ this._.output.push( '>' );\r
+\r
+ if ( rules && rules.indent )\r
+ this._.indentation += this.indentationChars;\r
+ }\r
+\r
+ if ( rules && rules.breakAfterOpen )\r
+ this.lineBreak();\r
+ },\r
+\r
+ /**\r
+ * Writes an attribute. This function should be called after opening the\r
+ * tag with {@link #openTagClose}.\r
+ * @param {String} attName The attribute name.\r
+ * @param {String} attValue The attribute value.\r
+ * @example\r
+ * // Writes ' class="MyClass"'.\r
+ * writer.attribute( 'class', 'MyClass' );\r
+ */\r
+ attribute : function( attName, attValue )\r
+ {\r
+ if ( this.forceSimpleAmpersand )\r
+ attValue = attValue.replace( /&/, '&' );\r
+\r
+ this._.output.push( ' ', attName, '="', attValue, '"' );\r
+ },\r
+\r
+ /**\r
+ * Writes a closer tag.\r
+ * @param {String} tagName The element name for this tag.\r
+ * @example\r
+ * // Writes "</p>".\r
+ * writer.closeTag( 'p' );\r
+ */\r
+ closeTag : function( tagName )\r
+ {\r
+ var rules = this._.rules[ tagName ];\r
+\r
+ if ( rules && rules.indent )\r
+ this._.indentation = this._.indentation.substr( this.indentationChars.length );\r
+\r
+ if ( this._.indent )\r
+ this.indentation();\r
+ // Do not break if indenting.\r
+ else if ( rules && rules.breakBeforeClose )\r
+ {\r
+ this.lineBreak();\r
+ this.indentation();\r
+ }\r
+\r
+ this._.output.push( '</', tagName, '>' );\r
+\r
+ if ( rules && rules.breakAfterClose )\r
+ this.lineBreak();\r
+ },\r
+\r
+ /**\r
+ * Writes text.\r
+ * @param {String} text The text value\r
+ * @example\r
+ * // Writes "Hello Word".\r
+ * writer.text( 'Hello Word' );\r
+ */\r
+ text : function( text )\r
+ {\r
+ if ( this._.indent )\r
+ {\r
+ this.indentation();\r
+ text = CKEDITOR.tools.ltrim( text );\r
+ }\r
+\r
+ this._.output.push( text );\r
+ },\r
+\r
+ /**\r
+ * Writes a comment.\r
+ * @param {String} comment The comment text.\r
+ * @example\r
+ * // Writes "<!-- My comment -->".\r
+ * writer.comment( ' My comment ' );\r
+ */\r
+ comment : function( comment )\r
+ {\r
+ if ( this._.indent )\r
+ this.indentation();\r
+\r
+ this._.output.push( '<!--', comment, '-->' );\r
+ },\r
+\r
+ /**\r
+ * Writes a line break. It uses the {@link #lineBreakChars} property for it.\r
+ * @example\r
+ * // Writes "\n" (e.g.).\r
+ * writer.lineBreak();\r
+ */\r
+ lineBreak : function()\r
+ {\r
+ if ( this._.output.length > 0 )\r
+ this._.output.push( this.lineBreakChars );\r
+ this._.indent = true;\r
+ },\r
+\r
+ /**\r
+ * Writes the current indentation chars. It uses the\r
+ * {@link #indentationChars} property, repeating it for the current\r
+ * indentation steps.\r
+ * @example\r
+ * // Writes "\t" (e.g.).\r
+ * writer.indentation();\r
+ */\r
+ indentation : function()\r
+ {\r
+ this._.output.push( this._.indentation );\r
+ this._.indent = false;\r
+ },\r
+\r
+ /**\r
+ * Sets formatting rules for a give element. The possible rules are:\r
+ * <ul>\r
+ * <li><b>indent</b>: indent the element contents.</li>\r
+ * <li><b>breakBeforeOpen</b>: break line before the opener tag for this element.</li>\r
+ * <li><b>breakAfterOpen</b>: break line after the opener tag for this element.</li>\r
+ * <li><b>breakBeforeClose</b>: break line before the closer tag for this element.</li>\r
+ * <li><b>breakAfterClose</b>: break line after the closer tag for this element.</li>\r
+ * </ul>\r
+ *\r
+ * All rules default to "false".\r
+ *\r
+ * By default, all elements available in the {@link CKEDITOR.dtd.$block),\r
+ * {@link CKEDITOR.dtd.$listItem} and {@link CKEDITOR.dtd.$tableContent}\r
+ * lists have all the above rules set to "true". Additionaly, the "br"\r
+ * element has the "breakAfterOpen" set to "true".\r
+ * @param {String} tagName The element name to which set the rules.\r
+ * @param {Object} rules An object containing the element rules.\r
+ * @example\r
+ * // Break line before and after "img" tags.\r
+ * writer.setRules( 'img',\r
+ * {\r
+ * breakBeforeOpen : true\r
+ * breakAfterOpen : true\r
+ * });\r
+ * @example\r
+ * // Reset the rules for the "h1" tag.\r
+ * writer.setRules( 'h1', {} );\r
+ */\r
+ setRules : function( tagName, rules )\r
+ {\r
+ this._.rules[ tagName ] = rules;\r
+ }\r
+ }\r
+});\r