@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
80 lines (77 loc) • 3.47 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.variablesFromItemBody = exports.parseFormulaDecimalSeparator = exports.formulaSyntaxError = void 0;
var _uniq = _interopRequireDefault(require("lodash/uniq"));
var _util = require("../components/formula/common/util");
var _quizI18n = require("@instructure/quiz-i18n");
var _formatMessage = _interopRequireDefault(require("@instructure/quiz-i18n/es/format-message"));
var variablesFromItemBody = exports.variablesFromItemBody = function variablesFromItemBody(itemBody) {
var body = itemBody || '';
var matches = body.match(/`[A-Za-z]\w*`/g) || [];
var matchesWithoutBackticks = matches.map(function (match) {
return match.replace(/`/g, '');
});
return (0, _uniq["default"])(matchesWithoutBackticks).sort();
};
var formulaSyntaxError = exports.formulaSyntaxError = function formulaSyntaxError(variables, formula) {
var substitutions = {};
variables.forEach(function (varName) {
return substitutions[varName] = 1;
});
try {
// TODO: This will fail if nothing has called components/formula/Edit/util/loadMathJs() yet.
// we should either change this function signature to return a promise and do
// loadMathjs().then(mathjs => mathjs.eval...) or make sure it is always preloaded by
// the time we get here.,
var math = _util.mathjsLoadingWrapper.mathjs;
// This parses the formula detecting if the locale uses comma as separator
var parsedFormula = parseFormulaDecimalSeparator(window.document.documentElement.lang || 'en-US', formula);
// we replace function e() with the constant e
// and function pi() with the constant pi
// this is to match legacy canvas quizzes behavior which accepted both e/pi and e()/pi()
var node = math.parse(parsedFormula);
var transformed = node.transform(function (node, path, parent) {
if (node.isFunctionNode && node.fn.isSymbolNode && node.fn.name === 'e') {
return new math.expression.node.ConstantNode(Math.E);
} else if (node.isFunctionNode && node.fn.isSymbolNode && node.fn.name === 'pi') {
return new math.expression.node.ConstantNode(Math.PI);
} else {
return node;
}
});
var compiled = transformed.compile();
compiled.eval(substitutions);
} catch (e) {
var message = e.message;
console.error('Formula Error: ' + e.message);
var match = message.match(/Undefined symbol ([A-Za-z]+)/);
if (match) {
return (0, _formatMessage["default"])('Undefined symbol {symbol}', {
symbol: match[1]
});
}
match = message.match(/Unexpected end of expression/);
if (match) {
return (0, _formatMessage["default"])('Unexpected end of expression');
}
match = message.match(/Unexpected operator ([^\s]+)/);
if (match) {
return (0, _formatMessage["default"])('Unexpected operator {operator}', {
operator: match[1]
});
}
return (0, _formatMessage["default"])('Invalid formula');
}
return null;
};
var parseFormulaDecimalSeparator = exports.parseFormulaDecimalSeparator = function parseFormulaDecimalSeparator(locale, formula) {
var _Decimal$getDelimiter = _quizI18n.Decimal.getDelimiters(locale),
decimal = _Decimal$getDelimiter.decimal;
if (decimal === '.') {
return formula;
}
return formula.replace(/(\d+),(\d+)/g, '$1.$2');
};