punctilio 3.0.8 → 3.0.10

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/dist/symbols.js CHANGED
@@ -1,14 +1,11 @@
1
1
  /**
2
2
  * Symbol transformations: ellipses, multiplication, math symbols, arrows.
3
3
  */
4
- import escapeStringRegexp from "escape-string-regexp";
5
- import { UNICODE_SYMBOLS, ESCAPED_DEFAULT_SEPARATOR, LATIN_LETTERS, wordBoundaryEnd, SPACE_CHARS, spaceBoundaryStart, spaceBoundaryEnd, cachedRegExp } from "./constants.js";
4
+ import { UNICODE_SYMBOLS, LATIN_LETTERS, wordBoundaryEnd, SPACE_CHARS, spaceBoundaryStart, spaceBoundaryEnd, cachedRegExp, getEscapedSeparator } from "./constants.js";
6
5
  const { ELLIPSIS, MULTIPLICATION, NOT_EQUAL, PLUS_MINUS, COPYRIGHT, REGISTERED, TRADEMARK, DEGREE, ARROW_RIGHT, ARROW_LEFT, ARROW_LEFT_RIGHT, APPROXIMATE, LESS_EQUAL, GREATER_EQUAL, NBSP, PRIME, DOUBLE_PRIME, SUPERSCRIPT_ST, SUPERSCRIPT_ND, SUPERSCRIPT_RD, SUPERSCRIPT_TH, DOUBLE_QUESTION, QUESTION_EXCLAMATION, EXCLAMATION_QUESTION, } = UNICODE_SYMBOLS;
7
6
  /** Convert "..." or ". . ." to "…". */
8
7
  export function ellipsis(text, options = {}) {
9
- const chr = options.separator
10
- ? escapeStringRegexp(options.separator)
11
- : ESCAPED_DEFAULT_SEPARATOR;
8
+ const chr = getEscapedSeparator(options);
12
9
  // Convert consecutive or spaced dots: ... or . . . → …
13
10
  // Captures preserve any separators between dots
14
11
  const pattern = cachedRegExp(`\\.[${SPACE_CHARS}]?(${chr})?\\.([${SPACE_CHARS}]?)(${chr})?\\.`, "g");
@@ -20,9 +17,7 @@ export function ellipsis(text, options = {}) {
20
17
  }
21
18
  /** Convert "5x5" to "5×5". Skips hex (0x5F). */
22
19
  export function multiplication(text, options = {}) {
23
- const chr = options.separator
24
- ? escapeStringRegexp(options.separator)
25
- : ESCAPED_DEFAULT_SEPARATOR;
20
+ const chr = getEscapedSeparator(options);
26
21
  // Match entire multiplication chains in one pass: "5 x 5 x 5" or "5x5x5"
27
22
  // Pattern matches: digit(s), then one or more (operator, digit(s)) groups
28
23
  const chainPattern = cachedRegExp(`(?<!\\d)(\\d+)((?:${chr}?\\s*[xX*]\\s*${chr}?\\d+)+)`, "g");
@@ -63,9 +58,7 @@ const MATH_SYMBOL_MAP = [
63
58
  ];
64
59
  /** Convert !=, <=, >=, +/-, ~= to Unicode equivalents. */
65
60
  export function mathSymbols(text, options = {}) {
66
- const chr = options.separator
67
- ? escapeStringRegexp(options.separator)
68
- : ESCAPED_DEFAULT_SEPARATOR;
61
+ const chr = getEscapedSeparator(options);
69
62
  for (const [left, right, lookahead, replacement] of MATH_SYMBOL_MAP) {
70
63
  const pattern = cachedRegExp(`${left}${chr}?${right}${lookahead}`, "g");
71
64
  text = text.replace(pattern, replacement);
@@ -101,9 +94,7 @@ const ARROW_MAP = [
101
94
  ];
102
95
  /** Convert -> and <-> to arrows. */
103
96
  export function arrows(text, options = {}) {
104
- const chr = options.separator
105
- ? escapeStringRegexp(options.separator)
106
- : ESCAPED_DEFAULT_SEPARATOR;
97
+ const chr = getEscapedSeparator(options);
107
98
  const start = spaceBoundaryStart(chr);
108
99
  const end = spaceBoundaryEnd(chr);
109
100
  for (const [arrowPattern, replacement] of ARROW_MAP) {
@@ -114,9 +105,7 @@ export function arrows(text, options = {}) {
114
105
  }
115
106
  /** Convert "20 C" or "20 F" to "20 °C" or "20 °F". Only matches uppercase C/F. */
116
107
  export function degrees(text, options = {}) {
117
- const chr = options.separator
118
- ? escapeStringRegexp(options.separator)
119
- : ESCAPED_DEFAULT_SEPARATOR;
108
+ const chr = getEscapedSeparator(options);
120
109
  // Temperature with optional space before C or F (uppercase only)
121
110
  // Handles separator between digit and unit
122
111
  // Uses marker-aware boundary to avoid false matches like "20C\uE000elsius"
@@ -201,16 +190,14 @@ function balancedPrimeReplacer(primeChar, escapedSeparator) {
201
190
  }
202
191
  /** Convert 5'10" to 5′10″ (prime marks). Call before smart quotes. */
203
192
  export function primeMarks(text, options = {}) {
204
- const escapedSeparator = options.separator
205
- ? escapeStringRegexp(options.separator)
206
- : ESCAPED_DEFAULT_SEPARATOR;
193
+ const escapedSeparator = getEscapedSeparator(options);
207
194
  const quotePrimePairs = [
208
195
  ["'", PRIME],
209
196
  ['"', DOUBLE_PRIME],
210
197
  ];
211
198
  for (const [quote, primeChar] of quotePrimePairs) {
212
- const escapedQuote = escapeStringRegexp(quote);
213
- const pattern = buildQuoteClassificationPattern(escapedQuote, escapedSeparator);
199
+ // ' and " are not regex-special, so they can be used directly as patterns
200
+ const pattern = buildQuoteClassificationPattern(quote, escapedSeparator);
214
201
  text = text.replace(pattern, balancedPrimeReplacer(primeChar, escapedSeparator));
215
202
  }
216
203
  return text;
@@ -234,9 +221,7 @@ const FRACTION_MAP = {
234
221
  };
235
222
  /** Convert 1/2, 1/4, etc. to ½, ¼, etc. */
236
223
  export function fractions(text, options = {}) {
237
- const chr = options.separator
238
- ? escapeStringRegexp(options.separator)
239
- : ESCAPED_DEFAULT_SEPARATOR;
224
+ const chr = getEscapedSeparator(options);
240
225
  for (const [ascii, unicode] of Object.entries(FRACTION_MAP)) {
241
226
  // Negative lookbehind/lookahead: ensures fraction is not part of a larger number or path
242
227
  // - (?<![/.\d]) prevents matching after slashes, dots, or digits
@@ -257,9 +242,7 @@ const ORDINAL_MAP = {
257
242
  };
258
243
  /** Convert 1st, 2nd, 3rd, 4th to superscript ordinals. */
259
244
  export function superscriptOrdinal(text, options = {}) {
260
- const chr = options.separator
261
- ? escapeStringRegexp(options.separator)
262
- : ESCAPED_DEFAULT_SEPARATOR;
245
+ const chr = getEscapedSeparator(options);
263
246
  // Match number + optional separator + ordinal suffix at word boundary
264
247
  // Use case-insensitive matching for the suffix
265
248
  // Uses marker-aware boundary to avoid false matches like "1st\uE000ly"
@@ -290,9 +273,7 @@ const PUNCTUATION_LIGATURE_MAP = [
290
273
  ];
291
274
  /** Convert ?? to ⁇, ?! to ⁈, !? to ⁉. Poor font support, disabled by default. */
292
275
  export function punctuationLigatures(text, options = {}) {
293
- const chr = options.separator
294
- ? escapeStringRegexp(options.separator)
295
- : ESCAPED_DEFAULT_SEPARATOR;
276
+ const chr = getEscapedSeparator(options);
296
277
  for (const [first, repeated, replacement] of PUNCTUATION_LIGATURE_MAP) {
297
278
  const pattern = cachedRegExp(`${first}(${chr})?${repeated}(?:${chr}?${repeated})*`, "g");
298
279
  text = text.replace(pattern, (_match, sep) => replacement + (sep || ""));
@@ -1 +1 @@
1
- {"version":3,"file":"symbols.js","sourceRoot":"","sources":["../src/symbols.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"symbols.js","sourceRoot":"","sources":["../src/symbols.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "punctilio",
3
- "version": "3.0.8",
3
+ "version": "3.0.10",
4
4
  "description": "Smart typography transformations: curly quotes, em-dashes, en-dashes, and more",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/constants.ts CHANGED
@@ -124,6 +124,19 @@ export const LATIN_LETTERS = "A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u00F
124
124
  export const DEFAULT_SEPARATOR = "\uE000"
125
125
  export const ESCAPED_DEFAULT_SEPARATOR = escapeStringRegexp(DEFAULT_SEPARATOR)
126
126
 
127
+ /**
128
+ * Returns the regex-escaped separator string for the given options.
129
+ * Centralizes the common pattern of falling back to the pre-escaped default.
130
+ *
131
+ * @param options - Object with an optional `separator` field
132
+ * @returns Regex-escaped separator string
133
+ */
134
+ export function getEscapedSeparator(options: { separator?: string }): string {
135
+ return options.separator
136
+ ? escapeStringRegexp(options.separator)
137
+ : ESCAPED_DEFAULT_SEPARATOR
138
+ }
139
+
127
140
  /**
128
141
  * Characters that have special meaning in regular expressions.
129
142
  * Used for testing that separator escaping works correctly.
package/src/dashes.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import escapeStringRegexp from "escape-string-regexp"
6
- import { UNICODE_SYMBOLS, DEFAULT_SEPARATOR, ESCAPED_DEFAULT_SEPARATOR, LATIN_LETTERS, wordBoundaryStart, wordBoundaryEnd } from "./constants.js"
6
+ import { UNICODE_SYMBOLS, DEFAULT_SEPARATOR, LATIN_LETTERS, wordBoundaryStart, wordBoundaryEnd, getEscapedSeparator, cachedRegExp } from "./constants.js"
7
7
 
8
8
  export type DashStyle = "american" | "british" | "none"
9
9
 
@@ -32,7 +32,7 @@ export const months = [
32
32
 
33
33
  /** Convert number ranges to en-dash (e.g., "1-5" → "1–5"). */
34
34
  export function enDashNumberRange(text: string, options: DashOptions = {}): string {
35
- const chr = options.separator ? escapeStringRegexp(options.separator) : ESCAPED_DEFAULT_SEPARATOR
35
+ const chr = getEscapedSeparator(options)
36
36
  const wb = wordBoundaryStart(chr)
37
37
  const wbe = wordBoundaryEnd(chr)
38
38
 
@@ -56,11 +56,11 @@ export function enDashNumberRange(text: string, options: DashOptions = {}): stri
56
56
  ].join("")
57
57
 
58
58
  text = text.replace(
59
- new RegExp(positiveRangePattern, "g"),
59
+ cachedRegExp(positiveRangePattern, "g"),
60
60
  (match, precedingAreaCode, start, end, following, suffix = "") => {
61
61
  if (following) return match
62
- const startNum = start.replace(new RegExp(chr, "g"), "")
63
- const endNum = end.replace(new RegExp(chr, "g"), "")
62
+ const startNum = start.replace(cachedRegExp(chr, "g"), "")
63
+ const endNum = end.replace(cachedRegExp(chr, "g"), "")
64
64
  if (/^(?:19|20)\d{2}$/.test(startNum) && /^(?:0[1-9]|1[0-2])$/.test(endNum)) return match
65
65
  // Skip phone number patterns: 3 digits followed by 4 digits with preceding area code
66
66
  // e.g., 555-123-4567 or (555) 123-4567 where we're matching the "123-4567" part
@@ -75,7 +75,7 @@ export function enDashNumberRange(text: string, options: DashOptions = {}): stri
75
75
  // Negative ranges: −5-5 → −5–5, −5--2 → −5–−2
76
76
  // Separate regex because MINUS isn't a word char, so \b in ${wb} would match after it
77
77
  text = text.replace(
78
- new RegExp(
78
+ cachedRegExp(
79
79
  `(?<![${LATIN_LETTERS}])(?<start>${MINUS}\\d[\\d.,]*${chr}?)-(?<neg>-)?(?<end>${chr}?\\d[\\d.,]*)(?<following>(?:${chr}?-${chr}?\\d+)*)(?<suffix>${chr}?[xKBTM])?${wbe}`,
80
80
  "g"
81
81
  ),
@@ -92,12 +92,12 @@ export function enDashNumberRange(text: string, options: DashOptions = {}): stri
92
92
  export function enDashDateRange(text: string, options: DashOptions = {}): string {
93
93
  const dashStyle = options.dashStyle ?? "american"
94
94
  if (dashStyle === "none") return text
95
- const chr = options.separator ? escapeStringRegexp(options.separator) : ESCAPED_DEFAULT_SEPARATOR
95
+ const chr = getEscapedSeparator(options)
96
96
  const wb = wordBoundaryStart(chr)
97
97
  const wbe = wordBoundaryEnd(chr)
98
98
 
99
99
  return text.replace(
100
- new RegExp(`${wb}(?<startMonth>${months})(?<startYear>${chr}? \\d{4})?(?<preSep>${chr}?)(?<preSpace> ?)-(?<postSpace> ?)(?<postSep>${chr}?)(?<endMonth>${months})(?<endYear> \\d{4})?${wbe}`, "g"),
100
+ cachedRegExp(`${wb}(?<startMonth>${months})(?<startYear>${chr}? \\d{4})?(?<preSep>${chr}?)(?<preSpace> ?)-(?<postSpace> ?)(?<postSep>${chr}?)(?<endMonth>${months})(?<endYear> \\d{4})?${wbe}`, "g"),
101
101
  (...args) => {
102
102
  const g = args.at(-1) as Record<string, string>
103
103
  const [pre, post] = dashStyle === "british" ? [" ", " "] : ["", ""]
@@ -108,19 +108,19 @@ export function enDashDateRange(text: string, options: DashOptions = {}): string
108
108
 
109
109
  /** Convert hyphens to minus signs in numeric contexts (e.g., "-5" → "−5"). */
110
110
  export function minusReplace(text: string, options: DashOptions = {}): string {
111
- const chr = escapeStringRegexp(options.separator ?? DEFAULT_SEPARATOR)
111
+ const chr = getEscapedSeparator(options)
112
112
 
113
113
  // Pattern 1a: Subtraction of negative number (e.g., "5 - -3" → "5 − −3")
114
114
  // Must come before Pattern 1b so the negative hyphen is consumed first
115
115
  text = text.replaceAll(
116
- new RegExp(`(?<=\\d${chr}?) - -(?<num>${chr}?\\d*\\.?\\d+)`, "g"),
116
+ cachedRegExp(`(?<=\\d${chr}?) - -(?<num>${chr}?\\d*\\.?\\d+)`, "g"),
117
117
  ` ${MINUS} ${MINUS}$<num>`
118
118
  )
119
119
 
120
120
  // Pattern 1b: Spaced math subtraction (e.g., "5 - 3" → "5 − 3")
121
121
  // Only when preceded by a digit - this distinguishes "5 - 3" from "Safari) - 9"
122
122
  text = text.replaceAll(
123
- new RegExp(`(?<=\\d${chr}?) - (?<num>${chr}?\\d*\\.?\\d+)`, "g"),
123
+ cachedRegExp(`(?<=\\d${chr}?) - (?<num>${chr}?\\d*\\.?\\d+)`, "g"),
124
124
  ` ${MINUS} $<num>`
125
125
  )
126
126
 
@@ -128,7 +128,7 @@ export function minusReplace(text: string, options: DashOptions = {}): string {
128
128
  // Match after: start of line, whitespace, (, or quotes (straight or curly)
129
129
  // No space allowed between hyphen and digit
130
130
  text = text.replaceAll(
131
- new RegExp(`(?<before>^|[\\s\\("${LEFT_DOUBLE_QUOTE}${RIGHT_DOUBLE_QUOTE}])-(?<num>\\d*\\.?\\d+)`, "gm"),
131
+ cachedRegExp(`(?<before>^|[\\s\\("${LEFT_DOUBLE_QUOTE}${RIGHT_DOUBLE_QUOTE}])-(?<num>\\d*\\.?\\d+)`, "gm"),
132
132
  `$<before>${MINUS}$<num>`
133
133
  )
134
134
 
@@ -136,7 +136,7 @@ export function minusReplace(text: string, options: DashOptions = {}): string {
136
136
  // Only when no word character precedes the separator — prevents both
137
137
  // "2{SEP}-3" in "1-2-3" and "GPT{SEP}-3" from being misidentified as negative 3
138
138
  text = text.replaceAll(
139
- new RegExp(`(?<![\\d.,${LATIN_LETTERS}])(?<before>${chr})-(?<num>\\d*\\.?\\d+)`, "gm"),
139
+ cachedRegExp(`(?<![\\d.,${LATIN_LETTERS}])(?<before>${chr})-(?<num>\\d*\\.?\\d+)`, "gm"),
140
140
  `$<before>${MINUS}$<num>`
141
141
  )
142
142
 
@@ -157,7 +157,7 @@ function convertParentheticalDashes(text: string, sep: string, style: DashStyle)
157
157
  // A single plain hyphen directly before a word character (through optional separators) is a
158
158
  // suspended/hanging hyphen ("Yes-men and -women"), not a parenthetical dash — skip it.
159
159
  // Em/en dashes and multiple hyphens can have zero trailing spaces.
160
- const spacedDashPattern = new RegExp(
160
+ const spacedDashPattern = cachedRegExp(
161
161
  `(?<=[^\\s]|^)(?<sepBefore>${escapedSep}?)[ ]+(?:[${EN_DASH}${EM_DASH}][-${EN_DASH}${EM_DASH}]*|-{2,}|-(?!${escapedSep}*[${LATIN_LETTERS}\\d]))(?!-*>)[ ]*(?<sepAfter>${escapedSep}?)(?<trailing>[ ]*)(?=\\S|$)`, "g"
162
162
  )
163
163
  text = text.replace(spacedDashPattern, (_match, sepBefore, sepAfter, trailing) => {
@@ -169,21 +169,21 @@ function convertParentheticalDashes(text: string, sep: string, style: DashStyle)
169
169
  // Convert dashes at text node boundaries: separator alone precedes dash (e.g., "word{sep}– rest")
170
170
  // Requires space after the dash to avoid matching number ranges like "1{sep}-{sep}5"
171
171
  text = text.replace(
172
- new RegExp(`(?<=[^\\s])(?<sepBefore>${escapedSep})[${EN_DASH}${EM_DASH}-]+[ ]+(?<sepAfter>${escapedSep}?)`, "g"),
172
+ cachedRegExp(`(?<=[^\\s])(?<sepBefore>${escapedSep})[${EN_DASH}${EM_DASH}-]+[ ]+(?<sepAfter>${escapedSep}?)`, "g"),
173
173
  `$<sepBefore>${maybeSpace}${localizedDash}${maybeSpace}$<sepAfter>`
174
174
  )
175
175
  // Convert multiple dashes: "word--word" or "word---word" or "quote"--"quote"
176
176
  const quoteChars = `"'${LEFT_DOUBLE_QUOTE}${RIGHT_DOUBLE_QUOTE}${LEFT_SINGLE_QUOTE}${RIGHT_SINGLE_QUOTE}`
177
177
  text = text.replace(
178
- new RegExp(`(?<=[${LATIN_LETTERS}\\d${quoteChars}])(?<sepBefore>${escapedSep}?)[${EN_DASH}${EM_DASH}-]{2,}(?<sepAfter>${escapedSep}?)(?=[${LATIN_LETTERS}${quoteChars} ])`, "g"),
178
+ cachedRegExp(`(?<=[${LATIN_LETTERS}\\d${quoteChars}])(?<sepBefore>${escapedSep}?)[${EN_DASH}${EM_DASH}-]{2,}(?<sepAfter>${escapedSep}?)(?=[${LATIN_LETTERS}${quoteChars} ])`, "g"),
179
179
  `$<sepBefore>${maybeSpace}${localizedDash}${maybeSpace}$<sepAfter>`
180
180
  )
181
181
  // Convert dashes at start of line
182
- text = text.replace(new RegExp(`^(?<leadingSep>${escapedSep})?[-]+ `, "gm"), `$<leadingSep>${localizedDash} `)
182
+ text = text.replace(cachedRegExp(`^(?<leadingSep>${escapedSep})?[-]+ `, "gm"), `$<leadingSep>${localizedDash} `)
183
183
  // British: convert unspaced em-dashes to spaced en-dashes (word—word → word – word)
184
184
  if (style === "british") {
185
185
  text = text.replace(
186
- new RegExp(`(?<=[${LATIN_LETTERS}.!?'"])(?<sepBefore>${escapedSep}?)${EM_DASH}(?<sepAfter>${escapedSep}?)(?=[${LATIN_LETTERS}])`, "g"),
186
+ cachedRegExp(`(?<=[${LATIN_LETTERS}.!?'"])(?<sepBefore>${escapedSep}?)${EM_DASH}(?<sepAfter>${escapedSep}?)(?=[${LATIN_LETTERS}])`, "g"),
187
187
  `$<sepBefore>${maybeSpace}${localizedDash}${maybeSpace}$<sepAfter>`
188
188
  )
189
189
  }
@@ -202,13 +202,13 @@ function normalizeEmDashSpacing(text: string, sep: string): string {
202
202
 
203
203
  // Remove all spaces around em-dashes
204
204
  text = text.replace(
205
- new RegExp(`(?<before>${escapedSep}?)[ ]*${EM_DASH}[ ]*(?<after>${escapedSep}?)`, "g"),
205
+ cachedRegExp(`(?<before>${escapedSep}?)[ ]*${EM_DASH}[ ]*(?<after>${escapedSep}?)`, "g"),
206
206
  `$<before>${EM_DASH}$<after>`
207
207
  )
208
208
 
209
209
  // Preserve space after em-dash at start of line (e.g., attribution)
210
210
  text = text.replace(
211
- new RegExp(`^(?<sep>${escapedSep}?)${EM_DASH}(?<after>[A-Z0-9])`, "gm"),
211
+ cachedRegExp(`^(?<sep>${escapedSep}?)${EM_DASH}(?<after>[A-Z0-9])`, "gm"),
212
212
  `$<sep>${EM_DASH} $<after>`
213
213
  )
214
214
 
package/src/nbsp.ts CHANGED
@@ -8,9 +8,7 @@
8
8
  * @module nbsp
9
9
  */
10
10
 
11
- import escapeStringRegexp from "escape-string-regexp"
12
-
13
- import { UNICODE_SYMBOLS, ESCAPED_DEFAULT_SEPARATOR, LATIN_LETTERS, wordBoundaryEnd } from "./constants.js"
11
+ import { UNICODE_SYMBOLS, LATIN_LETTERS, wordBoundaryEnd, getEscapedSeparator, cachedRegExp } from "./constants.js"
14
12
  import type { SymbolOptions } from "./symbols.js"
15
13
 
16
14
  const {
@@ -26,12 +24,6 @@ const {
26
24
 
27
25
  export type NbspOptions = Pick<SymbolOptions, "separator">
28
26
 
29
- function escapedSeparator(options: NbspOptions): string {
30
- return options.separator
31
- ? escapeStringRegexp(options.separator)
32
- : ESCAPED_DEFAULT_SEPARATOR
33
- }
34
-
35
27
  /** Space pattern matching regular space, tab, and nbsp. */
36
28
  const SPACE = `[ \\t${NBSP}]`
37
29
 
@@ -111,8 +103,8 @@ const COPYRIGHT_SYMBOLS = `[${COPYRIGHT}${REGISTERED}${TRADEMARK}]`
111
103
  * @example "a cat" → "a\u00A0cat", "I am" → "I\u00A0am"
112
104
  */
113
105
  export function nbspAfterShortWords(text: string, options: NbspOptions = {}): string {
114
- const sep = escapedSeparator(options)
115
- const pattern = new RegExp(
106
+ const sep = getEscapedSeparator(options)
107
+ const pattern = cachedRegExp(
116
108
  `(?<=^|${SPACE}|${PUNCTUATION_OR_QUOTE}|>)(?<shortWord>[${LATIN_LETTERS}]{1,2})(?<marker>${sep}?)${SPACE}`,
117
109
  "gmu"
118
110
  )
@@ -125,9 +117,9 @@ export function nbspAfterShortWords(text: string, options: NbspOptions = {}): st
125
117
  * @example "100 km" → "100\u00A0km", "5 kg" → "5\u00A0kg"
126
118
  */
127
119
  export function nbspBetweenNumberAndUnit(text: string, options: NbspOptions = {}): string {
128
- const sep = escapedSeparator(options)
120
+ const sep = getEscapedSeparator(options)
129
121
  const wbe = wordBoundaryEnd(sep)
130
- const pattern = new RegExp(
122
+ const pattern = cachedRegExp(
131
123
  `(?<digit>\\d)(?<marker1>${sep}?)${SPACE}(?<marker2>${sep}?)(?<unit>${UNIT_PATTERN})${wbe}`,
132
124
  "gm"
133
125
  )
@@ -142,8 +134,8 @@ export function nbspBetweenNumberAndUnit(text: string, options: NbspOptions = {}
142
134
  * true end of string.
143
135
  */
144
136
  export function nbspBeforeLastWord(text: string, options: NbspOptions = {}): string {
145
- const sep = escapedSeparator(options)
146
- const pattern = new RegExp(
137
+ const sep = getEscapedSeparator(options)
138
+ const pattern = cachedRegExp(
147
139
  `(?<=[\\w${sep}])${SPACE}(?<lastWord>[^\\s${sep}]{1,10})(?<ending>${sep}?(?:\\n\\n|$))`,
148
140
  "g"
149
141
  )
@@ -157,8 +149,8 @@ export function nbspBeforeLastWord(text: string, options: NbspOptions = {}): str
157
149
  * @example "Fig. 1" → "Fig.\u00A01", "p. 42" → "p.\u00A042"
158
150
  */
159
151
  export function nbspAfterReferenceAbbreviations(text: string, options: NbspOptions = {}): string {
160
- const sep = escapedSeparator(options)
161
- const pattern = new RegExp(
152
+ const sep = getEscapedSeparator(options)
153
+ const pattern = cachedRegExp(
162
154
  `(?<abbrev>${ABBREVIATION_PATTERN})(?<marker>${sep}?)${SPACE}(?=${sep}?\\d)`,
163
155
  "g"
164
156
  )
@@ -172,8 +164,8 @@ export function nbspAfterReferenceAbbreviations(text: string, options: NbspOptio
172
164
  * @example "§ 5" → "§\u00A05"
173
165
  */
174
166
  export function nbspAfterSectionSymbols(text: string, options: NbspOptions = {}): string {
175
- const sep = escapedSeparator(options)
176
- const pattern = new RegExp(
167
+ const sep = getEscapedSeparator(options)
168
+ const pattern = cachedRegExp(
177
169
  `(?<symbol>[§¶])(?<marker>${sep}?)${SPACE}(?=${sep}?\\d)`,
178
170
  "g"
179
171
  )
@@ -186,8 +178,8 @@ export function nbspAfterSectionSymbols(text: string, options: NbspOptions = {})
186
178
  * @example "Dr. Smith" → "Dr.\u00A0Smith", "Mr. Jones" → "Mr.\u00A0Jones"
187
179
  */
188
180
  export function nbspAfterHonorifics(text: string, options: NbspOptions = {}): string {
189
- const sep = escapedSeparator(options)
190
- const pattern = new RegExp(
181
+ const sep = getEscapedSeparator(options)
182
+ const pattern = cachedRegExp(
191
183
  `(?<honorific>${HONORIFIC_PATTERN})(?<marker>${sep}?)${SPACE}(?=${sep}?${UNICODE_UPPERCASE})`,
192
184
  "gu"
193
185
  )
@@ -201,8 +193,8 @@ export function nbspAfterHonorifics(text: string, options: NbspOptions = {}): st
201
193
  * @example "© 2024" → "©\u00A02024", "® Brand" → "®\u00A0Brand"
202
194
  */
203
195
  export function nbspAfterCopyrightSymbols(text: string, options: NbspOptions = {}): string {
204
- const sep = escapedSeparator(options)
205
- const pattern = new RegExp(
196
+ const sep = getEscapedSeparator(options)
197
+ const pattern = cachedRegExp(
206
198
  `(?<symbol>${COPYRIGHT_SYMBOLS})(?<marker>${sep}?)${SPACE}(?=${sep}?[\\d${UNICODE_UPPERCASE}])`,
207
199
  "gu"
208
200
  )
@@ -215,8 +207,8 @@ export function nbspAfterCopyrightSymbols(text: string, options: NbspOptions = {
215
207
  * @example "J. K. Rowling" → "J.\u00A0K.\u00A0Rowling"
216
208
  */
217
209
  export function nbspBetweenInitials(text: string, options: NbspOptions = {}): string {
218
- const sep = escapedSeparator(options)
219
- const pattern = new RegExp(
210
+ const sep = getEscapedSeparator(options)
211
+ const pattern = cachedRegExp(
220
212
  `(?<initial>${UNICODE_UPPERCASE}\\.)(?<marker>${sep}?)${SPACE}(?=${sep}?${UNICODE_UPPERCASE})`,
221
213
  "gu"
222
214
  )
package/src/quotes.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import escapeStringRegexp from "escape-string-regexp"
6
- import { UNICODE_SYMBOLS, DEFAULT_SEPARATOR, LATIN_LETTERS, TERMINAL_PUNCTUATION } from "./constants.js"
6
+ import { UNICODE_SYMBOLS, DEFAULT_SEPARATOR, LATIN_LETTERS, TERMINAL_PUNCTUATION, cachedRegExp } from "./constants.js"
7
7
 
8
8
  const {
9
9
  EM_DASH,
@@ -34,8 +34,8 @@ function convertSingleQuotes(text: string, sep: string): string {
34
34
  // Only match straight quotes, not already-converted curly quotes
35
35
  const singleQuoteChars = `'${LEFT_SINGLE_QUOTE}${RIGHT_SINGLE_QUOTE}${MODIFIER_LETTER_APOSTROPHE}`
36
36
  const singleQuoteOrWord = `[${singleQuoteChars}\\w]`
37
- text = text.replace(new RegExp(`(?<!${singleQuoteOrWord})''(?!${singleQuoteOrWord})`, "g"), `${LEFT_SINGLE_QUOTE}${RIGHT_SINGLE_QUOTE}`)
38
- text = text.replace(new RegExp(`(?<!${singleQuoteOrWord})'(\\s+)'(?!${singleQuoteOrWord})`, "g"), `${LEFT_SINGLE_QUOTE}$1${RIGHT_SINGLE_QUOTE}`)
37
+ text = text.replace(cachedRegExp(`(?<!${singleQuoteOrWord})''(?!${singleQuoteOrWord})`, "g"), `${LEFT_SINGLE_QUOTE}${RIGHT_SINGLE_QUOTE}`)
38
+ text = text.replace(cachedRegExp(`(?<!${singleQuoteOrWord})'(\\s+)'(?!${singleQuoteOrWord})`, "g"), `${LEFT_SINGLE_QUOTE}$1${RIGHT_SINGLE_QUOTE}`)
39
39
 
40
40
  const afterEndingSinglePatterns = `\\s\\.!?;,\\)${EM_DASH}\\-\\]"`
41
41
  // Full pattern with optional 's' for lookahead detection in apostropheRegex
@@ -45,32 +45,32 @@ function convertSingleQuotes(text: string, sep: string): string {
45
45
  // the general rules produced LSQ+n+RSQ which was fine. But MLA requires both
46
46
  // quotes to be MLA (semantic apostrophes), and the general rules can't achieve
47
47
  // that: neither quote is in a contraction context (no Latin letter on both sides).
48
- text = text.replace(new RegExp(`(?<=\\w${escapedSep}? )['${RIGHT_SINGLE_QUOTE}]n['${RIGHT_SINGLE_QUOTE}](?= ${escapedSep}?\\w)`, "gm"), `${MODIFIER_LETTER_APOSTROPHE}n${MODIFIER_LETTER_APOSTROPHE}`)
48
+ text = text.replace(cachedRegExp(`(?<=\\w${escapedSep}? )['${RIGHT_SINGLE_QUOTE}]n['${RIGHT_SINGLE_QUOTE}](?= ${escapedSep}?\\w)`, "gm"), `${MODIFIER_LETTER_APOSTROPHE}n${MODIFIER_LETTER_APOSTROPHE}`)
49
49
 
50
50
  // Possessive: 's followed by ending context (e.g., dog's) → U+02BC
51
51
  const afterPossessive = `(?=${escapedSep}?s${escapedSep}?(?:[${afterEndingSinglePatterns}]|$))`
52
52
  const possessiveSingle = `(?<=[^\\s${LEFT_DOUBLE_QUOTE}'])['${RIGHT_SINGLE_QUOTE}]${afterPossessive}`
53
- text = text.replace(new RegExp(possessiveSingle, "gm"), MODIFIER_LETTER_APOSTROPHE)
53
+ text = text.replace(cachedRegExp(possessiveSingle, "gm"), MODIFIER_LETTER_APOSTROPHE)
54
54
 
55
55
  // Closing single quote: ending context without 's' → U+2019
56
56
  const afterClosingSingle = `(?=${escapedSep}?(?:[${afterEndingSinglePatterns}]|$))`
57
57
  const closingSingle = `(?<=[^\\s${LEFT_DOUBLE_QUOTE}'])[']${afterClosingSingle}`
58
- text = text.replace(new RegExp(closingSingle, "gm"), RIGHT_SINGLE_QUOTE)
58
+ text = text.replace(cachedRegExp(closingSingle, "gm"), RIGHT_SINGLE_QUOTE)
59
59
 
60
60
  const contraction = `(?<=[${LATIN_LETTERS}])['${RIGHT_SINGLE_QUOTE}${MODIFIER_LETTER_APOSTROPHE}](?=${escapedSep}?[${LATIN_LETTERS}])`
61
- text = text.replace(new RegExp(contraction, "gm"), MODIFIER_LETTER_APOSTROPHE)
61
+ text = text.replace(cachedRegExp(contraction, "gm"), MODIFIER_LETTER_APOSTROPHE)
62
62
 
63
63
  const apostropheWhitelist = `(?=n${MODIFIER_LETTER_APOSTROPHE} )`
64
64
  const endQuoteNotContraction = `(?!${contraction})[${RIGHT_SINGLE_QUOTE}${MODIFIER_LETTER_APOSTROPHE}]${afterEndingSingle}`
65
65
  // Limit lookahead scan to 1000 chars to prevent catastrophic backtracking on pathological inputs
66
- const apostropheRegex = new RegExp(
66
+ const apostropheRegex = cachedRegExp(
67
67
  `(?<=^|[^\\w])['](${apostropheWhitelist}|(?![^${LEFT_SINGLE_QUOTE}'\\n]{0,1000}${endQuoteNotContraction}))`,
68
68
  "gm"
69
69
  )
70
70
  text = text.replace(apostropheRegex, MODIFIER_LETTER_APOSTROPHE)
71
71
 
72
72
  const beginningSingle = `(?<beforeContext>(?:^|[\\s${LEFT_DOUBLE_QUOTE}${RIGHT_DOUBLE_QUOTE}${EM_DASH}\\-\\(])${escapedSep}?)['](?=${escapedSep}?\\S)`
73
- text = text.replace(new RegExp(beginningSingle, "gm"), `$<beforeContext>${LEFT_SINGLE_QUOTE}`)
73
+ text = text.replace(cachedRegExp(beginningSingle, "gm"), `$<beforeContext>${LEFT_SINGLE_QUOTE}`)
74
74
 
75
75
  text = convertUnmatchedPluralPossessives(text, sep)
76
76
 
@@ -85,7 +85,7 @@ function convertSingleQuotes(text: string, sep: string): string {
85
85
  function convertUnmatchedPluralPossessives(text: string, sep: string): string {
86
86
  let singleQuoteBalance = 0
87
87
  return text.replace(
88
- new RegExp(`[${LEFT_SINGLE_QUOTE}${RIGHT_SINGLE_QUOTE}]`, "g"),
88
+ cachedRegExp(`[${LEFT_SINGLE_QUOTE}${RIGHT_SINGLE_QUOTE}]`, "g"),
89
89
  (match, offset) => {
90
90
  if (match === LEFT_SINGLE_QUOTE) {
91
91
  singleQuoteBalance++
@@ -115,19 +115,19 @@ function convertDoubleQuotes(text: string, sep: string): string {
115
115
  // Handle whitespace-only quotes " " - require non-quote chars on both sides
116
116
  text = text.replace(/(?<=^|[\s([{])"(?<whitespace>\s+)"(?=$|[\s)\]}.!?,;:])/g, `${LEFT_DOUBLE_QUOTE}$<whitespace>${RIGHT_DOUBLE_QUOTE}`)
117
117
 
118
- const beginningDouble = new RegExp(
118
+ const beginningDouble = cachedRegExp(
119
119
  `(?<=^|[\\s\\(\\/\\[\\{\\-${EM_DASH}${escapedSep}])(?<beforeChr>${escapedSep}?)["](?<afterChr>(?<sepWithPunct>${escapedSep}[ .,])|(?=${escapedSep}?\\.{3}|${escapedSep}?[^\\s\\)\\${EM_DASH},!?${escapedSep};:.\\}]))`,
120
120
  "gm"
121
121
  )
122
122
  text = text.replace(beginningDouble, `$<beforeChr>${LEFT_DOUBLE_QUOTE}$<afterChr>`)
123
123
 
124
- text = text.replace(new RegExp(`(?<=\\{)(?<sepSpace>${escapedSep}? )?["]`, "g"), `$<sepSpace>${LEFT_DOUBLE_QUOTE}`)
124
+ text = text.replace(cachedRegExp(`(?<=\\{)(?<sepSpace>${escapedSep}? )?["]`, "g"), `$<sepSpace>${LEFT_DOUBLE_QUOTE}`)
125
125
 
126
126
  const endingDouble = `(?<beforeQuote>[^\\s\\(])["]((?<sepAfter>${escapedSep})?)(?=${escapedSep}|[\\s/\\).,;${EM_DASH}:\\-\\}!?s]|$)`
127
- text = text.replace(new RegExp(endingDouble, "g"), `$<beforeQuote>${RIGHT_DOUBLE_QUOTE}$<sepAfter>`)
127
+ text = text.replace(cachedRegExp(endingDouble, "g"), `$<beforeQuote>${RIGHT_DOUBLE_QUOTE}$<sepAfter>`)
128
128
 
129
- text = text.replace(new RegExp(`["](?<sepEnd>${escapedSep}?)$`, "g"), `${RIGHT_DOUBLE_QUOTE}$<sepEnd>`)
130
- text = text.replace(new RegExp(`'(?=${RIGHT_DOUBLE_QUOTE})`, "gu"), RIGHT_SINGLE_QUOTE)
129
+ text = text.replace(cachedRegExp(`["](?<sepEnd>${escapedSep}?)$`, "g"), `${RIGHT_DOUBLE_QUOTE}$<sepEnd>`)
130
+ text = text.replace(cachedRegExp(`'(?=${RIGHT_DOUBLE_QUOTE})`, "gu"), RIGHT_SINGLE_QUOTE)
131
131
 
132
132
  return text
133
133
  }
@@ -138,14 +138,14 @@ function applyPunctuationStyle(text: string, sep: string, style: PunctuationStyl
138
138
 
139
139
  if (style === "american") {
140
140
  // Period outside → inside: "Hello". → "Hello."
141
- const periodOutsideRegex = new RegExp(
141
+ const periodOutsideRegex = cachedRegExp(
142
142
  `(?<![${TERMINAL_PUNCTUATION_CLASS}])(?<sepBefore>${escapedSep}?)(?<quote>[${RIGHT_SINGLE_QUOTE}${RIGHT_DOUBLE_QUOTE}])(?<sepAfter>${escapedSep}?)(?!\\.\\.\\.)\\.`,
143
143
  "g"
144
144
  )
145
145
  text = text.replace(periodOutsideRegex, "$<sepBefore>.$<quote>$<sepAfter>")
146
146
 
147
147
  // Comma outside → inside: "Hello", → "Hello,"
148
- const commaOutsideRegex = new RegExp(
148
+ const commaOutsideRegex = cachedRegExp(
149
149
  `(?<![${TERMINAL_PUNCTUATION_CLASS}])(?<sepBefore>${escapedSep}?)(?<quote>[${RIGHT_SINGLE_QUOTE}${RIGHT_DOUBLE_QUOTE}])(?<sepAfter>${escapedSep}?),`,
150
150
  "g"
151
151
  )
@@ -153,14 +153,14 @@ function applyPunctuationStyle(text: string, sep: string, style: PunctuationStyl
153
153
  } else if (style === "british") {
154
154
  // Period inside → outside: "Hello." → "Hello".
155
155
  // No terminal punctuation guard — "Stop!." inside is always wrong; move the period out.
156
- const periodInsideRegex = new RegExp(
156
+ const periodInsideRegex = cachedRegExp(
157
157
  `(?<sepBefore>${escapedSep}?)\\.(?<sepMiddle>${escapedSep}?)(?<quote>[${RIGHT_SINGLE_QUOTE}${RIGHT_DOUBLE_QUOTE}])`,
158
158
  "g"
159
159
  )
160
160
  text = text.replace(periodInsideRegex, "$<sepBefore>$<sepMiddle>$<quote>.")
161
161
 
162
162
  // Comma inside → outside: "Hello," → "Hello",
163
- const commaInsideRegex = new RegExp(
163
+ const commaInsideRegex = cachedRegExp(
164
164
  `,(?<sepAndQuote>${escapedSep}?[${RIGHT_DOUBLE_QUOTE}${RIGHT_SINGLE_QUOTE}])`,
165
165
  "g"
166
166
  )