diff --git a/dist/ueblueprint.js b/dist/ueblueprint.js
index 89eafb6..04cf737 100755
--- a/dist/ueblueprint.js
+++ b/dist/ueblueprint.js
@@ -431,22 +431,41 @@ class Utility {
/**
* @param {String} value
*/
- static sanitizeString(value, input = false) {
+ static encodeInputString(value) {
return value
.replace(/\n$/, "") // Remove trailing newline
.replaceAll("\u00A0", " ") // Replace special space symbol
+ .replaceAll("\r\n", String.raw`\r\n`) // Replace newline with \r\n
.replaceAll("\n", String.raw`\r\n`) // Replace newline with \r\n
}
/**
* @param {String} value
*/
- static renderInputString(value) {
+ static decodeInputString(value) {
return value
.replaceAll(" ", "\u00A0") // Replace special space symbol
.replaceAll(String.raw`\r\n`, "
\n") // Replace newline with \r\n
}
+ /**
+ * @param {String} value
+ */
+ static encodeString(value, input = false) {
+ return value
+ .replaceAll("\u00A0", " ") // Replace special space symbol
+ .replaceAll("\n", String.raw`\n`) // Replace newline with \n
+ }
+
+ /**
+ * @param {String} value
+ */
+ static decodeString(value, input = false) {
+ return value
+ .replaceAll(" ", "\u00A0") // Replace special space symbol
+ .replaceAll(String.raw`\n`, "\n") // Replace newline with \n
+ }
+
/**
* @param {String} value
*/
@@ -1263,7 +1282,7 @@ class ISerializer {
this.attributeKeyPrinter = attributeKeyPrinter ?? (k => k.join("."));
}
- writeValue(value) {
+ writeValue(value, fullKey = undefined) {
if (value === null) {
return "()"
}
@@ -1271,13 +1290,13 @@ class ISerializer {
// This is an exact match (and not instanceof) to hit also primitive types (by accessing value.constructor they are converted to objects automatically)
switch (value?.constructor) {
case Function:
- return this.writeValue(value())
+ return this.writeValue(value(), fullKey)
case Boolean:
return Utility.FirstCapital(value.toString())
case Number:
return value.toString()
case String:
- return `"${value}"`
+ return `"${Utility.encodeString(value)}"`
}
if (value instanceof Array) {
return `(${value.map(v => serialize(v) + ",").join("")})`
@@ -1308,7 +1327,7 @@ class ISerializer {
+ this.prefix
+ this.attributeKeyPrinter(fullKey)
+ this.attributeValueConjunctionSign
- + this.writeValue(value);
+ + this.writeValue(value, fullKey);
}
}
if (this.trailingSeparator && result.length && fullKey.length === 1) {
@@ -1371,7 +1390,7 @@ class ObjectSerializer extends ISerializer {
* @param {ObjectEntity} object
*/
write(object) {
- let result = `Begin Object Class=${object.Class.path} Name=${this.writeValue(object.Name)}
+ let result = `Begin Object Class=${object.Class.path} Name=${this.writeValue(object.Name, "Name")}
${this.subWrite([], object)
+ object
.CustomProperties.map(pin =>
@@ -3007,7 +3026,7 @@ class IInputPinTemplate extends PinTemplate {
* @param {PinElement} pin
*/
getInput(pin) {
- return Utility.sanitizeString(
+ return Utility.encodeInputString(
/** @type {HTMLElement} */(pin.querySelector(".ueb-pin-input-content")).innerText
)
}
@@ -3027,7 +3046,7 @@ class IInputPinTemplate extends PinTemplate {
return html`
`
@@ -3464,7 +3483,11 @@ class NodeElement extends ISelectableDraggableElement {
super.setLocation([this.entity.NodePosX.value, this.entity.NodePosY.value]);
}
+ /**
+ * @param {String} str
+ */
static fromSerializedObject(str) {
+ str = str.trim();
let entity = SerializerFactory.getSerializer(ObjectEntity).read(str);
return new NodeElement(entity)
}
@@ -4735,6 +4758,23 @@ class CustomSerializer extends GeneralSerializer {
// @ts-check
+class PinSerializer extends GeneralSerializer {
+
+ constructor() {
+ super(v => `${PinEntity.lookbehind} (${v})`, PinEntity, "", ",", true);
+ }
+
+ writeValue(value, fullKey) {
+ if (value?.constructor === String && fullKey == "DefaultValue") {
+ // @ts-expect-error
+ return `"${Utility.encodeInputString(value)}"`
+ }
+ return super.writeValue(value, fullKey)
+ }
+}
+
+// @ts-check
+
class ToStringSerializer extends GeneralSerializer {
constructor(entityType) {
@@ -4757,8 +4797,8 @@ function initializeSerializerFactory() {
);
SerializerFactory.registerSerializer(
- PinEntity,
- new GeneralSerializer(v => `${PinEntity.lookbehind} (${v})`, PinEntity, "", ",", true)
+ PinEntity,
+ new PinSerializer()
);
SerializerFactory.registerSerializer(
diff --git a/js/Utility.js b/js/Utility.js
index a5bb1a8..a6a0a50 100755
--- a/js/Utility.js
+++ b/js/Utility.js
@@ -149,22 +149,41 @@ export default class Utility {
/**
* @param {String} value
*/
- static sanitizeString(value, input = false) {
+ static encodeInputString(value) {
return value
.replace(/\n$/, "") // Remove trailing newline
.replaceAll("\u00A0", " ") // Replace special space symbol
+ .replaceAll("\r\n", String.raw`\r\n`) // Replace newline with \r\n
.replaceAll("\n", String.raw`\r\n`) // Replace newline with \r\n
}
/**
* @param {String} value
*/
- static renderInputString(value) {
+ static decodeInputString(value) {
return value
.replaceAll(" ", "\u00A0") // Replace special space symbol
.replaceAll(String.raw`\r\n`, "
\n") // Replace newline with \r\n
}
+ /**
+ * @param {String} value
+ */
+ static encodeString(value, input = false) {
+ return value
+ .replaceAll("\u00A0", " ") // Replace special space symbol
+ .replaceAll("\n", String.raw`\n`) // Replace newline with \n
+ }
+
+ /**
+ * @param {String} value
+ */
+ static decodeString(value, input = false) {
+ return value
+ .replaceAll(" ", "\u00A0") // Replace special space symbol
+ .replaceAll(String.raw`\n`, "\n") // Replace newline with \n
+ }
+
/**
* @param {String} value
*/
diff --git a/js/element/NodeElement.js b/js/element/NodeElement.js
index fc4508a..5b799c6 100644
--- a/js/element/NodeElement.js
+++ b/js/element/NodeElement.js
@@ -23,7 +23,11 @@ export default class NodeElement extends ISelectableDraggableElement {
super.setLocation([this.entity.NodePosX.value, this.entity.NodePosY.value])
}
+ /**
+ * @param {String} str
+ */
static fromSerializedObject(str) {
+ str = str.trim()
let entity = SerializerFactory.getSerializer(ObjectEntity).read(str)
return new NodeElement(entity)
}
diff --git a/js/export.js b/js/export.js
index d7e83a2..bf2a8f5 100755
--- a/js/export.js
+++ b/js/export.js
@@ -2,11 +2,10 @@
import Blueprint from "./Blueprint"
import Configuration from "./Configuration"
+import initializeSerializerFactory from "./serialization/initializeSerializerFactory"
import LinkElement from "./element/LinkElement"
import NodeElement from "./element/NodeElement"
-import initializeSerializerFactory from "./serialization/initializeSerializerFactory"
-
initializeSerializerFactory()
export { Blueprint as Blueprint, NodeElement as NodeElement, LinkElement as LinkElement, Configuration as Configuration }
diff --git a/js/serialization/ISerializer.js b/js/serialization/ISerializer.js
index 266eee4..96777c5 100644
--- a/js/serialization/ISerializer.js
+++ b/js/serialization/ISerializer.js
@@ -20,7 +20,7 @@ export default class ISerializer {
this.attributeKeyPrinter = attributeKeyPrinter ?? (k => k.join("."))
}
- writeValue(value) {
+ writeValue(value, fullKey = undefined) {
if (value === null) {
return "()"
}
@@ -28,13 +28,13 @@ export default class ISerializer {
// This is an exact match (and not instanceof) to hit also primitive types (by accessing value.constructor they are converted to objects automatically)
switch (value?.constructor) {
case Function:
- return this.writeValue(value())
+ return this.writeValue(value(), fullKey)
case Boolean:
return Utility.FirstCapital(value.toString())
case Number:
return value.toString()
case String:
- return `"${value}"`
+ return `"${Utility.encodeString(value)}"`
}
if (value instanceof Array) {
return `(${value.map(v => serialize(v) + ",").join("")})`
@@ -65,7 +65,7 @@ export default class ISerializer {
+ this.prefix
+ this.attributeKeyPrinter(fullKey)
+ this.attributeValueConjunctionSign
- + this.writeValue(value)
+ + this.writeValue(value, fullKey)
}
}
if (this.trailingSeparator && result.length && fullKey.length === 1) {
diff --git a/js/serialization/ObjectSerializer.js b/js/serialization/ObjectSerializer.js
index 49a1164..884bae8 100755
--- a/js/serialization/ObjectSerializer.js
+++ b/js/serialization/ObjectSerializer.js
@@ -46,7 +46,7 @@ export default class ObjectSerializer extends ISerializer {
* @param {ObjectEntity} object
*/
write(object) {
- let result = `Begin Object Class=${object.Class.path} Name=${this.writeValue(object.Name)}
+ let result = `Begin Object Class=${object.Class.path} Name=${this.writeValue(object.Name, "Name")}
${this.subWrite([], object)
+ object
.CustomProperties.map(pin =>
diff --git a/js/serialization/PinSerializer.js b/js/serialization/PinSerializer.js
new file mode 100755
index 0000000..7c4f6c4
--- /dev/null
+++ b/js/serialization/PinSerializer.js
@@ -0,0 +1,20 @@
+// @ts-check
+
+import PinEntity from "../entity/PinEntity"
+import Utility from "../Utility"
+import GeneralSerializer from "./GeneralSerializer"
+
+export default class PinSerializer extends GeneralSerializer {
+
+ constructor() {
+ super(v => `${PinEntity.lookbehind} (${v})`, PinEntity, "", ",", true)
+ }
+
+ writeValue(value, fullKey) {
+ if (value?.constructor === String && fullKey == "DefaultValue") {
+ // @ts-expect-error
+ return `"${Utility.encodeInputString(value)}"`
+ }
+ return super.writeValue(value, fullKey)
+ }
+}
diff --git a/js/serialization/initializeSerializerFactory.js b/js/serialization/initializeSerializerFactory.js
index 0e6c35c..d14a6b4 100755
--- a/js/serialization/initializeSerializerFactory.js
+++ b/js/serialization/initializeSerializerFactory.js
@@ -6,6 +6,7 @@ import GeneralSerializer from "./GeneralSerializer"
import GuidEntity from "../entity/GuidEntity"
import IdentifierEntity from "../entity/IdentifierEntity"
import IntegerEntity from "../entity/IntegerEntity"
+import InvariantTextEntity from "../entity/InvariantTextEntity"
import KeyBindingEntity from "../entity/KeyBindingEntity"
import LocalizedTextEntity from "../entity/LocalizedTextEntity"
import ObjectEntity from "../entity/ObjectEntity"
@@ -14,9 +15,9 @@ import ObjectSerializer from "./ObjectSerializer"
import PathSymbolEntity from "../entity/PathSymbolEntity"
import PinEntity from "../entity/PinEntity"
import PinReferenceEntity from "../entity/PinReferenceEntity"
+import PinSerializer from "./PinSerializer"
import SerializerFactory from "./SerializerFactory"
import ToStringSerializer from "./ToStringSerializer"
-import InvariantTextEntity from "../entity/InvariantTextEntity"
export default function initializeSerializerFactory() {
@@ -26,8 +27,8 @@ export default function initializeSerializerFactory() {
)
SerializerFactory.registerSerializer(
- PinEntity,
- new GeneralSerializer(v => `${PinEntity.lookbehind} (${v})`, PinEntity, "", ",", true)
+ PinEntity,
+ new PinSerializer()
)
SerializerFactory.registerSerializer(
diff --git a/js/template/IInputPinTemplate.js b/js/template/IInputPinTemplate.js
index 4d0b02e..f3a2757 100644
--- a/js/template/IInputPinTemplate.js
+++ b/js/template/IInputPinTemplate.js
@@ -65,7 +65,7 @@ export default class IInputPinTemplate extends PinTemplate {
* @param {PinElement} pin
*/
getInput(pin) {
- return Utility.sanitizeString(
+ return Utility.encodeInputString(
/** @type {HTMLElement} */(pin.querySelector(".ueb-pin-input-content")).innerText
)
}
@@ -85,7 +85,7 @@ export default class IInputPinTemplate extends PinTemplate {
return html`
`