Converting an SVG polygon path from relative to absolute coordinates
Your variable names are overly terse. It's had to follow the logic when it's all to do with a two-letter variable that also happens to be a 2D array.

Basically, you seem intent writing it as densely as possible rather than making it readable. But minifying javascript is what minification tools are for.

It's also strange that you pass in a complete path string, but you get an array back. An array that's missing the commands, and where you manually have to prefix M and postfix z. Why not output a complete path?

Your test just assumes that all the commands (apart from the initial M) was a L command. Which, since that the only command your code can interpret, isn't too terrible. It'd still be neater to rewrite the path code itself, though, and return a string.

Adding the z smells especially buggy, as it closes the path even if the original path wasn't closed.

As for overall structure/approach, I'd use replace with a callback and a global pattern, rather than create a match object, and much around with its contents.

In other words, I'd do this:



function pathToAbsolute(relativePath) {
  var pattern = /([ml])\s*(-?\d*\.?\d+)\s*,\s*(-?\d*\.?\d+)/ig,
      offset = null;
      
  // Scan the string for an M/L command (case-insensitive) and its two
  // coordinates, replacing any lower-case (relative) command with an
  // absolute version
  return relativePath.replace(pattern, function (match, command, x, y) {
    x = parseFloat(x);
    y = parseFloat(y);
    
    // If we don't have an offset yet or the command is absolute already,
    // then use the matched coordinates as the offset, and return the matched
    // string unaltered
    if(offset === null || command.toUpperCase() === command) {
      offset = { x: x, y: y };
      return match;
    }
    
    // If we're here, the command is relative, so add its coordinates to the
    // offset, and output the absolute version of the matched string
    offset.x += x;
    offset.y += y;
    
    return command.toUpperCase() + offset.x + "," + offset.y;
  });
}

// ========================
// Test code

var star = document.getElementById('star'),
    svg = star.parentNode,
    absPath = pathToAbsolute(star.getAttribute('d'));

var newStar = document.createElementNS('http://www.w3.org/2000/svg','path');
newStar.setAttribute('d', absPath);
newStar.setAttribute('fill','green');
newStar.setAttribute('transform','translate(30,30)');
svg.appendChild(newStar);
&lt;svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800"&gt;
   &lt;path id="star" fill="#eee" d="M301.113,12.011l99.25,179.996l201.864,38.778L461.706,380.808 l25.508,203.958l-186.101-87.287L115.01,584.766l25.507-203.958L0,230.785l201.86-38.778L301.113,12.011z"&gt;&lt;/path&gt;
&lt;/svg&gt;




Like yours it only looks for M and L commands - not any of the many other SVG commands. Though it shouldn't actually be too terrible to extend it to handle those as well. Especially, as this returns a complete path string that can be used right away. Not joining necessary, and no assuming all commands are Ls.

It does however still assume that the path is valid; that it starts with an m or M. So it's gigo: Garbage in, garbage out.



Edit: Although I do feel the code above answers the question as originally stated, here's a version that doesn't "transform a path", but parses it and returns an array.

function pathToAbsolute(relativePath) {
  var pattern = /([ml])\s*(-?\d*\.?\d+)\s*,\s*(-?\d*\.?\d+)/ig,
      coords = [];

  relativePath.replace(pattern, function (match, command, x, y) {
    var prev;

    x = parseFloat(x);
    y = parseFloat(y);

    if(coords.length === 0 || command.toUpperCase() === command) {
      coords.push([x, y]);
    } else {
      prev = coords[coords.length-1];
      coords.push([x + prev[0], y + prev[1]]);
    }
  });

  return coords;
}