@itwin/core-quantity 5.6.0-dev.13 → 5.6.0-dev.14
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/lib/cjs/Formatter/Format.d.ts +7 -1
- package/lib/cjs/Formatter/Format.d.ts.map +1 -1
- package/lib/cjs/Formatter/Format.js +49 -11
- package/lib/cjs/Formatter/Format.js.map +1 -1
- package/lib/cjs/Formatter/FormatEnums.d.ts +11 -0
- package/lib/cjs/Formatter/FormatEnums.d.ts.map +1 -1
- package/lib/cjs/Formatter/FormatEnums.js +33 -2
- package/lib/cjs/Formatter/FormatEnums.js.map +1 -1
- package/lib/cjs/Formatter/Formatter.d.ts +3 -0
- package/lib/cjs/Formatter/Formatter.d.ts.map +1 -1
- package/lib/cjs/Formatter/Formatter.js +70 -16
- package/lib/cjs/Formatter/Formatter.js.map +1 -1
- package/lib/cjs/Formatter/FormatterSpec.d.ts +2 -0
- package/lib/cjs/Formatter/FormatterSpec.d.ts.map +1 -1
- package/lib/cjs/Formatter/FormatterSpec.js +48 -0
- package/lib/cjs/Formatter/FormatterSpec.js.map +1 -1
- package/lib/cjs/Formatter/Interfaces.d.ts +25 -10
- package/lib/cjs/Formatter/Interfaces.d.ts.map +1 -1
- package/lib/cjs/Formatter/Interfaces.js.map +1 -1
- package/lib/cjs/Parser.d.ts +16 -1
- package/lib/cjs/Parser.d.ts.map +1 -1
- package/lib/cjs/Parser.js +87 -15
- package/lib/cjs/Parser.js.map +1 -1
- package/lib/cjs/ParserSpec.d.ts +2 -0
- package/lib/cjs/ParserSpec.d.ts.map +1 -1
- package/lib/cjs/ParserSpec.js +54 -1
- package/lib/cjs/ParserSpec.js.map +1 -1
- package/lib/esm/Formatter/Format.d.ts +7 -1
- package/lib/esm/Formatter/Format.d.ts.map +1 -1
- package/lib/esm/Formatter/Format.js +50 -12
- package/lib/esm/Formatter/Format.js.map +1 -1
- package/lib/esm/Formatter/FormatEnums.d.ts +11 -0
- package/lib/esm/Formatter/FormatEnums.d.ts.map +1 -1
- package/lib/esm/Formatter/FormatEnums.js +31 -1
- package/lib/esm/Formatter/FormatEnums.js.map +1 -1
- package/lib/esm/Formatter/Formatter.d.ts +3 -0
- package/lib/esm/Formatter/Formatter.d.ts.map +1 -1
- package/lib/esm/Formatter/Formatter.js +70 -16
- package/lib/esm/Formatter/Formatter.js.map +1 -1
- package/lib/esm/Formatter/FormatterSpec.d.ts +2 -0
- package/lib/esm/Formatter/FormatterSpec.d.ts.map +1 -1
- package/lib/esm/Formatter/FormatterSpec.js +48 -0
- package/lib/esm/Formatter/FormatterSpec.js.map +1 -1
- package/lib/esm/Formatter/Interfaces.d.ts +25 -10
- package/lib/esm/Formatter/Interfaces.d.ts.map +1 -1
- package/lib/esm/Formatter/Interfaces.js.map +1 -1
- package/lib/esm/Parser.d.ts +16 -1
- package/lib/esm/Parser.d.ts.map +1 -1
- package/lib/esm/Parser.js +87 -15
- package/lib/esm/Parser.js.map +1 -1
- package/lib/esm/ParserSpec.d.ts +2 -0
- package/lib/esm/ParserSpec.d.ts.map +1 -1
- package/lib/esm/ParserSpec.js +54 -1
- package/lib/esm/ParserSpec.js.map +1 -1
- package/package.json +5 -5
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.FormatterSpec = void 0;
|
|
11
|
+
const FormatEnums_1 = require("./FormatEnums");
|
|
11
12
|
const Formatter_1 = require("./Formatter");
|
|
12
13
|
// cSpell:ignore ZERONORMALIZED, nosign, onlynegative, signalways, negativeparentheses
|
|
13
14
|
// cSpell:ignore trailzeroes, keepsinglezero, zeroempty, keepdecimalpoint, applyrounding, fractiondash, showunitlabel, prependunitlabel, exponentonlynegative
|
|
@@ -55,6 +56,49 @@ class FormatterSpec {
|
|
|
55
56
|
get persistenceUnit() { return this._persistenceUnit; }
|
|
56
57
|
get azimuthBaseConversion() { return this._azimuthBaseConversion; }
|
|
57
58
|
get revolutionConversion() { return this._revolutionConversion; }
|
|
59
|
+
/** Build conversion specs for ratio format with 2 composite units (numerator/denominator). */
|
|
60
|
+
static async getRatioUnitConversions(units, unitsProvider, persistenceUnit) {
|
|
61
|
+
const conversions = [];
|
|
62
|
+
const [numeratorUnit, numeratorLabel] = units[0];
|
|
63
|
+
const [denominatorUnit, denominatorLabel] = units[1];
|
|
64
|
+
// Compute ratio scale: how many numerator units per denominator unit (e.g., IN:FT = 12)
|
|
65
|
+
const denominatorToNumerator = await unitsProvider.getConversion(denominatorUnit, numeratorUnit);
|
|
66
|
+
const displayRatioScale = denominatorToNumerator.factor;
|
|
67
|
+
// Avoid double-scaling: if persistence unit already encodes the display ratio, use factor 1.
|
|
68
|
+
// Check by name heuristic (e.g., IN_PER_FT with ratioUnits [IN, FT] → no scaling needed)
|
|
69
|
+
const persistenceName = persistenceUnit.name.toUpperCase();
|
|
70
|
+
const numName = numeratorUnit.name.toUpperCase().split(".").pop() ?? "";
|
|
71
|
+
const denName = denominatorUnit.name.toUpperCase().split(".").pop() ?? "";
|
|
72
|
+
// Split by word boundaries (underscores, dots) and check for exact token matches
|
|
73
|
+
const persistenceTokens = persistenceName.split(/[._]/);
|
|
74
|
+
const isPersistenceMatchingRatio = persistenceTokens.includes(numName) && persistenceTokens.includes(denName);
|
|
75
|
+
const ratioScaleFactor = isPersistenceMatchingRatio ? 1.0 : displayRatioScale;
|
|
76
|
+
// First conversion spec: effective ratio unit conversion
|
|
77
|
+
const ratioConversionSpec = {
|
|
78
|
+
name: `${numeratorUnit.name}_per_${denominatorUnit.name}`,
|
|
79
|
+
label: "",
|
|
80
|
+
system: numeratorUnit.system,
|
|
81
|
+
conversion: { factor: ratioScaleFactor, offset: 0.0 },
|
|
82
|
+
};
|
|
83
|
+
conversions.push(ratioConversionSpec);
|
|
84
|
+
// Numerator unit for label lookup
|
|
85
|
+
const numeratorSpec = {
|
|
86
|
+
name: numeratorUnit.name,
|
|
87
|
+
label: numeratorLabel?.length ? numeratorLabel : numeratorUnit.label,
|
|
88
|
+
system: numeratorUnit.system,
|
|
89
|
+
conversion: { factor: 1.0, offset: 0.0 },
|
|
90
|
+
};
|
|
91
|
+
conversions.push(numeratorSpec);
|
|
92
|
+
// Denominator unit for label lookup
|
|
93
|
+
const denominatorSpec = {
|
|
94
|
+
name: denominatorUnit.name,
|
|
95
|
+
label: denominatorLabel?.length ? denominatorLabel : denominatorUnit.label,
|
|
96
|
+
system: denominatorUnit.system,
|
|
97
|
+
conversion: { factor: 1.0, offset: 0.0 },
|
|
98
|
+
};
|
|
99
|
+
conversions.push(denominatorSpec);
|
|
100
|
+
return conversions;
|
|
101
|
+
}
|
|
58
102
|
/** Get an array of UnitConversionSpecs, one for each unit that is to be shown in the formatted quantity string. */
|
|
59
103
|
static async getUnitConversions(format, unitsProvider, inputUnit) {
|
|
60
104
|
const conversions = [];
|
|
@@ -68,6 +112,10 @@ class FormatterSpec {
|
|
|
68
112
|
throw new Error("Formatter Spec needs persistence unit to be specified");
|
|
69
113
|
}
|
|
70
114
|
}
|
|
115
|
+
// Handle 2-unit composite for ratio formats (scale factors)
|
|
116
|
+
if (format.type === FormatEnums_1.FormatType.Ratio && format.units && format.units.length === 2) {
|
|
117
|
+
return FormatterSpec.getRatioUnitConversions(format.units, unitsProvider, persistenceUnit);
|
|
118
|
+
}
|
|
71
119
|
if (format.units) {
|
|
72
120
|
let convertFromUnit = inputUnit;
|
|
73
121
|
for (const unit of format.units) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormatterSpec.js","sourceRoot":"","sources":["../../../src/Formatter/FormatterSpec.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Quantity\r\n */\r\n\r\nimport { UnitConversionProps, UnitConversionSpec, UnitProps, UnitsProvider } from \"../Interfaces\";\r\nimport { Format } from \"./Format\";\r\nimport { Formatter } from \"./Formatter\";\r\n\r\n// cSpell:ignore ZERONORMALIZED, nosign, onlynegative, signalways, negativeparentheses\r\n// cSpell:ignore trailzeroes, keepsinglezero, zeroempty, keepdecimalpoint, applyrounding, fractiondash, showunitlabel, prependunitlabel, exponentonlynegative\r\n\r\n/** A class that contains both formatting information and the conversion factors necessary to convert from an input unit to the units specified in the format.\r\n * Once created the FormatterSpec will be able to format quantity values with synchronous calls.\r\n * @beta\r\n */\r\nexport class FormatterSpec {\r\n protected _name: string;\r\n protected _conversions: UnitConversionSpec[] = []; // max four entries\r\n protected _format: Format;\r\n protected _persistenceUnit: UnitProps;\r\n protected _azimuthBaseConversion?: UnitConversionProps; // converts azimuth base unit to persistence unit\r\n protected _revolutionConversion?: UnitConversionProps; // converts revolution unit to persistence unit\r\n\r\n /** Constructor\r\n * @param name The name of a format specification.\r\n * @param format Defines the output format for the quantity value.\r\n * @param conversions An array of conversion factors necessary to convert from an input unit to the units specified in the format.\r\n * @param persistenceUnit The unit the magnitude value is input.\r\n * @param azimuthBaseConversion The conversion used to interpret azimuth base values.\r\n * @param revolutionConversion The conversion used to determine a revolution value (used for bearing and azimuth).\r\n */\r\n constructor(name: string, format: Format, conversions?: UnitConversionSpec[], persistenceUnit?: UnitProps, azimuthBaseConversion?: UnitConversionProps, revolutionConversion?: UnitConversionProps) {\r\n if (!persistenceUnit) {\r\n if (format.units) {\r\n const [props] = format.units[0];\r\n persistenceUnit = props;\r\n } else {\r\n throw new Error(\"Formatter Spec needs persistence unit to be specified\");\r\n }\r\n }\r\n\r\n this._name = name;\r\n this._format = format;\r\n this._persistenceUnit = persistenceUnit;\r\n if (conversions)\r\n this._conversions = conversions;\r\n this._azimuthBaseConversion = azimuthBaseConversion;\r\n this._revolutionConversion = revolutionConversion;\r\n }\r\n\r\n public get name(): string { return this._name; }\r\n /** Returns an array of UnitConversionSpecs, one for each unit that is to be shown in the formatted quantity string. */\r\n public get unitConversions(): UnitConversionSpec[] { return this._conversions; }\r\n public get format(): Format { return this._format; }\r\n public get persistenceUnit(): UnitProps { return this._persistenceUnit; }\r\n public get azimuthBaseConversion(): UnitConversionProps | undefined { return this._azimuthBaseConversion; }\r\n public get revolutionConversion(): UnitConversionProps | undefined { return this._revolutionConversion; }\r\n\r\n /** Get an array of UnitConversionSpecs, one for each unit that is to be shown in the formatted quantity string. */\r\n public static async getUnitConversions(format: Format, unitsProvider: UnitsProvider, inputUnit?: UnitProps): Promise<UnitConversionSpec[]> {\r\n const conversions: UnitConversionSpec[] = [];\r\n let persistenceUnit = inputUnit;\r\n if (!persistenceUnit) {\r\n if (format.units) {\r\n const [props] = format.units[0];\r\n persistenceUnit = props;\r\n } else {\r\n throw new Error(\"Formatter Spec needs persistence unit to be specified\");\r\n }\r\n }\r\n\r\n if (format.units) {\r\n let convertFromUnit = inputUnit;\r\n for (const unit of format.units) {\r\n let unitConversion: UnitConversionProps;\r\n if (convertFromUnit) {\r\n unitConversion = await unitsProvider.getConversion(convertFromUnit, unit[0]);\r\n } else {\r\n unitConversion = { factor: 1.0, offset: 0.0 };\r\n }\r\n const unitLabel = (unit[1] && unit[1].length > 0) ? unit[1] : unit[0].label;\r\n const spec = ({ name: unit[0].name, label: unitLabel, conversion: unitConversion, system: unit[0].system }) as UnitConversionSpec;\r\n\r\n conversions.push(spec);\r\n convertFromUnit = unit[0];\r\n }\r\n } else {\r\n // if format is only numeric and a input unit is defined set spec to use the input unit as the format unit\r\n if (inputUnit) {\r\n const spec: UnitConversionSpec = { name: inputUnit.name, label: inputUnit.label, system: inputUnit.system, conversion: { factor: 1.0, offset: 0.0 } };\r\n conversions.push(spec);\r\n }\r\n }\r\n\r\n return conversions;\r\n }\r\n\r\n /** Static async method to create a FormatSpec given the format and unit of the quantity that will be passed to the Formatter. The input unit will\r\n * be used to generate conversion information for each unit specified in the Format. This method is async due to the fact that the units provider must make\r\n * async calls to lookup unit definitions.\r\n * @param name The name of a format specification.\r\n * @param unitsProvider The units provider is used to look up unit definitions and provide conversion information for converting between units.\r\n * @param inputUnit The unit the value to be formatted. This unit is often referred to as persistence unit.\r\n */\r\n public static async create(name: string, format: Format, unitsProvider: UnitsProvider, inputUnit?: UnitProps): Promise<FormatterSpec> {\r\n const conversions: UnitConversionSpec[] = await FormatterSpec.getUnitConversions(format, unitsProvider, inputUnit);\r\n let azimuthBaseConversion: UnitConversionProps | undefined;\r\n if (format.azimuthBaseUnit !== undefined) {\r\n if (inputUnit !== undefined) {\r\n azimuthBaseConversion = await unitsProvider.getConversion(format.azimuthBaseUnit, inputUnit);\r\n } else {\r\n azimuthBaseConversion = { factor: 1.0, offset: 0.0 };\r\n }\r\n }\r\n let revolutionConversion: UnitConversionProps | undefined;\r\n if (format.revolutionUnit !== undefined) {\r\n if (inputUnit !== undefined) {\r\n revolutionConversion = await unitsProvider.getConversion(format.revolutionUnit, inputUnit);\r\n } else {\r\n revolutionConversion = { factor: 1.0, offset: 0.0 };\r\n }\r\n }\r\n\r\n return new FormatterSpec(name, format, conversions, inputUnit, azimuthBaseConversion, revolutionConversion);\r\n }\r\n\r\n /** Format a quantity value. */\r\n public applyFormatting(magnitude: number): string {\r\n return Formatter.formatQuantity(magnitude, this);\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"FormatterSpec.js","sourceRoot":"","sources":["../../../src/Formatter/FormatterSpec.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Quantity\r\n */\r\n\r\nimport { UnitConversionProps, UnitConversionSpec, UnitProps, UnitsProvider } from \"../Interfaces\";\r\nimport { Format } from \"./Format\";\r\nimport { FormatType } from \"./FormatEnums\";\r\nimport { Formatter } from \"./Formatter\";\r\n\r\n// cSpell:ignore ZERONORMALIZED, nosign, onlynegative, signalways, negativeparentheses\r\n// cSpell:ignore trailzeroes, keepsinglezero, zeroempty, keepdecimalpoint, applyrounding, fractiondash, showunitlabel, prependunitlabel, exponentonlynegative\r\n\r\n/** A class that contains both formatting information and the conversion factors necessary to convert from an input unit to the units specified in the format.\r\n * Once created the FormatterSpec will be able to format quantity values with synchronous calls.\r\n * @beta\r\n */\r\nexport class FormatterSpec {\r\n protected _name: string;\r\n protected _conversions: UnitConversionSpec[] = []; // max four entries\r\n protected _format: Format;\r\n protected _persistenceUnit: UnitProps;\r\n protected _azimuthBaseConversion?: UnitConversionProps; // converts azimuth base unit to persistence unit\r\n protected _revolutionConversion?: UnitConversionProps; // converts revolution unit to persistence unit\r\n\r\n /** Constructor\r\n * @param name The name of a format specification.\r\n * @param format Defines the output format for the quantity value.\r\n * @param conversions An array of conversion factors necessary to convert from an input unit to the units specified in the format.\r\n * @param persistenceUnit The unit the magnitude value is input.\r\n * @param azimuthBaseConversion The conversion used to interpret azimuth base values.\r\n * @param revolutionConversion The conversion used to determine a revolution value (used for bearing and azimuth).\r\n */\r\n constructor(name: string, format: Format, conversions?: UnitConversionSpec[], persistenceUnit?: UnitProps, azimuthBaseConversion?: UnitConversionProps, revolutionConversion?: UnitConversionProps) {\r\n if (!persistenceUnit) {\r\n if (format.units) {\r\n const [props] = format.units[0];\r\n persistenceUnit = props;\r\n } else {\r\n throw new Error(\"Formatter Spec needs persistence unit to be specified\");\r\n }\r\n }\r\n\r\n this._name = name;\r\n this._format = format;\r\n this._persistenceUnit = persistenceUnit;\r\n if (conversions)\r\n this._conversions = conversions;\r\n this._azimuthBaseConversion = azimuthBaseConversion;\r\n this._revolutionConversion = revolutionConversion;\r\n }\r\n\r\n public get name(): string { return this._name; }\r\n /** Returns an array of UnitConversionSpecs, one for each unit that is to be shown in the formatted quantity string. */\r\n public get unitConversions(): UnitConversionSpec[] { return this._conversions; }\r\n public get format(): Format { return this._format; }\r\n public get persistenceUnit(): UnitProps { return this._persistenceUnit; }\r\n public get azimuthBaseConversion(): UnitConversionProps | undefined { return this._azimuthBaseConversion; }\r\n public get revolutionConversion(): UnitConversionProps | undefined { return this._revolutionConversion; }\r\n\r\n /** Build conversion specs for ratio format with 2 composite units (numerator/denominator). */\r\n private static async getRatioUnitConversions(units: ReadonlyArray<[UnitProps, string | undefined]>, unitsProvider: UnitsProvider, persistenceUnit: UnitProps): Promise<UnitConversionSpec[]> {\r\n const conversions: UnitConversionSpec[] = [];\r\n\r\n const [numeratorUnit, numeratorLabel] = units[0];\r\n const [denominatorUnit, denominatorLabel] = units[1];\r\n\r\n // Compute ratio scale: how many numerator units per denominator unit (e.g., IN:FT = 12)\r\n const denominatorToNumerator = await unitsProvider.getConversion(denominatorUnit, numeratorUnit);\r\n const displayRatioScale = denominatorToNumerator.factor;\r\n\r\n // Avoid double-scaling: if persistence unit already encodes the display ratio, use factor 1.\r\n // Check by name heuristic (e.g., IN_PER_FT with ratioUnits [IN, FT] → no scaling needed)\r\n const persistenceName = persistenceUnit.name.toUpperCase();\r\n const numName = numeratorUnit.name.toUpperCase().split(\".\").pop() ?? \"\";\r\n const denName = denominatorUnit.name.toUpperCase().split(\".\").pop() ?? \"\";\r\n // Split by word boundaries (underscores, dots) and check for exact token matches\r\n const persistenceTokens = persistenceName.split(/[._]/);\r\n const isPersistenceMatchingRatio = persistenceTokens.includes(numName) && persistenceTokens.includes(denName);\r\n const ratioScaleFactor = isPersistenceMatchingRatio ? 1.0 : displayRatioScale;\r\n\r\n // First conversion spec: effective ratio unit conversion\r\n const ratioConversionSpec: UnitConversionSpec = {\r\n name: `${numeratorUnit.name}_per_${denominatorUnit.name}`,\r\n label: \"\",\r\n system: numeratorUnit.system,\r\n conversion: { factor: ratioScaleFactor, offset: 0.0 },\r\n };\r\n conversions.push(ratioConversionSpec);\r\n\r\n // Numerator unit for label lookup\r\n const numeratorSpec: UnitConversionSpec = {\r\n name: numeratorUnit.name,\r\n label: numeratorLabel?.length ? numeratorLabel : numeratorUnit.label,\r\n system: numeratorUnit.system,\r\n conversion: { factor: 1.0, offset: 0.0 },\r\n };\r\n conversions.push(numeratorSpec);\r\n\r\n // Denominator unit for label lookup\r\n const denominatorSpec: UnitConversionSpec = {\r\n name: denominatorUnit.name,\r\n label: denominatorLabel?.length ? denominatorLabel : denominatorUnit.label,\r\n system: denominatorUnit.system,\r\n conversion: { factor: 1.0, offset: 0.0 },\r\n };\r\n conversions.push(denominatorSpec);\r\n\r\n return conversions;\r\n }\r\n\r\n /** Get an array of UnitConversionSpecs, one for each unit that is to be shown in the formatted quantity string. */\r\n public static async getUnitConversions(format: Format, unitsProvider: UnitsProvider, inputUnit?: UnitProps): Promise<UnitConversionSpec[]> {\r\n const conversions: UnitConversionSpec[] = [];\r\n let persistenceUnit = inputUnit;\r\n if (!persistenceUnit) {\r\n if (format.units) {\r\n const [props] = format.units[0];\r\n persistenceUnit = props;\r\n } else {\r\n throw new Error(\"Formatter Spec needs persistence unit to be specified\");\r\n }\r\n }\r\n\r\n // Handle 2-unit composite for ratio formats (scale factors)\r\n if (format.type === FormatType.Ratio && format.units && format.units.length === 2) {\r\n return FormatterSpec.getRatioUnitConversions(format.units, unitsProvider, persistenceUnit);\r\n }\r\n\r\n if (format.units) {\r\n let convertFromUnit = inputUnit;\r\n for (const unit of format.units) {\r\n let unitConversion: UnitConversionProps;\r\n if (convertFromUnit) {\r\n unitConversion = await unitsProvider.getConversion(convertFromUnit, unit[0]);\r\n } else {\r\n unitConversion = { factor: 1.0, offset: 0.0 };\r\n }\r\n const unitLabel = (unit[1] && unit[1].length > 0) ? unit[1] : unit[0].label;\r\n const spec = ({ name: unit[0].name, label: unitLabel, conversion: unitConversion, system: unit[0].system }) as UnitConversionSpec;\r\n\r\n conversions.push(spec);\r\n convertFromUnit = unit[0];\r\n }\r\n } else {\r\n // if format is only numeric and a input unit is defined set spec to use the input unit as the format unit\r\n if (inputUnit) {\r\n const spec: UnitConversionSpec = { name: inputUnit.name, label: inputUnit.label, system: inputUnit.system, conversion: { factor: 1.0, offset: 0.0 } };\r\n conversions.push(spec);\r\n }\r\n }\r\n\r\n return conversions;\r\n }\r\n\r\n /** Static async method to create a FormatSpec given the format and unit of the quantity that will be passed to the Formatter. The input unit will\r\n * be used to generate conversion information for each unit specified in the Format. This method is async due to the fact that the units provider must make\r\n * async calls to lookup unit definitions.\r\n * @param name The name of a format specification.\r\n * @param unitsProvider The units provider is used to look up unit definitions and provide conversion information for converting between units.\r\n * @param inputUnit The unit the value to be formatted. This unit is often referred to as persistence unit.\r\n */\r\n public static async create(name: string, format: Format, unitsProvider: UnitsProvider, inputUnit?: UnitProps): Promise<FormatterSpec> {\r\n const conversions: UnitConversionSpec[] = await FormatterSpec.getUnitConversions(format, unitsProvider, inputUnit);\r\n let azimuthBaseConversion: UnitConversionProps | undefined;\r\n if (format.azimuthBaseUnit !== undefined) {\r\n if (inputUnit !== undefined) {\r\n azimuthBaseConversion = await unitsProvider.getConversion(format.azimuthBaseUnit, inputUnit);\r\n } else {\r\n azimuthBaseConversion = { factor: 1.0, offset: 0.0 };\r\n }\r\n }\r\n let revolutionConversion: UnitConversionProps | undefined;\r\n if (format.revolutionUnit !== undefined) {\r\n if (inputUnit !== undefined) {\r\n revolutionConversion = await unitsProvider.getConversion(format.revolutionUnit, inputUnit);\r\n } else {\r\n revolutionConversion = { factor: 1.0, offset: 0.0 };\r\n }\r\n }\r\n\r\n return new FormatterSpec(name, format, conversions, inputUnit, azimuthBaseConversion, revolutionConversion);\r\n }\r\n\r\n /** Format a quantity value. */\r\n public applyFormatting(magnitude: number): string {\r\n return Formatter.formatQuantity(magnitude, this);\r\n }\r\n}\r\n"]}
|
|
@@ -4,6 +4,25 @@
|
|
|
4
4
|
import { BeEvent } from "@itwin/core-bentley";
|
|
5
5
|
import { UnitProps } from "../Interfaces";
|
|
6
6
|
import { DecimalPrecision, FormatTraits, FormatType, FractionalPrecision } from "./FormatEnums";
|
|
7
|
+
/** Defines a unit specification with a name and optional label override.
|
|
8
|
+
* Used in composite formats and ratio unit specifications.
|
|
9
|
+
* @beta
|
|
10
|
+
*/
|
|
11
|
+
export interface FormatUnitSpec {
|
|
12
|
+
/** The name of the unit (e.g., "Units.FT", "Units.IN") */
|
|
13
|
+
readonly name: string;
|
|
14
|
+
/** Optional custom label that overrides the unit's default label (e.g., '"' for inches, "'" for feet) */
|
|
15
|
+
readonly label?: string;
|
|
16
|
+
}
|
|
17
|
+
/** A resolved [[FormatUnitSpec]] with the unit name replaced with the resolved UnitProps.
|
|
18
|
+
* @beta
|
|
19
|
+
*/
|
|
20
|
+
export interface ResolvedFormatUnitSpec {
|
|
21
|
+
/** The resolved unit */
|
|
22
|
+
readonly unit: UnitProps;
|
|
23
|
+
/** Optional custom label that overrides the unit's default label */
|
|
24
|
+
readonly label?: string;
|
|
25
|
+
}
|
|
7
26
|
/** Defines the units that make up a composite format and their display properties.
|
|
8
27
|
* A composite format allows displaying a single quantity value across multiple units,
|
|
9
28
|
* such as displaying length as "5 feet 6 inches" or angle as "45° 30' 15"".
|
|
@@ -15,12 +34,7 @@ export interface FormatCompositeProps {
|
|
|
15
34
|
readonly includeZero?: boolean;
|
|
16
35
|
/** Array of units this format is comprised of. Each unit specifies the unit name and
|
|
17
36
|
* an optional custom label that will override the unit's default label when displaying values. */
|
|
18
|
-
readonly units:
|
|
19
|
-
/** The name of the unit (e.g., "Units.FT", "Units.IN") */
|
|
20
|
-
readonly name: string;
|
|
21
|
-
/** Optional custom label that overrides the unit's default label (e.g., "ft" for feet, 'in' for inches) */
|
|
22
|
-
readonly label?: string;
|
|
23
|
-
}>;
|
|
37
|
+
readonly units: FormatUnitSpec[];
|
|
24
38
|
}
|
|
25
39
|
/** This interface defines the persistence format for describing the formatting of quantity values.
|
|
26
40
|
* @beta
|
|
@@ -39,6 +53,10 @@ export interface FormatProps {
|
|
|
39
53
|
readonly scientificType?: string;
|
|
40
54
|
/** conditionally required. */
|
|
41
55
|
readonly ratioType?: string;
|
|
56
|
+
/** The separator character for ratio formatting. Defaults to ':' if not specified. */
|
|
57
|
+
readonly ratioSeparator?: string;
|
|
58
|
+
/** The format type for the numbers within a ratio. Defaults to "Decimal". */
|
|
59
|
+
readonly ratioFormatType?: string;
|
|
42
60
|
/** conditionally required. */
|
|
43
61
|
readonly stationOffsetSize?: number;
|
|
44
62
|
readonly stationSeparator?: string;
|
|
@@ -69,10 +87,7 @@ export declare const isCustomFormatProps: (item: FormatProps) => item is CustomF
|
|
|
69
87
|
* @beta
|
|
70
88
|
*/
|
|
71
89
|
export type ResolvedFormatCompositeProps = Omit<FormatCompositeProps, "units"> & {
|
|
72
|
-
readonly units:
|
|
73
|
-
readonly unit: UnitProps;
|
|
74
|
-
readonly label?: string;
|
|
75
|
-
}>;
|
|
90
|
+
readonly units: ResolvedFormatUnitSpec[];
|
|
76
91
|
};
|
|
77
92
|
/** A [[FormatProps]] with all the references to units replaced with JSON representations of those units.
|
|
78
93
|
* @beta
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Interfaces.d.ts","sourceRoot":"","sources":["../../../src/Formatter/Interfaces.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEhG
|
|
1
|
+
{"version":3,"file":"Interfaces.d.ts","sourceRoot":"","sources":["../../../src/Formatter/Interfaces.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Interfaces.js","sourceRoot":"","sources":["../../../src/Formatter/Interfaces.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;
|
|
1
|
+
{"version":3,"file":"Interfaces.js","sourceRoot":"","sources":["../../../src/Formatter/Interfaces.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AA+FH;;GAEG;AACI,MAAM,mBAAmB,GAAG,CAAC,IAAiB,EAA6B,EAAE;IAClF,OAAQ,IAA0B,CAAC,MAAM,KAAK,SAAS,CAAC;AAC1D,CAAC,CAAC;AAFW,QAAA,mBAAmB,uBAE9B","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Quantity\r\n */\r\n\r\nimport { BeEvent } from \"@itwin/core-bentley\";\r\nimport { UnitProps } from \"../Interfaces\";\r\nimport { DecimalPrecision, FormatTraits, FormatType, FractionalPrecision } from \"./FormatEnums\";\r\n\r\n/** Defines a unit specification with a name and optional label override.\r\n * Used in composite formats and ratio unit specifications.\r\n * @beta\r\n */\r\nexport interface FormatUnitSpec {\r\n /** The name of the unit (e.g., \"Units.FT\", \"Units.IN\") */\r\n readonly name: string;\r\n /** Optional custom label that overrides the unit's default label (e.g., '\"' for inches, \"'\" for feet) */\r\n readonly label?: string;\r\n}\r\n\r\n/** A resolved [[FormatUnitSpec]] with the unit name replaced with the resolved UnitProps.\r\n * @beta\r\n */\r\nexport interface ResolvedFormatUnitSpec {\r\n /** The resolved unit */\r\n readonly unit: UnitProps;\r\n /** Optional custom label that overrides the unit's default label */\r\n readonly label?: string;\r\n}\r\n\r\n/** Defines the units that make up a composite format and their display properties.\r\n * A composite format allows displaying a single quantity value across multiple units,\r\n * such as displaying length as \"5 feet 6 inches\" or angle as \"45° 30' 15\"\".\r\n * @beta\r\n */\r\nexport interface FormatCompositeProps {\r\n /** separates values when formatting composite strings */\r\n readonly spacer?: string;\r\n readonly includeZero?: boolean;\r\n /** Array of units this format is comprised of. Each unit specifies the unit name and\r\n * an optional custom label that will override the unit's default label when displaying values. */\r\n readonly units: FormatUnitSpec[];\r\n}\r\n\r\n/** This interface defines the persistence format for describing the formatting of quantity values.\r\n * @beta\r\n */\r\nexport interface FormatProps {\r\n readonly type: string;\r\n readonly precision?: number;\r\n readonly roundFactor?: number;\r\n readonly minWidth?: number;\r\n readonly showSignOption?: string;\r\n readonly formatTraits?: string | string[];\r\n readonly decimalSeparator?: string;\r\n readonly thousandSeparator?: string;\r\n readonly uomSeparator?: string;\r\n\r\n /** conditionally required. */\r\n readonly scientificType?: string;\r\n\r\n /** conditionally required. */\r\n readonly ratioType?: string;\r\n /** The separator character for ratio formatting. Defaults to ':' if not specified. */\r\n readonly ratioSeparator?: string;\r\n /** The format type for the numbers within a ratio. Defaults to \"Decimal\". */\r\n readonly ratioFormatType?: string;\r\n\r\n /** conditionally required. */\r\n readonly stationOffsetSize?: number;\r\n readonly stationSeparator?: string;\r\n\r\n /** Optional base factor for station formatting. A positive integer, defaults to 1. */\r\n readonly stationBaseFactor?: number;\r\n\r\n /** The base value for azimuth, specified from east counter-clockwise. */\r\n readonly azimuthBase?: number;\r\n\r\n /** The name of the unit for the azimuth base value. */\r\n readonly azimuthBaseUnit?: string;\r\n\r\n /** If set to true, azimuth values are returned counter-clockwise from the base. */\r\n readonly azimuthCounterClockwise?: boolean;\r\n\r\n /** The name of the unit that represents a revolution/perigon. Required for bearing or azimuth types. */\r\n readonly revolutionUnit?: string;\r\n\r\n readonly allowMathematicOperations?: boolean;\r\n readonly composite?: FormatCompositeProps;\r\n}\r\n\r\n/** This interface is used when supporting Custom Formatters that need more than the standard set of properties.\r\n * @beta\r\n */\r\nexport interface CustomFormatProps extends FormatProps {\r\n readonly custom: any;\r\n}\r\n\r\n/** CustomFormatProps type guard.\r\n * @beta\r\n */\r\nexport const isCustomFormatProps = (item: FormatProps): item is CustomFormatProps => {\r\n return (item as CustomFormatProps).custom !== undefined;\r\n};\r\n\r\n/** A [[FormatCompositeProps]] with unit names replaced with JSON representations of those units.\r\n * @beta\r\n */\r\nexport type ResolvedFormatCompositeProps = Omit<FormatCompositeProps, \"units\"> & {\r\n readonly units: ResolvedFormatUnitSpec[];\r\n};\r\n\r\n/** A [[FormatProps]] with all the references to units replaced with JSON representations of those units.\r\n * @beta\r\n */\r\nexport type ResolvedFormatProps = Omit<FormatDefinition, \"azimuthBaseUnit\" | \"revolutionUnit\" | \"composite\"> & {\r\n readonly azimuthBaseUnit?: UnitProps;\r\n readonly revolutionUnit?: UnitProps;\r\n readonly composite?: ResolvedFormatCompositeProps;\r\n readonly custom?: any;\r\n};\r\n\r\n/** CloneFormat defines unit and label specification if primary unit is to be set during clone.\r\n * @beta\r\n */\r\nexport interface CloneUnit {\r\n unit?: UnitProps;\r\n label?: string;\r\n}\r\n\r\n/** CloneOptions that define modifications that can be made during the cloning of a Format.\r\n * @beta\r\n */\r\nexport interface CloneOptions {\r\n /** allows composite formats to be converted to only show primary unit */\r\n showOnlyPrimaryUnit?: boolean;\r\n /** allow format traits to be set */\r\n traits?: FormatTraits;\r\n /** allows new FormatType to be specified */\r\n type?: FormatType;\r\n /** allows precision to be set, this will throw if value is not valid for FormatType */\r\n precision?: DecimalPrecision | FractionalPrecision;\r\n /** allows primary unit and label to be specified */\r\n primaryUnit?: CloneUnit;\r\n}\r\n\r\n/** An extension of FormatProps to help identify formats.\r\n * @beta\r\n */\r\nexport interface FormatDefinition extends FormatProps {\r\n readonly name?: string;\r\n readonly label?: string;\r\n readonly description?: string;\r\n}\r\n\r\n/** Argument for [[FormatsProvider.onFormatsChanged]]\r\n * @beta\r\n */\r\nexport interface FormatsChangedArgs {\r\n /**\r\n * If `all` - all formats within the `FormatsProvider` have changed.\r\n * If array, the array items list the names of formats that were changed or removed.\r\n */\r\n formatsChanged: \"all\" | string[];\r\n}\r\n\r\n/** This interface is implemented by a class that would provide formats for use in formatting quantities.\r\n * @beta\r\n */\r\nexport interface FormatsProvider {\r\n /**\r\n * @param name The full name of the Format or KindOfQuantity.\r\n */\r\n getFormat(name: string): Promise<FormatDefinition | undefined>;\r\n\r\n /**\r\n * Fired when formats are added, removed, or changed.\r\n * If all formats are changed, a single string \"all\" is emitted. Else, an array of changed format names is emitted.\r\n */\r\n onFormatsChanged: BeEvent<(args: FormatsChangedArgs) => void>;\r\n}\r\n\r\n/** This interface is implemented by a class that would provide and allow creating formats for use in formatting quantities.\r\n * @beta\r\n */\r\nexport interface MutableFormatsProvider extends FormatsProvider {\r\n /**\r\n * Adds a new format or updates an existing format associated with the specified name.\r\n */\r\n addFormat(name: string, format: FormatDefinition): Promise<void>;\r\n /**\r\n * Removes the format associated with the specified name.\r\n * @param name The name of the format to remove.\r\n */\r\n removeFormat(name: string): Promise<void>;\r\n}\r\n"]}
|
package/lib/cjs/Parser.d.ts
CHANGED
|
@@ -16,7 +16,8 @@ export declare enum ParseError {
|
|
|
16
16
|
InvalidParserSpec = 6,
|
|
17
17
|
BearingPrefixOrSuffixMissing = 7,
|
|
18
18
|
MathematicOperationFoundButIsNotAllowed = 8,
|
|
19
|
-
BearingAngleOutOfRange = 9
|
|
19
|
+
BearingAngleOutOfRange = 9,
|
|
20
|
+
InvalidMathResult = 10
|
|
20
21
|
}
|
|
21
22
|
/** Parse error result from [[Parser.parseToQuantityValue]] or [[Parser.parseToQuantityValue]].
|
|
22
23
|
* @beta
|
|
@@ -116,6 +117,20 @@ export declare class Parser {
|
|
|
116
117
|
private static processSpecialBearingDirection;
|
|
117
118
|
private static parseBearingFormat;
|
|
118
119
|
private static parseAzimuthFormat;
|
|
120
|
+
/**
|
|
121
|
+
* Parse a ratio part string (numerator or denominator) to extract the numeric value and optional unit label.
|
|
122
|
+
* This method processes tokens without applying unit conversions, allowing the ratio format
|
|
123
|
+
* handler to manage conversions at the ratio level.
|
|
124
|
+
*
|
|
125
|
+
*
|
|
126
|
+
* @note Fractions are already handled by parseQuantitySpecification, which converts them to
|
|
127
|
+
* single numeric tokens (e.g., "1/2" becomes 0.5).
|
|
128
|
+
*
|
|
129
|
+
* @param partStr The string to parse, which may contain a number, fraction, or mixed fraction with optional unit label.
|
|
130
|
+
* @param format The format specification used for token parsing.
|
|
131
|
+
* @returns An object containing the parsed numeric value and optional unit label. Returns NaN for value if no number is found.
|
|
132
|
+
*/
|
|
133
|
+
private static parseRatioPart;
|
|
119
134
|
private static parseRatioFormat;
|
|
120
135
|
private static normalizeAngle;
|
|
121
136
|
private static getRevolution;
|
package/lib/cjs/Parser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Parser.d.ts","sourceRoot":"","sources":["../../src/Parser.ts"],"names":[],"mappings":"AAIA;;GAEG;AAIH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,aAAa,EAAuB,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjK,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C;;GAEG;AACH,oBAAY,UAAU;IACpB,2BAA2B,IAAI;IAC/B,0BAA0B,IAAA;IAC1B,8BAA8B,IAAA;IAC9B,WAAW,IAAA;IACX,oCAAoC,IAAA;IACpC,iBAAiB,IAAA;IACjB,4BAA4B,IAAA;IAC5B,uCAAuC,IAAA;IACvC,sBAAsB,IAAA;
|
|
1
|
+
{"version":3,"file":"Parser.d.ts","sourceRoot":"","sources":["../../src/Parser.ts"],"names":[],"mappings":"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"}
|
package/lib/cjs/Parser.js
CHANGED
|
@@ -26,13 +26,14 @@ var ParseError;
|
|
|
26
26
|
ParseError[ParseError["BearingPrefixOrSuffixMissing"] = 7] = "BearingPrefixOrSuffixMissing";
|
|
27
27
|
ParseError[ParseError["MathematicOperationFoundButIsNotAllowed"] = 8] = "MathematicOperationFoundButIsNotAllowed";
|
|
28
28
|
ParseError[ParseError["BearingAngleOutOfRange"] = 9] = "BearingAngleOutOfRange";
|
|
29
|
+
ParseError[ParseError["InvalidMathResult"] = 10] = "InvalidMathResult";
|
|
29
30
|
})(ParseError || (exports.ParseError = ParseError = {}));
|
|
30
31
|
var Operator;
|
|
31
32
|
(function (Operator) {
|
|
32
33
|
Operator["addition"] = "+";
|
|
33
34
|
Operator["subtraction"] = "-";
|
|
34
35
|
Operator["multiplication"] = "*";
|
|
35
|
-
Operator["division"] = "/";
|
|
36
|
+
Operator["division"] = "/";
|
|
36
37
|
})(Operator || (Operator = {}));
|
|
37
38
|
function isOperator(char) {
|
|
38
39
|
if (typeof char === "number") {
|
|
@@ -787,36 +788,107 @@ class Parser {
|
|
|
787
788
|
magnitude = this.normalizeAngle(magnitude, revolution);
|
|
788
789
|
return { ok: true, value: magnitude };
|
|
789
790
|
}
|
|
791
|
+
/**
|
|
792
|
+
* Parse a ratio part string (numerator or denominator) to extract the numeric value and optional unit label.
|
|
793
|
+
* This method processes tokens without applying unit conversions, allowing the ratio format
|
|
794
|
+
* handler to manage conversions at the ratio level.
|
|
795
|
+
*
|
|
796
|
+
*
|
|
797
|
+
* @note Fractions are already handled by parseQuantitySpecification, which converts them to
|
|
798
|
+
* single numeric tokens (e.g., "1/2" becomes 0.5).
|
|
799
|
+
*
|
|
800
|
+
* @param partStr The string to parse, which may contain a number, fraction, or mixed fraction with optional unit label.
|
|
801
|
+
* @param format The format specification used for token parsing.
|
|
802
|
+
* @returns An object containing the parsed numeric value and optional unit label. Returns NaN for value if no number is found.
|
|
803
|
+
*/
|
|
804
|
+
static parseRatioPart(partStr, format) {
|
|
805
|
+
partStr = partStr.trim();
|
|
806
|
+
// Parse tokens - fractions are automatically converted to decimal values by parseQuantitySpecification
|
|
807
|
+
const tempFormat = format.clone({ type: FormatEnums_1.FormatType.Decimal });
|
|
808
|
+
const tokens = Parser.parseQuantitySpecification(partStr, tempFormat);
|
|
809
|
+
let value = NaN;
|
|
810
|
+
let unitLabel;
|
|
811
|
+
// Pre-process: merge negative operators with following numbers
|
|
812
|
+
const processedTokens = [];
|
|
813
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
814
|
+
const token = tokens[i];
|
|
815
|
+
if (token.isOperator && i === 0 && token.value === "-" &&
|
|
816
|
+
i + 1 < tokens.length && tokens[i + 1].isNumber) {
|
|
817
|
+
// Merge negative sign with number
|
|
818
|
+
processedTokens.push(new ParseToken(-tokens[i + 1].value));
|
|
819
|
+
i++; // Skip the number token since we consumed it
|
|
820
|
+
}
|
|
821
|
+
else {
|
|
822
|
+
processedTokens.push(token);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
// Extract numeric value and unit label from processed tokens
|
|
826
|
+
for (const token of processedTokens) {
|
|
827
|
+
if (token.isNumber && isNaN(value)) {
|
|
828
|
+
value = token.value;
|
|
829
|
+
}
|
|
830
|
+
else if (token.isString && !token.isOperator) {
|
|
831
|
+
// String token that's not an operator - treat as unit label
|
|
832
|
+
unitLabel = token.value;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
return { value, unitLabel };
|
|
836
|
+
}
|
|
790
837
|
static parseRatioFormat(inString, spec) {
|
|
791
838
|
if (!inString)
|
|
792
839
|
return { ok: false, error: ParseError.NoValueOrUnitFoundInString };
|
|
793
|
-
const
|
|
840
|
+
const separator = spec.format.ratioSeparator ?? ":";
|
|
841
|
+
const parts = inString.split(separator);
|
|
794
842
|
if (parts.length > 2)
|
|
795
843
|
return { ok: false, error: ParseError.UnableToConvertParseTokensToQuantity };
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
if (parts.length === 1) {
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
844
|
+
// If the string doesn't contain the expected separator but contains other ratio-like separators,
|
|
845
|
+
// return an error since the wrong separator was used
|
|
846
|
+
if (parts.length === 1 && !inString.includes(separator)) {
|
|
847
|
+
// Check if the string contains other common ratio separators
|
|
848
|
+
const otherSeparators = [":", "=", "/"];
|
|
849
|
+
for (const otherSep of otherSeparators) {
|
|
850
|
+
if (otherSep !== separator && inString.includes(otherSep)) {
|
|
851
|
+
// The string looks like a ratio but uses the wrong separator
|
|
852
|
+
return { ok: false, error: ParseError.UnableToConvertParseTokensToQuantity };
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
// Parse as a regular quantity value (numerator only, denominator = 1)
|
|
856
|
+
const result = this.parseAndProcessTokens(inString, spec.format, spec.unitConversions);
|
|
857
|
+
return result;
|
|
803
858
|
}
|
|
804
|
-
|
|
859
|
+
// Parse numerator and denominator parts which may include unit labels
|
|
860
|
+
const numeratorPart = this.parseRatioPart(parts[0], spec.format);
|
|
861
|
+
const denominatorPart = parts.length === 1 ? { value: 1.0 } : this.parseRatioPart(parts[1], spec.format);
|
|
862
|
+
if (isNaN(numeratorPart.value) || isNaN(denominatorPart.value))
|
|
805
863
|
return { ok: false, error: ParseError.NoValueOrUnitFoundInString };
|
|
864
|
+
// Handle 2-unit composite case - simpler conversion using the pre-computed scale factor
|
|
865
|
+
if (spec.format.units && spec.format.units.length === 2 && spec.unitConversions.length >= 3) {
|
|
866
|
+
const ratioConvSpec = spec.unitConversions[0];
|
|
867
|
+
const scaleFactor = ratioConvSpec.conversion.factor;
|
|
868
|
+
if (denominatorPart.value === 0) {
|
|
869
|
+
return { ok: false, error: ParseError.InvalidMathResult };
|
|
870
|
+
}
|
|
871
|
+
// The ratio value is numerator/denominator in the display units (e.g., 12 for 12"=1')
|
|
872
|
+
// Divide by scale factor to get persistence unit value (e.g., 12/12 = 1.0)
|
|
873
|
+
const ratioValue = numeratorPart.value / denominatorPart.value;
|
|
874
|
+
const convertedValue = ratioValue / scaleFactor;
|
|
875
|
+
return { ok: true, value: convertedValue };
|
|
876
|
+
}
|
|
877
|
+
// Original flow for 1-unit composite - use Quantity.convertTo for proper unit conversion
|
|
806
878
|
const defaultUnit = spec.format.units && spec.format.units.length > 0 ? spec.format.units[0][0] : undefined;
|
|
807
879
|
const unitConversion = defaultUnit ? Parser.tryFindUnitConversion(defaultUnit.label, spec.unitConversions, defaultUnit) : undefined;
|
|
808
880
|
if (!unitConversion) {
|
|
809
881
|
throw new Exception_1.QuantityError(Exception_1.QuantityStatus.MissingRequiredProperty, `Missing input unit or unit conversion for interpreting ${spec.format.name}.`);
|
|
810
882
|
}
|
|
811
|
-
if (
|
|
812
|
-
if (unitConversion.inversion &&
|
|
883
|
+
if (denominatorPart.value === 0) {
|
|
884
|
+
if (unitConversion.inversion && numeratorPart.value === 1)
|
|
813
885
|
return { ok: true, value: 0.0 };
|
|
814
886
|
else
|
|
815
|
-
return { ok: false, error: ParseError.
|
|
887
|
+
return { ok: false, error: ParseError.InvalidMathResult };
|
|
816
888
|
}
|
|
817
889
|
let quantity;
|
|
818
890
|
if (spec.format.units && spec.outUnit) {
|
|
819
|
-
quantity = new Quantity_1.Quantity(spec.format.units[0][0],
|
|
891
|
+
quantity = new Quantity_1.Quantity(spec.format.units[0][0], numeratorPart.value / denominatorPart.value);
|
|
820
892
|
}
|
|
821
893
|
else {
|
|
822
894
|
throw new Exception_1.QuantityError(Exception_1.QuantityStatus.MissingRequiredProperty, "Missing presentation unit or persistence unit for ratio format.");
|
|
@@ -828,7 +900,7 @@ class Parser {
|
|
|
828
900
|
catch (err) {
|
|
829
901
|
// for input of "0:N" with reversed unit
|
|
830
902
|
if (err instanceof Exception_1.QuantityError && err.errorNumber === Exception_1.QuantityStatus.InvertingZero) {
|
|
831
|
-
return { ok: false, error: ParseError.
|
|
903
|
+
return { ok: false, error: ParseError.InvalidMathResult };
|
|
832
904
|
}
|
|
833
905
|
}
|
|
834
906
|
if (converted === undefined || !converted.isValid) {
|