@nkardaz/typography-rules 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +911 -0
- package/dist/api/blacklist.d.ts +72 -0
- package/dist/api/htmlNodes.d.ts +30 -0
- package/dist/api/index.d.ts +6 -0
- package/dist/api/newRule.d.ts +51 -0
- package/dist/api/registerRule.d.ts +27 -0
- package/dist/api/rulesInit.d.ts +49 -0
- package/dist/functions/chemNotation.d.ts +10 -0
- package/dist/functions/clearSpaces.d.ts +16 -0
- package/dist/functions/index.cjs +514 -0
- package/dist/functions/index.d.ts +8 -0
- package/dist/functions/index.mjs +491 -0
- package/dist/functions/rubyText.d.ts +11 -0
- package/dist/functions/runt.d.ts +3 -0
- package/dist/functions/smartNumberGrouping.d.ts +25 -0
- package/dist/functions/smartQuotes.d.ts +29 -0
- package/dist/functions/wrapWithTag.d.ts +42 -0
- package/dist/glyphs/index.cjs +737 -0
- package/dist/glyphs/index.d.ts +53 -0
- package/dist/glyphs/index.mjs +714 -0
- package/dist/glyphs/proto.d.ts +11 -0
- package/dist/glyphs/registry.d.ts +728 -0
- package/dist/glyphs/types.d.ts +151 -0
- package/dist/helpers/index.cjs +268 -0
- package/dist/helpers/index.d.ts +133 -0
- package/dist/helpers/index.mjs +245 -0
- package/dist/helpers/types.d.ts +71 -0
- package/dist/index.cjs +985 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.mjs +977 -0
- package/dist/style/index.d.ts +2 -0
- package/dist/style/main.css +16 -0
- package/dist/types.d.ts +223 -0
- package/dist/typography/aliases.d.ts +129 -0
- package/dist/typography/expressions/common.d.ts +29 -0
- package/dist/typography/expressions/en.d.ts +25 -0
- package/dist/typography/expressions/ru.d.ts +29 -0
- package/dist/typography/markup/common.d.ts +17 -0
- package/dist/typography/markup/en.d.ts +3 -0
- package/dist/typography/markup/index.d.ts +4 -0
- package/dist/typography/markup/ru.d.ts +3 -0
- package/dist/typography/sets/ang.d.ts +3 -0
- package/dist/typography/sets/common.d.ts +17 -0
- package/dist/typography/sets/en.d.ts +14 -0
- package/dist/typography/sets/index.d.ts +5 -0
- package/dist/typography/sets/ru.d.ts +16 -0
- package/dist/typography/store.d.ts +63 -0
- package/package.json +92 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
// src/typography/aliases.ts
|
|
2
|
+
function createAlias(map) {
|
|
3
|
+
const normalized = Object.fromEntries(
|
|
4
|
+
Object.entries(map).map(([key, values]) => [
|
|
5
|
+
key.toLowerCase(),
|
|
6
|
+
values.map((v) => v.toLowerCase())
|
|
7
|
+
])
|
|
8
|
+
);
|
|
9
|
+
const methods = {
|
|
10
|
+
/**
|
|
11
|
+
* Checks whether an alias exists in the map,
|
|
12
|
+
* either as a root key or as an alternative name.
|
|
13
|
+
*
|
|
14
|
+
* @param alias - The alias to look up (case-insensitive).
|
|
15
|
+
* @returns `true` if the alias is found, `false` otherwise.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ALIAS.has('English') // true
|
|
19
|
+
* ALIAS.has('fr') // false
|
|
20
|
+
*/
|
|
21
|
+
has(alias) {
|
|
22
|
+
const a = alias.toLowerCase();
|
|
23
|
+
if (a in normalized) return true;
|
|
24
|
+
return Object.values(normalized).some((vals) => vals.includes(a));
|
|
25
|
+
},
|
|
26
|
+
/**
|
|
27
|
+
* Resolves an alias to its root key.
|
|
28
|
+
*
|
|
29
|
+
* @param alias - The alias to resolve (case-insensitive).
|
|
30
|
+
* @returns The root key if found, `undefined` otherwise.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ALIAS.resolve('Russian') // 'ru'
|
|
34
|
+
* ALIAS.resolve('ru-RU') // 'ru'
|
|
35
|
+
* ALIAS.resolve('fr') // undefined
|
|
36
|
+
*/
|
|
37
|
+
resolve(alias) {
|
|
38
|
+
const a = alias.toLowerCase();
|
|
39
|
+
if (a in normalized) return a;
|
|
40
|
+
return Object.keys(normalized).find((k) => {
|
|
41
|
+
const values = normalized[k];
|
|
42
|
+
return Array.isArray(values) && values.includes(a);
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
/**
|
|
46
|
+
* Adds one or more alternative names to an existing or new root key.
|
|
47
|
+
* All values are automatically lowercased.
|
|
48
|
+
*
|
|
49
|
+
* @param root - The root key to add aliases to.
|
|
50
|
+
* @param aliases - One or more alternative names to register.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ALIAS.push('ru', 'Рус', 'ру')
|
|
54
|
+
* ALIAS.ru // ['ru-ru', 'russian', 'русский', 'рус', 'ру']
|
|
55
|
+
*/
|
|
56
|
+
push(root, ...aliases) {
|
|
57
|
+
for (const alias of aliases) {
|
|
58
|
+
const a = alias.toLowerCase();
|
|
59
|
+
const r = root.toLowerCase();
|
|
60
|
+
if (a in normalized) {
|
|
61
|
+
normalized[a]?.push(r);
|
|
62
|
+
} else {
|
|
63
|
+
normalized[a] = [r];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
/**
|
|
68
|
+
* Normalizes one or more strings to lowercase.
|
|
69
|
+
*
|
|
70
|
+
* @param alias - One or more strings to normalize.
|
|
71
|
+
* @returns An array of lowercased strings.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ALIAS.normalize('English', 'RU-RU') // ['english', 'ru-ru']
|
|
75
|
+
*/
|
|
76
|
+
normalize(...alias) {
|
|
77
|
+
return alias.map((a) => a.toLowerCase());
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
return new Proxy(methods, {
|
|
81
|
+
get(target, prop) {
|
|
82
|
+
if (prop in target) return target[prop];
|
|
83
|
+
return normalized[prop];
|
|
84
|
+
},
|
|
85
|
+
has(_target, prop) {
|
|
86
|
+
return prop in normalized;
|
|
87
|
+
},
|
|
88
|
+
ownKeys() {
|
|
89
|
+
return [...Object.keys(normalized), ...Object.keys(methods)];
|
|
90
|
+
},
|
|
91
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
92
|
+
if (prop in normalized || prop in methods) {
|
|
93
|
+
return { enumerable: true, configurable: true };
|
|
94
|
+
}
|
|
95
|
+
return void 0;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
var ALIAS = createAlias({
|
|
100
|
+
ru: ["ru-RU", "Russian", "\u0420\u0443\u0441\u0441\u043A\u0438\u0439"],
|
|
101
|
+
en: ["en-US", "English"],
|
|
102
|
+
ang: ["\xC6nglis\u010B", "\xC6nglisc", "Old English"]
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// src/helpers/index.ts
|
|
106
|
+
var NODE_MARKER = "\uE000\uEDFD\uF43E";
|
|
107
|
+
var PROTECTION_MARKER = "\uE001\uEDF1\uF111";
|
|
108
|
+
var NODE_MARKER_REGEX = new RegExp(NODE_MARKER, "g");
|
|
109
|
+
var PROTECTION_MARKER_REGEX = new RegExp(PROTECTION_MARKER, "g");
|
|
110
|
+
var patternProto = {
|
|
111
|
+
get values() {
|
|
112
|
+
return Object.keys(this).map((key) => {
|
|
113
|
+
const desc = Object.getOwnPropertyDescriptor(this, key);
|
|
114
|
+
return desc?.get ? this[key] : void 0;
|
|
115
|
+
}).filter((v) => v !== void 0);
|
|
116
|
+
},
|
|
117
|
+
combined(locale) {
|
|
118
|
+
const key = locale ? ALIAS.resolve(locale) ?? locale : void 0;
|
|
119
|
+
const baseSources = this.values.map((p) => `(${p.source})`);
|
|
120
|
+
const localeSources = [];
|
|
121
|
+
const locales = localeRegistry.get(this);
|
|
122
|
+
if (key && locales) {
|
|
123
|
+
const sub = locales.get(key);
|
|
124
|
+
if (sub) {
|
|
125
|
+
for (const rx of Object.values(sub)) {
|
|
126
|
+
localeSources.push(`(${rx.source})`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const source = [...baseSources, ...localeSources].join("|");
|
|
131
|
+
return new RegExp(source, "g");
|
|
132
|
+
},
|
|
133
|
+
insert(patterns) {
|
|
134
|
+
const locales = localeRegistry.get(this) ?? /* @__PURE__ */ new Map();
|
|
135
|
+
for (const key of Object.keys(patterns)) {
|
|
136
|
+
const value = patterns[key];
|
|
137
|
+
if (value instanceof RegExp) {
|
|
138
|
+
const src = value.source;
|
|
139
|
+
const flags = value.flags;
|
|
140
|
+
Object.defineProperty(this, key, {
|
|
141
|
+
get() {
|
|
142
|
+
return new RegExp(src, flags);
|
|
143
|
+
},
|
|
144
|
+
enumerable: true,
|
|
145
|
+
configurable: true
|
|
146
|
+
});
|
|
147
|
+
} else {
|
|
148
|
+
locales.set(key, value);
|
|
149
|
+
localeRegistry.set(this, locales);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
*[Symbol.iterator]() {
|
|
154
|
+
for (const key of Object.keys(this)) {
|
|
155
|
+
const desc = Object.getOwnPropertyDescriptor(this, key);
|
|
156
|
+
if (desc?.get) yield this[key];
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
function createPatterns(patterns) {
|
|
161
|
+
const result = Object.create(patternProto);
|
|
162
|
+
const locales = /* @__PURE__ */ new Map();
|
|
163
|
+
for (const key of Object.keys(patterns)) {
|
|
164
|
+
const value = patterns[key];
|
|
165
|
+
if (value instanceof RegExp) {
|
|
166
|
+
const src = value.source;
|
|
167
|
+
const flags = value.flags;
|
|
168
|
+
Object.defineProperty(result, key, {
|
|
169
|
+
get() {
|
|
170
|
+
return new RegExp(src, flags);
|
|
171
|
+
},
|
|
172
|
+
enumerable: true,
|
|
173
|
+
configurable: true
|
|
174
|
+
});
|
|
175
|
+
} else {
|
|
176
|
+
locales.set(key, value);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
localeRegistry.set(result, locales);
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
var localeRegistry = /* @__PURE__ */ new WeakMap();
|
|
183
|
+
var PROTECTED_PATTERNS = createPatterns({
|
|
184
|
+
email: /[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+/g,
|
|
185
|
+
url: /https?:\/\/[^\s]+/g,
|
|
186
|
+
unixPath: /\/[a-zA-Z0-9._\-/]+\.[a-zA-Z0-9]+/g,
|
|
187
|
+
windowsPath: /[A-Za-z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*/g,
|
|
188
|
+
xmlTag: /<\/?[a-zA-Z][^>]*>/g,
|
|
189
|
+
inlineCode: /`[^`\n]+`/g,
|
|
190
|
+
blockCode: /```[\s\S]*?```/g,
|
|
191
|
+
uuid: /\b[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\b/gi,
|
|
192
|
+
hash: /\b(?=[0-9a-f]*[a-f])[0-9a-f]{7,40}\b/gi,
|
|
193
|
+
ipv4: /\b(?:\d{1,3}\.){3}\d{1,3}\b/g,
|
|
194
|
+
ipv6: /\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/g,
|
|
195
|
+
mac: /\b(?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}\b/g,
|
|
196
|
+
version: /\bv?\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?\b/g,
|
|
197
|
+
selector: /[.#][A-Za-z_][\w-]*/g,
|
|
198
|
+
cliOption: /--?[a-zA-Z][\w-]*/g,
|
|
199
|
+
hashNumber: /(?<!\w)#[0-9]+\b/g,
|
|
200
|
+
isbn: /\b(?:97[89][- ]?)?(?:\d[- ]?){9}[\dX]\b/g,
|
|
201
|
+
issn: /\b\d{4}-\d{3}[\dX]\b/g,
|
|
202
|
+
doi: /\b10\.\d{4,9}\/[-._;()/:A-Za-z0-9]+\b/g,
|
|
203
|
+
orcid: /\b\d{4}-\d{4}-\d{4}-\d{3}[\dX]\b/g,
|
|
204
|
+
protect: /\[##\((.+)\)##\]/g,
|
|
205
|
+
["ru"]: {}
|
|
206
|
+
});
|
|
207
|
+
function protect(text, locale) {
|
|
208
|
+
const key = locale ? ALIAS.resolve(locale) ?? locale : void 0;
|
|
209
|
+
const captured = [];
|
|
210
|
+
const withNodeMarkers = text.replace(NODE_MARKER_REGEX, (match) => {
|
|
211
|
+
captured.push(match);
|
|
212
|
+
return PROTECTION_MARKER;
|
|
213
|
+
});
|
|
214
|
+
const withPatterns = withNodeMarkers.replace(PROTECTED_PATTERNS.combined(key), (match) => {
|
|
215
|
+
captured.push(match);
|
|
216
|
+
return PROTECTION_MARKER;
|
|
217
|
+
});
|
|
218
|
+
return [withPatterns, captured];
|
|
219
|
+
}
|
|
220
|
+
function unprotect(text, captured) {
|
|
221
|
+
const queue = [...captured];
|
|
222
|
+
return text.replace(PROTECTION_MARKER_REGEX, () => queue.shift() ?? "").replace(PROTECTED_PATTERNS.protect, "$1");
|
|
223
|
+
}
|
|
224
|
+
function joinNodes(nodes) {
|
|
225
|
+
return nodes.map((n) => n.value).join(NODE_MARKER);
|
|
226
|
+
}
|
|
227
|
+
function splitNodes(text, nodes) {
|
|
228
|
+
const segments = text.split(NODE_MARKER);
|
|
229
|
+
nodes.forEach((n, i) => {
|
|
230
|
+
n.value = segments[i] ?? n.value;
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
export {
|
|
234
|
+
NODE_MARKER,
|
|
235
|
+
NODE_MARKER_REGEX,
|
|
236
|
+
PROTECTED_PATTERNS,
|
|
237
|
+
PROTECTION_MARKER,
|
|
238
|
+
PROTECTION_MARKER_REGEX,
|
|
239
|
+
createPatterns,
|
|
240
|
+
joinNodes,
|
|
241
|
+
protect,
|
|
242
|
+
splitNodes,
|
|
243
|
+
unprotect
|
|
244
|
+
};
|
|
245
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw map of named RegExp patterns.
|
|
3
|
+
*
|
|
4
|
+
* Used as input to `createPatterns` to build a pattern registry
|
|
5
|
+
* with prototype utilities and safe per-access instantiation.
|
|
6
|
+
*/
|
|
7
|
+
export type PatternData = Record<string, RegExp | LocalePatterns>;
|
|
8
|
+
export type LocalePatterns = Record<string, RegExp>;
|
|
9
|
+
/**
|
|
10
|
+
* A pattern registry with prototype utilities attached.
|
|
11
|
+
*
|
|
12
|
+
* Each key from the source `PatternData` becomes a readonly accessor
|
|
13
|
+
* that returns a fresh `RegExp` instance on every access, preventing
|
|
14
|
+
* `lastIndex` pollution from the `g` flag across multiple calls.
|
|
15
|
+
*
|
|
16
|
+
* @template T — Shape of the source pattern map
|
|
17
|
+
*/
|
|
18
|
+
export type PatternSet<T extends PatternData> = {
|
|
19
|
+
[K in keyof T as T[K] extends RegExp ? K : never]: RegExp;
|
|
20
|
+
} & Record<string, RegExp | undefined> & PatternProto;
|
|
21
|
+
/**
|
|
22
|
+
* Prototype object attached to all pattern registries created by `createPatterns`.
|
|
23
|
+
*
|
|
24
|
+
* Provides shared `values` getter and `Symbol.iterator` without polluting
|
|
25
|
+
* the enumerable key space of the registry itself.
|
|
26
|
+
*
|
|
27
|
+
* Mirrors the role of `proto` in `createCharacters` from the glyphs module.
|
|
28
|
+
*/
|
|
29
|
+
export interface PatternProto {
|
|
30
|
+
/**
|
|
31
|
+
* Returns all RegExp patterns from the registry.
|
|
32
|
+
*
|
|
33
|
+
* Each access returns fresh `RegExp` instances with `lastIndex = 0`,
|
|
34
|
+
* preventing stateful issues with the `g` flag.
|
|
35
|
+
*
|
|
36
|
+
* Used when applying batch protection in preprocessing pipelines.
|
|
37
|
+
*/
|
|
38
|
+
readonly values: RegExp[];
|
|
39
|
+
/**
|
|
40
|
+
* Returns a single RegExp that combines all patterns via alternation.
|
|
41
|
+
*
|
|
42
|
+
* Built from `.source` of each pattern — safe to cache, as `lastIndex`
|
|
43
|
+
* is not involved at construction time.
|
|
44
|
+
*
|
|
45
|
+
* Prefer this over iterating `.values` with sequential `.replace()` calls —
|
|
46
|
+
* a single combined pass prevents one pattern from corrupting input for another.
|
|
47
|
+
*
|
|
48
|
+
* @param flags - RegExp flags for the combined pattern (default: `'g'`)
|
|
49
|
+
*/
|
|
50
|
+
combined(flags?: string, locale?: string): RegExp;
|
|
51
|
+
/**
|
|
52
|
+
* Populates the registry with new patterns.
|
|
53
|
+
*
|
|
54
|
+
* Each pattern is stored as a getter that returns a new `RegExp` instance
|
|
55
|
+
* on every access, ensuring `lastIndex` is always reset to `0` regardless
|
|
56
|
+
* of how the pattern was previously used.
|
|
57
|
+
*
|
|
58
|
+
* @param patterns - Raw map of named RegExp patterns
|
|
59
|
+
*/
|
|
60
|
+
insert(patterns: PatternData): void;
|
|
61
|
+
/**
|
|
62
|
+
* Iterator over all RegExp patterns in the registry.
|
|
63
|
+
*
|
|
64
|
+
* Each access returns fresh `RegExp` instances with `lastIndex = 0`,
|
|
65
|
+
* preventing stateful issues with the `g` flag.
|
|
66
|
+
*
|
|
67
|
+
* Enables usage in for..of loops, spreading, and pipeline-based processing.
|
|
68
|
+
*/
|
|
69
|
+
[Symbol.iterator](): Iterator<RegExp>;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=types.d.ts.map
|