(bugfix) extract strings encapsulated with backticks. Closes #139
This commit is contained in:
		| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "@biesbjerg/ngx-translate-extract", |   "name": "@biesbjerg/ngx-translate-extract", | ||||||
|   "version": "3.0.3", |   "version": "3.0.4", | ||||||
|   "description": "Extract strings from projects using ngx-translate", |   "description": "Extract strings from projects using ngx-translate", | ||||||
|   "main": "dist/index.js", |   "main": "dist/index.js", | ||||||
|   "typings": "dist/index.d.ts", |   "typings": "dist/index.d.ts", | ||||||
|   | |||||||
| @@ -4,7 +4,8 @@ import { | |||||||
| 	CallExpression, | 	CallExpression, | ||||||
| 	Node, | 	Node, | ||||||
| 	SyntaxKind, | 	SyntaxKind, | ||||||
| 	StringLiteral | 	StringLiteral, | ||||||
|  | 	NoSubstitutionTemplateLiteral | ||||||
| } from 'typescript'; | } from 'typescript'; | ||||||
|  |  | ||||||
| export abstract class AbstractAstParser { | export abstract class AbstractAstParser { | ||||||
| @@ -24,19 +25,23 @@ export abstract class AbstractAstParser { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		const firstArg = callNode.arguments[0]; | 		const firstArg = callNode.arguments[0]; | ||||||
| 		return this.findNodes(firstArg, SyntaxKind.StringLiteral) |  | ||||||
| 			.map((node: StringLiteral) => node.text); | 		return this.findNodes(firstArg, [ | ||||||
|  | 			SyntaxKind.StringLiteral, | ||||||
|  | 			SyntaxKind.NoSubstitutionTemplateLiteral | ||||||
|  | 		]) | ||||||
|  | 		.map((node: StringLiteral | NoSubstitutionTemplateLiteral) => node.text); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Find all child nodes of a kind | 	 * Find all child nodes of a kind | ||||||
| 	 */ | 	 */ | ||||||
| 	protected findNodes(node: Node, kind: SyntaxKind): Node[] { | 	protected findNodes(node: Node, kinds: SyntaxKind[]): Node[] { | ||||||
| 		const childrenNodes: Node[] = node.getChildren(this.sourceFile); | 		const childrenNodes: Node[] = node.getChildren(this.sourceFile); | ||||||
| 		const initialValue: Node[] = node.kind === kind ? [node] : []; | 		const initialValue: Node[] = kinds.includes(node.kind) ? [node] : []; | ||||||
|  |  | ||||||
| 		return childrenNodes.reduce((result: Node[], childNode: Node) => { | 		return childrenNodes.reduce((result: Node[], childNode: Node) => { | ||||||
| 			return result.concat(this.findNodes(childNode, kind)); | 			return result.concat(this.findNodes(childNode, kinds)); | ||||||
| 		}, initialValue); | 		}, initialValue); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -38,7 +38,7 @@ export class FunctionParser extends AbstractAstParser implements ParserInterface | |||||||
| 			node = this.sourceFile; | 			node = this.sourceFile; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		let callNodes = this.findNodes(node, SyntaxKind.CallExpression) as CallExpression[]; | 		let callNodes = this.findNodes(node, [SyntaxKind.CallExpression]) as CallExpression[]; | ||||||
| 		callNodes = callNodes | 		callNodes = callNodes | ||||||
| 			.filter(callNode => { | 			.filter(callNode => { | ||||||
| 				// Only call expressions with arguments | 				// Only call expressions with arguments | ||||||
|   | |||||||
| @@ -89,14 +89,14 @@ export class ServiceParser extends AbstractAstParser implements ParserInterface | |||||||
| 	 * Find class nodes | 	 * Find class nodes | ||||||
| 	 */ | 	 */ | ||||||
| 	protected findClassNodes(node: Node): ClassDeclaration[] { | 	protected findClassNodes(node: Node): ClassDeclaration[] { | ||||||
| 		return this.findNodes(node, SyntaxKind.ClassDeclaration) as ClassDeclaration[]; | 		return this.findNodes(node, [SyntaxKind.ClassDeclaration]) as ClassDeclaration[]; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Find constructor | 	 * Find constructor | ||||||
| 	 */ | 	 */ | ||||||
| 	protected findConstructorNode(node: ClassDeclaration): ConstructorDeclaration { | 	protected findConstructorNode(node: ClassDeclaration): ConstructorDeclaration { | ||||||
| 		const constructorNodes = this.findNodes(node, SyntaxKind.Constructor) as ConstructorDeclaration[]; | 		const constructorNodes = this.findNodes(node, [SyntaxKind.Constructor]) as ConstructorDeclaration[]; | ||||||
| 		if (constructorNodes) { | 		if (constructorNodes) { | ||||||
| 			return constructorNodes[0]; | 			return constructorNodes[0]; | ||||||
| 		} | 		} | ||||||
| @@ -106,7 +106,7 @@ export class ServiceParser extends AbstractAstParser implements ParserInterface | |||||||
| 	 * Find all calls to TranslateService methods | 	 * Find all calls to TranslateService methods | ||||||
| 	 */ | 	 */ | ||||||
| 	protected findCallNodes(node: Node, propertyIdentifier: string): CallExpression[] { | 	protected findCallNodes(node: Node, propertyIdentifier: string): CallExpression[] { | ||||||
| 		let callNodes = this.findNodes(node, SyntaxKind.CallExpression) as CallExpression[]; | 		let callNodes = this.findNodes(node, [SyntaxKind.CallExpression]) as CallExpression[]; | ||||||
| 		callNodes = callNodes | 		callNodes = callNodes | ||||||
| 			.filter(callNode => { | 			.filter(callNode => { | ||||||
| 				// Only call expressions with arguments | 				// Only call expressions with arguments | ||||||
|   | |||||||
| @@ -122,6 +122,19 @@ describe('ServiceParser', () => { | |||||||
| 		expect(key).to.deep.equal(['Hello', 'World']); | 		expect(key).to.deep.equal(['Hello', 'World']); | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
|  | 	it('should extract string arrays encapsulated in backticks', () => { | ||||||
|  | 		const contents = ` | ||||||
|  | 			@Component({ }) | ||||||
|  | 			export class AppComponent { | ||||||
|  | 				public constructor(protected _translateService: TranslateService) { } | ||||||
|  | 				public test() { | ||||||
|  | 					this._translateService.get([\`Hello\`, \`World\`]); | ||||||
|  | 				} | ||||||
|  | 		`; | ||||||
|  | 		const keys = parser.extract(contents, componentFilename).keys(); | ||||||
|  | 		expect(keys).to.deep.equal(['Hello', 'World']); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
| 	it('should not extract strings in get()/instant()/stream() methods of other services', () => { | 	it('should not extract strings in get()/instant()/stream() methods of other services', () => { | ||||||
| 		const contents = ` | 		const contents = ` | ||||||
| 			@Component({ }) | 			@Component({ }) | ||||||
|   | |||||||
| @@ -5,10 +5,10 @@ | |||||||
|         "noImplicitAny": true, |         "noImplicitAny": true, | ||||||
|         "removeComments": true, |         "removeComments": true, | ||||||
|         "declaration": true, |         "declaration": true, | ||||||
|         "target": "es6", |         "target": "es2015", | ||||||
|         "lib": [ |         "lib": [ | ||||||
|             "dom", |             "dom", | ||||||
|             "es2015" |             "es2018" | ||||||
|         ], |         ], | ||||||
|         "module": "commonjs", |         "module": "commonjs", | ||||||
|         "outDir": "./dist/", |         "outDir": "./dist/", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user