1
0
Fork 0
mirror of https://github.com/betaflight/betaflight-configurator.git synced 2025-07-25 17:25:16 +03:00

feat: use jquery package (#3540)

This commit is contained in:
Tomas Chmelevskij 2023-08-17 02:13:03 +03:00 committed by GitHub
parent 5ffd193783
commit 40c243fe47
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
68 changed files with 136 additions and 27 deletions

View file

@ -403,6 +403,7 @@ function dist_rollup() {
// I will be picked up by rollup and bundled accordingly.
'js/main_cordova': 'src/js/main_cordova.js',
'js/utils/common': 'src/js/utils/common.js',
'js/jquery': 'src/js/jquery.js',
'js/main': 'src/js/main.js',
'js/tabs/receiver_msp': 'src/js/tabs/receiver_msp.js',
},
@ -437,8 +438,16 @@ function dist_rollup() {
sourcemap: true,
// put any 3rd party module in vendor.js
manualChunks(id) {
/**
* This splits every npm module loaded in into it's own package
* to preserve the loading order. This is to prevent issues
* where after bundling some modules are loaded in the wrong order.
*/
if (id.includes('node_modules')) {
return 'vendor';
const parts = id.split(/[\\/]/);
const nodeModulesIndex = parts.indexOf('node_modules');
const packageName = parts[nodeModulesIndex + 1];
return packageName;
}
},
dir: DIST_DIR,

View file

@ -63,10 +63,10 @@
"i18next-xhr-backend": "^3.2.2",
"inflection": "^1.13.4",
"jbox": "^1.3.3",
"jquery": "^3.6.1",
"jquery": "^3.6.3",
"jquery-textcomplete": "^1.8.5",
"jquery-touchswipe": "^1.6.19",
"jquery-ui-npm": "^1.12.0",
"jquery-ui": "^1.13.2",
"jsdom": "^21.0.0",
"lodash.debounce": "^4.0.8",
"marked": "^4.1.1",
@ -135,6 +135,9 @@
"optionalDependencies": {
"appdmg": "^0.6.4"
},
"resolutions": {
"jquery": "3.6.3"
},
"husky": {
"hooks": {
"pre-commit": "yarn lint"

View file

@ -6,6 +6,7 @@ import DshotCommand from "../../js/utils/DshotCommand.js";
import FC from "../../js/fc.js";
import { API_VERSION_1_44 } from '../../js/data_storage.js';
import { getMixerImageSrc } from "../../js/utils/common.js";
import $ from "jquery";
class EscDshotDirectionComponent
{

View file

@ -8,6 +8,7 @@ import FC from "../../js/fc";
import { gui_log } from "../../js/gui_log";
import { i18n } from "../../js/localization";
import GUI, { TABS } from "../../js/gui";
import $ from "jquery";
export default class MotorOutputReorderComponent
{

View file

@ -3,6 +3,7 @@ import googleAnalytics from 'universal-ga';
import { set as setConfig, get as getConfig } from './ConfigStorage';
import GUI from './gui';
import CONFIGURATOR from './data_storage';
import $ from 'jquery';
let tracking = null;
export { tracking };

View file

@ -1,4 +1,5 @@
import { bit_check, bit_clear, bit_set } from './bit';
import $ from 'jquery';
class Beepers {
constructor(config, supportedConditions) {

View file

@ -1,6 +1,7 @@
import { gui_log } from './gui_log';
import { i18n } from "./localization";
import { get as getStorage, set as setStorage } from "./SessionStorage";
import $ from 'jquery';
export default class BuildApi {

View file

@ -3,6 +3,7 @@ import CONFIGURATOR from './data_storage';
import FC from './fc';
import semver from 'semver';
import { tracking } from './Analytics';
import $ from 'jquery';
/**
* Encapsulates the AutoComplete logic

View file

@ -1,6 +1,7 @@
import GUI from "./gui";
import windowWatcherUtil from "./utils/window_watchers";
import { checkSetupAnalytics } from "./Analytics";
import $ from 'jquery';
const css_dark = [
'./css/dark-theme.css',

View file

@ -2,6 +2,7 @@ import { bit_check, bit_set, bit_clear } from "./bit";
import { API_VERSION_1_44, API_VERSION_1_45 } from './data_storage';
import semver from "semver";
import { tracking } from "./Analytics";
import $ from 'jquery';
const Features = function (config) {
const self = this;

View file

@ -1,6 +1,7 @@
import { gui_log } from "./gui_log";
import { i18n } from "./localization";
import { checkChromeRuntimeError } from "./utils/common";
import $ from 'jquery';
/**
* Takes an ImageData object and returns an MCM symbol as an array of strings.

View file

@ -6,6 +6,7 @@ import { isExpertModeEnabled } from "./utils/isExportModeEnabled";
import semver from "semver";
import { mspHelper } from "./msp/MSPHelper";
import { TABS } from "./gui";
import $ from 'jquery';
const TuningSliders = {
// Legacy Sliders

View file

@ -3,6 +3,7 @@ import MSP from './msp';
import Switchery from 'switchery-latest';
import jBox from 'jbox';
import { checkChromeRuntimeError } from './utils/common';
import $ from 'jquery';
const TABS = {};
@ -316,7 +317,7 @@ class GuiControl {
documentationButton.html("Wiki").attr("href", `https://betaflight.com/docs/wiki/configurator/${tRex}-tab`);
// loading tooltip
jQuery(function () {
$(function () {
new jBox('Tooltip', {
attach: '.cf_tip',

View file

@ -1,3 +1,5 @@
import $ from "jquery";
/**
* log to GUI
* @param {string} message message to log to GUI

26
src/js/jquery.js vendored Normal file
View file

@ -0,0 +1,26 @@
import $ from 'jquery';
/**
* jQuery has plugins which load in all sort of different ways,
* not necessary as modules. This binds jquery package to global
* scope and is loaded in first, so that when plugins are loaded
* all of them have access to the same instance.
*/
if(typeof globalThis !== 'undefined') {
// eslint-disable-next-line no-undef
globalThis.jQuery = $;
// eslint-disable-next-line no-undef
globalThis.$ = $;
}
if(typeof window !== 'undefined') {
window.jQuery = $;
window.$ = $;
}
if(typeof global !== 'undefined') {
global.$ = $;
global.jQuery = $;
}
export default $;

9
src/js/jqueryPlugins.js vendored Normal file
View file

@ -0,0 +1,9 @@
import './jquery';
import 'jquery-ui/dist/jquery-ui';
import 'jquery-textcomplete';
import 'jquery-touchswipe';
import select2 from 'select2';
select2(jQuery);
import 'multiple-select';
import '../../libraries/jquery.nouislider.all.min.js';
import '../../libraries/jquery.flightindicators.js';

View file

@ -2,6 +2,7 @@ import i18next from 'i18next';
import i18nextXHRBackend from 'i18next-xhr-backend';
import { gui_log } from './gui_log.js';
import { get as getConfig, set as setConfig } from './ConfigStorage.js';
import $ from "jquery";
const i18n = {};
/*

View file

@ -1,3 +1,5 @@
import './jqueryPlugins';
import $ from 'jquery';
import 'jbox';
import '../components/init.js';
import { gui_log } from './gui_log.js';

View file

@ -1,4 +1,5 @@
import { i18n } from "./localization.js";
import $ from 'jquery';
const REQUIRED_WEBVIEW_VERSION = 72;
const WEBVIEW = {

View file

@ -9,6 +9,9 @@ import CONFIGURATOR from "../data_storage";
import serial from "../serial";
import { gui_log } from "../gui_log";
/**
* This seems to be mainly used in firmware flasher parts.
*/
const MSPConnectorImpl = function () {
this.baud = undefined;
this.port = undefined;

View file

@ -1,3 +1,4 @@
import '../injected_methods';
import { update_dataflash_global } from "../update_dataflash_global";
import { sensor_status } from "../sensor_helpers";
import { bit_check, bit_set } from "../bit";

View file

@ -1,4 +1,5 @@
import GUI from "./gui";
import $ from 'jquery';
const UI_PHONES = {
background: '#background',

View file

@ -5,6 +5,7 @@ import { generateVirtualApiVersions, getTextWidth } from './utils/common';
import { get as getConfig } from "./ConfigStorage";
import serial from "./serial";
import MdnsDiscovery from "./mdns_discovery";
import $ from 'jquery';
const TIMEOUT_CHECK = 500 ; // With 250 it seems that it produces a memory leak and slowdown in some versions, reason unknown

View file

@ -19,6 +19,7 @@ import { API_VERSION_1_42 } from "../data_storage";
import serial from "../serial";
import STM32DFU from "./stm32usbdfu";
import semver from "semver";
import $ from 'jquery';
const STM32_protocol = function () {
this.baud = null;

View file

@ -1,4 +1,5 @@
import { bit_check } from './bit';
import $ from 'jquery';
export function have_sensor(sensors_detected, sensor_code) {
switch(sensor_code) {

View file

@ -6,6 +6,7 @@ import { gui_log } from "./gui_log";
import inflection from "inflection";
import PortHandler from "./port_handler";
import { checkChromeRuntimeError } from "./utils/common";
import $ from 'jquery';
const serial = {
connected: false,

View file

@ -22,6 +22,7 @@ import { get as getConfig, set as setConfig } from "./ConfigStorage";
import { tracking } from "./Analytics";
import semver from 'semver';
import CryptoES from "crypto-es";
import $ from 'jquery';
import BuildApi from "./BuildApi";
let mspHelper;

View file

@ -7,6 +7,7 @@ import MSPCodes from '../msp/MSPCodes';
import { API_VERSION_1_42 } from '../data_storage';
import { gui_log } from '../gui_log';
import semver from 'semver';
import $ from 'jquery';
const adjustments = {};

View file

@ -8,6 +8,7 @@ import MSP from '../msp';
import MSPCodes from '../msp/MSPCodes';
import adjustBoxNameIfPeripheralWithModeID from '../peripherals';
import { getTextWidth } from '../utils/common';
import $ from 'jquery';
import inflection from "inflection";
const auxiliary = {};

View file

@ -12,6 +12,7 @@ import UI_PHONES from "../phones_ui";
import { gui_log } from "../gui_log";
import jBox from "jbox";
import { checkChromeRuntimeError } from "../utils/common";
import $ from 'jquery';
const cli = {
lineDelayMs: 15,

View file

@ -8,6 +8,7 @@ import MSP from '../msp';
import MSPCodes from '../msp/MSPCodes';
import { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_45 } from '../data_storage';
import { updateTabList } from '../utils/updateTabList';
import $ from 'jquery';
const configuration = {
analyticsChanges: {},

View file

@ -7,6 +7,7 @@ import MSPCodes from "../msp/MSPCodes";
import adjustBoxNameIfPeripheralWithModeID from "../peripherals";
import { API_VERSION_1_43, API_VERSION_1_44, API_VERSION_1_45, API_VERSION_1_46 } from "../data_storage";
import semver from 'semver';
import $ from 'jquery';
const failsafe = {};

View file

@ -1,3 +1,4 @@
import $ from 'jquery';
import { i18n } from '../localization';
import GUI, { TABS } from '../gui';
import { get as getConfig, set as setConfig } from '../ConfigStorage';

View file

@ -5,6 +5,7 @@ import GUI, { TABS } from '../gui';
import FC from '../fc';
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import $ from 'jquery';
import { have_sensor } from "../sensor_helpers";
import { mspHelper } from '../msp/MSPHelper';
import { updateTabList } from '../utils/updateTabList';

View file

@ -1,5 +1,6 @@
import GUI, { TABS } from '../gui';
import { i18n } from '../localization';
import $ from 'jquery';
const help = {};
help.initialize = function (callback) {

View file

@ -1,5 +1,6 @@
import GUI, { TABS } from '../gui';
import { i18n } from '../localization';
import $ from 'jquery';
const landing = {};
landing.initialize = function (callback) {

View file

@ -5,6 +5,7 @@ import FC from "../fc";
import semver from 'semver';
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import $ from 'jquery';
import { API_VERSION_1_46 } from '../data_storage';
const led_strip = {

View file

@ -8,6 +8,7 @@ import MSP from '../msp.js';
import MSPCodes from '../msp/MSPCodes.js';
import CONFIGURATOR from '../data_storage.js';
import { gui_log } from '../gui_log.js';
import $ from 'jquery';
const logging = {};
logging.initialize = function (callback) {

View file

@ -18,6 +18,7 @@ import { updateTabList } from "../utils/updateTabList";
import { isInt, getMixerImageSrc } from "../utils/common";
import semver from 'semver';
import * as d3 from 'd3';
import $ from 'jquery';
const motors = {
previousDshotBidir: null,

View file

@ -11,6 +11,7 @@ import { generateFilename } from "../utils/generate_filename";
import semver from 'semver';
import { showErrorDialog } from "../utils/showErrorDialog";
import { checkChromeRuntimeError } from "../utils/common";
import $ from 'jquery';
let sdcardTimer;

View file

@ -6,6 +6,7 @@ import CliAutoComplete from '../CliAutoComplete';
import DarkTheme, { setDarkTheme } from '../DarkTheme';
import { checkForConfiguratorUpdates } from '../utils/checkForConfiguratorUpdates';
import { checkSetupAnalytics } from '../Analytics';
import $ from 'jquery';
import CONFIGURATOR from '../data_storage';
const options = {};

View file

@ -15,6 +15,7 @@ import jBox from "jbox";
import inflection from "inflection";
import { checkChromeRuntimeError } from "../utils/common";
import debounce from "lodash.debounce";
import $ from 'jquery';
const FONT = {};
const SYM = {};

View file

@ -15,6 +15,7 @@ import { gui_log } from "../gui_log";
import { degToRad, isInt } from "../utils/common";
import semver from "semver";
import * as THREE from "three";
import $ from 'jquery';
const pid_tuning = {
RATE_PROFILE_MASK: 128,

View file

@ -8,6 +8,7 @@ import MSP from '../msp';
import MSPCodes from '../msp/MSPCodes';
import { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_45 } from '../data_storage';
import BOARD from '../boards';
import $ from 'jquery';
const ports = {
analyticsChanges: {},

View file

@ -6,6 +6,7 @@ import FC from '../fc';
import MSP from '../msp';
import MSPCodes from '../msp/MSPCodes';
import jBox from 'jbox';
import $ from 'jquery';
const power = {
supported: false,

View file

@ -18,7 +18,7 @@ import semver from 'semver';
import { updateTabList } from "../utils/updateTabList";
import * as THREE from 'three';
import * as d3 from "d3";
import $ from 'jquery';
import CryptoES from 'crypto-es';
const receiver = {

View file

@ -1,4 +1,5 @@
import windowWatcherUtil from "../utils/window_watchers";
import $ from 'jquery';
const css_dark = [
'/css/dark-theme.css',

View file

@ -7,6 +7,7 @@ import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import serial from "../serial";
import * as d3 from 'd3';
import $ from 'jquery';
import semver from 'semver';
import { API_VERSION_1_46 } from "../data_storage";

View file

@ -5,6 +5,7 @@ import FC from "../fc";
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import { gui_log } from "../gui_log";
import $ from 'jquery';
const servos = {};
servos.initialize = function (callback) {

View file

@ -11,6 +11,7 @@ import Model from '../model';
import MSPCodes from '../msp/MSPCodes';
import CONFIGURATOR, { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_46 } from '../data_storage';
import { gui_log } from '../gui_log';
import $ from 'jquery';
const setup = {
yaw_fix: 0.0,

View file

@ -3,6 +3,7 @@ import GUI, { TABS } from '../gui';
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import { gui_log } from "../gui_log";
import $ from 'jquery';
const setup_osd = {
};

View file

@ -1,5 +1,6 @@
import { i18n } from '../localization';
import GUI, { TABS } from '../gui';
import $ from 'jquery';
const staticTab = {};
staticTab.initialize = function (staticTabName, callback) {

View file

@ -5,6 +5,7 @@ import FC from "../fc";
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import { gui_log } from "../gui_log";
import $ from 'jquery';
const transponder = {
available: false,

View file

@ -14,6 +14,7 @@ import { API_VERSION_1_42, API_VERSION_1_44 } from '../data_storage';
import UI_PHONES from "../phones_ui";
import { gui_log } from "../gui_log";
import { checkChromeRuntimeError } from "../utils/common";
import $ from 'jquery';
const vtx = {
supported: false,

View file

@ -1,4 +1,5 @@
import FC from "./fc";
import $ from 'jquery';
export function update_dataflash_global() {
function formatFilesize(bytes) {

View file

@ -3,6 +3,7 @@ import { get as getConfig } from "../ConfigStorage";
import CONFIGURATOR from "../data_storage";
import { i18n } from "../localization";
import { gui_log } from "../gui_log";
import $ from 'jquery';
function notifyOutdatedVersion(data) {

View file

@ -2,6 +2,7 @@ import semver from "semver";
import { mixerList } from "../model";
import CONFIGURATOR from "../data_storage";
import { gui_log } from "../gui_log";
import $ from "jquery";
export function millitime() {
return new Date().getTime();

View file

@ -1,3 +1,5 @@
import $ from 'jquery';
export function isExpertModeEnabled() {
return $('input[name="expertModeCheckbox"]').is(':checked');
}

View file

@ -1,3 +1,4 @@
import $ from 'jquery';
export function showErrorDialog(message) {
const dialog = $('.dialogError')[0];

View file

@ -1,3 +1,5 @@
import $ from 'jquery';
export function updateTabList(features) {
const isExpertModeEnabled = $('input[name="expertModeCheckbox"]').is(':checked');

View file

@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="author" content="cTn"/>
<link type="text/css" rel="stylesheet" href="./node_modules/jbox/dist/jBox.min.css"/>
<link type="text/css" rel="stylesheet" href="../node_modules/jbox/dist/jBox.min.css"/>
<link type="text/css" rel="stylesheet" href="./js/libraries/jquery.nouislider.min.css"/>
<link type="text/css" rel="stylesheet" href="./js/libraries/jquery.nouislider.pips.min.css"/>
<link type="text/css" rel="stylesheet" href="./js/libraries/flightindicators.css"/>
@ -53,18 +53,11 @@
<link type="text/css" rel="stylesheet" href="./css/dark-theme.css" media="all" disabled/>
<script type="module" src="./js/jquery.js"></script>
<!-- TODO: probably won't need this here once everything is imported -->
<script type="module" src="./js/utils/common.js"></script>
<!-- CORDOVA_INCLUDE js/cordova_chromeapi.js -->
<!-- CORDOVA_INCLUDE js/cordova_startup.js -->
<script type="text/javascript" src="./node_modules/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="./node_modules/jquery-ui-npm/jquery-ui.min.js"></script>
<script type="text/javascript" src="./js/libraries/jquery.nouislider.all.min.js"></script>
<script type="text/javascript" src="./js/libraries/jquery.flightindicators.js"></script>
<script type="text/javascript" src="./node_modules/jquery-textcomplete/dist/jquery.textcomplete.min.js"></script>
<script type="text/javascript" src="./node_modules/jquery-touchswipe/jquery.touchSwipe.min.js"></script>
<script type="text/javascript" src="./node_modules/select2/dist/js/select2.min.js"></script>
<script type="text/javascript" src="./node_modules/multiple-select/dist/multiple-select.min.js"></script>
<script type="module" src="./js/main.js"></script>
<title></title>

View file

@ -5,6 +5,7 @@ import PresetTitlePanel from "../TitlePanel/PresetTitlePanel";
import FC from "../../../js/fc";
import { marked } from "marked";
import DOMPurify from "dompurify";
import $ from 'jquery';
export default class PresetsDetailedDialog {
constructor(domDialog, pickedPresetList, onPresetPickedCallback, favoritePresets) {

View file

@ -1,6 +1,7 @@
import { i18n } from "../../../js/localization";
import GUI from "../../../js/gui";
import PresetSource from "./PresetSource";
import $ from 'jquery';
export default class SourcePanel {
constructor(parentDiv, presetSource) {

View file

@ -2,6 +2,7 @@ import { i18n } from "../../../js/localization";
import { get as getConfig, set as setConfig } from "../../../js/ConfigStorage";
import PresetSource from "./PresetSource";
import SourcePanel from "./SourcePanel";
import $ from 'jquery';
export default class PresetsSourcesDialog {
constructor(domDialog) {

View file

@ -1,4 +1,5 @@
import { i18n } from "../../../js/localization";
import $ from 'jquery';
export default class PresetTitlePanel
{

View file

@ -1,3 +1,4 @@
import '../../js/jqueryPlugins';
import GUI, { TABS } from '../../js/gui';
import { get as getConfig, set as setConfig } from '../../js/ConfigStorage';
import { generateFilename } from '../../js/utils/generate_filename';
@ -5,6 +6,7 @@ import { i18n } from '../../js/localization';
import FC from '../../js/fc';
import CONFIGURATOR from '../../js/data_storage';
import UI_PHONES from '../../js/phones_ui';
import $ from 'jquery';
import { favoritePresets } from './FavoritePresets';
import CliEngine from './CliEngine';

View file

@ -9970,20 +9970,22 @@ jquery-touchswipe@^1.6.19:
resolved "https://registry.yarnpkg.com/jquery-touchswipe/-/jquery-touchswipe-1.6.19.tgz#dfd5ddaec0b78212dd500d29707129b9c7fd6cd4"
integrity sha512-b0BGje9reNRU3u6ksAK9QqnX7yBRgLNe/wYG7DOfyDlhBlYjayIT8bSOHmcuvptIDW/ubM9CTW/mnZf9Rohuow==
jquery-ui-npm@^1.12.0:
version "1.12.0"
resolved "https://registry.yarnpkg.com/jquery-ui-npm/-/jquery-ui-npm-1.12.0.tgz#3f2cae88195c7d48acf3786cfa900d0403814e4d"
integrity sha1-PyyuiBlcfUis83hs+pANBAOBTk0=
jquery-ui@^1.13.2:
version "1.13.2"
resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.13.2.tgz#de03580ae6604773602f8d786ad1abfb75232034"
integrity sha512-wBZPnqWs5GaYJmo1Jj0k/mrSkzdQzKDwhXNtHKcBdAcKVxMM3KNYFq+iJ2i1rwiG53Z8M4mTn3Qxrm17uH1D4Q==
dependencies:
jquery ">=1.8.0 <4.0.0"
jquery@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470"
integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==
jquery@3.6.3, "jquery@>=1.8.0 <4.0.0", jquery@^3.6.0:
version "3.6.3"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.3.tgz#23ed2ffed8a19e048814f13391a19afcdba160e6"
integrity sha512-bZ5Sy3YzKo9Fyc8wH2iIQK4JImJ6R0GWI9kL1/k7Z91ZBNgkRXE6U0JfHIizZbort8ZunhSI3jw9I6253ahKfg==
jquery@^3.6.1:
version "3.6.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.1.tgz#fab0408f8b45fc19f956205773b62b292c147a16"
integrity sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw==
jquery@^3.6.3:
version "3.7.0"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.0.tgz#fe2c01a05da500709006d8790fe21c8a39d75612"
integrity sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ==
js-base64@^2.1.9:
version "2.6.4"