function addMarker (id, val) {
      let marker = svgCanvas.getElem(id);
      if (marker) { return undefined; }
      if (val === '' || val === 'nomarker') { return undefined; }
      const color = svgCanvas.getColor('stroke');
      // NOTE: Safari didn't like a negative value in viewBox
      // so we use a standardized 0 0 100 100
      // with 50 50 being mapped to the marker position
      const scale = 2;
      const strokeWidth = 10;
      let refX = 50;
      const refY = 50;
      const viewBox = '0 0 100 100';
      const markerWidth = 5 * scale;
      const markerHeight = 5 * scale;
      const seType = val;

      if (!markerTypes[seType]) { return undefined; } // an unknown type!
      // positional markers(arrows) at end of line
      if (seType.includes('left')) refX = 0;
      if (seType.includes('right')) refX = 100;

      // create a generic marker
      marker = addElem({
        element: 'marker',
        attr: {
          id,
          markerUnits: 'strokeWidth',
          orient: 'auto',
          style: 'pointer-events:none',
          class: seType
        }
      });

      const mel = addElem(markerTypes[seType]);
      const fillcolor = (seType.substr(-2) === '_o')
        ? 'none'
        : color;

      mel.setAttribute('fill', fillcolor);
      mel.setAttribute('stroke', color);
      mel.setAttribute('stroke-width', strokeWidth);
      marker.append(mel);

      marker.setAttribute('viewBox', viewBox);
      marker.setAttribute('markerWidth', markerWidth);
      marker.setAttribute('markerHeight', markerHeight);
      marker.setAttribute('refX', refX);
      marker.setAttribute('refY', refY);
      svgCanvas.findDefs().append(marker);

      return marker;
    }
@param {string} id
@param {""|"\\nomarker"|"nomarker"|"leftarrow"|"rightarrow"|"textmarker"|"textmarker_top"|"textmarker_bottom"|"forwardslash"|"reverseslash"|"verticalslash"|"box"|"star"|"xmark"|"triangle"|"mcircle"} val
@returns {SVGMarkerElement}