So it turns out there were several other issues with the illustrator export script.
The main problem I was having was that it gave the wrong bounds for clipping groups so everything was misaligned when importing into spine. Other than that it was just some edge cases that broke things.
I ended up re-writing some of the export script, I think what I have now catches all of the issues that I found.
I re-wrote the parseLayer function:
function parseLayer(layer, info)
{
var pageItems = layer.pageItems;
var visibleBounds;
var left = Number.POSITIVE_INFINITY;
var top = Number.NEGATIVE_INFINITY;
var right = Number.NEGATIVE_INFINITY;
var bottom = Number.POSITIVE_INFINITY;
var found = false;
for (var j = 0; j < pageItems.length; j++ )
{
if (!pageItems[j].hidden)
{
visibleBounds = getVisibleBounds(pageItems[j]);
if (visibleBounds == undefined) continue;
found = true;
left = Math.min(visibleBounds[0], left);
right = Math.max(visibleBounds[2], right);
top = Math.max(visibleBounds[1], top);
bottom = Math.min(visibleBounds[3], bottom);
}
}
if (found)
{
var layerName = getLayerName(layer);
info.skinLayers[info.skinLayers.length] = layerName;
ldata = {};
ldata.width = (right - left).toFixed(2);
ldata.height = (top - bottom).toFixed(2);
ldata.x = (left + (ldata.width/2)).toFixed(2);
ldata.y = (top - (ldata.height/2)).toFixed(2);
info.slots[layerName] = ldata;
}
}
function getVisibleBounds(object)
{
var bounds, clippingItem;
if (object.typename == "GroupItem")
{
if (object.clipped)
{
for (var i = 0; i < object.pageItems.length; i++)
{
if (object.pageItems[i].hidden) continue;
if (object.pageItems[i].clipping)
{
clippingItem = object.pageItems[i];
break;
}
else if (object.pageItems[i].typename == "CompoundPathItem")
{
if (object.pageItems[i].pathItems[0].clipping)
{
clippingItem = object.pageItems[i];
break;
}
}
}
if (clippingItem != undefined)
{
bounds = clippingItem.visibleBounds;
}
}
if (bounds == undefined)
{
var subObjectBounds;
var bounds = [Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY];
var found = false;
for (var i = 0; i < object.pageItems.length; i++)
{
if (object.pageItems[i].hidden) continue;
found = true;
subObjectBounds = getVisibleBounds(object.pageItems[i]);
bounds[0] = Math.min(bounds[0], subObjectBounds[0]); // Left
bounds[1] = Math.max(bounds[1], subObjectBounds[1]); // Up
bounds[2] = Math.max(bounds[2], subObjectBounds[2]); // Right
bounds[3] = Math.min(bounds[3], subObjectBounds[3]); // Down
}
if (!found) bounds = undefined;
}
}
else
bounds = object.visibleBounds;
return bounds;
}