@lhncbc/ucum-lhc 4.1.7 → 4.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/browser-dist/ucum-lhc.js +36 -17
- package/package.json +2 -1
- package/source/unitString.js +26 -11
- package/source-cjs/unitString.js +26 -9
- package/source-cjs/unitString.js.map +1 -1
- package/CHANGELOG.md +0 -329
package/browser-dist/ucum-lhc.js
CHANGED
|
@@ -3073,6 +3073,8 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
|
|
|
3073
3073
|
|
|
3074
3074
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
3075
3075
|
|
|
3076
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
3077
|
+
|
|
3076
3078
|
/**
|
|
3077
3079
|
* This class handles the parsing of a unit string into a unit object
|
|
3078
3080
|
*/
|
|
@@ -3128,18 +3130,19 @@ var UnitString = /*#__PURE__*/function () {
|
|
|
3128
3130
|
|
|
3129
3131
|
this.suggestions = [];
|
|
3130
3132
|
} // end constructor
|
|
3131
|
-
|
|
3132
|
-
/**
|
|
3133
|
-
* Sets the emphasis strings to the HTML used in the webpage display - or
|
|
3134
|
-
* blanks them out, depending on the use parameter.
|
|
3135
|
-
*
|
|
3136
|
-
* @param use flag indicating whether or not to use the html message format;
|
|
3137
|
-
* defaults to true
|
|
3138
|
-
*/
|
|
3133
|
+
// The start of an error message about an invalid annotation character.
|
|
3139
3134
|
|
|
3140
3135
|
|
|
3141
3136
|
_createClass(UnitString, [{
|
|
3142
3137
|
key: "useHTMLInMessages",
|
|
3138
|
+
|
|
3139
|
+
/**
|
|
3140
|
+
* Sets the emphasis strings to the HTML used in the webpage display - or
|
|
3141
|
+
* blanks them out, depending on the use parameter.
|
|
3142
|
+
*
|
|
3143
|
+
* @param use flag indicating whether or not to use the html message format;
|
|
3144
|
+
* defaults to true
|
|
3145
|
+
*/
|
|
3143
3146
|
value: function useHTMLInMessages(use) {
|
|
3144
3147
|
if (use === undefined || use) {
|
|
3145
3148
|
this.openEmph_ = Ucum.openEmphHTML_;
|
|
@@ -3435,24 +3438,35 @@ var UnitString = /*#__PURE__*/function () {
|
|
|
3435
3438
|
var openBrace = uString.indexOf('{');
|
|
3436
3439
|
|
|
3437
3440
|
while (openBrace >= 0) {
|
|
3438
|
-
var
|
|
3441
|
+
var closeBrace = uString.indexOf('}');
|
|
3439
3442
|
|
|
3440
|
-
if (
|
|
3443
|
+
if (closeBrace < 0) {
|
|
3441
3444
|
this.retMsg_.push('Missing closing brace for annotation starting at ' + this.openEmph_ + uString.substr(openBrace) + this.closeEmph_);
|
|
3442
3445
|
openBrace = -1;
|
|
3443
3446
|
} else {
|
|
3444
|
-
var braceStr = uString.substring(openBrace,
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3447
|
+
var braceStr = uString.substring(openBrace, closeBrace + 1); // Check for valid characters in the annotation.
|
|
3448
|
+
|
|
3449
|
+
if (!UnitString.VALID_ANNOTATION_REGEX.test(braceStr)) {
|
|
3450
|
+
this.retMsg_.push(UnitString.INVALID_ANNOTATION_CHAR_MSG + this.openEmph_ + braceStr + this.closeEmph_);
|
|
3451
|
+
openBrace = -1; // end search for annotations
|
|
3452
|
+
} else {
|
|
3453
|
+
var aIdx = this.annotations_.length.toString();
|
|
3454
|
+
uString = uString.replace(braceStr, this.braceFlag_ + aIdx + this.braceFlag_);
|
|
3455
|
+
this.annotations_.push(braceStr);
|
|
3456
|
+
openBrace = uString.indexOf('{');
|
|
3457
|
+
}
|
|
3449
3458
|
}
|
|
3450
3459
|
} // end do while we have an opening brace
|
|
3451
3460
|
// check for a stray/unmatched closing brace
|
|
3452
3461
|
|
|
3453
3462
|
|
|
3454
|
-
|
|
3455
|
-
|
|
3463
|
+
if (this.retMsg_.length == 0) {
|
|
3464
|
+
// if there were no other errors above
|
|
3465
|
+
var _closeBrace = uString.indexOf('}');
|
|
3466
|
+
|
|
3467
|
+
if (_closeBrace >= 0) this.retMsg_.push('Missing opening brace for closing brace found at ' + this.openEmph_ + uString.substring(0, _closeBrace + 1) + this.closeEmph_);
|
|
3468
|
+
}
|
|
3469
|
+
|
|
3456
3470
|
return uString;
|
|
3457
3471
|
} // end _getAnnotations
|
|
3458
3472
|
|
|
@@ -4594,6 +4608,11 @@ var UnitString = /*#__PURE__*/function () {
|
|
|
4594
4608
|
|
|
4595
4609
|
exports.UnitString = UnitString;
|
|
4596
4610
|
|
|
4611
|
+
_defineProperty(UnitString, "INVALID_ANNOTATION_CHAR_MSG", 'An invalid character was found in the annotation ');
|
|
4612
|
+
|
|
4613
|
+
// A regular expression for validating annotation strings.
|
|
4614
|
+
_defineProperty(UnitString, "VALID_ANNOTATION_REGEX", /^\{[!-z|~]*\}$/);
|
|
4615
|
+
|
|
4597
4616
|
UnitString.getInstance = function () {
|
|
4598
4617
|
return new UnitString();
|
|
4599
4618
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lhncbc/ucum-lhc",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.8",
|
|
4
4
|
"description": "Implements Unified Code for Units of Measure (UCUM) functions in a javascript library",
|
|
5
5
|
"main": "source-cjs/ucumPkg.js",
|
|
6
6
|
"homepage": "https://lhncbc.github.io/ucum-lhc/",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@babel/cli": "^7.19.3",
|
|
30
30
|
"@babel/core": "^7.3.4",
|
|
31
|
+
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
31
32
|
"@babel/plugin-transform-modules-commonjs": "^7.8.3",
|
|
32
33
|
"@babel/preset-env": "^7.6.2",
|
|
33
34
|
"@babel/register": "^7.6.2",
|
package/source/unitString.js
CHANGED
|
@@ -59,10 +59,15 @@ export class UnitString {
|
|
|
59
59
|
|
|
60
60
|
// suggestions for unit strings that for which no unit was found
|
|
61
61
|
this.suggestions = [] ;
|
|
62
|
-
|
|
63
62
|
} // end constructor
|
|
64
63
|
|
|
65
64
|
|
|
65
|
+
// The start of an error message about an invalid annotation character.
|
|
66
|
+
static INVALID_ANNOTATION_CHAR_MSG = 'An invalid character was found in the annotation ';
|
|
67
|
+
|
|
68
|
+
// A regular expression for validating annotation strings.
|
|
69
|
+
static VALID_ANNOTATION_REGEX = /^\{[!-z|~]*\}$/;
|
|
70
|
+
|
|
66
71
|
/**
|
|
67
72
|
* Sets the emphasis strings to the HTML used in the webpage display - or
|
|
68
73
|
* blanks them out, depending on the use parameter.
|
|
@@ -383,20 +388,30 @@ export class UnitString {
|
|
|
383
388
|
}
|
|
384
389
|
else {
|
|
385
390
|
let braceStr = uString.substring(openBrace, closeBrace + 1);
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
this.
|
|
389
|
-
|
|
390
|
-
|
|
391
|
+
// Check for valid characters in the annotation.
|
|
392
|
+
if (!UnitString.VALID_ANNOTATION_REGEX.test(braceStr)) {
|
|
393
|
+
this.retMsg_.push(UnitString.INVALID_ANNOTATION_CHAR_MSG +
|
|
394
|
+
this.openEmph_ + braceStr + this.closeEmph_);
|
|
395
|
+
openBrace = -1; // end search for annotations
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
let aIdx = this.annotations_.length.toString();
|
|
399
|
+
uString = uString.replace(braceStr, this.braceFlag_ + aIdx +
|
|
400
|
+
this.braceFlag_);
|
|
401
|
+
this.annotations_.push(braceStr);
|
|
402
|
+
openBrace = uString.indexOf('{');
|
|
403
|
+
}
|
|
391
404
|
}
|
|
392
405
|
} // end do while we have an opening brace
|
|
393
406
|
|
|
394
407
|
// check for a stray/unmatched closing brace
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
this.
|
|
399
|
-
|
|
408
|
+
if (this.retMsg_.length == 0) { // if there were no other errors above
|
|
409
|
+
let closeBrace = uString.indexOf('}');
|
|
410
|
+
if (closeBrace >= 0)
|
|
411
|
+
this.retMsg_.push('Missing opening brace for closing brace found at ' +
|
|
412
|
+
this.openEmph_ + uString.substring(0, closeBrace + 1) +
|
|
413
|
+
this.closeEmph_);
|
|
414
|
+
}
|
|
400
415
|
return uString;
|
|
401
416
|
} // end _getAnnotations
|
|
402
417
|
|
package/source-cjs/unitString.js
CHANGED
|
@@ -11,6 +11,8 @@ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return
|
|
|
11
11
|
|
|
12
12
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
13
13
|
|
|
14
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
15
|
+
|
|
14
16
|
/**
|
|
15
17
|
* This class handles the parsing of a unit string into a unit object
|
|
16
18
|
*/
|
|
@@ -64,6 +66,8 @@ class UnitString {
|
|
|
64
66
|
|
|
65
67
|
this.suggestions = [];
|
|
66
68
|
} // end constructor
|
|
69
|
+
// The start of an error message about an invalid annotation character.
|
|
70
|
+
|
|
67
71
|
|
|
68
72
|
/**
|
|
69
73
|
* Sets the emphasis strings to the HTML used in the webpage display - or
|
|
@@ -72,8 +76,6 @@ class UnitString {
|
|
|
72
76
|
* @param use flag indicating whether or not to use the html message format;
|
|
73
77
|
* defaults to true
|
|
74
78
|
*/
|
|
75
|
-
|
|
76
|
-
|
|
77
79
|
useHTMLInMessages(use) {
|
|
78
80
|
if (use === undefined || use) {
|
|
79
81
|
this.openEmph_ = Ucum.openEmphHTML_;
|
|
@@ -369,18 +371,28 @@ class UnitString {
|
|
|
369
371
|
this.retMsg_.push('Missing closing brace for annotation starting at ' + this.openEmph_ + uString.substr(openBrace) + this.closeEmph_);
|
|
370
372
|
openBrace = -1;
|
|
371
373
|
} else {
|
|
372
|
-
let braceStr = uString.substring(openBrace, closeBrace + 1);
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
374
|
+
let braceStr = uString.substring(openBrace, closeBrace + 1); // Check for valid characters in the annotation.
|
|
375
|
+
|
|
376
|
+
if (!UnitString.VALID_ANNOTATION_REGEX.test(braceStr)) {
|
|
377
|
+
this.retMsg_.push(UnitString.INVALID_ANNOTATION_CHAR_MSG + this.openEmph_ + braceStr + this.closeEmph_);
|
|
378
|
+
openBrace = -1; // end search for annotations
|
|
379
|
+
} else {
|
|
380
|
+
let aIdx = this.annotations_.length.toString();
|
|
381
|
+
uString = uString.replace(braceStr, this.braceFlag_ + aIdx + this.braceFlag_);
|
|
382
|
+
this.annotations_.push(braceStr);
|
|
383
|
+
openBrace = uString.indexOf('{');
|
|
384
|
+
}
|
|
377
385
|
}
|
|
378
386
|
} // end do while we have an opening brace
|
|
379
387
|
// check for a stray/unmatched closing brace
|
|
380
388
|
|
|
381
389
|
|
|
382
|
-
|
|
383
|
-
|
|
390
|
+
if (this.retMsg_.length == 0) {
|
|
391
|
+
// if there were no other errors above
|
|
392
|
+
let closeBrace = uString.indexOf('}');
|
|
393
|
+
if (closeBrace >= 0) this.retMsg_.push('Missing opening brace for closing brace found at ' + this.openEmph_ + uString.substring(0, closeBrace + 1) + this.closeEmph_);
|
|
394
|
+
}
|
|
395
|
+
|
|
384
396
|
return uString;
|
|
385
397
|
} // end _getAnnotations
|
|
386
398
|
|
|
@@ -1509,6 +1521,11 @@ class UnitString {
|
|
|
1509
1521
|
|
|
1510
1522
|
exports.UnitString = UnitString;
|
|
1511
1523
|
|
|
1524
|
+
_defineProperty(UnitString, "INVALID_ANNOTATION_CHAR_MSG", 'An invalid character was found in the annotation ');
|
|
1525
|
+
|
|
1526
|
+
// A regular expression for validating annotation strings.
|
|
1527
|
+
_defineProperty(UnitString, "VALID_ANNOTATION_REGEX", /^\{[!-z|~]*\}$/);
|
|
1528
|
+
|
|
1512
1529
|
UnitString.getInstance = function () {
|
|
1513
1530
|
return new UnitString();
|
|
1514
1531
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../source/unitString.js"],"names":["Ucum","require","Unit","UnitTables","PrefixTables","UnitString","constructor","utabs_","getInstance","pfxTabs_","openEmph_","closeEmph_","bracesMsg_","parensFlag_","pFlagLen_","length","braceFlag_","bFlagLen_","vcMsgStart_","vcMsgEnd_","retMsg_","parensUnits_","annotations_","suggestions","useHTMLInMessages","use","undefined","openEmphHTML_","closeEmphHTML_","useBraceMsgForEachString","parseString","uStr","valConv","suggest","trim","Error","valMsgStart_","valMsgEnd_","cnvMsgStart_","cnvMsgEnd_","suggestions_","origString","retObj","_getAnnotations","endProcessing","sUnit","specUnits_","indexOf","replace","_parseTheString","finalUnit","intUtils_","isIntegerUnit","parensResp","_processParens","uArray","mkUArray","_makeUnitsArray","uLen","u1","curCode","Number","parenUnit","_getParensUnit","uRet","_makeUnit","push","_performUnitArithmetic","uString","openBrace","closeBrace","substr","braceStr","substring","aIdx","toString","uStrArray","uStrAryPos","stopProcessing","pu","trimmedCt","openCt","closeCt","openPos","closePos","theMsg","c","parseResp","join","uArray1","match","startNumCheck","unshift","isNumericString","numRes","dispVal","parensback","op","un","n","theOp","validOps_","numRes2","invalidString","parensString","nextParens","parensStr","pStr","retAry","retUnit","befAnnoText","aftAnnoText","psIdx","befText","peIdx","lastIndexOf","aftText","pNumText","csCode_","nMag","getProperty","assignVals","annoRet","_getAnnoText","suggestStat","_getSuggestions","power","asIdx","startText","aeIdx","endText","idx","idxNum","getSynonyms","suggSet","synLen","s","unit","unitArray","uCode","getUnitByCode","clone","getAnnoRet","_getUnitWithAnnotation","tryCode","ciCode_","addBrackets","name_","retUnitAry","getUnitByName","mString","dupMsg","r","rStr","RegExp","res","origCode","origUnit","exp","pfxCode","pfxObj","pfxVal","pfxExp","codeAndExp","_isCodeWithExponent","charAt","getPrefixByCode","getValue","getExp","pCodeLen","source_","resetFieldsForDerivedUnit","theDim","theMag","theName","theCiCode","thePrintSymbol","parseInt","expMul","mul","Math","pow","cnv_","theCode","getName","getCiCode","getPrintSymbol","expStr","annoText","msgLen","tryBrackets","mkUnitRet","pop","u2","nextUnit","msgString","thisOp","isDiv","divide","multiplyThese","err","message","ret"],"mappings":";;;;;;;AASA;;;;;;AATA;;;AAIA,IAAIA,IAAI,GAAGC,OAAO,CAAC,aAAD,CAAP,CAAuBD,IAAlC;;AACA,IAAIE,IAAI,GAAGD,OAAO,CAAC,WAAD,CAAP,CAAqBC,IAAhC;;AACA,IAAIC,UAAU,GAAGF,OAAO,CAAC,iBAAD,CAAP,CAA2BE,UAA5C;;AACA,IAAIC,YAAY,GAAGH,OAAO,CAAC,mBAAD,CAAP,CAA6BG,YAAhD;;AAIO,MAAMC,UAAN,CAAiB;AAEtB;;;AAGAC,EAAAA,WAAW,GAAG;AAEZ;AACA,SAAKC,MAAL,GAAcJ,UAAU,CAACK,WAAX,EAAd;AACA,SAAKC,QAAL,GAAgBL,YAAY,CAACI,WAAb,EAAhB,CAJY,CAMZ;AACA;AACA;;AACA,SAAKE,SAAL,GAAiBV,IAAI,CAACU,SAAtB;AACA,SAAKC,UAAL,GAAkBX,IAAI,CAACW,UAAvB,CAVY,CAYZ;AACA;AACA;AACA;AACA;;AACA,SAAKC,UAAL,GAAkB,EAAlB,CAjBY,CAmBZ;AACA;;AACA,SAAKC,WAAL,GAAmB,oBAAnB,CArBY,CAqB6B;;AACzC,SAAKC,SAAL,GAAiB,KAAKD,WAAL,CAAiBE,MAAlC;AACA,SAAKC,UAAL,GAAkB,oBAAlB,CAvBY,CAuB4B;;AACxC,SAAKC,SAAL,GAAiB,KAAKD,UAAL,CAAgBD,MAAjC,CAxBY,CA0BZ;AACA;;AACA,SAAKG,WAAL,GAAmB,IAAnB;AACA,SAAKC,SAAL,GAAiB,IAAjB,CA7BY,CA+BZ;AACA;AAEA;;AACA,SAAKC,OAAL,GAAe,EAAf,CAnCY,CAqCZ;;AACA,SAAKC,YAAL,GAAoB,EAApB,CAtCY,CAwCZ;;AACA,SAAKC,YAAL,GAAoB,EAApB,CAzCY,CA2CZ;;AACA,SAAKC,WAAL,GAAmB,EAAnB;AAED,GAnDqB,CAmDpB;;AAGF;;;;;;;;;AAOAC,EAAAA,iBAAiB,CAACC,GAAD,EAAM;AACrB,QAAIA,GAAG,KAAKC,SAAR,IAAqBD,GAAzB,EAA8B;AAC5B,WAAKf,SAAL,GAAiBV,IAAI,CAAC2B,aAAtB;AACA,WAAKhB,UAAL,GAAkBX,IAAI,CAAC4B,cAAvB;AACD,KAHD,MAIK;AACH,WAAKlB,SAAL,GAAiBV,IAAI,CAACU,SAAtB;AACA,WAAKC,UAAL,GAAkBX,IAAI,CAACW,UAAvB;AACD;AACF,GAtEqB,CAsEpB;;AAGF;;;;;;;;;AAOAkB,EAAAA,wBAAwB,CAACJ,GAAD,EAAM;AAC5B,QAAIA,GAAG,KAAKC,SAAR,IAAqBD,GAAzB,EACE,KAAKb,UAAL,GAAkBZ,IAAI,CAACY,UAAvB,CADF,KAGE,KAAKA,UAAL,GAAkB,EAAlB;AACH;AAGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCAkB,EAAAA,WAAW,CAACC,IAAD,EAAOC,OAAP,EAAgBC,OAAhB,EAAyB;AAElCF,IAAAA,IAAI,GAAGA,IAAI,CAACG,IAAL,EAAP,CAFkC,CAGlC;;AACA,QAAIH,IAAI,KAAK,EAAT,IAAeA,IAAI,KAAK,IAA5B,EAAkC;AAChC,YAAO,IAAII,KAAJ,CAAU,mDAAV,CAAP;AACD;;AAED,QAAIH,OAAO,KAAK,UAAhB,EAA4B;AAC1B,WAAKd,WAAL,GAAmBlB,IAAI,CAACoC,YAAxB;AACA,WAAKjB,SAAL,GAAiBnB,IAAI,CAACqC,UAAtB;AACD,KAHD,MAIK;AACH,WAAKnB,WAAL,GAAmBlB,IAAI,CAACsC,YAAxB;AACA,WAAKnB,SAAL,GAAiBnB,IAAI,CAACuC,UAAtB;AACD;;AAED,QAAIN,OAAO,KAAKP,SAAZ,IAAyBO,OAAO,KAAK,KAAzC,EAAgD;AAC9C,WAAKO,YAAL,GAAoB,IAApB;AACD,KAFD,MAGK;AACH,WAAKA,YAAL,GAAoB,EAApB;AACD;;AAED,SAAKpB,OAAL,GAAe,EAAf;AACA,SAAKC,YAAL,GAAoB,EAApB;AACA,SAAKC,YAAL,GAAoB,EAApB;AAEA,QAAImB,UAAU,GAAGV,IAAjB;AACA,QAAIW,MAAM,GAAG,EAAb,CA7BkC,CA+BlC;AACA;AACA;AACA;AACA;AACA;;AAEAX,IAAAA,IAAI,GAAG,KAAKY,eAAL,CAAqBZ,IAArB,CAAP;;AACA,QAAI,KAAKX,OAAL,CAAaL,MAAb,GAAsB,CAA1B,EAA6B;AAC3B2B,MAAAA,MAAM,CAAC,CAAD,CAAN,GAAY,IAAZ;AACAA,MAAAA,MAAM,CAAC,CAAD,CAAN,GAAY,IAAZ;AACD,KAHD,MAIK;AACH;AACA,UAAIE,aAAa,GAAG,KAAKxB,OAAL,CAAaL,MAAb,GAAsB,CAA1C,CAFG,CAIH;AACA;AACA;AACA;;AACA,UAAI8B,KAAK,GAAG,IAAZ;;AACA,WAAKA,KAAL,IAAc7C,IAAI,CAAC8C,UAAnB,EAA+B;AAC7B,eAAOf,IAAI,CAACgB,OAAL,CAAaF,KAAb,MAAwB,CAAC,CAAhC,EACEd,IAAI,GAAGA,IAAI,CAACiB,OAAL,CAAaH,KAAb,EAAoB7C,IAAI,CAAC8C,UAAL,CAAgBD,KAAhB,CAApB,CAAP;AACH,OAZE,CAcH;AACA;AACA;;;AACA,UAAId,IAAI,CAACgB,OAAL,CAAa,GAAb,IAAoB,CAAC,CAAzB,EAA4B;AAC1B,cAAO,IAAIZ,KAAJ,CAAU,mDAAV,CAAP;AACD,OAnBE,CAmBD;AAEF;AACA;AACA;AACA;;;AACAO,MAAAA,MAAM,GAAG,KAAKO,eAAL,CAAqBlB,IAArB,EAA2BU,UAA3B,CAAT;AACA,UAAIS,SAAS,GAAGR,MAAM,CAAC,CAAD,CAAtB,CA1BG,CA4BH;AACA;AACA;AACA;;AACA,UAAIS,SAAS,CAACC,aAAV,CAAwBF,SAAxB,KAAsC,OAAOA,SAAP,KAAqB,QAA/D,EAAyE;AACvEA,QAAAA,SAAS,GAAG,IAAIhD,IAAJ,CAAS;AACnB,qBAAWuC,UADQ;AAEnB,wBAAcS,SAFK;AAGnB,mBAAST;AAHU,SAAT,CAAZ;AAKAC,QAAAA,MAAM,CAAC,CAAD,CAAN,GAAYQ,SAAZ;AACD,OAvCE,CAuCD;;AACH,KAnFiC,CAmFhC;;;AAEFR,IAAAA,MAAM,CAAC,CAAD,CAAN,GAAY,KAAKtB,OAAjB;AACA,QAAI,KAAKoB,YAAL,IAAqB,KAAKA,YAAL,CAAkBzB,MAAlB,GAA2B,CAApD,EACE2B,MAAM,CAAC,CAAD,CAAN,GAAY,KAAKF,YAAjB;AACF,WAAOE,MAAP;AAED,GAxNqB,CAwNpB;;AAGF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BAO,EAAAA,eAAe,CAAClB,IAAD,EAAOU,UAAP,EAAmB;AAEhC;AACA,QAAIS,SAAS,GAAG,IAAhB,CAHgC,CAKhC;;AACA,QAAIN,aAAa,GAAG,KAAKxB,OAAL,CAAaL,MAAb,GAAsB,CAA1C,CANgC,CAQhC;AACA;AACA;;AACA,QAAIsC,UAAU,GAAG,KAAKC,cAAL,CAAoBvB,IAApB,EAA0BU,UAA1B,CAAjB;;AACAG,IAAAA,aAAa,GAAGS,UAAU,CAAC,CAAD,CAA1B,CAZgC,CAchC;;AACA,QAAIE,MAAM,GAAG,EAAb,CAfgC,CAiBhC;;AACA,QAAI,CAACX,aAAL,EAAoB;AAClBb,MAAAA,IAAI,GAAGsB,UAAU,CAAC,CAAD,CAAjB;AACAZ,MAAAA,UAAU,GAAGY,UAAU,CAAC,CAAD,CAAvB,CAFkB,CAIlB;AACA;;AACA,UAAIG,QAAQ,GAAG,KAAKC,eAAL,CAAqB1B,IAArB,EAA2BU,UAA3B,CAAf;;AAEAG,MAAAA,aAAa,GAAGY,QAAQ,CAAC,CAAD,CAAxB;;AACA,UAAI,CAACZ,aAAL,EAAoB;AAClBW,QAAAA,MAAM,GAAGC,QAAQ,CAAC,CAAD,CAAjB;AACAf,QAAAA,UAAU,GAAGe,QAAQ,CAAC,CAAD,CAArB,CAFkB,CAGlB;;AACA,YAAIE,IAAI,GAAGH,MAAM,CAACxC,MAAlB;;AACA,aAAK,IAAI4C,EAAE,GAAG,CAAd,EAAiBA,EAAE,GAAGD,IAAtB,EAA4BC,EAAE,EAA9B,EAAkC;AAChC;AACA,cAAIC,OAAO,GAAGL,MAAM,CAACI,EAAD,CAAN,CAAW,IAAX,CAAd,CAFgC,CAIhC;AAEA;AACA;;AACA,cAAIR,SAAS,CAACC,aAAV,CAAwBQ,OAAxB,CAAJ,EAAsC;AACpCL,YAAAA,MAAM,CAACI,EAAD,CAAN,CAAW,IAAX,IAAmBE,MAAM,CAACD,OAAD,CAAzB;AACD,WAFD,MAIK;AACH;AACA;AACA;AAEA,gBAAIA,OAAO,CAACb,OAAR,CAAgB,KAAKlC,WAArB,KAAqC,CAAzC,EAA4C;AAC1C,kBAAIiD,SAAS,GAAG,KAAKC,cAAL,CAAoBH,OAApB,EAA6BnB,UAA7B,CAAhB,CAD0C,CAE1C;AACA;;;AACA,kBAAI,CAACG,aAAL,EACEA,aAAa,GAAGkB,SAAS,CAAC,CAAD,CAAzB,CALwC,CAO1C;AACA;AACA;;AACA,kBAAI,CAAClB,aAAL,EAAoB;AAClBW,gBAAAA,MAAM,CAACI,EAAD,CAAN,CAAW,IAAX,IAAmBG,SAAS,CAAC,CAAD,CAA5B;AACD;AACF,aAbD,CAaE;AAEF;AACA;AAhBA,iBAiBK;AACH,oBAAIE,IAAI,GAAG,KAAKC,SAAL,CAAeL,OAAf,EAAwBnB,UAAxB,CAAX,CADG,CAEH;;;AACA,oBAAIuB,IAAI,CAAC,CAAD,CAAJ,KAAY,IAAhB,EAAsB;AACpBpB,kBAAAA,aAAa,GAAG,IAAhB;AACD,iBAFD,MAGK;AACHW,kBAAAA,MAAM,CAACI,EAAD,CAAN,CAAW,IAAX,IAAmBK,IAAI,CAAC,CAAD,CAAvB;AACAvB,kBAAAA,UAAU,GAAGuB,IAAI,CAAC,CAAD,CAAjB;AACD;AACF,eAhCE,CAgCD;;AACH,WA7C+B,CA6C9B;;AACH,SAnDiB,CAmDhB;;AACH,OA7DiB,CA6DhB;;AACH,KAhF+B,CAgF9B;AAEF;;;AACA,QAAI,CAACpB,aAAL,EAAoB;AAClB;AACA,UAAI,CAACW,MAAM,CAAC,CAAD,CAAN,KAAc,IAAd,IAAsBA,MAAM,CAAC,CAAD,CAAN,KAAc,GAApC,IACAA,MAAM,CAAC,CAAD,CAAN,CAAU,IAAV,MAAoB7B,SADpB,IACiC6B,MAAM,CAAC,CAAD,CAAN,CAAU,IAAV,MAAoB,IADtD,KAEG,KAAKnC,OAAL,CAAaL,MAAb,KAAwB,CAF/B,EAEkC;AAChC;AACA,aAAKK,OAAL,CAAa8C,IAAb,CAAmB,gBAAezB,UAAW,oBAA3B,GACf,kEADe,GAEf,iDAFH;AAGAG,QAAAA,aAAa,GAAG,IAAhB;AACD;AACF;;AACD,QAAI,CAACA,aAAL,EAAoB;AAClBM,MAAAA,SAAS,GAAG,KAAKiB,sBAAL,CAA4BZ,MAA5B,EAAoCd,UAApC,CAAZ;AACD;;AACD,WAAO,CAACS,SAAD,EAAYT,UAAZ,CAAP;AACD,GAzVqB,CAyVpB;;AAGF;;;;;;;;;;;;;;;AAaAE,EAAAA,eAAe,CAACyB,OAAD,EAAU;AACvB,QAAIC,SAAS,GAAGD,OAAO,CAACrB,OAAR,CAAgB,GAAhB,CAAhB;;AACA,WAAOsB,SAAS,IAAI,CAApB,EAAuB;AAErB,UAAIC,UAAU,GAAGF,OAAO,CAACrB,OAAR,CAAgB,GAAhB,CAAjB;;AACA,UAAIuB,UAAU,GAAG,CAAjB,EAAoB;AAClB,aAAKlD,OAAL,CAAa8C,IAAb,CAAkB,sDAChB,KAAKxD,SADW,GACC0D,OAAO,CAACG,MAAR,CAAeF,SAAf,CADD,GAEhB,KAAK1D,UAFP;AAGA0D,QAAAA,SAAS,GAAG,CAAC,CAAb;AACD,OALD,MAMK;AACH,YAAIG,QAAQ,GAAGJ,OAAO,CAACK,SAAR,CAAkBJ,SAAlB,EAA6BC,UAAU,GAAG,CAA1C,CAAf;AACA,YAAII,IAAI,GAAG,KAAKpD,YAAL,CAAkBP,MAAlB,CAAyB4D,QAAzB,EAAX;AACAP,QAAAA,OAAO,GAAGA,OAAO,CAACpB,OAAR,CAAgBwB,QAAhB,EAA0B,KAAKxD,UAAL,GAAkB0D,IAAlB,GAClC,KAAK1D,UADG,CAAV;AAEA,aAAKM,YAAL,CAAkB4C,IAAlB,CAAuBM,QAAvB;AACAH,QAAAA,SAAS,GAAGD,OAAO,CAACrB,OAAR,CAAgB,GAAhB,CAAZ;AACD;AACF,KAnBsB,CAmBrB;AAEF;;;AACA,QAAIuB,UAAU,GAAGF,OAAO,CAACrB,OAAR,CAAgB,GAAhB,CAAjB;AACA,QAAIuB,UAAU,IAAI,CAAlB,EACE,KAAKlD,OAAL,CAAa8C,IAAb,CAAkB,sDAChB,KAAKxD,SADW,GACC0D,OAAO,CAACK,SAAR,CAAkB,CAAlB,EAAqBH,UAAU,GAAG,CAAlC,CADD,GAEhB,KAAK3D,UAFP;AAGF,WAAOyD,OAAP;AACD,GArYqB,CAqYpB;;AAGF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BAd,EAAAA,cAAc,CAACc,OAAD,EAAU3B,UAAV,EAAsB;AAElC;AACA,QAAImC,SAAS,GAAG,EAAhB;AACA,QAAIC,UAAU,GAAG,CAAjB;AACA,QAAIC,cAAc,GAAG,KAArB;AAEA,QAAIC,EAAE,GAAG,KAAK1D,YAAL,CAAkBN,MAA3B,CAPkC,CASlC;AACA;AACA;;AACA,QAAIiE,SAAS,GAAG,CAAhB,CAZkC,CAclC;AACA;AACA;AACA;;AACA,WAAOZ,OAAO,KAAK,EAAZ,IAAkB,CAACU,cAA1B,EAA0C;AACxC,UAAIG,MAAM,GAAG,CAAb;AACA,UAAIC,OAAO,GAAG,CAAd;AACA,UAAIC,OAAO,GAAGf,OAAO,CAACrB,OAAR,CAAgB,GAAhB,CAAd,CAHwC,CAKxC;AACA;AACA;;AACA,UAAIoC,OAAO,GAAG,CAAd,EAAiB;AACf,YAAIC,QAAQ,GAAGhB,OAAO,CAACrB,OAAR,CAAgB,GAAhB,CAAf;;AACA,YAAIqC,QAAQ,IAAI,CAAhB,EAAmB;AACjB,cAAIC,MAAM,GAAI,qCAAD,GACV,kBAAiBjB,OAAO,CAACK,SAAR,CAAkB,CAAlB,EAAqBW,QAAQ,GAAGJ,SAAhC,CAA2C,EADlD,GAEV,GAAE,KAAKtE,SAAU,GAAE0D,OAAO,CAACG,MAAR,CAAea,QAAf,EAAyB,CAAzB,CAA4B,GAAE,KAAKzE,UAAW,EAFpE;;AAGA,cAAIyE,QAAQ,GAAGhB,OAAO,CAACrD,MAAR,GAAiB,CAAhC,EAAmC;AACjCsE,YAAAA,MAAM,IAAK,GAAEjB,OAAO,CAACG,MAAR,CAAea,QAAQ,GAAG,CAA1B,CAA6B,EAA1C;AACD;;AACD,eAAKhE,OAAL,CAAa8C,IAAb,CAAkBmB,MAAlB;AACAT,UAAAA,SAAS,CAACC,UAAD,CAAT,GAAwBT,OAAxB;AACAU,UAAAA,cAAc,GAAG,IAAjB;AACD,SAVD,CAUE;AAEF;AACA;AACA;AAdA,aAeK;AACHF,YAAAA,SAAS,CAACC,UAAD,CAAT,GAAwBT,OAAxB;AACAA,YAAAA,OAAO,GAAG,EAAV;AACD,WApBc,CAoBb;;AACH,OArBD,CAqBE;AAEF;AACA;AAxBA,WAyBK;AACHa,UAAAA,MAAM,IAAI,CAAV,CADG,CAEH;;AACA,cAAIvB,IAAI,GAAGU,OAAO,CAACrD,MAAnB;;AACA,cAAIoE,OAAO,GAAG,CAAd,EAAiB;AACfP,YAAAA,SAAS,CAACC,UAAU,EAAX,CAAT,GAA0BT,OAAO,CAACG,MAAR,CAAe,CAAf,EAAkBY,OAAlB,CAA1B;AACD,WANE,CAQH;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA,cAAIC,QAAQ,GAAG,CAAf;AACA,cAAIE,CAAC,GAAGH,OAAO,GAAG,CAAlB;;AACA,iBAAOG,CAAC,GAAG5B,IAAJ,IAAYuB,MAAM,IAAIC,OAA7B,EAAsCI,CAAC,EAAvC,EAA2C;AACzC,gBAAIlB,OAAO,CAACkB,CAAD,CAAP,KAAe,GAAnB,EACEL,MAAM,IAAI,CAAV,CADF,KAEK,IAAIb,OAAO,CAACkB,CAAD,CAAP,KAAe,GAAnB,EACHJ,OAAO,IAAI,CAAX;AACH,WAtBE,CAwBH;AACA;AACA;AACA;AACA;AACA;;;AACA,cAAID,MAAM,KAAKC,OAAf,EAAwB;AACtBE,YAAAA,QAAQ,GAAGE,CAAX;AACAV,YAAAA,SAAS,CAACC,UAAU,EAAX,CAAT,GAA0B,KAAKhE,WAAL,GAAmBkE,EAAE,CAACJ,QAAH,EAAnB,GAAmC,KAAK9D,WAAlE;;AACA,gBAAI0E,SAAS,GAAG,KAAKtC,eAAL,CACdmB,OAAO,CAACK,SAAR,CAAkBU,OAAO,GAAG,CAA5B,EAA+BC,QAAQ,GAAG,CAA1C,CADc,EACgC3C,UADhC,CAAhB;;AAEA,gBAAI8C,SAAS,CAAC,CAAD,CAAT,KAAiB,IAArB,EACET,cAAc,GAAG,IAAjB,CADF,KAEK;AACHrC,cAAAA,UAAU,GAAG8C,SAAS,CAAC,CAAD,CAAtB;AACA,mBAAKlE,YAAL,CAAkB0D,EAAE,EAApB,IAA0BQ,SAAS,CAAC,CAAD,CAAnC;AACAnB,cAAAA,OAAO,GAAGA,OAAO,CAACG,MAAR,CAAea,QAAf,CAAV;AACAJ,cAAAA,SAAS,GAAGI,QAAZ;AACD;AACF,WAbD,CAaE;AAEF;AACA;AAhBA,eAiBK;AACHR,cAAAA,SAAS,CAACV,IAAV,CAAezB,UAAU,CAAC8B,MAAX,CAAkBY,OAAlB,CAAf;AACA,mBAAK/D,OAAL,CAAa8C,IAAb,CAAmB,oDAAD,GACf,GAAEzB,UAAU,CAACgC,SAAX,CAAqB,CAArB,EAAwBU,OAAO,GAAGH,SAAlC,CAA6C,EADhC,GAEf,GAAE,KAAKtE,SAAU,GAAE+B,UAAU,CAAC8B,MAAX,CAAkBY,OAAlB,EAA2B,CAA3B,CAA8B,EAFlC,GAGf,GAAE,KAAKxE,UAAW,GAAE8B,UAAU,CAAC8B,MAAX,CAAkBY,OAAO,GAAG,CAA5B,CAA+B,EAHtD;AAIAL,cAAAA,cAAc,GAAG,IAAjB;AACD;AACF,SAxFuC,CAwFtC;;AACH,KA3GiC,CA2GhC;;;AACF,QAAIA,cAAJ,EACE,KAAKzD,YAAL,GAAoB,EAApB;AACF,WAAO,CAACuD,SAAS,CAACY,IAAV,CAAe,EAAf,CAAD,EAAqB/C,UAArB,EAAiCqC,cAAjC,CAAP;AACD,GArhBqB,CAqhBpB;;AAGF;;;;;;;;;;;;;;;;;;;;;AAmBArB,EAAAA,eAAe,CAAC1B,IAAD,EAAOU,UAAP,EAAmB;AAEhC;AACA;AACA;AAEA,QAAIgD,OAAO,GAAG1D,IAAI,CAAC2D,KAAL,CAAW,gBAAX,CAAd;AACA,QAAI9C,aAAa,GAAG,KAApB;AACA,QAAIW,MAAM,GAAG,EAAb;AACA,QAAIoC,aAAa,GAAG,0CAApB,CATgC,CAWhC;AACA;AACA;;AACA,QAAIF,OAAO,CAAC,CAAD,CAAP,KAAe,GAAnB,EAAwB;AACtBA,MAAAA,OAAO,CAACG,OAAR,CAAgB,GAAhB;AACD,KAFD,CAGA;AACA;AAJA,SAKK,IAAIH,OAAO,CAAC,CAAD,CAAP,KAAe,GAAnB,EAAwB;AAC3B,aAAKrE,OAAL,CAAa8C,IAAb,CAAmB,GAAEzB,UAAW,6BAAd,GACb,oEADa,GAEb,gEAFa,GAGb,YAHL;AAIAG,QAAAA,aAAa,GAAG,IAAhB;AACD;;AACD,QAAI,CAACA,aAAL,EAAoB;AAClB;AACA;AACA;AACA;AAEA,UAAI,CAACO,SAAS,CAAC0C,eAAV,CAA0BJ,OAAO,CAAC,CAAD,CAAjC,CAAL,EAA4C;AAC1C,YAAIK,MAAM,GAAGL,OAAO,CAAC,CAAD,CAAP,CAAWC,KAAX,CAAiBC,aAAjB,CAAb;;AACA,YAAIG,MAAM,IAAIA,MAAM,CAAC/E,MAAP,KAAkB,CAA5B,IAAiC+E,MAAM,CAAC,CAAD,CAAN,KAAc,EAA/C,IACFA,MAAM,CAAC,CAAD,CAAN,KAAc,EADZ,IACkBA,MAAM,CAAC,CAAD,CAAN,CAAU/C,OAAV,CAAkB,KAAK/B,UAAvB,MAAuC,CAD7D,EACgE;AAC9D,cAAI+E,OAAO,GAAGD,MAAM,CAAC,CAAD,CAApB;;AAEA,cAAI,CAAClD,aAAD,IAAkBkD,MAAM,CAAC,CAAD,CAAN,CAAU/C,OAAV,CAAkB,KAAKlC,WAAvB,MAAwC,CAAC,CAA/D,EAAkE;AAChE,gBAAImF,UAAU,GAAG,KAAKjC,cAAL,CAAoB+B,MAAM,CAAC,CAAD,CAA1B,EAA+BrD,UAA/B,CAAjB;;AACAqD,YAAAA,MAAM,CAAC,CAAD,CAAN,GAAYE,UAAU,CAAC,CAAD,CAAV,CAAc,SAAd,CAAZ;AACAD,YAAAA,OAAO,GAAI,IAAGD,MAAM,CAAC,CAAD,CAAI,GAAxB;AACAlD,YAAAA,aAAa,GAAGoD,UAAU,CAAC,CAAD,CAA1B;AACD;;AACD,cAAI,CAACpD,aAAL,EAAoB;AAClB,iBAAKxB,OAAL,CAAa8C,IAAb,CAAmB,GAAE4B,MAAM,CAAC,CAAD,CAAI,GAAEC,OAAQ,4BAAvB,GACf,KAAI,KAAK7E,WAAY,GAAE4E,MAAM,CAAC,CAAD,CAAI,IAAGC,OAAQ,GAAE,KAAK5E,SAAU,EADhE;AAEAsB,YAAAA,UAAU,GAAGA,UAAU,CAACO,OAAX,CAAoB,GAAE8C,MAAM,CAAC,CAAD,CAAI,GAAEC,OAAQ,EAA1C,EACV,GAAED,MAAM,CAAC,CAAD,CAAI,IAAGC,OAAQ,EADb,CAAb;AAEAN,YAAAA,OAAO,CAAC,CAAD,CAAP,GAAaK,MAAM,CAAC,CAAD,CAAnB;AACAL,YAAAA,OAAO,CAACG,OAAR,CAAgBE,MAAM,CAAC,CAAD,CAAtB,EAA2B,GAA3B;AACD;AACF;AACF,OA3BiB,CA2BhB;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA,UAAI,CAAClD,aAAL,EAAoB;AAClB,YAAIe,EAAE,GAAG8B,OAAO,CAAC1E,MAAjB;AACAwC,QAAAA,MAAM,GAAG,CAAC;AAAC0C,UAAAA,EAAE,EAAE,EAAL;AAASC,UAAAA,EAAE,EAAET,OAAO,CAAC,CAAD;AAApB,SAAD,CAAT;;AACA,aAAK,IAAIU,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGxC,EAApB,EAAwBwC,CAAC,EAAzB,EAA6B;AAE3B;AACA;AACA,cAAIC,KAAK,GAAGX,OAAO,CAACU,CAAC,EAAF,CAAnB,CAJ2B,CAK3B;AACA;;AACA,cAAI,CAACV,OAAO,CAACU,CAAD,CAAZ,EAAiB;AACf,iBAAK/E,OAAL,CAAa8C,IAAb,CAAmB,GAAEzB,UAAW,6BAAd,GACf,sCAAqC,KAAK/B,SAAU,EADrC,GAEf,GAAE0F,KAAM,GAAE,KAAKzF,UAAW,GAF7B;AAGAwF,YAAAA,CAAC,GAAGxC,EAAJ;AACAf,YAAAA,aAAa,GAAG,IAAhB;AACD,WAND,MAOK,IAAI5C,IAAI,CAACqG,SAAL,CAAetD,OAAf,CAAuB0C,OAAO,CAACU,CAAD,CAA9B,MAAuC,CAAC,CAA5C,EAA+C;AAClD,iBAAK/E,OAAL,CAAa8C,IAAb,CAAmB,GAAEzB,UAAW,6BAAd,GACf,iCAAgC,KAAK/B,SAAU,EADhC,GAEf,GAAE0F,KAAM,GAAE,KAAKzF,UAAW,MAAK,KAAKD,SAAU,EAF/B,GAGf,GAAE+E,OAAO,CAACU,CAAD,CAAI,GAAE,KAAKxF,UAAW,KAAI,KAAKD,SAAU,EAHnC,GAIf,GAAE0F,KAAM,GAAEX,OAAO,CAACU,CAAD,CAAI,GAAE,KAAKxF,UAAW,GAJ1C;AAKAwF,YAAAA,CAAC,GAAGxC,EAAJ;AACAf,YAAAA,aAAa,GAAG,IAAhB;AACD,WARI,MASA;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAI,CAACO,SAAS,CAAC0C,eAAV,CAA0BJ,OAAO,CAACU,CAAD,CAAjC,CAAL,EAA4C;AAC1C,kBAAIG,OAAO,GAAGb,OAAO,CAACU,CAAD,CAAP,CAAWT,KAAX,CAAiBC,aAAjB,CAAd;;AACA,kBAAIW,OAAO,IAAIA,OAAO,CAACvF,MAAR,KAAmB,CAA9B,IAAmCuF,OAAO,CAAC,CAAD,CAAP,KAAe,EAAlD,IACFA,OAAO,CAAC,CAAD,CAAP,KAAe,EADb,IACmBA,OAAO,CAAC,CAAD,CAAP,CAAWvD,OAAX,CAAmB,KAAK/B,UAAxB,MAAwC,CAD/D,EACkE;AAChE,oBAAIuF,aAAa,GAAGD,OAAO,CAAC,CAAD,CAA3B;;AACA,oBAAI,CAAC1D,aAAD,IAAkB0D,OAAO,CAAC,CAAD,CAAP,CAAWvD,OAAX,CAAmB,KAAKlC,WAAxB,MAAyC,CAAC,CAAhE,EAAmE;AACjE,sBAAImF,UAAU,GAAG,KAAKjC,cAAL,CAAoBuC,OAAO,CAAC,CAAD,CAA3B,EAAgC7D,UAAhC,CAAjB;;AACA6D,kBAAAA,OAAO,CAAC,CAAD,CAAP,GAAaN,UAAU,CAAC,CAAD,CAAV,CAAc,SAAd,CAAb;AACAO,kBAAAA,aAAa,GAAI,IAAGD,OAAO,CAAC,CAAD,CAAI,GAA/B;AACA1D,kBAAAA,aAAa,GAAGoD,UAAU,CAAC,CAAD,CAA1B;;AACA,sBAAI,CAACpD,aAAL,EAAoB;AAClB,yBAAKxB,OAAL,CAAa8C,IAAb,CAAmB,GAAEoC,OAAO,CAAC,CAAD,CAAI,GAAEC,aAAc,YAA9B,GACf,qBAAoB,KAAKrF,WAAY,GAAEoF,OAAO,CAAC,CAAD,CAAI,IAAGC,aAAc,EADpD,GAEf,GAAE,KAAKpF,SAAU,EAFpB;AAGA,wBAAIqF,YAAY,GAAI,IAAGF,OAAO,CAAC,CAAD,CAAI,IAAGC,aAAc,GAAnD;AACA9D,oBAAAA,UAAU,GAAGA,UAAU,CAACO,OAAX,CAAoB,GAAEsD,OAAO,CAAC,CAAD,CAAI,GAAEC,aAAc,EAAjD,EACXC,YADW,CAAb;;AAEA,wBAAIC,UAAU,GAAG,KAAKnD,cAAL,CAAoBkD,YAApB,EAAkC/D,UAAlC,CAAjB;;AACAG,oBAAAA,aAAa,GAAG6D,UAAU,CAAC,CAAD,CAA1B;;AACA,wBAAI,CAAC7D,aAAL,EAAoB;AAClBW,sBAAAA,MAAM,CAACW,IAAP,CAAY;AAAC+B,wBAAAA,EAAE,EAAEG,KAAL;AAAYF,wBAAAA,EAAE,EAAEO,UAAU,CAAC,CAAD;AAA1B,uBAAZ;AACD,qBAXiB,CAYlB;;AACD;AACF,iBAnBD,CAmBE;AAnBF,qBAoBK;AACH,wBAAIC,SAAS,GAAG,MAAMJ,OAAO,CAAC,CAAD,CAAb,GAAmB,GAAnB,GAAyBA,OAAO,CAAC,CAAD,CAAhC,GAAsC,GAAtD;;AACA,wBAAIjD,UAAU,GAAG,KAAKC,cAAL,CAAoBoD,SAApB,EAA+BjE,UAA/B,CAAjB,CAFG,CAGH;AACA;;;AACA,wBAAIY,UAAU,CAAC,CAAD,CAAd,EAAmB;AACjB8C,sBAAAA,CAAC,GAAGxC,EAAJ;AACAf,sBAAAA,aAAa,GAAG,IAAhB;AACD,qBAHD,MAIK;AACH,2BAAKxB,OAAL,CAAa8C,IAAb,CAAmB,GAAEoC,OAAO,CAAC,CAAD,CAAI,YAAd,GACf,qBAAoB,KAAKpF,WAAY,GAAEoF,OAAO,CAAC,CAAD,CAAI,IAAGA,OAAO,CAAC,CAAD,CAAI,EADjD,GAEf,GAAE,KAAKnF,SAAU,EAFpB;AAGAsB,sBAAAA,UAAU,GAAGA,UAAU,CAACO,OAAX,CAAmBsD,OAAO,CAAC,CAAD,CAA1B,EAA+BI,SAA/B,CAAb;AACAnD,sBAAAA,MAAM,CAACW,IAAP,CAAY;AAAC+B,wBAAAA,EAAE,EAAEG,KAAL;AAAYF,wBAAAA,EAAE,EAAE7C,UAAU,CAAC,CAAD;AAA1B,uBAAZ;AACD,qBAfE,CAeD;;AACH,mBAtC+D,CAsC9D;;AACH,eAxCD,CAwCE;AAxCF,mBAyCK;AACHE,kBAAAA,MAAM,CAACW,IAAP,CAAY;AAAC+B,oBAAAA,EAAE,EAAEG,KAAL;AAAYF,oBAAAA,EAAE,EAAET,OAAO,CAACU,CAAD;AAAvB,mBAAZ;AACD;AACF,aA9CD,MA+CK;AACH5C,cAAAA,MAAM,CAACW,IAAP,CAAY;AAAC+B,gBAAAA,EAAE,EAAEG,KAAL;AAAYF,gBAAAA,EAAE,EAAET,OAAO,CAACU,CAAD;AAAvB,eAAZ;AACD;AACF,WAlF0B,CAkFzB;;AACH,SAtFiB,CAsFhB;;AACH,OA3HiB,CA2HhB;;AACH,KAtJ+B,CAsJ9B;;;AACF,WAAO,CAAC5C,MAAD,EAASd,UAAT,EAAqBG,aAArB,CAAP;AACD,GAnsBqB,CAmsBpB;;AAGF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BAmB,EAAAA,cAAc,CAAC4C,IAAD,EAAOlE,UAAP,EAAmB;AAC/B,QAAIG,aAAa,GAAG,KAApB;AACA,QAAIgE,MAAM,GAAG,EAAb;AACA,QAAIC,OAAO,GAAG,IAAd;AACA,QAAIC,WAAW,GAAG,IAAlB;AACA,QAAIC,WAAW,GAAG,IAAlB,CAL+B,CAO/B;AACA;AACA;AACA;AACA;AACA;;AACA,QAAIC,KAAK,GAAGL,IAAI,CAAC5D,OAAL,CAAa,KAAKlC,WAAlB,CAAZ;AACA,QAAIoG,OAAO,GAAG,IAAd;;AACA,QAAID,KAAK,GAAG,CAAZ,EAAe;AACbC,MAAAA,OAAO,GAAGN,IAAI,CAACpC,MAAL,CAAY,CAAZ,EAAeyC,KAAK,GAAG,CAAvB,CAAV;AACD;;AACD,QAAIE,KAAK,GAAGP,IAAI,CAACQ,WAAL,CAAiB,KAAKtG,WAAtB,CAAZ;AACA,QAAIuG,OAAO,GAAG,IAAd;;AACA,QAAIF,KAAK,GAAG,KAAKpG,SAAb,GAAyB6F,IAAI,CAAC5F,MAAlC,EAA0C;AACxCqG,MAAAA,OAAO,GAAGT,IAAI,CAACpC,MAAL,CAAY2C,KAAK,GAAG,KAAKpG,SAAzB,CAAV;AACD,KAtB8B,CAwB/B;;;AACA,QAAIuG,QAAQ,GAAGV,IAAI,CAAClC,SAAL,CAAeuC,KAAK,GAAG,KAAKlG,SAA5B,EAAuCoG,KAAvC,CAAf,CAzB+B,CA2B/B;AACA;;AACA,QAAI/D,SAAS,CAAC0C,eAAV,CAA0BwB,QAA1B,CAAJ,EAAyC;AACvCR,MAAAA,OAAO,GAAG,KAAKxF,YAAL,CAAkBwC,MAAM,CAACwD,QAAD,CAAxB,CAAV;;AACA,UAAI,CAAClE,SAAS,CAACC,aAAV,CAAwByD,OAAxB,CAAL,EAAuC;AACrCF,QAAAA,IAAI,GAAGE,OAAO,CAACS,OAAf;AACD,OAFD,MAGK;AACHX,QAAAA,IAAI,GAAGE,OAAP;AACD;AACF,KARD,CASA;AATA,SAUK;AACH,cAAO,IAAI1E,KAAJ,CAAW,4CAA2CkF,QAAS,GAArD,GACd,YAAWV,IAAK,GADZ,CAAP;AAED,OA1C8B,CA4C/B;AACA;;;AACA,QAAIM,OAAJ,EAAa;AACX;AACA,UAAI9D,SAAS,CAAC0C,eAAV,CAA0BoB,OAA1B,CAAJ,EAAwC;AACtC,YAAIM,IAAI,GAAGV,OAAO,CAACW,WAAR,CAAoB,YAApB,CAAX;AACAD,QAAAA,IAAI,IAAI1D,MAAM,CAACoD,OAAD,CAAd;AACAJ,QAAAA,OAAO,CAACY,UAAR,CAAmB;AAAC,wBAAcF;AAAf,SAAnB;AACAZ,QAAAA,IAAI,GAAI,GAAEM,OAAQ,IAAGN,IAAK,EAA1B;AACA,aAAKvF,OAAL,CAAa8C,IAAb,CAAmB,GAAE+C,OAAQ,GAAEN,IAAK,8BAAlB,GAChB,KAAKzF,WADW,GACGyF,IADH,GACU,KAAKxF,SADjC;AAED,OAPD,MAQK;AACH,YAAI8F,OAAO,CAAClE,OAAR,CAAgB,KAAK/B,UAArB,KAAoC,CAAxC,EAA2C;AACzC,cAAI0G,OAAO,GAAG,KAAKC,YAAL,CAAkBV,OAAlB,EAA2BxE,UAA3B,CAAd,CADyC,CAEzC;AACA;AACA;AACA;;;AACA,cAAIiF,OAAO,CAAC,CAAD,CAAP,IAAcA,OAAO,CAAC,CAAD,CAAzB,EAA8B;AAC5B,kBAAO,IAAIvF,KAAJ,CAAW,qCAAD,GACd,GAAE8E,OAAQ,iDADI,GAEd,0BAAyBJ,OAAO,CAACS,OAAQ,EAFrC,CAAP;AAGD,WAVwC,CAWzC;AACA;;;AACAX,UAAAA,IAAI,IAAIe,OAAO,CAAC,CAAD,CAAf;AACA,eAAKtG,OAAL,CAAa8C,IAAb,CAAmB,kBAAiBwD,OAAO,CAAC,CAAD,CAAI,mBAA7B,GACf,oBADe,GACO,KAAKxG,WADZ,GAC0ByF,IAD1B,GACiC,KAAKxF,SADxD;AAED,SAhBD,CAiBA;AACA;AACA;AAnBA,aAoBK,IAAI,CAAC,KAAKqB,YAAV,EAAwB;AAC3B,iBAAKpB,OAAL,CAAa8C,IAAb,CAAmB,GAAE+C,OAAQ,4BAA2BN,IAAK,GAA3C,GACf,6CADH;AAEA/D,YAAAA,aAAa,GAAG,IAAhB;AACD,WAJI,CAKL;AALK,eAMA;AACH,kBAAIgF,WAAW,GAAG,KAAKC,eAAL,CAAqBZ,OAArB,CAAlB;;AACArE,cAAAA,aAAa,GAAKgF,WAAW,KAAK,WAAlC;AAED,aA/BE,CA+BD;AACA;;AACH,OA3CU,CA2CT;;AACH,KA1F8B,CA0F7B;AAEF;;;AACA,QAAIR,OAAJ,EAAa;AACX;AACA,UAAIA,OAAO,CAACrE,OAAR,CAAgB,KAAK/B,UAArB,KAAoC,CAAxC,EAA2C;AACzC,YAAI0G,OAAO,GAAG,KAAKC,YAAL,CAAkBP,OAAlB,EAA2B3E,UAA3B,CAAd,CADyC,CAEzC;AACA;AACA;AACA;;;AACA,YAAIiF,OAAO,CAAC,CAAD,CAAP,IAAcA,OAAO,CAAC,CAAD,CAAzB,EAA8B;AAC5B,gBAAO,IAAIvF,KAAJ,CAAW,oCAAD,GACd,GAAEiF,OAAQ,iDADI,GAEd,0BAAyBP,OAAO,CAACS,OAAQ,EAFrC,CAAP;AAGD,SAVwC,CAWzC;AACA;;;AACAX,QAAAA,IAAI,IAAIe,OAAO,CAAC,CAAD,CAAf;AACD,OAdD,CAeA;AACA;AAhBA,WAiBK;AAEH,cAAIvE,SAAS,CAAC0C,eAAV,CAA0BuB,OAA1B,CAAJ,EAAwC;AACtCT,YAAAA,IAAI,IAAIS,OAAR;AACAP,YAAAA,OAAO,GAAGA,OAAO,CAACiB,KAAR,CAAcjE,MAAM,CAACuD,OAAD,CAApB,CAAV;AACA,iBAAKhG,OAAL,CAAa8C,IAAb,CAAmB,gBAAekD,OAAQ,4BAAxB,GACf,8DADe,GAEhB,KAAKlG,WAFW,GAEGyF,IAFH,GAEU,KAAKxF,SAFjC;AAGD,WAND,CAOA;AACA;AACA;AATA,eAUK,IAAI,CAAC,KAAKqB,YAAV,EAAwB;AAC3B,mBAAKpB,OAAL,CAAa8C,IAAb,CAAmB,QAAOkD,OAAQ,4BAA2BT,IAAK,GAAhD,GACf,6CADH;AAEA/D,cAAAA,aAAa,GAAG,IAAhB;AACD,aAJI,CAKL;AALK,iBAMA;AACH,oBAAIgF,WAAW,GAAG,KAAKC,eAAL,CAAqBZ,OAArB,CAAlB;;AACArE,gBAAAA,aAAa,GAAKgF,WAAW,KAAK,WAAlC;AACD,eArBE,CAqBD;;AACH,SAzCU,CAyCT;;AACH,KAvI8B,CAuI7B;;;AACF,QAAI,CAAChF,aAAL,EAAoB;AAClB,UAAI,CAACiE,OAAL,EAAc;AACZA,QAAAA,OAAO,GAAG,IAAI3G,IAAJ,CAAS;AACjB,qBAAWyG,IADM;AAEjB,wBAAc,CAFG;AAGjB,mBAASA;AAHQ,SAAT,CAAV;AAID,OALD,MAMK,IAAIxD,SAAS,CAACC,aAAV,CAAwByD,OAAxB,CAAJ,EAAsC;AACzCA,QAAAA,OAAO,GAAG,IAAI3G,IAAJ,CAAS;AAAC,qBAAW2G,OAAZ;AACnB,wBAAcA,OADK;AAEnB,mBAASA;AAFU,SAAT,CAAV;AAGD,OAJI,MAKA;AACHA,QAAAA,OAAO,CAACS,OAAR,GAAkBX,IAAlB;AACD;AACF;;AACD,WAAO,CAACE,OAAD,EAAUjE,aAAV,CAAP;AACD,GA33BqB,CA23BpB;;AAEF;;;;;;;;;;;;;;;;;;;;;;;;AAsBA+E,EAAAA,YAAY,CAAChB,IAAD,EAAOlE,UAAP,EAAmB;AAE7B;AACA;AACA,QAAIsF,KAAK,GAAGpB,IAAI,CAAC5D,OAAL,CAAa,KAAK/B,UAAlB,CAAZ;AACA,QAAIgH,SAAS,GAAID,KAAK,GAAG,CAAT,GAAcpB,IAAI,CAAClC,SAAL,CAAe,CAAf,EAAkBsD,KAAlB,CAAd,GAAyC,IAAzD;;AACA,QAAIA,KAAK,KAAK,CAAd,EAAiB;AACfpB,MAAAA,IAAI,GAAGA,IAAI,CAACpC,MAAL,CAAYwD,KAAZ,CAAP;AACD,KAR4B,CAU7B;;;AACA,QAAIE,KAAK,GAAGtB,IAAI,CAAC5D,OAAL,CAAa,KAAK/B,UAAlB,EAA8B,CAA9B,CAAZ;AACA,QAAIkH,OAAO,GAAKD,KAAK,GAAG,KAAKhH,SAAd,GAA2B0F,IAAI,CAAC5F,MAAjC,GACZ4F,IAAI,CAACpC,MAAL,CAAY0D,KAAK,GAAG,KAAKhH,SAAzB,CADY,GAC0B,IADxC,CAZ6B,CAe7B;AACA;;AACA,QAAIkH,GAAG,GAAGxB,IAAI,CAAClC,SAAL,CAAe,KAAKxD,SAApB,EAA+BgH,KAA/B,CAAV;AACA,QAAIG,MAAM,GAAGvE,MAAM,CAACsE,GAAD,CAAnB;;AACA,QAAI,CAAChF,SAAS,CAAC0C,eAAV,CAA0BsC,GAA1B,CAAD,IAAmCC,MAAM,IAAI,KAAK9G,YAAL,CAAkBP,MAAnE,EAA2E;AACzE,YAAO,IAAIoB,KAAJ,CAAW,+CAA8CgG,GAAI,SAAnD,GACd,MAAKxB,IAAK,0BAAyBlE,UAAW,EAD1C,CAAP;AAED,KAtB4B,CAwB7B;;;AACAkE,IAAAA,IAAI,GAAG,KAAKrF,YAAL,CAAkB8G,MAAlB,CAAP;AACA,WAAO,CAACzB,IAAD,EAAOqB,SAAP,EAAkBE,OAAlB,CAAP;AACD,GA96BqB,CA86BpB;;AAGF;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBAL,EAAAA,eAAe,CAAClB,IAAD,EAAO;AAEpB,QAAIjE,MAAM,GAAGS,SAAS,CAACkF,WAAV,CAAsB1B,IAAtB,CAAb;;AACA,QAAIjE,MAAM,CAAC,QAAD,CAAN,KAAqB,WAAzB,EAAsC;AACpC,UAAI4F,OAAO,GAAG,EAAd;AACAA,MAAAA,OAAO,CAAC,KAAD,CAAP,GAAkB,GAAE3B,IAAK,gDAAR,GACC,qCADlB;AAEA2B,MAAAA,OAAO,CAAC,aAAD,CAAP,GAAyB3B,IAAzB;AACA,UAAI4B,MAAM,GAAG7F,MAAM,CAAC,OAAD,CAAN,CAAgB3B,MAA7B;AACAuH,MAAAA,OAAO,CAAC,OAAD,CAAP,GAAmB,EAAnB;;AACA,WAAK,IAAIE,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGD,MAApB,EAA4BC,CAAC,EAA7B,EAAiC;AAC/B,YAAIC,IAAI,GAAG/F,MAAM,CAAC,OAAD,CAAN,CAAgB8F,CAAhB,CAAX;AACA,YAAIE,SAAS,GAAG,CAACD,IAAI,CAAC,MAAD,CAAL,EAAeA,IAAI,CAAC,MAAD,CAAnB,EAA6BA,IAAI,CAAC,UAAD,CAAjC,CAAhB;AAEAH,QAAAA,OAAO,CAAC,OAAD,CAAP,CAAiBpE,IAAjB,CAAsBwE,SAAtB;AACD;;AACD,WAAKlG,YAAL,CAAkB0B,IAAlB,CAAuBoE,OAAvB;AACD,KAdD,MAeK;AACH,WAAKlH,OAAL,CAAa8C,IAAb,CAAmB,GAAEyC,IAAK,8CAAR,GACL,aADb;AAED;;AACD,WAAOjE,MAAM,CAAC,QAAD,CAAb;AACD,GAj+BqB,CAi+BpB;;AAGF;;;;;;;;;;;;;;;;;;;;;;;AAqBAuB,EAAAA,SAAS,CAAC0E,KAAD,EAAQlG,UAAR,EAAoB;AAE3B;AACA;AACA,QAAIoE,OAAO,GAAG,KAAKtG,MAAL,CAAYqI,aAAZ,CAA0BD,KAA1B,CAAd;;AACA,QAAI9B,OAAJ,EAAa;AACXA,MAAAA,OAAO,GAAGA,OAAO,CAACgC,KAAR,EAAV;AACD,KAFD,CAIA;AACA;AALA,SAMK,IAAIF,KAAK,CAAC5F,OAAN,CAAc,KAAK/B,UAAnB,KAAkC,CAAtC,EAAyC;AAC5C,YAAI8H,UAAU,GAAG,KAAKC,sBAAL,CAA4BJ,KAA5B,EAAmClG,UAAnC,CAAjB;;AACAoE,QAAAA,OAAO,GAAGiC,UAAU,CAAC,CAAD,CAApB;;AACA,YAAIjC,OAAJ,EAAa;AACXpE,UAAAA,UAAU,GAAGqG,UAAU,CAAC,CAAD,CAAvB;AACD,SAL2C,CAM5C;AACA;AACA;AACA;;AACD,OAVI,CAUH;AAVG,WAYA;AAEH;AACA;AACA;AAEA,cAAIH,KAAK,CAAC5F,OAAN,CAAc,GAAd,IAAqB,CAAC,CAA1B,EAA6B;AAC3B,gBAAIiG,OAAO,GAAGL,KAAK,CAAC3F,OAAN,CAAc,GAAd,EAAmB,GAAnB,CAAd;AACA6D,YAAAA,OAAO,GAAG,KAAKtG,MAAL,CAAYqI,aAAZ,CAA0BI,OAA1B,CAAV;;AACA,gBAAInC,OAAJ,EAAa;AACXA,cAAAA,OAAO,GAAGA,OAAO,CAACgC,KAAR,EAAV;AACAhC,cAAAA,OAAO,CAACS,OAAR,GAAkBT,OAAO,CAACS,OAAR,CAAgBtE,OAAhB,CAAwB,GAAxB,EAA6B,GAA7B,CAAlB;AACA6D,cAAAA,OAAO,CAACoC,OAAR,GAAkBpC,OAAO,CAACoC,OAAR,CAAgBjG,OAAhB,CAAwB,GAAxB,EAA6B,GAA7B,CAAlB;AACD;AACF,WAdE,CAeH;AACA;;;AACA,cAAI,CAAC6D,OAAL,EAAc;AACZ,gBAAIqC,WAAW,GAAG,MAAMP,KAAN,GAAc,GAAhC;AACA9B,YAAAA,OAAO,GAAG,KAAKtG,MAAL,CAAYqI,aAAZ,CAA0BM,WAA1B,CAAV;;AACA,gBAAIrC,OAAJ,EAAa;AACXA,cAAAA,OAAO,GAAGA,OAAO,CAACgC,KAAR,EAAV;AACApG,cAAAA,UAAU,GAAGA,UAAU,CAACO,OAAX,CAAmB2F,KAAnB,EAA0BO,WAA1B,CAAb;AACA,mBAAK9H,OAAL,CAAa8C,IAAb,CAAmB,GAAEyE,KAAM,uCAAT,GACf,GAAEO,WAAY,QADC,GACS,KAAKhI,WADd,GAEf,GAAEgI,WAAY,KAAIrC,OAAO,CAACsC,KAAM,IAAG,KAAKhI,SAAU,EAFrD;AAGD,aATW,CASV;;AACH,WA3BE,CA2BD;AAEF;;;AACA,cAAI,CAAC0F,OAAL,EAAc;AACZ,gBAAIuC,UAAU,GAAG,KAAK7I,MAAL,CAAY8I,aAAZ,CAA0BV,KAA1B,CAAjB;;AACA,gBAAIS,UAAU,IAAIA,UAAU,CAACrI,MAAX,GAAoB,CAAtC,EAAyC;AACvC8F,cAAAA,OAAO,GAAGuC,UAAU,CAAC,CAAD,CAAV,CAAcP,KAAd,EAAV;AACA,kBAAIS,OAAO,GAAG,uBAAuBX,KAAvB,GAA+B,MAA/B,GACZ9B,OAAO,CAACS,OADI,GACM,KADN,GACc,KAAKpG,WADnB,GAEZ2F,OAAO,CAACS,OAFI,GAEM,KAAKnG,SAFzB;AAGA,kBAAIoI,MAAM,GAAG,KAAb;;AACA,mBAAK,IAAIC,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAG,KAAKpI,OAAL,CAAaL,MAAjB,IAA2B,CAACwI,MAA5C,EAAoDC,CAAC,EAArD,EACED,MAAM,GAAG,KAAKnI,OAAL,CAAaoI,CAAb,MAAoBF,OAA7B;;AACF,kBAAI,CAACC,MAAL,EACE,KAAKnI,OAAL,CAAa8C,IAAb,CAAkBoF,OAAlB;AACF,kBAAIG,IAAI,GAAG,IAAIC,MAAJ,CAAW,iBAAiBf,KAAjB,GAAyB,cAApC,CAAX;AACA,kBAAIgB,GAAG,GAAGlH,UAAU,CAACiD,KAAX,CAAiB+D,IAAjB,CAAV;AACAhH,cAAAA,UAAU,GAAGA,UAAU,CAACO,OAAX,CAAmByG,IAAnB,EAAyBE,GAAG,CAAC,CAAD,CAAH,GAAS9C,OAAO,CAACS,OAAjB,GAA2BqC,GAAG,CAAC,CAAD,CAAvD,CAAb;AACAhB,cAAAA,KAAK,GAAG9B,OAAO,CAACS,OAAhB;AACD;AACF,WA/CE,CAiDH;AACA;;;AACA,cAAI,CAACT,OAAL,EAAc;AAEZ;AACA;AACA;AACA,gBAAIhE,KAAK,GAAG,IAAZ;;AACA,iBAAKA,KAAL,IAAc7C,IAAI,CAAC8C,UAAnB,EAA+B;AAC7B,kBAAI6F,KAAK,CAAC5F,OAAN,CAAc/C,IAAI,CAAC8C,UAAL,CAAgBD,KAAhB,CAAd,MAA0C,CAAC,CAA/C,EACE8F,KAAK,GAAGA,KAAK,CAAC3F,OAAN,CAAchD,IAAI,CAAC8C,UAAL,CAAgBD,KAAhB,CAAd,EAAsCA,KAAtC,CAAR;AACH;;AACDgE,YAAAA,OAAO,GAAG,KAAKtG,MAAL,CAAYqI,aAAZ,CAA0BD,KAA1B,CAAV;AACA,gBAAI9B,OAAJ,EACEA,OAAO,GAAGA,OAAO,CAACgC,KAAR,EAAV;AACH;;AACD,cAAI,CAAChC,OAAL,EAAc;AAEZ,gBAAI+C,QAAQ,GAAGjB,KAAf;AACA,gBAAIkB,QAAQ,GAAG,IAAf;AACA,gBAAIC,GAAG,GAAG,IAAV;AACA,gBAAIC,OAAO,GAAG,IAAd;AACA,gBAAIC,MAAM,GAAG,IAAb;AACA,gBAAIC,MAAM,GAAG,IAAb;AACA,gBAAIC,MAAM,GAAG,IAAb,CARY,CAUZ;AACA;;AACA,gBAAIC,UAAU,GAAG,KAAKC,mBAAL,CAAyBzB,KAAzB,CAAjB;;AACA,gBAAIwB,UAAJ,EAAgB;AACdxB,cAAAA,KAAK,GAAGwB,UAAU,CAAC,CAAD,CAAlB;AACAL,cAAAA,GAAG,GAAGK,UAAU,CAAC,CAAD,CAAhB;AACAN,cAAAA,QAAQ,GAAG,KAAKtJ,MAAL,CAAYqI,aAAZ,CAA0BD,KAA1B,CAAX;AACD,aAjBW,CAoBZ;AACA;;;AACA,gBAAI,CAACkB,QAAL,EAAe;AACb;AACAE,cAAAA,OAAO,GAAGpB,KAAK,CAAC0B,MAAN,CAAa,CAAb,CAAV;AACAL,cAAAA,MAAM,GAAG,KAAKvJ,QAAL,CAAc6J,eAAd,CAA8BP,OAA9B,CAAT,CAHa,CAKb;;AACA,kBAAIC,MAAJ,EAAY;AACVC,gBAAAA,MAAM,GAAGD,MAAM,CAACO,QAAP,EAAT;AACAL,gBAAAA,MAAM,GAAGF,MAAM,CAACQ,MAAP,EAAT;AACA,oBAAIC,QAAQ,GAAGV,OAAO,CAAChJ,MAAvB;AACA4H,gBAAAA,KAAK,GAAGA,KAAK,CAACpE,MAAN,CAAakG,QAAb,CAAR,CAJU,CAMV;;AACAZ,gBAAAA,QAAQ,GAAG,KAAKtJ,MAAL,CAAYqI,aAAZ,CAA0BD,KAA1B,CAAX,CAPU,CASV;AACA;AACA;AACA;;AAEA,oBAAI,CAACkB,QAAD,IAAaE,OAAO,IAAI,GAAxB,IAA+BpB,KAAK,CAACpE,MAAN,CAAa,CAAb,EAAgB,CAAhB,KAAsB,GAAzD,EAA8D;AAC5DwF,kBAAAA,OAAO,GAAG,IAAV;AACAC,kBAAAA,MAAM,GAAG,KAAKvJ,QAAL,CAAc6J,eAAd,CAA8BP,OAA9B,CAAT;AACAE,kBAAAA,MAAM,GAAGD,MAAM,CAACO,QAAP,EAAT;AACA5B,kBAAAA,KAAK,GAAGA,KAAK,CAACpE,MAAN,CAAa,CAAb,CAAR,CAJ4D,CAM5D;;AACAsF,kBAAAA,QAAQ,GAAG,KAAKtJ,MAAL,CAAYqI,aAAZ,CAA0BD,KAA1B,CAAX;AACD,iBAtBS,CAwBV;AACA;AACA;AACA;AACA;;;AACA,oBAAIkB,QAAQ,IAAIA,QAAQ,CAACa,OAAT,IAAoB,OAApC,EACEb,QAAQ,GAAG,IAAX;AACH,eArCY,CAqCX;;AACH,aA5DW,CA4DV;AAEF;AACA;AACA;AACA;;;AACA,gBAAI,CAACA,QAAL,EAAe;AACbhD,cAAAA,OAAO,GAAG,IAAV,CADa,CAEb;;AACA,kBAAI,KAAKrE,YAAT,EAAuB;AACrB,oBAAIoF,WAAW,GAAG,KAAKC,eAAL,CAAqB+B,QAArB,CAAlB;AACD,eAFD,MAGK;AACH,qBAAKxI,OAAL,CAAa8C,IAAb,CAAmB,GAAE0F,QAAS,4BAA9B;AACD;AACF,aATD,MAUK;AACH;AACA;AACA/C,cAAAA,OAAO,GAAGgD,QAAQ,CAAChB,KAAT,EAAV,CAHG,CAIH;AACA;AACA;;AACAhC,cAAAA,OAAO,CAAC8D,yBAAR;AACA,kBAAIC,MAAM,GAAG/D,OAAO,CAACW,WAAR,CAAoB,MAApB,CAAb;AACA,kBAAIqD,MAAM,GAAGhE,OAAO,CAACW,WAAR,CAAoB,YAApB,CAAb;AACA,kBAAIsD,OAAO,GAAGjE,OAAO,CAACW,WAAR,CAAoB,OAApB,CAAd;AACA,kBAAIuD,SAAS,GAAGlE,OAAO,CAACW,WAAR,CAAoB,SAApB,CAAhB;AACA,kBAAIwD,cAAc,GAAGnE,OAAO,CAACW,WAAR,CAAoB,cAApB,CAArB,CAZG,CAaH;AACA;;AACA,kBAAIsC,GAAJ,EAAS;AACPA,gBAAAA,GAAG,GAAGmB,QAAQ,CAACnB,GAAD,CAAd;AACA,oBAAIoB,MAAM,GAAGpB,GAAb;AACA,oBAAIc,MAAJ,EACEA,MAAM,GAAGA,MAAM,CAACO,GAAP,CAAWrB,GAAX,CAAT;AACFe,gBAAAA,MAAM,GAAGO,IAAI,CAACC,GAAL,CAASR,MAAT,EAAiBf,GAAjB,CAAT;AACAjD,gBAAAA,OAAO,CAACY,UAAR,CAAmB;AAAC,gCAAcoD;AAAf,iBAAnB,EANO,CAQP;;AACA,oBAAIb,MAAJ,EAAY;AAEV;AACA;AACA;AACA;AACA,sBAAIE,MAAJ,EAAY;AACVgB,oBAAAA,MAAM,IAAIlB,MAAM,CAACQ,MAAP,EAAV;AACAP,oBAAAA,MAAM,GAAGmB,IAAI,CAACC,GAAL,CAAS,EAAT,EAAaH,MAAb,CAAT;AACD,mBATS,CAUV;AACA;AACA;AACA;AACA;AACA;;AACD,iBAzBM,CAyBL;;AACH,eAzCE,CAyCD;AAEF;AACA;;;AACA,kBAAIlB,MAAJ,EAAY;AACV,oBAAInD,OAAO,CAACyE,IAAZ,EAAkB;AAChBzE,kBAAAA,OAAO,CAACY,UAAR,CAAmB;AAAC,+BAAWwC;AAAZ,mBAAnB;AACD,iBAFD,MAGK;AACHY,kBAAAA,MAAM,IAAIZ,MAAV;AACApD,kBAAAA,OAAO,CAACY,UAAR,CAAmB;AAAC,kCAAcoD;AAAf,mBAAnB;AACD;AACF,eArDE,CAsDH;AACA;;;AACA,kBAAIU,OAAO,GAAG1E,OAAO,CAACS,OAAtB;;AACA,kBAAI0C,MAAJ,EAAY;AACVc,gBAAAA,OAAO,GAAGd,MAAM,CAACwB,OAAP,KAAmBV,OAA7B;AACAS,gBAAAA,OAAO,GAAGxB,OAAO,GAAGwB,OAApB;AACAR,gBAAAA,SAAS,GAAGf,MAAM,CAACyB,SAAP,KAAqBV,SAAjC;AACAC,gBAAAA,cAAc,GAAGhB,MAAM,CAAC0B,cAAP,KAA0BV,cAA3C;AACAnE,gBAAAA,OAAO,CAACY,UAAR,CAAmB;AACjB,2BAASqD,OADQ;AAEjB,6BAAWS,OAFM;AAGjB,6BAAWR,SAHM;AAIjB,kCAAgBC;AAJC,iBAAnB;AAMD;;AACD,kBAAIlB,GAAJ,EAAS;AACP,oBAAI6B,MAAM,GAAG7B,GAAG,CAACnF,QAAJ,EAAb;AACAkC,gBAAAA,OAAO,CAACY,UAAR,CAAmB;AACjB,2BAASqD,OAAO,GAAG,OAAV,GAAoBa,MAApB,GAA6B,QADrB;AAEjB,6BAAWJ,OAAO,GAAGI,MAFJ;AAGjB,6BAAWZ,SAAS,GAAGY,MAHN;AAIjB,kCAAgBX,cAAc,GAAG,OAAjB,GAA2BW,MAA3B,GAAoC;AAJnC,iBAAnB;AAMD;AACF,aA1JW,CA0JV;;AAEH,WA7NE,CA6ND;;AACH,SArP0B,CAqPzB;;;AACF,WAAO,CAAC9E,OAAD,EAAUpE,UAAV,CAAP;AACD,GAhvCqB,CAgvCpB;;AAGF;;;;;;;;;;;;;;;AAaAsG,EAAAA,sBAAsB,CAACJ,KAAD,EAAQlG,UAAR,EAAoB;AAExC,QAAIoE,OAAO,GAAG,IAAd,CAFwC,CAIxC;;AACA,QAAIa,OAAO,GAAG,KAAKC,YAAL,CAAkBgB,KAAlB,EAAyBlG,UAAzB,CAAd;;AACA,QAAImJ,QAAQ,GAAGlE,OAAO,CAAC,CAAD,CAAtB;AACA,QAAIZ,WAAW,GAAGY,OAAO,CAAC,CAAD,CAAzB;AACA,QAAIX,WAAW,GAAGW,OAAO,CAAC,CAAD,CAAzB,CARwC,CAUxC;;AAEA,QAAI,KAAK9G,UAAL,IAAmB,KAAKQ,OAAL,CAAa2B,OAAb,CAAqB,KAAKnC,UAA1B,MAA0C,CAAC,CAAlE,EACE,KAAKQ,OAAL,CAAa8C,IAAb,CAAkB,KAAKtD,UAAvB,EAbsC,CAexC;AACA;AACA;AACA;AACA;;AACA,QAAIiL,MAAM,GAAG,KAAKzK,OAAL,CAAaL,MAA1B;;AACA,QAAI,CAAC+F,WAAD,IAAgB,CAACC,WAArB,EAAkC;AAChC,UAAI+E,WAAW,GAAG,MAAMF,QAAQ,CAACnH,SAAT,CAAmB,CAAnB,EAAsBmH,QAAQ,CAAC7K,MAAT,GAAkB,CAAxC,CAAN,GAAmD,GAArE;;AACA,UAAIgL,SAAS,GAAG,KAAK9H,SAAL,CAAe6H,WAAf,EAA4BrJ,UAA5B,CAAhB,CAFgC,CAIhC;AACA;;;AACA,UAAIsJ,SAAS,CAAC,CAAD,CAAb,EAAkB;AAChBlF,QAAAA,OAAO,GAAGkF,SAAS,CAAC,CAAD,CAAnB;AACAtJ,QAAAA,UAAU,GAAGA,UAAU,CAACO,OAAX,CAAmB4I,QAAnB,EAA6BE,WAA7B,CAAb;AACA,aAAK1K,OAAL,CAAa8C,IAAb,CAAmB,GAAE0H,QAAS,uCAAZ,GACf,GAAEE,WAAY,QADC,GACS,KAAK5K,WADd,GAEf,GAAE4K,WAAY,KAAIjF,OAAO,CAACsC,KAAM,IAAG,KAAKhI,SAAU,EAFrD;AAGD,OAND,CAOA;AAPA,WAQK;AACH;AACA,cAAI,KAAKC,OAAL,CAAaL,MAAb,GAAsB8K,MAA1B,EAAkC;AAChC,iBAAKzK,OAAL,CAAa4K,GAAb;AACD;;AACDrD,UAAAA,KAAK,GAAG,CAAR;AACA9B,UAAAA,OAAO,GAAG,CAAV;AACD;AACF,KAtBD,CAsBE;AAtBF,SAwBK;AACH;AACA;AACA;AACA,YAAIC,WAAW,IAAI,CAACC,WAApB,EAAiC;AAC/B;AACA;AACA;AACA,cAAI5D,SAAS,CAACC,aAAV,CAAwB0D,WAAxB,CAAJ,EAA0C;AACxCD,YAAAA,OAAO,GAAGC,WAAV;AACD,WAFD,CAGA;AAHA,eAIK;AACH,kBAAIiF,SAAS,GAAG,KAAK9H,SAAL,CAAe6C,WAAf,EAA4BrE,UAA5B,CAAhB,CADG,CAGH;;;AACA,kBAAIsJ,SAAS,CAAC,CAAD,CAAb,EAAkB;AAChBlF,gBAAAA,OAAO,GAAGkF,SAAS,CAAC,CAAD,CAAnB;AACAlF,gBAAAA,OAAO,CAACS,OAAR,IAAmBsE,QAAnB;AACAnJ,gBAAAA,UAAU,GAAGsJ,SAAS,CAAC,CAAD,CAAtB;AACD,eAJD,CAKA;AALA,mBAMK;AACH,uBAAK3K,OAAL,CAAa8C,IAAb,CAAmB,6BAA4B4C,WAAY,QAAzC,GACf,2BAA0B8E,QAAS,GADtC;AAED;AACF;AACF,SAvBD,CAwBA;AACA;AACA;AA1BA,aA2BK,IAAI,CAAC9E,WAAD,IAAgBC,WAApB,EAAiC;AAEpC;AACA;AACA,gBAAI5D,SAAS,CAACC,aAAV,CAAwB2D,WAAxB,CAAJ,EAA0C;AACxCF,cAAAA,OAAO,GAAGE,WAAW,GAAG6E,QAAxB;AACA,mBAAKxK,OAAL,CAAa8C,IAAb,CAAmB,kBAAiB0H,QAAS,cAC1C,GAAE7E,WAAY,gBADC,GACiB,KAAK7F,WADtB,GACoC2F,OADpC,GAEhB,KAAK1F,SAFP;AAGD,aALD,MAMK;AACH,kBAAI4K,SAAS,GAAG,KAAK9H,SAAL,CAAe8C,WAAf,EAA4BtE,UAA5B,CAAhB;;AACA,kBAAIsJ,SAAS,CAAC,CAAD,CAAb,EAAkB;AAChBlF,gBAAAA,OAAO,GAAGkF,SAAS,CAAC,CAAD,CAAnB;AACAlF,gBAAAA,OAAO,CAACS,OAAR,IAAmBsE,QAAnB;AACAnJ,gBAAAA,UAAU,GAAGoE,OAAO,CAACS,OAArB;AACA,qBAAKlG,OAAL,CAAa8C,IAAb,CAAmB,kBAAiB0H,QAAS,mBAA3B,GACf,oBADe,GACO,KAAK1K,WADZ,GAC0B2F,OAAO,CAACS,OADlC,GAEhB,KAAKnG,SAFP;AAGD,eAPD,CAQA;AARA,mBASK;AACH,uBAAKC,OAAL,CAAa8C,IAAb,CAAmB,6BAA4B4C,WAAY,QAAzC,GACf,0BAAyB8E,QAAS,GADrC;AAED;AACF;AACF,WA1BI,CA2BL;AACA;AACA;AA7BK,eA8BA;AACH,mBAAKxK,OAAL,CAAa8C,IAAb,CAAmB,6BAA4B4C,WAAY,GAAE8E,QAAS,EAApD,GACf,GAAE7E,WAAY,uDADC,GAEf,kCAFH;AAGD;AACF,OA/GuC,CA+GtC;;;AAEF,WAAO,CAACF,OAAD,EAAWpE,UAAX,CAAP;AAED,GAn3CqB,CAm3CpB;;AAGF;;;;;;;;;;;;;;;;;;AAgBA0B,EAAAA,sBAAsB,CAACZ,MAAD,EAASd,UAAT,EAAqB;AAEzC,QAAIS,SAAS,GAAGK,MAAM,CAAC,CAAD,CAAN,CAAU,IAAV,CAAhB;;AACA,QAAIJ,SAAS,CAACC,aAAV,CAAwBF,SAAxB,CAAJ,EAAwC;AACtCA,MAAAA,SAAS,GAAG,IAAIhD,IAAJ,CAAS;AAAC,mBAAYgD,SAAb;AACnB,sBAAeW,MAAM,CAACX,SAAD,CADF;AAEnB,iBAAUA;AAFS,OAAT,CAAZ;AAGD;;AACD,QAAIQ,IAAI,GAAGH,MAAM,CAACxC,MAAlB;AACA,QAAI6B,aAAa,GAAG,KAApB,CATyC,CAUzC;AACA;;AACA,SAAK,IAAIqJ,EAAE,GAAG,CAAd,EAAkBA,EAAE,GAAGvI,IAAN,IAAe,CAACd,aAAjC,EAAgDqJ,EAAE,EAAlD,EAAsD;AACpD,UAAIC,QAAQ,GAAG3I,MAAM,CAAC0I,EAAD,CAAN,CAAW,IAAX,CAAf;;AACA,UAAI9I,SAAS,CAACC,aAAV,CAAwB8I,QAAxB,CAAJ,EAAuC;AACrCA,QAAAA,QAAQ,GAAG,IAAIhM,IAAJ,CAAS;AAAC,qBAAYgM,QAAb;AAClB,wBAAerI,MAAM,CAACqI,QAAD,CADH;AAElB,mBAASA;AAFS,SAAT,CAAX;AAGD;;AACD,UAAIA,QAAQ,KAAK,IAAb,IACE,OAAOA,QAAP,KAAoB,QAArB,IAAmC,CAACA,QAAQ,CAAC1E,WADlD,EACiE;AAC/D,YAAI2E,SAAS,GAAI,gBAAe1J,UAAW,0BAA3B,GACA,SADhB;;AAEA,YAAIyJ,QAAJ,EAAc;AACZC,UAAAA,SAAS,IAAK,KAAI,KAAKzL,SAAU,GAAEwL,QAAQ,CAACvH,QAAT,EAAoB,EAA1C,GACC,GAAE,KAAKhE,UAAW,GADhC;AAED;;AACDwL,QAAAA,SAAS,IAAI,uCAAb;AACA,aAAK/K,OAAL,CAAa8C,IAAb,CAAkBiI,SAAlB;AACAvJ,QAAAA,aAAa,GAAG,IAAhB;AACD,OAXD,MAYK;AACH,YAAI;AACF;AACA,cAAIwJ,MAAM,GAAG7I,MAAM,CAAC0I,EAAD,CAAN,CAAW,IAAX,CAAb;AACA,cAAII,KAAK,GAAGD,MAAM,KAAK,GAAvB,CAHE,CAKF;AACA;;AACAC,UAAAA,KAAK,GAAGnJ,SAAS,GAAGA,SAAS,CAACoJ,MAAV,CAAiBJ,QAAjB,CAAf,GACGhJ,SAAS,GAAGA,SAAS,CAACqJ,aAAV,CAAwBL,QAAxB,CADpB;AAED,SATD,CAUA,OAAOM,GAAP,EAAY;AACV,eAAKpL,OAAL,CAAawE,OAAb,CAAqB4G,GAAG,CAACC,OAAzB;AACA7J,UAAAA,aAAa,GAAG,IAAhB;AACAM,UAAAA,SAAS,GAAG,IAAZ;AACD;AACF,OAnCmD,CAmClD;;AACH,KAhDwC,CAgDvC;;;AACF,WAAOA,SAAP;AACD,GAx7CqB,CAw7CnB;;AAGH;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBAkH,EAAAA,mBAAmB,CAACzB,KAAD,EAAQ;AAEzB,QAAI+D,GAAG,GAAG,EAAV;AACA,QAAI/C,GAAG,GAAGhB,KAAK,CAACjD,KAAN,CAAY,0BAAZ,CAAV,CAHyB,CAKzB;AACA;;AACA,QAAIiE,GAAG,IAAIA,GAAG,CAAC,CAAD,CAAV,IAAiBA,GAAG,CAAC,CAAD,CAAH,KAAW,EAAhC,EAAoC;AAClC+C,MAAAA,GAAG,CAACxI,IAAJ,CAASyF,GAAG,CAAC,CAAD,CAAZ;AACA+C,MAAAA,GAAG,CAACxI,IAAJ,CAASyF,GAAG,CAAC,CAAD,CAAZ;AACD,KAHD,CAGE;AAHF,SAIK;AACH+C,QAAAA,GAAG,GAAG,IAAN;AACD;;AACD,WAAOA,GAAP;AACD,GAl+CqB,CAk+CpB;;;AAl+CoB,C,CAo+CtB;;AAGF;;;;;;;;;;;;;;;AAWArM,UAAU,CAACG,WAAX,GAAyB,YAAU;AACjC,SAAO,IAAIH,UAAJ,EAAP;AACD,CAFD;AAIA","sourcesContent":["/**\n * This class handles the parsing of a unit string into a unit object\n */\n\nvar Ucum = require('./config.js').Ucum;\nvar Unit = require('./unit.js').Unit;\nvar UnitTables = require('./unitTables.js').UnitTables;\nvar PrefixTables = require('./prefixTables.js').PrefixTables;\n\nimport * as intUtils_ from \"./ucumInternalUtils.js\";\n\nexport class UnitString {\n\n /**\n * Constructor\n */\n constructor() {\n\n // Get instances of the unit and prefix tables and the utilities\n this.utabs_ = UnitTables.getInstance();\n this.pfxTabs_ = PrefixTables.getInstance();\n\n // Set emphasis characters to defaults. These are used to emphasize\n // certain characters or strings in user messages. They can be reset in\n // the useHTMLInMessages method.\n this.openEmph_ = Ucum.openEmph_;\n this.closeEmph_ = Ucum.closeEmph_;\n\n // Set the braces message to blank. This message is displayed for each\n // validation request on the web page, but is included separately as\n // a note on the validation spreadsheet. The useBraceMsgForEachString\n // method should be used to set the message to be displayed for each\n // unit string.\n this.bracesMsg_ = '';\n\n // Set the flags used, with indices, as place holders in unit strings\n // for parenthetical strings and strings within braces.\n this.parensFlag_ = \"parens_placeholder\"; // in lieu of Jehoshaphat\n this.pFlagLen_ = this.parensFlag_.length;\n this.braceFlag_ = \"braces_placeholder\"; // in lieu of Nebuchadnezzar\n this.bFlagLen_ = this.braceFlag_.length;\n\n // Initialize the message start/end strings, which will be set when\n // parseString is called.\n this.vcMsgStart_ = null;\n this.vcMsgEnd_ = null;\n\n // Arrays used by multiple methods within this class to hold persistent\n // data. Just gets too bulky to pass these guys around.\n\n // Messages to be returned to the calling function\n this.retMsg_ = [] ;\n\n // Units for parenthetical unit strings\n this.parensUnits_ = [] ;\n\n // annotation text for annotations found in unit strings\n this.annotations_ = [] ;\n\n // suggestions for unit strings that for which no unit was found\n this.suggestions = [] ;\n\n } // end constructor\n\n\n /**\n * Sets the emphasis strings to the HTML used in the webpage display - or\n * blanks them out, depending on the use parameter.\n *\n * @param use flag indicating whether or not to use the html message format;\n * defaults to true\n */\n useHTMLInMessages(use) {\n if (use === undefined || use) {\n this.openEmph_ = Ucum.openEmphHTML_;\n this.closeEmph_ = Ucum.closeEmphHTML_;\n }\n else {\n this.openEmph_ = Ucum.openEmph_;\n this.closeEmph_ = Ucum.closeEmph_;\n }\n } // end useHTMLInMessages\n\n\n /**\n * Sets the braces message to be displayed for each unit string validation\n * requested, as appropriate.\n *\n * @param use flag indicating whether or not to use the braces message;\n * defaults to true\n */\n useBraceMsgForEachString(use) {\n if (use === undefined || use)\n this.bracesMsg_ = Ucum.bracesMsg_;\n else\n this.bracesMsg_ = '';\n }\n\n\n /**\n * Parses a unit string, returns a unit, a possibly updated version of\n * the string passed in, and messages and suggestions where appropriate.\n *\n * The string returned may be updated if the input string contained unit\n * names, e.g., \"pound\". The unit code ([lb_av] for pound) is placed in\n * the string returned, a the returned messages array includes a note\n * explaining the substitution.\n *\n * @param uStr the string defining the unit\n * @param valConv indicates what type of request this is for - a request to\n * validate (pass in 'validate') or a request to convert (pass in 'convert');\n * optional, defaults to 'validate'\n * @param suggest a boolean to indicate whether or not suggestions are\n * requested for a string that cannot be resolved to a valid unit;\n * true indicates suggestions are wanted; false indicates they are not,\n * and is the default if the parameter is not specified;\n * @returns an array containing:\n * the unit object or null if a unit could not be created. In cases where\n * a fix was found for a problem string, .e.g., 2.mg for 2mg, a unit will\n * be returned but an error message will also be returned, describing\n * the substitution;\n * the possibly updated unit string passed in;\n * an array of any user messages (informational, error or warning)\n * generated (or an empty array); and\n * a suggestions array of hash objects (1 or more). Each hash contains\n * three elements:\n * 'msg' which is a message indicating what unit expression the\n * suggestions are for;\n * 'invalidUnit' which is the unit expression the suggestions are\n * for; and\n * 'units' which is an array of data for each suggested unit found.\n * Each array will contain the unit code, the unit name and the\n * unit guidance (if any).\n * The return array will not contain a suggestions array if a valid unit\n * was found or if suggestions were not requested.\n * @throws an error if nothing was specified.\n */\n parseString(uStr, valConv, suggest) {\n\n uStr = uStr.trim();\n // Make sure we have something to work with\n if (uStr === '' || uStr === null) {\n throw (new Error('Please specify a unit expression to be validated.'));\n }\n\n if (valConv === 'validate') {\n this.vcMsgStart_ = Ucum.valMsgStart_;\n this.vcMsgEnd_ = Ucum.valMsgEnd_;\n }\n else {\n this.vcMsgStart_ = Ucum.cnvMsgStart_;\n this.vcMsgEnd_ = Ucum.cnvMsgEnd_;\n }\n\n if (suggest === undefined || suggest === false) {\n this.suggestions_ = null;\n }\n else {\n this.suggestions_ = [] ;\n }\n\n this.retMsg_ = [];\n this.parensUnits_ = [];\n this.annotations_ = [] ;\n\n let origString = uStr;\n let retObj = [];\n\n // Extract any annotations, i.e., text enclosed in braces ({}) from the\n // string before further processing. Store each one in this.annotations_\n // array and put a placeholder in the string for the annotation. Do\n // this before other processing in case an annotation contains characters\n // that will be interpreted as parenthetical markers or operators in\n // subsequent processing.\n\n uStr = this._getAnnotations(uStr);\n if (this.retMsg_.length > 0) {\n retObj[0] = null;\n retObj[1] = null;\n }\n else {\n // Flag used to block further processing on an unrecoverable error\n let endProcessing = this.retMsg_.length > 0;\n\n // First check for one of the \"special\" units. If it's one of those, put\n // in a substitution phrase for it to avoid having it separated on its\n // embedded operator. This will only happen, by the way, if it is\n // preceded by a prefix or followed by an operator and another unit.\n let sUnit = null ;\n for (sUnit in Ucum.specUnits_) {\n while (uStr.indexOf(sUnit) !== -1)\n uStr = uStr.replace(sUnit, Ucum.specUnits_[sUnit]);\n }\n\n // Check for spaces and throw an error if any are found. The spec\n // explicitly forbids spaces except in annotations, which is why any\n // annotations are extracted before this check is made.\n if (uStr.indexOf(' ') > -1) {\n throw (new Error('Blank spaces are not allowed in unit expressions.'));\n } // end if blanks were found in the string\n\n // assign the array returned to retObj. It will contain 2 elements:\n // the unit returned in position 0; and the origString (possibly\n // modified) in position 1. The origString in position 1 will not\n // be changed by subsequent processing.\n retObj = this._parseTheString(uStr, origString);\n let finalUnit = retObj[0];\n\n // Do a final check to make sure that finalUnit is a unit and not\n // just a number. Something like \"8/{HCP}\" will return a \"unit\" of 8\n // - which is not a unit. Hm - evidently it is. So just create a unit\n // object for it.\n if (intUtils_.isIntegerUnit(finalUnit) || typeof finalUnit === 'number') {\n finalUnit = new Unit({\n 'csCode_': origString,\n 'magnitude_': finalUnit,\n 'name_': origString\n });\n retObj[0] = finalUnit;\n } // end final check\n } // end if no annotation errors were found\n\n retObj[2] = this.retMsg_;\n if (this.suggestions_ && this.suggestions_.length > 0)\n retObj[3] = this.suggestions_ ;\n return retObj;\n\n } // end parseString\n\n\n /**\n * Parses a unit string, returns a unit, a possibly updated version of\n * the string passed in, and messages where appropriate. This should\n * only be called from within this class (or by test code).\n *\n * The string returned may be updated if the input string contained unit\n * names, e.g., \"pound\". The unit code ([lb_av] for pound) is placed in\n * the string returned, a the returned messages array includes a note\n * explaining the substitution.\n *\n * @param uStr the string defining the unit\n * @param origString the original unit string passed in\n *\n * @returns\n * an array containing:\n * the unit object (or null if there were problems creating the unit); and\n * the possibly updated unit string passed in.\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n * the this.parensUnits_ array is referenced and possibly populated by\n * methods called within this one\n * the this.annotations_ array is referenced by methods called within\n * this one\n * the this.suggestions_ array may be populated by methods called within\n * this one\n */\n _parseTheString(uStr, origString) {\n\n // Unit to be returned\n let finalUnit = null;\n\n // Flag used to block further processing on an unrecoverable error\n let endProcessing = this.retMsg_.length > 0;\n\n // Call _processParens to search for and process any/all parenthetical\n // strings in uStr. Units created for parenthetical strings will be\n // stored in the this.parensUnits_ array.\n let parensResp = this._processParens(uStr, origString);\n endProcessing = parensResp[2];\n\n // The array used to hold the units and their operators.\n let uArray = [];\n\n // Continue if we didn't hit a problem\n if (!endProcessing) {\n uStr = parensResp[0];\n origString = parensResp[1];\n\n // Call _makeUnitsArray to convert the string to an array of unit\n // descriptors with operators.\n let mkUArray = this._makeUnitsArray(uStr, origString);\n\n endProcessing = mkUArray[2] ;\n if (!endProcessing) {\n uArray = mkUArray[0];\n origString = mkUArray[1];\n // Create a unit object out of each un element\n let uLen = uArray.length;\n for (let u1 = 0; u1 < uLen; u1++) {\n //for (let u1 = 0; u1 < uLen && !endProcessing; u1++) {\n let curCode = uArray[u1]['un'];\n\n // Determine the type of the \"un\" attribute of the current array element\n\n // Check to see if it's a number. If so write the number version of\n // the number back to the \"un\" attribute and move on\n if (intUtils_.isIntegerUnit(curCode)) {\n uArray[u1]['un'] = Number(curCode);\n }\n\n else {\n // The current unit array element is a string. Check now to see\n // if it is or contains a parenthesized unit from this.parensUnits_.\n // If so, call _getParens to process the string and get the unit.\n\n if (curCode.indexOf(this.parensFlag_) >= 0) {\n let parenUnit = this._getParensUnit(curCode, origString);\n // if we couldn't process the string, set the end flag and bypass\n // further processing.\n if (!endProcessing)\n endProcessing = parenUnit[1];\n\n // If we're good, put the unit in the uArray and replace the\n // curCode, which contains the parentheses placeholders, etc.,\n // with the unit's code - including any substitutions.\n if (!endProcessing) {\n uArray[u1]['un'] = parenUnit[0];\n }\n } // end if the curCode contains a parenthesized unit\n\n // Else it's not a parenthetical unit and not a number. Call\n // _makeUnit to create a unit for it.\n else {\n let uRet = this._makeUnit(curCode, origString);\n // If we didn't get a unit, set the endProcessing flag.\n if (uRet[0] === null) {\n endProcessing = true;\n }\n else {\n uArray[u1]['un'] = uRet[0];\n origString = uRet[1];\n }\n } // end if the curCode is not a parenthetical expression\n } // end if the \"un\" array is a not a number\n } // end do for each element in the units array\n } // end if _makeUnitsArray did not return an error\n } // end if _processParens did not find an error that causes a stop\n\n // If we're still good, continue\n if (!endProcessing) {\n // Process the units (and numbers) to create one final unit object\n if ((uArray[0] === null || uArray[0] === ' ' ||\n uArray[0]['un'] === undefined || uArray[0]['un'] === null)\n && this.retMsg_.length === 0) {\n // not sure what this might be, but this is a safeguard\n this.retMsg_.push(`Unit string (${origString}) did not contain ` +\n `anything that could be used to create a unit, or else something ` +\n `that is not handled yet by this package. Sorry`);\n endProcessing = true;\n }\n }\n if (!endProcessing) {\n finalUnit = this._performUnitArithmetic(uArray, origString);\n }\n return [finalUnit, origString];\n } // end _parseTheString\n\n\n /**\n * Extracts all annotations from a unit string, replacing them with\n * placeholders for later evaluation. The annotations are stored in the\n * this.annotations_ array. This should only be called from within this\n * class (or by test code).\n *\n * @param uString the unit string being parsed\n * @returns the string after the annotations are replaced with placeholders\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n * the this.annotations_ array is populated by this method\n */\n _getAnnotations(uString) {\n let openBrace = uString.indexOf('{');\n while (openBrace >= 0) {\n\n let closeBrace = uString.indexOf('}');\n if (closeBrace < 0) {\n this.retMsg_.push('Missing closing brace for annotation starting at ' +\n this.openEmph_ + uString.substr(openBrace) +\n this.closeEmph_);\n openBrace = -1;\n }\n else {\n let braceStr = uString.substring(openBrace, closeBrace + 1);\n let aIdx = this.annotations_.length.toString();\n uString = uString.replace(braceStr, this.braceFlag_ + aIdx +\n this.braceFlag_);\n this.annotations_.push(braceStr);\n openBrace = uString.indexOf('{');\n }\n } // end do while we have an opening brace\n\n // check for a stray/unmatched closing brace\n let closeBrace = uString.indexOf('}');\n if (closeBrace >= 0)\n this.retMsg_.push('Missing opening brace for closing brace found at ' +\n this.openEmph_ + uString.substring(0, closeBrace + 1) +\n this.closeEmph_);\n return uString;\n } // end _getAnnotations\n\n\n /**\n * Finds and processes any/all parenthesized unit strings. This should only\n * be called from within this class (or by test code).\n *\n * Nested parenthesized strings are processed from the inside out. The\n * parseString function is called from within this one for each parenthesized\n * unit string, and the resulting unit object is stored in this.parensUnits_,\n * to be processed after all strings are translated to units.\n *\n * A placeholder is placed in the unit string returned to indicate that the\n * unit object should be obtained from the this.parensUnits_ array. The\n * placeholder consists of the parenthesis flag (this.parensFlag_) followed\n * by the index of the unit in this.parensUnits_ followed by this.parensFlag_.\n *\n * @param uString the unit string being parsed, where this will be the full\n * string the first time this is called and parenthesized strings on any\n * subsequent calls\n * @param origString the original string first passed in to parseString\n * @returns\n * an array containing:\n * the string after the parentheses are replaced;\n * the original string; and\n * a boolean flag indicating whether or not an error occurred that\n * should stop processing.\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n * this this.parensUnits_ array will be populated with units found for\n * parenthetical unit strings\n */\n _processParens(uString, origString) {\n\n // Unit strings array and index\n let uStrArray = [];\n let uStrAryPos = 0;\n let stopProcessing = false;\n\n let pu = this.parensUnits_.length;\n\n // Count of characters trimmed off the beginning of the unit string (uString)\n // as units are removed from it; used for error messages to provide\n // context.\n let trimmedCt = 0;\n\n // Break the unit string into pieces that consist of text outside of\n // parenthetical strings and placeholders for the parenthetical units.\n // This method is called recursively for parenthetical strings and the units\n // returned are stored in the this.parensUnits_ array.\n while (uString !== \"\" && !stopProcessing) {\n let openCt = 0;\n let closeCt = 0;\n let openPos = uString.indexOf('(');\n\n // If an opening parenthesis was not found, check for an unmatched\n // close parenthesis. If one was found report the error and end\n // processing.\n if (openPos < 0) {\n let closePos = uString.indexOf(')');\n if (closePos >= 0) {\n let theMsg = `Missing open parenthesis for close ` +\n `parenthesis at ${uString.substring(0, closePos + trimmedCt)}` +\n `${this.openEmph_}${uString.substr(closePos, 1)}${this.closeEmph_}`;\n if (closePos < uString.length - 1) {\n theMsg += `${uString.substr(closePos + 1)}`;\n }\n this.retMsg_.push(theMsg);\n uStrArray[uStrAryPos] = uString;\n stopProcessing = true;\n } // end if a close parenthesis was found\n\n // If no parentheses were found in the current unit string, transfer\n // it to the units array and blank out the string, which will end\n // the search for parenthetical units.\n else {\n uStrArray[uStrAryPos] = uString;\n uString = \"\";\n } // end if no close parenthesis was found\n } // end if no open parenthesis was found\n\n // Otherwise an open parenthesis was found. Process the string that\n // includes the parenthetical group\n else {\n openCt += 1;\n // Write the text before the parentheses (if any) to the unit strings array\n let uLen = uString.length;\n if (openPos > 0) {\n uStrArray[uStrAryPos++] = uString.substr(0, openPos);\n }\n\n // Find the matching closePos, i.e., the one that closes the\n // parenthetical group that this one opens. Look also for\n // another open parenthesis, in case this includes nested parenthetical\n // strings. This continues until it finds the same number of close\n // parentheses as open parentheses, or runs out of string to check.\n // In the case of nested parentheses this will identify the outer set\n // of parentheses.\n let closePos = 0;\n let c = openPos + 1;\n for (; c < uLen && openCt != closeCt; c++) {\n if (uString[c] === '(')\n openCt += 1;\n else if (uString[c] === ')')\n closeCt += 1;\n }\n\n // Put a placeholder for the group in the unit strings array and recursively\n // call this method for the parenthetical group. Put the unit returned\n // in this.parensUnits_. Set the unit string to whatever follows\n // the position of the closing parenthesis for this group, to be\n // processed by the next iteration of this loop. If there's nothing\n // left uString is set to \"\".\n if (openCt === closeCt) {\n closePos = c;\n uStrArray[uStrAryPos++] = this.parensFlag_ + pu.toString() + this.parensFlag_;\n let parseResp = this._parseTheString(\n uString.substring(openPos + 1, closePos - 1), origString);\n if (parseResp[0] === null)\n stopProcessing = true;\n else {\n origString = parseResp[1];\n this.parensUnits_[pu++] = parseResp[0];\n uString = uString.substr(closePos);\n trimmedCt = closePos;\n }\n } // end if the number of open and close parentheses matched\n\n // If the number of open and close parentheses doesn't match, indicate\n // an error.\n else {\n uStrArray.push(origString.substr(openPos));\n this.retMsg_.push(`Missing close parenthesis for open parenthesis at ` +\n `${origString.substring(0, openPos + trimmedCt)}` +\n `${this.openEmph_}${origString.substr(openPos, 1)}` +\n `${this.closeEmph_}${origString.substr(openPos + 1)}`);\n stopProcessing = true;\n }\n } // end if an open parenthesis was found\n } // end do while the input string is not empty\n if (stopProcessing)\n this.parensUnits_ = [];\n return [uStrArray.join(''), origString, stopProcessing]\n } // end _processParens\n\n\n /**\n * Breaks the unit string into an array of unit descriptors and operators.\n * If a unit descriptor consists of a number preceding a unit code, with\n * no multiplication operator, e.g., 2mg instead of 2.mg, it is handled\n * as if it were a parenthetical expression.\n *\n * This should only be called from within this class (or by test code).\n *\n * @param uStr the unit string being parsed\n * @param origString the original string passed to parseString\n * @returns\n * an array containing:\n * the array representing the unit string;\n * the original string passed in, possibly updated with corrections; and\n * and a flag indicating whether or not processing can continue.\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n */\n _makeUnitsArray(uStr, origString) {\n\n // Separate the string into pieces based on delimiters / (division) and .\n // (multiplication). The idea is to get an array of units on which we\n // can then perform any operations (prefixes, multiplication, division).\n\n let uArray1 = uStr.match(/([./]|[^./]+)/g);\n let endProcessing = false ;\n let uArray = [];\n let startNumCheck = /(^[0-9]+)(\\[?[a-zA-Z\\_0-9a-zA-Z\\_]+\\]?$)/ ;\n\n // If the first element in the array is the division operator (/), the\n // string started with '/'. Add a first element containing 1 to the\n // array, which will cause the correct computation to be performed (inversion).\n if (uArray1[0] === \"/\") {\n uArray1.unshift(\"1\");\n }\n // If the first element in the array is the multiplication operator (.)\n // return an error.\n else if (uArray1[0] === '.') {\n this.retMsg_.push(`${origString} is not a valid UCUM code. ` +\n `The multiplication operator at the beginning of the expression is ` +\n `not valid. A multiplication operator must appear only between ` +\n `two codes.`);\n endProcessing = true ;\n }\n if (!endProcessing) {\n // Check to see if there is a number preceding a unit code, e.g., 2mg\n // If so, update the first element to remove the number (2mg -> mg) and\n // add two elements to the beginning of the array - the number and the\n // multiplication operator.\n\n if (!intUtils_.isNumericString(uArray1[0])) {\n let numRes = uArray1[0].match(startNumCheck);\n if (numRes && numRes.length === 3 && numRes[1] !== '' &&\n numRes[2] !== '' && numRes[2].indexOf(this.braceFlag_) !== 0) {\n let dispVal = numRes[2] ;\n\n if (!endProcessing && numRes[2].indexOf(this.parensFlag_) !== -1) {\n let parensback = this._getParensUnit(numRes[2], origString);\n numRes[2] = parensback[0]['csCode_'];\n dispVal = `(${numRes[2]})`;\n endProcessing = parensback[1];\n }\n if (!endProcessing) {\n this.retMsg_.push(`${numRes[1]}${dispVal} is not a valid UCUM code.` +\n ` ${this.vcMsgStart_}${numRes[1]}.${dispVal}${this.vcMsgEnd_}`);\n origString = origString.replace(`${numRes[1]}${dispVal}`,\n `${numRes[1]}.${dispVal}`);\n uArray1[0] = numRes[2];\n uArray1.unshift(numRes[1], '.');\n }\n }\n } // end if the first element is not a number (only)\n\n // Create an array of unit/operator objects. The unit is, for now, the\n // string containing the unit code (e.g., Hz for hertz) including\n // a possible prefix and exponent. The operator is the operator to be\n // applied to that unit and the one preceding it. So, a.b would give\n // us two objects. The first will have a unit of a, and a blank operator\n // (because it's the first unit). The second would have a unit of b\n // and the multiplication operator (.).\n if (!endProcessing) {\n let u1 = uArray1.length;\n uArray = [{op: \"\", un: uArray1[0]}];\n for (let n = 1; n < u1; n++) {\n\n // check to make sure that we don't have two operators together, e.g.,\n // mg./K. If so, let the user know the problem.\n let theOp = uArray1[n++];\n // oh wait - check to make sure something is even there, that the\n // user didn't end the expression with an operator.\n if (!uArray1[n]) {\n this.retMsg_.push(`${origString} is not a valid UCUM code. ` +\n `It is terminated with the operator ${this.openEmph_}` +\n `${theOp}${this.closeEmph_}.`);\n n = u1;\n endProcessing = true;\n }\n else if (Ucum.validOps_.indexOf(uArray1[n]) !== -1) {\n this.retMsg_.push(`${origString} is not a valid UCUM code. ` +\n `A unit code is missing between${this.openEmph_}` +\n `${theOp}${this.closeEmph_}and${this.openEmph_}` +\n `${uArray1[n]}${this.closeEmph_}in${this.openEmph_}` +\n `${theOp}${uArray1[n]}${this.closeEmph_}.`);\n n = u1;\n endProcessing = true;\n }\n else {\n // Check to see if a number precedes a unit code.\n // If so, send the element to _processParens, inserting the multiplication\n // operator where it belongs. Treating it as parenthetical keeps it from\n // being interpreted incorrectly because of operator parentheses. For\n // example, if the whole string is mg/2kJ we don't want to rewrite it as\n // mg/2.kJ - because mg/2 would be performed, followed by .kJ. Instead,\n // handling 2kJ as a parenthesized unit will make sure mg is divided by\n // 2.kJ.\n if (!intUtils_.isNumericString(uArray1[n])) {\n let numRes2 = uArray1[n].match(startNumCheck);\n if (numRes2 && numRes2.length === 3 && numRes2[1] !== '' &&\n numRes2[2] !== '' && numRes2[2].indexOf(this.braceFlag_) !== 0) {\n let invalidString = numRes2[0];\n if (!endProcessing && numRes2[2].indexOf(this.parensFlag_) !== -1) {\n let parensback = this._getParensUnit(numRes2[2], origString);\n numRes2[2] = parensback[0]['csCode_'];\n invalidString = `(${numRes2[2]})`;\n endProcessing = parensback[1];\n if (!endProcessing) {\n this.retMsg_.push(`${numRes2[1]}${invalidString} is not a ` +\n `valid UCUM code. ${this.vcMsgStart_}${numRes2[1]}.${invalidString}` +\n `${this.vcMsgEnd_}`);\n let parensString = `(${numRes2[1]}.${invalidString})`;\n origString = origString.replace(`${numRes2[1]}${invalidString}`,\n parensString);\n let nextParens = this._processParens(parensString, origString);\n endProcessing = nextParens[2];\n if (!endProcessing) {\n uArray.push({op: theOp, un: nextParens[0]});\n }\n //uArray.push({op: '.', un: numRes2[2]});\n }\n } // end if the string represents a parenthesized unit\n else {\n let parensStr = '(' + numRes2[1] + '.' + numRes2[2] + ')';\n let parensResp = this._processParens(parensStr, origString);\n // if a \"stop processing\" flag was returned, set the n index to end\n // the loop and set the endProcessing flag\n if (parensResp[2]) {\n n = u1;\n endProcessing = true;\n }\n else {\n this.retMsg_.push(`${numRes2[0]} is not a ` +\n `valid UCUM code. ${this.vcMsgStart_}${numRes2[1]}.${numRes2[2]}` +\n `${this.vcMsgEnd_}`);\n origString = origString.replace(numRes2[0], parensStr);\n uArray.push({op: theOp, un: parensResp[0]});\n } // end if no error on the processParens call\n } // end if the string does not represent a parenthesized unit\n } // end if the string is a number followed by a string\n else {\n uArray.push({op: theOp, un: uArray1[n]});\n }\n }\n else {\n uArray.push({op: theOp, un: uArray1[n]});\n }\n } // end if there isn't a missing operator or unit code\n } // end do for each element in uArray1\n } // end if a processing error didn't occur in getParensUnit\n } // end if the string did not begin with a '.' with no following digit\n return [uArray, origString, endProcessing];\n } // end _makeUnitsArray\n\n\n /**\n * Takes a unit string containing parentheses flags and returns the unit they\n * represent. Any text found before and/or after the parenthetical\n * expression is checked to see if we can tell what the user meant and\n * let them know what it should have been. For example, 2(mg), which\n * would resolve to 2mg, should be 2.mg.\n *\n * This should only be called from within this class (or by test code).\n *\n * @param pStr the string being parsed\n * @param origString the original unit string passed in; passed through\n * to _getAnnonText if annotation flags are found in any text preceding\n * or following the parenthetical unit\n * @returns\n * an array containing\n * the unit object; and\n * a flag indicating whether or not processing should be ended.\n * True indicates that the string was invalid and no corrections\n * (substitutions or suggestions) could be found;\n * False indicates that it was either valid or substitutions/suggestions\n * were made.\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n * this this.parensUnits_ array contains the units that are acquired by\n * this method\n * @throws an error if an invalid parensUnit index was found. This is\n * a processing error.\n */\n _getParensUnit(pStr, origString) {\n let endProcessing = false;\n let retAry = [];\n let retUnit = null;\n let befAnnoText = null;\n let aftAnnoText = null;\n\n // Get the location of the flags. We're assuming there are only two\n // because _processParens takes care of nesting. By the time we get\n // here we should not be looking a nested parens. Also get any text\n // before and after the parentheses. Once we get the unit we update\n // the input string with the unit's csCode_, which will wipe out any\n // before and after text\n let psIdx = pStr.indexOf(this.parensFlag_);\n let befText = null;\n if (psIdx > 0) {\n befText = pStr.substr(0, psIdx - 1);\n }\n let peIdx = pStr.lastIndexOf(this.parensFlag_);\n let aftText = null;\n if (peIdx + this.pFlagLen_ < pStr.length) {\n aftText = pStr.substr(peIdx + this.pFlagLen_);\n }\n\n // Get the text between the flags\n let pNumText = pStr.substring(psIdx + this.pFlagLen_, peIdx);\n\n // Make sure the index is a number, and if it is, get the unit from the\n // this.parensUnits_ array\n if (intUtils_.isNumericString(pNumText)) {\n retUnit = this.parensUnits_[Number(pNumText)];\n if (!intUtils_.isIntegerUnit(retUnit)) {\n pStr = retUnit.csCode_;\n }\n else {\n pStr = retUnit ;\n }\n }\n // If it's not a number, it's a programming error. Throw a fit.\n else {\n throw (new Error(`Processing error - invalid parens number ${pNumText} ` +\n `found in ${pStr}.`));\n }\n\n // If there's something in front of the starting parentheses flag, check to\n // see if it's a number or an annotation.\n if (befText) {\n // If it's a number, assume that multiplication was assumed\n if (intUtils_.isNumericString(befText)) {\n let nMag = retUnit.getProperty('magnitude_');\n nMag *= Number(befText);\n retUnit.assignVals({'magnitude_': nMag});\n pStr = `${befText}.${pStr}`;\n this.retMsg_.push(`${befText}${pStr} is not a valid UCUM code.\\n` +\n this.vcMsgStart_ + pStr + this.vcMsgEnd_);\n }\n else {\n if (befText.indexOf(this.braceFlag_) >= 0) {\n let annoRet = this._getAnnoText(befText, origString);\n // if we found not only an annotation, but text before or after\n // the annotation (remembering that this is all before the\n // parentheses) throw an error - because we don't know what\n // to do with it. Could it be missing an operator?\n if (annoRet[1] || annoRet[2]) {\n throw (new Error(`Text found before the parentheses (` +\n `${befText}) included an annotation along with other text ` +\n `for parenthetical unit ${retUnit.csCode_}`));\n }\n // Otherwise put the annotation after the unit string and note\n // the misplacement.\n pStr += annoRet[0];\n this.retMsg_.push(`The annotation ${annoRet[0]} before the unit ` +\n `code is invalid.\\n` + this.vcMsgStart_ + pStr + this.vcMsgEnd_);\n }\n // else the text before the parentheses is neither a number nor\n // an annotation. If suggestions were NOT requested, record an\n // error.\n else if (!this.suggestions_) {\n this.retMsg_.push(`${befText} preceding the unit code ${pStr} ` +\n `is invalid. Unable to make a substitution.`);\n endProcessing = true;\n }\n // otherwise try for suggestions\n else {\n let suggestStat = this._getSuggestions(befText);\n endProcessing = (suggestStat !== 'succeeded');\n\n } // end if a brace was found or, if not, suggestions were not or\n // were requested\n } // end if text preceding the parentheses was not a number\n } // end if there was text before the parentheses\n\n // Process any text after the parentheses\n if (aftText) {\n // if it's an annotation, get it and add it to the pStr\n if (aftText.indexOf(this.braceFlag_) >= 0) {\n let annoRet = this._getAnnoText(aftText, origString);\n // if we found not only an annotation, but text before or after\n // the annotation (remembering that this is all after the\n // parentheses) throw an error - because we don't know what\n // to do with it. Could it be missing an operator?\n if (annoRet[1] || annoRet[2]) {\n throw (new Error(`Text found after the parentheses (` +\n `${aftText}) included an annotation along with other text ` +\n `for parenthetical unit ${retUnit.csCode_}`));\n }\n // Otherwise put the annotation after the unit string - no message\n // needed.\n pStr += annoRet[0];\n }\n // Otherwise check to see if it's an exponent. If so, warn the\n // user that it's not valid - but try it anyway\n else {\n\n if (intUtils_.isNumericString(aftText)) {\n pStr += aftText;\n retUnit = retUnit.power(Number(aftText));\n this.retMsg_.push(`An exponent (${aftText}) following a parenthesis ` +\n `is invalid as of revision 1.9 of the UCUM Specification.\\n ` +\n this.vcMsgStart_ + pStr + this.vcMsgEnd_);\n }\n // else the text after the parentheses is neither a number nor\n // an annotation. If suggestions were NOT requested, record an\n // error.\n else if (!this.suggestions_) {\n this.retMsg_.push(`Text ${aftText} following the unit code ${pStr} ` +\n `is invalid. Unable to make a substitution.`);\n endProcessing = true;\n }\n // otherwise try for suggestions\n else {\n let suggestStat = this._getSuggestions(befText);\n endProcessing = (suggestStat !== 'succeeded');\n } // end if text following the parentheses not an exponent\n } // end if text following the parentheses is not an annotation\n } // end if there is text following the parentheses\n if (!endProcessing) {\n if (!retUnit) {\n retUnit = new Unit({\n 'csCode_': pStr,\n 'magnitude_': 1,\n 'name_': pStr});\n }\n else if (intUtils_.isIntegerUnit(retUnit)) {\n retUnit = new Unit({'csCode_': retUnit,\n 'magnitude_': retUnit,\n 'name_': retUnit});\n }\n else {\n retUnit.csCode_ = pStr;\n }\n }\n return [retUnit, endProcessing];\n } // end _getParensUnit\n\n /**\n * Takes a unit string containing annotation flags and returns the\n * annotation they represent. This also returns any text found before\n * the annotation and any found after the annotation.\n *\n * This should only be called from within this class (or by test code).\n * NEEDS FIX in next branch to handle string with multiple annotations.\n *\n * @param pStr the string being parsed\n * @param origString the original string being parsed; used in error msg\n * thrown for an invalid index to the annotations array\n * @returns\n * an array containing\n * the annotation for the pStr;\n * any text found before the annotation; and\n * any text found after the annotation.\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n * the this.annotations_ array is used as the source for the annotations text\n * @throws an error if for a processing error - an invalid annotation index.\n */\n _getAnnoText(pStr, origString) {\n\n // if the starting braces flag is not at index 0, get the starting\n // text and the adjust the pStr to omit it.\n let asIdx = pStr.indexOf(this.braceFlag_);\n let startText = (asIdx > 0) ? pStr.substring(0, asIdx) : null;\n if (asIdx !== 0) {\n pStr = pStr.substr(asIdx);\n }\n\n // Get the location of the end flag and, if text follows it, get the text\n let aeIdx = pStr.indexOf(this.braceFlag_, 1);\n let endText = ((aeIdx + this.bFlagLen_) < pStr.length) ?\n pStr.substr(aeIdx + this.bFlagLen_) : null;\n\n // Get the index of the annotation in this.annotations_.\n // Check it to make sure it's valid, and if not, throw an error\n let idx = pStr.substring(this.bFlagLen_, aeIdx);\n let idxNum = Number(idx);\n if (!intUtils_.isNumericString(idx) || idxNum >= this.annotations_.length) {\n throw (new Error(`Processing Error - invalid annotation index ${idx} found ` +\n `in ${pStr} that was created from ${origString}`));\n }\n\n // Replace the flags and annotation index with the annotation expression\n pStr = this.annotations_[idxNum];\n return [pStr, startText, endText];\n } // end _getAnnoText\n\n\n /**\n * Takes a unit string and looks for suggested units. This should be\n * called for unit strings that cannot be resolved to unit codes. The\n * string is searched for in the synonyms table found in the UnitTables\n * class. That table includes all synonyms and unit names for the units\n * in the unit data table.\n *\n * @param pStr the string being parsed\n * @returns an object that contains an element named 'status', whose\n * value indicates the status of the request:\n * 'succeeded' indicates that synonyms were found;\n * 'failed' indicates that no synonyms were found; or\n * 'error' which indicates that an error occurred\n *\n * the this.retMsg_ array will be updated with a message indicating whether\n * or not synonyms/suggestions were found\n * the this.suggestions_ array will be updated with a hash (added to the\n * array if it already contains others) that contains three elements:\n * 'msg' which is a message indicating what unit expression the\n * suggestions are for;\n * 'invalidUnit' which is the unit expression the suggestions are for; and\n * 'units' which is an array of data for each suggested unit found.\n * Each array will contain the unit code, the unit name and the\n * unit guidance (if any).\n */\n _getSuggestions(pStr) {\n\n let retObj = intUtils_.getSynonyms(pStr);\n if (retObj['status'] === 'succeeded') {\n let suggSet = {} ;\n suggSet['msg'] = `${pStr} is not a valid UCUM code. We found possible ` +\n `units that might be what was meant:`;\n suggSet['invalidUnit'] = pStr ;\n let synLen = retObj['units'].length ;\n suggSet['units'] = [] ;\n for (let s = 0; s < synLen; s++) {\n let unit = retObj['units'][s];\n let unitArray = [unit['code'], unit['name'], unit['guidance']];\n\n suggSet['units'].push(unitArray) ;\n }\n this.suggestions_.push(suggSet);\n }\n else {\n this.retMsg_.push(`${pStr} is not a valid UCUM code. No alternatives ` +\n `were found.`);\n }\n return retObj['status'] ;\n } // end getSuggestions\n\n\n /**\n * Creates a unit object from a string defining one unit. The string\n * should consist of a unit code for a unit already defined (base or\n * otherwise). It may include a prefix and an exponent, e.g., cm2\n * (centimeter squared). This should only be called from within this\n * class (or by test code).\n *\n * @params uCode the string defining the unit\n * @param origString the original string to be parsed; used to provide\n * context for messages\n * @returns\n * an array containing:\n * a unit object, or null if there were problems creating the unit; and\n * the origString passed in, which may be updated if a unit name was\n * translated to a unit code.\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n * the this.suggestions_ array will be populated if no unit (with or without\n * substitutions) could be found and suggestions were requested\n */\n _makeUnit(uCode, origString) {\n\n // First try the code just as is, without looking for annotations,\n // prefixes, exponents, or elephants.\n let retUnit = this.utabs_.getUnitByCode(uCode);\n if (retUnit) {\n retUnit = retUnit.clone();\n }\n\n // If we found it, we're done. No need to parse for those elephants (or\n // other stuff).\n else if (uCode.indexOf(this.braceFlag_) >= 0) {\n let getAnnoRet = this._getUnitWithAnnotation(uCode, origString);\n retUnit = getAnnoRet[0];\n if (retUnit) {\n origString = getAnnoRet[1];\n }\n // If a unit is not found, retUnit will be returned null and\n // the this.retMsg_ array will contain a message describing the problem.\n // If a unit is found, of course, all is good. So ... nothing left\n // to see here, move along.\n } // end if the uCode includes an annotation\n\n else {\n\n // So we didn't find a unit for the full uCode or for one with\n // annotations. Try looking for a unit that uses a carat (^)\n // instead of an asterisk (*)\n\n if (uCode.indexOf('^') > -1) {\n let tryCode = uCode.replace('^', '*');\n retUnit = this.utabs_.getUnitByCode(tryCode);\n if (retUnit) {\n retUnit = retUnit.clone();\n retUnit.csCode_ = retUnit.csCode_.replace('*', '^');\n retUnit.ciCode_ = retUnit.ciCode_.replace('*', '^');\n }\n }\n // If that didn't work, check to see if it should have brackets\n // around it (uCode = degF when it should be [degF]\n if (!retUnit) {\n let addBrackets = '[' + uCode + ']' ;\n retUnit = this.utabs_.getUnitByCode(addBrackets);\n if (retUnit) {\n retUnit = retUnit.clone();\n origString = origString.replace(uCode, addBrackets);\n this.retMsg_.push(`${uCode} is not a valid unit expression, but ` +\n `${addBrackets} is.\\n` + this.vcMsgStart_ +\n `${addBrackets} (${retUnit.name_})${this.vcMsgEnd_}`);\n } // end if we found the unit after adding brackets\n } // end trying to add brackets\n\n // If we didn't find it, try it as a name\n if (!retUnit) {\n let retUnitAry = this.utabs_.getUnitByName(uCode);\n if (retUnitAry && retUnitAry.length > 0) {\n retUnit = retUnitAry[0].clone();\n let mString = 'The UCUM code for ' + uCode + ' is ' +\n retUnit.csCode_ + '.\\n' + this.vcMsgStart_ +\n retUnit.csCode_ + this.vcMsgEnd_;\n let dupMsg = false;\n for (let r = 0; r < this.retMsg_.length && !dupMsg; r++)\n dupMsg = this.retMsg_[r] === mString;\n if (!dupMsg)\n this.retMsg_.push(mString);\n let rStr = new RegExp('(^|[.\\/({])(' + uCode + ')($|[.\\/)}])');\n let res = origString.match(rStr);\n origString = origString.replace(rStr, res[1] + retUnit.csCode_ + res[3]);\n uCode = retUnit.csCode_;\n }\n }\n\n // If we still don't have a unit, try assuming a modifier (prefix and/or\n // exponent) and look for a unit without the modifier\n if (!retUnit) {\n\n // Well, first see if it's one of the special units. If so,\n // replace the placeholder text with the actual unit string, keeping\n // whatever text (probably a prefix) goes with the unit string.\n let sUnit = null;\n for (sUnit in Ucum.specUnits_) {\n if (uCode.indexOf(Ucum.specUnits_[sUnit]) !== -1)\n uCode = uCode.replace(Ucum.specUnits_[sUnit], sUnit);\n }\n retUnit = this.utabs_.getUnitByCode(uCode);\n if (retUnit)\n retUnit = retUnit.clone();\n }\n if (!retUnit) {\n\n let origCode = uCode;\n let origUnit = null;\n let exp = null;\n let pfxCode = null;\n let pfxObj = null;\n let pfxVal = null;\n let pfxExp = null;\n\n // Look first for an exponent. If we got one, separate it out and\n // try to get the unit again\n let codeAndExp = this._isCodeWithExponent(uCode);\n if (codeAndExp) {\n uCode = codeAndExp[0];\n exp = codeAndExp[1];\n origUnit = this.utabs_.getUnitByCode(uCode);\n }\n\n\n // If we still don't have a unit, separate out the prefix, if any,\n // and try without it.\n if (!origUnit) {\n // Try for a single character prefix first.\n pfxCode = uCode.charAt(0);\n pfxObj = this.pfxTabs_.getPrefixByCode(pfxCode);\n\n // if we got a prefix, get its info and remove it from the unit code\n if (pfxObj) {\n pfxVal = pfxObj.getValue();\n pfxExp = pfxObj.getExp();\n let pCodeLen = pfxCode.length;\n uCode = uCode.substr(pCodeLen);\n\n // try again for the unit\n origUnit = this.utabs_.getUnitByCode(uCode);\n\n // If we still don't have a unit, see if the prefix could be the\n // two character \"da\" (deka) prefix. That's the only prefix with\n // two characters, and without this check it's interpreted as \"d\"\n // (deci) and the \"a\" is considered part of the unit code.\n\n if (!origUnit && pfxCode == 'd' && uCode.substr(0, 1) == 'a') {\n pfxCode = 'da';\n pfxObj = this.pfxTabs_.getPrefixByCode(pfxCode);\n pfxVal = pfxObj.getValue();\n uCode = uCode.substr(1);\n\n // try one more time for the unit\n origUnit = this.utabs_.getUnitByCode(uCode);\n }\n\n // Reject the unit we found if it might have another prefix.\n // Such things are in our tables through the LOINC source_\n // (ucum.csv) which has guidance and synonyms. I think it should be\n // safe to exclude anything whose source is LOINC from having a\n // prefix.\n if (origUnit && origUnit.source_ == 'LOINC')\n origUnit = null;\n } // end if we found a prefix\n } // end if we didn't get a unit after removing an exponent\n\n // If we still haven't found anything, we're done looking.\n // (We tried with the full unit string, with the unit string\n // without the exponent, the unit string without a prefix,\n // common errors, etc. That's all we can try).\n if (!origUnit) {\n retUnit = null ;\n // BUT if the user asked for suggestions, at least look for them\n if (this.suggestions_) {\n let suggestStat = this._getSuggestions(origCode);\n }\n else {\n this.retMsg_.push(`${origCode} is not a valid UCUM code.`);\n }\n }\n else {\n // Otherwise we found a unit object. Clone it and then apply the\n // prefix and exponent, if any, to it. And remove the guidance.\n retUnit = origUnit.clone();\n // If we are here, this is only part of the full unit string, so it is\n // not a base unit, and the synonyms will mostly likely not be correct for the full\n // string.\n retUnit.resetFieldsForDerivedUnit();\n let theDim = retUnit.getProperty('dim_');\n let theMag = retUnit.getProperty('magnitude_');\n let theName = retUnit.getProperty('name_');\n let theCiCode = retUnit.getProperty('ciCode_');\n let thePrintSymbol = retUnit.getProperty('printSymbol_');\n // If there is an exponent for the unit, apply it to the dimension\n // and magnitude now\n if (exp) {\n exp = parseInt(exp);\n let expMul = exp;\n if (theDim)\n theDim = theDim.mul(exp);\n theMag = Math.pow(theMag, exp);\n retUnit.assignVals({'magnitude_': theMag});\n\n // If there is also a prefix, apply the exponent to the prefix.\n if (pfxObj) {\n\n // if the prefix base is 10 it will have an exponent. Multiply\n // the current prefix exponent by the exponent for the unit\n // we're working with. Then raise the prefix value to the level\n // defined by the exponent.\n if (pfxExp) {\n expMul *= pfxObj.getExp();\n pfxVal = Math.pow(10, expMul);\n }\n // If the prefix base is not 10, it won't have an exponent.\n // At the moment I don't see any units using the prefixes\n // that aren't base 10. But if we get one the prefix value\n // will be applied to the magnitude (below) if the unit does\n // not have a conversion function, and to the conversion prefix\n // if it does.\n } // end if there's a prefix as well as the exponent\n } // end if there's an exponent\n\n // Now apply the prefix, if there is one, to the conversion\n // prefix or the magnitude\n if (pfxObj) {\n if (retUnit.cnv_) {\n retUnit.assignVals({'cnvPfx_': pfxVal});\n }\n else {\n theMag *= pfxVal;\n retUnit.assignVals({'magnitude_': theMag})\n }\n }\n // if we have a prefix and/or an exponent, add them to the unit\n // attributes - name, csCode, ciCode and print symbol\n let theCode = retUnit.csCode_;\n if (pfxObj) {\n theName = pfxObj.getName() + theName;\n theCode = pfxCode + theCode;\n theCiCode = pfxObj.getCiCode() + theCiCode;\n thePrintSymbol = pfxObj.getPrintSymbol() + thePrintSymbol;\n retUnit.assignVals({\n 'name_': theName,\n 'csCode_': theCode,\n 'ciCode_': theCiCode,\n 'printSymbol_': thePrintSymbol\n });\n }\n if (exp) {\n let expStr = exp.toString();\n retUnit.assignVals({\n 'name_': theName + '<sup>' + expStr + '</sup>',\n 'csCode_': theCode + expStr,\n 'ciCode_': theCiCode + expStr,\n 'printSymbol_': thePrintSymbol + '<sup>' + expStr + '</sup>'\n });\n }\n } // end if an original unit was found (without prefix and/or exponent)\n\n } // end if we didn't get a unit for the full unit code (w/out modifiers)\n } // end if we didn't find the unit on the first try, before parsing\n return [retUnit, origString];\n } // end _makeUnit\n\n\n /**\n * This method handles unit creation when an annotation is included\n * in the unit string. This basically isolates and retrieves the\n * annotation and then calls _makeUnit to try to get a unit from\n * any text that precedes or follows the annotation.\n *\n * @param uCode the string defining the unit\n * @param origString the original full string submitted to parseString\n * @returns the unit object found, or null if one could not be found\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n */\n _getUnitWithAnnotation(uCode, origString) {\n\n let retUnit = null;\n\n // Get the annotation and anything that precedes or follows it.\n let annoRet = this._getAnnoText(uCode, origString);\n let annoText = annoRet[0];\n let befAnnoText = annoRet[1];\n let aftAnnoText = annoRet[2];\n\n // Add the warning about annotations - just once.\n\n if (this.bracesMsg_ && this.retMsg_.indexOf(this.bracesMsg_) === -1)\n this.retMsg_.push(this.bracesMsg_);\n\n // If there's no text before or after the annotation, it's probably\n // something that should be interpreted as a 1, e.g., {KCT'U}.\n // HOWEVER, it could also be a case where someone used braces instead\n // of brackets, e.g., {degF} instead of [degF]. Check for that before\n // we assume it should be a 1.\n let msgLen = this.retMsg_.length;\n if (!befAnnoText && !aftAnnoText) {\n let tryBrackets = '[' + annoText.substring(1, annoText.length - 1) + ']';\n let mkUnitRet = this._makeUnit(tryBrackets, origString);\n\n // If we got back a unit, assign it to the returned unit, and add\n // a message to advise the user that brackets should enclose the code\n if (mkUnitRet[0]) {\n retUnit = mkUnitRet[0];\n origString = origString.replace(annoText, tryBrackets);\n this.retMsg_.push(`${annoText} is not a valid unit expression, but ` +\n `${tryBrackets} is.\\n` + this.vcMsgStart_ +\n `${tryBrackets} (${retUnit.name_})${this.vcMsgEnd_}`);\n }\n // Otherwise assume that this should be interpreted as a 1\n else {\n // remove error message generated for trybrackets\n if (this.retMsg_.length > msgLen) {\n this.retMsg_.pop();\n }\n uCode = 1;\n retUnit = 1;\n }\n } // end if it's only an annotation\n\n else {\n // if there's text before and no text after, assume the text before\n // the annotation is the unit code (with an annotation following it).\n // Call _makeUnit for the text before the annotation.\n if (befAnnoText && !aftAnnoText) {\n // make sure that what's before the annoText is not a number, e.g.,\n // /100{cells}. But f it is a number, just set the return unit to\n // the number.\n if (intUtils_.isIntegerUnit(befAnnoText)) {\n retUnit = befAnnoText ;\n }\n // Otherwise try to find a unit\n else {\n let mkUnitRet = this._makeUnit(befAnnoText, origString);\n\n // if a unit was returned\n if (mkUnitRet[0]) {\n retUnit = mkUnitRet[0];\n retUnit.csCode_ += annoText;\n origString = mkUnitRet[1];\n }\n // Otherwise add a not found message\n else {\n this.retMsg_.push(`Unable to find a unit for ${befAnnoText} that ` +\n `precedes the annotation ${annoText}.`);\n }\n }\n }\n // else if there's only text after the annotation, try for a unit\n // from the after text and assume the user put the annotation in\n // the wrong place (and tell them)\n else if (!befAnnoText && aftAnnoText) {\n\n // Again, test for a number and if it is a number, set the return\n // unit to the number.\n if (intUtils_.isIntegerUnit(aftAnnoText)) {\n retUnit = aftAnnoText + annoText ;\n this.retMsg_.push(`The annotation ${annoText} before the `\n `${aftAnnoText} is invalid.\\n` + this.vcMsgStart_ + retUnit +\n this.vcMsgEnd_);\n }\n else {\n let mkUnitRet = this._makeUnit(aftAnnoText, origString);\n if (mkUnitRet[0]) {\n retUnit = mkUnitRet[0];\n retUnit.csCode_ += annoText;\n origString = retUnit.csCode_;\n this.retMsg_.push(`The annotation ${annoText} before the unit ` +\n `code is invalid.\\n` + this.vcMsgStart_ + retUnit.csCode_ +\n this.vcMsgEnd_);\n }\n // Otherwise add a not found message\n else {\n this.retMsg_.push(`Unable to find a unit for ${befAnnoText} that ` +\n `follows the annotation ${annoText}.`);\n }\n }\n }\n // else it's got text before AND after the annotation. Now what?\n // For now this is an error. This may be a case of a missing\n // operator but that is not handled yet.\n else {\n this.retMsg_.push(`Unable to find a unit for ${befAnnoText}${annoText}` +\n `${aftAnnoText}.\\nWe are not sure how to interpret text both before ` +\n `and after the annotation. Sorry`);\n }\n } // else if there's text before/and or after the annotation\n\n return [retUnit , origString];\n\n } // end _getUnitWithAnnotations\n\n\n /**\n * Performs unit arithmetic for the units in the units array. That array\n * contains units/numbers and the operators (division or multiplication) to\n * be performed on each unit/unit or unit/number pair in the array. This\n * should only be called from within this class (or by test code).\n *\n * @params uArray the array that contains the units, numbers and operators\n * derived from the unit string passed in to parseString\n * @param origString the original string to be parsed; used to provide\n * context for messages\n *\n * @returns a single unit object that is the result of the unit arithmetic\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n */\n _performUnitArithmetic(uArray, origString) {\n\n let finalUnit = uArray[0]['un'];\n if (intUtils_.isIntegerUnit(finalUnit)) {\n finalUnit = new Unit({'csCode_' : finalUnit,\n 'magnitude_' : Number(finalUnit),\n 'name_' : finalUnit}) ;\n }\n let uLen = uArray.length ;\n let endProcessing = false ;\n // Perform the arithmetic for the units, starting with the first 2 units.\n // We only need to do the arithmetic if we have more than one unit.\n for (let u2 = 1; (u2 < uLen) && !endProcessing; u2++) {\n let nextUnit = uArray[u2]['un'];\n if (intUtils_.isIntegerUnit(nextUnit)) {\n nextUnit = new Unit({'csCode_' : nextUnit ,\n 'magnitude_' : Number(nextUnit),\n 'name_': nextUnit});\n }\n if (nextUnit === null ||\n ((typeof nextUnit !== 'number') && (!nextUnit.getProperty))) {\n let msgString = `Unit string (${origString}) contains unrecognized ` +\n 'element' ;\n if (nextUnit) {\n msgString += ` (${this.openEmph_}${nextUnit.toString()}` +\n `${this.closeEmph_})`;\n }\n msgString += '; could not parse full string. Sorry';\n this.retMsg_.push(msgString);\n endProcessing = true;\n }\n else {\n try {\n // Is the operation division?\n let thisOp = uArray[u2]['op'];\n let isDiv = thisOp === '/';\n\n // Perform the operation. Both the finalUnit and nextUnit\n // are unit objects.\n isDiv ? finalUnit = finalUnit.divide(nextUnit) :\n finalUnit = finalUnit.multiplyThese(nextUnit);\n }\n catch (err) {\n this.retMsg_.unshift(err.message) ;\n endProcessing = true ;\n finalUnit = null ;\n }\n } // end if we have another valid unit/number to process\n } // end do for each unit after the first one\n return finalUnit ;\n } // end _performUnitArithmetic\n\n\n /**\n * This tests a string to see if it starts with characters and ends with\n * digits. This is used to test for an exponent on a UCUM code (or what\n * we think might be a UCUM code). This is broken out to a separate\n * function so that the regular expression can be verified to provide the\n * results we expect, in case someone changes it. (Per Paul Lynch)\n * See \"Test _isCodeWithExponent method\" in testUnitString.spec.js\n *\n * This particular regex has been tweaked several times. This one\n * works with the following test strings:\n * \"m[H2O]-21 gives [\"m[H2O]-21\", \"m[H2O]\", \"-21\"]\n * \"m[H2O]+21 gives [\"m[H2O]+21\", \"m[H2O]\", \"+21\"]\n * \"m[H2O]21 gives [\"m[H2O]-21\", \"m[H2O]\", \"21\"]\n * \"s2\" gives [\"s2\", \"s, \"2\"]\n * \"kg\" gives null\n * \"m[H2O]\" gives null\n * \"m[H2O]23X\" gives null\n *\n * @params uCode the code being tested\n * @returns an array containing: (1) the code without the exponent (or\n * trailing number); and (2) the exponent/trailing number. Returns null\n * if there is no trailing number or something follows the trailing\n * number, or if the first part is not characters.\n */\n _isCodeWithExponent(uCode) {\n\n let ret = [] ;\n let res = uCode.match(/(^[^\\-\\+]+?)([\\-\\+\\d]+)$/);\n\n // If we got a return with an exponent, separate the exponent from the\n // unit and return both (as separate values)\n if (res && res[2] && res[2] !== \"\") {\n ret.push(res[1]);\n ret.push(res[2]);\n } // end if we got an exponent\n else {\n ret = null ;\n }\n return ret ;\n } // end _isCodeWithExponent\n\n} // end class UnitString\n\n\n/**\n * This function exists ONLY until the original UnitString constructor\n * is called for the first time. It's defined here in case getInstance\n * is called before the constructor. This calls the constructor.\n *\n * The constructor redefines the getInstance function to return the\n * singleton UnitString object. This is based on the UnitTables singleton\n * implementation; see more detail in the UnitTables constructor description.\n *\n * @return the singleton UnitString object.\n */\nUnitString.getInstance = function(){\n return new UnitString();\n} ;\n\n/*\n// Perform the first request for the object, to set the getInstance method.\nUnitString.getInstance();\n\n*/\n"],"file":"unitString.js"}
|
|
1
|
+
{"version":3,"sources":["../source/unitString.js"],"names":["Ucum","require","Unit","UnitTables","PrefixTables","UnitString","constructor","utabs_","getInstance","pfxTabs_","openEmph_","closeEmph_","bracesMsg_","parensFlag_","pFlagLen_","length","braceFlag_","bFlagLen_","vcMsgStart_","vcMsgEnd_","retMsg_","parensUnits_","annotations_","suggestions","useHTMLInMessages","use","undefined","openEmphHTML_","closeEmphHTML_","useBraceMsgForEachString","parseString","uStr","valConv","suggest","trim","Error","valMsgStart_","valMsgEnd_","cnvMsgStart_","cnvMsgEnd_","suggestions_","origString","retObj","_getAnnotations","endProcessing","sUnit","specUnits_","indexOf","replace","_parseTheString","finalUnit","intUtils_","isIntegerUnit","parensResp","_processParens","uArray","mkUArray","_makeUnitsArray","uLen","u1","curCode","Number","parenUnit","_getParensUnit","uRet","_makeUnit","push","_performUnitArithmetic","uString","openBrace","closeBrace","substr","braceStr","substring","VALID_ANNOTATION_REGEX","test","INVALID_ANNOTATION_CHAR_MSG","aIdx","toString","uStrArray","uStrAryPos","stopProcessing","pu","trimmedCt","openCt","closeCt","openPos","closePos","theMsg","c","parseResp","join","uArray1","match","startNumCheck","unshift","isNumericString","numRes","dispVal","parensback","op","un","n","theOp","validOps_","numRes2","invalidString","parensString","nextParens","parensStr","pStr","retAry","retUnit","befAnnoText","aftAnnoText","psIdx","befText","peIdx","lastIndexOf","aftText","pNumText","csCode_","nMag","getProperty","assignVals","annoRet","_getAnnoText","suggestStat","_getSuggestions","power","asIdx","startText","aeIdx","endText","idx","idxNum","getSynonyms","suggSet","synLen","s","unit","unitArray","uCode","getUnitByCode","clone","getAnnoRet","_getUnitWithAnnotation","tryCode","ciCode_","addBrackets","name_","retUnitAry","getUnitByName","mString","dupMsg","r","rStr","RegExp","res","origCode","origUnit","exp","pfxCode","pfxObj","pfxVal","pfxExp","codeAndExp","_isCodeWithExponent","charAt","getPrefixByCode","getValue","getExp","pCodeLen","source_","resetFieldsForDerivedUnit","theDim","theMag","theName","theCiCode","thePrintSymbol","parseInt","expMul","mul","Math","pow","cnv_","theCode","getName","getCiCode","getPrintSymbol","expStr","annoText","msgLen","tryBrackets","mkUnitRet","pop","u2","nextUnit","msgString","thisOp","isDiv","divide","multiplyThese","err","message","ret"],"mappings":"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","sourcesContent":["/**\n * This class handles the parsing of a unit string into a unit object\n */\n\nvar Ucum = require('./config.js').Ucum;\nvar Unit = require('./unit.js').Unit;\nvar UnitTables = require('./unitTables.js').UnitTables;\nvar PrefixTables = require('./prefixTables.js').PrefixTables;\n\nimport * as intUtils_ from \"./ucumInternalUtils.js\";\n\nexport class UnitString {\n\n /**\n * Constructor\n */\n constructor() {\n\n // Get instances of the unit and prefix tables and the utilities\n this.utabs_ = UnitTables.getInstance();\n this.pfxTabs_ = PrefixTables.getInstance();\n\n // Set emphasis characters to defaults. These are used to emphasize\n // certain characters or strings in user messages. They can be reset in\n // the useHTMLInMessages method.\n this.openEmph_ = Ucum.openEmph_;\n this.closeEmph_ = Ucum.closeEmph_;\n\n // Set the braces message to blank. This message is displayed for each\n // validation request on the web page, but is included separately as\n // a note on the validation spreadsheet. The useBraceMsgForEachString\n // method should be used to set the message to be displayed for each\n // unit string.\n this.bracesMsg_ = '';\n\n // Set the flags used, with indices, as place holders in unit strings\n // for parenthetical strings and strings within braces.\n this.parensFlag_ = \"parens_placeholder\"; // in lieu of Jehoshaphat\n this.pFlagLen_ = this.parensFlag_.length;\n this.braceFlag_ = \"braces_placeholder\"; // in lieu of Nebuchadnezzar\n this.bFlagLen_ = this.braceFlag_.length;\n\n // Initialize the message start/end strings, which will be set when\n // parseString is called.\n this.vcMsgStart_ = null;\n this.vcMsgEnd_ = null;\n\n // Arrays used by multiple methods within this class to hold persistent\n // data. Just gets too bulky to pass these guys around.\n\n // Messages to be returned to the calling function\n this.retMsg_ = [] ;\n\n // Units for parenthetical unit strings\n this.parensUnits_ = [] ;\n\n // annotation text for annotations found in unit strings\n this.annotations_ = [] ;\n\n // suggestions for unit strings that for which no unit was found\n this.suggestions = [] ;\n } // end constructor\n\n\n // The start of an error message about an invalid annotation character.\n static INVALID_ANNOTATION_CHAR_MSG = 'An invalid character was found in the annotation ';\n\n // A regular expression for validating annotation strings.\n static VALID_ANNOTATION_REGEX = /^\\{[!-z|~]*\\}$/;\n\n /**\n * Sets the emphasis strings to the HTML used in the webpage display - or\n * blanks them out, depending on the use parameter.\n *\n * @param use flag indicating whether or not to use the html message format;\n * defaults to true\n */\n useHTMLInMessages(use) {\n if (use === undefined || use) {\n this.openEmph_ = Ucum.openEmphHTML_;\n this.closeEmph_ = Ucum.closeEmphHTML_;\n }\n else {\n this.openEmph_ = Ucum.openEmph_;\n this.closeEmph_ = Ucum.closeEmph_;\n }\n } // end useHTMLInMessages\n\n\n /**\n * Sets the braces message to be displayed for each unit string validation\n * requested, as appropriate.\n *\n * @param use flag indicating whether or not to use the braces message;\n * defaults to true\n */\n useBraceMsgForEachString(use) {\n if (use === undefined || use)\n this.bracesMsg_ = Ucum.bracesMsg_;\n else\n this.bracesMsg_ = '';\n }\n\n\n /**\n * Parses a unit string, returns a unit, a possibly updated version of\n * the string passed in, and messages and suggestions where appropriate.\n *\n * The string returned may be updated if the input string contained unit\n * names, e.g., \"pound\". The unit code ([lb_av] for pound) is placed in\n * the string returned, a the returned messages array includes a note\n * explaining the substitution.\n *\n * @param uStr the string defining the unit\n * @param valConv indicates what type of request this is for - a request to\n * validate (pass in 'validate') or a request to convert (pass in 'convert');\n * optional, defaults to 'validate'\n * @param suggest a boolean to indicate whether or not suggestions are\n * requested for a string that cannot be resolved to a valid unit;\n * true indicates suggestions are wanted; false indicates they are not,\n * and is the default if the parameter is not specified;\n * @returns an array containing:\n * the unit object or null if a unit could not be created. In cases where\n * a fix was found for a problem string, .e.g., 2.mg for 2mg, a unit will\n * be returned but an error message will also be returned, describing\n * the substitution;\n * the possibly updated unit string passed in;\n * an array of any user messages (informational, error or warning)\n * generated (or an empty array); and\n * a suggestions array of hash objects (1 or more). Each hash contains\n * three elements:\n * 'msg' which is a message indicating what unit expression the\n * suggestions are for;\n * 'invalidUnit' which is the unit expression the suggestions are\n * for; and\n * 'units' which is an array of data for each suggested unit found.\n * Each array will contain the unit code, the unit name and the\n * unit guidance (if any).\n * The return array will not contain a suggestions array if a valid unit\n * was found or if suggestions were not requested.\n * @throws an error if nothing was specified.\n */\n parseString(uStr, valConv, suggest) {\n\n uStr = uStr.trim();\n // Make sure we have something to work with\n if (uStr === '' || uStr === null) {\n throw (new Error('Please specify a unit expression to be validated.'));\n }\n\n if (valConv === 'validate') {\n this.vcMsgStart_ = Ucum.valMsgStart_;\n this.vcMsgEnd_ = Ucum.valMsgEnd_;\n }\n else {\n this.vcMsgStart_ = Ucum.cnvMsgStart_;\n this.vcMsgEnd_ = Ucum.cnvMsgEnd_;\n }\n\n if (suggest === undefined || suggest === false) {\n this.suggestions_ = null;\n }\n else {\n this.suggestions_ = [] ;\n }\n\n this.retMsg_ = [];\n this.parensUnits_ = [];\n this.annotations_ = [] ;\n\n let origString = uStr;\n let retObj = [];\n\n // Extract any annotations, i.e., text enclosed in braces ({}) from the\n // string before further processing. Store each one in this.annotations_\n // array and put a placeholder in the string for the annotation. Do\n // this before other processing in case an annotation contains characters\n // that will be interpreted as parenthetical markers or operators in\n // subsequent processing.\n\n uStr = this._getAnnotations(uStr);\n if (this.retMsg_.length > 0) {\n retObj[0] = null;\n retObj[1] = null;\n }\n else {\n // Flag used to block further processing on an unrecoverable error\n let endProcessing = this.retMsg_.length > 0;\n\n // First check for one of the \"special\" units. If it's one of those, put\n // in a substitution phrase for it to avoid having it separated on its\n // embedded operator. This will only happen, by the way, if it is\n // preceded by a prefix or followed by an operator and another unit.\n let sUnit = null ;\n for (sUnit in Ucum.specUnits_) {\n while (uStr.indexOf(sUnit) !== -1)\n uStr = uStr.replace(sUnit, Ucum.specUnits_[sUnit]);\n }\n\n // Check for spaces and throw an error if any are found. The spec\n // explicitly forbids spaces except in annotations, which is why any\n // annotations are extracted before this check is made.\n if (uStr.indexOf(' ') > -1) {\n throw (new Error('Blank spaces are not allowed in unit expressions.'));\n } // end if blanks were found in the string\n\n // assign the array returned to retObj. It will contain 2 elements:\n // the unit returned in position 0; and the origString (possibly\n // modified) in position 1. The origString in position 1 will not\n // be changed by subsequent processing.\n retObj = this._parseTheString(uStr, origString);\n let finalUnit = retObj[0];\n\n // Do a final check to make sure that finalUnit is a unit and not\n // just a number. Something like \"8/{HCP}\" will return a \"unit\" of 8\n // - which is not a unit. Hm - evidently it is. So just create a unit\n // object for it.\n if (intUtils_.isIntegerUnit(finalUnit) || typeof finalUnit === 'number') {\n finalUnit = new Unit({\n 'csCode_': origString,\n 'magnitude_': finalUnit,\n 'name_': origString\n });\n retObj[0] = finalUnit;\n } // end final check\n } // end if no annotation errors were found\n\n retObj[2] = this.retMsg_;\n if (this.suggestions_ && this.suggestions_.length > 0)\n retObj[3] = this.suggestions_ ;\n return retObj;\n\n } // end parseString\n\n\n /**\n * Parses a unit string, returns a unit, a possibly updated version of\n * the string passed in, and messages where appropriate. This should\n * only be called from within this class (or by test code).\n *\n * The string returned may be updated if the input string contained unit\n * names, e.g., \"pound\". The unit code ([lb_av] for pound) is placed in\n * the string returned, a the returned messages array includes a note\n * explaining the substitution.\n *\n * @param uStr the string defining the unit\n * @param origString the original unit string passed in\n *\n * @returns\n * an array containing:\n * the unit object (or null if there were problems creating the unit); and\n * the possibly updated unit string passed in.\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n * the this.parensUnits_ array is referenced and possibly populated by\n * methods called within this one\n * the this.annotations_ array is referenced by methods called within\n * this one\n * the this.suggestions_ array may be populated by methods called within\n * this one\n */\n _parseTheString(uStr, origString) {\n\n // Unit to be returned\n let finalUnit = null;\n\n // Flag used to block further processing on an unrecoverable error\n let endProcessing = this.retMsg_.length > 0;\n\n // Call _processParens to search for and process any/all parenthetical\n // strings in uStr. Units created for parenthetical strings will be\n // stored in the this.parensUnits_ array.\n let parensResp = this._processParens(uStr, origString);\n endProcessing = parensResp[2];\n\n // The array used to hold the units and their operators.\n let uArray = [];\n\n // Continue if we didn't hit a problem\n if (!endProcessing) {\n uStr = parensResp[0];\n origString = parensResp[1];\n\n // Call _makeUnitsArray to convert the string to an array of unit\n // descriptors with operators.\n let mkUArray = this._makeUnitsArray(uStr, origString);\n\n endProcessing = mkUArray[2] ;\n if (!endProcessing) {\n uArray = mkUArray[0];\n origString = mkUArray[1];\n // Create a unit object out of each un element\n let uLen = uArray.length;\n for (let u1 = 0; u1 < uLen; u1++) {\n //for (let u1 = 0; u1 < uLen && !endProcessing; u1++) {\n let curCode = uArray[u1]['un'];\n\n // Determine the type of the \"un\" attribute of the current array element\n\n // Check to see if it's a number. If so write the number version of\n // the number back to the \"un\" attribute and move on\n if (intUtils_.isIntegerUnit(curCode)) {\n uArray[u1]['un'] = Number(curCode);\n }\n\n else {\n // The current unit array element is a string. Check now to see\n // if it is or contains a parenthesized unit from this.parensUnits_.\n // If so, call _getParens to process the string and get the unit.\n\n if (curCode.indexOf(this.parensFlag_) >= 0) {\n let parenUnit = this._getParensUnit(curCode, origString);\n // if we couldn't process the string, set the end flag and bypass\n // further processing.\n if (!endProcessing)\n endProcessing = parenUnit[1];\n\n // If we're good, put the unit in the uArray and replace the\n // curCode, which contains the parentheses placeholders, etc.,\n // with the unit's code - including any substitutions.\n if (!endProcessing) {\n uArray[u1]['un'] = parenUnit[0];\n }\n } // end if the curCode contains a parenthesized unit\n\n // Else it's not a parenthetical unit and not a number. Call\n // _makeUnit to create a unit for it.\n else {\n let uRet = this._makeUnit(curCode, origString);\n // If we didn't get a unit, set the endProcessing flag.\n if (uRet[0] === null) {\n endProcessing = true;\n }\n else {\n uArray[u1]['un'] = uRet[0];\n origString = uRet[1];\n }\n } // end if the curCode is not a parenthetical expression\n } // end if the \"un\" array is a not a number\n } // end do for each element in the units array\n } // end if _makeUnitsArray did not return an error\n } // end if _processParens did not find an error that causes a stop\n\n // If we're still good, continue\n if (!endProcessing) {\n // Process the units (and numbers) to create one final unit object\n if ((uArray[0] === null || uArray[0] === ' ' ||\n uArray[0]['un'] === undefined || uArray[0]['un'] === null)\n && this.retMsg_.length === 0) {\n // not sure what this might be, but this is a safeguard\n this.retMsg_.push(`Unit string (${origString}) did not contain ` +\n `anything that could be used to create a unit, or else something ` +\n `that is not handled yet by this package. Sorry`);\n endProcessing = true;\n }\n }\n if (!endProcessing) {\n finalUnit = this._performUnitArithmetic(uArray, origString);\n }\n return [finalUnit, origString];\n } // end _parseTheString\n\n\n /**\n * Extracts all annotations from a unit string, replacing them with\n * placeholders for later evaluation. The annotations are stored in the\n * this.annotations_ array. This should only be called from within this\n * class (or by test code).\n *\n * @param uString the unit string being parsed\n * @returns the string after the annotations are replaced with placeholders\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n * the this.annotations_ array is populated by this method\n */\n _getAnnotations(uString) {\n let openBrace = uString.indexOf('{');\n while (openBrace >= 0) {\n\n let closeBrace = uString.indexOf('}');\n if (closeBrace < 0) {\n this.retMsg_.push('Missing closing brace for annotation starting at ' +\n this.openEmph_ + uString.substr(openBrace) +\n this.closeEmph_);\n openBrace = -1;\n }\n else {\n let braceStr = uString.substring(openBrace, closeBrace + 1);\n // Check for valid characters in the annotation.\n if (!UnitString.VALID_ANNOTATION_REGEX.test(braceStr)) {\n this.retMsg_.push(UnitString.INVALID_ANNOTATION_CHAR_MSG +\n this.openEmph_ + braceStr + this.closeEmph_);\n openBrace = -1; // end search for annotations\n }\n else {\n let aIdx = this.annotations_.length.toString();\n uString = uString.replace(braceStr, this.braceFlag_ + aIdx +\n this.braceFlag_);\n this.annotations_.push(braceStr);\n openBrace = uString.indexOf('{');\n }\n }\n } // end do while we have an opening brace\n\n // check for a stray/unmatched closing brace\n if (this.retMsg_.length == 0) { // if there were no other errors above\n let closeBrace = uString.indexOf('}');\n if (closeBrace >= 0)\n this.retMsg_.push('Missing opening brace for closing brace found at ' +\n this.openEmph_ + uString.substring(0, closeBrace + 1) +\n this.closeEmph_);\n }\n return uString;\n } // end _getAnnotations\n\n\n /**\n * Finds and processes any/all parenthesized unit strings. This should only\n * be called from within this class (or by test code).\n *\n * Nested parenthesized strings are processed from the inside out. The\n * parseString function is called from within this one for each parenthesized\n * unit string, and the resulting unit object is stored in this.parensUnits_,\n * to be processed after all strings are translated to units.\n *\n * A placeholder is placed in the unit string returned to indicate that the\n * unit object should be obtained from the this.parensUnits_ array. The\n * placeholder consists of the parenthesis flag (this.parensFlag_) followed\n * by the index of the unit in this.parensUnits_ followed by this.parensFlag_.\n *\n * @param uString the unit string being parsed, where this will be the full\n * string the first time this is called and parenthesized strings on any\n * subsequent calls\n * @param origString the original string first passed in to parseString\n * @returns\n * an array containing:\n * the string after the parentheses are replaced;\n * the original string; and\n * a boolean flag indicating whether or not an error occurred that\n * should stop processing.\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n * this this.parensUnits_ array will be populated with units found for\n * parenthetical unit strings\n */\n _processParens(uString, origString) {\n\n // Unit strings array and index\n let uStrArray = [];\n let uStrAryPos = 0;\n let stopProcessing = false;\n\n let pu = this.parensUnits_.length;\n\n // Count of characters trimmed off the beginning of the unit string (uString)\n // as units are removed from it; used for error messages to provide\n // context.\n let trimmedCt = 0;\n\n // Break the unit string into pieces that consist of text outside of\n // parenthetical strings and placeholders for the parenthetical units.\n // This method is called recursively for parenthetical strings and the units\n // returned are stored in the this.parensUnits_ array.\n while (uString !== \"\" && !stopProcessing) {\n let openCt = 0;\n let closeCt = 0;\n let openPos = uString.indexOf('(');\n\n // If an opening parenthesis was not found, check for an unmatched\n // close parenthesis. If one was found report the error and end\n // processing.\n if (openPos < 0) {\n let closePos = uString.indexOf(')');\n if (closePos >= 0) {\n let theMsg = `Missing open parenthesis for close ` +\n `parenthesis at ${uString.substring(0, closePos + trimmedCt)}` +\n `${this.openEmph_}${uString.substr(closePos, 1)}${this.closeEmph_}`;\n if (closePos < uString.length - 1) {\n theMsg += `${uString.substr(closePos + 1)}`;\n }\n this.retMsg_.push(theMsg);\n uStrArray[uStrAryPos] = uString;\n stopProcessing = true;\n } // end if a close parenthesis was found\n\n // If no parentheses were found in the current unit string, transfer\n // it to the units array and blank out the string, which will end\n // the search for parenthetical units.\n else {\n uStrArray[uStrAryPos] = uString;\n uString = \"\";\n } // end if no close parenthesis was found\n } // end if no open parenthesis was found\n\n // Otherwise an open parenthesis was found. Process the string that\n // includes the parenthetical group\n else {\n openCt += 1;\n // Write the text before the parentheses (if any) to the unit strings array\n let uLen = uString.length;\n if (openPos > 0) {\n uStrArray[uStrAryPos++] = uString.substr(0, openPos);\n }\n\n // Find the matching closePos, i.e., the one that closes the\n // parenthetical group that this one opens. Look also for\n // another open parenthesis, in case this includes nested parenthetical\n // strings. This continues until it finds the same number of close\n // parentheses as open parentheses, or runs out of string to check.\n // In the case of nested parentheses this will identify the outer set\n // of parentheses.\n let closePos = 0;\n let c = openPos + 1;\n for (; c < uLen && openCt != closeCt; c++) {\n if (uString[c] === '(')\n openCt += 1;\n else if (uString[c] === ')')\n closeCt += 1;\n }\n\n // Put a placeholder for the group in the unit strings array and recursively\n // call this method for the parenthetical group. Put the unit returned\n // in this.parensUnits_. Set the unit string to whatever follows\n // the position of the closing parenthesis for this group, to be\n // processed by the next iteration of this loop. If there's nothing\n // left uString is set to \"\".\n if (openCt === closeCt) {\n closePos = c;\n uStrArray[uStrAryPos++] = this.parensFlag_ + pu.toString() + this.parensFlag_;\n let parseResp = this._parseTheString(\n uString.substring(openPos + 1, closePos - 1), origString);\n if (parseResp[0] === null)\n stopProcessing = true;\n else {\n origString = parseResp[1];\n this.parensUnits_[pu++] = parseResp[0];\n uString = uString.substr(closePos);\n trimmedCt = closePos;\n }\n } // end if the number of open and close parentheses matched\n\n // If the number of open and close parentheses doesn't match, indicate\n // an error.\n else {\n uStrArray.push(origString.substr(openPos));\n this.retMsg_.push(`Missing close parenthesis for open parenthesis at ` +\n `${origString.substring(0, openPos + trimmedCt)}` +\n `${this.openEmph_}${origString.substr(openPos, 1)}` +\n `${this.closeEmph_}${origString.substr(openPos + 1)}`);\n stopProcessing = true;\n }\n } // end if an open parenthesis was found\n } // end do while the input string is not empty\n if (stopProcessing)\n this.parensUnits_ = [];\n return [uStrArray.join(''), origString, stopProcessing]\n } // end _processParens\n\n\n /**\n * Breaks the unit string into an array of unit descriptors and operators.\n * If a unit descriptor consists of a number preceding a unit code, with\n * no multiplication operator, e.g., 2mg instead of 2.mg, it is handled\n * as if it were a parenthetical expression.\n *\n * This should only be called from within this class (or by test code).\n *\n * @param uStr the unit string being parsed\n * @param origString the original string passed to parseString\n * @returns\n * an array containing:\n * the array representing the unit string;\n * the original string passed in, possibly updated with corrections; and\n * and a flag indicating whether or not processing can continue.\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n */\n _makeUnitsArray(uStr, origString) {\n\n // Separate the string into pieces based on delimiters / (division) and .\n // (multiplication). The idea is to get an array of units on which we\n // can then perform any operations (prefixes, multiplication, division).\n\n let uArray1 = uStr.match(/([./]|[^./]+)/g);\n let endProcessing = false ;\n let uArray = [];\n let startNumCheck = /(^[0-9]+)(\\[?[a-zA-Z\\_0-9a-zA-Z\\_]+\\]?$)/ ;\n\n // If the first element in the array is the division operator (/), the\n // string started with '/'. Add a first element containing 1 to the\n // array, which will cause the correct computation to be performed (inversion).\n if (uArray1[0] === \"/\") {\n uArray1.unshift(\"1\");\n }\n // If the first element in the array is the multiplication operator (.)\n // return an error.\n else if (uArray1[0] === '.') {\n this.retMsg_.push(`${origString} is not a valid UCUM code. ` +\n `The multiplication operator at the beginning of the expression is ` +\n `not valid. A multiplication operator must appear only between ` +\n `two codes.`);\n endProcessing = true ;\n }\n if (!endProcessing) {\n // Check to see if there is a number preceding a unit code, e.g., 2mg\n // If so, update the first element to remove the number (2mg -> mg) and\n // add two elements to the beginning of the array - the number and the\n // multiplication operator.\n\n if (!intUtils_.isNumericString(uArray1[0])) {\n let numRes = uArray1[0].match(startNumCheck);\n if (numRes && numRes.length === 3 && numRes[1] !== '' &&\n numRes[2] !== '' && numRes[2].indexOf(this.braceFlag_) !== 0) {\n let dispVal = numRes[2] ;\n\n if (!endProcessing && numRes[2].indexOf(this.parensFlag_) !== -1) {\n let parensback = this._getParensUnit(numRes[2], origString);\n numRes[2] = parensback[0]['csCode_'];\n dispVal = `(${numRes[2]})`;\n endProcessing = parensback[1];\n }\n if (!endProcessing) {\n this.retMsg_.push(`${numRes[1]}${dispVal} is not a valid UCUM code.` +\n ` ${this.vcMsgStart_}${numRes[1]}.${dispVal}${this.vcMsgEnd_}`);\n origString = origString.replace(`${numRes[1]}${dispVal}`,\n `${numRes[1]}.${dispVal}`);\n uArray1[0] = numRes[2];\n uArray1.unshift(numRes[1], '.');\n }\n }\n } // end if the first element is not a number (only)\n\n // Create an array of unit/operator objects. The unit is, for now, the\n // string containing the unit code (e.g., Hz for hertz) including\n // a possible prefix and exponent. The operator is the operator to be\n // applied to that unit and the one preceding it. So, a.b would give\n // us two objects. The first will have a unit of a, and a blank operator\n // (because it's the first unit). The second would have a unit of b\n // and the multiplication operator (.).\n if (!endProcessing) {\n let u1 = uArray1.length;\n uArray = [{op: \"\", un: uArray1[0]}];\n for (let n = 1; n < u1; n++) {\n\n // check to make sure that we don't have two operators together, e.g.,\n // mg./K. If so, let the user know the problem.\n let theOp = uArray1[n++];\n // oh wait - check to make sure something is even there, that the\n // user didn't end the expression with an operator.\n if (!uArray1[n]) {\n this.retMsg_.push(`${origString} is not a valid UCUM code. ` +\n `It is terminated with the operator ${this.openEmph_}` +\n `${theOp}${this.closeEmph_}.`);\n n = u1;\n endProcessing = true;\n }\n else if (Ucum.validOps_.indexOf(uArray1[n]) !== -1) {\n this.retMsg_.push(`${origString} is not a valid UCUM code. ` +\n `A unit code is missing between${this.openEmph_}` +\n `${theOp}${this.closeEmph_}and${this.openEmph_}` +\n `${uArray1[n]}${this.closeEmph_}in${this.openEmph_}` +\n `${theOp}${uArray1[n]}${this.closeEmph_}.`);\n n = u1;\n endProcessing = true;\n }\n else {\n // Check to see if a number precedes a unit code.\n // If so, send the element to _processParens, inserting the multiplication\n // operator where it belongs. Treating it as parenthetical keeps it from\n // being interpreted incorrectly because of operator parentheses. For\n // example, if the whole string is mg/2kJ we don't want to rewrite it as\n // mg/2.kJ - because mg/2 would be performed, followed by .kJ. Instead,\n // handling 2kJ as a parenthesized unit will make sure mg is divided by\n // 2.kJ.\n if (!intUtils_.isNumericString(uArray1[n])) {\n let numRes2 = uArray1[n].match(startNumCheck);\n if (numRes2 && numRes2.length === 3 && numRes2[1] !== '' &&\n numRes2[2] !== '' && numRes2[2].indexOf(this.braceFlag_) !== 0) {\n let invalidString = numRes2[0];\n if (!endProcessing && numRes2[2].indexOf(this.parensFlag_) !== -1) {\n let parensback = this._getParensUnit(numRes2[2], origString);\n numRes2[2] = parensback[0]['csCode_'];\n invalidString = `(${numRes2[2]})`;\n endProcessing = parensback[1];\n if (!endProcessing) {\n this.retMsg_.push(`${numRes2[1]}${invalidString} is not a ` +\n `valid UCUM code. ${this.vcMsgStart_}${numRes2[1]}.${invalidString}` +\n `${this.vcMsgEnd_}`);\n let parensString = `(${numRes2[1]}.${invalidString})`;\n origString = origString.replace(`${numRes2[1]}${invalidString}`,\n parensString);\n let nextParens = this._processParens(parensString, origString);\n endProcessing = nextParens[2];\n if (!endProcessing) {\n uArray.push({op: theOp, un: nextParens[0]});\n }\n //uArray.push({op: '.', un: numRes2[2]});\n }\n } // end if the string represents a parenthesized unit\n else {\n let parensStr = '(' + numRes2[1] + '.' + numRes2[2] + ')';\n let parensResp = this._processParens(parensStr, origString);\n // if a \"stop processing\" flag was returned, set the n index to end\n // the loop and set the endProcessing flag\n if (parensResp[2]) {\n n = u1;\n endProcessing = true;\n }\n else {\n this.retMsg_.push(`${numRes2[0]} is not a ` +\n `valid UCUM code. ${this.vcMsgStart_}${numRes2[1]}.${numRes2[2]}` +\n `${this.vcMsgEnd_}`);\n origString = origString.replace(numRes2[0], parensStr);\n uArray.push({op: theOp, un: parensResp[0]});\n } // end if no error on the processParens call\n } // end if the string does not represent a parenthesized unit\n } // end if the string is a number followed by a string\n else {\n uArray.push({op: theOp, un: uArray1[n]});\n }\n }\n else {\n uArray.push({op: theOp, un: uArray1[n]});\n }\n } // end if there isn't a missing operator or unit code\n } // end do for each element in uArray1\n } // end if a processing error didn't occur in getParensUnit\n } // end if the string did not begin with a '.' with no following digit\n return [uArray, origString, endProcessing];\n } // end _makeUnitsArray\n\n\n /**\n * Takes a unit string containing parentheses flags and returns the unit they\n * represent. Any text found before and/or after the parenthetical\n * expression is checked to see if we can tell what the user meant and\n * let them know what it should have been. For example, 2(mg), which\n * would resolve to 2mg, should be 2.mg.\n *\n * This should only be called from within this class (or by test code).\n *\n * @param pStr the string being parsed\n * @param origString the original unit string passed in; passed through\n * to _getAnnonText if annotation flags are found in any text preceding\n * or following the parenthetical unit\n * @returns\n * an array containing\n * the unit object; and\n * a flag indicating whether or not processing should be ended.\n * True indicates that the string was invalid and no corrections\n * (substitutions or suggestions) could be found;\n * False indicates that it was either valid or substitutions/suggestions\n * were made.\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n * this this.parensUnits_ array contains the units that are acquired by\n * this method\n * @throws an error if an invalid parensUnit index was found. This is\n * a processing error.\n */\n _getParensUnit(pStr, origString) {\n let endProcessing = false;\n let retAry = [];\n let retUnit = null;\n let befAnnoText = null;\n let aftAnnoText = null;\n\n // Get the location of the flags. We're assuming there are only two\n // because _processParens takes care of nesting. By the time we get\n // here we should not be looking a nested parens. Also get any text\n // before and after the parentheses. Once we get the unit we update\n // the input string with the unit's csCode_, which will wipe out any\n // before and after text\n let psIdx = pStr.indexOf(this.parensFlag_);\n let befText = null;\n if (psIdx > 0) {\n befText = pStr.substr(0, psIdx - 1);\n }\n let peIdx = pStr.lastIndexOf(this.parensFlag_);\n let aftText = null;\n if (peIdx + this.pFlagLen_ < pStr.length) {\n aftText = pStr.substr(peIdx + this.pFlagLen_);\n }\n\n // Get the text between the flags\n let pNumText = pStr.substring(psIdx + this.pFlagLen_, peIdx);\n\n // Make sure the index is a number, and if it is, get the unit from the\n // this.parensUnits_ array\n if (intUtils_.isNumericString(pNumText)) {\n retUnit = this.parensUnits_[Number(pNumText)];\n if (!intUtils_.isIntegerUnit(retUnit)) {\n pStr = retUnit.csCode_;\n }\n else {\n pStr = retUnit ;\n }\n }\n // If it's not a number, it's a programming error. Throw a fit.\n else {\n throw (new Error(`Processing error - invalid parens number ${pNumText} ` +\n `found in ${pStr}.`));\n }\n\n // If there's something in front of the starting parentheses flag, check to\n // see if it's a number or an annotation.\n if (befText) {\n // If it's a number, assume that multiplication was assumed\n if (intUtils_.isNumericString(befText)) {\n let nMag = retUnit.getProperty('magnitude_');\n nMag *= Number(befText);\n retUnit.assignVals({'magnitude_': nMag});\n pStr = `${befText}.${pStr}`;\n this.retMsg_.push(`${befText}${pStr} is not a valid UCUM code.\\n` +\n this.vcMsgStart_ + pStr + this.vcMsgEnd_);\n }\n else {\n if (befText.indexOf(this.braceFlag_) >= 0) {\n let annoRet = this._getAnnoText(befText, origString);\n // if we found not only an annotation, but text before or after\n // the annotation (remembering that this is all before the\n // parentheses) throw an error - because we don't know what\n // to do with it. Could it be missing an operator?\n if (annoRet[1] || annoRet[2]) {\n throw (new Error(`Text found before the parentheses (` +\n `${befText}) included an annotation along with other text ` +\n `for parenthetical unit ${retUnit.csCode_}`));\n }\n // Otherwise put the annotation after the unit string and note\n // the misplacement.\n pStr += annoRet[0];\n this.retMsg_.push(`The annotation ${annoRet[0]} before the unit ` +\n `code is invalid.\\n` + this.vcMsgStart_ + pStr + this.vcMsgEnd_);\n }\n // else the text before the parentheses is neither a number nor\n // an annotation. If suggestions were NOT requested, record an\n // error.\n else if (!this.suggestions_) {\n this.retMsg_.push(`${befText} preceding the unit code ${pStr} ` +\n `is invalid. Unable to make a substitution.`);\n endProcessing = true;\n }\n // otherwise try for suggestions\n else {\n let suggestStat = this._getSuggestions(befText);\n endProcessing = (suggestStat !== 'succeeded');\n\n } // end if a brace was found or, if not, suggestions were not or\n // were requested\n } // end if text preceding the parentheses was not a number\n } // end if there was text before the parentheses\n\n // Process any text after the parentheses\n if (aftText) {\n // if it's an annotation, get it and add it to the pStr\n if (aftText.indexOf(this.braceFlag_) >= 0) {\n let annoRet = this._getAnnoText(aftText, origString);\n // if we found not only an annotation, but text before or after\n // the annotation (remembering that this is all after the\n // parentheses) throw an error - because we don't know what\n // to do with it. Could it be missing an operator?\n if (annoRet[1] || annoRet[2]) {\n throw (new Error(`Text found after the parentheses (` +\n `${aftText}) included an annotation along with other text ` +\n `for parenthetical unit ${retUnit.csCode_}`));\n }\n // Otherwise put the annotation after the unit string - no message\n // needed.\n pStr += annoRet[0];\n }\n // Otherwise check to see if it's an exponent. If so, warn the\n // user that it's not valid - but try it anyway\n else {\n\n if (intUtils_.isNumericString(aftText)) {\n pStr += aftText;\n retUnit = retUnit.power(Number(aftText));\n this.retMsg_.push(`An exponent (${aftText}) following a parenthesis ` +\n `is invalid as of revision 1.9 of the UCUM Specification.\\n ` +\n this.vcMsgStart_ + pStr + this.vcMsgEnd_);\n }\n // else the text after the parentheses is neither a number nor\n // an annotation. If suggestions were NOT requested, record an\n // error.\n else if (!this.suggestions_) {\n this.retMsg_.push(`Text ${aftText} following the unit code ${pStr} ` +\n `is invalid. Unable to make a substitution.`);\n endProcessing = true;\n }\n // otherwise try for suggestions\n else {\n let suggestStat = this._getSuggestions(befText);\n endProcessing = (suggestStat !== 'succeeded');\n } // end if text following the parentheses not an exponent\n } // end if text following the parentheses is not an annotation\n } // end if there is text following the parentheses\n if (!endProcessing) {\n if (!retUnit) {\n retUnit = new Unit({\n 'csCode_': pStr,\n 'magnitude_': 1,\n 'name_': pStr});\n }\n else if (intUtils_.isIntegerUnit(retUnit)) {\n retUnit = new Unit({'csCode_': retUnit,\n 'magnitude_': retUnit,\n 'name_': retUnit});\n }\n else {\n retUnit.csCode_ = pStr;\n }\n }\n return [retUnit, endProcessing];\n } // end _getParensUnit\n\n /**\n * Takes a unit string containing annotation flags and returns the\n * annotation they represent. This also returns any text found before\n * the annotation and any found after the annotation.\n *\n * This should only be called from within this class (or by test code).\n * NEEDS FIX in next branch to handle string with multiple annotations.\n *\n * @param pStr the string being parsed\n * @param origString the original string being parsed; used in error msg\n * thrown for an invalid index to the annotations array\n * @returns\n * an array containing\n * the annotation for the pStr;\n * any text found before the annotation; and\n * any text found after the annotation.\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n * the this.annotations_ array is used as the source for the annotations text\n * @throws an error if for a processing error - an invalid annotation index.\n */\n _getAnnoText(pStr, origString) {\n\n // if the starting braces flag is not at index 0, get the starting\n // text and the adjust the pStr to omit it.\n let asIdx = pStr.indexOf(this.braceFlag_);\n let startText = (asIdx > 0) ? pStr.substring(0, asIdx) : null;\n if (asIdx !== 0) {\n pStr = pStr.substr(asIdx);\n }\n\n // Get the location of the end flag and, if text follows it, get the text\n let aeIdx = pStr.indexOf(this.braceFlag_, 1);\n let endText = ((aeIdx + this.bFlagLen_) < pStr.length) ?\n pStr.substr(aeIdx + this.bFlagLen_) : null;\n\n // Get the index of the annotation in this.annotations_.\n // Check it to make sure it's valid, and if not, throw an error\n let idx = pStr.substring(this.bFlagLen_, aeIdx);\n let idxNum = Number(idx);\n if (!intUtils_.isNumericString(idx) || idxNum >= this.annotations_.length) {\n throw (new Error(`Processing Error - invalid annotation index ${idx} found ` +\n `in ${pStr} that was created from ${origString}`));\n }\n\n // Replace the flags and annotation index with the annotation expression\n pStr = this.annotations_[idxNum];\n return [pStr, startText, endText];\n } // end _getAnnoText\n\n\n /**\n * Takes a unit string and looks for suggested units. This should be\n * called for unit strings that cannot be resolved to unit codes. The\n * string is searched for in the synonyms table found in the UnitTables\n * class. That table includes all synonyms and unit names for the units\n * in the unit data table.\n *\n * @param pStr the string being parsed\n * @returns an object that contains an element named 'status', whose\n * value indicates the status of the request:\n * 'succeeded' indicates that synonyms were found;\n * 'failed' indicates that no synonyms were found; or\n * 'error' which indicates that an error occurred\n *\n * the this.retMsg_ array will be updated with a message indicating whether\n * or not synonyms/suggestions were found\n * the this.suggestions_ array will be updated with a hash (added to the\n * array if it already contains others) that contains three elements:\n * 'msg' which is a message indicating what unit expression the\n * suggestions are for;\n * 'invalidUnit' which is the unit expression the suggestions are for; and\n * 'units' which is an array of data for each suggested unit found.\n * Each array will contain the unit code, the unit name and the\n * unit guidance (if any).\n */\n _getSuggestions(pStr) {\n\n let retObj = intUtils_.getSynonyms(pStr);\n if (retObj['status'] === 'succeeded') {\n let suggSet = {} ;\n suggSet['msg'] = `${pStr} is not a valid UCUM code. We found possible ` +\n `units that might be what was meant:`;\n suggSet['invalidUnit'] = pStr ;\n let synLen = retObj['units'].length ;\n suggSet['units'] = [] ;\n for (let s = 0; s < synLen; s++) {\n let unit = retObj['units'][s];\n let unitArray = [unit['code'], unit['name'], unit['guidance']];\n\n suggSet['units'].push(unitArray) ;\n }\n this.suggestions_.push(suggSet);\n }\n else {\n this.retMsg_.push(`${pStr} is not a valid UCUM code. No alternatives ` +\n `were found.`);\n }\n return retObj['status'] ;\n } // end getSuggestions\n\n\n /**\n * Creates a unit object from a string defining one unit. The string\n * should consist of a unit code for a unit already defined (base or\n * otherwise). It may include a prefix and an exponent, e.g., cm2\n * (centimeter squared). This should only be called from within this\n * class (or by test code).\n *\n * @params uCode the string defining the unit\n * @param origString the original string to be parsed; used to provide\n * context for messages\n * @returns\n * an array containing:\n * a unit object, or null if there were problems creating the unit; and\n * the origString passed in, which may be updated if a unit name was\n * translated to a unit code.\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n * the this.suggestions_ array will be populated if no unit (with or without\n * substitutions) could be found and suggestions were requested\n */\n _makeUnit(uCode, origString) {\n\n // First try the code just as is, without looking for annotations,\n // prefixes, exponents, or elephants.\n let retUnit = this.utabs_.getUnitByCode(uCode);\n if (retUnit) {\n retUnit = retUnit.clone();\n }\n\n // If we found it, we're done. No need to parse for those elephants (or\n // other stuff).\n else if (uCode.indexOf(this.braceFlag_) >= 0) {\n let getAnnoRet = this._getUnitWithAnnotation(uCode, origString);\n retUnit = getAnnoRet[0];\n if (retUnit) {\n origString = getAnnoRet[1];\n }\n // If a unit is not found, retUnit will be returned null and\n // the this.retMsg_ array will contain a message describing the problem.\n // If a unit is found, of course, all is good. So ... nothing left\n // to see here, move along.\n } // end if the uCode includes an annotation\n\n else {\n\n // So we didn't find a unit for the full uCode or for one with\n // annotations. Try looking for a unit that uses a carat (^)\n // instead of an asterisk (*)\n\n if (uCode.indexOf('^') > -1) {\n let tryCode = uCode.replace('^', '*');\n retUnit = this.utabs_.getUnitByCode(tryCode);\n if (retUnit) {\n retUnit = retUnit.clone();\n retUnit.csCode_ = retUnit.csCode_.replace('*', '^');\n retUnit.ciCode_ = retUnit.ciCode_.replace('*', '^');\n }\n }\n // If that didn't work, check to see if it should have brackets\n // around it (uCode = degF when it should be [degF]\n if (!retUnit) {\n let addBrackets = '[' + uCode + ']' ;\n retUnit = this.utabs_.getUnitByCode(addBrackets);\n if (retUnit) {\n retUnit = retUnit.clone();\n origString = origString.replace(uCode, addBrackets);\n this.retMsg_.push(`${uCode} is not a valid unit expression, but ` +\n `${addBrackets} is.\\n` + this.vcMsgStart_ +\n `${addBrackets} (${retUnit.name_})${this.vcMsgEnd_}`);\n } // end if we found the unit after adding brackets\n } // end trying to add brackets\n\n // If we didn't find it, try it as a name\n if (!retUnit) {\n let retUnitAry = this.utabs_.getUnitByName(uCode);\n if (retUnitAry && retUnitAry.length > 0) {\n retUnit = retUnitAry[0].clone();\n let mString = 'The UCUM code for ' + uCode + ' is ' +\n retUnit.csCode_ + '.\\n' + this.vcMsgStart_ +\n retUnit.csCode_ + this.vcMsgEnd_;\n let dupMsg = false;\n for (let r = 0; r < this.retMsg_.length && !dupMsg; r++)\n dupMsg = this.retMsg_[r] === mString;\n if (!dupMsg)\n this.retMsg_.push(mString);\n let rStr = new RegExp('(^|[.\\/({])(' + uCode + ')($|[.\\/)}])');\n let res = origString.match(rStr);\n origString = origString.replace(rStr, res[1] + retUnit.csCode_ + res[3]);\n uCode = retUnit.csCode_;\n }\n }\n\n // If we still don't have a unit, try assuming a modifier (prefix and/or\n // exponent) and look for a unit without the modifier\n if (!retUnit) {\n\n // Well, first see if it's one of the special units. If so,\n // replace the placeholder text with the actual unit string, keeping\n // whatever text (probably a prefix) goes with the unit string.\n let sUnit = null;\n for (sUnit in Ucum.specUnits_) {\n if (uCode.indexOf(Ucum.specUnits_[sUnit]) !== -1)\n uCode = uCode.replace(Ucum.specUnits_[sUnit], sUnit);\n }\n retUnit = this.utabs_.getUnitByCode(uCode);\n if (retUnit)\n retUnit = retUnit.clone();\n }\n if (!retUnit) {\n\n let origCode = uCode;\n let origUnit = null;\n let exp = null;\n let pfxCode = null;\n let pfxObj = null;\n let pfxVal = null;\n let pfxExp = null;\n\n // Look first for an exponent. If we got one, separate it out and\n // try to get the unit again\n let codeAndExp = this._isCodeWithExponent(uCode);\n if (codeAndExp) {\n uCode = codeAndExp[0];\n exp = codeAndExp[1];\n origUnit = this.utabs_.getUnitByCode(uCode);\n }\n\n\n // If we still don't have a unit, separate out the prefix, if any,\n // and try without it.\n if (!origUnit) {\n // Try for a single character prefix first.\n pfxCode = uCode.charAt(0);\n pfxObj = this.pfxTabs_.getPrefixByCode(pfxCode);\n\n // if we got a prefix, get its info and remove it from the unit code\n if (pfxObj) {\n pfxVal = pfxObj.getValue();\n pfxExp = pfxObj.getExp();\n let pCodeLen = pfxCode.length;\n uCode = uCode.substr(pCodeLen);\n\n // try again for the unit\n origUnit = this.utabs_.getUnitByCode(uCode);\n\n // If we still don't have a unit, see if the prefix could be the\n // two character \"da\" (deka) prefix. That's the only prefix with\n // two characters, and without this check it's interpreted as \"d\"\n // (deci) and the \"a\" is considered part of the unit code.\n\n if (!origUnit && pfxCode == 'd' && uCode.substr(0, 1) == 'a') {\n pfxCode = 'da';\n pfxObj = this.pfxTabs_.getPrefixByCode(pfxCode);\n pfxVal = pfxObj.getValue();\n uCode = uCode.substr(1);\n\n // try one more time for the unit\n origUnit = this.utabs_.getUnitByCode(uCode);\n }\n\n // Reject the unit we found if it might have another prefix.\n // Such things are in our tables through the LOINC source_\n // (ucum.csv) which has guidance and synonyms. I think it should be\n // safe to exclude anything whose source is LOINC from having a\n // prefix.\n if (origUnit && origUnit.source_ == 'LOINC')\n origUnit = null;\n } // end if we found a prefix\n } // end if we didn't get a unit after removing an exponent\n\n // If we still haven't found anything, we're done looking.\n // (We tried with the full unit string, with the unit string\n // without the exponent, the unit string without a prefix,\n // common errors, etc. That's all we can try).\n if (!origUnit) {\n retUnit = null ;\n // BUT if the user asked for suggestions, at least look for them\n if (this.suggestions_) {\n let suggestStat = this._getSuggestions(origCode);\n }\n else {\n this.retMsg_.push(`${origCode} is not a valid UCUM code.`);\n }\n }\n else {\n // Otherwise we found a unit object. Clone it and then apply the\n // prefix and exponent, if any, to it. And remove the guidance.\n retUnit = origUnit.clone();\n // If we are here, this is only part of the full unit string, so it is\n // not a base unit, and the synonyms will mostly likely not be correct for the full\n // string.\n retUnit.resetFieldsForDerivedUnit();\n let theDim = retUnit.getProperty('dim_');\n let theMag = retUnit.getProperty('magnitude_');\n let theName = retUnit.getProperty('name_');\n let theCiCode = retUnit.getProperty('ciCode_');\n let thePrintSymbol = retUnit.getProperty('printSymbol_');\n // If there is an exponent for the unit, apply it to the dimension\n // and magnitude now\n if (exp) {\n exp = parseInt(exp);\n let expMul = exp;\n if (theDim)\n theDim = theDim.mul(exp);\n theMag = Math.pow(theMag, exp);\n retUnit.assignVals({'magnitude_': theMag});\n\n // If there is also a prefix, apply the exponent to the prefix.\n if (pfxObj) {\n\n // if the prefix base is 10 it will have an exponent. Multiply\n // the current prefix exponent by the exponent for the unit\n // we're working with. Then raise the prefix value to the level\n // defined by the exponent.\n if (pfxExp) {\n expMul *= pfxObj.getExp();\n pfxVal = Math.pow(10, expMul);\n }\n // If the prefix base is not 10, it won't have an exponent.\n // At the moment I don't see any units using the prefixes\n // that aren't base 10. But if we get one the prefix value\n // will be applied to the magnitude (below) if the unit does\n // not have a conversion function, and to the conversion prefix\n // if it does.\n } // end if there's a prefix as well as the exponent\n } // end if there's an exponent\n\n // Now apply the prefix, if there is one, to the conversion\n // prefix or the magnitude\n if (pfxObj) {\n if (retUnit.cnv_) {\n retUnit.assignVals({'cnvPfx_': pfxVal});\n }\n else {\n theMag *= pfxVal;\n retUnit.assignVals({'magnitude_': theMag})\n }\n }\n // if we have a prefix and/or an exponent, add them to the unit\n // attributes - name, csCode, ciCode and print symbol\n let theCode = retUnit.csCode_;\n if (pfxObj) {\n theName = pfxObj.getName() + theName;\n theCode = pfxCode + theCode;\n theCiCode = pfxObj.getCiCode() + theCiCode;\n thePrintSymbol = pfxObj.getPrintSymbol() + thePrintSymbol;\n retUnit.assignVals({\n 'name_': theName,\n 'csCode_': theCode,\n 'ciCode_': theCiCode,\n 'printSymbol_': thePrintSymbol\n });\n }\n if (exp) {\n let expStr = exp.toString();\n retUnit.assignVals({\n 'name_': theName + '<sup>' + expStr + '</sup>',\n 'csCode_': theCode + expStr,\n 'ciCode_': theCiCode + expStr,\n 'printSymbol_': thePrintSymbol + '<sup>' + expStr + '</sup>'\n });\n }\n } // end if an original unit was found (without prefix and/or exponent)\n\n } // end if we didn't get a unit for the full unit code (w/out modifiers)\n } // end if we didn't find the unit on the first try, before parsing\n return [retUnit, origString];\n } // end _makeUnit\n\n\n /**\n * This method handles unit creation when an annotation is included\n * in the unit string. This basically isolates and retrieves the\n * annotation and then calls _makeUnit to try to get a unit from\n * any text that precedes or follows the annotation.\n *\n * @param uCode the string defining the unit\n * @param origString the original full string submitted to parseString\n * @returns the unit object found, or null if one could not be found\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n */\n _getUnitWithAnnotation(uCode, origString) {\n\n let retUnit = null;\n\n // Get the annotation and anything that precedes or follows it.\n let annoRet = this._getAnnoText(uCode, origString);\n let annoText = annoRet[0];\n let befAnnoText = annoRet[1];\n let aftAnnoText = annoRet[2];\n\n // Add the warning about annotations - just once.\n\n if (this.bracesMsg_ && this.retMsg_.indexOf(this.bracesMsg_) === -1)\n this.retMsg_.push(this.bracesMsg_);\n\n // If there's no text before or after the annotation, it's probably\n // something that should be interpreted as a 1, e.g., {KCT'U}.\n // HOWEVER, it could also be a case where someone used braces instead\n // of brackets, e.g., {degF} instead of [degF]. Check for that before\n // we assume it should be a 1.\n let msgLen = this.retMsg_.length;\n if (!befAnnoText && !aftAnnoText) {\n let tryBrackets = '[' + annoText.substring(1, annoText.length - 1) + ']';\n let mkUnitRet = this._makeUnit(tryBrackets, origString);\n\n // If we got back a unit, assign it to the returned unit, and add\n // a message to advise the user that brackets should enclose the code\n if (mkUnitRet[0]) {\n retUnit = mkUnitRet[0];\n origString = origString.replace(annoText, tryBrackets);\n this.retMsg_.push(`${annoText} is not a valid unit expression, but ` +\n `${tryBrackets} is.\\n` + this.vcMsgStart_ +\n `${tryBrackets} (${retUnit.name_})${this.vcMsgEnd_}`);\n }\n // Otherwise assume that this should be interpreted as a 1\n else {\n // remove error message generated for trybrackets\n if (this.retMsg_.length > msgLen) {\n this.retMsg_.pop();\n }\n uCode = 1;\n retUnit = 1;\n }\n } // end if it's only an annotation\n\n else {\n // if there's text before and no text after, assume the text before\n // the annotation is the unit code (with an annotation following it).\n // Call _makeUnit for the text before the annotation.\n if (befAnnoText && !aftAnnoText) {\n // make sure that what's before the annoText is not a number, e.g.,\n // /100{cells}. But f it is a number, just set the return unit to\n // the number.\n if (intUtils_.isIntegerUnit(befAnnoText)) {\n retUnit = befAnnoText ;\n }\n // Otherwise try to find a unit\n else {\n let mkUnitRet = this._makeUnit(befAnnoText, origString);\n\n // if a unit was returned\n if (mkUnitRet[0]) {\n retUnit = mkUnitRet[0];\n retUnit.csCode_ += annoText;\n origString = mkUnitRet[1];\n }\n // Otherwise add a not found message\n else {\n this.retMsg_.push(`Unable to find a unit for ${befAnnoText} that ` +\n `precedes the annotation ${annoText}.`);\n }\n }\n }\n // else if there's only text after the annotation, try for a unit\n // from the after text and assume the user put the annotation in\n // the wrong place (and tell them)\n else if (!befAnnoText && aftAnnoText) {\n\n // Again, test for a number and if it is a number, set the return\n // unit to the number.\n if (intUtils_.isIntegerUnit(aftAnnoText)) {\n retUnit = aftAnnoText + annoText ;\n this.retMsg_.push(`The annotation ${annoText} before the `\n `${aftAnnoText} is invalid.\\n` + this.vcMsgStart_ + retUnit +\n this.vcMsgEnd_);\n }\n else {\n let mkUnitRet = this._makeUnit(aftAnnoText, origString);\n if (mkUnitRet[0]) {\n retUnit = mkUnitRet[0];\n retUnit.csCode_ += annoText;\n origString = retUnit.csCode_;\n this.retMsg_.push(`The annotation ${annoText} before the unit ` +\n `code is invalid.\\n` + this.vcMsgStart_ + retUnit.csCode_ +\n this.vcMsgEnd_);\n }\n // Otherwise add a not found message\n else {\n this.retMsg_.push(`Unable to find a unit for ${befAnnoText} that ` +\n `follows the annotation ${annoText}.`);\n }\n }\n }\n // else it's got text before AND after the annotation. Now what?\n // For now this is an error. This may be a case of a missing\n // operator but that is not handled yet.\n else {\n this.retMsg_.push(`Unable to find a unit for ${befAnnoText}${annoText}` +\n `${aftAnnoText}.\\nWe are not sure how to interpret text both before ` +\n `and after the annotation. Sorry`);\n }\n } // else if there's text before/and or after the annotation\n\n return [retUnit , origString];\n\n } // end _getUnitWithAnnotations\n\n\n /**\n * Performs unit arithmetic for the units in the units array. That array\n * contains units/numbers and the operators (division or multiplication) to\n * be performed on each unit/unit or unit/number pair in the array. This\n * should only be called from within this class (or by test code).\n *\n * @params uArray the array that contains the units, numbers and operators\n * derived from the unit string passed in to parseString\n * @param origString the original string to be parsed; used to provide\n * context for messages\n *\n * @returns a single unit object that is the result of the unit arithmetic\n *\n * the this.retMsg_ array will be updated with any user messages\n * (informational, error or warning) generated by this or called methods\n */\n _performUnitArithmetic(uArray, origString) {\n\n let finalUnit = uArray[0]['un'];\n if (intUtils_.isIntegerUnit(finalUnit)) {\n finalUnit = new Unit({'csCode_' : finalUnit,\n 'magnitude_' : Number(finalUnit),\n 'name_' : finalUnit}) ;\n }\n let uLen = uArray.length ;\n let endProcessing = false ;\n // Perform the arithmetic for the units, starting with the first 2 units.\n // We only need to do the arithmetic if we have more than one unit.\n for (let u2 = 1; (u2 < uLen) && !endProcessing; u2++) {\n let nextUnit = uArray[u2]['un'];\n if (intUtils_.isIntegerUnit(nextUnit)) {\n nextUnit = new Unit({'csCode_' : nextUnit ,\n 'magnitude_' : Number(nextUnit),\n 'name_': nextUnit});\n }\n if (nextUnit === null ||\n ((typeof nextUnit !== 'number') && (!nextUnit.getProperty))) {\n let msgString = `Unit string (${origString}) contains unrecognized ` +\n 'element' ;\n if (nextUnit) {\n msgString += ` (${this.openEmph_}${nextUnit.toString()}` +\n `${this.closeEmph_})`;\n }\n msgString += '; could not parse full string. Sorry';\n this.retMsg_.push(msgString);\n endProcessing = true;\n }\n else {\n try {\n // Is the operation division?\n let thisOp = uArray[u2]['op'];\n let isDiv = thisOp === '/';\n\n // Perform the operation. Both the finalUnit and nextUnit\n // are unit objects.\n isDiv ? finalUnit = finalUnit.divide(nextUnit) :\n finalUnit = finalUnit.multiplyThese(nextUnit);\n }\n catch (err) {\n this.retMsg_.unshift(err.message) ;\n endProcessing = true ;\n finalUnit = null ;\n }\n } // end if we have another valid unit/number to process\n } // end do for each unit after the first one\n return finalUnit ;\n } // end _performUnitArithmetic\n\n\n /**\n * This tests a string to see if it starts with characters and ends with\n * digits. This is used to test for an exponent on a UCUM code (or what\n * we think might be a UCUM code). This is broken out to a separate\n * function so that the regular expression can be verified to provide the\n * results we expect, in case someone changes it. (Per Paul Lynch)\n * See \"Test _isCodeWithExponent method\" in testUnitString.spec.js\n *\n * This particular regex has been tweaked several times. This one\n * works with the following test strings:\n * \"m[H2O]-21 gives [\"m[H2O]-21\", \"m[H2O]\", \"-21\"]\n * \"m[H2O]+21 gives [\"m[H2O]+21\", \"m[H2O]\", \"+21\"]\n * \"m[H2O]21 gives [\"m[H2O]-21\", \"m[H2O]\", \"21\"]\n * \"s2\" gives [\"s2\", \"s, \"2\"]\n * \"kg\" gives null\n * \"m[H2O]\" gives null\n * \"m[H2O]23X\" gives null\n *\n * @params uCode the code being tested\n * @returns an array containing: (1) the code without the exponent (or\n * trailing number); and (2) the exponent/trailing number. Returns null\n * if there is no trailing number or something follows the trailing\n * number, or if the first part is not characters.\n */\n _isCodeWithExponent(uCode) {\n\n let ret = [] ;\n let res = uCode.match(/(^[^\\-\\+]+?)([\\-\\+\\d]+)$/);\n\n // If we got a return with an exponent, separate the exponent from the\n // unit and return both (as separate values)\n if (res && res[2] && res[2] !== \"\") {\n ret.push(res[1]);\n ret.push(res[2]);\n } // end if we got an exponent\n else {\n ret = null ;\n }\n return ret ;\n } // end _isCodeWithExponent\n\n} // end class UnitString\n\n\n/**\n * This function exists ONLY until the original UnitString constructor\n * is called for the first time. It's defined here in case getInstance\n * is called before the constructor. This calls the constructor.\n *\n * The constructor redefines the getInstance function to return the\n * singleton UnitString object. This is based on the UnitTables singleton\n * implementation; see more detail in the UnitTables constructor description.\n *\n * @return the singleton UnitString object.\n */\nUnitString.getInstance = function(){\n return new UnitString();\n} ;\n\n/*\n// Perform the first request for the object, to set the getInstance method.\nUnitString.getInstance();\n\n*/\n"],"file":"unitString.js"}
|
package/CHANGELOG.md
DELETED
|
@@ -1,329 +0,0 @@
|
|
|
1
|
-
# Change Log
|
|
2
|
-
All notable changes to this project will be documented in this file.
|
|
3
|
-
|
|
4
|
-
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
|
5
|
-
and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
6
|
-
|
|
7
|
-
## [4.1.7] 2022-12-21
|
|
8
|
-
### Fixed
|
|
9
|
-
- Units from the data/ucum.csv file, which contains many unit strings with
|
|
10
|
-
prefixes, were previously permitted to take an additional prefix.
|
|
11
|
-
- Units derived from other units were previously being labeled as "base units",
|
|
12
|
-
though apparently without ill effect on the current public APIs.
|
|
13
|
-
|
|
14
|
-
## [4.1.6] 2022-09-13
|
|
15
|
-
### Changed
|
|
16
|
-
- Update version to 4.1.6 for tagging the last merge, which was to update
|
|
17
|
-
generated files but was not given a new version number and not tagged.
|
|
18
|
-
|
|
19
|
-
## [4.1.5] 2021-05-20
|
|
20
|
-
### Fixed
|
|
21
|
-
- Fixed generated name issue for complex units, https://github.com/lhncbc/ucum-lhc/issues/29
|
|
22
|
-
|
|
23
|
-
## [4.1.4] 2021-01-05
|
|
24
|
-
### Fixed
|
|
25
|
-
- Moved grunt-extract-sourcemap to devDependencies.
|
|
26
|
-
- Updated dependencies to avoid issues raised by npm audit (except one
|
|
27
|
-
on a devDependency).
|
|
28
|
-
|
|
29
|
-
## [4.1.3] 2020-04-20
|
|
30
|
-
### Fixed
|
|
31
|
-
- Fixed to work in IE 11.
|
|
32
|
-
|
|
33
|
-
## [4.1.2] 2020-04-03
|
|
34
|
-
### Changes
|
|
35
|
-
- Updated dependencies to get patches for security vulnerabilities.
|
|
36
|
-
|
|
37
|
-
## [4.1.1] 2020-03-09
|
|
38
|
-
### Changes
|
|
39
|
-
- removed unnecessary index.html
|
|
40
|
-
|
|
41
|
-
## [4.1.0] 2020-03-05
|
|
42
|
-
### Changes
|
|
43
|
-
- the sizes of ucumDefs.json and related files reduced
|
|
44
|
-
|
|
45
|
-
## [4.0.2] 2020-03-02
|
|
46
|
-
### Fixed
|
|
47
|
-
- ucumDefs.json generation: baseFactor_ and magnitude_ should be numbers
|
|
48
|
-
### Added
|
|
49
|
-
- added impexp/README.md about generating ucumDef.json
|
|
50
|
-
|
|
51
|
-
## [4.0.1] 2020-02-14
|
|
52
|
-
### Fixed
|
|
53
|
-
- 4.0.0 was just published today, and is missing a data file in the npm package.
|
|
54
|
-
This version fixes that.
|
|
55
|
-
|
|
56
|
-
## [4.0.0] 2020-01-27
|
|
57
|
-
### Changed
|
|
58
|
-
- This main file of the npm package is now a file that uses CommonJS modules
|
|
59
|
-
(i.e., NodeJs-compatible) instead of a browserified bundle. The problem with
|
|
60
|
-
serving a browserfied bundle via npm was that if you pulled it in and then
|
|
61
|
-
tried to browserify it along with application code, an exception would be thrown
|
|
62
|
-
because browserify has already run on part of the code. The change should be
|
|
63
|
-
transparent to the user of the package, but just in case there is some
|
|
64
|
-
unforeseen consequence, I am incrementing the major version. If your
|
|
65
|
-
application needs the browserified version, that is still available in the
|
|
66
|
-
browser-dist directory.
|
|
67
|
-
|
|
68
|
-
## [3.0.1] 2020-01-07
|
|
69
|
-
### Fixed
|
|
70
|
-
- Corrected processing so that strings like "1e2" are no longer considered valid
|
|
71
|
-
units.
|
|
72
|
-
|
|
73
|
-
## [3.0.0] - 2019-09-26
|
|
74
|
-
### Fixed
|
|
75
|
-
- Updated dependencies to get patches for security vulnerabilities.
|
|
76
|
-
- Minor corrections to the UCUM data (mostly with regard to extra properties we
|
|
77
|
-
added like "guidance").
|
|
78
|
-
### Changed
|
|
79
|
-
- As result of the dependency update, the build process needed to be revised,
|
|
80
|
-
and the individual transpiled files were removed. The package.json "main"
|
|
81
|
-
file has changed. This is not expected to cause a problem for normal usage of
|
|
82
|
-
the package (relying on the "main" file), and the API has not changed, but due
|
|
83
|
-
to the upheaval, a semver-major change seemed warranted.
|
|
84
|
-
|
|
85
|
-
## [2.6.4] - 2019-06-05
|
|
86
|
-
### Fixed
|
|
87
|
-
- Updated dependencies to get patches for security vulnerabilities.
|
|
88
|
-
|
|
89
|
-
## [2.6.3] - 2019-04-29
|
|
90
|
-
### Fixed
|
|
91
|
-
- Demo page: The validation message on the Validator tab was displayed
|
|
92
|
-
vertically when the unit was valid.
|
|
93
|
-
|
|
94
|
-
## [2.6.2] - 2019-03-29
|
|
95
|
-
### Fixed
|
|
96
|
-
- Demo page changes: fixed processing flow problem that allowed an attempt to
|
|
97
|
-
convert an invalid unit; tweaked flow on initial display of converter tab;
|
|
98
|
-
added meta data to the page to increase visibility to search engines.
|
|
99
|
-
|
|
100
|
-
## [2.6.1] - 2019-03-22
|
|
101
|
-
### Added
|
|
102
|
-
- Added mass<-> moles conversion to the UCUM Demo page, with a request to the
|
|
103
|
-
user to supply a molecular weight when such a conversion is requested.
|
|
104
|
-
|
|
105
|
-
## [2.6.0] - 2019-03-08
|
|
106
|
-
### Added
|
|
107
|
-
- Added capability to existing convertUnitTo library function to convert mass
|
|
108
|
-
to moles expression.
|
|
109
|
-
|
|
110
|
-
## [2.5.5] - 2019-02-28
|
|
111
|
-
### Fixed
|
|
112
|
-
- Fixed mismatches with version numbers as well as problem with library
|
|
113
|
-
distribution on 2.5.2.
|
|
114
|
-
|
|
115
|
-
## [2.5.2] - 2019-02-05
|
|
116
|
-
### Fixed
|
|
117
|
-
- Fixed problem with 2.5.0 where not all files were being included in the
|
|
118
|
-
source-es5/ucumPkg.js package.
|
|
119
|
-
|
|
120
|
-
## [2.5.0] - 2019-01-07
|
|
121
|
-
### Changed
|
|
122
|
-
- The changes made by browserify have been removed from the ucum-lhc package
|
|
123
|
-
available to node.js users, necessitating the creation of separate distributions.
|
|
124
|
-
The distribution of the library code starts at the source-es5/ucumPkg.js file.
|
|
125
|
-
The distribution in the browser-dist directory contains server side code that
|
|
126
|
-
includes browser related code. The distribution in the demo-dist directory
|
|
127
|
-
continues to contain the code related to the UCUM-LHC demo page.
|
|
128
|
-
|
|
129
|
-
## [2.4.4] - 2018-12-13
|
|
130
|
-
### Fixed
|
|
131
|
-
- fixed bug where validation of a unit string that contains an operator, such
|
|
132
|
-
as B[10.nV] is a valid string and validates correctly as a single valid UCUM
|
|
133
|
-
code, but did not validate correctly when preceded by a prefix, e.g., dB[10.nV].
|
|
134
|
-
|
|
135
|
-
## [2.4.3] - 2018-11-06
|
|
136
|
-
### Fixed
|
|
137
|
-
- fixed bug where validation of a unit string terminated with an operator
|
|
138
|
-
returned an incorrect response. It correctly flagged the string as an
|
|
139
|
-
invalid unit expression but included a coding error message that should
|
|
140
|
-
not have been included.
|
|
141
|
-
|
|
142
|
-
## [2.4.2] - 2018-11-05
|
|
143
|
-
### Fixed
|
|
144
|
-
- blocked division and multiplication operations as well as conversion
|
|
145
|
-
operations on arbitrary units
|
|
146
|
-
|
|
147
|
-
## [2.4.1] - 2018-10-25
|
|
148
|
-
### Added
|
|
149
|
-
- Added capability to open directly to converter page using url
|
|
150
|
-
https://ucum.nlm.nih.gov/ucum-lhc/demo.html#converter
|
|
151
|
-
|
|
152
|
-
## [2.4.0] - 2018-10-10
|
|
153
|
-
### Changed
|
|
154
|
-
- redesigned validator tab on Demo page to move messages closer to the
|
|
155
|
-
unit expression input field
|
|
156
|
-
- redesigned converter tab on Demo page to resemble an equation for the
|
|
157
|
-
conversion
|
|
158
|
-
|
|
159
|
-
## [2.3.4] - 2018-08-15
|
|
160
|
-
### Fixed
|
|
161
|
-
- Updated npm packages growl and semver to avoid critical security
|
|
162
|
-
vulnerabilities flagged by GitHub
|
|
163
|
-
|
|
164
|
-
## [2.3.3] - 2018-08-15
|
|
165
|
-
### Fixed
|
|
166
|
-
- Updated conversion code to properly handle conversion of unitless
|
|
167
|
-
measurements, such as moles.
|
|
168
|
-
- Updated code to make text for combined units, e.g., 2.(mmol/L), more
|
|
169
|
-
explicit in regards to evaluation order.
|
|
170
|
-
|
|
171
|
-
## [2.3.2] - 2018-06-27
|
|
172
|
-
### Fixed
|
|
173
|
-
- fixed appearance of the demo page converter tab so that when the page is
|
|
174
|
-
widened in the browser the text all anchors on the left. One portion
|
|
175
|
-
of the text was anchored to the right, which made a widened version look
|
|
176
|
-
wrong.
|
|
177
|
-
|
|
178
|
-
## [2.3.1] - 2018-06-13
|
|
179
|
-
### Fixed
|
|
180
|
-
- modifications to ensure that plain numbers, e.g., 7, are reported correctly.
|
|
181
|
-
### Added
|
|
182
|
-
- added unit name to demo output messages, where available, to make sure user
|
|
183
|
-
knows what unit is being reported as valid.
|
|
184
|
-
|
|
185
|
-
## [2.3.0] - 2018-05-23
|
|
186
|
-
### Added
|
|
187
|
-
- added information related to version number of the ucum-essence.xml
|
|
188
|
-
file used as well as changes made to it
|
|
189
|
-
|
|
190
|
-
## [2.2.1] - 2018-05-22
|
|
191
|
-
### Changed
|
|
192
|
-
- reformatted display of suggestions lists for the demo site to use a bulleted
|
|
193
|
-
list of suggestions rather than a plain text list.
|
|
194
|
-
## Fixed
|
|
195
|
-
- fixed a bug that prevented suggestion lists from being created for more than
|
|
196
|
-
one unit.
|
|
197
|
-
|
|
198
|
-
## [2.2.0] - 2018-05-02
|
|
199
|
-
### Changed
|
|
200
|
-
- added list selection listener to unit expression field on validation
|
|
201
|
-
tab of the demo page
|
|
202
|
-
### Fixed
|
|
203
|
-
- fixed autofill problem on Edge browser.
|
|
204
|
-
|
|
205
|
-
## [2.3.4] - 2018-05-?
|
|
206
|
-
- fixed positioning of text on converter tab of the demo page so that
|
|
207
|
-
it is consistent in how it lines up when the page is widened.
|
|
208
|
-
|
|
209
|
-
## [2.1.12] - 2018-04-26
|
|
210
|
-
### Changed
|
|
211
|
-
- changed unit name (not code) creation for constructed units to enclose
|
|
212
|
-
the name in square brackets and use an asterisk (*) for multiplication
|
|
213
|
-
instead of a period.
|
|
214
|
-
|
|
215
|
-
## [2.1.11] - 2018-04-23
|
|
216
|
-
### Fixed
|
|
217
|
-
- fix for overwritten units during data update process
|
|
218
|
-
|
|
219
|
-
## [2.1.10] - 2018-04-12
|
|
220
|
-
### Changed
|
|
221
|
-
- updates to register bower package
|
|
222
|
-
|
|
223
|
-
## [2.1.9] - 2018-04-03
|
|
224
|
-
### Changed
|
|
225
|
-
- updates to third party and UCUM LHC license information
|
|
226
|
-
|
|
227
|
-
## [2.1.8] - 2018-03-28
|
|
228
|
-
### Fixed
|
|
229
|
-
- fixes to csv file validator
|
|
230
|
-
|
|
231
|
-
## [2.1.7] - 2018-03-12
|
|
232
|
-
### Changed
|
|
233
|
-
- cosmetic updates to overview and demo pages related to banner, titles
|
|
234
|
-
|
|
235
|
-
## [2.1.6] - 2018-03-07
|
|
236
|
-
### Changed
|
|
237
|
-
- created npm package
|
|
238
|
-
|
|
239
|
-
## [2.1.5] - 2018-02-21
|
|
240
|
-
### Changed
|
|
241
|
-
- shifts module tests to use distribution package
|
|
242
|
-
- moves ucumFileValidator to demo directory
|
|
243
|
-
- updates README
|
|
244
|
-
|
|
245
|
-
## [2.1.4] - 2018-02-16
|
|
246
|
-
### Changed
|
|
247
|
-
- removes guidance text for constructed units, e.g., units that are created
|
|
248
|
-
on the fly, as they are specified for validation or conversion. For example,
|
|
249
|
-
m\[H2O\]/cm is constructed from m\[H2O\] (meter of water column) divided by
|
|
250
|
-
cm (centimeter). No guidance data is provided for this constructed unit.
|
|
251
|
-
|
|
252
|
-
## [2.1.3] - 2018-02-15
|
|
253
|
-
### Changed
|
|
254
|
-
- added disclaimer concerning conversion results to demo page convert
|
|
255
|
-
tab and to README.md page
|
|
256
|
-
|
|
257
|
-
## [2.1.2] - 2018-02-15
|
|
258
|
-
### Fixed
|
|
259
|
-
- completed bug fix for zero and negative number of units for conversions.
|
|
260
|
-
|
|
261
|
-
## [2.1.1] - 2018-01-25
|
|
262
|
-
### Changed
|
|
263
|
-
- updated link at the top of the demo page to refer back to the
|
|
264
|
-
overview page - and the link at the top of the overview page to
|
|
265
|
-
refer back to itself.
|
|
266
|
-
- added text to the demo file validation to clarify that only
|
|
267
|
-
units are validated. Prefixes on their own are not validated.
|
|
268
|
-
- updated the ucumDefs.json with version 2.1 (November 21, 2017) of the
|
|
269
|
-
ucum-essence.xml file from unitsofmeasure.org
|
|
270
|
-
### Fixed
|
|
271
|
-
- started fixes on a bug where a zero or negative number of units was considered an error.
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
## [2.1.0] - 2017-12-21
|
|
275
|
-
### Changed
|
|
276
|
-
- Upgraded the validation processing for conversion request on the
|
|
277
|
-
demo page; validation is now performed on the fly as each element
|
|
278
|
-
is entered. This is a change only to the demo page.
|
|
279
|
-
|
|
280
|
-
## [2.0.0] - 2017-12-01
|
|
281
|
-
### Added
|
|
282
|
-
- Added ability to get suggestions for invalid unit expressions.
|
|
283
|
-
|
|
284
|
-
## [1.2.0] - 2017-10-06
|
|
285
|
-
### Fixed
|
|
286
|
-
- Enhanced unit string validation to accommodate/correct:
|
|
287
|
-
- missing multiplication operators, e.g., **2mg** instead of **2.mg**;
|
|
288
|
-
- unit name specified instead of ucum code, e.g., **day** instead of **d**;
|
|
289
|
-
- misplaced annotations, e.g., **{creatine}**mol** instead of mol**{creatine}**;
|
|
290
|
-
- missing square brackets, e.g., **in_i** instead of **[in_i]**; and
|
|
291
|
-
- braces instead of brackets, e.g., **{degF}** instead of **[degF]**.
|
|
292
|
-
|
|
293
|
-
## [1.1.2] - 2017-08-07
|
|
294
|
-
### Changed
|
|
295
|
-
- Updated unit creation process to include updates to case-insensitve codes
|
|
296
|
-
and print symbol values when creating a unit from multiple units.
|
|
297
|
-
- Updated treatment of prefixes for special units that use conversion
|
|
298
|
-
functions to record prefix values in the separate conversion prefix field.
|
|
299
|
-
|
|
300
|
-
## [1.1.1] - 2017-07-13
|
|
301
|
-
### Changed
|
|
302
|
-
- Data file has been updated with enhanced synonyms and is also now written
|
|
303
|
-
in a a readable JSON format.
|
|
304
|
-
|
|
305
|
-
## [1.1.0] - 2017-07-06
|
|
306
|
-
### Changed
|
|
307
|
-
- Autocompleters no longer return multiple-unit strings, e.g., kg/cm.
|
|
308
|
-
Multiple-unit strings are still (very) valid, but the autocompleters just
|
|
309
|
-
return one list single-unit strings at a time.
|
|
310
|
-
- The commensurables list on the conversion tab's "convert to" field has been
|
|
311
|
-
changed to just use the same autocompleter as used for the "convert from" field.
|
|
312
|
-
The list will now include units that cannot be converted.
|
|
313
|
-
|
|
314
|
-
## [1.0.2] - 2017-06-23
|
|
315
|
-
### Fixed
|
|
316
|
-
- Allowed conversion of units with no dimensions
|
|
317
|
-
- added testing for the Unit.convertFrom and Unit.convertTo functions
|
|
318
|
-
|
|
319
|
-
## [1.0.1] - 2017-05-30
|
|
320
|
-
### Added
|
|
321
|
-
- This change log.
|
|
322
|
-
### Changed
|
|
323
|
-
- Streamlined divString function in Unit.js
|
|
324
|
-
- Moved parenthesized unit string processing to separate function
|
|
325
|
-
in UnitString.js (processParens).
|
|
326
|
-
- Added testing for the processParens function in testUnitString.spec.js
|
|
327
|
-
### Fixed
|
|
328
|
-
- Updated UcumFileValidator.js with previously changed function name
|
|
329
|
-
(validUnitString -> validateUnitString in UcumLhcUtils.js).
|