(str: string)
| 171 | } |
| 172 | |
| 173 | function applyCurlySingleQuotes(str: string): string { |
| 174 | const chars = [...str] |
| 175 | const result: string[] = [] |
| 176 | for (let i = 0; i < chars.length; i++) { |
| 177 | if (chars[i] === "'") { |
| 178 | // Don't convert apostrophes in contractions (e.g., "don't", "it's") |
| 179 | // An apostrophe between two letters is a contraction, not a quote |
| 180 | const prev = i > 0 ? chars[i - 1] : undefined |
| 181 | const next = i < chars.length - 1 ? chars[i + 1] : undefined |
| 182 | const prevIsLetter = prev !== undefined && /\p{L}/u.test(prev) |
| 183 | const nextIsLetter = next !== undefined && /\p{L}/u.test(next) |
| 184 | if (prevIsLetter && nextIsLetter) { |
| 185 | // Apostrophe in a contraction — use right single curly quote |
| 186 | result.push(RIGHT_SINGLE_CURLY_QUOTE) |
| 187 | } else { |
| 188 | result.push( |
| 189 | isOpeningContext(chars, i) |
| 190 | ? LEFT_SINGLE_CURLY_QUOTE |
| 191 | : RIGHT_SINGLE_CURLY_QUOTE, |
| 192 | ) |
| 193 | } |
| 194 | } else { |
| 195 | result.push(chars[i]!) |
| 196 | } |
| 197 | } |
| 198 | return result.join('') |
| 199 | } |
| 200 | |
| 201 | /** |
| 202 | * Transform edits to ensure replace_all always has a boolean value |
no test coverage detected