messageformat
Version:
Intl.MessageFormat / Unicode MessageFormat 2 parser, runtime and polyfill
53 lines (52 loc) • 1.95 kB
JavaScript
import { MessageError } 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 source = getValueSource(operand) ?? `:${name}`;
try {
const fnInput = operand ? [resolveValue(ctx, operand)] : [];
const rf = ctx.functions[name];
if (!rf) {
throw new MessageError('unknown-function', `Unknown function :${name}`);
}
const msgCtx = new MessageFunctionContext(ctx, source, options);
const opt = resolveOptions(ctx, options);
let res = rf(msgCtx, opt, ...fnInput);
if (res === null ||
(typeof res !== 'object' && typeof res !== 'function') ||
typeof res.type !== 'string' ||
typeof res.source !== 'string') {
throw new MessageError('bad-function-result', `Function :${name} did not return a MessageValue`);
}
if (msgCtx.dir)
res = { ...res, dir: msgCtx.dir, [BIDI_ISOLATE]: true };
if (msgCtx.id && typeof res.toParts === 'function') {
return {
...res,
toParts() {
const parts = res.toParts();
for (const part of parts)
part.id = msgCtx.id;
return parts;
}
};
}
return res;
}
catch (error) {
ctx.onError(error);
return fallback(source);
}
}
function resolveOptions(ctx, options) {
const opt = Object.create(null);
if (options) {
for (const [name, value] of options) {
if (!name.startsWith('u:'))
opt[name] = resolveValue(ctx, value);
}
}
return opt;
}