Skip to content

amrwc/ios-scriptable-scripts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

iOS Scriptable Scripts

Importing a script through iCloud Drive

  1. Save the script as a .js file.

    • Optionally, add Scriptable-specific directives at the top, similar to the following. Scriptable will do it automatically when the appearance will be adjusted from within the app.

      // Variables used by Scriptable.
      // These must be at the very top of the file. Do not edit.
      // icon-color: deep-green; icon-glyph: magic;
    • The file name is the title of the script in visible the app.

  2. Put the file in the Scriptable directory in iCloud Drive.

    The script should be visible inside the Scriptable app immediately after the directory has been synced.

Importing modules

There's a module importing functionality in the app.

Simply create an index.js file in a directory, where the directory name is the module name. Take this directory structure for instance:

SomeScriptableScript.js
lib/
├─ service/
│  ├─ FooBarService/
│     ├─ index.js
│  ├─ DifferentService/
│     ├─ index.js

Then, you import the module like so:

// SomeScriptableScript.js
const FooBarService = importModule('lib/service/FooBarService');

Relative imports also work:

// lib/service/DifferentService/index.js
const FooBarService = importModule('../FooBarService');

Known issues

Class fields

This doesn't work:

// lib/const/FeatureFlag/index.js
class FeatureFlag {
    static LOG_MODULE_IMPORTS = true;
}
module.exports = FeatureFlag;

// Other file
const FeatureFlag = importModule('lib/const/FeatureFlag');
console.log(FeatureFlag.LOG_MODULE_IMPORTS); // undefined

According to this website, it's unsupported in old browsers, which is what we might be dealing with here.

Instead, place 'class constants' in module.exports directly:

// lib/const/FeatureFlag/index.js
module.exports = {
    LOG_MODULE_IMPORTS: true,
};

// Other file
const FeatureFlag = importModule('lib/const/FeatureFlag');
console.log(FeatureFlag.LOG_MODULE_IMPORTS); // true

// Or, more concisely
const { LOG_MODULE_IMPORTS } = importModule('lib/const/FeatureFlag');
console.log(LOG_MODULE_IMPORTS); // true

Unit-testing

yarn install
yarn test

Scriptable's propriety library

Given the nature of Scriptable's propriety library, it's hard to unit test code that has references to static objects from inside the library.

A workaround is to define global objects around the tests:

const Data = (global.Data = jest.fn());

Then, used in tests:

const Data = (global.Data = jest.fn());

describe('when base64-encoding an image', () => {
	it.each([JPG, PNG, 'unsupported'])('should return an empty string when base64 encoding fails', (type) => {
		Data.fromJPEG = jest.fn().mockReturnValueOnce(null);
		Data.fromPNG = jest.fn().mockReturnValueOnce(null);

		expect(ImageUtil.base64EncodeImage(null, type)).toBe('');

		expect(Data.fromJPEG).toBeCalledTimes('jpg' === type ? 1 : 0);
		expect(Data.fromPNG).toBeCalledTimes('png' === type ? 1 : 0);
	});
});

Resources on global variables in JavaScript: