@jackens/nnn 2026.8.24 → 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 +0 -37
  2. package/nnn.js +10 -11
  3. package/package.json +1 -2
  4. package/readme.md +1 -79
package/nnn.d.ts CHANGED
@@ -64,43 +64,6 @@ export declare const c: (root: CRoot, splitter?: string) => string;
64
64
  * using the provided escape map.
65
65
  */
66
66
  export declare const createEscape: (escapeFn: (value: any) => string) => (template: TemplateStringsArray, ...values: unknown[]) => string;
67
- /**
68
- * Creates a function that
69
- * returns the appropriate noun form
70
- * based on a numeric value using `Intl.PluralRules`.
71
- *
72
- * Different languages have different plural rules.
73
- * The `Intl.PluralRules` API provides locale-aware
74
- * plural category selection.
75
- * Possible categories are:
76
- *
77
- * - `zero`: for zero items
78
- * (used in some languages like Arabic, Latvian)
79
- * - `one`: for singular (e.g., 1 item)
80
- * - `two`: for dual
81
- * (used in some languages like Arabic, Hebrew)
82
- * - `few`: for small plurals (e.g., 2-4 in Polish)
83
- * - `many`: for larger plurals (e.g., 5-21 in Polish)
84
- * - `other`: fallback category (used by all languages)
85
- *
86
- * @param locale
87
- *
88
- * A BCP 47 language tag (e.g., `pl`, `en`).
89
- *
90
- * @param forms
91
- *
92
- * An object mapping plural categories to noun forms.
93
- * Not all categories need to be provided;
94
- * if a category is missing,
95
- * the function falls back to `other`,
96
- * then to an empty string.
97
- *
98
- * @returns
99
- *
100
- * A function that takes a numeric value
101
- * and returns the appropriate noun form.
102
- */
103
- export declare const createPluralRules: (locale: string, forms: Partial<Record<Intl.LDMLPluralRule, string>>) => (value: number) => string;
104
67
  /**
105
68
  * A helper for building simple tokenizers
106
69
  * (see also {@link nanolightTs}).
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,17 +40,18 @@ 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
  }
@@ -56,9 +59,6 @@ var c = (root, splitter = "$$") => {
56
59
  };
57
60
  // src/nnn/createEscape.ts
58
61
  var createEscape = (escapeFn) => (template, ...values) => String.raw(template, ...values.map(escapeFn));
59
- // src/nnn/createPluralRules.ts
60
- var PLURAL_RULES = {};
61
- var createPluralRules = (locale, forms) => (value) => forms[(PLURAL_RULES[locale] ??= new Intl.PluralRules(locale)).select(value)] ?? forms.other ?? "";
62
62
  // src/nnn/createTokenizer.ts
63
63
  var createTokenizer = (decorator, ...specs) => (code) => {
64
64
  const result = [];
@@ -358,7 +358,6 @@ var vivify = (ref) => _vivify({ _: ref }, "_");
358
358
  export {
359
359
  c,
360
360
  createEscape,
361
- createPluralRules as createNounForm,
362
361
  createTokenizer,
363
362
  csvParse,
364
363
  fixPlTypography,
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.8.24"
46
+ "version": "2026.8.31"
48
47
  }
package/readme.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # nnn
2
2
 
3
- A collection of Jackens’ JavaScript helper utilities (version: `2026.8.24`).
3
+ A collection of Jackens’ JavaScript helper utilities (version: `2026.8.31`).
4
4
 
5
5
  ## Installation
6
6
 
@@ -20,7 +20,6 @@ npm i @jackens/nnn
20
20
  import {
21
21
  c,
22
22
  createEscape,
23
- createPluralRules,
24
23
  createTokenizer,
25
24
  csvParse,
26
25
  fixPlTypography,
@@ -64,10 +63,6 @@ import {
64
63
  - [`createEscape`](#createEscape):
65
64
  Creates a tag function
66
65
  for escaping interpolated values in template literals.
67
- - [`createPluralRules`](#createPluralRules):
68
- Creates a function that
69
- returns the appropriate noun form
70
- based on a numeric value using `Intl.PluralRules`.
71
66
  - [`createTokenizer`](#createTokenizer):
72
67
  A helper for building simple tokenizers
73
68
  (see also [`nanolightTs`](#nanolightTs)).
@@ -466,79 +461,6 @@ const expected = `
466
461
  expect(actual).to.equal(expected)
467
462
  ```
468
463
 
469
- ### createPluralRules
470
-
471
- ```ts
472
- const createPluralRules: (locale: string, forms: Partial<Record<Intl.LDMLPluralRule, string>>) => (value: number) => string;
473
- ```
474
-
475
- Creates a function that
476
- returns the appropriate noun form
477
- based on a numeric value using `Intl.PluralRules`.
478
-
479
- Different languages have different plural rules.
480
- The `Intl.PluralRules` API provides locale-aware
481
- plural category selection.
482
- Possible categories are:
483
-
484
- - `zero`: for zero items
485
- (used in some languages like Arabic, Latvian)
486
- - `one`: for singular (e.g., 1 item)
487
- - `two`: for dual
488
- (used in some languages like Arabic, Hebrew)
489
- - `few`: for small plurals (e.g., 2-4 in Polish)
490
- - `many`: for larger plurals (e.g., 5-21 in Polish)
491
- - `other`: fallback category (used by all languages)
492
-
493
- #### locale
494
-
495
- A BCP 47 language tag (e.g., `pl`, `en`).
496
-
497
- #### forms
498
-
499
- An object mapping plural categories to noun forms.
500
- Not all categories need to be provided;
501
- if a category is missing,
502
- the function falls back to `other`,
503
- then to an empty string.
504
-
505
- #### Returns
506
-
507
- A function that takes a numeric value
508
- and returns the appropriate noun form.
509
-
510
- #### Usage Examples
511
-
512
- ```ts
513
- const auto = createPluralRules('pl', {
514
- one: 'auto',
515
- few: 'auta',
516
- other: 'aut',
517
- })
518
-
519
- expect(auto(0)).to.equal('aut')
520
- expect(auto(1)).to.equal('auto')
521
- expect(auto(17)).to.equal('aut')
522
- expect(auto(42)).to.equal('auta')
523
-
524
- const car = createPluralRules('en', {
525
- one: 'car',
526
- other: 'cars',
527
- })
528
-
529
- expect(car(0)).to.equal('cars')
530
- expect(car(1)).to.equal('car')
531
- expect(car(17)).to.equal('cars')
532
- expect(car(42)).to.equal('cars')
533
-
534
- const empty = createPluralRules('en', {})
535
-
536
- expect(empty(0)).to.equal('')
537
- expect(empty(1)).to.equal('')
538
- expect(empty(17)).to.equal('')
539
- expect(empty(42)).to.equal('')
540
- ```
541
-
542
464
  ### createTokenizer
543
465
 
544
466
  ```ts