@jackens/nnn 2025.6.14 → 2025.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/nnn.d.ts +45 -39
  2. package/nnn.js +101 -107
  3. package/package.json +8 -8
  4. package/readme.md +110 -153
package/nnn.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * The type of arguments of the `c` helper.
3
3
  */
4
- export type CNode = {
5
- [attributeOrSelector: string]: string | number | CNode | undefined;
4
+ export type C_Node = {
5
+ [attribute_or_selector: string]: string | number | C_Node | undefined;
6
6
  };
7
7
  /**
8
8
  * The type of arguments of the `c` helper.
9
9
  */
10
- export type CRoot = Record<PropertyKey, CNode>;
10
+ export type C_Root = Record<PropertyKey, C_Node>;
11
11
  /**
12
12
  * A simple JS-to-CSS (aka CSS-in-JS) helper.
13
13
  *
@@ -15,43 +15,39 @@ export type CRoot = Record<PropertyKey, CNode>;
15
15
  *
16
16
  * - Keys of sub-objects whose values are NOT objects are treated as CSS attribute, and values are treated as values of those CSS attributes; the concatenation of keys of all parent objects is a CSS rule.
17
17
  * - All keys ignore the part starting with a splitter (default: `$$`) sign until the end of the key (e.g. `src$$1` → `src`, `@font-face$$1` → `@font-face`).
18
- * - In keys specifying CSS attribute, all uppercase letters are replaced by lowercase letters with an additional `-` character preceding them (e.g. `fontFamily` → `font-family`).
18
+ * - In keys specifying CSS attribute, all uppercase letters are replaced by lowercase letters with an additional `-` character preceding them (e.g. `fontFamily` → `font-family`), while all `_` characters are replaced by `-` character (e.g. `font_family` → `font-family`).
19
19
  * - Commas in keys that makes a CSS rule cause it to “split” and create separate rules for each part (e.g. `{div:{margin:1,'.a,.b,.c':{margin:2}}}` → `div{margin:1}div.a,div.b,div.c{margin:2}`).
20
20
  * - Top-level keys that begin with `@` are not concatenated with sub-object keys.
21
21
  */
22
- export declare const c: (root: CRoot, splitter?: string) => string;
22
+ export declare const c: (root: C_Root, splitter?: string) => string;
23
23
  /**
24
24
  * A tiny helper for parsing CSV.
25
25
  */
26
- export declare const csvParseRaw: (csv: string, separator?: string) => string[][];
26
+ export declare const csv_parse: (csv: string, separator?: string) => string[][];
27
27
  /**
28
- * A tiny helper for parsing CSV.
29
- */
30
- export declare const csvParse: (csv: string, separator?: string) => Record<PropertyKey, string>[];
31
- /**
32
- * The type of arguments of the `escapeValues` and `escape` helpers.
28
+ * The type of arguments of the `escape_values` and `escape` helpers.
33
29
  */
34
- export type EscapeMap = Map<unknown, (value?: unknown) => string>;
30
+ export type Escape_Map = Map<unknown, (value?: unknown) => string>;
35
31
  /**
36
- * A generic helper for escaping `values` by given `escapeMap`.
32
+ * A generic helper for escaping `values` by given `escape_map`.
37
33
  */
38
- export declare const escapeValues: (escapeMap: EscapeMap, values: unknown[]) => string[];
34
+ export declare const escape_values: (escape_map: Escape_Map, values: unknown[]) => string[];
39
35
  /**
40
- * A generic helper for escaping `values` by given `escapeMap` (in *TemplateStrings* flavor).
36
+ * A generic helper for escaping `values` by given `escape_map` (in *TemplateStrings* flavor).
41
37
  */
42
- export declare const escape: (escapeMap: EscapeMap, template: TemplateStringsArray, ...values: unknown[]) => string;
38
+ export declare const escape: (escape_map: Escape_Map, template: TemplateStringsArray, ...values: unknown[]) => string;
43
39
  /**
44
40
  * A helper that implements typographic corrections specific to Polish typography.
45
41
  */
46
- export declare const fixTypography: (node: Node) => void;
42
+ export declare const fix_typography: (node: Node) => void;
47
43
  /**
48
44
  * The type of arguments of the `h` and `s` helpers.
49
45
  */
50
- export type HArgs1 = Record<PropertyKey, unknown> | null | undefined | Node | string | number | HArgs;
46
+ export type H_Args_1 = Record<PropertyKey, unknown> | null | undefined | Node | string | number | H_Args;
51
47
  /**
52
48
  * The type of arguments of the `h` and `s` helpers.
53
49
  */
54
- export type HArgs = [string | Node, ...HArgs1[]];
50
+ export type H_Args = [string | Node, ...H_Args_1[]];
55
51
  /**
56
52
  * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also `s`).
57
53
  *
@@ -64,9 +60,9 @@ export type HArgs = [string | Node, ...HArgs1[]];
64
60
  * - All other arguments of type `HArgs` are passed to `h` and the results are appended to the element being created or modified.
65
61
  */
66
62
  export declare const h: {
67
- <T extends keyof HTMLElementTagNameMap>(tag: T, ...args1: HArgs1[]): HTMLElementTagNameMap[T];
68
- <N extends Node>(node: N, ...args1: HArgs1[]): N;
69
- (tagOrNode: string | Node, ...args1: HArgs1[]): Node;
63
+ <T extends keyof HTMLElementTagNameMap>(tag: T, ...args1: H_Args_1[]): HTMLElementTagNameMap[T];
64
+ <N extends Node>(node: N, ...args1: H_Args_1[]): N;
65
+ (tag_or_node: string | Node, ...args1: H_Args_1[]): Node;
70
66
  };
71
67
  /**
72
68
  * A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also `h`).
@@ -80,58 +76,68 @@ export declare const h: {
80
76
  * - All other arguments of type `HArgs` are passed to `s` and the results are appended to the element being created or modified.
81
77
  */
82
78
  export declare const s: {
83
- <T extends keyof SVGElementTagNameMap>(tag: T, ...args1: HArgs1[]): SVGElementTagNameMap[T];
84
- <N extends Node>(node: N, ...args1: HArgs1[]): N;
85
- (tagOrNode: string | Node, ...args1: HArgs1[]): Node;
79
+ <T extends keyof SVGElementTagNameMap>(tag: T, ...args1: H_Args_1[]): SVGElementTagNameMap[T];
80
+ <N extends Node>(node: N, ...args1: H_Args_1[]): N;
81
+ (tag_or_node: string | Node, ...args1: H_Args_1[]): Node;
86
82
  };
87
83
  /**
88
84
  * A convenient shortcut for `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
89
85
  */
90
- export declare const svgUse: (id: string, ...args: HArgs1[]) => SVGSVGElement;
86
+ export declare const svg_use: (id: string, ...args: H_Args_1[]) => SVGSVGElement;
91
87
  /**
92
88
  * A replacement for the `in` operator (not to be confused with the `for-in` loop) that works properly.
93
89
  */
94
- export declare const hasOwn: (ref: unknown, key: unknown) => boolean;
90
+ export declare const has_own: (ref: unknown, key: unknown) => boolean;
95
91
  /**
96
92
  * A helper that checks if the given argument is of type `any[]`.
97
93
  */
98
- export declare const isArray: (arg: any) => arg is any[];
94
+ export declare const is_array: (arg: any) => arg is any[];
95
+ declare const FINITE_NUMBER: unique symbol;
96
+ type Finite_Number = number & {
97
+ readonly [FINITE_NUMBER]: true;
98
+ };
99
+ /**
100
+ * A helper that checks if the given argument is of type `number` but not `±Infinity` nor `NaN`.
101
+ */
102
+ export declare const is_finite_number: ((arg: unknown) => arg is Finite_Number);
99
103
  /**
100
104
  * A helper that checks if the given argument is of type `number`.
101
105
  */
102
- export declare const isNumber: (arg: any) => arg is number;
106
+ export declare const is_number: (arg: unknown) => arg is number;
103
107
  /**
104
108
  * A helper that checks if the given argument is of type `Record<PropertyKey, unknown>`.
105
109
  */
106
- export declare const isRecord: (arg: any) => arg is Record<PropertyKey, unknown>;
110
+ export declare const is_record: (arg: unknown) => arg is Record<PropertyKey, unknown>;
107
111
  /**
108
112
  * A helper that checks if the given argument is of type `string`.
109
113
  */
110
- export declare const isString: (arg: any) => arg is string;
114
+ export declare const is_string: (arg: unknown) => arg is string;
115
+ export {};
111
116
  /**
112
117
  * `JSON.parse` with “JavaScript turned on”.
113
118
  *
114
119
  * Objects having *exactly* one property which is present in the `handlers` map, i.e. objects of the form:
115
120
  *
116
121
  * ```js
117
- * { "«handlerName»": [«params»] }
122
+ * { "«handler_name»": [«params»] }
118
123
  * ```
119
124
  *
120
125
  * are replaced by the result of call
121
126
  *
122
127
  * ```js
123
- * handlers['«handlerName»'](...«params»)
128
+ * handlers['«handler_name»'](...«params»)
124
129
  * ```
125
130
  */
126
- export declare const jsOnParse: (handlers: Record<PropertyKey, Function>, text: string) => any;
131
+ export declare const js_on_parse: (handlers: Record<PropertyKey, Function>, text: string) => any;
132
+ import type { H_Args_1 } from './h.js';
127
133
  /**
128
- * A generic helper for syntax highlighting (see also `nanolightJs`).
134
+ * A generic helper for syntax highlighting (see also `nanolight_js`).
129
135
  */
130
- export declare const nanolight: (pattern: RegExp, highlighters: ((chunk: string, index: number) => HArgs1)[], code: string) => HArgs1[];
136
+ export declare const nanolight: (pattern: RegExp, highlighters: ((chunk: string, index: number) => H_Args_1)[], code: string) => H_Args_1[];
131
137
  /**
132
138
  * A helper for highlighting JavaScript (see also `nanolight`).
133
139
  */
134
- export declare const nanolightJs: (code: string) => HArgs1[];
140
+ export declare const nanolight_js: (code: string) => H_Args_1[];
135
141
  /**
136
142
  * A helper that implements TypeScript’s `Pick` utility type (see also `omit`).
137
143
  */
@@ -143,7 +149,7 @@ export declare const omit: <T, K extends keyof T>(ref: T, keys: unknown[]) => Om
143
149
  /**
144
150
  * A helper for choosing the correct singular and plural.
145
151
  */
146
- export declare const plUral: (singular: string, plural2: string, plural5: string, value: number) => string;
152
+ export declare const pl_ural: (singular: string, plural_2: string, plural_5: string, value: number) => string;
147
153
  /**
148
154
  * A helper that protects calls to nested properties by a `Proxy` that initializes non-existent values with an empty object.
149
155
  */
@@ -153,4 +159,4 @@ export declare const pro: (ref: unknown) => any;
153
159
  *
154
160
  * - The optional `node` parameter should have the format `/^[0123456789abcdef]+$/`. Its value will be trimmed to last 12 characters and left padded with zeros.
155
161
  */
156
- export declare const uuid1: (date?: Date, node?: string) => string;
162
+ export declare const uuid_v1: (date?: Date, node?: string) => string;
package/nnn.js CHANGED
@@ -1,38 +1,40 @@
1
1
  // src/nnn/is.ts
2
- var isArray = Array.isArray;
3
- var isNumber = (arg) => typeof arg === "number";
4
- var isRecord = (arg) => typeof arg === "object" && arg != null && !isArray(arg);
5
- var isString = (arg) => typeof arg === "string";
2
+ var is_array = Array.isArray;
3
+ var is_finite_number = Number.isFinite;
4
+ var is_number = (arg) => typeof arg === "number";
5
+ var is_record = (arg) => typeof arg === "object" && arg != null && !is_array(arg);
6
+ var is_string = (arg) => typeof arg === "string";
6
7
 
7
8
  // src/nnn/c.ts
8
- var _c = (node, prefix, result, split) => {
9
+ var _c = (node, prefix, result, splitter) => {
9
10
  const queue = [[node, prefix]];
10
11
  while (queue.length > 0) {
11
- const [style0, prefix0] = queue.shift() ?? [];
12
- if (style0 == null || prefix0 == null) {
12
+ const [style_0, prefix_0] = queue.shift() ?? [];
13
+ if (style_0 == null || prefix_0 == null) {
13
14
  continue;
14
15
  }
15
- if (isArray(style0)) {
16
- result.push(prefix0, prefix0 !== "" ? "{" : "", style0.join(";"), prefix0 !== "" ? "}" : "");
16
+ if (is_array(style_0)) {
17
+ result.push(prefix_0, prefix_0 !== "" ? "{" : "", style_0.join(";"), prefix_0 !== "" ? "}" : "");
17
18
  } else {
18
19
  const todo = [];
19
20
  let attributes = [];
20
- let attributesPushed = false;
21
- for (const key in style0) {
22
- const value = style0[key];
23
- if (isString(value) || isNumber(value)) {
24
- if (!attributesPushed) {
25
- attributesPushed = true;
21
+ let attributes_pushed = false;
22
+ for (const key in style_0) {
23
+ const value = style_0[key];
24
+ if (is_string(value) || is_number(value)) {
25
+ if (!attributes_pushed) {
26
+ attributes_pushed = true;
26
27
  attributes = [];
27
- todo.push([attributes, prefix0]);
28
+ todo.push([attributes, prefix_0]);
28
29
  }
29
- attributes.push(`${split(key).replace(/([A-Z])/g, (_, letter) => "-" + letter.toLowerCase())}:${value}`);
30
+ const attribute = key.split(splitter)[0].replace(/_/g, "-").replace(/([A-Z])/g, (_, letter) => "-" + letter.toLowerCase());
31
+ attributes.push(`${attribute}:${value}`);
30
32
  } else if (value != null) {
31
- attributesPushed = false;
32
- const prefixN = [];
33
- const keyChunks = key.split(",");
34
- prefix0.split(",").forEach((prefixChunk) => keyChunks.forEach((keyChunk) => prefixN.push(prefixChunk + keyChunk)));
35
- todo.push([value, prefixN.join(",")]);
33
+ attributes_pushed = false;
34
+ const prefix_n = [];
35
+ const key_chunks = key.split(",");
36
+ prefix_0.split(",").forEach((prefix_chunk) => key_chunks.forEach((key_chunk) => prefix_n.push(prefix_chunk + key_chunk)));
37
+ todo.push([value, prefix_n.join()]);
36
38
  }
37
39
  }
38
40
  queue.unshift(...todo);
@@ -40,67 +42,59 @@ var _c = (node, prefix, result, split) => {
40
42
  }
41
43
  };
42
44
  var c = (root, splitter = "$$") => {
43
- const split = (text) => text.split(splitter)[0];
44
45
  const chunks = [];
45
46
  for (const key in root) {
46
47
  const value = root[key];
47
48
  if (value != null) {
48
49
  if (key[0] === "@") {
49
- chunks.push(split(key) + "{");
50
- _c(value, "", chunks, split);
50
+ chunks.push(key.split(splitter)[0] + "{");
51
+ _c(value, "", chunks, splitter);
51
52
  chunks.push("}");
52
53
  } else {
53
- _c(value, split(key), chunks, split);
54
+ _c(value, key.split(splitter)[0], chunks, splitter);
54
55
  }
55
56
  }
56
57
  }
57
58
  return chunks.join("");
58
59
  };
59
- // src/nnn/csvParse.ts
60
- var csvParseRaw = (csv, separator = ",") => {
61
- const regExp = new RegExp(`${separator}|(?<!")\\s*"((?:[^"]|"")*)"\\s*(?!")`, "g");
62
- return csv.replace(/\r/g, "").replace(/\n+$/, "").replace(/\n|(?<!")("(?:[^"]|"")*")(?!")/g, (_, chunk) => chunk ?? "\r").split("\r").map((line) => line.replace(regExp, (_, chunk) => chunk == null ? "\r" : chunk.replace(/""/g, '"')).split("\r"));
63
- };
64
- var csvParse = (csv, separator = ",") => {
65
- const rows = csvParseRaw(csv, separator);
66
- const keys = rows.shift();
67
- return keys != null ? rows.map((row) => keys.reduce((record, key, index) => {
68
- record[key] = row[index];
69
- return record;
70
- }, {})) : [];
60
+ // src/nnn/csv_parse.ts
61
+ var csv_parse = (csv, separator = ",") => {
62
+ const main_pattern = /\n|(?<!")("(?:[^"]|"")*")(?!")/g;
63
+ const line_pattern = new RegExp(`${separator}|(?<!")\\s*"((?:[^"]|"")*)"\\s*(?!")`, "g");
64
+ return csv.replace(/\r/g, "").replace(/\n+$/, "").replace(main_pattern, (_, chunk) => chunk ?? "\r").split("\r").map((line) => line.replace(line_pattern, (_, chunk) => chunk == null ? "\r" : chunk.replace(/""/g, '"')).split("\r"));
71
65
  };
72
66
  // src/nnn/escape.ts
73
- var escapeValues = (escapeMap, values) => values.map((value) => (escapeMap.get(value?.constructor) ?? escapeMap.get(undefined))?.(value) ?? "");
74
- var escape = (escapeMap, template, ...values) => String.raw(template, ...escapeValues(escapeMap, values));
67
+ var escape_values = (escape_map, values) => values.map((value) => (escape_map.get(value?.constructor) ?? escape_map.get(undefined))?.(value) ?? "");
68
+ var escape = (escape_map, template, ...values) => String.raw(template, ...escape_values(escape_map, values));
75
69
  // src/nnn/h.ts
76
- var _h = (namespaceURI) => {
77
- const createElement = namespaceURI == null ? (tag) => document.createElement(tag) : (tag) => document.createElementNS(namespaceURI, tag);
78
- const h = (tagOrNode, ...args) => {
79
- const node = isString(tagOrNode) ? createElement(tagOrNode) : tagOrNode;
70
+ var _h = (namespace_uri) => {
71
+ const create_element = namespace_uri == null ? (tag) => document.createElement(tag) : (tag) => document.createElementNS(namespace_uri, tag);
72
+ const h = (tag_or_node, ...args) => {
73
+ const node = is_string(tag_or_node) ? create_element(tag_or_node) : tag_or_node;
80
74
  args.forEach((arg) => {
81
75
  let child = null;
82
76
  if (arg instanceof Node) {
83
77
  child = arg;
84
- } else if (isArray(arg)) {
78
+ } else if (is_array(arg)) {
85
79
  child = h(...arg);
86
- } else if (isRecord(arg)) {
80
+ } else if (is_record(arg)) {
87
81
  for (const name in arg) {
88
82
  const value = arg[name];
89
83
  if (name[0] === "$") {
90
84
  const name1 = name.slice(1);
91
- if (isRecord(value)) {
92
- node[name1] = node[name1] ?? {};
85
+ if (is_record(value)) {
86
+ node[name1] ??= {};
93
87
  Object.assign(node[name1], value);
94
88
  } else {
95
89
  node[name1] = value;
96
90
  }
97
91
  } else if (node instanceof Element) {
98
- const indexOfColon = name.indexOf(":");
99
- if (indexOfColon >= 0) {
100
- const nsKey = name.slice(0, indexOfColon);
101
- if (nsKey === "xlink") {
92
+ const index_of_colon = name.indexOf(":");
93
+ if (index_of_colon >= 0) {
94
+ const ns_key = name.slice(0, index_of_colon);
95
+ if (ns_key === "xlink") {
102
96
  const ns = "http://www.w3.org/1999/xlink";
103
- const basename = name.slice(indexOfColon + 1);
97
+ const basename = name.slice(index_of_colon + 1);
104
98
  if (value === true) {
105
99
  node.setAttributeNS(ns, basename, "");
106
100
  } else if (value === false) {
@@ -120,7 +114,7 @@ var _h = (namespaceURI) => {
120
114
  }
121
115
  }
122
116
  }
123
- } else if (isString(arg)) {
117
+ } else if (is_string(arg)) {
124
118
  child = document.createTextNode(arg);
125
119
  }
126
120
  if (child != null) {
@@ -133,54 +127,54 @@ var _h = (namespaceURI) => {
133
127
  };
134
128
  var h = _h();
135
129
  var s = _h("http://www.w3.org/2000/svg");
136
- var svgUse = (id, ...args) => s("svg", ["use", { "xlink:href": "#" + id }], ...args);
130
+ var svg_use = (id, ...args) => s("svg", ["use", { "xlink:href": "#" + id }], ...args);
137
131
 
138
- // src/nnn/fixTypography.ts
132
+ // src/nnn/fix_typography.ts
139
133
  var TAGS_TO_SKIP = ["IFRAME", "NOSCRIPT", "PRE", "SCRIPT", "STYLE", "TEXTAREA"];
140
- var fixTypography = (node) => {
134
+ var fix_typography = (node) => {
141
135
  const queue = [node];
142
136
  while (queue.length > 0) {
143
- const node0 = queue.shift();
144
- if (node0 instanceof Element) {
145
- node0.childNodes.forEach((childNode) => {
146
- if (childNode instanceof Text) {
147
- queue.push(childNode);
148
- } else if (childNode instanceof Element && !TAGS_TO_SKIP.includes(childNode.tagName)) {
149
- queue.push(childNode);
137
+ const node_0 = queue.shift();
138
+ if (node_0 instanceof Element) {
139
+ node_0.childNodes.forEach((child_node) => {
140
+ if (child_node instanceof Text) {
141
+ queue.push(child_node);
142
+ } else if (child_node instanceof Element && !TAGS_TO_SKIP.includes(child_node.tagName)) {
143
+ queue.push(child_node);
150
144
  }
151
145
  });
152
- } else if (node0 instanceof Text) {
153
- const nodeValue = node0.nodeValue?.trim?.();
154
- if (nodeValue != null) {
155
- let previousNode = node0;
156
- nodeValue.split(/(\s|\(|„)([aiouwz—]\s)/gi).forEach((chunk, i) => {
146
+ } else if (node_0 instanceof Text) {
147
+ const node_value = node_0.nodeValue?.trim?.();
148
+ if (node_value != null) {
149
+ let previous_node = node_0;
150
+ node_value.split(/(\s|\(|„)([aiouwz—]\s)/gi).forEach((chunk, i) => {
157
151
  i %= 3;
158
- const currentNode = i === 2 ? h("span", { style: "white-space:nowrap" }, chunk) : i === 1 ? document.createTextNode(chunk) : document.createTextNode(chunk.replace(/(\/(?=[^/\s])|\.(?=[^\s]))/g, "$1​"));
159
- if (node0.parentNode != null) {
160
- node0.parentNode.insertBefore(currentNode, previousNode.nextSibling);
152
+ const current_node = i === 2 ? h("span", { style: "white-space:nowrap" }, chunk) : i === 1 ? document.createTextNode(chunk) : document.createTextNode(chunk.replace(/(\/(?=[^/\s])|\.(?=[^\s]))/g, "$1​"));
153
+ if (node_0.parentNode != null) {
154
+ node_0.parentNode.insertBefore(current_node, previous_node.nextSibling);
161
155
  }
162
- previousNode = currentNode;
156
+ previous_node = current_node;
163
157
  });
164
- node0.parentNode?.removeChild(node0);
158
+ node_0.parentNode?.removeChild(node_0);
165
159
  }
166
160
  }
167
161
  }
168
162
  };
169
- // src/nnn/hasOwn.ts
170
- var hasOwn = (ref, key) => ref != null && Object.hasOwn(ref, key);
171
- // src/nnn/jsOnParse.ts
172
- var jsOnParse = (handlers, text) => JSON.parse(text, (key, value) => {
173
- if (isRecord(value)) {
174
- let isSecondKey = false;
163
+ // src/nnn/has_own.ts
164
+ var has_own = (ref, key) => ref != null && Object.hasOwn(ref, key);
165
+ // src/nnn/js_on_parse.ts
166
+ var js_on_parse = (handlers, text) => JSON.parse(text, (key, value) => {
167
+ if (is_record(value)) {
168
+ let is_second_key = false;
175
169
  for (key in value) {
176
- if (isSecondKey) {
170
+ if (is_second_key) {
177
171
  return value;
178
172
  }
179
- isSecondKey = true;
173
+ is_second_key = true;
180
174
  }
181
175
  const handler = handlers[key];
182
176
  const params = value[key];
183
- if (handler instanceof Function && isArray(params)) {
177
+ if (handler instanceof Function && is_array(params)) {
184
178
  return handler(...params);
185
179
  }
186
180
  }
@@ -197,8 +191,8 @@ var nanolight = (pattern, highlighters, code) => {
197
191
  });
198
192
  return result;
199
193
  };
200
- // src/nnn/nanolightJs.ts
201
- var nanolightJs = nanolight.bind(0, /('.*?'|".*?"|`[\s\S]*?`)|(\/\/.*?\n|\/\*[\s\S]*?\*\/)|(any|bigint|break|boolean|case|catch|class|const|continue|debugger|default|delete|do|else|eval|export|extends|false|finally|for|from|function|goto|if|import|in|instanceof|is|keyof|let|NaN|new|number|null|package|return|string|super|switch|symbol|this|throw|true|try|type|typeof|undefined|unknown|var|void|while|with|yield)(?!\w)|([<>=.?:&|!^~*/%+-])|(0x[\dabcdef_]+|0o[01234567_]+|0b[01_]+|\d[\d_]*(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?)|([$\w]+)(?=\()|([$\wąćęłńóśżźĄĆĘŁŃÓŚŻŹ]+)/, [
194
+ // src/nnn/nanolight_js.ts
195
+ var nanolight_js = nanolight.bind(0, /('.*?'|".*?"|`[\s\S]*?`)|(\/\/.*?\n|\/\*[\s\S]*?\*\/)|(any|bigint|break|boolean|case|catch|class|const|continue|debugger|default|delete|do|else|eval|export|extends|false|finally|for|from|function|goto|if|import|in|instanceof|is|keyof|let|NaN|new|number|null|package|return|string|super|switch|symbol|this|throw|true|try|type|typeof|undefined|unknown|var|void|while|with|yield)(?!\w)|([<>=.?:&|!^~*/%+-])|(0x[\dabcdef_]+|0o[01234567_]+|0b[01_]+|\d[\d_]*(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?)|([$\w]+)(?=\()|([$\wąćęłńóśżźĄĆĘŁŃÓŚŻŹ]+)/, [
202
196
  (chunk) => chunk,
203
197
  (chunk) => ["span", { class: "string" }, chunk],
204
198
  (chunk) => ["span", { class: "comment" }, chunk],
@@ -211,47 +205,47 @@ var nanolightJs = nanolight.bind(0, /('.*?'|".*?"|`[\s\S]*?`)|(\/\/.*?\n|\/\*[\s
211
205
  // src/nnn/pick.ts
212
206
  var pick = (ref, keys) => Object.fromEntries(Object.entries(ref).filter(([key]) => keys.includes(key)));
213
207
  var omit = (ref, keys) => Object.fromEntries(Object.entries(ref).filter(([key]) => !keys.includes(key)));
214
- // src/nnn/plUral.ts
215
- var plUral = (singular, plural2, plural5, value) => {
216
- const absValue = Math.abs(value);
217
- const absValueMod10 = absValue % 10;
218
- return value === 1 ? singular : (absValueMod10 === 2 || absValueMod10 === 3 || absValueMod10 === 4) && absValue !== 12 && absValue !== 13 && absValue !== 14 ? plural2 : plural5;
208
+ // src/nnn/pl_ural.ts
209
+ var pl_ural = (singular, plural_2, plural_5, value) => {
210
+ const abs_value = Math.abs(value);
211
+ const abs_value_mod_10 = abs_value % 10;
212
+ return value === 1 ? singular : (abs_value_mod_10 === 2 || abs_value_mod_10 === 3 || abs_value_mod_10 === 4) && abs_value !== 12 && abs_value !== 13 && abs_value !== 14 ? plural_2 : plural_5;
219
213
  };
220
214
  // src/nnn/pro.ts
221
215
  var pro = (ref) => new Proxy(ref, {
222
216
  get(target, key) {
223
- return pro(target[key] = target[key] ?? {});
217
+ return pro(target[key] ??= {});
224
218
  }
225
219
  });
226
- // src/nnn/uuid1.ts
220
+ // src/nnn/uuid_v1.ts
227
221
  var ZEROS = "0".repeat(16);
228
222
  var counter = 0;
229
- var uuid1 = (date = new Date, node = Math.random().toString(16).slice(2)) => {
223
+ var uuid_v1 = (date = new Date, node = Math.random().toString(16).slice(2)) => {
230
224
  const time = ZEROS + (1e4 * (+date + 12219292800000)).toString(16);
231
225
  counter = counter + 1 & 16383;
232
226
  return time.slice(-8).concat("-", time.slice(-12, -8), -1, time.slice(-15, -12), "-", (8 | counter >> 12).toString(16), (ZEROS + (counter & 4095).toString(16)).slice(-3), "-", (ZEROS + node).slice(-12));
233
227
  };
234
228
  export {
235
- uuid1,
236
- svgUse,
229
+ uuid_v1,
230
+ svg_use,
237
231
  s,
238
232
  pro,
239
- plUral,
233
+ pl_ural,
240
234
  pick,
241
235
  omit,
242
- nanolightJs,
236
+ nanolight_js,
243
237
  nanolight,
244
- jsOnParse,
245
- isString,
246
- isRecord,
247
- isNumber,
248
- isArray,
249
- hasOwn,
238
+ js_on_parse,
239
+ is_string,
240
+ is_record,
241
+ is_number,
242
+ is_finite_number,
243
+ is_array,
244
+ has_own,
250
245
  h,
251
- fixTypography,
252
- escapeValues,
246
+ fix_typography,
247
+ escape_values,
253
248
  escape,
254
- csvParseRaw,
255
- csvParse,
249
+ csv_parse,
256
250
  c
257
251
  };
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "c",
6
6
  "CSS-in-JS",
7
7
  "CSV",
8
- "csvParse",
8
+ "csv_parse",
9
9
  "DOM",
10
10
  "escape",
11
11
  "h",
@@ -14,13 +14,14 @@
14
14
  "HyperScript",
15
15
  "in",
16
16
  "is",
17
- "isArray",
18
- "isNumber",
19
- "isRecord",
20
- "isString",
17
+ "is_array",
18
+ "is_finite_number",
19
+ "is_number",
20
+ "is_record",
21
+ "is_string",
21
22
  "JS-to-CSS",
22
23
  "JSON",
23
- "jsOnParse",
24
+ "js_on_parse",
24
25
  "nanolight",
25
26
  "nnn",
26
27
  "omit",
@@ -28,7 +29,6 @@
28
29
  "SVG",
29
30
  "typography",
30
31
  "uuid",
31
- "uuid1",
32
32
  "uuidv1"
33
33
  ],
34
34
  "license": "MIT",
@@ -36,5 +36,5 @@
36
36
  "name": "@jackens/nnn",
37
37
  "type": "module",
38
38
  "types": "nnn.d.ts",
39
- "version": "2025.6.14"
39
+ "version": "2025.9.3"
40
40
  }
package/readme.md CHANGED
@@ -28,72 +28,72 @@ import { «something» } from './node_modules/@jackens/nnn/nnn.js'
28
28
 
29
29
  ## Exports
30
30
 
31
- - `CNode`: The type of arguments of the `c` helper.
32
- - `CRoot`: The type of arguments of the `c` helper.
33
- - `EscapeMap`: The type of arguments of the `escapeValues` and `escape` helpers.
34
- - `HArgs`: The type of arguments of the `h` and `s` helpers.
35
- - `HArgs1`: The type of arguments of the `h` and `s` helpers.
31
+ - `C_Node`: The type of arguments of the `c` helper.
32
+ - `C_Root`: The type of arguments of the `c` helper.
33
+ - `Escape_Map`: The type of arguments of the `escape_values` and `escape` helpers.
34
+ - `H_Args`: The type of arguments of the `h` and `s` helpers.
35
+ - `H_Args_1`: The type of arguments of the `h` and `s` helpers.
36
36
  - `c`: A simple JS-to-CSS (aka CSS-in-JS) helper.
37
- - `csvParse`: A tiny helper for parsing CSV.
38
- - `csvParseRaw`: A tiny helper for parsing CSV.
39
- - `escape`: A generic helper for escaping `values` by given `escapeMap` (in *TemplateStrings* flavor).
40
- - `escapeValues`: A generic helper for escaping `values` by given `escapeMap`.
41
- - `fixTypography`: A helper that implements typographic corrections specific to Polish typography.
37
+ - `csv_parse`: A tiny helper for parsing CSV.
38
+ - `escape`: A generic helper for escaping `values` by given `escape_map` (in *TemplateStrings* flavor).
39
+ - `escape_values`: A generic helper for escaping `values` by given `escape_map`.
40
+ - `fix_typography`: A helper that implements typographic corrections specific to Polish typography.
42
41
  - `h`: A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `HTMLElement`s (see also `s`).
43
- - `hasOwn`: A replacement for the `in` operator (not to be confused with the `for-in` loop) that works properly.
44
- - `isArray`: A helper that checks if the given argument is of type `any[]`.
45
- - `isNumber`: A helper that checks if the given argument is of type `number`.
46
- - `isRecord`: A helper that checks if the given argument is of type `Record<PropertyKey, unknown>`.
47
- - `isString`: A helper that checks if the given argument is of type `string`.
48
- - `jsOnParse`: `JSON.parse` with “JavaScript turned on”.
49
- - `nanolight`: A generic helper for syntax highlighting (see also `nanolightJs`).
50
- - `nanolightJs`: A helper for highlighting JavaScript (see also `nanolight`).
42
+ - `has_own`: A replacement for the `in` operator (not to be confused with the `for-in` loop) that works properly.
43
+ - `is_array`: A helper that checks if the given argument is of type `any[]`.
44
+ - `is_finite_number`: A helper that checks if the given argument is of type `number` but not `±Infinity` nor `NaN`.
45
+ - `is_number`: A helper that checks if the given argument is of type `number`.
46
+ - `is_record`: A helper that checks if the given argument is of type `Record<PropertyKey, unknown>`.
47
+ - `is_string`: A helper that checks if the given argument is of type `string`.
48
+ - `js_on_parse`: `JSON.parse` with “JavaScript turned on”.
49
+ - `nanolight`: A generic helper for syntax highlighting (see also `nanolight_js`).
50
+ - `nanolight_js`: A helper for highlighting JavaScript (see also `nanolight`).
51
51
  - `omit`: A helper that implements TypeScript’s `Omit` utility type (see also `pick`).
52
52
  - `pick`: A helper that implements TypeScript’s `Pick` utility type (see also `omit`).
53
- - `plUral`: A helper for choosing the correct singular and plural.
53
+ - `pl_ural`: A helper for choosing the correct singular and plural.
54
54
  - `pro`: A helper that protects calls to nested properties by a `Proxy` that initializes non-existent values with an empty object.
55
55
  - `s`: A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style helper for creating and modifying `SVGElement`s (see also `h`).
56
- - `svgUse`: A convenient shortcut for `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
57
- - `uuid1`: A helper that generates a UUID v1 identifier (with a creation timestamp).
56
+ - `svg_use`: A convenient shortcut for `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
57
+ - `uuid_v1`: A helper that generates a UUID v1 identifier (with a creation timestamp).
58
58
 
59
- ### CNode
59
+ ### C_Node
60
60
 
61
61
  ```ts
62
- type CNode = {
63
- [attributeOrSelector: string]: string | number | CNode | undefined;
62
+ type C_Node = {
63
+ [attribute_or_selector: string]: string | number | C_Node | undefined;
64
64
  };
65
65
  ```
66
66
 
67
67
  The type of arguments of the `c` helper.
68
68
 
69
- ### CRoot
69
+ ### C_Root
70
70
 
71
71
  ```ts
72
- type CRoot = Record<PropertyKey, CNode>;
72
+ type C_Root = Record<PropertyKey, C_Node>;
73
73
  ```
74
74
 
75
75
  The type of arguments of the `c` helper.
76
76
 
77
- ### EscapeMap
77
+ ### Escape_Map
78
78
 
79
79
  ```ts
80
- type EscapeMap = Map<unknown, (value?: unknown) => string>;
80
+ type Escape_Map = Map<unknown, (value?: unknown) => string>;
81
81
  ```
82
82
 
83
- The type of arguments of the `escapeValues` and `escape` helpers.
83
+ The type of arguments of the `escape_values` and `escape` helpers.
84
84
 
85
- ### HArgs
85
+ ### H_Args
86
86
 
87
87
  ```ts
88
- type HArgs = [string | Node, ...HArgs1[]];
88
+ type H_Args = [string | Node, ...H_Args_1[]];
89
89
  ```
90
90
 
91
91
  The type of arguments of the `h` and `s` helpers.
92
92
 
93
- ### HArgs1
93
+ ### H_Args_1
94
94
 
95
95
  ```ts
96
- type HArgs1 = Record<PropertyKey, unknown> | null | undefined | Node | string | number | HArgs;
96
+ type H_Args_1 = Record<PropertyKey, unknown> | null | undefined | Node | string | number | H_Args;
97
97
  ```
98
98
 
99
99
  The type of arguments of the `h` and `s` helpers.
@@ -101,7 +101,7 @@ The type of arguments of the `h` and `s` helpers.
101
101
  ### c
102
102
 
103
103
  ```ts
104
- const c: (root: CRoot, splitter?: string) => string;
104
+ const c: (root: C_Root, splitter?: string) => string;
105
105
  ```
106
106
 
107
107
  A simple JS-to-CSS (aka CSS-in-JS) helper.
@@ -110,7 +110,7 @@ The `root` parameter provides a hierarchical description of CSS rules.
110
110
 
111
111
  - Keys of sub-objects whose values are NOT objects are treated as CSS attribute, and values are treated as values of those CSS attributes; the concatenation of keys of all parent objects is a CSS rule.
112
112
  - All keys ignore the part starting with a splitter (default: `$$`) sign until the end of the key (e.g. `src$$1` → `src`, `@font-face$$1` → `@font-face`).
113
- - In keys specifying CSS attribute, all uppercase letters are replaced by lowercase letters with an additional `-` character preceding them (e.g. `fontFamily` → `font-family`).
113
+ - In keys specifying CSS attribute, all uppercase letters are replaced by lowercase letters with an additional `-` character preceding them (e.g. `fontFamily` → `font-family`), while all `_` characters are replaced by `-` character (e.g. `font_family` → `font-family`).
114
114
  - Commas in keys that makes a CSS rule cause it to “split” and create separate rules for each part (e.g. `{div:{margin:1,'.a,.b,.c':{margin:2}}}` → `div{margin:1}div.a,div.b,div.c{margin:2}`).
115
115
  - Top-level keys that begin with `@` are not concatenated with sub-object keys.
116
116
 
@@ -177,11 +177,11 @@ const actual = c({
177
177
  src$$1: 'url(otf/jackens.otf)',
178
178
  src$$2: "url(otf/jackens.otf) format('opentype')," +
179
179
  "url(svg/jackens.svg) format('svg')",
180
- fontWeight: 'normal',
181
- fontStyle: 'normal'
180
+ font_weight: 'normal',
181
+ 'font-style': 'normal'
182
182
  },
183
183
  '@font-face$$2': {
184
- fontFamily: 'C64',
184
+ font_family: 'C64',
185
185
  src: 'url(fonts/C64_Pro_Mono-STYLE.woff)'
186
186
  },
187
187
  '@keyframes spin': {
@@ -191,7 +191,7 @@ const actual = c({
191
191
  div: {
192
192
  border: 'solid red 1px',
193
193
  '.c1': { 'background-color': '#000' },
194
- ' .c1': { backgroundColor: 'black' },
194
+ ' .c1': { background_color: 'black' },
195
195
  '.c2': { backgroundColor: 'rgb(0,0,0)' }
196
196
  },
197
197
  '@media(min-width:200px)': {
@@ -310,10 +310,10 @@ const expected = `
310
310
  expect(actual).to.deep.equal(expected)
311
311
  ```
312
312
 
313
- ### csvParse
313
+ ### csv_parse
314
314
 
315
315
  ```ts
316
- const csvParse: (csv: string, separator?: string) => Record<PropertyKey, string>[];
316
+ const csv_parse: (csv: string, separator?: string) => string[][];
317
317
  ```
318
318
 
319
319
  A tiny helper for parsing CSV.
@@ -329,38 +329,7 @@ yyy",zzz
329
329
  42 , "42" , 17
330
330
 
331
331
  `
332
-
333
- expect(csvParse(text)).to.deep.equal([{
334
- 'aaa\n"aaa"\naaa': 'xxx,xxx',
335
- bbb: 'yyy\nyyy',
336
- 'ccc,ccc': 'zzz'
337
- }, {
338
- 'aaa\n"aaa"\naaa': ' 42 ',
339
- bbb: '42',
340
- 'ccc,ccc': ' 17'
341
- }])
342
- ```
343
-
344
- ### csvParseRaw
345
-
346
- ```ts
347
- const csvParseRaw: (csv: string, separator?: string) => string[][];
348
- ```
349
-
350
- A tiny helper for parsing CSV.
351
-
352
- #### Usage Examples
353
-
354
- ```ts
355
- const text = `"aaa
356
- ""aaa""
357
- aaa",bbb, "ccc,ccc"
358
- "xxx,xxx", "yyy
359
- yyy",zzz
360
- 42 , "42" , 17
361
-
362
- `
363
- expect(csvParseRaw(text)).to.deep.equal([
332
+ expect(csv_parse(text)).to.deep.equal([
364
333
  ['aaa\n"aaa"\naaa', 'bbb', 'ccc,ccc'],
365
334
  ['xxx,xxx', 'yyy\nyyy', 'zzz'],
366
335
  [' 42 ', '42', ' 17']
@@ -370,24 +339,24 @@ expect(csvParseRaw(text)).to.deep.equal([
370
339
  ### escape
371
340
 
372
341
  ```ts
373
- const escape: (escapeMap: EscapeMap, template: TemplateStringsArray, ...values: unknown[]) => string;
342
+ const escape: (escape_map: Escape_Map, template: TemplateStringsArray, ...values: unknown[]) => string;
374
343
  ```
375
344
 
376
- A generic helper for escaping `values` by given `escapeMap` (in *TemplateStrings* flavor).
345
+ A generic helper for escaping `values` by given `escape_map` (in *TemplateStrings* flavor).
377
346
 
378
347
  #### Usage Examples
379
348
 
380
349
  ```ts
381
- const escapeMap: EscapeMap = new Map([
350
+ const escape_map: Escape_Map = new Map([
382
351
  [undefined, () => 'NULL'],
383
- [Array, (values: unknown[]) => escapeValues(escapeMap, values).join(', ')],
352
+ [Array, (values: unknown[]) => escape_values(escape_map, values).join(', ')],
384
353
  [Boolean, (value: boolean) => `b'${+value}'`],
385
354
  [Date, (value: Date) => `'${value.toISOString().replace(/^(.+)T(.+)\..*$/, '$1 $2')}'`],
386
355
  [Number, (value: number) => `${value}`],
387
356
  [String, (value: string) => `'${value.replace(/'/g, "''")}'`]
388
357
  ])
389
358
 
390
- const sql = escape.bind(null, escapeMap)
359
+ const sql = escape.bind(null, escape_map)
391
360
 
392
361
  const actual = sql`
393
362
  SELECT *
@@ -402,18 +371,18 @@ const expected = `
402
371
  expect(actual).to.deep.equal(expected)
403
372
  ```
404
373
 
405
- ### escapeValues
374
+ ### escape_values
406
375
 
407
376
  ```ts
408
- const escapeValues: (escapeMap: EscapeMap, values: unknown[]) => string[];
377
+ const escape_values: (escape_map: Escape_Map, values: unknown[]) => string[];
409
378
  ```
410
379
 
411
- A generic helper for escaping `values` by given `escapeMap`.
380
+ A generic helper for escaping `values` by given `escape_map`.
412
381
 
413
- ### fixTypography
382
+ ### fix_typography
414
383
 
415
384
  ```ts
416
- const fixTypography: (node: Node) => void;
385
+ const fix_typography: (node: Node) => void;
417
386
  ```
418
387
 
419
388
  A helper that implements typographic corrections specific to Polish typography.
@@ -423,7 +392,7 @@ A helper that implements typographic corrections specific to Polish typography.
423
392
  ```ts
424
393
  const p = h('p', 'Pchnąć w tę łódź jeża lub ośm skrzyń fig (zob. https://pl.wikipedia.org/wiki/Pangram).')
425
394
 
426
- fixTypography(p)
395
+ fix_typography(p)
427
396
 
428
397
  expect(p.innerHTML).to.deep.equal(
429
398
  'Pchnąć <span style="white-space:nowrap">w </span>tę łódź jeża lub ośm skrzyń fig ' +
@@ -434,9 +403,9 @@ expect(p.innerHTML).to.deep.equal(
434
403
 
435
404
  ```ts
436
405
  const h: {
437
- <T extends keyof HTMLElementTagNameMap>(tag: T, ...args1: HArgs1[]): HTMLElementTagNameMap[T];
438
- <N extends Node>(node: N, ...args1: HArgs1[]): N;
439
- (tagOrNode: string | Node, ...args1: HArgs1[]): Node;
406
+ <T extends keyof HTMLElementTagNameMap>(tag: T, ...args1: H_Args_1[]): HTMLElementTagNameMap[T];
407
+ <N extends Node>(node: N, ...args1: H_Args_1[]): N;
408
+ (tag_or_node: string | Node, ...args1: H_Args_1[]): Node;
440
409
  };
441
410
  ```
442
411
 
@@ -518,10 +487,10 @@ h(div, { $key: { two: 2 } })
518
487
  expect(div.key).to.deep.equal({ one: 1, two: 2 })
519
488
  ```
520
489
 
521
- ### hasOwn
490
+ ### has_own
522
491
 
523
492
  ```ts
524
- const hasOwn: (ref: unknown, key: unknown) => boolean;
493
+ const has_own: (ref: unknown, key: unknown) => boolean;
525
494
  ```
526
495
 
527
496
  A replacement for the `in` operator (not to be confused with the `for-in` loop) that works properly.
@@ -532,69 +501,82 @@ A replacement for the `in` operator (not to be confused with the `for-in` loop)
532
501
  const obj = { 42: null, null: 'k,e,y', 'k,e,y': 42 }
533
502
 
534
503
  expect(42 in obj).to.be.true
535
- expect(hasOwn(obj, 42)).to.be.true
504
+ expect(has_own(obj, 42)).to.be.true
536
505
 
537
506
  expect('42' in obj).to.be.true
538
- expect(hasOwn(obj, '42')).to.be.true
507
+ expect(has_own(obj, '42')).to.be.true
539
508
 
540
509
  expect('null' in obj).to.be.true
541
- expect(hasOwn(obj, 'null')).to.be.true
510
+ expect(has_own(obj, 'null')).to.be.true
542
511
 
543
512
  expect(null in obj).to.be.true
544
- expect(hasOwn(obj, null)).to.be.true
513
+ expect(has_own(obj, null)).to.be.true
545
514
 
546
515
  expect('k,e,y' in obj).to.be.true
547
- expect(hasOwn(obj, 'k,e,y')).to.be.true
516
+ expect(has_own(obj, 'k,e,y')).to.be.true
548
517
 
549
518
  expect(['k', 'e', 'y'] in obj).to.be.true
550
- expect(hasOwn(obj, ['k', 'e', 'y'])).to.be.true
519
+ expect(has_own(obj, ['k', 'e', 'y'])).to.be.true
551
520
 
552
521
  expect('toString' in obj).to.be.true
553
- expect(hasOwn(obj, 'toString')).to.be.false
522
+ expect(has_own(obj, 'toString')).to.be.false
554
523
 
555
524
  expect(() => 'key' in null).to.throw
556
- expect(hasOwn(null, 'key')).to.be.false
525
+ expect(has_own(null, 'key')).to.be.false
557
526
 
558
527
  expect(() => 'key' in undefined).to.throw
559
- expect(hasOwn(undefined, 'key')).to.be.false
528
+ expect(has_own(undefined, 'key')).to.be.false
560
529
  ```
561
530
 
562
- ### isArray
531
+ ### is_array
563
532
 
564
533
  ```ts
565
- const isArray: (arg: any) => arg is any[];
534
+ const is_array: (arg: any) => arg is any[];
535
+ declare const FINITE_NUMBER: unique symbol;
536
+ type Finite_Number = number & {
537
+ readonly [FINITE_NUMBER]: true;
538
+ };
566
539
  ```
567
540
 
568
541
  A helper that checks if the given argument is of type `any[]`.
569
542
 
570
- ### isNumber
543
+ ### is_finite_number
544
+
545
+ ```ts
546
+ const is_finite_number: ((arg: unknown) => arg is Finite_Number);
547
+ ```
548
+
549
+ A helper that checks if the given argument is of type `number` but not `±Infinity` nor `NaN`.
550
+
551
+ ### is_number
571
552
 
572
553
  ```ts
573
- const isNumber: (arg: any) => arg is number;
554
+ const is_number: (arg: unknown) => arg is number;
574
555
  ```
575
556
 
576
557
  A helper that checks if the given argument is of type `number`.
577
558
 
578
- ### isRecord
559
+ ### is_record
579
560
 
580
561
  ```ts
581
- const isRecord: (arg: any) => arg is Record<PropertyKey, unknown>;
562
+ const is_record: (arg: unknown) => arg is Record<PropertyKey, unknown>;
582
563
  ```
583
564
 
584
565
  A helper that checks if the given argument is of type `Record<PropertyKey, unknown>`.
585
566
 
586
- ### isString
567
+ ### is_string
587
568
 
588
569
  ```ts
589
- const isString: (arg: any) => arg is string;
570
+ const is_string: (arg: unknown) => arg is string;
571
+ export {};
590
572
  ```
591
573
 
592
574
  A helper that checks if the given argument is of type `string`.
593
575
 
594
- ### jsOnParse
576
+ ### js_on_parse
595
577
 
596
578
  ```ts
597
- const jsOnParse: (handlers: Record<PropertyKey, Function>, text: string) => any;
579
+ const js_on_parse: (handlers: Record<PropertyKey, Function>, text: string) => any;
598
580
  ```
599
581
 
600
582
  `JSON.parse` with “JavaScript turned on”.
@@ -602,13 +584,13 @@ const jsOnParse: (handlers: Record<PropertyKey, Function>, text: string) => any;
602
584
  Objects having *exactly* one property which is present in the `handlers` map, i.e. objects of the form:
603
585
 
604
586
  ```js
605
- { "«handlerName»": [«params»] }
587
+ { "«handler_name»": [«params»] }
606
588
  ```
607
589
 
608
590
  are replaced by the result of call
609
591
 
610
592
  ```js
611
- handlers['«handlerName»'](...«params»)
593
+ handlers['«handler_name»'](...«params»)
612
594
  ```
613
595
 
614
596
  #### Usage Examples
@@ -619,7 +601,7 @@ const handlers = {
619
601
  $foo: () => 'bar'
620
602
  }
621
603
 
622
- const actual = jsOnParse(handlers, `[
604
+ const actual = js_on_parse(handlers, `[
623
605
  {
624
606
  "$hello": ["World"]
625
607
  },
@@ -661,15 +643,15 @@ expect(actual).to.deep.equal(expected)
661
643
  ### nanolight
662
644
 
663
645
  ```ts
664
- const nanolight: (pattern: RegExp, highlighters: ((chunk: string, index: number) => HArgs1)[], code: string) => HArgs1[];
646
+ const nanolight: (pattern: RegExp, highlighters: ((chunk: string, index: number) => H_Args_1)[], code: string) => H_Args_1[];
665
647
  ```
666
648
 
667
- A generic helper for syntax highlighting (see also `nanolightJs`).
649
+ A generic helper for syntax highlighting (see also `nanolight_js`).
668
650
 
669
- ### nanolightJs
651
+ ### nanolight_js
670
652
 
671
653
  ```ts
672
- const nanolightJs: (code: string) => HArgs1[];
654
+ const nanolight_js: (code: string) => H_Args_1[];
673
655
  ```
674
656
 
675
657
  A helper for highlighting JavaScript (see also `nanolight`).
@@ -677,9 +659,9 @@ A helper for highlighting JavaScript (see also `nanolight`).
677
659
  #### Usage Examples
678
660
 
679
661
  ```ts
680
- const codeJs = 'const answerToLifeTheUniverseAndEverything = 42'
662
+ const code_js = 'const answerToLifeTheUniverseAndEverything = 42'
681
663
 
682
- expect(nanolightJs(codeJs)).to.deep.equal([
664
+ expect(nanolight_js(code_js)).to.deep.equal([
683
665
  ['span', { class: 'keyword' }, 'const'],
684
666
  ' ',
685
667
  ['span', { class: 'literal' }, 'answerToLifeTheUniverseAndEverything'],
@@ -722,10 +704,10 @@ const obj = { a: 42, b: '42', c: 17 }
722
704
  expect(pick(obj, ['a', 'b'])).to.deep.equal({ a: 42, b: '42' })
723
705
  ```
724
706
 
725
- ### plUral
707
+ ### pl_ural
726
708
 
727
709
  ```ts
728
- const plUral: (singular: string, plural2: string, plural5: string, value: number) => string;
710
+ const pl_ural: (singular: string, plural_2: string, plural_5: string, value: number) => string;
729
711
  ```
730
712
 
731
713
  A helper for choosing the correct singular and plural.
@@ -733,14 +715,14 @@ A helper for choosing the correct singular and plural.
733
715
  #### Usage Examples
734
716
 
735
717
  ```ts
736
- const auto = plUral.bind(null, 'auto', 'auta', 'aut')
718
+ const auto = pl_ural.bind(null, 'auto', 'auta', 'aut')
737
719
 
738
720
  expect(auto(0)).to.deep.equal('aut')
739
721
  expect(auto(1)).to.deep.equal('auto')
740
722
  expect(auto(17)).to.deep.equal('aut')
741
723
  expect(auto(42)).to.deep.equal('auta')
742
724
 
743
- const car = plUral.bind(null, 'car', 'cars', 'cars')
725
+ const car = pl_ural.bind(null, 'car', 'cars', 'cars')
744
726
 
745
727
  expect(car(0)).to.deep.equal('cars')
746
728
  expect(car(1)).to.deep.equal('car')
@@ -790,9 +772,9 @@ expect(ref).to.deep.equal({ one: { two: { three: { four: 1234 } } } })
790
772
 
791
773
  ```ts
792
774
  const s: {
793
- <T extends keyof SVGElementTagNameMap>(tag: T, ...args1: HArgs1[]): SVGElementTagNameMap[T];
794
- <N extends Node>(node: N, ...args1: HArgs1[]): N;
795
- (tagOrNode: string | Node, ...args1: HArgs1[]): Node;
775
+ <T extends keyof SVGElementTagNameMap>(tag: T, ...args1: H_Args_1[]): SVGElementTagNameMap[T];
776
+ <N extends Node>(node: N, ...args1: H_Args_1[]): N;
777
+ (tag_or_node: string | Node, ...args1: H_Args_1[]): Node;
796
778
  };
797
779
  ```
798
780
 
@@ -806,49 +788,24 @@ A lightweight [HyperScript](https://github.com/hyperhype/hyperscript)-style help
806
788
  - All other arguments of type `string`/`number` are converted to `Text` nodes and appended to the element being created or modified.
807
789
  - All other arguments of type `HArgs` are passed to `s` and the results are appended to the element being created or modified.
808
790
 
809
- ### svgUse
791
+ ### svg_use
810
792
 
811
793
  ```ts
812
- const svgUse: (id: string, ...args: HArgs1[]) => SVGSVGElement;
794
+ const svg_use: (id: string, ...args: H_Args_1[]) => SVGSVGElement;
813
795
  ```
814
796
 
815
797
  A convenient shortcut for `s('svg', ['use', { 'xlink:href': '#' + id }], ...args)`.
816
798
 
817
- ### uuid1
799
+ ### uuid_v1
818
800
 
819
801
  ```ts
820
- const uuid1: (date?: Date, node?: string) => string;
802
+ const uuid_v1: (date?: Date, node?: string) => string;
821
803
  ```
822
804
 
823
805
  A helper that generates a UUID v1 identifier (with a creation timestamp).
824
806
 
825
807
  - The optional `node` parameter should have the format `/^[0123456789abcdef]+$/`. Its value will be trimmed to last 12 characters and left padded with zeros.
826
808
 
827
- #### Usage Examples
828
-
829
- ```ts
830
- for (let i = 1; i <= 22136; ++i) {
831
- const uuid = uuid1()
832
-
833
- i === 1 && expect(uuid.split('-')[3]).to.deep.equal('8001')
834
- i === 4095 && expect(uuid.split('-')[3]).to.deep.equal('8fff')
835
- i === 4096 && expect(uuid.split('-')[3]).to.deep.equal('9000')
836
- i === 9029 && expect(uuid.split('-')[3]).to.deep.equal('a345')
837
- i === 13398 && expect(uuid.split('-')[3]).to.deep.equal('b456')
838
- i === 16384 && expect(uuid.split('-')[3]).to.deep.equal('8000')
839
- i === 17767 && expect(uuid.split('-')[3]).to.deep.equal('8567')
840
- }
841
- ```
842
-
843
- ```ts
844
- expect(uuid1(new Date(), '000123456789abc').split('-')[4]).to.deep.equal('123456789abc')
845
- expect(uuid1(new Date(), '123456789').split('-')[4]).to.deep.equal('000123456789')
846
- ```
847
-
848
- ```ts
849
- expect(uuid1(new Date(323325000000)).startsWith('c1399400-9a71-11bd')).to.be.true
850
- ```
851
-
852
809
  ## License
853
810
 
854
811
  The MIT License (MIT)