tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

UnitConverterSimple.sys.mjs (6258B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import { UrlbarUtils } from "moz-src:///browser/components/urlbar/UrlbarUtils.sys.mjs";
      6 
      7 // NOTE: This units table need to be localized upon supporting multi locales
      8 //       since it supports en-US only.
      9 //       e.g. Should support plugada or funty as well for pound.
     10 /**
     11 * @type {{[key: string]: any}[]}
     12 */
     13 const UNITS_GROUPS = [
     14  {
     15    // Angle
     16    degree: 1,
     17    deg: "degree",
     18    d: "degree",
     19    radian: Math.PI / 180.0,
     20    rad: "radian",
     21    r: "radian",
     22    gradian: 1 / 0.9,
     23    grad: "gradian",
     24    g: "gradian",
     25    minute: 60,
     26    min: "minute",
     27    m: "minute",
     28    second: 3600,
     29    sec: "second",
     30    s: "second",
     31    sign: 1 / 30.0,
     32    mil: 1 / 0.05625,
     33    revolution: 1 / 360.0,
     34    circle: 1 / 360.0,
     35    turn: 1 / 360.0,
     36    quadrant: 1 / 90.0,
     37    rightangle: 1 / 90.0,
     38    sextant: 1 / 60.0,
     39  },
     40  {
     41    // Force
     42    newton: 1,
     43    n: "newton",
     44    kilonewton: 0.001,
     45    kn: "kilonewton",
     46    "gram-force": 101.9716213,
     47    gf: "gram-force",
     48    "kilogram-force": 0.1019716213,
     49    kgf: "kilogram-force",
     50    "ton-force": 0.0001019716213,
     51    tf: "ton-force",
     52    exanewton: 1.0e-18,
     53    en: "exanewton",
     54    petanewton: 1.0e-15,
     55    PN: "petanewton",
     56    Pn: "petanewton",
     57    teranewton: 1.0e-12,
     58    tn: "teranewton",
     59    giganewton: 1.0e-9,
     60    gn: "giganewton",
     61    meganewton: 0.000001,
     62    MN: "meganewton",
     63    Mn: "meganewton",
     64    hectonewton: 0.01,
     65    hn: "hectonewton",
     66    dekanewton: 0.1,
     67    dan: "dekanewton",
     68    decinewton: 10,
     69    dn: "decinewton",
     70    centinewton: 100,
     71    cn: "centinewton",
     72    millinewton: 1000,
     73    mn: "millinewton",
     74    micronewton: 1000000,
     75    µn: "micronewton",
     76    nanonewton: 1000000000,
     77    nn: "nanonewton",
     78    piconewton: 1000000000000,
     79    pn: "piconewton",
     80    femtonewton: 1000000000000000,
     81    fn: "femtonewton",
     82    attonewton: 1000000000000000000,
     83    an: "attonewton",
     84    dyne: 100000,
     85    dyn: "dyne",
     86    "joule/meter": 1,
     87    "j/m": "joule/meter",
     88    "joule/centimeter": 100,
     89    "j/cm": "joule/centimeter",
     90    "ton-force-short": 0.0001124045,
     91    short: "ton-force-short",
     92    "ton-force-long": 0.0001003611,
     93    tonf: "ton-force-long",
     94    "kip-force": 0.0002248089,
     95    kipf: "kip-force",
     96    "pound-force": 0.2248089431,
     97    lbf: "pound-force",
     98    "ounce-force": 3.5969430896,
     99    ozf: "ounce-force",
    100    poundal: 7.2330138512,
    101    pdl: "poundal",
    102    pond: 101.9716213,
    103    p: "pond",
    104    kilopond: 0.1019716213,
    105    kp: "kilopond",
    106  },
    107  {
    108    // Length
    109    meter: 1,
    110    m: "meter",
    111    nanometer: 1000000000,
    112    micrometer: 1000000,
    113    millimeter: 1000,
    114    mm: "millimeter",
    115    centimeter: 100,
    116    cm: "centimeter",
    117    kilometer: 0.001,
    118    km: "kilometer",
    119    mile: 0.0006213689,
    120    mi: "mile",
    121    yard: 1.0936132983,
    122    yd: "yard",
    123    foot: 3.280839895,
    124    feet: "foot",
    125    ft: "foot",
    126    inch: 39.37007874,
    127    inches: "inch",
    128    in: "inch",
    129  },
    130  {
    131    // Mass
    132    kilogram: 1,
    133    kg: "kilogram",
    134    gram: 1000,
    135    g: "gram",
    136    milligram: 1000000,
    137    mg: "milligram",
    138    ton: 0.001,
    139    t: "ton",
    140    longton: 0.0009842073,
    141    "l.t.": "longton",
    142    "l/t": "longton",
    143    shortton: 0.0011023122,
    144    "s.t.": "shortton",
    145    "s/t": "shortton",
    146    pound: 2.2046244202,
    147    lbs: "pound",
    148    lb: "pound",
    149    ounce: 35.273990723,
    150    oz: "ounce",
    151    carat: 5000,
    152    ffd: 5000,
    153  },
    154 ];
    155 
    156 // There are some units that will be same in lower case in same unit group.
    157 // e.g. Mn: meganewton and mn: millinewton on force group.
    158 // Handle them as case-sensitive.
    159 const CASE_SENSITIVE_UNITS = ["PN", "Pn", "MN", "Mn"];
    160 
    161 const NUMBER_REGEX = "-?\\d+(?:\\.\\d+)?\\s*";
    162 const UNIT_REGEX = "[A-Za-zµ0-9_./-]+";
    163 
    164 // NOTE: This regex need to be localized upon supporting multi locales
    165 //       since it supports en-US input format only.
    166 const QUERY_REGEX = new RegExp(
    167  `^(${NUMBER_REGEX})(${UNIT_REGEX})(?:\\s+in\\s+|\\s+to\\s+|\\s*=\\s*)(${UNIT_REGEX})`,
    168  "i"
    169 );
    170 
    171 /**
    172 * This module converts simple unit such as angle and length.
    173 */
    174 export class UnitConverterSimple {
    175  /**
    176   * Convert the given search string.
    177   *
    178   * @param {string} searchString
    179   *   The string to be converted
    180   * @returns {string} conversion result.
    181   */
    182  convert(searchString) {
    183    const regexResult = QUERY_REGEX.exec(searchString);
    184    if (!regexResult) {
    185      return null;
    186    }
    187 
    188    const target = findUnitGroup(regexResult[2], regexResult[3]);
    189 
    190    if (!target) {
    191      return null;
    192    }
    193 
    194    const { group, inputUnit, outputUnit } = target;
    195    const inputNumber = Number(regexResult[1]);
    196    const outputNumber = (inputNumber / group[inputUnit]) * group[outputUnit];
    197 
    198    let formattedUnit;
    199    try {
    200      const formatter = new Intl.NumberFormat("en-US", {
    201        style: "unit",
    202        unit: outputUnit,
    203      });
    204      const parts = formatter.formatToParts(1);
    205      formattedUnit = parts.find(part => part.type == "unit").value;
    206    } catch (e) {
    207      formattedUnit = outputUnit;
    208    }
    209 
    210    return `${UrlbarUtils.formatUnitConversionResult(outputNumber)} ${formattedUnit}`;
    211  }
    212 }
    213 
    214 /**
    215 * Returns the suitable units for the given two values.
    216 * If could not found suitable unit, returns null.
    217 *
    218 * @param {string} inputUnit
    219 *    A set of units to convert, mapped to the `inputUnit` value on the return
    220 * @param {string} outputUnit
    221 *    A set of units to convert, mapped to the `outputUnit` value on the return
    222 */
    223 function findUnitGroup(inputUnit, outputUnit) {
    224  inputUnit = toSuitableUnit(inputUnit);
    225  outputUnit = toSuitableUnit(outputUnit);
    226 
    227  const group = UNITS_GROUPS.find(ug => ug[inputUnit] && ug[outputUnit]);
    228 
    229  if (!group) {
    230    return null;
    231  }
    232 
    233  const inputValue = group[inputUnit];
    234  const outputValue = group[outputUnit];
    235 
    236  return {
    237    group,
    238    inputUnit: typeof inputValue === "string" ? inputValue : inputUnit,
    239    outputUnit: typeof outputValue === "string" ? outputValue : outputUnit,
    240  };
    241 }
    242 
    243 /**
    244 * Converts the unit value to an appropriate case if necessary.
    245 *
    246 * @param {string} unit
    247 */
    248 function toSuitableUnit(unit) {
    249  return CASE_SENSITIVE_UNITS.includes(unit) ? unit : unit.toLowerCase();
    250 }