Rootless

Automate iOS, iPadOS, and macOS using plain JavaScript. Build custom widgets and interact directly with native APIs.

Download on the App Store
Rootless app interface

Plain JavaScript

Supports ES6. Scripts are stored as plain .js files on your disk.

Native APIs & Documentation

Integrate directly with iOS native APIs. Fully documented, available offline.

Siri Shortcuts

Trigger scripts via Siri. Present tables, websites, and custom HTML natively.

System Integration

Run from the Share Sheet, process inputs, and manage local files via Files.app.

x-callback-url

Communicate seamlessly and trigger workflows with other apps on your device.

Customizable & Ready

Tailor the code editor to your liking. Includes several example scripts to start immediately.

Documentation

Also inside the app, or as rootless.json.

Format

Numbers, units and lists in the reader's region

Formats numbers, currencies, percentages, byte counts, lists and measurements using the device's locale: grouping separators, decimal marks, unit systems and list conjunctions. A hand-rolled k/m/b shortener or a hardcoded "km" is wrong outside the region it was written in.

Properties

usesMetricBoolean

True where this device's region uses the metric system.

localeString

The device's locale identifier, e.g. "en_US".

Methods

Format.number(value, options?)String

Decimal number.

  • value Number required

    The number to format.

  • options Any
    • digits Number

      Maximum decimal places. Default 0.

    • minDigits Number

      Minimum decimal places, padded with zeros. Default 0.

    • grouping Boolean

      Thousands separator. Default true.

Format.compact(value, options?)String

Shortened number, 12500 becomes "13K", localised.

  • value Number required

    The number to shorten.

  • options Any
    • digits Number

      Maximum decimal places. Default 1.

Format.percent(value, options?)String

Percentage from a fraction: 0.42 becomes "42%".

  • value Number required

    A fraction, not 0 to 100. 0.42 gives "42%".

  • options Any
    • digits Number

      Maximum decimal places. Default 0.

Format.currency(value, options?)String

Money. Defaults to the region's currency.

  • value Number required

    The amount.

  • options Any
    • code String

      ISO 4217 code such as "EUR". Defaults to the device's currency.

    • digits Number

      Fixed decimal places. Defaults to what the currency uses.

Format.bytes(value, options?)String

Byte count, 1048576 becomes "1 MB". ("file" or "memory").

  • value Number required

    A count of bytes.

  • options Any
    • style String

      "memory" counts in powers of 1024. Anything else counts in powers of 1000, which is what a file size uses.

Format.ordinal(value)String

Ordinal: 3 becomes "3rd".

  • value Number required
Format.list(items)String

Joins with the region's conjunction: "a, b, and c".

  • items [String] required

    The strings to join.

returns The list joined the way the device's language does it, conjunction included.

Format.measurement(value, options)String

A value with a unit, converted to whatever the region uses. unit is required. One of millimeters, centimeters, meters, kilometers, inches, feet, yards, miles, celsius, fahrenheit, kelvin, metersPerSecond, kilometersPerHour, milesPerHour, knots, grams, kilograms, ounces, pounds, kilocalories, kilojoules. Set to to pin the output unit instead of letting the locale choose.

  • value Number required

    The amount, in the unit named below.

  • options Any required
    • unit String required

      The unit value is in.

    • to String

      Convert to this unit. Left out, the device's region decides.

    • style String

      "short", "medium" or "long", for "km", "km" or "kilometers".

    • digits Number

      Maximum decimal places.

Examples

A stats row

Column({ children: [
  Text(Format.compact(12500)),                       // "13K"
  Text(Format.percent(0.42)),                        // "42%"
  Text(Format.measurement(4213, { unit: "meters" })), // "4.2 km" or "2.6 mi"
  Text(Format.list(["Mon", "Wed", "Fri"])),          // "Mon, Wed, and Fri"
]})