static parseOptions(
    parentOptions,
    newOptions,
    allowDeletion = false,
    globalOptions = {},
    copyFromGlobals = false
  ) {
    const fields = [
      "endPointOffset",
      "arrowStrikethrough",
      "id",
      "from",
      "hidden",
      "hoverWidth",
      "labelHighlightBold",
      "length",
      "line",
      "opacity",
      "physics",
      "scaling",
      "selectionWidth",
      "selfReferenceSize",
      "selfReference",
      "to",
      "title",
      "value",
      "width",
      "font",
      "chosen",
      "widthConstraint",
    ];

    // only deep extend the items in the field array. These do not have shorthand.
    selectiveDeepExtend(fields, parentOptions, newOptions, allowDeletion);

    // Only use endPointOffset values (from and to) if it's valid values
    if (
      newOptions.endPointOffset !== undefined &&
      newOptions.endPointOffset.from !== undefined
    ) {
      if (Number.isFinite(newOptions.endPointOffset.from)) {
        parentOptions.endPointOffset.from = newOptions.endPointOffset.from;
      } else {
        parentOptions.endPointOffset.from =
          globalOptions.endPointOffset.from !== undefined
            ? globalOptions.endPointOffset.from
            : 0;
        console.error("endPointOffset.from is not a valid number");
      }
    }

    if (
      newOptions.endPointOffset !== undefined &&
      newOptions.endPointOffset.to !== undefined
    ) {
      if (Number.isFinite(newOptions.endPointOffset.to)) {
        parentOptions.endPointOffset.to = newOptions.endPointOffset.to;
      } else {
        parentOptions.endPointOffset.to =
          globalOptions.endPointOffset.to !== undefined
            ? globalOptions.endPointOffset.to
            : 0;
        console.error("endPointOffset.to is not a valid number");
      }
    }

    // Only copy label if it's a legal value.
    if (isValidLabel(newOptions.label)) {
      parentOptions.label = newOptions.label;
    } else if (!isValidLabel(parentOptions.label)) {
      parentOptions.label = undefined;
    }

    mergeOptions(parentOptions, newOptions, "smooth", globalOptions);
    mergeOptions(parentOptions, newOptions, "shadow", globalOptions);
    mergeOptions(parentOptions, newOptions, "background", globalOptions);

    if (newOptions.dashes !== undefined && newOptions.dashes !== null) {
      parentOptions.dashes = newOptions.dashes;
    } else if (allowDeletion === true && newOptions.dashes === null) {
      parentOptions.dashes = Object.create(globalOptions.dashes); // this sets the pointer of the option back to the global option.
    }

    // set the scaling newOptions
    if (newOptions.scaling !== undefined && newOptions.scaling !== null) {
      if (newOptions.scaling.min !== undefined) {
        parentOptions.scaling.min = newOptions.scaling.min;
      }
      if (newOptions.scaling.max !== undefined) {
        parentOptions.scaling.max = newOptions.scaling.max;
      }
      mergeOptions(
        parentOptions.scaling,
        newOptions.scaling,
        "label",
        globalOptions.scaling
      );
    } else if (allowDeletion === true && newOptions.scaling === null) {
      parentOptions.scaling = Object.create(globalOptions.scaling); // this sets the pointer of the option back to the global option.
    }

    // handle multiple input cases for arrows
    if (newOptions.arrows !== undefined && newOptions.arrows !== null) {
      if (typeof newOptions.arrows === "string") {
        const arrows = newOptions.arrows.toLowerCase();
        parentOptions.arrows.to.enabled = arrows.indexOf("to") != -1;
        parentOptions.arrows.middle.enabled = arrows.indexOf("middle") != -1;
        parentOptions.arrows.from.enabled = arrows.indexOf("from") != -1;
      } else if (typeof newOptions.arrows === "object") {
        mergeOptions(
          parentOptions.arrows,
          newOptions.arrows,
          "to",
          globalOptions.arrows
        );
        mergeOptions(
          parentOptions.arrows,
          newOptions.arrows,
          "middle",
          globalOptions.arrows
        );
        mergeOptions(
          parentOptions.arrows,
          newOptions.arrows,
          "from",
          globalOptions.arrows
        );
      } else {
        throw new Error(
          "The arrow newOptions can only be an object or a string. Refer to the documentation. You used:" +
            JSON.stringify(newOptions.arrows)
        );
      }
    } else if (allowDeletion === true && newOptions.arrows === null) {
      parentOptions.arrows = Object.create(globalOptions.arrows); // this sets the pointer of the option back to the global option.
    }

    // handle multiple input cases for color
    if (newOptions.color !== undefined && newOptions.color !== null) {
      const fromColor = isString(newOptions.color)
        ? {
            color: newOptions.color,
            highlight: newOptions.color,
            hover: newOptions.color,
            inherit: false,
            opacity: 1,
          }
        : newOptions.color;
      const toColor = parentOptions.color;

      // If passed, fill in values from default options - required in the case of no prototype bridging
      if (copyFromGlobals) {
        deepExtend(toColor, globalOptions.color, false, allowDeletion);
      } else {
        // Clear local properties - need to do it like this in order to retain prototype bridges
        for (const i in toColor) {
          if (Object.prototype.hasOwnProperty.call(toColor, i)) {
            delete toColor[i];
          }
        }
      }

      if (isString(toColor)) {
        toColor.color = toColor;
        toColor.highlight = toColor;
        toColor.hover = toColor;
        toColor.inherit = false;
        if (fromColor.opacity === undefined) {
          toColor.opacity = 1.0; // set default
        }
      } else {
        let colorsDefined = false;
        if (fromColor.color !== undefined) {
          toColor.color = fromColor.color;
          colorsDefined = true;
        }
        if (fromColor.highlight !== undefined) {
          toColor.highlight = fromColor.highlight;
          colorsDefined = true;
        }
        if (fromColor.hover !== undefined) {
          toColor.hover = fromColor.hover;
          colorsDefined = true;
        }
        if (fromColor.inherit !== undefined) {
          toColor.inherit = fromColor.inherit;
        }
        if (fromColor.opacity !== undefined) {
          toColor.opacity = Math.min(1, Math.max(0, fromColor.opacity));
        }

        if (colorsDefined === true) {
          toColor.inherit = false;
        } else {
          if (toColor.inherit === undefined) {
            toColor.inherit = "from"; // Set default
          }
        }
      }
    } else if (allowDeletion === true && newOptions.color === null) {
      parentOptions.color = bridgeObject(globalOptions.color); // set the object back to the global options
    }

    if (allowDeletion === true && newOptions.font === null) {
      parentOptions.font = bridgeObject(globalOptions.font); // set the object back to the global options
    }

    if (Object.prototype.hasOwnProperty.call(newOptions, "selfReferenceSize")) {
      console.warn(
        "The selfReferenceSize property has been deprecated. Please use selfReference property instead. The selfReference can be set like thise selfReference:{size:30, angle:Math.PI / 4}"
      );
      parentOptions.selfReference.size = newOptions.selfReferenceSize;
    }
  }
@param {object} parentOptions
@param {object} newOptions
@param {boolean} [allowDeletion]
@param {object} [globalOptions]
@param {boolean} [copyFromGlobals]