@ai-matrx/content-ir 0.22.6 → 0.23.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/CHANGELOG.md +21 -0
- package/dist/convert.cjs +36 -292
- package/dist/convert.cjs.map +1 -1
- package/dist/convert.js +35 -291
- package/dist/convert.js.map +1 -1
- package/dist/core.cjs +3 -290
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +2 -289
- package/dist/core.js.map +1 -1
- package/dist/directives.cjs +3 -37
- package/dist/directives.cjs.map +1 -1
- package/dist/directives.js +2 -36
- package/dist/directives.js.map +1 -1
- package/dist/index.cjs +235 -311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +227 -310
- package/dist/index.js.map +1 -1
- package/dist/json-extract.cjs +942 -0
- package/dist/json-extract.cjs.map +1 -0
- package/dist/json-extract.d.cts +176 -0
- package/dist/json-extract.d.ts +176 -0
- package/dist/json-extract.js +928 -0
- package/dist/json-extract.js.map +1 -0
- package/dist/source.cjs +199 -0
- package/dist/source.cjs.map +1 -1
- package/dist/source.d.cts +138 -1
- package/dist/source.d.ts +138 -1
- package/dist/source.js +193 -1
- package/dist/source.js.map +1 -1
- package/dist/surfaces.cjs +4 -40
- package/dist/surfaces.cjs.map +1 -1
- package/dist/surfaces.js +2 -38
- package/dist/surfaces.js.map +1 -1
- package/package.json +28 -7
- package/dist/text-case.cjs +0 -333
- package/dist/text-case.cjs.map +0 -1
- package/dist/text-case.d.cts +0 -87
- package/dist/text-case.d.ts +0 -87
- package/dist/text-case.js +0 -320
- package/dist/text-case.js.map +0 -1
package/dist/text-case.js
DELETED
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
// text-case.ts
|
|
2
|
-
var DEFAULT_WORD_REPLACEMENTS = {
|
|
3
|
-
// Acronyms & initialisms
|
|
4
|
-
"api": "API",
|
|
5
|
-
"apis": "APIs",
|
|
6
|
-
"ui": "UI",
|
|
7
|
-
"ux": "UX",
|
|
8
|
-
"id": "ID",
|
|
9
|
-
"ids": "IDs",
|
|
10
|
-
"qr": "QR",
|
|
11
|
-
"ssr": "SSR",
|
|
12
|
-
"csr": "CSR",
|
|
13
|
-
"ssg": "SSG",
|
|
14
|
-
"isr": "ISR",
|
|
15
|
-
"spa": "SPA",
|
|
16
|
-
"pwa": "PWA",
|
|
17
|
-
"sdk": "SDK",
|
|
18
|
-
"sdks": "SDKs",
|
|
19
|
-
"cli": "CLI",
|
|
20
|
-
"tty": "TTY",
|
|
21
|
-
"repl": "REPL",
|
|
22
|
-
"ci": "CI",
|
|
23
|
-
"cd": "CD",
|
|
24
|
-
"cpu": "CPU",
|
|
25
|
-
"cpus": "CPUs",
|
|
26
|
-
"gpu": "GPU",
|
|
27
|
-
"gpus": "GPUs",
|
|
28
|
-
"ram": "RAM",
|
|
29
|
-
"rom": "ROM",
|
|
30
|
-
"ssd": "SSD",
|
|
31
|
-
"ssds": "SSDs",
|
|
32
|
-
"hdd": "HDD",
|
|
33
|
-
"hdds": "HDDs",
|
|
34
|
-
"kpi": "KPI",
|
|
35
|
-
"kpis": "KPIs",
|
|
36
|
-
"sla": "SLA",
|
|
37
|
-
"slas": "SLAs",
|
|
38
|
-
"slo": "SLO",
|
|
39
|
-
"slos": "SLOs",
|
|
40
|
-
"sli": "SLI",
|
|
41
|
-
"slis": "SLIs",
|
|
42
|
-
"dom": "DOM",
|
|
43
|
-
// Web, formats, protocols
|
|
44
|
-
"url": "URL",
|
|
45
|
-
"urls": "URLs",
|
|
46
|
-
"uri": "URI",
|
|
47
|
-
"uris": "URIs",
|
|
48
|
-
"http": "HTTP",
|
|
49
|
-
"https": "HTTPS",
|
|
50
|
-
"html": "HTML",
|
|
51
|
-
"css": "CSS",
|
|
52
|
-
"json": "JSON",
|
|
53
|
-
"yaml": "YAML",
|
|
54
|
-
"yml": "YML",
|
|
55
|
-
"toml": "TOML",
|
|
56
|
-
"csv": "CSV",
|
|
57
|
-
"pdf": "PDF",
|
|
58
|
-
"tsv": "TSV",
|
|
59
|
-
"jpg": "JPG",
|
|
60
|
-
"jpeg": "JPEG",
|
|
61
|
-
"png": "PNG",
|
|
62
|
-
"gif": "GIF",
|
|
63
|
-
"webp": "WebP",
|
|
64
|
-
"heic": "HEIC",
|
|
65
|
-
"heif": "HEIF",
|
|
66
|
-
"bmp": "BMP",
|
|
67
|
-
"tiff": "TIFF",
|
|
68
|
-
"ico": "ICO",
|
|
69
|
-
"xml": "XML",
|
|
70
|
-
"sql": "SQL",
|
|
71
|
-
"db": "DB",
|
|
72
|
-
"dbs": "DBs",
|
|
73
|
-
"nosql": "NoSQL",
|
|
74
|
-
"graphql": "GraphQL",
|
|
75
|
-
"grpc": "gRPC",
|
|
76
|
-
"rest": "REST",
|
|
77
|
-
"restful": "RESTful",
|
|
78
|
-
"websocket": "WebSocket",
|
|
79
|
-
"websockets": "WebSockets",
|
|
80
|
-
"webrtc": "WebRTC",
|
|
81
|
-
// Networking
|
|
82
|
-
"ip": "IP",
|
|
83
|
-
"ipv4": "IPv4",
|
|
84
|
-
"ipv6": "IPv6",
|
|
85
|
-
"dns": "DNS",
|
|
86
|
-
"dhcp": "DHCP",
|
|
87
|
-
"nat": "NAT",
|
|
88
|
-
"tcp": "TCP",
|
|
89
|
-
"udp": "UDP",
|
|
90
|
-
"icmp": "ICMP",
|
|
91
|
-
"ttl": "TTL",
|
|
92
|
-
"lan": "LAN",
|
|
93
|
-
"wan": "WAN",
|
|
94
|
-
"vlan": "VLAN",
|
|
95
|
-
"cdn": "CDN",
|
|
96
|
-
"ftp": "FTP",
|
|
97
|
-
"ssh": "SSH",
|
|
98
|
-
"tls": "TLS",
|
|
99
|
-
"ssl": "SSL",
|
|
100
|
-
// Security & crypto
|
|
101
|
-
"jwt": "JWT",
|
|
102
|
-
"jws": "JWS",
|
|
103
|
-
"jwe": "JWE",
|
|
104
|
-
"hmac": "HMAC",
|
|
105
|
-
"rsa": "RSA",
|
|
106
|
-
"ecdsa": "ECDSA",
|
|
107
|
-
"aes": "AES",
|
|
108
|
-
"pbkdf2": "PBKDF2",
|
|
109
|
-
"argon2": "Argon2",
|
|
110
|
-
"scrypt": "scrypt",
|
|
111
|
-
"totp": "TOTP",
|
|
112
|
-
"hotp": "HOTP",
|
|
113
|
-
"mfa": "MFA",
|
|
114
|
-
"2fa": "2FA",
|
|
115
|
-
"csrf": "CSRF",
|
|
116
|
-
"xss": "XSS",
|
|
117
|
-
"ssrf": "SSRF",
|
|
118
|
-
"rce": "RCE",
|
|
119
|
-
"dos": "DoS",
|
|
120
|
-
"ddos": "DDoS",
|
|
121
|
-
"mitm": "MITM",
|
|
122
|
-
"csp": "CSP",
|
|
123
|
-
"cors": "CORS",
|
|
124
|
-
"pii": "PII",
|
|
125
|
-
"phi": "PHI",
|
|
126
|
-
"gdpr": "GDPR",
|
|
127
|
-
"ccpa": "CCPA",
|
|
128
|
-
"hipaa": "HIPAA",
|
|
129
|
-
"rfc": "RFC",
|
|
130
|
-
// Platforms, langs, tools (single-token)
|
|
131
|
-
"javascript": "JavaScript",
|
|
132
|
-
"typescript": "TypeScript",
|
|
133
|
-
"jsx": "JSX",
|
|
134
|
-
"tsx": "TSX",
|
|
135
|
-
"node": "Node",
|
|
136
|
-
// (used when tokenized alone)
|
|
137
|
-
"deno": "Deno",
|
|
138
|
-
"bun": "Bun",
|
|
139
|
-
"react": "React",
|
|
140
|
-
"nextjs": "Next.js",
|
|
141
|
-
// if your tokenizer drops dots, keep this
|
|
142
|
-
"nodejs": "Node.js",
|
|
143
|
-
"postgresql": "PostgreSQL",
|
|
144
|
-
"postgres": "Postgres",
|
|
145
|
-
"mysql": "MySQL",
|
|
146
|
-
"sqlite": "SQLite",
|
|
147
|
-
"redis": "Redis",
|
|
148
|
-
"supabase": "Supabase",
|
|
149
|
-
"docker": "Docker",
|
|
150
|
-
"kubernetes": "Kubernetes",
|
|
151
|
-
"k8s": "Kubernetes",
|
|
152
|
-
"helm": "Helm",
|
|
153
|
-
"npm": "npm",
|
|
154
|
-
"pnpm": "pnpm",
|
|
155
|
-
"yarn": "Yarn",
|
|
156
|
-
"eslint": "ESLint",
|
|
157
|
-
"prettier": "Prettier",
|
|
158
|
-
"vite": "Vite",
|
|
159
|
-
"webpack": "Webpack",
|
|
160
|
-
"babel": "Babel",
|
|
161
|
-
// OS & vendors
|
|
162
|
-
"macos": "macOS",
|
|
163
|
-
"ios": "iOS",
|
|
164
|
-
"ipados": "iPadOS",
|
|
165
|
-
"watchos": "watchOS",
|
|
166
|
-
"tvos": "tvOS",
|
|
167
|
-
"windows": "Windows",
|
|
168
|
-
"linux": "Linux",
|
|
169
|
-
"ubuntu": "Ubuntu",
|
|
170
|
-
"github": "GitHub",
|
|
171
|
-
"gitlab": "GitLab",
|
|
172
|
-
"bitbucket": "Bitbucket",
|
|
173
|
-
// Data & analytics
|
|
174
|
-
"etl": "ETL",
|
|
175
|
-
"elt": "ELT",
|
|
176
|
-
"olap": "OLAP",
|
|
177
|
-
"oltp": "OLTP",
|
|
178
|
-
"bi": "BI",
|
|
179
|
-
// Time & locales
|
|
180
|
-
"utc": "UTC",
|
|
181
|
-
"gmt": "GMT",
|
|
182
|
-
"pst": "PST",
|
|
183
|
-
"pdt": "PDT",
|
|
184
|
-
"pt": "PT",
|
|
185
|
-
// Common “small words” to keep lowercase (unless first/last word)
|
|
186
|
-
"or": "or",
|
|
187
|
-
"and": "and",
|
|
188
|
-
"the": "the",
|
|
189
|
-
"of": "of",
|
|
190
|
-
"in": "in",
|
|
191
|
-
"to": "to",
|
|
192
|
-
"with": "with",
|
|
193
|
-
"as": "as",
|
|
194
|
-
"by": "by",
|
|
195
|
-
"for": "for",
|
|
196
|
-
"on": "on",
|
|
197
|
-
"at": "at",
|
|
198
|
-
"up": "up",
|
|
199
|
-
"a": "a",
|
|
200
|
-
"an": "an",
|
|
201
|
-
"is": "is",
|
|
202
|
-
"are": "are",
|
|
203
|
-
"was": "was",
|
|
204
|
-
"were": "were",
|
|
205
|
-
"be": "be",
|
|
206
|
-
"but": "but",
|
|
207
|
-
"nor": "nor",
|
|
208
|
-
"so": "so",
|
|
209
|
-
"yet": "yet",
|
|
210
|
-
"per": "per",
|
|
211
|
-
"via": "via",
|
|
212
|
-
// Latin abbreviations (tokenized as words in some pipelines)
|
|
213
|
-
"eg": "e.g.",
|
|
214
|
-
"ie": "i.e.",
|
|
215
|
-
"etc": "etc.",
|
|
216
|
-
"aka": "aka",
|
|
217
|
-
"vs": "vs.",
|
|
218
|
-
"v": "v.",
|
|
219
|
-
// Client abbreviations
|
|
220
|
-
"CIC": "CIC",
|
|
221
|
-
"AGR": "AGR",
|
|
222
|
-
"AGER": "AGER",
|
|
223
|
-
"DD": "DD",
|
|
224
|
-
"TS": "TS",
|
|
225
|
-
"TM": "TM",
|
|
226
|
-
"arman": "Arman"
|
|
227
|
-
};
|
|
228
|
-
var DEFAULT_OPTIONS = {
|
|
229
|
-
textCase: "title",
|
|
230
|
-
wordReplacements: DEFAULT_WORD_REPLACEMENTS,
|
|
231
|
-
trim: true
|
|
232
|
-
};
|
|
233
|
-
function formatText(text, options = {}) {
|
|
234
|
-
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
235
|
-
if (!text) return "";
|
|
236
|
-
let normalized = text.replace(/_/g, " ").replace(/-/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\s+/g, " ");
|
|
237
|
-
if (opts.trim) {
|
|
238
|
-
normalized = normalized.trim();
|
|
239
|
-
}
|
|
240
|
-
let caseTransformed = normalized;
|
|
241
|
-
switch (opts.textCase) {
|
|
242
|
-
case "title":
|
|
243
|
-
caseTransformed = normalized.replace(
|
|
244
|
-
/\w\S*/g,
|
|
245
|
-
(word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
|
|
246
|
-
);
|
|
247
|
-
break;
|
|
248
|
-
case "sentence":
|
|
249
|
-
if (normalized.length > 0) {
|
|
250
|
-
caseTransformed = normalized.charAt(0).toUpperCase() + normalized.slice(1).toLowerCase();
|
|
251
|
-
}
|
|
252
|
-
break;
|
|
253
|
-
case "lower":
|
|
254
|
-
caseTransformed = normalized.toLowerCase();
|
|
255
|
-
break;
|
|
256
|
-
case "upper":
|
|
257
|
-
caseTransformed = normalized.toUpperCase();
|
|
258
|
-
break;
|
|
259
|
-
}
|
|
260
|
-
let result = caseTransformed;
|
|
261
|
-
if (opts.wordReplacements) {
|
|
262
|
-
Object.entries(opts.wordReplacements).forEach(([key, value]) => {
|
|
263
|
-
const regex = new RegExp(`\\b${key}\\b`, "gi");
|
|
264
|
-
result = result.replace(regex, value);
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
return result;
|
|
268
|
-
}
|
|
269
|
-
function createFormatter(defaultOptions = {}) {
|
|
270
|
-
return (text, overrideOptions = {}) => formatText(text, { ...defaultOptions, ...overrideOptions });
|
|
271
|
-
}
|
|
272
|
-
var formatTitleCase = createFormatter({ textCase: "title" });
|
|
273
|
-
var formatSentenceCase = createFormatter({ textCase: "sentence" });
|
|
274
|
-
var formatNormalCase = createFormatter({ textCase: "normal" });
|
|
275
|
-
var formatUpperCase = createFormatter({ textCase: "upper" });
|
|
276
|
-
var formatLowerCase = createFormatter({ textCase: "lower" });
|
|
277
|
-
var formatWithoutReplacements = createFormatter({ wordReplacements: {} });
|
|
278
|
-
var IDENTIFIER_ACRONYMS = [
|
|
279
|
-
"ID",
|
|
280
|
-
"URL",
|
|
281
|
-
"PDF",
|
|
282
|
-
"HTML",
|
|
283
|
-
"JSON",
|
|
284
|
-
"API",
|
|
285
|
-
"AI",
|
|
286
|
-
"UI",
|
|
287
|
-
"CSV",
|
|
288
|
-
"SMS",
|
|
289
|
-
"SEO",
|
|
290
|
-
"LLM",
|
|
291
|
-
"MCP",
|
|
292
|
-
"UUID",
|
|
293
|
-
"ISO"
|
|
294
|
-
];
|
|
295
|
-
var IDENTIFIER_ACRONYM_SET = new Set(IDENTIFIER_ACRONYMS.map((a) => a.toLowerCase()));
|
|
296
|
-
function humanizeIdentifier(identifier) {
|
|
297
|
-
const text = (identifier ?? "").trim();
|
|
298
|
-
if (text === "") return "";
|
|
299
|
-
if (!text.includes("_") && /\s/.test(text)) {
|
|
300
|
-
return /^\p{Ll}/u.test(text) ? text.charAt(0).toUpperCase() + text.slice(1) : text;
|
|
301
|
-
}
|
|
302
|
-
return text.replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)(?![A-Z]s(?![a-z]))([A-Z][a-z])/g, "$1 $2").split(/[_\-.\s]+/).filter((part) => part.length > 0).map(identifierWord).join(" ");
|
|
303
|
-
}
|
|
304
|
-
function identifierWord(part) {
|
|
305
|
-
const lower = part.toLowerCase();
|
|
306
|
-
if (IDENTIFIER_ACRONYM_SET.has(lower)) return part.toUpperCase();
|
|
307
|
-
if (lower.length > 1 && lower.endsWith("s") && IDENTIFIER_ACRONYM_SET.has(lower.slice(0, -1))) {
|
|
308
|
-
return `${lower.slice(0, -1).toUpperCase()}s`;
|
|
309
|
-
}
|
|
310
|
-
return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
|
|
311
|
-
}
|
|
312
|
-
function displayLabel(label, identifier) {
|
|
313
|
-
const own = (label ?? "").trim();
|
|
314
|
-
if (own !== "") return own;
|
|
315
|
-
return humanizeIdentifier(identifier) || identifier;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
export { DEFAULT_WORD_REPLACEMENTS, IDENTIFIER_ACRONYMS, createFormatter, displayLabel, formatLowerCase, formatNormalCase, formatSentenceCase, formatText, formatTitleCase, formatUpperCase, formatWithoutReplacements, humanizeIdentifier };
|
|
319
|
-
//# sourceMappingURL=text-case.js.map
|
|
320
|
-
//# sourceMappingURL=text-case.js.map
|
package/dist/text-case.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../text-case.ts"],"names":[],"mappings":"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","file":"text-case.js","sourcesContent":["/**\n * `@ai-matrx/content-ir/text-case` — THE text-case and identifier-label rules.\n *\n * Pure TS. Public face for apps: `@ai-matrx/kit/text-case` (re-exports this). Lives\n * here, the lowest pure layer, because both content-ir (`formatBlockLabel`) and kit\n * need it and kit already depends on content-ir.\n */\n/**\n * Text formatting options\n */\nexport type TextCaseOption = 'title' | 'sentence' | 'normal' | 'lower' | 'upper';\n\nexport interface TextFormatterOptions {\n /**\n * Text case to apply after normalization\n * - title: First Letter Of Each Word Capitalized\n * - sentence: First letter of first word capitalized\n * - normal: No case transformation after normalization\n * - lower: all text lowercase\n * - upper: ALL TEXT UPPERCASE\n */\n textCase?: TextCaseOption;\n \n /**\n * Map of words to replace with specific formatting\n * Example: { 'api': 'API', 'ui': 'UI' }\n */\n wordReplacements?: Record<string, string>;\n \n /**\n * Whether to trim the result\n */\n trim?: boolean;\n}\n\n/**\n * Default word replacements for common acronyms and terms\n */\nexport type ReplacementMap = Readonly<Record<string, string>>;\n\nexport const DEFAULT_WORD_REPLACEMENTS: ReplacementMap = {\n // Acronyms & initialisms\n 'api': 'API',\n 'apis': 'APIs',\n 'ui': 'UI',\n 'ux': 'UX',\n 'id': 'ID',\n 'ids': 'IDs',\n 'qr': 'QR',\n 'ssr': 'SSR',\n 'csr': 'CSR',\n 'ssg': 'SSG',\n 'isr': 'ISR',\n 'spa': 'SPA',\n 'pwa': 'PWA',\n 'sdk': 'SDK',\n 'sdks': 'SDKs',\n 'cli': 'CLI',\n 'tty': 'TTY',\n 'repl': 'REPL',\n 'ci': 'CI',\n 'cd': 'CD',\n 'cpu': 'CPU',\n 'cpus': 'CPUs',\n 'gpu': 'GPU',\n 'gpus': 'GPUs',\n 'ram': 'RAM',\n 'rom': 'ROM',\n 'ssd': 'SSD',\n 'ssds': 'SSDs',\n 'hdd': 'HDD',\n 'hdds': 'HDDs',\n 'kpi': 'KPI',\n 'kpis': 'KPIs',\n 'sla': 'SLA',\n 'slas': 'SLAs',\n 'slo': 'SLO',\n 'slos': 'SLOs',\n 'sli': 'SLI',\n 'slis': 'SLIs',\n 'dom': 'DOM',\n\n // Web, formats, protocols\n 'url': 'URL',\n 'urls': 'URLs',\n 'uri': 'URI',\n 'uris': 'URIs',\n 'http': 'HTTP',\n 'https': 'HTTPS',\n 'html': 'HTML',\n 'css': 'CSS',\n 'json': 'JSON',\n 'yaml': 'YAML',\n 'yml': 'YML',\n 'toml': 'TOML',\n 'csv': 'CSV',\n 'pdf': 'PDF',\n 'tsv': 'TSV',\n 'jpg': 'JPG',\n 'jpeg': 'JPEG',\n 'png': 'PNG',\n 'gif': 'GIF',\n 'webp': 'WebP',\n 'heic': 'HEIC',\n 'heif': 'HEIF',\n 'bmp': 'BMP',\n 'tiff': 'TIFF',\n 'ico': 'ICO',\n 'xml': 'XML',\n 'sql': 'SQL',\n 'db': 'DB',\n 'dbs': 'DBs',\n 'nosql': 'NoSQL',\n 'graphql': 'GraphQL',\n 'grpc': 'gRPC',\n 'rest': 'REST',\n 'restful': 'RESTful',\n 'websocket': 'WebSocket',\n 'websockets': 'WebSockets',\n 'webrtc': 'WebRTC',\n\n // Networking\n 'ip': 'IP',\n 'ipv4': 'IPv4',\n 'ipv6': 'IPv6',\n 'dns': 'DNS',\n 'dhcp': 'DHCP',\n 'nat': 'NAT',\n 'tcp': 'TCP',\n 'udp': 'UDP',\n 'icmp': 'ICMP',\n 'ttl': 'TTL',\n 'lan': 'LAN',\n 'wan': 'WAN',\n 'vlan': 'VLAN',\n 'cdn': 'CDN',\n 'ftp': 'FTP',\n 'ssh': 'SSH',\n 'tls': 'TLS',\n 'ssl': 'SSL',\n\n // Security & crypto\n 'jwt': 'JWT',\n 'jws': 'JWS',\n 'jwe': 'JWE',\n 'hmac': 'HMAC',\n 'rsa': 'RSA',\n 'ecdsa': 'ECDSA',\n 'aes': 'AES',\n 'pbkdf2': 'PBKDF2',\n 'argon2': 'Argon2',\n 'scrypt': 'scrypt',\n 'totp': 'TOTP',\n 'hotp': 'HOTP',\n 'mfa': 'MFA',\n '2fa': '2FA',\n 'csrf': 'CSRF',\n 'xss': 'XSS',\n 'ssrf': 'SSRF',\n 'rce': 'RCE',\n 'dos': 'DoS',\n 'ddos': 'DDoS',\n 'mitm': 'MITM',\n 'csp': 'CSP',\n 'cors': 'CORS',\n 'pii': 'PII',\n 'phi': 'PHI',\n 'gdpr': 'GDPR',\n 'ccpa': 'CCPA',\n 'hipaa': 'HIPAA',\n 'rfc': 'RFC',\n\n // Platforms, langs, tools (single-token)\n 'javascript': 'JavaScript',\n 'typescript': 'TypeScript',\n 'jsx': 'JSX',\n 'tsx': 'TSX',\n 'node': 'Node', // (used when tokenized alone)\n 'deno': 'Deno',\n 'bun': 'Bun',\n 'react': 'React',\n 'nextjs': 'Next.js', // if your tokenizer drops dots, keep this\n 'nodejs': 'Node.js',\n 'postgresql': 'PostgreSQL',\n 'postgres': 'Postgres',\n 'mysql': 'MySQL',\n 'sqlite': 'SQLite',\n 'redis': 'Redis',\n 'supabase': 'Supabase',\n 'docker': 'Docker',\n 'kubernetes': 'Kubernetes',\n 'k8s': 'Kubernetes',\n 'helm': 'Helm',\n 'npm': 'npm',\n 'pnpm': 'pnpm',\n 'yarn': 'Yarn',\n 'eslint': 'ESLint',\n 'prettier': 'Prettier',\n 'vite': 'Vite',\n 'webpack': 'Webpack',\n 'babel': 'Babel',\n\n // OS & vendors\n 'macos': 'macOS',\n 'ios': 'iOS',\n 'ipados': 'iPadOS',\n 'watchos': 'watchOS',\n 'tvos': 'tvOS',\n 'windows': 'Windows',\n 'linux': 'Linux',\n 'ubuntu': 'Ubuntu',\n 'github': 'GitHub',\n 'gitlab': 'GitLab',\n 'bitbucket': 'Bitbucket',\n\n // Data & analytics\n 'etl': 'ETL',\n 'elt': 'ELT',\n 'olap': 'OLAP',\n 'oltp': 'OLTP',\n 'bi': 'BI',\n\n // Time & locales\n 'utc': 'UTC',\n 'gmt': 'GMT',\n 'pst': 'PST',\n 'pdt': 'PDT',\n 'pt': 'PT',\n\n // Common “small words” to keep lowercase (unless first/last word)\n 'or': 'or',\n 'and': 'and',\n 'the': 'the',\n 'of': 'of',\n 'in': 'in',\n 'to': 'to',\n 'with': 'with',\n 'as': 'as',\n 'by': 'by',\n 'for': 'for',\n 'on': 'on',\n 'at': 'at',\n 'up': 'up',\n 'a': 'a',\n 'an': 'an',\n 'is': 'is',\n 'are': 'are',\n 'was': 'was',\n 'were': 'were',\n 'be': 'be',\n 'but': 'but',\n 'nor': 'nor',\n 'so': 'so',\n 'yet': 'yet',\n 'per': 'per',\n 'via': 'via',\n\n // Latin abbreviations (tokenized as words in some pipelines)\n 'eg': 'e.g.',\n 'ie': 'i.e.',\n 'etc': 'etc.',\n 'aka': 'aka',\n 'vs': 'vs.',\n 'v': 'v.',\n\n // Client abbreviations\n 'CIC': 'CIC',\n 'AGR': 'AGR',\n 'AGER': 'AGER',\n 'DD': 'DD',\n 'TS': 'TS',\n 'TM': 'TM',\n 'arman': \"Arman\",\n};\n\n/**\n * Default options for text formatting\n */\nconst DEFAULT_OPTIONS: TextFormatterOptions = {\n textCase: 'title',\n wordReplacements: DEFAULT_WORD_REPLACEMENTS,\n trim: true,\n};\n\n/**\n * Formats text by normalizing case styles, applying case transformations,\n * and replacing specific words with custom formatting.\n * \n * @param text The input text to format\n * @param options Formatting options\n * @returns Formatted text\n */\nexport function formatText(text: string, options: TextFormatterOptions = {}): string {\n // Merge provided options with defaults\n const opts = { ...DEFAULT_OPTIONS, ...options };\n \n // Handle empty text\n if (!text) return '';\n \n // Step 1: Normalize various case styles to space-separated words\n let normalized = text\n // Convert snake_case to space-separated\n .replace(/_/g, ' ')\n // Convert kebab-case to space-separated\n .replace(/-/g, ' ')\n // Convert camelCase and PascalCase to space-separated\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n // Replace multiple spaces with a single space\n .replace(/\\s+/g, ' ');\n \n // Step 2: Apply trim if needed\n if (opts.trim) {\n normalized = normalized.trim();\n }\n \n // Step 3: Apply the specified text case\n let caseTransformed = normalized;\n switch (opts.textCase) {\n case 'title':\n caseTransformed = normalized.replace(/\\w\\S*/g, (word) => \n word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()\n );\n break;\n case 'sentence':\n if (normalized.length > 0) {\n caseTransformed = normalized.charAt(0).toUpperCase() + normalized.slice(1).toLowerCase();\n }\n break;\n case 'lower':\n caseTransformed = normalized.toLowerCase();\n break;\n case 'upper':\n caseTransformed = normalized.toUpperCase();\n break;\n case 'normal':\n default:\n // No case transformation\n break;\n }\n \n // Step 4: Apply word replacements if provided\n let result = caseTransformed;\n if (opts.wordReplacements) {\n Object.entries(opts.wordReplacements).forEach(([key, value]) => {\n // Create a regex that matches the key as a whole word (case insensitive)\n const regex = new RegExp(`\\\\b${key}\\\\b`, 'gi');\n result = result.replace(regex, value);\n });\n }\n \n return result;\n}\n\n/**\n * Creates a pre-configured formatter function with specific options\n * \n * @param defaultOptions Default options for the formatter\n * @returns A formatter function with the specified default options\n */\nexport function createFormatter(defaultOptions: TextFormatterOptions = {}) {\n return (text: string, overrideOptions: TextFormatterOptions = {}) => \n formatText(text, { ...defaultOptions, ...overrideOptions });\n}\n\n// Some pre-configured formatters for common use cases\nexport const formatTitleCase = createFormatter({ textCase: 'title' });\nexport const formatSentenceCase = createFormatter({ textCase: 'sentence' });\nexport const formatNormalCase = createFormatter({ textCase: 'normal' });\nexport const formatUpperCase = createFormatter({ textCase: 'upper' });\nexport const formatLowerCase = createFormatter({ textCase: 'lower' });\nexport const formatWithoutReplacements = createFormatter({ wordReplacements: {} });\n\n// ── humanizeIdentifier — THE one identifier-to-words rule ────────────────────\n//\n// A screen never shows a machine identifier (`normal_text`, `note_id`,\n// `workflowCatalog`). It shows the thing's own label; when the thing carries no\n// label, it shows the identifier through this function — the ONE humanizer every\n// app and package uses (matrx-frontend, records-ui, diff, chat, agents). The\n// Python twin is matrx-utils `matrx_utils.text_case.humanize_identifier`; both run the parity corpus\n// `humanize_cases` in `@ai-matrx/agents` `context/rules-corpus.json`.\n\n/** Words always written in capitals when they are a whole word of an identifier. */\nexport const IDENTIFIER_ACRONYMS: readonly string[] = [\n \"ID\", \"URL\", \"PDF\", \"HTML\", \"JSON\", \"API\", \"AI\", \"UI\", \"CSV\", \"SMS\", \"SEO\", \"LLM\", \"MCP\", \"UUID\", \"ISO\",\n];\nconst IDENTIFIER_ACRONYM_SET = new Set(IDENTIFIER_ACRONYMS.map((a) => a.toLowerCase()));\n\n/**\n * An identifier in words — the label of a thing nobody named.\n *\n * 1. `null` / `undefined` / empty / whitespace → `\"\"`.\n * 2. Already words — contains whitespace and no `_` (`\"Customer's iPhone model\"`,\n * `\"Version 2.0\"`) — is returned trimmed and untouched, except that a\n * lowercase first letter is capitalized.\n * 3. Otherwise split camelCase (`myValue` → `my Value`, `HTMLParser` →\n * `HTML Parser`, `userIDs` → `user IDs`), then on runs of `_`, `-`, `.` and\n * whitespace; drop empty parts;\n * 4. a part that is, case-insensitively, one of `IDENTIFIER_ACRONYMS` is\n * upper-cased, and one of them plus `s` is the plural (`ids` → `IDs`); any\n * other part gets its first character upper-cased and the rest lower-cased\n * (acronyms are whole parts only: `url2pdf` → `Url2pdf`);\n * 5. join with single spaces.\n *\n * `note_id` → `Note ID`, `normal_text` → `Normal Text`, `myValue_ID` → `My Value ID`.\n * An identifier with no word characters returns `\"\"` — callers fall back.\n */\nexport function humanizeIdentifier(identifier: string | null | undefined): string {\n const text = (identifier ?? \"\").trim();\n if (text === \"\") return \"\";\n if (!text.includes(\"_\") && /\\s/.test(text)) {\n return /^\\p{Ll}/u.test(text) ? text.charAt(0).toUpperCase() + text.slice(1) : text;\n }\n return text\n .replace(/([a-z\\d])([A-Z])/g, \"$1 $2\")\n .replace(/([A-Z]+)(?![A-Z]s(?![a-z]))([A-Z][a-z])/g, \"$1 $2\")\n .split(/[_\\-.\\s]+/)\n .filter((part) => part.length > 0)\n .map(identifierWord)\n .join(\" \");\n}\n\nfunction identifierWord(part: string): string {\n const lower = part.toLowerCase();\n if (IDENTIFIER_ACRONYM_SET.has(lower)) return part.toUpperCase();\n if (lower.length > 1 && lower.endsWith(\"s\") && IDENTIFIER_ACRONYM_SET.has(lower.slice(0, -1))) {\n return `${lower.slice(0, -1).toUpperCase()}s`;\n }\n return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();\n}\n\n/**\n * What a screen shows for a thing: its own label when it has one, else its\n * identifier through `humanizeIdentifier`, else the identifier itself.\n */\nexport function displayLabel(label: string | null | undefined, identifier: string): string {\n const own = (label ?? \"\").trim();\n if (own !== \"\") return own;\n return humanizeIdentifier(identifier) || identifier;\n}\n"]}
|