(originalText, opts)
| 180 | } |
| 181 | |
| 182 | async function formatRange(originalText, opts) { |
| 183 | const { ast, text } = await parseText(originalText, opts); |
| 184 | const [rangeStart, rangeEnd] = calculateRange(text, opts, ast) ?? [0, 0]; |
| 185 | const rangeString = text.slice(rangeStart, rangeEnd); |
| 186 | |
| 187 | // Try to extend the range backwards to the beginning of the line. |
| 188 | // This is so we can detect indentation correctly and restore it. |
| 189 | // Use `Math.min` since `lastIndexOf` returns 0 when `rangeStart` is 0 |
| 190 | const rangeStart2 = Math.min( |
| 191 | rangeStart, |
| 192 | text.lastIndexOf("\n", rangeStart) + 1, |
| 193 | ); |
| 194 | const indentString = text.slice(rangeStart2, rangeStart).match(/^\s*/)[0]; |
| 195 | |
| 196 | const alignmentSize = getAlignmentSize(indentString, opts.tabWidth); |
| 197 | |
| 198 | const rangeResult = await coreFormat( |
| 199 | rangeString, |
| 200 | { |
| 201 | ...opts, |
| 202 | rangeStart: 0, |
| 203 | rangeEnd: Number.POSITIVE_INFINITY, |
| 204 | // Track the cursor offset only if it's within our range |
| 205 | cursorOffset: |
| 206 | opts.cursorOffset > rangeStart && opts.cursorOffset <= rangeEnd |
| 207 | ? opts.cursorOffset - rangeStart |
| 208 | : -1, |
| 209 | // Always use `lf` to format, we'll replace it later |
| 210 | endOfLine: "lf", |
| 211 | }, |
| 212 | alignmentSize, |
| 213 | ); |
| 214 | |
| 215 | // Since the range contracts to avoid trailing whitespace, |
| 216 | // we need to remove the newline that was inserted by the `format` call. |
| 217 | const rangeTrimmed = rangeResult.formatted.trimEnd(); |
| 218 | |
| 219 | let { cursorOffset } = opts; |
| 220 | if (cursorOffset > rangeEnd) { |
| 221 | // handle the case where the cursor was past the end of the range |
| 222 | cursorOffset += rangeTrimmed.length - rangeString.length; |
| 223 | } else if (rangeResult.cursorOffset >= 0) { |
| 224 | // handle the case where the cursor was in the range |
| 225 | cursorOffset = rangeResult.cursorOffset + rangeStart; |
| 226 | } |
| 227 | // keep the cursor as it was if it was before the start of the range |
| 228 | |
| 229 | let formatted = |
| 230 | text.slice(0, rangeStart) + rangeTrimmed + text.slice(rangeEnd); |
| 231 | if (opts.endOfLine !== "lf") { |
| 232 | const eol = convertEndOfLineOptionToCharacter(opts.endOfLine); |
| 233 | if (cursorOffset >= 0 && eol === "\r\n") { |
| 234 | cursorOffset += countEndOfLineCharacters( |
| 235 | formatted.slice(0, cursorOffset), |
| 236 | "\n", |
| 237 | ); |
| 238 | } |
| 239 |
no test coverage detected
searching dependent graphs…