diff --git a/src/message/context.ts b/src/message/context.ts index 2262e34dc..508a68aa9 100644 --- a/src/message/context.ts +++ b/src/message/context.ts @@ -41,6 +41,19 @@ export type MessageContextOptions = { processor?: MessageProcessor } +export const enum HelperNameMap { + LIST = 'list', + NAMED = 'named', + PLURAL_INDEX = 'pluralIndex', + PLURAL_RULE = 'pluralRule', + ORG_PLURAL_RULE = 'orgPluralRule', + MODIFIER = 'modifier', + MESSAGE = 'message', + TYPE = 'type', + INTERPOLATE = 'interpolate', + NORMALIZE = 'normalize' +} + export type MessageContext = { list: (index: number) => unknown named: (key: string) => unknown @@ -166,15 +179,15 @@ export function createMessageContext( : DEFAULT_INTERPOLATE return { - list, - named, - pluralIndex, - pluralRule, - orgPluralRule, - modifier, - message, - type, - interpolate, - normalize + [HelperNameMap.LIST]: list, + [HelperNameMap.NAMED]: named, + [HelperNameMap.PLURAL_INDEX]: pluralIndex, + [HelperNameMap.PLURAL_RULE]: pluralRule, + [HelperNameMap.ORG_PLURAL_RULE]: orgPluralRule, + [HelperNameMap.MODIFIER]: modifier, + [HelperNameMap.MESSAGE]: message, + [HelperNameMap.TYPE]: type, + [HelperNameMap.INTERPOLATE]: interpolate, + [HelperNameMap.NORMALIZE]: normalize } } diff --git a/src/message/generator.ts b/src/message/generator.ts index 9cb7019a9..15a29c6f7 100644 --- a/src/message/generator.ts +++ b/src/message/generator.ts @@ -13,8 +13,8 @@ import { LiteralNode } from './parser' import { CodeGenOptions } from './options' - -export const INTERPOLATE_CODE = `const interpolate = val => { return val == null ? "" : Array.isArray(val) || ((Object.prototype.toString.call(val) === "[object Object]") && val.toString === Object.prototype.toString) ? JSON.stringify(val, null, 2) : String(val) }` +import { HelperNameMap } from './context' +import { isString } from '../utils' type CodeGenContext = { source?: string @@ -32,6 +32,7 @@ type CodeGenerator = Readonly<{ indent: () => void deindent: (withoutNewLine?: boolean) => void newline: () => void + helper: (key: string) => string }> function createCodeGenerator(source?: string): CodeGenerator { @@ -67,26 +68,30 @@ function createCodeGenerator(source?: string): CodeGenerator { _newline(_context.indentLevel) } + const helper = (key: string): string => `_${key}` + return { context, push, indent, deindent, - newline + newline, + helper } } function generateLinkedNode(generator: CodeGenerator, node: LinkedNode): void { + const { helper } = generator if (node.modifier) { - generator.push('ctx.modifier(') + generator.push(`${helper(HelperNameMap.MODIFIER)}(`) generateNode(generator, node.modifier) generator.push(')(') } - generator.push('ctx.message(') + generator.push(`${helper(HelperNameMap.MESSAGE)}(`) generateNode(generator, node.key) generator.push(')(ctx)') if (node.modifier) { - generator.push(', ctx.type)') + generator.push(`, ${helper(HelperNameMap.TYPE)})`) } } @@ -94,7 +99,8 @@ function generateMessageNode( generator: CodeGenerator, node: MessageNode ): void { - generator.push('ctx.normalize([') + const { helper } = generator + generator.push(`${helper(HelperNameMap.NORMALIZE)}([`) generator.indent() const length = node.items.length for (let i = 0; i < length; i++) { @@ -109,6 +115,7 @@ function generateMessageNode( } function generatePluralNode(generator: CodeGenerator, node: PluralNode): void { + const { helper } = generator if (node.cases.length > 1) { generator.push('[') generator.indent() @@ -122,7 +129,9 @@ function generatePluralNode(generator: CodeGenerator, node: PluralNode): void { } generator.deindent() generator.push( - `][ctx.pluralRule(ctx.pluralIndex, ${length}, ctx.orgPluralRule)]` + `][${helper(HelperNameMap.PLURAL_RULE)}(${helper( + HelperNameMap.PLURAL_INDEX + )}, ${length}, ${helper(HelperNameMap.ORG_PLURAL_RULE)})]` ) } } @@ -136,6 +145,7 @@ function generateResource(generator: CodeGenerator, node: ResourceNode): void { } function generateNode(generator: CodeGenerator, node: Node): void { + const { helper } = generator switch (node.type) { case NodeTypes.Resource: generateResource(generator, node as ResourceNode) @@ -156,11 +166,17 @@ function generateNode(generator: CodeGenerator, node: Node): void { generator.push(JSON.stringify((node as LinkedKeyNode).value)) break case NodeTypes.List: - generator.push(`ctx.interpolate(ctx.list(${(node as ListNode).index}))`) + generator.push( + `${helper(HelperNameMap.INTERPOLATE)}(${helper(HelperNameMap.LIST)}(${ + (node as ListNode).index + }))` + ) break case NodeTypes.Named: generator.push( - `ctx.interpolate(ctx.named(${JSON.stringify((node as NamedNode).key)}))` + `${helper(HelperNameMap.INTERPOLATE)}(${helper( + HelperNameMap.NAMED + )}(${JSON.stringify((node as NamedNode).key)}))` ) break case NodeTypes.Literal: @@ -181,12 +197,24 @@ export const generate = ( ast: ResourceNode, options: CodeGenOptions = {} // eslint-disable-line ): string => { + const mode = isString(options.mode) ? options.mode : 'normal' + const helpers = ast.helpers || [] const generator = createCodeGenerator(ast.loc && ast.loc.source) - generator.push(`function __msg__ (ctx) {`) + + generator.push(mode === 'normal' ? `function __msg__ (ctx) {` : `(ctx) => {`) generator.indent() + + if (helpers.length > 0) { + generator.push( + `const { ${helpers.map(s => `${s}: _${s}`).join(', ')} } = ctx` + ) + generator.newline() + } + generator.push(`return `) generateNode(generator, ast) generator.deindent() generator.push(`}`) + return generator.context().code } diff --git a/src/message/options.ts b/src/message/options.ts index ef8cf0025..b3936c4f8 100644 --- a/src/message/options.ts +++ b/src/message/options.ts @@ -28,8 +28,7 @@ export type TransformOptions = { } export type CodeGenOptions = { - // TODO: other options - // onError?: CompileErrorHandler + mode?: 'normal' | 'arrow' // default normal onError?: CompileErrorHandler } diff --git a/src/message/parser.ts b/src/message/parser.ts index d7790868b..3b163f7f1 100644 --- a/src/message/parser.ts +++ b/src/message/parser.ts @@ -29,7 +29,7 @@ export interface Node { export interface ResourceNode extends Node { type: NodeTypes.Resource body: MessageNode | PluralNode - needInterpolate?: boolean + helpers?: string[] } export interface PluralNode extends Node { diff --git a/src/message/transformer.ts b/src/message/transformer.ts index ee1f8f4cc..f4e38ba46 100644 --- a/src/message/transformer.ts +++ b/src/message/transformer.ts @@ -7,6 +7,7 @@ import { LinkedNode } from './parser' import { TransformOptions } from './options' +import { HelperNameMap } from './context' // TODO: if we offer custom transform for uses, should be defined TransformOptions type to here // ex. @@ -15,11 +16,12 @@ import { TransformOptions } from './options' type TransformContext = { ast: ResourceNode - needInterpolate: boolean + helpers: Set } type Transformer = Readonly<{ context: () => TransformContext + helper: (name: string) => string }> function createTransformer( @@ -27,12 +29,16 @@ function createTransformer( ): Transformer { const _context = { ast, - needInterpolate: false + helpers: new Set() } as TransformContext const context = (): TransformContext => _context + const helper = (name: string): string => { + _context.helpers.add(name) + return name + } - return { context } + return { context, helper } } function traverseNodes(nodes: Node[], transformer: Transformer): void { @@ -42,25 +48,35 @@ function traverseNodes(nodes: Node[], transformer: Transformer): void { } function traverseNode(node: Node, transformer: Transformer): void { - const context = transformer.context() - // TODO: if we need pre-hook of transform, should be implemeted to here switch (node.type) { case NodeTypes.Plural: traverseNodes((node as PluralNode).cases, transformer) + transformer.helper(HelperNameMap.PLURAL_INDEX) + transformer.helper(HelperNameMap.PLURAL_RULE) + transformer.helper(HelperNameMap.ORG_PLURAL_RULE) break case NodeTypes.Message: traverseNodes((node as MessageNode).items, transformer) break case NodeTypes.Linked: const linked = node as LinkedNode - linked.modifier && traverseNode(linked.modifier, transformer) + if (linked.modifier) { + traverseNode(linked.modifier, transformer) + transformer.helper(HelperNameMap.MODIFIER) + transformer.helper(HelperNameMap.TYPE) + } traverseNode(linked.key, transformer) + transformer.helper(HelperNameMap.MESSAGE) break case NodeTypes.List: + transformer.helper(HelperNameMap.INTERPOLATE) + transformer.helper(HelperNameMap.LIST) + break case NodeTypes.Named: - context.needInterpolate = true + transformer.helper(HelperNameMap.INTERPOLATE) + transformer.helper(HelperNameMap.NAMED) break default: // TODO: @@ -76,9 +92,12 @@ export function transform( options: TransformOptions = {} // eslint-disable-line ): void { const transformer = createTransformer(ast) + transformer.helper(HelperNameMap.NORMALIZE) + // traverse ast.body && traverseNode(ast.body, transformer) + // set meta information const context = transformer.context() - ast.needInterpolate = context.needInterpolate + ast.helpers = [...context.helpers] } diff --git a/test/message/__snapshots__/compiler.test.ts.snap b/test/message/__snapshots__/compiler.test.ts.snap index eeb23447e..fffce2f35 100644 --- a/test/message/__snapshots__/compiler.test.ts.snap +++ b/test/message/__snapshots__/compiler.test.ts.snap @@ -2,31 +2,33 @@ exports[`@.caml:{'no apples'} | {0} apple | {n} apples: code 1`] = ` "function __msg__ (ctx) { + const { normalize: _normalize, modifier: _modifier, type: _type, message: _message, interpolate: _interpolate, list: _list, named: _named, pluralIndex: _pluralIndex, pluralRule: _pluralRule, orgPluralRule: _orgPluralRule } = ctx return [ - ctx.normalize([ - ctx.modifier(\\"caml\\")(ctx.message(\\"no apples\\")(ctx), ctx.type) - ]), ctx.normalize([ - ctx.interpolate(ctx.list(0)), \\" apple\\" - ]), ctx.normalize([ - ctx.interpolate(ctx.named(\\"n\\")), \\" apples\\" + _normalize([ + _modifier(\\"caml\\")(_message(\\"no apples\\")(ctx), _type) + ]), _normalize([ + _interpolate(_list(0)), \\" apple\\" + ]), _normalize([ + _interpolate(_named(\\"n\\")), \\" apples\\" ]) - ][ctx.pluralRule(ctx.pluralIndex, 3, ctx.orgPluralRule)] + ][_pluralRule(_pluralIndex, 3, _orgPluralRule)] }" `; exports[`edge cases | | | : code 1`] = ` "function __msg__ (ctx) { + const { normalize: _normalize, pluralIndex: _pluralIndex, pluralRule: _pluralRule, orgPluralRule: _orgPluralRule } = ctx return [ - ctx.normalize([ + _normalize([ - ]), ctx.normalize([ + ]), _normalize([ - ]), ctx.normalize([ + ]), _normalize([ - ]), ctx.normalize([ + ]), _normalize([ ]) - ][ctx.pluralRule(ctx.pluralIndex, 4, ctx.orgPluralRule)] + ][_pluralRule(_pluralIndex, 4, _orgPluralRule)] }" `; @@ -52,7 +54,8 @@ Object { exports[`warnHtmlMessage default: code 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"

hello

\\" ]) }" @@ -60,7 +63,8 @@ exports[`warnHtmlMessage default: code 1`] = ` exports[`warnHtmlMessage false: code 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"

hello

\\" ]) }" diff --git a/test/message/__snapshots__/generator.test.ts.snap b/test/message/__snapshots__/generator.test.ts.snap index 431c740a0..f9b7c647c 100644 --- a/test/message/__snapshots__/generator.test.ts.snap +++ b/test/message/__snapshots__/generator.test.ts.snap @@ -2,55 +2,62 @@ exports[`linked key: hi @:name ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ - \\"hi \\", ctx.message(\\"name\\")(ctx), \\" !\\" + const { normalize: _normalize, message: _message } = ctx + return _normalize([ + \\"hi \\", _message(\\"name\\")(ctx), \\" !\\" ]) }" `; exports[`linked list: hi @:{0} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ - \\"hi \\", ctx.message(ctx.interpolate(ctx.list(0)))(ctx), \\" !\\" + const { normalize: _normalize, interpolate: _interpolate, list: _list, message: _message } = ctx + return _normalize([ + \\"hi \\", _message(_interpolate(_list(0)))(ctx), \\" !\\" ]) }" `; exports[`linked modifier: hi @.upper:{'name'} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ - \\"hi \\", ctx.modifier(\\"upper\\")(ctx.message(\\"name\\")(ctx), ctx.type), \\" !\\" + const { normalize: _normalize, modifier: _modifier, type: _type, message: _message } = ctx + return _normalize([ + \\"hi \\", _modifier(\\"upper\\")(_message(\\"name\\")(ctx), _type), \\" !\\" ]) }" `; exports[`linked named: hi @:{name} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ - \\"hi \\", ctx.message(ctx.interpolate(ctx.named(\\"name\\")))(ctx), \\" !\\" + const { normalize: _normalize, interpolate: _interpolate, named: _named, message: _message } = ctx + return _normalize([ + \\"hi \\", _message(_interpolate(_named(\\"name\\")))(ctx), \\" !\\" ]) }" `; exports[`list basic: hi {0} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ - \\"hi \\", ctx.interpolate(ctx.list(0)), \\" !\\" + const { normalize: _normalize, interpolate: _interpolate, list: _list } = ctx + return _normalize([ + \\"hi \\", _interpolate(_list(0)), \\" !\\" ]) }" `; exports[`list multiple: {0} {1} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ - ctx.interpolate(ctx.list(0)), \\" \\", ctx.interpolate(ctx.list(1)), \\" !\\" + const { normalize: _normalize, interpolate: _interpolate, list: _list } = ctx + return _normalize([ + _interpolate(_list(0)), \\" \\", _interpolate(_list(1)), \\" !\\" ]) }" `; exports[`literal !#%^&*()-_+=[]:;?.<>"\`: hi {'!#%^&*()-_+=[]:;?.<>"\`'} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"hi \\", \\"!#%^&*()-_+=[]:;?.<>\\\\\\"\`\\", \\" !\\" ]) }" @@ -58,7 +65,8 @@ exports[`literal !#%^&*()-_+=[]:;?.<>"\`: hi {'!#%^&*()-_+=[]:;?.<>"\`'} ! 1`] = exports[`literal {}: {'{}'} 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"{}\\" ]) }" @@ -66,7 +74,8 @@ exports[`literal {}: {'{}'} 1`] = ` exports[`literal ascii: hi {'kazupon'} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"hi \\", \\"kazupon\\", \\" !\\" ]) }" @@ -74,7 +83,8 @@ exports[`literal ascii: hi {'kazupon'} ! 1`] = ` exports[`literal emoji: hi {'😺'} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"hi \\", \\"😺\\", \\" !\\" ]) }" @@ -82,7 +92,8 @@ exports[`literal emoji: hi {'😺'} ! 1`] = ` exports[`literal escaped single quote: hi {'\\''} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"hi \\", \\"'\\", \\" !\\" ]) }" @@ -90,7 +101,8 @@ exports[`literal escaped single quote: hi {'\\''} ! 1`] = ` exports[`literal escaped slash: hi {'\\\\'} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"hi \\", \\"\\\\\\\\\\", \\" !\\" ]) }" @@ -98,7 +110,8 @@ exports[`literal escaped slash: hi {'\\\\'} ! 1`] = ` exports[`literal escaped unicode 4 digits: hi {'\\\\u0041'} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"hi \\", \\"\\\\\\\\u0041\\", \\" !\\" ]) }" @@ -106,7 +119,8 @@ exports[`literal escaped unicode 4 digits: hi {'\\\\u0041'} ! 1`] = ` exports[`literal escaped unicode 6 digits: hi {'\\\\U01F602'} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"hi \\", \\"\\\\\\\\U01F602\\", \\" !\\" ]) }" @@ -114,7 +128,8 @@ exports[`literal escaped unicode 6 digits: hi {'\\\\U01F602'} ! 1`] = ` exports[`literal multibytes: hi {'かずぽん'} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"hi \\", \\"かずぽん\\", \\" !\\" ]) }" @@ -122,7 +137,8 @@ exports[`literal multibytes: hi {'かずぽん'} ! 1`] = ` exports[`literal unicode 4 digits: hi {'A'} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"hi \\", \\"A\\", \\" !\\" ]) }" @@ -130,59 +146,80 @@ exports[`literal unicode 4 digits: hi {'A'} ! 1`] = ` exports[`literal unicode 6 digits: hi {'U01F602'} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"hi \\", \\"U01F602\\", \\" !\\" ]) }" `; +exports[`mode arrow: @.caml:{'no apples'} | {0} apple | {n} apples 1`] = ` +"(ctx) => { + const { normalize: _normalize, modifier: _modifier, type: _type, message: _message, interpolate: _interpolate, list: _list, named: _named, pluralIndex: _pluralIndex, pluralRule: _pluralRule, orgPluralRule: _orgPluralRule } = ctx + return [ + _normalize([ + _modifier(\\"caml\\")(_message(\\"no apples\\")(ctx), _type) + ]), _normalize([ + _interpolate(_list(0)), \\" apple\\" + ]), _normalize([ + _interpolate(_named(\\"n\\")), \\" apples\\" + ]) + ][_pluralRule(_pluralIndex, 3, _orgPluralRule)] +}" +`; + exports[`named basic: hi {name} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ - \\"hi \\", ctx.interpolate(ctx.named(\\"name\\")), \\" !\\" + const { normalize: _normalize, interpolate: _interpolate, named: _named } = ctx + return _normalize([ + \\"hi \\", _interpolate(_named(\\"name\\")), \\" !\\" ]) }" `; exports[`named multiple: {greeting} {name} ! 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ - ctx.interpolate(ctx.named(\\"greeting\\")), \\" \\", ctx.interpolate(ctx.named(\\"name\\")), \\" !\\" + const { normalize: _normalize, interpolate: _interpolate, named: _named } = ctx + return _normalize([ + _interpolate(_named(\\"greeting\\")), \\" \\", _interpolate(_named(\\"name\\")), \\" !\\" ]) }" `; exports[`plural complex: @.caml:{'no apples'} | {0} apple | {n} apples 1`] = ` "function __msg__ (ctx) { + const { normalize: _normalize, modifier: _modifier, type: _type, message: _message, interpolate: _interpolate, list: _list, named: _named, pluralIndex: _pluralIndex, pluralRule: _pluralRule, orgPluralRule: _orgPluralRule } = ctx return [ - ctx.normalize([ - ctx.modifier(\\"caml\\")(ctx.message(\\"no apples\\")(ctx), ctx.type) - ]), ctx.normalize([ - ctx.interpolate(ctx.list(0)), \\" apple\\" - ]), ctx.normalize([ - ctx.interpolate(ctx.named(\\"n\\")), \\" apples\\" + _normalize([ + _modifier(\\"caml\\")(_message(\\"no apples\\")(ctx), _type) + ]), _normalize([ + _interpolate(_list(0)), \\" apple\\" + ]), _normalize([ + _interpolate(_named(\\"n\\")), \\" apples\\" ]) - ][ctx.pluralRule(ctx.pluralIndex, 3, ctx.orgPluralRule)] + ][_pluralRule(_pluralIndex, 3, _orgPluralRule)] }" `; exports[`plural simple: no apples | one apple | too much apples 1`] = ` "function __msg__ (ctx) { + const { normalize: _normalize, pluralIndex: _pluralIndex, pluralRule: _pluralRule, orgPluralRule: _orgPluralRule } = ctx return [ - ctx.normalize([ + _normalize([ \\"no apples\\" - ]), ctx.normalize([ + ]), _normalize([ \\"one apple\\" - ]), ctx.normalize([ + ]), _normalize([ \\"too much apples \\" ]) - ][ctx.pluralRule(ctx.pluralIndex, 3, ctx.orgPluralRule)] + ][_pluralRule(_pluralIndex, 3, _orgPluralRule)] }" `; exports[`text basic: hello world 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"hello world\\" ]) }" @@ -191,7 +228,8 @@ exports[`text basic: hello world 1`] = ` exports[`text multline: hello world 1`] = ` "function __msg__ (ctx) { - return ctx.normalize([ + const { normalize: _normalize } = ctx + return _normalize([ \\"hello\\\\n world\\" ]) }" diff --git a/test/message/__snapshots__/transformer.test.ts.snap b/test/message/__snapshots__/transformer.test.ts.snap index 088f5a045..f80be4411 100644 --- a/test/message/__snapshots__/transformer.test.ts.snap +++ b/test/message/__snapshots__/transformer.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`transform 1`] = ` +exports[`transform: ast 1`] = ` Object { "body": Object { "cases": Array [ @@ -204,6 +204,18 @@ Object { "type": 1, }, "end": 50, + "helpers": Array [ + "normalize", + "modifier", + "type", + "message", + "interpolate", + "list", + "named", + "pluralIndex", + "pluralRule", + "orgPluralRule", + ], "loc": Object { "end": Object { "column": 51, @@ -216,8 +228,22 @@ Object { "offset": 0, }, }, - "needInterpolate": true, "start": 0, "type": 0, } `; + +exports[`transform: helpers 1`] = ` +Array [ + "normalize", + "modifier", + "type", + "message", + "interpolate", + "list", + "named", + "pluralIndex", + "pluralRule", + "orgPluralRule", +] +`; diff --git a/test/message/generator.test.ts b/test/message/generator.test.ts index 8366df653..0e8b815e4 100644 --- a/test/message/generator.test.ts +++ b/test/message/generator.test.ts @@ -1,3 +1,5 @@ +/* eslint-disable no-irregular-whitespace */ + import { createParser } from '../../src/message/parser' import { transform } from '../../src/message/transformer' import { generate } from '../../src/message/generator' @@ -10,7 +12,7 @@ describe('text', () => { transform(ast) const code = generate(ast) expect(code).toMatchSnapshot(msg) - expect(code).toMatch(`return ctx.normalize([`) + expect(code).toMatch(`return _normalize([`) expect(code).toMatch(`"hello world"`) expect(code).toMatch(`])`) }) @@ -22,7 +24,7 @@ describe('text', () => { transform(ast) const code = generate(ast) expect(code).toMatchSnapshot(msg) - expect(code).toMatch(`return ctx.normalize([`) + expect(code).toMatch(`return _normalize([`) expect(code).toMatch(`"hello\\n world"`) expect(code).toMatch(`])`) }) @@ -36,8 +38,8 @@ describe('list', () => { transform(ast) const code = generate(ast) expect(code).toMatchSnapshot(msg) - expect(code).toMatch(`return ctx.normalize([`) - expect(code).toMatch(`"hi ", ctx.interpolate(ctx.list(0)), " !"`) + expect(code).toMatch(`return _normalize([`) + expect(code).toMatch(`"hi ", _interpolate(_list(0)), " !"`) expect(code).toMatch(`])`) }) @@ -48,9 +50,9 @@ describe('list', () => { transform(ast) const code = generate(ast) expect(code).toMatchSnapshot(msg) - expect(code).toMatch(`return ctx.normalize([`) + expect(code).toMatch(`return _normalize([`) expect(code).toMatch( - `ctx.interpolate(ctx.list(0)), " ", ctx.interpolate(ctx.list(1)), " !"` + `_interpolate(_list(0)), " ", _interpolate(_list(1)), " !"` ) expect(code).toMatch(`])`) }) @@ -64,8 +66,8 @@ describe('named', () => { transform(ast) const code = generate(ast) expect(code).toMatchSnapshot(msg) - expect(code).toMatch(`return ctx.normalize([`) - expect(code).toMatch(`"hi ", ctx.interpolate(ctx.named("name")), " !"`) + expect(code).toMatch(`return _normalize([`) + expect(code).toMatch(`"hi ", _interpolate(_named("name")), " !"`) expect(code).toMatch(`])`) }) @@ -76,9 +78,9 @@ describe('named', () => { transform(ast) const code = generate(ast) expect(code).toMatchSnapshot(msg) - expect(code).toMatch(`return ctx.normalize([`) + expect(code).toMatch(`return _normalize([`) expect(code).toMatch( - `ctx.interpolate(ctx.named("greeting")), " ", ctx.interpolate(ctx.named("name")), " !"` + `_interpolate(_named("greeting")), " ", _interpolate(_named("name")), " !"` ) expect(code).toMatch(`])`) }) @@ -193,8 +195,8 @@ describe('linked', () => { transform(ast) const code = generate(ast) expect(code).toMatchSnapshot(msg) - expect(code).toMatch(`return ctx.normalize([`) - expect(code).toMatch(`"hi ", ctx.message("name")(ctx), " !"`) + expect(code).toMatch(`return _normalize([`) + expect(code).toMatch(`"hi ", _message("name")(ctx), " !"`) expect(code).toMatch(`])`) }) @@ -205,10 +207,8 @@ describe('linked', () => { transform(ast) const code = generate(ast) expect(code).toMatchSnapshot(msg) - expect(code).toMatch(`return ctx.normalize([`) - expect(code).toMatch( - `"hi ", ctx.message(ctx.interpolate(ctx.list(0)))(ctx), " !"` - ) + expect(code).toMatch(`return _normalize([`) + expect(code).toMatch(`"hi ", _message(_interpolate(_list(0)))(ctx), " !"`) expect(code).toMatch(`])`) }) @@ -219,9 +219,9 @@ describe('linked', () => { transform(ast) const code = generate(ast) expect(code).toMatchSnapshot(msg) - expect(code).toMatch(`return ctx.normalize([`) + expect(code).toMatch(`return _normalize([`) expect(code).toMatch( - `"hi ", ctx.message(ctx.interpolate(ctx.named("name")))(ctx), " !"` + `"hi ", _message(_interpolate(_named("name")))(ctx), " !"` ) expect(code).toMatch(`])`) }) @@ -233,9 +233,9 @@ describe('linked', () => { transform(ast) const code = generate(ast) expect(code).toMatchSnapshot(msg) - expect(code).toMatch(`return ctx.normalize([`) + expect(code).toMatch(`return _normalize([`) expect(code).toMatch( - `"hi ", ctx.modifier("upper")(ctx.message("name")(ctx), ctx.type), " !"` + `"hi ", _modifier("upper")(_message("name")(ctx), _type), " !"` ) expect(code).toMatch(`])`) }) @@ -250,37 +250,45 @@ describe('plural', () => { const code = generate(ast) expect(code).toMatchSnapshot(msg) expect(code).toMatch(`return [`) - expect(code).toMatch(`ctx.normalize([`) + expect(code).toMatch(`_normalize([`) expect(code).toMatch(`"no apples"`) - expect(code).toMatch(` ]), ctx.normalize([`) + expect(code).toMatch(` ]), _normalize([`) expect(code).toMatch(`"one apple"`) - expect(code).toMatch(` ]), ctx.normalize([`) + expect(code).toMatch(` ]), _normalize([`) expect(code).toMatch(`"too much apples "`) expect(code).toMatch(` ])`) - expect(code).toMatch( - `][ctx.pluralRule(ctx.pluralIndex, 3, ctx.orgPluralRule)]` - ) + expect(code).toMatch(`][_pluralRule(_pluralIndex, 3, _orgPluralRule)]`) }) test('complex', () => { const parser = createParser() - const msg = `@.caml:{'no apples'} | {0} apple | {n} apples` // eslint-disable-line no-irregular-whitespace + const msg = `@.caml:{'no apples'} | {0} apple | {n} apples` const ast = parser.parse(msg) transform(ast) const code = generate(ast) expect(code).toMatchSnapshot(msg) expect(code).toMatch(`return [`) - expect(code).toMatch(`ctx.normalize([`) - expect(code).toMatch( - `ctx.modifier("caml")(ctx.message("no apples")(ctx), ctx.type)` - ) - expect(code).toMatch(` ]), ctx.normalize([`) - expect(code).toMatch(`ctx.interpolate(ctx.list(0)), " apple"`) - expect(code).toMatch(` ]), ctx.normalize([`) - expect(code).toMatch(`ctx.interpolate(ctx.named("n")), " apples"`) // eslint-disable-line no-irregular-whitespace + expect(code).toMatch(`_normalize([`) + expect(code).toMatch(`_modifier("caml")(_message("no apples")(ctx), _type)`) + expect(code).toMatch(` ]), _normalize([`) + expect(code).toMatch(`_interpolate(_list(0)), " apple"`) + expect(code).toMatch(` ]), _normalize([`) + expect(code).toMatch(`_interpolate(_named("n")), " apples"`) expect(code).toMatch(` ])`) - expect(code).toMatch( - `][ctx.pluralRule(ctx.pluralIndex, 3, ctx.orgPluralRule)]` - ) + expect(code).toMatch(`][_pluralRule(_pluralIndex, 3, _orgPluralRule)]`) }) }) + +describe('mode', () => { + test('arrow', () => { + const parser = createParser() + const msg = `@.caml:{'no apples'} | {0} apple | {n} apples` + const ast = parser.parse(msg) + transform(ast) + const code = generate(ast, { mode: 'arrow' }) + expect(code).toMatchSnapshot(msg) + expect(code).toMatch(`(ctx) => {`) + }) +}) + +/* eslint-enable no-irregular-whitespace */ diff --git a/test/message/transformer.test.ts b/test/message/transformer.test.ts index 2dbc43af6..29dbc800c 100644 --- a/test/message/transformer.test.ts +++ b/test/message/transformer.test.ts @@ -7,6 +7,6 @@ test('transform', () => { `@.upper:{'no apples'} | {0} apple | {count} apples` // eslint-disable-line no-irregular-whitespace ) // eslint-disable-line no-irregular-whitespace transform(ast) - expect(ast.needInterpolate).toEqual(true) - expect(ast).toMatchSnapshot(ast) + expect(ast.helpers).toMatchSnapshot('helpers') + expect(ast).toMatchSnapshot('ast') })