@jackens/nnn
Version:
Jackens’ JavaScript helpers.
446 lines (445 loc) • 14.7 kB
TypeScript
/**
* Represents a CSS rule node for the {@link c} helper. Keys are CSS properties or nested selectors.
*/
export type CNode = {
[attributeOrSelector: string]: string | number | CNode | undefined;
};
/**
* Represents the root CSS object for the {@link c} helper. Keys are top-level selectors or at-rules.
*/
export type CRoot = Record<PropertyKey, CNode>;
/**
* A minimal CSS-in-JS helper that converts a JavaScript object hierarchy into a CSS string.
*
* @param root
*
* An object describing CSS rules.
* Keys are selectors or at-rules; values are either CSS property values or nested rule objects.
*
* @param splitter
*
* A delimiter used to create unique keys (default: `'$$'`).
* The substring from `splitter` to the end of a key is ignored (e.g., `src$$1` → `src`).
*
* @returns
*
* A CSS string representing the compiled rules.
*
* @remarks
*
* - Keys whose values are primitives (`string` | `number`) are treated as CSS properties.
* - In property keys, uppercase letters become lowercase with a `-` prefix (e.g., `fontFamily` → `font-family`);
* underscores become hyphens (e.g., `font_family` → `font-family`).
* - Comma-separated selector keys expand into multiple selectors
* (e.g., `{ div: { '.a,.b': { margin: 1 } } }` → `div.a,div.b{margin:1}`).
* - Top-level keys starting with `@` (at-rules) are not concatenated with child selectors.
*/
export declare const c: (root: CRoot, splitter?: string) => string;
/**
* Parses a CSV string into a two-dimensional array of strings.
*
* Supports quoted fields with escaped double quotes (`""`). Carriage returns are normalized.
*
* @param csv
*
* The CSV string to parse.
*
* @param separator
*
* The field delimiter (default: `','`).
*
* @returns
*
* A 2D array where each inner array represents a row of fields.
*/
export declare const csvParse: (csv: string, separator?: string) => string[][];
/**
* Applies Polish-specific typographic corrections to a DOM subtree.
*
* This function prevents orphaned conjunctions (single-letter words like “a”, “i”, “o”, “u”, “w”, “z”)
* from appearing at the end of a line by wrapping them with the following word in a non-breaking span.
* It also inserts zero-width spaces after slashes and dots to allow line breaks.
*
* @param node
*
* The root DOM node to process. All descendant text nodes are corrected recursively,
* except those inside `IFRAME`, `NOSCRIPT`, `PRE`, `SCRIPT`, `STYLE`, or `TEXTAREA` elements.
*/
export declare const fixPlTypography: (node: Node) => void;
/**
* Single argument type for the {@link h} and {@link s} helpers.
*/
export type HArgs1 = Record<PropertyKey, unknown> | null | undefined | Node | string | number | HArgs;
/**
* Tuple argument type for the {@link h} and {@link s} helpers.
*/
export type HArgs = [string | Node, ...HArgs1[]];
/**
* A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also {@link s}).
*
* @param tagOrNode
*
* If a `string`, it is treated as the tag name for a new element.
* If a `Node`, that node is modified in place.
*
* @param args
*
* Additional arguments processed as follows:
* - `Object`: maps attributes/properties. Keys starting with `$` set element properties (without the `$` prefix);
* other keys set attributes via `setAttribute`. A value of `false` removes the attribute.
* - `null`/`undefined`: ignored.
* - `Node`: appended as a child.
* - `string`/`number`: converted to a `Text` node and appended.
* - {@link HArgs} array: processed recursively.
*
* @returns
*
* The created or modified `HTMLElement`.
*/
export declare const h: {
<T extends keyof HTMLElementTagNameMap>(tag: T, ...args1: HArgs1[]): HTMLElementTagNameMap[T];
<N extends Node>(node: N, ...args1: HArgs1[]): N;
(tagOrNode: string | Node, ...args1: HArgs1[]): Node;
};
/**
* A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also {@link h}).
*
* @param tagOrNode
*
* If a `string`, it is treated as the tag name for a new element.
* If a `Node`, that node is modified in place.
*
* @param args
*
* Additional arguments processed as follows:
* - `Object`: maps attributes/properties. Keys starting with `$` set element properties (without the `$` prefix);
* other keys set attributes via `setAttributeNS`. A value of `false` removes the attribute.
* - `null`/`undefined`: ignored.
* - `Node`: appended as a child.
* - `string`/`number`: converted to a `Text` node and appended.
* - {@link HArgs} array: processed recursively.
*
* @returns
*
* The created or modified `SVGElement`.
*/
export declare const s: {
<T extends keyof SVGElementTagNameMap>(tag: T, ...args1: HArgs1[]): SVGElementTagNameMap[T];
<N extends Node>(node: N, ...args1: HArgs1[]): N;
(tagOrNode: string | Node, ...args1: HArgs1[]): Node;
};
/**
* Checks whether an object has the specified key as its own property.
*
* A null-safe wrapper around `Object.hasOwn`.
*
* @param ref
*
* The object to check.
*
* @param key
*
* The property key to look for.
*
* @returns
*
* `true` if `ref` is not nullish and has `key` as an own property, `false` otherwise.
*/
export declare const hasOwn: (ref: unknown, key: unknown) => boolean;
/**
* Checks whether the argument is an array.
*
* @param arg
*
* The value to check.
*
* @returns
*
* `true` if `arg` is an array, `false` otherwise.
*/
export declare const isArray: (arg: unknown) => arg is unknown[];
/**
* Checks whether the argument is a finite number (excludes `±Infinity` and `NaN`).
*
* @param arg
*
* The value to check.
*
* @returns
*
* `true` if `arg` is a finite number, `false` otherwise.
*/
export declare const isFiniteNumber: (arg: unknown) => arg is number;
/**
* Checks whether the argument is an integer number.
*
* @param arg
*
* The value to check.
*
* @returns
*
* `true` if `arg` is an integer number, `false` otherwise.
*/
export declare const isInteger: (arg: unknown) => arg is number;
/**
* Checks whether the argument is of type `number` (includes `NaN` and `±Infinity`).
*
* @param arg
*
* The value to check.
*
* @returns
*
* `true` if `typeof arg === 'number'`, `false` otherwise.
*/
export declare const isNumber: (arg: unknown) => arg is number;
/**
* Checks whether the argument is a plain object (not `null` and not an array).
*
* @param arg
*
* The value to check.
*
* @returns
*
* `true` if `arg` is a plain object, `false` otherwise.
*/
export declare const isRecord: (arg: unknown) => arg is Record<PropertyKey, unknown>;
/**
* Checks whether the argument is a string.
*
* @param arg
*
* The value to check.
*
* @returns
*
* `true` if `typeof arg === 'string'`, `false` otherwise.
*/
export declare const isString: (arg: unknown) => arg is string;
/**
* Parses JSON with support for handler-based value transformation (“JavaScript ON”).
*
* Objects with exactly one property whose key exists in `handlers` and whose value is an array
* are replaced by invoking the corresponding handler with the array elements as arguments.
*
* @param handlers
*
* An object mapping handler names to functions.
*
* @param text
*
* The JSON string to parse.
*
* @returns
*
* The parsed value with handler substitutions applied.
*/
export declare const jsOnParse: (handlers: Record<PropertyKey, Function>, text: string) => any;
/**
* A Monokai-inspired color scheme for use with the {@link c} helper and {@link nanolightTs} tokenizer.
*/
export declare const monokai: CRoot;
/**
* A TypeScript/JavaScript syntax highlighting tokenizer built using {@link newTokenizer}.
*
* @param code
*
* The source code string to tokenize.
*
* @returns
*
* An array of {@link HArgs1} elements suitable for rendering with {@link h}.
*/
export declare const nanolightTs: (code: string) => HArgs1[];
/**
* Creates a tag function for escaping interpolated values in template literals.
*
* @param escapeFn
*
* A function that takes a value and returns its escaped string representation.
*
* @returns
*
* A tag function that escapes interpolated values using the provided escape map.
*/
export declare const newEscape: (escapeFn: (value: any) => string) => (template: TemplateStringsArray, ...values: unknown[]) => string;
/**
* Creates a function that returns the appropriate noun form based on a numeric value using `Intl.PluralRules`.
*
* Different languages have different plural rules. The `Intl.PluralRules` API provides locale-aware plural category selection.
* Possible categories are:
*
* - `zero`: for zero items (used in some languages like Arabic, Latvian)
* - `one`: for singular (e.g., 1 item)
* - `two`: for dual (used in some languages like Arabic, Hebrew)
* - `few`: for small plurals (e.g., 2-4 in Polish)
* - `many`: for larger plurals (e.g., 5-21 in Polish)
* - `other`: fallback category (used by all languages)
*
* @param locale
*
* A BCP 47 language tag (e.g., `pl`, `en`).
*
* @param forms
*
* An object mapping plural categories to noun forms. Not all categories need to be provided;
* if a category is missing, the function falls back to `other`, then to an empty string.
*
* @returns
*
* A function that takes a numeric value and returns the appropriate noun form.
*/
export declare const newNounForm: (locale: string, forms: Partial<Record<Intl.LDMLPluralRule, string>>) => (value: number) => string;
/**
* A helper for building simple tokenizers (see also {@link nanolightTs}).
*
* @param decorator
*
* A function that wraps each matched chunk. It receives the matched text (`chunk`)
* and optionally the `metadata` associated with the pattern that produced the match.
* For unmatched text between patterns, `metadata` is `undefined`.
*
* @param specs
*
* An array of tuples `[metadata, pattern]` where:
* - `metadata`: arbitrary data (e.g., a CSS class name) passed to `decorator` when the pattern matches.
* - `pattern`: a `string` or `RegExp` to match against the input.
*
* @returns
*
* A tokenizer function that accepts a code string and returns an array of decorated tokens.
*
* @remarks
*
* 1. Matches starting at an earlier position take precedence.
* 2. Among matches at the same position, the longer one wins.
* 3. Among matches of the same position and length, the one defined earlier wins.
*/
export declare const newTokenizer: <M, T>(decorator: (chunk: string, metadata?: M) => T, ...specs: [M, string | RegExp][]) => (code: string) => T[];
/**
* Creates a new object excluding the specified keys from the source object.
*
* A runtime equivalent of TypeScript’s `Omit<T, K>` utility type. See also {@link pick}.
*
* @param ref
*
* The source object.
*
* @param keys
*
* An array of keys to exclude from the result.
*
* @returns
*
* A new object without the specified keys.
*/
export declare const omit: <T, K extends keyof T>(ref: T, keys: unknown[]) => Omit<T, K>;
/**
* Creates a new object containing only the specified keys from the source object.
*
* A runtime equivalent of TypeScript’s `Pick<T, K>` utility type. See also {@link omit}.
*
* @param ref
*
* The source object.
*
* @param keys
*
* An array of keys to include in the result.
*
* @returns
*
* A new object with only the specified keys.
*/
export declare const pick: <T, K extends keyof T>(ref: T, keys: K[]) => Pick<T, K>;
/**
* A responsive web design helper that generates CSS rules for a grid-like layout.
*
* @param root
*
* The CSS root object to populate (see {@link c}).
*
* @param selector
*
* The CSS selector for the grid item.
*
* @param cellWidthPx
*
* The base cell width in pixels.
*
* @param cellHeightPx
*
* The base cell height in pixels.
*
* @param specs
*
* An array of breakpoint specifications, each a tuple of:
* - `maxWidth`: maximum number of cells per row (defines the viewport breakpoint).
* - `width` (optional, default `1`): number of horizontal cells the element spans.
* - `height` (optional, default `1`): number of vertical cells the element spans.
*/
export declare const rwd: (root: CRoot, selector: string, cellWidthPx: number, cellHeightPx: number, ...specs: [number, number?, number?][]) => void;
/**
* Shorthand for creating an SVG element with a `<use>` child referencing an icon by ID.
*
* Equivalent to: `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
*
* @param id
*
* The ID of the symbol to reference (without the `#` prefix).
*
* @param args
*
* Additional arguments passed to the outer `<svg>` element.
*
* @returns
*
* An `SVGSVGElement` containing a `<use>` element.
*/
export declare const svgUse: (id: string, ...args: HArgs1[]) => SVGSVGElement;
/**
* Generates a UUID v1 (time-based) identifier.
*
* @param date
*
* The date to use for the timestamp portion (default: current date/time).
*
* @param node
*
* A hexadecimal `string` for the node portion (default: random).
* Must match `/^[0-9a-f]*$/`; it is trimmed to the last 12 characters and left-padded with zeros if shorter.
*
* @returns
*
* A UUID v1 `string` in the standard format `xxxxxxxx-xxxx-1xxx-xxxx-xxxxxxxxxxxx`.
*/
export declare const uuidV1: (date?: Date, node?: string) => string;
/**
* A Proxy-based helper for auto-vivification of nested object structures.
*
* Accessing, assigning, or deleting any nested property on the returned proxy automatically creates intermediate objects
* (or arrays for numeric-string keys matching `^(0|[1-9]\d*)$`) as needed, allowing deep operations without explicit null checks.
*
* Intermediates of the last level in a get-only property chain are NOT auto-created.
* For example, `vivify(ref).one.two` will create `ref.one` as `{}`, but will NOT create `ref.one.two`.
* Only when a deeper access, assignment, or deletion occurs
* (e.g. `delete vivify(ref).one.two.three` or `vivify(ref).one.two.three = 4`) will `ref.one.two` be materialized.
*
* When traversal reaches a primitive value, no auto-creation happens;
* the primitive’s own property is returned instead
* (e.g. accessing `.toString.name` on a number yields `'toString'` without modifying the underlying structure).
*
* Deletion on a non-existing intermediate path will auto-create intermediates up to the parent of the deleted key
* (e.g. `delete vivify(ref).one.two.three` will create `ref.one.two` as `{}` if it does not exist).
*
* @param ref
*
* The root object to wrap.
*
* @returns
*
* A proxy that auto-creates nested objects/arrays on property access.
*/
export declare const vivify: (ref: unknown) => any;