(cs: string, str: string)
| 402 | * @returns {string} |
| 403 | */ |
| 404 | export const applyToText = (cs: string, str: string): string => { |
| 405 | const unpacked = unpack(cs); |
| 406 | assert(str.length === unpacked.oldLen, `mismatched apply: ${str.length} / ${unpacked.oldLen}`); |
| 407 | const bankIter = new StringIterator(unpacked.charBank); |
| 408 | const strIter = new StringIterator(str); |
| 409 | const assem = new StringAssembler(); |
| 410 | for (const op of deserializeOps(unpacked.ops)) { |
| 411 | switch (op.opcode) { |
| 412 | case '+': |
| 413 | // op is + and op.lines 0: no newlines must be in op.chars |
| 414 | // op is + and op.lines >0: op.chars must include op.lines newlines |
| 415 | if (op.lines !== bankIter.peek(op.chars).split('\n').length - 1) { |
| 416 | throw new Error(`newline count is wrong in op +; cs:${cs} and text:${str}`); |
| 417 | } |
| 418 | assem.append(bankIter.take(op.chars)); |
| 419 | break; |
| 420 | case '-': |
| 421 | // op is - and op.lines 0: no newlines must be in the deleted string |
| 422 | // op is - and op.lines >0: op.lines newlines must be in the deleted string |
| 423 | if (op.lines !== strIter.peek(op.chars).split('\n').length - 1) { |
| 424 | throw new Error(`newline count is wrong in op -; cs:${cs} and text:${str}`); |
| 425 | } |
| 426 | strIter.skip(op.chars); |
| 427 | break; |
| 428 | case '=': |
| 429 | // op is = and op.lines 0: no newlines must be in the copied string |
| 430 | // op is = and op.lines >0: op.lines newlines must be in the copied string |
| 431 | if (op.lines !== strIter.peek(op.chars).split('\n').length - 1) { |
| 432 | throw new Error(`newline count is wrong in op =; cs:${cs} and text:${str}`); |
| 433 | } |
| 434 | assem.append(strIter.take(op.chars)); |
| 435 | break; |
| 436 | } |
| 437 | } |
| 438 | assem.append(strIter.take(strIter.remaining())); |
| 439 | return assem.toString(); |
| 440 | }; |
| 441 | |
| 442 | /** |
| 443 | * Applies a changeset on an array of lines. |
no test coverage detected