@jackens/nnn 2026.4.15 → 2026.8.31

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 +52 -89
  2. package/nnn.js +81 -83
  3. package/package.json +1 -2
  4. package/readme.md +554 -591
package/nnn.d.ts CHANGED
@@ -49,6 +49,57 @@ export type CRoot = Record<PropertyKey, CNode>;
49
49
  * are not concatenated with child selectors.
50
50
  */
51
51
  export declare const c: (root: CRoot, splitter?: string) => string;
52
+ /**
53
+ * Creates a tag function
54
+ * for escaping interpolated values in template literals.
55
+ *
56
+ * @param escapeFn
57
+ *
58
+ * A function that takes a value
59
+ * and returns its escaped string representation.
60
+ *
61
+ * @returns
62
+ *
63
+ * A tag function that escapes interpolated values
64
+ * using the provided escape map.
65
+ */
66
+ export declare const createEscape: (escapeFn: (value: any) => string) => (template: TemplateStringsArray, ...values: unknown[]) => string;
67
+ /**
68
+ * A helper for building simple tokenizers
69
+ * (see also {@link nanolightTs}).
70
+ *
71
+ * @param decorator
72
+ *
73
+ * A function that wraps each matched chunk.
74
+ * It receives the matched text (`chunk`)
75
+ * and optionally the `metadata`
76
+ * associated with the pattern that produced the match.
77
+ * For unmatched text between patterns,
78
+ * `metadata` is `undefined`.
79
+ *
80
+ * @param specs
81
+ *
82
+ * An array of tuples `[metadata, pattern]` where:
83
+ * - `metadata`: arbitrary data (e.g., a CSS class name)
84
+ * passed to `decorator` when the pattern matches.
85
+ * - `pattern`: a `string` or `RegExp`
86
+ * to match against the input.
87
+ *
88
+ * @returns
89
+ *
90
+ * A tokenizer function that accepts a code string
91
+ * and returns an array of decorated tokens.
92
+ *
93
+ * @remarks
94
+ *
95
+ * 1. Matches starting at an earlier position
96
+ * take precedence.
97
+ * 2. Among matches at the same position,
98
+ * the longer one wins.
99
+ * 3. Among matches of the same position and length,
100
+ * the one defined earlier wins.
101
+ */
102
+ export declare const createTokenizer: <M, T>(decorator: (chunk: string, metadata?: M) => T, ...specs: [M, string | RegExp][]) => (code: string) => T[];
52
103
  /**
53
104
  * Parses a CSV string
54
105
  * into a two-dimensional array of strings.
@@ -315,7 +366,7 @@ export declare const jsOnParse: (handlers: Record<PropertyKey, Function>, text:
315
366
  export declare const monokai: CRoot;
316
367
  /**
317
368
  * A TypeScript/JavaScript syntax highlighting tokenizer
318
- * built using {@link newTokenizer}.
369
+ * built using {@link createTokenizer}.
319
370
  *
320
371
  * @param code
321
372
  *
@@ -327,94 +378,6 @@ export declare const monokai: CRoot;
327
378
  * suitable for rendering with {@link h}.
328
379
  */
329
380
  export declare const nanolightTs: (code: string) => HArgs1[];
330
- /**
331
- * Creates a tag function
332
- * for escaping interpolated values in template literals.
333
- *
334
- * @param escapeFn
335
- *
336
- * A function that takes a value
337
- * and returns its escaped string representation.
338
- *
339
- * @returns
340
- *
341
- * A tag function that escapes interpolated values
342
- * using the provided escape map.
343
- */
344
- export declare const newEscape: (escapeFn: (value: any) => string) => (template: TemplateStringsArray, ...values: unknown[]) => string;
345
- /**
346
- * Creates a function that
347
- * returns the appropriate noun form
348
- * based on a numeric value using `Intl.PluralRules`.
349
- *
350
- * Different languages have different plural rules.
351
- * The `Intl.PluralRules` API provides locale-aware
352
- * plural category selection.
353
- * Possible categories are:
354
- *
355
- * - `zero`: for zero items
356
- * (used in some languages like Arabic, Latvian)
357
- * - `one`: for singular (e.g., 1 item)
358
- * - `two`: for dual
359
- * (used in some languages like Arabic, Hebrew)
360
- * - `few`: for small plurals (e.g., 2-4 in Polish)
361
- * - `many`: for larger plurals (e.g., 5-21 in Polish)
362
- * - `other`: fallback category (used by all languages)
363
- *
364
- * @param locale
365
- *
366
- * A BCP 47 language tag (e.g., `pl`, `en`).
367
- *
368
- * @param forms
369
- *
370
- * An object mapping plural categories to noun forms.
371
- * Not all categories need to be provided;
372
- * if a category is missing,
373
- * the function falls back to `other`,
374
- * then to an empty string.
375
- *
376
- * @returns
377
- *
378
- * A function that takes a numeric value
379
- * and returns the appropriate noun form.
380
- */
381
- export declare const newNounForm: (locale: string, forms: Partial<Record<Intl.LDMLPluralRule, string>>) => (value: number) => string;
382
- /**
383
- * A helper for building simple tokenizers
384
- * (see also {@link nanolightTs}).
385
- *
386
- * @param decorator
387
- *
388
- * A function that wraps each matched chunk.
389
- * It receives the matched text (`chunk`)
390
- * and optionally the `metadata`
391
- * associated with the pattern that produced the match.
392
- * For unmatched text between patterns,
393
- * `metadata` is `undefined`.
394
- *
395
- * @param specs
396
- *
397
- * An array of tuples `[metadata, pattern]` where:
398
- * - `metadata`: arbitrary data (e.g., a CSS class name)
399
- * passed to `decorator` when the pattern matches.
400
- * - `pattern`: a `string` or `RegExp`
401
- * to match against the input.
402
- *
403
- * @returns
404
- *
405
- * A tokenizer function that accepts a code string
406
- * and returns an array of decorated tokens.
407
- *
408
- * @remarks
409
- *
410
- * 1. Matches starting at an earlier position
411
- * take precedence.
412
- * 2. Among matches at the same position,
413
- * the longer one wins.
414
- * 3. Among matches of the same position and length,
415
- * the one defined earlier wins.
416
- */
417
- export declare const newTokenizer: <M, T>(decorator: (chunk: string, metadata?: M) => T, ...specs: [M, string | RegExp][]) => (code: string) => T[];
418
381
  /**
419
382
  * Creates a new object excluding the specified keys
420
383
  * from the source object.
package/nnn.js CHANGED
@@ -6,6 +6,8 @@ var isString = (arg) => typeof arg === "string";
6
6
  var isRecord = (arg) => typeof arg === "object" && arg != null && !isArray(arg);
7
7
 
8
8
  // src/nnn/c.ts
9
+ var DEFAULT_SPLITTER = "$$";
10
+ var getName = (key, splitter = DEFAULT_SPLITTER) => key.split(splitter)[0].replace(/_/g, "-").replace(/([A-Z])/g, (_, letter) => "-" + letter.toLowerCase());
9
11
  var _c = (node, prefix, result, splitter) => {
10
12
  const queue = [[node, prefix]];
11
13
  while (queue.length > 0) {
@@ -18,19 +20,19 @@ var _c = (node, prefix, result, splitter) => {
18
20
  let attributesPushed = false;
19
21
  for (const key in style0) {
20
22
  const value = style0[key];
23
+ const name = getName(key, splitter);
21
24
  if (isString(value) || isNumber(value)) {
22
25
  if (!attributesPushed) {
23
26
  attributesPushed = true;
24
27
  attributes = [];
25
28
  todo.push([attributes, prefix0]);
26
29
  }
27
- const attribute = key.split(splitter)[0].replace(/_/g, "-").replace(/([A-Z])/g, (_, letter) => "-" + letter.toLowerCase());
28
- attributes.push(`${attribute}:${value}`);
30
+ attributes.push(`${name}:${value}`);
29
31
  } else if (value != null) {
30
32
  attributesPushed = false;
31
33
  const prefixN = [];
32
- const keyChunks = key.split(",");
33
- prefix0.split(",").forEach((prefixChunk) => keyChunks.forEach((keyChunk) => prefixN.push(prefixChunk + keyChunk)));
34
+ const nameChunks = name.split(",");
35
+ prefix0.split(",").forEach((prefixChunk) => nameChunks.forEach((nameChunk) => prefixN.push(prefixChunk + nameChunk)));
34
36
  todo.push([value, prefixN.join()]);
35
37
  }
36
38
  }
@@ -38,22 +40,63 @@ var _c = (node, prefix, result, splitter) => {
38
40
  }
39
41
  }
40
42
  };
41
- var c = (root, splitter = "$$") => {
43
+ var c = (root, splitter = DEFAULT_SPLITTER) => {
42
44
  const chunks = [];
43
45
  for (const key in root) {
44
46
  const value = root[key];
47
+ const name = getName(key, splitter);
45
48
  if (value != null) {
46
49
  if (key[0] === "@") {
47
- chunks.push(key.split(splitter)[0] + "{");
50
+ chunks.push(name + "{");
48
51
  _c(value, "", chunks, splitter);
49
52
  chunks.push("}");
50
53
  } else {
51
- _c(value, key.split(splitter)[0], chunks, splitter);
54
+ _c(value, name, chunks, splitter);
52
55
  }
53
56
  }
54
57
  }
55
58
  return chunks.join("");
56
59
  };
60
+ // src/nnn/createEscape.ts
61
+ var createEscape = (escapeFn) => (template, ...values) => String.raw(template, ...values.map(escapeFn));
62
+ // src/nnn/createTokenizer.ts
63
+ var createTokenizer = (decorator, ...specs) => (code) => {
64
+ const result = [];
65
+ while (code.length > 0) {
66
+ let bestMetadata;
67
+ let bestIndex = Infinity;
68
+ let bestChunk = "";
69
+ for (const [metadata, pattern] of specs) {
70
+ let index = -1;
71
+ let chunk = "";
72
+ if (isString(pattern) && pattern.length > 0) {
73
+ index = code.indexOf(pattern);
74
+ chunk = code.slice(index, index + pattern.length);
75
+ }
76
+ if (pattern instanceof RegExp) {
77
+ const match = code.match(pattern);
78
+ index = match?.index ?? -1;
79
+ chunk = match?.[0] ?? "";
80
+ }
81
+ if (index >= 0 && chunk.length > 0 && (index < bestIndex || index === bestIndex && chunk.length > bestChunk.length)) {
82
+ bestMetadata = metadata;
83
+ bestIndex = index;
84
+ bestChunk = chunk;
85
+ }
86
+ }
87
+ if (bestMetadata != null) {
88
+ if (bestIndex > 0) {
89
+ result.push(decorator(code.slice(0, bestIndex)));
90
+ }
91
+ result.push(decorator(bestChunk, bestMetadata));
92
+ code = code.slice(bestIndex + bestChunk.length);
93
+ } else {
94
+ result.push(decorator(code));
95
+ break;
96
+ }
97
+ }
98
+ return result;
99
+ };
57
100
  // src/nnn/csvParse.ts
58
101
  var MAIN_PATTERN = /\n|(?<!")("(?:[^"]|"")*")(?!")/g;
59
102
  var csvParse = (csv, separator = ",") => {
@@ -210,13 +253,13 @@ var monokai = {
210
253
  bg: { color: "var(--bg)" },
211
254
  fg: { color: "var(--fg)" },
212
255
  comment: { color: "var(--comment)" },
213
- "identifier-1": { color: "var(--identifier-1)" },
214
- "identifier-2": { color: "var(--identifier-2)" },
215
- "identifier-3": { color: "var(--identifier-3)" },
216
- "identifier-4": { color: "var(--identifier-4)" },
217
- "keyword-1": { color: "var(--keyword-1)" },
218
- "keyword-2": { color: "var(--keyword-2)" },
219
- "keyword-3": { color: "var(--keyword-3)" },
256
+ identifier_1: { color: "var(--identifier-1)" },
257
+ identifier_2: { color: "var(--identifier-2)" },
258
+ identifier_3: { color: "var(--identifier-3)" },
259
+ identifier_4: { color: "var(--identifier-4)" },
260
+ keyword_1: { color: "var(--keyword-1)" },
261
+ keyword_2: { color: "var(--keyword-2)" },
262
+ keyword_3: { color: "var(--keyword-3)" },
220
263
  number: { color: "var(--number)" },
221
264
  operator: { color: "var(--operator)" },
222
265
  punctuation: { color: "var(--punctuation)" },
@@ -241,45 +284,6 @@ var monokai = {
241
284
  }
242
285
  }
243
286
  };
244
- // src/nnn/newTokenizer.ts
245
- var newTokenizer = (decorator, ...specs) => (code) => {
246
- const result = [];
247
- while (code.length > 0) {
248
- let bestMetadata;
249
- let bestIndex = Infinity;
250
- let bestChunk = "";
251
- for (const [metadata, pattern] of specs) {
252
- let index = -1;
253
- let chunk = "";
254
- if (isString(pattern) && pattern.length > 0) {
255
- index = code.indexOf(pattern);
256
- chunk = code.slice(index, index + pattern.length);
257
- }
258
- if (pattern instanceof RegExp) {
259
- const match = code.match(pattern);
260
- index = match?.index ?? -1;
261
- chunk = match?.[0] ?? "";
262
- }
263
- if (index >= 0 && chunk.length > 0 && (index < bestIndex || index === bestIndex && chunk.length > bestChunk.length)) {
264
- bestMetadata = metadata;
265
- bestIndex = index;
266
- bestChunk = chunk;
267
- }
268
- }
269
- if (bestMetadata != null) {
270
- if (bestIndex > 0) {
271
- result.push(decorator(code.slice(0, bestIndex)));
272
- }
273
- result.push(decorator(bestChunk, bestMetadata));
274
- code = code.slice(bestIndex + bestChunk.length);
275
- } else {
276
- result.push(decorator(code));
277
- break;
278
- }
279
- }
280
- return result;
281
- };
282
-
283
287
  // src/nnn/nanolightTs.ts
284
288
  var COMMENT = "comment";
285
289
  var IDENTIFIER_1 = "identifier-1";
@@ -293,12 +297,7 @@ var NUMBER = "number";
293
297
  var OPERATOR = "operator";
294
298
  var PUNCTUATION = "punctuation";
295
299
  var STRING = "string";
296
- var nanolightTs = /* @__PURE__ */ newTokenizer((chunk, name) => name != null ? ["span", { class: name }, chunk] : chunk, [COMMENT, /\/\*.*?\*\//s], [COMMENT, /(?<!\\)\/\/.*?(?=\n)/], [STRING, /".*?"/], [STRING, /'.*?'/], [STRING, /`.*?`/s], [STRING, /\/[^\s]*[^\\]\/[dgimsuvy]*/], [NUMBER, /0b[01_]+/], [NUMBER, /0o[01234567_]+/], [NUMBER, /0x[\dabcdef_]+/], [NUMBER, /\d[\d_]*(\.[\d_]+)?(e[+-]?[\d_]+)?/], [OPERATOR, "!"], [OPERATOR, "!="], [OPERATOR, "!=="], [OPERATOR, "%"], [OPERATOR, "%="], [OPERATOR, "&&"], [OPERATOR, "&&="], [OPERATOR, "&"], [OPERATOR, "&="], [OPERATOR, "*"], [OPERATOR, "**"], [OPERATOR, "**="], [OPERATOR, "*="], [OPERATOR, "+"], [OPERATOR, "++"], [OPERATOR, "+="], [OPERATOR, "-"], [OPERATOR, "--"], [OPERATOR, "-="], [OPERATOR, "..."], [OPERATOR, "/"], [OPERATOR, "/="], [OPERATOR, ":"], [OPERATOR, "<"], [OPERATOR, "<<"], [OPERATOR, "<<="], [OPERATOR, "<="], [OPERATOR, "="], [OPERATOR, "=="], [OPERATOR, "==="], [OPERATOR, "=>"], [OPERATOR, ">"], [OPERATOR, ">="], [OPERATOR, ">>"], [OPERATOR, ">>="], [OPERATOR, ">>>"], [OPERATOR, ">>>="], [OPERATOR, "?"], [OPERATOR, "?"], [OPERATOR, "??"], [OPERATOR, "??="], [OPERATOR, "^"], [OPERATOR, "^="], [OPERATOR, "|"], [OPERATOR, "|="], [OPERATOR, "||"], [OPERATOR, "||="], [OPERATOR, "~"], [OPERATOR, "~="], [OPERATOR, /(?<=\s):/], [PUNCTUATION, "("], [PUNCTUATION, ")"], [PUNCTUATION, ","], [PUNCTUATION, "."], [PUNCTUATION, ":"], [PUNCTUATION, ";"], [PUNCTUATION, "?."], [PUNCTUATION, "["], [PUNCTUATION, "]"], [PUNCTUATION, "{"], [PUNCTUATION, "}"], [KEYWORD_1, "as"], [KEYWORD_1, "async"], [KEYWORD_1, "await"], [KEYWORD_1, "break"], [KEYWORD_1, "case"], [KEYWORD_1, "catch"], [KEYWORD_1, "class"], [KEYWORD_1, "const"], [KEYWORD_1, "continue"], [KEYWORD_1, "debugger"], [KEYWORD_1, "default"], [KEYWORD_1, "delete"], [KEYWORD_1, "do"], [KEYWORD_1, "else"], [KEYWORD_1, "export"], [KEYWORD_1, "extends"], [KEYWORD_1, "finally"], [KEYWORD_1, "for"], [KEYWORD_1, "from"], [KEYWORD_1, "function"], [KEYWORD_1, "function*"], [KEYWORD_1, "goto"], [KEYWORD_1, "if"], [KEYWORD_1, "import"], [KEYWORD_1, "in"], [KEYWORD_1, "instanceof"], [KEYWORD_1, "is"], [KEYWORD_1, "keyof"], [KEYWORD_1, "let"], [KEYWORD_1, "new"], [KEYWORD_1, "of"], [KEYWORD_1, "package"], [KEYWORD_1, "return"], [KEYWORD_1, "super"], [KEYWORD_1, "switch"], [KEYWORD_1, "this"], [KEYWORD_1, "throw"], [KEYWORD_1, "try"], [KEYWORD_1, "type"], [KEYWORD_1, "typeof"], [KEYWORD_1, "var"], [KEYWORD_1, "void"], [KEYWORD_1, "while"], [KEYWORD_1, "with"], [KEYWORD_1, "yield"], [KEYWORD_1, "yield*"], [KEYWORD_2, "false"], [KEYWORD_2, "Infinity"], [KEYWORD_2, "NaN"], [KEYWORD_2, "null"], [KEYWORD_2, "true"], [KEYWORD_2, "undefined"], [KEYWORD_3, "any"], [KEYWORD_3, "bigint"], [KEYWORD_3, "boolean"], [KEYWORD_3, "eval"], [KEYWORD_3, "number"], [KEYWORD_3, "string"], [KEYWORD_3, "symbol"], [KEYWORD_3, "unknown"], [IDENTIFIER_1, /[\p{Lu}_$][\p{Lu}\d_$]*/u], [IDENTIFIER_2, /[\p{L}_$][\p{L}\d_$]*(?=[(`])/u], [IDENTIFIER_3, /\p{Lu}[\p{L}\d_$]*/u], [IDENTIFIER_4, /[\p{L}_$][\p{L}\d_$]*/u]);
297
- // src/nnn/newEscape.ts
298
- var newEscape = (escapeFn) => (template, ...values) => String.raw(template, ...values.map(escapeFn));
299
- // src/nnn/newNounForm.ts
300
- var PLURAL_RULES = {};
301
- var newNounForm = (locale, forms) => (value) => forms[(PLURAL_RULES[locale] ??= new Intl.PluralRules(locale)).select(value)] ?? forms.other ?? "";
300
+ var nanolightTs = /* @__PURE__ */ createTokenizer((chunk, name) => name != null ? ["span", { class: name }, chunk] : chunk, [COMMENT, /\/\*.*?\*\//s], [COMMENT, /(?<!\\)\/\/.*?(?=\n)/], [STRING, /".*?"/], [STRING, /'.*?'/], [STRING, /`.*?`/s], [STRING, /\/[^\s]*[^\\]\/[dgimsuvy]*/], [NUMBER, /0b[01_]+/], [NUMBER, /0o[01234567_]+/], [NUMBER, /0x[\dabcdef_]+/], [NUMBER, /\d[\d_]*(\.[\d_]+)?(e[+-]?[\d_]+)?/], [OPERATOR, "!"], [OPERATOR, "!="], [OPERATOR, "!=="], [OPERATOR, "%"], [OPERATOR, "%="], [OPERATOR, "&&"], [OPERATOR, "&&="], [OPERATOR, "&"], [OPERATOR, "&="], [OPERATOR, "*"], [OPERATOR, "**"], [OPERATOR, "**="], [OPERATOR, "*="], [OPERATOR, "+"], [OPERATOR, "++"], [OPERATOR, "+="], [OPERATOR, "-"], [OPERATOR, "--"], [OPERATOR, "-="], [OPERATOR, "..."], [OPERATOR, "/"], [OPERATOR, "/="], [OPERATOR, ":"], [OPERATOR, "<"], [OPERATOR, "<<"], [OPERATOR, "<<="], [OPERATOR, "<="], [OPERATOR, "="], [OPERATOR, "=="], [OPERATOR, "==="], [OPERATOR, "=>"], [OPERATOR, ">"], [OPERATOR, ">="], [OPERATOR, ">>"], [OPERATOR, ">>="], [OPERATOR, ">>>"], [OPERATOR, ">>>="], [OPERATOR, "?"], [OPERATOR, "?"], [OPERATOR, "??"], [OPERATOR, "??="], [OPERATOR, "^"], [OPERATOR, "^="], [OPERATOR, "|"], [OPERATOR, "|="], [OPERATOR, "||"], [OPERATOR, "||="], [OPERATOR, "~"], [OPERATOR, "~="], [OPERATOR, /(?<=\s):/], [PUNCTUATION, "("], [PUNCTUATION, ")"], [PUNCTUATION, ","], [PUNCTUATION, "."], [PUNCTUATION, ":"], [PUNCTUATION, ";"], [PUNCTUATION, "?."], [PUNCTUATION, "["], [PUNCTUATION, "]"], [PUNCTUATION, "{"], [PUNCTUATION, "}"], [KEYWORD_1, "as"], [KEYWORD_1, "async"], [KEYWORD_1, "await"], [KEYWORD_1, "break"], [KEYWORD_1, "case"], [KEYWORD_1, "catch"], [KEYWORD_1, "class"], [KEYWORD_1, "const"], [KEYWORD_1, "continue"], [KEYWORD_1, "debugger"], [KEYWORD_1, "default"], [KEYWORD_1, "delete"], [KEYWORD_1, "do"], [KEYWORD_1, "else"], [KEYWORD_1, "export"], [KEYWORD_1, "extends"], [KEYWORD_1, "finally"], [KEYWORD_1, "for"], [KEYWORD_1, "from"], [KEYWORD_1, "function"], [KEYWORD_1, "function*"], [KEYWORD_1, "goto"], [KEYWORD_1, "if"], [KEYWORD_1, "import"], [KEYWORD_1, "in"], [KEYWORD_1, "instanceof"], [KEYWORD_1, "is"], [KEYWORD_1, "keyof"], [KEYWORD_1, "let"], [KEYWORD_1, "new"], [KEYWORD_1, "of"], [KEYWORD_1, "package"], [KEYWORD_1, "return"], [KEYWORD_1, "super"], [KEYWORD_1, "switch"], [KEYWORD_1, "this"], [KEYWORD_1, "throw"], [KEYWORD_1, "try"], [KEYWORD_1, "type"], [KEYWORD_1, "typeof"], [KEYWORD_1, "var"], [KEYWORD_1, "void"], [KEYWORD_1, "while"], [KEYWORD_1, "with"], [KEYWORD_1, "yield"], [KEYWORD_1, "yield*"], [KEYWORD_2, "false"], [KEYWORD_2, "Infinity"], [KEYWORD_2, "NaN"], [KEYWORD_2, "null"], [KEYWORD_2, "true"], [KEYWORD_2, "undefined"], [KEYWORD_3, "any"], [KEYWORD_3, "bigint"], [KEYWORD_3, "boolean"], [KEYWORD_3, "eval"], [KEYWORD_3, "number"], [KEYWORD_3, "string"], [KEYWORD_3, "symbol"], [KEYWORD_3, "unknown"], [IDENTIFIER_1, /[\p{Lu}_$][\p{Lu}\d_$]*/u], [IDENTIFIER_2, /[\p{L}_$][\p{L}\d_$]*(?=[(`])/u], [IDENTIFIER_3, /\p{Lu}[\p{L}\d_$]*/u], [IDENTIFIER_4, /[\p{L}_$][\p{L}\d_$]*/u]);
302
301
  // src/nnn/omit.ts
303
302
  var omit = (ref, keys) => Object.fromEntries(Object.entries(ref).filter(([key]) => !keys.includes(key)));
304
303
  // src/nnn/pick.ts
@@ -313,8 +312,8 @@ var rwd = (root, selector, cellWidthPx, cellHeightPx, ...specs) => {
313
312
  main.height = `${cellHeightPx}px`;
314
313
  specs.sort(([a], [b]) => a - b);
315
314
  for (let [maxWidth, width, height] of specs) {
316
- const mediaSelector = `@media(min-width:${cellWidthPx * maxWidth}px)`;
317
- const node = maxWidth === 1 ? main : (root[mediaSelector] ??= {})[selector] ??= {};
315
+ const atRule = `@media(min-width:${cellWidthPx * maxWidth}px)`;
316
+ const node = maxWidth === 1 ? main : (root[atRule] ??= {})[selector] ??= {};
318
317
  width ??= 1;
319
318
  height ??= 1;
320
319
  let gcd = 100 * width;
@@ -357,27 +356,26 @@ var _vivify = (parent, parentKey) => new Proxy(parent, {
357
356
  });
358
357
  var vivify = (ref) => _vivify({ _: ref }, "_");
359
358
  export {
360
- vivify,
361
- uuidV1,
362
- svgUse,
363
- s,
364
- rwd,
365
- pick,
366
- omit,
367
- newTokenizer,
368
- newNounForm,
369
- newEscape,
370
- nanolightTs,
371
- monokai,
372
- jsOnParse,
373
- isString,
374
- isRecord,
375
- isNumber,
376
- isFiniteNumber,
377
- isArray,
378
- hasOwn,
379
- h,
380
- fixPlTypography,
359
+ c,
360
+ createEscape,
361
+ createTokenizer,
381
362
  csvParse,
382
- c
363
+ fixPlTypography,
364
+ h,
365
+ hasOwn,
366
+ isArray,
367
+ isFiniteNumber,
368
+ isNumber,
369
+ isRecord,
370
+ isString,
371
+ jsOnParse,
372
+ monokai,
373
+ nanolightTs,
374
+ omit,
375
+ pick,
376
+ rwd,
377
+ s,
378
+ svgUse,
379
+ uuidV1,
380
+ vivify
383
381
  };
package/package.json CHANGED
@@ -25,7 +25,6 @@
25
25
  "Monokai",
26
26
  "nanolight",
27
27
  "nnn",
28
- "noun form",
29
28
  "omit",
30
29
  "pick",
31
30
  "Responsive Web Design",
@@ -44,5 +43,5 @@
44
43
  "name": "@jackens/nnn",
45
44
  "type": "module",
46
45
  "types": "nnn.d.ts",
47
- "version": "2026.4.15"
46
+ "version": "2026.8.31"
48
47
  }