From 3041ca337e99019b8b75e6bf569eff3f638be5f1 Mon Sep 17 00:00:00 2001
From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com>
Date: Mon, 11 Dec 2023 08:42:29 +0100
Subject: [PATCH] docs: improve JSDoc of codec classes (#287)
In addition, apply minor refactoring
- Codec.decodeCell: improve signature (default value)
- ObjectCodec
- use Codec type instead of value in import
- simplify implementation of ObjectCodec.isNumericAttribute
---
packages/core/src/serialization/Codec.ts | 62 ++++++--------
.../core/src/serialization/CodecRegistry.ts | 38 +++------
.../core/src/serialization/ObjectCodec.ts | 82 +++++++++----------
3 files changed, 78 insertions(+), 104 deletions(-)
diff --git a/packages/core/src/serialization/Codec.ts b/packages/core/src/serialization/Codec.ts
index 85343b6a9..499166a7d 100644
--- a/packages/core/src/serialization/Codec.ts
+++ b/packages/core/src/serialization/Codec.ts
@@ -45,21 +45,19 @@ const createXmlDocument = () => {
* The following code is used to encode a graph model.
*
* ```javascript
- * var encoder = new Codec();
- * var result = encoder.encode(graph.getDataModel());
- * var xml = mxUtils.getXml(result);
+ * const encoder = new Codec();
+ * const result = encoder.encode(graph.getDataModel());
+ * const xml = mxUtils.getXml(result);
* ```
*
* #### Example
*
* Using the code below, an XML document is decoded into an existing model. The
- * document may be obtained using one of the functions in mxUtils for loading
- * an XML file, eg. {@link mxUtils.get}, or using {@link mxUtils.parseXml} for parsing an
- * XML string.
+ * document may be obtained using {@link parseXml} for parsing an XML string.
*
* ```javascript
- * var doc = mxUtils.parseXml(xmlString);
- * var codec = new Codec(doc);
+ * const doc = xmlUtils.parseXml(xmlString);
+ * const codec = new Codec(doc);
* codec.decode(doc.documentElement, graph.getDataModel());
* ```
*
@@ -70,18 +68,17 @@ const createXmlDocument = () => {
* be added anywhere in the cell hierarchy after parsing.
*
* ```javascript
- * var xml = '';
- * var doc = mxUtils.parseXml(xml);
- * var codec = new Codec(doc);
- * var elt = doc.documentElement.firstChild;
- * var cells = [];
+ * const xml = '';
+ * const doc = mxUtils.parseXml(xml);
+ * const codec = new Codec(doc);
+ * let elt = doc.documentElement.firstChild;
+ * const cells = [];
*
* while (elt != null)
* {
* cells.push(codec.decode(elt));
* elt = elt.nextSibling;
* }
- *
* graph.addCells(cells);
* ```
*
@@ -91,13 +88,13 @@ const createXmlDocument = () => {
* output is displayed in a dialog box.
*
* ```javascript
- * var enc = new Codec();
- * var cells = graph.getSelectionCells();
- * mxUtils.alert(mxUtils.getPrettyXml(enc.encode(cells)));
+ * const enc = new Codec();
+ * const cells = graph.getSelectionCells();
+ * const xml = xmlUtils.getPrettyXml(enc.encode(cells));
* ```
*
* Newlines in the XML can be converted to , in which case a ' ' argument
- * must be passed to {@link mxUtils.getXml} as the second argument.
+ * must be passed to {@link getXml} as the second argument.
*
* ### Debugging
*
@@ -105,11 +102,11 @@ const createXmlDocument = () => {
* encoded objects:
*
* ```javascript
- * var oldEncode = encode;
+ * const oldEncode = encode;
* encode(obj)
* {
* MaxLog.show();
- * MaxLog.debug('Codec.encode: obj='+mxUtils.getFunctionName(obj.constructor));
+ * MaxLog.debug('Codec.encode: obj='+StringUtils.getFunctionName(obj.constructor));
*
* return oldEncode.apply(this, arguments);
* };
@@ -146,7 +143,7 @@ class Codec {
/**
* Lookup table for resolving IDs to elements.
*/
- elements: any = null; // { [key: string]: Element } | null
+ elements: any = null; // TODO why not { [key: string]: Element } | null
/**
* Specifies if default values should be encoded. Default is false.
@@ -154,7 +151,7 @@ class Codec {
encodeDefaults = false;
/**
- * Assoiates the given object with the given ID and returns the given object.
+ * Associates the given object with the given ID and returns the given object.
*
* @param id ID for the object to be associated with.
* @param obj Object to be associated with the ID.
@@ -199,7 +196,7 @@ class Codec {
* Example:
*
* ```javascript
- * var codec = new Codec();
+ * const codec = new Codec();
* codec.lookup(id)
* {
* return model.getCell(id);
@@ -222,11 +219,6 @@ class Codec {
return this.elements[id];
}
- /**
- * Returns the element with the given ID from {@link document}.
- *
- * @param id String that contains the ID.
- */
updateElements(): void {
if (this.elements == null) {
this.elements = {};
@@ -299,7 +291,7 @@ class Codec {
* Example:
*
* ```javascript
- * var codec = new Codec();
+ * const codec = new Codec();
* codec.reference(obj)
* {
* return obj.getCustomId();
@@ -313,8 +305,7 @@ class Codec {
}
/**
- * Encodes the specified object and returns the resulting
- * XML node.
+ * Encodes the specified object and returns the resulting XML node.
*
* @param obj Object to be encoded.
*/
@@ -345,7 +336,7 @@ class Codec {
* the new instance if no object was given.
*
* @param node XML node to be decoded.
- * @param into Optional object to be decodec into.
+ * @param into Optional object to be decoded into.
*/
decode(node: Element | null, into?: any): any {
this.updateElements();
@@ -418,10 +409,9 @@ class Codec {
* @param restoreStructures Optional boolean indicating whether
* the graph structure should be restored by calling insert
* and insertEdge on the parent and terminals, respectively.
- * Default is true.
+ * Default is `true`.
*/
- decodeCell(node: Element, restoreStructures?: boolean): Cell {
- restoreStructures = restoreStructures != null ? restoreStructures : true;
+ decodeCell(node: Element, restoreStructures = true): Cell {
let cell = null;
if (node != null && node.nodeType === NODETYPE.ELEMENT) {
@@ -490,7 +480,7 @@ class Codec {
* are not null.
*
* @param node XML node to set the attribute for.
- * @param attributes Attributename to be set.
+ * @param attribute The name of the attribute to be set.
* @param value New value of the attribute.
*/
setAttribute(node: Element, attribute: string, value: any): void {
diff --git a/packages/core/src/serialization/CodecRegistry.ts b/packages/core/src/serialization/CodecRegistry.ts
index 2c7a71fe2..d3f2b6722 100644
--- a/packages/core/src/serialization/CodecRegistry.ts
+++ b/packages/core/src/serialization/CodecRegistry.ts
@@ -21,12 +21,12 @@ import ObjectCodec from './ObjectCodec';
/**
* Singleton class that acts as a global registry for codecs.
*
- * ### Adding an :
+ * ### Adding a Codec
*
* 1. Define a default codec with a new instance of the object to be handled.
*
* ```javascript
- * var codec = new ObjectCodec(new Transactions());
+ * const codec = new ObjectCodec(new Transactions());
* ```
*
* 2. Define the functions required for encoding and decoding objects.
@@ -36,36 +36,27 @@ import ObjectCodec from './ObjectCodec';
* codec.decode = function(dec: Codec, node: Element, into: any): any { ... }
* ```
*
- * 3. Register the codec in the .
+ * 3. Register the codec in the CodecRegistry.
*
* ```javascript
* CodecRegistry.register(codec);
* ```
*
- * {@link ObjectCodec.decode} may be used to either create a new
- * instance of an object or to configure an existing instance,
- * in which case the into argument points to the existing
- * object. In this case, we say the codec "configures" the
- * object.
- *
- * @class CodecRegistry
+ * {@link ObjectCodec.decode} may be used to either create a new instance of an object or to configure an existing instance,
+ * in which case the into argument points to the existing object. In this case, we say the codec "configures" the object.
*/
class CodecRegistry {
static codecs: { [key: string]: ObjectCodec | undefined } = {};
/**
- * Maps from classnames to codecnames.
- * @static
+ * Maps from classnames to codec names.
*/
static aliases: { [key: string]: string | undefined } = {};
/**
- * Registers a new codec and associates the name of the template
- * constructor in the codec with the codec object.
+ * Registers a new codec and associates the name of the template constructor in the codec with the codec object.
*
- * @static
- *
- * @param codec - {@link ObjectCodec} to be registered.
+ * @param codec ObjectCodec to be registered.
*/
static register(codec: ObjectCodec): ObjectCodec {
if (codec != null) {
@@ -81,20 +72,16 @@ class CodecRegistry {
}
/**
- * Adds an alias for mapping a classname to a codecname.
- * @static
+ * Adds an alias for mapping a classname to a codec name.
*/
static addAlias(classname: string, codecname: string): void {
CodecRegistry.aliases[classname] = codecname;
}
/**
- * Returns a codec that handles objects that are constructed
- * using the given constructor.
+ * Returns a codec that handles objects that are constructed using the given constructor.
*
- * @static
- *
- * @param ctor - JavaScript constructor function.
+ * @param constructor_ JavaScript constructor function.
*/
static getCodec(constructor_: any): ObjectCodec | null {
let codec = null;
@@ -109,8 +96,7 @@ class CodecRegistry {
codec = CodecRegistry.codecs[name] ?? null;
- // Registers a new default codec for the given constructor
- // if no codec has been previously defined.
+ // Registers a new default codec for the given constructor if no codec has been previously defined.
if (codec == null) {
try {
codec = new ObjectCodec(new constructor_());
diff --git a/packages/core/src/serialization/ObjectCodec.ts b/packages/core/src/serialization/ObjectCodec.ts
index d2be2841c..cfaba64ab 100644
--- a/packages/core/src/serialization/ObjectCodec.ts
+++ b/packages/core/src/serialization/ObjectCodec.ts
@@ -24,7 +24,7 @@ import { NODETYPE } from '../util/Constants';
import { isInteger, isNumeric } from '../util/mathUtils';
import { getTextContent } from '../util/domUtils';
import { load } from '../util/MaxXmlRequest';
-import Codec from './Codec';
+import type Codec from './Codec';
/**
* Generic codec for JavaScript objects that implements a mapping between
@@ -36,7 +36,7 @@ import Codec from './Codec';
* Consider the following example.
*
* ```javascript
- * var obj = new Object();
+ * const obj = new Object();
* obj.foo = "Foo";
* obj.bar = "Bar";
* ```
@@ -44,8 +44,8 @@ import Codec from './Codec';
* This object is encoded into an XML node using the following.
*
* ```javascript
- * var enc = new Codec();
- * var node = enc.encode(obj);
+ * const enc = new Codec();
+ * const node = enc.encode(obj);
* ```
*
* The output of the encoding may be viewed using {@link MaxLog} as follows.
@@ -63,7 +63,7 @@ import Codec from './Codec';
*
* In the above output, the foo and bar fields have been mapped to attributes
* with the same names, and the name of the constructor was used for the
- * nodename.
+ * node name.
*
* ### Booleans
*
@@ -75,15 +75,15 @@ import Codec from './Codec';
*
* The above scheme is applied to all atomic fields, that is, to all non-object
* fields of an object. For object fields, a child node is created with a
- * special attribute that contains the fieldname. This special attribute is
+ * special attribute that contains the field name. This special attribute is
* called "as" and hence, as is a reserved word that should not be used for a
- * fieldname.
+ * field name.
*
* Consider the following example where foo is an object and bar is an atomic
* property of foo.
*
* ```javascript
- * var obj = {foo: {bar: "Bar"}};
+ * const obj = {foo: {bar: "Bar"}};
* ```
*
* This will be mapped to the following XML structure by ObjectCodec.
@@ -95,13 +95,13 @@ import Codec from './Codec';
* ```
*
* In the above output, the inner Object node contains the as-attribute that
- * specifies the fieldname in the enclosing object. That is, the field foo was
+ * specifies the field name in the enclosing object. That is, the field foo was
* mapped to a child node with an as-attribute that has the value foo.
*
* ### Arrays
*
* Arrays are special objects that are either associative, in which case each
- * key, value pair is treated like a field where the key is the fieldname, or
+ * key, value pair is treated like a field where the key is the field name, or
* they are a sequence of atomic values and objects, which is mapped to a
* sequence of child nodes. For object elements, the above scheme is applied
* without the use of the special as-attribute for creating each child. For
@@ -113,7 +113,7 @@ import Codec from './Codec';
* called bar with an atomic value, and foo with an object value.
*
* ```javascript
- * var obj = ["Bar", {bar: "Bar"}];
+ * const obj = ["Bar", {bar: "Bar"}];
* obj["bar"] = "Bar";
* obj["foo"] = {bar: "Bar"};
* ```
@@ -139,7 +139,7 @@ import Codec from './Codec';
* which are used to lookup the object in a table within {@link Codec}. The
* {@link isReference} function is in charge of deciding if a specific field should
* be encoded as a reference or not. Its default implementation returns true if
- * the fieldname is in {@link idrefs}, an array of strings that is used to configure
+ * the field name is in {@link idrefs}, an array of strings that is used to configure
* the {@link ObjectCodec}.
*
* Using this approach, the mapping does not guarantee that the referenced
@@ -174,11 +174,11 @@ import Codec from './Codec';
* For decoding JavaScript expressions, the add-node may be used with a text
* content that contains the JavaScript expression. For example, the following
* creates a field called foo in the enclosing object and assigns it the value
- * of {@link mxConstants.ALIGN_LEFT}.
+ * of {@link Constants.ALIGN.LEFT}.
*
* ```javascript
*
* ```
*
@@ -195,8 +195,6 @@ import Codec from './Codec';
* functions on the resulting object.
*
* Expressions are only evaluated if {@link allowEval} is true.
- *
- * @class ObjectCodec
*/
class ObjectCodec {
constructor(
@@ -220,8 +218,9 @@ class ObjectCodec {
/**
* Static global switch that specifies if expressions in arrays are allowed.
- * Default is false. NOTE: Enabling this carries a possible security risk.
- * @static
+ *
+ * **NOTE**: Enabling this carries a possible security risk.
+ * @default false
*/
static allowEval = false;
@@ -231,8 +230,7 @@ class ObjectCodec {
template: any;
/**
- * Array containing the variable names that should be
- * ignored by the codec.
+ * Array containing the variable names that should be ignored by the codec.
*/
exclude: string[];
@@ -244,21 +242,22 @@ class ObjectCodec {
idrefs: string[];
/**
- * Maps from from fieldnames to XML attribute names.
+ * Maps from field names to XML attribute names.
*/
mapping: { [key: string]: string };
/**
- * Maps from from XML attribute names to fieldnames.
+ * Maps from XML attribute names to fieldnames.
*/
reverse: { [key: string]: string };
/**
- * Returns the name used for the nodenames and lookup of the codec when
+ * Returns the name used for the node names and lookup of the codec when
* classes are encoded and nodes are decoded. For classes to work with
* this the codec registry automatically adds an alias for the classname
- * if that is different than what this returns. The default implementation
- * returns the classname of the template class.
+ * if that is different from what this returns.
+ *
+ * The default implementation returns the classname of the template class.
*/
getName(): string {
return this.template.constructor.name;
@@ -272,7 +271,7 @@ class ObjectCodec {
}
/**
- * Returns the fieldname for the given attributename.
+ * Returns the field name for the given attribute name.
* Looks up the value in the {@link reverse} mapping or returns
* the input if there is no reverse mapping for the
* given name.
@@ -290,7 +289,7 @@ class ObjectCodec {
}
/**
- * Returns the attributename for the given fieldname.
+ * Returns the attribute name for the given field name.
* Looks up the value in the {@link mapping} or returns
* the input if there is no mapping for the
* given name.
@@ -308,8 +307,8 @@ class ObjectCodec {
/**
* Returns true if the given attribute is to be ignored by the codec. This
- * implementation returns true if the given fieldname is in {@link exclude} or
- * if the fieldname equals {@link ObjectIdentity.FIELD_NAME}.
+ * implementation returns true if the given field name is in {@link exclude} or
+ * if the field name equals {@link ObjectIdentity.FIELD_NAME}.
*
* @param obj Object instance that contains the field.
* @param attr Fieldname of the field.
@@ -322,12 +321,12 @@ class ObjectCodec {
}
/**
- * Returns true if the given fieldname is to be treated
+ * Returns true if the given field name is to be treated
* as a textual reference (ID). This implementation returns
- * true if the given fieldname is in {@link idrefs}.
+ * true if the given field name is in {@link idrefs}.
*
* @param obj Object instance that contains the field.
- * @param attr Fieldname of the field.
+ * @param attr Field name of the field.
* @param value Value of the field.
* @param write Boolean indicating if the field is being encoded or decoded.
* Write is true if the field is being encoded, else it is being decoded.
@@ -545,7 +544,7 @@ class ObjectCodec {
* Returns true if the given object attribute is a boolean value.
*
* @param enc {@link Codec} that controls the encoding process.
- * @param obj Objec to convert the attribute for.
+ * @param obj Object to convert the attribute for.
* @param name Name of the attribute to be converted.
* @param value Value of the attribute to be converted.
*/
@@ -580,20 +579,19 @@ class ObjectCodec {
*
* @param dec {@link Codec} that controls the decoding process.
* @param attr XML attribute to be converted.
- * @param obj Objec to convert the attribute for.
+ * @param obj Object to convert the attribute for.
*/
isNumericAttribute(dec: Codec, attr: any, obj: any): boolean {
// Handles known numeric attributes for generic objects
- const result =
+ return (
(obj.constructor === Geometry &&
(attr.name === 'x' ||
attr.name === 'y' ||
attr.name === 'width' ||
attr.name === 'height')) ||
(obj.constructor === Point && (attr.name === 'x' || attr.name === 'y')) ||
- isNumeric(attr.value);
-
- return result;
+ isNumeric(attr.value)
+ );
}
/**
@@ -711,7 +709,7 @@ class ObjectCodec {
*
* @param dec {@link Codec} that controls the decoding process.
* @param node XML node to be decoded.
- * @param obj Objec to encode the node into.
+ * @param obj Object to encode the node into.
*/
decodeAttributes(dec: Codec, node: Element, obj: any): void {
const attrs = node.attributes;
@@ -847,8 +845,8 @@ class ObjectCodec {
/**
* Sets the decoded child node as a value of the given object. If the
- * object is a map, then the value is added with the given fieldname as a
- * key. If the fieldname is not empty, then setFieldValue is called or
+ * object is a map, then the value is added with the given field name as a
+ * key. If the field name is not empty, then setFieldValue is called or
* else, if the object is a collection, the value is added to the
* collection. For strongly typed languages it may be required to
* override this with the correct code to add an entry to an object.
@@ -915,7 +913,7 @@ class ObjectCodec {
* without any changes. The return value of this method
* is returned to the decoder from {@link decode}.
*
- * @param enc {@link Codec} that controls the encoding process.
+ * @param dec {@link Codec} that controls the encoding process.
* @param node XML node to be decoded.
* @param obj Object that represents the default decoding.
*/