@openpronoun/core 0.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 +5 -0
- package/dist/index.cjs +539 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +503 -0
- package/dist/index.js.map +1 -0
- package/package.json +55 -0
package/README.md
ADDED
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
FILLER_PATTERNS: () => FILLER_PATTERNS,
|
|
24
|
+
FORM_TO_SET: () => FORM_TO_SET,
|
|
25
|
+
PLACEHOLDER_STRINGS: () => PLACEHOLDER_STRINGS,
|
|
26
|
+
PRONOUN_DICTIONARY: () => PRONOUN_DICTIONARY,
|
|
27
|
+
SPECIAL_KEYWORDS: () => SPECIAL_KEYWORDS,
|
|
28
|
+
SPECIAL_TYPES: () => import_zod.SPECIAL_TYPES,
|
|
29
|
+
customEntrySchema: () => import_zod.customEntrySchema,
|
|
30
|
+
filterByAudience: () => filterByAudience,
|
|
31
|
+
format: () => format,
|
|
32
|
+
parse: () => parse,
|
|
33
|
+
pronounEntrySchema: () => import_zod.pronounEntrySchema,
|
|
34
|
+
pronounPreferenceSchema: () => import_zod.pronounPreferenceSchema,
|
|
35
|
+
pronounSetSchema: () => import_zod.pronounSetSchema,
|
|
36
|
+
specialPreferenceSchema: () => import_zod.specialPreferenceSchema,
|
|
37
|
+
validate: () => validate,
|
|
38
|
+
validateOrThrow: () => validateOrThrow,
|
|
39
|
+
validationErrors: () => validationErrors
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(index_exports);
|
|
42
|
+
|
|
43
|
+
// src/constants.ts
|
|
44
|
+
var PRONOUN_DICTIONARY = [
|
|
45
|
+
// Common sets
|
|
46
|
+
{
|
|
47
|
+
subjective: "she",
|
|
48
|
+
objective: "her",
|
|
49
|
+
possessive_adjective: "her",
|
|
50
|
+
possessive_pronoun: "hers",
|
|
51
|
+
reflexive: "herself"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
subjective: "he",
|
|
55
|
+
objective: "him",
|
|
56
|
+
possessive_adjective: "his",
|
|
57
|
+
possessive_pronoun: "his",
|
|
58
|
+
reflexive: "himself"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
subjective: "they",
|
|
62
|
+
objective: "them",
|
|
63
|
+
possessive_adjective: "their",
|
|
64
|
+
possessive_pronoun: "theirs",
|
|
65
|
+
reflexive: "themselves"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
subjective: "it",
|
|
69
|
+
objective: "it",
|
|
70
|
+
possessive_adjective: "its",
|
|
71
|
+
possessive_pronoun: "its",
|
|
72
|
+
reflexive: "itself"
|
|
73
|
+
},
|
|
74
|
+
// Neopronouns
|
|
75
|
+
{
|
|
76
|
+
subjective: "xe",
|
|
77
|
+
objective: "xem",
|
|
78
|
+
possessive_adjective: "xyr",
|
|
79
|
+
possessive_pronoun: "xyrs",
|
|
80
|
+
reflexive: "xemself"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
subjective: "ze",
|
|
84
|
+
objective: "zir",
|
|
85
|
+
possessive_adjective: "zir",
|
|
86
|
+
possessive_pronoun: "zirs",
|
|
87
|
+
reflexive: "zirself"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
subjective: "fae",
|
|
91
|
+
objective: "faer",
|
|
92
|
+
possessive_adjective: "faer",
|
|
93
|
+
possessive_pronoun: "faers",
|
|
94
|
+
reflexive: "faerself"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
subjective: "per",
|
|
98
|
+
objective: "per",
|
|
99
|
+
possessive_adjective: "per",
|
|
100
|
+
possessive_pronoun: "pers",
|
|
101
|
+
reflexive: "perself"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
subjective: "ey",
|
|
105
|
+
objective: "em",
|
|
106
|
+
possessive_adjective: "eir",
|
|
107
|
+
possessive_pronoun: "eirs",
|
|
108
|
+
reflexive: "emself"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
subjective: "e",
|
|
112
|
+
objective: "em",
|
|
113
|
+
possessive_adjective: "eir",
|
|
114
|
+
possessive_pronoun: "eirs",
|
|
115
|
+
reflexive: "emself"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
subjective: "ze",
|
|
119
|
+
objective: "hir",
|
|
120
|
+
possessive_adjective: "hir",
|
|
121
|
+
possessive_pronoun: "hirs",
|
|
122
|
+
reflexive: "hirself"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
subjective: "ae",
|
|
126
|
+
objective: "aer",
|
|
127
|
+
possessive_adjective: "aer",
|
|
128
|
+
possessive_pronoun: "aers",
|
|
129
|
+
reflexive: "aerself"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
subjective: "co",
|
|
133
|
+
objective: "co",
|
|
134
|
+
possessive_adjective: "cos",
|
|
135
|
+
possessive_pronoun: "cos",
|
|
136
|
+
reflexive: "coself"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
subjective: "ne",
|
|
140
|
+
objective: "nem",
|
|
141
|
+
possessive_adjective: "nir",
|
|
142
|
+
possessive_pronoun: "nirs",
|
|
143
|
+
reflexive: "nemself"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
subjective: "thon",
|
|
147
|
+
objective: "thon",
|
|
148
|
+
possessive_adjective: "thons",
|
|
149
|
+
possessive_pronoun: "thons",
|
|
150
|
+
reflexive: "thonself"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
subjective: "ve",
|
|
154
|
+
objective: "ver",
|
|
155
|
+
possessive_adjective: "vis",
|
|
156
|
+
possessive_pronoun: "vis",
|
|
157
|
+
reflexive: "verself"
|
|
158
|
+
}
|
|
159
|
+
];
|
|
160
|
+
function buildFormToSet() {
|
|
161
|
+
const map = /* @__PURE__ */ new Map();
|
|
162
|
+
for (const entry of PRONOUN_DICTIONARY) {
|
|
163
|
+
map.set(entry.subjective, entry);
|
|
164
|
+
}
|
|
165
|
+
for (const entry of PRONOUN_DICTIONARY) {
|
|
166
|
+
for (const form of [
|
|
167
|
+
entry.objective,
|
|
168
|
+
entry.possessive_adjective,
|
|
169
|
+
entry.possessive_pronoun,
|
|
170
|
+
entry.reflexive
|
|
171
|
+
]) {
|
|
172
|
+
if (!map.has(form)) {
|
|
173
|
+
map.set(form, entry);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return map;
|
|
178
|
+
}
|
|
179
|
+
var FORM_TO_SET = buildFormToSet();
|
|
180
|
+
var SPECIAL_KEYWORDS = {
|
|
181
|
+
any: [
|
|
182
|
+
"any",
|
|
183
|
+
"any pronoun",
|
|
184
|
+
"any pronouns",
|
|
185
|
+
"any/all",
|
|
186
|
+
"all/any",
|
|
187
|
+
"any and all",
|
|
188
|
+
"any and all pronouns",
|
|
189
|
+
"all",
|
|
190
|
+
"all pronouns",
|
|
191
|
+
"no preference",
|
|
192
|
+
"whatever",
|
|
193
|
+
"whatever you want",
|
|
194
|
+
"whatever you prefer",
|
|
195
|
+
"whatever is fine",
|
|
196
|
+
"whatever you feel comfortable",
|
|
197
|
+
"i don't care",
|
|
198
|
+
"i dont care",
|
|
199
|
+
"idc",
|
|
200
|
+
"doesn't matter",
|
|
201
|
+
"doesnt matter",
|
|
202
|
+
"i go by all",
|
|
203
|
+
"most are acceptable"
|
|
204
|
+
],
|
|
205
|
+
none: [
|
|
206
|
+
"none",
|
|
207
|
+
"no pronouns",
|
|
208
|
+
"avoid pronouns",
|
|
209
|
+
"use my name",
|
|
210
|
+
"name only",
|
|
211
|
+
"just my name",
|
|
212
|
+
"refer to me by name"
|
|
213
|
+
],
|
|
214
|
+
ask: ["ask", "ask me", "ask my pronouns", "ask me my pronouns", "please ask"],
|
|
215
|
+
unspecified: [
|
|
216
|
+
"unsure",
|
|
217
|
+
"not sure",
|
|
218
|
+
"not sure yet",
|
|
219
|
+
"prefer not to disclose",
|
|
220
|
+
"prefer not to say",
|
|
221
|
+
"choose not to disclose",
|
|
222
|
+
"undecided",
|
|
223
|
+
"i don't know",
|
|
224
|
+
"i dont know",
|
|
225
|
+
"don't know",
|
|
226
|
+
"dont know",
|
|
227
|
+
"don't know yet",
|
|
228
|
+
"dont know yet",
|
|
229
|
+
"dunno",
|
|
230
|
+
"private"
|
|
231
|
+
]
|
|
232
|
+
};
|
|
233
|
+
var PLACEHOLDER_STRINGS = [
|
|
234
|
+
"n/a",
|
|
235
|
+
"na",
|
|
236
|
+
"tbd",
|
|
237
|
+
"-",
|
|
238
|
+
"none given"
|
|
239
|
+
];
|
|
240
|
+
var FILLER_PATTERNS = [
|
|
241
|
+
// suffix fillers
|
|
242
|
+
/\s+is\s+fine\s*$/i,
|
|
243
|
+
/\s+are\s+fine\s*$/i,
|
|
244
|
+
/\s+also\s*$/i,
|
|
245
|
+
/\s+as\s+well\s*$/i,
|
|
246
|
+
/\s+preferred\s*$/i,
|
|
247
|
+
/\s+only\s*$/i,
|
|
248
|
+
/\s+please\s*$/i,
|
|
249
|
+
/\s+now\s*$/i,
|
|
250
|
+
// prefix fillers
|
|
251
|
+
/^please\s+/i,
|
|
252
|
+
/^only\s+/i,
|
|
253
|
+
/^just\s+use\s+/i,
|
|
254
|
+
/^i\s+use\s+/i,
|
|
255
|
+
/^i\s+go\s+by\s+/i,
|
|
256
|
+
// whole-segment filler phrase
|
|
257
|
+
/^relevant\s+pronouns\s+are\s+fine\s*$/i
|
|
258
|
+
];
|
|
259
|
+
|
|
260
|
+
// src/parser/index.ts
|
|
261
|
+
function matchSpecialKeyword(text) {
|
|
262
|
+
for (const [type, keywords] of Object.entries(SPECIAL_KEYWORDS)) {
|
|
263
|
+
if (keywords.includes(text)) return type;
|
|
264
|
+
}
|
|
265
|
+
return void 0;
|
|
266
|
+
}
|
|
267
|
+
function isPlaceholder(text) {
|
|
268
|
+
return PLACEHOLDER_STRINGS.includes(text);
|
|
269
|
+
}
|
|
270
|
+
function formBelongsToEntry(form, entry) {
|
|
271
|
+
return entry.subjective === form || entry.objective === form || entry.possessive_adjective === form || entry.possessive_pronoun === form || entry.reflexive === form;
|
|
272
|
+
}
|
|
273
|
+
function makeStandardEntry(set, context, excluded2) {
|
|
274
|
+
const entry = {
|
|
275
|
+
subjective: set.subjective,
|
|
276
|
+
objective: set.objective,
|
|
277
|
+
possessive_adjective: set.possessive_adjective,
|
|
278
|
+
possessive_pronoun: set.possessive_pronoun,
|
|
279
|
+
reflexive: set.reflexive
|
|
280
|
+
};
|
|
281
|
+
if (context !== void 0) entry["context"] = context;
|
|
282
|
+
if (excluded2) entry["exclude"] = true;
|
|
283
|
+
return entry;
|
|
284
|
+
}
|
|
285
|
+
function resolveTokens(tokensLc, originalText, context, excluded2) {
|
|
286
|
+
const hasKnownToken = tokensLc.some((t) => FORM_TO_SET.has(t));
|
|
287
|
+
if (!hasKnownToken) {
|
|
288
|
+
const entry = { type: "custom", display: originalText };
|
|
289
|
+
if (context !== void 0) entry.context = context;
|
|
290
|
+
if (excluded2) entry.exclude = true;
|
|
291
|
+
return [entry];
|
|
292
|
+
}
|
|
293
|
+
const result = [];
|
|
294
|
+
let currentSet = null;
|
|
295
|
+
for (const token of tokensLc) {
|
|
296
|
+
const candidate = FORM_TO_SET.get(token);
|
|
297
|
+
if (!candidate) continue;
|
|
298
|
+
if (currentSet === null) {
|
|
299
|
+
currentSet = candidate;
|
|
300
|
+
} else if (candidate === currentSet || formBelongsToEntry(token, currentSet)) {
|
|
301
|
+
} else if (candidate.subjective === currentSet.subjective) {
|
|
302
|
+
currentSet = candidate;
|
|
303
|
+
} else {
|
|
304
|
+
result.push(makeStandardEntry(currentSet, context, excluded2));
|
|
305
|
+
currentSet = candidate;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (currentSet !== null) {
|
|
309
|
+
result.push(makeStandardEntry(currentSet, context, excluded2));
|
|
310
|
+
}
|
|
311
|
+
return result;
|
|
312
|
+
}
|
|
313
|
+
function deduplicateEntries(entries) {
|
|
314
|
+
const seen = /* @__PURE__ */ new Set();
|
|
315
|
+
return entries.filter((entry) => {
|
|
316
|
+
let key;
|
|
317
|
+
if ("type" in entry && entry.type !== "custom") {
|
|
318
|
+
key = `special:${entry.type}`;
|
|
319
|
+
} else if ("type" in entry && entry.type === "custom") {
|
|
320
|
+
key = `custom:${entry.display}`;
|
|
321
|
+
} else if ("subjective" in entry && entry.subjective) {
|
|
322
|
+
key = `sub:${entry.subjective}`;
|
|
323
|
+
} else if ("sub" in entry && entry.sub) {
|
|
324
|
+
key = `sub:${entry.sub}`;
|
|
325
|
+
} else {
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
if (seen.has(key)) return false;
|
|
329
|
+
seen.add(key);
|
|
330
|
+
return true;
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
function parse(input) {
|
|
334
|
+
if (!input?.trim()) return null;
|
|
335
|
+
const text = input.replace(/[‘’‛]/g, "'").replace(/^["'](.+)["']$/, "$1").replace(/\\/g, "/").replace(/\s*\/\s*/g, "/").replace(/\s+/g, " ").trim();
|
|
336
|
+
if (!text) return null;
|
|
337
|
+
const textLc = text.toLowerCase();
|
|
338
|
+
if (isPlaceholder(textLc)) return null;
|
|
339
|
+
const wholeSpecialType = matchSpecialKeyword(textLc);
|
|
340
|
+
if (wholeSpecialType) return [{ type: wholeSpecialType }];
|
|
341
|
+
const segments = text.split(/,\s*|;\s*|\s+&\s+|\s+and\s+|\s+or\s+/i);
|
|
342
|
+
const entries = [];
|
|
343
|
+
for (const rawSeg of segments) {
|
|
344
|
+
const seg = rawSeg.trim();
|
|
345
|
+
if (!seg) continue;
|
|
346
|
+
let workSeg = seg;
|
|
347
|
+
let workLc = seg.toLowerCase();
|
|
348
|
+
let context;
|
|
349
|
+
const parenMatch = workSeg.match(/\s*\(([^)]+)\)\s*$/) ?? workSeg.match(/\s*\[([^\]]+)\]\s*$/);
|
|
350
|
+
if (parenMatch) {
|
|
351
|
+
context = parenMatch[1].trim() || void 0;
|
|
352
|
+
workSeg = workSeg.slice(0, parenMatch.index).trim();
|
|
353
|
+
workLc = workSeg.toLowerCase();
|
|
354
|
+
}
|
|
355
|
+
for (const pattern of FILLER_PATTERNS) {
|
|
356
|
+
workSeg = workSeg.replace(pattern, "").trim();
|
|
357
|
+
}
|
|
358
|
+
workLc = workSeg.toLowerCase();
|
|
359
|
+
if (!workLc) continue;
|
|
360
|
+
const segSpecialType = matchSpecialKeyword(workLc);
|
|
361
|
+
if (segSpecialType) {
|
|
362
|
+
const entry = { type: segSpecialType };
|
|
363
|
+
if (context !== void 0)
|
|
364
|
+
entry["context"] = context;
|
|
365
|
+
entries.push(entry);
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
if (isPlaceholder(workLc)) continue;
|
|
369
|
+
let excluded2 = false;
|
|
370
|
+
const exclusionMatch = workLc.match(
|
|
371
|
+
/^(?:just\s+not|not|never|except)\s+(.+)$/
|
|
372
|
+
);
|
|
373
|
+
if (exclusionMatch) {
|
|
374
|
+
excluded2 = true;
|
|
375
|
+
const remainder = exclusionMatch[1];
|
|
376
|
+
workSeg = workSeg.slice(workSeg.length - remainder.length);
|
|
377
|
+
workLc = remainder;
|
|
378
|
+
}
|
|
379
|
+
const tokensLc = workLc.split(/[/ ]+/).filter(Boolean);
|
|
380
|
+
if (tokensLc.length === 0) continue;
|
|
381
|
+
const resolved = resolveTokens(tokensLc, workSeg, context, excluded2);
|
|
382
|
+
entries.push(...resolved);
|
|
383
|
+
}
|
|
384
|
+
const deduped = deduplicateEntries(entries);
|
|
385
|
+
return deduped.length > 0 ? deduped : null;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// src/formatter.ts
|
|
389
|
+
function sub(e) {
|
|
390
|
+
if ("subjective" in e) return e.subjective;
|
|
391
|
+
if ("sub" in e) return e.sub;
|
|
392
|
+
return void 0;
|
|
393
|
+
}
|
|
394
|
+
function obj(e) {
|
|
395
|
+
if ("objective" in e) return e.objective;
|
|
396
|
+
if ("obj" in e) return e.obj;
|
|
397
|
+
return void 0;
|
|
398
|
+
}
|
|
399
|
+
function ppn(e) {
|
|
400
|
+
if ("possessive_pronoun" in e) return e.possessive_pronoun;
|
|
401
|
+
if ("p_pn" in e) return e.p_pn;
|
|
402
|
+
return void 0;
|
|
403
|
+
}
|
|
404
|
+
function ctx(e) {
|
|
405
|
+
if ("context" in e && e.context) return e.context;
|
|
406
|
+
if ("ctx" in e && e.ctx)
|
|
407
|
+
return e.ctx;
|
|
408
|
+
return void 0;
|
|
409
|
+
}
|
|
410
|
+
function ranking(e) {
|
|
411
|
+
if ("ranking" in e && e.ranking !== void 0) return e.ranking;
|
|
412
|
+
if ("rnk" in e && e.rnk !== void 0)
|
|
413
|
+
return e.rnk;
|
|
414
|
+
return void 0;
|
|
415
|
+
}
|
|
416
|
+
function privacy(e) {
|
|
417
|
+
if ("privacy" in e && e.privacy !== void 0) return e.privacy;
|
|
418
|
+
if ("pvc" in e && e.pvc !== void 0)
|
|
419
|
+
return e.pvc;
|
|
420
|
+
return void 0;
|
|
421
|
+
}
|
|
422
|
+
function excluded(e) {
|
|
423
|
+
if ("exclude" in e && e.exclude === true) return true;
|
|
424
|
+
if ("exc" in e && e.exc === true) return true;
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
function capitalize(s) {
|
|
428
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
429
|
+
}
|
|
430
|
+
function capitalizeSlashSeparated(s) {
|
|
431
|
+
return s.split("/").map(capitalize).join("/");
|
|
432
|
+
}
|
|
433
|
+
function formatSingleEntry(entry, form) {
|
|
434
|
+
if ("type" in entry) {
|
|
435
|
+
const t = entry.type;
|
|
436
|
+
if (t === "any") return "Any pronouns";
|
|
437
|
+
if (t === "none") return "No pronouns (use name)";
|
|
438
|
+
if (t === "ask") return "Ask me my pronouns";
|
|
439
|
+
if (t === "unspecified") return "Unspecified";
|
|
440
|
+
if (t === "custom") {
|
|
441
|
+
const display = entry.display;
|
|
442
|
+
return capitalizeSlashSeparated(display);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
const s = sub(entry);
|
|
446
|
+
const o = obj(entry);
|
|
447
|
+
const p = ppn(entry);
|
|
448
|
+
if (!s || !o) return "";
|
|
449
|
+
let base;
|
|
450
|
+
if (form === "expanded") {
|
|
451
|
+
base = `${capitalize(s)}/${capitalize(o)}/${capitalize(p ?? o)}`;
|
|
452
|
+
} else {
|
|
453
|
+
base = `${capitalize(s)}/${capitalize(o)}`;
|
|
454
|
+
}
|
|
455
|
+
const context = ctx(entry);
|
|
456
|
+
if (context) base += ` (${context})`;
|
|
457
|
+
return base;
|
|
458
|
+
}
|
|
459
|
+
function format(preference, options = {}) {
|
|
460
|
+
const form = options.form ?? "short";
|
|
461
|
+
const isPublic = options.audience === "public";
|
|
462
|
+
let visible = preference.filter((e) => {
|
|
463
|
+
if (isPublic) {
|
|
464
|
+
const p = privacy(e);
|
|
465
|
+
if (p !== void 0 && p >= 1) return false;
|
|
466
|
+
}
|
|
467
|
+
return true;
|
|
468
|
+
});
|
|
469
|
+
visible = [...visible].sort((a, b) => {
|
|
470
|
+
const ra = ranking(a);
|
|
471
|
+
const rb = ranking(b);
|
|
472
|
+
if (ra !== void 0 && rb !== void 0) return ra - rb;
|
|
473
|
+
if (ra !== void 0) return -1;
|
|
474
|
+
if (rb !== void 0) return 1;
|
|
475
|
+
return 0;
|
|
476
|
+
});
|
|
477
|
+
if (form === "detailed") {
|
|
478
|
+
const positive = visible.filter((e) => !excluded(e));
|
|
479
|
+
const negative = visible.filter((e) => excluded(e));
|
|
480
|
+
const posStr = positive.map((e) => formatSingleEntry(e, "short")).filter(Boolean).join(", ");
|
|
481
|
+
if (negative.length === 0) return posStr;
|
|
482
|
+
const negStr = negative.map((e) => {
|
|
483
|
+
const s = sub(e);
|
|
484
|
+
const o = obj(e);
|
|
485
|
+
return s && o ? `not ${capitalize(s)}/${capitalize(o)}` : "";
|
|
486
|
+
}).filter(Boolean).join(", ");
|
|
487
|
+
return negStr ? `${posStr} (${negStr})` : posStr;
|
|
488
|
+
}
|
|
489
|
+
const displayable = visible.filter((e) => !excluded(e));
|
|
490
|
+
return displayable.map((e) => formatSingleEntry(e, form)).filter(Boolean).join(", ");
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// src/types.ts
|
|
494
|
+
var import_zod = require("@openpronoun/zod");
|
|
495
|
+
|
|
496
|
+
// src/validator.ts
|
|
497
|
+
function validate(input) {
|
|
498
|
+
return import_zod.pronounPreferenceSchema.safeParse(input).success;
|
|
499
|
+
}
|
|
500
|
+
function validateOrThrow(input) {
|
|
501
|
+
return import_zod.pronounPreferenceSchema.parse(input);
|
|
502
|
+
}
|
|
503
|
+
function validationErrors(input) {
|
|
504
|
+
const result = import_zod.pronounPreferenceSchema.safeParse(input);
|
|
505
|
+
if (result.success) return [];
|
|
506
|
+
return result.error.issues.map(
|
|
507
|
+
(e) => `${e.path.map(String).join(".")}: ${e.message}`
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// src/privacy.ts
|
|
512
|
+
function filterByAudience(preference, audience) {
|
|
513
|
+
if (audience !== "public") return preference;
|
|
514
|
+
return preference.filter((entry) => {
|
|
515
|
+
const p = "privacy" in entry ? entry.privacy : "pvc" in entry ? entry.pvc : void 0;
|
|
516
|
+
return p === void 0 || p < 1;
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
520
|
+
0 && (module.exports = {
|
|
521
|
+
FILLER_PATTERNS,
|
|
522
|
+
FORM_TO_SET,
|
|
523
|
+
PLACEHOLDER_STRINGS,
|
|
524
|
+
PRONOUN_DICTIONARY,
|
|
525
|
+
SPECIAL_KEYWORDS,
|
|
526
|
+
SPECIAL_TYPES,
|
|
527
|
+
customEntrySchema,
|
|
528
|
+
filterByAudience,
|
|
529
|
+
format,
|
|
530
|
+
parse,
|
|
531
|
+
pronounEntrySchema,
|
|
532
|
+
pronounPreferenceSchema,
|
|
533
|
+
pronounSetSchema,
|
|
534
|
+
specialPreferenceSchema,
|
|
535
|
+
validate,
|
|
536
|
+
validateOrThrow,
|
|
537
|
+
validationErrors
|
|
538
|
+
});
|
|
539
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/parser/index.ts","../src/formatter.ts","../src/types.ts","../src/validator.ts","../src/privacy.ts"],"sourcesContent":["export { parse } from \"./parser\";\nexport { format } from \"./formatter\";\nexport { validate, validateOrThrow, validationErrors } from \"./validator\";\nexport { filterByAudience } from \"./privacy\";\nexport {\n PRONOUN_DICTIONARY,\n FORM_TO_SET,\n SPECIAL_KEYWORDS,\n PLACEHOLDER_STRINGS,\n FILLER_PATTERNS,\n} from \"./constants\";\nexport type { CanonicalEntry } from \"./constants\";\nexport type {\n PronounPreference,\n PronounEntry,\n PronounSet,\n SpecialPreference,\n CustomEntry,\n FormatOptions,\n} from \"./types\";\nexport {\n pronounPreferenceSchema,\n pronounEntrySchema,\n pronounSetSchema,\n specialPreferenceSchema,\n customEntrySchema,\n SPECIAL_TYPES,\n} from \"./types\";\n","export interface CanonicalEntry {\n readonly subjective: string;\n readonly objective: string;\n readonly possessive_adjective: string;\n readonly possessive_pronoun: string;\n readonly reflexive: string;\n}\n\nexport const PRONOUN_DICTIONARY: readonly CanonicalEntry[] = [\n // Common sets\n {\n subjective: \"she\",\n objective: \"her\",\n possessive_adjective: \"her\",\n possessive_pronoun: \"hers\",\n reflexive: \"herself\",\n },\n {\n subjective: \"he\",\n objective: \"him\",\n possessive_adjective: \"his\",\n possessive_pronoun: \"his\",\n reflexive: \"himself\",\n },\n {\n subjective: \"they\",\n objective: \"them\",\n possessive_adjective: \"their\",\n possessive_pronoun: \"theirs\",\n reflexive: \"themselves\",\n },\n {\n subjective: \"it\",\n objective: \"it\",\n possessive_adjective: \"its\",\n possessive_pronoun: \"its\",\n reflexive: \"itself\",\n },\n // Neopronouns\n {\n subjective: \"xe\",\n objective: \"xem\",\n possessive_adjective: \"xyr\",\n possessive_pronoun: \"xyrs\",\n reflexive: \"xemself\",\n },\n {\n subjective: \"ze\",\n objective: \"zir\",\n possessive_adjective: \"zir\",\n possessive_pronoun: \"zirs\",\n reflexive: \"zirself\",\n },\n {\n subjective: \"fae\",\n objective: \"faer\",\n possessive_adjective: \"faer\",\n possessive_pronoun: \"faers\",\n reflexive: \"faerself\",\n },\n {\n subjective: \"per\",\n objective: \"per\",\n possessive_adjective: \"per\",\n possessive_pronoun: \"pers\",\n reflexive: \"perself\",\n },\n {\n subjective: \"ey\",\n objective: \"em\",\n possessive_adjective: \"eir\",\n possessive_pronoun: \"eirs\",\n reflexive: \"emself\",\n },\n {\n subjective: \"e\",\n objective: \"em\",\n possessive_adjective: \"eir\",\n possessive_pronoun: \"eirs\",\n reflexive: \"emself\",\n },\n {\n subjective: \"ze\",\n objective: \"hir\",\n possessive_adjective: \"hir\",\n possessive_pronoun: \"hirs\",\n reflexive: \"hirself\",\n },\n {\n subjective: \"ae\",\n objective: \"aer\",\n possessive_adjective: \"aer\",\n possessive_pronoun: \"aers\",\n reflexive: \"aerself\",\n },\n {\n subjective: \"co\",\n objective: \"co\",\n possessive_adjective: \"cos\",\n possessive_pronoun: \"cos\",\n reflexive: \"coself\",\n },\n {\n subjective: \"ne\",\n objective: \"nem\",\n possessive_adjective: \"nir\",\n possessive_pronoun: \"nirs\",\n reflexive: \"nemself\",\n },\n {\n subjective: \"thon\",\n objective: \"thon\",\n possessive_adjective: \"thons\",\n possessive_pronoun: \"thons\",\n reflexive: \"thonself\",\n },\n {\n subjective: \"ve\",\n objective: \"ver\",\n possessive_adjective: \"vis\",\n possessive_pronoun: \"vis\",\n reflexive: \"verself\",\n },\n] as const;\n\n// Reverse lookup: any known form → its canonical entry.\n// Subjective always takes priority; other forms use first-write-wins.\nfunction buildFormToSet(): Map<string, CanonicalEntry> {\n const map = new Map<string, CanonicalEntry>();\n for (const entry of PRONOUN_DICTIONARY) {\n // Subjective always wins (overwrite)\n map.set(entry.subjective, entry);\n }\n for (const entry of PRONOUN_DICTIONARY) {\n for (const form of [\n entry.objective,\n entry.possessive_adjective,\n entry.possessive_pronoun,\n entry.reflexive,\n ]) {\n if (!map.has(form)) {\n map.set(form, entry);\n }\n }\n }\n return map;\n}\n\nexport const FORM_TO_SET: ReadonlyMap<string, CanonicalEntry> =\n buildFormToSet();\n\nexport const SPECIAL_KEYWORDS = {\n any: [\n \"any\",\n \"any pronoun\",\n \"any pronouns\",\n \"any/all\",\n \"all/any\",\n \"any and all\",\n \"any and all pronouns\",\n \"all\",\n \"all pronouns\",\n \"no preference\",\n \"whatever\",\n \"whatever you want\",\n \"whatever you prefer\",\n \"whatever is fine\",\n \"whatever you feel comfortable\",\n \"i don't care\",\n \"i dont care\",\n \"idc\",\n \"doesn't matter\",\n \"doesnt matter\",\n \"i go by all\",\n \"most are acceptable\",\n ],\n none: [\n \"none\",\n \"no pronouns\",\n \"avoid pronouns\",\n \"use my name\",\n \"name only\",\n \"just my name\",\n \"refer to me by name\",\n ],\n ask: [\"ask\", \"ask me\", \"ask my pronouns\", \"ask me my pronouns\", \"please ask\"],\n unspecified: [\n \"unsure\",\n \"not sure\",\n \"not sure yet\",\n \"prefer not to disclose\",\n \"prefer not to say\",\n \"choose not to disclose\",\n \"undecided\",\n \"i don't know\",\n \"i dont know\",\n \"don't know\",\n \"dont know\",\n \"don't know yet\",\n \"dont know yet\",\n \"dunno\",\n \"private\",\n ],\n} as const;\n\nexport const PLACEHOLDER_STRINGS: readonly string[] = [\n \"n/a\",\n \"na\",\n \"tbd\",\n \"-\",\n \"none given\",\n];\n\nexport const FILLER_PATTERNS: readonly RegExp[] = [\n // suffix fillers\n /\\s+is\\s+fine\\s*$/i,\n /\\s+are\\s+fine\\s*$/i,\n /\\s+also\\s*$/i,\n /\\s+as\\s+well\\s*$/i,\n /\\s+preferred\\s*$/i,\n /\\s+only\\s*$/i,\n /\\s+please\\s*$/i,\n /\\s+now\\s*$/i,\n // prefix fillers\n /^please\\s+/i,\n /^only\\s+/i,\n /^just\\s+use\\s+/i,\n /^i\\s+use\\s+/i,\n /^i\\s+go\\s+by\\s+/i,\n // whole-segment filler phrase\n /^relevant\\s+pronouns\\s+are\\s+fine\\s*$/i,\n];\n","import type {\n CustomEntry,\n PronounEntry,\n PronounPreference,\n SpecialPreference,\n} from \"../types\";\n\nimport {\n FILLER_PATTERNS,\n FORM_TO_SET,\n PLACEHOLDER_STRINGS,\n SPECIAL_KEYWORDS,\n type CanonicalEntry,\n} from \"../constants\";\n\ntype SpecialType = \"any\" | \"none\" | \"ask\" | \"unspecified\";\n\nfunction matchSpecialKeyword(text: string): SpecialType | undefined {\n for (const [type, keywords] of Object.entries(SPECIAL_KEYWORDS) as [\n SpecialType,\n readonly string[],\n ][]) {\n if ((keywords as readonly string[]).includes(text)) return type;\n }\n return undefined;\n}\n\nfunction stripFiller(text: string): string {\n let s = text;\n for (const pattern of FILLER_PATTERNS) {\n s = s.replace(pattern, \"\").trim();\n }\n return s;\n}\n\nfunction isPlaceholder(text: string): boolean {\n return PLACEHOLDER_STRINGS.includes(text);\n}\n\nfunction formBelongsToEntry(form: string, entry: CanonicalEntry): boolean {\n return (\n entry.subjective === form ||\n entry.objective === form ||\n entry.possessive_adjective === form ||\n entry.possessive_pronoun === form ||\n entry.reflexive === form\n );\n}\n\nfunction makeStandardEntry(\n set: CanonicalEntry,\n context: string | undefined,\n excluded: boolean,\n): PronounEntry {\n const entry: Record<string, unknown> = {\n subjective: set.subjective,\n objective: set.objective,\n possessive_adjective: set.possessive_adjective,\n possessive_pronoun: set.possessive_pronoun,\n reflexive: set.reflexive,\n };\n if (context !== undefined) entry[\"context\"] = context;\n if (excluded) entry[\"exclude\"] = true;\n return entry as PronounEntry;\n}\n\nfunction resolveTokens(\n tokensLc: string[],\n originalText: string,\n context: string | undefined,\n excluded: boolean,\n): PronounEntry[] {\n const hasKnownToken = tokensLc.some((t) => FORM_TO_SET.has(t));\n\n if (!hasKnownToken) {\n const entry: CustomEntry = { type: \"custom\", display: originalText };\n if (context !== undefined) entry.context = context;\n if (excluded) entry.exclude = true;\n return [entry];\n }\n\n const result: PronounEntry[] = [];\n let currentSet: CanonicalEntry | null = null;\n\n for (const token of tokensLc) {\n const candidate = FORM_TO_SET.get(token);\n if (!candidate) continue;\n\n if (currentSet === null) {\n currentSet = candidate;\n } else if (\n candidate === currentSet ||\n formBelongsToEntry(token, currentSet)\n ) {\n // same set or an alternate form of the current set — keep accumulating\n } else if (candidate.subjective === currentSet.subjective) {\n // same subjective, different set — disambiguation token (e.g. \"zir\" after \"ze\")\n currentSet = candidate;\n } else {\n result.push(makeStandardEntry(currentSet, context, excluded));\n currentSet = candidate;\n }\n }\n\n if (currentSet !== null) {\n result.push(makeStandardEntry(currentSet, context, excluded));\n }\n\n return result;\n}\n\nfunction deduplicateEntries(entries: PronounEntry[]): PronounEntry[] {\n const seen = new Set<string>();\n return entries.filter((entry) => {\n let key: string;\n if (\"type\" in entry && entry.type !== \"custom\") {\n key = `special:${entry.type}`;\n } else if (\"type\" in entry && entry.type === \"custom\") {\n key = `custom:${(entry as CustomEntry).display}`;\n } else if (\"subjective\" in entry && entry.subjective) {\n key = `sub:${entry.subjective}`;\n } else if (\"sub\" in entry && (entry as { sub?: string }).sub) {\n key = `sub:${(entry as { sub?: string }).sub}`;\n } else {\n return true;\n }\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nexport function parse(\n input: string | null | undefined,\n): PronounPreference | null {\n if (!input?.trim()) return null;\n\n // Normalize: smart quotes, surrounding quotes, backslash→slash,\n // spaces around slashes, collapsed whitespace.\n const text = input\n .replace(/[‘’‛]/g, \"'\")\n .replace(/^[\"'](.+)[\"']$/, \"$1\")\n .replace(/\\\\/g, \"/\")\n .replace(/\\s*\\/\\s*/g, \"/\")\n .replace(/\\s+/g, \" \")\n .trim();\n\n if (!text) return null;\n\n const textLc = text.toLowerCase();\n\n if (isPlaceholder(textLc)) return null;\n\n // Check whole input against special keywords before splitting.\n const wholeSpecialType = matchSpecialKeyword(textLc);\n if (wholeSpecialType) return [{ type: wholeSpecialType }];\n\n // Split on set-level separators: comma, semicolon, ampersand, \"and\", \"or\".\n const segments = text.split(/,\\s*|;\\s*|\\s+&\\s+|\\s+and\\s+|\\s+or\\s+/i);\n\n const entries: PronounEntry[] = [];\n\n for (const rawSeg of segments) {\n const seg = rawSeg.trim();\n if (!seg) continue;\n\n let workSeg = seg;\n let workLc = seg.toLowerCase();\n\n // Extract parenthetical or bracketed context: \"she/her (at work)\" or \"[at work]\".\n let context: string | undefined;\n const parenMatch =\n workSeg.match(/\\s*\\(([^)]+)\\)\\s*$/) ??\n workSeg.match(/\\s*\\[([^\\]]+)\\]\\s*$/);\n if (parenMatch) {\n context = parenMatch[1]!.trim() || undefined;\n workSeg = workSeg.slice(0, parenMatch.index!).trim();\n workLc = workSeg.toLowerCase();\n }\n\n // Strip filler phrases — apply FILLER_PATTERNS to the original-case workSeg\n // (all patterns have /i), then re-derive workLc.\n for (const pattern of FILLER_PATTERNS) {\n workSeg = workSeg.replace(pattern, \"\").trim();\n }\n workLc = workSeg.toLowerCase();\n\n if (!workLc) continue;\n\n // Check special keyword BEFORE exclusion detection so that phrases like\n // \"not sure yet\" are caught here and not misread as exclusions.\n const segSpecialType = matchSpecialKeyword(workLc);\n if (segSpecialType) {\n const entry: SpecialPreference = { type: segSpecialType };\n if (context !== undefined)\n (entry as Record<string, unknown>)[\"context\"] = context;\n entries.push(entry);\n continue;\n }\n\n // Placeholder check.\n if (isPlaceholder(workLc)) continue;\n\n // Detect and strip exclusion prefix (\"just not\", \"not\", \"never\", \"except\").\n let excluded = false;\n const exclusionMatch = workLc.match(\n /^(?:just\\s+not|not|never|except)\\s+(.+)$/,\n );\n if (exclusionMatch) {\n excluded = true;\n const remainder = exclusionMatch[1]!;\n workSeg = workSeg.slice(workSeg.length - remainder.length);\n workLc = remainder;\n }\n\n // Tokenize by \"/\" and space, resolve to known sets.\n const tokensLc = workLc.split(/[/ ]+/).filter(Boolean);\n if (tokensLc.length === 0) continue;\n\n const resolved = resolveTokens(tokensLc, workSeg, context, excluded);\n entries.push(...resolved);\n }\n\n const deduped = deduplicateEntries(entries);\n return deduped.length > 0 ? deduped : null;\n}\n","import type { FormatOptions, PronounEntry, PronounPreference } from \"./types\";\n\n// Helpers for reading either full or compact key styles.\n\nfunction sub(e: PronounEntry): string | undefined {\n if (\"subjective\" in e) return e.subjective;\n if (\"sub\" in e) return (e as { sub?: string }).sub;\n return undefined;\n}\n\nfunction obj(e: PronounEntry): string | undefined {\n if (\"objective\" in e) return e.objective;\n if (\"obj\" in e) return (e as { obj?: string }).obj;\n return undefined;\n}\n\nfunction ppn(e: PronounEntry): string | undefined {\n if (\"possessive_pronoun\" in e) return e.possessive_pronoun;\n if (\"p_pn\" in e) return (e as { p_pn?: string }).p_pn;\n return undefined;\n}\n\nfunction ctx(e: PronounEntry): string | undefined {\n if (\"context\" in e && e.context) return e.context;\n if (\"ctx\" in e && (e as { ctx?: string }).ctx)\n return (e as { ctx?: string }).ctx;\n return undefined;\n}\n\nfunction ranking(e: PronounEntry): number | undefined {\n if (\"ranking\" in e && e.ranking !== undefined) return e.ranking;\n if (\"rnk\" in e && (e as { rnk?: number }).rnk !== undefined)\n return (e as { rnk?: number }).rnk;\n return undefined;\n}\n\nfunction privacy(e: PronounEntry): number | undefined {\n if (\"privacy\" in e && e.privacy !== undefined) return e.privacy;\n if (\"pvc\" in e && (e as { pvc?: number }).pvc !== undefined)\n return (e as { pvc?: number }).pvc;\n return undefined;\n}\n\nfunction excluded(e: PronounEntry): boolean {\n if (\"exclude\" in e && e.exclude === true) return true;\n if (\"exc\" in e && (e as { exc?: boolean }).exc === true) return true;\n return false;\n}\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nfunction capitalizeSlashSeparated(s: string): string {\n return s.split(\"/\").map(capitalize).join(\"/\");\n}\n\nfunction formatSingleEntry(\n entry: PronounEntry,\n form: \"short\" | \"expanded\" | \"detailed\",\n): string {\n if (\"type\" in entry) {\n const t = entry.type;\n if (t === \"any\") return \"Any pronouns\";\n if (t === \"none\") return \"No pronouns (use name)\";\n if (t === \"ask\") return \"Ask me my pronouns\";\n if (t === \"unspecified\") return \"Unspecified\";\n if (t === \"custom\") {\n const display = (entry as { type: \"custom\"; display: string }).display;\n return capitalizeSlashSeparated(display);\n }\n }\n\n const s = sub(entry);\n const o = obj(entry);\n const p = ppn(entry);\n\n if (!s || !o) return \"\";\n\n let base: string;\n if (form === \"expanded\") {\n base = `${capitalize(s)}/${capitalize(o)}/${capitalize(p ?? o)}`;\n } else {\n base = `${capitalize(s)}/${capitalize(o)}`;\n }\n\n const context = ctx(entry);\n if (context) base += ` (${context})`;\n\n return base;\n}\n\nexport function format(\n preference: PronounPreference,\n options: FormatOptions = {},\n): string {\n const form = options.form ?? \"short\";\n const isPublic = options.audience === \"public\";\n\n // Filter by privacy for public audience.\n let visible = preference.filter((e) => {\n if (isPublic) {\n const p = privacy(e);\n if (p !== undefined && p >= 1) return false;\n }\n return true;\n });\n\n // Sort by ranking (ascending — lower number = higher preference).\n // Entries without ranking stay at the end in their original order.\n visible = [...visible].sort((a, b) => {\n const ra = ranking(a);\n const rb = ranking(b);\n if (ra !== undefined && rb !== undefined) return ra - rb;\n if (ra !== undefined) return -1;\n if (rb !== undefined) return 1;\n return 0;\n });\n\n if (form === \"detailed\") {\n const positive = visible.filter((e) => !excluded(e));\n const negative = visible.filter((e) => excluded(e));\n\n const posStr = positive\n .map((e) => formatSingleEntry(e, \"short\"))\n .filter(Boolean)\n .join(\", \");\n\n if (negative.length === 0) return posStr;\n\n const negStr = negative\n .map((e) => {\n const s = sub(e);\n const o = obj(e);\n return s && o ? `not ${capitalize(s)}/${capitalize(o)}` : \"\";\n })\n .filter(Boolean)\n .join(\", \");\n\n return negStr ? `${posStr} (${negStr})` : posStr;\n }\n\n // short / expanded: omit excluded entries.\n const displayable = visible.filter((e) => !excluded(e));\n\n return displayable\n .map((e) => formatSingleEntry(e, form))\n .filter(Boolean)\n .join(\", \");\n}\n","export type {\n PronounPreference,\n PronounEntry,\n PronounSet,\n SpecialPreference,\n CustomEntry,\n} from \"@openpronoun/zod\";\n\nexport {\n pronounPreferenceSchema,\n pronounEntrySchema,\n pronounSetSchema,\n specialPreferenceSchema,\n customEntrySchema,\n SPECIAL_TYPES,\n} from \"@openpronoun/zod\";\n\nexport interface FormatOptions {\n form?: \"short\" | \"expanded\" | \"detailed\";\n audience?: string;\n}\n","import type { PronounPreference } from \"./types\";\n\nimport { pronounPreferenceSchema } from \"./types\";\n\nexport function validate(input: unknown): input is PronounPreference {\n return pronounPreferenceSchema.safeParse(input).success;\n}\n\nexport function validateOrThrow(input: unknown): PronounPreference {\n return pronounPreferenceSchema.parse(input);\n}\n\nexport function validationErrors(input: unknown): string[] {\n const result = pronounPreferenceSchema.safeParse(input);\n if (result.success) return [];\n return result.error.issues.map(\n (e) => `${e.path.map(String).join(\".\")}: ${e.message}`,\n );\n}\n","import type { PronounPreference } from \"./types\";\n\nexport function filterByAudience(\n preference: PronounPreference,\n audience: string,\n): PronounPreference {\n if (audience !== \"public\") return preference;\n return preference.filter((entry) => {\n const p =\n \"privacy\" in entry\n ? entry.privacy\n : \"pvc\" in entry\n ? (entry as { pvc?: number }).pvc\n : undefined;\n return p === undefined || p < 1;\n });\n}\n"],"mappings":"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","names":["excluded"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { PronounPreference } from '@openpronoun/zod';
|
|
2
|
+
export { CustomEntry, PronounEntry, PronounPreference, PronounSet, SPECIAL_TYPES, SpecialPreference, customEntrySchema, pronounEntrySchema, pronounPreferenceSchema, pronounSetSchema, specialPreferenceSchema } from '@openpronoun/zod';
|
|
3
|
+
|
|
4
|
+
interface FormatOptions {
|
|
5
|
+
form?: "short" | "expanded" | "detailed";
|
|
6
|
+
audience?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
declare function parse(input: string | null | undefined): PronounPreference | null;
|
|
10
|
+
|
|
11
|
+
declare function format(preference: PronounPreference, options?: FormatOptions): string;
|
|
12
|
+
|
|
13
|
+
declare function validate(input: unknown): input is PronounPreference;
|
|
14
|
+
declare function validateOrThrow(input: unknown): PronounPreference;
|
|
15
|
+
declare function validationErrors(input: unknown): string[];
|
|
16
|
+
|
|
17
|
+
declare function filterByAudience(preference: PronounPreference, audience: string): PronounPreference;
|
|
18
|
+
|
|
19
|
+
interface CanonicalEntry {
|
|
20
|
+
readonly subjective: string;
|
|
21
|
+
readonly objective: string;
|
|
22
|
+
readonly possessive_adjective: string;
|
|
23
|
+
readonly possessive_pronoun: string;
|
|
24
|
+
readonly reflexive: string;
|
|
25
|
+
}
|
|
26
|
+
declare const PRONOUN_DICTIONARY: readonly CanonicalEntry[];
|
|
27
|
+
declare const FORM_TO_SET: ReadonlyMap<string, CanonicalEntry>;
|
|
28
|
+
declare const SPECIAL_KEYWORDS: {
|
|
29
|
+
readonly any: readonly ["any", "any pronoun", "any pronouns", "any/all", "all/any", "any and all", "any and all pronouns", "all", "all pronouns", "no preference", "whatever", "whatever you want", "whatever you prefer", "whatever is fine", "whatever you feel comfortable", "i don't care", "i dont care", "idc", "doesn't matter", "doesnt matter", "i go by all", "most are acceptable"];
|
|
30
|
+
readonly none: readonly ["none", "no pronouns", "avoid pronouns", "use my name", "name only", "just my name", "refer to me by name"];
|
|
31
|
+
readonly ask: readonly ["ask", "ask me", "ask my pronouns", "ask me my pronouns", "please ask"];
|
|
32
|
+
readonly unspecified: readonly ["unsure", "not sure", "not sure yet", "prefer not to disclose", "prefer not to say", "choose not to disclose", "undecided", "i don't know", "i dont know", "don't know", "dont know", "don't know yet", "dont know yet", "dunno", "private"];
|
|
33
|
+
};
|
|
34
|
+
declare const PLACEHOLDER_STRINGS: readonly string[];
|
|
35
|
+
declare const FILLER_PATTERNS: readonly RegExp[];
|
|
36
|
+
|
|
37
|
+
export { type CanonicalEntry, FILLER_PATTERNS, FORM_TO_SET, type FormatOptions, PLACEHOLDER_STRINGS, PRONOUN_DICTIONARY, SPECIAL_KEYWORDS, filterByAudience, format, parse, validate, validateOrThrow, validationErrors };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { PronounPreference } from '@openpronoun/zod';
|
|
2
|
+
export { CustomEntry, PronounEntry, PronounPreference, PronounSet, SPECIAL_TYPES, SpecialPreference, customEntrySchema, pronounEntrySchema, pronounPreferenceSchema, pronounSetSchema, specialPreferenceSchema } from '@openpronoun/zod';
|
|
3
|
+
|
|
4
|
+
interface FormatOptions {
|
|
5
|
+
form?: "short" | "expanded" | "detailed";
|
|
6
|
+
audience?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
declare function parse(input: string | null | undefined): PronounPreference | null;
|
|
10
|
+
|
|
11
|
+
declare function format(preference: PronounPreference, options?: FormatOptions): string;
|
|
12
|
+
|
|
13
|
+
declare function validate(input: unknown): input is PronounPreference;
|
|
14
|
+
declare function validateOrThrow(input: unknown): PronounPreference;
|
|
15
|
+
declare function validationErrors(input: unknown): string[];
|
|
16
|
+
|
|
17
|
+
declare function filterByAudience(preference: PronounPreference, audience: string): PronounPreference;
|
|
18
|
+
|
|
19
|
+
interface CanonicalEntry {
|
|
20
|
+
readonly subjective: string;
|
|
21
|
+
readonly objective: string;
|
|
22
|
+
readonly possessive_adjective: string;
|
|
23
|
+
readonly possessive_pronoun: string;
|
|
24
|
+
readonly reflexive: string;
|
|
25
|
+
}
|
|
26
|
+
declare const PRONOUN_DICTIONARY: readonly CanonicalEntry[];
|
|
27
|
+
declare const FORM_TO_SET: ReadonlyMap<string, CanonicalEntry>;
|
|
28
|
+
declare const SPECIAL_KEYWORDS: {
|
|
29
|
+
readonly any: readonly ["any", "any pronoun", "any pronouns", "any/all", "all/any", "any and all", "any and all pronouns", "all", "all pronouns", "no preference", "whatever", "whatever you want", "whatever you prefer", "whatever is fine", "whatever you feel comfortable", "i don't care", "i dont care", "idc", "doesn't matter", "doesnt matter", "i go by all", "most are acceptable"];
|
|
30
|
+
readonly none: readonly ["none", "no pronouns", "avoid pronouns", "use my name", "name only", "just my name", "refer to me by name"];
|
|
31
|
+
readonly ask: readonly ["ask", "ask me", "ask my pronouns", "ask me my pronouns", "please ask"];
|
|
32
|
+
readonly unspecified: readonly ["unsure", "not sure", "not sure yet", "prefer not to disclose", "prefer not to say", "choose not to disclose", "undecided", "i don't know", "i dont know", "don't know", "dont know", "don't know yet", "dont know yet", "dunno", "private"];
|
|
33
|
+
};
|
|
34
|
+
declare const PLACEHOLDER_STRINGS: readonly string[];
|
|
35
|
+
declare const FILLER_PATTERNS: readonly RegExp[];
|
|
36
|
+
|
|
37
|
+
export { type CanonicalEntry, FILLER_PATTERNS, FORM_TO_SET, type FormatOptions, PLACEHOLDER_STRINGS, PRONOUN_DICTIONARY, SPECIAL_KEYWORDS, filterByAudience, format, parse, validate, validateOrThrow, validationErrors };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
// src/constants.ts
|
|
2
|
+
var PRONOUN_DICTIONARY = [
|
|
3
|
+
// Common sets
|
|
4
|
+
{
|
|
5
|
+
subjective: "she",
|
|
6
|
+
objective: "her",
|
|
7
|
+
possessive_adjective: "her",
|
|
8
|
+
possessive_pronoun: "hers",
|
|
9
|
+
reflexive: "herself"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
subjective: "he",
|
|
13
|
+
objective: "him",
|
|
14
|
+
possessive_adjective: "his",
|
|
15
|
+
possessive_pronoun: "his",
|
|
16
|
+
reflexive: "himself"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
subjective: "they",
|
|
20
|
+
objective: "them",
|
|
21
|
+
possessive_adjective: "their",
|
|
22
|
+
possessive_pronoun: "theirs",
|
|
23
|
+
reflexive: "themselves"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
subjective: "it",
|
|
27
|
+
objective: "it",
|
|
28
|
+
possessive_adjective: "its",
|
|
29
|
+
possessive_pronoun: "its",
|
|
30
|
+
reflexive: "itself"
|
|
31
|
+
},
|
|
32
|
+
// Neopronouns
|
|
33
|
+
{
|
|
34
|
+
subjective: "xe",
|
|
35
|
+
objective: "xem",
|
|
36
|
+
possessive_adjective: "xyr",
|
|
37
|
+
possessive_pronoun: "xyrs",
|
|
38
|
+
reflexive: "xemself"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
subjective: "ze",
|
|
42
|
+
objective: "zir",
|
|
43
|
+
possessive_adjective: "zir",
|
|
44
|
+
possessive_pronoun: "zirs",
|
|
45
|
+
reflexive: "zirself"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
subjective: "fae",
|
|
49
|
+
objective: "faer",
|
|
50
|
+
possessive_adjective: "faer",
|
|
51
|
+
possessive_pronoun: "faers",
|
|
52
|
+
reflexive: "faerself"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
subjective: "per",
|
|
56
|
+
objective: "per",
|
|
57
|
+
possessive_adjective: "per",
|
|
58
|
+
possessive_pronoun: "pers",
|
|
59
|
+
reflexive: "perself"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
subjective: "ey",
|
|
63
|
+
objective: "em",
|
|
64
|
+
possessive_adjective: "eir",
|
|
65
|
+
possessive_pronoun: "eirs",
|
|
66
|
+
reflexive: "emself"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
subjective: "e",
|
|
70
|
+
objective: "em",
|
|
71
|
+
possessive_adjective: "eir",
|
|
72
|
+
possessive_pronoun: "eirs",
|
|
73
|
+
reflexive: "emself"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
subjective: "ze",
|
|
77
|
+
objective: "hir",
|
|
78
|
+
possessive_adjective: "hir",
|
|
79
|
+
possessive_pronoun: "hirs",
|
|
80
|
+
reflexive: "hirself"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
subjective: "ae",
|
|
84
|
+
objective: "aer",
|
|
85
|
+
possessive_adjective: "aer",
|
|
86
|
+
possessive_pronoun: "aers",
|
|
87
|
+
reflexive: "aerself"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
subjective: "co",
|
|
91
|
+
objective: "co",
|
|
92
|
+
possessive_adjective: "cos",
|
|
93
|
+
possessive_pronoun: "cos",
|
|
94
|
+
reflexive: "coself"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
subjective: "ne",
|
|
98
|
+
objective: "nem",
|
|
99
|
+
possessive_adjective: "nir",
|
|
100
|
+
possessive_pronoun: "nirs",
|
|
101
|
+
reflexive: "nemself"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
subjective: "thon",
|
|
105
|
+
objective: "thon",
|
|
106
|
+
possessive_adjective: "thons",
|
|
107
|
+
possessive_pronoun: "thons",
|
|
108
|
+
reflexive: "thonself"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
subjective: "ve",
|
|
112
|
+
objective: "ver",
|
|
113
|
+
possessive_adjective: "vis",
|
|
114
|
+
possessive_pronoun: "vis",
|
|
115
|
+
reflexive: "verself"
|
|
116
|
+
}
|
|
117
|
+
];
|
|
118
|
+
function buildFormToSet() {
|
|
119
|
+
const map = /* @__PURE__ */ new Map();
|
|
120
|
+
for (const entry of PRONOUN_DICTIONARY) {
|
|
121
|
+
map.set(entry.subjective, entry);
|
|
122
|
+
}
|
|
123
|
+
for (const entry of PRONOUN_DICTIONARY) {
|
|
124
|
+
for (const form of [
|
|
125
|
+
entry.objective,
|
|
126
|
+
entry.possessive_adjective,
|
|
127
|
+
entry.possessive_pronoun,
|
|
128
|
+
entry.reflexive
|
|
129
|
+
]) {
|
|
130
|
+
if (!map.has(form)) {
|
|
131
|
+
map.set(form, entry);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return map;
|
|
136
|
+
}
|
|
137
|
+
var FORM_TO_SET = buildFormToSet();
|
|
138
|
+
var SPECIAL_KEYWORDS = {
|
|
139
|
+
any: [
|
|
140
|
+
"any",
|
|
141
|
+
"any pronoun",
|
|
142
|
+
"any pronouns",
|
|
143
|
+
"any/all",
|
|
144
|
+
"all/any",
|
|
145
|
+
"any and all",
|
|
146
|
+
"any and all pronouns",
|
|
147
|
+
"all",
|
|
148
|
+
"all pronouns",
|
|
149
|
+
"no preference",
|
|
150
|
+
"whatever",
|
|
151
|
+
"whatever you want",
|
|
152
|
+
"whatever you prefer",
|
|
153
|
+
"whatever is fine",
|
|
154
|
+
"whatever you feel comfortable",
|
|
155
|
+
"i don't care",
|
|
156
|
+
"i dont care",
|
|
157
|
+
"idc",
|
|
158
|
+
"doesn't matter",
|
|
159
|
+
"doesnt matter",
|
|
160
|
+
"i go by all",
|
|
161
|
+
"most are acceptable"
|
|
162
|
+
],
|
|
163
|
+
none: [
|
|
164
|
+
"none",
|
|
165
|
+
"no pronouns",
|
|
166
|
+
"avoid pronouns",
|
|
167
|
+
"use my name",
|
|
168
|
+
"name only",
|
|
169
|
+
"just my name",
|
|
170
|
+
"refer to me by name"
|
|
171
|
+
],
|
|
172
|
+
ask: ["ask", "ask me", "ask my pronouns", "ask me my pronouns", "please ask"],
|
|
173
|
+
unspecified: [
|
|
174
|
+
"unsure",
|
|
175
|
+
"not sure",
|
|
176
|
+
"not sure yet",
|
|
177
|
+
"prefer not to disclose",
|
|
178
|
+
"prefer not to say",
|
|
179
|
+
"choose not to disclose",
|
|
180
|
+
"undecided",
|
|
181
|
+
"i don't know",
|
|
182
|
+
"i dont know",
|
|
183
|
+
"don't know",
|
|
184
|
+
"dont know",
|
|
185
|
+
"don't know yet",
|
|
186
|
+
"dont know yet",
|
|
187
|
+
"dunno",
|
|
188
|
+
"private"
|
|
189
|
+
]
|
|
190
|
+
};
|
|
191
|
+
var PLACEHOLDER_STRINGS = [
|
|
192
|
+
"n/a",
|
|
193
|
+
"na",
|
|
194
|
+
"tbd",
|
|
195
|
+
"-",
|
|
196
|
+
"none given"
|
|
197
|
+
];
|
|
198
|
+
var FILLER_PATTERNS = [
|
|
199
|
+
// suffix fillers
|
|
200
|
+
/\s+is\s+fine\s*$/i,
|
|
201
|
+
/\s+are\s+fine\s*$/i,
|
|
202
|
+
/\s+also\s*$/i,
|
|
203
|
+
/\s+as\s+well\s*$/i,
|
|
204
|
+
/\s+preferred\s*$/i,
|
|
205
|
+
/\s+only\s*$/i,
|
|
206
|
+
/\s+please\s*$/i,
|
|
207
|
+
/\s+now\s*$/i,
|
|
208
|
+
// prefix fillers
|
|
209
|
+
/^please\s+/i,
|
|
210
|
+
/^only\s+/i,
|
|
211
|
+
/^just\s+use\s+/i,
|
|
212
|
+
/^i\s+use\s+/i,
|
|
213
|
+
/^i\s+go\s+by\s+/i,
|
|
214
|
+
// whole-segment filler phrase
|
|
215
|
+
/^relevant\s+pronouns\s+are\s+fine\s*$/i
|
|
216
|
+
];
|
|
217
|
+
|
|
218
|
+
// src/parser/index.ts
|
|
219
|
+
function matchSpecialKeyword(text) {
|
|
220
|
+
for (const [type, keywords] of Object.entries(SPECIAL_KEYWORDS)) {
|
|
221
|
+
if (keywords.includes(text)) return type;
|
|
222
|
+
}
|
|
223
|
+
return void 0;
|
|
224
|
+
}
|
|
225
|
+
function isPlaceholder(text) {
|
|
226
|
+
return PLACEHOLDER_STRINGS.includes(text);
|
|
227
|
+
}
|
|
228
|
+
function formBelongsToEntry(form, entry) {
|
|
229
|
+
return entry.subjective === form || entry.objective === form || entry.possessive_adjective === form || entry.possessive_pronoun === form || entry.reflexive === form;
|
|
230
|
+
}
|
|
231
|
+
function makeStandardEntry(set, context, excluded2) {
|
|
232
|
+
const entry = {
|
|
233
|
+
subjective: set.subjective,
|
|
234
|
+
objective: set.objective,
|
|
235
|
+
possessive_adjective: set.possessive_adjective,
|
|
236
|
+
possessive_pronoun: set.possessive_pronoun,
|
|
237
|
+
reflexive: set.reflexive
|
|
238
|
+
};
|
|
239
|
+
if (context !== void 0) entry["context"] = context;
|
|
240
|
+
if (excluded2) entry["exclude"] = true;
|
|
241
|
+
return entry;
|
|
242
|
+
}
|
|
243
|
+
function resolveTokens(tokensLc, originalText, context, excluded2) {
|
|
244
|
+
const hasKnownToken = tokensLc.some((t) => FORM_TO_SET.has(t));
|
|
245
|
+
if (!hasKnownToken) {
|
|
246
|
+
const entry = { type: "custom", display: originalText };
|
|
247
|
+
if (context !== void 0) entry.context = context;
|
|
248
|
+
if (excluded2) entry.exclude = true;
|
|
249
|
+
return [entry];
|
|
250
|
+
}
|
|
251
|
+
const result = [];
|
|
252
|
+
let currentSet = null;
|
|
253
|
+
for (const token of tokensLc) {
|
|
254
|
+
const candidate = FORM_TO_SET.get(token);
|
|
255
|
+
if (!candidate) continue;
|
|
256
|
+
if (currentSet === null) {
|
|
257
|
+
currentSet = candidate;
|
|
258
|
+
} else if (candidate === currentSet || formBelongsToEntry(token, currentSet)) {
|
|
259
|
+
} else if (candidate.subjective === currentSet.subjective) {
|
|
260
|
+
currentSet = candidate;
|
|
261
|
+
} else {
|
|
262
|
+
result.push(makeStandardEntry(currentSet, context, excluded2));
|
|
263
|
+
currentSet = candidate;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (currentSet !== null) {
|
|
267
|
+
result.push(makeStandardEntry(currentSet, context, excluded2));
|
|
268
|
+
}
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
function deduplicateEntries(entries) {
|
|
272
|
+
const seen = /* @__PURE__ */ new Set();
|
|
273
|
+
return entries.filter((entry) => {
|
|
274
|
+
let key;
|
|
275
|
+
if ("type" in entry && entry.type !== "custom") {
|
|
276
|
+
key = `special:${entry.type}`;
|
|
277
|
+
} else if ("type" in entry && entry.type === "custom") {
|
|
278
|
+
key = `custom:${entry.display}`;
|
|
279
|
+
} else if ("subjective" in entry && entry.subjective) {
|
|
280
|
+
key = `sub:${entry.subjective}`;
|
|
281
|
+
} else if ("sub" in entry && entry.sub) {
|
|
282
|
+
key = `sub:${entry.sub}`;
|
|
283
|
+
} else {
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
if (seen.has(key)) return false;
|
|
287
|
+
seen.add(key);
|
|
288
|
+
return true;
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
function parse(input) {
|
|
292
|
+
if (!input?.trim()) return null;
|
|
293
|
+
const text = input.replace(/[‘’‛]/g, "'").replace(/^["'](.+)["']$/, "$1").replace(/\\/g, "/").replace(/\s*\/\s*/g, "/").replace(/\s+/g, " ").trim();
|
|
294
|
+
if (!text) return null;
|
|
295
|
+
const textLc = text.toLowerCase();
|
|
296
|
+
if (isPlaceholder(textLc)) return null;
|
|
297
|
+
const wholeSpecialType = matchSpecialKeyword(textLc);
|
|
298
|
+
if (wholeSpecialType) return [{ type: wholeSpecialType }];
|
|
299
|
+
const segments = text.split(/,\s*|;\s*|\s+&\s+|\s+and\s+|\s+or\s+/i);
|
|
300
|
+
const entries = [];
|
|
301
|
+
for (const rawSeg of segments) {
|
|
302
|
+
const seg = rawSeg.trim();
|
|
303
|
+
if (!seg) continue;
|
|
304
|
+
let workSeg = seg;
|
|
305
|
+
let workLc = seg.toLowerCase();
|
|
306
|
+
let context;
|
|
307
|
+
const parenMatch = workSeg.match(/\s*\(([^)]+)\)\s*$/) ?? workSeg.match(/\s*\[([^\]]+)\]\s*$/);
|
|
308
|
+
if (parenMatch) {
|
|
309
|
+
context = parenMatch[1].trim() || void 0;
|
|
310
|
+
workSeg = workSeg.slice(0, parenMatch.index).trim();
|
|
311
|
+
workLc = workSeg.toLowerCase();
|
|
312
|
+
}
|
|
313
|
+
for (const pattern of FILLER_PATTERNS) {
|
|
314
|
+
workSeg = workSeg.replace(pattern, "").trim();
|
|
315
|
+
}
|
|
316
|
+
workLc = workSeg.toLowerCase();
|
|
317
|
+
if (!workLc) continue;
|
|
318
|
+
const segSpecialType = matchSpecialKeyword(workLc);
|
|
319
|
+
if (segSpecialType) {
|
|
320
|
+
const entry = { type: segSpecialType };
|
|
321
|
+
if (context !== void 0)
|
|
322
|
+
entry["context"] = context;
|
|
323
|
+
entries.push(entry);
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
if (isPlaceholder(workLc)) continue;
|
|
327
|
+
let excluded2 = false;
|
|
328
|
+
const exclusionMatch = workLc.match(
|
|
329
|
+
/^(?:just\s+not|not|never|except)\s+(.+)$/
|
|
330
|
+
);
|
|
331
|
+
if (exclusionMatch) {
|
|
332
|
+
excluded2 = true;
|
|
333
|
+
const remainder = exclusionMatch[1];
|
|
334
|
+
workSeg = workSeg.slice(workSeg.length - remainder.length);
|
|
335
|
+
workLc = remainder;
|
|
336
|
+
}
|
|
337
|
+
const tokensLc = workLc.split(/[/ ]+/).filter(Boolean);
|
|
338
|
+
if (tokensLc.length === 0) continue;
|
|
339
|
+
const resolved = resolveTokens(tokensLc, workSeg, context, excluded2);
|
|
340
|
+
entries.push(...resolved);
|
|
341
|
+
}
|
|
342
|
+
const deduped = deduplicateEntries(entries);
|
|
343
|
+
return deduped.length > 0 ? deduped : null;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// src/formatter.ts
|
|
347
|
+
function sub(e) {
|
|
348
|
+
if ("subjective" in e) return e.subjective;
|
|
349
|
+
if ("sub" in e) return e.sub;
|
|
350
|
+
return void 0;
|
|
351
|
+
}
|
|
352
|
+
function obj(e) {
|
|
353
|
+
if ("objective" in e) return e.objective;
|
|
354
|
+
if ("obj" in e) return e.obj;
|
|
355
|
+
return void 0;
|
|
356
|
+
}
|
|
357
|
+
function ppn(e) {
|
|
358
|
+
if ("possessive_pronoun" in e) return e.possessive_pronoun;
|
|
359
|
+
if ("p_pn" in e) return e.p_pn;
|
|
360
|
+
return void 0;
|
|
361
|
+
}
|
|
362
|
+
function ctx(e) {
|
|
363
|
+
if ("context" in e && e.context) return e.context;
|
|
364
|
+
if ("ctx" in e && e.ctx)
|
|
365
|
+
return e.ctx;
|
|
366
|
+
return void 0;
|
|
367
|
+
}
|
|
368
|
+
function ranking(e) {
|
|
369
|
+
if ("ranking" in e && e.ranking !== void 0) return e.ranking;
|
|
370
|
+
if ("rnk" in e && e.rnk !== void 0)
|
|
371
|
+
return e.rnk;
|
|
372
|
+
return void 0;
|
|
373
|
+
}
|
|
374
|
+
function privacy(e) {
|
|
375
|
+
if ("privacy" in e && e.privacy !== void 0) return e.privacy;
|
|
376
|
+
if ("pvc" in e && e.pvc !== void 0)
|
|
377
|
+
return e.pvc;
|
|
378
|
+
return void 0;
|
|
379
|
+
}
|
|
380
|
+
function excluded(e) {
|
|
381
|
+
if ("exclude" in e && e.exclude === true) return true;
|
|
382
|
+
if ("exc" in e && e.exc === true) return true;
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
function capitalize(s) {
|
|
386
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
387
|
+
}
|
|
388
|
+
function capitalizeSlashSeparated(s) {
|
|
389
|
+
return s.split("/").map(capitalize).join("/");
|
|
390
|
+
}
|
|
391
|
+
function formatSingleEntry(entry, form) {
|
|
392
|
+
if ("type" in entry) {
|
|
393
|
+
const t = entry.type;
|
|
394
|
+
if (t === "any") return "Any pronouns";
|
|
395
|
+
if (t === "none") return "No pronouns (use name)";
|
|
396
|
+
if (t === "ask") return "Ask me my pronouns";
|
|
397
|
+
if (t === "unspecified") return "Unspecified";
|
|
398
|
+
if (t === "custom") {
|
|
399
|
+
const display = entry.display;
|
|
400
|
+
return capitalizeSlashSeparated(display);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
const s = sub(entry);
|
|
404
|
+
const o = obj(entry);
|
|
405
|
+
const p = ppn(entry);
|
|
406
|
+
if (!s || !o) return "";
|
|
407
|
+
let base;
|
|
408
|
+
if (form === "expanded") {
|
|
409
|
+
base = `${capitalize(s)}/${capitalize(o)}/${capitalize(p ?? o)}`;
|
|
410
|
+
} else {
|
|
411
|
+
base = `${capitalize(s)}/${capitalize(o)}`;
|
|
412
|
+
}
|
|
413
|
+
const context = ctx(entry);
|
|
414
|
+
if (context) base += ` (${context})`;
|
|
415
|
+
return base;
|
|
416
|
+
}
|
|
417
|
+
function format(preference, options = {}) {
|
|
418
|
+
const form = options.form ?? "short";
|
|
419
|
+
const isPublic = options.audience === "public";
|
|
420
|
+
let visible = preference.filter((e) => {
|
|
421
|
+
if (isPublic) {
|
|
422
|
+
const p = privacy(e);
|
|
423
|
+
if (p !== void 0 && p >= 1) return false;
|
|
424
|
+
}
|
|
425
|
+
return true;
|
|
426
|
+
});
|
|
427
|
+
visible = [...visible].sort((a, b) => {
|
|
428
|
+
const ra = ranking(a);
|
|
429
|
+
const rb = ranking(b);
|
|
430
|
+
if (ra !== void 0 && rb !== void 0) return ra - rb;
|
|
431
|
+
if (ra !== void 0) return -1;
|
|
432
|
+
if (rb !== void 0) return 1;
|
|
433
|
+
return 0;
|
|
434
|
+
});
|
|
435
|
+
if (form === "detailed") {
|
|
436
|
+
const positive = visible.filter((e) => !excluded(e));
|
|
437
|
+
const negative = visible.filter((e) => excluded(e));
|
|
438
|
+
const posStr = positive.map((e) => formatSingleEntry(e, "short")).filter(Boolean).join(", ");
|
|
439
|
+
if (negative.length === 0) return posStr;
|
|
440
|
+
const negStr = negative.map((e) => {
|
|
441
|
+
const s = sub(e);
|
|
442
|
+
const o = obj(e);
|
|
443
|
+
return s && o ? `not ${capitalize(s)}/${capitalize(o)}` : "";
|
|
444
|
+
}).filter(Boolean).join(", ");
|
|
445
|
+
return negStr ? `${posStr} (${negStr})` : posStr;
|
|
446
|
+
}
|
|
447
|
+
const displayable = visible.filter((e) => !excluded(e));
|
|
448
|
+
return displayable.map((e) => formatSingleEntry(e, form)).filter(Boolean).join(", ");
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// src/types.ts
|
|
452
|
+
import {
|
|
453
|
+
pronounPreferenceSchema,
|
|
454
|
+
pronounEntrySchema,
|
|
455
|
+
pronounSetSchema,
|
|
456
|
+
specialPreferenceSchema,
|
|
457
|
+
customEntrySchema,
|
|
458
|
+
SPECIAL_TYPES
|
|
459
|
+
} from "@openpronoun/zod";
|
|
460
|
+
|
|
461
|
+
// src/validator.ts
|
|
462
|
+
function validate(input) {
|
|
463
|
+
return pronounPreferenceSchema.safeParse(input).success;
|
|
464
|
+
}
|
|
465
|
+
function validateOrThrow(input) {
|
|
466
|
+
return pronounPreferenceSchema.parse(input);
|
|
467
|
+
}
|
|
468
|
+
function validationErrors(input) {
|
|
469
|
+
const result = pronounPreferenceSchema.safeParse(input);
|
|
470
|
+
if (result.success) return [];
|
|
471
|
+
return result.error.issues.map(
|
|
472
|
+
(e) => `${e.path.map(String).join(".")}: ${e.message}`
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// src/privacy.ts
|
|
477
|
+
function filterByAudience(preference, audience) {
|
|
478
|
+
if (audience !== "public") return preference;
|
|
479
|
+
return preference.filter((entry) => {
|
|
480
|
+
const p = "privacy" in entry ? entry.privacy : "pvc" in entry ? entry.pvc : void 0;
|
|
481
|
+
return p === void 0 || p < 1;
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
export {
|
|
485
|
+
FILLER_PATTERNS,
|
|
486
|
+
FORM_TO_SET,
|
|
487
|
+
PLACEHOLDER_STRINGS,
|
|
488
|
+
PRONOUN_DICTIONARY,
|
|
489
|
+
SPECIAL_KEYWORDS,
|
|
490
|
+
SPECIAL_TYPES,
|
|
491
|
+
customEntrySchema,
|
|
492
|
+
filterByAudience,
|
|
493
|
+
format,
|
|
494
|
+
parse,
|
|
495
|
+
pronounEntrySchema,
|
|
496
|
+
pronounPreferenceSchema,
|
|
497
|
+
pronounSetSchema,
|
|
498
|
+
specialPreferenceSchema,
|
|
499
|
+
validate,
|
|
500
|
+
validateOrThrow,
|
|
501
|
+
validationErrors
|
|
502
|
+
};
|
|
503
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/parser/index.ts","../src/formatter.ts","../src/types.ts","../src/validator.ts","../src/privacy.ts"],"sourcesContent":["export interface CanonicalEntry {\n readonly subjective: string;\n readonly objective: string;\n readonly possessive_adjective: string;\n readonly possessive_pronoun: string;\n readonly reflexive: string;\n}\n\nexport const PRONOUN_DICTIONARY: readonly CanonicalEntry[] = [\n // Common sets\n {\n subjective: \"she\",\n objective: \"her\",\n possessive_adjective: \"her\",\n possessive_pronoun: \"hers\",\n reflexive: \"herself\",\n },\n {\n subjective: \"he\",\n objective: \"him\",\n possessive_adjective: \"his\",\n possessive_pronoun: \"his\",\n reflexive: \"himself\",\n },\n {\n subjective: \"they\",\n objective: \"them\",\n possessive_adjective: \"their\",\n possessive_pronoun: \"theirs\",\n reflexive: \"themselves\",\n },\n {\n subjective: \"it\",\n objective: \"it\",\n possessive_adjective: \"its\",\n possessive_pronoun: \"its\",\n reflexive: \"itself\",\n },\n // Neopronouns\n {\n subjective: \"xe\",\n objective: \"xem\",\n possessive_adjective: \"xyr\",\n possessive_pronoun: \"xyrs\",\n reflexive: \"xemself\",\n },\n {\n subjective: \"ze\",\n objective: \"zir\",\n possessive_adjective: \"zir\",\n possessive_pronoun: \"zirs\",\n reflexive: \"zirself\",\n },\n {\n subjective: \"fae\",\n objective: \"faer\",\n possessive_adjective: \"faer\",\n possessive_pronoun: \"faers\",\n reflexive: \"faerself\",\n },\n {\n subjective: \"per\",\n objective: \"per\",\n possessive_adjective: \"per\",\n possessive_pronoun: \"pers\",\n reflexive: \"perself\",\n },\n {\n subjective: \"ey\",\n objective: \"em\",\n possessive_adjective: \"eir\",\n possessive_pronoun: \"eirs\",\n reflexive: \"emself\",\n },\n {\n subjective: \"e\",\n objective: \"em\",\n possessive_adjective: \"eir\",\n possessive_pronoun: \"eirs\",\n reflexive: \"emself\",\n },\n {\n subjective: \"ze\",\n objective: \"hir\",\n possessive_adjective: \"hir\",\n possessive_pronoun: \"hirs\",\n reflexive: \"hirself\",\n },\n {\n subjective: \"ae\",\n objective: \"aer\",\n possessive_adjective: \"aer\",\n possessive_pronoun: \"aers\",\n reflexive: \"aerself\",\n },\n {\n subjective: \"co\",\n objective: \"co\",\n possessive_adjective: \"cos\",\n possessive_pronoun: \"cos\",\n reflexive: \"coself\",\n },\n {\n subjective: \"ne\",\n objective: \"nem\",\n possessive_adjective: \"nir\",\n possessive_pronoun: \"nirs\",\n reflexive: \"nemself\",\n },\n {\n subjective: \"thon\",\n objective: \"thon\",\n possessive_adjective: \"thons\",\n possessive_pronoun: \"thons\",\n reflexive: \"thonself\",\n },\n {\n subjective: \"ve\",\n objective: \"ver\",\n possessive_adjective: \"vis\",\n possessive_pronoun: \"vis\",\n reflexive: \"verself\",\n },\n] as const;\n\n// Reverse lookup: any known form → its canonical entry.\n// Subjective always takes priority; other forms use first-write-wins.\nfunction buildFormToSet(): Map<string, CanonicalEntry> {\n const map = new Map<string, CanonicalEntry>();\n for (const entry of PRONOUN_DICTIONARY) {\n // Subjective always wins (overwrite)\n map.set(entry.subjective, entry);\n }\n for (const entry of PRONOUN_DICTIONARY) {\n for (const form of [\n entry.objective,\n entry.possessive_adjective,\n entry.possessive_pronoun,\n entry.reflexive,\n ]) {\n if (!map.has(form)) {\n map.set(form, entry);\n }\n }\n }\n return map;\n}\n\nexport const FORM_TO_SET: ReadonlyMap<string, CanonicalEntry> =\n buildFormToSet();\n\nexport const SPECIAL_KEYWORDS = {\n any: [\n \"any\",\n \"any pronoun\",\n \"any pronouns\",\n \"any/all\",\n \"all/any\",\n \"any and all\",\n \"any and all pronouns\",\n \"all\",\n \"all pronouns\",\n \"no preference\",\n \"whatever\",\n \"whatever you want\",\n \"whatever you prefer\",\n \"whatever is fine\",\n \"whatever you feel comfortable\",\n \"i don't care\",\n \"i dont care\",\n \"idc\",\n \"doesn't matter\",\n \"doesnt matter\",\n \"i go by all\",\n \"most are acceptable\",\n ],\n none: [\n \"none\",\n \"no pronouns\",\n \"avoid pronouns\",\n \"use my name\",\n \"name only\",\n \"just my name\",\n \"refer to me by name\",\n ],\n ask: [\"ask\", \"ask me\", \"ask my pronouns\", \"ask me my pronouns\", \"please ask\"],\n unspecified: [\n \"unsure\",\n \"not sure\",\n \"not sure yet\",\n \"prefer not to disclose\",\n \"prefer not to say\",\n \"choose not to disclose\",\n \"undecided\",\n \"i don't know\",\n \"i dont know\",\n \"don't know\",\n \"dont know\",\n \"don't know yet\",\n \"dont know yet\",\n \"dunno\",\n \"private\",\n ],\n} as const;\n\nexport const PLACEHOLDER_STRINGS: readonly string[] = [\n \"n/a\",\n \"na\",\n \"tbd\",\n \"-\",\n \"none given\",\n];\n\nexport const FILLER_PATTERNS: readonly RegExp[] = [\n // suffix fillers\n /\\s+is\\s+fine\\s*$/i,\n /\\s+are\\s+fine\\s*$/i,\n /\\s+also\\s*$/i,\n /\\s+as\\s+well\\s*$/i,\n /\\s+preferred\\s*$/i,\n /\\s+only\\s*$/i,\n /\\s+please\\s*$/i,\n /\\s+now\\s*$/i,\n // prefix fillers\n /^please\\s+/i,\n /^only\\s+/i,\n /^just\\s+use\\s+/i,\n /^i\\s+use\\s+/i,\n /^i\\s+go\\s+by\\s+/i,\n // whole-segment filler phrase\n /^relevant\\s+pronouns\\s+are\\s+fine\\s*$/i,\n];\n","import type {\n CustomEntry,\n PronounEntry,\n PronounPreference,\n SpecialPreference,\n} from \"../types\";\n\nimport {\n FILLER_PATTERNS,\n FORM_TO_SET,\n PLACEHOLDER_STRINGS,\n SPECIAL_KEYWORDS,\n type CanonicalEntry,\n} from \"../constants\";\n\ntype SpecialType = \"any\" | \"none\" | \"ask\" | \"unspecified\";\n\nfunction matchSpecialKeyword(text: string): SpecialType | undefined {\n for (const [type, keywords] of Object.entries(SPECIAL_KEYWORDS) as [\n SpecialType,\n readonly string[],\n ][]) {\n if ((keywords as readonly string[]).includes(text)) return type;\n }\n return undefined;\n}\n\nfunction stripFiller(text: string): string {\n let s = text;\n for (const pattern of FILLER_PATTERNS) {\n s = s.replace(pattern, \"\").trim();\n }\n return s;\n}\n\nfunction isPlaceholder(text: string): boolean {\n return PLACEHOLDER_STRINGS.includes(text);\n}\n\nfunction formBelongsToEntry(form: string, entry: CanonicalEntry): boolean {\n return (\n entry.subjective === form ||\n entry.objective === form ||\n entry.possessive_adjective === form ||\n entry.possessive_pronoun === form ||\n entry.reflexive === form\n );\n}\n\nfunction makeStandardEntry(\n set: CanonicalEntry,\n context: string | undefined,\n excluded: boolean,\n): PronounEntry {\n const entry: Record<string, unknown> = {\n subjective: set.subjective,\n objective: set.objective,\n possessive_adjective: set.possessive_adjective,\n possessive_pronoun: set.possessive_pronoun,\n reflexive: set.reflexive,\n };\n if (context !== undefined) entry[\"context\"] = context;\n if (excluded) entry[\"exclude\"] = true;\n return entry as PronounEntry;\n}\n\nfunction resolveTokens(\n tokensLc: string[],\n originalText: string,\n context: string | undefined,\n excluded: boolean,\n): PronounEntry[] {\n const hasKnownToken = tokensLc.some((t) => FORM_TO_SET.has(t));\n\n if (!hasKnownToken) {\n const entry: CustomEntry = { type: \"custom\", display: originalText };\n if (context !== undefined) entry.context = context;\n if (excluded) entry.exclude = true;\n return [entry];\n }\n\n const result: PronounEntry[] = [];\n let currentSet: CanonicalEntry | null = null;\n\n for (const token of tokensLc) {\n const candidate = FORM_TO_SET.get(token);\n if (!candidate) continue;\n\n if (currentSet === null) {\n currentSet = candidate;\n } else if (\n candidate === currentSet ||\n formBelongsToEntry(token, currentSet)\n ) {\n // same set or an alternate form of the current set — keep accumulating\n } else if (candidate.subjective === currentSet.subjective) {\n // same subjective, different set — disambiguation token (e.g. \"zir\" after \"ze\")\n currentSet = candidate;\n } else {\n result.push(makeStandardEntry(currentSet, context, excluded));\n currentSet = candidate;\n }\n }\n\n if (currentSet !== null) {\n result.push(makeStandardEntry(currentSet, context, excluded));\n }\n\n return result;\n}\n\nfunction deduplicateEntries(entries: PronounEntry[]): PronounEntry[] {\n const seen = new Set<string>();\n return entries.filter((entry) => {\n let key: string;\n if (\"type\" in entry && entry.type !== \"custom\") {\n key = `special:${entry.type}`;\n } else if (\"type\" in entry && entry.type === \"custom\") {\n key = `custom:${(entry as CustomEntry).display}`;\n } else if (\"subjective\" in entry && entry.subjective) {\n key = `sub:${entry.subjective}`;\n } else if (\"sub\" in entry && (entry as { sub?: string }).sub) {\n key = `sub:${(entry as { sub?: string }).sub}`;\n } else {\n return true;\n }\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nexport function parse(\n input: string | null | undefined,\n): PronounPreference | null {\n if (!input?.trim()) return null;\n\n // Normalize: smart quotes, surrounding quotes, backslash→slash,\n // spaces around slashes, collapsed whitespace.\n const text = input\n .replace(/[‘’‛]/g, \"'\")\n .replace(/^[\"'](.+)[\"']$/, \"$1\")\n .replace(/\\\\/g, \"/\")\n .replace(/\\s*\\/\\s*/g, \"/\")\n .replace(/\\s+/g, \" \")\n .trim();\n\n if (!text) return null;\n\n const textLc = text.toLowerCase();\n\n if (isPlaceholder(textLc)) return null;\n\n // Check whole input against special keywords before splitting.\n const wholeSpecialType = matchSpecialKeyword(textLc);\n if (wholeSpecialType) return [{ type: wholeSpecialType }];\n\n // Split on set-level separators: comma, semicolon, ampersand, \"and\", \"or\".\n const segments = text.split(/,\\s*|;\\s*|\\s+&\\s+|\\s+and\\s+|\\s+or\\s+/i);\n\n const entries: PronounEntry[] = [];\n\n for (const rawSeg of segments) {\n const seg = rawSeg.trim();\n if (!seg) continue;\n\n let workSeg = seg;\n let workLc = seg.toLowerCase();\n\n // Extract parenthetical or bracketed context: \"she/her (at work)\" or \"[at work]\".\n let context: string | undefined;\n const parenMatch =\n workSeg.match(/\\s*\\(([^)]+)\\)\\s*$/) ??\n workSeg.match(/\\s*\\[([^\\]]+)\\]\\s*$/);\n if (parenMatch) {\n context = parenMatch[1]!.trim() || undefined;\n workSeg = workSeg.slice(0, parenMatch.index!).trim();\n workLc = workSeg.toLowerCase();\n }\n\n // Strip filler phrases — apply FILLER_PATTERNS to the original-case workSeg\n // (all patterns have /i), then re-derive workLc.\n for (const pattern of FILLER_PATTERNS) {\n workSeg = workSeg.replace(pattern, \"\").trim();\n }\n workLc = workSeg.toLowerCase();\n\n if (!workLc) continue;\n\n // Check special keyword BEFORE exclusion detection so that phrases like\n // \"not sure yet\" are caught here and not misread as exclusions.\n const segSpecialType = matchSpecialKeyword(workLc);\n if (segSpecialType) {\n const entry: SpecialPreference = { type: segSpecialType };\n if (context !== undefined)\n (entry as Record<string, unknown>)[\"context\"] = context;\n entries.push(entry);\n continue;\n }\n\n // Placeholder check.\n if (isPlaceholder(workLc)) continue;\n\n // Detect and strip exclusion prefix (\"just not\", \"not\", \"never\", \"except\").\n let excluded = false;\n const exclusionMatch = workLc.match(\n /^(?:just\\s+not|not|never|except)\\s+(.+)$/,\n );\n if (exclusionMatch) {\n excluded = true;\n const remainder = exclusionMatch[1]!;\n workSeg = workSeg.slice(workSeg.length - remainder.length);\n workLc = remainder;\n }\n\n // Tokenize by \"/\" and space, resolve to known sets.\n const tokensLc = workLc.split(/[/ ]+/).filter(Boolean);\n if (tokensLc.length === 0) continue;\n\n const resolved = resolveTokens(tokensLc, workSeg, context, excluded);\n entries.push(...resolved);\n }\n\n const deduped = deduplicateEntries(entries);\n return deduped.length > 0 ? deduped : null;\n}\n","import type { FormatOptions, PronounEntry, PronounPreference } from \"./types\";\n\n// Helpers for reading either full or compact key styles.\n\nfunction sub(e: PronounEntry): string | undefined {\n if (\"subjective\" in e) return e.subjective;\n if (\"sub\" in e) return (e as { sub?: string }).sub;\n return undefined;\n}\n\nfunction obj(e: PronounEntry): string | undefined {\n if (\"objective\" in e) return e.objective;\n if (\"obj\" in e) return (e as { obj?: string }).obj;\n return undefined;\n}\n\nfunction ppn(e: PronounEntry): string | undefined {\n if (\"possessive_pronoun\" in e) return e.possessive_pronoun;\n if (\"p_pn\" in e) return (e as { p_pn?: string }).p_pn;\n return undefined;\n}\n\nfunction ctx(e: PronounEntry): string | undefined {\n if (\"context\" in e && e.context) return e.context;\n if (\"ctx\" in e && (e as { ctx?: string }).ctx)\n return (e as { ctx?: string }).ctx;\n return undefined;\n}\n\nfunction ranking(e: PronounEntry): number | undefined {\n if (\"ranking\" in e && e.ranking !== undefined) return e.ranking;\n if (\"rnk\" in e && (e as { rnk?: number }).rnk !== undefined)\n return (e as { rnk?: number }).rnk;\n return undefined;\n}\n\nfunction privacy(e: PronounEntry): number | undefined {\n if (\"privacy\" in e && e.privacy !== undefined) return e.privacy;\n if (\"pvc\" in e && (e as { pvc?: number }).pvc !== undefined)\n return (e as { pvc?: number }).pvc;\n return undefined;\n}\n\nfunction excluded(e: PronounEntry): boolean {\n if (\"exclude\" in e && e.exclude === true) return true;\n if (\"exc\" in e && (e as { exc?: boolean }).exc === true) return true;\n return false;\n}\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nfunction capitalizeSlashSeparated(s: string): string {\n return s.split(\"/\").map(capitalize).join(\"/\");\n}\n\nfunction formatSingleEntry(\n entry: PronounEntry,\n form: \"short\" | \"expanded\" | \"detailed\",\n): string {\n if (\"type\" in entry) {\n const t = entry.type;\n if (t === \"any\") return \"Any pronouns\";\n if (t === \"none\") return \"No pronouns (use name)\";\n if (t === \"ask\") return \"Ask me my pronouns\";\n if (t === \"unspecified\") return \"Unspecified\";\n if (t === \"custom\") {\n const display = (entry as { type: \"custom\"; display: string }).display;\n return capitalizeSlashSeparated(display);\n }\n }\n\n const s = sub(entry);\n const o = obj(entry);\n const p = ppn(entry);\n\n if (!s || !o) return \"\";\n\n let base: string;\n if (form === \"expanded\") {\n base = `${capitalize(s)}/${capitalize(o)}/${capitalize(p ?? o)}`;\n } else {\n base = `${capitalize(s)}/${capitalize(o)}`;\n }\n\n const context = ctx(entry);\n if (context) base += ` (${context})`;\n\n return base;\n}\n\nexport function format(\n preference: PronounPreference,\n options: FormatOptions = {},\n): string {\n const form = options.form ?? \"short\";\n const isPublic = options.audience === \"public\";\n\n // Filter by privacy for public audience.\n let visible = preference.filter((e) => {\n if (isPublic) {\n const p = privacy(e);\n if (p !== undefined && p >= 1) return false;\n }\n return true;\n });\n\n // Sort by ranking (ascending — lower number = higher preference).\n // Entries without ranking stay at the end in their original order.\n visible = [...visible].sort((a, b) => {\n const ra = ranking(a);\n const rb = ranking(b);\n if (ra !== undefined && rb !== undefined) return ra - rb;\n if (ra !== undefined) return -1;\n if (rb !== undefined) return 1;\n return 0;\n });\n\n if (form === \"detailed\") {\n const positive = visible.filter((e) => !excluded(e));\n const negative = visible.filter((e) => excluded(e));\n\n const posStr = positive\n .map((e) => formatSingleEntry(e, \"short\"))\n .filter(Boolean)\n .join(\", \");\n\n if (negative.length === 0) return posStr;\n\n const negStr = negative\n .map((e) => {\n const s = sub(e);\n const o = obj(e);\n return s && o ? `not ${capitalize(s)}/${capitalize(o)}` : \"\";\n })\n .filter(Boolean)\n .join(\", \");\n\n return negStr ? `${posStr} (${negStr})` : posStr;\n }\n\n // short / expanded: omit excluded entries.\n const displayable = visible.filter((e) => !excluded(e));\n\n return displayable\n .map((e) => formatSingleEntry(e, form))\n .filter(Boolean)\n .join(\", \");\n}\n","export type {\n PronounPreference,\n PronounEntry,\n PronounSet,\n SpecialPreference,\n CustomEntry,\n} from \"@openpronoun/zod\";\n\nexport {\n pronounPreferenceSchema,\n pronounEntrySchema,\n pronounSetSchema,\n specialPreferenceSchema,\n customEntrySchema,\n SPECIAL_TYPES,\n} from \"@openpronoun/zod\";\n\nexport interface FormatOptions {\n form?: \"short\" | \"expanded\" | \"detailed\";\n audience?: string;\n}\n","import type { PronounPreference } from \"./types\";\n\nimport { pronounPreferenceSchema } from \"./types\";\n\nexport function validate(input: unknown): input is PronounPreference {\n return pronounPreferenceSchema.safeParse(input).success;\n}\n\nexport function validateOrThrow(input: unknown): PronounPreference {\n return pronounPreferenceSchema.parse(input);\n}\n\nexport function validationErrors(input: unknown): string[] {\n const result = pronounPreferenceSchema.safeParse(input);\n if (result.success) return [];\n return result.error.issues.map(\n (e) => `${e.path.map(String).join(\".\")}: ${e.message}`,\n );\n}\n","import type { PronounPreference } from \"./types\";\n\nexport function filterByAudience(\n preference: PronounPreference,\n audience: string,\n): PronounPreference {\n if (audience !== \"public\") return preference;\n return preference.filter((entry) => {\n const p =\n \"privacy\" in entry\n ? entry.privacy\n : \"pvc\" in entry\n ? (entry as { pvc?: number }).pvc\n : undefined;\n return p === undefined || p < 1;\n });\n}\n"],"mappings":"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","names":["excluded"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openpronoun/core",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Reference TypeScript implementation of the OpenPronoun specification — parsing, formatting, and validation.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"require": {
|
|
21
|
+
"types": "./dist/index.d.cts",
|
|
22
|
+
"default": "./dist/index.cjs"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"main": "./dist/index.cjs",
|
|
27
|
+
"module": "./dist/index.js",
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup",
|
|
31
|
+
"dev": "tsup --watch",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"lint": "eslint .",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"check:exports": "publint && attw --pack ."
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@openpronoun/zod": "*"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"zod": "^4"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@arethetypeswrong/cli": "latest",
|
|
45
|
+
"@eslint/js": "latest",
|
|
46
|
+
"@openpronoun/conformance": "*",
|
|
47
|
+
"eslint": "latest",
|
|
48
|
+
"publint": "latest",
|
|
49
|
+
"tsup": "latest",
|
|
50
|
+
"typescript": "latest",
|
|
51
|
+
"typescript-eslint": "latest",
|
|
52
|
+
"vitest": "latest",
|
|
53
|
+
"zod": "^4"
|
|
54
|
+
}
|
|
55
|
+
}
|