11cb0ef41Sopenharmony_ciconst { hasOwnProperty } = Object.prototype 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst encode = (obj, opt = {}) => { 41cb0ef41Sopenharmony_ci if (typeof opt === 'string') { 51cb0ef41Sopenharmony_ci opt = { section: opt } 61cb0ef41Sopenharmony_ci } 71cb0ef41Sopenharmony_ci opt.align = opt.align === true 81cb0ef41Sopenharmony_ci opt.newline = opt.newline === true 91cb0ef41Sopenharmony_ci opt.sort = opt.sort === true 101cb0ef41Sopenharmony_ci opt.whitespace = opt.whitespace === true || opt.align === true 111cb0ef41Sopenharmony_ci // The `typeof` check is required because accessing the `process` directly fails on browsers. 121cb0ef41Sopenharmony_ci /* istanbul ignore next */ 131cb0ef41Sopenharmony_ci opt.platform = opt.platform || (typeof process !== 'undefined' && process.platform) 141cb0ef41Sopenharmony_ci opt.bracketedArray = opt.bracketedArray !== false 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci /* istanbul ignore next */ 171cb0ef41Sopenharmony_ci const eol = opt.platform === 'win32' ? '\r\n' : '\n' 181cb0ef41Sopenharmony_ci const separator = opt.whitespace ? ' = ' : '=' 191cb0ef41Sopenharmony_ci const children = [] 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci const keys = opt.sort ? Object.keys(obj).sort() : Object.keys(obj) 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci let padToChars = 0 241cb0ef41Sopenharmony_ci // If aligning on the separator, then padToChars is determined as follows: 251cb0ef41Sopenharmony_ci // 1. Get the keys 261cb0ef41Sopenharmony_ci // 2. Exclude keys pointing to objects unless the value is null or an array 271cb0ef41Sopenharmony_ci // 3. Add `[]` to array keys 281cb0ef41Sopenharmony_ci // 4. Ensure non empty set of keys 291cb0ef41Sopenharmony_ci // 5. Reduce the set to the longest `safe` key 301cb0ef41Sopenharmony_ci // 6. Get the `safe` length 311cb0ef41Sopenharmony_ci if (opt.align) { 321cb0ef41Sopenharmony_ci padToChars = safe( 331cb0ef41Sopenharmony_ci ( 341cb0ef41Sopenharmony_ci keys 351cb0ef41Sopenharmony_ci .filter(k => obj[k] === null || Array.isArray(obj[k]) || typeof obj[k] !== 'object') 361cb0ef41Sopenharmony_ci .map(k => Array.isArray(obj[k]) ? `${k}[]` : k) 371cb0ef41Sopenharmony_ci ) 381cb0ef41Sopenharmony_ci .concat(['']) 391cb0ef41Sopenharmony_ci .reduce((a, b) => safe(a).length >= safe(b).length ? a : b) 401cb0ef41Sopenharmony_ci ).length 411cb0ef41Sopenharmony_ci } 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci let out = '' 441cb0ef41Sopenharmony_ci const arraySuffix = opt.bracketedArray ? '[]' : '' 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci for (const k of keys) { 471cb0ef41Sopenharmony_ci const val = obj[k] 481cb0ef41Sopenharmony_ci if (val && Array.isArray(val)) { 491cb0ef41Sopenharmony_ci for (const item of val) { 501cb0ef41Sopenharmony_ci out += safe(`${k}${arraySuffix}`).padEnd(padToChars, ' ') + separator + safe(item) + eol 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci } else if (val && typeof val === 'object') { 531cb0ef41Sopenharmony_ci children.push(k) 541cb0ef41Sopenharmony_ci } else { 551cb0ef41Sopenharmony_ci out += safe(k).padEnd(padToChars, ' ') + separator + safe(val) + eol 561cb0ef41Sopenharmony_ci } 571cb0ef41Sopenharmony_ci } 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci if (opt.section && out.length) { 601cb0ef41Sopenharmony_ci out = '[' + safe(opt.section) + ']' + (opt.newline ? eol + eol : eol) + out 611cb0ef41Sopenharmony_ci } 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci for (const k of children) { 641cb0ef41Sopenharmony_ci const nk = splitSections(k, '.').join('\\.') 651cb0ef41Sopenharmony_ci const section = (opt.section ? opt.section + '.' : '') + nk 661cb0ef41Sopenharmony_ci const child = encode(obj[k], { 671cb0ef41Sopenharmony_ci ...opt, 681cb0ef41Sopenharmony_ci section, 691cb0ef41Sopenharmony_ci }) 701cb0ef41Sopenharmony_ci if (out.length && child.length) { 711cb0ef41Sopenharmony_ci out += eol 721cb0ef41Sopenharmony_ci } 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci out += child 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci return out 781cb0ef41Sopenharmony_ci} 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_cifunction splitSections (str, separator) { 811cb0ef41Sopenharmony_ci var lastMatchIndex = 0 821cb0ef41Sopenharmony_ci var lastSeparatorIndex = 0 831cb0ef41Sopenharmony_ci var nextIndex = 0 841cb0ef41Sopenharmony_ci var sections = [] 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ci do { 871cb0ef41Sopenharmony_ci nextIndex = str.indexOf(separator, lastMatchIndex) 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci if (nextIndex !== -1) { 901cb0ef41Sopenharmony_ci lastMatchIndex = nextIndex + separator.length 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci if (nextIndex > 0 && str[nextIndex - 1] === '\\') { 931cb0ef41Sopenharmony_ci continue 941cb0ef41Sopenharmony_ci } 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci sections.push(str.slice(lastSeparatorIndex, nextIndex)) 971cb0ef41Sopenharmony_ci lastSeparatorIndex = nextIndex + separator.length 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci } while (nextIndex !== -1) 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci sections.push(str.slice(lastSeparatorIndex)) 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci return sections 1041cb0ef41Sopenharmony_ci} 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ciconst decode = (str, opt = {}) => { 1071cb0ef41Sopenharmony_ci opt.bracketedArray = opt.bracketedArray !== false 1081cb0ef41Sopenharmony_ci const out = Object.create(null) 1091cb0ef41Sopenharmony_ci let p = out 1101cb0ef41Sopenharmony_ci let section = null 1111cb0ef41Sopenharmony_ci // section |key = value 1121cb0ef41Sopenharmony_ci const re = /^\[([^\]]*)\]\s*$|^([^=]+)(=(.*))?$/i 1131cb0ef41Sopenharmony_ci const lines = str.split(/[\r\n]+/g) 1141cb0ef41Sopenharmony_ci const duplicates = {} 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci for (const line of lines) { 1171cb0ef41Sopenharmony_ci if (!line || line.match(/^\s*[;#]/) || line.match(/^\s*$/)) { 1181cb0ef41Sopenharmony_ci continue 1191cb0ef41Sopenharmony_ci } 1201cb0ef41Sopenharmony_ci const match = line.match(re) 1211cb0ef41Sopenharmony_ci if (!match) { 1221cb0ef41Sopenharmony_ci continue 1231cb0ef41Sopenharmony_ci } 1241cb0ef41Sopenharmony_ci if (match[1] !== undefined) { 1251cb0ef41Sopenharmony_ci section = unsafe(match[1]) 1261cb0ef41Sopenharmony_ci if (section === '__proto__') { 1271cb0ef41Sopenharmony_ci // not allowed 1281cb0ef41Sopenharmony_ci // keep parsing the section, but don't attach it. 1291cb0ef41Sopenharmony_ci p = Object.create(null) 1301cb0ef41Sopenharmony_ci continue 1311cb0ef41Sopenharmony_ci } 1321cb0ef41Sopenharmony_ci p = out[section] = out[section] || Object.create(null) 1331cb0ef41Sopenharmony_ci continue 1341cb0ef41Sopenharmony_ci } 1351cb0ef41Sopenharmony_ci const keyRaw = unsafe(match[2]) 1361cb0ef41Sopenharmony_ci let isArray 1371cb0ef41Sopenharmony_ci if (opt.bracketedArray) { 1381cb0ef41Sopenharmony_ci isArray = keyRaw.length > 2 && keyRaw.slice(-2) === '[]' 1391cb0ef41Sopenharmony_ci } else { 1401cb0ef41Sopenharmony_ci duplicates[keyRaw] = (duplicates?.[keyRaw] || 0) + 1 1411cb0ef41Sopenharmony_ci isArray = duplicates[keyRaw] > 1 1421cb0ef41Sopenharmony_ci } 1431cb0ef41Sopenharmony_ci const key = isArray ? keyRaw.slice(0, -2) : keyRaw 1441cb0ef41Sopenharmony_ci if (key === '__proto__') { 1451cb0ef41Sopenharmony_ci continue 1461cb0ef41Sopenharmony_ci } 1471cb0ef41Sopenharmony_ci const valueRaw = match[3] ? unsafe(match[4]) : true 1481cb0ef41Sopenharmony_ci const value = valueRaw === 'true' || 1491cb0ef41Sopenharmony_ci valueRaw === 'false' || 1501cb0ef41Sopenharmony_ci valueRaw === 'null' ? JSON.parse(valueRaw) 1511cb0ef41Sopenharmony_ci : valueRaw 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci // Convert keys with '[]' suffix to an array 1541cb0ef41Sopenharmony_ci if (isArray) { 1551cb0ef41Sopenharmony_ci if (!hasOwnProperty.call(p, key)) { 1561cb0ef41Sopenharmony_ci p[key] = [] 1571cb0ef41Sopenharmony_ci } else if (!Array.isArray(p[key])) { 1581cb0ef41Sopenharmony_ci p[key] = [p[key]] 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci } 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci // safeguard against resetting a previously defined 1631cb0ef41Sopenharmony_ci // array by accidentally forgetting the brackets 1641cb0ef41Sopenharmony_ci if (Array.isArray(p[key])) { 1651cb0ef41Sopenharmony_ci p[key].push(value) 1661cb0ef41Sopenharmony_ci } else { 1671cb0ef41Sopenharmony_ci p[key] = value 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci } 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}} 1721cb0ef41Sopenharmony_ci // use a filter to return the keys that have to be deleted. 1731cb0ef41Sopenharmony_ci const remove = [] 1741cb0ef41Sopenharmony_ci for (const k of Object.keys(out)) { 1751cb0ef41Sopenharmony_ci if (!hasOwnProperty.call(out, k) || 1761cb0ef41Sopenharmony_ci typeof out[k] !== 'object' || 1771cb0ef41Sopenharmony_ci Array.isArray(out[k])) { 1781cb0ef41Sopenharmony_ci continue 1791cb0ef41Sopenharmony_ci } 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci // see if the parent section is also an object. 1821cb0ef41Sopenharmony_ci // if so, add it to that, and mark this one for deletion 1831cb0ef41Sopenharmony_ci const parts = splitSections(k, '.') 1841cb0ef41Sopenharmony_ci p = out 1851cb0ef41Sopenharmony_ci const l = parts.pop() 1861cb0ef41Sopenharmony_ci const nl = l.replace(/\\\./g, '.') 1871cb0ef41Sopenharmony_ci for (const part of parts) { 1881cb0ef41Sopenharmony_ci if (part === '__proto__') { 1891cb0ef41Sopenharmony_ci continue 1901cb0ef41Sopenharmony_ci } 1911cb0ef41Sopenharmony_ci if (!hasOwnProperty.call(p, part) || typeof p[part] !== 'object') { 1921cb0ef41Sopenharmony_ci p[part] = Object.create(null) 1931cb0ef41Sopenharmony_ci } 1941cb0ef41Sopenharmony_ci p = p[part] 1951cb0ef41Sopenharmony_ci } 1961cb0ef41Sopenharmony_ci if (p === out && nl === l) { 1971cb0ef41Sopenharmony_ci continue 1981cb0ef41Sopenharmony_ci } 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci p[nl] = out[k] 2011cb0ef41Sopenharmony_ci remove.push(k) 2021cb0ef41Sopenharmony_ci } 2031cb0ef41Sopenharmony_ci for (const del of remove) { 2041cb0ef41Sopenharmony_ci delete out[del] 2051cb0ef41Sopenharmony_ci } 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci return out 2081cb0ef41Sopenharmony_ci} 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ciconst isQuoted = val => { 2111cb0ef41Sopenharmony_ci return (val.startsWith('"') && val.endsWith('"')) || 2121cb0ef41Sopenharmony_ci (val.startsWith("'") && val.endsWith("'")) 2131cb0ef41Sopenharmony_ci} 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ciconst safe = val => { 2161cb0ef41Sopenharmony_ci if ( 2171cb0ef41Sopenharmony_ci typeof val !== 'string' || 2181cb0ef41Sopenharmony_ci val.match(/[=\r\n]/) || 2191cb0ef41Sopenharmony_ci val.match(/^\[/) || 2201cb0ef41Sopenharmony_ci (val.length > 1 && isQuoted(val)) || 2211cb0ef41Sopenharmony_ci val !== val.trim() 2221cb0ef41Sopenharmony_ci ) { 2231cb0ef41Sopenharmony_ci return JSON.stringify(val) 2241cb0ef41Sopenharmony_ci } 2251cb0ef41Sopenharmony_ci return val.split(';').join('\\;').split('#').join('\\#') 2261cb0ef41Sopenharmony_ci} 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ciconst unsafe = (val, doUnesc) => { 2291cb0ef41Sopenharmony_ci val = (val || '').trim() 2301cb0ef41Sopenharmony_ci if (isQuoted(val)) { 2311cb0ef41Sopenharmony_ci // remove the single quotes before calling JSON.parse 2321cb0ef41Sopenharmony_ci if (val.charAt(0) === "'") { 2331cb0ef41Sopenharmony_ci val = val.slice(1, -1) 2341cb0ef41Sopenharmony_ci } 2351cb0ef41Sopenharmony_ci try { 2361cb0ef41Sopenharmony_ci val = JSON.parse(val) 2371cb0ef41Sopenharmony_ci } catch { 2381cb0ef41Sopenharmony_ci // ignore errors 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci } else { 2411cb0ef41Sopenharmony_ci // walk the val to find the first not-escaped ; character 2421cb0ef41Sopenharmony_ci let esc = false 2431cb0ef41Sopenharmony_ci let unesc = '' 2441cb0ef41Sopenharmony_ci for (let i = 0, l = val.length; i < l; i++) { 2451cb0ef41Sopenharmony_ci const c = val.charAt(i) 2461cb0ef41Sopenharmony_ci if (esc) { 2471cb0ef41Sopenharmony_ci if ('\\;#'.indexOf(c) !== -1) { 2481cb0ef41Sopenharmony_ci unesc += c 2491cb0ef41Sopenharmony_ci } else { 2501cb0ef41Sopenharmony_ci unesc += '\\' + c 2511cb0ef41Sopenharmony_ci } 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci esc = false 2541cb0ef41Sopenharmony_ci } else if (';#'.indexOf(c) !== -1) { 2551cb0ef41Sopenharmony_ci break 2561cb0ef41Sopenharmony_ci } else if (c === '\\') { 2571cb0ef41Sopenharmony_ci esc = true 2581cb0ef41Sopenharmony_ci } else { 2591cb0ef41Sopenharmony_ci unesc += c 2601cb0ef41Sopenharmony_ci } 2611cb0ef41Sopenharmony_ci } 2621cb0ef41Sopenharmony_ci if (esc) { 2631cb0ef41Sopenharmony_ci unesc += '\\' 2641cb0ef41Sopenharmony_ci } 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ci return unesc.trim() 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci return val 2691cb0ef41Sopenharmony_ci} 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_cimodule.exports = { 2721cb0ef41Sopenharmony_ci parse: decode, 2731cb0ef41Sopenharmony_ci decode, 2741cb0ef41Sopenharmony_ci stringify: encode, 2751cb0ef41Sopenharmony_ci encode, 2761cb0ef41Sopenharmony_ci safe, 2771cb0ef41Sopenharmony_ci unsafe, 2781cb0ef41Sopenharmony_ci} 279