|
1 | 1 | using System.Buffers; |
2 | | -using System.Text.Json; |
3 | 2 |
|
4 | 3 | namespace Cubist.Helium; |
5 | 4 |
|
6 | 5 | /// <summary> Extension methods to write formatted and indented html. </summary> |
7 | 6 | public static class PrettyPrintExtensions |
8 | 7 | { |
9 | | - private record PrettyPrintContext(bool Indent); |
10 | | - |
11 | 8 | /// <summary> pretty-prints this node to a string </summary> |
12 | 9 | public static string PrettyPrint(this Node n) |
13 | 10 | { |
14 | | - var sw = new StringWriter(); |
15 | | - var indent = new IndentWriter(sw); |
16 | | - PrettyPrintNode(n, indent); |
| 11 | + using var sw = new StringWriter(); |
| 12 | + using var iw = new IndentWriter(sw); |
| 13 | + n.PrettyPrintTo(iw); |
17 | 14 | return sw.ToString(); |
18 | 15 | } |
19 | 16 |
|
20 | | - /// <summary> pretty-prints this node to the indent writer </summary> |
21 | | - public static void PrettyPrintTo(this Node n, IndentWriter w) |
22 | | - => PrettyPrintNode(n, w); |
23 | | - |
24 | | - private static void PrettyPrintNode(Node n, IndentWriter w) |
25 | | - { |
26 | | - switch (n) |
27 | | - { |
28 | | - case He he: |
29 | | - PrettyPrintElement(he, w); |
30 | | - break; |
31 | | - case Text text: |
32 | | - text.WriteTo(w); |
33 | | - break; |
34 | | - case Json json: |
35 | | - PrettyPrintJson(json, w); |
36 | | - break; |
37 | | - case CData cdata: |
38 | | - cdata.WriteTo(w); |
39 | | - break; |
40 | | - case Comment comment: |
41 | | - comment.WriteTo(w); |
42 | | - break; |
43 | | - case Css css: |
44 | | - css.WriteTo(w); |
45 | | - break; |
46 | | - case HtmlDocument doc: |
47 | | - PrettyPrintDocument(doc, w); |
48 | | - break; |
49 | | - } |
50 | | - } |
51 | | - |
52 | | - private static void PrettyPrintJson(Json json, IndentWriter w) |
53 | | - { |
54 | | - var options = new JsonSerializerOptions(json.Options) { WriteIndented = true }; |
55 | | - var str = JsonSerializer.Serialize(json.Value, options); |
56 | | - w.WriteLine(str); |
57 | | - } |
58 | | - |
59 | | - |
60 | | - private static bool IsInline(this Node n) |
| 17 | + /// <summary> Returns true if this is an inline node, with only inline child nodes </summary> |
| 18 | + public static bool IsInline(this Node n) |
61 | 19 | => n is CData || |
62 | 20 | (n is Text t && !t.Value.Contains('\n')) || |
63 | 21 | (n is He he && he.Tag.IsInline() && |
@@ -102,76 +60,6 @@ public static bool SplitNewline(this ReadOnlySpan<char> s, out ReadOnlySpan<char |
102 | 60 | return false; |
103 | 61 | } |
104 | 62 |
|
105 | | - private static void PrettyPrintElement(He he, IndentWriter w) |
106 | | - { |
107 | | - var indent = !he.IsInline(); |
108 | | - |
109 | | - he.WriteStartTag(w); |
110 | | - |
111 | | - var allChildrenInline = he.All(n => n.IsInline()); |
112 | | - using (w.Indent()) |
113 | | - { |
114 | | - if (indent && !allChildrenInline) |
115 | | - w.WriteLine(); |
116 | | - |
117 | | - foreach (var child in he) |
118 | | - PrettyPrintNode(child, w); |
119 | | - |
120 | | - if (indent && !allChildrenInline && he.Count > 0 && he.Last().IsInline()) |
121 | | - w.WriteLine(); |
122 | | - } |
123 | | - |
124 | | - |
125 | | - if (!he.Tag.IsVoid()) |
126 | | - { |
127 | | - he.WriteCloseTag(w); |
128 | | - |
129 | | - } |
130 | | - if (indent) |
131 | | - w.WriteLine(); |
132 | | - |
133 | | - } |
134 | | - |
135 | | - private static void PrettyPrintDocument(HtmlDocument doc, IndentWriter w) |
136 | | - { |
137 | | - doc.DocType.WriteTo(w); |
138 | | - w.WriteLine(); |
139 | | - doc.Html.WriteStartTag(w); |
140 | | - |
141 | | - w.WriteLine(); |
142 | | - doc.Head.WriteStartTag(w); |
143 | | - w.WriteLine(); |
144 | | - |
145 | | - using (w.Indent()) |
146 | | - { |
147 | | - foreach (var child in doc.Head) |
148 | | - { |
149 | | - PrettyPrintNode(child, w); |
150 | | - if (child is He e && e.Tag.IsVoid()) |
151 | | - w.WriteLine(); |
152 | | - } |
153 | | - } |
154 | | - |
155 | | - doc.Head.WriteCloseTag(w); |
156 | | - w.WriteLine(); |
157 | | - |
158 | | - doc.Body.WriteStartTag(w); |
159 | | - w.WriteLine(); |
160 | | - |
161 | | - using (w.Indent()) |
162 | | - { |
163 | | - foreach (var child in doc.Body) |
164 | | - { |
165 | | - PrettyPrintNode(child, w); |
166 | | - } |
167 | | - } |
168 | | - |
169 | | - doc.Body.WriteCloseTag(w); |
170 | | - w.WriteLine(); |
171 | | - |
172 | | - doc.Html.WriteCloseTag(w); |
173 | | - } |
174 | | - |
175 | 63 | private static readonly ArrayPool<char> _indents = ArrayPool<char>.Create(); |
176 | 64 |
|
177 | 65 | /// <summary> Writes the indent whitespace for the given <paramref name="level"/> </summary> |
|
0 commit comments