Skip to content

Commit

Permalink
re-add --marker option
Browse files Browse the repository at this point in the history
    -m or --marker is an old option that was in
    biesbjerg/ngx-translate-extract

    it was removed and replaced by the ngx-extract-translate-marker
    mechanism but this new mechanism does not allow to easily
    customize what the marker function does
    (some users have use cases where this is not a no-op)
  • Loading branch information
tmijieux committed Jan 27, 2023
1 parent a32b817 commit f8d1279
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { PipeParser } from '../parsers/pipe.parser.js';
import { DirectiveParser } from '../parsers/directive.parser.js';
import { ServiceParser } from '../parsers/service.parser.js';
import { MarkerParser } from '../parsers/marker.parser.js';
import { FunctionParser } from '../parsers/function.parser.js';
import { PostProcessorInterface } from '../post-processors/post-processor.interface.js';
import { SortByKeyPostProcessor } from '../post-processors/sort-by-key.post-processor.js';
import { KeyAsDefaultValuePostProcessor } from '../post-processors/key-as-default-value.post-processor.js';
Expand Down Expand Up @@ -79,6 +80,12 @@ export const cli: any = y // temporary any
describe: 'Remove obsolete strings after merge',
type: 'boolean'
})
.option('marker', {
alias: 'm',
describe: 'Name of a custom marker function for extracting strings',
type: 'string',
default: undefined
})
.option('key-as-default-value', {
alias: 'k',
describe: 'Use key as default value',
Expand Down Expand Up @@ -115,7 +122,12 @@ const extractTask = new ExtractTask(cli.input, cli.output, {
});

// Parsers
const parsers: ParserInterface[] = [new PipeParser(), new DirectiveParser(), new ServiceParser(), new MarkerParser()];
const parsers: ParserInterface[] = [new PipeParser(), new DirectiveParser(), new ServiceParser()];
if (cli.marker) {
parsers.push(new FunctionParser(cli.marker))
} else {
parsers.push(new MarkerParser())
}
extractTask.setParsers(parsers);

// Post processors
Expand Down
33 changes: 33 additions & 0 deletions src/parsers/function.parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { tsquery } from '@phenomnomnominal/tsquery';

import { ParserInterface } from './parser.interface.js';
import { TranslationCollection } from '../utils/translation.collection.js';
import { getStringsFromExpression, findSimpleCallExpressions } from '../utils/ast-helpers.js';
import pkg from 'typescript';
const { isIdentifier } = pkg;

export class FunctionParser implements ParserInterface {
constructor(private fnName: string) {}

public extract(source: string, filePath: string): TranslationCollection | null {
const sourceFile = tsquery.ast(source, filePath);

let collection: TranslationCollection = new TranslationCollection();

const callExpressions = findSimpleCallExpressions(sourceFile, this.fnName);
callExpressions.forEach((callExpression) => {
if (!isIdentifier(callExpression.expression)
|| callExpression.expression.escapedText != this.fnName) {
return
}

const [firstArg] = callExpression.arguments;
if (!firstArg) {
return;
}
const strings = getStringsFromExpression(firstArg);
collection = collection.addKeys(strings);
});
return collection;
}
}
8 changes: 8 additions & 0 deletions src/utils/ast-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ export function findFunctionCallExpressions(node: Node, fnName: string | string[
return tsquery<CallExpression>(node, query);
}

export function findSimpleCallExpressions(node: Node, fnName: string) {
if (Array.isArray(fnName)) {
fnName = fnName.join('|');
}
const query = `CallExpression:has(Identifier[name="${fnName}"])`;
return tsquery<CallExpression>(node, query);
}

export function findPropertyCallExpressions(node: Node, prop: string, fnName: string | string[]): CallExpression[] {
if (Array.isArray(fnName)) {
fnName = fnName.join('|');
Expand Down
61 changes: 61 additions & 0 deletions tests/parsers/function.parser.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { expect } from 'chai';

import { FunctionParser } from '../../src/parsers/function.parser.js';

describe('FunctionParser', () => {
const componentFilename: string = 'test.component.ts';

let parser: FunctionParser;

beforeEach(() => {
parser = new FunctionParser('MK');
});

it('should extract strings using marker function', () => {
const contents = `
MK('Hello world');
MK(['I', 'am', 'extracted']);
otherFunction('But I am not');
MK(message || 'binary expression');
MK(message ? message : 'conditional operator');
MK('FOO.bar');
`;
const keys = parser.extract(contents, componentFilename).keys();
expect(keys).to.deep.equal(['Hello world', 'I', 'am', 'extracted', 'binary expression', 'conditional operator', 'FOO.bar']);
});

it('should extract split strings', () => {
const contents = `
MK('Hello ' + 'world');
MK('This is a ' + 'very ' + 'very ' + 'very ' + 'very ' + 'long line.');
MK('Mix ' + \`of \` + 'different ' + \`types\`);
`;
const keys = parser.extract(contents, componentFilename).keys();
expect(keys).to.deep.equal(['Hello world', 'This is a very very very very long line.', 'Mix of different types']);
});

it('should extract split strings while keeping html tags', () => {
const contents = `
MK('Hello ' + 'world');
MK('This <em>is</em> a ' + 'very ' + 'very ' + 'very ' + 'very ' + 'long line.');
MK('Mix ' + \`of \` + 'different ' + \`types\`);
`;
const keys = parser.extract(contents, componentFilename).keys();
expect(keys).to.deep.equal(['Hello world', 'This <em>is</em> a very very very very long line.', 'Mix of different types']);
});

it('should extract the strings', () => {
const contents = `
export class AppModule {
constructor() {
MK('DYNAMIC_TRAD.val1');
MK('DYNAMIC_TRAD.val2');
}
}
`;
const keys = parser.extract(contents, componentFilename).keys();
expect(keys).to.deep.equal(['DYNAMIC_TRAD.val1', 'DYNAMIC_TRAD.val2']);
});

});

0 comments on commit f8d1279

Please sign in to comment.