Git Product home page Git Product logo

shortcuts-js's Introduction

Shortcuts JS Logo

GitHub license npm version Build Status Coverage Status PRs Welcome Discord

A Node.js iOS 12 Shortcuts creator.

Find out more at Shortcuts.fun.

@joshfarrant/shortcuts-js on npm.

NPM | Documentation | Contributing | Medium | Discord

See this issue for a complete list of all Actions implemented so far.

We have a Discord! If you need any help or have any questions, come and say hi! Join the Discord

Is the Action you want not available?

We're still working our way through the long list of built-in Shortcut Actions, if there's one you need sooner rather than later then Open an Issue and let us know; we might be able to prioritise it.

Alternatively, it's super easy to add an Action yourself! A simple Action should only take about 15 minutes to implement. Check out the Contributing Guide for more info on where to start. If for any reason you get stuck just Open an Issue. We're happy to help!

Minimal Example

npm install @joshfarrant/shortcuts-js
// Only used to create the .shortcut file
const fs = require('fs');

const {
  actionOutput,
  buildShortcut,
  withVariables,
} = require('@joshfarrant/shortcuts-js');
const {
  calculate,
  comment,
  number,
  showResult
} = require('@joshfarrant/shortcuts-js/actions');

// We'll use this later to reference the output of a calculation
const calcVar = actionOutput();

// Define our list of actions
const actions = [
  comment({
    text: 'Hello, world!',
  }),
  number({
    number: 42,
  }),
  calculate({
    operand: 3,
    operation: '/',
  }, calcVar),
  showResult({
    /**
     * We can use the result of the calculation in this Shortcuts's input
     * by passing the string to the 'withVariables' tag function
     */
    text: withVariables`Total is ${calcVar}!`,
  }),
];

// Generate the Shortcut data
const shortcut = buildShortcut(actions);

// Write the Shortcut to a file in the current directory
fs.writeFile('My Fancy Shortcut.shortcut', shortcut, (err) => {
  if (err) {
    console.error('Something went wrong :(', err);
    return;
  }
  console.log('Shortcut created!');
});

Running this code will build a Shortcut named 'My Fancy Shortcut.shortcut' in the current directory.

This can be AirDropped to an iPhone or iPad running iOS 12, at which point it will be automatically opened and imported into Shortcuts.

Shortcut Image

Further Examples

For brevity, these examples omit the code for writing the file to disk and just focus on building the Shortcut. See the Minimal Example above for an example of how to create the .shortcut file.

Battery level checker, with conditional action

const {
  actionOutput,
  buildShortcut,
  withVariables,
} = require('@joshfarrant/shortcuts-js');
const {
  conditional,
  getBatteryLevel,
  setLowPowerMode,
  showResult,
} = require('@joshfarrant/shortcuts-js/actions');

const batteryLevel = actionOutput();

const actions = [
  getBatteryLevel({}, batteryLevel),
  conditional({
    input: '<',
    value: 20,
    ifTrue: [
      setLowPowerMode({
        value: true,
      }),
      showResult({
        text: withVariables`Your battery is at ${batteryLevel}%, you might want to charge it.`,
      }),
    ],
    ifFalse: [
      showResult({
        text: withVariables`Your battery is at ${batteryLevel}%, you're probably fine for now.`,
      }),
    ],
  })
];

const shortcut = buildShortcut(actions);

Battery Checker Shortcut Image

Shortcut folder creator

This example creates folders and subfolders of Shortcuts so they can be easily run from one 'Folder' Shortcut.

This Shortcut could be tedious to set up using the drag-and-drop interface of the Shortcuts app, however we can simplify the generation of this Shortcut by using a function to build our actions from a predefined array of strings.

const {
  buildShortcut,
  withVariables,
} = require('@joshfarrant/shortcuts-js');
const {
  conditional,
  getBatteryLevel,
  setLowPowerMode,
  showResult,
} = require('@joshfarrant/shortcuts-js/actions');

const foldersArr = [
  ['Health', [ // The name of the folder
    'Log Sleep', // The names of Shortcuts to contain in that folder
    'Log Run',
    'Log Cycle',
  ]],
  ['Home', [
    ['Lights', [
      'Lights On', // We can go as many levels deep as we like
      'Lights Off',
    ]],
    ['Heating', [
      'Heating On',
      'Heating Off',
    ]],
    ['Cameras', [
      'Cameras On',
      'Cameras Off',
    ]],
    ['Door', [
      'Lock Door',
      'Unlock Door',
    ]],
  ]],
  ['Audio', [
    'Play Playlist',
    'Resume Podcast'
  ]],
];

const buildFolders = (arr) => (
  arr.map(shortcut => (
    Array.isArray(shortcut) ? ({
      label: shortcut[0],
      actions: [
        chooseFromMenu({
          prompt: shortcut[0],
          items: buildFolders(shortcut[1]),
        }),
      ],
    }
    ) : ({
      label: shortcut,
      actions: [
        runShortcut({
          name: shortcut,
        }),
      ],
    })
  ))
);

const actions = [
  chooseFromMenu({
    prompt: 'Open',
    items: buildFolders(foldersArr),
  }),
];

const shortcut = buildShortcut(actions);

Folder Shortcut Gif

Anything Else

If you're having any issues getting started, or you'd just like some advice, then please don't be afraid to Open an Issue, we're here to help!

shortcuts-js's People

Contributors

archez avatar bachya avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar gcordalis avatar ikaikastine avatar jakebathman avatar jb1905 avatar joshfarrant avatar jtokash avatar lee-hyunkyu avatar n33kos avatar pfgithub avatar pietropizzi avatar regaw-leinad avatar swatto avatar xalien95 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

shortcuts-js's Issues

Shortcut for iOS setting?

Shortcut for IOS, how shortcuts can I get to the specified place?
For example: IOS-- Settings -- Accessibility -- Touch -- Accessibility -- Device

Document new options parameter for buildShortcut function

#16 added support for an optional options parameter to the buildShortcut function.

Currently, the supported options are:

buildShortcut([], {
  icon: {
    color: COLORS.LIGHT_BLUE // Or any color specified in src/meta/colors.ts
    glyph: GLYPHS.E9AE // Or any glyph specified in src/meta/glyphs.ts
  },
});

Currently, this functionality isn't documented anywhere. It would be useful to add some information about this feature (along with an example) to the README.

Additionally, we could improve the typedoc documentation comments for the buildShortcut function to include information about the options object and it's accepted types.

All Actions to be implemented

This is an up-to-date list of all actions Shortcuts JS will eventually implement. Actions which have already been implemented will be ticked off as they are added.

For the moment, the list includes all Actions in the 'Scripting' list and 'Content Types' section from the Shortcuts app. There are a few Actions from 3rd party apps in those sections, so they have been included here too. Any requests for additional 3rd party app Actions which aren't on this list should be added as new issues, rather than as comments on this issue.

If you'd like to help out, then feel free to grab any Action from this list and implement it! Have a look at the Contributing Guide for more info on how to add a new Action.

If I've missed anything, please let me know! 🙂

Actions

Scripting

  • Comment
  • Show Result

Content

  • Count
  • Get Name
  • Get Type
  • Nothing
  • Set Name
  • View Content Graph

Control Flow

  • Choose from Menu
  • Continue Shortcut in App
  • Exit Shortcut
  • If
  • Repeat
  • Repeat with Each
  • Wait
  • Wait to Return - 💙 @Archez

Device

Dictionaries

  • Dictionary
  • Get Dictionary from Input - 💙 @gcordalis
  • Get Dictionary Value
  • Set Dictionary Value - 💙 @gcordalis

Files

Lists

  • Choose from List
  • Get Item from List
  • List

Maths

  • Calculate
  • Calculate Statistics - 💙 @bachya
  • Convert Measurement
  • Format Number
  • Measurement
  • Number
  • Random Number - 💙 @bachya
  • Round Number

Notification

Run Script Over SSH

  • Run Script Over SSH - 💙 @Archez

Shortcuts

  • Get My Shortcuts - 💙 @JB1905
  • Run Shortcut

Variables

  • Add to Variable - 💙 @Archez
  • Get Variable - 💙 @Archez
  • Set Variable

X-Callback

  • Open X-Callback URL
  • URL Encode - 💙 @gcordalis

Editorial

  • Run Editorial Workflow

Pythonista

  • Edit Script (Pythonista) - 💙 @bachya
  • Run Script (Pythonista) - 💙 @bachya

Tally

  • Get Tally (Tally)
  • Update Tally (Tally)

Content Types

Apps

App Store

  • Get Details of App Store App
  • Search App Store

Calendar

Calendar

  • Add New Event
  • Filter Event Attendees
  • Find Calendar Events
  • Get Details of Calendar Events
  • Get Details of Event Attendees
  • Get Upcoming Events
  • Remove Events
  • Show in Calendar - 💙 @gcordalis

Clock

Dates

Reminders

  • Add New Reminder
  • Find Reminders
  • Get Details of Reminders
  • Get Upcoming Reminders
  • Remove Reminders - 💙 @gcordalis

Fantastical

  • Add Event via Fantastical
  • Add Reminder via Fantastical
  • Show in Fantastical

Contacts

Contacts

  • Contacts
  • Find Contacts
  • Get Contacts from Input - 💙 @gcordalis
  • Get Details of Contacts
  • Select Contact

Mail

  • Email Address
  • Get Email Addresses from Input - 💙 @gcordalis
  • Select Email Address - 💙 @gcordalis

Payments

  • Request Payment
  • Send Payment

Phone

  • Call
  • FaceTime
  • Get Phone Numbers from Input - 💙 @gcordalis
  • Phone Number
  • Select Phone Number - 💙 @gcordalis

Skype

  • Call via Skype

Documents

Archives

Books

Editing

File Storage

  • Append to File
  • Create Folder
  • Delete Files
  • Get File
  • Get Link to File - 💙 @gcordalis
  • Save File

Files

  • Filter Files
  • Format File Size
  • Get Details of Files
  • Open In...

Previewing

Printing

Bear

  • Add to Bear Note
  • Create Bear Note
  • Create Bear Note from URL
  • Get Contents of Bear Note
  • Open Bear Note
  • Search in Bear

Drafts

  • Add to Draft
  • Get Contents of Draft
  • Open Draft
  • Run Drafts Action

Evernote

  • Append to Note
  • Create New Note
  • Delete Notes
  • Get Note Link
  • Get Notes

GoodReader

  • Open in GoodReader

Ulysses

  • Add to Ulysses Sheet
  • Attach to Ulysses Sheet
  • Get Details of Ulysses Sheet
  • Get Ulysses Sheet
  • New Ulysses Group
  • New Ulysses Sheet
  • Open Ulysses

Health

Health

  • Find Health Samples
  • Get Details of Health Sample
  • Log Health Sample
  • Log Workout

Home

Home

  • Run Home Scene

Location

  • Filter Locations
  • Get Current Location
  • Get Details of Locations

Maps

  • Get Addresses from Input - 💙 @gcordalis
  • Get Distance
  • Get Halfway Point
  • Get Maps URL - 💙 @JB1905
  • Get Travel Time
  • Search Local Businesses
  • Show Directions
  • Show in Maps - 💙 @JB1905
  • Street Address

Weather

  • Get Current Weather
  • Get Details of Weather Conditions
  • Get Weather Forecast

BlindSquare

  • Show in BlindSquare

Music

iTunes Store

  • Get Details of iTunes Artist
  • Get Details of iTunes Product
  • Search iTunes Store
  • Show in iTunes Store - 💙 @gcordalis

Music

  • Add to Playlist
  • Add to Up Next
  • Clear Up Next - 💙 @gcordalis
  • Clear Playlist
  • Find Music
  • Get Current Song - 💙 @gcordalis
  • Get Details of Music
  • Get Playlist
  • Play Music
  • Select Music

Playback

Photos & Video

Audio

  • Record Audio

Camera

  • Take Photo
  • Take Video

Editing

  • Combine Images
  • Crop Image
  • Flip Image
  • Markup - 💙 @JB1905
  • Mask Image
  • Overlay Image
  • Resize Image
  • Rotate Image

GIFs

  • Add Frame to GIF
  • Get Frames from Image - 💙 @gcordalis
  • Make GIF
  • Make Video from GIF

Images

  • Convert Image
  • Filter Images
  • Get Details of Images
  • Get Images from Input - 💙 @gcordalis

Photos

Video

Imgur

  • Upload to Imgur

Lightroom

  • Import to Lightroom

Sharing

Clipboard

  • Copy to Clipboard
  • Get Clipboard - 💙 @gcordalis

Mail

  • Send Email

Messaging

  • Send Message

Notes

Photos

  • Post to Shared Album

System

Facebook

Instagram

Tumblr

Tweetbot

  • Open Tweetbot
  • Search Text
  • Tweet
  • View Profile in Tweetbot

Twitter

WhatsApp

  • Send Message via WhatsApp
  • Send Photo via WhatsApp

WordPress

Text

  • Detect Language with Microsoft - 💙 @gcordalis
  • Dictate Text
  • Generate QR Code
  • Get Name of Emoji - 💙 @gcordalis
  • Get Text from Input - 💙 @gcordalis
  • Scan QR/Barcode - 💙 @gcordalis
  • Show Definition - 💙 @gcordalis
  • Speak Text
  • Text
  • Translate Text with Microsoft

Rich Text

  • Make HTML from Rich Text
  • Make Markdown from Rich Text - 💙 @gcordalis
  • Make Rich Text from HTML - 💙 @gcordalis
  • Make Rich Text from Markdown - 💙 @gcordalis

Text Editing

  • Change Case
  • Combine Text
  • Correct Spelling - 💙 @gcordalis
  • Get Group from Matched Text
  • Match Text - 💙 @gcordalis
  • Replace Text
  • Split Text

2Do

  • Add 2Do Task

Captio

  • Append to Note
  • Send Note

Clear

  • Add Clear List
  • Add Clear Task

Day One

  • Create Day One Entry

Due

  • Add Due Reminder

iTranslate

  • Show in iTranslate

OmniFocus

  • Add OmniFocus Item
  • Add TaskPaper to OmniFocus

The Hit List

  • Add Task to The Hit List

Things

  • Add Things To-Do

Todoist

  • Add Todoist Item

Trello

  • Add Trello Card
  • Create Trello Board
  • Create Trello List
  • Get Details of Trello Item
  • Get Trello Items

Wunderlist

  • Add Wunderlist Task

Web

Articles

  • Filter Articles
  • Get Details of Diffbot Article
  • Get Diffbot Article from Web Page - 💙 @gcordalis

Giphy

  • Search Giphy

Safari

  • Add to Reading List - 💙 @gcordalis
  • Get Contents of Web Page - 💙 @gcordalis
  • Get Details of Safari Web Page
  • Open URLs - 💙 @gcordalis
  • Run JavaScript on Web Page - 💙 @gcordalis
  • Search Web
  • Show Web Page

URLs

  • Expand URL - 💙 @gcordalis
  • Get Component of URL
  • Get Contents of URL
  • Get Headers of URL - 💙 @gcordalis
  • Get Items from RSS Feed
  • Get RSS Feeds from Page
  • Get URLs from Input - 💙 @gcordalis
  • URL

Associate

  • Convert URL with Associate
  • Search in Associate

Blink

  • Convert URL with Blink
  • Search in Blink

Chrome

  • Open URLs in Chrome - 💙 @JB1905

CloudApp

  • Upload to CloudApp

Instapaper

  • Add to Instapaper
  • Get Instapaper Bookmarks

Opener

  • Open URL in Opener

Overcast

  • Add to Overcast

Pinboard

  • Add to Pinboard
  • Get Pinboard Bookmarks

Pocket

  • Add to Pocket
  • Get Items from Pocket

Add Bear actions

  • These actions aren't already listed in the 'All Actions to be implemented' issue here.
  • These actions haven't already been requested in another issue.
  • Fill out the information below, deleting the examples in italics.

What is the name of the app these actions are a part of?
Bear

Is this a free or paid app?
Free

Please list all of the actions this app exposes.

  • Search in Bear
  • Create Bear Note
  • ...etc

Provide a link to download a .shortcut file containing as many of these actions as possible.
iCloud

Improve contribution guide

The contribution guide assumes some knowledge of the node ecosystem, which can be a barrier to those who’ve not worked with node and npm before. It could be useful to add a bit of information to the guide on how to install/build/run the project locally.

Sent with GitHawk

Error in REDME

I found an error in "Shortcut folder creator" in README.md.

const {
  buildShortcut,
  withVariables,
} = require('@joshfarrant/shortcuts-js');
const {
  conditional,
  getBatteryLevel,
  setLowPowerMode,
  showResult,
} = require('@joshfarrant/shortcuts-js/actions');

I think this part should be below:

const { buildShortcut } = require("@joshfarrant/shortcuts-js");
const {
  chooseFromMenu,
  runShortcut,
} = require("@joshfarrant/shortcuts-js/actions");

What is there to do before v1?

There's been a lot going on with Shortcuts JS since launch, the vast majority of which has been thanks to work done by our Contributors, so a massive thank you to @pietropizzi, @Archez, @DanielRuf, @xAlien95, @gcordalis, @JB1905, @bachya, and @ikaikastine. 🎉

With so much going on, I thought it could be useful to try to consolidate all of the tasks that will need to be completed before we can consider the library at v1. We can branch off individual tasks into their own issues as need be, but at the moment it would be nice to get a big picture of everything that's left to do.

In my mind, I'd imagined that a v1 release would essentially expose all of the main functionality found in the official Shortcuts app. That includes:

  • Supporting all 312 built-in actions.
  • Full support for creating and using variables.
  • Ability to choose an icon colour and glyph for the generated Shortcut
  • Import questions

Progress with these items so far is as follows:

  • Actions - As of this morning we passed 1/6th (16.6%) of all actions implemented! 🎉 Slightly more if we include #37 (pending discussion in #39).
  • Variables - @xAlien95 has been doing some fantastic work on this in #10.
  • Shortcut Icon - This was added by @gcordalis in #16 and is working very well. It would be a bonus if we could get the names of the glyphs in before v1, as outlined in #45.
  • Import Questions - This hasn't been looked at at all, as far as I'm aware.

I'm probably missing some things here, so please let me know and I'll add it in.

As an aside, I'd also like to come up with a better documentation solution before hitting v1. The current docs are just ok and, while they're better than the previous solution (using jsdoc), they're still not fantastic. I get the feeling we're going to have to roll our own solution, as none of the out-of-the-box options are quite right. Hopefully we'll be able to base this custom solution on the JSON output from typedoc as that won't require any changes to the code, and typedoc is actually pretty good at what it does.

Thanks again to everyone for their contributions! 💙

How do I get started?

I unzipped the archive. Now what? How do I compile it? Readme just contains code examples without specifying what to do with the contents. Usually, you compile and install. How's it different in this case?

Fluent Builder Interface

I was thinking, it might be useful to apply a builder pattern to allow for a fluent interface that creates simple shortcuts?

let calcId = '';
const shortcut = shortcutBuilder()
  .comment({ text: 'Hello World' })
  .number({ number: 42 })
  .calculate({ operand: 3, operation: '/' }, id => (calcId = id))
  .showResult({ text: withVariables`Total is ${calcId}!` })
  .build();

It may not be useful for all cases but certainly some.

Unfortunately, manually maintaining a single class supporting every action being added over time wouldn't be favourable.

Thus, inspired some solutions discussed here I set about to throw together a little prototype to see if it is actually possible to simply generate one from all the actions and came up with this:

import * as Actions from '../actions';
import WFWorkflowAction from '../interfaces/WF/WFWorkflowAction';
import { buildShortcut } from './buildShortcut';

/**
 * These are just helper types
 */

// tslint:disable-next-line:no-any
type AnyFunc = (...args: any[]) => any;
type ObjectOfFuncs = Record<string, AnyFunc>;

// tslint:disable-next-line:no-any
type AsReturnType<T extends AnyFunc, R> = T extends (...args: infer P) => any
  ? (...args: P) => R
  : never;

type ActionCallback = (uuid: string) => void;
type ActionBuilder<OptionsType> = (
  options: OptionsType,
  callback?: ActionCallback,
) => WFWorkflowAction | WFWorkflowAction[];

type ActionsType = typeof Actions;

/**
 * This generates the appropriate IBuilder<T> type
 */
type IBuilder<T extends ObjectOfFuncs, R> = {
  [k in keyof T]: AsReturnType<T[k], IBuilder<T, R>>
} & { build(): R };

/**
 * This generates a proxy object that delegates down to
 * the original actions or returns a built shortcut as appropriate.
 */
type IShortcutBuilder = IBuilder<ActionsType, string>;
export const shortcutBuilder = (): IShortcutBuilder => {
  let actions: WFWorkflowAction[] = [];
  const builder = new Proxy(Actions, {
    // tslint:disable-next-line:no-any
    get(target: any, prop: PropertyKey): AnyFunc {
      if (prop === 'build') return () => buildShortcut(actions);

      return <OptionsType>(
        options: OptionsType,
        callback?: (uuid: string) => void,
      ): IShortcutBuilder => {
        const result = (target[prop] as ActionBuilder<OptionsType>)(
          options,
          callback,
        );

        if (Array.isArray(result)) {
          actions = actions.concat(result);
        } else {
          actions.push(result);
        }
        return builder;
      };
    },
  });
  return builder;
};

It's not the prettiest and there is probably room for improvement but it does prove the concept.
Apart from that, it does maintain the typings required for code completion but you do lose the code comments which isn't great.

Just a little toy example but I thought I would share it out of interest to someone, if nothing else.
It would be great to hear about other potential solutions to the problem.

ChooseFromMenu not defined

/usr/local/bin/node /Users/useraccount/Library/Preferences/WebStorm2018.3/scratches/scratch.js
/Users/useraccount/Library/Preferences/WebStorm2018.3/scratches/scratch.js:19
const actions = [
^

ReferenceError: chooseFromMenu is not defined
at Object. (/Users/useraccount/Library/Preferences/WebStorm2018.3/scratches/scratch.js:19:17)
at Module._compile (internal/modules/cjs/loader.js:721:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:732:10)
at Module.load (internal/modules/cjs/loader.js:620:32)
at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
at Function.Module._load (internal/modules/cjs/loader.js:552:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:774:12)
at executeUserCode (internal/bootstrap/node.js:499:15)
at startMainThreadExecution (internal/bootstrap/node.js:436:3)

Process finished with exit code 1

Calculate - Scientific Operation Doesn't Work

Upon testing the Scientific Operation in the Calculate action I've discovered that the correct shortcut format isn't being generated.

A standard Calculate action has 2 properties, WFMathOperand and WFMathOperation.
When using a Scientific Operation a 3rd property is used WFScientificMathOperation.

When using a Scientific Operation with Shortcuts-JS the WFMathOperation property is being removed when it should be being set to ...

This is a sample output from the Shortcuts app:

  <array>
    <dict>
      <key>WFWorkflowActionIdentifier</key>
      <string>is.workflow.actions.math</string>
      <key>WFWorkflowActionParameters</key>
      <dict>
        <key>WFMathOperand</key>
        <integer>0</integer>
        <key>WFMathOperation</key>
        <string>…</string>
        <key>WFScientificMathOperation</key>
        <string>tan(x)</string>
      </dict>
    </dict>
  </array>

Using this JS:

const actions = [
  calculate({
    operand: 0,
    operation: "tan(x)"
  })
];

in Shortcuts-JS produces a shortcut without the WFMathOperation property:

  <array>
    <dict>
      <key>WFWorkflowActionIdentifier</key>
      <string>is.workflow.actions.math</string>
      <key>WFWorkflowActionParameters</key>
      <dict>
        <key>WFMathOperand</key>
        <integer>0</integer>
        <key>WFMathOperation</key>
        <string>tan(x)</string>
      </dict>
    </dict>
  </array>

Getting Shortcuts to "tap" items on the screen

I need to create shortcuts that will interact with elements on the screen of an app. For example if there is a menu icon I'd want the shortcut to "tap" that and then to "tap" a specific item on the menu. Is there no way to identify a location on the screen to touch? This can be done with the Accessibility>Voice Control>Show Grid if you are giving voice commands, so why isn't there a way to script it into a shortcut?

Using variables in actions

Inspired by this, I'm currently working on a JavaScript to iOS shortcuts transpiler. I've gotten most of the parsing done and I'm now working on the transpiler portion of the project. My intention is to utilize this library since I really appreciate the effort you have put in it and what shape it's taking.

One question comes to mind however, how are variables handled? Most actions on iOS are able to work with either magic variables or actual variables as parameters (not input). How are these or how will these be available through this package?

Add getFile Action

  • These actions aren't already listed in the 'All Actions to be implemented' issue here.
  • These actions haven't already been requested in another issue.
  • Fill out the information below, deleting the examples in italics.

What is the name of the app these actions are a part of?
Shortcuts

Is this a free or paid app?
Free

Please list all of the actions this app exposes.

Provide a link to download a .shortcut file containing as many of these actions as possible.

I'm not sure if I need to do this, the contributing doc is a bit ambiguous. This issue template is setup for different apps, not this library. But the contributing doc still says to open an issue for an action. So here's the issue :) and the pr is #607.

Better Contribution flow

I tried adding an action. Here is what I had difficulties with, maybe it could be a point of possible improvement.

  • npm test is ran on every commit
    This causes the commits to take forever to happen. The tests should be ran ideally on the PR, not per commit.

  • interfaces/WF and interfaces/WF/WFWorkflowActionParameters.ts need some docs and coordination.
    I had trouble understanding if I need to reuse stuff in there, if I should add more, how to name them, where to put them. I think these two need some kind of rules to know when we need to add them and how to name them.

  • tslint autofix?
    I got some complaints for things that tslint could actually fix for me. Maybe a script in the package.json for autofixing would be useful. Also an editorconfig file for the spacing would be useful, as I have mine with tabs by default so I had to fix the spacing on the new file I made.

  • don't use default exports
    With export default:

// comment.ts
const comment = () => {}

export default comment

// index.ts
import comment from './comment'
export {
  comment,
}

With export:

// comment.ts
export const comment = () => {}

// index.ts
export { comment } from './comment'

Without default, we get fewer lines, less verbosity, and now the editor can autoimport by just typing the name of the function we want to use.

  • Inconsistent types with , and ;
    I think I saw some files using type A = { bla: boolean, foo: string } and some using interface B { bla: boolean; foo: string }. It would be nice to be consistent. I think tslint has a rule for this.

  • | in types
    I saw types like:

type A =
  'foo'
  | 'bla'
  | 'blu'

A better way to write this is:

type A =
  | 'foo'
  | 'bla'
  | 'blu'

It's easier to read, understand, and easier to run a sort func, like in vim.

I hope some of these make sense. These are just my suggestions, take for here what you like. I'm happy to discuss more about any of these. Thanks. :)

Health Actions

I just forked this repo and have started working on built-in actions for the Health app. I read it afterwards that I was supposed to create an issue for it first.

Can I go forward with it?

Related to #6

Hacktoberfest Opt-in

Hacktober-fest is opt-in for repos now, can we add the 'hacktoberfest' topic to the repo?

Add Change Case Action

  • These actions aren't already listed in the 'All Actions to be implemented' issue here.
  • These actions haven't already been requested in another issue.
  • Fill out the information below, deleting the examples in italics.

What is the name of the app these actions are a part of?
Shortcuts

Is this a free or paid app?
Free

Please list all of the actions this app exposes.

  • ...etc

Provide a link to download a .shortcut file containing as many of these actions as possible.

Create more interesting examples

There's currently a single example Shortcut in the README, however it would be nice to have a few more examples showcasing what Shortcuts-js can do, as well as showing some of the more interesting/useful actions.

One of the benefits of building our Shortcuts with JS is that it's possible to create Shortcuts that would be hugely time-consuming or tedious to create with the drag-and-drop interface the Shortcuts app provides. It would be nice to have an example of this where a series of actions are generated using a loop, or extracted into their own function which can then be easily reused.

Proposals on variables

I'm in the process of presenting a fork in which variables (named variables, magic variables and global variables (Ask, Clipboard, CurrentDate and ExtensionInput)) are objects instead of strings. In my local repository, I wrote:

const ActionOutput = (name?: string): Attachment => ({
  OutputUUID: uuidv4(),
  OutputName: name,
  Type: 'ActionOutput',
});

const Variable = (name: string): Attachment => ({
  VariableName: name,
  Type: 'Variable',
});

const Ask: Attachment = { Type: 'Ask' };
const Clipboard: Attachment = { Type: 'Clipboard' };
const CurrentDate: Attachment = { Type: 'CurrentDate' }; // TODO date/time formats
const ExtensionInput: Attachment = { Type: 'ExtensionInput' };

Using lowerCamelCase, an ask global variable would conflict with the ask() action function, so I ended up distinguishing them using CapitalCamelCase for variable objects. It could make sense since in my fork ActionOutput and Variable acts like JS types/classes:

const {
  buildShortcut,
  withVariables,
  ActionOutput,
  Clipboard,
} = require('@joshfarrant/shortcuts-js');
const {
  calculate,
  comment,
  number,
  showResult
} = require('@joshfarrant/shortcuts-js/actions');

// We'll use this later to reference the output of a calculation
const calcVar = ActionOutput('My result');

// Define our list of actions
const actions = [
  comment({
    text: 'Hello, world!',
  }),
  number({
    number: 42,
  }),
  calculate({
    operand: 3,
    operation: '/',
  }, calcVar),
  showResult({
    /**
     * We can use the result of the calculation in this Shortcuts's input
     * by passing the string to the 'withVariables' tag function
     */
    text: withVariables`Total is ${calcVar}! ${Clipboard}`,
  }),
];

Unfortunately the current lint script accepts variable names only in lowerCamelCase or UPPER_CASE.
How should I name the Ask global variable?

ImportQuestion

Great job!

Is there a chance to add the ImportQuestion option?

Thank you!

List of every action in shortcuts and their parameters

This json file contains information about every default action in shortcuts 2.1.2, it was extracted from the shortcuts app by xAlien95 on the r/shortcuts discord.

JSON file: https://pastebin.com/raw/7y7D0nvC

An example action:

"is.workflow.actions.gettext": {
	"ActionClass": "WFTextAction",
	"ActionKeywords": [
		"text",
		"such text",
		"very speech",
		"much words",
		"so wow",
		"string"
	],
	"Category": "Text",
	"Description": {
		"DescriptionSummary": "Passes the specified text to the next action."
	},
	"IconName": "Text.png",
	"Name": "Text",
	"Output": {
		"Multiple": false,
		"OutputName": "Text",
		"Types": [
			"NSString"
		]
	},
	"Parameters": [
		{
			"Class": "WFTextInputParameter",
			"DefaultValue": "",
			"Key": "WFTextActionText",
			"Multiline": true,
			"Placeholder": "Enter text..."
		}
	]
},

Improve generated documentation

The generated docs currently just about do the job, but they're far from perfect.

It would be nice to have the docs generated from the Typescript types, rather than having to markup the code with jsdoc comments, which often just duplicate the information given in the typings. I'd be interested to see how other Typescript libraries handle generated documentation.

Also, the current theme being used on Shortcuts.fun isn't great, it would be worth looking into alternatives.

Any input on either of these points would be appreciated.

github

  • These actions aren't already listed in the 'All Actions to be implemented' issue here.
  • These actions haven't already been requested in another issue.
  • Fill out the information below, deleting the examples in italics.

What is the name of the app these actions are a part of?
Bear

Is this a free or paid app?
Free

Please list all of the actions this app exposes.

  • Search in Bear
  • Create Bear Note
  • ...etc

Provide a link to download a .shortcut file containing as many of these actions as possible.
iCloud

Add icon color/glyph parameters

I'm not familiar with typescript and was hoping to create a PR that allows additional parameters to be passed with the buildShortcut function to allow custom icon color/glyph.

I've tested this with the package when it's been built and it works well.

My idea of the implementation is to pass an object shortcutIcon with color and glyph as keys within the object.

This parameter would be used in buildShortcutTemplate and each value applied as below:

exports.buildShortcutTemplate = (actions = [], shortcutIcon) => ({
    WFWorkflowClientVersion: '724',
    WFWorkflowClientRelease: '2.1',
    WFWorkflowIcon: {
        WFWorkflowIconStartColor: shortcutIcon.color,
        WFWorkflowIconGlyphNumber: shortcutIcon.glyph,
    },

Development Requirement

I'm not an Apple guy other than Ipad and phone. What are you guys using for development - computer models and software? I've messed around with node.js - can this stuff be done on a windows machine?
How would the shortcut get back to the Ipad- phone.
Thanks

Chrome warns about usage of navigator.userAgent, navigator.appVersion, and navigator.platform

Chrome 103 on Windows warns about Shortcuts.js's usage of navigator.userAgent, navigator.appVersion, and navigator.platform:

A page or script is accessing at least one of navigator.userAgent, navigator.appVersion, and navigator.platform. Starting in Chrome 101, the amount of information available in the User Agent string will be reduced.

To fix this issue, replace the usage of navigator.userAgent, navigator.appVersion, and navigator.platform with feature detection, progressive enhancement, or migrate to navigator.userAgentData.

Note that for performance reasons, only the first access to one of the properties is shown."

https://blog.chromium.org/2021/09/user-agent-reduction-origin-trial-and-dates.html

Discovered when using "create-react-app".

image

Decide how to handle 3rd party actions

We need to decide how best to store and expose actions from 3rd party apps.

#37 Adds support for Pythonista actions, and it would be good to start as we mean to go on with regards to these actions.

This has briefly been discussed before (here) but it would be good to get more feedback on the correct approach to take.

My main concern is that I don't want the import of these 3rd party actions to be too messy. Ideally we'd have something like:

import {
  editScript,
  runScript,
} from '@joshfarrant/shortcuts-js/actions/pythonista';

We could potentially have something like

import {
  pythonista,
} from '@joshfarrant/shortcuts-js/actions';

const {
  editScript,
  runScript,
} = pythonista;

Which is arguably a bit cleaner, but does introduce the possibility of collisions between app names and built-in action names, which probably rules this option out.

In terms of directory structure we could have:

├─ actions
│  └─ com.omz-software.Pythonista (Alternately this could just be 'Pythonista')
│     ├─ editScript.ts
│     ├─ index.ts
│     ├─ runScript.ts
│  ├─ addToVariable.ts
│  ├─ ask.ts
│  ├─ calculate.ts
│  ├─ ...etc

Does anyone else have any thoughts on this?

Find a way to track Actions to be implemented

Up to this point I've just picked actions almost at random and implemented them. It would be nice to have a more structured way of tracking actions which are yet to be implemented.

Is there a nicer way to do this than just having a huge checklist the README or an issue?

Decide on rules for naming Actions

CONTRIBUTING.md currently states

The file (and action) you're creating should be the name of the action as it appears in the Shortcuts app, camelCased.

This works fine for the majority of actions, however it's not perfect when naming actions with upper case words in the name, eg SSH and URL.

We might want to consider tweaking the rule to allow for action names to keep upper-case strings as upper-case. The table below shows some examples of this.

Action Name Proposed Current
Get Contents of URL getContentsOfURL getContentsOfUrl
Get Current IP Address getCurrentIPAddress getCurrentIPAddress
Run Script Over SSH runScriptOverSSH runScriptOverSSH
URL URL url

@xAlien95 has pointed out:

It's in line with standard JavaScript functions/properties such as innerHTML

Does anyone foresee any issues with one solution over the other? If not, I'll probably go with the proposed change.

Shortcut parser needs to support both binary bplist and xml plist

Format of shorcuts exported to iCloud seems to no longer be binary bplist.
It is now XML plist:

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>WFWorkflowActions</key>
	<array>
		<dict>
			<key>WFWorkflowActionIdentifier</key>
			<string>is.workflow.actions.comment</string>
			<key>WFWorkflowActionParameters</key>
			<dict>
				<key>WFCommentActionText</key>
				<string>Hello, world!</string>
			</dict>
		</dict>

scripts/parse.js needs to be updated to support both formats.

Jump/Go to Bottom of Page Request

  • These actions aren't already listed in the 'All Actions to be implemented' issue here.
  • These actions haven't already been requested in another issue.
  • Fill out the information below, deleting the examples in italics.

What is the name of the app these actions are a part of?
All Apps if possible, at least as a shortcut

Is this a free or paid app?
Free

Please list all of the actions this app exposes.

  • _want capability to jump to the bottom of the page either by a gesture (like apple’s built-in jump/go to top of page/screen tap) or like you’ve provided on this page: #6

Provide a link to download a .shortcut file containing as many of these actions as possible.
iCloud

setBrightness action doesn't work

The setBrightness action doesn't assign the correct value type for shortcuts to handle.

Shortcuts-JS assigns a value type of <integer> where the native Shortcuts App assigns <real>.

Here is an example of the generated shortcut file using Shortcuts-JS:

<array>
  <dict>
    <key>WFWorkflowActionIdentifier</key>
    <string>is.workflow.actions.setbrightness</string>
    <key>WFWorkflowActionParameters</key>
    <dict>
      <key>WFBrightness</key>
      <integer>88</integer>
    </dict>
  </dict>
</array>

And this from the native Shortcuts App:

<array>
  <dict>
    <key>WFWorkflowActionIdentifier</key>
    <string>is.workflow.actions.setbrightness</string>
    <key>WFWorkflowActionParameters</key>
    <dict>
      <key>WFBrightness</key>
      <real>0.8868458271026611</real>
    </dict>
  </dict>
</array>

Building a shortcut using the below code sets the brightness to 100 when loaded into the app.

const fs = require("fs");
const { buildShortcut } = require("@joshfarrant/shortcuts-js");
const { setBrightness } = require("@joshfarrant/shortcuts-js/actions");

const actions = [
  setBrightness({
    brightness: 25
  })
];

const shortcut = buildShortcut(actions);

fs.writeFile("Brightness.shortcut", shortcut, err => {
  if (err) {
    console.error("Something went wrong :(", err);
    return;
  }
  console.log("Shortcut created!");
});

Color and glyphs are not available

When attempting to set the color and glyph of a shortcut icon, a TypeError is thrown:

const fs = require('fs');
const { buildShortcut } = require('@joshfarrant/shortcuts-js');
const { COLORS, GLYPHS } = require('@joshfarrant/shortcuts-js/meta');

const actions = [];

const shortcut = buildShortcut(actions, 'My New Shortcut', {
  icon: {
    color: COLORS.GRAY,
    glyph: GLYPHS.ROCKET
  }
});

fs.writeFile('myNewShortcut.shortcut', shortcut, err => {
  if (err) {
    console.error(err);
    return;
  }

  console.log('Shortcut created successfully!');
});
$ node myNewShortcut.js 
/myNewShortcut.js:14
    color: COLORS.GRAY,
                  ^

TypeError: Cannot read property 'GRAY' of undefined
    at Object.<anonymous> (/myNewShortcut.js:14:19)
    at Module._compile (internal/modules/cjs/loader.js:816:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:827:10)
    at Module.load (internal/modules/cjs/loader.js:685:32)
    at Function.Module._load (internal/modules/cjs/loader.js:620:12)
    at Function.Module.runMain (internal/modules/cjs/loader.js:877:12)
    at internal/main/run_main_module.js:21:11

Assign names to the available Shortcut icon glyphs

#16 added support for specifying the icon glyph of a generated Shortcut, however there's currently no easy way to choose an icon without having to refer to other sources to find the code for your icon of choice.

It would be nice if the user could just do something like

import {
  GLYPHS,
} from '@joshfarrant/shortcuts-js/meta';

buildShortcut([], {
  icon: {
    glyph: GLYPHS.KEYBOARD,
  },
});

Here, the user accesses a glyph using a readable name, KEYBOARD, rather than using E836, as it is at the moment.

There's no standardised set of names for these glyphs, so naming them may be a bit of a challenge and might need to be broken down into a few different stages.

@xAlien95 has already done a huge amount of (probably very tedious!) work for this by coming up with Italian names for the glyphs (here). I don't want this work to go to waste, so for starters it can serve as a point of reference when coming up with the English names. Additionally, it would be nice if we could have language specific files for these glyph names, with the Italian versions in a meta/index-it.ts file, English in a meta/index-en.ts file, etc.

Help would be appreciated on this one, so feel free to jump right in! Even just adding the names for a couple of glyphs would be a big help.

Again, I stress that anyone wishing to get started with this to take a look at the previous discussion in #15 and #16, and specifically @xAlien95's work referenced in this comment.

Speak Text

  • These actions aren't already listed in the 'All Actions to be implemented' issue here.
  • These actions haven't already been requested in another issue.
  • Fill out the information below, deleting the examples in italics.

What is the name of the app these actions are a part of?
Shortcuts

Is this a free or paid app?
Free

Please list all of the actions this app exposes.

  • Speak Text

Provide a link to download a .shortcut file containing as many of these actions as possible.
iCloud

showInMaps Action does not include options for 3rd party providers

The Show in Maps actions provides the option to select Apple Maps, Google Maps or Waze if more than one service is installed on the device.

The current implementation only supports the default option, Apple Maps.

options need to be added to the action, /interfaces/WF/WFMapsApps should be created with Apple Maps, Google Maps and Waze as options.

Creating ShortCut URL in iCloud

Hi

I have an idea but I don't know if its possible.

You can export a ShortCut as an iCloud Link from the ShortCut App so others can use the ShortCut.

Your simply send them the link and they can tap to install. The problem is, its generic not personalised to the user.

We want to open a customised url.

Using a Mac as a server is it possible to create an iCloud Link for a Personalised ShortCut that we build in the browser using your library. We would be creating a new iCloud Link for each user and storing the ShortCut temporary in our iCloud Storage and then deleting shortly after.

If so, how

Thanks

Add a script which can import a .shortcut file and generate JS from it

It could be useful to essentially do the reverse of what Shortcuts-js currently does, and generate JavaScript from an imported .shortcut file.

This could be useful to help people get started with the library and start modifying their existing Shortcuts.

We'd have to find a way to add a placeholder (maybe a comment action?) if a specific action isn't yet implemented in Shortcuts-js.

Add Replace Text Action

  • These actions aren't already listed in the 'All Actions to be implemented' issue here.
  • These actions haven't already been requested in another issue.
  • Fill out the information below, deleting the examples in italics.

What is the name of the app these actions are a part of?
Shortcuts

Is this a free or paid app?
Free

Please list all of the actions this app exposes.

  • ...etc

#410

Looking for new maintainers 💖

As anyone who's opened an issue or PR to this repo in the last year (or probably more) has realised, I've really not been giving Shortcuts JS the attention it needs or deserves.

I put a huge amount of time into this project over the course of the first year and a bit. Building out the initial proof-of-concept was fantastic fun and I genuinely believe that reverse engineering the .shortcut file and getting proving the core idea of this project was one of the most interesting things I've done in my development career.

Despite that, it's been clear to me for a very long time that I don't have the capacity to be the sole maintainer of the project any more.

I really want this project to continue and to thrive. I feel like I've only really scratched the surface of what's possible with this concept and I'm certain that there are people out there who would want to and are capable of taking Shortcuts JS to the next level. I'm proud of the codebase that contributors and I built out (fully-typed, 100% test coverage, very modular and readable) and I'm confident that continuing to build on the library should be a breeze.

All of this is to say that I'm now actively looking for new maintainers of the project. I'll ping a few of the more active contributors from the past below, but really this is open to anyone (or any group of people) who would be happy to take the reins, bring the community together, and propel this project to the next level.

If you'd be interested in becoming a maintainer of this project then feel free to reply below or message me directly. Equally if you have any questions just pop them below too.

Thanks all 🙂

Josh


Ping @xAlien95 @bachya @gcordalis @JB1905

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.