public override void chars(string text) { if (preStack.Count > 0) { text = ReplaceForPre(text); } else if (text.Trim() != "") { text = ReplaceMultipleWhitespaveWithOne(text); var prevText = HtmlToMarkdownConverterHelper.peekTillNotEmpty(nodeStack.ToList()); if (prevText.EndsWith(" ")) { text = text.TrimStart(); } } else { nodeStack.Push(""); return; } //if(blockquoteStack.length > 0 && peekTillNotEmpty(nodeList).endsWith("\n")) { if (blockquoteStack.Count > 0) { var array = blockquoteStack.ToArray(); Array.Reverse(array); nodeStack.Push(string.Join(string.Empty, array)); } nodeStack.Push(ReplaceSpecialChars(text)); }
public bool removeIfEmptyTag(string start) { var cleaned = false; if (start == HtmlToMarkdownConverterHelper.peekTillNotEmpty(nodeStack.ToList())) { while (nodeStack.Peek() != start) { nodeStack.Pop(); } nodeStack.Pop(); cleaned = true; } return(cleaned); }
private void block(bool isEndBlock) { if (nodeStack.Count == 0) { return; } var lastItem = nodeStack.Pop(); if (string.IsNullOrWhiteSpace(lastItem)) { return; } if (!isEndBlock) { string block; if (Regex.IsMatch(lastItem, @"\s*\n\n\s*$")) { lastItem = Regex.Replace(lastItem, @"\s*\n\n\s*$", "\n\n"); block = ""; } else if (Regex.IsMatch(lastItem, @"\s*\n\s*$")) { lastItem = Regex.Replace(lastItem, @"\s*\n\s*$", "\n"); block = "\n"; } else if (Regex.IsMatch(lastItem, @"\s+$")) { block = "\n\n"; } else { block = "\n\n"; } nodeStack.Push(lastItem); nodeStack.Push(block); } else { nodeStack.Push(lastItem); if (!HtmlToMarkdownConverterHelper.endsWith(lastItem, "\n")) { nodeStack.Push("\n\n"); } } }
public override void end(string tag) { tag = tag.ToLower(); switch (tag) { case "title": case "h1": case "h2": case "h3": case "h4": case "h5": case "h6": if (!removeIfEmptyTag(Markdown.Tags[tag])) { block(true); } break; case "p": case "div": case "table": case "tbody": case "tr": case "td": while (nodeStack.Count > 0 && nodeStack.Peek().Trim() == "") { nodeStack.Pop(); } block(true); break; case "b": case "strong": case "i": case "em": case "dfn": case "var": case "cite": if (!removeIfEmptyTag(Markdown.Tags[tag])) { nodeStack.Push(sliceText(Markdown.Tags[tag]).Trim()); nodeStack.Push(Markdown.Tags[tag]); } break; case "a": var text = sliceText("["); text = Regex.Replace(text, @"\s+", " "); text = text.Trim(); if (text == "") { nodeStack.Pop(); break; } var attrs = linkAttrStack.Pop(); var url = attrs.ContainsKey("href") && attrs["href"].Value != "" ? attrs["href"].Value : ""; if (url == "") { nodeStack.Pop(); nodeStack.Push(text); break; } nodeStack.Push(text); if (!inlineStyle && !HtmlToMarkdownConverterHelper.startsWith(nodeStack.Peek(), "!")) { var l = links.IndexOf(url); if (l == -1) { links.Add(url); l = links.Count - 1; } nodeStack.Push("][" + l + "]"); } else { if (HtmlToMarkdownConverterHelper.startsWith(nodeStack.Peek(), "!")) { var localText = nodeStack.Pop(); localText = nodeStack.Pop() + localText; block(false); nodeStack.Push(localText); } var title = attrs.ContainsKey("title") && attrs["title"].Value != "" ? attrs["title"].Value : ""; var trimmedTitle = title.Trim(); nodeStack.Push("](" + url + (false == string.IsNullOrWhiteSpace(title) ? " \"" + Regex.Replace(trimmedTitle, @"\s+", " ") + "\"" : "") + ")"); if (HtmlToMarkdownConverterHelper.startsWith(nodeStack.Peek(), "!")) { block(true); } } break; case "ul": case "ol": case "dl": listBlock(); listTagStack.Pop(); break; case "li": case "dt": var li = getListMarkdownTag(); if (!removeIfEmptyTag(li)) { var liContent = sliceText(li).Trim(); if (liContent.StartsWith("[![")) { nodeStack.Pop(); block(false); nodeStack.Push(liContent); block(true); } else { nodeStack.Push(liContent); listBlock(); } } break; case "blockquote": blockquoteStack.Pop(); break; case "pre": // //uncomment following experimental code to discard line numbers when syntax highlighters are used // //notes this code thorough testing before production user // /* // var p=[]; // var flag = true; // var count = 0, whiteSpace = 0, line = 0; // console.log(">> " + peek(nodeList)); // while(peek(nodeList).startsWith(" ") || flag == true) // { // //console.log('inside'); // var text = nodeList.pop(); // p.push(text); // if(flag == true && !text.startsWith(" ")) { // continue; // } else { // flag = false; // } // //var result = parseInt(text.trim()); // if(!isNaN(text.trim())) { // count++; // } else if(text.trim() == ""){ // whiteSpace++; // } else { // line++; // } // flag = false; // } // console.log(line); // if(line != 0) // { // while(p.length != 0) { // nodeList.push(p.pop()); // } // } // */ // block(true); // preStack.pop(); break; case "code": case "span": if (preStack.Count > 0) { break; } else if (string.IsNullOrWhiteSpace(nodeStack.Peek())) { nodeStack.Pop(); nodeStack.Push(Markdown.Tags[tag]); } else { var item = nodeStack.Pop(); nodeStack.Push(item.Trim()); nodeStack.Push(Markdown.Tags[tag]); } break; //case "table": // nodeList.push("</table>"); // break; //case "thead": // nodeList.push("</thead>"); // break; //case "tbody": // nodeList.push("</tbody>"); // break; //case "tr": // nodeList.push("</tr>"); // break; //case "td": // nodeList.push("</td>"); // break; case "br": case "hr": case "img": break; } }
public override void start(string tag, Dictionary <string, HtmlAttribute> attrs, bool unary) { tag = tag.ToLower(); if (unary && (tag != "br" && tag != "hr" && tag != "img")) { return; } switch (tag) { case "p": case "div": case "table": case "tbody": case "tr": case "td": block(false); break; } switch (tag) { case "br": nodeStack.Push(Markdown.Tags[tag]); break; case "hr": block(false); nodeStack.Push(Markdown.Tags[tag]); break; case "title": case "h1": case "h2": case "h3": case "h4": case "h5": case "h6": block(false); nodeStack.Push(Markdown.Tags[tag]); break; case "b": case "strong": case "i": case "em": case "dfn": case "var": case "cite": nodeStack.Push(Markdown.Tags[tag]); break; case "code": case "span": if (preStack.Count > 0) { break; } else if (false == nodeStack.SafePeek().EndsWith(" ")) { nodeStack.Push(Markdown.Tags[tag]); } break; case "ul": case "ol": case "dl": listTagStack.Push(Markdown.Tags[tag]); // lists are block elements if (listTagStack.Count > 1) { listBlock(); } else { block(false); } break; case "li": case "dt": var li = getListMarkdownTag(); nodeStack.Push(li); break; case "a": linkAttrStack.Push(HtmlToMarkdownConverterHelper.convertAttrs(attrs)); nodeStack.Push("["); break; case "img": var attribs = HtmlToMarkdownConverterHelper.convertAttrs(attrs); string alt, title, url; url = attribs.ContainsKey("src") ? attribs["src"].Value : ""; if (string.IsNullOrWhiteSpace(url)) { break; } alt = attribs.ContainsKey("alt") ? attribs["alt"].Value.Trim() : ""; title = attribs.ContainsKey("title") ? attribs["title"].Value.Trim() : ""; // if parent of image tag is nested in anchor tag use inline style if (!inlineStyle && false == HtmlToMarkdownConverterHelper.startsWith(HtmlToMarkdownConverterHelper.peekTillNotEmpty(nodeStack.ToList()), "[")) { var l = links.IndexOf(url); if (l == -1) { links.Add(url); l = links.Count - 1; } block(false); nodeStack.Push("!["); if (alt != "") { nodeStack.Push(alt); } else if (title != null) { nodeStack.Push(title); } nodeStack.Push("][" + l + "]"); block(false); } else { //if image is not a link image then treat images as block elements if (false == HtmlToMarkdownConverterHelper.startsWith(HtmlToMarkdownConverterHelper.peekTillNotEmpty(nodeStack.ToList()), "[")) { block(false); } nodeStack.Push("![" + alt + "](" + url + (false == string.IsNullOrWhiteSpace(title) ? " \"" + title + "\"" : "") + ")"); if (false == HtmlToMarkdownConverterHelper.startsWith(HtmlToMarkdownConverterHelper.peekTillNotEmpty(nodeStack.ToList()), "[")) { block(true); } } break; case "blockquote": //listBlock(); block(false); blockquoteStack.Push(Markdown.Tags[tag]); break; case "pre": block(false); preStack.Push(true); nodeStack.Push(" "); break; //case "table": // nodeStack.Push("<table>"); // break; //case "thead": // nodeStack.Push("<thead>"); // break; //case "tbody": // nodeStack.Push("<tbody>"); // break; //case "tr": // nodeStack.Push("<tr>"); // break; //case "td": // nodeStack.Push("<td>"); // break; } }