Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Setup

This document describes how to use the library contained in this lib directory to create scripts that run:

  1. In CLI on macOS
  2. From the share sheet on iOS/iPadOS (Using Shortcuts)
  3. From the home screen on iOS/iPadOS (Using Shortcuts)
  4. In the Scriptable App on iOS/iPadOS

Writing Scripts

In order for scripts to be able to run in all environments, they cannot use:

  • require(...) (importing NodeJS modules)
  • import ... (ES6-style imports)
  • importModule(...) (Scriptable-style import)

Instead, use these four lines to import the correct set of library functions depending on environment:

// @ts-ignore
// eslint-disable-next-line
try { require; } catch(e) { require = importModule; }
const lib = require('./lib/lib.js');

The lib variable will then contain the library, with functions to:

  1. Request complex input (date/times, choosing from a set, files/folders, etc.)
  2. Download/Upload Data
  3. Reading/writing to the filesystem (text or binary)
  4. Displaying notifications, text logs, rich HTML, or rendered Markdown

For a full list of functions and constants in the bridge library, see the API documentation.

Environment Setup: Scriptable and CLI

  1. Download Scriptable on an iOS/iPadOS Device
  2. On a Mac: Copy this lib directory into the Scriptable iCloud directory
  3. On a Mac: Put this code in ~/.zshrc:
export PATH_SCRIPTABLE=~/Library/Mobile\ Documents/iCloud~dk~simonbs~Scriptable/Documents
for file in $PATH_SCRIPTABLE/*.js; do
    alias $(basename $file | tr '[A-Z]' '[a-z]' | tr ' ' '-')="node \"$file\""
done

Once done, all scripts will be aliased for use in the CLI in lower-kebab-case. For instance, if a script is called Test File Name.js, a user could run: test-file-name.js --help.

Also, at this point, all scripts can be run in the Scriptable app on iOS.

Environment Setup: Shortcuts (Share Sheets and Home Screens)

For each script whose getInput(...) call specifies share: true, create a shortcut. That shortcut should accept strings and urls, so that it displays on the share sheet. It should have the following steps:

  1. Dictionary (↓) → Run shortcut (Scriptable Harness[2]), Input: ()[3]
    1. (script) (Text) → (ScriptName)[1]
    2. (share) (Text) → ($SHORTCUT-INPUT)

For each script that does not need to show up on a share sheet, create a shortcut. That shortcut should accept no input, and it should have the following steps:

  1. Dictionary (↓) → Run shortcut (Scriptable Harness[2]), Input: ()[3]
    1. (script) (Text) → (ScriptName)[1]
    2. (share) (Text) → ()

That shortcut can be added to the home screen.

Notes:

  1. "ScriptName" is the script to run. For example: Test File Name to run: Test File Name.js.
  2. This requires having created the "Scriptable Harness" shortcut described in the "Helper Shortcuts" section below.
  3. always refers to the result of the previous item in the same scope, including "Repeat Results" when referenced right outside/after a "Repeat".

Helper Shortcuts

Scriptable Harness Run JS

Bash Script

export PATH="{{PATH}}"

node "/Path/To/This/Repository/{{NAME}}.js" --shortcuts-args "$1" --shortcuts-mode "{{MODE}}"

Notes:

  1. The {{PATH}} text should be replaced by pasting after running echo $PATH | pbcopy in a terminal.
  2. The {{NAME}} text should be replaced with the shortcuts $name variable block.
  3. The {{MODE}} text should be replaced with the shortcuts $mode variable block.

Shortcuts Code

  1. Set variable (input) to ($SHORTCUT-INPUT)
  2. Get (Value) for (name) in ($input) → Set variable (name) to ()
  3. Get (Value) for (args) in ($input) → Set variable (args) to ()
  4. Get (Value) for (mode) in ($input) → Set variable (mode) to ()
  5. Get (Value) for (inScriptable) in ($input) → Set variable (inScriptable) to (↪ as boolean)
  6. If (OS) (is) (macOS)
    1. Run Shell Script (BASH SCRIPT IN SECTION ABOVE), Shell: (zsh), Input: ($args), Pass Input: (as arguments), Run as Administrator: (☐)
  7. Otherwise
    1. Get file from (iCloud → Scriptable) at path ($name.js), Error if Not Found: (☑) → $MAGIC-SCRIPTABLE-FILE
    2. If $inScriptable
      1. [Scriptable] Run Inline Script ($MAGIC-SCRIPTABLE-FILE as text), Texts: [$args, $mode], Run In App: (☑), Show When Run: (☑)
    3. Otherwise
      1. [Scriptable] Run Inline Script ($MAGIC-SCRIPTABLE-FILE as text), Texts: [$args, $mode], Run In App: (☐), Show When Run: (☐)

Scriptable Harness Get File

  1. Set variable (input) to ($SHORTCUT-INPUT)
  2. Get (Value) for (type) in ($input) → Replace (pathF) with (F) in () → Text(s) → Set variable (type) to ()
  3. Get (Value) for (bookmarkName) in ($input) → Set variable (bookmarkName) to ()
  4. Select File/Folder ($type), Select Multiple: (☐) → $MAGIC-FILE
  5. If (OS) (is) (macOS)
    1. Stop and output ($MAGIC-FILE as File Path)
  6. Otherwise
    1. [Scriptable] Create bookmark named ($bookmarkName) for ($MAGIC-FILE)
    2. Stop and output $bookmarkName

Scriptable Harness

  1. Set variable (inputDictionary) to ($SHORTCUT-INPUT)
  2. Get (Value) for (script) in ($inputDictionary) → Set variable (script) to ()
  3. Get (Value) for (share) in ($inputDictionary) → Set variable (share-raw) to ()
  4. Text ($share-raw) → Set variable (share-input) to ()
  5. Dictionary () → Set variable (output) to ()
  6. Get file from (iCloud → Scriptable → args) at path ($script.json), Error If Not Found: (☐) → $MAGIC-FILE-ARGS
  7. If ($MAGIC-FILE-ARGS) (has any value)
    1. Set variable (argJsonString) to $MAGIC-FILE-ARGS
  8. Otherwise
    1. Dictionary (↓) → Run (Scriptable Harness Run JS), Input: () → Set variable (argJsonString) to ()
      1. (name) (Text) → ($script)
      2. (args) (Text) → ({})
      3. (mode) (Text) → (shortcuts.getArgs)
      4. (inScriptable) (Boolean) → (False)
  9. Get dictionary from ($argJsonString) → $MAGIC-ARGS
  10. Get (Value) for (inScriptable) in ($MAGIC-ARGS) → Set variable (inScriptable) to ()
  11. Get (Value) for (outputType) in ($MAGIC-ARGS) → Text () → Set variable (outputType) to ()
  12. Get (Value) for (args) in ($MAGIC-ARGS)
  13. → Repeat with each item in ()
    1. // Parse Argument Properties
    2. Get (Value) for (name) in ($REPEAT-ITEM) → Text () → Set variable (name) to ()
    3. Get (Value) for (type) in ($REPEAT-ITEM) → Text () → Set variable (type) to ()
    4. Get (Value) for (help) in ($REPEAT-ITEM) → Text () → Set variable (help) to ()
    5. Get (Value) for (bookmarkName) in ($REPEAT-ITEM) → Text () → Set variable (bookmarkName) to ()
    6. Get (Value) for (share) in ($REPEAT-ITEM) → Text () → Set variable (share) to ()
    7. // Argument is SHARE
    8. If ($share) (is) (Yes)
      1. Match (^\s+$) in ($share-input) → $MAGIC-MATCH
      2. If (All) are true: ($MAGIC-MATCH as text) (does not have any value) and ($share-input) (is not) ()
        1. Set ($name) to ($share-input) in ($output) → Set variable (output) to ()
        2. Text (share) → Set variable (type) to ()
    9. // Argument is PATHFILE or PATHFOLDER
    10. If Any are true: ($type) is (pathFile) or ($type) is (pathFolder)
      1. Show alert ($help), Title: ($name), Show Cancel Button: (☐)
      2. Dictionary (↓) → Run (Scriptable Harness Get File), Input: ()
        1. (type) (Text) → ($type)
        2. (bookmarkName) (Text) → ($bookmarkName)
      3. → Set ($name) to () in $output → Set variable (output) to ()
    11. // Argument is ENUM
    12. If ($type) is (enum)
      1. Dictionary () → Set variable (enumMap) to ()
      2. Get (Value) for (choices) in ($REPEAT-ITEM)
      3. → Repeat with each item in ()
        1. Get (Value) for (title) in ($REPEAT-ITEM-2) → $MAGIC-enumTitle
        2. Get (Value) for (code) in ($REPEAT-ITEM-2) → $MAGIC-enumCode
        3. Set ($MAGIC-enumTitle) to ($MAGIC-enumCode) in $enumMap → Set variable (enumMap) to ()
        4. Text ($MAGIC-enumTitle)
      4. → Choose from (), Prompt ($name: $help)
      5. → Get (Value) for () in (enumMap)
      6. → Set ($name) to () in $output → Set variable (output) to ()
    13. // Argument is STRING
    14. If ($type) (is) (string)
      1. Ask for (Text) with ($name: $help)
      2. → Set ($name) to () in ($output) → Set variable (output) to ()
    15. // Argument is BOOLEAN
    16. If ($type) (is) (boolean)
      1. Dictionary (↓) → $MAGIC-BOOLEANS
        1. (True) (Boolean) → (True)
        2. (False) (Boolean) → (False)
      2. → Choose from (↪ as Keys), Prompt: ($name: $help) → Get (Value) for () in ($MAGIC-BOOLEANS)
      3. → Set ($name) to () in ($output) → Set variable (output) to ()
    17. // Argument is DATE
    18. If ($type) (is) (date)
      1. Ask for (Date and Time) with ($name: $help), Default Date and Time: ($CURRENT-DATE)
      2. → Format (), Date Format: (RFC 2822)
      3. → Set ($name) to () in ($output) → Set variable (output) to ()
  14. Dictionary (↓) → Run (Scriptable Harness Run JS), Input: () → $MAGIC-JS-OUTPUT
    1. (name) (Text) → ($script)
    2. (mode) (Text) → (shortcuts.setArgs)
    3. (inScriptable) (Boolean) → ($inScriptable)
    4. (args) (Text) → ($output)
  15. Show notification ($MAGIC-JS-OUTPUT)
  16. If ($outputType) (is) (data)
    1. Copy ($MAGIC-JS-OUTPUT) to clipboard

Save to Files (Extension)

Accepts: Text

  1. Text: "$SHORTCUT-INPUT"
  2. Set name of ($PREVIOUS) to (Text) More(Don't Include File Extension: (On))
  3. Save ($PREVIOUS) Service: (iCloud Drive) Ask Where to Save: (On)