Repository: prettier/plugin-xml
Pull request #705 (2023-08-08 20:13:15)

xml:space="preserve" option


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9679fd6..285a17b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
 
 ## [Unreleased]
 
+### Added
+
+- Respect `xml:space="preserve"` as an override to the `xmlWhitespaceSensitivity` option.
+
 ## [3.1.1] - 2023-07-14
 
 ### Changed
diff --git a/src/printer.js b/src/printer.js
index 8c549c8..3e227f6 100644
--- a/src/printer.js
+++ b/src/printer.js
@@ -26,10 +26,41 @@ function hasIgnoreRanges(comments) {
   return false;
 }
 
-function isWhitespaceIgnorable(node) {
-  const { CData, Comment, reference } = node.children;
+function isWhitespaceIgnorable(opts, attributes, content) {
+  // If the whitespace sensitivity setting is "strict", then we can't ignore the
+  // whitespace.
+  if (opts.xmlWhitespaceSensitivity === "strict") {
+    return false;
+  }
+
+  // If there is an xml:space attribute set to "preserve", then we can't ignore
+  // the whitespace.
+  if (
+    attributes &&
+    attributes.some(
+      (attribute) =>
+        attribute &&
+        attribute.children.Name[0].image === "xml:space" &&
+        attribute.children.STRING[0].image.slice(1, -1) === "preserve"
+    )
+  ) {
+    return false;
+  }
 
-  return !CData && !reference && !hasIgnoreRanges(Comment);
+  // If there are character data or reference nodes in the content, then we
+  // can't ignore the whitespace.
+  if (content.children.CData || content.children.reference) {
+    return false;
+  }
+
+  // If there are comments in the content and the comments are ignore ranges,
+  // then we can't ignore the whitespace.
+  if (hasIgnoreRanges(content.children.Comment)) {
+    return false;
+  }
+
+  // Otherwise we can.
+  return true;
 }
 
 function printIToken(path) {
@@ -451,10 +482,7 @@ function printElement(path, opts, print) {
     END[0].image
   ]);
 
-  if (
-    opts.xmlWhitespaceSensitivity !== "strict" &&
-    isWhitespaceIgnorable(content[0])
-  ) {
+  if (isWhitespaceIgnorable(opts, attribute, content[0])) {
     const fragments = path.call(
       (childrenPath) => printElementFragments(childrenPath, opts, print),
       "children",


Test patch:
diff --git a/test/__snapshots__/format.test.js.snap b/test/__snapshots__/format.test.js.snap
index 7105dee..90b1f97 100644
--- a/test/__snapshots__/format.test.js.snap
+++ b/test/__snapshots__/format.test.js.snap
@@ -80,6 +80,10 @@ use {
     <content />
   </div>
 
+  <div xml:space="preserve">
+      <content />
+  </div>
+
   <div
     verylongattribute="verylongvalue"
     anotherverylongattribute="anotherverylongvalue" />
@@ -203,6 +207,10 @@ use {
     <content/>
   </div>
 
+  <div xml:space="preserve">
+      <content/>
+  </div>
+
   <div
     verylongattribute="verylongvalue"
     anotherverylongattribute="anotherverylongvalue"/>
@@ -319,6 +327,10 @@ use {
     <content />
   </div>
 
+  <div xml:space="preserve">
+      <content />
+  </div>
+
   <div
     verylongattribute="verylongvalue"
     anotherverylongattribute="anotherverylongvalue"
@@ -459,6 +471,10 @@ use {
     <content />
   </div>
 
+  <div xml:space="preserve">
+      <content />
+  </div>
+
   <div
     verylongattribute="verylongvalue"
     anotherverylongattribute="anotherverylongvalue"
@@ -588,6 +604,10 @@ use {
     <content />
   </div>
 
+  <div xml:space="preserve">
+      <content />
+  </div>
+
   <div
     verylongattribute="verylongvalue"
     anotherverylongattribute="anotherverylongvalue"
@@ -707,6 +727,10 @@ use {
     <content />
   </div>
 
+  <div xml:space="preserve">
+      <content />
+  </div>
+
   <div
     verylongattribute="verylongvalue"
     anotherverylongattribute="anotherverylongvalue"
@@ -826,6 +850,10 @@ use {
     <content />
   </div>
 
+  <div xml:space='preserve'>
+      <content />
+  </div>
+
   <div
     verylongattribute='verylongvalue'
     anotherverylongattribute='anotherverylongvalue'
@@ -954,6 +982,10 @@ use {
     <content/>
   </div>
 
+  <div xml:space="preserve">
+      <content/>
+  </div>
+
   <div
     verylongattribute="verylongvalue"
     anotherverylongattribute="anotherverylongvalue"
@@ -1082,6 +1114,10 @@ use {
     <content />
   </div>
 
+  <div xml:space="preserve">
+      <content />
+  </div>
+
   <div
     verylongattribute="verylongvalue"
     anotherverylongattribute="anotherverylongvalue"
@@ -1203,6 +1239,10 @@ use {
     <content />
   </div>
 
+  <div xml:space="preserve">
+      <content />
+  </div>
+
   <div
     verylongattribute="verylongvalue"
     anotherverylongattribute="anotherverylongvalue"
diff --git a/test/fixture.xml b/test/fixture.xml
index e87ae5e..8f2142c 100644
--- a/test/fixture.xml
+++ b/test/fixture.xml
@@ -62,6 +62,10 @@
     <content />
   </div>
 
+  <div xml:space="preserve">
+      <content />
+  </div>
+
   <div verylongattribute="verylongvalue" anotherverylongattribute="anotherverylongvalue" />
 
   <div attr1='singleQuotes' att2="doubleQuotes" />