UNPKG

@zeix/ui-element

Version:

UIElement - minimal reactive framework based on Web Components

108 lines (97 loc) 3.22 kB
import type { AttributeParser } from '../component' /* === Internal Function === */ const parseNumber = ( parseFn: (v: string) => number, value: string | null, ): number | undefined => { if (value == null) return const parsed = parseFn(value) return Number.isFinite(parsed) ? parsed : undefined } /* === Exported Functions === */ /** * Parse a boolean attribute as an actual boolean value * * @since 0.7.0 * @param {C} _ - host element * @param {string} value - maybe string value * @returns {boolean} */ const asBoolean: AttributeParser<HTMLElement, boolean> = ( _: HTMLElement, value: string | null, ): boolean => value !== 'false' && value != null /** * Parse an attribute as as number forced to integer with a fallback * * @since 0.11.0 * @param {number} [fallback=0] - fallback value * @returns {Parser<HTMLElement, number>} - parser function */ const asInteger = (fallback: number = 0): AttributeParser<HTMLElement, number> => (_: HTMLElement, value: string | null): number => parseNumber(parseInt, value) ?? fallback /** * Parse an attribute as as number with a fallback * * @since 0.11.0 * @param {number} [fallback=0] - fallback value * @returns {Parser<number, HTMLElement>} - parser function */ const asNumber = (fallback: number = 0): AttributeParser<HTMLElement, number> => (_: HTMLElement, value: string | null): number => parseNumber(parseFloat, value) ?? fallback /** * Parse an attribute as a string with a fallback * * @since 0.11.0 * @param {string} [fallback=''] - fallback value * @returns {Parser<string, HTMLElement>} - parser function */ const asString = (fallback: string = ''): AttributeParser<HTMLElement, string> => (_: HTMLElement, value: string | null): string => value ?? fallback /** * Parse an attribute as a multi-state value (for examnple: true, false, mixed), defaulting to the first valid option * * @since 0.9.0 * @param {string[]} valid - array of valid values * @returns {Parser<string, HTMLElement>} - parser function */ const asEnum = (valid: [string, ...string[]]): AttributeParser<HTMLElement, string> => (_: HTMLElement, value: string | null): string => value != null && valid.includes(value.toLowerCase()) ? value : valid[0] /** * Parse an attribute as a JSON serialized object with a fallback * * @since 0.11.0 * @param {T} fallback - fallback value * @returns {Parser<T, HTMLElement>} - parser function * @throws {ReferenceError} - if the value and fallback are both null or undefined * @throws {SyntaxError} - if the value is not a valid JSON object */ const asJSON = <T extends {}>(fallback: T): AttributeParser<HTMLElement, T> => (_: HTMLElement, value: string | null): T => { if ((value ?? fallback) == null) throw new ReferenceError( 'Value and fallback are both null or undefined', ) if (value == null) return fallback if (value === '') throw new SyntaxError('Empty string is not valid JSON') let result: T | undefined try { result = JSON.parse(value) } catch (error) { throw new SyntaxError(`Failed to parse JSON: ${String(error)}`, { cause: error, }) } return result ?? fallback } export { asBoolean, asInteger, asNumber, asString, asEnum, asJSON }