From 5e7f7109e19b33bc142aa7b06e9044420232a578 Mon Sep 17 00:00:00 2001
From: ringabout <43030857+ringabout@users.noreply.github.com>
Date: Tue, 24 Jan 2023 20:35:19 +0800
Subject: [PATCH] fixes #21290; deindent if the last same level is a text node
(#21293)
* fixes #21290; deindent if the last same level is a text node
* add one more test
---
lib/pure/xmltree.nim | 37 +++++++++++++++++++++----------------
tests/stdlib/txmltree.nim | 18 +++++++++++++++++-
2 files changed, 38 insertions(+), 17 deletions(-)
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 7a2cebe87..c3923ca50 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -723,20 +723,8 @@ proc addIndent(result: var string, indent: int, addNewLines: bool) =
for i in 1 .. indent:
result.add(' ')
-proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
- addNewLines = true) =
- ## Adds the textual representation of `n` to string `result`.
- runnableExamples:
- var
- a = newElement("firstTag")
- b = newText("my text")
- c = newComment("my comment")
- s = ""
- s.add(c)
- s.add(a)
- s.add(b)
- assert s == "my text"
-
+proc addImpl(result: var string, n: XmlNode, indent = 0, indWidth = 2,
+ addNewLines = true, lastNodeIsText = false) =
proc noWhitespace(n: XmlNode): bool =
for i in 0 ..< n.len:
if n[i].kind in {xnText, xnEntity}: return true
@@ -756,7 +744,7 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
case n.k
of xnElement:
- if indent > 0:
+ if indent > 0 and not lastNodeIsText:
result.addIndent(indent, addNewLines)
let
@@ -785,8 +773,10 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
else:
indent+indWidth
result.add('>')
+ var lastNodeIsText = false
for i in 0 ..< n.len:
- result.add(n[i], indentNext, indWidth, addNewLines)
+ result.addImpl(n[i], indentNext, indWidth, addNewLines, lastNodeIsText)
+ lastNodeIsText = n[i].kind == xnText
if not n.noWhitespace():
result.addIndent(indent, addNewLines)
@@ -811,6 +801,21 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
result.add(n.fText)
result.add(';')
+proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
+ addNewLines = true) {.inline.} =
+ ## Adds the textual representation of `n` to string `result`.
+ runnableExamples:
+ var
+ a = newElement("firstTag")
+ b = newText("my text")
+ c = newComment("my comment")
+ s = ""
+ s.add(c)
+ s.add(a)
+ s.add(b)
+ assert s == "my text"
+ result.addImpl(n, indent, indWidth, addNewLines)
+
proc `$`*(n: XmlNode): string =
## Converts `n` into its string representation.
##
diff --git a/tests/stdlib/txmltree.nim b/tests/stdlib/txmltree.nim
index f6b7c62e8..4362f5ec3 100644
--- a/tests/stdlib/txmltree.nim
+++ b/tests/stdlib/txmltree.nim
@@ -1,4 +1,4 @@
-import std/[xmltree, assertions]
+import std/[xmltree, assertions, xmlparser]
block:
@@ -83,3 +83,19 @@ block:
x.add newElement("sonTag")
x.add newEntity("my entity")
doAssert $x == "my text&my entity;"
+
+block: # bug #21290
+ let x = newXmlTree("foo",[
+ newXmlTree("bar",[
+ newText("Hola"),
+ newXmlTree("qux",[
+ newXmlTree("plugh",[])
+ ])
+ ])
+ ])
+
+ let s = $x
+ doAssert $parseXml(s) == s
+ doAssert s == """
+ Hola
+"""