UNPKG

@jackens/nnn

Version:

Jackens’ JavaScript helpers.

446 lines (445 loc) 14.7 kB
/** * 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;