Allow programmatically supplying name to dom.export in JS API
cmcculloh-kr opened this issue · 1 comments
TL;DR: Allow user to provide name for file asset is to be exported to. Perhaps something like fileName
:
dom.export(artboard, {
output: path,
fileName: artboard.name,
formats: format.fileFormat,
scales: format.size,
overwriting: true,
});
Note: The above assumes that the fileFormat suffix will NOT be appended to the name. So a fileName: "bob"
exported as PNG would end up being called bob
. The suffix/prefix in sketch should likewise NOT be included. So, if the user specifies that the exported file should have a @2x
suffix through sketch's interface, the final filename should still be bob
. This will afford developers full control over their exported filenames.
Expanded explanation
Currently export does not (appear to) allow you to supply a name for the exported asset. Exports are named after a combination of their layerName + their export size (but completely ignoring the user's settings for suffix/prefix). So, a layer named bob
set to export as PNG
at 2x
and a prefix of what-about-
would result in a file named bob@2x.png
instead of the (to me, expected) what-about-bob.png
(note that the later would match Sketch's inbuilt export behavior, whereas the former does not, which makes things inconsistent for the user).
In order to work around this I have to export the asset, reconstruct the name Sketch gave it (for instance, it tacks @2x on to the artboard name regardless of what I have set in sketch, which I take to be a bug), and then move the asset from that location to the location I want it to be at (in order to rename it to what I would like it to be named).
Here's the code for that:
const fm = NSFileManager.defaultManager();
const dom = require('sketch/dom');
const doc = dom.getSelectedDocument();
const absPath = (path) => NSString.stringWithString(path).stringByExpandingTildeInPath();
const combinePath = (a, b) => NSString.stringWithString(a).stringByAppendingPathComponent(b);
const endsWith = (str, suffix) => str.indexOf(suffix, str.length - suffix.length) !== -1;
const outputPath = absPath('~/test');
const tempPath = combinePath(outputPath, '/~~~');
function makeExportName(artboard, format) {
return [].concat(
format.prefix ? format.prefix : [],
artboard.name,
format.suffix ? format.suffix : [],
'.',
format.fileFormat,
).join('')
}
const getArtboardsFromLayers = (layers) =>
layers.flatMap((layer) => {
switch (layer.type) {
case 'Page':
case 'Group':
case 'Symbol':
if (layer.layers) {
return getArtboardsFromLayers(layer.layers);
}
break;
case 'Artboard':
return [ layer ];
break;
default:
return [];
}
});
const layers = doc.getLayersNamed('main');
const artboards = getArtboardsFromLayers(layers);
artboards.forEach((artboard) => {
artboard.exportFormats.forEach((format) => {
dom.export(artboard, {
output: tempPath,
formats: format.fileFormat,
scales: format.size,
overwriting: true,
});
const errorPtr = MOPointer.alloc().init();
const files = fm.contentsOfDirectoryAtPath_error_(tempPath, errorPtr);
console.log('exported');
if (files && files.count()) {
const tempFilePath = combinePath(tempPath, files.firstObject());
// assets
let outputFilePath = combinePath(outputPath, makeExportName(artboard, format));
console.log('here: ', outputFilePath)
if (endsWith(outputFilePath, 'null.png')) {
outputFilePath = outputFilePath.replace('null.png', '.png');
}
if (outputFilePath.startsWith('null')) {
outputFilePath = outputFilePath.replace('null', '');
}
outputFilePath = outputFilePath.replace('null', '');
fm.removeItemAtPath_error_(outputFilePath, null);
fm.moveItemAtPath_toPath_error_(tempFilePath, outputFilePath, null)
}
});
});
If this proposed change were implemented, I could instead just do:
const fm = NSFileManager.defaultManager();
const dom = require('sketch/dom');
const doc = dom.getSelectedDocument();
const absPath = (path) => NSString.stringWithString(path).stringByExpandingTildeInPath();
const combinePath = (a, b) => NSString.stringWithString(a).stringByAppendingPathComponent(b);
const endsWith = (str, suffix) => str.indexOf(suffix, str.length - suffix.length) !== -1;
const outputPath = absPath('~/test');
const tempPath = combinePath(outputPath, '/~~~');
const getArtboardsFromLayers = (layers) =>
layers.flatMap((layer) => {
switch (layer.type) {
case 'Page':
case 'Group':
case 'Symbol':
if (layer.layers) {
return getArtboardsFromLayers(layer.layers);
}
break;
case 'Artboard':
return [ layer ];
break;
default:
return [];
}
});
const layers = doc.getLayersNamed('main');
const artboards = getArtboardsFromLayers(layers);
artboards.forEach((artboard) => {
artboard.exportFormats.forEach((format) => {
dom.export(artboard, {
output: tempPath,
fileName: artboard.name,
formats: format.fileFormat,
scales: format.size,
overwriting: true,
});
});
});
+1