hyperformula-dc
Version:
HyperFormula is a JavaScript engine for efficient processing of spreadsheet-like data and formulas
436 lines (346 loc) • 14.6 kB
JavaScript
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
import "core-js/modules/es.regexp.exec.js";
import "core-js/modules/es.string.split.js";
import "core-js/modules/es.string.search.js";
import "core-js/modules/es.array.join.js";
import "core-js/modules/es.array.reverse.js";
import "core-js/modules/es.string.starts-with.js";
import "core-js/modules/es.string.match.js";
import "core-js/modules/es.number.to-fixed.js";
import "core-js/modules/es.number.constructor.js";
import "core-js/modules/es.object.to-string.js";
import "core-js/modules/es.regexp.to-string.js";
import "core-js/modules/es.string.replace.js";
import "core-js/modules/es.symbol.js";
import "core-js/modules/es.symbol.description.js";
import "core-js/modules/es.symbol.iterator.js";
import "core-js/modules/es.array.iterator.js";
import "core-js/modules/es.string.iterator.js";
import "core-js/modules/web.dom-collections.iterator.js";
import "core-js/modules/es.array.slice.js";
import "core-js/modules/es.function.name.js";
import "core-js/modules/es.array.from.js";
/**
* @license
* Copyright (c) 2021 Handsoncode. All rights reserved.
*/
import { secondsExtendedRegexp } from '../DateTimeDefault';
import { numberToSimpleTime } from '../DateTimeHelper';
import { parseForDateTimeFormat, parseForNumberFormat, TokenType } from './parser';
export function format(value, formatArg, config, dateHelper) {
var tryDateTime = config.stringifyDateTime(dateHelper.numberToSimpleDateTime(value), formatArg); // default points to defaultStringifyDateTime()
if (tryDateTime !== undefined) {
return tryDateTime;
}
var tryDuration = config.stringifyDuration(numberToSimpleTime(value), formatArg);
if (tryDuration !== undefined) {
return tryDuration;
}
var expression = parseForNumberFormat(formatArg);
if (expression !== undefined) {
return numberFormat(formatArg, value);
}
return formatArg;
}
export function padLeft(number, size) {
var result = number + '';
while (result.length < size) {
result = '0' + result;
}
return result;
}
export function padRight(number, size) {
var result = number + '';
while (result.length < size) {
result = result + '0';
}
return result;
}
function countChars(text, char) {
return text.split(char).length - 1;
}
var maskRegex = /[0-9\-+#]/;
var notMaskRegex = /[^\d\-+#]/g;
function getIndex(mask) {
return mask.search(maskRegex);
}
function processMask() {
var mask = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '#.##';
var maskObj = {
prefix: '',
suffix: '',
mask: '',
maskHasNegativeSign: true,
maskHasPositiveSign: true,
decimal: '',
separator: '',
integer: '',
fraction: ''
};
var len = mask.length;
var start = getIndex(mask);
maskObj.prefix = start > 0 ? mask.substring(0, start) : ''; // Reverse string: not an ideal method if there are surrogate pairs
var end = getIndex(mask.split('').reverse().join(''));
var offset = len - end;
var substr = mask.substring(offset, offset + 1); // Add 1 to offset if mask has a trailing decimal/comma
var indx = offset + (substr === '.' || substr === ',' ? 1 : 0);
maskObj.suffix = end > 0 ? mask.substring(indx, len) : '';
maskObj.mask = mask.substring(start, indx);
maskObj.maskHasNegativeSign = maskObj.mask.startsWith('-');
maskObj.maskHasPositiveSign = maskObj.mask.startsWith('+'); // Search for group separator & decimal; anything not digit,
// not +/- sign, and not #
var result = maskObj.mask.match(notMaskRegex); // Treat the right most symbol as decimal
maskObj.decimal = result && result[result.length - 1] || '.'; // Treat the left most symbol as group separator
maskObj.separator = result && result[1] && result[0] || ','; // Split the decimal for the format string if any
result = maskObj.mask.split(maskObj.decimal);
maskObj.integer = result[0];
maskObj.fraction = result[1];
return maskObj;
}
function processValue(value, maskObj, options) {
var isNegative = false;
var valObj = {
value: value,
sign: '',
integer: '',
fraction: '',
result: ''
};
if (value < 0) {
isNegative = true; // Process only abs(), and turn on flag.
valObj.value = -valObj.value;
}
valObj.sign = isNegative ? '-' : ''; // Fix the decimal first, toFixed will auto fill trailing zero.
valObj.value = Number(valObj.value).toFixed(maskObj.fraction && maskObj.fraction.length); // Convert number to string to trim off *all* trailing decimal zero(es)
valObj.value = Number(valObj.value).toString(); // Fill back any trailing zero according to format
// look for last zero in format
var posTrailZero = maskObj.fraction && maskObj.fraction.lastIndexOf('0');
var _valObj$value$split = valObj.value.split('.'),
_valObj$value$split2 = _slicedToArray(_valObj$value$split, 2),
_valObj$value$split2$ = _valObj$value$split2[0],
valInteger = _valObj$value$split2$ === void 0 ? '0' : _valObj$value$split2$,
_valObj$value$split2$2 = _valObj$value$split2[1],
valFraction = _valObj$value$split2$2 === void 0 ? '' : _valObj$value$split2$2;
if (!valInteger) {
valInteger = '0';
}
if (!valFraction || valFraction && valFraction.length <= posTrailZero) {
valFraction = posTrailZero < 0 ? '' : Number('0.' + valFraction).toFixed(posTrailZero + 1).replace('0.', '');
}
valObj.integer = valInteger;
valObj.fraction = valFraction;
addSeparators(valObj, maskObj); // Remove negative sign if result is zero
if (valObj.result === '0' || valObj.result === '') {
// Remove negative sign if result is zero
isNegative = false;
valObj.sign = '';
}
if (!isNegative && maskObj.maskHasPositiveSign) {
valObj.sign = '+';
} else if (isNegative && maskObj.maskHasPositiveSign) {
valObj.sign = '-';
} else if (isNegative) {
valObj.sign = options && options.enforceMaskSign && !maskObj.maskHasNegativeSign ? '' : '-';
}
return valObj;
}
function addSeparators(valObj, maskObj) {
valObj.result = ''; // Look for separator
var szSep = maskObj.integer.split(maskObj.separator); // Join back without separator for counting the pos of any leading 0
var maskInteger = szSep.join('');
var posLeadZero = maskInteger && maskInteger.indexOf('0');
if (posLeadZero > -1) {
while (valObj.integer.length < maskInteger.length - posLeadZero) {
valObj.integer = '0' + valObj.integer;
}
} else if (Number(valObj.integer) === 0) {
valObj.integer = '';
} // Process the first group separator from decimal (.) only, the rest ignore.
// get the length of the last slice of split result.
var posSeparator = szSep[1] && szSep[szSep.length - 1].length;
if (posSeparator) {
var len = valObj.integer.length;
var offset = len % posSeparator;
for (var indx = 0; indx < len; indx++) {
valObj.result += valObj.integer.charAt(indx); // -posSeparator so that won't trail separator on full length
if (!((indx - offset + 1) % posSeparator) && indx < len - posSeparator) {
valObj.result += maskObj.separator;
}
}
} else {
valObj.result = valObj.integer;
}
valObj.result += maskObj.fraction && valObj.fraction ? maskObj.decimal + valObj.fraction : '';
return valObj;
}
function numberFormat(token, value) {
var result = '';
var maskObj = processMask(token);
var valObj = processValue(value, maskObj, {});
return result = maskObj.prefix + valObj.sign + valObj.result + maskObj.suffix;
}
export function defaultStringifyDuration(time, formatArg) {
var expression = parseForDateTimeFormat(formatArg);
if (expression === undefined) {
return undefined;
}
var tokens = expression.tokens;
var result = '';
var _iterator = _createForOfIteratorHelper(tokens),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var token = _step.value;
if (token.type === TokenType.FREE_TEXT) {
result += token.value;
continue;
}
if (secondsExtendedRegexp.test(token.value)) {
var fractionOfSecondPrecision = token.value.length - 3;
result += (time.seconds < 10 ? '0' : '') + Math.round(time.seconds * Math.pow(10, fractionOfSecondPrecision)) / Math.pow(10, fractionOfSecondPrecision);
continue;
}
switch (token.value.toLowerCase()) {
case 'h':
case 'hh':
{
result += padLeft(time.hours, token.value.length);
time.hours = 0;
break;
}
case '[hh]':
{
result += padLeft(time.hours, token.value.length - 2);
time.hours = 0;
break;
}
case 'm':
case 'mm':
{
result += padLeft(time.minutes, token.value.length);
time.minutes = 0;
break;
}
case '[mm]':
{
result += padLeft(time.minutes + 60 * time.hours, token.value.length - 2);
time.minutes = 0;
time.hours = 0;
break;
}
/* seconds */
case 's':
case 'ss':
{
result += padLeft(time.seconds, token.value.length);
break;
}
default:
{
return undefined;
}
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return result;
}
export function defaultStringifyDateTime(dateTime, formatArg) {
var expression = parseForDateTimeFormat(formatArg);
if (expression === undefined) {
return undefined;
}
var tokens = expression.tokens;
var result = '';
var minutes = false;
var ampm = tokens.some(function (token) {
return token.type === TokenType.FORMAT && (token.value === 'a/p' || token.value === 'A/P' || token.value === 'am/pm' || token.value === 'AM/PM');
});
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
if (token.type === TokenType.FREE_TEXT) {
result += token.value;
continue;
}
if (secondsExtendedRegexp.test(token.value)) {
var fractionOfSecondPrecision = token.value.length - 3;
result += (dateTime.seconds < 10 ? '0' : '') + Math.round(dateTime.seconds * Math.pow(10, fractionOfSecondPrecision)) / Math.pow(10, fractionOfSecondPrecision);
continue;
}
switch (token.value.toLowerCase()) {
/* hours*/
case 'h':
case 'hh':
{
minutes = true;
result += padLeft(ampm ? (dateTime.hours + 11) % 12 + 1 : dateTime.hours, token.value.length);
break;
}
/* days */
case 'd':
case 'dd':
{
result += padLeft(dateTime.day, token.value.length);
break;
}
/* seconds */
case 's':
case 'ss':
{
result += padLeft(Math.round(dateTime.seconds), token.value.length);
break;
}
/* minutes / months */
case 'm':
case 'mm':
{
if (i + 1 < tokens.length && tokens[i + 1].value.startsWith(':')) {
minutes = true;
}
if (minutes) {
result += padLeft(dateTime.minutes, token.value.length);
} else {
result += padLeft(dateTime.month, token.value.length);
}
minutes = true;
break;
}
/* years */
case 'yy':
{
result += padLeft(dateTime.year % 100, token.value.length);
break;
}
case 'yyyy':
{
result += dateTime.year;
break;
}
/* AM / PM */
case 'am/pm':
case 'a/p':
{
var _token$value$split = token.value.split('/'),
_token$value$split2 = _slicedToArray(_token$value$split, 2),
am = _token$value$split2[0],
pm = _token$value$split2[1];
result += dateTime.hours < 12 ? am : pm;
break;
}
default:
{
return undefined;
}
}
}
return result;
}