Macotron

macotron.url

Open URLs in the app you choose, and route links that macOS hands to Macotron to your plugin's handlers. With this, a plugin can act as the default browser and send each link to the right one.

// Send work links to Chrome and everything else to Safari.
for (const scheme of ["http", "https"]) {
  macotron.url.setDefaultHandler(scheme);
  macotron.url.on(scheme, "github.com", (e) => macotron.url.open(e.url, "com.google.Chrome"));
  macotron.url.on(scheme, "*", (e) => macotron.url.open(e.url, "com.apple.Safari"));
}

Opening

open(url: string, bundleID?: string, profile?: string): boolean

Opens url in the app with this bundle ID, or in the system default app for the URL when you leave bundleID out. profile is passed to the app as --profile-directory=<profile>, which selects a profile in Chrome and other Chromium browsers. Returns false when the URL does not parse or no app has that bundle ID.

Routing

Macotron can receive http, https, mailto and macotron links. It receives the first three only when it is the default handler for them; see setDefaultHandler.

on(scheme: string, host: string | RegExp, callback: (event: URLEvent) => void): void

Calls callback for links with this scheme and host. A host string matches that host and its subdomains, so "example.com" also matches docs.example.com. "*" matches any host. A RegExp is tested against the host.

For each link, Macotron picks one handler, in this order:

  1. An exact host match.
  2. The longest matching parent domain.
  3. The first RegExp that matches, in the order you registered them.
  4. A "*" handler for the scheme.
  5. The onFallback handler.

Scheme and host compare without regard to case. Links that arrive while plugins are loading wait and are delivered once loading finishes.

The event has these fields:

FieldWhat it holds
urlThe full URL.
schemeFor example "https".
hostFor example "github.com", or "".
pathFor example "/apple/swift".
queryThe text after ?, or "" when there is none.
sourceBundleThe bundle ID of the app that sent the link, when macOS reports it.

onFallback(callback: (event: URLEvent) => void): void

Calls callback for any link that no on handler matches, in every scheme. Only one fallback exists at a time; a later call replaces it, from any plugin.

When nothing handles a link, Macotron passes it to the app that would open it if Macotron were not installed. If there is no such app, Macotron posts a notification so the link is not lost.

Prefer on(scheme, "*", …) over onFallback in a browser picker. A fallback also catches mailto: links and would send them to a browser.

setDefaultHandler(scheme: string): boolean

Makes Macotron the system default app for scheme, for example "https". Returns false for an empty scheme or when macOS refuses.

Any web page or app can open a macotron:// link, so these links can start plugin actions from outside. Before Macotron routes one, it shows an "Allow URL Event?" alert with the URL and the sending app. The handler runs only if the user clicks Allow.

// open "macotron://timer/start?min=25"
macotron.url.on("macotron", "timer", ({ path, query }) => {
  if (path === "/start") {
    const min = Number((query.match(/min=(\d+)/) || [])[1]) || 25;
    startTimer(min);
  }
});

See also