Brunobkr/llama.cpp_AlgMor24_github
ΩFFFΣLLIa • llama.cpp • AlgMor24 ██████╗ ███████╗███████╗███████╗██╗ ██╗ ██╗ █████╗ ██╔═══██╗██╔════╝██╔════╝██╔════╝██║ ██║ ██║██╔══██╗ ██║ ██║█████╗ █████╗ █████╗ ██║ ██║ ██║███████║ ██║ ██║██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ██║██╔══██║ ╚██████╔╝██║ ██║ ███████╗███████╗███████╗██║██║ ██║ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝ High-Performance LLM / VLM Inference & Autonomous Agentic Ecosystem… See the full description on the dataset page: https://huggingface.co/datasets/Brunobkr/llama.cpp_AlgMor24_github.
03.1k
1import { encode } from '@jridgewell/sourcemap-codec';2 3class BitSet {4 constructor(arg) {5 this.bits = arg instanceof BitSet ? arg.bits.slice() : [];6 }7 8 add(n) {9 this.bits[n >> 5] |= 1 << (n & 31);10 }11 12 has(n) {13 return !!(this.bits[n >> 5] & (1 << (n & 31)));14 }15}16 17class Chunk {18 constructor(start, end, content) {19 this.start = start;20 this.end = end;21 this.original = content;22 23 this.intro = '';24 this.outro = '';25 26 this.content = content;27 this.storeName = false;28 this.edited = false;29 30 {31 this.previous = null;32 this.next = null;33 }34 }35 36 appendLeft(content) {37 this.outro += content;38 }39 40 appendRight(content) {41 this.intro = this.intro + content;42 }43 44 clone() {45 const chunk = new Chunk(this.start, this.end, this.original);46 47 chunk.intro = this.intro;48 chunk.outro = this.outro;49 chunk.content = this.content;50 chunk.storeName = this.storeName;51 chunk.edited = this.edited;52 53 return chunk;54 }55 56 contains(index) {57 return this.start < index && index < this.end;58 }59 60 eachNext(fn) {61 let chunk = this;62 while (chunk) {63 fn(chunk);64 chunk = chunk.next;65 }66 }67 68 eachPrevious(fn) {69 let chunk = this;70 while (chunk) {71 fn(chunk);72 chunk = chunk.previous;73 }74 }75 76 edit(content, storeName, contentOnly) {77 this.content = content;78 if (!contentOnly) {79 this.intro = '';80 this.outro = '';81 }82 this.storeName = storeName;83 84 this.edited = true;85 86 return this;87 }88 89 prependLeft(content) {90 this.outro = content + this.outro;91 }92 93 prependRight(content) {94 this.intro = content + this.intro;95 }96 97 reset() {98 this.intro = '';99 this.outro = '';100 if (this.edited) {101 this.content = this.original;102 this.storeName = false;103 this.edited = false;104 }105 }106 107 split(index) {108 const sliceIndex = index - this.start;109 110 const originalBefore = this.original.slice(0, sliceIndex);111 const originalAfter = this.original.slice(sliceIndex);112 113 this.original = originalBefore;114 115 const newChunk = new Chunk(index, this.end, originalAfter);116 newChunk.outro = this.outro;117 this.outro = '';118 119 this.end = index;120 121 if (this.edited) {122 // after split we should save the edit content record into the correct chunk123 // to make sure sourcemap correct124 // For example:125 // ' test'.trim()126 // split -> ' ' + 'test'127 // ✔️ edit -> '' + 'test'128 // ✖️ edit -> 'test' + ''129 // TODO is this block necessary?...130 newChunk.edit('', false);131 this.content = '';132 } else {133 this.content = originalBefore;134 }135 136 newChunk.next = this.next;137 if (newChunk.next) newChunk.next.previous = newChunk;138 newChunk.previous = this;139 this.next = newChunk;140 141 return newChunk;142 }143 144 toString() {145 return this.intro + this.content + this.outro;146 }147 148 trimEnd(rx) {149 this.outro = this.outro.replace(rx, '');150 if (this.outro.length) return true;151 152 const trimmed = this.content.replace(rx, '');153 154 if (trimmed.length) {155 if (trimmed !== this.content) {156 this.split(this.start + trimmed.length).edit('', undefined, true);157 if (this.edited) {158 // save the change, if it has been edited159 this.edit(trimmed, this.storeName, true);160 }161 }162 return true;163 } else {164 this.edit('', undefined, true);165 166 this.intro = this.intro.replace(rx, '');167 if (this.intro.length) return true;168 }169 }170 171 trimStart(rx) {172 this.intro = this.intro.replace(rx, '');173 if (this.intro.length) return true;174 175 const trimmed = this.content.replace(rx, '');176 177 if (trimmed.length) {178 if (trimmed !== this.content) {179 const newChunk = this.split(this.end - trimmed.length);180 if (this.edited) {181 // save the change, if it has been edited182 newChunk.edit(trimmed, this.storeName, true);183 }184 this.edit('', undefined, true);185 }186 return true;187 } else {188 this.edit('', undefined, true);189 190 this.outro = this.outro.replace(rx, '');191 if (this.outro.length) return true;192 }193 }194}195 196function getBtoa() {197 if (typeof globalThis !== 'undefined' && typeof globalThis.btoa === 'function') {198 return (str) => globalThis.btoa(unescape(encodeURIComponent(str)));199 } else if (typeof Buffer === 'function') {200 return (str) => Buffer.from(str, 'utf-8').toString('base64');201 } else {202 return () => {203 throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.');204 };205 }206}207 208const btoa = /*#__PURE__*/ getBtoa();209 210class SourceMap {211 constructor(properties) {212 this.version = 3;213 this.file = properties.file;214 this.sources = properties.sources;215 this.sourcesContent = properties.sourcesContent;216 this.names = properties.names;217 this.mappings = encode(properties.mappings);218 if (typeof properties.x_google_ignoreList !== 'undefined') {219 this.x_google_ignoreList = properties.x_google_ignoreList;220 }221 if (typeof properties.debugId !== 'undefined') {222 this.debugId = properties.debugId;223 }224 }225 226 toString() {227 return JSON.stringify(this);228 }229 230 toUrl() {231 return 'data:application/json;charset=utf-8;base64,' + btoa(this.toString());232 }233}234 235function guessIndent(code) {236 const lines = code.split('\n');237 238 const tabbed = lines.filter((line) => /^\t+/.test(line));239 const spaced = lines.filter((line) => /^ {2,}/.test(line));240 241 if (tabbed.length === 0 && spaced.length === 0) {242 return null;243 }244 245 // More lines tabbed than spaced? Assume tabs, and246 // default to tabs in the case of a tie (or nothing247 // to go on)248 if (tabbed.length >= spaced.length) {249 return '\t';250 }251 252 // Otherwise, we need to guess the multiple253 const min = spaced.reduce((previous, current) => {254 const numSpaces = /^ +/.exec(current)[0].length;255 return Math.min(numSpaces, previous);256 }, Infinity);257 258 return new Array(min + 1).join(' ');259}260 261function getRelativePath(from, to) {262 const fromParts = from.split(/[/\\]/);263 const toParts = to.split(/[/\\]/);264 265 fromParts.pop(); // get dirname266 267 while (fromParts[0] === toParts[0]) {268 fromParts.shift();269 toParts.shift();270 }271 272 if (fromParts.length) {273 let i = fromParts.length;274 while (i--) fromParts[i] = '..';275 }276 277 return fromParts.concat(toParts).join('/');278}279 280const toString = Object.prototype.toString;281 282function isObject(thing) {283 return toString.call(thing) === '[object Object]';284}285 286function getLocator(source) {287 const originalLines = source.split('\n');288 const lineOffsets = [];289 290 for (let i = 0, pos = 0; i < originalLines.length; i++) {291 lineOffsets.push(pos);292 pos += originalLines[i].length + 1;293 }294 295 return function locate(index) {296 let i = 0;297 let j = lineOffsets.length;298 while (i < j) {299 const m = (i + j) >> 1;300 if (index < lineOffsets[m]) {301 j = m;302 } else {303 i = m + 1;304 }305 }306 const line = i - 1;307 const column = index - lineOffsets[line];308 return { line, column };309 };310}311 312const wordRegex = /\w/;313 314class Mappings {315 constructor(hires) {316 this.hires = hires;317 this.generatedCodeLine = 0;318 this.generatedCodeColumn = 0;319 this.raw = [];320 this.rawSegments = this.raw[this.generatedCodeLine] = [];321 this.pending = null;322 }323 324 addEdit(sourceIndex, content, loc, nameIndex) {325 if (content.length) {326 const contentLengthMinusOne = content.length - 1;327 let contentLineEnd = content.indexOf('\n', 0);328 let previousContentLineEnd = -1;329 // Loop through each line in the content and add a segment, but stop if the last line is empty,330 // else code afterwards would fill one line too many331 while (contentLineEnd >= 0 && contentLengthMinusOne > contentLineEnd) {332 const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];333 if (nameIndex >= 0) {334 segment.push(nameIndex);335 }336 this.rawSegments.push(segment);337 338 this.generatedCodeLine += 1;339 this.raw[this.generatedCodeLine] = this.rawSegments = [];340 this.generatedCodeColumn = 0;341 342 previousContentLineEnd = contentLineEnd;343 contentLineEnd = content.indexOf('\n', contentLineEnd + 1);344 }345 346 const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];347 if (nameIndex >= 0) {348 segment.push(nameIndex);349 }350 this.rawSegments.push(segment);351 352 this.advance(content.slice(previousContentLineEnd + 1));353 } else if (this.pending) {354 this.rawSegments.push(this.pending);355 this.advance(content);356 }357 358 this.pending = null;359 }360 361 addUneditedChunk(sourceIndex, chunk, original, loc, sourcemapLocations) {362 let originalCharIndex = chunk.start;363 let first = true;364 // when iterating each char, check if it's in a word boundary365 let charInHiresBoundary = false;366 367 while (originalCharIndex < chunk.end) {368 if (original[originalCharIndex] === '\n') {369 loc.line += 1;370 loc.column = 0;371 this.generatedCodeLine += 1;372 this.raw[this.generatedCodeLine] = this.rawSegments = [];373 this.generatedCodeColumn = 0;374 first = true;375 charInHiresBoundary = false;376 } else {377 if (this.hires || first || sourcemapLocations.has(originalCharIndex)) {378 const segment = [this.generatedCodeColumn, sourceIndex, loc.line, loc.column];379 380 if (this.hires === 'boundary') {381 // in hires "boundary", group segments per word boundary than per char382 if (wordRegex.test(original[originalCharIndex])) {383 // for first char in the boundary found, start the boundary by pushing a segment384 if (!charInHiresBoundary) {385 this.rawSegments.push(segment);386 charInHiresBoundary = true;387 }388 } else {389 // for non-word char, end the boundary by pushing a segment390 this.rawSegments.push(segment);391 charInHiresBoundary = false;392 }393 } else {394 this.rawSegments.push(segment);395 }396 }397 398 loc.column += 1;399 this.generatedCodeColumn += 1;400 first = false;401 }402 403 originalCharIndex += 1;404 }405 406 this.pending = null;407 }408 409 advance(str) {410 if (!str) return;411 412 const lines = str.split('\n');413 414 if (lines.length > 1) {415 for (let i = 0; i < lines.length - 1; i++) {416 this.generatedCodeLine++;417 this.raw[this.generatedCodeLine] = this.rawSegments = [];418 }419 this.generatedCodeColumn = 0;420 }421 422 this.generatedCodeColumn += lines[lines.length - 1].length;423 }424}425 426const n = '\n';427 428const warned = {429 insertLeft: false,430 insertRight: false,431 storeName: false,432};433 434class MagicString {435 constructor(string, options = {}) {436 const chunk = new Chunk(0, string.length, string);437 438 Object.defineProperties(this, {439 original: { writable: true, value: string },440 outro: { writable: true, value: '' },441 intro: { writable: true, value: '' },442 firstChunk: { writable: true, value: chunk },443 lastChunk: { writable: true, value: chunk },444 lastSearchedChunk: { writable: true, value: chunk },445 byStart: { writable: true, value: {} },446 byEnd: { writable: true, value: {} },447 filename: { writable: true, value: options.filename },448 indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },449 sourcemapLocations: { writable: true, value: new BitSet() },450 storedNames: { writable: true, value: {} },451 indentStr: { writable: true, value: undefined },452 ignoreList: { writable: true, value: options.ignoreList },453 offset: { writable: true, value: options.offset || 0 },454 });455 456 this.byStart[0] = chunk;457 this.byEnd[string.length] = chunk;458 }459 460 addSourcemapLocation(char) {461 this.sourcemapLocations.add(char);462 }463 464 append(content) {465 if (typeof content !== 'string') throw new TypeError('outro content must be a string');466 467 this.outro += content;468 return this;469 }470 471 appendLeft(index, content) {472 index = index + this.offset;473 474 if (typeof content !== 'string') throw new TypeError('inserted content must be a string');475 476 this._split(index);477 478 const chunk = this.byEnd[index];479 480 if (chunk) {481 chunk.appendLeft(content);482 } else {483 this.intro += content;484 }485 return this;486 }487 488 appendRight(index, content) {489 index = index + this.offset;490 491 if (typeof content !== 'string') throw new TypeError('inserted content must be a string');492 493 this._split(index);494 495 const chunk = this.byStart[index];496 497 if (chunk) {498 chunk.appendRight(content);499 } else {500 this.outro += content;501 }502 return this;503 }504 505 clone() {506 const cloned = new MagicString(this.original, { filename: this.filename, offset: this.offset });507 508 let originalChunk = this.firstChunk;509 let clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());510 511 while (originalChunk) {512 cloned.byStart[clonedChunk.start] = clonedChunk;513 cloned.byEnd[clonedChunk.end] = clonedChunk;514 515 const nextOriginalChunk = originalChunk.next;516 const nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();517 518 if (nextClonedChunk) {519 clonedChunk.next = nextClonedChunk;520 nextClonedChunk.previous = clonedChunk;521 522 clonedChunk = nextClonedChunk;523 }524 525 originalChunk = nextOriginalChunk;526 }527 528 cloned.lastChunk = clonedChunk;529 530 if (this.indentExclusionRanges) {531 cloned.indentExclusionRanges = this.indentExclusionRanges.slice();532 }533 534 cloned.sourcemapLocations = new BitSet(this.sourcemapLocations);535 536 cloned.intro = this.intro;537 cloned.outro = this.outro;538 539 return cloned;540 }541 542 generateDecodedMap(options) {543 options = options || {};544 545 const sourceIndex = 0;546 const names = Object.keys(this.storedNames);547 const mappings = new Mappings(options.hires);548 549 const locate = getLocator(this.original);550 551 if (this.intro) {552 mappings.advance(this.intro);553 }554 555 this.firstChunk.eachNext((chunk) => {556 const loc = locate(chunk.start);557 558 if (chunk.intro.length) mappings.advance(chunk.intro);559 560 if (chunk.edited) {561 mappings.addEdit(562 sourceIndex,563 chunk.content,564 loc,565 chunk.storeName ? names.indexOf(chunk.original) : -1,566 );567 } else {568 mappings.addUneditedChunk(sourceIndex, chunk, this.original, loc, this.sourcemapLocations);569 }570 571 if (chunk.outro.length) mappings.advance(chunk.outro);572 });573 574 if (this.outro) {575 mappings.advance(this.outro);576 }577 578 return {579 file: options.file ? options.file.split(/[/\\]/).pop() : undefined,580 sources: [581 options.source ? getRelativePath(options.file || '', options.source) : options.file || '',582 ],583 sourcesContent: options.includeContent ? [this.original] : undefined,584 names,585 mappings: mappings.raw,586 x_google_ignoreList: this.ignoreList ? [sourceIndex] : undefined,587 };588 }589 590 generateMap(options) {591 return new SourceMap(this.generateDecodedMap(options));592 }593 594 _ensureindentStr() {595 if (this.indentStr === undefined) {596 this.indentStr = guessIndent(this.original);597 }598 }599 600 _getRawIndentString() {601 this._ensureindentStr();602 return this.indentStr;603 }604 605 getIndentString() {606 this._ensureindentStr();607 return this.indentStr === null ? '\t' : this.indentStr;608 }609 610 indent(indentStr, options) {611 const pattern = /^[^\r\n]/gm;612 613 if (isObject(indentStr)) {614 options = indentStr;615 indentStr = undefined;616 }617 618 if (indentStr === undefined) {619 this._ensureindentStr();620 indentStr = this.indentStr || '\t';621 }622 623 if (indentStr === '') return this; // noop624 625 options = options || {};626 627 // Process exclusion ranges628 const isExcluded = {};629 630 if (options.exclude) {631 const exclusions =632 typeof options.exclude[0] === 'number' ? [options.exclude] : options.exclude;633 exclusions.forEach((exclusion) => {634 for (let i = exclusion[0]; i < exclusion[1]; i += 1) {635 isExcluded[i] = true;636 }637 });638 }639 640 let shouldIndentNextCharacter = options.indentStart !== false;641 const replacer = (match) => {642 if (shouldIndentNextCharacter) return `${indentStr}${match}`;643 shouldIndentNextCharacter = true;644 return match;645 };646 647 this.intro = this.intro.replace(pattern, replacer);648 649 let charIndex = 0;650 let chunk = this.firstChunk;651 652 while (chunk) {653 const end = chunk.end;654 655 if (chunk.edited) {656 if (!isExcluded[charIndex]) {657 chunk.content = chunk.content.replace(pattern, replacer);658 659 if (chunk.content.length) {660 shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === '\n';661 }662 }663 } else {664 charIndex = chunk.start;665 666 while (charIndex < end) {667 if (!isExcluded[charIndex]) {668 const char = this.original[charIndex];669 670 if (char === '\n') {671 shouldIndentNextCharacter = true;672 } else if (char !== '\r' && shouldIndentNextCharacter) {673 shouldIndentNextCharacter = false;674 675 if (charIndex === chunk.start) {676 chunk.prependRight(indentStr);677 } else {678 this._splitChunk(chunk, charIndex);679 chunk = chunk.next;680 chunk.prependRight(indentStr);681 }682 }683 }684 685 charIndex += 1;686 }687 }688 689 charIndex = chunk.end;690 chunk = chunk.next;691 }692 693 this.outro = this.outro.replace(pattern, replacer);694 695 return this;696 }697 698 insert() {699 throw new Error(700 'magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)',701 );702 }703 704 insertLeft(index, content) {705 if (!warned.insertLeft) {706 console.warn(707 'magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead',708 );709 warned.insertLeft = true;710 }711 712 return this.appendLeft(index, content);713 }714 715 insertRight(index, content) {716 if (!warned.insertRight) {717 console.warn(718 'magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead',719 );720 warned.insertRight = true;721 }722 723 return this.prependRight(index, content);724 }725 726 move(start, end, index) {727 start = start + this.offset;728 end = end + this.offset;729 index = index + this.offset;730 731 if (index >= start && index <= end) throw new Error('Cannot move a selection inside itself');732 733 this._split(start);734 this._split(end);735 this._split(index);736 737 const first = this.byStart[start];738 const last = this.byEnd[end];739 740 const oldLeft = first.previous;741 const oldRight = last.next;742 743 const newRight = this.byStart[index];744 if (!newRight && last === this.lastChunk) return this;745 const newLeft = newRight ? newRight.previous : this.lastChunk;746 747 if (oldLeft) oldLeft.next = oldRight;748 if (oldRight) oldRight.previous = oldLeft;749 750 if (newLeft) newLeft.next = first;751 if (newRight) newRight.previous = last;752 753 if (!first.previous) this.firstChunk = last.next;754 if (!last.next) {755 this.lastChunk = first.previous;756 this.lastChunk.next = null;757 }758 759 first.previous = newLeft;760 last.next = newRight || null;761 762 if (!newLeft) this.firstChunk = first;763 if (!newRight) this.lastChunk = last;764 return this;765 }766 767 overwrite(start, end, content, options) {768 options = options || {};769 return this.update(start, end, content, { ...options, overwrite: !options.contentOnly });770 }771 772 update(start, end, content, options) {773 start = start + this.offset;774 end = end + this.offset;775 776 if (typeof content !== 'string') throw new TypeError('replacement content must be a string');777 778 if (this.original.length !== 0) {779 while (start < 0) start += this.original.length;780 while (end < 0) end += this.original.length;781 }782 783 if (end > this.original.length) throw new Error('end is out of bounds');784 if (start === end)785 throw new Error(786 'Cannot overwrite a zero-length range – use appendLeft or prependRight instead',787 );788 789 this._split(start);790 this._split(end);791 792 if (options === true) {793 if (!warned.storeName) {794 console.warn(795 'The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string',796 );797 warned.storeName = true;798 }799 800 options = { storeName: true };801 }802 const storeName = options !== undefined ? options.storeName : false;803 const overwrite = options !== undefined ? options.overwrite : false;804 805 if (storeName) {806 const original = this.original.slice(start, end);807 Object.defineProperty(this.storedNames, original, {808 writable: true,809 value: true,810 enumerable: true,811 });812 }813 814 const first = this.byStart[start];815 const last = this.byEnd[end];816 817 if (first) {818 let chunk = first;819 while (chunk !== last) {820 if (chunk.next !== this.byStart[chunk.end]) {821 throw new Error('Cannot overwrite across a split point');822 }823 chunk = chunk.next;824 chunk.edit('', false);825 }826 827 first.edit(content, storeName, !overwrite);828 } else {829 // must be inserting at the end830 const newChunk = new Chunk(start, end, '').edit(content, storeName);831 832 // TODO last chunk in the array may not be the last chunk, if it's moved...833 last.next = newChunk;834 newChunk.previous = last;835 }836 return this;837 }838 839 prepend(content) {840 if (typeof content !== 'string') throw new TypeError('outro content must be a string');841 842 this.intro = content + this.intro;843 return this;844 }845 846 prependLeft(index, content) {847 index = index + this.offset;848 849 if (typeof content !== 'string') throw new TypeError('inserted content must be a string');850 851 this._split(index);852 853 const chunk = this.byEnd[index];854 855 if (chunk) {856 chunk.prependLeft(content);857 } else {858 this.intro = content + this.intro;859 }860 return this;861 }862 863 prependRight(index, content) {864 index = index + this.offset;865 866 if (typeof content !== 'string') throw new TypeError('inserted content must be a string');867 868 this._split(index);869 870 const chunk = this.byStart[index];871 872 if (chunk) {873 chunk.prependRight(content);874 } else {875 this.outro = content + this.outro;876 }877 return this;878 }879 880 remove(start, end) {881 start = start + this.offset;882 end = end + this.offset;883 884 if (this.original.length !== 0) {885 while (start < 0) start += this.original.length;886 while (end < 0) end += this.original.length;887 }888 889 if (start === end) return this;890 891 if (start < 0 || end > this.original.length) throw new Error('Character is out of bounds');892 if (start > end) throw new Error('end must be greater than start');893 894 this._split(start);895 this._split(end);896 897 let chunk = this.byStart[start];898 899 while (chunk) {900 chunk.intro = '';901 chunk.outro = '';902 chunk.edit('');903 904 chunk = end > chunk.end ? this.byStart[chunk.end] : null;905 }906 return this;907 }908 909 reset(start, end) {910 start = start + this.offset;911 end = end + this.offset;912 913 if (this.original.length !== 0) {914 while (start < 0) start += this.original.length;915 while (end < 0) end += this.original.length;916 }917 918 if (start === end) return this;919 920 if (start < 0 || end > this.original.length) throw new Error('Character is out of bounds');921 if (start > end) throw new Error('end must be greater than start');922 923 this._split(start);924 this._split(end);925 926 let chunk = this.byStart[start];927 928 while (chunk) {929 chunk.reset();930 931 chunk = end > chunk.end ? this.byStart[chunk.end] : null;932 }933 return this;934 }935 936 lastChar() {937 if (this.outro.length) return this.outro[this.outro.length - 1];938 let chunk = this.lastChunk;939 do {940 if (chunk.outro.length) return chunk.outro[chunk.outro.length - 1];941 if (chunk.content.length) return chunk.content[chunk.content.length - 1];942 if (chunk.intro.length) return chunk.intro[chunk.intro.length - 1];943 } while ((chunk = chunk.previous));944 if (this.intro.length) return this.intro[this.intro.length - 1];945 return '';946 }947 948 lastLine() {949 let lineIndex = this.outro.lastIndexOf(n);950 if (lineIndex !== -1) return this.outro.substr(lineIndex + 1);951 let lineStr = this.outro;952 let chunk = this.lastChunk;953 do {954 if (chunk.outro.length > 0) {955 lineIndex = chunk.outro.lastIndexOf(n);956 if (lineIndex !== -1) return chunk.outro.substr(lineIndex + 1) + lineStr;957 lineStr = chunk.outro + lineStr;958 }959 960 if (chunk.content.length > 0) {961 lineIndex = chunk.content.lastIndexOf(n);962 if (lineIndex !== -1) return chunk.content.substr(lineIndex + 1) + lineStr;963 lineStr = chunk.content + lineStr;964 }965 966 if (chunk.intro.length > 0) {967 lineIndex = chunk.intro.lastIndexOf(n);968 if (lineIndex !== -1) return chunk.intro.substr(lineIndex + 1) + lineStr;969 lineStr = chunk.intro + lineStr;970 }971 } while ((chunk = chunk.previous));972 lineIndex = this.intro.lastIndexOf(n);973 if (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr;974 return this.intro + lineStr;975 }976 977 slice(start = 0, end = this.original.length - this.offset) {978 start = start + this.offset;979 end = end + this.offset;980 981 if (this.original.length !== 0) {982 while (start < 0) start += this.original.length;983 while (end < 0) end += this.original.length;984 }985 986 let result = '';987 988 // find start chunk989 let chunk = this.firstChunk;990 while (chunk && (chunk.start > start || chunk.end <= start)) {991 // found end chunk before start992 if (chunk.start < end && chunk.end >= end) {993 return result;994 }995 996 chunk = chunk.next;997 }998 999 if (chunk && chunk.edited && chunk.start !== start)1000 throw new Error(`Cannot use replaced character ${start} as slice start anchor.`);1001 1002 const startChunk = chunk;1003 while (chunk) {1004 if (chunk.intro && (startChunk !== chunk || chunk.start === start)) {1005 result += chunk.intro;1006 }1007 1008 const containsEnd = chunk.start < end && chunk.end >= end;1009 if (containsEnd && chunk.edited && chunk.end !== end)1010 throw new Error(`Cannot use replaced character ${end} as slice end anchor.`);1011 1012 const sliceStart = startChunk === chunk ? start - chunk.start : 0;1013 const sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;1014 1015 result += chunk.content.slice(sliceStart, sliceEnd);1016 1017 if (chunk.outro && (!containsEnd || chunk.end === end)) {1018 result += chunk.outro;1019 }1020 1021 if (containsEnd) {1022 break;1023 }1024 1025 chunk = chunk.next;1026 }1027 1028 return result;1029 }1030 1031 // TODO deprecate this? not really very useful1032 snip(start, end) {1033 const clone = this.clone();1034 clone.remove(0, start);1035 clone.remove(end, clone.original.length);1036 1037 return clone;1038 }1039 1040 _split(index) {1041 if (this.byStart[index] || this.byEnd[index]) return;1042 1043 let chunk = this.lastSearchedChunk;1044 let previousChunk = chunk;1045 const searchForward = index > chunk.end;1046 1047 while (chunk) {1048 if (chunk.contains(index)) return this._splitChunk(chunk, index);1049 1050 chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];1051 1052 // Prevent infinite loop (e.g. via empty chunks, where start === end)1053 if (chunk === previousChunk) return;1054 1055 previousChunk = chunk;1056 }1057 }1058 1059 _splitChunk(chunk, index) {1060 if (chunk.edited && chunk.content.length) {1061 // zero-length edited chunks are a special case (overlapping replacements)1062 const loc = getLocator(this.original)(index);1063 throw new Error(1064 `Cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`,1065 );1066 }1067 1068 const newChunk = chunk.split(index);1069 1070 this.byEnd[index] = chunk;1071 this.byStart[index] = newChunk;1072 this.byEnd[newChunk.end] = newChunk;1073 1074 if (chunk === this.lastChunk) this.lastChunk = newChunk;1075 1076 this.lastSearchedChunk = chunk;1077 return true;1078 }1079 1080 toString() {1081 let str = this.intro;1082 1083 let chunk = this.firstChunk;1084 while (chunk) {1085 str += chunk.toString();1086 chunk = chunk.next;1087 }1088 1089 return str + this.outro;1090 }1091 1092 isEmpty() {1093 let chunk = this.firstChunk;1094 do {1095 if (1096 (chunk.intro.length && chunk.intro.trim()) ||1097 (chunk.content.length && chunk.content.trim()) ||1098 (chunk.outro.length && chunk.outro.trim())1099 )1100 return false;1101 } while ((chunk = chunk.next));1102 return true;1103 }1104 1105 length() {1106 let chunk = this.firstChunk;1107 let length = 0;1108 do {1109 length += chunk.intro.length + chunk.content.length + chunk.outro.length;1110 } while ((chunk = chunk.next));1111 return length;1112 }1113 1114 trimLines() {1115 return this.trim('[\\r\\n]');1116 }1117 1118 trim(charType) {1119 return this.trimStart(charType).trimEnd(charType);1120 }1121 1122 trimEndAborted(charType) {1123 const rx = new RegExp((charType || '\\s') + '+$');1124 1125 this.outro = this.outro.replace(rx, '');1126 if (this.outro.length) return true;1127 1128 let chunk = this.lastChunk;1129 1130 do {1131 const end = chunk.end;1132 const aborted = chunk.trimEnd(rx);1133 1134 // if chunk was trimmed, we have a new lastChunk1135 if (chunk.end !== end) {1136 if (this.lastChunk === chunk) {1137 this.lastChunk = chunk.next;1138 }1139 1140 this.byEnd[chunk.end] = chunk;1141 this.byStart[chunk.next.start] = chunk.next;1142 this.byEnd[chunk.next.end] = chunk.next;1143 }1144 1145 if (aborted) return true;1146 chunk = chunk.previous;1147 } while (chunk);1148 1149 return false;1150 }1151 1152 trimEnd(charType) {1153 this.trimEndAborted(charType);1154 return this;1155 }1156 trimStartAborted(charType) {1157 const rx = new RegExp('^' + (charType || '\\s') + '+');1158 1159 this.intro = this.intro.replace(rx, '');1160 if (this.intro.length) return true;1161 1162 let chunk = this.firstChunk;1163 1164 do {1165 const end = chunk.end;1166 const aborted = chunk.trimStart(rx);1167 1168 if (chunk.end !== end) {1169 // special case...1170 if (chunk === this.lastChunk) this.lastChunk = chunk.next;1171 1172 this.byEnd[chunk.end] = chunk;1173 this.byStart[chunk.next.start] = chunk.next;1174 this.byEnd[chunk.next.end] = chunk.next;1175 }1176 1177 if (aborted) return true;1178 chunk = chunk.next;1179 } while (chunk);1180 1181 return false;1182 }1183 1184 trimStart(charType) {1185 this.trimStartAborted(charType);1186 return this;1187 }1188 1189 hasChanged() {1190 return this.original !== this.toString();1191 }1192 1193 _replaceRegexp(searchValue, replacement) {1194 function getReplacement(match, str) {1195 if (typeof replacement === 'string') {1196 return replacement.replace(/\$(\$|&|\d+)/g, (_, i) => {1197 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_a_parameter1198 if (i === '$') return '$';1199 if (i === '&') return match[0];1200 const num = +i;