Skip to content

Commit

Permalink
fix(@angular-devkit/schematics): add support for BOM to UpdateRecorder
Browse files Browse the repository at this point in the history
Fixes #10644
  • Loading branch information
hansl committed Jun 6, 2018
1 parent 505159b commit 352ad3e
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
36 changes: 36 additions & 0 deletions packages/angular_devkit/schematics/src/tree/recorder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ export class UpdateRecorderBase implements UpdateRecorder {
this._path = entry.path;
}

static createFromFileEntry(entry: FileEntry): UpdateRecorderBase {
const c0 = entry.content.readUInt8(0, true);
const c1 = entry.content.readUInt8(1, true);
const c2 = entry.content.readUInt8(2, true);

// Check if we're BOM.
if (c0 == 0xEF && c1 == 0xBB && c2 == 0xBF) {
return new UpdateRecorderBom(entry);
} else if (c0 === 0xFF && c1 == 0xFE) {
return new UpdateRecorderBom(entry, 2);
} else if (c0 === 0xFE && c1 == 0xFF) {
return new UpdateRecorderBom(entry, 2);
}

return new UpdateRecorderBase(entry);
}

get path() { return this._path; }

// These just record changes.
Expand Down Expand Up @@ -50,3 +67,22 @@ export class UpdateRecorderBase implements UpdateRecorder {
return this._content.generate();
}
}


export class UpdateRecorderBom extends UpdateRecorderBase {
constructor(entry: FileEntry, private _delta = 3) {
super(entry);
}

insertLeft(index: number, content: Buffer | string) {
return super.insertLeft(index + this._delta, content);
}

insertRight(index: number, content: Buffer | string) {
return super.insertRight(index + this._delta, content);
}

remove(index: number, length: number) {
return super.remove(index + this._delta, length);
}
}
66 changes: 66 additions & 0 deletions packages/angular_devkit/schematics/src/tree/recorder_spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { normalize } from '@angular-devkit/core';
import { SimpleFileEntry } from './entry';
import { UpdateRecorderBase, UpdateRecorderBom } from './recorder';

describe('UpdateRecorderBase', () => {
it('works for simple files', () => {
const buffer = new Buffer('Hello World');
const entry = new SimpleFileEntry(normalize('/some/path'), buffer);

const recorder = new UpdateRecorderBase(entry);
recorder.insertLeft(5, ' beautiful');
const result = recorder.apply(buffer);
expect(result.toString()).toBe('Hello beautiful World');
});

it('works for simple files (2)', () => {
const buffer = new Buffer('Hello World');
const entry = new SimpleFileEntry(normalize('/some/path'), buffer);

const recorder = new UpdateRecorderBase(entry);
recorder.insertRight(5, ' beautiful');
const result = recorder.apply(buffer);
expect(result.toString()).toBe('Hello beautiful World');
});

it('can create the proper recorder', () => {
const e = new SimpleFileEntry(normalize('/some/path'), new Buffer('hello'));
expect(UpdateRecorderBase.createFromFileEntry(e) instanceof UpdateRecorderBase).toBe(true);
expect(UpdateRecorderBase.createFromFileEntry(e) instanceof UpdateRecorderBom).toBe(false);
});

it('can create the proper recorder (bom)', () => {
const eBom = new SimpleFileEntry(normalize('/some/path'), new Buffer('\uFEFFhello'));
expect(UpdateRecorderBase.createFromFileEntry(eBom) instanceof UpdateRecorderBase).toBe(true);
expect(UpdateRecorderBase.createFromFileEntry(eBom) instanceof UpdateRecorderBom).toBe(true);
});

it('supports empty files', () => {
const e = new SimpleFileEntry(normalize('/some/path'), new Buffer(''));
expect(UpdateRecorderBase.createFromFileEntry(e) instanceof UpdateRecorderBase).toBe(true);
});

it('supports empty files (bom)', () => {
const eBom = new SimpleFileEntry(normalize('/some/path'), new Buffer('\uFEFF'));
expect(UpdateRecorderBase.createFromFileEntry(eBom) instanceof UpdateRecorderBase).toBe(true);
});
});

describe('UpdateRecorderBom', () => {
it('works for simple files', () => {
const buffer = new Buffer('\uFEFFHello World');
const entry = new SimpleFileEntry(normalize('/some/path'), buffer);

const recorder = new UpdateRecorderBom(entry);
recorder.insertLeft(5, ' beautiful');
const result = recorder.apply(buffer);
expect(result.toString()).toBe('\uFEFFHello beautiful World');
});
});
2 changes: 1 addition & 1 deletion packages/angular_devkit/schematics/src/tree/virtual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export class VirtualTree implements Tree {
throw new FileDoesNotExistException(path);
}

return new UpdateRecorderBase(entry);
return UpdateRecorderBase.createFromFileEntry(entry);
}

commitUpdate(record: UpdateRecorder) {
Expand Down

0 comments on commit 352ad3e

Please sign in to comment.