text: (function(undefined) {
    "use strict";
  
    var shapes = [];
    var register = function(name, drawShape, drawBorder) {
      shapes.push({
        name: name,
        drawShape: drawShape,
        drawBorder: drawBorder
      });
    };
  
    var enumerateShapes = function() {
      return shapes;
    };
  
    /**
     * For the standard closed shapes - the shape fill and border are drawn the
     * same, with some minor differences for fill and border. To facilitate this we
     * create the generic draw functions, that take a shape drawing func and
     * return a shape-renderer/border-renderer
     * ----------
     */
    var genericDrawShape = function(shapeFunc) {
      return function(node, x, y, size, color, context) {
        context.fillStyle = color;
        context.beginPath();
        shapeFunc(node, x, y, size, context);
        context.closePath();
        context.fill();
      };
    };
  
    var genericDrawBorder = function(shapeFunc) {
      return function(node, x, y, size, color, context) {
        context.strokeStyle = color;
        context.lineWidth = size / 5;
        context.beginPath();
        shapeFunc(node, x, y, size, context);
        context.closePath();
        context.stroke();
      };
    };
  
    /**
     * We now proced to use the generics to define our standard shape/border
     * drawers: square, diamond, equilateral (polygon), and star
     * ----------
     */
    var drawSquare = function(node, x, y, size, context) {
      var rotate = (Math.PI * 45) / 180; // 45 deg rotation of a diamond shape
      context.moveTo(x + size * Math.sin(rotate), y - size * Math.cos(rotate)); // first point on outer radius, dwangle 'rotate'
      for (var i = 1; i < 4; i++) {
        context.lineTo(
          x + Math.sin(rotate + (2 * Math.PI * i) / 4) * size,
          y - Math.cos(rotate + (2 * Math.PI * i) / 4) * size
        );
      }
    };
    register(
      "square",
      genericDrawShape(drawSquare),
      genericDrawBorder(drawSquare)
    );
  
    var drawCircle = function(node, x, y, size, context) {
      console.log("circle");
      console.log(node, "node");
      console.log(context, "context");
  
      context.arc(x, y, size, 0, Math.PI * 2, true);
    };
    register(
      "circle",
      genericDrawShape(drawCircle),
      genericDrawBorder(drawCircle)
    );
  
    var drawDiamond = function(node, x, y, size, context) {
      context.moveTo(x - size, y);
      context.lineTo(x, y - size);
      context.lineTo(x + size, y);
      context.lineTo(x, y + size);
    };
    register(
      "diamond",
      genericDrawShape(drawDiamond),
      genericDrawBorder(drawDiamond)
    );
  
    var drawCross = function(node, x, y, size, context) {
      var lineWeight = (node.cross && node.cross.lineWeight) || 5;
      context.moveTo(x - size, y - lineWeight);
      context.lineTo(x - size, y + lineWeight);
      context.lineTo(x - lineWeight, y + lineWeight);
      context.lineTo(x - lineWeight, y + size);
      context.lineTo(x + lineWeight, y + size);
      context.lineTo(x + lineWeight, y + lineWeight);
      context.lineTo(x + size, y + lineWeight);
      context.lineTo(x + size, y - lineWeight);
      context.lineTo(x + lineWeight, y - lineWeight);
      context.lineTo(x + lineWeight, y - size);
      context.lineTo(x - lineWeight, y - size);
      context.lineTo(x - lineWeight, y - lineWeight);
    };
    register("cross", genericDrawShape(drawCross), genericDrawBorder(drawCross));
  
    var drawEquilateral = function(node, x, y, size, context) {
      var pcount = (node.equilateral && node.equilateral.numPoints) || 5;
      var rotate =
        (((node.equilateral && node.equilateral.rotate) || 0) * Math.PI) / 180;
      var radius = size;
      context.moveTo(
        x + radius * Math.sin(rotate),
        y - radius * Math.cos(rotate)
      ); // first point on outer radius, angle 'rotate'
      for (var i = 1; i < pcount; i++) {
        context.lineTo(
          x + Math.sin(rotate + (2 * Math.PI * i) / pcount) * radius,
          y - Math.cos(rotate + (2 * Math.PI * i) / pcount) * radius
        );
      }
    };
    register(
      "equilateral",
      genericDrawShape(drawEquilateral),
      genericDrawBorder(drawEquilateral)
    );
  
    var starShape = function(node, x, y, size, context) {
      var pcount = (node.star && node.star.numPoints) || 5,
        inRatio = (node.star && node.star.innerRatio) || 0.5,
        outR = size,
        inR = size * inRatio,
        angleOffset = Math.PI / pcount;
      context.moveTo(x, y - size); // first point on outer radius, top
      for (var i = 0; i < pcount; i++) {
        context.lineTo(
          x + Math.sin(angleOffset + (2 * Math.PI * i) / pcount) * inR,
          y - Math.cos(angleOffset + (2 * Math.PI * i) / pcount) * inR
        );
        context.lineTo(
          x + Math.sin((2 * Math.PI * (i + 1)) / pcount) * outR,
          y - Math.cos((2 * Math.PI * (i + 1)) / pcount) * outR
        );
      }
    };
    register("star", genericDrawShape(starShape), genericDrawBorder(starShape));
  
    var drawImg = function(node, x, y, size, context) {
      let img = new window.Image();
      img.addEventListener("load", function() {
        context.drawImage(img, x, y);
      });
      img.clip = 0.7;
      img.setAttribute("src", "https://www.gravatar.com/avatar/HASH");
      console.log(img, "img");
      //context.drawImage("https://www.gravatar.com/avatar/HASH", 10, 10);
    };
  
    register("image");
  
    /**
     * An example of a non standard shape (pacman). Here we WILL NOT use the
     * genericDraw functions, but rather register a full custom node renderer for
     * fill, and skip the border renderer which is irrelevant for this shape
     * ----------
     */
    var drawPacman = function(node, x, y, size, color, context) {
      context.fillStyle = "yellow";
      context.beginPath();
      context.arc(x, y, size, 1.25 * Math.PI, 0, false);
      context.arc(x, y, size, 0, 0.75 * Math.PI, false);
      context.lineTo(x, y);
      context.closePath();
      context.fill();
  
      context.fillStyle = "white";
      context.strokeStyle = "black";
      context.beginPath();
      context.arc(x + size / 3, y - size / 3, size / 4, 0, 2 * Math.PI, false);
      context.closePath();
      context.fill();
      context.stroke();
  
      context.fillStyle = "black";
      context.beginPath();
      context.arc(
        x + (4 * size) / 9,
        y - size / 3,
        size / 8,
        0,
        2 * Math.PI,
        false
      );
      context.closePath();
      context.fill();
    };
    register("pacman", drawPacman, null);
  
    /**
     * Exporting
     * ----------
     */
    window.ShapeLibrary = {
      // Functions
      enumerate: enumerateShapes,
      // add: addShape,
  
      // Version
      version: "0.1"
    };
  }.call(this));
  