regexparam

repository·main·Indexed 20 days ago

https://github.com/lukeed/regexparam

A tiny utility (399B) for converting route patterns, such as '/users/:id', into Regular Expressions. It provides a lightweight alternative to path-to-regexp with capabilities for parsing route patterns via parse() and injecting values into patterns via inject(). It supports static paths, named parameters, optional parameters, and wildcards, and is compatible with npm and Deno.

Tokens
2.7K
Snippets
8
Records
9
Agent score
70%

What's inside regexparam

  1. Use existing RegExps with parse()

    main

    If you pass a RegExp directly to parse(), the module does not parse or manipulate it. It treats the input as an authoritative pattern.

    Important implications:

    • regexparam has no insight into the route structure.
    • The returned keys property will always be false.
    • The returned pattern will be identical to your input.
    • You are responsible for managing and parsing your own keys (e.g., using named capture groups or manual array destructuring).
    import { parse } from 'regexparam';
    
    // Using Named Capture Groups (requires environment support for ES2018+)
    const named = parse(/^\/posts[/](?<year>[0-9]{4})[/](?<month>[0-9]{2})[/](?<title>[^\/]+)/i);
    const { groups } = named.pattern.exec('/posts/2019/05/hello-world');
    //=> { year: '2019', month: '05', title: 'hello-world' }
    
    // Using standard capture groups
    const manual = parse(/^\/posts[/]([0-9]{4})[/]([0-9]{2})[/]([^\/]+)/i);
    const [url, year, month, title] = manual.pattern.exec('/posts/2019/05/hello-world');
    // year: 2019, month: 05, title: hello-world
  2. Use regexparam in Deno

    main

    You can use regexparam in Deno by importing from the official Deno registry or third-party CDNs with ESM support.

    // Official Deno registry:
    import regexparam from 'https://deno.land/x/regexparam/src/index.js';
    
    // Third-party CDNs:
    import regexparam from 'https://cdn.skypack.dev/regexparam';
    import regexparam from 'https://esm.sh/regexparam';
  3. Convert route patterns to RegExp with parse()

    main

    Use parse(input, loose?) to turn a pathing string into a RegExp and extract parameter names.

    Supported Operators:

    • Static: /foo, /foo/bar
    • Parameter: /:title, /books/:title
    • Parameter w/ Suffix: /movies/:title.mp4, /movies/:title.(mp4|mov)
    • Optional Parameters: /:title?, /books/:title?
    • Wildcards: *, /books/*
    • Optional Wildcard: /books/*?

    Returns: An object { keys, pattern }:

    • pattern: A RegExp instance. Note that when testing against this RegExp, your path must begin with a leading slash ("/").
    • keys: An array of parameter names in order of appearance. If the input was a RegExp instead of a string, keys will be false.

    The loose option: If true, the generated RegExp will allow URLs that are longer than the pattern itself. By default (false), the RegExp ensures the URL begins and ends with the pattern.

    import { parse } from 'regexparam';
    
    // Parameter and Optional Parameter
    let foo = parse('/books/:genre/:title?')
    // foo.pattern => /^\/books\/([^\/]+?)(?:\/([^\/]+?))?\/?$/i
    // foo.keys => ['genre', 'title']
    
    foo.pattern.test('/books/horror'); //=> true
    
    // Parameter with suffix
    let bar = parse('/movies/:title.(mp4|mov)');
    // bar.pattern => /^\/movies\/([^\/]+?)\.(mp4|mov)\/?$/i
    // bar.keys => ['title']
    
    bar.pattern.test('/movies/narnia.mp4'); //=> true
    
    // Wildcard
    let baz = parse('users/*');
    // baz.pattern => /^\/users\/(.*)\/?$/i
    // baz.keys => ['*']
  4. Inject values into route patterns with inject()

    main

    Use inject(pattern, values) to replace pattern segments/parameters with specific values.

    Behavior:

    • Named segments (e.g., /:name) that do not have a corresponding key in values are kept in the output string.
    • Exception: Optional segments (e.g., /:name?) and wildcard segments (e.g., /*) are removed if they do not have a match in values.
    • To replace a wildcard segment, use the key '*' in the values object.

    Returns: A new string with the injected values.

    import { inject } from 'regexparam';
    
    // Basic injection
    inject('/users/:id', { id: 'lukeed' }); //=> '/users/lukeed'
    
    // Injection with suffix
    inject('/movies/:title.mp4', { title: 'narnia' }); //=> '/movies/narnia.mp4'
    
    // Wildcard injection
    inject('/posts/:slug/*', { slug: 'hello', '*': 'x/y/z' }); //=> '/posts/hello/x/y/z'
    
    // Missing non-optional value (kept in output)
    inject('/hello/:world', { abc: 123 }); //=> '/hello/:world'
  5. Parse a route string or RegExp with parse()

    main

    The parse function converts a route string containing named parameters (e.g., :id) or wildcards (e.g., *) into a regular expression and a list of parameter keys.

    • If passing a string: It returns an object containing keys (an array of parameter names) and pattern (the generated RegExp). Use the loose option if you want to allow more flexible matching.
    • If passing a RegExp: It returns an object containing keys: false and the original pattern.
    // Parsing a string route
    const { keys, pattern } = parse('/user/:id');
    // keys: ['id'], pattern: /\/user\/([^\/]+)\/?/ 
    
    // Parsing a RegExp
    const { keys, pattern } = parse(/\/user\/([^\/]+)\/?/);
    // keys: false, pattern: /\/user\/([^\/]+)\/?/
  6. Inject values into a route with inject()

    main

    The inject function takes a route pattern string and an object of values, then replaces the parameter placeholders with the corresponding values from the object.

    • Named parameters (e.g., :id) are replaced by values.id.
    • Wildcard parameters (e.g., *) are replaced by values['*'].
    • If a parameter is marked as optional (e.g., :id? or *?) and the value is missing in the values object, the segment is omitted from the resulting string.
    • If a non-optional parameter is missing from the values object, it is replaced by its literal name (e.g., :id becomes /id).
    import { inject } from 'regexparam';
    
    // Injecting named parameters
    const route = inject('/user/:id', { id: '123' });
    // Returns: '/user/123'
    
    // Injecting wildcard parameters
    const wildcardRoute = inject('/files/*', { '*': 'images' });
    // Returns: '/files/images'
    
    // Handling optional parameters
    const optionalRoute = inject('/post/:id?', { });
    // Returns: '/post'
    
    // Handling missing non-optional parameters
    const missingRoute = inject('/user/:id', { });
    // Returns: '/user/id'
  7. Parse a route pattern with parse()

    main

    The parse function converts a route pattern string or a RegExp into a structured object containing the extracted keys and a compiled RegExp for matching.

    • If the input is a RegExp, it returns { keys: false, pattern: input }.
    • If the input is a string, it parses segments starting with : (named parameters) or * (wildcard parameters).
    • The loose option (boolean) allows for open-ended matching. When loose is true, the resulting regex uses a lookahead (?=$|\/) instead of requiring the end of the string or a trailing slash. This option is ignored if the input is a RegExp.

    Supported syntax:

    • :name: A named parameter (e.g., :id).
    • :name?: An optional named parameter.
    • :name.ext: A named parameter with a specific file extension suffix.
    • *: A wildcard parameter.
    • *?: An optional wildcard parameter.
    import { parse } from 'regexparam';
    
    // Parsing a string pattern
    const result = parse('/user/:id');
    // Returns: { keys: ['id'], pattern: /^\/user\/([^/]+?)\/?$/i }
    
    // Parsing with loose matching
    const looseResult = parse('/user/:id', true);
    // Returns: { keys: ['id'], pattern: /^\/user\/([^/]+?)(?=$|\/)/i }
    
    // Parsing a RegExp
    const regexpResult = parse(/^\/static\/(.*)$/);
    // Returns: { keys: false, pattern: /^\/static\/(.*)$/ }
  8. Understand the RouteParams<T> type

    main

    The RouteParams<T> type is a recursive conditional type that automatically infers the shape of the parameters object required for a given route string T.

    It supports the following syntax patterns:

    • /* or *?: Represents a wildcard. Maps to { wild: string } or { wild?: string }.
    • :param: A required parameter. Maps to { [param]: string }.
    • :param?: An optional parameter. Maps to { [param]?: string }.
    • *: A catch-all wildcard. Maps to { '*': string } or { '*': string }.