зеркало из https://github.com/mozilla/gecko-dev.git
157 строки
3.9 KiB
JavaScript
157 строки
3.9 KiB
JavaScript
/* 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/. */
|
|
|
|
"use strict";
|
|
|
|
loader.lazyRequireGetter(
|
|
this,
|
|
"validator",
|
|
"devtools/shared/storage/vendor/stringvalidator/validator"
|
|
);
|
|
loader.lazyRequireGetter(this, "JSON5", "devtools/shared/storage/vendor/json5");
|
|
|
|
const MATH_REGEX = /(?:(?:^|[-+_*/])(?:\s*-?\d+(\.\d+)?(?:[eE][+-]?\d+)?\s*))+$/;
|
|
|
|
/**
|
|
* Tries to parse a string into an object on the basis of key-value pairs,
|
|
* separated by various separators. If failed, tries to parse for single
|
|
* separator separated values to form an array.
|
|
*
|
|
* @param {string} value
|
|
* The string to be parsed into an object or array
|
|
*/
|
|
function _extractKeyValPairs(value) {
|
|
const makeObject = (keySep, pairSep) => {
|
|
const object = {};
|
|
for (const pair of value.split(pairSep)) {
|
|
const [key, val] = pair.split(keySep);
|
|
object[key] = val;
|
|
}
|
|
return object;
|
|
};
|
|
|
|
// Possible separators.
|
|
const separators = ["=", ":", "~", "#", "&", "\\*", ",", "\\."];
|
|
// Testing for object
|
|
for (let i = 0; i < separators.length; i++) {
|
|
const kv = separators[i];
|
|
for (let j = 0; j < separators.length; j++) {
|
|
if (i == j) {
|
|
continue;
|
|
}
|
|
const p = separators[j];
|
|
const word = `[^${kv}${p}]*`;
|
|
const keyValue = `${word}${kv}${word}`;
|
|
const keyValueList = `${keyValue}(${p}${keyValue})*`;
|
|
const regex = new RegExp(`^${keyValueList}$`);
|
|
if (
|
|
value.match &&
|
|
value.match(regex) &&
|
|
value.includes(kv) &&
|
|
(value.includes(p) || value.split(kv).length == 2)
|
|
) {
|
|
return makeObject(kv, p);
|
|
}
|
|
}
|
|
}
|
|
// Testing for array
|
|
for (const p of separators) {
|
|
const word = `[^${p}]*`;
|
|
const wordList = `(${word}${p})+${word}`;
|
|
const regex = new RegExp(`^${wordList}$`);
|
|
|
|
if (regex.test(value)) {
|
|
const pNoBackslash = p.replace(/\\*/g, "");
|
|
return value.split(pNoBackslash);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Check whether the value string represents something that should be
|
|
* displayed as text. If so then it shouldn't be parsed into a tree.
|
|
*
|
|
* @param {String} value
|
|
* The value to be parsed.
|
|
*/
|
|
function _shouldParse(value) {
|
|
const validators = [
|
|
"isBase64",
|
|
"isBoolean",
|
|
"isCurrency",
|
|
"isDataURI",
|
|
"isEmail",
|
|
"isFQDN",
|
|
"isHexColor",
|
|
"isIP",
|
|
"isISO8601",
|
|
"isMACAddress",
|
|
"isSemVer",
|
|
"isURL",
|
|
];
|
|
|
|
// Check for minus calculations e.g. 8-3 because otherwise 5 will be displayed.
|
|
if (MATH_REGEX.test(value)) {
|
|
return false;
|
|
}
|
|
|
|
// Check for any other types that shouldn't be parsed.
|
|
for (const test of validators) {
|
|
if (validator[test](value)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Seems like this is data that should be parsed.
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Tries to parse a string value into either a json or a key-value separated
|
|
* object. The value can also be a key separated array.
|
|
*
|
|
* @param {string} originalValue
|
|
* The string to be parsed into an object
|
|
*/
|
|
function parseItemValue(originalValue) {
|
|
// Find if value is URLEncoded ie
|
|
let decodedValue = "";
|
|
try {
|
|
decodedValue = decodeURIComponent(originalValue);
|
|
} catch (e) {
|
|
// Unable to decode, nothing to do
|
|
}
|
|
const value =
|
|
decodedValue && decodedValue !== originalValue
|
|
? decodedValue
|
|
: originalValue;
|
|
|
|
if (!_shouldParse(value)) {
|
|
return value;
|
|
}
|
|
|
|
let obj = null;
|
|
try {
|
|
obj = JSON5.parse(value);
|
|
} catch (ex) {
|
|
obj = null;
|
|
}
|
|
|
|
if (!obj && value) {
|
|
obj = _extractKeyValPairs(value);
|
|
}
|
|
|
|
// return if obj is null, or same as value, or just a string.
|
|
if (!obj || obj === value || typeof obj === "string") {
|
|
return value;
|
|
}
|
|
|
|
// If we got this far, originalValue is an object literal or array,
|
|
// and we have successfully parsed it
|
|
return obj;
|
|
}
|
|
|
|
exports.parseItemValue = parseItemValue;
|