// @flow import defineFunction from "../defineFunction"; import ParseError from "../ParseError"; import {assertNodeType} from "../parseNode"; // \@char is an internal function that takes a grouped decimal argument like // {123} and converts into symbol with code 123. It is used by the *macro* // \char defined in macros.js. defineFunction({ type: "textord", names: ["\\@char"], props: { numArgs: 1, allowedInText: true, }, handler({parser}, args) { const arg = assertNodeType(args[0], "ordgroup"); const group = arg.body; let number = ""; for (let i = 0; i < group.length; i++) { const node = assertNodeType(group[i], "textord"); number += node.text; } let code = parseInt(number); let text; if (isNaN(code)) { throw new ParseError(`\\@char has non-numeric argument ${number}`); // If we drop IE support, the following code could be replaced with // text = String.fromCodePoint(code) } else if (code < 0 || code >= 0x10ffff) { throw new ParseError(`\\@char with invalid code point ${number}`); } else if (code <= 0xffff) { text = String.fromCharCode(code); } else { // Astral code point; split into surrogate halves code -= 0x10000; text = String.fromCharCode((code >> 10) + 0xd800, (code & 0x3ff) + 0xdc00); } return { type: "textord", mode: parser.mode, text: text, }; }, });