diff --git a/packages/angular_devkit/schematics/src/tree/recorder.ts b/packages/angular_devkit/schematics/src/tree/recorder.ts index be8e485e6f8b..8b18b8182e55 100644 --- a/packages/angular_devkit/schematics/src/tree/recorder.ts +++ b/packages/angular_devkit/schematics/src/tree/recorder.ts @@ -30,9 +30,9 @@ export class UpdateRecorderBase implements UpdateRecorder { if (c0 == 0xEF && c1 == 0xBB && c2 == 0xBF) { return new UpdateRecorderBom(entry); } else if (c0 === 0xFF && c1 == 0xFE) { - return new UpdateRecorderBom(entry, 2); + return new UpdateRecorderBom(entry); } else if (c0 === 0xFE && c1 == 0xFF) { - return new UpdateRecorderBom(entry, 2); + return new UpdateRecorderBom(entry); } return new UpdateRecorderBase(entry); @@ -70,7 +70,7 @@ export class UpdateRecorderBase implements UpdateRecorder { export class UpdateRecorderBom extends UpdateRecorderBase { - constructor(entry: FileEntry, private _delta = 3) { + constructor(entry: FileEntry, private _delta = 1) { super(entry); } diff --git a/packages/angular_devkit/schematics/src/utility/update-buffer.ts b/packages/angular_devkit/schematics/src/utility/update-buffer.ts index 44a9f620a914..165305ddabae 100644 --- a/packages/angular_devkit/schematics/src/utility/update-buffer.ts +++ b/packages/angular_devkit/schematics/src/utility/update-buffer.ts @@ -201,19 +201,31 @@ export class UpdateBuffer { } protected _slice(start: number): [Chunk, Chunk] { - this._assertIndex(start); + // If start is longer than the content, use start, otherwise determine exact position in string. + const index = start >= this._originalContent.length ? start : this._getTextPosition(start); + + this._assertIndex(index); // Find the chunk by going through the list. - const h = this._linkedList.find(chunk => start <= chunk.end); + const h = this._linkedList.find(chunk => index <= chunk.end); if (!h) { throw Error('Chunk cannot be found.'); } - if (start == h.end && h.next !== null) { + if (index == h.end && h.next !== null) { return [h, h.next]; } - return [h, h.slice(start)]; + return [h, h.slice(index)]; + } + + /** + * Gets the position in the content based on the position in the string. + * Some characters might be wider than one byte, thus we have to determine the position using + * string functions. + */ + protected _getTextPosition(index: number): number { + return Buffer.from(this._originalContent.toString().substring(0, index)).length; } get length(): number { diff --git a/packages/angular_devkit/schematics/src/utility/update-buffer_spec.ts b/packages/angular_devkit/schematics/src/utility/update-buffer_spec.ts index f6e7cc2aa271..64e650feeb29 100644 --- a/packages/angular_devkit/schematics/src/utility/update-buffer_spec.ts +++ b/packages/angular_devkit/schematics/src/utility/update-buffer_spec.ts @@ -58,6 +58,16 @@ describe('UpdateBuffer', () => { mb.insertLeft(6, Buffer.from('Awesome ')); expect(mb.toString()).toBe('Hello Great Awesome Beautiful World'); }); + + it('works with special characters', () => { + const mb = new UpdateBuffer(Buffer.from('Ülaut')); + + mb.insertLeft(1, Buffer.from('m')); + expect(mb.toString()).toBe('Ümlaut'); + + mb.insertLeft(0, Buffer.from('Hello ')); + expect(mb.toString()).toBe('Hello Ümlaut'); + }); }); describe('delete', () => {