magic-string.cjs.js 32KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301
  1. 'use strict';
  2. var vlq = require('vlq');
  3. function Chunk ( start, end, content ) {
  4. this.start = start;
  5. this.end = end;
  6. this.original = content;
  7. this.intro = '';
  8. this.outro = '';
  9. this.content = content;
  10. this.storeName = false;
  11. this.edited = false;
  12. // we make these non-enumerable, for sanity while debugging
  13. Object.defineProperties( this, {
  14. previous: { writable: true, value: null },
  15. next: { writable: true, value: null }
  16. });
  17. }
  18. Chunk.prototype = {
  19. appendLeft: function appendLeft ( content ) {
  20. this.outro += content;
  21. },
  22. appendRight: function appendRight ( content ) {
  23. this.intro = this.intro + content;
  24. },
  25. clone: function clone () {
  26. var chunk = new Chunk( this.start, this.end, this.original );
  27. chunk.intro = this.intro;
  28. chunk.outro = this.outro;
  29. chunk.content = this.content;
  30. chunk.storeName = this.storeName;
  31. chunk.edited = this.edited;
  32. return chunk;
  33. },
  34. contains: function contains ( index ) {
  35. return this.start < index && index < this.end;
  36. },
  37. eachNext: function eachNext ( fn ) {
  38. var chunk = this;
  39. while ( chunk ) {
  40. fn( chunk );
  41. chunk = chunk.next;
  42. }
  43. },
  44. eachPrevious: function eachPrevious ( fn ) {
  45. var chunk = this;
  46. while ( chunk ) {
  47. fn( chunk );
  48. chunk = chunk.previous;
  49. }
  50. },
  51. edit: function edit ( content, storeName, contentOnly ) {
  52. this.content = content;
  53. if ( !contentOnly ) {
  54. this.intro = '';
  55. this.outro = '';
  56. }
  57. this.storeName = storeName;
  58. this.edited = true;
  59. return this;
  60. },
  61. prependLeft: function prependLeft ( content ) {
  62. this.outro = content + this.outro;
  63. },
  64. prependRight: function prependRight ( content ) {
  65. this.intro = content + this.intro;
  66. },
  67. split: function split ( index ) {
  68. var sliceIndex = index - this.start;
  69. var originalBefore = this.original.slice( 0, sliceIndex );
  70. var originalAfter = this.original.slice( sliceIndex );
  71. this.original = originalBefore;
  72. var newChunk = new Chunk( index, this.end, originalAfter );
  73. newChunk.outro = this.outro;
  74. this.outro = '';
  75. this.end = index;
  76. if ( this.edited ) {
  77. // TODO is this block necessary?...
  78. newChunk.edit( '', false );
  79. this.content = '';
  80. } else {
  81. this.content = originalBefore;
  82. }
  83. newChunk.next = this.next;
  84. if ( newChunk.next ) { newChunk.next.previous = newChunk; }
  85. newChunk.previous = this;
  86. this.next = newChunk;
  87. return newChunk;
  88. },
  89. toString: function toString () {
  90. return this.intro + this.content + this.outro;
  91. },
  92. trimEnd: function trimEnd ( rx ) {
  93. this.outro = this.outro.replace( rx, '' );
  94. if ( this.outro.length ) { return true; }
  95. var trimmed = this.content.replace( rx, '' );
  96. if ( trimmed.length ) {
  97. if ( trimmed !== this.content ) {
  98. this.split( this.start + trimmed.length ).edit( '', false );
  99. }
  100. return true;
  101. } else {
  102. this.edit( '', false );
  103. this.intro = this.intro.replace( rx, '' );
  104. if ( this.intro.length ) { return true; }
  105. }
  106. },
  107. trimStart: function trimStart ( rx ) {
  108. this.intro = this.intro.replace( rx, '' );
  109. if ( this.intro.length ) { return true; }
  110. var trimmed = this.content.replace( rx, '' );
  111. if ( trimmed.length ) {
  112. if ( trimmed !== this.content ) {
  113. this.split( this.end - trimmed.length );
  114. this.edit( '', false );
  115. }
  116. return true;
  117. } else {
  118. this.edit( '', false );
  119. this.outro = this.outro.replace( rx, '' );
  120. if ( this.outro.length ) { return true; }
  121. }
  122. }
  123. };
  124. var _btoa;
  125. if ( typeof window !== 'undefined' && typeof window.btoa === 'function' ) {
  126. _btoa = window.btoa;
  127. } else if ( typeof Buffer === 'function' ) {
  128. _btoa = function (str) { return new Buffer( str ).toString( 'base64' ); };
  129. } else {
  130. _btoa = function () {
  131. throw new Error( 'Unsupported environment: `window.btoa` or `Buffer` should be supported.' );
  132. };
  133. }
  134. var btoa = _btoa;
  135. function SourceMap ( properties ) {
  136. this.version = 3;
  137. this.file = properties.file;
  138. this.sources = properties.sources;
  139. this.sourcesContent = properties.sourcesContent;
  140. this.names = properties.names;
  141. this.mappings = properties.mappings;
  142. }
  143. SourceMap.prototype = {
  144. toString: function toString () {
  145. return JSON.stringify( this );
  146. },
  147. toUrl: function toUrl () {
  148. return 'data:application/json;charset=utf-8;base64,' + btoa( this.toString() );
  149. }
  150. };
  151. function guessIndent ( code ) {
  152. var lines = code.split( '\n' );
  153. var tabbed = lines.filter( function (line) { return /^\t+/.test( line ); } );
  154. var spaced = lines.filter( function (line) { return /^ {2,}/.test( line ); } );
  155. if ( tabbed.length === 0 && spaced.length === 0 ) {
  156. return null;
  157. }
  158. // More lines tabbed than spaced? Assume tabs, and
  159. // default to tabs in the case of a tie (or nothing
  160. // to go on)
  161. if ( tabbed.length >= spaced.length ) {
  162. return '\t';
  163. }
  164. // Otherwise, we need to guess the multiple
  165. var min = spaced.reduce( function ( previous, current ) {
  166. var numSpaces = /^ +/.exec( current )[0].length;
  167. return Math.min( numSpaces, previous );
  168. }, Infinity );
  169. return new Array( min + 1 ).join( ' ' );
  170. }
  171. function getRelativePath ( from, to ) {
  172. var fromParts = from.split( /[\/\\]/ );
  173. var toParts = to.split( /[\/\\]/ );
  174. fromParts.pop(); // get dirname
  175. while ( fromParts[0] === toParts[0] ) {
  176. fromParts.shift();
  177. toParts.shift();
  178. }
  179. if ( fromParts.length ) {
  180. var i = fromParts.length;
  181. while ( i-- ) { fromParts[i] = '..'; }
  182. }
  183. return fromParts.concat( toParts ).join( '/' );
  184. }
  185. var toString = Object.prototype.toString;
  186. function isObject ( thing ) {
  187. return toString.call( thing ) === '[object Object]';
  188. }
  189. function getLocator ( source ) {
  190. var originalLines = source.split( '\n' );
  191. var start = 0;
  192. var lineRanges = originalLines.map( function ( line, i ) {
  193. var end = start + line.length + 1;
  194. var range = { start: start, end: end, line: i };
  195. start = end;
  196. return range;
  197. });
  198. var i = 0;
  199. function rangeContains ( range, index ) {
  200. return range.start <= index && index < range.end;
  201. }
  202. function getLocation ( range, index ) {
  203. return { line: range.line, column: index - range.start };
  204. }
  205. return function locate ( index ) {
  206. var range = lineRanges[i];
  207. var d = index >= range.end ? 1 : -1;
  208. while ( range ) {
  209. if ( rangeContains( range, index ) ) { return getLocation( range, index ); }
  210. i += d;
  211. range = lineRanges[i];
  212. }
  213. };
  214. }
  215. function Mappings ( hires ) {
  216. var this$1 = this;
  217. var offsets = {
  218. generatedCodeColumn: 0,
  219. sourceIndex: 0,
  220. sourceCodeLine: 0,
  221. sourceCodeColumn: 0,
  222. sourceCodeName: 0
  223. };
  224. var generatedCodeLine = 0;
  225. var generatedCodeColumn = 0;
  226. this.raw = [];
  227. var rawSegments = this.raw[ generatedCodeLine ] = [];
  228. var pending = null;
  229. this.addEdit = function ( sourceIndex, content, original, loc, nameIndex ) {
  230. if ( content.length ) {
  231. rawSegments.push([
  232. generatedCodeColumn,
  233. sourceIndex,
  234. loc.line,
  235. loc.column,
  236. nameIndex ]);
  237. } else if ( pending ) {
  238. rawSegments.push( pending );
  239. }
  240. this$1.advance( content );
  241. pending = null;
  242. };
  243. this.addUneditedChunk = function ( sourceIndex, chunk, original, loc, sourcemapLocations ) {
  244. var originalCharIndex = chunk.start;
  245. var first = true;
  246. while ( originalCharIndex < chunk.end ) {
  247. if ( hires || first || sourcemapLocations[ originalCharIndex ] ) {
  248. rawSegments.push([
  249. generatedCodeColumn,
  250. sourceIndex,
  251. loc.line,
  252. loc.column,
  253. -1
  254. ]);
  255. }
  256. if ( original[ originalCharIndex ] === '\n' ) {
  257. loc.line += 1;
  258. loc.column = 0;
  259. generatedCodeLine += 1;
  260. this$1.raw[ generatedCodeLine ] = rawSegments = [];
  261. generatedCodeColumn = 0;
  262. } else {
  263. loc.column += 1;
  264. generatedCodeColumn += 1;
  265. }
  266. originalCharIndex += 1;
  267. first = false;
  268. }
  269. pending = [
  270. generatedCodeColumn,
  271. sourceIndex,
  272. loc.line,
  273. loc.column,
  274. -1 ];
  275. };
  276. this.advance = function (str) {
  277. if ( !str ) { return; }
  278. var lines = str.split( '\n' );
  279. var lastLine = lines.pop();
  280. if ( lines.length ) {
  281. generatedCodeLine += lines.length;
  282. this$1.raw[ generatedCodeLine ] = rawSegments = [];
  283. generatedCodeColumn = lastLine.length;
  284. } else {
  285. generatedCodeColumn += lastLine.length;
  286. }
  287. };
  288. this.encode = function () {
  289. return this$1.raw.map( function (segments) {
  290. var generatedCodeColumn = 0;
  291. return segments.map( function (segment) {
  292. var arr = [
  293. segment[0] - generatedCodeColumn,
  294. segment[1] - offsets.sourceIndex,
  295. segment[2] - offsets.sourceCodeLine,
  296. segment[3] - offsets.sourceCodeColumn
  297. ];
  298. generatedCodeColumn = segment[0];
  299. offsets.sourceIndex = segment[1];
  300. offsets.sourceCodeLine = segment[2];
  301. offsets.sourceCodeColumn = segment[3];
  302. if ( ~segment[4] ) {
  303. arr.push( segment[4] - offsets.sourceCodeName );
  304. offsets.sourceCodeName = segment[4];
  305. }
  306. return vlq.encode( arr );
  307. }).join( ',' );
  308. }).join( ';' );
  309. };
  310. }
  311. var Stats = function Stats () {
  312. Object.defineProperties( this, {
  313. startTimes: { value: {} }
  314. });
  315. };
  316. Stats.prototype.time = function time ( label ) {
  317. this.startTimes[ label ] = process.hrtime();
  318. };
  319. Stats.prototype.timeEnd = function timeEnd ( label ) {
  320. var elapsed = process.hrtime( this.startTimes[ label ] );
  321. if ( !this[ label ] ) { this[ label ] = 0; }
  322. this[ label ] += elapsed[0] * 1e3 + elapsed[1] * 1e-6;
  323. };
  324. var warned = {
  325. insertLeft: false,
  326. insertRight: false,
  327. storeName: false
  328. };
  329. function MagicString$1 ( string, options ) {
  330. if ( options === void 0 ) options = {};
  331. var chunk = new Chunk( 0, string.length, string );
  332. Object.defineProperties( this, {
  333. original: { writable: true, value: string },
  334. outro: { writable: true, value: '' },
  335. intro: { writable: true, value: '' },
  336. firstChunk: { writable: true, value: chunk },
  337. lastChunk: { writable: true, value: chunk },
  338. lastSearchedChunk: { writable: true, value: chunk },
  339. byStart: { writable: true, value: {} },
  340. byEnd: { writable: true, value: {} },
  341. filename: { writable: true, value: options.filename },
  342. indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
  343. sourcemapLocations: { writable: true, value: {} },
  344. storedNames: { writable: true, value: {} },
  345. indentStr: { writable: true, value: guessIndent( string ) }
  346. });
  347. this.byStart[ 0 ] = chunk;
  348. this.byEnd[ string.length ] = chunk;
  349. }
  350. MagicString$1.prototype = {
  351. addSourcemapLocation: function addSourcemapLocation ( char ) {
  352. this.sourcemapLocations[ char ] = true;
  353. },
  354. append: function append ( content ) {
  355. if ( typeof content !== 'string' ) { throw new TypeError( 'outro content must be a string' ); }
  356. this.outro += content;
  357. return this;
  358. },
  359. appendLeft: function appendLeft ( index, content ) {
  360. if ( typeof content !== 'string' ) { throw new TypeError( 'inserted content must be a string' ); }
  361. this._split( index );
  362. var chunk = this.byEnd[ index ];
  363. if ( chunk ) {
  364. chunk.appendLeft( content );
  365. } else {
  366. this.intro += content;
  367. }
  368. return this;
  369. },
  370. appendRight: function appendRight ( index, content ) {
  371. if ( typeof content !== 'string' ) { throw new TypeError( 'inserted content must be a string' ); }
  372. this._split( index );
  373. var chunk = this.byStart[ index ];
  374. if ( chunk ) {
  375. chunk.appendRight( content );
  376. } else {
  377. this.outro += content;
  378. }
  379. return this;
  380. },
  381. clone: function clone () {
  382. var cloned = new MagicString$1( this.original, { filename: this.filename });
  383. var originalChunk = this.firstChunk;
  384. var clonedChunk = cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone();
  385. while ( originalChunk ) {
  386. cloned.byStart[ clonedChunk.start ] = clonedChunk;
  387. cloned.byEnd[ clonedChunk.end ] = clonedChunk;
  388. var nextOriginalChunk = originalChunk.next;
  389. var nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
  390. if ( nextClonedChunk ) {
  391. clonedChunk.next = nextClonedChunk;
  392. nextClonedChunk.previous = clonedChunk;
  393. clonedChunk = nextClonedChunk;
  394. }
  395. originalChunk = nextOriginalChunk;
  396. }
  397. cloned.lastChunk = clonedChunk;
  398. if ( this.indentExclusionRanges ) {
  399. cloned.indentExclusionRanges = this.indentExclusionRanges.slice();
  400. }
  401. Object.keys( this.sourcemapLocations ).forEach( function (loc) {
  402. cloned.sourcemapLocations[ loc ] = true;
  403. });
  404. return cloned;
  405. },
  406. generateMap: function generateMap ( options ) {
  407. var this$1 = this;
  408. options = options || {};
  409. var sourceIndex = 0;
  410. var names = Object.keys( this.storedNames );
  411. var mappings = new Mappings( options.hires );
  412. var locate = getLocator( this.original );
  413. if ( this.intro ) {
  414. mappings.advance( this.intro );
  415. }
  416. this.firstChunk.eachNext( function (chunk) {
  417. var loc = locate( chunk.start );
  418. if ( chunk.intro.length ) { mappings.advance( chunk.intro ); }
  419. if ( chunk.edited ) {
  420. mappings.addEdit( sourceIndex, chunk.content, chunk.original, loc, chunk.storeName ? names.indexOf( chunk.original ) : -1 );
  421. } else {
  422. mappings.addUneditedChunk( sourceIndex, chunk, this$1.original, loc, this$1.sourcemapLocations );
  423. }
  424. if ( chunk.outro.length ) { mappings.advance( chunk.outro ); }
  425. });
  426. var map = new SourceMap({
  427. file: ( options.file ? options.file.split( /[\/\\]/ ).pop() : null ),
  428. sources: [ options.source ? getRelativePath( options.file || '', options.source ) : null ],
  429. sourcesContent: options.includeContent ? [ this.original ] : [ null ],
  430. names: names,
  431. mappings: mappings.encode()
  432. });
  433. return map;
  434. },
  435. getIndentString: function getIndentString () {
  436. return this.indentStr === null ? '\t' : this.indentStr;
  437. },
  438. indent: function indent ( indentStr, options ) {
  439. var this$1 = this;
  440. var pattern = /^[^\r\n]/gm;
  441. if ( isObject( indentStr ) ) {
  442. options = indentStr;
  443. indentStr = undefined;
  444. }
  445. indentStr = indentStr !== undefined ? indentStr : ( this.indentStr || '\t' );
  446. if ( indentStr === '' ) { return this; } // noop
  447. options = options || {};
  448. // Process exclusion ranges
  449. var isExcluded = {};
  450. if ( options.exclude ) {
  451. var exclusions = typeof options.exclude[0] === 'number' ? [ options.exclude ] : options.exclude;
  452. exclusions.forEach( function (exclusion) {
  453. for ( var i = exclusion[0]; i < exclusion[1]; i += 1 ) {
  454. isExcluded[i] = true;
  455. }
  456. });
  457. }
  458. var shouldIndentNextCharacter = options.indentStart !== false;
  459. var replacer = function (match) {
  460. if ( shouldIndentNextCharacter ) { return ("" + indentStr + match); }
  461. shouldIndentNextCharacter = true;
  462. return match;
  463. };
  464. this.intro = this.intro.replace( pattern, replacer );
  465. var charIndex = 0;
  466. var chunk = this.firstChunk;
  467. while ( chunk ) {
  468. var end = chunk.end;
  469. if ( chunk.edited ) {
  470. if ( !isExcluded[ charIndex ] ) {
  471. chunk.content = chunk.content.replace( pattern, replacer );
  472. if ( chunk.content.length ) {
  473. shouldIndentNextCharacter = chunk.content[ chunk.content.length - 1 ] === '\n';
  474. }
  475. }
  476. } else {
  477. charIndex = chunk.start;
  478. while ( charIndex < end ) {
  479. if ( !isExcluded[ charIndex ] ) {
  480. var char = this$1.original[ charIndex ];
  481. if ( char === '\n' ) {
  482. shouldIndentNextCharacter = true;
  483. } else if ( char !== '\r' && shouldIndentNextCharacter ) {
  484. shouldIndentNextCharacter = false;
  485. if ( charIndex === chunk.start ) {
  486. chunk.prependRight( indentStr );
  487. } else {
  488. this$1._splitChunk( chunk, charIndex );
  489. chunk = chunk.next;
  490. chunk.prependRight( indentStr );
  491. }
  492. }
  493. }
  494. charIndex += 1;
  495. }
  496. }
  497. charIndex = chunk.end;
  498. chunk = chunk.next;
  499. }
  500. this.outro = this.outro.replace( pattern, replacer );
  501. return this;
  502. },
  503. insert: function insert () {
  504. throw new Error( 'magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)' );
  505. },
  506. insertLeft: function insertLeft ( index, content ) {
  507. if ( !warned.insertLeft ) {
  508. console.warn( 'magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead' ); // eslint-disable-line no-console
  509. warned.insertLeft = true;
  510. }
  511. return this.appendLeft( index, content );
  512. },
  513. insertRight: function insertRight ( index, content ) {
  514. if ( !warned.insertRight ) {
  515. console.warn( 'magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead' ); // eslint-disable-line no-console
  516. warned.insertRight = true;
  517. }
  518. return this.prependRight( index, content );
  519. },
  520. move: function move ( start, end, index ) {
  521. if ( index >= start && index <= end ) { throw new Error( 'Cannot move a selection inside itself' ); }
  522. this._split( start );
  523. this._split( end );
  524. this._split( index );
  525. var first = this.byStart[ start ];
  526. var last = this.byEnd[ end ];
  527. var oldLeft = first.previous;
  528. var oldRight = last.next;
  529. var newRight = this.byStart[ index ];
  530. if ( !newRight && last === this.lastChunk ) { return this; }
  531. var newLeft = newRight ? newRight.previous : this.lastChunk;
  532. if ( oldLeft ) { oldLeft.next = oldRight; }
  533. if ( oldRight ) { oldRight.previous = oldLeft; }
  534. if ( newLeft ) { newLeft.next = first; }
  535. if ( newRight ) { newRight.previous = last; }
  536. if ( !first.previous ) { this.firstChunk = last.next; }
  537. if ( !last.next ) {
  538. this.lastChunk = first.previous;
  539. this.lastChunk.next = null;
  540. }
  541. first.previous = newLeft;
  542. last.next = newRight || null;
  543. if ( !newLeft ) { this.firstChunk = first; }
  544. if ( !newRight ) { this.lastChunk = last; }
  545. return this;
  546. },
  547. overwrite: function overwrite ( start, end, content, options ) {
  548. var this$1 = this;
  549. if ( typeof content !== 'string' ) { throw new TypeError( 'replacement content must be a string' ); }
  550. while ( start < 0 ) { start += this$1.original.length; }
  551. while ( end < 0 ) { end += this$1.original.length; }
  552. if ( end > this.original.length ) { throw new Error( 'end is out of bounds' ); }
  553. if ( start === end ) { throw new Error( 'Cannot overwrite a zero-length range – use appendLeft or prependRight instead' ); }
  554. this._split( start );
  555. this._split( end );
  556. if ( options === true ) {
  557. if ( !warned.storeName ) {
  558. console.warn( 'The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string' ); // eslint-disable-line no-console
  559. warned.storeName = true;
  560. }
  561. options = { storeName: true };
  562. }
  563. var storeName = options !== undefined ? options.storeName : false;
  564. var contentOnly = options !== undefined ? options.contentOnly : false;
  565. if ( storeName ) {
  566. var original = this.original.slice( start, end );
  567. this.storedNames[ original ] = true;
  568. }
  569. var first = this.byStart[ start ];
  570. var last = this.byEnd[ end ];
  571. if ( first ) {
  572. if ( end > first.end && first.next !== this.byStart[ first.end ] ) {
  573. throw new Error( 'Cannot overwrite across a split point' );
  574. }
  575. first.edit( content, storeName, contentOnly );
  576. if ( first !== last ) {
  577. var chunk = first.next;
  578. while ( chunk !== last ) {
  579. chunk.edit( '', false );
  580. chunk = chunk.next;
  581. }
  582. chunk.edit( '', false );
  583. }
  584. }
  585. else {
  586. // must be inserting at the end
  587. var newChunk = new Chunk( start, end, '' ).edit( content, storeName );
  588. // TODO last chunk in the array may not be the last chunk, if it's moved...
  589. last.next = newChunk;
  590. newChunk.previous = last;
  591. }
  592. return this;
  593. },
  594. prepend: function prepend ( content ) {
  595. if ( typeof content !== 'string' ) { throw new TypeError( 'outro content must be a string' ); }
  596. this.intro = content + this.intro;
  597. return this;
  598. },
  599. prependLeft: function prependLeft ( index, content ) {
  600. if ( typeof content !== 'string' ) { throw new TypeError( 'inserted content must be a string' ); }
  601. this._split( index );
  602. var chunk = this.byEnd[ index ];
  603. if ( chunk ) {
  604. chunk.prependLeft( content );
  605. } else {
  606. this.intro = content + this.intro;
  607. }
  608. return this;
  609. },
  610. prependRight: function prependRight ( index, content ) {
  611. if ( typeof content !== 'string' ) { throw new TypeError( 'inserted content must be a string' ); }
  612. this._split( index );
  613. var chunk = this.byStart[ index ];
  614. if ( chunk ) {
  615. chunk.prependRight( content );
  616. } else {
  617. this.outro = content + this.outro;
  618. }
  619. return this;
  620. },
  621. remove: function remove ( start, end ) {
  622. var this$1 = this;
  623. while ( start < 0 ) { start += this$1.original.length; }
  624. while ( end < 0 ) { end += this$1.original.length; }
  625. if ( start === end ) { return this; }
  626. if ( start < 0 || end > this.original.length ) { throw new Error( 'Character is out of bounds' ); }
  627. if ( start > end ) { throw new Error( 'end must be greater than start' ); }
  628. this._split( start );
  629. this._split( end );
  630. var chunk = this.byStart[ start ];
  631. while ( chunk ) {
  632. chunk.intro = '';
  633. chunk.outro = '';
  634. chunk.edit( '' );
  635. chunk = end > chunk.end ? this$1.byStart[ chunk.end ] : null;
  636. }
  637. return this;
  638. },
  639. slice: function slice ( start, end ) {
  640. var this$1 = this;
  641. if ( start === void 0 ) start = 0;
  642. if ( end === void 0 ) end = this.original.length;
  643. while ( start < 0 ) { start += this$1.original.length; }
  644. while ( end < 0 ) { end += this$1.original.length; }
  645. var result = '';
  646. // find start chunk
  647. var chunk = this.firstChunk;
  648. while ( chunk && ( chunk.start > start || chunk.end <= start ) ) {
  649. // found end chunk before start
  650. if ( chunk.start < end && chunk.end >= end ) {
  651. return result;
  652. }
  653. chunk = chunk.next;
  654. }
  655. if ( chunk && chunk.edited && chunk.start !== start ) { throw new Error(("Cannot use replaced character " + start + " as slice start anchor.")); }
  656. var startChunk = chunk;
  657. while ( chunk ) {
  658. if ( chunk.intro && ( startChunk !== chunk || chunk.start === start ) ) {
  659. result += chunk.intro;
  660. }
  661. var containsEnd = chunk.start < end && chunk.end >= end;
  662. if ( containsEnd && chunk.edited && chunk.end !== end ) { throw new Error(("Cannot use replaced character " + end + " as slice end anchor.")); }
  663. var sliceStart = startChunk === chunk ? start - chunk.start : 0;
  664. var sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
  665. result += chunk.content.slice( sliceStart, sliceEnd );
  666. if ( chunk.outro && ( !containsEnd || chunk.end === end ) ) {
  667. result += chunk.outro;
  668. }
  669. if ( containsEnd ) {
  670. break;
  671. }
  672. chunk = chunk.next;
  673. }
  674. return result;
  675. },
  676. // TODO deprecate this? not really very useful
  677. snip: function snip ( start, end ) {
  678. var clone = this.clone();
  679. clone.remove( 0, start );
  680. clone.remove( end, clone.original.length );
  681. return clone;
  682. },
  683. _split: function _split ( index ) {
  684. var this$1 = this;
  685. if ( this.byStart[ index ] || this.byEnd[ index ] ) { return; }
  686. var chunk = this.lastSearchedChunk;
  687. var searchForward = index > chunk.end;
  688. while ( true ) {
  689. if ( chunk.contains( index ) ) { return this$1._splitChunk( chunk, index ); }
  690. chunk = searchForward ?
  691. this$1.byStart[ chunk.end ] :
  692. this$1.byEnd[ chunk.start ];
  693. }
  694. },
  695. _splitChunk: function _splitChunk ( chunk, index ) {
  696. if ( chunk.edited && chunk.content.length ) { // zero-length edited chunks are a special case (overlapping replacements)
  697. var loc = getLocator( this.original )( index );
  698. throw new Error( ("Cannot split a chunk that has already been edited (" + (loc.line) + ":" + (loc.column) + " – \"" + (chunk.original) + "\")") );
  699. }
  700. var newChunk = chunk.split( index );
  701. this.byEnd[ index ] = chunk;
  702. this.byStart[ index ] = newChunk;
  703. this.byEnd[ newChunk.end ] = newChunk;
  704. if ( chunk === this.lastChunk ) { this.lastChunk = newChunk; }
  705. this.lastSearchedChunk = chunk;
  706. return true;
  707. },
  708. toString: function toString () {
  709. var str = this.intro;
  710. var chunk = this.firstChunk;
  711. while ( chunk ) {
  712. str += chunk.toString();
  713. chunk = chunk.next;
  714. }
  715. return str + this.outro;
  716. },
  717. trimLines: function trimLines () {
  718. return this.trim('[\\r\\n]');
  719. },
  720. trim: function trim ( charType ) {
  721. return this.trimStart( charType ).trimEnd( charType );
  722. },
  723. trimEnd: function trimEnd ( charType ) {
  724. var this$1 = this;
  725. var rx = new RegExp( ( charType || '\\s' ) + '+$' );
  726. this.outro = this.outro.replace( rx, '' );
  727. if ( this.outro.length ) { return this; }
  728. var chunk = this.lastChunk;
  729. do {
  730. var end = chunk.end;
  731. var aborted = chunk.trimEnd( rx );
  732. // if chunk was trimmed, we have a new lastChunk
  733. if ( chunk.end !== end ) {
  734. if ( this$1.lastChunk === chunk ) {
  735. this$1.lastChunk = chunk.next;
  736. }
  737. this$1.byEnd[ chunk.end ] = chunk;
  738. this$1.byStart[ chunk.next.start ] = chunk.next;
  739. this$1.byEnd[ chunk.next.end ] = chunk.next;
  740. }
  741. if ( aborted ) { return this$1; }
  742. chunk = chunk.previous;
  743. } while ( chunk );
  744. return this;
  745. },
  746. trimStart: function trimStart ( charType ) {
  747. var this$1 = this;
  748. var rx = new RegExp( '^' + ( charType || '\\s' ) + '+' );
  749. this.intro = this.intro.replace( rx, '' );
  750. if ( this.intro.length ) { return this; }
  751. var chunk = this.firstChunk;
  752. do {
  753. var end = chunk.end;
  754. var aborted = chunk.trimStart( rx );
  755. if ( chunk.end !== end ) {
  756. // special case...
  757. if ( chunk === this$1.lastChunk ) { this$1.lastChunk = chunk.next; }
  758. this$1.byEnd[ chunk.end ] = chunk;
  759. this$1.byStart[ chunk.next.start ] = chunk.next;
  760. this$1.byEnd[ chunk.next.end ] = chunk.next;
  761. }
  762. if ( aborted ) { return this$1; }
  763. chunk = chunk.next;
  764. } while ( chunk );
  765. return this;
  766. }
  767. };
  768. var hasOwnProp = Object.prototype.hasOwnProperty;
  769. function Bundle ( options ) {
  770. if ( options === void 0 ) options = {};
  771. this.intro = options.intro || '';
  772. this.separator = options.separator !== undefined ? options.separator : '\n';
  773. this.sources = [];
  774. this.uniqueSources = [];
  775. this.uniqueSourceIndexByFilename = {};
  776. }
  777. Bundle.prototype = {
  778. addSource: function addSource ( source ) {
  779. if ( source instanceof MagicString$1 ) {
  780. return this.addSource({
  781. content: source,
  782. filename: source.filename,
  783. separator: this.separator
  784. });
  785. }
  786. if ( !isObject( source ) || !source.content ) {
  787. throw new Error( 'bundle.addSource() takes an object with a `content` property, which should be an instance of MagicString, and an optional `filename`' );
  788. }
  789. [ 'filename', 'indentExclusionRanges', 'separator' ].forEach( function (option) {
  790. if ( !hasOwnProp.call( source, option ) ) { source[ option ] = source.content[ option ]; }
  791. });
  792. if ( source.separator === undefined ) { // TODO there's a bunch of this sort of thing, needs cleaning up
  793. source.separator = this.separator;
  794. }
  795. if ( source.filename ) {
  796. if ( !hasOwnProp.call( this.uniqueSourceIndexByFilename, source.filename ) ) {
  797. this.uniqueSourceIndexByFilename[ source.filename ] = this.uniqueSources.length;
  798. this.uniqueSources.push({ filename: source.filename, content: source.content.original });
  799. } else {
  800. var uniqueSource = this.uniqueSources[ this.uniqueSourceIndexByFilename[ source.filename ] ];
  801. if ( source.content.original !== uniqueSource.content ) {
  802. throw new Error( ("Illegal source: same filename (" + (source.filename) + "), different contents") );
  803. }
  804. }
  805. }
  806. this.sources.push( source );
  807. return this;
  808. },
  809. append: function append ( str, options ) {
  810. this.addSource({
  811. content: new MagicString$1( str ),
  812. separator: ( options && options.separator ) || ''
  813. });
  814. return this;
  815. },
  816. clone: function clone () {
  817. var bundle = new Bundle({
  818. intro: this.intro,
  819. separator: this.separator
  820. });
  821. this.sources.forEach( function (source) {
  822. bundle.addSource({
  823. filename: source.filename,
  824. content: source.content.clone(),
  825. separator: source.separator
  826. });
  827. });
  828. return bundle;
  829. },
  830. generateMap: function generateMap ( options ) {
  831. var this$1 = this;
  832. if ( options === void 0 ) options = {};
  833. var names = [];
  834. this.sources.forEach( function (source) {
  835. Object.keys( source.content.storedNames ).forEach( function (name) {
  836. if ( !~names.indexOf( name ) ) { names.push( name ); }
  837. });
  838. });
  839. var mappings = new Mappings( options.hires );
  840. if ( this.intro ) {
  841. mappings.advance( this.intro );
  842. }
  843. this.sources.forEach( function ( source, i ) {
  844. if ( i > 0 ) {
  845. mappings.advance( this$1.separator );
  846. }
  847. var sourceIndex = source.filename ? this$1.uniqueSourceIndexByFilename[ source.filename ] : -1;
  848. var magicString = source.content;
  849. var locate = getLocator( magicString.original );
  850. if ( magicString.intro ) {
  851. mappings.advance( magicString.intro );
  852. }
  853. magicString.firstChunk.eachNext( function (chunk) {
  854. var loc = locate( chunk.start );
  855. if ( chunk.intro.length ) { mappings.advance( chunk.intro ); }
  856. if ( source.filename ) {
  857. if ( chunk.edited ) {
  858. mappings.addEdit( sourceIndex, chunk.content, chunk.original, loc, chunk.storeName ? names.indexOf( chunk.original ) : -1 );
  859. } else {
  860. mappings.addUneditedChunk( sourceIndex, chunk, magicString.original, loc, magicString.sourcemapLocations );
  861. }
  862. }
  863. else {
  864. mappings.advance( chunk.content );
  865. }
  866. if ( chunk.outro.length ) { mappings.advance( chunk.outro ); }
  867. });
  868. if ( magicString.outro ) {
  869. mappings.advance( magicString.outro );
  870. }
  871. });
  872. return new SourceMap({
  873. file: ( options.file ? options.file.split( /[\/\\]/ ).pop() : null ),
  874. sources: this.uniqueSources.map( function (source) {
  875. return options.file ? getRelativePath( options.file, source.filename ) : source.filename;
  876. }),
  877. sourcesContent: this.uniqueSources.map( function (source) {
  878. return options.includeContent ? source.content : null;
  879. }),
  880. names: names,
  881. mappings: mappings.encode()
  882. });
  883. },
  884. getIndentString: function getIndentString () {
  885. var indentStringCounts = {};
  886. this.sources.forEach( function (source) {
  887. var indentStr = source.content.indentStr;
  888. if ( indentStr === null ) { return; }
  889. if ( !indentStringCounts[ indentStr ] ) { indentStringCounts[ indentStr ] = 0; }
  890. indentStringCounts[ indentStr ] += 1;
  891. });
  892. return ( Object.keys( indentStringCounts ).sort( function ( a, b ) {
  893. return indentStringCounts[a] - indentStringCounts[b];
  894. })[0] ) || '\t';
  895. },
  896. indent: function indent ( indentStr ) {
  897. var this$1 = this;
  898. if ( !arguments.length ) {
  899. indentStr = this.getIndentString();
  900. }
  901. if ( indentStr === '' ) { return this; } // noop
  902. var trailingNewline = !this.intro || this.intro.slice( -1 ) === '\n';
  903. this.sources.forEach( function ( source, i ) {
  904. var separator = source.separator !== undefined ? source.separator : this$1.separator;
  905. var indentStart = trailingNewline || ( i > 0 && /\r?\n$/.test( separator ) );
  906. source.content.indent( indentStr, {
  907. exclude: source.indentExclusionRanges,
  908. indentStart: indentStart//: trailingNewline || /\r?\n$/.test( separator ) //true///\r?\n/.test( separator )
  909. });
  910. // TODO this is a very slow way to determine this
  911. trailingNewline = source.content.toString().slice( 0, -1 ) === '\n';
  912. });
  913. if ( this.intro ) {
  914. this.intro = indentStr + this.intro.replace( /^[^\n]/gm, function ( match, index ) {
  915. return index > 0 ? indentStr + match : match;
  916. });
  917. }
  918. return this;
  919. },
  920. prepend: function prepend ( str ) {
  921. this.intro = str + this.intro;
  922. return this;
  923. },
  924. toString: function toString () {
  925. var this$1 = this;
  926. var body = this.sources.map( function ( source, i ) {
  927. var separator = source.separator !== undefined ? source.separator : this$1.separator;
  928. var str = ( i > 0 ? separator : '' ) + source.content.toString();
  929. return str;
  930. }).join( '' );
  931. return this.intro + body;
  932. },
  933. trimLines: function trimLines () {
  934. return this.trim('[\\r\\n]');
  935. },
  936. trim: function trim ( charType ) {
  937. return this.trimStart( charType ).trimEnd( charType );
  938. },
  939. trimStart: function trimStart ( charType ) {
  940. var this$1 = this;
  941. var rx = new RegExp( '^' + ( charType || '\\s' ) + '+' );
  942. this.intro = this.intro.replace( rx, '' );
  943. if ( !this.intro ) {
  944. var source;
  945. var i = 0;
  946. do {
  947. source = this$1.sources[i];
  948. if ( !source ) {
  949. break;
  950. }
  951. source.content.trimStart( charType );
  952. i += 1;
  953. } while ( source.content.toString() === '' ); // TODO faster way to determine non-empty source?
  954. }
  955. return this;
  956. },
  957. trimEnd: function trimEnd ( charType ) {
  958. var this$1 = this;
  959. var rx = new RegExp( ( charType || '\\s' ) + '+$' );
  960. var source;
  961. var i = this.sources.length - 1;
  962. do {
  963. source = this$1.sources[i];
  964. if ( !source ) {
  965. this$1.intro = this$1.intro.replace( rx, '' );
  966. break;
  967. }
  968. source.content.trimEnd( charType );
  969. i -= 1;
  970. } while ( source.content.toString() === '' ); // TODO faster way to determine non-empty source?
  971. return this;
  972. }
  973. };
  974. MagicString$1.Bundle = Bundle;
  975. MagicString$1.default = MagicString$1; // work around TypeScript bug https://github.com/Rich-Harris/magic-string/pull/121
  976. module.exports = MagicString$1;
  977. //# sourceMappingURL=magic-string.cjs.js.map