UNPKG

messageformat

Version:

Intl.MessageFormat / Unicode MessageFormat 2 parser, runtime and polyfill

55 lines (54 loc) 2.14 kB
import { MessageError, MessageResolutionError } from "../errors.js"; import { fallback } from "../functions/fallback.js"; import { BIDI_ISOLATE } from "../message-value.js"; import { MessageFunctionContext } from "./function-context.js"; import { getValueSource, resolveValue } from "./resolve-value.js"; export function resolveFunctionRef(ctx, operand, { name, options }) { const fnSource = `:${name}`; const source = getValueSource(operand) ?? fnSource; try { const fnInput = operand ? [resolveValue(ctx, operand)] : []; const rf = ctx.functions[name]; if (!rf) { throw new MessageResolutionError('unknown-function', `Unknown function ${fnSource}`, source); } const msgCtx = new MessageFunctionContext(ctx, source, options); const opt = resolveOptions(ctx, options); const res = rf(msgCtx, opt, ...fnInput); if (res === null || typeof res !== 'object' || typeof res.type !== 'string') { throw new MessageResolutionError('bad-function-result', `Function ${fnSource} did not return a MessageValue`, source); } const override = { source }; if (msgCtx.dir) { override.dir = msgCtx.dir; override[BIDI_ISOLATE] = true; } if (msgCtx.id && typeof res.toParts === 'function') { override.toParts = () => { const parts = res.toParts(); for (const part of parts) part.id = msgCtx.id; return parts; }; } return { ...res, ...override }; } catch (error) { ctx.onError(error instanceof MessageError ? error : new MessageResolutionError('bad-function-result', String(error), source, error)); return fallback(source); } } function resolveOptions(ctx, options) { const opt = Object.create(null); if (options) { for (const [name, value] of Object.entries(options)) { if (!name.startsWith('u:')) opt[name] = resolveValue(ctx, value); } } return opt; }