0.4.0 • Published 3 years ago

@josephuspaye/match-common-formats v0.4.0

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

match-common-formats

Match a piece of text to common formats like URLs, email addresses, colors, and more.

Due to the large number of formats to match, this project is completed in parts:

  • Part 1: URIs (URIs + URNs + URLs) and IP Addresses (IPv4 + IPv6): Published in v0.1.0.
  • Part 2: Colors - RGB hexadecimal (8, 6, 4, and 3-character codes); rgb(), rgba(), hsl(), and hsla() (with comma and space separators): Published in v0.2.0.
  • Part 3: Email addresses and social tokens (@mentions and #hashtags): Published in v0.3.0.
  • Part 4: Currency (e.g. 2,000AUD or LRD2,000,000.75): Published in v0.4.0.

This project is part of #CreateWeekly, my attempt to create something new publicly every week in 2020.

Demo

Installation

npm install -g @josephuspaye/match-common-formats

Usage

Match with all matchers

The following example shows how to match a piece of text with all matchers:

import { match } from '@josephuspaye/match-common-formats';

const first = match('example.com'); // matches a URL
const second = match('192.168.0.1'); // matches an IP address
const third = match('hello@example.com'); // matches an email address and a URL

console.log({ first, second, third });
{
  "first": [
    {
      "type": "url",
      "label": "Web URL",
      "input": "example.com",
      "url": "http://example.com",
      "scheme": "http"
    }
  ],
  "second": [
    {
      "type": "ip-address",
      "label": "IPv4 Address",
      "input": "192.168.0.1",
      "version": "ipv4",
      "address": "192.168.0.1"
    }
  ],
  "third": [
    {
      "type": "email-address",
      "label": "Email Address",
      "input": "hello@example.com",
      "address": "hello@example.com"
    },
    {
      "type": "url",
      "label": "Web URL",
      "input": "hello@example.com",
      "url": "http://hello@example.com",
      "scheme": "http"
    }
  ]
}

Stop matching after first match

The following example shows how to match a piece of text with all matchers, stopping after the first match:

import { match } from '@josephuspaye/match-common-formats';

// Would normally match a hex color code and a hashtag, but specifying `matchOne`
// stops after the first match, returning only the color match
const matches = match('#bad', { matchOne: true });

console.log({ matches });
{
  "matches": [
    {
      "input": "#bad",
      "expected": [
        {
          "type": "color",
          "label": "Hexadecimal Color Code",
          "input": "#bad",
          "format": "hex",
          "color": "#bad"
        }
      ]
    }
  ]
}

Match with select matchers

The following example shows how to match a piece of text with select matchers:

import {
  match,
  matchUri,
  matchIpAddress,
} from '@josephuspaye/match-common-formats';

const first = match('example.com', { matchers: [matchUri] });
const second = match('example.com', { matchers: [matchIpAddress] }); // matches will be empty

console.log({ first, second });
{
  "first": [
    {
      "type": "url",
      "label": "Web URL",
      "input": "example.com",
      "url": "http://example.com",
      "scheme": "http"
    }
  ],
  "second": []
}

Match with a specific matcher

The following example shows how to match a piece of text with a specific matcher:

import { match, matchIpAddress } from '@josephuspaye/match-common-formats';

const first = matchIpAddress('10.0.0.1');
const second = matchIpAddress('example.com'); // no match

console.log({ first, second });
{
  "first": {
    "type": "ip-address",
    "label": "IPv4 Address",
    "input": "10.0.0.1",
    "version": "ipv4",
    "address": "10.0.0.1"
  },
  "second": null
}

Available formats

FormatTypeInput example
URIuri (data)data:image/png;base64,...
URNurn (isbn)urn:isbn:0451450523
URLurl (http)get.pizza
URLurl (https)https://example.com
URLurl (http)localhost:3000
IP Addressip-address (ipv4)127.0.0.1
IP Addressip-address (ipv6)::1
RGB Color (Hex)color (hex)#bad, #bada55, #abcd, #aabbccdd
RGB Colorcolor (rgb)rgb(22, 22, 22)
RGB Alpha Colorcolor (rgba)rgba(22, 22, 22, 0.5)
HSL Colorcolor (hsl)hsl(22deg, 50%, 20%)
HSL Alpha Colorcolor (hsla)hsla(22deg, 50%, 20%, 80%)
Email address*email-addressjohn.doe+newsletters@example.com
Social token (mention)mention@JosephusPaye
Social token (hashtag)hashtag#CreateWeekly
Currencycurrency2,000,000LRD
CurrencycurrencyAUD2000.00

Notes

  • The email address matcher is not technically "complete", as it doesn't match addresses with unknown TLDs, IP addresses, or special characters in the local part that are not +, -, _, or .. It is designed to match only a subset of technically valid email address, ones that are more "common".

API

interface MatchCommon {
  type: string;
  label: string;
  input: string;
}

interface Url extends MatchCommon {
  type: 'url';
  url: string;
  scheme: string;
}

interface Uri extends MatchCommon {
  type: 'uri';
  uri: string;
  scheme: string;
}

interface Urn extends MatchCommon {
  type: 'urn';
  urn: string;
  namespaceId: string;
  namespaceString: string;
}

interface IpAddress extends MatchCommon {
  type: 'ip-address';
  version: 'ipv4' | 'ipv6';
  address: string;
}

interface Color extends MatchCommon {
  type: 'color';
  format: 'hex' | 'rgb' | 'rgba' | 'hsl' | 'hsla';
  color: string;
}

interface EmailAddress extends MatchCommon {
  type: 'email-address';
  address: string;
}

interface SocialToken extends MatchCommon {
  type: 'mention' | 'hashtag';

  /**
   * The mention or hashtag, with the @ or # prefix
   */
  token: string;
}

interface KnownCurrency {
  code: string;
  name: string;
  symbol: string;
  otherSymbols?: string[];
}

interface Currency extends MatchCommon {
  type: 'currency';
  currency: KnownCurrency;
  amount: number;
}

type Match =
  | Uri
  | Url
  | Urn
  | IpAddress
  | Color
  | EmailAddress
  | SocialToken
  | Currency;

type Matcher = (string: string) => Match | null;

interface MatchOptions {
  /**
   * A list of matchers to apply, defaults to all matchers
   */
  matchers?: Matcher[];

  /**
   * Stop matching after the first match
   * @default false
   */
  matchOne?: boolean;
}

/**
 * The default matchers
 */
const defaultMatchers: Matcher[];

/**
 * Match the given string to a URN, URL, or URI
 */
function matchUri(string: string): Url | Uri | Urn | null;

/**
 * Match the given string to an IPv4 or IPv6 address
 */
function matchIpAddress(string: string): IpAddress | null;

/**
 * Match the given string to a hex (RGB), rgb(), rgba(), hsl(), or hsla() color code
 */
function matchColor(string: string): Color | null;

/**
 * Match the given string to an email address
 */
function matchEmailAddress(string: string): EmailAddress | null;

/**
 * Match the given string to a social token (@mention or #hashtag)
 */
function matchSocialToken(string: string): SocialToken | null;

/**
 * Match the given string to a currency value
 */
function matchCurrency(
  string: string,
  options?: {
    matchSymbol?: boolean;
    decimalSymbol?: ',' | '.';
    thousandSeparator?: ',' | '.' | ' ';
  }
): Currency | null;

/**
 * Compare the given string to known formats, optionally only those
 * matched by the given matchers, and get the matches
 */
function match(string: string, options?: MatchOptions): Match[];

Licence

MIT

0.4.0

3 years ago

0.3.1

3 years ago

0.3.0

3 years ago

0.2.0

3 years ago

0.1.2

3 years ago

0.1.1

3 years ago

0.1.0

3 years ago