0
votes

I'm trying to automate the creation and inspection of master slides in Keynote using JavaScript for automation.

Creating master slides

It's easy to create a new document with a given theme and add slides with particular master slides to it.

// Create a new document using the "White" theme.
var Keynote = Application('Keynote');
var doc = Keynote.Document({
    documentTheme: Keynote.themes['White']
});
Keynote.documents.push(doc);

// Create and append a new "Title & Bullets" slide.
var slide = Keynote.Slide({
    baseSlide: doc.masterSlides['Title & Bullets']
});
doc.slides.push(slide);

This creates a new document with the "White" theme and appends a new "Title & Bullets" slide.

A similar approach does not work for master slides.

// Create a new document using the "White" theme.
var Keynote = Application('Keynote');
var doc = Keynote.Document({
    documentTheme: Keynote.themes['White']
});
Keynote.documents.push(doc);

// Create and append a new master slide.
var slide = Keynote.MasterSlide({
    name: "Testing"
});
doc.masterSlides.push(slide);

This creates a new document but no new master slide is created. Looking at the Script Editor Replies window, the push returns null in contrast to pushing a new Slide onto doc.slides which returns 2 (the number of slides in the array).

It is possible to duplicate a master slide, but only when Keynote is in "Edit Master Slide" mode. If the "Edit Master Slide" button has been clicked, then it's possible to duplicate a master slide.

var Keynote = Application('Keynote');
var doc = Keynote.documents[0];
var ms = doc.masterSlides['Title & Bullets'];
ms.duplicate();

This creates a new master slide named "Title & Bullets copy".

Inspecting master slides' properties

Inspecting master slides has similar, but slightly different issues. The following code should log the position, width, and height of the title item on the "Title & Bullets" master slide of the open document.

var Keynote = Application('Keynote');
var doc = Keynote.documents[0];
var ms = doc.masterSlides['Title & Bullets'];

var title = ms.defaultTitleItem();
var pos = title.position();

console.log("(x,y) = (" + pos.x + "," + pos.y + ")");
console.log("width x height = " + title.width() + " x " + title.height());

When run either outside of "Edit Master Slide" mode or in "Edit Master Slide" mode but with a different master slide selected, this code writes

/* (x,y) = (0,0) */
/* width x height = 0 x 0 */

to the log. In contrast, when run with the "Title & Bullets" master slide selected in "Edit Master Slide" mode, the correct values are logged.

/* (x,y) = (75,35) */
/* width x height = 874 x 170 */

Question

What is the appropriate way to create master slides, inspect their properties, and ultimately change them?

1

1 Answers

2
votes

Write your code in AppleScript first and see if you can get it to work there. AppleScript is an awful language, but its Apple event support is second to none and it's the de-facto standard against which all scriptable apps are developed and tested.

If it fails in AS then Keynote is broken. If it works in AS but fails when you translate it to JXA, JXA is broken. Both the CocoaScripting framework (used to implement Apple event support in macOS Apps) and JXA have a lot of defects and deficiencies, plus of course individual scriptable apps can contain their own bugs and bad design too†, so you'll have to figure out if it's the app or JXA that is failing through process of elimination.

...

From your description of observed behaviors and knowing that Apple's own scriptable apps are often buggy and ill-designed, I'm leaning towards the app, but I haven't touched iWork apps in years so can't say for sure.

If you find it's the app and decide to file a bug report (which sometimes works and other times doesn't), make sure to include the AppleScript code that illustrates the problem; AS is the de-facto standard and JXA is not, so it'll be one less layer of obfuscation and potential bugs for troubleshooters to wade through.


(†Not helped by the fact that Apple's developer documentation on how Apple event automation actually works and how to implement it well is dreadful too.)