diff --git a/src/MagicString.js b/src/MagicString.js index e73353a..eb7d1f0 100644 --- a/src/MagicString.js +++ b/src/MagicString.js @@ -7,6 +7,8 @@ import getLocator from './utils/getLocator.js'; import Mappings from './utils/Mappings.js'; import Stats from './utils/Stats.js'; +const n = '\n'; + const warned = { insertLeft: false, insertRight: false, @@ -460,6 +462,8 @@ export default class MagicString { } lastChar() { + if (this.outro.length) + return this.outro[this.outro.length - 1]; let chunk = this.lastChunk; do { if (chunk.outro.length) @@ -469,9 +473,45 @@ export default class MagicString { if (chunk.intro.length) return chunk.intro[chunk.intro.length - 1]; } while (chunk = chunk.previous); + if (this.intro.length) + return this.intro[this.intro.length - 1]; return ''; } + lastLine() { + let lineIndex = this.outro.lastIndexOf(n); + if (lineIndex !== -1) + return this.outro.substr(lineIndex + 1); + let lineStr = this.outro; + let chunk = this.lastChunk; + do { + if (chunk.outro.length > 0) { + lineIndex = chunk.outro.lastIndexOf(n); + if (lineIndex !== -1) + return chunk.outro.substr(lineIndex + 1) + lineStr; + lineStr = chunk.outro + lineStr; + } + + if (chunk.content.length > 0) { + lineIndex = chunk.content.lastIndexOf(n); + if (lineIndex !== -1) + return chunk.content.substr(lineIndex + 1) + lineStr; + lineStr = chunk.content + lineStr; + } + + if (chunk.intro.length > 0) { + lineIndex = chunk.intro.lastIndexOf(n); + if (lineIndex !== -1) + return chunk.intro.substr(lineIndex + 1) + lineStr; + lineStr = chunk.intro + lineStr; + } + } while (chunk = chunk.previous); + lineIndex = this.intro.lastIndexOf(n); + if (lineIndex !== -1) + return this.intro.substr(lineIndex + 1) + lineStr; + return this.intro + lineStr; + } + slice(start = 0, end = this.original.length) { while (start < 0) start += this.original.length; while (end < 0) end += this.original.length; @@ -581,6 +621,19 @@ export default class MagicString { return str + this.outro; } + length() { + let len = this.intro.length; + + let chunk = this.firstChunk; + while (chunk) { + len += chunk.intro.length + chunk.content.length + chunk.outro.length; + chunk = chunk.next; + } + + len += this.outro.length; + return len; + } + isEmpty() { let chunk = this.firstChunk; do { diff --git a/test/MagicString.js b/test/MagicString.js index 5726f8e..80421b7 100644 --- a/test/MagicString.js +++ b/test/MagicString.js @@ -1191,4 +1191,27 @@ describe( 'MagicString', () => { assert.equal( s.isEmpty(), true ); }); }); + + describe( 'lastLine', () => { + it( 'should support lastLine', () => { + const s = new MagicString( ' abcde\nfghijkl ' ); + + assert.equal( s.lastLine(), 'fghijkl ' ); + + s.prepend( ' ' ); + s.append( ' ' ); + s.remove( 1, 6 ); + s.remove( 9, 15 ); + + assert.equal( s.lastLine(), 'fg ' ); + + s.overwrite( 7, 8, '\n' ); + + assert.equal( s.lastLine(), 'g ' ); + + s.append('\n//lastline'); + + assert.equal( s.lastLine(), '//lastline' ); + }); + }); });