2017-09-13 07:52:34 +02:00

145 lines
2.8 KiB
JavaScript
Vendored

export default function Chunk ( start, end, content ) {
this.start = start;
this.end = end;
this.original = content;
this.intro = '';
this.outro = '';
this.content = content;
this.storeName = false;
this.edited = false;
// we make these non-enumerable, for sanity while debugging
Object.defineProperties( this, {
previous: { writable: true, value: null },
next: { writable: true, value: null }
});
}
Chunk.prototype = {
append ( content ) {
this.outro += content;
},
clone () {
const chunk = new Chunk( this.start, this.end, this.original );
chunk.intro = this.intro;
chunk.outro = this.outro;
chunk.content = this.content;
chunk.storeName = this.storeName;
chunk.edited = this.edited;
return chunk;
},
contains ( index ) {
return this.start < index && index < this.end;
},
eachNext ( fn ) {
let chunk = this;
while ( chunk ) {
fn( chunk );
chunk = chunk.next;
}
},
eachPrevious ( fn ) {
let chunk = this;
while ( chunk ) {
fn( chunk );
chunk = chunk.previous;
}
},
edit ( content, storeName ) {
this.content = content;
this.storeName = storeName;
this.edited = true;
return this;
},
prepend ( content ) {
this.intro = content + this.intro;
},
split ( index ) {
const sliceIndex = index - this.start;
const originalBefore = this.original.slice( 0, sliceIndex );
const originalAfter = this.original.slice( sliceIndex );
this.original = originalBefore;
const newChunk = new Chunk( index, this.end, originalAfter );
newChunk.outro = this.outro;
this.outro = '';
this.end = index;
if ( this.edited ) {
// TODO is this block necessary?...
newChunk.edit( '', false );
this.content = '';
} else {
this.content = originalBefore;
}
newChunk.next = this.next;
if ( newChunk.next ) newChunk.next.previous = newChunk;
newChunk.previous = this;
this.next = newChunk;
return newChunk;
},
toString () {
return this.intro + this.content + this.outro;
},
trimEnd ( rx ) {
this.outro = this.outro.replace( rx, '' );
if ( this.outro.length ) return true;
const trimmed = this.content.replace( rx, '' );
if ( trimmed.length ) {
if ( trimmed !== this.content ) {
this.split( this.start + trimmed.length ).edit( '', false );
}
return true;
} else {
this.edit( '', false );
this.intro = this.intro.replace( rx, '' );
if ( this.intro.length ) return true;
}
},
trimStart ( rx ) {
this.intro = this.intro.replace( rx, '' );
if ( this.intro.length ) return true;
const trimmed = this.content.replace( rx, '' );
if ( trimmed.length ) {
if ( trimmed !== this.content ) {
this.split( this.end - trimmed.length );
this.edit( '', false );
}
return true;
} else {
this.edit( '', false );
this.outro = this.outro.replace( rx, '' );
if ( this.outro.length ) return true;
}
}
};