Repository: clientIO/joint (JavaScript)

Issue:
Vectorizer: Input Space Character Becomes \u00A0 (Non-Breaking Space)
## Description

The conversion from `\u0020` to `\u00A0` was introduced for historical reasons but is no longer necessary and can be safely removed from the codebase.

See [`V.sanitizeText()`](https://github.com/clientIO/joint/blob/master/packages/joint-core/src/V/index.mjs#L1332-L1340).

Discussed in https://github.com/clientIO/joint/discussions/2966




Fix (patch):
diff --git a/packages/joint-core/src/V/index.mjs b/packages/joint-core/src/V/index.mjs
index 15814d233..12fb117ea 100644
--- a/packages/joint-core/src/V/index.mjs
+++ b/packages/joint-core/src/V/index.mjs
@@ -485,10 +485,19 @@ const V = (function() {
 
         if (content && typeof content !== 'string') throw new Error('Vectorizer: text() expects the first argument to be a string.');
 
-        // Replace all spaces with the Unicode No-break space (http://www.fileformat.info/info/unicode/char/a0/index.htm).
-        // IE would otherwise collapse all spaces into one.
-        content = V.sanitizeText(content);
         opt || (opt = {});
+
+        // Backwards-compatibility: if no content was provided, treat it as an
+        // empty string so that subsequent string operations (e.g. split) do
+        // not throw and behaviour matches the previous implementation that
+        // always sanitised the input.
+        if (content == null) content = '';
+
+        if (opt.useNoBreakSpace) {
+            // Replace all spaces with the Unicode No-break space (http://www.fileformat.info/info/unicode/char/a0/index.htm).
+            // IE would otherwise collapse all spaces into one.
+            content = V.sanitizeText(content);
+        }
         // Should we allow the text to be selected?
         var displayEmpty = opt.displayEmpty;
         // End of Line character
@@ -1332,6 +1341,9 @@ const V = (function() {
     // also exposed so that the programmer can use it in case he needs to. This is useful e.g. in tests
     // when you want to compare the actual DOM text content without having to add the unicode character in
     // the place of all spaces.
+    /** 
+     * @deprecated Use regular spaces and rely on xml:space="preserve" instead.
+     */
     V.sanitizeText = function(text) {
 
         return (text || '').replace(/ /g, '\u00A0');
diff --git a/packages/joint-core/src/dia/attributes/text.mjs b/packages/joint-core/src/dia/attributes/text.mjs
index 7a68eacdd..3a3f85bac 100644
--- a/packages/joint-core/src/dia/attributes/text.mjs
+++ b/packages/joint-core/src/dia/attributes/text.mjs
@@ -54,9 +54,10 @@ const textAttributesNS = {
             const eol = attrs.eol;
             const x = attrs.x;
             let textPath = attrs['text-path'];
+            const useNoBreakSpace = attrs['use-no-break-space'] === true;
             // Update the text only if there was a change in the string
             // or any of its attributes.
-            const textHash = JSON.stringify([text, lineHeight, annotations, textVerticalAnchor, eol, displayEmpty, textPath, x, fontSize]);
+            const textHash = JSON.stringify([text, lineHeight, annotations, textVerticalAnchor, eol, displayEmpty, textPath, x, fontSize, useNoBreakSpace]);
             if (cache === undefined || cache !== textHash) {
                 // Chrome bug:
                 // <tspan> positions defined as `em` are not updated
@@ -79,7 +80,8 @@ const textAttributesNS = {
                     x,
                     textVerticalAnchor,
                     eol,
-                    displayEmpty
+                    displayEmpty,
+                    useNoBreakSpace
                 });
                 $.data.set(node, cacheName, textHash);
             }
diff --git a/packages/joint-core/types/vectorizer.d.ts b/packages/joint-core/types/vectorizer.d.ts
index 988a7ff90..466ceed5d 100644
--- a/packages/joint-core/types/vectorizer.d.ts
+++ b/packages/joint-core/types/vectorizer.d.ts
@@ -27,6 +27,7 @@ export namespace Vectorizer {
         annotations?: TextAnnotation[];
         includeAnnotationIndices?: boolean;
         displayEmpty?: boolean;
+        useNoBreakSpace?: boolean;
     }
 
     interface GetBBoxOptions {
@@ -233,6 +234,9 @@ interface VStatic {
 
     ensureId(node: SVGElement | VElement): string;
 
+    /** 
+     * @deprecated Use regular spaces and rely on xml:space="preserve" instead.
+     */
     sanitizeText(text: string): string;
 
     isUndefined(value: any): boolean;