/* Function: GetText * Converts a block of formatted text to NDMarkup and adds it to the output. It ends when it reaches the closing tag for anything * already on the tag stack. */ protected void GetText(ref XMLIterator iterator, StringBuilder output, TagStack tagStack) { output.Append("<p>"); tagStack.OpenTag(null, "</p>"); int surroundingPTagIndex = tagStack.Count - 1; while (iterator.IsInBounds) { if (iterator.IsOn(XMLElementType.Text)) { output.EntityEncodeAndAppend(iterator.String); iterator.Next(); } else if (iterator.IsOn(XMLElementType.EntityChar)) { output.EntityEncodeAndAppend(iterator.EntityValue); iterator.Next(); } else if (iterator.IsOn(XMLElementType.LineBreak)) { // Add a literal line break. We'll replace these with spaces or double spaces later. Right now we can't decide // which it should be because you can't run a regex directly on a StringBuilder and it would be inefficient to convert // it to a string on every line break. output.Append('\n'); iterator.Next(); } else if (iterator.IsOnTag("para")) { // Text can appear both inside and outside of <para> tags, and whitespace can appear between <para> tags that // can be mistaken for content, so rather than put in a lot of logic we handle it in a very dirty but simple way. Every // <para> tag--opening, closing, standalone (technically invalid)--causes a paragraph break. Normalize() will clean it // up for us afterwards. tagStack.CloseTag(surroundingPTagIndex + 1, output); // Reuse our surrounding tag output.Append("</p><p>"); iterator.Next(); } else if (iterator.IsOnTag("code", TagForm.Opening)) { output.Append("</p>"); GetCode(ref iterator, output, tagStack); output.Append("<p>"); } else if (iterator.IsOnTag("example", TagForm.Opening)) { // <example> can be nested in addition to a top-level tag. output.Append("</p><h>"); output.EntityEncodeAndAppend( Engine.Locale.Get("NaturalDocs.Engine", "XML.Heading.example") ); output.Append("</h><p>"); tagStack.OpenTag("example", "</p><p>"); iterator.Next(); } else if (iterator.IsOnTag("list", TagForm.Opening)) { output.Append("</p>"); GetList(ref iterator, output, tagStack); output.Append("<p>"); } else if (iterator.IsOnTag("paramref") || iterator.IsOnTag("typeparamref")) { // Can't assume all the properties are set string name = iterator.TagProperty("name"); if (name != null) { output.EntityEncodeAndAppend(name); } iterator.Next(); } else if (iterator.IsOnTag("see", TagForm.Standalone)) { // Can't assume all the properties are set string cref = iterator.TagProperty("cref"); if (cref != null) { output.Append("<link type=\"naturaldocs\" originaltext=\""); output.EntityEncodeAndAppend(cref); output.Append("\">"); } else { string langword = iterator.TagProperty("langword"); if (langword != null) { output.EntityEncodeAndAppend(langword); } } iterator.Next(); } else if (iterator.IsOnTag(TagForm.Opening)) { tagStack.OpenTag(iterator.TagType); iterator.Next(); } else if (iterator.IsOnTag(TagForm.Closing)) { int openingTagIndex = tagStack.FindTag(iterator.TagType); if (openingTagIndex == -1) { } else if (openingTagIndex < surroundingPTagIndex) { break; } else { tagStack.CloseTag(openingTagIndex, output); } iterator.Next(); } else { // Ignore indent. Spaces between words will be handled by line breaks. // Ignore unrecognized standalone tags. iterator.Next(); } } tagStack.CloseTag(surroundingPTagIndex, output); }
/* Function: GetSimpleText * Converts a block of plain unformatted text to NDMarkup and adds it to the output. Unlike <GetText()> this will not surround the * output in paragraph tags. It ends when it reaches the closing tag for anything already on the tag stack. */ protected void GetSimpleText(ref XMLIterator iterator, StringBuilder output, TagStack tagStack) { int surroundingTagCount = tagStack.Count; while (iterator.IsInBounds) { if (iterator.IsOn(XMLElementType.Text)) { output.EntityEncodeAndAppend(iterator.String); iterator.Next(); } else if (iterator.IsOn(XMLElementType.EntityChar)) { output.EntityEncodeAndAppend(iterator.EntityValue); iterator.Next(); } else if (iterator.IsOn(XMLElementType.LineBreak)) { // Add a literal line break. We'll replace these with spaces or double spaces later. Right now we can't decide // which it should be because you can't run a regex directly on a StringBuilder and it would be inefficient to convert // it to a string on every line break. output.Append('\n'); iterator.Next(); } else if (iterator.IsOnTag("paramref") || iterator.IsOnTag("typeparamref")) { // Can't assume all the properties are set string name = iterator.TagProperty("name"); if (name != null) { output.Append(name); } iterator.Next(); } else if (iterator.IsOnTag(TagForm.Opening)) { tagStack.OpenTag(iterator.TagType); iterator.Next(); } else if (iterator.IsOnTag(TagForm.Closing)) { int openingTagIndex = tagStack.FindTag(iterator.TagType); if (openingTagIndex == -1) { } else if (openingTagIndex <= surroundingTagCount - 1) { break; } else { tagStack.CloseTag(openingTagIndex, output); } iterator.Next(); } else { // Ignore indent. Spaces between words will be handled by line breaks. // Ignore unrecognized standalone tags. iterator.Next(); } } if (tagStack.Count > surroundingTagCount) { tagStack.CloseTag(surroundingTagCount, output); } }
/* Function: TryToGetTopLevelListItem * If the iterator is on a param, typeparam, exception, or permission tag it will convert it to NDMarkup, add it to the * comment in a list block, move the iterator past it, and return true. Otherwise it returns false and nothing is changed. */ protected bool TryToGetTopLevelListItem(ref XMLIterator iterator, XMLComment comment) { if (iterator.IsOnTag("param", TagForm.Opening) == false && iterator.IsOnTag("exception", TagForm.Opening) == false && iterator.IsOnTag("permission", TagForm.Opening) == false && iterator.IsOnTag("typeparam", TagForm.Opening) == false && iterator.IsOnTag("see", TagForm.Opening) == false && iterator.IsOnTag("see", TagForm.Standalone) == false && iterator.IsOnTag("seealso", TagForm.Opening) == false && iterator.IsOnTag("seealso", TagForm.Standalone) == false) { return(false); } string keyword = iterator.TagType; if (keyword == "see") { keyword = "seealso"; } XMLComment.ListBlock block = comment.GetListBlock(keyword); string name = null; string description = null; if (keyword == "param" || keyword == "typeparam") { name = iterator.TagProperty("name"); } else { name = iterator.TagProperty("cref") ?? iterator.TagProperty("langword"); } if (iterator.TagForm == TagForm.Opening) { TagStack tagStack = new TagStack(); tagStack.OpenTag(keyword); iterator.Next(); StringBuilder descriptionBuilder = new StringBuilder(); GetText(ref iterator, descriptionBuilder, tagStack); tagStack.CloseAllTags(descriptionBuilder); description = Normalize(descriptionBuilder.ToString()); if (iterator.IsOnTag(keyword, TagForm.Closing)) { iterator.Next(); } } else { iterator.Next(); } if (name != null) { block.Add(name, description); } return(true); }