/* Function: TryToGetTopLevelTextBlock * If the iterator is on a summary, remark, returns, or top-level example tag it will convert it to NDMarkup, add it to the comment * in a text block, move the iterator past it, and return true. Otherwise it returns false and nothing is changed. */ protected bool TryToGetTopLevelTextBlock(ref XMLIterator iterator, XMLComment comment) { if (iterator.IsOnTag("summary", TagForm.Opening) == false && iterator.IsOnTag("remark", TagForm.Opening) == false && iterator.IsOnTag("remarks", TagForm.Opening) == false && iterator.IsOnTag("example", TagForm.Opening) == false && iterator.IsOnTag("returns", TagForm.Opening) == false && iterator.IsOnTag("value", TagForm.Opening) == false) { return(false); } string keyword = iterator.TagType; string blockType = keyword; if (keyword == "remarks") { blockType = "remark"; } XMLComment.TextBlock block = comment.GetTextBlock(blockType); TagStack tagStack = new TagStack(); tagStack.OpenTag(keyword); iterator.Next(); GetText(ref iterator, block.Text, tagStack); tagStack.CloseAllTags(block.Text); if (iterator.IsOnTag(keyword, TagForm.Closing)) { iterator.Next(); } return(true); }
/* 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); }
/* Function: GetText * * Converts a stretch of formatted text to NDMarkup. * * Modes: * * Normal - The iterator continues until it goes out of bounds. * ListItem - The iterator continues until it reaches a closing li tag. It also skips certain formatting that is not supported * in list items in NDMarkup. */ protected void GetText(ref JavadocIterator iterator, StringBuilder output, GetTextMode mode = GetTextMode.Normal) { output.Append("<p>"); TagStack tagStack = new TagStack(); tagStack.OpenTag(null, "</p>"); while (iterator.IsInBounds) { if (iterator.IsOn(JavadocElementType.Text)) { output.EntityEncodeAndAppend(iterator.String); iterator.Next(); } else if (iterator.IsOn(JavadocElementType.EntityChar)) { output.EntityEncodeAndAppend(iterator.EntityValue); iterator.Next(); } else if (iterator.IsOn(JavadocElementType.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.IsOnHTMLTag("p")) { // Text can appear both inside and outside of <p> tags, whitespace can appear between <p> tags that can be // mistaken for content, and people can use <p> tags as standalone rather than opening tags. Rather than put in // logic to try to account for all of this we handle it in a very dirty but simple way. Every <p> tag--opening, closing, // or standalone--causes a paragraph break. Normalize() will clean it up for us afterwards. tagStack.CloseTag(1, output); // Reuse our surrounding tag output.Append("</p><p>"); iterator.Next(); } else if (iterator.IsOnHTMLTag("b") || iterator.IsOnHTMLTag("strong")) { if (iterator.HTMLTagForm == TagForm.Opening) { tagStack.OpenTag(iterator.TagType, "</b>"); output.Append("<b>"); } else if (iterator.HTMLTagForm == TagForm.Closing) { tagStack.CloseTag(iterator.TagType, output); } iterator.Next(); } else if (iterator.IsOnHTMLTag("i") || iterator.IsOnHTMLTag("em")) { if (iterator.HTMLTagForm == TagForm.Opening) { tagStack.OpenTag(iterator.TagType, "</i>"); output.Append("<i>"); } else if (iterator.HTMLTagForm == TagForm.Closing) { tagStack.CloseTag(iterator.TagType, output); } iterator.Next(); } else if (iterator.IsOnHTMLTag("u")) { if (iterator.HTMLTagForm == TagForm.Opening) { tagStack.OpenTag(iterator.TagType, "</u>"); output.Append("<u>"); } else if (iterator.HTMLTagForm == TagForm.Closing) { tagStack.CloseTag(iterator.TagType, output); } iterator.Next(); } else if (iterator.IsOnHTMLTag("pre", TagForm.Opening) && mode == GetTextMode.Normal) // Ignore pre's in list items { output.Append("</p>"); GetPre(ref iterator, output); output.Append("<p>"); } else if (iterator.IsOnHTMLTag("ul") || iterator.IsOnHTMLTag("ol")) { if (iterator.HTMLTagForm == TagForm.Opening) { output.Append("</p>"); GetList(ref iterator, output); output.Append("<p>"); } else if (iterator.HTMLTagForm == TagForm.Closing && mode == GetTextMode.ListItem) { break; } else { iterator.Next(); } } else if (iterator.IsOnHTMLTag("li", TagForm.Closing) && mode == GetTextMode.ListItem) { break; } else if (iterator.IsOnHTMLTag("a", TagForm.Opening)) { string href = iterator.HTMLTagProperty("href"); if (href == null || href == "" || href == "#" || href.StartsWith("{@docRoot}") || href.StartsWith("javascript:", StringComparison.OrdinalIgnoreCase)) { iterator.Next(); } else { GetHTMLLink(ref iterator, output); } } else if (iterator.IsOnJavadocTag("code") || iterator.IsOnJavadocTag("literal")) { // These get added without searching the contents for nested tags output.EntityEncodeAndAppend(iterator.JavadocTagValue); iterator.Next(); } else if (iterator.IsOnJavadocTag("link") || iterator.IsOnJavadocTag("linkPlain")) { Tokenizer linkContent = new Tokenizer(iterator.JavadocTagValue); TokenIterator linkIterator = linkContent.FirstToken; string symbol = GetJavadocLinkSymbol(ref linkIterator); linkIterator.NextPastWhitespace(); string description = GetSimpleText(linkIterator, linkContent.LastToken); description = Normalize(description); if (description == null || description == "") { output.Append("<link type=\"naturaldocs\" originaltext=\""); output.EntityEncodeAndAppend(symbol); output.Append("\">"); } else { output.Append("<link type=\"naturaldocs\" originaltext=\""); output.EntityEncodeAndAppend(description); output.Append(" at "); output.EntityEncodeAndAppend(symbol); output.Append("\">"); } iterator.Next(); } else if (iterator.IsOnJavadocTag("value")) { string symbol = iterator.JavadocTagValue; if (symbol == null || symbol == "") { output.EntityEncodeAndAppend( Locale.Get("NaturalDocs.Engine", "Javadoc.Substitution.value") ); } else { string substitution = Locale.Get("NaturalDocs.Engine", "Javadoc.Substitution.value(symbol)", '\x1F'); int substitutionIndex = substitution.IndexOf('\x1F'); if (substitutionIndex == -1) { output.EntityEncodeAndAppend(substitution); } else { if (substitutionIndex > 0) { output.EntityEncodeAndAppend(substitution, 0, substitutionIndex); } output.Append("<link type=\"naturaldocs\" originaltext=\""); output.EntityEncodeAndAppend(symbol); output.Append("\">"); if (substitutionIndex < substitution.Length - 1) { output.EntityEncodeAndAppend(substitution, substitutionIndex + 1, substitution.Length - (substitutionIndex + 1)); } } } iterator.Next(); } else { // Ignore indent. Spaces between words will be handled by line breaks. // Ignore HTML comments. // Ignore unrecognized HTML tags. iterator.Next(); } } tagStack.CloseAllTags(output); }