|
| 1 | +/** |
| 2 | + * A simplified version of the message parser that handles messages like vue-i18n v8. |
| 3 | + * This parser probably has poor performance. |
| 4 | + */ |
| 5 | +import type { |
| 6 | + CompileError, |
| 7 | + NamedNode, |
| 8 | + ResourceNode |
| 9 | +} from '@intlify/message-compiler' |
| 10 | +import { NodeTypes } from './utils' |
| 11 | +import { parse as baseParse } from './parser' |
| 12 | +import type { MessageElementNode } from './traverser' |
| 13 | +import { traverseNode } from './traverser' |
| 14 | + |
| 15 | +// The deprecated Rails i18n format. |
| 16 | +export type ModuloNamedNode = NamedNode & { modulo?: boolean } |
| 17 | + |
| 18 | +export function parse(code: string): { |
| 19 | + ast: ResourceNode |
| 20 | + errors: CompileError[] |
| 21 | +} { |
| 22 | + const { ast, errors } = baseParse(code) |
| 23 | + |
| 24 | + traverseNode(ast, node => { |
| 25 | + if (node.type === NodeTypes.Message) { |
| 26 | + transformModuloNamedNode(node.items) |
| 27 | + } |
| 28 | + }) |
| 29 | + return { |
| 30 | + ast, |
| 31 | + errors |
| 32 | + } |
| 33 | + |
| 34 | + function transformModuloNamedNode(nodes: MessageElementNode[]) { |
| 35 | + // Converts nodes with a '%' before the brackets into modulo nodes. |
| 36 | + for (let index = nodes.length - 1; index >= 1; index--) { |
| 37 | + const node = nodes[index] |
| 38 | + if ( |
| 39 | + node.type !== NodeTypes.Named || |
| 40 | + code[node.loc!.start.offset - 1] !== '%' |
| 41 | + ) |
| 42 | + continue |
| 43 | + |
| 44 | + const prev = nodes[index - 1] |
| 45 | + if (prev.type !== NodeTypes.Text || !prev.value?.endsWith('%')) continue |
| 46 | + |
| 47 | + node.modulo = true |
| 48 | + |
| 49 | + prev.loc!.end.offset -= 1 |
| 50 | + prev.loc!.end.column -= 1 |
| 51 | + prev.end! -= 1 |
| 52 | + prev.value = prev.value!.slice(0, -1) |
| 53 | + if (prev.start === prev.end) { |
| 54 | + nodes.splice(index - 1, 1) |
| 55 | + index-- |
| 56 | + } |
| 57 | + } |
| 58 | + } |
| 59 | +} |
0 commit comments