Merge branch 'directive-parsing' of https://github.com/ocombe/ng2-translate-extract into ocombe-directive-parsing
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,6 @@ | |||||||
| # IDE | # IDE | ||||||
| .vscode | .vscode | ||||||
|  | .idea | ||||||
|  |  | ||||||
| # Logs and other files | # Logs and other files | ||||||
| npm-debug.log* | npm-debug.log* | ||||||
|   | |||||||
| @@ -45,6 +45,7 @@ | |||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@types/glob": "^5.0.30", |     "@types/glob": "^5.0.30", | ||||||
|     "@types/lodash": "^4.14.41", |     "@types/lodash": "^4.14.41", | ||||||
|  |     "cheerio": "~0.22.0", | ||||||
|     "cli": "^1.0.1", |     "cli": "^1.0.1", | ||||||
|     "fs": "0.0.1-security", |     "fs": "0.0.1-security", | ||||||
|     "glob": "^7.1.1", |     "glob": "^7.1.1", | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| import { Extractor } from './extractor'; | import { Extractor } from './extractor'; | ||||||
| import { JsonSerializer } from './serializers/json.serializer'; | import { JsonSerializer } from './serializers/json.serializer'; | ||||||
| import { PotSerializer } from './serializers/pot.serializer'; |  | ||||||
|  |  | ||||||
| const dir = '/path/to/extract/strings/from'; | const dir = '/path/to/extract/strings/from'; | ||||||
| const dest = '/path/to/save/template/to/template.pot'; | const dest = '/path/to/save/template/to/template.pot'; | ||||||
|   | |||||||
| @@ -1,23 +1,20 @@ | |||||||
| import { ParserInterface } from './parsers/parser.interface'; | import { ParserInterface } from './parsers/parser.interface'; | ||||||
| import { HtmlParser } from './parsers/html.parser'; | import { PipeParser } from './parsers/pipe.parser'; | ||||||
| import { TypescriptParser } from './parsers/typescript.parser'; | import { DirectiveParser } from "./parsers/directive.parser"; | ||||||
|  | import { ServiceParser } from './parsers/service.parser'; | ||||||
| import { SerializerInterface } from './serializers/serializer.interface'; | import { SerializerInterface } from './serializers/serializer.interface'; | ||||||
| import { PotSerializer } from './serializers/pot.serializer'; |  | ||||||
|  |  | ||||||
| import * as lodash from 'lodash'; | import * as lodash from 'lodash'; | ||||||
| import * as glob from 'glob'; | import * as glob from 'glob'; | ||||||
| import * as fs from 'fs'; | import * as fs from 'fs'; | ||||||
|  |  | ||||||
| export interface TypeParserMap { |  | ||||||
| 	[ext: string]: ParserInterface |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export class Extractor { | export class Extractor { | ||||||
|  |  | ||||||
| 	public parsers: TypeParserMap = { | 	public parsers: ParserInterface[] = [ | ||||||
| 		html: new HtmlParser(), | 		new PipeParser(), | ||||||
| 		ts: new TypescriptParser() | 		new ServiceParser(), | ||||||
| 	}; | 		new DirectiveParser() | ||||||
|  | 	]; | ||||||
|  |  | ||||||
| 	public globPatterns: string[] = [ | 	public globPatterns: string[] = [ | ||||||
| 		'/**/*.ts', | 		'/**/*.ts', | ||||||
| @@ -67,15 +64,14 @@ export class Extractor { | |||||||
| 	 * Extract messages from file using specialized parser | 	 * Extract messages from file using specialized parser | ||||||
| 	 */ | 	 */ | ||||||
| 	protected _extractMessages(filePath: string): string[] { | 	protected _extractMessages(filePath: string): string[] { | ||||||
| 		const ext: string = filePath.split('.').pop(); | 		let results = []; | ||||||
| 		if (!this.parsers.hasOwnProperty(ext)) { |  | ||||||
| 			return []; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		const contents: string = fs.readFileSync(filePath, 'utf-8'); | 		const contents: string = fs.readFileSync(filePath, 'utf-8'); | ||||||
| 		const parser: ParserInterface = this.parsers[ext]; | 		this.parsers.forEach((parser: ParserInterface) => { | ||||||
|  | 			results = results.concat(parser.process(contents)); | ||||||
|  | 		}); | ||||||
|  |  | ||||||
| 		return parser.process(contents); | 		return results; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
							
								
								
									
										66
									
								
								src/parsers/directive.parser.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/parsers/directive.parser.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  | import {ParserInterface} from './parser.interface'; | ||||||
|  | import * as $ from 'cheerio'; | ||||||
|  |  | ||||||
|  | export class DirectiveParser implements ParserInterface { | ||||||
|  |  | ||||||
|  |     public patterns = { | ||||||
|  |         template: `template:\\s?(("|'|\`)(.|[\\r\\n])+?[^\\\\]\\2)` | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     protected _parseTemplate(content) { | ||||||
|  |         let results: string[] = [], | ||||||
|  |             template = content.trim() | ||||||
|  |             // hack for cheerio that doesn't support wrapped attributes | ||||||
|  |                 .replace('[translate]=', '__translate__='); | ||||||
|  |  | ||||||
|  |         $(template).find('[translate],[__translate__]').contents().filter(function() { | ||||||
|  |             return this.nodeType === 3; // node type 3 = text node | ||||||
|  |         }).each(function() { | ||||||
|  |             let key, | ||||||
|  |                 $this = $(this), | ||||||
|  |                 element = $(this).parent(), | ||||||
|  |                 wrappedAttr = element.attr('__translate__'), // previously [translate]= | ||||||
|  |                 attr = element.attr('translate'); // translate= | ||||||
|  |  | ||||||
|  |             // only support string values for now | ||||||
|  |             if(wrappedAttr && wrappedAttr.match(/^['"].*['"]$/)) { | ||||||
|  |                 key = wrappedAttr.substr(1, wrappedAttr.length - 2); | ||||||
|  |             } else if(attr) { | ||||||
|  |                 key = attr; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(!key) { | ||||||
|  |                 key = $this.text().replace(/\\n/gi, '').trim(); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(key) { | ||||||
|  |                 results.push(key); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         return results; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public process(contents: string): string[] { | ||||||
|  |         const regExp = new RegExp(this.patterns.template, 'gi'); | ||||||
|  |  | ||||||
|  |         let results: string[] = [], | ||||||
|  |             hasTemplate = false, | ||||||
|  |             matches; | ||||||
|  |  | ||||||
|  |         while(matches = regExp.exec(contents)) { | ||||||
|  |             let content = matches[1] | ||||||
|  |                 .substr(1, matches[1].length - 2); | ||||||
|  |  | ||||||
|  |             hasTemplate = true; | ||||||
|  |             results = results.concat(this._parseTemplate(content)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!hasTemplate) { | ||||||
|  |             this._parseTemplate(contents); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return results; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,11 +1,10 @@ | |||||||
| import { ParserInterface } from './parser.interface'; | import { ParserInterface } from './parser.interface'; | ||||||
| 
 | 
 | ||||||
| export class HtmlParser implements ParserInterface { | export class PipeParser implements ParserInterface { | ||||||
| 
 | 
 | ||||||
| 	public patterns = { | 	public patterns = { | ||||||
| 		PipeSingleQuote: '\'((?:\\\\.|[^\'\\\\])*)\'\\s*\\|\\s*translate(:.*?)?', | 		pipe: `(['"\`])([^\\1\\r\\n]*)\\1\\s+\\|\\s*translate(:.*?)?` | ||||||
| 		PipeDoubleQuote: '"((?:\\\\.|[^"\\\\])*)"\\s*\\|\\s*translate(:.*?)?' | 	}; | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	public process(contents: string): string[] { | 	public process(contents: string): string[] { | ||||||
| 		let results: string[] = []; | 		let results: string[] = []; | ||||||
| @@ -15,7 +14,7 @@ export class HtmlParser implements ParserInterface { | |||||||
| 
 | 
 | ||||||
| 			let matches; | 			let matches; | ||||||
| 			while (matches = regExp.exec(contents)) { | 			while (matches = regExp.exec(contents)) { | ||||||
| 				results.push(matches[1]); | 				results.push(matches[2]); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @@ -1,11 +1,10 @@ | |||||||
| import { ParserInterface } from './parser.interface'; | import { ParserInterface } from './parser.interface'; | ||||||
| 
 | 
 | ||||||
| export class TypescriptParser implements ParserInterface { | export class ServiceParser implements ParserInterface { | ||||||
| 
 | 
 | ||||||
| 	public patterns = { | 	public patterns = { | ||||||
| 		TranslateServiceMethodsSingleQuote: '{{TRANSLATE_SERVICE}}\.(?:get|instant)\\s*\\\(\\s*\'((?:\\\\.|[^\'\\\\])*)\\s*\'', | 		translateServiceMethods: `{{TRANSLATE_SERVICE}}\.(?:get|instant)\\s*\\\(\\s*(['"\`])([^\\1\\r\\n]+)\\1`, | ||||||
| 		TranslateServiceMethodsDoubleQuote: '{{TRANSLATE_SERVICE}}\.(?:get|instant)\\s*\\\(\\s*"((?:\\\\.|[^"\\\\])*)\\s*"', | 	}; | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	public process(contents: string): string[] { | 	public process(contents: string): string[] { | ||||||
| 		let results: string[] = []; | 		let results: string[] = []; | ||||||
| @@ -22,7 +21,7 @@ export class TypescriptParser implements ParserInterface { | |||||||
| 
 | 
 | ||||||
| 			let matches; | 			let matches; | ||||||
| 			while (matches = regExp.exec(contents)) { | 			while (matches = regExp.exec(contents)) { | ||||||
| 				results.push(matches[1]); | 				results.push(matches[2]); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @@ -49,7 +48,7 @@ export class TypescriptParser implements ParserInterface { | |||||||
| 	 * Extract name of TranslateService variable for use in patterns | 	 * Extract name of TranslateService variable for use in patterns | ||||||
| 	 */ | 	 */ | ||||||
| 	protected _extractTranslateServiceVar(contents: string): string { | 	protected _extractTranslateServiceVar(contents: string): string { | ||||||
| 		const matches = contents.match(/([a-z0-9_]+)\s*:\s*TranslateService/i) | 		const matches = contents.match(/([a-z0-9_]+)\s*:\s*TranslateService/i); | ||||||
| 		if (matches === null) { | 		if (matches === null) { | ||||||
| 			return ''; | 			return ''; | ||||||
| 		} | 		} | ||||||
		Reference in New Issue
	
	Block a user