/// <summary> /// Inserts an attribute to an XElement in the source code editor. /// </summary> /// <param name='el'> /// the tag's XElement instance /// </param> /// <param name='key'> /// Key. /// </param> /// <param name='value'> /// Value. /// </param> public void InsertAttribute(XElement el, string key, string value) { int line = el.Region.EndLine; int column = 1; // a preceding space or nothing string preambula = String.Empty; // a space or nothing after the last quote string ending = String.Empty; if (el.IsSelfClosing) { column = el.Region.EndColumn - 2; // "/>" // a space before the /> of the tag ending = " "; } else { column = el.Region.EndColumn - 1; // ">" // no need for a space in the end of an openning tag } // check if a space is needed infront of the attribute // or the method should write at the first column of a new line if (column > 1) { string whatsBeforeUs = document.GetTextFromEditor(line, column - 1, line, column); if (!String.IsNullOrWhiteSpace(whatsBeforeUs)) { preambula = " "; } } // finally, insert the result document.InsertText( new TextLocation(line, column), String.Format("{0}{1}=\"{2}\"{3}", preambula, key, value, ending) ); }
/// <summary> /// Serializes a XNode to a HTML tag. This is a recursive method. /// </summary> /// <param name='node'> /// Node. /// </param> /// <param name='sb'> /// A string builder instance. /// </param> void SerializeNode(XNode node, StringBuilder sb) { prevTagLocation = node.Region.End; var element = node as XElement; if (element == null) { return; } string id = XDocumentHelper.GetAttributeValueCI(element.Attributes, "id"); // Controls are runat="server" and have unique id in the Container if (element.Name.HasPrefix || XDocumentHelper.IsRunAtServer(element)) { IComponent component = host.GetComponent(id); // HTML controls, doesn't need special rendering var control = component as Control; // genarete placeholder if (control != null) { StringWriter strWriter = new StringWriter(); HtmlTextWriter writer = new HtmlTextWriter(strWriter); control.RenderControl(writer); writer.Close(); strWriter.Flush(); sb.Append(strWriter.ToString()); strWriter.Close(); if (!element.IsSelfClosing) { prevTagLocation = element.ClosingTag.Region.End; } return; } } // strip script tags if (element.Name.Name.ToLower() == "script") { return; } // the node is a html element sb.AppendFormat("<{0}", element.Name.FullName); // print the attributes foreach (MonoDevelop.Xml.StateEngine.XAttribute attr in element.Attributes) { string name = attr.Name.Name.ToLower(); // strip runat and on* event attributes if ((name != "runat") && (name.Substring(0, 2).ToLower() != "on")) { sb.AppendFormat(" {0}=\"{1}\"", attr.Name.FullName, attr.Value); } } if (element.IsSelfClosing) { sb.Append(" />"); } else { sb.Append(">"); // we are currentyl on the head tag // add designer content - js and css if (element.Name.Name.ToLower() == "head") { sb.Append(designerContext); } if (element.Name.Name.ToLower() == "body") { GetDesignerInitParams(sb); } // serializing the childnodes if any foreach (MonoDevelop.Xml.StateEngine.XNode nd in element.Nodes) { // get the text before the openning tag of the child element sb.Append(document.GetTextFromEditor(prevTagLocation, nd.Region.Begin)); // and the element itself SerializeNode(nd, sb); } // printing the text after the closing tag of the child elements int lastChildEndLine = element.Region.EndLine; int lastChildEndColumn = element.Region.EndColumn; // if the element have 1+ children if (element.LastChild != null) { var lastChild = element.LastChild as MonoDevelop.Xml.StateEngine.XElement; // the last child is an XML tag if (lastChild != null) { // the tag is selfclosing if (lastChild.IsSelfClosing) { lastChildEndLine = lastChild.Region.EndLine; lastChildEndColumn = lastChild.Region.EndColumn; // the tag is not selfclosing and has a closing tag } else if (lastChild.ClosingTag != null) { lastChildEndLine = lastChild.ClosingTag.Region.EndLine; lastChildEndColumn = lastChild.ClosingTag.Region.EndColumn; } else { // TODO: the element is not closed. Warn the user } // the last child is not a XML element. Probably AspNet tag. TODO: find the end location of that tag } else { lastChildEndLine = element.LastChild.Region.EndLine; lastChildEndLine = element.LastChild.Region.EndLine; } } if (element.ClosingTag != null) { sb.Append(document.GetTextFromEditor(new TextLocation(lastChildEndLine, lastChildEndColumn), element.ClosingTag.Region.Begin)); prevTagLocation = element.ClosingTag.Region.End; } else { // TODO: the element is not closed. Warn the user } sb.AppendFormat("</{0}>", element.Name.FullName); } }