diff --git a/ini.js b/ini.js index ddf5bd9..4e7f59f 100644 --- a/ini.js +++ b/ini.js @@ -1,17 +1,16 @@ - exports.parse = exports.decode = decode exports.stringify = exports.encode = encode exports.safe = safe exports.unsafe = unsafe -var eol = process.platform === "win32" ? "\r\n" : "\n" +var eol = process.platform === 'win32' ? '\r\n' : '\n' function encode (obj, opt) { var children = [] - , out = "" + var out = '' - if (typeof opt === "string") { + if (typeof opt === 'string') { opt = { section: opt, whitespace: false @@ -21,16 +20,15 @@ function encode (obj, opt) { opt.whitespace = opt.whitespace === true } - var separator = opt.whitespace ? " = " : "=" + var separator = opt.whitespace ? ' = ' : '=' Object.keys(obj).forEach(function (k, _, __) { var val = obj[k] if (val && Array.isArray(val)) { - val.forEach(function(item) { - out += safe(k + "[]") + separator + safe(item) + "\n" - }) - } - else if (val && typeof val === "object") { + val.forEach(function (item) { + out += safe(k + '[]') + separator + safe(item) + '\n' + }) + } else if (val && typeof val === 'object') { children.push(k) } else { out += safe(k) + separator + safe(val) + eol @@ -38,12 +36,12 @@ function encode (obj, opt) { }) if (opt.section && out.length) { - out = "[" + safe(opt.section) + "]" + eol + out + out = '[' + safe(opt.section) + ']' + eol + out } children.forEach(function (k, _, __) { var nk = dotSplit(k).join('\\.') - var section = (opt.section ? opt.section + "." : "") + nk + var section = (opt.section ? opt.section + '.' : '') + nk var child = encode(obj[k], { section: section, whitespace: opt.whitespace @@ -59,22 +57,20 @@ function encode (obj, opt) { function dotSplit (str) { return str.replace(/\1/g, '\u0002LITERAL\\1LITERAL\u0002') - .replace(/\\\./g, '\u0001') - .split(/\./).map(function (part) { - return part.replace(/\1/g, '\\.') - .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001') - }) + .replace(/\\\./g, '\u0001') + .split(/\./).map(function (part) { + return part.replace(/\1/g, '\\.') + .replace(/\2LITERAL\\1LITERAL\2/g, '\u0001') + }) } function decode (str) { var out = {} - , p = out - , section = null - , state = "START" - // section |key = value - , re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i - , lines = str.split(/[\r\n]+/g) - , section = null + var p = out + var section = null + // section |key = value + var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i + var lines = str.split(/[\r\n]+/g) lines.forEach(function (line, _, __) { if (!line || line.match(/^\s*[;#]/)) return @@ -86,7 +82,7 @@ function decode (str) { return } var key = unsafe(match[2]) - , value = match[3] ? unsafe((match[4] || "")) : true + var value = match[3] ? unsafe((match[4] || '')) : true switch (value) { case 'true': case 'false': @@ -94,22 +90,20 @@ function decode (str) { } // Convert keys with '[]' suffix to an array - if (key.length > 2 && key.slice(-2) === "[]") { - key = key.substring(0, key.length - 2) - if (!p[key]) { - p[key] = [] - } - else if (!Array.isArray(p[key])) { - p[key] = [p[key]] - } + if (key.length > 2 && key.slice(-2) === '[]') { + key = key.substring(0, key.length - 2) + if (!p[key]) { + p[key] = [] + } else if (!Array.isArray(p[key])) { + p[key] = [p[key]] + } } // safeguard against resetting a previously defined // array by accidentally forgetting the brackets if (Array.isArray(p[key])) { p[key].push(value) - } - else { + } else { p[key] = value } }) @@ -117,18 +111,24 @@ function decode (str) { // {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}} // use a filter to return the keys that have to be deleted. Object.keys(out).filter(function (k, _, __) { - if (!out[k] || typeof out[k] !== "object" || Array.isArray(out[k])) return false + if (!out[k] || + typeof out[k] !== 'object' || + Array.isArray(out[k])) { + return false + } // see if the parent section is also an object. // if so, add it to that, and mark this one for deletion var parts = dotSplit(k) - , p = out - , l = parts.pop() - , nl = l.replace(/\\\./g, '.') + var p = out + var l = parts.pop() + var nl = l.replace(/\\\./g, '.') parts.forEach(function (part, _, __) { - if (!p[part] || typeof p[part] !== "object") p[part] = {} + if (!p[part] || typeof p[part] !== 'object') p[part] = {} p = p[part] }) - if (p === out && nl === l) return false + if (p === out && nl === l) { + return false + } p[nl] = out[k] return true }).forEach(function (del, _, __) { @@ -139,51 +139,53 @@ function decode (str) { } function isQuoted (val) { - return (val.charAt(0) === "\"" && val.slice(-1) === "\"") - || (val.charAt(0) === "'" && val.slice(-1) === "'") + return (val.charAt(0) === '"' && val.slice(-1) === '"') || + (val.charAt(0) === "'" && val.slice(-1) === "'") } function safe (val) { - return ( typeof val !== "string" - || val.match(/[=\r\n]/) - || val.match(/^\[/) - || (val.length > 1 - && isQuoted(val)) - || val !== val.trim() ) - ? JSON.stringify(val) - : val.replace(/;/g, '\\;').replace(/#/g, "\\#") + return (typeof val !== 'string' || + val.match(/[=\r\n]/) || + val.match(/^\[/) || + (val.length > 1 && + isQuoted(val)) || + val !== val.trim()) ? + JSON.stringify(val) : + val.replace(/;/g, '\\;').replace(/#/g, '\\#') } function unsafe (val, doUnesc) { - val = (val || "").trim() + val = (val || '').trim() if (isQuoted(val)) { // remove the single quotes before calling JSON.parse if (val.charAt(0) === "'") { - val = val.substr(1, val.length - 2); + val = val.substr(1, val.length - 2) } try { val = JSON.parse(val) } catch (_) {} } else { // walk the val to find the first not-escaped ; character var esc = false - var unesc = ""; + var unesc = '' for (var i = 0, l = val.length; i < l; i++) { var c = val.charAt(i) if (esc) { - if ("\\;#".indexOf(c) !== -1) + if ('\\;#'.indexOf(c) !== -1) { unesc += c - else - unesc += "\\" + c + } else { + unesc += '\\' + c + } esc = false - } else if (";#".indexOf(c) !== -1) { + } else if (';#'.indexOf(c) !== -1) { break - } else if (c === "\\") { + } else if (c === '\\') { esc = true } else { unesc += c } } - if (esc) - unesc += "\\" + if (esc) { + unesc += '\\' + } return unesc } return val diff --git a/package.json b/package.json index 53445b6..3462b73 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ }, "main": "ini.js", "scripts": { + "pretest": "standard ini.js", "test": "tap test/*.js" }, "engines": { @@ -16,6 +17,7 @@ }, "dependencies": {}, "devDependencies": { + "standard": "^4.0.1", "tap": "^1.2.0" }, "license": "ISC",