Code Monkey home page Code Monkey logo

metrick's Introduction

๐Ÿ“ Metrick

npm metrick Build Status codecov

Babel-powered unit magick

Introduction

Metrick is a library which allows you to convert units and avoid using magic numbers! In combination with a JavaScript syntax extension included with Babel, it allows for a new, clean and human-like syntax for doing so.

For example;

import { seconds, minute, milliseconds } from 'metrick/duration';

// Explicit syntax
setTimeout(
  () => console.log('1 minute has passed!'),
  1::minute.in(milliseconds)
);

// Implicit syntax
setTimeout(
  () => console.log('30 seconds have passed!'),
  30::seconds
);

Here, two syntaxes are demonstrated; explicit and implicit!

Explicit syntax

import { gibibyte, megabytes } from 'metrick/data';
import { years, days } from 'metrick/duration';

console.log(1::gibibyte.in(megabytes)); // => 1073.741824
console.log(25::years.in(days));        // => 9132.5

The explicit syntax makes use of an in function to convert the original unit into another supplied unit. Passing a valid Unit object of the same type to in will return the result as a number.

Implicit syntax

import { megabits } from 'metrick/data';
import { hours } from 'metrick/duration';

console.log(50::megabits); // => 50000000
console.log(24::hours);    // => 86400000

Implicit syntax will convert the number to the default unit of the type of unit you're using. For instance, Data units implicitly convert to bits, and Duration units implicitly convert to milliseconds.

In general, the implicit unit is the applicable SI base unit, however, in the case of Duration the implicit unit is milliseconds, for compatibility with standard JavaScript methods which deal with time.

Shoutout to Glen Maddern for the idea behind implicit syntax

Usage

Note: This presumes you already use Babel to transpile your project's JavaScript. If you don't, instructions are available on Babel's website

Configure Babel to transform function bind syntax by installing babel-plugin-transform-function-bind with your favourite Node package management tool, and then adding the plugin to your .babelrc;

{
  "plugins": [
    "transform-function-bind"
  ]
}

Custom unit types

A base Unit constructor exists, which you can extend to create your own classes of unit. All you need to do is extend it!

For instance, here's an implementation of an Illuminance unit type (a unit unlikely to be included with Metrick ๐Ÿ˜œ);

import Unit from 'metrick/unit';

export default class Illuminance extends Unit {
  // No overrides are necessary; we're using classes to check for conversion compatibility!
}

// SI base unit, implicit unit
export default const lux = new Illuminance();

export default const footcandle = new Illuminance(10.763910417::lux);
// pluralise for better readability
export default const footcandles = footcandle;

export default const lumenPerSquareInch = new Illuminance(1550.0031::lux);

export default const phot = new Illuminance(10000::lux);

Custom units

Each type of unit exposes a constructor to create a compatible unit type. The constructors accept two forms of defining the relationship between units;

  • One Number argument, indicating the multiplier between the unit and the base unit
  • Two Functions, each accepting one numeric argument and transform to and from the base unit

For instance, here's an implementation of .beats as a Duration unit, using the multiplier argument;

import Duration, { days, seconds, minutes } from 'metrick/duration';

// each .beat is 1/1000th of a day, Durations are measured in seconds
const dotBeat = new Duration((1 / 1000)::days.in(seconds));

// pluralise for better readability
const dotBeats = dotBeat;

console.log(1::dotBeat.in(minutes));   // => 1.4400000000000002
console.log(12::dotBeats.in(minutes)); // => 17.280000000000005

As an example of providing Functions, here's an implementation of a Gas Mark temperature conversion;

import Temperature, { celsius } from 'metrick/temperature';

const gasMark = new Temperature(
  (temperature) => (
    temperature * 14 + 394.15
  ),

  (temperature) => (
    (temperature - 394.15) / 14
  )
);

console.log(1::gasMark.in(celsius)); // => 135
console.log(5::gasMark.in(celsius)); // => 191

Included units

Currently, Metrick includes units for Data and Duration.

Note: All built-in units are exported with their singular and plural names - here we only list plural for brevity.

Data

  • bits (SI base unit, implicit unit)
  • bytes
  • exabits
  • exabytes
  • exbibits
  • exbibytes
  • gibibits
  • gibibytes
  • gigabits
  • gigabytes
  • kibibits
  • kibibytes
  • kilobits
  • kilobytes
  • mebibits
  • mebibytes
  • megabits
  • megabytes
  • nibbles
  • pebibits
  • pebibytes
  • petabits
  • petabytes
  • tebibits
  • tebibytes
  • terabits
  • terabytes

Duration

  • days
  • hours
  • milliseconds (implicit unit)
  • minutes
  • months
  • seconds (SI base unit)
  • weeks
  • years

Length

Metric
  • centimetres
  • kilometres
  • metres (SI base unit, implicit unit)
  • millimetres
Imperial
  • chains
  • feet (singular is foot)
  • inches (singular is inch)
  • miles
  • paces
  • yards
Weird
  • spats
  • twips
  • astronomicalUnits

Temperature

Note: Built-in temperature units are exported both with and without degrees prefix - here we only list without for brevity.

  • celsius
  • fahrenheit
  • kelvin (SI base unit, implicit unit)

Full-library export

The library also includes a main entry point at index.js, which exposes all the available parts of the library. This is not recommended as if, for example, you Webpack the whole library, you'll include conversions you may not be using!

import { Duration as DurationConstructor, duration } from 'metrick';
import Duration, { minute } from 'metrick/duration';

console.log(DurationConstructor === Duration) // => true
console.log(duration.minute === minute);      // => true

Wait, how does this work?

This is making use of the function bind syntax extension. This extension adds a :: operator to JavaScript, which binds functions following to objects immediately before.

Caveats

This syntax extension is experimental - it's not even in any specification, merely a proposal which happens to have a transform available in Babel.

Likewise, this is technically a bit of an abuse of this; implicit syntax takes advantage of the fact that the bind operator implicitly makes a call to the bind method of what is supposed to be a supplied function, and instead returns the implicit unit conversion in these cases.

Also, technically, the function bind proposal suggests that the syntax check that the function passed is callable, but Babel's transform does not test this. Metrick instead uses an object which happens to have a bind method, so this particular approach may break in more strict, future versions of the transformation - but hopefully not!

metrick's People

Contributors

dependabot[bot] avatar renovate-bot avatar ticky 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

Watchers

 avatar  avatar  avatar

metrick's Issues

Dependency deprecation warning: babel-preset-es2015 (npm)

On registry https://registry.npmjs.org/, the "latest" version (v6.24.1) of dependency babel-preset-es2015 has the following deprecation notice:

๐Ÿ™Œ Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!

Marking the latest version of an npm package as deprecated results in the entire package being considered deprecated, so contact the package author you think this is a mistake.

Affected package file(s): package.json

If you don't care about this, you can close this issue and not be warned about babel-preset-es2015's deprecation again. If you would like to completely disable all future deprecation warnings then add the following to your config:

"suppressNotifications": ["deprecationWarningIssues"]

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

npm
package.json
  • @babel/cli 7.8.4
  • @babel/core 7.9.0
  • @babel/plugin-proposal-function-bind 7.8.3
  • @babel/plugin-proposal-object-rest-spread 7.9.5
  • @babel/preset-env 7.9.5
  • babel-core 7.0.0-bridge.0
  • babel-eslint 10.1.0
  • babel-jest 25.1.0
  • eslint 6.8.0
  • flow-bin 0.127.0
  • jest 25.1.0
travis
.travis.yml

  • Check this box to trigger a request for Renovate to run again on this repository

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.