diff --git a/src/cli/extract.ts b/src/cli/extract.ts index 71b5f40..27fa283 100755 --- a/src/cli/extract.ts +++ b/src/cli/extract.ts @@ -21,7 +21,7 @@ const options = cli.parse({ [options.dir, options.output].forEach(dir => { if (!fs.existsSync(dir)) { - cli.fatal('The directory path you supplied was not found: ' + dir); + cli.fatal(`The directory path you supplied was not found: '${dir}'`); } }); @@ -39,17 +39,12 @@ const patterns: string[] = [ '/**/*.js' ]; -const extractor: Extractor = new Extractor(parsers, patterns); - try { + const extractor: Extractor = new Extractor(parsers, patterns); cli.info(`Extracting strings from '${options.dir}'`); const extracted: TranslationCollection = extractor.process(options.dir); cli.ok(`* Extracted ${extracted.count()} strings`); - if (extracted.isEmpty()) { - process.exit(); - } - let collection: TranslationCollection = extracted; let compiler = new JsonCompiler(); @@ -60,8 +55,10 @@ try { if (!options.replace && fs.existsSync(dest)) { const existing: TranslationCollection = compiler.parse(fs.readFileSync(dest, 'utf-8')); - collection = extracted.union(existing); - cli.ok(`* Merged ${existing.count()} existing strings`); + if (existing.count() > 0) { + collection = extracted.union(existing); + cli.ok(`* Merged ${existing.count()} existing strings`); + } if (options.clean) { const collectionCount = collection.count(); diff --git a/src/compilers/po.compiler.ts b/src/compilers/po.compiler.ts index 0f1fcf5..dc43fd6 100644 --- a/src/compilers/po.compiler.ts +++ b/src/compilers/po.compiler.ts @@ -25,7 +25,7 @@ export class PoCompiler implements CompilerInterface { msgstr: collection.get(key) }; return translations; - }, {}) + }, {}) } }; @@ -45,7 +45,7 @@ export class PoCompiler implements CompilerInterface { .reduce((values, key) => { values[key] = po.translations[this.domain][key].msgstr.pop(); return values; - }, {}); + }, {}); return new TranslationCollection(values); } diff --git a/src/parsers/abstract-template.parser.ts b/src/parsers/abstract-template.parser.ts index 817c3c1..791ad26 100644 --- a/src/parsers/abstract-template.parser.ts +++ b/src/parsers/abstract-template.parser.ts @@ -12,7 +12,7 @@ export abstract class AbstractTemplateParser { * Extracts inline template from components */ protected _extractInlineTemplate(contents: string): string { - const match = new RegExp(/template\s*:\s*(["'`])((.|[\r\n])+?[^\\])\1/).exec(contents); + const match = new RegExp(/template\s*:\s*(["'`])([^\1]*?)\1/).exec(contents); if (match !== null) { return match[2]; } diff --git a/src/parsers/pipe.parser.ts b/src/parsers/pipe.parser.ts index cb69717..d51294d 100644 --- a/src/parsers/pipe.parser.ts +++ b/src/parsers/pipe.parser.ts @@ -15,7 +15,7 @@ export class PipeParser extends AbstractTemplateParser implements ParserInterfac protected _parseTemplate(template: string): TranslationCollection { let collection: TranslationCollection = new TranslationCollection(); - const regExp = new RegExp(/(['"`])([^\1\r\n]*)\1\s*\|\s*translate(:.*?)?/, 'g'); + const regExp = new RegExp(/(['"`])([^\1]*)\1\s*\|\s*translate/, 'g'); let matches: RegExpExecArray; while (matches = regExp.exec(template)) { diff --git a/src/parsers/service.parser.ts b/src/parsers/service.parser.ts index 3fdf48c..ec53d35 100644 --- a/src/parsers/service.parser.ts +++ b/src/parsers/service.parser.ts @@ -11,10 +11,10 @@ export class ServiceParser implements ParserInterface { return collection; } - const methodRegExp: RegExp = new RegExp(/(?:get|instant)\s*\(\s*(\[?(['"`])([^\1\r\n]+)\2\]?)/); + const methodRegExp: RegExp = new RegExp(/(?:get|instant)\s*\(\s*(\[?\s*(['"`])([^\1\r\n]*)\2\s*\]?)/); const regExp: RegExp = new RegExp(`${translateServiceVar}\.${methodRegExp.source}`, 'g'); - let matches; + let matches: RegExpExecArray; while (matches = regExp.exec(contents)) { if (this._stringContainsArray(matches[1])) { collection = collection.addKeys(this._stringToArray(matches[1])); diff --git a/src/utils/translation.collection.ts b/src/utils/translation.collection.ts index ea5ff47..ced5f94 100644 --- a/src/utils/translation.collection.ts +++ b/src/utils/translation.collection.ts @@ -18,7 +18,7 @@ export class TranslationCollection { const values = keys.reduce((results, key) => { results[key] = ''; return results; - }, {}); + }, {}); return new TranslationCollection(Object.assign({}, this.values, values)); } diff --git a/tests/parsers/abstract-template.parser.spec.ts b/tests/parsers/abstract-template.parser.spec.ts index ce86fa3..126f1ba 100644 --- a/tests/parsers/abstract-template.parser.spec.ts +++ b/tests/parsers/abstract-template.parser.spec.ts @@ -41,6 +41,12 @@ describe('AbstractTemplateParser', () => { expect(result).to.equal(false); }); + it('should normalize bound attributes', () => { + const contents = `

Hello World

`; + const template = parser.normalizeTemplateAttributes(contents); + expect(template).to.equal('

Hello World

'); + }); + it('should extract inline template', () => { const contents = ` @Component({ @@ -53,10 +59,25 @@ describe('AbstractTemplateParser', () => { expect(template).to.equal('

Hello World

'); }); - it('should normalize bound attributes', () => { - const contents = `

Hello World

`; - const template = parser.normalizeTemplateAttributes(contents); - expect(template).to.equal('

Hello World

'); + it('should extract inline template spanning multiple lines', () => { + const contents = ` + @Component({ + selector: 'test', + template: ' +

+ Hello World +

+ ', + styles: [' + p { + color: red; + } + '] + }) + export class TestComponent { } + `; + const template = parser.extractInlineTemplate(contents); + expect(template).to.equal('\n\t\t\t\t\t

\n\t\t\t\t\t\tHello World\n\t\t\t\t\t

\n\t\t\t\t'); }); }); diff --git a/tests/parsers/pipe.parser.spec.ts b/tests/parsers/pipe.parser.spec.ts index b3bbb1e..f177c90 100644 --- a/tests/parsers/pipe.parser.spec.ts +++ b/tests/parsers/pipe.parser.spec.ts @@ -18,6 +18,12 @@ describe('PipeParser', () => { expect(keys).to.deep.equal(['World']); }); + it('should extract strings with escaped quotes', () => { + const contents = `Hello {{ 'World\'s largest potato' | translate }}`; + const keys = parser.extract(contents, templateFilename).keys(); + expect(keys).to.deep.equal([`World's largest potato`]); + }); + it('should extract interpolated strings using translate pipe in attributes', () => { const contents = ``; const keys = parser.extract(contents, templateFilename).keys(); diff --git a/tests/parsers/service.parser.spec.ts b/tests/parsers/service.parser.spec.ts index aac62e3..83af601 100644 --- a/tests/parsers/service.parser.spec.ts +++ b/tests/parsers/service.parser.spec.ts @@ -103,4 +103,24 @@ describe('ServiceParser', () => { expect(keys).to.deep.equal([]); }); + it('should extract strings with liberal spacing', () => { + const contents = ` + @Component({ }) + export class AppComponent { + public constructor( + protected _translateService: TranslateService, + protected _otherService: OtherService + ) { } + public test() { + this._translateService.instant('Hello'); + this._translateService.get ( 'World' ); + this._translateService.instant ( ['How'] ); + this._translateService.get([ 'Are' ]); + this._translateService.get([ 'You' , 'Today' ]); + } + `; + const keys = parser.extract(contents, componentFilename).keys(); + expect(keys).to.deep.equal(['Hello', 'World', 'How', 'Are', 'You', 'Today']); + }); + });