Adding a directive parser, and refactoring code a bit
This commit is contained in:
parent
7d8ed8400c
commit
24214729c1
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*
|
||||||
|
@ -37,6 +37,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 '';
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user