Skip to content

Commit

Permalink
Add extractor to parse HTML from JS strings (#64)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Jefferson Carvalho <[email protected]>
  • Loading branch information
JeffersonCarvalh0 and Jefferson Carvalho committed Jul 10, 2023
1 parent d01c3bc commit 4563ac0
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 2 deletions.
22 changes: 22 additions & 0 deletions src/js/extractors/factories/htmlTemplate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as ts from 'typescript';

import { IJsExtractorFunction } from '../../../js/parser';
import { Validate } from '../../../utils/validate';
import { HtmlParser } from '../../../html/parser';

export function htmlTemplateExtractor(htmlParser: HtmlParser): IJsExtractorFunction {
Validate.required.argument({ htmlParser });

return (node: ts.Node, sourceFile: ts.SourceFile, _, lineNumberStart = 1) => {
if (ts.isStringLiteralLike(node)) {
const source = node.getText(sourceFile);
const location = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));

htmlParser.parseString(
source,
sourceFile.fileName,
{ lineNumberStart: lineNumberStart + location.line }
);
}
};
}
2 changes: 2 additions & 0 deletions src/js/extractors/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { callExpressionExtractor } from './factories/callExpression';
import { htmlTemplateExtractor } from './factories/htmlTemplate';

export abstract class JsExtractors {
public static callExpression: typeof callExpressionExtractor = callExpressionExtractor;
public static htmlTemplate: typeof htmlTemplateExtractor = htmlTemplateExtractor;
}
4 changes: 2 additions & 2 deletions src/js/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as ts from 'typescript';
import { Parser, IAddMessageCallback, IParseOptions } from '../parser';
import { IMessage } from '../builder';

export type IJsExtractorFunction = (node: ts.Node, sourceFile: ts.SourceFile, addMessage: IAddMessageCallback) => void;
export type IJsExtractorFunction = (node: ts.Node, sourceFile: ts.SourceFile, addMessage: IAddMessageCallback, lineNumberStart: number) => void;

export interface IJsParseOptions extends IParseOptions {
scriptKind?: ts.ScriptKind;
Expand All @@ -24,7 +24,7 @@ export class JsParser extends Parser<IJsExtractorFunction, IJsParseOptions> {
});

for (let extractor of this.extractors) {
extractor(node, sourceFile, addMessageCallback);
extractor(node, sourceFile, addMessageCallback, lineNumberStart);
}

ts.forEachChild(node, n => {
Expand Down
148 changes: 148 additions & 0 deletions tests/js/extractors/factories/htmlTemplate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { htmlTemplateExtractor } from '../../../../src/js/extractors/factories/htmlTemplate'
import { HtmlExtractors } from '../../../../src/html/extractors';
import { JsParser } from '../../../../src/js/parser';
import { HtmlParser } from '../../../../src/html/parser';
import { CatalogBuilder, IMessage } from '../../../../src/builder';

describe('JS: HTML template extractor', () => {
describe('calling html parser ', () => {
let builder: CatalogBuilder;
let messages: IMessage[]
let jsParser: JsParser;
let htmlParser: HtmlParser;

beforeEach(() => {
messages = [];

builder = <any>{
addMessage: jest.fn((message: IMessage) => {
messages.push(message);
})
};

htmlParser = new HtmlParser(builder, [
HtmlExtractors.elementContent('translate')
]);

jsParser = new JsParser(builder, [
htmlTemplateExtractor(htmlParser)
]);
});

test('single line (regular string)', () => {
jsParser.parseString('let itBe = "<div> <translate> test </translate> </div>"');
expect(messages).toEqual([
{
text: 'test'
}
])
});

test('single line (template string)', () => {
jsParser.parseString('let itBe = "<div> <translate> test </translate> </div>"');
expect(messages).toEqual([
{
text: 'test'
}
])
});

test('with lineNumberStart option (regular string)', () => {
jsParser.parseString(
'let itBe = "<div> <translate> test </translate> </div>"',
'test',
{ lineNumberStart: 10 }
);

expect(messages).toEqual([
{
text: 'test',
references: ['test:10'],
},
])
})

test('with lineNumberStart option (template string)', () => {
jsParser.parseString(
'let itBe = "<div> <translate> test </translate> </div>"',
'test',
{ lineNumberStart: 10 }
);

expect(messages).toEqual([
{
text: 'test',
references: ['test:10'],
},
])
})

test('HTML inside a template literal with the correct line numbers', () => {
jsParser.parseString(`
let tuce = \`
<div>
<translate> First level </translate>
<div>
<translate> Second level </translate>
<div> <translate> Third level </translate> </div>
</div>
</div>\`
`, 'test')

expect(messages).toEqual([
{
text: 'First level',
references: ['test:10'],
},
{
text: 'Second level',
references: ['test:12'],
},
{
text: 'Third level',
references: ['test:13'],
},
])
})

test('HTML inside a template literal with correct line numbers and with lineNumberStart', () => {
jsParser.parseString(`
let tuce = \`
<div>
<translate> First level </translate>
<div>
<translate> Second level </translate>
<div> <translate> Third level </translate> </div>
</div>
</div>\`
`, 'test', { lineNumberStart: 10 })

expect(messages).toEqual([
{
text: 'First level',
references: ['test:19'],
},
{
text: 'Second level',
references: ['test:21'],
},
{
text: 'Third level',
references: ['test:22'],
},
])
})
})
})

0 comments on commit 4563ac0

Please sign in to comment.