utils.js (4052B)
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 "use strict"; 6 7 loader.lazyRequireGetter( 8 this, 9 "validator", 10 "resource://devtools/shared/storage/vendor/stringvalidator/validator.js" 11 ); 12 loader.lazyRequireGetter( 13 this, 14 "JSON5", 15 "resource://devtools/shared/storage/vendor/json5.js" 16 ); 17 18 const MATH_REGEX = 19 /(?:(?:^|[-+_*/])(?:\s*-?\d+(\.\d+)?(?:[eE][+-]?\d+)?\s*))+$/; 20 21 /** 22 * Tries to parse a string into an object on the basis of key-value pairs, 23 * separated by various separators. If failed, tries to parse for single 24 * separator separated values to form an array. 25 * 26 * @param {string} value 27 * The string to be parsed into an object or array 28 */ 29 function _extractKeyValPairs(value) { 30 const makeObject = (keySep, pairSep) => { 31 const object = {}; 32 for (const pair of value.split(pairSep)) { 33 const [key, val] = pair.split(keySep); 34 object[key] = val; 35 } 36 return object; 37 }; 38 39 // Possible separators. 40 const separators = ["=", ":", "~", "#", "&", "\\*", ",", "\\."]; 41 // Testing for object 42 for (let i = 0; i < separators.length; i++) { 43 const kv = separators[i]; 44 for (let j = 0; j < separators.length; j++) { 45 if (i == j) { 46 continue; 47 } 48 const p = separators[j]; 49 const word = `[^${kv}${p}]*`; 50 const keyValue = `${word}${kv}${word}`; 51 const keyValueList = `${keyValue}(${p}${keyValue})*`; 52 const regex = new RegExp(`^${keyValueList}$`); 53 if ( 54 value.match && 55 value.match(regex) && 56 value.includes(kv) && 57 (value.includes(p) || value.split(kv).length == 2) 58 ) { 59 return makeObject(kv, p); 60 } 61 } 62 } 63 // Testing for array 64 for (const p of separators) { 65 const word = `[^${p}]*`; 66 const wordList = `(${word}${p})+${word}`; 67 const regex = new RegExp(`^${wordList}$`); 68 69 if (regex.test(value)) { 70 const pNoBackslash = p.replace(/\\*/g, ""); 71 return value.split(pNoBackslash); 72 } 73 } 74 return null; 75 } 76 77 /** 78 * Check whether the value string represents something that should be 79 * displayed as text. If so then it shouldn't be parsed into a tree. 80 * 81 * @param {string} value 82 * The value to be parsed. 83 */ 84 function _shouldParse(value) { 85 const validators = [ 86 "isBase64", 87 "isBoolean", 88 "isCurrency", 89 "isDataURI", 90 "isEmail", 91 "isFQDN", 92 "isHexColor", 93 "isIP", 94 "isISO8601", 95 "isMACAddress", 96 "isSemVer", 97 "isURL", 98 ]; 99 100 // Check for minus calculations e.g. 8-3 because otherwise 5 will be displayed. 101 if (MATH_REGEX.test(value)) { 102 return false; 103 } 104 105 // Check for any other types that shouldn't be parsed. 106 for (const test of validators) { 107 if (validator[test](value)) { 108 return false; 109 } 110 } 111 112 // Seems like this is data that should be parsed. 113 return true; 114 } 115 116 /** 117 * Tries to parse a string value into either a json or a key-value separated 118 * object. The value can also be a key separated array. 119 * 120 * @param {string} originalValue 121 * The string to be parsed into an object 122 */ 123 function parseItemValue(originalValue) { 124 // Find if value is URLEncoded ie 125 let decodedValue = ""; 126 try { 127 decodedValue = decodeURIComponent(originalValue); 128 } catch (e) { 129 // Unable to decode, nothing to do 130 } 131 const value = 132 decodedValue && decodedValue !== originalValue 133 ? decodedValue 134 : originalValue; 135 136 if (!_shouldParse(value)) { 137 return value; 138 } 139 140 let obj = null; 141 try { 142 obj = JSON5.parse(value); 143 } catch (ex) { 144 obj = null; 145 } 146 147 if (!obj && value) { 148 obj = _extractKeyValPairs(value); 149 } 150 151 // return if obj is null, or same as value, or just a string. 152 if (!obj || obj === value || typeof obj === "string") { 153 return value; 154 } 155 156 // If we got this far, originalValue is an object literal or array, 157 // and we have successfully parsed it 158 return obj; 159 } 160 161 exports.parseItemValue = parseItemValue;