summaryrefslogtreecommitdiffstats
path: root/browser/components/urlbar/unitconverters/UnitConverterSimple.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/urlbar/unitconverters/UnitConverterSimple.sys.mjs')
-rw-r--r--browser/components/urlbar/unitconverters/UnitConverterSimple.sys.mjs243
1 files changed, 243 insertions, 0 deletions
diff --git a/browser/components/urlbar/unitconverters/UnitConverterSimple.sys.mjs b/browser/components/urlbar/unitconverters/UnitConverterSimple.sys.mjs
new file mode 100644
index 0000000000..47ba0cc856
--- /dev/null
+++ b/browser/components/urlbar/unitconverters/UnitConverterSimple.sys.mjs
@@ -0,0 +1,243 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// NOTE: This units table need to be localized upon supporting multi locales
+// since it supports en-US only.
+// e.g. Should support plugada or funty as well for pound.
+const UNITS_GROUPS = [
+ {
+ // Angle
+ degree: 1,
+ deg: "degree",
+ d: "degree",
+ radian: Math.PI / 180.0,
+ rad: "radian",
+ r: "radian",
+ gradian: 1 / 0.9,
+ grad: "gradian",
+ g: "gradian",
+ minute: 60,
+ min: "minute",
+ m: "minute",
+ second: 3600,
+ sec: "second",
+ s: "second",
+ sign: 1 / 30.0,
+ mil: 1 / 0.05625,
+ revolution: 1 / 360.0,
+ circle: 1 / 360.0,
+ turn: 1 / 360.0,
+ quadrant: 1 / 90.0,
+ rightangle: 1 / 90.0,
+ sextant: 1 / 60.0,
+ },
+ {
+ // Force
+ newton: 1,
+ n: "newton",
+ kilonewton: 0.001,
+ kn: "kilonewton",
+ "gram-force": 101.9716213,
+ gf: "gram-force",
+ "kilogram-force": 0.1019716213,
+ kgf: "kilogram-force",
+ "ton-force": 0.0001019716213,
+ tf: "ton-force",
+ exanewton: 1.0e-18,
+ en: "exanewton",
+ petanewton: 1.0e-15,
+ PN: "petanewton",
+ Pn: "petanewton",
+ teranewton: 1.0e-12,
+ tn: "teranewton",
+ giganewton: 1.0e-9,
+ gn: "giganewton",
+ meganewton: 0.000001,
+ MN: "meganewton",
+ Mn: "meganewton",
+ hectonewton: 0.01,
+ hn: "hectonewton",
+ dekanewton: 0.1,
+ dan: "dekanewton",
+ decinewton: 10,
+ dn: "decinewton",
+ centinewton: 100,
+ cn: "centinewton",
+ millinewton: 1000,
+ mn: "millinewton",
+ micronewton: 1000000,
+ µn: "micronewton",
+ nanonewton: 1000000000,
+ nn: "nanonewton",
+ piconewton: 1000000000000,
+ pn: "piconewton",
+ femtonewton: 1000000000000000,
+ fn: "femtonewton",
+ attonewton: 1000000000000000000,
+ an: "attonewton",
+ dyne: 100000,
+ dyn: "dyne",
+ "joule/meter": 1,
+ "j/m": "joule/meter",
+ "joule/centimeter": 100,
+ "j/cm": "joule/centimeter",
+ "ton-force-short": 0.0001124045,
+ short: "ton-force-short",
+ "ton-force-long": 0.0001003611,
+ tonf: "ton-force-long",
+ "kip-force": 0.0002248089,
+ kipf: "kip-force",
+ "pound-force": 0.2248089431,
+ lbf: "pound-force",
+ "ounce-force": 3.5969430896,
+ ozf: "ounce-force",
+ poundal: 7.2330138512,
+ pdl: "poundal",
+ pond: 101.9716213,
+ p: "pond",
+ kilopond: 0.1019716213,
+ kp: "kilopond",
+ },
+ {
+ // Length
+ meter: 1,
+ m: "meter",
+ nanometer: 1000000000,
+ micrometer: 1000000,
+ millimeter: 1000,
+ mm: "millimeter",
+ centimeter: 100,
+ cm: "centimeter",
+ kilometer: 0.001,
+ km: "kilometer",
+ mile: 0.0006213689,
+ mi: "mile",
+ yard: 1.0936132983,
+ yd: "yard",
+ foot: 3.280839895,
+ feet: "foot",
+ ft: "foot",
+ inch: 39.37007874,
+ inches: "inch",
+ in: "inch",
+ },
+ {
+ // Mass
+ kilogram: 1,
+ kg: "kilogram",
+ gram: 1000,
+ g: "gram",
+ milligram: 1000000,
+ mg: "milligram",
+ ton: 0.001,
+ t: "ton",
+ longton: 0.0009842073,
+ "l.t.": "longton",
+ "l/t": "longton",
+ shortton: 0.0011023122,
+ "s.t.": "shortton",
+ "s/t": "shortton",
+ pound: 2.2046244202,
+ lbs: "pound",
+ lb: "pound",
+ ounce: 35.273990723,
+ oz: "ounce",
+ carat: 5000,
+ ffd: 5000,
+ },
+];
+
+// There are some units that will be same in lower case in same unit group.
+// e.g. Mn: meganewton and mn: millinewton on force group.
+// Handle them as case-sensitive.
+const CASE_SENSITIVE_UNITS = ["PN", "Pn", "MN", "Mn"];
+
+const NUMBER_REGEX = "-?\\d+(?:\\.\\d+)?\\s*";
+const UNIT_REGEX = "[A-Za-zµ0-9_./-]+";
+
+// NOTE: This regex need to be localized upon supporting multi locales
+// since it supports en-US input format only.
+const QUERY_REGEX = new RegExp(
+ `^(${NUMBER_REGEX})(${UNIT_REGEX})(?:\\s+in\\s+|\\s+to\\s+|\\s*=\\s*)(${UNIT_REGEX})`,
+ "i"
+);
+
+const DECIMAL_PRECISION = 10;
+
+/**
+ * This module converts simple unit such as angle and length.
+ */
+export class UnitConverterSimple {
+ /**
+ * Convert the given search string.
+ *
+ * @param {string} searchString
+ * The string to be converted
+ * @returns {string} conversion result.
+ */
+ convert(searchString) {
+ const regexResult = QUERY_REGEX.exec(searchString);
+ if (!regexResult) {
+ return null;
+ }
+
+ const target = findUnitGroup(regexResult[2], regexResult[3]);
+
+ if (!target) {
+ return null;
+ }
+
+ const { group, inputUnit, outputUnit } = target;
+ const inputNumber = Number(regexResult[1]);
+ const outputNumber = parseFloat(
+ ((inputNumber / group[inputUnit]) * group[outputUnit]).toPrecision(
+ DECIMAL_PRECISION
+ )
+ );
+
+ try {
+ return new Intl.NumberFormat("en-US", {
+ style: "unit",
+ unit: outputUnit,
+ maximumFractionDigits: DECIMAL_PRECISION,
+ }).format(outputNumber);
+ } catch (e) {}
+
+ return `${outputNumber} ${outputUnit}`;
+ }
+}
+
+/**
+ * Returns the suitable units for the given two values.
+ * If could not found suitable unit, returns null.
+ *
+ * @param {string} inputUnit
+ * A set of units to convert, mapped to the `inputUnit` value on the return
+ * @param {string} outputUnit
+ * A set of units to convert, mapped to the `outputUnit` value on the return
+ * @returns {{ inputUnit: string, outputUnit: string }} The suitable units.
+ */
+function findUnitGroup(inputUnit, outputUnit) {
+ inputUnit = toSuitableUnit(inputUnit);
+ outputUnit = toSuitableUnit(outputUnit);
+
+ const group = UNITS_GROUPS.find(ug => ug[inputUnit] && ug[outputUnit]);
+
+ if (!group) {
+ return null;
+ }
+
+ const inputValue = group[inputUnit];
+ const outputValue = group[outputUnit];
+
+ return {
+ group,
+ inputUnit: typeof inputValue === "string" ? inputValue : inputUnit,
+ outputUnit: typeof outputValue === "string" ? outputValue : outputUnit,
+ };
+}
+
+function toSuitableUnit(unit) {
+ return CASE_SENSITIVE_UNITS.includes(unit) ? unit : unit.toLowerCase();
+}