protected override void VisitTextPart(TextPart entity) { TextConverter converter; string header, footer; if (_body != null) { // since we've already found the body, treat this as an attachment _attachments.Add(entity); return; } GetHeaderFooter(out header, out footer); if (entity.IsHtml) { converter = new HtmlToHtml { Header = UIStrings.MarkOfTheWeb + Environment.NewLine, HeaderFormat = HeaderFooterFormat.Html, HtmlTagCallback = HtmlTagCallback }; } else if (entity.IsFlowed) { var flowed = new FlowedToHtml { Header = UIStrings.MarkOfTheWeb + Environment.NewLine + header, HeaderFormat = HeaderFooterFormat.Html, Footer = footer, FooterFormat = HeaderFooterFormat.Html }; string delsp; if (entity.ContentType.Parameters.TryGetValue("delsp", out delsp)) flowed.DeleteSpace = delsp.ToLowerInvariant() == "yes"; converter = flowed; } else { converter = new TextToHtml { Header = UIStrings.MarkOfTheWeb + Environment.NewLine + header, HeaderFormat = HeaderFooterFormat.Html, Footer = footer, FooterFormat = HeaderFooterFormat.Html }; } string text = entity.Text; _body = converter.Convert(entity.Text); }
/// <summary> /// Convert the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </summary> /// <remarks> /// Converts the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </remarks> /// <param name="reader">The text reader.</param> /// <param name="writer">The text writer.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="reader"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="writer"/> is <c>null</c>.</para> /// </exception> public override void Convert (TextReader reader, TextWriter writer) { if (reader == null) throw new ArgumentNullException (nameof (reader)); if (writer == null) throw new ArgumentNullException (nameof (writer)); if (!string.IsNullOrEmpty (Header)) { if (HeaderFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml (); using (var sr = new StringReader (Header)) converter.Convert (sr, writer); } else { writer.Write (Header); } } using (var htmlWriter = new HtmlWriter (writer)) { var callback = HtmlTagCallback ?? DefaultHtmlTagCallback; var stack = new List<HtmlToHtmlTagContext> (); var tokenizer = new HtmlTokenizer (reader); HtmlToHtmlTagContext ctx; HtmlToken token; while (tokenizer.ReadNextToken (out token)) { switch (token.Kind) { default: if (!SuppressContent (stack)) htmlWriter.WriteToken (token); break; case HtmlTokenKind.Tag: var tag = (HtmlTagToken) token; if (!tag.IsEndTag) { //if (NormalizeHtml && AutoClosingTags.Contains (startTag.TagName) && // (ctx = Pop (stack, startTag.TagName)) != null && // ctx.InvokeCallbackForEndTag && !SuppressContent (stack)) { // var value = string.Format ("</{0}>", ctx.TagName); // var name = ctx.TagName; // // ctx = new HtmlToHtmlTagContext (new HtmlTokenTag (HtmlTokenKind.EndTag, name, value)) { // InvokeCallbackForEndTag = ctx.InvokeCallbackForEndTag, // SuppressInnerContent = ctx.SuppressInnerContent, // DeleteEndTag = ctx.DeleteEndTag, // DeleteTag = ctx.DeleteTag // }; // callback (ctx, htmlWriter); //} if (!tag.IsEmptyElement) { ctx = new HtmlToHtmlTagContext (tag); if (FilterHtml && ctx.TagId == HtmlTagId.Script) { ctx.SuppressInnerContent = true; ctx.DeleteEndTag = true; ctx.DeleteTag = true; } else if (!SuppressContent (stack)) { callback (ctx, htmlWriter); } stack.Add (ctx); } else if (!SuppressContent (stack)) { ctx = new HtmlToHtmlTagContext (tag); if (!FilterHtml || ctx.TagId != HtmlTagId.Script) callback (ctx, htmlWriter); } } else { if ((ctx = Pop (stack, tag.Name)) != null) { if (!SuppressContent (stack)) { if (ctx.InvokeCallbackForEndTag) { ctx = new HtmlToHtmlTagContext (tag) { InvokeCallbackForEndTag = ctx.InvokeCallbackForEndTag, SuppressInnerContent = ctx.SuppressInnerContent, DeleteEndTag = ctx.DeleteEndTag, DeleteTag = ctx.DeleteTag }; callback (ctx, htmlWriter); } else if (!ctx.DeleteEndTag) { htmlWriter.WriteEndTag (tag.Name); } } } else if (!SuppressContent (stack)) { ctx = new HtmlToHtmlTagContext (tag); callback (ctx, htmlWriter); } } break; } } htmlWriter.Flush (); } if (!string.IsNullOrEmpty (Footer)) { if (FooterFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml (); using (var sr = new StringReader (Footer)) converter.Convert (sr, writer); } else { writer.Write (Footer); } } }
/// <summary> /// Convert the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </summary> /// <remarks> /// Converts the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </remarks> /// <param name="reader">The text reader.</param> /// <param name="writer">The text writer.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="reader"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="writer"/> is <c>null</c>.</para> /// </exception> public override void Convert(TextReader reader, TextWriter writer) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (!string.IsNullOrEmpty(Header)) { if (HeaderFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml(); using (var sr = new StringReader(Header)) converter.Convert(sr, writer); } else { writer.Write(Header); } } using (var htmlWriter = new HtmlWriter(writer)) { var callback = HtmlTagCallback ?? DefaultHtmlTagCallback; var stack = new List <FlowedToHtmlTagContext> (); var para = new StringBuilder(); int currentQuoteDepth = 0; int paraQuoteDepth = -1; int quoteDepth; string line; while ((line = reader.ReadLine()) != null) { // unquote the line line = Unquote(line, out quoteDepth); // remove space-stuffing if (line.Length > 0 && line[0] == ' ') { line = line.Substring(1); } if (para.Length == 0) { paraQuoteDepth = quoteDepth; } else if (quoteDepth != paraQuoteDepth) { // Note: according to rfc3676, when a folded line has a different quote // depth than the previous line, then quote-depth rules win and we need // to treat this as a new paragraph. WriteParagraph(htmlWriter, stack, ref currentQuoteDepth, para, paraQuoteDepth); paraQuoteDepth = quoteDepth; para.Length = 0; } para.Append(line); if (line.Length == 0 || line[line.Length - 1] != ' ') { // line did not end with a space, so the next line will start a new paragraph WriteParagraph(htmlWriter, stack, ref currentQuoteDepth, para, paraQuoteDepth); paraQuoteDepth = 0; para.Length = 0; } else if (DeleteSpace) { // Note: lines ending with a space mean that the next line is a continuation para.Length--; } } for (int i = stack.Count; i > 0; i--) { var ctx = stack[i - 1]; ctx.SetIsEndTag(true); if (ctx.InvokeCallbackForEndTag) { callback(ctx, htmlWriter); } else { ctx.WriteTag(htmlWriter); } } htmlWriter.Flush(); } if (!string.IsNullOrEmpty(Footer)) { if (FooterFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml(); using (var sr = new StringReader(Footer)) converter.Convert(sr, writer); } else { writer.Write(Footer); } } }
/// <summary> /// Convert the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </summary> /// <remarks> /// Converts the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </remarks> /// <param name="reader">The text reader.</param> /// <param name="writer">The text writer.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="reader"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="writer"/> is <c>null</c>.</para> /// </exception> public override void Convert(TextReader reader, TextWriter writer) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (!string.IsNullOrEmpty(Header)) { if (HeaderFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml { OutputHtmlFragment = true }; using (var sr = new StringReader(Header)) converter.Convert(sr, writer); } else { writer.Write(Header); } } using (var htmlWriter = new HtmlWriter(writer)) { var callback = HtmlTagCallback ?? DefaultHtmlTagCallback; var stack = new List <HtmlToHtmlTagContext> (); var tokenizer = new HtmlTokenizer(reader); HtmlToHtmlTagContext ctx; HtmlToken token; while (tokenizer.ReadNextToken(out token)) { switch (token.Kind) { default: if (!SuppressContent(stack)) { htmlWriter.WriteToken(token); } break; case HtmlTokenKind.Comment: if (!FilterComments && !SuppressContent(stack)) { htmlWriter.WriteToken(token); } break; case HtmlTokenKind.Tag: var tag = (HtmlTagToken)token; if (!tag.IsEndTag) { //if (NormalizeHtml && AutoClosingTags.Contains (startTag.TagName) && // (ctx = Pop (stack, startTag.TagName)) != null && // ctx.InvokeCallbackForEndTag && !SuppressContent (stack)) { // var value = string.Format ("</{0}>", ctx.TagName); // var name = ctx.TagName; // // ctx = new HtmlToHtmlTagContext (new HtmlTokenTag (HtmlTokenKind.EndTag, name, value)) { // InvokeCallbackForEndTag = ctx.InvokeCallbackForEndTag, // SuppressInnerContent = ctx.SuppressInnerContent, // DeleteEndTag = ctx.DeleteEndTag, // DeleteTag = ctx.DeleteTag // }; // callback (ctx, htmlWriter); //} if (!tag.IsEmptyElement) { ctx = new HtmlToHtmlTagContext(tag); if (FilterHtml && ctx.TagId == HtmlTagId.Script) { ctx.SuppressInnerContent = true; ctx.DeleteEndTag = true; ctx.DeleteTag = true; } else if (!SuppressContent(stack)) { callback(ctx, htmlWriter); } stack.Add(ctx); } else if (!SuppressContent(stack)) { ctx = new HtmlToHtmlTagContext(tag); if (!FilterHtml || ctx.TagId != HtmlTagId.Script) { callback(ctx, htmlWriter); } } } else { if ((ctx = Pop(stack, tag.Name)) != null) { if (!SuppressContent(stack)) { if (ctx.InvokeCallbackForEndTag) { ctx = new HtmlToHtmlTagContext(tag) { InvokeCallbackForEndTag = ctx.InvokeCallbackForEndTag, SuppressInnerContent = ctx.SuppressInnerContent, DeleteEndTag = ctx.DeleteEndTag, DeleteTag = ctx.DeleteTag }; callback(ctx, htmlWriter); } else if (!ctx.DeleteEndTag) { htmlWriter.WriteEndTag(tag.Name); } } } else if (!SuppressContent(stack)) { ctx = new HtmlToHtmlTagContext(tag); callback(ctx, htmlWriter); } } break; } } htmlWriter.Flush(); } if (!string.IsNullOrEmpty(Footer)) { if (FooterFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml { OutputHtmlFragment = true }; using (var sr = new StringReader(Footer)) converter.Convert(sr, writer); } else { writer.Write(Footer); } } }
/// <summary> /// Convert the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </summary> /// <remarks> /// Converts the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </remarks> /// <param name="reader">The text reader.</param> /// <param name="writer">The text writer.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="reader"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="writer"/> is <c>null</c>.</para> /// </exception> public override void Convert (TextReader reader, TextWriter writer) { if (reader == null) throw new ArgumentNullException (nameof (reader)); if (writer == null) throw new ArgumentNullException (nameof (writer)); if (!string.IsNullOrEmpty (Header)) { if (HeaderFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml (); using (var sr = new StringReader (Header)) converter.Convert (sr, writer); } else { writer.Write (Header); } } using (var htmlWriter = new HtmlWriter (writer)) { var callback = HtmlTagCallback ?? DefaultHtmlTagCallback; var stack = new List<FlowedToHtmlTagContext> (); var para = new StringBuilder (); int currentQuoteDepth = 0; int paraQuoteDepth = -1; int quoteDepth; string line; while ((line = reader.ReadLine ()) != null) { // unquote the line line = Unquote (line, out quoteDepth); // remove space-stuffing if (line.Length > 0 && line[0] == ' ') line = line.Substring (1); if (para.Length == 0) { paraQuoteDepth = quoteDepth; } else if (quoteDepth != paraQuoteDepth) { // Note: according to rfc3676, when a folded line has a different quote // depth than the previous line, then quote-depth rules win and we need // to treat this as a new paragraph. WriteParagraph (htmlWriter, stack, ref currentQuoteDepth, para, paraQuoteDepth); paraQuoteDepth = quoteDepth; para.Length = 0; } para.Append (line); if (line.Length == 0 || line[line.Length - 1] != ' ') { // line did not end with a space, so the next line will start a new paragraph WriteParagraph (htmlWriter, stack, ref currentQuoteDepth, para, paraQuoteDepth); paraQuoteDepth = 0; para.Length = 0; } else if (DeleteSpace) { // Note: lines ending with a space mean that the next line is a continuation para.Length--; } } for (int i = stack.Count; i > 0; i--) { var ctx = stack[i - 1]; ctx.SetIsEndTag (true); if (ctx.InvokeCallbackForEndTag) callback (ctx, htmlWriter); else ctx.WriteTag (htmlWriter); } htmlWriter.Flush (); } if (!string.IsNullOrEmpty (Footer)) { if (FooterFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml (); using (var sr = new StringReader (Footer)) converter.Convert (sr, writer); } else { writer.Write (Footer); } } }
void RenderText (TextPart text) { string html; if (text.IsHtml) { // the text content is already in HTML format html = text.Text; } else if (text.IsFlowed) { var converter = new FlowedToHtml (); string delsp; // the delsp parameter specifies whether or not to delete spaces at the end of flowed lines if (!text.ContentType.Parameters.TryGetValue ("delsp", out delsp)) delsp = "no"; if (string.Compare (delsp, "yes", StringComparison.OrdinalIgnoreCase) == 0) converter.DeleteSpace = true; html = converter.Convert (text.Text); } else { html = new TextToHtml ().Convert (text.Text); } webView.LoadHtmlString (html, new NSUrl ("index.html")); }
protected override void VisitTextPart (TextPart entity) { TextConverter converter; if (body != null) { // since we've already found the body, treat this as an attachment attachments.Add (entity); return; } if (entity.IsHtml) { converter = new HtmlToHtml { HtmlTagCallback = HtmlTagCallback }; } else if (entity.IsFlowed) { var flowed = new FlowedToHtml (); string delsp; if (entity.ContentType.Parameters.TryGetValue ("delsp", out delsp)) flowed.DeleteSpace = delsp.ToLowerInvariant () == "yes"; converter = flowed; } else { converter = new TextToHtml (); } body = converter.Convert (entity.Text); }
/// <summary> /// Convert the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </summary> /// <remarks> /// Converts the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </remarks> /// <param name="reader">The text reader.</param> /// <param name="writer">The text writer.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="reader"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="writer"/> is <c>null</c>.</para> /// </exception> public override void Convert(TextReader reader, TextWriter writer) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (!OutputHtmlFragment) { writer.Write("<html><body>"); } if (!string.IsNullOrEmpty(Header)) { if (HeaderFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml { OutputHtmlFragment = true }; using (var sr = new StringReader(Header)) converter.Convert(sr, writer); } else { writer.Write(Header); } } using (var htmlWriter = new HtmlWriter(writer)) { var callback = HtmlTagCallback ?? DefaultHtmlTagCallback; var stack = new List <TextToHtmlTagContext> (); int currentQuoteDepth = 0, quoteDepth; TextToHtmlTagContext ctx; string line; while ((line = reader.ReadLine()) != null) { line = Unquote(line, out quoteDepth); while (currentQuoteDepth < quoteDepth) { ctx = new TextToHtmlTagContext(HtmlTagId.BlockQuote); callback(ctx, htmlWriter); currentQuoteDepth++; stack.Add(ctx); } while (quoteDepth < currentQuoteDepth) { ctx = stack[stack.Count - 1]; stack.RemoveAt(stack.Count - 1); if (!SuppressContent(stack) && !ctx.DeleteEndTag) { ctx.SetIsEndTag(true); if (ctx.InvokeCallbackForEndTag) { callback(ctx, htmlWriter); } else { ctx.WriteTag(htmlWriter); } } if (ctx.TagId == HtmlTagId.BlockQuote) { currentQuoteDepth--; } } if (!SuppressContent(stack)) { WriteText(htmlWriter, line); ctx = new TextToHtmlTagContext(HtmlTagId.Br); callback(ctx, htmlWriter); } } for (int i = stack.Count; i > 0; i--) { ctx = stack[i - 1]; ctx.SetIsEndTag(true); if (ctx.InvokeCallbackForEndTag) { callback(ctx, htmlWriter); } else { ctx.WriteTag(htmlWriter); } } htmlWriter.Flush(); } if (!string.IsNullOrEmpty(Footer)) { if (FooterFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml { OutputHtmlFragment = true }; using (var sr = new StringReader(Footer)) converter.Convert(sr, writer); } else { writer.Write(Footer); } } if (!OutputHtmlFragment) { writer.Write("</body></html>"); } }
/// <summary> /// Convert the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </summary> /// <remarks> /// Converts the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </remarks> /// <param name="reader">The text reader.</param> /// <param name="writer">The text writer.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="reader"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="writer"/> is <c>null</c>.</para> /// </exception> public override void Convert (TextReader reader, TextWriter writer) { if (reader == null) throw new ArgumentNullException (nameof (reader)); if (writer == null) throw new ArgumentNullException (nameof (writer)); if (!string.IsNullOrEmpty (Header)) { if (HeaderFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml (); using (var sr = new StringReader (Header)) converter.Convert (sr, writer); } else { writer.Write (Header); } } using (var htmlWriter = new HtmlWriter (writer)) { var callback = HtmlTagCallback ?? DefaultHtmlTagCallback; var stack = new List<TextToHtmlTagContext> (); int currentQuoteDepth = 0, quoteDepth; TextToHtmlTagContext ctx; string line; while ((line = reader.ReadLine ()) != null) { line = Unquote (line, out quoteDepth); while (currentQuoteDepth < quoteDepth) { ctx = new TextToHtmlTagContext (HtmlTagId.BlockQuote); callback (ctx, htmlWriter); currentQuoteDepth++; stack.Add (ctx); } while (quoteDepth < currentQuoteDepth) { ctx = stack[stack.Count - 1]; stack.RemoveAt (stack.Count - 1); if (!SuppressContent (stack) && !ctx.DeleteEndTag) { ctx.SetIsEndTag (true); if (ctx.InvokeCallbackForEndTag) callback (ctx, htmlWriter); else ctx.WriteTag (htmlWriter); } if (ctx.TagId == HtmlTagId.BlockQuote) currentQuoteDepth--; } if (!SuppressContent (stack)) { WriteText (htmlWriter, line); ctx = new TextToHtmlTagContext (HtmlTagId.Br); callback (ctx, htmlWriter); } } for (int i = stack.Count; i > 0; i--) { ctx = stack[i - 1]; ctx.SetIsEndTag (true); if (ctx.InvokeCallbackForEndTag) callback (ctx, htmlWriter); else ctx.WriteTag (htmlWriter); } htmlWriter.Flush (); } if (!string.IsNullOrEmpty (Footer)) { if (FooterFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml (); using (var sr = new StringReader (Footer)) converter.Convert (sr, writer); } else { writer.Write (Footer); } } }
public void TestSimpleTextWithUrlsToHtml () { const string expected = "Check out <a href=\"http://www.xamarin.com\">http://www.xamarin.com</a> - it's amazing!<br/>"; string text = "Check out http://www.xamarin.com - it's amazing!" + Environment.NewLine; var converter = new TextToHtml (); var result = converter.Convert (text); Assert.AreEqual (expected, result); }
public void TestSimpleTextToHtml () { const string expected = "This is some sample text. This is line #1.<br/>" + "This is line #2.<br/>" + "And this is line #3.<br/>"; string text = "This is some sample text. This is line #1." + Environment.NewLine + "This is line #2." + Environment.NewLine + "And this is line #3." + Environment.NewLine; var converter = new TextToHtml (); var result = converter.Convert (text); Assert.AreEqual (expected, result); }
protected internal override void VisitTextPart (TextPart entity) { TextConverter converter; if (body != null) { base.VisitTextPart (entity); return; } if (entity.IsHtml) { converter = new HtmlToHtml { HtmlTagCallback = HtmlTagCallback }; } else if (entity.IsFlowed) { var flowed = new FlowedToHtml (); string delsp; if (entity.ContentType.Parameters.TryGetValue ("delsp", out delsp)) flowed.DeleteSpace = delsp.ToLowerInvariant () == "yes"; converter = flowed; } else { converter = new TextToHtml (); } body = converter.Convert (entity.Text); base.VisitTextPart (entity); }
/// <summary> /// Convert the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </summary> /// <remarks> /// Converts the contents of <paramref name="reader"/> from the <see cref="InputFormat"/> to the /// <see cref="OutputFormat"/> and uses the <paramref name="writer"/> to write the resulting text. /// </remarks> /// <param name="reader">The text reader.</param> /// <param name="writer">The text writer.</param> /// <exception cref="System.ArgumentNullException"> /// <para><paramref name="reader"/> is <c>null</c>.</para> /// <para>-or-</para> /// <para><paramref name="writer"/> is <c>null</c>.</para> /// </exception> public override void Convert(TextReader reader, TextWriter writer) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (!string.IsNullOrEmpty(Header)) { if (HeaderFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml(); using (var sr = new StringReader(Header)) converter.Convert(sr, writer); } else { writer.Write(Header); } } using (var htmlWriter = new HtmlWriter(writer)) { var callback = HtmlTagCallback ?? DefaultHtmlTagCallback; var stack = new List <HtmlToHtmlTagContext> (); var tokenizer = new HtmlTokenizer(reader); HtmlToHtmlTagContext ctx; HtmlToken token; while (tokenizer.ReadNextToken(out token)) { switch (token.Kind) { default: if (!SuppressContent(stack)) { htmlWriter.WriteToken(token); } break; case HtmlTokenKind.Tag: var tag = (HtmlTagToken)token; if (!tag.IsEndTag) { if (!tag.IsEmptyElement) { ctx = new HtmlToHtmlTagContext(tag); if (FilterHtml && ctx.TagId == HtmlTagId.Script) { ctx.SuppressInnerContent = true; ctx.DeleteEndTag = true; ctx.DeleteTag = true; } else if (!SuppressContent(stack)) { callback(ctx, htmlWriter); } stack.Add(ctx); } else if (!SuppressContent(stack)) { ctx = new HtmlToHtmlTagContext(tag); if (!FilterHtml || ctx.TagId != HtmlTagId.Script) { callback(ctx, htmlWriter); } } } else { if ((ctx = Pop(stack, tag.Name)) != null) { if (!SuppressContent(stack)) { if (ctx.InvokeCallbackForEndTag) { ctx = new HtmlToHtmlTagContext(tag) { InvokeCallbackForEndTag = ctx.InvokeCallbackForEndTag, SuppressInnerContent = ctx.SuppressInnerContent, DeleteEndTag = ctx.DeleteEndTag, DeleteTag = ctx.DeleteTag }; callback(ctx, htmlWriter); } else if (!ctx.DeleteEndTag) { htmlWriter.WriteEndTag(tag.Name); } } } else if (!SuppressContent(stack)) { ctx = new HtmlToHtmlTagContext(tag); callback(ctx, htmlWriter); } } break; case HtmlTokenKind.Comment: if (!StripComments) { htmlWriter.WriteToken(token); } break; } } htmlWriter.Flush(); } if (!string.IsNullOrEmpty(Footer)) { if (FooterFormat == HeaderFooterFormat.Text) { var converter = new TextToHtml(); using (var sr = new StringReader(Footer)) converter.Convert(sr, writer); } else { writer.Write(Footer); } } }