diff --git a/src/cli/cli.ts b/src/cli/cli.ts
index d3df4b37..9edc3709 100755
--- a/src/cli/cli.ts
+++ b/src/cli/cli.ts
@@ -104,6 +104,12 @@ export const cli = y
type: 'string',
conflicts: ['null-as-default-value', 'key-as-default-value']
})
+ .option('newline-at-eof', {
+ alias: 'nl',
+ describe: 'Add newline at the end of the generated file',
+ default: false,
+ type: 'boolean'
+ })
.group(['format', 'format-indentation', 'sort', 'clean', 'replace'], 'Output')
.group(['key-as-default-value', 'null-as-default-value', 'string-as-default-value'], 'Extracted key value (defaults to empty string)')
.conflicts('key-as-default-value', 'null-as-default-value')
@@ -145,7 +151,8 @@ extractTask.setPostProcessors(postProcessors);
// Compiler
const compiler: CompilerInterface = CompilerFactory.create(cli.format, {
- indentation: cli.formatIndentation
+ indentation: cli.formatIndentation,
+ eofNewline: cli.newlineAtEof
});
extractTask.setCompiler(compiler);
diff --git a/src/compilers/core.compiler.ts b/src/compilers/core.compiler.ts
new file mode 100644
index 00000000..7d36af91
--- /dev/null
+++ b/src/compilers/core.compiler.ts
@@ -0,0 +1,21 @@
+import { CompilerInterface } from './compiler.interface';
+import { TranslationCollection } from '../utils/translation.collection';
+
+export abstract class CoreCompiler implements CompilerInterface {
+ public abstract extension: string;
+ public eofNewline = false;
+
+ protected constructor(options?: any) {
+ if (options && typeof options.eofNewline !== 'undefined') {
+ this.eofNewline = options.eofNewline;
+ }
+ }
+
+ public compile(collection: TranslationCollection): string {
+ return this.compileSpecific(collection) + (this.eofNewline ? '\n' : '');
+ }
+
+ protected abstract compileSpecific(collection: TranslationCollection): string;
+
+ public abstract parse(contents: string): TranslationCollection;
+}
diff --git a/src/compilers/json.compiler.ts b/src/compilers/json.compiler.ts
index d24adfb2..a496982c 100644
--- a/src/compilers/json.compiler.ts
+++ b/src/compilers/json.compiler.ts
@@ -1,21 +1,22 @@
-import { CompilerInterface } from './compiler.interface';
import { TranslationCollection } from '../utils/translation.collection';
import { stripBOM } from '../utils/utils';
import { flatten } from 'flat';
+import { CoreCompiler } from './core.compiler';
-export class JsonCompiler implements CompilerInterface {
+export class JsonCompiler extends CoreCompiler {
public indentation: string = '\t';
public extension: string = 'json';
public constructor(options?: any) {
+ super(options);
if (options && typeof options.indentation !== 'undefined') {
this.indentation = options.indentation;
}
}
- public compile(collection: TranslationCollection): string {
+ protected compileSpecific(collection: TranslationCollection): string {
return JSON.stringify(collection.values, null, this.indentation);
}
diff --git a/src/compilers/namespaced-json.compiler.ts b/src/compilers/namespaced-json.compiler.ts
index c4fa943d..1729270a 100644
--- a/src/compilers/namespaced-json.compiler.ts
+++ b/src/compilers/namespaced-json.compiler.ts
@@ -1,21 +1,22 @@
-import { CompilerInterface } from './compiler.interface';
import { TranslationCollection } from '../utils/translation.collection';
import { stripBOM } from '../utils/utils';
import { flatten, unflatten } from 'flat';
+import { CoreCompiler } from './core.compiler';
-export class NamespacedJsonCompiler implements CompilerInterface {
+export class NamespacedJsonCompiler extends CoreCompiler {
public indentation: string = '\t';
public extension = 'json';
public constructor(options?: any) {
+ super(options);
if (options && typeof options.indentation !== 'undefined') {
this.indentation = options.indentation;
}
}
- public compile(collection: TranslationCollection): string {
+ protected compileSpecific(collection: TranslationCollection): string {
const values: {} = unflatten(collection.values, {
object: true
});
diff --git a/src/compilers/po.compiler.ts b/src/compilers/po.compiler.ts
index af6d2831..2c5c0a63 100644
--- a/src/compilers/po.compiler.ts
+++ b/src/compilers/po.compiler.ts
@@ -1,9 +1,9 @@
-import { CompilerInterface } from './compiler.interface';
import { TranslationCollection, TranslationType } from '../utils/translation.collection';
import { po } from 'gettext-parser';
+import { CoreCompiler } from './core.compiler';
-export class PoCompiler implements CompilerInterface {
+export class PoCompiler extends CoreCompiler {
public extension: string = 'po';
/**
@@ -11,9 +11,11 @@ export class PoCompiler implements CompilerInterface {
*/
public domain: string = '';
- public constructor(options?: any) {}
+ public constructor(options?: any) {
+ super(options);
+ }
- public compile(collection: TranslationCollection): string {
+ protected compileSpecific(collection: TranslationCollection): string {
const data = {
charset: 'utf-8',
headers: {
diff --git a/tests/compilers/namespaced-json.compiler.spec.ts b/tests/compilers/namespaced-json.compiler.spec.ts
index 48a61556..f620194d 100644
--- a/tests/compilers/namespaced-json.compiler.spec.ts
+++ b/tests/compilers/namespaced-json.compiler.spec.ts
@@ -5,9 +5,11 @@ import { NamespacedJsonCompiler } from '../../src/compilers/namespaced-json.comp
describe('NamespacedJsonCompiler', () => {
let compiler: NamespacedJsonCompiler;
+ let eofNewlineCompiler: NamespacedJsonCompiler;
beforeEach(() => {
compiler = new NamespacedJsonCompiler();
+ eofNewlineCompiler = new NamespacedJsonCompiler({ eofNewline: true });
});
it('should flatten keys on parse', () => {
@@ -35,6 +37,8 @@ describe('NamespacedJsonCompiler', () => {
});
const result: string = compiler.compile(collection);
expect(result).to.equal('{\n\t"NAMESPACE": {\n\t\t"KEY": {\n\t\t\t"FIRST_KEY": "",\n\t\t\t"SECOND_KEY": "VALUE"\n\t\t}\n\t}\n}');
+ const resultNewline: string = eofNewlineCompiler.compile(collection);
+ expect(resultNewline).to.equal('{\n\t"NAMESPACE": {\n\t\t"KEY": {\n\t\t\t"FIRST_KEY": "",\n\t\t\t"SECOND_KEY": "VALUE"\n\t\t}\n\t}\n}\n');
});
it('should preserve numeric values on compile', () => {
@@ -45,6 +49,8 @@ describe('NamespacedJsonCompiler', () => {
});
const result: string = compiler.compile(collection);
expect(result).to.equal('{\n\t"option": {\n\t\t"0": "",\n\t\t"1": "",\n\t\t"2": ""\n\t}\n}');
+ const resultNewline: string = eofNewlineCompiler.compile(collection);
+ expect(resultNewline).to.equal('{\n\t"option": {\n\t\t"0": "",\n\t\t"1": "",\n\t\t"2": ""\n\t}\n}\n');
});
it('should use custom indentation chars', () => {
@@ -66,5 +72,7 @@ describe('NamespacedJsonCompiler', () => {
});
const result: string = compiler.compile(collection);
expect(result).to.equal('{\n\t"BROWSE": "",\n\t"LOGIN": ""\n}');
+ const resultNewline: string = eofNewlineCompiler.compile(collection);
+ expect(resultNewline).to.equal('{\n\t"BROWSE": "",\n\t"LOGIN": ""\n}\n');
});
});
diff --git a/tests/compilers/po.compiler.spec.ts b/tests/compilers/po.compiler.spec.ts
index 8d0fd298..8f104f81 100644
--- a/tests/compilers/po.compiler.spec.ts
+++ b/tests/compilers/po.compiler.spec.ts
@@ -5,9 +5,11 @@ import { PoCompiler } from '../../src/compilers/po.compiler';
describe('PoCompiler', () => {
let compiler: PoCompiler;
+ let eofNewlineCompiler: PoCompiler;
beforeEach(() => {
compiler = new PoCompiler();
+ eofNewlineCompiler = new PoCompiler({ eofNewline: true });
});
it('should still include html ', () => {
@@ -17,6 +19,8 @@ describe('PoCompiler', () => {
});
const result: Buffer = Buffer.from(compiler.compile(collection));
expect(result.toString('utf8')).to.equal('msgid ""\nmsgstr ""\n"mime-version: 1.0\\n"\n"Content-Type: text/plain; charset=utf-8\\n"\n"Content-Transfer-Encoding: 8bit\\n"\n\nmsgid "A test"\nmsgstr "Un test"\n\nmsgid "With a lot of html included"\nmsgstr "Avec beaucoup d\'html inclus"');
+ const resultNewline: Buffer = Buffer.from(eofNewlineCompiler.compile(collection));
+ expect(resultNewline.toString('utf8')).to.equal('msgid ""\nmsgstr ""\n"mime-version: 1.0\\n"\n"Content-Type: text/plain; charset=utf-8\\n"\n"Content-Transfer-Encoding: 8bit\\n"\n\nmsgid "A test"\nmsgstr "Un test"\n\nmsgid "With a lot of html included"\nmsgstr "Avec beaucoup d\'html inclus"\n');
});
});