My plugin runs with the below error with 「Athens」2025.1 version:
artboard.sketchObject.children is not a function. (In ‘artboard.sketchObject.children()’, ‘artboard.sketchObject.children’ is undefined);
While it’s not clear how children and layerEnumerator are used later in the script, one way to get rid of them is to use sketch.find JS API:
const sketch = require('sketch')
// ...
originArtboards.forEach(artboard => {
// These children are normal JS objects,
// so you can forEach/filter/map/etc them directly
const children = sketch.find("*", artboard);
const chldrenCount = children.length;
});
I noticed that the official plugin development API documentation lacks comprehensiveness. For example, APIs such as artboard.sketchObject.children or artboard.sketchObject.children().objectEnumerator() used in my plugin code are not explained in the official documentation. Could you please provide me with the latest and most detailed plugin development API documentation? Thank you very much.
So as soon as you see sketchObject in your code it means that everything that follows (children() and objectEnumerator() calls in this case) is a private API.
These private methods and functions are not documented by design – since they exist for Sketch itself to use, not plugin developers. Their usage in plugins, while sometimes justified and unavoidable even, usually predates the official JavaScript API – so there’s a good chance you may replace them with stable and more ergonomic modern counterparts.
For instance, objectEnumerator() is nothing more than an awkward way to iterate the children array – which is not needed when working with normal JS API arrays and objects.
And the undocumented children() call itself could be replaced by sketch.find() one I’ve mentioned above that does exactly the same.
I also agree that documentation should probably cover not only what’s available in the JS API, but also help with migration from outdated private APIs to modern public ones. Until it does, I’m here to answer any of your further questions!
As for hasFixed*() methods, there’re JS APIs available to inspect layer’s sizing and pinning details:
let hasFixedWidth = (layer.horizontalSizing === 0);
let hasFixedHeight = (layer.verticalSizing === 0);
Now determining whether a certain layer side is pinned is a bit more involved, but still very much possible:
let hasFixedLeft = (
// Here we have to check if *only* the left side is pinned ...
layer.horizontalPins === 1
||
// ... or both left *and* right sides are pinned
layer.horizontalPins == 5
);
// Same for other side as well
let hasFixedRight = (layer.horizontalPins === 4 || layer.horizontalPins == 5);
// And for the vertical axis
let hasFixedTop = (layer.verticalPins === 1 || layer.verticalPins == 5);
let hasFixedBottom = (layer.verticalPins === 4 || layer.verticalPins == 5);
This API is certainly very awkward to use, but you can write a simple wrapper function around them for convenience.
FYI: Pins are only active on layers that either
a) belong to a Frame, or
b) don’t belong to a Frame nor Graphic, but to a regular non-top-level Group (ie it’s not a page-level one).
You can check the type of a specific Group object via its groupBehavior property:
if (layer.parent?.groupBehavior === 2) {
// The parent is a <Graphic> group, which does NOT allow layer pinning.
// In order words, layerHasFixedEdge() will always return `false` for any sublayer of this group
const pinsAllowed = false;
}
All of the canFix*() checks are redundant in Athens as they’d always evaluate to true (unless you’re in a Graphic group, in which case the result will be false – again, see above).
I mean your exportImage() function might as well be rewritten to use the JS API: