From 3ddb57a0a9887f13cb89b02a9f1baaee5700f87f Mon Sep 17 00:00:00 2001 From: Panagiotis Bakatselos Date: Mon, 18 Nov 2024 08:26:07 +0100 Subject: [PATCH] feat: Add support for the ngx-translate `_()` marker function (#57) Closes: #56 --- src/parsers/marker.parser.ts | 15 +++++++- tests/parsers/marker.parser.spec.ts | 58 +++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/src/parsers/marker.parser.ts b/src/parsers/marker.parser.ts index 64dccfe..f740ed1 100644 --- a/src/parsers/marker.parser.ts +++ b/src/parsers/marker.parser.ts @@ -1,15 +1,18 @@ import { ParserInterface } from './parser.interface.js'; import { TranslationCollection } from '../utils/translation.collection.js'; import { getNamedImportAlias, findFunctionCallExpressions, getStringsFromExpression, getAST } from '../utils/ast-helpers.js'; +import { SourceFile } from 'typescript'; -const MARKER_MODULE_NAME = 'ngx-translate-extract-marker'; +const MARKER_MODULE_NAME = new RegExp('ngx-translate-extract-marker'); const MARKER_IMPORT_NAME = 'marker'; +const NGX_TRANSLATE_MARKER_MODULE_NAME = '@ngx-translate/core'; +const NGX_TRANSLATE_MARKER_IMPORT_NAME = '_'; export class MarkerParser implements ParserInterface { public extract(source: string, filePath: string): TranslationCollection | null { const sourceFile = getAST(source, filePath); - const markerImportName = getNamedImportAlias(sourceFile, MARKER_IMPORT_NAME, new RegExp(MARKER_MODULE_NAME)); + const markerImportName = this.getMarkerImportNameFromSource(sourceFile); if (!markerImportName) { return null; } @@ -27,4 +30,12 @@ export class MarkerParser implements ParserInterface { }); return collection; } + + private getMarkerImportNameFromSource(sourceFile: SourceFile): string { + const markerImportName = + getNamedImportAlias(sourceFile, MARKER_IMPORT_NAME, MARKER_MODULE_NAME) || + getNamedImportAlias(sourceFile, NGX_TRANSLATE_MARKER_IMPORT_NAME, NGX_TRANSLATE_MARKER_MODULE_NAME); + + return markerImportName ?? ''; + } } diff --git a/tests/parsers/marker.parser.spec.ts b/tests/parsers/marker.parser.spec.ts index ec20cfb..26b3b35 100644 --- a/tests/parsers/marker.parser.spec.ts +++ b/tests/parsers/marker.parser.spec.ts @@ -75,16 +75,68 @@ describe('MarkerParser', () => { it('should not break after bracket syntax casting', () => { const contents = ` import { marker } from '@colsen1991/ngx-translate-extract-marker'; - + marker('hello'); - const input: unknown = 'hello'; + const input: unknown = 'hello'; const myNiceVar1 = input as string; marker('hello.after.as.syntax'); - + const myNiceVar2 = input; marker('hello.after.bracket.syntax'); `; const keys = parser.extract(contents, componentFilename).keys(); expect(keys).to.deep.equal(['hello', 'hello.after.as.syntax', 'hello.after.bracket.syntax']); }); + + describe('marker from @ngx-translate/core', () => { + it('should extract strings using marker (_) function', () => { + const contents = ` + import {_} from '@ngx-translate/core'; + _('Hello world'); + _(['I', 'am', 'extracted']); + otherFunction('But I am not'); + _(message || 'binary expression'); + _(message ? message : 'conditional operator'); + _('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 strings using an alias function', () => { + const contents = ` + import {_ as marker} from '@ngx-translate/core'; + marker('Hello world'); + marker(['I', 'am', 'extracted']); + otherFunction('But I am not'); + marker(message || 'binary expression'); + marker(message ? message : 'conditional operator'); + marker('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 = ` + import {_} from '@ngx-translate/core'; + _('Hello ' + 'world'); + _('This is a ' + 'very ' + 'very ' + 'very ' + 'very ' + 'long line.'); + _('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 = ` + import {_} from '@ngx-translate/core'; + _('Hello ' + 'world'); + _('This is a ' + 'very ' + 'very ' + 'very ' + 'very ' + 'long line.'); + _('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']); + }); + }) });