pronouny 0.4.0 → 1.0.0
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.
- package/README.md +228 -68
- package/lib/cjs/Pronoun.d.ts +55 -0
- package/lib/cjs/Pronoun.d.ts.map +1 -0
- package/lib/cjs/Pronoun.js +109 -0
- package/lib/cjs/Pronoun.js.map +1 -0
- package/lib/cjs/PronounSet.d.ts +70 -0
- package/lib/cjs/PronounSet.d.ts.map +1 -0
- package/lib/cjs/PronounSet.js +126 -0
- package/lib/cjs/PronounSet.js.map +1 -0
- package/lib/cjs/Pronouny.d.ts +91 -0
- package/lib/cjs/Pronouny.d.ts.map +1 -0
- package/lib/cjs/Pronouny.js +171 -0
- package/lib/cjs/Pronouny.js.map +1 -0
- package/lib/cjs/defaults.d.ts +13 -0
- package/lib/cjs/defaults.d.ts.map +1 -0
- package/lib/cjs/defaults.js +65 -0
- package/lib/cjs/defaults.js.map +1 -0
- package/lib/cjs/errors.d.ts +20 -0
- package/lib/cjs/errors.d.ts.map +1 -0
- package/lib/cjs/errors.js +29 -0
- package/lib/cjs/errors.js.map +1 -0
- package/lib/cjs/index.d.ts +24 -302
- package/lib/cjs/index.d.ts.map +1 -0
- package/lib/cjs/index.js +32 -542
- package/lib/cjs/index.js.map +1 -0
- package/lib/cjs/package.json +3 -0
- package/lib/cjs/template.d.ts +26 -0
- package/lib/cjs/template.d.ts.map +1 -0
- package/lib/cjs/template.js +46 -0
- package/lib/cjs/template.js.map +1 -0
- package/lib/cjs/types.d.ts +93 -0
- package/lib/cjs/types.d.ts.map +1 -0
- package/lib/cjs/types.js +48 -0
- package/lib/cjs/types.js.map +1 -0
- package/lib/cjs/utils.d.ts +24 -0
- package/lib/cjs/utils.d.ts.map +1 -0
- package/lib/cjs/utils.js +45 -0
- package/lib/cjs/utils.js.map +1 -0
- package/lib/esm/Pronoun.d.ts +55 -0
- package/lib/esm/Pronoun.d.ts.map +1 -0
- package/lib/esm/Pronoun.js +104 -0
- package/lib/esm/Pronoun.js.map +1 -0
- package/lib/esm/PronounSet.d.ts +70 -0
- package/lib/esm/PronounSet.d.ts.map +1 -0
- package/lib/esm/PronounSet.js +122 -0
- package/lib/esm/PronounSet.js.map +1 -0
- package/lib/esm/Pronouny.d.ts +91 -0
- package/lib/esm/Pronouny.d.ts.map +1 -0
- package/lib/esm/Pronouny.js +168 -0
- package/lib/esm/Pronouny.js.map +1 -0
- package/lib/esm/defaults.d.ts +13 -0
- package/lib/esm/defaults.d.ts.map +1 -0
- package/lib/esm/defaults.js +62 -0
- package/lib/esm/defaults.js.map +1 -0
- package/lib/esm/errors.d.ts +20 -0
- package/lib/esm/errors.d.ts.map +1 -0
- package/lib/esm/errors.js +25 -0
- package/lib/esm/errors.js.map +1 -0
- package/lib/esm/index.d.ts +24 -302
- package/lib/esm/index.d.ts.map +1 -0
- package/lib/esm/index.js +22 -540
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/package.json +3 -0
- package/lib/esm/template.d.ts +26 -0
- package/lib/esm/template.d.ts.map +1 -0
- package/lib/esm/template.js +43 -0
- package/lib/esm/template.js.map +1 -0
- package/lib/esm/types.d.ts +93 -0
- package/lib/esm/types.d.ts.map +1 -0
- package/lib/esm/types.js +44 -0
- package/lib/esm/types.js.map +1 -0
- package/lib/esm/utils.d.ts +24 -0
- package/lib/esm/utils.d.ts.map +1 -0
- package/lib/esm/utils.js +38 -0
- package/lib/esm/utils.js.map +1 -0
- package/package.json +19 -4
package/README.md
CHANGED
|
@@ -1,115 +1,275 @@
|
|
|
1
1
|
# Pronouny
|
|
2
2
|
|
|
3
|
-
**Pronouny** is a typed library
|
|
3
|
+
**Pronouny** is a small, typed library that makes programmatically resolving English pronouns easy. It ships as both ESM and CommonJS, has zero runtime dependencies, and is designed to be extended.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```sh
|
|
8
|
+
npm install pronouny
|
|
9
|
+
```
|
|
8
10
|
|
|
9
|
-
##
|
|
11
|
+
## Quick start
|
|
10
12
|
|
|
11
13
|
```ts
|
|
12
|
-
// Single import
|
|
13
14
|
import Pronouny from "pronouny";
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
const p = new Pronouny();
|
|
17
|
+
|
|
18
|
+
const vayne = {
|
|
19
|
+
username: "vaynegarden",
|
|
20
|
+
pronouns: p.set("she/they"),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
console.log(vayne.pronouns.parse`${vayne.username} updated ${"their"} status.`);
|
|
24
|
+
// "vaynegarden updated her status." or "...their status.", chosen
|
|
25
|
+
// consistently for the whole sentence.
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Concepts
|
|
29
|
+
|
|
30
|
+
Pronouny has three classes:
|
|
31
|
+
|
|
32
|
+
| Class | What it is |
|
|
33
|
+
| ---------------- | ------------------------------------------------------------------- |
|
|
34
|
+
| **`Pronouny`** | The resolver. Registers pronouns and turns strings into `Pronoun`s. |
|
|
35
|
+
| **`Pronoun`** | A single pronoun with all five grammatical forms. |
|
|
36
|
+
| **`PronounSet`** | An ordered set of `Pronoun`s for one entity (e.g. `she/they`). |
|
|
37
|
+
|
|
38
|
+
Every pronoun has five **forms**:
|
|
39
|
+
|
|
40
|
+
| Form | Example (`she`) | Aliases accepted on input |
|
|
41
|
+
| ---------------------- | --------------- | ------------------------- |
|
|
42
|
+
| `subject` | she | |
|
|
43
|
+
| `object` | her | |
|
|
44
|
+
| `possessive` | hers | |
|
|
45
|
+
| `possessiveDeterminer` | her | `possessiveAdjective` |
|
|
46
|
+
| `reflexive` | herself | `intensive` |
|
|
47
|
+
|
|
48
|
+
## Configuration
|
|
49
|
+
|
|
50
|
+
All configuration is optional. The defaults are shown below, and any
|
|
51
|
+
option can be overridden per call by passing a partial config as the
|
|
52
|
+
last argument to most methods.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
17
55
|
const p = new Pronouny({
|
|
18
|
-
//
|
|
56
|
+
// Recoverable errors resolve to a fallback instead of throwing.
|
|
19
57
|
failQuietly: true,
|
|
20
58
|
|
|
21
|
-
//
|
|
22
|
-
// pronoun to limit scope. Set to "true" to force
|
|
23
|
-
// recursive search.
|
|
59
|
+
// resolve() only matches ids/subject forms. Set true to match any form.
|
|
24
60
|
deepSearch: false,
|
|
25
61
|
|
|
26
|
-
//
|
|
27
|
-
// Set to false to force using 0 index.
|
|
62
|
+
// Pick forms/pronouns at random. Set false to always use the first.
|
|
28
63
|
useRandom: true,
|
|
29
64
|
|
|
30
|
-
//
|
|
65
|
+
// The id used whenever resolution fails quietly.
|
|
31
66
|
fallbackPronoun: "they",
|
|
32
67
|
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Pronouny ships with `he`, `she`, `they`, `it`, `you`, `we`, and `i`
|
|
71
|
+
registered by default.
|
|
72
|
+
|
|
73
|
+
## Usage
|
|
74
|
+
|
|
75
|
+
### Adding and removing pronouns
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
// Register a pronoun under a unique id. A form may be a single string
|
|
79
|
+
// or an array of accepted spellings.
|
|
80
|
+
const ze = p.add("ze", {
|
|
81
|
+
subject: "ze",
|
|
82
|
+
object: "hir",
|
|
83
|
+
possessive: "hirs",
|
|
84
|
+
possessiveDeterminer: "hir",
|
|
85
|
+
reflexive: "hirself",
|
|
86
|
+
});
|
|
33
87
|
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
false
|
|
44
|
-
);
|
|
88
|
+
// Because ids are explicit, two pronouns can share a subject form —
|
|
89
|
+
// e.g. a plural and a singular "they":
|
|
90
|
+
p.add("they-singular", {
|
|
91
|
+
subject: "they",
|
|
92
|
+
object: "them",
|
|
93
|
+
possessive: "theirs",
|
|
94
|
+
possessiveDeterminer: "their",
|
|
95
|
+
reflexive: "themself",
|
|
96
|
+
});
|
|
45
97
|
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
p.add(pronounZe);
|
|
98
|
+
// Remove a pronoun by id.
|
|
99
|
+
p.remove("it");
|
|
100
|
+
```
|
|
50
101
|
|
|
51
|
-
|
|
52
|
-
p.remove(p.resolve("I"));
|
|
53
|
-
// this deletes the "I" pronoun from the map.
|
|
102
|
+
### Resolving and identifying
|
|
54
103
|
|
|
55
|
-
|
|
56
|
-
p.
|
|
57
|
-
// ^Pronouny ^PronounSet ^Pronoun ^string
|
|
104
|
+
```ts
|
|
105
|
+
p.resolve("she").id; // "she"
|
|
58
106
|
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
107
|
+
// Shallow resolution (default) only matches ids and subject forms, so
|
|
108
|
+
// "him" falls back to "they":
|
|
109
|
+
p.resolve("him").id; // "they"
|
|
110
|
+
|
|
111
|
+
// Deep resolution matches any form:
|
|
112
|
+
p.resolve("him", { deepSearch: true }).id; // "he"
|
|
113
|
+
|
|
114
|
+
// identify() reports which form a word is, or undefined:
|
|
115
|
+
p.identify("her"); // "object"
|
|
116
|
+
p.identify("their"); // "possessiveDeterminer"
|
|
117
|
+
p.identify("banana"); // undefined
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Getting a specific form
|
|
121
|
+
|
|
122
|
+
Use `.as(form)` on a `Pronoun`, or on a `PronounSet` to pick one member
|
|
123
|
+
first.
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
const they = p.resolve("they");
|
|
127
|
+
they.as("subject"); // "they"
|
|
128
|
+
they.as("possessiveDeterminer"); // "their"
|
|
129
|
+
they.as("intensive"); // alias of "reflexive"
|
|
130
|
+
|
|
131
|
+
// A PronounSet picks a member (per config) then returns the form:
|
|
132
|
+
p.set("she/they").as("object"); // "her" or "them"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Template parsing
|
|
136
|
+
|
|
137
|
+
`parse` is a tagged-template helper. Interpolated pronoun words are
|
|
138
|
+
rewritten into the correct form and capitalisation is preserved;
|
|
139
|
+
everything else is left untouched.
|
|
140
|
+
|
|
141
|
+
On a `Pronoun`, every substitution uses that pronoun. On a `PronounSet`,
|
|
142
|
+
each substitution independently draws a pronoun from the set (per the
|
|
143
|
+
`useRandom` config), so a multi-pronoun set is distributed across the
|
|
144
|
+
string:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
const pronouns = p.set("she/they");
|
|
148
|
+
|
|
149
|
+
pronouns.parse`${"They"} lost ${"their"} keys — help ${"them"}!`;
|
|
150
|
+
// e.g. "She lost their keys — help them!" — each slot is drawn from the set.
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Set `useRandom: false` if you want every slot to use the first member of
|
|
154
|
+
the set instead.
|
|
155
|
+
|
|
156
|
+
## Error handling
|
|
157
|
+
|
|
158
|
+
When `failQuietly` is `false`, recoverable problems throw a typed
|
|
159
|
+
[`PnyError`](src/errors.ts) instead of falling back:
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import Pronouny, { PnyError } from "pronouny";
|
|
163
|
+
|
|
164
|
+
const strict = new Pronouny({ failQuietly: false });
|
|
165
|
+
|
|
166
|
+
try {
|
|
167
|
+
strict.resolve("notapronoun");
|
|
168
|
+
} catch (err) {
|
|
169
|
+
if (err instanceof PnyError) {
|
|
170
|
+
console.error(err.type); // "PronounResolutionError"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`PnyError` extends the native `Error`, so it works with normal
|
|
176
|
+
`try`/`catch` and `instanceof`.
|
|
177
|
+
|
|
178
|
+
## Extending the defaults
|
|
179
|
+
|
|
180
|
+
Pass your own pronoun map as the second constructor argument to replace
|
|
181
|
+
the built-ins entirely:
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
import Pronouny, { DEFAULT_PRONOUNS } from "pronouny";
|
|
65
185
|
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
186
|
+
// Start from the defaults and add to them.
|
|
187
|
+
const p = new Pronouny(
|
|
188
|
+
{},
|
|
189
|
+
{
|
|
190
|
+
...DEFAULT_PRONOUNS,
|
|
191
|
+
xe: {
|
|
192
|
+
subject: "xe",
|
|
193
|
+
object: "xem",
|
|
194
|
+
possessive: "xyrs",
|
|
195
|
+
possessiveDeterminer: "xyr",
|
|
196
|
+
reflexive: "xemself",
|
|
197
|
+
},
|
|
198
|
+
},
|
|
71
199
|
);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Development
|
|
203
|
+
|
|
204
|
+
```sh
|
|
205
|
+
npm install
|
|
206
|
+
npm test # run the Jest suite
|
|
207
|
+
npm run build # emit ESM + CJS + type declarations to lib/
|
|
75
208
|
```
|
|
76
209
|
|
|
77
210
|
## Changelog
|
|
78
211
|
|
|
212
|
+
### v1.0.0
|
|
213
|
+
|
|
214
|
+
- **Rewritten as a modular, multi-file package** with a proper dual
|
|
215
|
+
ESM/CJS build, type declarations, and an `exports` map.
|
|
216
|
+
- **Bug fixes:**
|
|
217
|
+
- Per-call config no longer mutates the shared instance config.
|
|
218
|
+
- Random selection and index bounds now reach the last element and
|
|
219
|
+
no longer read out of bounds.
|
|
220
|
+
- `deepSearch` now actually performs a deep search.
|
|
221
|
+
- `parse()` compares words case-insensitively, so capitalised
|
|
222
|
+
non-pronoun words are left alone.
|
|
223
|
+
- **Performance:** resolution and identification are backed by
|
|
224
|
+
hash-map indexes (O(1)) instead of linear scans.
|
|
225
|
+
- **Errors:** `PnyError` now extends the native `Error` and is only
|
|
226
|
+
thrown when `failQuietly` is disabled (no more unconditional
|
|
227
|
+
`console.error`).
|
|
228
|
+
- Pronouns are registered under explicit ids, so multiple pronouns can
|
|
229
|
+
share the same subject form.
|
|
230
|
+
- Added `it` to the default pronouns and `identify()`, `has()`,
|
|
231
|
+
`get()`, and `list()` to `Pronouny`.
|
|
232
|
+
|
|
233
|
+
### v0.5.0
|
|
234
|
+
|
|
235
|
+
- Added `parse()` method to `Pronoun` and `PronounSet` to allow for parsing of strings into their correct pronoun forms.
|
|
236
|
+
- Added optional `resolver` property to `Pronoun`s to allow retracing to related Pronouny instance.
|
|
237
|
+
- Added `identify()` method to `Pronouny` to allow for identification for type of pronouns.
|
|
238
|
+
|
|
79
239
|
### v0.4.0
|
|
80
240
|
|
|
81
|
-
-
|
|
82
|
-
-
|
|
83
|
-
-
|
|
241
|
+
- Optimized `forEach()` calls to use `for` loops instead.
|
|
242
|
+
- Added `fallbackPronoun` option to allow for configuration of pronoun to use in case of quiet failure states.
|
|
243
|
+
- Removed redundant `set` parameter from `[PronounSet].remove()` calls.
|
|
84
244
|
|
|
85
245
|
### v0.3.1
|
|
86
246
|
|
|
87
|
-
-
|
|
88
|
-
-
|
|
89
|
-
-
|
|
247
|
+
- Added documentation.
|
|
248
|
+
- Reordered `failQuietly` and `useRandom` on `Pronoun`.
|
|
249
|
+
- Tested and fixed examples.
|
|
90
250
|
|
|
91
251
|
### v0.3.0
|
|
92
252
|
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
253
|
+
- Rewritten to consolidate functionality into a single default export `Pronouny`.
|
|
254
|
+
- Includes "we", "you", and "I" pronouns by default.
|
|
255
|
+
- Added a config object so you can decide on error handling globally.
|
|
256
|
+
- All methods are now chainable for ease of use.
|
|
97
257
|
|
|
98
258
|
### v0.2.0
|
|
99
259
|
|
|
100
|
-
-
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
-
|
|
260
|
+
- Now fails silently when trying to resolve pronouns that don't exist or indexing out of bounds.
|
|
261
|
+
- Implementation of `PronounSet` class changed to Set from Array to prevent duplicate pronouns.
|
|
262
|
+
- added `get()` method to `PronounSet` class to retrieve a random Pronoun object.
|
|
263
|
+
- Added `add()` and `remove()` on `PronounSet`
|
|
104
264
|
|
|
105
265
|
### v0.1.2
|
|
106
266
|
|
|
107
|
-
-
|
|
267
|
+
- Initial release.
|
|
108
268
|
|
|
109
269
|
## TODO
|
|
110
270
|
|
|
111
|
-
-
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
115
|
-
-
|
|
271
|
+
- [x] Consolidate implementation into one general-use class.
|
|
272
|
+
- [x] Add global configuration for pronoun use.
|
|
273
|
+
- [x] Use more performant data structures. _(hash-map indexes for O(1) resolve/identify)_
|
|
274
|
+
- [x] Cleaner error handling. _(typed `PnyError extends Error`, thrown only when not failing quietly)_
|
|
275
|
+
- [x] Unique pronoun identifiers to allow for pronouns with the same first subject pronoun to have multiple forms. _(pronouns are keyed by explicit `id`)_
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The {@link Pronoun} class.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
import type Pronouny from "./Pronouny.js";
|
|
6
|
+
import { type PartialConfig, type PronounComponents, type PronounFormInput, type PronounInput } from "./types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Normalise a loose {@link PronounInput} into strict
|
|
9
|
+
* {@link PronounComponents}, accepting single strings or arrays and
|
|
10
|
+
* legacy alias keys. Throws a {@link PnyError} if any form is missing.
|
|
11
|
+
*/
|
|
12
|
+
export declare function normalizeComponents(id: string, input: PronounInput): PronounComponents;
|
|
13
|
+
/**
|
|
14
|
+
* # `Pronoun`
|
|
15
|
+
* A single pronoun with all five grammatical {@link PronounForm forms}.
|
|
16
|
+
* Each form may hold several accepted spellings.
|
|
17
|
+
*
|
|
18
|
+
* Create pronouns through {@link Pronouny.add} so they are registered
|
|
19
|
+
* for resolution, or construct one directly for standalone use.
|
|
20
|
+
*/
|
|
21
|
+
export declare class Pronoun {
|
|
22
|
+
/** Unique identifier within a {@link Pronouny} instance. */
|
|
23
|
+
readonly id: string;
|
|
24
|
+
/** The normalised forms of this pronoun. */
|
|
25
|
+
readonly components: PronounComponents;
|
|
26
|
+
/** The Pronouny instance this pronoun belongs to, if any. */
|
|
27
|
+
resolver?: Pronouny;
|
|
28
|
+
constructor(id: string, input: PronounInput, resolver?: Pronouny);
|
|
29
|
+
private get config();
|
|
30
|
+
/**
|
|
31
|
+
* Retrieve a single surface string for the requested grammatical
|
|
32
|
+
* form.
|
|
33
|
+
*
|
|
34
|
+
* @param form The form to retrieve. Accepts aliases such as
|
|
35
|
+
* `possessiveAdjective` and `intensive`. Defaults to
|
|
36
|
+
* `subject`.
|
|
37
|
+
* @param index Retrieve the `index`-th spelling of the form. When
|
|
38
|
+
* `-1` (default) a spelling is chosen according to the
|
|
39
|
+
* `useRandom` config.
|
|
40
|
+
* @param config Optional per-call config overrides.
|
|
41
|
+
*/
|
|
42
|
+
as(form?: PronounFormInput, index?: number, config?: PartialConfig): string;
|
|
43
|
+
/**
|
|
44
|
+
* Tagged-template helper. Interpolated pronoun words are rewritten
|
|
45
|
+
* to the matching form of *this* pronoun, preserving capitalisation.
|
|
46
|
+
* Non-pronoun values pass through unchanged.
|
|
47
|
+
*
|
|
48
|
+
* ```ts
|
|
49
|
+
* he.parse`${"They"} updated ${"their"} status.`;
|
|
50
|
+
* // "He updated his status."
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
parse(strings: TemplateStringsArray, ...values: unknown[]): string;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=Pronoun.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Pronoun.d.ts","sourceRoot":"","sources":["../../src/Pronoun.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAG1C,OAAO,EAIN,KAAK,aAAa,EAClB,KAAK,iBAAiB,EAEtB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,MAAM,YAAY,CAAC;AAGpB;;;;GAIG;AACH,wBAAgB,mBAAmB,CAClC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,YAAY,GACjB,iBAAiB,CAsCnB;AAED;;;;;;;GAOG;AACH,qBAAa,OAAO;IACnB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,4CAA4C;IAC5C,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IAEvC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,QAAQ,CAAC;gBAER,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,QAAQ;IAMhE,OAAO,KAAK,MAAM,GAEjB;IAED;;;;;;;;;;;OAWG;IACH,EAAE,CACD,IAAI,GAAE,gBAA4B,EAClC,KAAK,SAAK,EACV,MAAM,CAAC,EAAE,aAAa,GACpB,MAAM;IA4BT;;;;;;;;;OASG;IACH,KAAK,CACJ,OAAO,EAAE,oBAAoB,EAC7B,GAAG,MAAM,EAAE,OAAO,EAAE,GAClB,MAAM;CAKT"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The {@link Pronoun} class.
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.Pronoun = void 0;
|
|
8
|
+
exports.normalizeComponents = normalizeComponents;
|
|
9
|
+
const errors_js_1 = require("./errors.js");
|
|
10
|
+
const template_js_1 = require("./template.js");
|
|
11
|
+
const types_js_1 = require("./types.js");
|
|
12
|
+
const utils_js_1 = require("./utils.js");
|
|
13
|
+
/**
|
|
14
|
+
* Normalise a loose {@link PronounInput} into strict
|
|
15
|
+
* {@link PronounComponents}, accepting single strings or arrays and
|
|
16
|
+
* legacy alias keys. Throws a {@link PnyError} if any form is missing.
|
|
17
|
+
*/
|
|
18
|
+
function normalizeComponents(id, input) {
|
|
19
|
+
const source = input;
|
|
20
|
+
const pick = (...keys) => {
|
|
21
|
+
for (const key of keys) {
|
|
22
|
+
const value = source[key];
|
|
23
|
+
if (value !== undefined) {
|
|
24
|
+
return (0, utils_js_1.toArray)(value).map(String);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
};
|
|
29
|
+
const components = {
|
|
30
|
+
subject: pick("subject"),
|
|
31
|
+
object: pick("object"),
|
|
32
|
+
possessive: pick("possessive"),
|
|
33
|
+
possessiveDeterminer: pick("possessiveDeterminer", "possessiveAdjective", "psAdjective"),
|
|
34
|
+
reflexive: pick("reflexive", "intensive"),
|
|
35
|
+
};
|
|
36
|
+
for (const form of types_js_1.PRONOUN_FORMS) {
|
|
37
|
+
const value = components[form];
|
|
38
|
+
if (!value || value.length === 0) {
|
|
39
|
+
throw new errors_js_1.PnyError("PronounValidationError", `Pronoun "${id}" is missing a value for the "${form}" form.`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return components;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* # `Pronoun`
|
|
46
|
+
* A single pronoun with all five grammatical {@link PronounForm forms}.
|
|
47
|
+
* Each form may hold several accepted spellings.
|
|
48
|
+
*
|
|
49
|
+
* Create pronouns through {@link Pronouny.add} so they are registered
|
|
50
|
+
* for resolution, or construct one directly for standalone use.
|
|
51
|
+
*/
|
|
52
|
+
class Pronoun {
|
|
53
|
+
constructor(id, input, resolver) {
|
|
54
|
+
this.id = id;
|
|
55
|
+
this.components = normalizeComponents(id, input);
|
|
56
|
+
this.resolver = resolver;
|
|
57
|
+
}
|
|
58
|
+
get config() {
|
|
59
|
+
return this.resolver?.config ?? types_js_1.DEFAULT_CONFIG;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Retrieve a single surface string for the requested grammatical
|
|
63
|
+
* form.
|
|
64
|
+
*
|
|
65
|
+
* @param form The form to retrieve. Accepts aliases such as
|
|
66
|
+
* `possessiveAdjective` and `intensive`. Defaults to
|
|
67
|
+
* `subject`.
|
|
68
|
+
* @param index Retrieve the `index`-th spelling of the form. When
|
|
69
|
+
* `-1` (default) a spelling is chosen according to the
|
|
70
|
+
* `useRandom` config.
|
|
71
|
+
* @param config Optional per-call config overrides.
|
|
72
|
+
*/
|
|
73
|
+
as(form = "subject", index = -1, config) {
|
|
74
|
+
const cfg = (0, utils_js_1.mergeConfig)(this.config, config);
|
|
75
|
+
const canonical = (0, types_js_1.canonicalForm)(form);
|
|
76
|
+
const ctx = this.components[canonical];
|
|
77
|
+
if (!ctx || ctx.length === 0) {
|
|
78
|
+
if (cfg.failQuietly)
|
|
79
|
+
return "";
|
|
80
|
+
throw new errors_js_1.PnyError("PronounFormError", `Pronoun "${this.id}" has no "${canonical}" form.`);
|
|
81
|
+
}
|
|
82
|
+
if (index >= 0) {
|
|
83
|
+
if (index >= ctx.length) {
|
|
84
|
+
if (cfg.failQuietly)
|
|
85
|
+
return ctx[0];
|
|
86
|
+
throw new errors_js_1.PnyError("PronounIndexingError", `Index ${index} is out of range for the "${canonical}" form of "${this.id}" (length ${ctx.length}).`);
|
|
87
|
+
}
|
|
88
|
+
return ctx[index];
|
|
89
|
+
}
|
|
90
|
+
if (!cfg.useRandom)
|
|
91
|
+
return ctx[0];
|
|
92
|
+
return ctx[(0, utils_js_1.randomIndex)(ctx.length)];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Tagged-template helper. Interpolated pronoun words are rewritten
|
|
96
|
+
* to the matching form of *this* pronoun, preserving capitalisation.
|
|
97
|
+
* Non-pronoun values pass through unchanged.
|
|
98
|
+
*
|
|
99
|
+
* ```ts
|
|
100
|
+
* he.parse`${"They"} updated ${"their"} status.`;
|
|
101
|
+
* // "He updated his status."
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
parse(strings, ...values) {
|
|
105
|
+
return (0, template_js_1.renderTemplate)(this.resolver, strings, values, (form) => this.as(form));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
exports.Pronoun = Pronoun;
|
|
109
|
+
//# sourceMappingURL=Pronoun.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Pronoun.js","sourceRoot":"","sources":["../../src/Pronoun.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The {@link PronounSet} class.
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
import { Pronoun } from "./Pronoun.js";
|
|
6
|
+
import type Pronouny from "./Pronouny.js";
|
|
7
|
+
import type { PartialConfig, PronounFormInput } from "./types.js";
|
|
8
|
+
/** A pronoun, or a string that can be resolved to one. */
|
|
9
|
+
export type PronounLike = Pronoun | string;
|
|
10
|
+
/**
|
|
11
|
+
* # `PronounSet`
|
|
12
|
+
* An ordered, de-duplicated collection of {@link Pronoun}s representing
|
|
13
|
+
* how a single entity may be referred to (e.g. `she/they`).
|
|
14
|
+
*
|
|
15
|
+
* Create one with {@link Pronouny.set}. Call {@link PronounSet.use} to
|
|
16
|
+
* pick a pronoun, or {@link PronounSet.as} / {@link PronounSet.parse}
|
|
17
|
+
* to render a form directly.
|
|
18
|
+
*/
|
|
19
|
+
export declare class PronounSet {
|
|
20
|
+
/** The pronouns in this set, in insertion order. */
|
|
21
|
+
readonly pronouns: Set<Pronoun>;
|
|
22
|
+
/** The Pronouny instance that owns this set. */
|
|
23
|
+
readonly resolver: Pronouny;
|
|
24
|
+
constructor(resolver: Pronouny, pronouns?: Iterable<PronounLike> | PronounLike);
|
|
25
|
+
private resolveOne;
|
|
26
|
+
/**
|
|
27
|
+
* Add one or more pronouns to the set. Strings are resolved through
|
|
28
|
+
* the owning {@link Pronouny} instance. Chainable.
|
|
29
|
+
*/
|
|
30
|
+
add(pronoun: Iterable<PronounLike> | PronounLike): this;
|
|
31
|
+
/**
|
|
32
|
+
* Remove one or more pronouns from the set. Strings are resolved
|
|
33
|
+
* through the owning {@link Pronouny} instance. Chainable.
|
|
34
|
+
*/
|
|
35
|
+
remove(pronoun: Iterable<PronounLike> | PronounLike): this;
|
|
36
|
+
/** The number of pronouns in the set. */
|
|
37
|
+
get size(): number;
|
|
38
|
+
/** The pronouns as an array, in insertion order. */
|
|
39
|
+
list(): Pronoun[];
|
|
40
|
+
/**
|
|
41
|
+
* Pick a single {@link Pronoun} from the set.
|
|
42
|
+
*
|
|
43
|
+
* @param index Retrieve the `index`-th pronoun. When `-1` (default)
|
|
44
|
+
* a pronoun is chosen according to the `useRandom`
|
|
45
|
+
* config.
|
|
46
|
+
* @param config Optional per-call config overrides.
|
|
47
|
+
*/
|
|
48
|
+
use(index?: number, config?: PartialConfig): Pronoun;
|
|
49
|
+
/**
|
|
50
|
+
* Pick a pronoun from the set and return the requested grammatical
|
|
51
|
+
* form. Shorthand for `set.use(-1, config).as(form, -1, config)`.
|
|
52
|
+
*/
|
|
53
|
+
as(form?: PronounFormInput, config?: PartialConfig): string;
|
|
54
|
+
/**
|
|
55
|
+
* Tagged-template helper. Each interpolated pronoun word is resolved
|
|
56
|
+
* independently, drawing a fresh pronoun from the set (per the
|
|
57
|
+
* `useRandom` config) for every substitution — so a multi-pronoun
|
|
58
|
+
* set is distributed across the string rather than fixed to one
|
|
59
|
+
* member. Interpolated pronoun words are rewritten to the matching
|
|
60
|
+
* form (preserving capitalisation); other values pass through
|
|
61
|
+
* unchanged.
|
|
62
|
+
*
|
|
63
|
+
* ```ts
|
|
64
|
+
* pronouns.parse`${"They"} updated ${"their"} status.`;
|
|
65
|
+
* // e.g. "She updated their status."
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
parse(strings: TemplateStringsArray, ...values: unknown[]): string;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=PronounSet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PronounSet.d.ts","sourceRoot":"","sources":["../../src/PronounSet.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAG1C,OAAO,KAAK,EAAE,aAAa,EAAe,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG/E,0DAA0D;AAC1D,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AAE3C;;;;;;;;GAQG;AACH,qBAAa,UAAU;IACtB,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IAEhC,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBAG3B,QAAQ,EAAE,QAAQ,EAClB,QAAQ,GAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,WACjB;IAOlB,OAAO,CAAC,UAAU;IAMlB;;;OAGG;IACH,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,WAAW,GAAG,IAAI;IAWvD;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,WAAW,GAAG,IAAI;IAW1D,yCAAyC;IACzC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,oDAAoD;IACpD,IAAI,IAAI,OAAO,EAAE;IAIjB;;;;;;;OAOG;IACH,GAAG,CAAC,KAAK,SAAK,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO;IA6BhD;;;OAGG;IACH,EAAE,CAAC,IAAI,GAAE,gBAA4B,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,MAAM;IAItE;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM;CAQlE"}
|