diff --git a/src/FSharp.Data.Html.Core/HtmlNode.fs b/src/FSharp.Data.Html.Core/HtmlNode.fs
index 217a1c8ee..29a608d99 100644
--- a/src/FSharp.Data.Html.Core/HtmlNode.fs
+++ b/src/FSharp.Data.Html.Core/HtmlNode.fs
@@ -118,8 +118,9 @@ type HtmlNode =
/// The actual content
static member NewCData content = HtmlCData(content)
- override x.ToString() =
- let sb = StringBuilder()
+ /// Serialize this node into an existing StringBuilder.
+ /// Used by HtmlDocument.ToString() to avoid creating an intermediate string per element.
+ member internal x.SerializeTo(sb: StringBuilder, indentation: int, canAddNewLine: bool, insidePre: bool) =
let append (str: string) = sb.Append str |> ignore
let appendEndTag name =
@@ -127,16 +128,16 @@ type HtmlNode =
append name
append ">"
- let newLine indentation plus =
+ let newLine ind plus =
sb.AppendLine() |> ignore
- sb.Append(' ', indentation + plus) |> ignore
+ sb.Append(' ', ind + plus) |> ignore
// serialization uses an explicit work stack instead of call-stack recursion:
// the parser accepts arbitrarily deep documents (it uses its own stack), so
// ToString must not StackOverflow on them either
let work = System.Collections.Generic.Stack unit>()
- let rec serialize indentation canAddNewLine insidePre html =
+ let rec serialize ind canAdd inPre html =
match html with
| HtmlElement(name, attributes, elements) ->
let onlyText =
@@ -146,10 +147,10 @@ type HtmlNode =
| _ -> false)
let isPreTag = name = "pre"
- let nowInsidePre = insidePre || isPreTag
+ let nowInsidePre = inPre || isPreTag
- if canAddNewLine && not insidePre && not (onlyText || isPreTag) then
- newLine indentation 0
+ if canAdd && not inPre && not (onlyText || isPreTag) then
+ newLine ind 0
append "<"
append name
@@ -169,13 +170,13 @@ type HtmlNode =
else
append ">"
- if not insidePre && not (onlyText || isPreTag) then
- newLine indentation 2
+ if not inPre && not (onlyText || isPreTag) then
+ newLine ind 2
// pushed first so it runs after all children are processed
work.Push(fun () ->
- if not insidePre && not (onlyText || isPreTag) then
- newLine indentation 0
+ if not inPre && not (onlyText || isPreTag) then
+ newLine ind 0
appendEndTag name)
@@ -186,7 +187,7 @@ type HtmlNode =
for i in elements.Length - 1 .. -1 .. 0 do
let element = elements.[i]
let canAddNewLine = i > 0
- work.Push(fun () -> serialize (indentation + 2) canAddNewLine nowInsidePre element)
+ work.Push(fun () -> serialize (ind + 2) canAddNewLine nowInsidePre element)
| HtmlText str -> append str
| HtmlComment str ->
append "