Glob

Allow you to match a string against a glob like pattern. You can find it in the @banquette/utils-glob package.

Introduction

This package is not meant to support all the edge cases of the glob notation. In fact, it supports only the very basics, making it very lightweight.

The reason this package exists instead of using one of the thousands libraries out there, is mainly because of a need of partial matches. In @banquette/form for example, it is very useful to know if a mask partially match, to know to go down and test the children.

Anyway, if it can be of any use outside of Banquette, the doc is worth it.

How it works

You have two methods at your disposal:

/**
 * Match a mask against a path.
 */
match(mask: string, path: string, tags?: string[]): MatchResult;

/**
 * Match multiple patterns and keep the best result.
 */
matchBest(masks: string[], path: string, tags?: string[]): MatchResult;

The mask is the glob pattern, the path is the string being tested. Here is a usage example:

import { MatchResult } from "@banquette/utils-glob";

const result: MatchResult = match('/category/*', '/category/name');

if (result.pattern === MatchType.Full) {
    // The pattern fully matches.
}

Match result

MatchResult is an object containing the following:

interface MatchResult {
    /**
     * Hold how the pattern part of the mask match.
     *
     * - MatchType.Full: the pattern perfectly match
     * - MatchType.Partial: the beginning of the path match the pattern
     * - MatchType.None: the pattern doesn't match at all
     */
    pattern: MatchType;

    /**
     * Hold how the mask's tags match the subject.
     *
     * - MatchType.Full: all tags defined in the pattern have been found
     * - MatchType.Partial: some tags defined in the pattern have been found
     * - MatchType.None: none of the tags defined in the pattern have been found
     */
    tags: MatchType;
}

MatchType is th following:

enum MatchType {
    None,
    Partial,
    Full
}

Tags

The third parameter of both match and matchBest takes an array of String, called tags. Tags are suffixes that can optionally be added to a mask, this is used in @banquette/form to add the active states of the components being tested:

const path = '/category/name:focused:enabled';
const result = match(path, '/category/*', ['enabled']);

Here we're matching any path under /category/ that have at least a enabled tag.

This is totally optional.

Examples

Here are some usage examples so you can see what syntax is supported:

// Fixed pattern
match('/firstName', '/firstName'); // full
match('/firstName', '/'); // partial
match('/category/name', '/category/name'); // full
match('/category/name', '/category'); // partial
match('/non-existent', '/'); // partial

// Star
match('/tags/*/color', '/tags/0/color'); // full
match('/tags/*/*', '/'); // partial
match('/*Name', '/firstName'); // full
match('/*Name', '/lastName'); // full
match('/*Name', '/'); // partial

// Globstar
match('/**/name', '/category/name'); // full
match('/**/name', '/articles/0/category/name'); // full
match('/**/name', '/tags/0/name'); // full
match('/**/name', '/'); // partial
match('/**/name', '/firstName'); // partial
match('/tags/**', '/tags'); // full
match('/tags/**', '/tags/0/color'); // full
match('/tags/**', '/tags/0/name'); // full
match('/tags/**', '/tags/0'); // full
match('/tags/**', '/'); // partial

// choices
match('/{firstName,lastName}', '/firstName'); // full
match('/{firstName,lastName}', '/lastName'); // full
match('/{category,tags}/name', '/category/name'); // full
match('/{category,tags}/name', '/category'); // partial